• Login
sketchucation logo sketchucation
  • Login
⚠️ Libfredo 15.4b | Minor release with bugfixes and improvements Update

Surface Outer Loop?

Scheduled Pinned Locked Moved Developers' Forum
11 Posts 5 Posters 603 Views 5 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
    sdmitch
    last edited by 27 Jan 2013, 17:32

    A combination of Select Outer Edges http://sketchucation.com/forums/viewtopic.php?t=20274 and the edge sort routine found in FollowMe and Keep http://sketchucation.com/forums/viewtopic.php?t=16465 should do it.

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

    http://sdmitch.blogspot.com/

    1 Reply Last reply Reply Quote 0
    • D Offline
      Dan Rathbun
      last edited by 27 Jan 2013, 17:33

      IDEA: How about creating a Geom::PolygonMesh from the "surface" ?

      The Geom::PolygonMesh class can report hidden edges using a negative value, see it's
      polygons() method.

      I'm not here much anymore.

      1 Reply Last reply Reply Quote 0
      • D Offline
        Dan Rathbun
        last edited by 27 Jan 2013, 20:47

        How about posting some sample surfaces to test with ?

        Here's a shot at it.
        Assume argument surface is an array of Sketchup::Drawingelement subclass objects

          def get_surface_border(surface)
            #
            border = []
            edges  = []
            verts  = []
            #
            t1 = Time.now.to_f
            #
            for f in surface.grep(Sketchup;;Face)
              for e in f.outer_loop
                edges << e if e.faces.length == 1
              end
            end
            #
            border << edges.pop
            #
            edges.length.times do |n|
              for e in edges
                border << edges.delete(e) if e.start == border.last.end
              end
            end
            #
            for e in border
              verts << e.start unless verts.include?(e.start)
              verts << e.end unless verts.include?(e.end)
            end
            #
            t2 = Time.now.to_f
            #
            if @@debug
              if edges.empty?
                puts("All Edges added to border")
              else
                puts("Edges left over; (#{edges.length})")
                for e in edges
                  puts("#{e.inspect}")
                  puts("  start( #{e.start.position.x}, #{e.start.position.y}, #{e.start.position.z})")
                  puts("    end( #{e.end.position.x}, #{e.end.position.y}, #{e.end.position.z})")
                end
              end
              #
              puts("Elapsed Time in secs; #{t1 - t2}")
            end
            #
            return verts
            #
          end # get_surface_border()
        

        I'm not here much anymore.

        1 Reply Last reply Reply Quote 0
        • J Offline
          Jim
          last edited by 27 Jan 2013, 21:32

          File has 198 faces, but only 51 surfaces.

          I think I have the surface loops settled - just need to put the edge loop vertices in "loop" order.


          surface-test.skp

          Hi

          1 Reply Last reply Reply Quote 0
          • D Offline
            Dan Rathbun
            last edited by 27 Jan 2013, 22:31

            Never mind lines 9 thru 13, then. I could not tell what you wanted from the meager description in the OP.
            (I assumed the surface edges would bound only 1 face.)

            Something similar to lines 15 thru 26 for sorting.
            (Basically pick an edge, somehow, then find the next edge whose start vertex == the previous one's end vertex.)

            I'm not here much anymore.

            1 Reply Last reply Reply Quote 0
            • S Offline
              sdmitch
              last edited by 27 Jan 2013, 22:46

              Unless there is a Sketchup::Surface entity, which doesn't seem to be the case, it would seem to be impossible to isolate the surface from its neighbors. Also since the surfaces are not grouped, the outer_loop edges are shared with the adjacent surface/face and can not be identified using the .face.length==1.

              Dan, your code could work with one tweek. The statement, for e in f.outer_loop needs .edges added to it.

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

              http://sdmitch.blogspot.com/

              1 Reply Last reply Reply Quote 0
              • T Offline
                TIG Moderator
                last edited by 27 Jan 2013, 23:32

                It's not impossible - just very convoluted !

                Pick any face.
                Find its edges.
                Discard all edges that are not hidden/soft/smooth.
                If there are no edges left then it's a lone face.
                If there are one or more edges remaining then find the faces also using those edges - not including the already 'got' face[s]..
                These will form part of the 'surface'.
                Ripple out looking at these faces and their edges in a similar way, collecting the faces that share hidden/soft/smooth edges with them in turn - again not including any faces already 'got'.
                Eventually you'll have a collection of all faces connected to the first face by 'non-solid' edges - i.e. the faces forming a surface.
                Now you can get all of the solid-edges that these faces use.
                Of course some of these solid-edges might not be the surface's 'perimeter' [e.g. a solid edge shared by to faces that are otherwise connected through some non-solid edges and other faces] - these rogues can be discarded simply by looking to see if their faces are all within the faces-collection: all solid-edges that have a face that is not in the surface-set, OR have no other faces will form the surface's perimeter[s].
                Now go through those and find all connected edges [common vertices] - these edge-sets could be an outer and perhaps one or more 'inner loops'. To order the edge sets into a list on sequential vertices is covered in code like 'weld'... the basis is that you choose an edge in the edge-set and look at its end-vertex, then find the other edge that is in the edge-set that is also using that vertex and then get that edge's other_vertex and so on stepping around, eventually returning to the first edge's start vertex... you have by then assembled an array of ordered vertices in the loop... if you want to establish if the 'loop' of vertices is cw or ccw you'll need to do some vector magic, assembling the angles between the vectors from a set of three vertices in order and their 'cross', from that you can establish if the loop goes cw or ccw ?

                TIG

                1 Reply Last reply Reply Quote 0
                • T Offline
                  thomthom
                  last edited by 28 Jan 2013, 10:04

                  @jim said:

                  File has 198 faces, but only 51 surfaces.

                  I think I have the surface loops settled - just need to put the edge loop vertices in "loop" order.

                  Maybe you can grab something from TT_Lib2: https://bitbucket.org/thomthom/tt-library-2/src/7a54ed9e11bf31db6fd326476996fc878003402f/TT_Lib2/edges.rb?at=Version%202.7.0

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

                  1 Reply Last reply Reply Quote 0
                  • J Offline
                    Jim
                    last edited by 30 Jan 2013, 23:51

                    @thomthom said:

                    Maybe you can grab something from TT_Lib2: https://bitbucket.org/thomthom/tt-libra ... on%202.7.0

                    Thanks, Thomthom - those work great.

                    Here's the surface code, for those interested in such things.

                    
                        def self.surface_from_face(face)
                          surface = adjacent_faces(face)
                        end
                    
                        def self.adjacent_faces(face, faces_found = [])
                          faces_found << face if faces_found.empty?
                          edges = face.edges
                          edges.each do |edge|
                            if edge.soft? and edge.smooth?
                              faces_to_add = edge.faces - faces_found
                              faces_found.concat(faces_to_add)
                              faces_to_add.each{|f| adjacent_faces(f, faces_found)}
                            end
                          end
                          faces_found
                        end
                    
                        def self.all_surfaces
                          model = Sketchup.active_model
                          if model.selection.length == 0
                            all_faces = model.entities.grep(Sketchup;;Face)
                          else
                            all_faces = model.selection.grep(Sketchup;;Face)
                          end
                          surfaces = []
                          while(all_faces.size > 0)
                            surface = surface_from_face(all_faces[0])
                            surfaces << surface
                            all_faces = all_faces - surface
                          end
                          surfaces
                        end
                    
                    
                    

                    Hi

                    1 Reply Last reply Reply Quote 0
                    • T Offline
                      thomthom
                      last edited by 31 Jan 2013, 08:34

                      Here's my variant: http://sketchucation.com/forums/viewtopic.php?f=180&t=41211#p365380
                      Would be interesting to profile them.

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

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

                      Advertisement