Arch: IFC exporter now exports 2D geometry as IfcAnnotations

This commit is contained in:
Yorik van Havre 2016-09-14 18:55:55 -03:00
parent 8eedc79f35
commit 0ad956c45b
3 changed files with 123 additions and 51 deletions

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>456</width>
<height>637</height>
<height>666</height>
</rect>
</property>
<property name="windowTitle">
@ -470,6 +470,26 @@
</item>
</layout>
</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>
</widget>
</item>

View File

@ -126,7 +126,7 @@ def getPreferences():
global ROOT_ELEMENT, GET_EXTRUSIONS, MERGE_MATERIALS
global MERGE_MODE_ARCH, MERGE_MODE_STRUCT, CREATE_CLONES
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")
if FreeCAD.GuiUp and p.GetBool("ifcShowDialog",False):
import FreeCADGui
@ -151,6 +151,7 @@ def getPreferences():
STORE_UID = p.GetBool("ifcStoreUid",True)
SERIALIZE = p.GetBool("ifcSerialize",False)
SPLIT_LAYERS = p.GetBool("ifcSplitLayers",False)
EXPORT_2D = p.GetBool("ifcExport2D",True)
def explore(filename=None):
@ -963,6 +964,16 @@ def export(exportList,filename):
context = ifcfile.by_type("IfcGeometricRepresentationContext")[0]
project = ifcfile.by_type("IfcProject")[0]
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)
products = {} # { Name: IfcEntity, ... }
surfstyles = {} # { (r,g,b): IfcEntity, ... }
@ -1300,7 +1311,37 @@ def export(exportList,filename):
products[g[0]] = 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,"..."
filename = decode(filename)
@ -1314,6 +1355,60 @@ def export(exportList,filename):
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):
"""returns an IfcShapeRepresentation object or None"""
@ -1325,7 +1420,7 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess
tostore = False
# check for clones
if not subtraction:
if (not subtraction) and (not forcebrep):
for k,v in clones.items():
if (obj.Name == k ) or (obj.Name in v):
if k in sharedobjects:
@ -1399,51 +1494,7 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess
# extruded composite curve
else:
segments = []
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)
po = createCurve(ifcfile,p)
profile = ifcfile.createIfcArbitraryClosedProfileDef("AREA",None,pol)
if profile and not(DraftVecUtils.isNull(extrusionv)):

View File

@ -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")
elif linestyle == "Dotted":
l = p.GetString("svgDottedLine","0.02,0.02")
elif "," in linestyle:
l = linestyle
elif linestyle:
if "," in linestyle:
l = linestyle
if l:
l = l.split(",")
try: