Loop.convex? question
-
I was experimenting with loop.convex? and found that extra co-linear points make a surface fail this test. As a result for example if I had a rectangle that I extrude it up, and then draw a rectangle on the bottom edge of one of the side surfaces that represents a door; the floor which would have otherwise passed the convex test, now fails it. I made a variation on the sample code in the API documentation to demonstrate it. Does anyone know an easy way to catch these cases so they don't fail?
depth = 100 width = 100 model = Sketchup.active_model entities = model.active_entities pts = [] pts[0] = [0, 0, 0] pts[1] = [width, 0, 0] pts[2] = [width, depth, 0] pts[3] = [0, depth, 0] # Add the face to the entities in the model face = entities.add_face pts loop = face.outer_loop status = loop.convex? if (status) UI.messagebox "Loop is Convex" else UI.messagebox "Loop is not Convex" end ptsB = [] ptsB[0] = [200+0, 0, 0] ptsB[1] = [200+width/2, 0, 0] ptsB[2] = [200+width, 0, 0] ptsB[3] = [200+width, depth, 0] ptsB[4] = [200+0, depth, 0] # Add the face to the entities in the model face = entities.add_face ptsB loop = face.outer_loop status = loop.convex? if (status) UI.messagebox "Loop is Convex" else UI.messagebox "Loop is not Convex" end
-
Kind of a related question. I have a source data file that has clean versions of for example the floor that has only 4 verticies vs 6 (2 extra for the door). An alternative approach is to bring in those verticies, and do a loop.convex? test on them. But it appears I have to make a face before I can make a loop? Any way to do that without actually drawing a face. Otherwise, I can draw and erase a face, but seems like it would slow things down.
-
You could get the vertices and get rid of the ones that form coliner edges. Make a new temporary face and go from there. Not pretty, but works. Maybe some has a better idea?
Oh, anyone got a simple/elequent way of getting the new vertices set, instead of what I did?
depth = 100 width = 100 model = Sketchup.active_model entities = model.active_entities ptsB = [] ptsB[0] = [200+0, 0, 0] ptsB[1] = [200+width/2, 0, 0] ptsB[2] = [200+width, 0, 0] ptsB[3] = [200+width, depth, 0] ptsB[4] = [200+0, depth, 0] # Add the face to the entities in the model face = entities.add_face ptsB # Only keep non-colinear vertices v = [] ver = face.outer_loop.vertices n = (ver.length - 2) v1 = ver[0].position v2 = ver[1].position u1 = [(v2.x - v1.x), (v2.y - v1.y), (v2.z - v1.z)].normalize! u1_saved = u1 for i in 1..n do v1 = ver[i].position v2 = ver[i+1].position u2 = [(v2.x - v1.x), (v2.y - v1.y), (v2.z - v1.z)].normalize! if u1 != u2 then v.push ver[i] end u1 = u2 end v1 = ver[(ver.length - 1)].position v2 = ver[0].position u2 = [(v2.x - v1.x), (v2.y - v1.y), (v2.z - v1.z)].normalize! if u1 != u2 then v.push ver[(ver.length - 1)] end u1 = u2 if u1 != u1_saved then v.push ver[0] end # make new face & loop group = entities.add_group face2 = group.entities.add_face v loop = face2.outer_loop status = loop.convex? if (status) UI.messagebox "Loop is Convex" else UI.messagebox "Loop is not Convex" end group.erase!
-
You could do your own convex function.
I got a method for getting only the corner vertices of a face:
http://www.thomthom.net/software/sketchup/tt_lib2/doc/TT/Face.html#corners-class_method
(Click View Source)In my old TT_Lib1 library I had a method for getting the convext shape of a set of points in 2d space. http://forums.sketchucation.com/viewtopic.php?f=180&t=34306&start=15#p302805
Didier made one for 3d I think. (See later that thread)
Maybe you can cobble together something from this to your ownconvex?
method? -
Thanks for the feedback. The data file that is drawing my geometry in the first place already has a smaller list of verticies that is clean. So I guess that is the best option, going back to that, drawing a temporary face to test, and throwing it away. I don't know how much of a performance hit that will be over testing an existing face. But what I can do is pre-test with the existing face, and then only create a temporary face to test on the ones that initially fail.
David
Below is the code I ended up with. My SketchUp objects are drawn from data in an external file. I could have drawn temporary faces for convex test for every surface but decided to do the initial test off of the existing SketchUp faces, and then do a second test on faces that fail the convex test to confirm that they really are non-convex. This second test goes back to the data file, draws a temporary surface, tests it, and throws it away. The data file is already fee of un-necessary stray points.
if @hash['NON_CONVEX_SURFACES'] face = interior_partition_surfaces[index].entity loop = face.outer_loop status = loop.convex? # if face is convex skip over it if status next else # failed first convex test, run second one pointstemp = interior_partition_surfaces[index].model_object_polygon.points model = Sketchup.active_model entities = model.active_entities facetemp = entities.add_face pointstemp loop2 = facetemp.outer_loop status2 = loop2.convex? # erase facetemp facetempall = facetemp.all_connected entities.erase_entities facetempall if status2 # next statement skips the rest of this if face is convex next end end end
Advertisement