ImportLDraw icon indicating copy to clipboard operation
ImportLDraw copied to clipboard

Some lines aren't applied to mesh edges

Open ali1234 opened this issue 5 years ago • 5 comments

The problem happens because the code tests every triangle and quad edge against the lines in the model. But for some models this fails because two triangles may be used with a single line. For example the space minifig body:

screenshot_2018-11-10_16-36-51

Here the bevel weight (blue lines) has not been set on the edge nearest the camera. On the front of the body this edge is made of two quads. On the side it is many quads. But in the ldraw file the line is defined as a single segment. Therefore no single quad edge has the same vertices as the line segment, and bevel/sharp is never applied.

ali1234 avatar Nov 10 '18 16:11 ali1234

Note that it is possible for an edge and a line to share no vertices, and also to only partially overlap, and still be required to match, as in this case:

edgo

ali1234 avatar Nov 10 '18 16:11 ali1234

This tests every edge against every line to see if they are collinear and overlapping:

        for e in bm.edges:

            a, b = e.verts[0].co, e.verts[1].co
            ab = b - a
            ba = a - b

            for c, d in geometry.edges:

                ac = c - a
                ad = d - a
                bc = c - b
                bd = d - b

                if ((ab).dot(ac) > 0 and (ba).dot(bd) > 0) or ((ab).dot(ad) > 0 and (ba).dot(bc) > 0):
                    if (ac - (ac.project(ab))).length < epsilon and (bd - (bd.project(ba))).length < epsilon:
                        e.smooth = False
                        e[bwLayer] = 1.0

Unfortunately it is very slow. The tower bridge model takes 7 minutes to load with this algorithm.

ali1234 avatar Nov 10 '18 23:11 ali1234

Here's a corner case that still isn't handled properly:

screenshot_2018-11-11_16-12-34

screenshot_2018-11-11_16-12-07

The triangles here share no vertices with the long side edge, so the geometry merge does not fix them. Then the whole of the side edge is marked because it overlaps with the three line segments.

This would require checking every pair of edges for collinearity on top of every edge-line pair. In other words it would be extremely slow without some kind of partitioning to cut down on the search space.

ali1234 avatar Nov 11 '18 16:11 ali1234

I think it may be possible to use the KDTree (see the start of addSharpEdges) to help cut down the search space.

TobyLobster avatar Nov 11 '18 16:11 TobyLobster

I have an idea how to do this. The same algorithm used for merging edges should work for lines, ie split an edge if it shares exactly one vertex with a collinear line by replacing all the faces that contain it. Finding the line can be done with the KDTree. In the above example this would create new vertices on the side edges, and then the triangle parts would end up merging into those.

The problem is that this means adding new vertices into the mesh and I haven't figured out how to do that without invalidating all of the state.

One possible idea: add all of the edges from geometry.edges into bm.edges, set them all sharp, then run the edge merge - but allow merging edges with zero faces.

ali1234 avatar Nov 12 '18 13:11 ali1234