Programmatically creating Geometry problems

This is my first post in this jolly nice forum, so I’ll get right to it. I have a particularly weird problem while generating geometry from a set of vertices that generate edges which in turn create faces. I am pretty sure that the points and geometry are correct math wise, but I cannot seem to figure out why Sketchup fails to create a face where I want it to.

Talk is cheap, so here is a scene that has an empty face, which is the one that fails to be created. Load the file and then open the Ruby console and type in the following:

# points for face
points = [
[5.65553, 11.15667, 0.0], [5.65553, 6.15667, 0.0], [5.65553, 6.15667, 2.7], 
[5.65553, 11.15667, 2.7], [5.65553, 11.15667, 0.0], [5.65553, 10.33172, 0.87517], 
[5.65553, 10.33172, 2.09517], [5.65553, 7.18172, 2.09517], [5.65553, 7.18172, 0.87517], 
[5.65553, 10.33172, 0.87517]]
# press enter and then type this
f = Sketchup.active_model.active_entities.add_face(points)
# then if you try to find the area of the face, to see if it was created OK
f.area
Error: #<NoMethodError: undefined method `area' for nil:NilClass>
<main>:in `<main>'
SketchUp:1:in `eval'

Now I am really baffled as to why this happens, searched the web and found nothing concrete and most obvious problems (like axis misalignment and so on is not present). Additionally, the funny thing is that if I move the geometry back a bit and type the above command it actually completes and shows the face fine… you can view this in this file.

Anyone has any clue on what’s going on? I am not a really good Sketchup user so I might missing something really obvious here…

Edit: Clarified the language a bit as well as bolded the links.

Because points is not the same variable as pts. Use the same variable name.

And welcome to the forums.

Oh, that was a typo; my bad! Regardless try that using points. You’ll see that I mean.

Yes, I see this:

points = [
[5.65553, 11.15667, 0.0], [5.65553, 6.15667, 0.0], [5.65553, 6.15667, 2.7], 
[5.65553, 11.15667, 2.7], [5.65553, 11.15667, 0.0], [5.65553, 10.33172, 0.87517], 
[5.65553, 10.33172, 2.09517], [5.65553, 7.18172, 2.09517], [5.65553, 7.18172, 0.87517], 
[5.65553, 10.33172, 0.87517]]
# press enter and then type this
f = Sketchup.active_model.active_entities.add_face(points)
p f
# then if you try to find the area of the face, to see if it was created OK
p f.area

You must have missed the part which I linked a file (this one), which you have to load before executing the script. Then you will see that I mean.

Ah yes it does fail with the existing geometry. Unsure why at this time, but I’m still looking into it.

That’s no problem! Thanks for the effort… clarified the language in the original post as well so that it’s more clear that you have to first download and load the linked file before executing the script! Let me know if you have any ideas as to why this happens!

Cheers!

So what is the final outcome of the code? What are you trying to do specifically because there may be better ways of accomplishing the goal. Typically, you want to draw using Ruby the same order as you would draw using the mouse because the same rules apply.

Wouldn’t you draw the outside loop before creating the inner loop? Perhaps it “shouldn’t” matter, but sometimes it does in SketchUp.

I am just drawing face by face, nothing else. Mathwise as I said, geometry is fine; it’s just sketchup refusing to draw some faces and an example of that problem is shown in the files. I cannot be anymore specific than this I am afraid.

It looks like you are trying to draw two faces … one within the other … but you are using one continuous set of 10 points to do so. If you break this down into two parts, one for each face, then I think you will have more luck.

pts1 = [[5.65553, 11.15667, 0.0],[5.65553, 6.15667, 0.0],[5.65553, 6.15667, 2.7],[5.65553, 11.15667, 2.7],[5.65553, 11.15667, 0.0]]
pts2 = [[5.65553, 10.33172, 0.87517],[5.65553, 10.33172, 2.09517],[5.65553, 7.18172, 2.09517],[5.65553, 7.18172, 0.87517],[5.65553, 10.33172, 0.87517]]
f1 = Sketchup.active_model.active_entities.add_face(pts1)
f2 = Sketchup.active_model.active_entities.add_face(pts2)

Doing it this way also allows you to delete the second face (if desired) using:

f2.erase!

(Moved to the Developers > Ruby API category. Removed “extension” and “extensions” tags, as this is just discussing creating faces not extensions.)


Better ways to test a reference if it is a face (instead of causing an exception):

if !f.nil?
if f != nil
if f.is_a?(Sketchup::Face)
if f.respond_to?(:area)

…or, because in Ruby, nil and false are the only objects that evaluate as FALSE:

if f

(Ie, if the reference is pointing at any other object, even an empty string or an empty array, it will evaluate as TRUE.)

1 Like

@DanRathbun, I know all these constructs already, I just put up a quick and dirty example to show the problem.

@jimhami42 Interesting, do you happen to know of there is a way to checking (and in turn finding) these two faces from a given number of vertices?

Are you not creating the faces? Then you get the reference to each face.

@thomthom, @jimhami42 I mean, from the initial array of points how and where to know where to split (in two or more faces). That’s before the face creation and if I try to create it using the initial points I get an error.

In my experience creating a face where edges intersect or merge with existing edges, creates undefined results. Sometimes the face will be reversed, or like in your case, not created at all. The only two solutions I know, are making sure you are not drawing over existing geometry, or if you can’t control that you need to draw your geometry in a group, then explode it. This keeps your geometry from merging with existing geometry until the face is created. This seems like a bug to me, because no edges are created until the add_face is executed.

I’m not sure why your initial points are the way they are. Each face should have a separate boundary. “Crossing over” from the outer outline to the inner outline is inconsistent with face definitions. If you know that there are four points (plus the original) making up the faces, then use the first five points to create the first face and the second five points to create the second face.

I’m at work and can’t access the model, so I can’t confirm my suggestion. Can’t the intersection and break up of edges be disabled with:

Sketchup.break_edges= false

API reference: http://www.sketchup.com/intl/en/developer/docs/ourdoc/sketchup#break_edges=

The description for the getter “break_edges?” includes:

Break edges is the SketchUp 7 feature that automatically splits edges that the user draws which cross over one another.

That you can do, but I believe it’s still not possible to have two identical edges at the same location without them merging. Internally I believe it goes some thing like this when you create a face:

edge1 = [pt1,p2]
edge2 = [pt2,p3]
edge3 = [pt3,p4]
edge3 merges with existing edges and becomes a deleted entity
edge4 = [pt4,p1]
the face tries to be created but an internal error screams ‘reference to deleted entity’ (or something like that)

1 Like

I’m not sure why it acts like that but this should show you what I mean.
In the first case (using the original posted model) it doesn’t work to create the face. The next two times it does even though the last time, the model appears to be identical to the original. I can verify the behavior, but I’m not sure I can give a correct explanation for it.

,

@Neil_Burkholder yes :confused:, I am really baffled as well. I’d really like if someone could shed a light why this happens so I can find a solution whenever this happens not only on this particular model…