gumyr / build123d

A python CAD programming library
Apache License 2.0
565 stars 93 forks source link

Trouble loading certain STL files #472

Closed jdegenstein closed 10 months ago

jdegenstein commented 10 months ago

cyl_w_rect_hole.zip build123d has trouble properly loading the attached STL file which has been verified as manifold using multiple external tools.

image

build123d returns a Shell when it should have been a Solid. After further investigation, it was found that the two methods for checking if an object is manifold disagree if this object is manifold.:

mesh_3mf.IsManifoldAndOriented()=True #Lib3MF method
shape_obj.is_manifold=False #OCCT-based method

There are 4 total faces with their normal direction flipped, and 3 faces are on the bottom of the object (pictured): image

importer3 = Mesher()
stl3 = importer3.read("cyl_w_rect_hole.stl")
stl3 = stl3[0]
print(type(stl3)) #returns ...Shell

strict_normal = filter(
    lambda v: v.normal_at() == Vector(0,0,1)
    and v.area != 0,
    stl3.faces().group_by(Axis.Z)[0],
)
flipped_faces=list(strict_normal)

strict_normal2 = filter(
    lambda v: v.normal_at() == Vector(-1,0,0),
    stl3.faces().filter_by(Axis.X).group_by(Axis.X)[0],
)

flipped_faces.append(*list(strict_normal2))

show(stl3, flipped_faces)

for face in flipped_faces:
    print(face.vertices())

Returns:

[Vertex: (5.767554759979248, -7.226373195648193, 0.0), Vertex: (5.767554759979248, -6.5179619789123535, 0.0), Vertex: (17.320520401000977, -9.999995231628418, 0.0)]
[Vertex: (5.767554759979248, -6.186254024505615, 0.0), Vertex: (5.767554759979248, -5.47706937789917, 0.0), Vertex: (17.820159912109375, -9.079829216003418, 0.0)]
[Vertex: (5.767554759979248, -5.132949352264404, 0.0), Vertex: (5.767554759979248, -4.424521446228027, 0.0), Vertex: (18.270936965942383, -8.134744644165039, 0.0)]
[Vertex: (-5.767554759979248, -1.9726612567901611, 0.0), Vertex: (-5.767554759979248, -1.3000463247299194, 0.0), Vertex: (-5.767554759979248, -0.9113571047782898, 0.0), Vertex: (-5.767554759979248, -0.2291174829006195, 0.0), Vertex: (-5.767554759979248, 0.15582090616226196, 0.0), Vertex: (-5.767554759979248, 0.846271812915802, 0.0), Vertex: (-5.767554759979248, 1.225943922996521, 0.0), Vertex: (-5.767554759979248, 1.3390579223632812, 39.99998092651367)]

The last flipped face somehow has 8 vertices.

gumyr commented 10 months ago

I was under the impression that it was not possible to create a valid shell/solid if the vertices along an edge weren't consistent - this is wrong. Here is an experiment:

from build123d import *
from build123d import downcast
from ocp_vscode import *
from OCP.BRepBuilderAPI import (
    BRepBuilderAPI_MakeFace,
    BRepBuilderAPI_MakePolygon,
    BRepBuilderAPI_MakeSolid,
    BRepBuilderAPI_MakeVertex,
    BRepBuilderAPI_Sewing,
)
from OCP.gp import gp_Pnt

pnt_set = [
    [gp_Pnt(*p) for p in [(0, 0, 0), (0.5, 0, 0), (0, 1, 0)]],
    [gp_Pnt(*p) for p in [(0.5, 0, 0), (1, 0, 0), (0, 1, 0)]],
    [gp_Pnt(*p) for p in [(0, 0, 0), (1, 0, 0), (0, -1, 0)]],
    [gp_Pnt(*p) for p in [(0, -1, 0), (0, 1, 0), (0, 0, -1)]],
    [gp_Pnt(*p) for p in [(0, -1, 0), (0, 0, -1), (1, 0, 0)]],
    [gp_Pnt(*p) for p in [(0, 1, 0), (1, 0, 0), (0, 0, -1)]],
]
shell_builder = BRepBuilderAPI_Sewing()
for pnts in pnt_set:
    vertices = [downcast(BRepBuilderAPI_MakeVertex(pnt).Vertex()) for pnt in pnts]
    wire_builder = BRepBuilderAPI_MakePolygon(*vertices, Close=True)
    face_builder = BRepBuilderAPI_MakeFace(wire_builder.Wire())
    shell_builder.Add(face_builder.Face())

shell_builder.Perform()
occ_sewed_shape = downcast(shell_builder.SewedShape())
solid_builder = BRepBuilderAPI_MakeSolid(occ_sewed_shape)
ocp_solid = solid_builder.Solid()
bd_solid = Solid(ocp_solid)
print(bd_solid.is_manifold, bd_solid.is_valid(), bd_solid.volume, len(bd_solid.faces()))
# bd_solid.clean()
# print(bd_solid.is_manifold, bd_solid.is_valid(), bd_solid.volume, len(bd_solid.faces()))
show(occ_sewed_shape, ocp_solid, bd_solid)

image

True True 0.33333333333333337 6

clean() has the predicted impact of reducing the number of faces to four.