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

This commit is contained in:
Kristoffer Andersen
2022-04-14 13:39:56 +02:00
committed by GitHub
17 changed files with 341 additions and 209 deletions
@@ -173,7 +173,7 @@
style="stroke-width:0.999999px" style="stroke-width:0.999999px"
y="1036.1166" y="1036.1166"
x="3030.9653" x="3030.9653"
id="tspan2527">{{revision}}</tspan></text> id="tspan2527">{{Revision}}</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3918px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.999999px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13.3918px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.999999px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
@@ -183,7 +183,7 @@
id="tspan2531" id="tspan2531"
x="2804.7021" x="2804.7021"
y="1036.1166" y="1036.1166"
style="stroke-width:0.999999px">{{number}}</tspan></text> style="stroke-width:0.999999px">{{Identification}} - {{Name}}</tspan></text>
</g> </g>
<g <g
transform="matrix(0.26458333,0,0,0.26458334,-3.180917e-5,297.00003)" transform="matrix(0.26458333,0,0,0.26458334,-3.180917e-5,297.00003)"

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

@@ -169,7 +169,7 @@
style="stroke-width:0.264583px" style="stroke-width:0.264583px"
y="397.13919" y="397.13919"
x="554.94287" x="554.94287"
id="tspan2527">{{revision}}</tspan></text> id="tspan2527">{{Revision}}</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325px;line-height:125%;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
@@ -179,7 +179,7 @@
id="tspan2531" id="tspan2531"
x="495.07742" x="495.07742"
y="397.13919" y="397.13919"
style="stroke-width:0.264583px">{{number}}</tspan></text> style="stroke-width:0.264583px">{{Identification}} - {{Name}}</tspan></text>
<g <g
style="stroke-width:3.77953" style="stroke-width:3.77953"
id="g90669" id="g90669"

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

@@ -172,7 +172,7 @@
id="tspan2527" id="tspan2527"
x="544.94287" x="544.94287"
y="284.13919" y="284.13919"
style="stroke-width:0.264583px">{{revision}}</tspan></text> style="stroke-width:0.264583px">{{Revision}}</tspan></text>
<text <text
id="text2533" id="text2533"
y="284.13919" y="284.13919"
@@ -182,7 +182,7 @@
style="stroke-width:0.264583px" style="stroke-width:0.264583px"
y="284.13919" y="284.13919"
x="485.07742" x="485.07742"
id="tspan2531">{{number}}</tspan></text> id="tspan2531">{{Identification}} - {{Name}}</tspan></text>
</g> </g>
<g <g
style="stroke-width:3.77953" style="stroke-width:3.77953"

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

@@ -70,7 +70,7 @@
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.96055365px;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.26458332px" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.96055365px;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:center;text-anchor:middle;stroke-width:0.26458332px"
y="103.10933" y="103.10933"
x="32.822662" x="32.822662"
id="tspan857">{{no}}</tspan></text> id="tspan857">{{Identification}}</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.71626091px;line-height:125%;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458329px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:17.71626091px;line-height:125%;font-family:Arial;-inkscape-font-specification:Arial;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458329px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
@@ -80,7 +80,7 @@
id="tspan861" id="tspan861"
x="39.12896" x="39.12896"
y="100.19173" y="100.19173"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325247px;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:start;text-anchor:start;stroke-width:0.26458329px">{{name}}</tspan></text> style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325247px;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:start;text-anchor:start;stroke-width:0.26458329px">{{Name}}</tspan></text>
<text <text
id="text867" id="text867"
y="105.0553" y="105.0553"
@@ -90,6 +90,6 @@
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325247px;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:start;text-anchor:start;stroke-width:0.26458332px" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.54325247px;font-family:'OpenGost Type B TT';-inkscape-font-specification:'OpenGost Type B TT';text-align:start;text-anchor:start;stroke-width:0.26458332px"
y="105.0553" y="105.0553"
x="39.285267" x="39.285267"
id="tspan865">{{scale}}</tspan></text> id="tspan865">{{Scale}}</tspan></text>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

