Skip to content
Permalink
Browse files

Arch: Adapted IFC, OBJ and DAE exporters to support external color in…

…formation when running in non-GUI mode
  • Loading branch information...
yorikvanhavre committed Jun 12, 2019
1 parent b60a736 commit b4ddf631824725d876d5aa850b130a072b74e406
Showing with 195 additions and 38 deletions.
  1. +2 −0 src/Mod/Arch/ArchIFC.py
  2. +37 −2 src/Mod/Arch/importDAE.py
  3. +128 −30 src/Mod/Arch/importIFC.py
  4. +28 −6 src/Mod/Arch/importOBJ.py
@@ -41,6 +41,8 @@ def getIfcProduct(IfcType):
"Returns an IFC product name from an obj.IfcType"

name = "Ifc" + IfcType.replace(" ", "")
if IfcType == "Undefined":
name = "IfcBuildingElementProxy"
if name in ArchIFCSchema.IfcProducts:
return ArchIFCSchema.IfcProducts[name]

@@ -49,7 +49,9 @@ def translate(context,text):
pass

def checkCollada():

"checks if collada if available"

global collada
COLLADA = None
try:
@@ -60,8 +62,11 @@ def checkCollada():
else:
return True


def triangulate(shape):

"triangulates the given face"

p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
mesher = p.GetInt("ColladaMesher",0)
tessellation = p.GetFloat("ColladaTessellation",1.0)
@@ -82,7 +87,9 @@ def triangulate(shape):


def open(filename):

"called when freecad wants to open a file"

if not checkCollada():
return
docname = (os.path.splitext(os.path.basename(filename))[0]).encode("utf8")
@@ -92,8 +99,11 @@ def open(filename):
read(filename)
return doc


def insert(filename,docname):

"called when freecad wants to import a file"

if not checkCollada():
return
try:
@@ -104,8 +114,11 @@ def insert(filename,docname):
read(filename)
return doc


def decode(name):

"decodes encoded strings"

try:
decodedName = (name.decode("utf8"))
except UnicodeDecodeError:
@@ -116,7 +129,11 @@ def decode(name):
decodedName = name
return decodedName


def read(filename):

"reads a DAE file"

global col
col = collada.Collada(filename, ignore=[collada.DaeUnsupportedError])
# Read the unitmeter info from dae file and compute unit to convert to mm
@@ -169,8 +186,11 @@ def read(filename):
if color and FreeCAD.GuiUp:
obj.ViewObject.ShapeColor = color

def export(exportList,filename,tessellation=1):

def export(exportList,filename,tessellation=1,colors=None):

"called when freecad exports a file"

if not checkCollada(): return
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
scale = p.GetFloat("ColladaScalingFactor",1.0)
@@ -261,7 +281,22 @@ def export(exportList,filename,tessellation=1):
matref = "ref_"+obj.Material.Name
matnode = collada.scene.MaterialNode(matref, mat, inputs=[])
if not matnode:
if FreeCAD.GuiUp:
if colors:
if obj.Name in colors:
color = colors[obj.Name]
if color:
if isinstance(color[0],tuple):
# this is a diffusecolor. For now, use the first color - #TODO: Support per-face colors
color = color[0]
#print("found color for obj",obj.Name,":",color)
kd = color[:3]
effect = collada.material.Effect("effect_"+obj.Name, [], "phong", diffuse=kd, specular=(1,1,1))
mat = collada.material.Material("mat_"+obj.Name, obj.Name, effect)
colmesh.effects.append(effect)
colmesh.materials.append(mat)
matref = "ref_"+obj.Name
matnode = collada.scene.MaterialNode(matref, mat, inputs=[])
elif FreeCAD.GuiUp:
if hasattr(obj.ViewObject,"ShapeColor"):
kd = obj.ViewObject.ShapeColor[:3]
effect = collada.material.Effect("effect_"+obj.Name, [], "phong", diffuse=kd, specular=(1,1,1))
@@ -1462,7 +1462,9 @@ def createIfcPresentationStyleAssignment(self,name,r,g,b,t=0):

# ************************************************************************************************
# ********** export IFC ****************
def export(exportList,filename):


def export(exportList,filename,colors=None):

"exports FreeCAD contents to an IFC file"

@@ -1671,7 +1673,7 @@ def export(exportList,filename):

# getting the representation

representation,placement,shapetype = getRepresentation(ifcfile,context,obj,forcebrep=(brepflag or FORCE_BREP))
representation,placement,shapetype = getRepresentation(ifcfile,context,obj,forcebrep=(brepflag or FORCE_BREP),colors=colors)
if getstd:
if isStandardCase(obj,ifctype):
ifctype += "StandardCase"
@@ -1713,7 +1715,7 @@ def export(exportList,filename):

