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

    Intersect_with revisited

    Scheduled Pinned Locked Moved Developers' Forum
    27 Posts 8 Posters 2.6k 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.
    • S Offline
      slbaumgartner
      last edited by

      @tt_su said:

      @slbaumgartner said:

      If you ponder Entities#intersect_with, you will notice a peculiar aspect: there are three Entities collections involved in the operation,

      Two Entities collections, and one array of entities.
      First is the one you call intersect_with on, the second is there the new entities will appear. The last is the set of entities to intersect with the Entities collection you called intersect_with on.

      @slbaumgartner said:

      All of the examples I found used Groups, and despite having an associated Transformation, the Entities in a Group are actually captured in model coordinates at all times.

      Hm... not quite sure what you get at here. But it could be that when you make a group the origin set at the model origin. But if you move the group after creating it the coordinates will be offset. I think this differs from components where the origin is set to the boundingbox minimum.

      Both of those early observations were corrected in the more detailed PDF essay later in this topic (which still contains some errors about how the new Edges interact with pre-existing geometry in the destination Entities collection). Ongoing learning and probing...

      1 Reply Last reply Reply Quote 0
      • thomthomT Offline
        thomthom
        last edited by

        My bad - I didn't look through the whole thread.

        Thomas Thomassen β€” SketchUp Monkey & Coding addict
        List of my plugins and link to the CookieWare fund

        1 Reply Last reply Reply Quote 0
        • S Offline
          slbaumgartner
          last edited by

          I wrote up my explorations of this method as the attached essay. Corrections and feedback welcome!

          Steve

          [Edit: March 2015]
          I have since found two errors in the essay.

          First, the Edges created by #intersect_with will interact with any pre-existing geometry in dest_ents. They may split and be split by pre-existing Edges and Faces in dest_ents. When this happens, new Faces and Edges in dest_ents will result. Again, this happens based on pre-existing content in dest_ents, not based on any interaction with content in ents or with_ents other than the intersection of their Faces.

          Second, my description of handling nested Groups and Components is logically correct, but you can't get the required Transformations the way I described. The reason is that for a ComponentInstance or Group that is nested inside another Component or Group, the #parent method returns the ComponentDefinition of the outer Entity, not the specific instance that contains the instance you started with. For Groups this is less of an issue, since each Group's ComponentDefinition has only a single instance. You can access this instance to get the next stage of nesting, and repeat this #parent, #instances[0] sequence to build up the full "path" of Transformations. But for a Component, the ComponentDefinition may have multiple instances, each with a different Transformation, and you need significantly more complicated logic to figure out which one you are trying to use for the intersection. In the SketchUp GUI, you have to open each level of nesting for edit, and the resulting sequence of transformations is accumulated in model#active_path. I don't know of a simple equivalent when you chose the target Entities in Ruby code.


          SketchUp Intersect_with.pdf

          1 Reply Last reply Reply Quote 0
          • sdmitchS Offline
            sdmitch
            last edited by

            My pet peeve with intesect_with is sketchup's random results. In several of my plugins, like FloorGenerator, I create a grid on a face by intersecting a group that defines the grid consisting to faces perpendicular to the "floor" and a group containing the "floor". The "floor" group is then exploded. This works perfectly most of the time but, as faces get more complicated, results can be erratic as illustrated in this screen shot.dbm1.jpg The red faces are faces that consist of two or more grid "cells". Each group was processed with the same plugin using the same grid size with different results.

            Anyone else seen this

            Nothing is worthless, it can always be used as a bad example.

            http://sdmitch.blogspot.com/

            1 Reply Last reply Reply Quote 0
            • S Offline
              slbaumgartner
              last edited by

              @sdmitch said:

              The red faces are faces that consist of two or more grid "cells".

              I'm not sure what you mean by this. Do you mean that the intersection produces duplicate Faces?

              1 Reply Last reply Reply Quote 0
              • sdmitchS Offline
                sdmitch
                last edited by

                @slbaumgartner said:

                @sdmitch said:

                The red faces are faces that consist of two or more grid "cells".

                I'm not sure what you mean by this. Do you mean that the intersection produces duplicate Faces?

                No not duplicate faces but what should be two or more faces somehow combined into one face.

                Nothing is worthless, it can always be used as a bad example.

                http://sdmitch.blogspot.com/

                1 Reply Last reply Reply Quote 0
                • S Offline
                  slbaumgartner
                  last edited by

                  What technique are you using to identify the red faces? They look pretty regularly sized, so I am confused about what the floor grid looked like...were its cells of varying size?

                  I've not seen that effect, but it looks like it is sensitive to the exact geometry involved and its location in model coordinates. Maybe there are "leaks", i.e. Faces not quite closed because of where the intersection points were placed? That could be a consequence of finite computer arithmetic during the intersection. Those look like roof planes, and if so this is probably not the infamous nearby vertices behavior. Maybe you could examine a sample closely to see?

                  1 Reply Last reply Reply Quote 0
                  • sdmitchS Offline
                    sdmitch
                    last edited by

                    @slbaumgartner said:

                    What technique are you using to identify the red faces? They look pretty regularly sized, so I am confused about what the floor grid looked like...were its cells of varying size?

                    I've not seen that effect, but it looks like it is sensitive to the exact geometry involved and its location in model coordinates. Maybe there are "leaks", i.e. Faces not quite closed because of where the intersection points were placed? That could be a consequence of finite computer arithmetic during the intersection. Those look like roof planes, and if so this is probably not the infamous nearby vertices behavior. Maybe you could examine a sample closely to see?

                    I compared the area of the face to what the area of a full "cell" would be and colored red any faces that exceeded the limit. In this case the grid is 1m X 1m.

                    I would agree that there might be faces not closed if the results was the same each time but, as you can see, that is not the case.

                    Here is an example of what should be three faces combined into one.dbm2.jpg
                    and the coordinates of the vertices

                    1. Point3d(3571.39, 1044.32, 154.416), 1. Point3d(3571.39, 1043.97, 154.137), 1. Point3d(3582.77, 1043.97, 154.137), 1. Point3d(3582.77, 1074.56, 178.92), 1. Point3d(3614.04, 1074.56, 178.92), 1. Point3d(3622.14, 1092.34, 193.32), 1. Point3d(3622.14, 1105.15, 203.702), 1. Point3d(3582.77, 1105.15, 203.702), 1. Point3d(3582.77, 1135.75, 228.485), 1. Point3d(3543.4, 1135.75, 228.485), 1. Point3d(3543.4, 1105.15, 203.702), 1. Point3d(3582.77, 1105.15, 203.702), 1. Point3d(3582.77, 1074.56, 178.92), 1. Point3d(3571.39, 1074.56, 178.92), 1. Point3d(3571.39, 1070.32, 175.479)

                    Nothing is worthless, it can always be used as a bad example.

                    http://sdmitch.blogspot.com/

                    1 Reply Last reply Reply Quote 0
                    • S Offline
                      slbaumgartner
                      last edited by

                      Most intriguing! I don't have an answer, but here's some more discussion for thought...

                      At least to the precision you printed out, points 4 and 13 are identical, as are points 8 and 12, yet these vertices have not been merged. That is probably the cause of the behavior: the sequence of vertices looks like an ordinary outer loop to SketchUp. But why are they separate? And why did SketchUp gather them into a Face? Possibilities that come to mind:

                      • they differ in decimal places beyond what you printed but still larger than the merge vertices threshold of 0.001". I don't know what units you used, so can't tell. At full precision, there might be a tiny gap between these points.
                      • the merge vertices and geometry cleanup operation misfired (which would be a bug!)
                      • the intersect operation explicitly built these Faces that way (which would also be a bug!)

                      Regarding the randomness, do you get different results if you undo the operation and then redo it with the identical geometry? If this produces the same results but moving or changing the geometry in any way causes different results, it sounds like a computer arithmetic problem that varies depending on the exact values encountered (not that this observation gives you a clue what to do about it πŸ˜„.

                      One trick I've had work in some situations is to nest everything one extra level deep in a Group, do the work, and then explode that temporary Group when completed. This seems to trigger another round of geometry cleanup which may repair the flaws.

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

                        If you are likely to get faces with 'twisted vertices', e.g. forming 'bow-ties' or in your case worse...
                        Then I suggests the following...
                        Collect the vertices' points into an array.
                        Get a face normal vector from one of the faces - vec=face.normal
                        Add a temporary group into those faces' context.
                        Iterate the collected vertices' points.
                        For each point, add short 'vertical' edge to the temp_group.entities...
                        Collecting the new edges as you go...
                        Initially tedges=[]
                        then iterating...
                        tedges << ents.add_line(point, point.offset(vec))
                        When done, explode the group to try and split the 'bow-tie' faces.
                        Finally erase the tedges - testing for validity...
                        temp_group.explode tedges.each{|e| e.erase! if e.valid? }
                        If those faces which need to get fixed are 'coplanar', then there is no risk of the new tedges geometry clashing with some existing geometry, so the validity check is academic...
                        πŸ˜•

                        TIG

                        1 Reply Last reply Reply Quote 0
                        • sdmitchS Offline
                          sdmitch
                          last edited by

                          @slbaumgartner said:

                          Most intriguing! I don't have an answer, but here's some more discussion for thought...

                          At least to the precision you printed out, points 4 and 13 are identical, as are points 8 and 12, yet these vertices have not been merged. That is probably the cause of the behavior: the sequence of vertices looks like an ordinary outer loop to SketchUp. But why are they separate? And why did SketchUp gather them into a Face? Possibilities that come to mind:

                          • they differ in decimal places beyond what you printed but still larger than the merge vertices threshold of 0.001". I don't know what units you used, so can't tell. At full precision, there might be a tiny gap between these points.
                          • the merge vertices and geometry cleanup operation misfired (which would be a bug!)
                          • the intersect operation explicitly built these Faces that way (which would also be a bug!)

                          Regarding the randomness, do you get different results if you undo the operation and then redo it with the identical geometry? If this produces the same results but moving or changing the geometry in any way causes different results, it sounds like a computer arithmetic problem that varies depending on the exact values encountered (not that this observation gives you a clue what to do about it πŸ˜„.

                          One trick I've had work in some situations is to nest everything one extra level deep in a Group, do the work, and then explode that temporary Group when completed. This seems to trigger another round of geometry cleanup which may repair the flaws.

                          I have set the precision to the max and that doesn't solve the problem. I have undone and redone with different results. I thought about the multi-level group and created three levels worth that may have lessened but didn't eliminate the problem.

                          There definitely seems to be a problem somewhere in the way sketchup integrates the edges created by the intersect into the model.


                          dbm.gif

                          Nothing is worthless, it can always be used as a bad example.

                          http://sdmitch.blogspot.com/

                          1 Reply Last reply Reply Quote 0
                          • C Offline
                            CAUL
                            last edited by

                            @sdmitch said:

                            [...]Anyone else seen this

                            Yes, I've encountered this as well and have had some success with the following method. Instead of exploding the intersection edges into the face group with one explosion, the edges are distributed randomly over something like 20 groups, and these are then exploded into the face group. On complex geometry this is both faster and more robust, for some unknown reason.

                            I've added a small file and a code snippet to illustrate the principle. Select the two groups and run the script.

                            
                            mod = Sketchup.active_model # Open model
                            ent = mod.entities # All entities in model
                            sel = mod.selection # Current selection
                            
                            gs = sel.grep(Sketchup;;Group)
                            
                            #find the edge group
                            eg = gs.select{|g| g.entities.grep(Sketchup;;Face).length == 0}[0]
                            #find the face group
                            fg = gs.select{|g| g.entities.grep(Sketchup;;Face).length != 0}[0]
                            
                            #collect all edges from the edge group
                            es = eg.entities.grep(Sketchup;;Edge)
                            #compute a tranformation from the edge group into the face group
                            tr = eg.transformation * fg.transformation.inverse
                            
                            #create #no_of_groups empty groups in the face group
                            no_of_groups = 20
                            ess = [] 
                            (1..no_of_groups).each { |i| ess << fg.entities.add_group }
                            
                            #add edges more or less randomly to the groups
                            i = 0
                            es.each { |e| 
                              ess[i % no_of_groups].entities.add_line(e.start.position.transform(tr), e.end.position.transform(tr)) 
                              i += 1
                            }
                            
                            #explode all groups
                            ess.each { |g| g.explode }
                            
                            #delete the edge group
                            eg.erase!
                            
                            

                            IntersectionTest.skp

                            1 Reply Last reply Reply Quote 0
                            • sdmitchS Offline
                              sdmitch
                              last edited by

                              Thanks Caul for your input. Although I wasn't able to use your model since I'm stuck in 2014, I was able to use the code in a model of my own. Even using your technique, the number of groups created is critical. In my tests, 20 groups gave desired results but, when I reduced the number to 10, I got the same results that I had been getting with multiple faces combined into one.

                              Nothing is worthless, it can always be used as a bad example.

                              http://sdmitch.blogspot.com/

                              1 Reply Last reply Reply Quote 0
                              • C Offline
                                CAUL
                                last edited by

                                @sdmitch said:

                                Thanks Caul for your input. Although I wasn't able to use your model since I'm stuck in 2014, I was able to use the code in a model of my own. Even using your technique, the number of groups created is critical. In my tests, 20 groups gave desired results but, when I reduced the number to 10, I got the same results that I had been getting with multiple faces combined into one.

                                After toying around with this a little bit on very complex grids I think that the most robust approach is to use only two sub groups. One with horizontal edges and the other with vertical edges. This seems to solve almost all cases...


                                sk8

                                1 Reply Last reply Reply Quote 0
                                • sdmitchS Offline
                                  sdmitch
                                  last edited by

                                  Perhaps but then you have the added burden of figuring out what is horizontal and what is vertical. Creating a group for each edge seems to work every time and does so fairly quickly.

                                  Nothing is worthless, it can always be used as a bad example.

                                  http://sdmitch.blogspot.com/

                                  1 Reply Last reply Reply Quote 0
                                  • sdmitchS Offline
                                    sdmitch
                                    last edited by

                                    @tig said:

                                    If you are likely to get faces with 'twisted vertices', e.g. forming 'bow-ties' or in your case worse...
                                    Then I suggests the following...
                                    Collect the vertices' points into an array.
                                    Get a face normal vector from one of the faces - vec=face.normal
                                    Add a temporary group into those faces' context.
                                    Iterate the collected vertices' points.
                                    For each point, add short 'vertical' edge to the temp_group.entities...
                                    Collecting the new edges as you go...
                                    Initially tedges=[]
                                    then iterating...
                                    tedges << ents.add_line(point, point.offset(vec))
                                    When done, explode the group to try and split the 'bow-tie' faces.
                                    Finally erase the tedges - testing for validity...
                                    temp_group.explode tedges.each{|e| e.erase! if e.valid? }
                                    If those faces which need to get fixed are 'coplanar', then there is no risk of the new tedges geometry clashing with some existing geometry, so the validity check is academic...
                                    πŸ˜•

                                    I had come up with a similar process to deal with the "bow ties" by finding the faces that were to big, saving the edges, deleting the face, and finally doing a .find_edges for each of the edges. This seemed to work in most cases but would obviously fail if the faces were "cell" fragments.

                                    Nothing is worthless, it can always be used as a bad example.

                                    http://sdmitch.blogspot.com/

                                    1 Reply Last reply Reply Quote 0
                                    • C Offline
                                      CAUL
                                      last edited by

                                      @sdmitch said:

                                      Perhaps but then you have the added burden of figuring out what is horizontal and what is vertical. Creating a group for each edge seems to work every time and does so fairly quickly.

                                      The trouble is that entities.add_group becomes very slow after a while. Nevertheless, I've attached my final version. It divides the edges into classes based on orientation, and these classes are then further divided into groups of max 250 edges. All examples seems to merge correctly. There is also some verification built into the code.

                                      I encountered this problem in flowify where the (extended) projection grid intersects the geometry and even though distributing the edges over many groups alliviated the problem it did not fully solve it, so I'm quite happy to have found a better way.

                                      As a general observation, intersection is really two distinct problems, the first is to find the intersection edges and the second is to merge the geometry. My biggest problem with intersect stems from the first part. A face in Sketchup does only have to be almost flat while the intersection between two faces is computed from two exactly flat mathematical planes. This means that the intersection edges may fail to merge with the not-exactly-flat face due to tolerance issues. I've found that the following procedure produces a more robust intersect, especially for complicated surfaces:

                                      1) Transform the geometry to a gigantic scale
                                      2) Check all faces by computing a plane form the vertices and then check that all vertices are on that plane. If they are not, then triangulate the face.
                                      3) Intersect


                                      Complicated grids..


                                      GridTest.rb

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

                                      Advertisement