Arch: Adapted IFC importer for new IfcOpenShell6
Squashed following commits: * Arch: Adapted IFC importer for IfcOpenShell6 * Arch: further fixes for ifcopenshell6 compatibility * Arch: IFC importer now converts to/from meters for better compatibility with IfcOpenShell * Arch: further fixes with ifcopenshell6 * Arch: precision adjustments in IFC exporter * Arch: small fix in makeRoof
This commit is contained in:
parent
6202476061
commit
40f0927705
|
@ -26,10 +26,10 @@ __author__ = "Yorik van Havre"
|
|||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
# Possible roles for IFC objects
|
||||
Roles = ['Undefined','Beam','Beam Standard Case','Chimney','Column','Column Standard Case','Covering','Curtain Wall',
|
||||
'Door','Door Standard Case','Foundation','Furniture','Hydro Equipment','Electric Equipment',
|
||||
'Member','Plate','Railing','Ramp','Ramp Flight','Rebar','Pile','Roof','Shading Device','Slab','Space'
|
||||
'Stair','Stair Flight','Tendon','Wall','Wall Standard Case','Wall Layer','Window','Window Standard Case']
|
||||
Roles = ['Undefined','Beam','Chimney','Column','Covering','Curtain Wall',
|
||||
'Door','Foundation','Furniture','Hydro Equipment','Electric Equipment',
|
||||
'Member','Plate','Railing','Ramp','Ramp Flight','Rebar','Pile','Roof','Shading Device','Slab','Space',
|
||||
'Stair','Stair Flight','Tendon','Wall','Wall Layer','Window']
|
||||
|
||||
import FreeCAD,Draft
|
||||
from FreeCAD import Vector
|
||||
|
@ -301,6 +301,7 @@ class Component:
|
|||
self.Type = "Component"
|
||||
self.Subvolume = None
|
||||
self.MoveWithHost = False
|
||||
obj.Role = Roles
|
||||
|
||||
def execute(self,obj):
|
||||
return
|
||||
|
|
|
@ -47,45 +47,45 @@ def makeRoof(baseobj=None,facenr=1, angles=[45.,], run = [], idrel = [0,],thickn
|
|||
_ViewProviderRoof(obj.ViewObject)
|
||||
if baseobj:
|
||||
obj.Base = baseobj
|
||||
if obj.Base.isDerivedFrom("Part::Feature"):
|
||||
if (obj.Base.Shape.Faces and obj.Face):
|
||||
w = obj.Base.Shape.Faces[obj.Face-1].Wires[0]
|
||||
elif obj.Base.Shape.Wires:
|
||||
w = obj.Base.Shape.Wires[0]
|
||||
if w:
|
||||
if w.isClosed():
|
||||
edges = DraftGeomUtils.sortEdges(w.Edges)
|
||||
l = len(edges)
|
||||
|
||||
la = len(angles)
|
||||
alist = angles
|
||||
for i in range(l-la):
|
||||
alist.append(angles[0])
|
||||
obj.Angles=alist
|
||||
|
||||
lr = len(run)
|
||||
rlist = run
|
||||
for i in range(l-lr):
|
||||
rlist.append(w.Edges[i].Length/2.)
|
||||
obj.Runs = rlist
|
||||
|
||||
lidrel = len(idrel)
|
||||
rellist = idrel
|
||||
for i in range(l-lidrel):
|
||||
rellist.append(0)
|
||||
obj.IdRel = rellist
|
||||
|
||||
lthick = len(thickness)
|
||||
tlist = thickness
|
||||
for i in range(l-lthick):
|
||||
tlist.append(thickness[0])
|
||||
obj.Thickness = tlist
|
||||
|
||||
lover = len(overhang)
|
||||
olist = overhang
|
||||
for i in range(l-lover):
|
||||
olist.append(overhang[0])
|
||||
obj.Overhang = olist
|
||||
if obj.Base.isDerivedFrom("Part::Feature"):
|
||||
if (obj.Base.Shape.Faces and obj.Face):
|
||||
w = obj.Base.Shape.Faces[obj.Face-1].Wires[0]
|
||||
elif obj.Base.Shape.Wires:
|
||||
w = obj.Base.Shape.Wires[0]
|
||||
if w:
|
||||
if w.isClosed():
|
||||
edges = DraftGeomUtils.sortEdges(w.Edges)
|
||||
l = len(edges)
|
||||
|
||||
la = len(angles)
|
||||
alist = angles
|
||||
for i in range(l-la):
|
||||
alist.append(angles[0])
|
||||
obj.Angles=alist
|
||||
|
||||
lr = len(run)
|
||||
rlist = run
|
||||
for i in range(l-lr):
|
||||
rlist.append(w.Edges[i].Length/2.)
|
||||
obj.Runs = rlist
|
||||
|
||||
lidrel = len(idrel)
|
||||
rellist = idrel
|
||||
for i in range(l-lidrel):
|
||||
rellist.append(0)
|
||||
obj.IdRel = rellist
|
||||
|
||||
lthick = len(thickness)
|
||||
tlist = thickness
|
||||
for i in range(l-lthick):
|
||||
tlist.append(thickness[0])
|
||||
obj.Thickness = tlist
|
||||
|
||||
lover = len(overhang)
|
||||
olist = overhang
|
||||
for i in range(l-lover):
|
||||
olist.append(overhang[0])
|
||||
obj.Overhang = olist
|
||||
obj.Face = facenr
|
||||
return obj
|
||||
|
||||
|
|
|
@ -214,6 +214,8 @@ class _Space(ArchComponent.Component):
|
|||
def getArea(self,obj):
|
||||
"returns the horizontal area at the center of the space"
|
||||
import Part,DraftGeomUtils
|
||||
if not hasattr(obj.Shape,"CenterOfMass"):
|
||||
return 0
|
||||
try:
|
||||
pl = Part.makePlane(1,1)
|
||||
pl.translate(obj.Shape.CenterOfMass)
|
||||
|
|
|
@ -116,42 +116,6 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="toolTip">
|
||||
<string>A scaling factor to apply to imported IFC objects</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Scaling factor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::PrefDoubleSpinBox" name="gui::prefdoublespinbox">
|
||||
<property name="toolTip">
|
||||
<string>IFC files are typically written in millimeters. If you are working in a different unit, this allow you to scale all your units to be expressed in millimeters.</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="prefEntry" stdset="0">
|
||||
<cstring>IfcScalingFactor</cstring>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Arch</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -30,6 +30,7 @@ import os,time,tempfile,uuid,FreeCAD,Part,Draft,Arch
|
|||
if open.__module__ == '__builtin__':
|
||||
pyopen = open # because we'll redefine open below
|
||||
|
||||
# which IFC type must create which FreeCAD type
|
||||
typesmap = { "Site": ["IfcSite"],
|
||||
"Building": ["IfcBuilding"],
|
||||
"Floor": ["IfcBuildingStorey"],
|
||||
|
@ -42,13 +43,16 @@ typesmap = { "Site": ["IfcSite"],
|
|||
"Rebar": ["IfcReinforcingBar"],
|
||||
"Equipment": ["IfcFurnishingElement","IfcSanitaryTerminal","IfcFlowTerminal","IfcElectricAppliance"]
|
||||
}
|
||||
|
||||
|
||||
# specific name translations
|
||||
translationtable = { "Foundation":"Footing",
|
||||
"Floor":"BuildingStorey",
|
||||
"Rebar":"ReinforcingBar",
|
||||
"HydroEquipment":"SanitaryTerminal",
|
||||
"ElectricEquipment":"ElectricAppliance",
|
||||
"Furniture":"FurnishingElement"
|
||||
"Furniture":"FurnishingElement",
|
||||
"Stair Flight":"StairFlight",
|
||||
"Curtain Wall":"CurtainWall"
|
||||
}
|
||||
|
||||
ifctemplate = """ISO-10303-21;
|
||||
|
@ -70,11 +74,11 @@ DATA;
|
|||
#10=IFCDIRECTION((0.,1.,0.));
|
||||
#11=IFCGEOMETRICREPRESENTATIONCONTEXT('Plan','Model',3,1.E-05,#9,#10);
|
||||
#12=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
|
||||
#13=IFCSIUNIT(*,.LENGTHUNIT.,.MILLI.,.METRE.);
|
||||
#13=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
|
||||
#14=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
|
||||
#15=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
|
||||
#16=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
|
||||
#17=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.01745),#16);
|
||||
#17=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453292519943295),#16);
|
||||
#18=IFCCONVERSIONBASEDUNIT(#12,.PLANEANGLEUNIT.,'DEGREE',#17);
|
||||
#19=IFCUNITASSIGNMENT((#13,#14,#15,#18));
|
||||
#20=IFCPROJECT('$projectid',#5,'$project',$,$,$,$,(#11),#19);
|
||||
|
@ -83,11 +87,10 @@ END-ISO-10303-21;
|
|||
"""
|
||||
|
||||
|
||||
def explore(filename=None,toplevel="IfcRoot"):
|
||||
"""explore([filename],[toplevel]): opens a dialog showing
|
||||
def explore(filename=None):
|
||||
"""explore([filename]): opens a dialog showing
|
||||
the contents of an IFC file. If no filename is given, a dialog will
|
||||
pop up to choose a file. toplevel (default IFcRoot) can be used to
|
||||
limit the display to a certain category of objects and its derivates."""
|
||||
pop up to choose a file."""
|
||||
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||
DEBUG = p.GetBool("ifcDebug",False)
|
||||
|
@ -95,9 +98,8 @@ def explore(filename=None,toplevel="IfcRoot"):
|
|||
try:
|
||||
import ifcopenshell
|
||||
except:
|
||||
if DEBUG: print "using legacy importer"
|
||||
import importIFClegacy
|
||||
return importIFClegacy.explore(filename)
|
||||
FreeCAD.Console.PrintError("IfcOpenShell was not found on this system. IFC support is disabled\n")
|
||||
return
|
||||
|
||||
if not filename:
|
||||
from PySide import QtGui
|
||||
|
@ -115,7 +117,6 @@ def explore(filename=None,toplevel="IfcRoot"):
|
|||
print "File not found"
|
||||
return
|
||||
|
||||
ifcopenshell.clean()
|
||||
ifc = ifcopenshell.open(filename)
|
||||
tree = QtGui.QTreeWidget()
|
||||
tree.setColumnCount(3)
|
||||
|
@ -130,8 +131,14 @@ def explore(filename=None,toplevel="IfcRoot"):
|
|||
bold = QtGui.QFont()
|
||||
bold.setWeight(75)
|
||||
bold.setBold(True)
|
||||
|
||||
entities = ifc.by_type("IfcRoot")
|
||||
entities += ifc.by_type("IfcRepresentation")
|
||||
entities += ifc.by_type("IfcRepresentationItem")
|
||||
entities += ifc.by_type("IfcPlacement")
|
||||
entities = sorted(entities, key=lambda eid: eid.id())
|
||||
|
||||
for entity in ifc.by_type(toplevel):
|
||||
for entity in entities:
|
||||
item = QtGui.QTreeWidgetItem(tree)
|
||||
if hasattr(entity,"id"):
|
||||
item.setText(0,str(entity.id()))
|
||||
|
@ -161,18 +168,18 @@ def explore(filename=None,toplevel="IfcRoot"):
|
|||
i = 0
|
||||
while True:
|
||||
try:
|
||||
argname = entity.wrapped_data.get_argument_name(i)
|
||||
argname = entity.attribute_name(i)
|
||||
except:
|
||||
break
|
||||
else:
|
||||
try:
|
||||
argvalue = entity.wrapped_data.get_argument(i)
|
||||
argvalue = getattr(entity,argname)
|
||||
except:
|
||||
print "Error in entity ",entity
|
||||
break
|
||||
else:
|
||||
if not argname in ["Id", "GlobalId"]:
|
||||
if isinstance(argvalue,ifcopenshell.ifc_wrapper.entity_instance):
|
||||
if isinstance(argvalue,ifcopenshell.entity_instance):
|
||||
t = "Entity #" + str(argvalue.id()) + ": " + str(argvalue.is_a())
|
||||
elif isinstance(argvalue,list):
|
||||
t = ""
|
||||
|
@ -183,7 +190,7 @@ def explore(filename=None,toplevel="IfcRoot"):
|
|||
item.setText(2,str(t))
|
||||
if isinstance(argvalue,list):
|
||||
for argitem in argvalue:
|
||||
if isinstance(argitem,ifcopenshell.ifc_wrapper.entity_instance):
|
||||
if isinstance(argitem,ifcopenshell.entity_instance):
|
||||
t = "Entity #" + str(argitem.id()) + ": " + str(argitem.is_a())
|
||||
else:
|
||||
t = argitem
|
||||
|
@ -221,14 +228,12 @@ def insert(filename,docname,skip=[]):
|
|||
PREFIX_NUMBERS = p.GetBool("ifcPrefixNumbers",False)
|
||||
SKIP = p.GetString("ifcSkip","")
|
||||
SEPARATE_OPENINGS = p.GetBool("ifcSeparateOpenings",False)
|
||||
SCALE = p.GetFloat("IfcScalingFactor",1.0)
|
||||
|
||||
try:
|
||||
import ifcopenshell
|
||||
except:
|
||||
if DEBUG: print "using legacy importer"
|
||||
import importIFClegacy
|
||||
return importIFClegacy.insert(filename,docname,skip)
|
||||
FreeCAD.Console.PrintError("IfcOpenShell was not found on this system. IFC support is disabled\n")
|
||||
return
|
||||
|
||||
if DEBUG: print "opening ",filename,"..."
|
||||
try:
|
||||
|
@ -238,13 +243,17 @@ def insert(filename,docname,skip=[]):
|
|||
FreeCAD.ActiveDocument = doc
|
||||
|
||||
global ifcfile # keeping global for debugging purposes
|
||||
ifcopenshell.clean()
|
||||
if isinstance(filename,unicode):
|
||||
import sys #workaround since ifcopenshell currently can't handle unicode filenames
|
||||
filename = filename.encode(sys.getfilesystemencoding())
|
||||
ifcfile = ifcopenshell.open(filename)
|
||||
shape_attributes = ifcopenshell.SEW_SHELLS
|
||||
if SEPARATE_OPENINGS: shape_attributes += ifcopenshell.DISABLE_OPENING_SUBTRACTIONS
|
||||
from ifcopenshell import geom
|
||||
settings = ifcopenshell.geom.settings()
|
||||
settings.set(settings.USE_BREP_DATA,True)
|
||||
settings.set(settings.SEW_SHELLS,True)
|
||||
settings.set(settings.USE_WORLD_COORDS,True)
|
||||
if SEPARATE_OPENINGS:
|
||||
settings.set(settings.DISABLE_OPENING_SUBTRACTIONS,True)
|
||||
sites = ifcfile.by_type("IfcSite")
|
||||
buildings = ifcfile.by_type("IfcBuilding")
|
||||
floors = ifcfile.by_type("IfcBuildingStorey")
|
||||
|
@ -264,7 +273,9 @@ def insert(filename,docname,skip=[]):
|
|||
subtractions.append([r.RelatedOpeningElement.id(), r.RelatingBuildingElement.id()])
|
||||
for r in ifcfile.by_type("IfcRelDefinesByProperties"):
|
||||
for obj in r.RelatedObjects:
|
||||
properties.setdefault(obj.id(),[]).extend([e.id() for e in r.RelatingPropertyDefinition.HasProperties])
|
||||
if r.RelatingPropertyDefinition.is_a("IfcPropertySet"):
|
||||
properties.setdefault(obj.id(),[]).extend([e.id() for e in r.RelatingPropertyDefinition.HasProperties])
|
||||
count = 0
|
||||
|
||||
# products
|
||||
for product in products:
|
||||
|
@ -275,17 +286,20 @@ def insert(filename,docname,skip=[]):
|
|||
if PREFIX_NUMBERS: name = "ID" + str(pid) + " " + name
|
||||
obj = None
|
||||
baseobj = None
|
||||
brep = None
|
||||
|
||||
if (ptype == "IfcOpeningElement") and (not SEPARATE_OPENINGS): continue
|
||||
if pid in skip: continue
|
||||
if ptype in SKIP: continue
|
||||
|
||||
brep = ifcopenshell.create_shape(product,shape_attributes)
|
||||
if pid in skip: continue # user given id skip list
|
||||
if ptype in SKIP: continue # preferences-set type skip list
|
||||
try:
|
||||
cr = ifcopenshell.geom.create_shape(settings,product)
|
||||
brep = cr.geometry.brep_data
|
||||
except:
|
||||
pass
|
||||
if brep:
|
||||
shape = Part.Shape()
|
||||
shape.importBrepFromString(brep)
|
||||
if SCALE != 1:
|
||||
shape.scale(SCALE)
|
||||
shape.scale(1000.0) # IfcOpenShell always outputs in meters
|
||||
if not shape.isNull():
|
||||
baseobj = FreeCAD.ActiveDocument.addObject("Part::Feature",name+"_body")
|
||||
baseobj.Shape = shape
|
||||
|
@ -299,6 +313,9 @@ def insert(filename,docname,skip=[]):
|
|||
tr = dict((v,k) for k, v in translationtable.iteritems())
|
||||
if r in tr.keys():
|
||||
r = tr[r]
|
||||
# remove the "StandardCase"
|
||||
if "StandardCase" in r:
|
||||
r = r[:-12]
|
||||
obj.Role = r
|
||||
except:
|
||||
pass
|
||||
|
@ -313,7 +330,8 @@ def insert(filename,docname,skip=[]):
|
|||
if obj:
|
||||
sh = baseobj.Shape.ShapeType if hasattr(baseobj,"Shape") else "None"
|
||||
sols = str(baseobj.Shape.Solids) if hasattr(baseobj,"Shape") else ""
|
||||
if DEBUG: print "creating object ",pid," : ",ptype, " with shape: ",sh," ",sols
|
||||
pc = str(int((float(count)/len(products)*100)))+"% "
|
||||
if DEBUG: print pc,"creating object ",pid," : ",ptype, " with shape: ",sh," ",sols
|
||||
objects[pid] = obj
|
||||
|
||||
# properties
|
||||
|
@ -322,25 +340,31 @@ def insert(filename,docname,skip=[]):
|
|||
a = obj.IfcAttributes
|
||||
for p in properties[pid]:
|
||||
o = ifcfile[p]
|
||||
a[o.Name] = str(o.NominalValue)
|
||||
if o.is_a("IfcPropertySingleValue"):
|
||||
a[o.Name] = str(o.NominalValue)
|
||||
obj.IfcAttributes = a
|
||||
|
||||
count += 1
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
if DEBUG: print "Processing relationships..."
|
||||
|
||||
# subtractions
|
||||
if SEPARATE_OPENINGS:
|
||||
for subtraction in subtractions:
|
||||
if (subtraction[0] in objects.keys()) and (subtraction[1] in objects.keys()):
|
||||
Arch.removeComponents(objects[subtraction[0]],objects[subtraction[1]])
|
||||
|
||||
#print objects[subtraction[0]].Name, objects[subtraction[1]].Name
|
||||
Arch.removeComponents(objects[subtraction[0]],objects[subtraction[1]])
|
||||
|
||||
# additions
|
||||
for host,children in additions.iteritems():
|
||||
if host in objects.keys():
|
||||
cobs = [objects[child] for child in children if child in objects.keys()]
|
||||
if cobs:
|
||||
Arch.addComponents(cobs,objects[host])
|
||||
|
||||
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
|
||||
# cleaning bad shapes
|
||||
for obj in objects.values():
|
||||
if obj.isDerivedFrom("Part::Feature"):
|
||||
|
@ -365,9 +389,8 @@ def export(exportList,filename):
|
|||
global ifcopenshell
|
||||
import ifcopenshell
|
||||
except:
|
||||
if DEBUG: print "using legacy exporter"
|
||||
import importIFClegacy
|
||||
return importIFClegacy.export(exportList,filename)
|
||||
FreeCAD.Console.PrintError("IfcOpenShell was not found on this system. IFC support is disabled\n")
|
||||
return
|
||||
|
||||
if isinstance(filename,unicode):
|
||||
import sys #workaround since ifcopenshell currently can't handle unicode filenames
|
||||
|
@ -452,9 +475,9 @@ def export(exportList,filename):
|
|||
if ifctype in ["IfcSlab","IfcFooting","IfcRoof"]:
|
||||
args = args + ["NOTDEFINED"]
|
||||
elif ifctype in ["IfcWindow","IfcDoor"]:
|
||||
args = args + [obj.Width.Value, obj.Height.Value]
|
||||
args = args + [obj.Width.Value/1000.0, obj.Height.Value/1000.0]
|
||||
elif ifctype == "IfcSpace":
|
||||
args = args + ["ELEMENT","INTERNAL",obj.Shape.BoundBox.ZMin]
|
||||
args = args + ["ELEMENT","INTERNAL",obj.Shape.BoundBox.ZMin/1000.0]
|
||||
elif ifctype == "IfcBuildingElementProxy":
|
||||
args = args + ["ELEMENT"]
|
||||
elif ifctype == "IfcSite":
|
||||
|
@ -565,9 +588,12 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess
|
|||
if hasattr(obj.Proxy,"getProfiles"):
|
||||
p = obj.Proxy.getProfiles(obj,noplacement=True)
|
||||
extrusionv = obj.Proxy.getExtrusionVector(obj,noplacement=True)
|
||||
extrusionv.multiply(0.001) # to meters
|
||||
if (len(p) == 1) and extrusionv:
|
||||
p = p[0]
|
||||
p.scale(0.001) # to meters
|
||||
r = obj.Proxy.getPlacement(obj)
|
||||
r.Base = r.Base.multiply(0.001) # to meters
|
||||
|
||||
if len(p.Edges) == 1:
|
||||
|
||||
|
@ -624,7 +650,7 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess
|
|||
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.create_entity("IfcParameterValue",p1)],[ifcfile.create_entity("IfcParameterValue",p2)],follow,"PARAMETER")
|
||||
curve = ifcfile.createIfcTrimmedCurve(cir,[ifcfile.createIfcParameterValue(p1)],[ifcfile.createIfcParameterValue(p2)],follow,"PARAMETER")
|
||||
|
||||
else:
|
||||
verts = [vertex.Point for vertex in e.Vertexes]
|
||||
|
@ -683,6 +709,7 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess
|
|||
dataset = fcshape.Shells
|
||||
print "Warning! object contains no solids"
|
||||
for fcsolid in dataset:
|
||||
fcsolid.scale(0.001) # to meters
|
||||
faces = []
|
||||
curves = False
|
||||
for fcface in fcsolid.Faces:
|
||||
|
|
Loading…
Reference in New Issue
Block a user