if hasattr(obj,"Additions") and (shapetype in ["extrusion","no shape"]):
for o in obj.Additions:
r2,p2,c2 = getRepresentation(ifcfile,context,o)
r2,p2,c2 = getRepresentation(ifcfile,context,o,colors=colors)
if DEBUG: print(" adding ",c2," : ",o.Label)
l = o.Label
if six.PY2:
@@ -1750,7 +1752,7 @@ def export(exportList,filename):
guests.append(o)
if hasattr(obj,"Subtractions") and (shapetype in ["extrusion","no shape"]):
for o in obj.Subtractions + guests:
r2,p2,c2 = getRepresentation(ifcfile,context,o,subtraction=True)
r2,p2,c2 = getRepresentation(ifcfile,context,o,subtraction=True,colors=colors)
if DEBUG: print(" subtracting ",c2," : ",o.Label)
l = o.Label
if six.PY2:
@@ -2597,34 +2599,112 @@ def export(exportList,filename):
remaining = [anno for anno in annos.values() if anno not in swallowed]
if remaining:
if not defaulthost:
defaulthost = ifcfile.createIfcBuildingStorey(
if ADD_DEFAULT_STOREY:
defaulthost = ifcfile.createIfcBuildingStorey(
ifcopenshell.guid.new(),
history,
"Default Storey",
'',
None,
None,
None,
None,
"ELEMENT",
None
)
# if ADD_DEFAULT_STOREY is on, we need a building to host it, regardless of ADD_DEFAULT_BUILDING
if not buildings:
buildings = [ifcfile.createIfcBuilding(
ifcopenshell.guid.new(),
history,
"Default Building",
'',
None,
None,
None,
None,
"ELEMENT",
None,
None,
None
)]
if sites:
ifcfile.createIfcRelAggregates(
ifcopenshell.guid.new(),
history,
'SiteLink',
'',
sites[0],
buildings
)
else:
ifcfile.createIfcRelAggregates(
ifcopenshell.guid.new(),
history,
'ProjectLink',
'',
project,buildings
)
ifcfile.createIfcRelAggregates(
ifcopenshell.guid.new(),
history,
'DefaultStoreyLink',
'',
buildings[0],
[defaulthost]
)
elif ADD_DEFAULT_BUILDING:
if not buildings:
defaulthost = ifcfile.createIfcBuilding(
ifcopenshell.guid.new(),
history,
"Default Building",
'',
None,
None,
None,
None,
"ELEMENT",
None,
None,
None
)
if sites:
ifcfile.createIfcRelAggregates(
ifcopenshell.guid.new(),
history,
'SiteLink',
'',
sites[0],
[defaulthost]
)
else:
ifcfile.createIfcRelAggregates(
ifcopenshell.guid.new(),
history,
'ProjectLink',
'',
project,
[defaulthost]
)
if defaulthost:
ifcfile.createIfcRelContainedInSpatialStructure(
ifcopenshell.guid.new(),
history,
"Default Storey",
'AnnotationsLink',
'',
None,
None,
None,
None,
"ELEMENT",
None
remaining,
defaulthost
)
else:
ifcfile.createIfcRelAggregates(
ifcopenshell.guid.new(),
history,
'DefaultStoreyLink',
'ProjectLink',
'',
buildings[0],
[defaulthost]
project,
remaining
)
ifcfile.createIfcRelContainedInSpatialStructure(
ifcopenshell.guid.new(),
history,
'AnnotationsLink',
'',
remaining,
defaulthost
)

if DEBUG: print("writing ",filename,"...")

@@ -2648,6 +2728,8 @@ def export(exportList,filename):

# ************************************************************************************************
# ********** helper for export IFC **************


def isStandardCase(obj,ifctype):

if ifctype.endswith("StandardCase"):
@@ -2997,7 +3079,7 @@ def getProfile(ifcfile,p):
return profile


def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tessellation=1):
def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tessellation=1,colors=None):

"""returns an IfcShapeRepresentation object or None"""

@@ -3292,20 +3374,36 @@ def getRepresentation(ifcfile,context,obj,forcebrep=False,subtraction=False,tess
solidType = "MappedRepresentation"

# set surface style
if FreeCAD.GuiUp and (not subtraction) and hasattr(obj.ViewObject,"ShapeColor"):
shapecolor = None
diffusecolor = None
transparency = 0.0
if colors:
# color dict is given
if obj.Name in colors:
color = colors[obj.Name]
shapecolor = color
if isinstance(color[0],tuple):
# this is a diffusecolor. For now, use the first color - #TODO: Support per-face colors
diffusecolor = color
shapecolor = color[0]
elif FreeCAD.GuiUp and (not subtraction) and hasattr(obj.ViewObject,"ShapeColor"):
# every object gets a surface style. If the obj has a material, the surfstyle
# is named after it. Revit will treat surfacestyles as materials (and discard
# actual ifcmaterial)
shapecolor = obj.ViewObject.ShapeColor[:3]
transparency = obj.ViewObject.Transparency/100.0
if hasattr(obj.ViewObject,"DiffuseColor"):
diffusecolor = obj.ViewObject.DiffuseColor
if shapecolor:
key = None
rgbt = [obj.ViewObject.ShapeColor[:3]+(obj.ViewObject.Transparency/100.0,) for shape in shapes]
if hasattr(obj.ViewObject,"DiffuseColor") \
and obj.ViewObject.DiffuseColor \
and (len(obj.ViewObject.DiffuseColor) == len(obj.Shape.Faces)) \
rgbt = [shapecolor+(transparency,) for shape in shapes]
if diffusecolor \
and (len(diffusecolor) == len(obj.Shape.Faces)) \
and (len(obj.Shape.Solids) == len(shapes)):
i = 0
rgbt = []
for sol in obj.Shape.Solids:
rgbt.append(obj.ViewObject.DiffuseColor[i])
rgbt.append(diffusecolor[i])
i += len(sol.Faces)
for i,shape in enumerate(shapes):
key = rgbt[i]

1 comment on commit b4ddf63

@berndhahnebach

This comment has been minimized.

Copy link
Contributor

commented on b4ddf63 Jun 13, 2019

👍

Please sign in to comment.
You can’t perform that action at this time.