Reverse faces problem after using followme

hello everyone,
i’m trying the followme method to create some roofs but sometimes it gives reversed faces problem, how can i detect reversed faces and correct them using ruby, i found some plugins but they kinda repeat the “reverse faces” tool in sketchup and they need a click on the face.
how can i do it for the entire model without ? which means how can i detect if a face is in the wrong orientation and reversed ?
thnx a lot


AutoSave_faces_holes.skp (103.9 KB)

if you group things , the group will have a center…

every face inside your group has a center and a face normal [direction]…

you can check if the direction from the group center to the face center is the same as the direction of the face normals…

it gets more complex than that, but for your simple examples it would work…

john

1 Like

Correctly orient the triangular face before the followme operation.

OR once you have made the sloping ‘roof’ face check its normal and reverse it if necessary…

face.reverse if face.normal.z < 0

1 Like

With one key exception, SketchUp follows the “right hand rule” based on the ordering of the points when you create a face in the Ruby API using entities.add_face. That is, if the points are ordered counterclockwise from your point of view, then you are looking toward the front of the face. The exception is that if the face is created at z==0, SketchUp will always force its normal to point to negative z regardless of the order of your points.

When the face is created or modified by operations other than entities.add_face, you might not know which way the normal ended up and will have to test.

John gave you a somewhat mathematical approach (which works so long as the figure is convex), and TIG gave you a pragmatic one for your specific situation. My practice goes along the lines TIG describes: “correct” depends on how I want the face to be oriented, and since I am creating the model in Ruby code, I know what direction that is. Usually a test such as TIG describes using the x, y, or z value of the normal is sufficient.

1 Like

thank you so much for all your answers i’ll try them. :slight_smile:

@slbaumgartner @john_drivenupthewall @TIG yes but in cases where the normal’s z coordinate equals 0 it doesn’t so how to detect that a face that has z==0 and the group is a cube so the vector from face center to group center is also has a z==0 .
how can i find if in a case like that, that the face is reversed ?
thnx a lot i’ve been stuck in that part.

If the normal’s z coordinate is 0, the normal is pointed horizontally, that is, the face is in a vertical plane. You still have to know which way in x and/or y you meant it to go and test the normal’s x or y against that.

We were talking of ‘roof planes’, which have a Z > 0 when facing up and Z < 0 when facing down.
Z = 1 is flat+up and Z = -1 is flat+down.
As has been said when Z == 0 it’s vertical.
i.e. it’s a ‘wall’ !
If you are working in a group then you can do a ‘raytest’ and see if it hits - this is fine for a simple cube but prone to errors in complex forms…
http://www.sketchup.com/intl/en/developer/docs/ourdoc/model#raytest

Here’s an example snippet:
Let’s assume the reference to the group is name ‘group’, and you iterate all faces in turn…

vec = face.normal
cen = face.bounds.center
ray = model.raytest([cen, vec])
### if it hits something and that is in the cube group then we reverse the face ?
if ray && ray[1].include?(group)
  face.reverse!
end

Of course you could always create your faces from 4 points set up in a counterclockwise direction to set the normal [i.e. the right-hand rule]- always remembering that faces made flat on the ground will ALWAYS face down irrespective of the vertices’ ordering, so IF you want them to face up check for the Z==-1 and face.bounds.center.z==0 and reverse them IF desired…

@TIG no it didn’t work for this model, it only detects 1 face a reversed one, the others no.

group=Sketchup.active_model.entities.add_group(Sketchup.active_model.entities.to_a)
group.entities.grep(Sketchup::Face).each { |face|


vec = face.normal
cen = face.bounds.center
ray = Sketchup.active_model.raytest([cen, vec])
### if it hits something and that is in the cube group then we reverse the face ?
if ray && ray[1].include?(group)
UI.messagebox("reversed")
  face.reverse!
else 
UI.messagebox("not reversed")
end

}

reversed cube.skp (99.5 KB)

Make the array of entities to add to the new group before adding the group, otherwise you are trying to group itself ?
Also grouping non-active objects this way can splat !

Consider this…

model = Sketchup.active_model
ents = model.active_entities
p group = ents.add_group(ents.to_a)
### the 'p ' is to give you the group reference in the Ruby Console.

### then look at each face in turn...

To see what’s getting returned in each ‘ray’ add p ray after it’s made…
That way at least you can inspect the results in the Ruby Console for each face…

1 Like

@TIG i tried this but the problem is in ray it returns nil for 5 times out of 6 the only time that it’s not nil it detects one reversed face correctly.

I see that too.
If you ..add_cline(cen, cen.offset(vec)) you can see where the ray is being cast, so it should hit something if it’s inward looking !!
As well as reversing the face[s] you can also use face.material='red' to show the changes face[s]…

It returns ‘nil’ if there’s no hit [should be 3 times] - BUT clearly there should be hits in those 2 cases that get missed.

A mystery indeed…
I’ll see what I can dig up…

Meanwhile, anyone else got any bright ideas ?

@TIG i added the line but it shows the 5 points outside the model.
the red faces are the one reversed i did a back material in red.

reversed cube.skp (98.6 KB)

That’s the answer !
How stupid of me not to see it before…

Because the group is going to have its internal origin that’s unlikely to be the model’s ORIGIN, then we need to transform the ‘cen’, try this:

group = Sketchup.active_model.entities.add_group(Sketchup.active_model.entities.to_a)
tr = group.transformation ### FIX
group.entities.grep(Sketchup::Face).each { |face|
    vec = face.normal
    cen = face.bounds.center.transform!(tr) ### FIX
    ray = Sketchup.active_model.raytest([cen, vec])
    ### if it hits something and that is in the cube group then we reverse the face ?
    if ray && ray[1].include?(group)
        #UI.messagebox("reversed")
        face.reverse!
        face.material = 'red'
    else 
        #UI.messagebox("not reversed")
    end
}

It works !

@TIG yeah right i didn’t think of it too, it worked like a charm thnx a lot you r great

@TIG hello i tested this method on a not manifold group and it didn’t work logic i guess, but isn’t it possible to test if the ray hits the blue boundingbox that appear when i click on the group ? even if it’s not a closed one ?

I think that manifold matters only in the sense that this test will go nuts if there are internal faces or spurious flaps on the shape. Also, it will work only for convex objects, otherwise an outward ray from a face in a “fold” may pass through other parts of the same object.

The bounding box is a graphic gimmick that has no existence in the real geometry of the model, so a raytest will never hit it. I suppose you could draw your own solid using the information from the bounding box and test that…

@slbaumgartner isn’t it possible to test if the raytest will hit a material, like giving red as a back color and start a ray from the center of the group to the center of each face and if it hits material red so the face is reversed ? is that possible ?

Model#raytest returns a two-element Array: [Point3d, path to Drawingelement hit]. The hit path is an ordered Array of the Entities that had to be opened in order to get to the Drawingelement hit by the ray. For example [Group, Face].

A Material is not a Drawingelement, so raytest will never “hit” it as such. And since raytest doesn’t give you anything except the identity of the Face it hit, to decide whether reversed or not you are back where you started!