mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 18:21:59 +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.append(absolute_placement)
|
||||||
absolute_placements = set(absolute_placements)
|
absolute_placements = set(absolute_placements)
|
||||||
|
|
||||||
angle = float(self.args[3])
|
transformation = self.identity_matrix()
|
||||||
transformation = self.z_rotation_matrix(math.radians(angle)) if angle else np.eye(4)
|
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[0][3] += float(self.args[0])
|
||||||
transformation[1][3] += float(self.args[1])
|
transformation[1][3] += float(self.args[1])
|
||||||
transformation[2][3] += float(self.args[2])
|
transformation[2][3] += float(self.args[2])
|
||||||
@@ -55,13 +62,29 @@ class Patcher:
|
|||||||
return self.get_absolute_placement(object_placement.PlacementRelTo)
|
return self.get_absolute_placement(object_placement.PlacementRelTo)
|
||||||
return object_placement
|
return object_placement
|
||||||
|
|
||||||
def z_rotation_matrix(self, angle):
|
def identity_matrix(self):
|
||||||
return [
|
return np.eye(4)
|
||||||
[math.cos(angle), -math.sin(angle), 0., 0.],
|
|
||||||
[math.sin(angle), math.cos(angle), 0., 0.],
|
def x_rotation_matrix(self, angle, transformation):
|
||||||
[0., 0., 1., 0.],
|
transformation[1][1] = math.cos(angle)
|
||||||
[0., 0., 0., 1.],
|
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):
|
def get_relative_placement(self, m):
|
||||||
x = np.array((m[0][0], m[1][0], m[2][0]))
|
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)
|
engine = reporter.Console(specs, use_colour=not args.no_color)
|
||||||
elif args.reporter == "Json":
|
elif args.reporter == "Json":
|
||||||
engine = reporter.Json(specs)
|
engine = reporter.Json(specs)
|
||||||
|
elif args.reporter == "Html":
|
||||||
|
engine = reporter.Html(specs)
|
||||||
|
|
||||||
engine.report()
|
engine.report()
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,11 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import math
|
||||||
import logging
|
import logging
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
class Reporter:
|
class Reporter:
|
||||||
def __init__(self, ids):
|
def __init__(self, ids):
|
||||||
@@ -150,11 +153,14 @@ class Json(Reporter):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
total = len(specification.applicable_entities)
|
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 {
|
return {
|
||||||
"name": specification.name,
|
"name": specification.name,
|
||||||
"status": specification.status,
|
"status": specification.status,
|
||||||
"total_successes": total - len(specification.failed_entities),
|
"total_successes": total_successes,
|
||||||
"total": total,
|
"total": total,
|
||||||
|
"percentage": percentage,
|
||||||
"required": specification.minOccurs != 0,
|
"required": specification.minOccurs != 0,
|
||||||
"requirements": requirements,
|
"requirements": requirements,
|
||||||
}
|
}
|
||||||
@@ -171,6 +177,32 @@ class Json(Reporter):
|
|||||||
return json.dump(self.results, outfile)
|
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):
|
class BcfHandler(logging.StreamHandler):
|
||||||
"""Logging handler for creation of BCF report files.
|
"""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