Arch: IFC exporter now exports 2D geometry as IfcAnnotations
This commit is contained in:
parent
8eedc79f35
commit
0ad956c45b
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>456</width>
|
<width>456</width>
|
||||||
<height>637</height>
|
<height>666</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -470,6 +470,26 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_18">
|
||||||
|
<item>
|
||||||
|
<widget class="Gui::PrefCheckBox" name="checkBox_12">
|
||||||
|
<property name="text">
|
||||||
|
<string>Export 2D objects as IfcAnnotations</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="prefEntry" stdset="0">
|
||||||
|
<cstring>ifcExport2D</cstring>
|
||||||
|
</property>
|
||||||
|
<property name="prefPath" stdset="0">
|
||||||
|
<cstring>Mod/Arch</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -126,7 +126,7 @@ def getPreferences():
|
||||||
global ROOT_ELEMENT, GET_EXTRUSIONS, MERGE_MATERIALS
|
global ROOT_ELEMENT, GET_EXTRUSIONS, MERGE_MATERIALS
|
||||||
global MERGE_MODE_ARCH, MERGE_MODE_STRUCT, CREATE_CLONES
|
global MERGE_MODE_ARCH, MERGE_MODE_STRUCT, CREATE_CLONES
|
||||||
global FORCE_BREP, IMPORT_PROPERTIES, STORE_UID, SERIALIZE
|
global FORCE_BREP, IMPORT_PROPERTIES, STORE_UID, SERIALIZE
|
||||||
global SPLIT_LAYERS
|
global SPLIT_LAYERS, EXPORT_2D
|
||||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||||
if FreeCAD.GuiUp and p.GetBool("ifcShowDialog",False):
|
if FreeCAD.GuiUp and p.GetBool("ifcShowDialog",False):
|
||||||
import FreeCADGui
|
import FreeCADGui
|
||||||
|
@ -151,6 +151,7 @@ def getPreferences():
|
||||||
STORE_UID = p.GetBool("ifcStoreUid",True)
|
STORE_UID = p.GetBool("ifcStoreUid",True)
|
||||||
SERIALIZE = p.GetBool("ifcSerialize",False)
|
SERIALIZE = p.GetBool("ifcSerialize",False)
|
||||||
SPLIT_LAYERS = p.GetBool("ifcSplitLayers",False)
|
SPLIT_LAYERS = p.GetBool("ifcSplitLayers",False)
|
||||||
|
EXPORT_2D = p.GetBool("ifcExport2D",True)
|
||||||
|
|
||||||
|
|
||||||
def explore(filename=None):
|
def explore(filename=None):
|
||||||
|
@ -963,6 +964,16 @@ def export(exportList,filename):
|
||||||
context = ifcfile.by_type("IfcGeometricRepresentationContext")[0]
|
context = ifcfile.by_type("IfcGeometricRepresentationContext")[0]
|
||||||
project = ifcfile.by_type("IfcProject")[0]
|
project = ifcfile.by_type("IfcProject")[0]
|
||||||
objectslist = Draft.getGroupContents(exportList,walls=True,addgroups=True)
|
objectslist = Draft.getGroupContents(exportList,walls=True,addgroups=True)
|
||||||
|
annotations = []
|
||||||
|
for obj in objectslist:
|
||||||
|
if obj.isDerivedFrom("Part::Part2DObject"):
|
||||||
|
annotations.append(obj)
|
||||||
|
elif obj.isDerivedFrom("App::Annotation"):
|
||||||
|
annotations.append(obj)
|
||||||
|
elif obj.isDerivedFrom("Part::Feature"):
|
||||||
|
if obj.Shape:
|
||||||
|
if not obj.Shape.Faces:
|
||||||
|
annotations.append(obj)
|
||||||
objectslist = Arch.pruneIncluded(objectslist)
|
objectslist = Arch.pruneIncluded(objectslist)
|
||||||
products = {} # { Name: IfcEntity, ... }
|
products = {} # { Name: IfcEntity, ... }
|
||||||
surfstyles = {} # { (r,g,b): IfcEntity, ... }
|
surfstyles = {} # { (r,g,b): IfcEntity, ... }
|
||||||
|
@ -1300,7 +1311,37 @@ def export(exportList,filename):
|
||||||
products[g[0]] = grp
|
products[g[0]] = grp
|
||||||
ass = ifcfile.createIfcRelAssignsToGroup(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'GroupLink','',children,None,grp)
|
ass = ifcfile.createIfcRelAssignsToGroup(ifcopenshell.guid.compress(uuid.uuid1().hex),history,'GroupLink','',children,None,grp)
|
||||||
|
|
||||||
|
# 2D objects
|
||||||
|
|
||||||
|
if EXPORT_2D:
|
||||||
|
if annotations and DEBUG: print "exporting 2D objects..."
|
||||||
|
for anno in annotations:
|
||||||
|
xvc = ifcfile.createIfcDirection((1.0,0.0,0.0))
|
||||||
|
zvc = ifcfile.createIfcDirection((0.0,0.0,1.0))
|
||||||
|
ovc = ifcfile.createIfcCartesianPoint((0.0,0.0,0.0))
|
||||||
|
gpl = ifcfile.createIfcAxis2Placement3D(ovc,zvc,xvc)
|
||||||
|
if anno.isDerivedFrom("Part::Feature"):
|
||||||
|
reps = []
|
||||||
|
sh = anno.Shape.copy()
|
||||||
|
sh.scale(0.001) # to meters
|
||||||
|
ehc = []
|
||||||
|
for w in sh.Wires:
|
||||||
|
reps.append(createCurve(ifcfile,w))
|
||||||
|
for e in w.Edges:
|
||||||
|
ehc.append(e.hashCode())
|
||||||
|
for e in sh.Edges:
|
||||||
|
if not e.hashCode in ehc:
|
||||||
|
reps.append(createCurve(ifcfile,e))
|
||||||
|
elif anno.isDerivedFrom("App::Annotation"):
|
||||||
|
l = anno.Position
|
||||||
|
pos = ifcfile.createIfcCartesianPoint((l.x,l.y,l.z))
|
||||||
|
tpl = ifcfile.createIfcAxis2Placement3D(pos,None,None)
|
||||||
|
txt = ifcfile.createIfcTextLiteral(";".join(anno.LabelText).encode("utf8"),tpl,"LEFT")
|
||||||
|
reps = [txt]
|
||||||
|
shp = ifcfile.createIfcShapeRepresentation(context,'Annotation','Annotation2D',reps)
|
||||||
|
rep = ifcfile.createIfcProductDefinitionShape(None,None,[shp])
|
||||||
|
ann = ifcfile.createIfcAnnotation(ifcopenshell.guid.compress(uuid.uuid1().hex),history,anno.Label.encode('utf8'),'',None,gpl,rep)
|
||||||
|
|
||||||
if DEBUG: print "writing ",filename,"..."
|
if DEBUG: print "writing ",filename,"..."
|
||||||
|
|
||||||
filename = decode(filename)
|
filename = decode(filename)
|
||||||
|
@ -1314,6 +1355,60 @@ def export(exportList,filename):
|
||||||
os.remove(templatefile)
|
os.remove(templatefile)
|
||||||
|
|
||||||
|
|
||||||
|
def createCurve(ifcfile,wire):
|
||||||
|
"creates an IfcCompositeCurve from a shape"
|
||||||
|
|
||||||
|
segments = []
|
||||||
|
pol = None
|
||||||
|
last = None
|
||||||
|
if wire.ShapeType == "edge":
|
||||||
|
edges = [edge]
|
||||||
|
else:
|
||||||
|
edges = Part.__sortEdges__(wire.Edges)
|
||||||
|
for e in edges:
|
||||||
|
if isinstance(e.Curve,Part.Circle):
|
||||||
|
follow = True
|
||||||
|
if last:
|
||||||
|
if not DraftVecUtils.equals(last,e.Vertexes[0].Point):
|
||||||
|
follow = False
|
||||||
|
last = e.Vertexes[0].Point
|
||||||
|
else:
|
||||||
|
last = e.Vertexes[-1].Point
|
||||||
|
else:
|
||||||
|
last = e.Vertexes[-1].Point
|
||||||
|
p1 = math.degrees(-DraftVecUtils.angle(e.Vertexes[0].Point.sub(e.Curve.Center)))
|
||||||
|
p2 = math.degrees(-DraftVecUtils.angle(e.Vertexes[-1].Point.sub(e.Curve.Center)))
|
||||||
|
da = DraftVecUtils.angle(e.valueAt(e.FirstParameter+0.1).sub(e.Curve.Center),e.Vertexes[0].Point.sub(e.Curve.Center))
|
||||||
|
if p1 < 0:
|
||||||
|
p1 = 360 + p1
|
||||||
|
if p2 < 0:
|
||||||
|
p2 = 360 + p2
|
||||||
|
if da > 0:
|
||||||
|
follow = not(follow)
|
||||||
|
xvc = ifcfile.createIfcDirection((1.0,0.0))
|
||||||
|
ovc = ifcfile.createIfcCartesianPoint(tuple(e.Curve.Center)[:2])
|
||||||
|
plc = ifcfile.createIfcAxis2Placement2D(ovc,xvc)
|
||||||
|
cir = ifcfile.createIfcCircle(plc,e.Curve.Radius)
|
||||||
|
curve = ifcfile.createIfcTrimmedCurve(cir,[ifcfile.createIfcParameterValue(p1)],[ifcfile.createIfcParameterValue(p2)],follow,"PARAMETER")
|
||||||
|
else:
|
||||||
|
verts = [vertex.Point for vertex in e.Vertexes]
|
||||||
|
if last:
|
||||||
|
if not DraftVecUtils.equals(last,verts[0]):
|
||||||
|
verts.reverse()
|
||||||
|
last = e.Vertexes[0].Point
|
||||||
|
else:
|
||||||
|
last = e.Vertexes[-1].Point
|
||||||
|
else:
|
||||||
|
last = e.Vertexes[-1].Point
|
||||||
|
pts = [ifcfile.createIfcCartesianPoint(tuple(v)[:2]) for v in verts]
|
||||||
|
curve = ifcfile.createIfcPolyline(pts)
|
||||||
|
segment = ifcfile.createIfcCompositeCurveSegment("CONTINUOUS",True,curve)
|
||||||
|
segments.append(segment)
|
||||||
|
if segments:
|
||||||
|
pol = ifcfile.createIfcCompositeCurve(segments,False)
|
||||||
|
return pol
|
||||||
|
|
||||||
|
|
||||||
def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tessellation=1):
|
def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tessellation=1):
|
||||||
"""returns an IfcShapeRepresentation object or None"""
|
"""returns an IfcShapeRepresentation object or None"""
|
||||||
|
|
||||||
|
@ -1325,7 +1420,7 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess
|
||||||
tostore = False
|
tostore = False
|
||||||
|
|
||||||
# check for clones
|
# check for clones
|
||||||
if not subtraction:
|
if (not subtraction) and (not forcebrep):
|
||||||
for k,v in clones.items():
|
for k,v in clones.items():
|
||||||
if (obj.Name == k ) or (obj.Name in v):
|
if (obj.Name == k ) or (obj.Name in v):
|
||||||
if k in sharedobjects:
|
if k in sharedobjects:
|
||||||
|
@ -1399,51 +1494,7 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess
|
||||||
|
|
||||||
# extruded composite curve
|
# extruded composite curve
|
||||||
else:
|
else:
|
||||||
segments = []
|
po = createCurve(ifcfile,p)
|
||||||
last = None
|
|
||||||
edges = Part.__sortEdges__(p.Edges)
|
|
||||||
for e in edges:
|
|
||||||
if isinstance(e.Curve,Part.Circle):
|
|
||||||
follow = True
|
|
||||||
if last:
|
|
||||||
if not DraftVecUtils.equals(last,e.Vertexes[0].Point):
|
|
||||||
follow = False
|
|
||||||
last = e.Vertexes[0].Point
|
|
||||||
else:
|
|
||||||
last = e.Vertexes[-1].Point
|
|
||||||
else:
|
|
||||||
last = e.Vertexes[-1].Point
|
|
||||||
p1 = math.degrees(-DraftVecUtils.angle(e.Vertexes[0].Point.sub(e.Curve.Center)))
|
|
||||||
p2 = math.degrees(-DraftVecUtils.angle(e.Vertexes[-1].Point.sub(e.Curve.Center)))
|
|
||||||
da = DraftVecUtils.angle(e.valueAt(e.FirstParameter+0.1).sub(e.Curve.Center),e.Vertexes[0].Point.sub(e.Curve.Center))
|
|
||||||
if p1 < 0:
|
|
||||||
p1 = 360 + p1
|
|
||||||
if p2 < 0:
|
|
||||||
p2 = 360 + p2
|
|
||||||
if da > 0:
|
|
||||||
follow = not(follow)
|
|
||||||
xvc = ifcfile.createIfcDirection((1.0,0.0))
|
|
||||||
ovc = ifcfile.createIfcCartesianPoint(tuple(e.Curve.Center)[:2])
|
|
||||||
plc = ifcfile.createIfcAxis2Placement2D(ovc,xvc)
|
|
||||||
cir = ifcfile.createIfcCircle(plc,e.Curve.Radius)
|
|
||||||
curve = ifcfile.createIfcTrimmedCurve(cir,[ifcfile.createIfcParameterValue(p1)],[ifcfile.createIfcParameterValue(p2)],follow,"PARAMETER")
|
|
||||||
|
|
||||||
else:
|
|
||||||
verts = [vertex.Point for vertex in e.Vertexes]
|
|
||||||
if last:
|
|
||||||
if not DraftVecUtils.equals(last,verts[0]):
|
|
||||||
verts.reverse()
|
|
||||||
last = e.Vertexes[0].Point
|
|
||||||
else:
|
|
||||||
last = e.Vertexes[-1].Point
|
|
||||||
else:
|
|
||||||
last = e.Vertexes[-1].Point
|
|
||||||
pts = [ifcfile.createIfcCartesianPoint(tuple(v)[:2]) for v in verts]
|
|
||||||
curve = ifcfile.createIfcPolyline(pts)
|
|
||||||
segment = ifcfile.createIfcCompositeCurveSegment("CONTINUOUS",True,curve)
|
|
||||||
segments.append(segment)
|
|
||||||
|
|
||||||
pol = ifcfile.createIfcCompositeCurve(segments,False)
|
|
||||||
profile = ifcfile.createIfcArbitraryClosedProfileDef("AREA",None,pol)
|
profile = ifcfile.createIfcArbitraryClosedProfileDef("AREA",None,pol)
|
||||||
|
|
||||||
if profile and not(DraftVecUtils.isNull(extrusionv)):
|
if profile and not(DraftVecUtils.isNull(extrusionv)):
|
||||||
|
|
|
@ -1765,8 +1765,9 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
|
||||||
l = p.GetString("svgDashdotLine","0.09,0.05,0.02,0.05")
|
l = p.GetString("svgDashdotLine","0.09,0.05,0.02,0.05")
|
||||||
elif linestyle == "Dotted":
|
elif linestyle == "Dotted":
|
||||||
l = p.GetString("svgDottedLine","0.02,0.02")
|
l = p.GetString("svgDottedLine","0.02,0.02")
|
||||||
elif "," in linestyle:
|
elif linestyle:
|
||||||
l = linestyle
|
if "," in linestyle:
|
||||||
|
l = linestyle
|
||||||
if l:
|
if l:
|
||||||
l = l.split(",")
|
l = l.split(",")
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user