BIM: NativeIFC 2D support - optimized export of FreeCAD dimensions
This commit is contained in:
committed by
Yorik van Havre
parent
43b2411996
commit
c0d452f6c5
@@ -1676,13 +1676,31 @@ def buildAddress(obj,ifcfile):
|
||||
return addr
|
||||
|
||||
|
||||
def createCurve(ifcfile,wire,scaling=1.0):
|
||||
def createCurve(ifcfile, wire, scaling=1.0):
|
||||
"""creates an IfcIndexdPolyCurve from a wire
|
||||
if possible, or defects to createCurveWithArcs"""
|
||||
|
||||
if wire.ShapeType != "Wire":
|
||||
return createCurveWithArcs(ifcfile, wire, scaling)
|
||||
for e in wire.Edges:
|
||||
if isinstance(e.Curve,Part.Circle):
|
||||
return createCurveWithArcs(ifcfile, wire, scaling)
|
||||
verts = [v.Point for v in wire.Vertexes]
|
||||
if scaling != 1:
|
||||
verts = [v.multiply(scaling) for v in verts]
|
||||
verts = tuple([tuple(v) for v in verts])
|
||||
pts = ifcfile.createIfcCartesianPointList3D(verts)
|
||||
idc = ifcfile.createIfcIndexedPolyCurve(pts, None, None)
|
||||
return idc
|
||||
|
||||
|
||||
def createCurveWithArcs(ifcfile,wire,scaling=1.0):
|
||||
"creates an IfcCompositeCurve from a shape"
|
||||
|
||||
segments = []
|
||||
pol = None
|
||||
last = None
|
||||
if wire.ShapeType == "edge":
|
||||
if wire.ShapeType == "Edge":
|
||||
edges = [wire]
|
||||
else:
|
||||
edges = Part.__sortEdges__(wire.Edges)
|
||||
@@ -2512,11 +2530,13 @@ def create_annotation(anno, ifcfile, context, history, preferences):
|
||||
if curves:
|
||||
reps.append(ifcfile.createIfcGeometricCurveSet(curves))
|
||||
curves = []
|
||||
# leftover edges
|
||||
for e in sh.Edges:
|
||||
if e.hashCode not in ehc:
|
||||
if e.hashCode() not in ehc:
|
||||
curves.append(createCurve(ifcfile,e))
|
||||
if curves:
|
||||
reps.append(ifcfile.createIfcGeometricCurveSet(curves))
|
||||
# Append text
|
||||
l = FreeCAD.Vector(vp.tbase).multiply(preferences['SCALE_FACTOR'])
|
||||
zdir = None
|
||||
xdir = None
|
||||
|
||||
@@ -774,8 +774,9 @@ def getVector(entity,scaling=1000):
|
||||
return v
|
||||
|
||||
|
||||
def get2DShape(representation,scaling=1000):
|
||||
"""Returns a shape from a 2D IfcShapeRepresentation"""
|
||||
def get2DShape(representation,scaling=1000,notext=False):
|
||||
"""Returns a shape from a 2D IfcShapeRepresentation
|
||||
if notext is True, no Draft text is created"""
|
||||
|
||||
import Part
|
||||
import DraftVecUtils
|
||||
@@ -885,9 +886,9 @@ def get2DShape(representation,scaling=1000):
|
||||
[p1, p2, p3] = index2points(s)
|
||||
result.append(Part.Arc(p1, p2, p3))
|
||||
else:
|
||||
raise RuntimeError("Illegal IfcIndexedPolyCurve segment")
|
||||
raise RuntimeError("Illegal IfcIndexedPolyCurve segment: "+s.is_a())
|
||||
else:
|
||||
print("getCurveSet: unhandled element: ", el)
|
||||
print("importIFCHelper.getCurveSet: unhandled element: ", el)
|
||||
|
||||
return result
|
||||
|
||||
@@ -909,6 +910,8 @@ def get2DShape(representation,scaling=1000):
|
||||
else:
|
||||
result = preresult
|
||||
elif item.is_a("IfcTextLiteral"):
|
||||
if notext:
|
||||
continue
|
||||
pl = getPlacement(item.Placement, scaling)
|
||||
if pl:
|
||||
t = Draft.make_text(item.Literal.split(";"), pl)
|
||||
|
||||
@@ -139,15 +139,17 @@ def get_dimension(annotation):
|
||||
if annotation.ObjectType == "DIMENSION":
|
||||
s = ifcopenshell.util.unit.calculate_unit_scale(annotation.file) * 1000
|
||||
for rep in annotation.Representation.Representations:
|
||||
shape = importIFCHelper.get2DShape(rep, s)
|
||||
shape = importIFCHelper.get2DShape(rep, s, notext=True)
|
||||
if shape and len(shape) == 1:
|
||||
if len(shape[0].Vertexes) >= 2:
|
||||
# two-point polyline (BBIM)
|
||||
res = [rep, shape[0].Vertexes[0].Point, shape[0].Vertexes[-1].Point]
|
||||
if len(shape[0].Vertexes) > 2:
|
||||
# 4-point polyline (FreeCAD)
|
||||
res.append(shape[0].Vertexes[0].Point)
|
||||
res.append(shape[0].Vertexes[1].Point)
|
||||
return res
|
||||
else:
|
||||
print(annotation,"NOT A DIMENSION")
|
||||
return None
|
||||
|
||||
|
||||
|
||||
@@ -564,7 +564,7 @@ def get_annotation_shape(annotation, ifcfile, coin=False):
|
||||
shapes2d = []
|
||||
for rep in annotation.Representation.Representations:
|
||||
if rep.RepresentationIdentifier in ["Annotation", "FootPrint", "Axis"]:
|
||||
sh = importIFCHelper.get2DShape(rep, ifcscale)
|
||||
sh = importIFCHelper.get2DShape(rep, ifcscale, notext=True)
|
||||
if sh:
|
||||
shapes2d.extend(sh)
|
||||
if shapes2d:
|
||||
|
||||
@@ -257,10 +257,10 @@ def create_object(ifcentity, document, ifcfile, shapemode=0, objecttype=None):
|
||||
)
|
||||
if not objecttype:
|
||||
if ifcentity.is_a("IfcAnnotation"):
|
||||
if ifc_export.get_text(ifcentity):
|
||||
objecttype = "text"
|
||||
elif ifc_export.get_dimension(ifcentity):
|
||||
if ifc_export.get_dimension(ifcentity):
|
||||
objecttype = "dimension"
|
||||
elif ifc_export.get_text(ifcentity):
|
||||
objecttype = "text"
|
||||
FreeCAD.Console.PrintLog(s)
|
||||
obj = add_object(document, otype=objecttype)
|
||||
add_properties(obj, ifcfile, ifcentity, shapemode=shapemode)
|
||||
@@ -656,33 +656,32 @@ def add_properties(
|
||||
setattr(obj, attr, str(value))
|
||||
# annotation properties
|
||||
if ifcentity.is_a("IfcAnnotation"):
|
||||
text = ifc_export.get_text(ifcentity)
|
||||
if text:
|
||||
# the two props below are already taken care of, normally
|
||||
if "Placement" not in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyPlacement", "Placement", "Base")
|
||||
if "Text" not in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyStringList", "Text", "Base")
|
||||
obj.Text = [text.Literal]
|
||||
obj.Placement = ifc_export.get_placement(ifcentity.ObjectPlacement, ifcfile)
|
||||
dim = ifc_export.get_dimension(ifcentity)
|
||||
if dim and len(dim) >= 3:
|
||||
if "Start" not in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyVectorDistance", "Start", "Base")
|
||||
if "End" not in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyVectorDistance", "End", "Base")
|
||||
if "Dimline" not in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyVectorDistance", "Dimline", "Base")
|
||||
obj.Start = dim[1]
|
||||
obj.End = dim[2]
|
||||
if len(dim) > 3:
|
||||
obj.Dimline = dim[3]
|
||||
else:
|
||||
mid = obj.End.sub(obj.Start)
|
||||
mid.multiply(0.5)
|
||||
obj.Dimline = obj.Start.add(mid)
|
||||
else:
|
||||
dim = ifc_export.get_dimension(ifcentity)
|
||||
if dim and len(dim) >= 3:
|
||||
# the two props below are already taken care of, normally
|
||||
if "Start" not in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyVectorDistance", "Start", "Base")
|
||||
if "End" not in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyVectorDistance", "End", "Base")
|
||||
if "Dimline" not in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyVectorDistance", "Dimline", "Base")
|
||||
obj.Start = dim[1]
|
||||
obj.End = dim[2]
|
||||
if len(dim) > 3:
|
||||
obj.Dimline = dim[3]
|
||||
else:
|
||||
mid = obj.End.sub(obj.Start)
|
||||
mid.multiply(0.5)
|
||||
obj.Dimline = obj.Start.add(mid)
|
||||
text = ifc_export.get_text(ifcentity)
|
||||
if text:
|
||||
if "Placement" not in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyPlacement", "Placement", "Base")
|
||||
if "Text" not in obj.PropertiesList:
|
||||
obj.addProperty("App::PropertyStringList", "Text", "Base")
|
||||
obj.Text = [text.Literal]
|
||||
obj.Placement = ifc_export.get_placement(ifcentity.ObjectPlacement, ifcfile)
|
||||
|
||||
# link Label2 and Description
|
||||
if "Description" in obj.PropertiesList and hasattr(obj, "setExpression"):
|
||||
obj.setExpression("Label2", "Description")
|
||||
@@ -1184,8 +1183,35 @@ def create_relationship(old_obj, obj, parent, element, ifcfile, mode=None):
|
||||
parent_element = get_ifc_element(parent)
|
||||
else:
|
||||
parent_element = parent
|
||||
# case 4: anything inside group
|
||||
if parent_element.is_a("IfcGroup"):
|
||||
# IFC objects can be part of multiple groups but we do the FreeCAD way here
|
||||
for assignment in getattr(element,"HasAssignments",[]):
|
||||
if assignment.is_a("IfcRelAssignsToGroup"):
|
||||
if element in assignment.RelatedObjects:
|
||||
oldgroup = assignment.RelatingGr
|
||||
try:
|
||||
api_run(
|
||||
"group.unassign_group",
|
||||
ifcfile,
|
||||
products=[element],
|
||||
group=oldgroup
|
||||
)
|
||||
except:
|
||||
# older version of IfcOpenShell
|
||||
api_run(
|
||||
"group.unassign_group",
|
||||
ifcfile,
|
||||
product=element,
|
||||
group=oldgroup
|
||||
)
|
||||
try:
|
||||
uprel = api_run("group.assign_group", ifcfile, products=[element], group=parent_element)
|
||||
except:
|
||||
# older version of IfcOpenShell
|
||||
uprel = api_run("group.assign_group", ifcfile, product=element, group=parent_element)
|
||||
# case 1: element inside spatiual structure
|
||||
if parent_element.is_a("IfcSpatialStructureElement") and element.is_a("IfcElement"):
|
||||
elif parent_element.is_a("IfcSpatialStructureElement") and element.is_a("IfcElement"):
|
||||
# first remove the FreeCAD object from any parent
|
||||
if old_obj:
|
||||
for old_par in old_obj.InList:
|
||||
|
||||
Reference in New Issue
Block a user