sketchucation logo sketchucation
    • Login
    🤑 SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

    Ruby question: create faces from edges? Faces with holes?

    Scheduled Pinned Locked Moved Developers' Forum
    9 Posts 4 Posters 1.8k Views 4 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.
    • falkF Offline
      falk
      last edited by

      Hi all; can anybody explain what I'm doing wrong here? The documentation indicates that I can create a face from an array of edges, but it fails.

      Now my real question is: how do I create a face with a hole in it.

      [pre:3oekbghz]require 'sketchup.rb'

      def foo_panel
      entities = Sketchup.active_model.entities

      Create a face from points

      face = entities.add_face [[0,0,10], [20,0,10], [20,0,30], [0,0,30]]
      puts face

      Create an array of edges from points

      edges = entities.add_edges [[30,0,10], [50,0,10], [50,0,30],
      [30,0,30], [30,0,10]]
      puts edges.length

      Create a face from that array of edges -- why does this fail?

      face = entities.add_face(edges)
      puts face
      end[/pre:3oekbghz]

      1 Reply Last reply Reply Quote 0
      • Dan RathbunD Offline
        Dan Rathbun
        last edited by

        Did you verify that edges really is an array of Sketchup::Edge objects ?

        Sometimes the API dictionary errors have not been corrected.

        If the array is correct, you can convert an array to a parameter list with the ***** operator, like:
        entities.add_face( *edges )

        Also, you can use Edge#find_faces to create the faces(s) bounded by the edge arguments.

        I'm not here much anymore.

        1 Reply Last reply Reply Quote 0
        • Dan RathbunD Offline
          Dan Rathbun
          last edited by

          Also use this to be sure your acting within the current active editing context:
          entities = Sketchup.active_model.active_entities

          I'm not here much anymore.

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

            Assuming you have an array of just coplanar edges.
            Make an array of all of the entities with ents_in = edges[0].parent.entities.to_a
            Now you iterate them and use;
            edges.each{|edge| edge.find_faces }
            Next get the new faces:
            new_faces = (edges[0].parent.entities.to_a - ents_in).grep(Sketchup::Face)
            You could then look through those and assuming the outer 'doughnut' has no connected faces the face with only one loop is a 'hole' ?
            new_faces.each{|face| face.erase! unless face.loops[1] }

            If you are 'creating' the loops of edges...
            First make the faces in the hole[s] using ..add_face(some_inner_edges) [keep a reference to the face[s]], then make the doughnut face using ..add_face(some_outer_edges): then finally erase the hole's face[s].

            TIG

            1 Reply Last reply Reply Quote 0
            • falkF Offline
              falk
              last edited by

              @dan rathbun said:

              Also use this to be sure your acting within the current active editing context:
              entities = Sketchup.active_model.active_entities

              Thanks; I don't think that's the issue: the code I posted above is literally the entire ruby program and I'm executing it in an empty model.

              I'll definitely try the suggestions you made above and see what happens.

              1 Reply Last reply Reply Quote 0
              • falkF Offline
                falk
                last edited by

                Well, pretty much no joy on any of the suggestions here. Oddly enough, I found that manually retracing an edge only produced a face for certain edges. It's almost as if I was creating corrupt edges somehow.

                I dumped the edges array, and it's definitely an array of four edges, all with endpoints exactly where they should be and all definitely co-planar.

                I'm a little perplexed; this is almost the simplest possible test case for generating a face from edges. I can't imagine why it would fail. I'm also going to try creating the edges from Point3d objects and see if that makes a difference.

                FWIW, I looked through all the plugins I've downloaded for SU and none of them generate faces from edges, they all do it from points.

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

                  I see your point having now replicated your code:
                  the ..add_face(edges) fails...
                  I never use it either...

                  BUT there are ways of making a face from edges...
                  Collect the edges vertices, get a unique set and use those - vertices work as well as points in many such methods:
                  vs=[] edges.each{|e| vs << e.vertices } vs.flatten! vs.uniq! entities.add_face(vs)

                  TIG

                  1 Reply Last reply Reply Quote 0
                  • falkF Offline
                    falk
                    last edited by

                    I've replicated the problem in SU8 and SU2014 both. I think it's simply a bug in the ruby API. I suspect that nobody actually tries to create faces from edges.

                    The disturbing thing is, if I just create a square made out of edges, and retrace some of the edges by hand, I only get a face created if I retrace the last two edges. The first two don't work. It's as if the edges were corrupted somehow.

                    Anyway, I'm just going to go ahead and create faces from points. I can make a hole in the face using the technique you mentioned: create a face inside another face, then erase the inner face. It worked fine, so I'll just go with that.

                    1 Reply Last reply Reply Quote 0
                    • tt_suT Offline
                      tt_su
                      last edited by

                      The issue is that edges = entities.add_edges [[30,0,10], [50,0,10], [50,0,30], [30,0,30], [30,0,10]] doesn't weld the start and end point. Therefore there are two vertices at the same 3d point that isn't welded. add_face(edges) require the edges to form a closed loop - the edges you have in this case just looks to be closed.

                      It's unexpected, I agree, but changing the behaviour now might break existing extensions.

                      But any reason for first creating edges and then creating the face from the edges instead of just creating the face with the points directly?

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

                      Advertisement