sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    [Plugin] 2dBoolean ver1.3.1 beta UPDATE 20 dec 2013

    Scheduled Pinned Locked Moved Plugins
    88 Posts 8 Posters 48.8k Views 8 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • TIGT Offline
      TIG Moderator
      last edited by

      No... try to simplify your code. πŸ˜„
      I'm trying to suggest a streamlined approach, that both faster and 'easier to get your head around'.
      After the intersecting etc... edges will be split by every edge of the face and then these possibly split edges will either fall 'on' the face, 'off' the face, OR with both vertices on the face's perimeters...
      Collect all of the edges inside the group.
      Check each edge in turn, looking at its two vertices' positions and seeing where they are 'on' the face.
      Some edges are clearly 'on' - some are clearly 'off'... from testing a vertex.position in the face.classy_point() method... There are several possible results but careful interpretation will prove VERY useful...
      If there are questionable edges [with both vertices on the face's edges or face's vertices] you can check if that edge is 'spanning' a convex or concave corner. If it's 'concave' the midpoint of the edge is not on the face so it has to be erased later on...
      So just do the tests as I described... and make an array of 'edge-failures'.
      Once you've been through all of the edges in the group you can then erase the array of edge-failures 'en mass'.
      Done - the group is trimmed to every perimeter of the face - including its 'holes'.
      Because faces need edges they'll also go with the 'removed edges'.
      this is much simpler... πŸ˜„

      TIG

      1 Reply Last reply Reply Quote 0
      • jolranJ Offline
        jolran
        last edited by

        @unknownuser said:

        I'm trying to suggest a streamlined approach

        I will try to do my best. I think I know now what you mean. If I do it right, I think we will see some speed improvements as well.

        Finally time to do some coding, been preoccupied with bunch of boring things today.

        Off to work πŸ˜„

        1 Reply Last reply Reply Quote 0
        • jolranJ Offline
          jolran
          last edited by

          Well I think we are back to par with this method!

          And it seams a whole lot faster. Haven't tried on heavy geometry. But It really feels faster.

          It seams to erase edges as it should be. And on the + side edges inside holes get's erased, which is really good.

          Actually point outside is all you need. I don't think there is any need to test on every scenario?

          I've set up the iterator like this. Where gp2edge is edge.array and comparefaces are the face to be used in classify point.
          Names will get shorter later on. I think it's good when workin on the code to have explaining names..

           gp2edge.to_a.each{|edge| 
                        comparefaces.to_a.each{|face| 
          	   
          	                    if face.classify_point(edge.start)==Sketchup;;Face;;PointOutside and              
                                     face.classify_point(edge.end)==Sketchup;;Face;;PointOutside
          					       
          						   gp2ptogo << edge
          				       
          					   end
          	                    
          						if face.classify_point(edge.start.position.offset(edge.line[1], edge.length/2))==Sketchup;;Face;;PointOutside
          				           
          						   gp2ptogo << edge
          				      
          					  end
          				
          				} 
                      }
          

          Now if we could just get rid of the faces in the holes. I'm gonna try pt=tface.bounds.center.project_to_plane(face.plane) and see what happends....

          1 Reply Last reply Reply Quote 0
          • TIGT Offline
            TIG Moderator
            last edited by

            Testing for one of the vertex 'points outside' the face will remove most unwanted edges... BUT imagine this... in a face's hole you have an intersected line drawn across if from one edge to the other, you don't want that line BUT neither of the vertices test 'outside' because they are both on the face's edges or vertices... so they pass... just as if they were the perimeter to the form... BUT my suggestion will find these - test the edge's midpoint for being 'on the face' or on a face's edge if it is then it's NOT in a hole so we keep it [i.e. it's a perimeter edge or a line spanning from one edge to another across the face itself rather than across a hole], but if NOT then it's to be erased as it is spanning over a hole...
            You must test for this scenario.
            Make a large linear group that will span over a whole face with single lines - without that test they'll all get erased as none of them will have vertices on a face?
            β˜€
            πŸ’­ Instead of testing both vertices for every edge test every edge's midpoint [which is easy enough to find!], for being 'on face' [not in a hole] OR 'on edge' OR 'on vertex' - if it passes ANY one of these it's kept, BUT if it passes NONE of these then it goes on the list for erasing at the end - this reduces the number of tests by over a half! It will have noticeable speed improvements and less convoluted checking... πŸ˜•

            TIG

            1 Reply Last reply Reply Quote 0
            • jolranJ Offline
              jolran
              last edited by

              @unknownuser said:

              test the edge's midpoint for being 'on the face' or on a face's edge if it is then it's NOT in a hole so we keep it [i.e. it's a perimeter edge or a line spanning from one edge to another across the face itself rather than across a hole], but if NOT then it's to be erased as it is spanning over a hole...

              Yes, this code, no? if face.classify_point(edge.start.position.offset(edge.line[1, edge.length/2))==Sketchup::Face::PointOutside]

              I'm working on the face thing now.. If I get that working there should be some serious testing, and then come back and fix things if needed.

              And yeah! There are speed increases. I will time it later when doing som more complex geometry.

              Thanks for this TIG.

              If this will get OK, Hatchfaces would use this intersection as well. Am doing some JS, html tutorials at the same time as coding πŸ˜‰

              1 Reply Last reply Reply Quote 0
              • jolranJ Offline
                jolran
                last edited by

                I don't think we can use face.bounds.center as a point in face.classify method. Eg (face.bounds.center.project_to_plane(face.plane))

                The center point of a face can be in a hole if the face is surrounding the hole. Hope the pic explains..
                (the big face gets erased!)

                The BIG problem was to erase edges inside holes. Wich you fixed πŸ˜„ !!

                So now when that seams to be working. I'm thinking, recreating the holes a' la face.clone. Then erasing the faces. This would not have been possible before if there where edges inside the hole.

                Edited: Hm, since there already are faces in the holes, the new one ends up on top and intersection is needed. Could be difficult to retrieve them for erasing after that.. OR rather, it might be excessive to create the faces just the get hold of them..


                faces-1.jpg

                1 Reply Last reply Reply Quote 0
                • TIGT Offline
                  TIG Moderator
                  last edited by

                  Please reread my posts, we are not talking about finding the center of any faces OR making any 'face clones'... πŸ˜•
                  Just intersect the group's entities with the face.edges+[face] etc.
                  Find all of the edges in the intersected group.
                  Look at each edge...
                  mid=edge.start.position.offset(edge.line[1],edge.length/2)
                  Then use
                  result=face.classify_point(mid)
                  To see if it's on the face or an edge/vertex - if it's not it's earmarked to go!
                  Done.

                  TIG

                  1 Reply Last reply Reply Quote 0
                  • jolranJ Offline
                    jolran
                    last edited by

                    I have reread your posts, over and over πŸ˜„

                    @unknownuser said:

                    Just intersect the group's entities with the face.edges+[face] etc.
                    Find all of the edges in the intersected group.
                    Look at each edge...
                    mid=edge.start.position.offset(edge.line[1],edge.length/2)
                    Then use
                    result=face.classify_point(mid)
                    To see if it's on the face or an edge/vertex - if it's not it's earmarked to go!

                    This IS what I'm doing already. Edges are being erased as they should be.

                    gp2edge.to_a.each{|edge| 
                                  comparefaces.to_a.each{|face| 
                    	   
                    	                    if face.classify_point(edge.start)==Sketchup;;Face;;PointOutside and              
                                               face.classify_point(edge.end)==Sketchup;;Face;;PointOutside
                    					       
                    						   gp2ptogo << edge
                    				       
                    					   end
                    	                    
                    						if face.classify_point(edge.start.position.offset(edge.line[1], edge.length/2))==Sketchup;;Face;;PointOutside
                    				           
                    						   gp2ptogo << edge
                    				      
                    					   end
                                           
                    					   
                    				} 
                                }
                    

                    The problem is that faces inside holes wont get erased unless we tell'em to. πŸ˜„

                    If you mean to reread your posts to take care of THIS particular problem, I'm sorry did not understand how, by information provided. I'm working at the problem right now, and it should not be as difficult as erasing the edges inside holes.


                    faces2-1.jpg

                    1 Reply Last reply Reply Quote 0
                    • jolranJ Offline
                      jolran
                      last edited by

                      Hmm. This problem I havent got a clue about..

                      The calculation is irregular. Sometimes it fails to erase the required faces..

                      I don't know If it's worth killing thyself for.. Most of the times there will be plenty of geometry so this calculation isent needed anyway... But I would like to know why comparison fails and if there are any resque methods for these kinds of failures.


                      hole tests.jpg

                      1 Reply Last reply Reply Quote 0
                      • jolranJ Offline
                        jolran
                        last edited by

                        OK, got it! hopefully

                        Made a group of faces from face.clone holes. Took their face.bounds.centers.
                        Then compared cutting.components (faces.center.bounds) to those other centers.
                        Since center is a point=position I could use ==comparison. Just delete face if they where in the same position..

                        The code can probably be optimized, but first do some testing and see if it holds!

                        1 Reply Last reply Reply Quote 0
                        • TIGT Offline
                          TIG Moderator
                          last edited by

                          πŸ˜• Why are you still using 'face clone holes' and 'bounds center' ??? πŸ˜•
                          You are still making it too complex...
                          Simply use the group that is to be trimmed and intersect group.entities with the face.edges+[face], placing the results in the group.entities.
                          If the original thing to 'trim' is a component-instance, as I tried to explain... make it into a group...
                          group=instance.parent.entities.add_group(instance) instance.explode
                          NOW inspect the group.entities to get unneeded off-face edges and then remove them [as explained]...

                          After you're done every thing IF desired then exploding the group will merge it with the face ? [you could erase the face first]

                          TIG

                          1 Reply Last reply Reply Quote 0
                          • jolranJ Offline
                            jolran
                            last edited by

                            Gee!! πŸ‘Š Now I get what you are saying..

                            Explode the COLORED face.group onto the face.clone. I did not get that part.

                            OK I will try your method now. Thanks.

                            1 Reply Last reply Reply Quote 0
                            • jolranJ Offline
                              jolran
                              last edited by

                              I'm sorry. Tried to do what you said, or what I think you mean. 😳

                              But still don't understand how the faces in holes are supposed to disapear when merging them(exploding) onto the face.
                              This is done after intersection and trimming the edges..

                              Just to make sure we talk about the same entities here. face.edges+[face] is the face.clone.entities right?

                              Group is the selected component or group in Sketchup(turned into a group by definition).

                              Now, to be able to explode the group onto face.clone the group off course have to be inside face.clone group=gp.

                              Then after all that, the last step is to transform the group and turn it into a cutting component.

                              1 Reply Last reply Reply Quote 0
                              • TIGT Offline
                                TIG Moderator
                                last edited by

                                We still speak at cross-purposes πŸ˜’

                                Try to 'forget' everything so far...

                                Your code already finds the 'face' and 'group' that is overlaid on it that we need.
                                [if it's a component-instance you first add it to a group [explode it] and use that group].
                                You can then use the group.entities.intersect_with()...
                                Add the intersection geometry into group.entities made when it intersects with (face.edges+[face]).
                                We now have a group containing all of the edges and faces needed.
                                Some of these are in holes in the face or outside of the face altogether.
                                To find these iterate all edges in the group.entities, compose an array of any edges which fail a set of face.classify_point() tests on the edge's midpoint - an edge passes and is NOT erased if it is ON the face [in off or in a hole], OR on a face's edge, OR on a face's vertex. Otherwise it fails.
                                When you have the list of 'edges2go' you erase them en mass.
                                Now you should have a group with all edges/faces trimmed to the perimeters of the face - including any holes in the face...
                                At this point the group is laid on the face and will z-fight between the faces.

                                You can them convert that group into a gluing cutting component with appropriate axes and in the same transformation, glued_to the face...
                                You can then offer the user the chance to explode the group and merge the group's trimmed faces and the original face...
                                πŸ˜•

                                TIG

                                1 Reply Last reply Reply Quote 0
                                • jolranJ Offline
                                  jolran
                                  last edited by

                                  Ahh ok. That is more streamlined. πŸ˜„

                                  SS=Sketchup.active_model.selection-face. So no face.clone is needed then?

                                  @unknownuser said:

                                  When you have the list of 'edges2go' you erase them en mass.
                                  Now you should have a group with all edges/faces trimmed to the perimeters of the face - including any holes in the face...

                                  This I still am not convinced about. You have to forgive me if I seam like a stuborn idiot, but please look at the picture. There will be 1 face remaining if we only delete edges2go. ❓

                                  OR do you mean it will go away after the intersection? I havent tested yet.


                                  Faced with a problem-1.jpg

                                  1 Reply Last reply Reply Quote 0
                                  • TIGT Offline
                                    TIG Moderator
                                    last edited by

                                    β˜€
                                    At last I can see the issue too. πŸ˜’
                                    I was missing some points in one of your earlier posts. 😳
                                    So... after all of the edges2go are collected and erased we might still have some 'never-split' faces over 'holes' that will still need to be removed, or also such faces over 'holes' that are abutting a 'perimeter' of the face.

                                    Therefore we MUST go back to earlier ideas... πŸ˜’ πŸ˜’

                                    After the midpoint tests of the group's edges and the 'edges2go' tidy up [which WILL remove a lot of unwanted dross] we MUST examine the group's faces in turn.
                                    We can get a point on each of these faces and test it using face.classify_point(pt) if it returns as 'off the face' [i.e in a hole] then we .erase! it.
                                    Finally we then do a final 'tidy up' - i.e. removing faceless-edges left after unwanted faces are removed.

                                    Here's the whole test/fix...
                                    faces=[] group.entities.each{|e| faces << e if e.class==Sketchup::Face } tedges=[] faces.each{|gface| pt=gface.bounds.center.project_to_plane(face.plane) if face.classify_point(pt)==Sketchup::Face::PointOutside tedges << gface.edges gface.erase! end } tedges.flatten! tedges.uniq! tedges.each{|e| e.erase! if e.valid? and not e.faces[0] }

                                    Once that's all done we can worry about making the group into the gluing/cutting component, with corrected axes as before... 😲

                                    TIG

                                    1 Reply Last reply Reply Quote 0
                                    • jolranJ Offline
                                      jolran
                                      last edited by

                                      He he! No worries πŸ˜„

                                      Sometimes when I reread my posts I wonder what the heck I was talking about. That's why I post so many pictures πŸ˜„ To clear things up.

                                      This new code of yours look very nice. Can't wait to test it out.

                                      @unknownuser said:

                                      tedges.uniq!

                                      Haven't seen that command before? To remove duplicates? Need to read more about pure Ruby...

                                      @unknownuser said:

                                      Once that's all done we can worry about making the group into the gluing/cutting component, with corrected axes as before...

                                      I was thinking of putting in the option to make group instead of component, should one wish. Could be useful if the user only has edges with no faces.

                                      Thanks a lot for your help, TIG!

                                      1 Reply Last reply Reply Quote 0
                                      • jolranJ Offline
                                        jolran
                                        last edited by

                                        I'm having trouble with this part of the code. Maybe should add some parameters to it?

                                        faces.each{|gface|
                                        pt=gface.bounds.center.project_to_plane(face.plane)
                                        if face.classify_point(pt)==Sketchup;;Face;;PointOutside
                                        tedges << gface.edges
                                        gface.erase!
                                        end
                                        }
                                        

                                        If you look at the picture, you will see that it might not work in all cases with that code.
                                        Especially when having big faces.

                                        In the earlier posts I was trying to figure out a way to erase faces more selectively.
                                        By using IF the FACES center==HOLES center >> erase.faces! (Simplified code)

                                        However, when I did that, sometimes there where errors. Or faces that would not get deleted.


                                        Faced with a problem-2.jpg

                                        1 Reply Last reply Reply Quote 0
                                        • TIGT Offline
                                          TIG Moderator
                                          last edited by

                                          The .flatten! combines nested arrays
                                          The .uniq! removes duplicates
                                          Also [not applicable to THIS tool] .compact! would remove 'nil' array elements, or .sort! puts the list 'in order'...

                                          Now to the chase.........
                                          I also see this 'unexpected' possibility of faces we want to keep being false-flagged as 'holes'.
                                          So we need to trap for real 'hole' faces - the outer_loop edges will always have two faces...

                                          faces2go=[]### rather than erase as we go we'll collect them...
                                          faces.each{|gface|
                                            ### we skip the gface IF it's NOT a 'hole'
                                            ### just 1 one-faced edges is enough for != hole
                                            hole=true
                                            gface.outer_loop.edges.each{|e|
                                              if e.faces.length==1
                                                hole=false
                                                break
                                              end
                                            }
                                            next if not hole
                                            ###
                                            pt=gface.bounds.center.project_to_plane(face.plane)
                                            if face.classify_point(pt)==Sketchup;;Face;;PointOutside
                                              tedges << gface.edges
                                              faces2go << gface ### save them up
                                            end
                                          }
                                          
                                          

                                          THEN erase_entities on faces2go and then erase! any of the tedges that don't have a face...

                                          TIG

                                          1 Reply Last reply Reply Quote 0
                                          • jolranJ Offline
                                            jolran
                                            last edited by

                                            @unknownuser said:

                                            The .flatten! combines nested arrays
                                            The .uniq! removes duplicates
                                            Also [not applicable to THIS tool] .compact! would remove 'nil' array elements, or .sort! puts the list 'in order'...

                                            πŸ‘ Great to know. Will be useful.

                                            Your code works! Almost

                                            Like with the method I used before(face.clone holes.centers), I'm experiencing some faces don't get erased. (Having a model that look like a swiss cheese)

                                            I wonder why this happends. Your code should be working...

                                            For ex. I run the plugin once. Maybe 3 faces are not deleted but the edges are trimmed to fit. I run the plugin again with the component selected, then it is OK!

                                            It is like it needs another rescue operation? πŸ˜• Or maybe run the last command twice? Seems excessive..

                                            I will check my code as well. Been moving snippets back and forth, it need some cleaning up.

                                            And another thing. Was it GO for NOT using faceclone? Intersect with SS or Glue face?
                                            I havent implemented that yet, still using face.clone. Shouldent matter in this regard...


                                            Almost.jpg

                                            1 Reply Last reply Reply Quote 0
                                            • 1
                                            • 2
                                            • 3
                                            • 4
                                            • 5
                                            • 4 / 5
                                            • First post
                                              Last post
                                            Buy SketchPlus
                                            Buy SUbD
                                            Buy WrapR
                                            Buy eBook
                                            Buy Modelur
                                            Buy Vertex Tools
                                            Buy SketchCuisine
                                            Buy FormFonts

                                            Advertisement