mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-12 06:32:09 +00:00
IfcTester can now output reports in BCF
This commit is contained in:
@@ -57,6 +57,8 @@ elif args.reporter == "Html":
|
|||||||
engine = reporter.Html(specs)
|
engine = reporter.Html(specs)
|
||||||
elif args.reporter == "Ods":
|
elif args.reporter == "Ods":
|
||||||
engine = reporter.Ods(specs)
|
engine = reporter.Ods(specs)
|
||||||
|
elif args.reporter == "Bcf":
|
||||||
|
engine = reporter.Bcf(specs)
|
||||||
|
|
||||||
engine.report()
|
engine.report()
|
||||||
|
|
||||||
|
|||||||
@@ -169,10 +169,7 @@ class Json(Reporter):
|
|||||||
{
|
{
|
||||||
"description": requirement.to_string("requirement"),
|
"description": requirement.to_string("requirement"),
|
||||||
"status": requirement.status,
|
"status": requirement.status,
|
||||||
"failed_entities": [
|
"failed_entities": self.report_failed_entities(requirement),
|
||||||
{"reason": requirement.failed_reasons[i], "element": str(e)}
|
|
||||||
for i, e in enumerate(requirement.failed_entities[0:10])
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
total = len(specification.applicable_entities)
|
total = len(specification.applicable_entities)
|
||||||
@@ -188,6 +185,12 @@ class Json(Reporter):
|
|||||||
"requirements": requirements,
|
"requirements": requirements,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def report_failed_entities(self, requirement):
|
||||||
|
return [
|
||||||
|
{"reason": requirement.failed_reasons[i], "element": str(e)}
|
||||||
|
for i, e in enumerate(requirement.failed_entities)
|
||||||
|
]
|
||||||
|
|
||||||
def to_string(self):
|
def to_string(self):
|
||||||
import json
|
import json
|
||||||
|
|
||||||
@@ -321,97 +324,29 @@ class Ods(Json):
|
|||||||
self.doc.save(filepath, True)
|
self.doc.save(filepath, True)
|
||||||
|
|
||||||
|
|
||||||
class Bcf(Reporter):
|
class Bcf(Json):
|
||||||
def __init__(self, ids, with_viewpoint=True, filepath=None, group=False):
|
def report_failed_entities(self, requirement):
|
||||||
super().__init__(ids)
|
return [
|
||||||
|
{"reason": requirement.failed_reasons[i], "element": e} for i, e in enumerate(requirement.failed_entities)
|
||||||
|
]
|
||||||
|
|
||||||
|
def to_file(self, filepath):
|
||||||
from bcf.v2.bcfxml import BcfXml
|
from bcf.v2.bcfxml import BcfXml
|
||||||
|
|
||||||
self.with_viewpoint = with_viewpoint
|
bcfxml = BcfXml.create_new(self.results["title"])
|
||||||
self.group = group
|
for specification in self.results["specifications"]:
|
||||||
self.bcf = BcfXml()
|
if specification["status"]:
|
||||||
self.bcf.new_project()
|
continue
|
||||||
if not filepath:
|
for requirement in specification["requirements"]:
|
||||||
self.filepath=os.path.join(sys.path[0], self.ids.info['title'] + '.bcf')
|
if requirement["status"]:
|
||||||
# self.bcf.filepath = sys.path[0]
|
continue
|
||||||
self.bcf.project.name = self.ids.info.get("title", "Untitled IDS")
|
for failure in requirement["failed_entities"]:
|
||||||
self.bcf.author = self.ids.info.get("author", "your@email.com")
|
element = failure["element"]
|
||||||
self.bcf.creation_date = datetime.datetime.today().replace(microsecond=0).isoformat()
|
title = f"{element.id()}/{element.is_a()}/"
|
||||||
self.bcf.modified_date = datetime.datetime.today().replace(microsecond=0).isoformat()
|
title += getattr(element, "Name", None) or "Unnamed"
|
||||||
|
title += " - " + failure.get("reason", "No reason")
|
||||||
def report(self):
|
description = f'{specification["name"]} - {requirement["description"]}'
|
||||||
for specification in self.ids.specifications:
|
topic = bcfxml.add_topic(title, description, "IfcTester")
|
||||||
self.report_specification(specification, save_project=False)
|
if element.is_a("IfcElement"):
|
||||||
self.bcf.save_project(self.filepath)
|
topic.add_viewpoint(element)
|
||||||
|
bcfxml.save_project(filepath)
|
||||||
def report_specification(self, specification, save_project=True):
|
|
||||||
from bcf.v2 import data as bcf
|
|
||||||
for requirement in specification.requirements:
|
|
||||||
if self.group:
|
|
||||||
topic = bcf.Topic()
|
|
||||||
topic.title = requirement.to_string("requirement")
|
|
||||||
topic.description = ";\n".join([requirement.failed_reasons[i] + " for " + str(e.get_info()['type']) + ": " + str(e.GlobalId) for i, e in enumerate(requirement.failed_entities)])
|
|
||||||
self.bcf.add_topic(topic)
|
|
||||||
if self.with_viewpoint:
|
|
||||||
self.add_viewpoint(topic, requirement)
|
|
||||||
else:
|
|
||||||
for i, e in enumerate(requirement.failed_entities):
|
|
||||||
topic = bcf.Topic()
|
|
||||||
topic.title = requirement.to_string("requirement")
|
|
||||||
topic.description = requirement.failed_reasons[i] + " for " + str(e.get_info()['type']) + ": " + str(e.GlobalId)
|
|
||||||
self.bcf.add_topic(topic)
|
|
||||||
if self.with_viewpoint:
|
|
||||||
self.add_viewpoint(topic, requirement)
|
|
||||||
if save_project:
|
|
||||||
self.bcf.save_project(self.filepath)
|
|
||||||
|
|
||||||
def add_viewpoint(self, topic, requirement):
|
|
||||||
import numpy as np
|
|
||||||
import ifcopenshell.util.placement
|
|
||||||
from bcf.v2 import data as bcf
|
|
||||||
|
|
||||||
viewpoint = bcf.Viewpoint()
|
|
||||||
viewpoint.perspective_camera = bcf.PerspectiveCamera()
|
|
||||||
ifc_elem = requirement.failed_entities[0]
|
|
||||||
target_position = np.array(ifcopenshell.util.placement.get_local_placement(ifc_elem.ObjectPlacement))
|
|
||||||
target_position = target_position[:, 3][0:3]
|
|
||||||
camera_position = target_position + np.array((5, 5, 5))
|
|
||||||
viewpoint.perspective_camera.camera_view_point.x = camera_position[0]
|
|
||||||
viewpoint.perspective_camera.camera_view_point.y = camera_position[1]
|
|
||||||
viewpoint.perspective_camera.camera_view_point.z = camera_position[2]
|
|
||||||
camera_direction = camera_position - target_position
|
|
||||||
camera_direction = camera_direction / np.linalg.norm(camera_direction)
|
|
||||||
camera_right = np.cross(np.array([0.0, 0.0, 1.0]), camera_direction)
|
|
||||||
camera_right = camera_right / np.linalg.norm(camera_right)
|
|
||||||
camera_up = np.cross(camera_direction, camera_right)
|
|
||||||
camera_up = camera_up / np.linalg.norm(camera_up)
|
|
||||||
rotation_transform = np.zeros((4, 4))
|
|
||||||
rotation_transform[0, :3] = camera_right
|
|
||||||
rotation_transform[1, :3] = camera_up
|
|
||||||
rotation_transform[2, :3] = camera_direction
|
|
||||||
rotation_transform[-1, -1] = 1
|
|
||||||
translation_transform = np.eye(4)
|
|
||||||
translation_transform[:3, -1] = -camera_position
|
|
||||||
look_at_transform = np.matmul(rotation_transform, translation_transform)
|
|
||||||
mat = np.linalg.inv(look_at_transform)
|
|
||||||
viewpoint.perspective_camera.camera_direction.x = mat[0][2] * -1
|
|
||||||
viewpoint.perspective_camera.camera_direction.y = mat[1][2] * -1
|
|
||||||
viewpoint.perspective_camera.camera_direction.z = mat[2][2] * -1
|
|
||||||
viewpoint.perspective_camera.camera_up_vector.x = mat[0][1]
|
|
||||||
viewpoint.perspective_camera.camera_up_vector.y = mat[1][1]
|
|
||||||
viewpoint.perspective_camera.camera_up_vector.z = mat[2][1]
|
|
||||||
viewpoint.components = bcf.Components()
|
|
||||||
for e in requirement.failed_entities:
|
|
||||||
c = bcf.Component()
|
|
||||||
c.ifc_guid = e.GlobalId
|
|
||||||
viewpoint.components.selection.append(c)
|
|
||||||
viewpoint.components.visibility = bcf.ComponentVisibility()
|
|
||||||
viewpoint.components.visibility.default_visibility = True
|
|
||||||
# add single pixel png file as a snapshot, as viewpoints without snapshots won't open in viewers
|
|
||||||
png = b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x01\x03\x00\x00\x00%\xdbV\xca\x00\x00\x00\x03PLTE\x00\x00\x00\xa7z=\xda\x00\x00\x00\x01tRNS\x00@\xe6\xd8f\x00\x00\x00\nIDAT\x08\xd7c`\x00\x00\x00\x02\x00\x01\xe2!\xbc3\x00\x00\x00\x00IEND\xaeB`\x82"
|
|
||||||
snapshot_path = os.path.join(self.bcf.filepath, topic.guid, topic.guid+".png")
|
|
||||||
snapshot = open(snapshot_path, "wb")
|
|
||||||
snapshot.write(png)
|
|
||||||
snapshot.close()
|
|
||||||
viewpoint.snapshot = topic.guid+".png"
|
|
||||||
self.bcf.add_viewpoint(topic, viewpoint)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user