• Login
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.
  • F Offline
    falk
    last edited by 24 Jul 2014, 05:29

    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
    • D Offline
      Dan Rathbun
      last edited by 24 Jul 2014, 09:04

      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
      • D Offline
        Dan Rathbun
        last edited by 24 Jul 2014, 09:07

        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
        • T Offline
          TIG Moderator
          last edited by 24 Jul 2014, 10:22

          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
          • F Offline
            falk
            last edited by 24 Jul 2014, 15:08

            @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
            • F Offline
              falk
              last edited by 24 Jul 2014, 15:48

              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
              • T Offline
                TIG Moderator
                last edited by 24 Jul 2014, 18:36

                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
                • F Offline
                  falk
                  last edited by 24 Jul 2014, 20:53

                  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 25 Jul 2014, 13:44

                    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
                    1 / 1
                    • First post
                      1/9
                      Last post
                    Buy SketchPlus
                    Buy SUbD
                    Buy WrapR
                    Buy eBook
                    Buy Modelur
                    Buy Vertex Tools
                    Buy SketchCuisine
                    Buy FormFonts

                    Advertisement