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
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better π
Register LoginAdvertisement