BIM: Add support to import lines from obj files

Single lines and polylines from 'l' instructions are imported as
Draft::Wire objects and grouped with an App:Part object so that
the lines contained in the obj file are included in the
corresponding object definition.

Single lines defined in the obj file within a block are converted
into a non-closed polyline if the second point of a line matches
the first point of the following line.

Fixes #21326
This commit is contained in:
Ralf Habacker
2025-05-13 13:04:24 +02:00
parent ec88f39f6d
commit 5e0c109cb1

View File

@@ -287,6 +287,13 @@ def export(exportList,filename,colors=None):
FreeCAD.Console.PrintMessage(translate("Arch","Successfully written") + ' ' + filenamemtl + "\n")
# return entry after given index from an array or None on array end
def peek(index, array):
if index < len(array) - 1:
return array[index+1].strip()
else:
return None
def open(filename):
"called when freecad wants to open a file"
docname = os.path.splitext(os.path.basename(filename))[0]
@@ -310,6 +317,8 @@ def insert(filename,docname):
with pyopen(filename,"r",encoding="utf8") as infile:
verts = []
medges = []
edges = []
facets = []
activeobject = None
material = None
@@ -324,7 +333,7 @@ def insert(filename,docname):
activeobjectExists = True
if not activeobjectExists:
activeobject = meshName
for line in content_array:
for index, line in enumerate(content_array):
line = line.strip()
if line[:7] == "mtllib ":
matlib = os.path.join(os.path.dirname(filename),line[7:])
@@ -349,8 +358,9 @@ def insert(filename,docname):
colortable[mname] = [color,trans]
elif line[:2] == "o ":
if activeobject:
makeMesh(doc,activeobject,verts,facets,material,colortable)
makeMesh(doc,activeobject,verts,medges,facets,material,colortable)
material = None
medges = []
facets = []
activeobject = line[2:]
elif line[:2] == "v ":
@@ -362,14 +372,26 @@ def insert(filename,docname):
i = i.split("/")[0]
fa.append(int(i))
facets.append(fa)
elif line[:2] == "l ":
edge = []
for i in line[2:].split():
if "/" in i:
i = i.split("/")[0]
edge.append(int(i))
edges.append(edge)
# combine lines into medges
l = peek(index, content_array)
if l == None or l[:2] != "l ":
medges = edges
edges = []
elif line[:7] == "usemtl ":
material = line[7:]
if activeobject:
makeMesh(doc,activeobject,verts,facets,material,colortable)
makeMesh(doc,activeobject,verts,medges,facets,material,colortable)
FreeCAD.Console.PrintMessage(translate("Arch","Successfully imported") + ' ' + filename + "\n")
return doc
def makeMesh(doc,activeobject,verts,facets,material,colortable):
def makeMesh(doc,activeobject,verts,edges,facets,material,colortable):
mfacets = []
if facets:
for facet in facets:
@@ -391,8 +413,49 @@ def makeMesh(doc,activeobject,verts,facets,material,colortable):
mobj = doc.addObject("Mesh::Feature",activeobject)
mobj.Label = activeobject
mobj.Mesh = Mesh.Mesh(mfacets)
if material and FreeCAD.GuiUp:
if material in colortable:
mobj.ViewObject.ShapeColor = colortable[material][0]
if FreeCAD.GuiUp and material and material in colortable:
mobj.ViewObject.ShapeColor = colortable[material][0]
if colortable[material][1] is not None:
mobj.ViewObject.Transparency = colortable[material][1]
# make polylines from edges
medges = []
if edges:
polyline = []
for edge in edges:
# single line
if len(edge) == 2:
i1 = edge[0]
i2 = edge[1]
if i1 == i2:
continue
if len(polyline) > 0:
if polyline[-1] == i1:
polyline.append(i2)
else:
medges.append(polyline)
polyline = []
polyline.append(i1)
polyline.append(i2)
else:
polyline.append(i1)
polyline.append(i2)
else:
medges.append(edge)
if len(polyline) > 0:
medges.append(polyline)
if medges:
part = doc.addObject("App::Part", activeobject)
part.Label = activeobject
features = []
for strip in medges:
points = [FreeCAD.Vector(*verts[i-1]) for i in strip]
wire = Draft.make_wire(points)
if FreeCAD.GuiUp and material and material in colortable:
wire.ViewObject.ShapeColor = colortable[material][0]
if colortable[material][1] is not None:
mobj.ViewObject.Transparency = colortable[material][1]
wire.ViewObject.Transparency = colortable[material][1]
features.append(wire)
part.addObjects(features)
doc.recompute()