Merge branch 'IfcOpenShell:v0.7.0' into pr-daily-builds

This commit is contained in:
Kristoffer Andersen
2022-08-09 09:13:22 +02:00
committed by GitHub
4 changed files with 151 additions and 10 deletions
@@ -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]))
+2
View File
@@ -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()
+33 -1
View File
@@ -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>