| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | """This module contains geometry editing and geometry properties-related tools""" |
| |
|
| | import ifcopenshell |
| | import ifcopenshell.util.unit |
| |
|
| | import FreeCAD |
| |
|
| | from . import ifc_tools |
| |
|
| |
|
| | def add_geom_properties(obj): |
| | """Adds geometry properties to a FreeCAD object""" |
| |
|
| | element = ifc_tools.get_ifc_element(obj) |
| | if not ifc_tools.has_representation(element): |
| | return |
| | ifcfile = ifc_tools.get_ifcfile(obj) |
| | scaling = ifcopenshell.util.unit.calculate_unit_scale(ifcfile) |
| | scaling = scaling * 1000 |
| | for rep in element.Representation.Representations: |
| | if rep.RepresentationIdentifier == "Body": |
| | if len(rep.Items) == 1: |
| | |
| | if rep.Items[0].is_a("IfcExtrudedAreaSolid"): |
| | ext = rep.Items[0] |
| | if "ExtrusionDepth" not in obj.PropertiesList: |
| | obj.addProperty( |
| | "App::PropertyLength", "ExtrusionDepth", "Geometry", locked=True |
| | ) |
| | obj.ExtrusionDepth = ext.Depth * scaling |
| | if "ExtrusionDirection" not in obj.PropertiesList: |
| | obj.addProperty( |
| | "App::PropertyVector", "ExtrusionDirection", "Geometry", locked=True |
| | ) |
| | obj.ExtrusionDirection = FreeCAD.Vector(ext.ExtrudedDirection.DirectionRatios) |
| |
|
| | |
| | if ext.SweptArea.is_a("IfcRectangleProfileDef"): |
| | if "RectangleLength" not in obj.PropertiesList: |
| | obj.addProperty( |
| | "App::PropertyLength", "RectangleLength", "Geometry", locked=True |
| | ) |
| | obj.RectangleLength = ext.SweptArea.XDim * scaling |
| | if "RectangleWidth" not in obj.PropertiesList: |
| | obj.addProperty( |
| | "App::PropertyLength", "RectangleWidth", "Geometry", locked=True |
| | ) |
| | obj.RectangleWidth = ext.SweptArea.YDim * scaling |
| |
|
| | |
| | elif ext.SweptArea.is_a("IfcArbitraryClosedProfileDef"): |
| | if ext.SweptArea.OuterCurve.is_a("IfcPolyline"): |
| | if "PolylinePoints" not in obj.PropertiesList: |
| | obj.addProperty( |
| | "App::PropertyVectorList", |
| | "PolylinePoints", |
| | "Geometry", |
| | locked=True, |
| | ) |
| | points = [p.Coordinates for p in ext.SweptArea.OuterCurve.Points] |
| | points = [p + (0,) for p in points if len(p) < 3] |
| | points = [FreeCAD.Vector(p).multiply(scaling) for p in points] |
| | obj.PolylinePoints = points |
| |
|
| | |
| | elif ext.SweptArea.is_a("IfcIShapeProfileDef"): |
| | for p in [ |
| | "FilletRadius", |
| | "FlangeEdgeRadius", |
| | "FlangeSlope", |
| | "FlangeThickness", |
| | "OverallDepth", |
| | "OverallWidth", |
| | "WebThickness", |
| | ]: |
| | if hasattr(ext.SweptArea, p): |
| | obj.addProperty("App::PropertyLength", p, "Geometry", locked=True) |
| | value = getattr(ext.SweptArea, p) |
| | if not value: |
| | value = 0 |
| | value = value * scaling |
| | setattr(obj, p, value) |
| | obj.addProperty( |
| | "App::PropertyString", "ProfileName", "Geometry", locked=True |
| | ) |
| | obj.ProfileName = ext.SweptArea.ProfileName |
| |
|
| | |
| | elif False: |
| | |
| | if len(rep.Items) == 1: |
| | if rep.Items[0].is_a("IfcCompositeCurve"): |
| | if len(rep.Items[0].Segments) == 1: |
| | if rep.Items[0].Segments[0].is_a("IfcCompositeCurveSegment"): |
| | if rep.Items[0].Segments[0].ParentCurve.is_a("IfcPolyline"): |
| | pol = rep.Items[0].Segments[0].ParentCurve |
| | if len(pol.Points) == 2: |
| | if "AxisStart" not in obj.PropertiesList: |
| | obj.addProperty( |
| | "App::PropertyPosition", |
| | "AxisStart", |
| | "Geometry", |
| | locked=True, |
| | ) |
| | obj.AxisStart = FreeCAD.Vector( |
| | pol.Points[0].Coordinates |
| | ).multiply(scaling) |
| | if "AxisEnd" not in obj.PropertiesList: |
| | obj.addProperty( |
| | "App::PropertyPosition", |
| | "AxisEnd", |
| | "Geometry", |
| | locked=True, |
| | ) |
| | obj.AxisEnd = FreeCAD.Vector( |
| | pol.Points[1].Coordinates |
| | ).multiply(scaling) |
| |
|
| |
|
| | def set_attribute(ifcfile, element, prop, value): |
| | """Sets an attribute. Returns True if the attribute was changed""" |
| |
|
| | if value != getattr(element, prop): |
| | ifc_tools.api_run( |
| | "attribute.edit_attributes", |
| | ifcfile, |
| | product=element, |
| | attributes={prop: value}, |
| | ) |
| | return True |
| | return False |
| |
|
| |
|
| | def set_geom_property(obj, prop): |
| | """Updates the internal IFC file with the given value""" |
| |
|
| | |
| |
|
| | element = ifc_tools.get_ifc_element(obj) |
| | if not ifc_tools.has_representation(element): |
| | return False |
| | ifcfile = ifc_tools.get_ifcfile(obj) |
| | scaling = ifcopenshell.util.unit.calculate_unit_scale(ifcfile) |
| | scaling = 0.001 / scaling |
| | changed = False |
| |
|
| | if prop == "ExtrusionDepth": |
| | for rep in element.Representation.Representations: |
| | if rep.RepresentationIdentifier == "Body": |
| | if len(rep.Items) == 1: |
| | if rep.Items[0].is_a("IfcExtrudedAreaSolid"): |
| | elem = rep.Items[0] |
| | value = getattr(obj, prop).Value * scaling |
| | changed = set_attribute(ifcfile, elem, "Depth", value) |
| |
|
| | elif prop == "ExtrusionDirection": |
| | for rep in element.Representation.Representations: |
| | if rep.RepresentationIdentifier == "Body": |
| | if len(rep.Items) == 1: |
| | if rep.Items[0].is_a("IfcExtrudedAreaSolid"): |
| | elem = rep.Items[0].ExtrudedDirection |
| | value = tuple(getattr(obj, prop)) |
| | changed = set_attribute(ifcfile, elem, "DirectionRatios", value) |
| |
|
| | elif prop == "RectangleLength": |
| | for rep in element.Representation.Representations: |
| | if rep.RepresentationIdentifier == "Body": |
| | if len(rep.Items) == 1: |
| | if rep.Items[0].is_a("IfcExtrudedAreaSolid"): |
| | elem = rep.Items[0].SweptArea |
| | if elem.is_a("IfcRectangleProfileDef"): |
| | value = getattr(obj, prop).Value * scaling |
| | changed = set_attribute(ifcfile, elem, "XDim", value) |
| |
|
| | elif prop == "RectangleWidth": |
| | for rep in element.Representation.Representations: |
| | if rep.RepresentationIdentifier == "Body": |
| | if len(rep.Items) == 1: |
| | if rep.Items[0].is_a("IfcExtrudedAreaSolid"): |
| | elem = rep.Items[0].SweptArea |
| | if elem.is_a("IfcRectangleProfileDef"): |
| | value = getattr(obj, prop).Value * scaling |
| | changed = set_attribute(ifcfile, elem, "YDim", value) |
| |
|
| | elif prop == "PolylinePoints": |
| | |
| | for rep in element.Representation.Representations: |
| | if rep.RepresentationIdentifier == "Body": |
| | if len(rep.Items) == 1: |
| | if rep.Items[0].is_a("IfcExtrudedAreaSolid"): |
| | if rep.Items[0].SweptArea.is_a("IfcArbitraryClosedProfileDef"): |
| | if rep.Items[0].SweptArea.OuterCurve.is_a("IfcPolyline"): |
| | elem = rep.Items[0].SweptArea.OuterCurve |
| | elem_points = elem.Points |
| | psize = elem_points[0].Dim |
| | points = getattr(obj, prop) |
| | if len(points) > len(elem_points): |
| | for i in range(len(points) - len(elem_points)): |
| | p = ifc_tools.api_run( |
| | "root.create_entity", |
| | ifcfile, |
| | ifc_class="IfcCartesianPoint", |
| | ) |
| | elem_points.append(p) |
| | elem.Points = elem_points |
| | elif len(points) < len(elem_points): |
| | rest = [] |
| | for i in range(len(elem_points) - len(points)): |
| | rest.append(elem_points.pop()) |
| | elem.Points = elem_points |
| | for r in rest: |
| | ifc_tools.api_run("root.remove_product", ifcfile, product=r) |
| | if len(points) == len(elem_points): |
| | for i in range(len(points)): |
| | v = FreeCAD.Vector(points[i]).multiply(scaling) |
| | coord = tuple(v)[:psize] |
| | ifc_tools.api_run( |
| | "attribute.edit_attributes", |
| | ifcfile, |
| | product=elem_points[i], |
| | attributes={"Coordinates": coord}, |
| | ) |
| | changed = True |
| |
|
| | elif prop in [ |
| | "FilletRadius", |
| | "FlangeEdgeRadius", |
| | "FlangeSlope", |
| | "FlangeThickness", |
| | "OverallDepth", |
| | "OverallWidth", |
| | "WebThickness", |
| | ]: |
| | for rep in element.Representation.Representations: |
| | if rep.RepresentationIdentifier == "Body": |
| | if len(rep.Items) == 1: |
| | if rep.Items[0].SweptArea.is_a("IfcIShapeProfileDef"): |
| | elem = rep.Items[0].SweptArea |
| | value = getattr(obj, prop).Value * scaling |
| | if value == 0 and getattr(elem, prop) is None: |
| | value = None |
| | changed = set_attribute(ifcfile, elem, prop, value) |
| |
|
| | elif prop in ["ProfileName"]: |
| | for rep in element.Representation.Representations: |
| | if rep.RepresentationIdentifier == "Body": |
| | if len(rep.Items) == 1: |
| | if rep.Items[0].SweptArea.is_a("IfcIShapeProfileDef"): |
| | elem = rep.Items[0].SweptArea |
| | value = obj.ProfileName |
| | changed = set_attribute(ifcfile, elem, prop, value) |
| |
|
| | if changed: |
| | FreeCAD.Console.PrintLog( |
| | "DEBUG: Changing prop" |
| | + obj.Label |
| | + ":" |
| | + str(prop) |
| | + "to" |
| | + str(getattr(obj, prop)) |
| | + "\n" |
| | ) |
| | return changed |
| |
|