@@ -635,14 +635,8 @@ class RemoveDrawingFromSheet(bpy.types.Operator):
def execute(self, context): def execute(self, context):
reference = tool.Ifc.get().by_id(self.reference) reference = tool.Ifc.get().by_id(self.reference)
if tool.Ifc.get_schema() == "IFC2X3": sheet = tool.Drawing.get_reference_sheet(reference)
sheet = reference.ReferenceToDocument[0] drawing = tool.Drawing.get_reference_element(reference)
drawing = [r for r in tool.Ifc.by_type("IfcRelAssociatesDocument") if r.RelatingDocument == reference][
0
].RelatedObjects[0]
else:
sheet = reference.ReferencedDocument
drawing = reference.DocumentRefForObjects[0].RelatedObjects[0]
tool.Ifc.run("document.unassign_document", product=drawing, document=reference) tool.Ifc.run("document.unassign_document", product=drawing, document=reference)
tool.Ifc.run("document.remove_reference", reference=reference) tool.Ifc.run("document.remove_reference", reference=reference)
@@ -667,10 +661,11 @@ class CreateSheets(bpy.types.Operator):
scene = context.scene scene = context.scene
props = scene.DocProperties props = scene.DocProperties
active_sheet = props.sheets[props.active_sheet_index] active_sheet = props.sheets[props.active_sheet_index]
name = active_sheet.name sheet = tool.Ifc.get().by_id(active_sheet.ifc_definition_id)
name = tool.Drawing.get_sheet_filename(sheet)
sheet_builder = sheeter.SheetBuilder() sheet_builder = sheeter.SheetBuilder()
sheet_builder.data_dir = scene.BIMProperties.data_dir sheet_builder.data_dir = scene.BIMProperties.data_dir
sheet_builder.build(name) sheet_builder.build(sheet)
svg2pdf_command = context.preferences.addons["blenderbim"].preferences.svg2pdf_command svg2pdf_command = context.preferences.addons["blenderbim"].preferences.svg2pdf_command
svg2dxf_command = context.preferences.addons["blenderbim"].preferences.svg2dxf_command svg2dxf_command = context.preferences.addons["blenderbim"].preferences.svg2dxf_command
@@ -72,8 +72,10 @@ def update_diagram_scale(self, context):
scale = self.diagram_scale scale = self.diagram_scale
if scale == "CUSTOM": if scale == "CUSTOM":
scale = self.custom_diagram_scale scale = self.custom_diagram_scale
scale = scale.split("|")[1] if "|" not in scale:
element = tool.Ifc.get_entity(context.scene.camera) return
human_scale, scale = scale.split("|")
element = tool.Ifc.get_entity(context.active_object)
if not element: if not element:
return return
pset = ifcopenshell.util.element.get_psets(element).get("EPset_Drawing") pset = ifcopenshell.util.element.get_psets(element).get("EPset_Drawing")
@@ -81,7 +83,9 @@ def update_diagram_scale(self, context):
pset = tool.Ifc.get().by_id(pset["id"]) pset = tool.Ifc.get().by_id(pset["id"])
else: else:
pset = ifcopenshell.api.run("pset.add_pset", tool.Ifc.get(), product=element, name="EPset_Drawing") pset = ifcopenshell.api.run("pset.add_pset", tool.Ifc.get(), product=element, name="EPset_Drawing")
ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Scale": scale}) ifcopenshell.api.run(
"pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Scale": scale, "HumanScale": human_scale}
)
def get_diagram_scales(self, context): def get_diagram_scales(self, context):
@@ -67,7 +67,7 @@ class SheetBuilder:
drawing_dir = os.path.join(self.data_dir, "diagrams") drawing_dir = os.path.join(self.data_dir, "diagrams")
sheet_path = os.path.join(sheet_dir, sheet_name + ".svg") sheet_path = os.path.join(sheet_dir, sheet_name + ".svg")
drawing_path = os.path.join(drawing_dir, filename + ".svg") drawing_path = os.path.join(drawing_dir, filename + ".svg")
underlay_path = os.path.join(drawing_dir, filename + ".png") underlay_path = os.path.join(drawing_dir, filename + "-underlay.png")
if not os.path.isfile(sheet_path): if not os.path.isfile(sheet_path):
raise FileNotFoundError raise FileNotFoundError
@@ -92,6 +92,7 @@ class SheetBuilder:
if os.path.isfile(underlay_path): if os.path.isfile(underlay_path):
background = ET.SubElement(view, "image") background = ET.SubElement(view, "image")
background.attrib["data-type"] = "background"
background.attrib["xlink:href"] = os.path.relpath(underlay_path, sheet_dir) background.attrib["xlink:href"] = os.path.relpath(underlay_path, sheet_dir)
background.attrib["x"] = "30" background.attrib["x"] = "30"
background.attrib["y"] = "30" background.attrib["y"] = "30"
@@ -100,6 +101,7 @@ class SheetBuilder:
if os.path.isfile(drawing_path): if os.path.isfile(drawing_path):
foreground = ET.SubElement(view, "image") foreground = ET.SubElement(view, "image")
foreground.attrib["data-type"] = "foreground"
foreground.attrib["xlink:href"] = os.path.relpath(drawing_path, sheet_dir) foreground.attrib["xlink:href"] = os.path.relpath(drawing_path, sheet_dir)
foreground.attrib["x"] = "30" foreground.attrib["x"] = "30"
foreground.attrib["y"] = "30" foreground.attrib["y"] = "30"
@@ -119,9 +121,7 @@ class SheetBuilder:
sheet_tree = ET.parse(sheet_path) sheet_tree = ET.parse(sheet_path)
sheet_root = sheet_tree.getroot() sheet_root = sheet_tree.getroot()
print('removing drawing', sheet_root.findall("{http://www.w3.org/2000/svg}g"))
for g in sheet_root.findall("{http://www.w3.org/2000/svg}g"): for g in sheet_root.findall("{http://www.w3.org/2000/svg}g"):
print('checking g', g)
if g.attrib["data-type"] == "drawing" and g.attrib["data-guid"] == drawing.GlobalId: if g.attrib["data-type"] == "drawing" and g.attrib["data-guid"] == drawing.GlobalId:
sheet_root.remove(g) sheet_root.remove(g)
break break
@@ -160,13 +160,15 @@ class SheetBuilder:
title_tree = ET.parse(os.path.join(self.data_dir, "templates", "view-title.svg")) title_tree = ET.parse(os.path.join(self.data_dir, "templates", "view-title.svg"))
title_root = title_tree.getroot() title_root = title_tree.getroot()
title = ET.SubElement(parent, "image") title = ET.SubElement(parent, "image")
title.attrib["data-type"] = "view-title"
title.attrib["xlink:href"] = "../templates/view-title.svg" title.attrib["xlink:href"] = "../templates/view-title.svg"
title.attrib["x"] = str(x) title.attrib["x"] = str(x)
title.attrib["y"] = str(y) title.attrib["y"] = str(y)
title.attrib["width"] = str(self.convert_to_mm(title_root.attrib.get("width"))) title.attrib["width"] = str(self.convert_to_mm(title_root.attrib.get("width")))
title.attrib["height"] = str(self.convert_to_mm(title_root.attrib.get("height"))) title.attrib["height"] = str(self.convert_to_mm(title_root.attrib.get("height")))
def build(self, sheet_name): def build(self, sheet):
sheet_name = tool.Drawing.get_sheet_filename(sheet)
os.makedirs(os.path.join(self.data_dir, "build", sheet_name), exist_ok=True) os.makedirs(os.path.join(self.data_dir, "build", sheet_name), exist_ok=True)
sheet_path = os.path.join(self.data_dir, "sheets", f"{sheet_name}.svg") sheet_path = os.path.join(self.data_dir, "sheets", f"{sheet_name}.svg")
@@ -177,48 +179,60 @@ class SheetBuilder:
tree = ET.parse(sheet_path) tree = ET.parse(sheet_path)
root = tree.getroot() root = tree.getroot()
titleblock = root.findall('{http://www.w3.org/2000/svg}g[@data-type="titleblock"]')[0] self.build_titleblock(root, sheet)
image = titleblock.findall("{http://www.w3.org/2000/svg}image")[0] self.build_drawings(root, sheet)
titleblock.append(self.parse_embedded_svg(image, {"number": sheet_name, "revision": "A"}))
titleblock.remove(image)
self.group_number = 1
self.build_drawings(root.findall('{http://www.w3.org/2000/svg}g[@data-type="drawing"]'), sheet_name)
self.build_schedules(root.findall('{http://www.w3.org/2000/svg}g[@data-type="schedule"]')) self.build_schedules(root.findall('{http://www.w3.org/2000/svg}g[@data-type="schedule"]'))
with open(os.path.join(self.data_dir, "build", sheet_name, f"{sheet_name}.svg"), "wb") as output: with open(os.path.join(self.data_dir, "build", sheet_name, f"{sheet_name}.svg"), "wb") as output:
tree.write(output) tree.write(output)
def build_drawings(self, drawings, sheet_name): def build_titleblock(self, root, sheet):
for view in drawings: titleblock = root.findall('{http://www.w3.org/2000/svg}g[@data-type="titleblock"]')[0]
image = titleblock.findall("{http://www.w3.org/2000/svg}image")[0]
titleblock.append(self.parse_embedded_svg(image, sheet.get_info()))
titleblock.remove(image)
def build_drawings(self, root, sheet):
sheet_name = tool.Drawing.get_sheet_filename(sheet)
references = tool.Drawing.get_document_references(sheet)
drawing_references = {tool.Drawing.get_reference_element(r): r for r in references}
for view in root.findall('{http://www.w3.org/2000/svg}g[@data-type="drawing"]'):
drawing = [d for d in drawing_references.keys() if d and d.GlobalId == view.attrib["data-guid"]][0]
reference = drawing_references[drawing]
images = view.findall("{http://www.w3.org/2000/svg}image") images = view.findall("{http://www.w3.org/2000/svg}image")
background = images[0]
foreground = images[1]
view_title = images[2]
self.scale = "NTS"
# Add foreground background = None
view.append(self.parse_embedded_svg(foreground, {})) foreground = None
view_title = None
# Add background for image in images:
background_path = os.path.join(self.data_dir, "sheets", self.get_href(background)) if image.attrib["data-type"] == "background":
background = image
elif image.attrib["data-type"] == "foreground":
foreground = image
elif image.attrib["data-type"] == "view-title":
view_title = image
copy(background_path, os.path.join(self.data_dir, "build", sheet_name)) if foreground is not None:
view.append(self.parse_embedded_svg(foreground, {}))
# Add view title if background is not None:
foreground_path = self.get_href(foreground) background_path = os.path.join(self.data_dir, "sheets", self.get_href(background))
view.append( copy(background_path, os.path.join(self.data_dir, "build", sheet_name))
self.parse_embedded_svg(
view_title, if view_title is not None:
{"no": self.group_number, "name": ntpath.basename(foreground_path)[0:-4], "scale": self.scale}, foreground_path = self.get_href(foreground)
) data = reference.get_info()
) if not data["Name"]:
data["Name"] = ntpath.basename(foreground_path)[0:-4]
data["Scale"] = tool.Drawing.get_drawing_human_scale(drawing)
view.append(self.parse_embedded_svg(view_title, data))
for image in images: for image in images:
view.remove(image) view.remove(image)
self.group_number += 1
def build_schedules(self, schedules): def build_schedules(self, schedules):
for group in schedules: for group in schedules:
images = group.findall("{http://www.w3.org/2000/svg}image") images = group.findall("{http://www.w3.org/2000/svg}image")
@@ -231,15 +245,13 @@ class SheetBuilder:
path = self.get_href(schedule) path = self.get_href(schedule)
group.append( group.append(
self.parse_embedded_svg( self.parse_embedded_svg(
group_title, {"no": self.group_number, "name": ntpath.basename(path)[0:-4], "scale": self.scale} group_title, {"no": 1, "name": ntpath.basename(path)[0:-4], "scale": self.scale}
) )
) )
for image in images: for image in images:
group.remove(image) group.remove(image)
self.group_number += 1
def get_href(self, element): def get_href(self, element):
return urllib.parse.unquote(element.attrib.get("{http://www.w3.org/1999/xlink}href")) return urllib.parse.unquote(element.attrib.get("{http://www.w3.org/1999/xlink}href"))
@@ -453,9 +453,23 @@ class SvgWriter:
(symbol_position * self.scale)[1], (symbol_position * self.scale)[1],
) )
self.svg.add(self.svg.use("#section-arrow", insert=tuple(symbol_position * self.scale), transform=transform)) self.svg.add(
self.svg.use("#section-arrow", insert=tuple(symbol_position * self.scale), transform=transform)
)
self.svg.add(self.svg.use("#section-tag", insert=tuple(symbol_position * self.scale))) self.svg.add(self.svg.use("#section-tag", insert=tuple(symbol_position * self.scale)))
reference_id, sheet_id = self.get_reference_and_sheet_id_from_annotation(tool.Ifc.get_entity(obj))
text_position = list(symbol_position * self.scale)
text_style = {
"font-size": annotation.Annotator.get_svg_text_size(2.5),
"font-family": "OpenGost Type B TT",
"text-anchor": "middle",
"alignment-baseline": "middle",
"dominant-baseline": "middle",
}
self.svg.add(self.svg.text(reference_id, insert=(text_position[0], text_position[1] - 2.5), **text_style))
self.svg.add(self.svg.text(sheet_id, insert=(text_position[0], text_position[1] + 2.5), **text_style))
def draw_elevation_annotation(self, obj): def draw_elevation_annotation(self, obj):
x_offset = self.raw_width / 2 x_offset = self.raw_width / 2
y_offset = self.raw_height / 2 y_offset = self.raw_height / 2
@@ -475,6 +489,34 @@ class SvgWriter:
self.svg.add(self.svg.use("#elevation-arrow", insert=tuple(symbol_position * self.scale), transform=transform)) self.svg.add(self.svg.use("#elevation-arrow", insert=tuple(symbol_position * self.scale), transform=transform))
self.svg.add(self.svg.use("#elevation-tag", insert=tuple(symbol_position * self.scale))) self.svg.add(self.svg.use("#elevation-tag", insert=tuple(symbol_position * self.scale)))
reference_id, sheet_id = self.get_reference_and_sheet_id_from_annotation(tool.Ifc.get_entity(obj))
text_position = list(symbol_position * self.scale)
text_style = {
"font-size": annotation.Annotator.get_svg_text_size(2.5),
"font-family": "OpenGost Type B TT",
"text-anchor": "middle",
"alignment-baseline": "middle",
"dominant-baseline": "middle",
}
self.svg.add(self.svg.text(reference_id, insert=(text_position[0], text_position[1] - 2.5), **text_style))
self.svg.add(self.svg.text(sheet_id, insert=(text_position[0], text_position[1] + 2.5), **text_style))
def get_reference_and_sheet_id_from_annotation(self, element):
reference_id = "-"
sheet_id = "-"
drawing = tool.Drawing.get_annotation_element(element)
reference = tool.Drawing.get_drawing_reference(drawing)
if reference:
sheet = tool.Drawing.get_reference_sheet(reference)
if sheet:
if tool.Ifc.get_schema() == "IFC2X3":
reference_id = reference.ItemReference or "-"
sheet_id = sheet.DocumentId or "-"
else:
reference_id = reference.Identification or "-"
sheet_id = sheet.Identification or "-"
return (reference_id, sheet_id)
return ("-", "-")
def draw_text_annotation(self, text_obj, position): def draw_text_annotation(self, text_obj, position):
x_offset = self.raw_width / 2 x_offset = self.raw_width / 2
@@ -502,7 +544,7 @@ class SvgWriter:
if text_obj.BIMTextProperties.symbol != "None": if text_obj.BIMTextProperties.symbol != "None":
self.svg.add( self.svg.add(
self.svg.use("#{}".format(text_obj.BIMTextProperties.symbol), insert=tuple(text_position * self.scale)) self.svg.use(f"#{text_obj.BIMTextProperties.symbol}", insert=tuple(text_position * self.scale))
) )
if text_literal.BoxAlignment == "top-left": if text_literal.BoxAlignment == "top-left":
@@ -533,11 +575,15 @@ class SvgWriter:
alignment_baseline = "baseline" alignment_baseline = "baseline"
text_anchor = "end" text_anchor = "end"
text_body = text_literal.Literal literal = text_literal.Literal
if text_obj.name in self.annotations.get("template_variables", {}):
text_body = pystache.render(text_body, self.annotations["template_variables"][text_obj.name])
for line_number, text_line in enumerate(text_body.split("\n")): product = tool.Drawing.get_text_product(element)
selector = ifcopenshell.util.selector.Selector
variables = {}
for variable in re.findall("{{.*?}}", literal):
literal = literal.replace(variable, selector.get_element_value(product, variable[2:-2]) or "")
for line_number, text_line in enumerate(literal.replace("\\n", "\n").split("\n")):
self.svg.add( self.svg.add(
self.svg.text( self.svg.text(
text_line, text_line,
@@ -28,6 +28,7 @@ classes = (
operator.UnlinkIfc, operator.UnlinkIfc,
operator.UnloadLink, operator.UnloadLink,
operator.LoadLink, operator.LoadLink,
operator.ToggleLinkVisibility,
operator.SelectLibraryFile, operator.SelectLibraryFile,
operator.ChangeLibraryElement, operator.ChangeLibraryElement,
operator.RefreshLibrary, operator.RefreshLibrary,
@@ -685,10 +685,31 @@ class LoadLink(bpy.types.Operator):
continue continue
bpy.data.scenes[0].collection.children.link(child) bpy.data.scenes[0].collection.children.link(child)
link = context.scene.BIMProjectProperties.links.get(filepath) link = context.scene.BIMProjectProperties.links.get(filepath)
link.collection_name = child.name
link.is_loaded = True link.is_loaded = True
return {"FINISHED"} return {"FINISHED"}
class ToggleLinkVisibility(bpy.types.Operator):
bl_idname = "bim.toggle_link_visibility"
bl_label = "Toggle Link Visibility"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Toggle visibility between SOLID and WIREFRAME"
collection_name: bpy.props.StringProperty()
def execute(self, context):
collection_name = self.collection_name
objs = filter(lambda obj: "IfcOpeningElement" not in obj.name, bpy.data.collections[collection_name].all_objects)
for i,obj in enumerate(objs):
if i == 0:
if obj.display_type == "WIRE":
display_type = "TEXTURED"
else:
display_type = "WIRE"
obj.display_type = display_type
return {"FINISHED"}
class ExportIFC(bpy.types.Operator): class ExportIFC(bpy.types.Operator):
bl_idname = "export_ifc.bim" bl_idname = "export_ifc.bim"
bl_label = "Export IFC" bl_label = "Export IFC"
@@ -85,6 +85,7 @@ class FilterCategory(PropertyGroup):
class Link(PropertyGroup): class Link(PropertyGroup):
name: StringProperty(name="Name") name: StringProperty(name="Name")
collection_name: StringProperty(name="Collection Name")
is_loaded: BoolProperty(name="Is Loaded", default=False) is_loaded: BoolProperty(name="Is Loaded", default=False)
@@ -286,6 +286,8 @@ class BIM_UL_links(UIList):
row = layout.row(align=True) row = layout.row(align=True)
if item.is_loaded: if item.is_loaded:
row.label(text=item.name) row.label(text=item.name)
op = row.operator("bim.toggle_link_visibility", text="", icon="HIDE_OFF")
op.collection_name = item.collection_name
op = row.operator("bim.unload_link", text="", icon="UNLINKED") op = row.operator("bim.unload_link", text="", icon="UNLINKED")
op.filepath = item.name op.filepath = item.name
else: else:
+1 -1
View File
@@ -115,7 +115,7 @@ def add_drawing(ifc, collector, drawing, target_view=None, location_hint=None):
ifc.run("group.assign_group", group=group, product=element) ifc.run("group.assign_group", group=group, product=element)
collector.assign(camera) collector.assign(camera)
pset = ifc.run("pset.add_pset", product=element, name="EPset_Drawing") pset = ifc.run("pset.add_pset", product=element, name="EPset_Drawing")
ifc.run("pset.edit_pset", pset=pset, properties={"TargetView": target_view, "Scale": "1/100"}) ifc.run("pset.edit_pset", pset=pset, properties={"TargetView": target_view, "Scale": "1/100", "HumanScale": "1:100"})
drawing.import_drawings() drawing.import_drawings()
+40 -11
View File
@@ -201,7 +201,7 @@ class Drawing(blenderbim.core.tool.Drawing):
name = document.Identification or "X" name = document.Identification or "X"
else: else:
name = document.DocumentId or "X" name = document.DocumentId or "X"
name += " - " + document.Name or "Unnamed" name += " - " + (document.Name or "Unnamed")
return name return name
@classmethod @classmethod
@@ -291,24 +291,17 @@ class Drawing(blenderbim.core.tool.Drawing):
if not new.is_expanded: if not new.is_expanded:
continue continue
if tool.Ifc.get_schema() == "IFC2X3": for reference in cls.get_document_references(sheet):
references = sheet.DocumentReferences or []
else:
references = sheet.HasDocumentReferences or []
for reference in references:
new = props.sheets.add() new = props.sheets.add()
new.ifc_definition_id = reference.id() new.ifc_definition_id = reference.id()
new.is_sheet = False new.is_sheet = False
if tool.Ifc.get_schema() == "IFC2X3": if tool.Ifc.get_schema() == "IFC2X3":
new.identification = reference.ItemReference or "X" new.identification = reference.ItemReference or "X"
element = [
r for r in tool.Ifc.by_type("IfcRelAssociatesDocument") if r.RelatingDocument == reference
][0].RelatedObjects[0]
else: else:
new.identification = reference.Identification or "X" new.identification = reference.Identification or "X"
element = reference.DocumentRefForObjects[0].RelatedObjects[0]
element = cls.get_reference_element(reference)
new.name = element.Name new.name = element.Name
new.reference_type = "DRAWING" new.reference_type = "DRAWING"
@@ -720,3 +713,39 @@ class Drawing(blenderbim.core.tool.Drawing):
if grid_obj.matrix_world != obj.matrix_world: if grid_obj.matrix_world != obj.matrix_world:
bpy.ops.bim.update_representation(obj=obj.name) bpy.ops.bim.update_representation(obj=obj.name)
tool.Geometry.record_object_position(obj) tool.Geometry.record_object_position(obj)
@classmethod
def get_document_references(cls, document):
if tool.Ifc.get_schema() == "IFC2X3":
return document.DocumentReferences or []
return document.HasDocumentReferences or []
@classmethod
def get_reference_element(cls, reference):
if tool.Ifc.get_schema() == "IFC2X3":
return [
r for r in tool.Ifc.by_type("IfcRelAssociatesDocument") if r.RelatingDocument == reference
][0].RelatedObjects[0]
return reference.DocumentRefForObjects[0].RelatedObjects[0]
@classmethod
def get_drawing_human_scale(cls, drawing):
return ifcopenshell.util.element.get_psets(drawing)["EPset_Drawing"]["HumanScale"]
@classmethod
def get_annotation_element(cls, element):
for rel in element.HasAssignments:
if rel.is_a("IfcRelAssignsToProduct"):
return rel.RelatingProduct
@classmethod
def get_drawing_reference(cls, drawing):
for rel in drawing.HasAssociations:
if rel.is_a("IfcRelAssociatesDocument"):
return rel.RelatingDocument
@classmethod
def get_reference_sheet(cls, reference):
if tool.Ifc.get_schema() == "IFC2X3":
return reference.ReferenceToDocument[0]
return reference.ReferencedDocument
+137 -128
View File
@@ -5,14 +5,14 @@ Installation
There are different methods of installation, depending on your situation. There are different methods of installation, depending on your situation.
1. **Packaged installation** is recommended for regular users. 1. **Stable installation** is recommended for regular users.
2. **Daily build installation** is recommended for power users helping with testing. 2. **Unstable installation** is recommended for power users helping with testing.
3. **Unpackaged installation** is recommended for package managers. 3. **Building from source** is recommended for distributing a build from source.
4. **Distro installation** is recommended for those who use a Linux package manager. 4. **Live development environment** is recommended for developers who are actively coding.
5. **Source installation** is recommended for developers. 5. **Distro installation** is recommended for those who use a Linux package manager.
Packaged installation Stable installation
--------------------- -------------------
The BlenderBIM Add-on is packaged like a regular Blender add-on, so installation The BlenderBIM Add-on is packaged like a regular Blender add-on, so installation
is the same as any other Blender add-on. The full instructions for end-user is the same as any other Blender add-on. The full instructions for end-user
@@ -24,25 +24,129 @@ Like all Blender add-ons, they can be installed using ``Edit > Preferences >
Addons > Install > Choose Downloaded ZIP > Enable Add-on Checkbox``. You can Addons > Install > Choose Downloaded ZIP > Enable Add-on Checkbox``. You can
enable add-ons permanently by using ``Save User Settings`` from the Addons menu. enable add-ons permanently by using ``Save User Settings`` from the Addons menu.
Daily build installation Unstable installation
------------------------ ---------------------
Daily builds are almost the same as **Packaged installation**, except that they **Unstable installation** is almost the same as **Stable installation**, except
are typically updated every day. Simply download a daily build from the `Github that they are typically updated every day. Simply download a daily build from
releases page <https://github.com/IfcOpenShell/IfcOpenShell/releases>`__, then the `Github releases page
follow the same instructions as a packaged installation. <https://github.com/IfcOpenShell/IfcOpenShell/releases>`__, then follow the same
instructions as a packaged installation.
You will need to choose which daily build to download. You will need to choose which build to download.
- If you are on Blender >=3.1, choose py310
- If you are on Blender >=2.93 and <3.1, choose py39
- If you are on Blender <2.93, choose py37 - If you are on Blender <2.93, choose py37
- If you are on Blender >=2.93, choose py39
- Choose linux, macos, or win depending on your operating system - Choose linux, macos, or win depending on your operating system
Daily builds are not always stable. Sometimes, a build may be delayed, or Sometimes, a build may be delayed, or contain broken code. We try to avoid this,
contain broken code. We try to avoid this, but it happens. but it happens.
Unpackaged installation Building from source
----------------------- --------------------
It is possible to run the latest bleeding edge version of BlenderBIM without
having to wait for an official release, since BlenderBIM is coded in Python and
doesn't require any compilation.
Note that the BlenderBIM Add-on does depend on IfcOpenShell, and IfcOpenShell
does require compilation. The following instructions will use a pre-built
IfcOpenShell (using an IfcOpenBot build) for convenience. Instructions on how to
compile IfcOpenShell is out of scope of this document.
You can create your own package by using the Makefile as shown below. You can
choose between a ``PLATFORM`` of ``linux``, ``macos``, and ``win``. You can
choose between a ``PYVERSION`` of ``py39``, ``py37``, or ``py310``.
::
$ cd src/blenderbim
$ make dist PLATFORM=linux PYVERSION=py310
$ ls dist/
This will give you a fully packaged Blender add-on zip that you can distribute
and install.
Live development environment
----------------------------
One option for developers who want to actively develop from source is to follow
the instructions from **Building from source**. However, creating a build,
uninstalling the old add-on, and installing a new build is a slow process.
Although it works, it is very slow, so we do not recommend it.
A more rapid approach is to follow the **Unstable installation** method, as this
provides all dependencies for you out of the box. Then, we can replace certain
Python files that tend to be updated frequently with those from the Git
repository. We're going to use symlinks (Windows users can use ``mklink``), so
we can code in our Git repository, and see the changes in our Blender
installation (you will need to restart Blender to see changes).
In addition, we're also going to replace the Python code of the IfcOpenShell
dependency with our Git repository, since most of the BlenderBIM Add-on
functionality is agnostic of Blender, and is actually part of IfcOpenShell.
Therefore, we need to keep this dependency highly updated as well.
The downside with this approach is that if a new dependency is added, or a
compiled dependency version requirement has changed, or the build system
changes, you'll need to fix your setup manually. But this is relatively rare.
::
$ git clone https://github.com/IfcOpenShell/IfcOpenShell.git
$ cd IfcOpenShell
# Remove the Blender add-on Python code
$ rm -r /path/to/blender/X.XX/scripts/addons/blenderbim/bim/
# Replace them with links to the Git repository
$ ln -s src/blenderbim/blenderbim/bim /path/to/blender/X.XX/scripts/addons/blenderbim/bim
# Remove the IfcOpenShell dependency Python code
$ rm -r /path/to/blender/X.XX/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api
$ rm -r /path/to/blender/X.XX/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/util
# Replace them with links to the Git repository
$ ln -s src/ifcopenshell-python/ifcopenshell/api /path/to/blender/X.XX/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api
$ ln -s src/ifcopenshell-python/ifcopenshell/util /path/to/blender/X.XX/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/util
On Windows:
::
$ git clone https://github.com/IfcOpenShell/IfcOpenShell.git
$ cd IfcOpenShell
# Remove the Blender add-on Python code
$ rd /S /Q "\path\to\blender\X.XX\scripts\addons\blenderbim\bim\"
# Replace them with links to the Git repository
$ mklink /D "\path\to\blender\X.XX\scripts\addons\blenderbim\bim" "src\blenderbim\blenderbim\bim"
# Remove the IfcOpenShell dependency Python code
$ rd \S \Q "\path\to\blender\X.XX\scripts\addons\blenderbim\libs\site\packages\ifcopenshell\api"
$ rd \S \Q "\path\to\blender\X.XX\scripts\addons\blenderbim\libs\site\packages\ifcopenshell\util"
# Replace them with links to the Git repository
$ mklink \D "\path\to\blender\X.XX\scripts\addons\blenderbim\libs\site\packages\ifcopenshell\api" "src\ifcopenshell-python\ifcopenshell\api"
$ mklink \D "\path\to\blender\X.XX\scripts\addons\blenderbim\libs\site\packages\ifcopenshell\util" "src\ifcopenshell-python\ifcopenshell\util"
After you modify your code in the Git repository, you will need to restart
Blender for the changes to take effect. In ``Edit > Preferences > Add-ons`` you
will see that the version number of the BlenderBIM Add-on has changed to
``0.0.999999``, which represents an un-versioned BlenderBIM Add-on.
Distro installation
-------------------
Those on Arch Linux can check out this `AUR package <https://aur.archlinux.org/packages/ifcopenshell-git/>`__.
Tips for package managers
-------------------------
If you are interested in packaging the BlenderBIM Add-on for a packaging
manager, read on.
The BlenderBIM Add-on is fully contained in the ``blenderbim/`` subfolder of the The BlenderBIM Add-on is fully contained in the ``blenderbim/`` subfolder of the
Blender add-ons directory. This is typically distributed as a zipfile as per Blender add-ons directory. This is typically distributed as a zipfile as per
@@ -58,9 +162,8 @@ This corresponds to the structure found in the source code `here
<https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.6.0/src/blenderbim/blenderbim>`__. <https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.6.0/src/blenderbim/blenderbim>`__.
The BlenderBIM Add-on is complex, and requires many dependencies, including The BlenderBIM Add-on is complex, and requires many dependencies, including
Python modules, binaries, and static assets. These dependencies are bundled with Python modules, binaries, and static assets. When packaged for users, these
the add-on for convenience in the **Packaged installation** and **Daily build dependencies are bundled with the add-on for convenience.
installation** methods.
If you choose to install the BlenderBIM Add-on and use your own system If you choose to install the BlenderBIM Add-on and use your own system
dependencies, the source of truth for how dependencies are bundled are found in dependencies, the source of truth for how dependencies are bundled are found in
@@ -92,7 +195,7 @@ Required Python modules to be stored in ``libs/site/packages/`` are:
elementpath elementpath
six six
lark-parser lark-parser
fcl hppfcl
behave behave
parse parse
parse_type parse_type
@@ -108,14 +211,8 @@ Required Python modules to be stored in ``libs/site/packages/`` are:
Notes: Notes:
1. ``ifcopenshell`` almost always requires the latest version due to the fast paced nature of the add-on development. 1. ``ifcopenshell`` almost always requires the latest version due to the fast paced nature of the add-on development.
2. ``fcl`` is not bundled for MacOS, due to lack of maintained community build. This is required for clash detection. 2. ``behave`` requires `patches <https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.6.0/src/ifcbimtester/patch>`__.
3. ``behave`` requires `patches <https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.6.0/src/ifcbimtester/patch>`__. 3. ``ifcjson`` can be found `here <https://github.com/IFCJSON-Team/IFC2JSON_python/tree/master/file_converters>`__.
4. ``ifcjson`` can be found `here <https://github.com/IFCJSON-Team/IFC2JSON_python/tree/master/file_converters>`__.
Required binaries are:
::
libs/IfcConvert
Required static assets are: Required static assets are:
:: ::
@@ -123,121 +220,31 @@ Required static assets are:
bim/data/gantt/jsgantt.js (from jsgantt-improved) bim/data/gantt/jsgantt.js (from jsgantt-improved)
bim/data/gantt/jsgantt.css (from jsgantt-improved) bim/data/gantt/jsgantt.css (from jsgantt-improved)
Distro installation
-------------------
Those on Arch Linux can check out this `AUR package <https://aur.archlinux.org/packages/ifcopenshell-git/>`__.
Source installation
-------------------
It is possible to run the latest bleeding edge version of BlenderBIM without
having to wait for an official release, since BlenderBIM is coded in Python and
doesn't require any compilation.
Note that the BlenderBIM Add-on does depend on IfcOpenShell, and IfcOpenShell
does require compilation. The following instructions will use a pre-built
IfcOpenShell (using an IfcOpenBot build) for convenience. Instructions on how to
compile IfcOpenShell is out of scope of this document.
You can create your own package by using the Makefile as shown below. You can
choose between a ``PLATFORM`` of ``linux``, ``macos``, and ``win``. You can
choose between a ``PYVERSION`` of ``py39`` and ``py37``.
::
$ cd src/blenderbim
$ make dist PLATFORM=linux PYVERSION=py39
$ ls dist/
However, creating a build, uninstalling the old add-on, and installing a new
build is a slow process. You can do this, but we do not recommend it. A more
rapid approach is to follow the **Daily build installation** method, as this
provides all dependencies for you out of the box. Then, we can replace certain
Python files that tend to be updated frequently with those from the Git
repository. We're going to use symlinks (Windows users can use ``mklink``), so
we can code in our Git repository, and see the changes in our Blender
installation.
In addition, we're also going to replace the Python code of the IfcOpenShell
dependency with our Git repository, since most of the BlenderBIM Add-on
functionality is agnostic of Blender, and is actually part of IfcOpenShell.
Therefore, we need to keep this dependency highly updated as well.
The downside with this approach is that if a new dependency is added, or a
compiled dependency version requirement has changed, or the build system
changes, you'll need to fix your setup manually. But this is relatively rare.
::
$ git clone https://github.com/IfcOpenShell/IfcOpenShell.git
$ cd IfcOpenShell
# Remove the Blender add-on Python code
$ rm -r /path/to/blender/2.XX/scripts/addons/blenderbim/bim/
# Replace them with links to the Git repository
$ ln -s src/blenderbim/blenderbim/bim /path/to/blender/2.XX/scripts/addons/blenderbim/bim
# Remove the IfcOpenShell dependency Python code
$ rm -r /path/to/blender/2.XX/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api
$ rm -r /path/to/blender/2.XX/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/util
# Replace them with links to the Git repository
$ ln -s src/ifcopenshell-python/ifcopenshell/api /path/to/blender/2.XX/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api
$ ln -s src/ifcopenshell-python/ifcopenshell/util /path/to/blender/2.XX/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/util
On Windows:
::
$ git clone https://github.com/IfcOpenShell/IfcOpenShell.git
$ cd IfcOpenShell
# Remove the Blender add-on Python code
$ rd /S /Q "\path\to\blender\2.XX\scripts\addons\blenderbim\bim\"
# Replace them with links to the Git repository
$ mklink /D "\path\to\blender\2.XX\scripts\addons\blenderbim\bim" "src\blenderbim\blenderbim\bim"
# Remove the IfcOpenShell dependency Python code
$ rd \S \Q "\path\to\blender\2.XX\scripts\addons\blenderbim\libs\site\packages\ifcopenshell\api"
$ rd \S \Q "\path\to\blender\2.XX\scripts\addons\blenderbim\libs\site\packages\ifcopenshell\util"
# Replace them with links to the Git repository
$ mklink \D "\path\to\blender\2.XX\scripts\addons\blenderbim\libs\site\packages\ifcopenshell\api" "src\ifcopenshell-python\ifcopenshell\api"
$ mklink \D "\path\to\blender\2.XX\scripts\addons\blenderbim\libs\site\packages\ifcopenshell\util" "src\ifcopenshell-python\ifcopenshell\util"
After you modify your code in the Git repository, you will need to restart
Blender for the changes to take effect. In ``Edit > Preferences > Add-ons`` you
will see that the version number of BlenderBIM has changed to ``0.0.999999``,
which represents an un-versioned BlenderBIM.
Where is the BlenderBIM Add-on installed? Where is the BlenderBIM Add-on installed?
----------------------------------------- -----------------------------------------
If you downloaded Blender as a ``.zip`` file without running an installer, you If you downloaded Blender as a ``.zip`` file without running an installer, you
will find the BlenderBIM Add-on installed in the following directory, where will find the BlenderBIM Add-on installed in the following directory, where
``2.XX`` is the Blender version: ``X.XX`` is the Blender version:
:: ::
/path/to/blender/2.XX/scripts/addons/ /path/to/blender/X.XX/scripts/addons/
Otherwise, if you installed Blender using an installation package, the add-ons Otherwise, if you installed Blender using an installation package, the add-ons
folder depends on which operating system you use. On Linux: folder depends on which operating system you use. On Linux:
:: ::
~/.config/blender/2.XX/scripts/addons/ ~/.config/blender/X.XX/scripts/addons/
On Mac: On Mac:
:: ::
/Users/{YOUR_USER}/Library/Application Support/Blender/2.XX/ /Users/{YOUR_USER}/Library/Application Support/Blender/X.XX/
On Windows: On Windows:
:: ::
C:\Users\{YOUR_USER}\AppData\Roaming\Blender Foundation\2.XX\scripts\addons C:\Users\{YOUR_USER}\AppData\Roaming\Blender Foundation\X.XX\scripts\addons
Upon installation, the BlenderBIM Add-on is stored in the ``blenderbim/`` Upon installation, the BlenderBIM Add-on is stored in the ``blenderbim/``
directory. directory.
@@ -264,8 +271,10 @@ FAQ
1. I get an error similar to "ImportError: IfcOpenShell not built for 'linux/64bit/python3.7'" 1. I get an error similar to "ImportError: IfcOpenShell not built for 'linux/64bit/python3.7'"
If you are using Blender <2.93, then you need to use a daily build. See the Check which BlenderBIM Add-on build you are using. The zip will have either
instructions above for a daily build installation. ``py37``, ``py39``, or ``py310`` in the name. See the instructions in the
**Unstable installation** section to check that you have installed the correct
version.
2. I am on Ubuntu and get an error similar to "ImportError: /lib/x86_64-linux-gnu/libm.so.6: version GLIBC_2.29 not found" 2. I am on Ubuntu and get an error similar to "ImportError: /lib/x86_64-linux-gnu/libm.so.6: version GLIBC_2.29 not found"
+15 -3
View File
@@ -111,6 +111,18 @@ public:
std::map<int, TopoDS_Shape> Shape; std::map<int, TopoDS_Shape> Shape;
}; };
namespace util {
template <typename T>
typename std::enable_if<std::is_pointer<T>::value, T&>::type conditional_address_of(T& t) {
return t;
}
template <typename T>
typename std::enable_if<!std::is_pointer<T>::value, T*>::type conditional_address_of(T& t) {
return &t;
}
}
class IFC_GEOM_API MAKE_TYPE_NAME(Kernel) : public IfcGeom::Kernel { class IFC_GEOM_API MAKE_TYPE_NAME(Kernel) : public IfcGeom::Kernel {
private: private:
@@ -126,7 +138,7 @@ private:
class faceset_helper { class faceset_helper {
private: private:
MAKE_TYPE_NAME(Kernel)* kernel_; MAKE_TYPE_NAME(Kernel)* kernel_;
std::set<LP> duplicates_; std::set<typename std::conditional<std::is_pointer<LP>::value, LP, const LP*>::type> duplicates_;
std::map<const void*, int> vertex_mapping_; std::map<const void*, int> vertex_mapping_;
std::map<std::pair<int, int>, TopoDS_Edge> edges_; std::map<std::pair<int, int>, TopoDS_Edge> edges_;
// not always in use // not always in use
@@ -225,8 +237,8 @@ private:
return true; return true;
} }
bool wire(LP loop, TopoDS_Wire& wire) { bool wire(const LP& loop, TopoDS_Wire& wire) {
if (duplicates_.find(loop) != duplicates_.end()) { if (duplicates_.find(util::conditional_address_of(loop)) != duplicates_.end()) {
return false; return false;
} }
BRep_Builder builder; BRep_Builder builder;
+3 -3
View File
@@ -5613,7 +5613,7 @@ IfcGeom::Kernel::faceset_helper<CP, LP>::faceset_helper(
if (edge_sets.find(segment_set) != edge_sets.end()) { if (edge_sets.find(segment_set) != edge_sets.end()) {
duplicate_faces++; duplicate_faces++;
duplicates_.insert(*ps); duplicates_.insert(util::conditional_address_of(*ps));
continue; continue;
} }
edge_sets.insert(segment_set); edge_sets.insert(segment_set);
@@ -5646,8 +5646,8 @@ IfcGeom::Kernel::faceset_helper<CP, LP>::faceset_helper(
} }
} }
if (loops_removed || (non_manifold && should_be_closed)) { if (duplicates_.size() || loops_removed || (non_manifold && should_be_closed)) {
Logger::Warning(boost::lexical_cast<std::string>(duplicate_faces) + " duplicate faces removed, " + boost::lexical_cast<std::string>(loops_removed) + " loops removed and " + boost::lexical_cast<std::string>(non_manifold) + " non-manifold edges"); Logger::Warning(boost::lexical_cast<std::string>(duplicate_faces) + " duplicate faces removed, " + boost::lexical_cast<std::string>(loops_removed) + " degenerate loops eliminated and " + boost::lexical_cast<std::string>(non_manifold) + " non-manifold edges");
} }
} }