mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-06 07:51:47 +00:00
Merge branch 'IfcOpenShell:v0.7.0' into pr-daily-builds
This commit is contained in:
@@ -39,8 +39,15 @@ class Patcher:
|
||||
absolute_placements.append(absolute_placement)
|
||||
absolute_placements = set(absolute_placements)
|
||||
|
||||
angle = float(self.args[3])
|
||||
transformation = self.z_rotation_matrix(math.radians(angle)) if angle else np.eye(4)
|
||||
transformation = self.identity_matrix()
|
||||
if len(self.args) == 4:
|
||||
angle = self.args[3]
|
||||
if angle:
|
||||
transformation = self.z_rotation_matrix(math.radians(angle), transformation)
|
||||
elif len(self.args) == 6:
|
||||
for arg in (("x", self.args[3]), ("y", self.args[4]), ("z", self.args[5])):
|
||||
if arg[1]:
|
||||
transformation = getattr(self, f"{arg[0]}_rotation_matrix")(math.radians(arg[1]), transformation)
|
||||
transformation[0][3] += float(self.args[0])
|
||||
transformation[1][3] += float(self.args[1])
|
||||
transformation[2][3] += float(self.args[2])
|
||||
@@ -55,13 +62,29 @@ class Patcher:
|
||||
return self.get_absolute_placement(object_placement.PlacementRelTo)
|
||||
return object_placement
|
||||
|
||||
def z_rotation_matrix(self, angle):
|
||||
return [
|
||||
[math.cos(angle), -math.sin(angle), 0., 0.],
|
||||
[math.sin(angle), math.cos(angle), 0., 0.],
|
||||
[0., 0., 1., 0.],
|
||||
[0., 0., 0., 1.],
|
||||
]
|
||||
def identity_matrix(self):
|
||||
return np.eye(4)
|
||||
|
||||
def x_rotation_matrix(self, angle, transformation):
|
||||
transformation[1][1] = math.cos(angle)
|
||||
transformation[1][2] = -math.sin(angle)
|
||||
transformation[2][1] = math.sin(angle)
|
||||
transformation[2][2] = math.cos(angle)
|
||||
return transformation
|
||||
|
||||
def y_rotation_matrix(self, angle, transformation):
|
||||
transformation[0][0] = math.cos(angle)
|
||||
transformation[0][2] = math.sin(angle)
|
||||
transformation[2][0] = -math.sin(angle)
|
||||
transformation[2][2] = math.cos(angle)
|
||||
return transformation
|
||||
|
||||
def z_rotation_matrix(self, angle, transformation):
|
||||
transformation[0][0] = math.cos(angle)
|
||||
transformation[0][1] = -math.sin(angle)
|
||||
transformation[1][0] = math.sin(angle)
|
||||
transformation[1][1] = math.cos(angle)
|
||||
return transformation
|
||||
|
||||
def get_relative_placement(self, m):
|
||||
x = np.array((m[0][0], m[1][0], m[2][0]))
|
||||
|
||||
@@ -51,6 +51,8 @@ if args.reporter == "Console":
|
||||
engine = reporter.Console(specs, use_colour=not args.no_color)
|
||||
elif args.reporter == "Json":
|
||||
engine = reporter.Json(specs)
|
||||
elif args.reporter == "Html":
|
||||
engine = reporter.Html(specs)
|
||||
|
||||
engine.report()
|
||||
|
||||
|
||||
@@ -18,8 +18,11 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import math
|
||||
import logging
|
||||
import datetime
|
||||
|
||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
class Reporter:
|
||||
def __init__(self, ids):
|
||||
@@ -150,11 +153,14 @@ class Json(Reporter):
|
||||
}
|
||||
)
|
||||
total = len(specification.applicable_entities)
|
||||
total_successes = total - len(specification.failed_entities)
|
||||
percentage = math.floor((total_successes / total) * 100) if total else "N/A"
|
||||
return {
|
||||
"name": specification.name,
|
||||
"status": specification.status,
|
||||
"total_successes": total - len(specification.failed_entities),
|
||||
"total_successes": total_successes,
|
||||
"total": total,
|
||||
"percentage": percentage,
|
||||
"required": specification.minOccurs != 0,
|
||||
"requirements": requirements,
|
||||
}
|
||||
@@ -171,6 +177,32 @@ class Json(Reporter):
|
||||
return json.dump(self.results, outfile)
|
||||
|
||||
|
||||
class Html(Json):
|
||||
def __init__(self, ids):
|
||||
super().__init__(ids)
|
||||
self.results = {}
|
||||
|
||||
def report(self):
|
||||
self.results["title"] = self.ids.info.get("title", "Untitled IDS")
|
||||
self.results["time"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
self.results["specifications"] = []
|
||||
for specification in self.ids.specifications:
|
||||
self.results["specifications"].append(self.report_specification(specification))
|
||||
return self.results
|
||||
|
||||
def to_string(self):
|
||||
import pystache
|
||||
|
||||
with open(os.path.join(cwd, "templates", "report.html"), "r") as file:
|
||||
return pystache.render(file.read(), self.results)
|
||||
|
||||
def to_file(self, filepath):
|
||||
import pystache
|
||||
|
||||
with open(os.path.join(cwd, "templates", "report.html"), "r") as file:
|
||||
with open(filepath, "w") as outfile:
|
||||
return outfile.write(pystache.render(file.read(), self.results))
|
||||
|
||||
|
||||
class BcfHandler(logging.StreamHandler):
|
||||
"""Logging handler for creation of BCF report files.
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
<!--
|
||||
IfcTester - IDS based model auditing
|
||||
Copyright (C) 2022 Dion Moult <dion@thinkmoult.com>
|
||||
|
||||
This file is part of IfcTester.
|
||||
|
||||
IfcTester is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
IfcTester is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with IfcTester. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html lang={{_lang}}>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="foobaro">
|
||||
<title>{{name}}</title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Comfortaa|Inconsolata|Open+Sans&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
body { font-family: 'Arial', sans-serif; padding: 10px 40px; }
|
||||
span.time { color: #999; font-style: italic; float: right; }
|
||||
span.step-time { float: right; color: #555; font-size: 0.8em; font-style: italic; }
|
||||
span.success { background-color: #97cc64; padding: 5px; border-radius: 5px; color: #FFF; font-weight: bold; }
|
||||
span.failure { background-color: #fb5a3e; padding: 5px; border-radius: 5px; color: #FFF; font-weight: bold; }
|
||||
p.failure { background-color: #fb5a3e; padding: 5px; border-radius: 5px; color: #fff; }
|
||||
p.unspecified { background-color: #994f00; padding: 5px; border-radius: 5px; color: #fff; }
|
||||
p.skipped { background-color: #8b8d8f; padding: 5px; border-radius: 5px; color: #fff; }
|
||||
p.description { background-color: #eee; border-radius: 5px; padding: 20px; margin-left: auto; margin-right: auto; display: inline-block; font-weight: bold;}
|
||||
li { padding: 10px; font-family: monospace; }
|
||||
li.success { background-color: #b6cca1; color: #333; }
|
||||
li.failure { background-color: #fbb4a8; color: #900; }
|
||||
li.unspecified { background-color: #ffd37f; color: #a30; }
|
||||
li.skipped { background-color: #f5f5f5; color: #333; }
|
||||
li p { margin-bottom: 0px; }
|
||||
footer { color: #999; font-size: 0.8em; }
|
||||
header { text-align: center; }
|
||||
hr { margin: 20px; margin-left: 0px; margin-right: 0px; border: none; border-top: 1px solid #ccc; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>{{title}}</h1>
|
||||
<p><strong>{{time}}</strong></p>
|
||||
</header>
|
||||
{{#specifications}}
|
||||
<section>
|
||||
<h2>{{name}}</h2>
|
||||
<p>
|
||||
<span class="{{#status}}success{{/status}}{{^status}}failure{{/status}}">{{#status}}Pass{{/status}}{{^status}}Fail{{/status}}</span>
|
||||
Passed: <strong>{{total_successes}} / {{total}}</strong> ({{percentage}}%)
|
||||
</p>
|
||||
<ol>
|
||||
{{#requirements}}
|
||||
<li class="{{#status}}success{{/status}}{{^status}}failure{{/status}}">
|
||||
{{description}}
|
||||
{{^status}}{{#total}}
|
||||
<p class="failure{{#is_unspecified}} unspecified{{/is_unspecified}}{{#is_skipped}} skipped{{/is_skipped}}">
|
||||
{{#failed_entities}}
|
||||
{{reason}} <em style="color: #fbb4a8;">{{element}}</em><br />
|
||||
{{/failed_entities}}
|
||||
</p>
|
||||
{{/total}}{{/status}}
|
||||
</li>
|
||||
{{/requirements}}
|
||||
</ol>
|
||||
</section>
|
||||
{{/specifications}}
|
||||
<hr>
|
||||
<footer>
|
||||
<p>
|
||||
Report by <a href="https://blenderbim.org/">BlenderBIM</a> and <a href="http://ifcopenshell.org/">IfcOpenShell</a>.
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user