diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py
index 23c5f52986..c416a5c648 100644
--- a/src/Mod/Arch/importIFC.py
+++ b/src/Mod/Arch/importIFC.py
@@ -45,11 +45,11 @@ import importIFCHelper
#
# This module provides tools to import IFC files.
-DEBUG = False # Set to True to see debug messages. Otherwise, totally silent
-ZOOMOUT = True # Set to False to not zoom extents after import
+DEBUG = False # Set to True to see debug messages. Otherwise, totally silent
+ZOOMOUT = True # Set to False to not zoom extents after import
if open.__module__ in ['__builtin__','io']:
- pyopen = open # because we'll redefine open below
+ pyopen = open # because we'll redefine open below
# ************************************************************************************************
@@ -232,10 +232,10 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
# IfcOpenShell multiplies the precision value of the file by 100
# So we raise the precision by 100 too to compensate...
- #ctxs = ifcfile.by_type("IfcGeometricRepresentationContext")
- #for ctx in ctxs:
- # if not ctx.is_a("IfcGeometricRepresentationSubContext"):
- # ctx.Precision = ctx.Precision/100
+ # ctxs = ifcfile.by_type("IfcGeometricRepresentationContext")
+ # for ctx in ctxs:
+ # if not ctx.is_a("IfcGeometricRepresentationSubContext"):
+ # ctx.Precision = ctx.Precision/100
# set default ifcopenshell options to work in brep mode
from ifcopenshell import geom
@@ -258,12 +258,12 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
materials = ifcfile.by_type("IfcMaterial")
products, annotations = importIFCHelper.buildRelProductsAnnotations(ifcfile, preferences['ROOT_ELEMENT'])
# empty relation tables
- objects = {} # { id:object, ... }
- shapes = {} # { id:shaoe } only used for merge mode
- structshapes = {} # { id:shaoe } only used for merge mode
- sharedobjects = {} # { representationmapid:object }
- parametrics = [] # a list of imported objects whose parametric relationships need processing after all objects have been created
- profiles = {} # to store reused extrusion profiles {ifcid:fcobj,...}
+ objects = {} # { id:object, ... }
+ shapes = {} # { id:shaoe } only used for merge mode
+ structshapes = {} # { id:shaoe } only used for merge mode
+ sharedobjects = {} # { representationmapid:object }
+ parametrics = [] # a list of imported objects whose parametric relationships need processing after all objects have been created
+ profiles = {} # to store reused extrusion profiles {ifcid:fcobj,...}
# filled relation tables
# TODO for the following tables might be better use inverse attributes, done for properties
# see https://forum.freecadweb.org/viewtopic.php?f=39&t=37892
@@ -272,7 +272,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
groups = importIFCHelper.buildRelGroups(ifcfile)
subtractions = importIFCHelper.buildRelSubtractions(ifcfile)
mattable = importIFCHelper.buildRelMattable(ifcfile)
- colors = importIFCHelper.buildRelColors(ifcfile, prodrepr)
+ colors = importIFCHelper.buildRelProductColors(ifcfile, prodrepr)
if preferences['DEBUG']: print("done.")
# only import a list of IDs and their children, if defined
@@ -356,10 +356,10 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
if preferences['MERGE_MODE_STRUCT'] == 3 and not archobj:
if preferences['DEBUG']: print(" skipped.")
continue
- if pid in skip: # user given id skip list
+ if pid in skip: # user given id skip list
if preferences['DEBUG']: print(" skipped.")
continue
- if ptype in preferences['SKIP']: # preferences-set type skip list
+ if ptype in preferences['SKIP']: # preferences-set type skip list
if preferences['DEBUG']: print(" skipped.")
continue
@@ -380,7 +380,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
clone = sharedobjects[originalid]
else:
sharedobjects[originalid] = None
- store = originalid # flag this object to be stored later
+ store = originalid # flag this object to be stored later
# set additional setting for structural entities
if hasattr(settings,"INCLUDE_CURVES"):
@@ -392,7 +392,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
cr = ifcopenshell.geom.create_shape(settings,product)
brep = cr.geometry.brep_data
except:
- pass # IfcOpenShell will yield an error if a given product has no shape, but we don't care, we're brave enough
+ pass # IfcOpenShell will yield an error if a given product has no shape, but we don't care, we're brave enough
# from now on we have a brep string
if brep:
@@ -401,7 +401,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
# create a Part shape
shape = Part.Shape()
shape.importBrepFromString(brep,False)
- shape.scale(1000.0) # IfcOpenShell always outputs in meters, we convert to mm, the freecad internal unit
+ shape.scale(1000.0) # IfcOpenShell always outputs in meters, we convert to mm, the freecad internal unit
if shape.isNull():
if preferences['DEBUG']: print("null shape ",end="")
@@ -428,7 +428,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
# we are not using Arch objects
# additional tweaks to set when not using Arch objects
- if ptype == "IfcSpace": # do not add spaces to compounds
+ if ptype == "IfcSpace": # do not add spaces to compounds
if preferences['DEBUG']: print("skipping space ",pid,end="")
elif structobj:
structshapes[pid] = shape
@@ -451,7 +451,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
sortmethod = "z"
else:
sortmethod = "area"
- ex = Arch.getExtrusionData(shape,sortmethod) # is this an extrusion?
+ ex = Arch.getExtrusionData(shape,sortmethod) # is this an extrusion?
if ex:
# check for extrusion profile
@@ -623,9 +623,9 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
for attribute in ArchIFCSchema.IfcProducts[product.is_a()]["attributes"]:
if attribute["name"] == "Name":
continue
- #print("attribute:",attribute["name"])
+ # print("attribute:",attribute["name"])
if hasattr(product, attribute["name"]) and getattr(product, attribute["name"]) and hasattr(obj,attribute["name"]):
- #print("Setting attribute",attribute["name"],"to",getattr(product, attribute["name"]))
+ # print("Setting attribute",attribute["name"],"to",getattr(product, attribute["name"]))
setattr(obj, attribute["name"], getattr(product, attribute["name"]))
# TODO: ArchIFCSchema.IfcProducts uses the IFC version from the FreeCAD prefs.
# This might not coincide with the file being opened, hence some attributes are not properly read.
@@ -726,7 +726,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
if preferences['DEBUG']:
print("property NominalValue",l.NominalValue.is_a(),type(l.NominalValue.is_a()))
print("property NominalValue.wrappedValue",l.NominalValue.wrappedValue,type(l.NominalValue.wrappedValue))
- #print("l.NominalValue.Unit",l.NominalValue.Unit,type(l.NominalValue.Unit))
+ # print("l.NominalValue.Unit",l.NominalValue.Unit,type(l.NominalValue.Unit))
ifc_spreadsheet.set(str('C'+str(n)), l.NominalValue.is_a())
if l.NominalValue.is_a() in ['IfcLabel','IfcText','IfcIdentifier','IfcDescriptiveMeasure']:
if six.PY2:
@@ -756,13 +756,13 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
for p in psets[c]:
l = ifcfile[p]
if l.is_a("IfcPropertySingleValue"):
- a[l.Name.encode("utf8")] = str(l.NominalValue) # no py3 support here
+ a[l.Name.encode("utf8")] = str(l.NominalValue) # no py3 support here
obj.IfcData = a
# color
if FreeCAD.GuiUp and (pid in colors) and hasattr(obj.ViewObject,"ShapeColor"):
- #if preferences['DEBUG']: print(" setting color: ",int(colors[pid][0]*255),"/",int(colors[pid][1]*255),"/",int(colors[pid][2]*255))
+ # if preferences['DEBUG']: print(" setting color: ",int(colors[pid][0]*255),"/",int(colors[pid][1]*255),"/",int(colors[pid][2]*255))
obj.ViewObject.ShapeColor = colors[pid]
# if preferences['DEBUG'] is on, recompute after each shape
@@ -818,7 +818,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
if preferences['DEBUG']: print("Joining Structural shapes...",end="")
- for host,children in groups.items(): # Structural
+ for host,children in groups.items(): # Structural
if ifcfile[host].is_a("IfcStructuralAnalysisModel"):
compound = []
for c in children:
@@ -831,7 +831,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
obj = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
obj.Label = name
obj.Shape = Part.makeCompound(compound)
- if structshapes: # remaining Structural shapes
+ if structshapes: # remaining Structural shapes
obj = FreeCAD.ActiveDocument.addObject("Part::Feature","UnclaimedStruct")
obj.Shape = Part.makeCompound(structshapes.values())
@@ -902,7 +902,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
if preferences['DEBUG']: print("Joining Arch shapes...",end="")
- for host,children in additions.items(): # Arch
+ for host,children in additions.items(): # Arch
if ifcfile[host].is_a("IfcBuildingStorey"):
compound = []
for c in children:
@@ -920,7 +920,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
obj = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
obj.Label = name
obj.Shape = Part.makeCompound(compound)
- if shapes: # remaining Arch shapes
+ if shapes: # remaining Arch shapes
obj = FreeCAD.ActiveDocument.addObject("Part::Feature","UnclaimedArch")
obj.Shape = Part.makeCompound(shapes.values())
@@ -951,7 +951,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
cobs = []
for child in children:
if child in objects.keys() \
- and child not in swallowed: # don't add objects already in groups
+ and child not in swallowed: # don't add objects already in groups
cobs.append(objects[child])
if not cobs:
continue
@@ -995,9 +995,9 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
if preferences['DEBUG']: print(count,"/",len(annotations),"object #"+str(aid),":",annotation.is_a(),end="")
if aid in skip:
- continue # user given id skip list
+ continue # user given id skip list
if annotation.is_a() in preferences['SKIP']:
- continue # preferences-set type skip list
+ continue # preferences-set type skip list
if annotation.is_a("IfcGrid"):
axes = []
uvwaxes = ()
@@ -1010,7 +1010,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
for axis in uvwaxes:
if axis.AxisCurve:
sh = importIFCHelper.get2DShape(axis.AxisCurve,ifcscale)
- if sh and (len(sh[0].Vertexes) == 2): # currently only straight axes are supported
+ if sh and (len(sh[0].Vertexes) == 2): # currently only straight axes are supported
sh = sh[0]
l = sh.Length
pl = FreeCAD.Placement()
@@ -1055,7 +1055,7 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
anno = FreeCAD.ActiveDocument.addObject("Part::Feature",name)
anno.Shape = sh
p = importIFCHelper.getPlacement(annotation.ObjectPlacement,ifcscale)
- if p: # and annotation.is_a("IfcAnnotation"):
+ if p: # and annotation.is_a("IfcAnnotation"):
anno.Placement = p
else:
if preferences['DEBUG']: print(" no shape")
@@ -1075,8 +1075,8 @@ def insert(filename,docname,skip=[],only=[],root=None,preferences=None):
# Materials
if preferences['DEBUG'] and materials: print("Creating materials...",end="")
- #print("mattable:",mattable)
- #print("materials:",materials)
+ # print("mattable:",mattable)
+ # print("materials:",materials)
fcmats = {}
for material in materials:
# get and set material name
diff --git a/src/Mod/Arch/importIFCHelper.py b/src/Mod/Arch/importIFCHelper.py
index 3e0dd5d02c..d29dec1f16 100644
--- a/src/Mod/Arch/importIFCHelper.py
+++ b/src/Mod/Arch/importIFCHelper.py
@@ -166,7 +166,7 @@ def buildRelProductsAnnotations(ifcfile, root_element):
def buildRelProductRepresentation(ifcfile):
"""build the product/representations relation table"""
- prodrepr = {} # product/representations table
+ prodrepr = {} # product/representations table
for p in ifcfile.by_type("IfcProduct"):
if hasattr(p,"Representation"):
@@ -188,7 +188,7 @@ def buildRelProductRepresentation(ifcfile):
def buildRelAdditions(ifcfile):
"""build the additions relation table"""
- additions = {} # { host:[child,...], ... }
+ additions = {} # { host:[child,...], ... }
for r in ifcfile.by_type("IfcRelContainedInSpatialStructure"):
additions.setdefault(r.RelatingStructure.id(),[]).extend([e.id() for e in r.RelatedElements])
@@ -201,7 +201,7 @@ def buildRelAdditions(ifcfile):
def buildRelGroups(ifcfile):
"""build the groups relation table"""
- groups = {} # { host:[child,...], ... } # used in structural IFC
+ groups = {} # { host:[child,...], ... } # used in structural IFC
for r in ifcfile.by_type("IfcRelAssignsToGroup"):
groups.setdefault(r.RelatingGroup.id(),[]).extend([e.id() for e in r.RelatedObjects])
@@ -212,7 +212,7 @@ def buildRelGroups(ifcfile):
def buildRelSubtractions(ifcfile):
"""build the subtractions relation table"""
- subtractions = [] # [ [opening,host], ... ]
+ subtractions = [] # [ [opening,host], ... ]
for r in ifcfile.by_type("IfcRelVoidsElement"):
subtractions.append([r.RelatedOpeningElement.id(), r.RelatingBuildingElement.id()])
@@ -223,7 +223,7 @@ def buildRelSubtractions(ifcfile):
def buildRelMattable(ifcfile):
"""build the mattable relation table"""
- mattable = {} # { objid:matid }
+ mattable = {} # { objid:matid }
for r in ifcfile.by_type("IfcRelAssociatesMaterial"):
for o in r.RelatedObjects:
@@ -239,10 +239,17 @@ def buildRelMattable(ifcfile):
return mattable
+# ************************************************************************************************
+# color relation tables
+# products can have a color and materials can have a color and products can have a material
+# colors for material assigned to a product and product color can be different
+
+
def buildRelColors(ifcfile, prodrepr):
"""build the colors relation table and"""
- colors = {} # { id:(r,g,b) }
+ # returns all IfcStyledItem colors, material and product colors
+ colors = {} # { id:(r,g,b) }
style_material_id = {} # { style_entity_id: material_id) }
# get style_color_rgb table
@@ -269,12 +276,13 @@ def buildRelColors(ifcfile, prodrepr):
for p in prodrepr.keys():
if r.Item.id() in prodrepr[p]:
style_material_id[r.id()] = p
- # print(p)
+ # print(p)
# print(ifcfile[p]) # product
'''
# a much faster version for Nova style_material_id with product_ids
+ # no material colors, Nova ifc files often do not have materials at all
for p in prodrepr.keys():
- # print("\n")
+ # print("\n")
# print(ifcfile[p]) # IfcProduct
# print(ifcfile[p].Representation) # IfcProductDefinitionShape
# print(ifcfile[p].Representation.Representations[0]) # IfcShapeRepresentation
@@ -300,13 +308,120 @@ def buildRelColors(ifcfile, prodrepr):
return colors
-def getRelProperties(ifcfile):
- """Builds and returns a dictionary of {object:[properties]} from an IFC file"""
+def buildRelProductColors(ifcfile, prodrepr):
- # this method no longer used by this importer module
+ # gets the colors for the products
+ colors = {} # { id:(r,g,b) }
+
+ for p in prodrepr.keys():
+
+ # print(p)
+
+ # representation item, see docu IfcRepresentationItem
+ # all kind of geometric or topological representation items
+ # IfcExtrudedAreaSolid, IfcMappedItem, IfcFacetedBrep, IfcBooleanResult, etc
+ representation_item = ifcfile[p].Representation.Representations[0].Items[0]
+ # print(representation_item)
+
+ # get the geometric representations which have a presentation style
+ # all representation items have the inverse attribute StyledByItem for this
+ # there will be gemetric representations which do not have a presentation style
+ # the StyledByItem will be empty than
+ if representation_item.StyledByItem:
+
+ # it has to be a IfcStyledItem, no check needed
+ styled_item = representation_item.StyledByItem[0]
+
+ # write into colors table if a IfcStyledItem exists for this product
+ # write None if something goes wrong or if the ifc file has errors and thus no valid color is returned
+ colors[p] = getColorFromStyledItem(styled_item)
+
+ return colors
+
+
+def buildRelMaterialColors(ifcfile, prodrepr):
+ # not implemented
+ pass
+
+
+def getColorFromStyledItem(styled_item):
+
+ # styled_item should be a IfcStyledItem
+ if not styled_item.is_a("IfcStyledItem"):
+ print("Not a IfcStyledItem passed.")
+ return None
+
+ rgb_color = None
+
+ # print(styled_item)
+ # The IfcStyledItem holds presentation style information for products,
+ # either explicitly for an IfcGeometricRepresentationItem being part of
+ # an IfcShapeRepresentation assigned to a product, or by assigning presentation
+ # information to IfcMaterial being assigned as other representation for a product.
+
+ # In current IFC release (IFC2x3) only one presentation style assignment shall be assigned.
+
+ if len(styled_item.Styles) != 1:
+ if len(styled_item.Styles) == 0:
+ pass
+ # ca 100x in 210_King_Merged.ifc
+ # empty styles, #4952778=IfcStyledItem(#4952779,(),$)
+ # this is an error in the ifc file IMHO
+ # print(ifcfile[p])
+ # print(styled_item)
+ # print(styled_item.Styles)
+ else:
+ pass
+ # never seen an ifc with more than one Styles in IfcStyledItem
+ else:
+ # get the IfcPresentationStyleAssignment, there should only be one, see above
+ assign_style = styled_item.Styles[0]
+ # print(assign_style) # IfcPresentationStyleAssignment
+
+ # IfcPresentationStyleAssignment can hold various kinde and count of styles
+ # see IfcPresentationStyleSelect
+ if assign_style.Styles[0].is_a("IfcSurfaceStyle"):
+ # Schependomlaan and Nova and others
+ # print(assign_style.Styles[0].Styles[0]) # IfcSurfaceStyleRendering
+ rgb_color = assign_style.Styles[0].Styles[0].SurfaceColour # IfcColourRgb
+ # print(rgb_color)
+ elif assign_style.Styles[0].is_a("IfcCurveStyle"):
+ if (
+ len(assign_style.Styles) == 2
+ and assign_style.Styles[1].is_a("IfcSurfaceStyle")
+ ):
+ # Allplan, new IFC export started in 2017
+ # print(assign_style.Styles[0].CurveColour) # IfcDraughtingPreDefinedColour
+ # on index 1 ist das was wir brauchen !!!
+ rgb_color = assign_style.Styles[1].Styles[0].SurfaceColour
+ # print(rgb_color)
+ else:
+ # 2x Annotations in 210_King_Merged.ifc
+ # print(ifcfile[p])
+ # print(assign_style.Styles[0])
+ # print(assign_style.Styles[0].CurveColour)
+ rgb_color = assign_style.Styles[0].CurveColour
+
+ if rgb_color is not None:
+ col = rgb_color.Red, rgb_color.Green, rgb_color.Blue
+ # print(col)
+ else:
+ col = None
+
+ return col
+
+
+# ************************************************************************************************
+# property related methods
+def buildRelProperties(ifcfile):
+ """
+ Builds and returns a dictionary of {object:[properties]} from an IFC file
+ """
+
+ # this method no longer used by the importer module
# but this relation table might be useful anyway for other purposes
- properties = {} # { objid : { psetid : [propertyid, ... ], ... }, ... }
+ properties = {} # { objid : { psetid : [propertyid, ... ], ... }, ... }
for r in ifcfile.by_type("IfcRelDefinesByProperties"):
for obj in r.RelatedObjects:
if not obj.id() in properties:
@@ -336,6 +451,37 @@ def getIfcPropertySets(ifcfile, pid):
return psets
+def getIfcProperties(ifcfile, pid, psets, d):
+ """builds valid property values for FreeCAD"""
+
+ for pset in psets.keys():
+ # print("reading pset: ",pset)
+ psetname = ifcfile[pset].Name
+ if six.PY2:
+ psetname = psetname.encode("utf8")
+ for prop in psets[pset]:
+ e = ifcfile[prop]
+ pname = e.Name
+ if six.PY2:
+ pname = pname.encode("utf8")
+ if e.is_a("IfcPropertySingleValue"):
+ if e.NominalValue:
+ ptype = e.NominalValue.is_a()
+ if ptype in ['IfcLabel','IfcText','IfcIdentifier','IfcDescriptiveMeasure']:
+ pvalue = e.NominalValue.wrappedValue
+ if six.PY2:
+ pvalue = pvalue.encode("utf8")
+ else:
+ pvalue = str(e.NominalValue.wrappedValue)
+ if hasattr(e.NominalValue,'Unit'):
+ if e.NominalValue.Unit:
+ pvalue += e.NominalValue.Unit
+ d[pname+";;"+psetname] = ptype+";;"+pvalue
+ # print("adding property: ",pname,ptype,pvalue," pset ",psetname)
+ return d
+
+
+# ************************************************************************************************
def getScaling(ifcfile):
"""returns a scaling factor from file units to mm"""
@@ -362,7 +508,7 @@ def getScaling(ifcfile):
for u in ua.Units:
if u.UnitType == "LENGTHUNIT":
if u.is_a("IfcConversionBasedUnit"):
- f = getUnit(u.ConversionFactor.UnitComponent)
+ f = getUnit(u.ConversionFactor.UnitComponent)
return f * u.ConversionFactor.ValueComponent.wrappedValue
elif u.is_a("IfcSIUnit") or u.is_a("IfcUnit"):
return getUnit(u)
@@ -402,8 +548,8 @@ def getPlacement(entity,scaling=1000):
if loc:
pl.move(loc)
elif entity.is_a("IfcLocalPlacement"):
- pl = getPlacement(entity.PlacementRelTo,1) # original placement
- relpl = getPlacement(entity.RelativePlacement,1) # relative transf
+ pl = getPlacement(entity.PlacementRelTo,1) # original placement
+ relpl = getPlacement(entity.RelativePlacement,1) # relative transf
if pl and relpl:
pl = pl.multiply(relpl)
elif relpl:
@@ -425,7 +571,7 @@ def getVector(entity,scaling=1000):
v = None
if entity.is_a("IfcDirection"):
if len(entity.DirectionRatios) == 3:
- v= FreeCAD.Vector(tuple(entity.DirectionRatios))
+ v = FreeCAD.Vector(tuple(entity.DirectionRatios))
else:
v = FreeCAD.Vector(tuple(entity.DirectionRatios+[0]))
elif entity.is_a("IfcCartesianPoint"):
@@ -433,8 +579,8 @@ def getVector(entity,scaling=1000):
v = FreeCAD.Vector(tuple(entity.Coordinates))
else:
v = FreeCAD.Vector(tuple(entity.Coordinates+[0]))
- #if v:
- # v.multiply(scaling)
+ # if v:
+ # v.multiply(scaling)
return v
@@ -531,43 +677,13 @@ def get2DShape(representation,scaling=1000):
if rot.Angle:
pla.Rotation = rot
for r in preresult:
- #r.Placement = pla
+ # r.Placement = pla
result.append(r)
else:
result = preresult
elif item.is_a("IfcTextLiteral"):
t = Draft.makeText([item.Literal],point=getPlacement(item.Placement,scaling).Base)
- return t # dirty hack... Object creation should not be done here
+ return t # dirty hack... Object creation should not be done here
elif representation.is_a() in ["IfcPolyline","IfcCircle","IfcTrimmedCurve"]:
result = getCurveSet(representation)
return result
-
-
-def getIfcProperties(ifcfile, pid, psets, d):
- """builds valid property values for FreeCAD"""
-
- for pset in psets.keys():
- #print("reading pset: ",pset)
- psetname = ifcfile[pset].Name
- if six.PY2:
- psetname = psetname.encode("utf8")
- for prop in psets[pset]:
- e = ifcfile[prop]
- pname = e.Name
- if six.PY2:
- pname = pname.encode("utf8")
- if e.is_a("IfcPropertySingleValue"):
- if e.NominalValue:
- ptype = e.NominalValue.is_a()
- if ptype in ['IfcLabel','IfcText','IfcIdentifier','IfcDescriptiveMeasure']:
- pvalue = e.NominalValue.wrappedValue
- if six.PY2:
- pvalue = pvalue.encode("utf8")
- else:
- pvalue = str(e.NominalValue.wrappedValue)
- if hasattr(e.NominalValue,'Unit'):
- if e.NominalValue.Unit:
- pvalue += e.NominalValue.Unit
- d[pname+";;"+psetname] = ptype+";;"+pvalue
- #print("adding property: ",pname,ptype,pvalue," pset ",psetname)
- return d
diff --git a/src/Mod/Draft/DraftGeomUtils.py b/src/Mod/Draft/DraftGeomUtils.py
index 45dd4942bc..ac54097671 100644
--- a/src/Mod/Draft/DraftGeomUtils.py
+++ b/src/Mod/Draft/DraftGeomUtils.py
@@ -872,21 +872,28 @@ def sortEdgesOld(lEdges, aVertex=None):
return []
-def invert(edge):
- '''invert(edge): returns an inverted copy of this edge'''
- if len(edge.Vertexes) == 1:
- return edge
- if geomType(edge) == "Line":
- return Part.LineSegment(edge.Vertexes[-1].Point,edge.Vertexes[0].Point).toShape()
- elif geomType(edge) == "Circle":
- mp = findMidpoint(edge)
- return Part.Arc(edge.Vertexes[-1].Point,mp,edge.Vertexes[0].Point).toShape()
- elif geomType(edge) in ["BSplineCurve","BezierCurve"]:
- if isLine(edge.Curve):
- return Part.LineSegment(edge.Vertexes[-1].Point,edge.Vertexes[0].Point).toShape()
- print("DraftGeomUtils.invert: unable to invert ",edge.Curve)
- return edge
-
+def invert(shape):
+ '''invert(edge): returns an inverted copy of this edge or wire'''
+ if shape.ShapeType == "Wire":
+ edges = [invert(edge) for edge in shape.OrderedEdges]
+ edges.reverse()
+ return Part.Wire(edges)
+ elif shape.ShapeType == "Edge":
+ if len(shape.Vertexes) == 1:
+ return shape
+ if geomType(shape) == "Line":
+ return Part.LineSegment(shape.Vertexes[-1].Point,shape.Vertexes[0].Point).toShape()
+ elif geomType(shape) == "Circle":
+ mp = findMidpoint(shape)
+ return Part.Arc(shape.Vertexes[-1].Point,mp,shape.Vertexes[0].Point).toShape()
+ elif geomType(shape) in ["BSplineCurve","BezierCurve"]:
+ if isLine(shape.Curve):
+ return Part.LineSegment(shape.Vertexes[-1].Point,shape.Vertexes[0].Point).toShape()
+ print("DraftGeomUtils.invert: unable to invert",shape.Curve)
+ return shape
+ else:
+ print("DraftGeomUtils.invert: unable to handle",shape.ShapeType)
+ return shape
def flattenWire(wire):
'''flattenWire(wire): forces a wire to get completely flat
diff --git a/src/Mod/Draft/getSVG.py b/src/Mod/Draft/getSVG.py
index 6166d54ad1..faea430ec7 100644
--- a/src/Mod/Draft/getSVG.py
+++ b/src/Mod/Draft/getSVG.py
@@ -1,7 +1,6 @@
import six
import FreeCAD, math, os, DraftVecUtils, WorkingPlane
-import Part, DraftGeomUtils
from FreeCAD import Vector
from Draft import getType, getrgb, svgpatterns, gui
@@ -68,24 +67,34 @@ def getPattern(pat):
return ''
-def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direction=None,linestyle=None,color=None,linespacing=None,techdraw=False,rotation=0,fillSpaces=False):
+def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direction=None,linestyle=None,color=None,linespacing=None,techdraw=False,rotation=0,fillSpaces=False,override=True):
'''getSVG(object,[scale], [linewidth],[fontsize],[fillstyle],[direction],[linestyle],[color],[linespacing]):
returns a string containing a SVG representation of the given object,
with the given linewidth and fontsize (used if the given object contains
any text). You can also supply an arbitrary projection vector. the
scale parameter allows to scale linewidths down, so they are resolution-independant.'''
+ import Part, DraftGeomUtils
+
# if this is a group, gather all the svg views of its children
if hasattr(obj,"isDerivedFrom"):
- if obj.isDerivedFrom("App::DocumentObjectGroup"):
+ if obj.isDerivedFrom("App::DocumentObjectGroup") or getType(obj) == "Layer":
svg = ""
for child in obj.Group:
- svg += getSVG(child,scale,linewidth,fontsize,fillstyle,direction,linestyle,color,linespacing,techdraw)
+ svg += getSVG(child,scale,linewidth,fontsize,fillstyle,direction,linestyle,color,linespacing,techdraw,rotation,fillSpaces,override)
return svg
pathdata = []
svg = ""
linewidth = float(linewidth)/scale
+ if not override:
+ if hasattr(obj,"ViewObject"):
+ if hasattr(obj.ViewObject,"LineWidth"):
+ if hasattr(obj.ViewObject.LineWidth,"Value"):
+ lw = obj.ViewObject.LineWidth.Value
+ else:
+ lw = obj.ViewObject.LineWidth
+ linewidth = lw*linewidth
fontsize = (float(fontsize)/scale)/2
if linespacing:
linespacing = float(linespacing)/scale
@@ -102,7 +111,7 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
elif isinstance(direction,WorkingPlane.plane):
plane = direction
stroke = "#000000"
- if color:
+ if color and override:
if "#" in color:
stroke = color
else:
@@ -111,10 +120,18 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
if hasattr(obj,"ViewObject"):
if hasattr(obj.ViewObject,"LineColor"):
stroke = getrgb(obj.ViewObject.LineColor)
-
+ elif hasattr(obj.ViewObject,"TextColor"):
+ stroke = getrgb(obj.ViewObject.TextColor)
+ lstyle = "none"
+ if override:
+ lstyle = getLineStyle(linestyle, scale)
+ else:
+ if hasattr(obj,"ViewObject"):
+ if hasattr(obj.ViewObject,"DrawStyle"):
+ lstyle = getLineStyle(obj.ViewObject.DrawStyle, scale)
def getPath(edges=[],wires=[],pathname=None):
- import Part,DraftGeomUtils
+
svg = "\n'
return svg
- def getText(color,fontsize,fontname,angle,base,text,linespacing=0.5,align="center",flip=True):
+ def getText(tcolor,fontsize,fontname,angle,base,text,linespacing=0.5,align="center",flip=True):
if isinstance(angle,FreeCAD.Rotation):
if not plane:
angle = angle.Angle
@@ -390,13 +413,13 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
if techdraw:
svg = ""
for i in range(len(text)):
- t = text[i]
+ t = text[i].replace("&","&").replace("<","<").replace(">",">")
if six.PY2 and not isinstance(t, six.text_type):
t = t.decode("utf8")
# possible workaround if UTF8 is unsupported
# import unicodedata
# t = u"".join([c for c in unicodedata.normalize("NFKD",t) if not unicodedata.combining(c)]).encode("utf8")
- svg += '\n' + t + '\n'
else:
- svg = '\n'
if len(text) == 1:
try:
- svg += text[0]
+ svg += text[0].replace("&","&").replace("<","<").replace(">",">")
except:
- svg += text[0].decode("utf8")
+ svg += text[0].decode("utf8").replace("&","&").replace("<","<").replace(">",">")
else:
for i in range(len(text)):
if i == 0:
@@ -436,9 +459,9 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
else:
svg += ''
try:
- svg += text[i]
+ svg += text[i].replace("&","&").replace("<","<").replace(">",">")
except:
- svg += text[i].decode("utf8")
+ svg += text[i].decode("utf8").replace("&","&").replace("<","<").replace(">",">")
svg += '\n'
svg += '\n'
return svg
@@ -454,7 +477,6 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
fill = "#888888"
else:
fill = 'url(#'+fillstyle+')'
- lstyle = getLineStyle(linestyle, scale)
svg += getPath(obj.Edges,pathname="")
@@ -552,7 +574,6 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
# drawing arc
fill= "none"
- lstyle = getLineStyle(linestyle, scale)
if obj.ViewObject.DisplayMode == "2D":
svg += getPath([prx.circle])
else:
@@ -666,7 +687,7 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
print ("export of axes to SVG is only available in GUI mode")
else:
vobj = obj.ViewObject
- lorig = getLineStyle(linestyle, scale)
+ lorig = lstyle
fill = 'none'
rad = vobj.BubbleSize.Value/2
n = 0
@@ -703,10 +724,10 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
svg += '' + obj.ViewObject.Proxy.bubbletexts[n].string.getValues()[0] + '\n'
svg += '\n'
n += 1
+ lstyle = lorig
elif getType(obj) == "Pipe":
fill = stroke
- lstyle = getLineStyle(linestyle, scale)
if obj.Base and obj.Diameter:
svg += getPath(obj.Base.Shape.Edges)
for f in obj.Shape.Faces:
@@ -716,7 +737,6 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
elif getType(obj) == "Rebar":
fill = "none"
- lstyle = getLineStyle(linestyle, scale)
if obj.Proxy:
if not hasattr(obj.Proxy,"wires"):
obj.Proxy.execute(obj)
@@ -743,7 +763,6 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
fill_opacity = 1 - (obj.ViewObject.Transparency / 100.0)
else:
fill = "#888888"
- lstyle = getLineStyle(linestyle, scale)
svg += getPath(wires=[obj.Proxy.face.OuterWire])
c = getrgb(obj.ViewObject.TextColor)
n = obj.ViewObject.FontName
@@ -790,12 +809,14 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
fill = "#888888"
else:
fill = 'none'
- lstyle = getLineStyle(linestyle, scale)
if len(obj.Shape.Vertexes) > 1:
wiredEdges = []
if obj.Shape.Faces:
for i,f in enumerate(obj.Shape.Faces):
+ # place outer wire first
+ wires = [f.OuterWire]
+ wires.extend([w for w in f.Wires if w.hashCode() != f.OuterWire.hashCode()])
svg += getPath(wires=f.Wires,pathname='%s_f%04d' % \
(obj.Name,i))
wiredEdges.extend(f.Edges)
@@ -827,5 +848,5 @@ def getSVG(obj,scale=1,linewidth=0.35,fontsize=12,fillstyle="shape color",direct
# techdraw expects bottom-to-top coordinates
if techdraw:
- svg = ''+svg+''
+ svg = '\n '+svg+'\n'
return svg
diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py
index 1f87c136c6..d55ff2f149 100644
--- a/src/Mod/Draft/importDXF.py
+++ b/src/Mod/Draft/importDXF.py
@@ -271,6 +271,13 @@ def getACI(ob,text=False):
if not gui:
return 0
else:
+ # detect if we need to set "BYLAYER"
+ for parent in ob.InList:
+ if Draft.getType(parent) == "Layer":
+ if ob in parent.Group:
+ if hasattr(parent,"ViewObject") and hasattr(parent.ViewObject,"OverrideChildren"):
+ if parent.ViewObject.OverrideChildren:
+ return 256 # BYLAYER
if text:
col=ob.ViewObject.TextColor
else:
diff --git a/src/Mod/Fem/femmesh/gmshtools.py b/src/Mod/Fem/femmesh/gmshtools.py
index 9e75f8a9b6..96487bf4fc 100644
--- a/src/Mod/Fem/femmesh/gmshtools.py
+++ b/src/Mod/Fem/femmesh/gmshtools.py
@@ -62,55 +62,55 @@ class GmshTools():
self.geotol = 1e-08
# order
- # known_element_orders = ['1st', '2nd']
+ # known_element_orders = ["1st", "2nd"]
self.order = self.mesh_obj.ElementOrder
- if self.order == '1st':
- self.order = '1'
- elif self.order == '2nd':
- self.order = '2'
+ if self.order == "1st":
+ self.order = "1"
+ elif self.order == "2nd":
+ self.order = "2"
else:
- print('Error in order')
+ print("Error in order")
# dimension
self.dimension = self.mesh_obj.ElementDimension
# Algorithm2D
algo2D = self.mesh_obj.Algorithm2D
- if algo2D == 'Automatic':
- self.algorithm2D = '2'
- elif algo2D == 'MeshAdapt':
- self.algorithm2D = '1'
- elif algo2D == 'Delaunay':
- self.algorithm2D = '5'
- elif algo2D == 'Frontal':
- self.algorithm2D = '6'
- elif algo2D == 'BAMG':
- self.algorithm2D = '7'
- elif algo2D == 'DelQuad':
- self.algorithm2D = '8'
+ if algo2D == "Automatic":
+ self.algorithm2D = "2"
+ elif algo2D == "MeshAdapt":
+ self.algorithm2D = "1"
+ elif algo2D == "Delaunay":
+ self.algorithm2D = "5"
+ elif algo2D == "Frontal":
+ self.algorithm2D = "6"
+ elif algo2D == "BAMG":
+ self.algorithm2D = "7"
+ elif algo2D == "DelQuad":
+ self.algorithm2D = "8"
else:
- self.algorithm2D = '2'
+ self.algorithm2D = "2"
# Algorithm3D
algo3D = self.mesh_obj.Algorithm3D
- if algo3D == 'Automatic':
- self.algorithm3D = '1'
- elif algo3D == 'Delaunay':
- self.algorithm3D = '1'
- elif algo3D == 'New Delaunay':
- self.algorithm3D = '2'
- elif algo3D == 'Frontal':
- self.algorithm3D = '4'
- elif algo3D == 'Frontal Delaunay':
- self.algorithm3D = '5'
- elif algo3D == 'Frontal Hex':
- self.algorithm3D = '6'
- elif algo3D == 'MMG3D':
- self.algorithm3D = '7'
- elif algo3D == 'R-tree':
- self.algorithm3D = '9'
+ if algo3D == "Automatic":
+ self.algorithm3D = "1"
+ elif algo3D == "Delaunay":
+ self.algorithm3D = "1"
+ elif algo3D == "New Delaunay":
+ self.algorithm3D = "2"
+ elif algo3D == "Frontal":
+ self.algorithm3D = "4"
+ elif algo3D == "Frontal Delaunay":
+ self.algorithm3D = "5"
+ elif algo3D == "Frontal Hex":
+ self.algorithm3D = "6"
+ elif algo3D == "MMG3D":
+ self.algorithm3D = "7"
+ elif algo3D == "R-tree":
+ self.algorithm3D = "9"
else:
- self.algorithm3D = '1'
+ self.algorithm3D = "1"
# mesh groups
if self.mesh_obj.GroupsOfNodes is True:
@@ -120,30 +120,30 @@ class GmshTools():
self.group_elements = {}
# mesh regions
- self.ele_length_map = {} # { 'ElementString' : element length }
- self.ele_node_map = {} # { 'ElementString' : [element nodes] }
+ self.ele_length_map = {} # { "ElementString" : element length }
+ self.ele_node_map = {} # { "ElementString" : [element nodes] }
# mesh boundary layer
self.bl_setting_list = [] # list of dict, each item map to MeshBoundaryLayer object
self.bl_boundary_list = [] # to remove duplicated boundary edge or faces
# other initializations
- self.temp_file_geometry = ''
- self.temp_file_mesh = ''
- self.temp_file_geo = ''
- self.mesh_name = ''
- self.gmsh_bin = ''
+ self.temp_file_geometry = ""
+ self.temp_file_mesh = ""
+ self.temp_file_geo = ""
+ self.mesh_name = ""
+ self.gmsh_bin = ""
self.error = False
def create_mesh(self):
print("\nWe are going to start Gmsh FEM mesh run!")
print(
- ' Part to mesh: Name --> {}, Label --> {}, ShapeType --> {}'
+ " Part to mesh: Name --> {}, Label --> {}, ShapeType --> {}"
.format(self.part_obj.Name, self.part_obj.Label, self.part_obj.Shape.ShapeType)
)
- print(' CharacteristicLengthMax: ' + str(self.clmax))
- print(' CharacteristicLengthMin: ' + str(self.clmin))
- print(' ElementOrder: ' + self.order)
+ print(" CharacteristicLengthMax: " + str(self.clmax))
+ print(" CharacteristicLengthMin: " + str(self.clmin))
+ print(" ElementOrder: " + self.order)
self.get_dimension()
self.get_tmp_file_paths()
self.get_gmsh_command()
@@ -158,45 +158,45 @@ class GmshTools():
def get_dimension(self):
# Dimension
- # known_element_dimensions = ['From Shape', '1D', '2D', '3D']
+ # known_element_dimensions = ["From Shape", "1D", "2D", "3D"]
# if not given, Gmsh uses the highest available.
# A use case for not "From Shape" would be a surface (2D) mesh of a solid
- if self.dimension == 'From Shape':
+ if self.dimension == "From Shape":
shty = self.part_obj.Shape.ShapeType
- if shty == 'Solid' or shty == 'CompSolid':
- # print('Found: ' + shty)
- self.dimension = '3'
- elif shty == 'Face' or shty == 'Shell':
- # print('Found: ' + shty)
- self.dimension = '2'
- elif shty == 'Edge' or shty == 'Wire':
- # print('Found: ' + shty)
- self.dimension = '1'
- elif shty == 'Vertex':
- # print('Found: ' + shty)
+ if shty == "Solid" or shty == "CompSolid":
+ # print("Found: " + shty)
+ self.dimension = "3"
+ elif shty == "Face" or shty == "Shell":
+ # print("Found: " + shty)
+ self.dimension = "2"
+ elif shty == "Edge" or shty == "Wire":
+ # print("Found: " + shty)
+ self.dimension = "1"
+ elif shty == "Vertex":
+ # print("Found: " + shty)
FreeCAD.Console.PrintError("You can not mesh a Vertex.\n")
- self.dimension = '0'
- elif shty == 'Compound':
- # print(' Found a ' + shty)
+ self.dimension = "0"
+ elif shty == "Compound":
+ # print(" Found a " + shty)
FreeCAD.Console.PrintLog(
" Found a Compound. Since it could contain"
"any kind of shape dimension 3 is used.\n"
)
- self.dimension = '3' # dimension 3 works for 2D and 1d shapes as well
+ self.dimension = "3" # dimension 3 works for 2D and 1d shapes as well
else:
- self.dimension = '0'
+ self.dimension = "0"
FreeCAD.Console.PrintError(
- 'Could not retrieve Dimension from shape type. Please choose dimension.'
+ "Could not retrieve Dimension from shape type. Please choose dimension."
)
- elif self.dimension == '3D':
- self.dimension = '3'
- elif self.dimension == '2D':
- self.dimension = '2'
- elif self.dimension == '1D':
- self.dimension = '1'
+ elif self.dimension == "3D":
+ self.dimension = "3"
+ elif self.dimension == "2D":
+ self.dimension = "2"
+ elif self.dimension == "1D":
+ self.dimension = "1"
else:
- print('Error in dimension')
- print(' ElementDimension: ' + self.dimension)
+ print("Error in dimension")
+ print(" ElementDimension: " + self.dimension)
def get_tmp_file_paths(self):
if system() == "Linux":
@@ -207,15 +207,15 @@ class GmshTools():
path_sep = "/"
tmpdir = tempfile.gettempdir()
# geometry file
- self.temp_file_geometry = tmpdir + path_sep + self.part_obj.Name + '_Geometry.brep'
- print(' ' + self.temp_file_geometry)
+ self.temp_file_geometry = tmpdir + path_sep + self.part_obj.Name + "_Geometry.brep"
+ print(" " + self.temp_file_geometry)
# mesh file
- self.mesh_name = self.part_obj.Name + '_Mesh_TmpGmsh'
- self.temp_file_mesh = tmpdir + path_sep + self.mesh_name + '.unv'
- print(' ' + self.temp_file_mesh)
+ self.mesh_name = self.part_obj.Name + "_Mesh_TmpGmsh"
+ self.temp_file_mesh = tmpdir + path_sep + self.mesh_name + ".unv"
+ print(" " + self.temp_file_mesh)
# Gmsh input file
- self.temp_file_geo = tmpdir + path_sep + 'shape2mesh.geo'
- print(' ' + self.temp_file_geo)
+ self.temp_file_geo = tmpdir + path_sep + "shape2mesh.geo"
+ print(" " + self.temp_file_geo)
def get_gmsh_command(self):
gmsh_std_location = FreeCAD.ParamGet(
@@ -229,12 +229,12 @@ class GmshTools():
).SetString("gmshBinaryPath", gmsh_path)
self.gmsh_bin = gmsh_path
elif system() == "Linux":
- p1 = subprocess.Popen(['which', 'gmsh'], stdout=subprocess.PIPE)
+ p1 = subprocess.Popen(["which", "gmsh"], stdout=subprocess.PIPE)
if p1.wait() == 0:
output = p1.stdout.read()
if sys.version_info.major >= 3:
- output = output.decode('utf-8')
- gmsh_path = output.split('\n')[0]
+ output = output.decode("utf-8")
+ gmsh_path = output.split("\n")[0]
elif p1.wait() == 1:
error_message = (
"Gmsh binary gmsh not found in standard system binary path. "
@@ -263,7 +263,7 @@ class GmshTools():
self.gmsh_bin = FreeCAD.getHomePath() + "bin/gmsh.exe"
else:
self.gmsh_bin = "gmsh"
- print(' ' + self.gmsh_bin)
+ print(" " + self.gmsh_bin)
def get_group_data(self):
# TODO: solids, faces, edges and vertexes don't seem to work together in one group,
@@ -271,10 +271,10 @@ class GmshTools():
# mesh group objects
if not self.mesh_obj.MeshGroupList:
- # print(' No mesh group objects.')
+ # print(" No mesh group objects.")
pass
else:
- print(' Mesh group objects, we need to get the elements.')
+ print(" Mesh group objects, we need to get the elements.")
for mg in self.mesh_obj.MeshGroupList:
new_group_elements = meshtools.get_mesh_group_elements(mg, self.part_obj)
for ge in new_group_elements:
@@ -288,7 +288,7 @@ class GmshTools():
"User parameter:BaseApp/Preferences/Mod/Fem/General"
).GetBool("AnalysisGroupMeshing", False)
if self.analysis and analysis_group_meshing:
- print(' Group meshing for analysis.')
+ print(" Group meshing for analysis.")
self.group_nodes_export = True
new_group_elements = meshtools.get_analysis_group_elements(
self.analysis,
@@ -300,18 +300,18 @@ class GmshTools():
else:
FreeCAD.Console.PrintError(" A group with this name exists already.\n")
else:
- print(' No Group meshing for analysis.')
+ print(" No Group meshing for analysis.")
if self.group_elements:
- print(' {}'.format(self.group_elements))
+ print(" {}".format(self.group_elements))
def get_region_data(self):
# mesh regions
if not self.mesh_obj.MeshRegionList:
- # print(' No mesh regions.')
+ # print(" No mesh regions.")
pass
else:
- print(' Mesh regions, we need to get the elements.')
+ print(" Mesh regions, we need to get the elements.")
# by the use of MeshRegion object and a BooleanSplitCompound
# there could be problems with node numbers see
# http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&start=40#p149467
@@ -324,11 +324,11 @@ class GmshTools():
or part.Proxy.Type == "FeatureSlice" \
or part.Proxy.Type == "FeatureXOR":
error_message = (
- ' The mesh to shape is a boolean split tools Compound '
- 'and the mesh has mesh region list. '
- 'Gmsh could return unexpected meshes in such circumstances. '
- 'It is strongly recommended to extract the shape to mesh '
- 'from the Compound and use this one.'
+ " The mesh to shape is a boolean split tools Compound "
+ "and the mesh has mesh region list. "
+ "Gmsh could return unexpected meshes in such circumstances. "
+ "It is strongly recommended to extract the shape to mesh "
+ "from the Compound and use this one."
)
FreeCAD.Console.PrintError(error_message + "\n")
# TODO: no gui popup because FreeCAD will be in a endless output loop
@@ -387,14 +387,14 @@ class GmshTools():
)
else:
FreeCAD.Console.PrintError(
- 'The meshregion: {} is not used to create the mesh '
- 'because the reference list is empty.\n'
+ "The meshregion: {} is not used to create the mesh "
+ "because the reference list is empty.\n"
.format(mr_obj.Name)
)
else:
FreeCAD.Console.PrintError(
- 'The meshregion: {} is not used to create the '
- 'mesh because the CharacteristicLength is 0.0 mm.\n'
+ "The meshregion: {} is not used to create the "
+ "mesh because the CharacteristicLength is 0.0 mm.\n"
.format(mr_obj.Name)
)
for eleml in self.ele_length_map:
@@ -402,8 +402,8 @@ class GmshTools():
ele_shape = meshtools.get_element(self.part_obj, eleml)
ele_vertexes = meshtools.get_vertexes_by_element(self.part_obj.Shape, ele_shape)
self.ele_node_map[eleml] = ele_vertexes
- print(' {}'.format(self.ele_length_map))
- print(' {}'.format(self.ele_node_map))
+ print(" {}".format(self.ele_length_map))
+ print(" {}".format(self.ele_node_map))
def get_boundary_layer_data(self):
# mesh boundary layer
@@ -412,11 +412,11 @@ class GmshTools():
# Mesh.CharacteristicLengthMin, must be zero
# or a value less than first inflation layer height
if not self.mesh_obj.MeshBoundaryLayerList:
- # print(' No mesh boundary layer setting document object.')
+ # print(" No mesh boundary layer setting document object.")
pass
else:
- print(' Mesh boundary layers, we need to get the elements.')
- if self.part_obj.Shape.ShapeType == 'Compound':
+ print(" Mesh boundary layers, we need to get the elements.")
+ if self.part_obj.Shape.ShapeType == "Compound":
# see http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&start=40#p149467 and
# http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&p=149520#p149520
err = (
@@ -478,30 +478,30 @@ class GmshTools():
.format(elems, mr_obj.Name)
)
setting = {}
- setting['hwall_n'] = Units.Quantity(mr_obj.MinimumThickness).Value
- setting['ratio'] = mr_obj.GrowthRate
- setting['thickness'] = sum([
- setting['hwall_n'] * setting['ratio'] ** i for i in range(
+ setting["hwall_n"] = Units.Quantity(mr_obj.MinimumThickness).Value
+ setting["ratio"] = mr_obj.GrowthRate
+ setting["thickness"] = sum([
+ setting["hwall_n"] * setting["ratio"] ** i for i in range(
mr_obj.NumberOfLayers
)
])
- # setting['hwall_n'] * 5 # tangential cell dimension
- setting['hwall_t'] = setting['thickness']
+ # setting["hwall_n"] * 5 # tangential cell dimension
+ setting["hwall_t"] = setting["thickness"]
# hfar: cell dimension outside boundary
# should be set later if some character length is set
- if self.clmax > setting['thickness'] * 0.8 \
- and self.clmax < setting['thickness'] * 1.6:
- setting['hfar'] = self.clmax
+ if self.clmax > setting["thickness"] * 0.8 \
+ and self.clmax < setting["thickness"] * 1.6:
+ setting["hfar"] = self.clmax
else:
# set a value for safety, it may works as background mesh cell size
- setting['hfar'] = setting['thickness']
+ setting["hfar"] = setting["thickness"]
# from face name -> face id is done in geo file write up
# TODO: fan angle setup is not implemented yet
- if self.dimension == '2':
- setting['EdgesList'] = belem_list
- elif self.dimension == '3':
- setting['FacesList'] = belem_list
+ if self.dimension == "2":
+ setting["EdgesList"] = belem_list
+ elif self.dimension == "3":
+ setting["FacesList"] = belem_list
else:
FreeCAD.Console.PrintError(
"boundary layer is only supported for 2D and 3D mesh"
@@ -509,38 +509,38 @@ class GmshTools():
self.bl_setting_list.append(setting)
else:
FreeCAD.Console.PrintError(
- 'The mesh boundary layer: {} is not used to create '
- 'the mesh because the reference list is empty.\n'
+ "The mesh boundary layer: {} is not used to create "
+ "the mesh because the reference list is empty.\n"
.format(mr_obj.Name)
)
else:
FreeCAD.Console.PrintError(
- 'The mesh boundary layer: {} is not used to create '
- 'the mesh because the min thickness is 0.0 mm.\n'
+ "The mesh boundary layer: {} is not used to create "
+ "the mesh because the min thickness is 0.0 mm.\n"
.format(mr_obj.Name)
)
- print(' {}'.format(self.bl_setting_list))
+ print(" {}".format(self.bl_setting_list))
def write_boundary_layer(self, geo):
# currently single body is supported
if len(self.bl_setting_list):
geo.write("// boundary layer setting\n")
- print(' Start to write boundary layer setup')
+ print(" Start to write boundary layer setup")
field_number = 1
for item in self.bl_setting_list:
prefix = "Field[" + str(field_number) + "]"
geo.write(prefix + " = BoundaryLayer;\n")
for k in item:
v = item[k]
- if k in set(['EdgesList', 'FacesList']):
+ if k in set(["EdgesList", "FacesList"]):
# the element name of FreeCAD which starts
- # with 1 (example: 'Face1'), same as Gmsh
+ # with 1 (example: "Face1"), same as Gmsh
# el_id = int(el[4:]) # FIXME: strip `face` or `edge` prefix
- ele_nodes = (''.join((str(el[4:]) + ', ') for el in v)).rstrip(', ')
- line = prefix + '.' + str(k) + ' = {' + ele_nodes + ' };\n'
+ ele_nodes = ("".join((str(el[4:]) + ", ") for el in v)).rstrip(", ")
+ line = prefix + "." + str(k) + " = {" + ele_nodes + " };\n"
geo.write(line)
else:
- line = prefix + '.' + str(k) + ' = ' + str(v) + ';\n'
+ line = prefix + "." + str(k) + " = " + str(v) + ";\n"
geo.write(line)
print(line)
geo.write("BoundaryLayer Field = " + str(field_number) + ";\n")
@@ -548,9 +548,9 @@ class GmshTools():
field_number += 1
geo.write("\n")
geo.flush()
- print(' finished in boundary layer setup')
+ print(" finished in boundary layer setup")
else:
- # print(' no boundary layer setup is found for this mesh')
+ # print(" no boundary layer setup is found for this mesh")
geo.write("// no boundary layer settings for this mesh\n")
def write_part_file(self):
@@ -561,40 +561,40 @@ class GmshTools():
geo.write("// geo file for meshing with Gmsh meshing software created by FreeCAD\n")
geo.write("\n")
geo.write("// open brep geometry\n")
- geo.write('Merge "' + self.temp_file_geometry + '";\n')
+ geo.write("Merge "" + self.temp_file_geometry + "";\n")
geo.write("\n")
if self.group_elements:
- # print(' We are going to have to find elements to make mesh groups for.')
+ # print(" We are going to have to find elements to make mesh groups for.")
geo.write("// group data\n")
# we use the element name of FreeCAD which starts
- # with 1 (example: 'Face1'), same as Gmsh
+ # with 1 (example: "Face1"), same as Gmsh
# for unit test we need them to have a fixed order
for group in sorted(self.group_elements.keys()):
gdata = self.group_elements[group]
# print(gdata)
# geo.write("// " + group + "\n")
- ele_nr = ''
- if gdata[0].startswith('Solid'):
- physical_type = 'Volume'
+ ele_nr = ""
+ if gdata[0].startswith("Solid"):
+ physical_type = "Volume"
for ele in gdata:
- ele_nr += (ele.lstrip('Solid') + ', ')
- elif gdata[0].startswith('Face'):
- physical_type = 'Surface'
+ ele_nr += (ele.lstrip("Solid") + ", ")
+ elif gdata[0].startswith("Face"):
+ physical_type = "Surface"
for ele in gdata:
- ele_nr += (ele.lstrip('Face') + ', ')
- elif gdata[0].startswith('Edge'):
- physical_type = 'Line'
+ ele_nr += (ele.lstrip("Face") + ", ")
+ elif gdata[0].startswith("Edge"):
+ physical_type = "Line"
for ele in gdata:
- ele_nr += (ele.lstrip('Edge') + ', ')
- elif gdata[0].startswith('Vertex'):
- physical_type = 'Point'
+ ele_nr += (ele.lstrip("Edge") + ", ")
+ elif gdata[0].startswith("Vertex"):
+ physical_type = "Point"
for ele in gdata:
- ele_nr += (ele.lstrip('Vertex') + ', ')
+ ele_nr += (ele.lstrip("Vertex") + ", ")
if ele_nr:
- ele_nr = ele_nr.rstrip(', ')
+ ele_nr = ele_nr.rstrip(", ")
# print(ele_nr)
geo.write(
- 'Physical ' + physical_type + '("' + group + '") = {' + ele_nr + '};\n'
+ "Physical " + physical_type + "("" + group + "") = {" + ele_nr + "};\n"
)
geo.write("\n")
geo.write("// Characteristic Length\n")
@@ -604,8 +604,8 @@ class GmshTools():
geo.write("// Characteristic Length according CharacteristicLengthMap\n")
for e in self.ele_length_map:
ele_nodes = (
- ''.join((str(n + 1) + ', ') for n in self.ele_node_map[e])
- ).rstrip(', ')
+ "".join((str(n + 1) + ", ") for n in self.ele_node_map[e])
+ ).rstrip(", ")
geo.write("// " + e + "\n")
elestr1 = "{"
elestr2 = "}"
@@ -633,23 +633,23 @@ class GmshTools():
else:
geo.write("Mesh.CharacteristicLengthMin = " + str(self.clmin) + ";\n")
geo.write("\n")
- if hasattr(self.mesh_obj, 'RecombineAll') and self.mesh_obj.RecombineAll is True:
+ if hasattr(self.mesh_obj, "RecombineAll") and self.mesh_obj.RecombineAll is True:
geo.write("// other mesh options\n")
geo.write("Mesh.RecombineAll = 1;\n")
geo.write("\n")
geo.write("// optimize the mesh\n")
# Gmsh tetra optimizer
- if hasattr(self.mesh_obj, 'OptimizeStd') and self.mesh_obj.OptimizeStd is True:
+ if hasattr(self.mesh_obj, "OptimizeStd") and self.mesh_obj.OptimizeStd is True:
geo.write("Mesh.Optimize = 1;\n")
else:
geo.write("Mesh.Optimize = 0;\n")
# Netgen optimizer in Gmsh
- if hasattr(self.mesh_obj, 'OptimizeNetgen') and self.mesh_obj.OptimizeNetgen is True:
+ if hasattr(self.mesh_obj, "OptimizeNetgen") and self.mesh_obj.OptimizeNetgen is True:
geo.write("Mesh.OptimizeNetgen = 1;\n")
else:
geo.write("Mesh.OptimizeNetgen = 0;\n")
# higher order mesh optimizing
- if hasattr(self.mesh_obj, 'HighOrderOptimize') and self.mesh_obj.HighOrderOptimize is True:
+ if hasattr(self.mesh_obj, "HighOrderOptimize") and self.mesh_obj.HighOrderOptimize is True:
geo.write(
"Mesh.HighOrderOptimize = 1; // for more HighOrderOptimize "
"parameter check http://gmsh.info/doc/texinfo/gmsh.html\n"
@@ -673,7 +673,7 @@ class GmshTools():
"5=Delaunay, 6=Frontal, 7=BAMG, 8=DelQuad)\n"
)
if len(self.bl_setting_list) and self.dimension == 3:
- geo.write("Mesh.Algorithm = " + 'DelQuad' + ";\n") # Frontal/DelQuad are tested
+ geo.write("Mesh.Algorithm = " + "DelQuad" + ";\n") # Frontal/DelQuad are tested
else:
geo.write("Mesh.Algorithm = " + self.algorithm2D + ";\n")
geo.write(
@@ -686,7 +686,7 @@ class GmshTools():
geo.write("// meshing\n")
# remove duplicate vertices
# see https://forum.freecadweb.org/viewtopic.php?f=18&t=21571&start=20#p179443
- if hasattr(self.mesh_obj, 'CoherenceMesh') and self.mesh_obj.CoherenceMesh is True:
+ if hasattr(self.mesh_obj, "CoherenceMesh") and self.mesh_obj.CoherenceMesh is True:
geo.write(
"Geometry.Tolerance = {}; // set geometrical "
"tolerance (also used for merging nodes)\n"
@@ -727,7 +727,7 @@ class GmshTools():
geo.close()
def run_gmsh_with_geo(self):
- comandlist = [self.gmsh_bin, '-', self.temp_file_geo]
+ comandlist = [self.gmsh_bin, "-", self.temp_file_geo]
# print(comandlist)
try:
p = subprocess.Popen(
@@ -738,14 +738,14 @@ class GmshTools():
)
output, error = p.communicate()
if sys.version_info.major >= 3:
- # output = output.decode('utf-8')
- error = error.decode('utf-8')
+ # output = output.decode("utf-8")
+ error = error.decode("utf-8")
# stdout is still cut at some point
# but the warnings are in stderr and thus printed :-)
# print(output)
# print(error)
except:
- error = 'Error executing: {}\n'.format(" ".join(comandlist))
+ error = "Error executing: {}\n".format(" ".join(comandlist))
FreeCAD.Console.PrintError(error)
self.error = True
return error
@@ -754,25 +754,25 @@ class GmshTools():
if not self.error:
fem_mesh = Fem.read(self.temp_file_mesh)
self.mesh_obj.FemMesh = fem_mesh
- FreeCAD.Console.PrintMessage(' The Part should have a pretty new FEM mesh!\n')
+ FreeCAD.Console.PrintMessage(" The Part should have a pretty new FEM mesh!\n")
else:
- FreeCAD.Console.PrintError('No mesh was created.\n')
+ FreeCAD.Console.PrintError("No mesh was created.\n")
del self.temp_file_geometry
del self.temp_file_mesh
## @}
-'''
+"""
# simple example how to use the class GmshTools
import Part, ObjectsFem
doc = App.ActiveDocument
-box_obj = doc.addObject('Part::Box', 'Box')
+box_obj = doc.addObject("Part::Box", "Box")
doc.recompute()
-femmesh_obj = ObjectsFem.makeMeshGmsh(doc, box_obj.Name + '_Mesh')
+femmesh_obj = ObjectsFem.makeMeshGmsh(doc, box_obj.Name + "_Mesh")
femmesh_obj.Part = box_obj
doc.recompute()
box_obj.ViewObject.Visibility = False
@@ -783,9 +783,9 @@ error = gmsh_mesh.create_mesh()
print(error)
doc.recompute()
-'''
+"""
-'''
+"""
TODO
class GmshTools should be splittet in two classes
one class should only collect the mesh parameter from mesh object and his childs
@@ -794,4 +794,4 @@ writes the input file runs gmsh reads back the unv and returns a FemMesh
gmsh binary will be collected in the second class
with this we could mesh without document objects
create a shape and run meshinging class, get the FemMesh :-)
-'''
+"""
diff --git a/src/Mod/Fem/femmesh/meshtools.py b/src/Mod/Fem/femmesh/meshtools.py
index 7cc82168cf..aae871210d 100644
--- a/src/Mod/Fem/femmesh/meshtools.py
+++ b/src/Mod/Fem/femmesh/meshtools.py
@@ -37,8 +37,8 @@ def get_femnodes_by_femobj_with_references(
):
node_set = []
if femmesh.GroupCount:
- node_set = get_femmesh_groupdata_sets_by_name(femmesh, femobj, 'Node')
- # FreeCAD.Console.PrintMessage('node_set_group: {}\n'.format(node_set))
+ node_set = get_femmesh_groupdata_sets_by_name(femmesh, femobj, "Node")
+ # FreeCAD.Console.PrintMessage("node_set_group: {}\n".format(node_set))
if node_set:
FreeCAD.Console.PrintMessage(
" Finite element mesh nodes where retrieved "
@@ -49,8 +49,8 @@ def get_femnodes_by_femobj_with_references(
" Finite element mesh nodes will be retrieved "
"by searching the appropriate nodes in the finite element mesh.\n"
)
- node_set = get_femnodes_by_references(femmesh, femobj['Object'].References)
- # FreeCAD.Console.PrintMessage('node_set_nogroup: {}\n'.format(node_set))
+ node_set = get_femnodes_by_references(femmesh, femobj["Object"].References)
+ # FreeCAD.Console.PrintMessage("node_set_nogroup: {}\n".format(node_set))
return node_set
@@ -62,8 +62,8 @@ def get_femelements_by_references(
references,
femnodes_ele_table=None
):
- '''get the femelements for a list of references
- '''
+ """get the femelements for a list of references
+ """
references_femelements = []
for ref in references:
# femnodes for the current ref
@@ -91,8 +91,8 @@ def get_femnodes_by_references(
femmesh,
references
):
- '''get the femnodes for a list of references
- '''
+ """get the femnodes for a list of references
+ """
references_femnodes = []
for ref in references:
references_femnodes += get_femnodes_by_refshape(femmesh, ref)
@@ -112,25 +112,25 @@ def get_femnodes_by_refshape(
# the following method getElement(element) does not return Solid elements
r = get_element(ref[0], refelement)
FreeCAD.Console.PrintMessage(
- ' '
- 'ReferenceShape ... Type: {0}, '
- 'Object name: {1}, '
- 'Object label: {2}, '
- 'Element name: {3}\n'
+ " "
+ "ReferenceShape ... Type: {0}, "
+ "Object name: {1}, "
+ "Object label: {2}, "
+ "Element name: {3}\n"
.format(r.ShapeType, ref[0].Name, ref[0].Label, refelement)
)
- if r.ShapeType == 'Vertex':
+ if r.ShapeType == "Vertex":
nodes += femmesh.getNodesByVertex(r)
- elif r.ShapeType == 'Edge':
+ elif r.ShapeType == "Edge":
nodes += femmesh.getNodesByEdge(r)
- elif r.ShapeType == 'Face':
+ elif r.ShapeType == "Face":
nodes += femmesh.getNodesByFace(r)
- elif r.ShapeType == 'Solid':
+ elif r.ShapeType == "Solid":
nodes += femmesh.getNodesBySolid(r)
else:
FreeCAD.Console.PrintMessage(
- ' '
- 'No Vertice, Edge, Face or Solid as reference shapes!\n'
+ " "
+ "No Vertice, Edge, Face or Solid as reference shapes!\n"
)
return nodes
@@ -151,7 +151,7 @@ def get_femelement_table(
for i in femmesh.Edges:
femelement_table[i] = femmesh.getElementNodes(i)
else:
- FreeCAD.Console.PrintError('Neither solid nor face nor edge femmesh!\n')
+ FreeCAD.Console.PrintError("Neither solid nor face nor edge femmesh!\n")
return femelement_table
@@ -199,7 +199,7 @@ def get_femnodes_ele_table(
femnodes_mesh,
femelement_table
):
- '''the femnodes_ele_table contains for each node its membership in elements
+ """the femnodes_ele_table contains for each node its membership in elements
{nodeID : [[eleID, NodePosition], [], ...], nodeID : [[], [], ...], ...}
stored information is:
element number, the number of nodes per element
@@ -213,22 +213,22 @@ def get_femnodes_ele_table(
volume or face or edgemesh the femnodes_ele_table only
has either volume or face or edge elements
see get_femelement_table()
- '''
+ """
femnodes_ele_table = {} # node_dict in ulrichs class
for n in femnodes_mesh: # initialize it with sorted node keys and empty lists
femnodes_ele_table[n] = []
for ele in femelement_table:
ele_list = femelement_table[ele]
- # FreeCAD.Console.PrintMessage('{}\n'.format(ele_list))
+ # FreeCAD.Console.PrintMessage("{}\n".format(ele_list))
pos = int(1)
for ele_node in ele_list:
femnodes_ele_table[ele_node].append([ele, pos])
pos = pos << 1
FreeCAD.Console.PrintLog(
- 'len femnodes_ele_table: {}\n'
+ "len femnodes_ele_table: {}\n"
.format(len(femnodes_ele_table))
)
- FreeCAD.Console.PrintLog('femnodes_ele_table: {}\n'.format(femnodes_ele_table))
+ FreeCAD.Console.PrintLog("femnodes_ele_table: {}\n".format(femnodes_ele_table))
return femnodes_ele_table
@@ -236,8 +236,8 @@ def get_femnodes_ele_table(
def get_copy_of_empty_femelement_table(
femelement_table
):
- '''{eleID : 0, eleID : 0, ...}
- '''
+ """{eleID : 0, eleID : 0, ...}
+ """
empty_femelement_table = {}
for ele in femelement_table: # initialize it with sorted element keys and empty int
empty_femelement_table[ele] = 0
@@ -250,9 +250,9 @@ def get_bit_pattern_dict(
femnodes_ele_table,
node_set
):
- '''Now we are looking for nodes inside of the Faces = filling the bit_pattern_dict
+ """Now we are looking for nodes inside of the Faces = filling the bit_pattern_dict
{eleID : [lenEleNodes, binary_position]}
- see forum post for a very good explanation of what's really happening
+ see forum post for a very good explanation of what"s really happening
https://forum.freecadweb.org/viewtopic.php?f=18&t=17318&start=50#p141108
The bit_pattern_dict holds later an integer (bit array) for each element, which gives us
the information we are searching for:
@@ -260,10 +260,10 @@ def get_bit_pattern_dict(
or has this element a face we are searching for?
The number in the ele_dict is organized as a bit array.
The corresponding bit is set, if the node of the node_set is contained in the element.
- '''
- FreeCAD.Console.PrintLog('len femnodes_ele_table: ' + str(len(femnodes_ele_table)) + '\n')
- FreeCAD.Console.PrintLog('len node_set: ' + str(len(node_set)) + '\n')
- FreeCAD.Console.PrintLog('node_set: {}\n'.format(node_set))
+ """
+ FreeCAD.Console.PrintLog("len femnodes_ele_table: " + str(len(femnodes_ele_table)) + "\n")
+ FreeCAD.Console.PrintLog("len node_set: " + str(len(node_set)) + "\n")
+ FreeCAD.Console.PrintLog("node_set: {}\n".format(node_set))
bit_pattern_dict = get_copy_of_empty_femelement_table(femelement_table)
# # initializing the bit_pattern_dict
for ele in femelement_table:
@@ -272,8 +272,8 @@ def get_bit_pattern_dict(
for node in node_set:
for nList in femnodes_ele_table[node]:
bit_pattern_dict[nList[0]][1] += nList[1]
- FreeCAD.Console.PrintLog('len bit_pattern_dict: ' + str(len(bit_pattern_dict)) + '\n')
- # FreeCAD.Console.PrintMessage('bit_pattern_dict: {}\n'.format(bit_pattern_dict))
+ FreeCAD.Console.PrintLog("len bit_pattern_dict: " + str(len(bit_pattern_dict)) + "\n")
+ # FreeCAD.Console.PrintMessage("bit_pattern_dict: {}\n".format(bit_pattern_dict))
return bit_pattern_dict
@@ -281,8 +281,8 @@ def get_bit_pattern_dict(
def get_ccxelement_faces_from_binary_search(
bit_pattern_dict
):
- '''get the CalculiX element face numbers
- '''
+ """get the CalculiX element face numbers
+ """
tet10_mask = {
119: 1,
411: 2,
@@ -332,8 +332,8 @@ def get_ccxelement_faces_from_binary_search(
for key in mask_dict:
if (key & bit_pattern_dict[ele][1]) == key:
faces.append([ele, mask_dict[key]])
- FreeCAD.Console.PrintLog('found Faces: {}\n'.format(len(faces)))
- # FreeCAD.Console.PrintMessage('faces: {}\n'.format(faces))
+ FreeCAD.Console.PrintLog("found Faces: {}\n".format(len(faces)))
+ # FreeCAD.Console.PrintMessage("faces: {}\n".format(faces))
return faces
@@ -343,12 +343,12 @@ def get_femelements_by_femnodes_bin(
femnodes_ele_table,
node_list
):
- '''for every femelement of femelement_table
+ """for every femelement of femelement_table
if all nodes of the femelement are in node_list,
the femelement is added to the list which is returned
blind fast binary search, but works for volumes only
- '''
- FreeCAD.Console.PrintMessage('binary search: get_femelements_by_femnodes_bin\n')
+ """
+ FreeCAD.Console.PrintMessage("binary search: get_femelements_by_femnodes_bin\n")
vol_masks = {
4: 15,
6: 63,
@@ -358,7 +358,7 @@ def get_femelements_by_femnodes_bin(
20: 1048575}
# Now we are looking for nodes inside of the Volumes = filling the bit_pattern_dict
FreeCAD.Console.PrintMessage(
- 'len femnodes_ele_table: {}\n'
+ "len femnodes_ele_table: {}\n"
.format(len(femnodes_ele_table))
)
bit_pattern_dict = get_bit_pattern_dict(femelement_table, femnodes_ele_table, node_list)
@@ -366,12 +366,12 @@ def get_femelements_by_femnodes_bin(
ele_list = [] # The ele_list contains the result of the search.
for ele in bit_pattern_dict:
FreeCAD.Console.PrintLog(
- 'bit_pattern_dict[ele][0]: {}\n'.format(bit_pattern_dict[ele][0])
+ "bit_pattern_dict[ele][0]: {}\n".format(bit_pattern_dict[ele][0])
)
if bit_pattern_dict[ele][1] == vol_masks[bit_pattern_dict[ele][0]]:
ele_list.append(ele)
- FreeCAD.Console.PrintMessage('found Volumes: {}\n'.format(len(ele_list)))
- # FreeCAD.Console.PrintMessage(' volumes: {}\n'.format(ele_list))
+ FreeCAD.Console.PrintMessage("found Volumes: {}\n".format(len(ele_list)))
+ # FreeCAD.Console.PrintMessage(" volumes: {}\n".format(ele_list))
return ele_list
@@ -380,12 +380,12 @@ def get_femelements_by_femnodes_std(
femelement_table,
node_list
):
- '''for every femelement of femelement_table
+ """for every femelement of femelement_table
if all nodes of the femelement are in node_list,
the femelement is added to the list which is returned
e: elementlist
- nodes: nodelist '''
- FreeCAD.Console.PrintMessage('std search: get_femelements_by_femnodes_std\n')
+ nodes: nodelist """
+ FreeCAD.Console.PrintMessage("std search: get_femelements_by_femnodes_std\n")
e = [] # elementlist
for elementID in sorted(femelement_table):
nodecount = 0
@@ -402,7 +402,7 @@ def get_femvolumeelements_by_femfacenodes(
femelement_table,
node_list
):
- '''assume femelement_table only has volume elements
+ """assume femelement_table only has volume elements
for every femvolumeelement of femelement_table
for tetra4 and tetra10 the C++ methods could be used --> test again to be sure
if hexa8 volume element
@@ -414,7 +414,7 @@ def get_femvolumeelements_by_femfacenodes(
if penta15 volume element
--> if exact 6 or 8 element nodes are in node_list --> add femelement
e: elementlist
- nodes: nodelist '''
+ nodes: nodelist """
e = [] # elementlist
for elementID in sorted(femelement_table):
nodecount = 0
@@ -457,11 +457,11 @@ def get_femvolumeelements_by_femfacenodes(
e.append(elementID)
else:
FreeCAD.Console.PrintError(
- 'Error in get_femvolumeelements_by_femfacenodes(): '
- 'unknown volume element: {}\n'
+ "Error in get_femvolumeelements_by_femfacenodes(): "
+ "unknown volume element: {}\n"
.format(el_nd_ct)
)
- # FreeCAD.Console.PrintMessage('{}\n'.format(sorted(e)))
+ # FreeCAD.Console.PrintMessage("{}\n".format(sorted(e)))
return e
@@ -478,14 +478,14 @@ def get_femelement_sets(
referenced_femelements = []
has_remaining_femelements = None
for fem_object_i, fem_object in enumerate(fem_objects):
- obj = fem_object['Object']
+ obj = fem_object["Object"]
FreeCAD.Console.PrintMessage(
"Constraint: {} --> We're going to search "
"in the mesh for the element ID's.\n"
.format(obj.Name)
)
# unique short identifier
- fem_object['ShortName'] = get_elset_short_name(obj, fem_object_i)
+ fem_object["ShortName"] = get_elset_short_name(obj, fem_object_i)
if obj.References:
ref_shape_femelements = []
ref_shape_femelements = get_femelements_by_references(
@@ -495,7 +495,7 @@ def get_femelement_sets(
)
referenced_femelements += ref_shape_femelements
count_femelements += len(ref_shape_femelements)
- fem_object['FEMElements'] = ref_shape_femelements
+ fem_object["FEMElements"] = ref_shape_femelements
else:
has_remaining_femelements = obj.Name
# get remaining femelements for the fem_objects
@@ -506,15 +506,15 @@ def get_femelement_sets(
remaining_femelements.append(elemid)
count_femelements += len(remaining_femelements)
for fem_object in fem_objects:
- obj = fem_object['Object']
+ obj = fem_object["Object"]
if obj.Name == has_remaining_femelements:
- fem_object['FEMElements'] = sorted(remaining_femelements)
+ fem_object["FEMElements"] = sorted(remaining_femelements)
# check if all worked out well
if femelements_count_ok(len(femelement_table), count_femelements):
return True
else:
FreeCAD.Console.PrintError(
- 'Error in get_femelement_sets -- > femelements_count_ok() failed!\n'
+ "Error in get_femelement_sets -- > femelements_count_ok() failed!\n"
)
return False
@@ -526,17 +526,17 @@ def get_femelement_direction1D_set(
beamrotation_objects,
theshape=None
):
- '''
+ """
get for each geometry edge direction, the normal and the element ids and
# write all into the beamrotation_objects
means no return value, we're going to write into the beamrotation_objects dictionary
FEMRotations1D is a list of dictionaries for every beamdirection of all edges
- beamrot_obj['FEMRotations1D'] = [{
- 'ids' : [theids],
- 'direction' : direction,
- 'normal' : normal
+ beamrot_obj["FEMRotations1D"] = [{
+ "ids" : [theids],
+ "direction" : direction,
+ "normal" : normal
}, ... ]
- '''
+ """
if len(beamrotation_objects) == 0:
# no beamrotation document object, all beams use standard rotation of 0 degree (angle)
# we need theshape (the shape which was meshed)
@@ -545,9 +545,9 @@ def get_femelement_direction1D_set(
# add normals for each direction
rotation_angle = 0
for rot in rotations_ids:
- rot['normal'] = get_beam_normal(rot['direction'], rotation_angle)
- # key 'Object' will be empty
- beamrotation_objects.append({'FEMRotations1D': rotations_ids, 'ShortName': 'Rstd'})
+ rot["normal"] = get_beam_normal(rot["direction"], rotation_angle)
+ # key "Object" will be empty
+ beamrotation_objects.append({"FEMRotations1D": rotations_ids, "ShortName": "Rstd"})
elif len(beamrotation_objects) == 1:
# one beamrotation document object with no references
# all beams use rotation from this object
@@ -555,11 +555,11 @@ def get_femelement_direction1D_set(
# since ccx needs to split them in sets anyway we need to take care of this too
rotations_ids = get_femelement_directions_theshape(femmesh, femelement_table, theshape)
# add normals for each direction
- rotation_angle = beamrotation_objects[0]['Object'].Rotation
+ rotation_angle = beamrotation_objects[0]["Object"].Rotation
for rot in rotations_ids:
- rot['normal'] = get_beam_normal(rot['direction'], rotation_angle)
- beamrotation_objects[0]['FEMRotations1D'] = rotations_ids
- beamrotation_objects[0]['ShortName'] = 'R0'
+ rot["normal"] = get_beam_normal(rot["direction"], rotation_angle)
+ beamrotation_objects[0]["FEMRotations1D"] = rotations_ids
+ beamrotation_objects[0]["ShortName"] = "R0"
elif len(beamrotation_objects) > 1:
# multiple beam rotation document objects
# rotations defined by reference shapes, TODO implement this
@@ -573,9 +573,9 @@ def get_femelement_direction1D_set(
# pre check, only one beam rotation with empty ref shapes is allowed
# we need theshape for multiple rotations too
# because of the corner cases mentioned above
- FreeCAD.Console.PrintError('Multiple Rotations not yet supported!\n')
+ FreeCAD.Console.PrintError("Multiple Rotations not yet supported!\n")
for rot_object in beamrotation_objects: # debug output
- FreeCAD.Console.PrintMessage('{}\n'.format(rot_object['FEMRotations1D']))
+ FreeCAD.Console.PrintMessage("{}\n".format(rot_object["FEMRotations1D"]))
# ************************************************************************************************
@@ -585,15 +585,15 @@ def get_femelement_directions_theshape(femmesh, femelement_table, theshape):
# add directions and all ids for each direction
for e in theshape.Shape.Edges:
the_edge = {}
- the_edge['direction'] = e.Vertexes[1].Point - e.Vertexes[0].Point
+ the_edge["direction"] = e.Vertexes[1].Point - e.Vertexes[0].Point
edge_femnodes = femmesh.getNodesByEdge(e) # femnodes for the current edge
# femelements for this edge
- the_edge['ids'] = get_femelements_by_femnodes_std(femelement_table, edge_femnodes)
+ the_edge["ids"] = get_femelements_by_femnodes_std(femelement_table, edge_femnodes)
for rot in rotations_ids:
# tolerance will be managed by FreeCAD
# see https://forum.freecadweb.org/viewtopic.php?f=22&t=14179
- if rot['direction'] == the_edge['direction']:
- rot['ids'] += the_edge['ids']
+ if rot["direction"] == the_edge["direction"]:
+ rot["ids"] += the_edge["ids"]
break
else:
rotations_ids.append(the_edge)
@@ -651,8 +651,8 @@ def get_beam_normal(beam_direction, defined_angle):
dot_nt = vector_a[0] * normal_n[0] + vector_a[1] * normal_n[1] + vector_a[2] * normal_n[2]
dot = vector_a[0] * normal_n[0] + vector_a[1] * normal_n[1] + vector_a[2] * normal_n[2]
- FreeCAD.Console.PrintLog('{}\n'.format(dot))
- FreeCAD.Console.PrintLog('{}\n'.format(normal_n))
+ FreeCAD.Console.PrintLog("{}\n".format(dot))
+ FreeCAD.Console.PrintLog("{}\n".format(normal_n))
# dummy usage of the axis dot to get flake8 quiet
del dot_x, dot_y, dot_z, dot, dot_nt
@@ -671,15 +671,15 @@ def get_femmesh_groupdata_sets_by_name(
# no check is done in this regard !!!
# we just check for the group name and the group data type
# what happens if a reference shape was changed
- # but the mesh and the mesh groups were not created new !?!
- obj = fem_object['Object']
+ # but the mesh and the mesh groups where not created new !?!
+ obj = fem_object["Object"]
if femmesh.GroupCount:
for g in femmesh.Groups:
grp_name = femmesh.getGroupName(g)
if grp_name.startswith(obj.Name + "_"):
if femmesh.getGroupElementType(g) == group_data_type:
FreeCAD.Console.PrintMessage(
- ' found mesh group for the IDs: {}, Type: {}\n'
+ " found mesh group for the IDs: {}, Type: {}\n"
.format(grp_name, group_data_type)
)
return femmesh.getGroupElements(g) # == ref_shape_femelements
@@ -695,24 +695,24 @@ def get_femelement_sets_from_group_data(
count_femelements = 0
sum_group_elements = []
for fem_object_i, fem_object in enumerate(fem_objects):
- obj = fem_object['Object']
+ obj = fem_object["Object"]
FreeCAD.Console.PrintMessage(
"Constraint: {} --> We have mesh groups. "
"We will search for appropriate group data.\n"
.format(obj.Name)
)
# unique short identifier
- fem_object['ShortName'] = get_elset_short_name(obj, fem_object_i)
+ fem_object["ShortName"] = get_elset_short_name(obj, fem_object_i)
# see comments over there !
- group_elements = get_femmesh_groupdata_sets_by_name(femmesh, fem_object, 'Volume')
+ group_elements = get_femmesh_groupdata_sets_by_name(femmesh, fem_object, "Volume")
sum_group_elements += group_elements
count_femelements += len(group_elements)
- fem_object['FEMElements'] = group_elements
+ fem_object["FEMElements"] = group_elements
# check if all worked out well
if not femelements_count_ok(femmesh.VolumeCount, count_femelements):
FreeCAD.Console.PrintError(
- 'Error in get_femelement_sets_from_group_data -- > '
- 'femelements_count_ok() failed!\n'
+ "Error in get_femelement_sets_from_group_data -- > "
+ "femelements_count_ok() failed!\n"
)
return False
else:
@@ -724,20 +724,20 @@ def get_elset_short_name(
obj,
i
):
- if hasattr(obj, "Proxy") and obj.Proxy.Type == 'Fem::Material':
- return 'M' + str(i)
- elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'Fem::FemElementGeometry1D':
- return 'B' + str(i)
- elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'Fem::FemElementRotation1D':
- return 'R' + str(i)
- elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'Fem::FemElementFluid1D':
- return 'F' + str(i)
- elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'Fem::FemElementGeometry2D':
- return 'S' + str(i)
+ if hasattr(obj, "Proxy") and obj.Proxy.Type == "Fem::Material":
+ return "M" + str(i)
+ elif hasattr(obj, "Proxy") and obj.Proxy.Type == "Fem::FemElementGeometry1D":
+ return "B" + str(i)
+ elif hasattr(obj, "Proxy") and obj.Proxy.Type == "Fem::FemElementRotation1D":
+ return "R" + str(i)
+ elif hasattr(obj, "Proxy") and obj.Proxy.Type == "Fem::FemElementFluid1D":
+ return "F" + str(i)
+ elif hasattr(obj, "Proxy") and obj.Proxy.Type == "Fem::FemElementGeometry2D":
+ return "S" + str(i)
else:
FreeCAD.Console.PrintError(
- 'Error in creating short elset name '
- 'for obj: {} --> Proxy.Type: {}\n'
+ "Error in creating short elset name "
+ "for obj: {} --> Proxy.Type: {}\n"
.format(obj.Name, obj.Proxy.Type)
)
@@ -751,9 +751,9 @@ def get_force_obj_vertex_nodeload_table(
):
# force_obj_node_load_table:
# [
- # ('refshape_name.elemname', node_load_table),
+ # ("refshape_name.elemname", node_load_table),
# ...,
- # ('refshape_name.elemname', node_load_table)
+ # ("refshape_name.elemname", node_load_table)
# ]
force_obj_node_load_table = []
node_load = frc_obj.Force / len(frc_obj.References)
@@ -762,15 +762,15 @@ def get_force_obj_vertex_nodeload_table(
for elem in elem_tup:
ref_node = o.Shape.getElement(elem)
FreeCAD.Console.PrintMessage(
- ' '
- 'ReferenceShape ... Type: {0}, '
- 'Object name: {1}, '
- 'Object label: {2}, '
- 'Element name: {3}\n'
+ " "
+ "ReferenceShape ... Type: {0}, "
+ "Object name: {1}, "
+ "Object label: {2}, "
+ "Element name: {3}\n"
.format(ref_node.ShapeType, o.Name, o.Label, elem)
)
node = femmesh.getNodesByVertex(ref_node)
- elem_info_string = 'node load on shape: ' + o.Name + ':' + elem
+ elem_info_string = "node load on shape: " + o.Name + ":" + elem
force_obj_node_load_table.append(
(elem_info_string, {node[0]: node_load / node_count})
)
@@ -789,9 +789,9 @@ def get_force_obj_edge_nodeload_table(
):
# force_obj_node_load_table:
# [
- # ('refshape_name.elemname', node_load_table),
+ # ("refshape_name.elemname", node_load_table),
# ...,
- # ('refshape_name.elemname', node_load_table)
+ # ("refshape_name.elemname", node_load_table)
# ]
force_obj_node_load_table = []
sum_ref_edge_length = 0
@@ -801,11 +801,11 @@ def get_force_obj_edge_nodeload_table(
for elem in elem_tup:
ref_edge = o.Shape.getElement(elem)
FreeCAD.Console.PrintMessage(
- ' '
- 'ReferenceShape ... Type: {0}, '
- 'Object name: {1}, '
- 'Object label: {2}, '
- 'Element name: {3}\n'
+ " "
+ "ReferenceShape ... Type: {0}, "
+ "Object name: {1}, "
+ "Object label: {2}, "
+ "Element name: {3}\n"
.format(ref_edge.ShapeType, o.Name, o.Label, elem)
)
sum_ref_edge_length += ref_edge.Length
@@ -840,14 +840,14 @@ def get_force_obj_edge_nodeload_table(
ratio_refedge_lengths = sum_node_lengths / ref_edge.Length
if ratio_refedge_lengths < 0.99 or ratio_refedge_lengths > 1.01:
FreeCAD.Console.PrintError(
- 'Error on: ' + frc_obj.Name + ' --> ' + o.Name + '.' + elem + '\n'
+ "Error on: " + frc_obj.Name + " --> " + o.Name + "." + elem + "\n"
)
- FreeCAD.Console.PrintMessage(' sum_node_lengths: {}\n'.format(sum_node_lengths))
- FreeCAD.Console.PrintMessage(' refedge_length: {}\n'.format(ref_edge.Length))
+ FreeCAD.Console.PrintMessage(" sum_node_lengths: {}\n".format(sum_node_lengths))
+ FreeCAD.Console.PrintMessage(" refedge_length: {}\n".format(ref_edge.Length))
bad_refedge = ref_edge
sum_ref_edge_node_length += sum_node_lengths
- elem_info_string = 'node loads on shape: ' + o.Name + ':' + elem
+ elem_info_string = "node loads on shape: " + o.Name + ":" + elem
force_obj_node_load_table.append((elem_info_string, node_load_table))
for ref_shape in force_obj_node_load_table:
@@ -857,74 +857,74 @@ def get_force_obj_edge_nodeload_table(
ratio = sum_node_load / frc_obj.Force
if ratio < 0.99 or ratio > 1.01:
FreeCAD.Console.PrintMessage(
- 'Deviation sum_node_load to frc_obj.Force is more than 1% : {}\n'
+ "Deviation sum_node_load to frc_obj.Force is more than 1% : {}\n"
.format(ratio)
)
FreeCAD.Console.PrintMessage(
- ' sum_ref_edge_node_length: {}\n'
+ " sum_ref_edge_node_length: {}\n"
.format(sum_ref_edge_node_length)
)
FreeCAD.Console.PrintMessage(
- ' sum_ref_edge_length: {}\n'
+ " sum_ref_edge_length: {}\n"
.format(sum_ref_edge_length)
)
FreeCAD.Console.PrintMessage(
- ' sum_node_load: {}\n'
+ " sum_node_load: {}\n"
.format(sum_node_load)
)
FreeCAD.Console.PrintMessage(
- ' frc_obj.Force: {}\n'
+ " frc_obj.Force: {}\n"
.format(frc_obj.Force)
)
FreeCAD.Console.PrintMessage(
- ' the reason could be simply a circle length --> '
- 'see method get_ref_edge_node_lengths\n'
+ " the reason could be simply a circle length --> "
+ "see method get_ref_edge_node_lengths\n"
)
FreeCAD.Console.PrintMessage(
- ' the reason could also be a problem in '
- 'retrieving the ref_edge_node_length\n'
+ " the reason could also be a problem in "
+ "retrieving the ref_edge_node_length\n"
)
# try debugging of the last bad refedge
- FreeCAD.Console.PrintMessage('DEBUGGING\n')
- FreeCAD.Console.PrintMessage('\n'.format(bad_refedge))
+ FreeCAD.Console.PrintMessage("DEBUGGING\n")
+ FreeCAD.Console.PrintMessage("\n".format(bad_refedge))
- FreeCAD.Console.PrintMessage('bad_refedge_nodes\n')
+ FreeCAD.Console.PrintMessage("bad_refedge_nodes\n")
bad_refedge_nodes = femmesh.getNodesByEdge(bad_refedge)
- FreeCAD.Console.PrintMessage('{}\n'.format(len(bad_refedge_nodes)))
- FreeCAD.Console.PrintMessage('{}\n'.format(bad_refedge_nodes))
+ FreeCAD.Console.PrintMessage("{}\n".format(len(bad_refedge_nodes)))
+ FreeCAD.Console.PrintMessage("{}\n".format(bad_refedge_nodes))
# import FreeCADGui
# FreeCADGui.ActiveDocument.Compound_Mesh.HighlightedNodes = bad_refedge_nodes
- FreeCAD.Console.PrintMessage('bad_edge_table\n')
+ FreeCAD.Console.PrintMessage("bad_edge_table\n")
# bad_edge_table:
# { meshedgeID : ( nodeID, ... , nodeID ) }
bad_edge_table = get_ref_edgenodes_table(femmesh, femelement_table, bad_refedge)
- FreeCAD.Console.PrintMessage('{}\n'.format(len(bad_edge_table)))
+ FreeCAD.Console.PrintMessage("{}\n".format(len(bad_edge_table)))
bad_edge_table_nodes = []
for elem in bad_edge_table:
- FreeCAD.Console.PrintMessage(elem, ' --> \n'.format(bad_edge_table[elem]))
+ FreeCAD.Console.PrintMessage(elem, " --> \n".format(bad_edge_table[elem]))
for node in bad_edge_table[elem]:
if node not in bad_edge_table_nodes:
bad_edge_table_nodes.append(node)
- FreeCAD.Console.PrintMessage('sorted(bad_edge_table_nodes)\n')
+ FreeCAD.Console.PrintMessage("sorted(bad_edge_table_nodes)\n")
# should be == bad_refedge_nodes
- FreeCAD.Console.PrintMessage('{}\n'.format(sorted(bad_edge_table_nodes)))
+ FreeCAD.Console.PrintMessage("{}\n".format(sorted(bad_edge_table_nodes)))
# import FreeCADGui
# FreeCADGui.ActiveDocument.Compound_Mesh.HighlightedNodes = bad_edge_table_nodes
# bad_node_length_table:
# [ (nodeID, length), ... , (nodeID, length) ]
# some nodes will have more than one entry
- FreeCAD.Console.PrintMessage('good_edge_table\n')
+ FreeCAD.Console.PrintMessage("good_edge_table\n")
good_edge_table = delete_duplicate_mesh_elements(bad_edge_table)
for elem in good_edge_table:
- FreeCAD.Console.PrintMessage('{} --> {}\n'.format(elem, bad_edge_table[elem]))
+ FreeCAD.Console.PrintMessage("{} --> {}\n".format(elem, bad_edge_table[elem]))
- FreeCAD.Console.PrintMessage('bad_node_length_table\n')
+ FreeCAD.Console.PrintMessage("bad_node_length_table\n")
bad_node_length_table = get_ref_edgenodes_lengths(femnodes_mesh, bad_edge_table)
for n, l in bad_node_length_table:
- FreeCAD.Console.PrintMessage('{} --> {}\n'.format(n, l))
+ FreeCAD.Console.PrintMessage("{} --> {}\n".format(n, l))
return force_obj_node_load_table
@@ -1012,7 +1012,7 @@ def get_ref_edgenodes_lengths(
return []
node_length_table = []
mesh_edge_length = 0
- # FreeCAD.Console.PrintMessage('{}\n'.format(len(edge_table)))
+ # FreeCAD.Console.PrintMessage("{}\n".format(len(edge_table)))
for me in edge_table:
femmesh_edgetype = len(edge_table[me])
if femmesh_edgetype == 2: # 2 node femmesh edge
@@ -1023,7 +1023,7 @@ def get_ref_edgenodes_lengths(
P2 = femnodes_mesh[edge_table[me][1]]
edge_vec = P2 - P1
mesh_edge_length = edge_vec.Length
- # FreeCAD.Console.PrintMessage('{}\n'.format(mesh_edge_length))
+ # FreeCAD.Console.PrintMessage("{}\n".format(mesh_edge_length))
end_node_length = mesh_edge_length / 2.0
node_length_table.append((edge_table[me][0], end_node_length))
node_length_table.append((edge_table[me][1], end_node_length))
@@ -1039,7 +1039,7 @@ def get_ref_edgenodes_lengths(
edge_vec1 = P3 - P1
edge_vec2 = P2 - P3
mesh_edge_length = edge_vec1.Length + edge_vec2.Length
- # FreeCAD.Console.PrintMessage('{} --> {}\n'.format(me, mesh_edge_length))
+ # FreeCAD.Console.PrintMessage("{} --> {}\n".format(me, mesh_edge_length))
end_node_length = mesh_edge_length / 6.0
middle_node_length = mesh_edge_length * 2.0 / 3.0
node_length_table.append((edge_table[me][0], end_node_length))
@@ -1061,9 +1061,9 @@ def get_force_obj_face_nodeload_table(
):
# force_obj_node_load_table:
# [
- # ('refshape_name.elemname',node_load_table),
+ # ("refshape_name.elemname",node_load_table),
# ...,
- # ('refshape_name.elemname',node_load_table)
+ # ("refshape_name.elemname",node_load_table)
# ]
force_obj_node_load_table = []
sum_ref_face_area = 0
@@ -1073,11 +1073,11 @@ def get_force_obj_face_nodeload_table(
for elem in elem_tup:
ref_face = o.Shape.getElement(elem)
FreeCAD.Console.PrintMessage(
- ' '
- 'ReferenceShape ... Type: {0}, '
- 'Object name: {1}, '
- 'Object label: {2}, '
- 'Element name: {3}\n'
+ " "
+ "ReferenceShape ... Type: {0}, "
+ "Object name: {1}, "
+ "Object label: {2}, "
+ "Element name: {3}\n"
.format(ref_face.ShapeType, o.Name, o.Label, elem)
)
sum_ref_face_area += ref_face.Area
@@ -1112,13 +1112,13 @@ def get_force_obj_face_nodeload_table(
ratio_refface_areas = sum_node_areas / ref_face.Area
if ratio_refface_areas < 0.99 or ratio_refface_areas > 1.01:
FreeCAD.Console.PrintError(
- 'Error on: ' + frc_obj.Name + ' --> ' + o.Name + '.' + elem + '\n'
+ "Error on: " + frc_obj.Name + " --> " + o.Name + "." + elem + "\n"
)
- FreeCAD.Console.PrintMessage(' sum_node_areas: {}\n'.format(sum_node_areas))
- FreeCAD.Console.PrintMessage(' ref_face_area: {}\n'.format(ref_face.Area))
+ FreeCAD.Console.PrintMessage(" sum_node_areas: {}\n".format(sum_node_areas))
+ FreeCAD.Console.PrintMessage(" ref_face_area: {}\n".format(ref_face.Area))
sum_ref_face_node_area += sum_node_areas
- elem_info_string = 'node loads on shape: ' + o.Name + ':' + elem
+ elem_info_string = "node loads on shape: " + o.Name + ":" + elem
force_obj_node_load_table.append((elem_info_string, node_load_table))
for ref_shape in force_obj_node_load_table:
@@ -1128,32 +1128,32 @@ def get_force_obj_face_nodeload_table(
ratio = sum_node_load / frc_obj.Force
if ratio < 0.99 or ratio > 1.01:
FreeCAD.Console.PrintMessage(
- 'Deviation sum_node_load to frc_obj.Force is more than 1% : {}\n'
+ "Deviation sum_node_load to frc_obj.Force is more than 1% : {}\n"
.format(ratio)
)
FreeCAD.Console.PrintMessage(
- ' sum_ref_face_node_area: {}\n'
+ " sum_ref_face_node_area: {}\n"
.format(sum_ref_face_node_area)
)
FreeCAD.Console.PrintMessage(
- ' sum_ref_face_area: {}\n'
+ " sum_ref_face_area: {}\n"
.format(sum_ref_face_area)
)
FreeCAD.Console.PrintMessage(
- ' sum_node_load: {}\n'
+ " sum_node_load: {}\n"
.format(sum_node_load)
)
FreeCAD.Console.PrintMessage(
- ' frc_obj.Force: {}\n'
+ " frc_obj.Force: {}\n"
.format(frc_obj.Force)
)
FreeCAD.Console.PrintMessage(
- ' the reason could be simply a circle area --> '
- 'see method get_ref_face_node_areas\n'
+ " the reason could be simply a circle area --> "
+ "see method get_ref_face_node_areas\n"
)
FreeCAD.Console.PrintMessage(
- ' the reason could also be a problem in '
- 'retrieving the ref_face_node_area\n'
+ " the reason could also be a problem in "
+ "retrieving the ref_face_node_area\n"
)
return force_obj_node_load_table
@@ -1169,9 +1169,9 @@ def get_ref_facenodes_table(
if is_solid_femmesh(femmesh):
if has_no_face_data(femmesh):
FreeCAD.Console.PrintMessage(
- ' No face data in finite volume element mesh. '
- 'FreeCAD uses getccxVolumesByFace() '
- 'to retrieve the volume elements of the ref_face.\n'
+ " No face data in finite volume element mesh. "
+ "FreeCAD uses getccxVolumesByFace() "
+ "to retrieve the volume elements of the ref_face.\n"
)
# there is no face data
# if we retrieve the nodes ourself we will have a problem:
@@ -1186,8 +1186,8 @@ def get_ref_facenodes_table(
ref_face_volume_elements = femmesh.getccxVolumesByFace(ref_face)
if ref_face_volume_elements: # mesh with tetras
FreeCAD.Console.PrintLog(
- ' Use of getccxVolumesByFace() has '
- 'returned volume elements of the ref_face.\n'
+ " Use of getccxVolumesByFace() has "
+ "returned volume elements of the ref_face.\n"
)
for ve in ref_face_volume_elements:
veID = ve[0]
@@ -1199,9 +1199,9 @@ def get_ref_facenodes_table(
face_table[veID] = ve_ref_face_nodes
else: # mesh with hexa or penta
FreeCAD.Console.PrintLog(
- ' The use of getccxVolumesByFace() has NOT returned '
- 'volume elements of the ref_face. '
- 'FreeCAD tries to use get_femvolumeelements_by_femfacenodes().\n'
+ " The use of getccxVolumesByFace() has NOT returned "
+ "volume elements of the ref_face. "
+ "FreeCAD tries to use get_femvolumeelements_by_femfacenodes().\n"
)
# list of integer [mv]
ref_face_volume_elements = get_femvolumeelements_by_femfacenodes(
@@ -1226,7 +1226,7 @@ def get_ref_facenodes_table(
ref_face_elements = get_femelements_by_femnodes_std(femelement_table, ref_face_nodes)
for mf in ref_face_elements:
face_table[mf] = femelement_table[mf]
- # FreeCAD.Console.PrintMessage('{}\n'.format(face_table))
+ # FreeCAD.Console.PrintMessage("{}\n".format(face_table))
return face_table
@@ -1397,13 +1397,13 @@ def build_mesh_faces_of_volume_elements(
face_nodenumber_table[veID] = []
for n in face_table[veID]:
index = femelement_table[veID].index(n)
- # FreeCAD.Console.PrintMessage('{}\n'.format(index))
+ # FreeCAD.Console.PrintMessage("{}\n".format(index))
# local node number = index + 1
face_nodenumber_table[veID].append(index + 1)
- FreeCAD.Console.PrintLog('VolElement: {}\n'.format(veID))
- FreeCAD.Console.PrintLog(' --> {}\n'.format(femelement_table[veID]))
- FreeCAD.Console.PrintLog(' --> {}\n'.format(face_table[veID]))
- FreeCAD.Console.PrintLog(' --> {}\n'.format(face_nodenumber_table[veID]))
+ FreeCAD.Console.PrintLog("VolElement: {}\n".format(veID))
+ FreeCAD.Console.PrintLog(" --> {}\n".format(femelement_table[veID]))
+ FreeCAD.Console.PrintLog(" --> {}\n".format(face_table[veID]))
+ FreeCAD.Console.PrintLog(" --> {}\n".format(face_nodenumber_table[veID]))
for veID in face_nodenumber_table:
vol_node_ct = len(femelement_table[veID])
face_node_indexs = sorted(face_nodenumber_table[veID])
@@ -1539,7 +1539,7 @@ def build_mesh_faces_of_volume_elements(
# index = node number - 1i -= 1
face_nodes.append(femelement_table[veID][i])
face_table[veID] = face_nodes # reset the entry in face_table
- # FreeCAD.Console.PrintMessage(' --> {}\n'.format(face_table[veID]))
+ # FreeCAD.Console.PrintMessage(" --> {}\n".format(face_table[veID]))
return face_table
@@ -1551,7 +1551,7 @@ def get_ref_shape_node_sum_geom_table(
# sum of length or area for each node of the ref_shape
node_sum_geom_table = {}
for n, A in node_geom_table:
- # FreeCAD.Console.PrintMessage('{} --> {}\n'.format(n, A))
+ # FreeCAD.Console.PrintMessage("{} --> {}\n".format(n, A))
if n in node_sum_geom_table:
node_sum_geom_table[n] = node_sum_geom_table[n] + A
else:
@@ -1571,7 +1571,7 @@ def get_pressure_obj_faces(
# get the nodes
# sorted and duplicates removed
prs_face_node_set = get_femnodes_by_femobj_with_references(femmesh, femobj)
- # FreeCAD.Console.PrintMessage('prs_face_node_set: {}\n'.format(prs_face_node_set))
+ # FreeCAD.Console.PrintMessage("prs_face_node_set: {}\n".format(prs_face_node_set))
# fill the bit_pattern_dict and search for the faces
bit_pattern_dict = get_bit_pattern_dict(
femelement_table,
@@ -1584,8 +1584,8 @@ def get_pressure_obj_faces(
# normally we should call get_femelements_by_references and
# the group check should be integrated there
if femmesh.GroupCount:
- meshfaces = get_femmesh_groupdata_sets_by_name(femmesh, femobj, 'Face')
- # FreeCAD.Console.PrintMessage('{}\n'.format(meshfaces))
+ meshfaces = get_femmesh_groupdata_sets_by_name(femmesh, femobj, "Face")
+ # FreeCAD.Console.PrintMessage("{}\n".format(meshfaces))
if not meshfaces:
FreeCAD.Console.PrintError(
"Error: Something went wrong in getting the group element faces.\n"
@@ -1615,12 +1615,12 @@ def get_pressure_obj_faces_depreciated(
femobj
):
pressure_faces = []
- for o, elem_tup in femobj['Object'].References:
+ for o, elem_tup in femobj["Object"].References:
for elem in elem_tup:
ref_shape = o.Shape.getElement(elem)
- elem_info_string = 'face load on shape: ' + o.Name + ':' + elem
- FreeCAD.Console.PrintMessage('{}\n'.format(elem_info_string))
- if ref_shape.ShapeType == 'Face':
+ elem_info_string = "face load on shape: " + o.Name + ":" + elem
+ FreeCAD.Console.PrintMessage("{}\n".format(elem_info_string))
+ if ref_shape.ShapeType == "Face":
pressure_faces.append(
(elem_info_string, femmesh.getccxVolumesByFace(ref_shape))
)
@@ -1633,17 +1633,17 @@ def get_mesh_group_elements(
mesh_group_obj,
aPart
):
- '''the Reference shapes of the mesh_group_object are searched in the Shape of aPart.
+ """the Reference shapes of the mesh_group_object are searched in the Shape of aPart.
If found in shape they are added to a dict
- {MeshGroupIdentifier : ['ShapeType of the Elements'], [ElementID, ElementID, ...], ...}
- '''
+ {MeshGroupIdentifier : ["ShapeType of the Elements"], [ElementID, ElementID, ...], ...}
+ """
group_elements = {} # { name : [element, element, ... , element]}
if mesh_group_obj.References:
grp_ele = get_reference_group_elements(mesh_group_obj, aPart)
group_elements[grp_ele[0]] = grp_ele[1]
else:
FreeCAD.Console.PrintError(
- ' Empty reference in mesh group object: {} {}\n'
+ " Empty reference in mesh group object: {} {}\n"
.format(mesh_group_obj.Name, mesh_group_obj.Label)
)
return group_elements
@@ -1654,10 +1654,10 @@ def get_analysis_group_elements(
aAnalysis,
aPart
):
- ''' all Reference shapes of all Analysis member are searched in the Shape of aPart.
+ """ all Reference shapes of all Analysis member are searched in the Shape of aPart.
If found in shape they are added to a dict
- {ConstraintName : ['ShapeType of the Elements'], [ElementID, ElementID, ...], ...}
- '''
+ {ConstraintName : ["ShapeType of the Elements"], [ElementID, ElementID, ...], ...}
+ """
group_elements = {} # { name : [element, element, ... , element]}
empty_references = []
for m in aAnalysis.Group:
@@ -1668,7 +1668,7 @@ def get_analysis_group_elements(
grp_ele = get_reference_group_elements(m, aPart)
group_elements[grp_ele[0]] = grp_ele[1]
else:
- FreeCAD.Console.PrintMessage(' Empty reference: ' + m.Name + '\n')
+ FreeCAD.Console.PrintMessage(" Empty reference: " + m.Name + "\n")
empty_references.append(m)
if empty_references:
if len(empty_references) == 1:
@@ -1679,29 +1679,29 @@ def get_analysis_group_elements(
)
else:
FreeCAD.Console.PrintError(
- 'Problem: more than one object with empty references.\n'
+ "Problem: more than one object with empty references.\n"
)
FreeCAD.Console.PrintMessage(
- 'We are going to try to get the empty material references anyway.\n'
+ "We are going to try to get the empty material references anyway.\n"
)
# FemElementGeometry2D, ElementGeometry1D and
# FemElementFluid1D could have empty references,
# but on solid meshes only materials should have empty references
for er in empty_references:
- FreeCAD.Console.PrintMessage(er.Name + '\n')
+ FreeCAD.Console.PrintMessage(er.Name + "\n")
group_elements = get_anlysis_empty_references_group_elements(
group_elements,
aAnalysis,
aPart.Shape
)
# check if all groups have at least one element,
- # it doesn't mean ALL reference shapes for a group have been found
+ # it doesn"t mean ALL reference shapes for a group have been found
for g in group_elements:
- # FreeCAD.Console.PrintMessage('{}\n'.format(group_elements[g]))
+ # FreeCAD.Console.PrintMessage("{}\n".format(group_elements[g]))
if len(group_elements[g]) == 0:
FreeCAD.Console.PrintError(
- 'Error: The shapes for the mesh group for the reference '
- 'shapes of analysis member: {} could not be found!\n'
+ "Error: The shapes for the mesh group for the reference "
+ "shapes of analysis member: {} could not be found!\n"
.format(g)
)
return group_elements
@@ -1712,14 +1712,14 @@ def get_reference_group_elements(
obj,
aPart
):
- ''' obj is an FEM object which has reference shapes like the group object
+ """ obj is an FEM object which has reference shapes like the group object
the material, most of the constraints
aPart is geometry feature normally CompSolid
the method searches all reference shapes of obj inside aPart even if
the reference shapes are a totally different geometry feature.
- a tuple is returned ('Name or Label of the FEMobject', ['Element1', 'Element2', ...])
+ a tuple is returned ("Name or Label of the FEMobject", ["Element1", "Element2", ...])
The names in the list are the Elements of the geometry aPart
- whereas 'Solid1' == aPart.Shape.Solids[0]
+ whereas "Solid1" == aPart.Shape.Solids[0]
!!! It is strongly recommended to use as reference shapes the Solids of a CompSolid
and not the Solids the CompSolid is made of !!!
see https://forum.freecadweb.org/viewtopic.php?f=18&t=12212&p=175777#p175777
@@ -1727,7 +1727,7 @@ def get_reference_group_elements(
Occt might change the Solids a CompSolid is made of during
creation of the CompSolid by adding Edges and vertices
Thus the Elements do not have the same geometry anymore
- '''
+ """
aShape = aPart.Shape
if hasattr(obj, "UseLabel") and obj.UseLabel:
# TODO: check the character of the Label
@@ -1740,8 +1740,8 @@ def get_reference_group_elements(
for r in obj.References:
parent = r[0]
childs = r[1]
- # FreeCAD.Console.PrintMessage('{}\n'.format(parent))
- # FreeCAD.Console.PrintMessage('{}\n'.format(childs))
+ # FreeCAD.Console.PrintMessage("{}\n".format(parent))
+ # FreeCAD.Console.PrintMessage("{}\n".format(childs))
for child in childs:
# the method getElement(element) does not return Solid elements
ref_shape = get_element(parent, child)
@@ -1749,42 +1749,42 @@ def get_reference_group_elements(
stype = ref_shape.ShapeType
elif stype != ref_shape.ShapeType:
FreeCAD.Console.PrintError(
- 'Error, two refshapes in References with different ShapeTypes.\n'
+ "Error, two refshapes in References with different ShapeTypes.\n"
)
- FreeCAD.Console.PrintLog('\n'.format(ref_shape))
+ FreeCAD.Console.PrintLog("\n".format(ref_shape))
found_element = find_element_in_shape(aShape, ref_shape)
if found_element is not None:
elements.append(found_element)
else:
FreeCAD.Console.PrintError(
- 'Problem: For the geometry of the '
- 'following shape was no Shape found: {}\n'
+ "Problem: For the geometry of the "
+ "following shape was no Shape found: {}\n"
.format(ref_shape)
)
- FreeCAD.Console.PrintMessage(' ' + obj.Name + '\n')
- FreeCAD.Console.PrintMessage(' ' + str(obj.References) + '\n')
- FreeCAD.Console.PrintMessage(' ' + r[0].Name + '\n')
+ FreeCAD.Console.PrintMessage(" " + obj.Name + "\n")
+ FreeCAD.Console.PrintMessage(" " + str(obj.References) + "\n")
+ FreeCAD.Console.PrintMessage(" " + r[0].Name + "\n")
if parent.Name != aPart.Name:
FreeCAD.Console.PrintError(
- 'The reference Shape is not a child '
- 'nor it is the shape the mesh is made of. : {}\n'
+ "The reference Shape is not a child "
+ "nor it is the shape the mesh is made of. : {}\n"
.format(ref_shape)
)
FreeCAD.Console.PrintMessage(
- '{}--> Name of the Feature we where searching in.\n'
+ "{}--> Name of the Feature we where searching in.\n"
.format(aPart.Name)
)
FreeCAD.Console.PrintMessage(
- '{} --> Name of the parent Feature of reference Shape '
- '(Use the same as in the line before and you '
- 'will have less trouble :-) !!!!!!).\n'
+ "{} --> Name of the parent Feature of reference Shape "
+ "(Use the same as in the line before and you "
+ "will have less trouble :-) !!!!!!).\n"
.format(parent.Name)
)
# import Part
# Part.show(aShape)
# Part.show(ref_shape)
else:
- FreeCAD.Console.PrintError('This should not happen, please debug!\n')
+ FreeCAD.Console.PrintError("This should not happen, please debug!\n")
# in this case we would not have needed to use the
# is_same_geometry() inside find_element_in_shape()
# AFAIK we could have used the Part methods isPartner() or even isSame()
@@ -1798,16 +1798,16 @@ def get_anlysis_empty_references_group_elements(
aAnalysis,
aShape
):
- '''get the elementIDs if the Reference shape is empty
+ """get the elementIDs if the Reference shape is empty
see get_analysis_group_elements() for more information
on solid meshes only material objects could have an
empty reference without there being something wrong!
face meshes could have empty ShellThickness and
edge meshes could have empty BeamSection/FluidSection
- '''
- # FreeCAD.Console.PrintMessage('{}\n'.format(group_elements))
+ """
+ # FreeCAD.Console.PrintMessage("{}\n".format(group_elements))
material_ref_shapes = []
- material_shape_type = ''
+ material_shape_type = ""
missed_material_refshapes = []
empty_reference_material = None
for m in aAnalysis.Group:
@@ -1817,52 +1817,52 @@ def get_anlysis_empty_references_group_elements(
empty_reference_material = m.Name
else:
FreeCAD.Console.PrintError(
- 'Problem in get_anlysis_empty_references_group_elements, '
- 'we seem to have two or more materials with empty references\n'
+ "Problem in get_anlysis_empty_references_group_elements, "
+ "we seem to have two or more materials with empty references\n"
)
return {}
elif hasattr(m, "References") and m.References:
# ShapeType of the group elements, strip the number of the first group element
# http://stackoverflow.com/questions/12851791/removing-numbers-from-string
- group_shape_type = ''.join(i for i in group_elements[m.Name][0] if not i.isdigit())
+ group_shape_type = "".join(i for i in group_elements[m.Name][0] if not i.isdigit())
if not material_shape_type:
material_shape_type = group_shape_type
elif material_shape_type != group_shape_type:
FreeCAD.Console.PrintError(
- 'Problem, material shape type does not match '
- 'get_anlysis_empty_references_group_elements\n'
+ "Problem, material shape type does not match "
+ "get_anlysis_empty_references_group_elements\n"
)
for ele in group_elements[m.Name]:
material_ref_shapes.append(ele)
- if material_shape_type == 'Solid':
- # FreeCAD.Console.PrintMessage('{}\n'.format(len(aShape.Solids)))
+ if material_shape_type == "Solid":
+ # FreeCAD.Console.PrintMessage("{}\n".format(len(aShape.Solids)))
for i in range(len(aShape.Solids)):
- ele = 'Solid' + str(i + 1)
+ ele = "Solid" + str(i + 1)
if ele not in material_ref_shapes:
missed_material_refshapes.append(ele)
- elif material_shape_type == 'Face':
- # FreeCAD.Console.PrintMessage('{}\n'.format(len(aShape.Faces)))
+ elif material_shape_type == "Face":
+ # FreeCAD.Console.PrintMessage("{}\n".format(len(aShape.Faces)))
for i in range(len(aShape.Faces)):
- ele = 'Face' + str(i + 1)
+ ele = "Face" + str(i + 1)
if ele not in material_ref_shapes:
missed_material_refshapes.append(ele)
- elif material_shape_type == 'Edge':
- # FreeCAD.Console.PrintMessage('{}\n'.format(len(aShape.Edges)))
+ elif material_shape_type == "Edge":
+ # FreeCAD.Console.PrintMessage("{}\n".format(len(aShape.Edges)))
for i in range(len(aShape.Edges)):
- ele = 'Edge' + str(i + 1)
+ ele = "Edge" + str(i + 1)
if ele not in material_ref_shapes:
missed_material_refshapes.append(ele)
else:
FreeCAD.Console.PrintMessage(
- ' One material with no reference shapes. No need to make a group for materials.\n'
+ " One material with no reference shapes. No need to make a group for materials.\n"
)
# make no changes group_elements
return group_elements
- # FreeCAD.Console.PrintMessage('{}\n'.format(sorted(material_ref_shapes)))
- # FreeCAD.Console.PrintMessage('{}\n'.format(sorted(missed_material_refshapes)))
+ # FreeCAD.Console.PrintMessage("{}\n".format(sorted(material_ref_shapes)))
+ # FreeCAD.Console.PrintMessage("{}\n".format(sorted(missed_material_refshapes)))
# FreeCAD.Console.PrintMessage(group_elements)
group_elements[empty_reference_material] = sorted(missed_material_refshapes)
- # FreeCAD.Console.PrintMessage('{}\n'.format(group_elements))
+ # FreeCAD.Console.PrintMessage("{}\n".format(group_elements))
return group_elements
@@ -1873,52 +1873,52 @@ def find_element_in_shape(
):
# import Part
ele_st = anElement.ShapeType
- if ele_st == 'Solid' or ele_st == 'CompSolid':
+ if ele_st == "Solid" or ele_st == "CompSolid":
for index, solid in enumerate(aShape.Solids):
- # FreeCAD.Console.PrintMessage('{}\n'.format(is_same_geometry(solid, anElement)))
+ # FreeCAD.Console.PrintMessage("{}\n".format(is_same_geometry(solid, anElement)))
if is_same_geometry(solid, anElement):
- # FreeCAD.Console.PrintMessage('{}\n'.format(index))
+ # FreeCAD.Console.PrintMessage("{}\n".format(index))
# Part.show(aShape.Solids[index])
ele = ele_st + str(index + 1)
return ele
FreeCAD.Console.PrintError(
- 'Solid ' + str(anElement) + ' not found in: ' + str(aShape) + '\n'
+ "Solid " + str(anElement) + " not found in: " + str(aShape) + "\n"
)
- if ele_st == 'Solid' and aShape.ShapeType == 'Solid':
+ if ele_st == "Solid" and aShape.ShapeType == "Solid":
message_part = (
- 'We have been searching for a Solid in a Solid and we have not found it. '
- 'In most cases this should be searching for a Solid inside a CompSolid. '
- 'Check the ShapeType of your Part to mesh.'
+ "We have been searching for a Solid in a Solid and we have not found it. "
+ "In most cases this should be searching for a Solid inside a CompSolid. "
+ "Check the ShapeType of your Part to mesh."
)
- FreeCAD.Console.PrintMessage(message_part + '\n')
+ FreeCAD.Console.PrintMessage(message_part + "\n")
# Part.show(anElement)
# Part.show(aShape)
- elif ele_st == 'Face' or ele_st == 'Shell':
+ elif ele_st == "Face" or ele_st == "Shell":
for index, face in enumerate(aShape.Faces):
- # FreeCAD.Console.PrintMessage('{}\n'.format(is_same_geometry(face, anElement)))
+ # FreeCAD.Console.PrintMessage("{}\n".format(is_same_geometry(face, anElement)))
if is_same_geometry(face, anElement):
- # FreeCAD.Console.PrintMessage('{}\n'.format(index))
+ # FreeCAD.Console.PrintMessage("{}\n".format(index))
# Part.show(aShape.Faces[index])
ele = ele_st + str(index + 1)
return ele
- elif ele_st == 'Edge' or ele_st == 'Wire':
+ elif ele_st == "Edge" or ele_st == "Wire":
for index, edge in enumerate(aShape.Edges):
- # FreeCAD.Console.PrintMessage('{}\n'.format(is_same_geometry(edge, anElement)))
+ # FreeCAD.Console.PrintMessage("{}\n".format(is_same_geometry(edge, anElement)))
if is_same_geometry(edge, anElement):
- # FreeCAD.Console.PrintMessage(index, '\n')
+ # FreeCAD.Console.PrintMessage(index, "\n")
# Part.show(aShape.Edges[index])
ele = ele_st + str(index + 1)
return ele
- elif ele_st == 'Vertex':
+ elif ele_st == "Vertex":
for index, vertex in enumerate(aShape.Vertexes):
- # FreeCAD.Console.PrintMessage('{}\n'.format(is_same_geometry(vertex, anElement)))
+ # FreeCAD.Console.PrintMessage("{}\n".format(is_same_geometry(vertex, anElement)))
if is_same_geometry(vertex, anElement):
- # FreeCAD.Console.PrintMessage('{}\n'.format(index))
+ # FreeCAD.Console.PrintMessage("{}\n".format(index))
# Part.show(aShape.Vertexes[index])
ele = ele_st + str(index + 1)
return ele
- elif ele_st == 'Compound':
- FreeCAD.Console.PrintError('Compound is not supported.\n')
+ elif ele_st == "Compound":
+ FreeCAD.Console.PrintError("Compound is not supported.\n")
# ************************************************************************************************
@@ -1930,44 +1930,44 @@ def get_vertexes_by_element(
# import Part
ele_vertexes = []
ele_st = anElement.ShapeType
- if ele_st == 'Solid' or ele_st == 'CompSolid':
+ if ele_st == "Solid" or ele_st == "CompSolid":
for index, solid in enumerate(aShape.Solids):
if is_same_geometry(solid, anElement):
for vele in aShape.Solids[index].Vertexes:
for i, v in enumerate(aShape.Vertexes):
if vele.isSame(v): # use isSame, because orientation could be different
ele_vertexes.append(i)
- # FreeCAD.Console.PrintMessage(' ' + str(sorted(ele_vertexes)), '\n')
+ # FreeCAD.Console.PrintMessage(" " + str(sorted(ele_vertexes)), "\n")
return ele_vertexes
FreeCAD.Console.PrintError(
- 'Error, Solid ' + str(anElement) + ' not found in: ' + str(aShape) + '\n'
+ "Error, Solid " + str(anElement) + " not found in: " + str(aShape) + "\n"
)
- elif ele_st == 'Face' or ele_st == 'Shell':
+ elif ele_st == "Face" or ele_st == "Shell":
for index, face in enumerate(aShape.Faces):
if is_same_geometry(face, anElement):
for vele in aShape.Faces[index].Vertexes:
for i, v in enumerate(aShape.Vertexes):
if vele.isSame(v): # use isSame, because orientation could be different
ele_vertexes.append(i)
- # FreeCAD.Console.PrintMessage(' ' + str(sorted(ele_vertexes)) + '\n')
+ # FreeCAD.Console.PrintMessage(" " + str(sorted(ele_vertexes)) + "\n")
return ele_vertexes
- elif ele_st == 'Edge' or ele_st == 'Wire':
+ elif ele_st == "Edge" or ele_st == "Wire":
for index, edge in enumerate(aShape.Edges):
if is_same_geometry(edge, anElement):
for vele in aShape.Edges[index].Vertexes:
for i, v in enumerate(aShape.Vertexes):
if vele.isSame(v): # use isSame, because orientation could be different
ele_vertexes.append(i)
- # FreeCAD.Console.PrintMessage(' ' + str(sorted(ele_vertexes)) + '\n')
+ # FreeCAD.Console.PrintMessage(" " + str(sorted(ele_vertexes)) + "\n")
return ele_vertexes
- elif ele_st == 'Vertex':
+ elif ele_st == "Vertex":
for index, vertex in enumerate(aShape.Vertexes):
if is_same_geometry(vertex, anElement):
ele_vertexes.append(index)
- # FreeCAD.Console.PrintMessage(' ' + str(sorted(ele_vertexes)) + '\n')
+ # FreeCAD.Console.PrintMessage(" " + str(sorted(ele_vertexes)) + "\n")
return ele_vertexes
- elif ele_st == 'Compound':
- FreeCAD.Console.PrintError('Compound is not supported.\n')
+ elif ele_st == "Compound":
+ FreeCAD.Console.PrintError("Compound is not supported.\n")
# ************************************************************************************************
@@ -1979,8 +1979,8 @@ def is_same_geometry(
# it is a hack, but I do not know any better !
# check of Volume and Area before starting with the vertices could be added
# BoundBox is possible too, but is BB calculations robust?!
- # FreeCAD.Console.PrintMessage('{}\n'.format(shape1))
- # FreeCAD.Console.PrintMessage('{}\n'.format(shape2))
+ # FreeCAD.Console.PrintMessage("{}\n".format(shape1))
+ # FreeCAD.Console.PrintMessage("{}\n".format(shape2))
same_Vertexes = 0
if len(shape1.Vertexes) == len(shape2.Vertexes) and len(shape1.Vertexes) > 1:
# compare CenterOfMass
@@ -1993,7 +1993,7 @@ def is_same_geometry(
if vs1.X == vs2.X and vs1.Y == vs2.Y and vs1.Z == vs2.Z:
same_Vertexes += 1
continue
- # FreeCAD.Console.PrintMessage('{}\n'.(same_Vertexes))
+ # FreeCAD.Console.PrintMessage("{}\n".(same_Vertexes))
if same_Vertexes == len(shape1.Vertexes):
return True
else:
@@ -2014,11 +2014,11 @@ def get_element(
part,
element
):
- if element.startswith('Solid'):
- index = int(element.lstrip('Solid')) - 1
+ if element.startswith("Solid"):
+ index = int(element.lstrip("Solid")) - 1
if index >= len(part.Shape.Solids):
FreeCAD.Console.PrintError(
- 'Index out of range. This Solid does not exist in the Shape!\n'
+ "Index out of range. This Solid does not exist in the Shape!\n"
)
return None
else:
@@ -2033,18 +2033,18 @@ def femelements_count_ok(
count_femelements
):
FreeCAD.Console.PrintMessage(
- 'Count finite elements as sum of constraints: {}\n'
+ "Count finite elements as sum of constraints: {}\n"
.format(count_femelements)
)
FreeCAD.Console.PrintMessage(
- 'Count finite elements of the finite element mesh: {}\n'
+ "Count finite elements of the finite element mesh: {}\n"
.format(len_femelement_table)
)
if count_femelements == len_femelement_table:
return True
else:
FreeCAD.Console.PrintMessage(
- 'ERROR: femelement_table != count_femelements\n'
+ "ERROR: femelement_table != count_femelements\n"
)
return False
@@ -2144,8 +2144,8 @@ def get_three_non_colinear_nodes(
# Code to obtain three non-colinear nodes on the PlaneRotation support face
# nodes_coords --> [(nodenumber, x, y, z), (nodenumber, x, y, z), ...]
if not nodes_coords:
- FreeCAD.Console.PrintMessage('{}\n'.format(len(nodes_coords)))
- FreeCAD.Console.PrintMessage('Error: No nodes in nodes_coords\n')
+ FreeCAD.Console.PrintMessage("{}\n".format(len(nodes_coords)))
+ FreeCAD.Console.PrintMessage("Error: No nodes in nodes_coords\n")
return []
dum_max = [1, 2, 3, 4, 5, 6, 7, 8, 0]
for i in range(len(nodes_coords)):
@@ -2180,7 +2180,7 @@ def get_three_non_colinear_nodes(
node_dis = [node_3, tot]
node_1 = int(dum_max[0])
node_2 = int(dum_max[4])
- FreeCAD.Console.PrintMessage('{}\n'.format([node_1, node_2, node_3]))
+ FreeCAD.Console.PrintMessage("{}\n".format([node_1, node_2, node_3]))
return [node_1, node_2, node_3]
@@ -2217,9 +2217,9 @@ def get_rectangular_coords(
b_y = B[1] * cos(z_rot) - B[0] * sin(z_rot)
A = [a_x, a_y, a_z]
B = [b_x, b_y, b_z]
- A_coords = str(round(A[0], 4)) + ',' + str(round(A[1], 4)) + ',' + str(round(A[2], 4))
- B_coords = str(round(B[0], 4)) + ',' + str(round(B[1], 4)) + ',' + str(round(B[2], 4))
- coords = A_coords + ',' + B_coords
+ A_coords = str(round(A[0], 4)) + "," + str(round(A[1], 4)) + "," + str(round(A[2], 4))
+ B_coords = str(round(B[0], 4)) + "," + str(round(B[1], 4)) + "," + str(round(B[2], 4))
+ coords = A_coords + "," + B_coords
return coords
@@ -2237,9 +2237,9 @@ def get_cylindrical_coords(
Bz = base[2] - 10 * vec[2]
A = [Ax, Ay, Az]
B = [Bx, By, Bz]
- A_coords = str(A[0]) + ',' + str(A[1]) + ',' + str(A[2])
- B_coords = str(B[0]) + ',' + str(B[1]) + ',' + str(B[2])
- coords = A_coords + ',' + B_coords
+ A_coords = str(A[0]) + "," + str(A[1]) + "," + str(A[2])
+ B_coords = str(B[0]) + "," + str(B[1]) + "," + str(B[2])
+ coords = A_coords + "," + B_coords
return coords
@@ -2248,7 +2248,7 @@ def write_D_network_element_to_inputfile(
fileName
):
# replace B32 elements with D elements for fluid section
- f = open(fileName, 'r+')
+ f = open(fileName, "r+")
lines = f.readlines()
f.seek(0)
for line in lines:
@@ -2267,7 +2267,7 @@ def use_correct_fluidinout_ele_def(
fileName,
fluid_inout_nodes_file
):
- f = open(fileName, 'r')
+ f = open(fileName, "r")
cnt = 0
line = f.readline()
@@ -2280,7 +2280,7 @@ def use_correct_fluidinout_ele_def(
# obtain element line numbers for inlet and outlet
while (len(line) > 1):
- ind = line.find(',')
+ ind = line.find(",")
elem = line[0:ind]
for i in range(len(FluidInletoutlet_ele)):
if (elem == FluidInletoutlet_ele[i][0]):
@@ -2290,30 +2290,30 @@ def use_correct_fluidinout_ele_def(
f.close()
# re-define elements for INLET and OUTLET
- f = open(fileName, 'r+')
+ f = open(fileName, "r+")
lines = f.readlines()
f.seek(0)
cnt = 0
elem_counter = 0
FreeCAD.Console.PrintMessage(
- '1DFlow inout nodes file: {}\n'
+ "1DFlow inout nodes file: {}\n"
.format(fluid_inout_nodes_file)
)
inout_nodes_file = open(fluid_inout_nodes_file, "w")
for line in lines:
- new_line = ''
+ new_line = ""
for i in range(len(FluidInletoutlet_ele)):
if (cnt == FluidInletoutlet_ele[i][2]):
elem_counter = elem_counter + 1
- a = line.split(',')
+ a = line.split(",")
for j in range(len(a)):
if elem_counter == 1:
if j == 1:
- new_line = new_line + ' 0,'
+ new_line = new_line + " 0,"
node1 = int(a[j + 2])
node2 = int(a[j + 1])
node3 = int(a[j])
- inout_nodes_file.write('{},{},{},{}\n'.format(
+ inout_nodes_file.write("{},{},{},{}\n".format(
node1,
node2,
node3,
@@ -2322,22 +2322,22 @@ def use_correct_fluidinout_ele_def(
elif j == 3:
new_line = new_line + a[j]
else:
- new_line = new_line + a[j] + ','
+ new_line = new_line + a[j] + ","
else:
if j == 3:
- new_line = new_line + ' 0\n'
+ new_line = new_line + " 0\n"
node1 = int(a[j - 2])
node2 = int(a[j - 1])
node3 = int(a[j])
- inout_nodes_file.write('{},{},{},{}\n'.format(
+ inout_nodes_file.write("{},{},{},{}\n".format(
node1,
node2,
node3,
FluidInletoutlet_ele[i][1]
))
else:
- new_line = new_line + a[j] + ','
- if new_line == '':
+ new_line = new_line + a[j] + ","
+ if new_line == "":
f.write(line)
else:
f.write(new_line)
@@ -2351,10 +2351,10 @@ def use_correct_fluidinout_ele_def(
def compact_mesh(
old_femmesh
):
- '''
+ """
removes all gaps in node and element ids, start ids with 1
returns a tuple (FemMesh, node_assignment_map, element_assignment_map)
- '''
+ """
node_map = {} # {old_node_id: new_node_id, ...}
elem_map = {} # {old_elem_id: new_elem_id, ...}
old_nodes = old_femmesh.Nodes
diff --git a/src/Mod/Path/App/AppPath.cpp b/src/Mod/Path/App/AppPath.cpp
index 026968c503..2e93cd169b 100644
--- a/src/Mod/Path/App/AppPath.cpp
+++ b/src/Mod/Path/App/AppPath.cpp
@@ -34,6 +34,7 @@
#include "CommandPy.h"
#include "Path.h"
#include "PathPy.h"
+#include "Tool.h"
#include "Tooltable.h"
#include "ToolPy.h"
#include "TooltablePy.h"
diff --git a/src/Mod/Path/App/CMakeLists.txt b/src/Mod/Path/App/CMakeLists.txt
index 2ef5835eac..32fc5b19ae 100644
--- a/src/Mod/Path/App/CMakeLists.txt
+++ b/src/Mod/Path/App/CMakeLists.txt
@@ -43,6 +43,7 @@ SET(Python_SRCS
PathPy.xml
PathPyImp.cpp
ToolPy.xml
+ ToolPyImp.cpp
TooltablePy.xml
TooltablePyImp.cpp
FeaturePathCompoundPy.xml
@@ -65,6 +66,8 @@ SET(Path_SRCS
Command.h
Path.cpp
Path.h
+ Tool.cpp
+ Tool.h
Tooltable.cpp
Tooltable.h
PropertyPath.cpp
diff --git a/src/Mod/Path/App/PropertyTool.h b/src/Mod/Path/App/PropertyTool.h
index 85e1756fe9..706e4fae6b 100644
--- a/src/Mod/Path/App/PropertyTool.h
+++ b/src/Mod/Path/App/PropertyTool.h
@@ -24,7 +24,7 @@
#ifndef PROPERTYTOOL_H
#define PROPERTYTOOL_H
-#include "Tooltable.h"
+#include "Tool.h"
#include
namespace Path
diff --git a/src/Mod/Path/App/Tool.cpp b/src/Mod/Path/App/Tool.cpp
new file mode 100644
index 0000000000..288626911e
--- /dev/null
+++ b/src/Mod/Path/App/Tool.cpp
@@ -0,0 +1,258 @@
+/***************************************************************************
+ * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2014 *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+#include "PreCompiled.h"
+
+#ifndef _PreComp_
+
+#endif
+#include
+#include
+#include
+#include "Tool.h"
+
+using namespace Base;
+using namespace Path;
+
+TYPESYSTEM_SOURCE(Path::Tool , Base::Persistence);
+
+// Constructors & destructors
+
+Tool::Tool(const char* name,
+ ToolType type,
+ ToolMaterial /*material*/,
+ double diameter,
+ double lengthoffset,
+ double flatradius,
+ double cornerradius,
+ double cuttingedgeangle,
+ double cuttingedgeheight)
+:Name(name),Type(type),Material(MATUNDEFINED),Diameter(diameter),LengthOffset(lengthoffset),
+FlatRadius(flatradius),CornerRadius(cornerradius),CuttingEdgeAngle(cuttingedgeangle),
+CuttingEdgeHeight(cuttingedgeheight)
+{
+}
+
+Tool::Tool()
+{
+ Type = UNDEFINED;
+ Material = MATUNDEFINED;
+ Diameter = 0;
+ LengthOffset = 0;
+ FlatRadius = 0;
+ CornerRadius = 0;
+ CuttingEdgeAngle = 180;
+ CuttingEdgeHeight = 0;
+}
+
+Tool::~Tool()
+{
+}
+
+// Reimplemented from base class
+unsigned int Tool::getMemSize (void) const
+{
+ return 0;
+}
+
+void Tool::Save (Writer &writer) const
+{
+ writer.Stream() << writer.ind() << "" << std::endl;
+}
+
+void Tool::Restore(XMLReader &reader)
+{
+ reader.readElement("Tool");
+ Name = reader.getAttribute("name");
+ Diameter = reader.hasAttribute("diameter") ? (double) reader.getAttributeAsFloat("diameter") : 0.0;
+ LengthOffset = reader.hasAttribute("length") ? (double) reader.getAttributeAsFloat("length") : 0.0;
+ FlatRadius = reader.hasAttribute("flat") ? (double) reader.getAttributeAsFloat("flat") : 0.0;
+ CornerRadius = reader.hasAttribute("corner") ? (double) reader.getAttributeAsFloat("corner") : 0.0;
+ CuttingEdgeAngle = reader.hasAttribute("angle") ? (double) reader.getAttributeAsFloat("angle") : 180.0;
+ CuttingEdgeHeight = reader.hasAttribute("height") ? (double) reader.getAttributeAsFloat("height") : 0.0;
+ std::string type = reader.hasAttribute("type") ? reader.getAttribute("type") : "";
+ std::string mat = reader.hasAttribute("mat") ? reader.getAttribute("mat") : "";
+
+ Type = getToolType(type);
+ Material = getToolMaterial(mat);
+
+
+}
+
+const std::vector Tool::ToolTypes(void)
+{
+ std::vector toolTypes(13);
+ toolTypes[0] ="EndMill";
+ toolTypes[1] ="Drill";
+ toolTypes[2] ="CenterDrill";
+ toolTypes[3] ="CounterSink";
+ toolTypes[4] ="CounterBore";
+ toolTypes[5] ="FlyCutter";
+ toolTypes[6] ="Reamer";
+ toolTypes[7] ="Tap";
+ toolTypes[8] ="SlotCutter";
+ toolTypes[9] ="BallEndMill";
+ toolTypes[10] ="ChamferMill";
+ toolTypes[11] ="CornerRound";
+ toolTypes[12] ="Engraver";
+ return toolTypes;
+
+}
+
+const std::vector Tool::ToolMaterials(void)
+{
+ std::vector toolMat(7);
+ toolMat[0] ="Carbide";
+ toolMat[1] ="HighSpeedSteel";
+ toolMat[2] ="HighCarbonToolSteel";
+ toolMat[3] ="CastAlloy";
+ toolMat[4] ="Ceramics";
+ toolMat[5] ="Diamond";
+ toolMat[6] ="Sialon";
+ return toolMat;
+
+}
+
+Tool::ToolType Tool::getToolType(std::string type)
+{
+ Tool::ToolType Type;
+ if(type=="EndMill")
+ Type = Tool::ENDMILL;
+ else if(type=="Drill")
+ Type = Tool::DRILL;
+ else if(type=="CenterDrill")
+ Type = Tool::CENTERDRILL;
+ else if(type=="CounterSink")
+ Type = Tool::COUNTERSINK;
+ else if(type=="CounterBore")
+ Type = Tool::COUNTERBORE;
+ else if(type=="FlyCutter")
+ Type = Tool::FLYCUTTER;
+ else if(type=="Reamer")
+ Type = Tool::REAMER;
+ else if(type=="Tap")
+ Type = Tool::TAP;
+ else if(type=="SlotCutter")
+ Type = Tool::SLOTCUTTER;
+ else if(type=="BallEndMill")
+ Type = Tool::BALLENDMILL;
+ else if(type=="ChamferMill")
+ Type = Tool::CHAMFERMILL;
+ else if(type=="CornerRound")
+ Type = Tool::CORNERROUND;
+ else if(type=="Engraver")
+ Type = Tool::ENGRAVER;
+ else
+ Type = Tool::UNDEFINED;
+
+ return Type;
+}
+
+Tool::ToolMaterial Tool::getToolMaterial(std::string mat)
+{
+ Tool::ToolMaterial Material;
+ if(mat=="Carbide")
+ Material = Tool::CARBIDE;
+ else if(mat=="HighSpeedSteel")
+ Material = Tool::HIGHSPEEDSTEEL;
+ else if(mat=="HighCarbonToolSteel")
+ Material = Tool::HIGHCARBONTOOLSTEEL;
+ else if(mat=="CastAlloy")
+ Material = Tool::CASTALLOY;
+ else if(mat=="Ceramics")
+ Material = Tool::CERAMICS;
+ else if(mat=="Diamond")
+ Material = Tool::DIAMOND;
+ else if(mat=="Sialon")
+ Material = Tool::SIALON;
+ else
+ Material = Tool::MATUNDEFINED;
+
+ return Material;
+}
+
+const char* Tool::TypeName(Tool::ToolType typ) {
+ switch (typ) {
+ case Tool::DRILL:
+ return "Drill";
+ case Tool::CENTERDRILL:
+ return "CenterDrill";
+ case Tool::COUNTERSINK:
+ return "CounterSink";
+ case Tool::COUNTERBORE:
+ return "CounterBore";
+ case Tool::FLYCUTTER:
+ return "FlyCutter";
+ case Tool::REAMER:
+ return "Reamer";
+ case Tool::TAP:
+ return "Tap";
+ case Tool::ENDMILL:
+ return "EndMill";
+ case Tool::SLOTCUTTER:
+ return "SlotCutter";
+ case Tool::BALLENDMILL:
+ return "BallEndMill";
+ case Tool::CHAMFERMILL:
+ return "ChamferMill";
+ case Tool::CORNERROUND:
+ return "CornerRound";
+ case Tool::ENGRAVER:
+ return "Engraver";
+ case Tool::UNDEFINED:
+ return "Undefined";
+ }
+ return "Undefined";
+}
+
+const char* Tool::MaterialName(Tool::ToolMaterial mat)
+{
+ switch (mat) {
+ case Tool::HIGHSPEEDSTEEL:
+ return "HighSpeedSteel";
+ case Tool::CARBIDE:
+ return "Carbide";
+ case Tool::HIGHCARBONTOOLSTEEL:
+ return "HighCarbonToolSteel";
+ case Tool::CASTALLOY:
+ return "CastAlloy";
+ case Tool::CERAMICS:
+ return "Ceramics";
+ case Tool::DIAMOND:
+ return "Diamond";
+ case Tool::SIALON:
+ return "Sialon";
+ case Tool::MATUNDEFINED:
+ return "Undefined";
+ }
+ return "Undefined";
+}
\ No newline at end of file
diff --git a/src/Mod/Path/App/Tool.h b/src/Mod/Path/App/Tool.h
new file mode 100644
index 0000000000..c8a5690fc3
--- /dev/null
+++ b/src/Mod/Path/App/Tool.h
@@ -0,0 +1,104 @@
+/***************************************************************************
+ * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2014 *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+#ifndef PATH_TOOL_H
+#define PATH_TOOL_H
+
+#include
+#include
+#include