# Why am I inconsistently getting my outer faces going the right direction

I’m not really understanding why sometimes the faces are correct like picture 1 and sometimes they are not correct like picture 2.

# code

``````SKETCHUP_CONSOLE.clear
Sketchup.file_new

# Default code, use or delete...
mod = Sketchup.active_model # Open model
ent = mod.entities # All entities in model
sel = mod.selection # Current selection

face.reverse! unless face.normal.z == 1
e1_dir = edges_to_follow[0].line[1]

min_v = [0,0,0]
d = 1
z = 1
o = 0

cut_vector = [-d,d,-z-o]
up_vector = [d,d,z-o]
down_vector = [d,d,-z-o]
trim_vector = [-d,d,z-o]
p " e1 direction = #{e1_dir}"
trimmer_pts = [ min_v.offset(cut_vector),min_v.offset(trim_vector),min_v.offset(up_vector),min_v.offset(down_vector)]

p " trim_face direction = #{trim_face.normal}"
trim_face.reverse! unless trim_face.normal.samedirection?(e1_dir)
p " trim_face direction = #{trim_face.normal}"
trim_face.followme edges_to_follow

pts = [ min_v.offset(cut_vector),min_v.offset(down_vector),min_v.offset(up_vector)]

p " cut direction = #{cut.normal}"
# make cut face follow edges
cut.reverse! unless cut.normal.samedirection?(e1_dir)
p " cut direction = #{cut.normal}"

cut.followme edges_to_follow
``````

The winding order of vertices matter.

Also the ground plane may have special behavior. It is expected that faces drawn on the ground plane will be pushpulled upward, so these faces are made to originally have their normal facing downwards so that the face will be facing outward in the resultant 3d solid.

The winding order of the vertices for the face being used for followme or the ones for the bottom face making up the edges that I am following?

Perhaps better as …

``````face.reverse! unless face.normal == Z_AXIS
``````

If you wanted to test facing downwards …

``````face.reverse! unless face.normal == Z_AXIS.reverse
``````

If you look at the API doc for the Toplevel namespace you’ll see the API defines
`X_AXIS`, `Y_AXIS`, `Z_AXIS` (vectors), `ORIGIN` (Point3d) and `IDENTITY` (Transformation)
that we can use in our code. (Just don’t change any of them as everyone uses them.)

I mean that the direction of the normal (facing direction) will depend upon the order that you give when creating faces.

And that you should beware of the ground plane, because in some situations SketchUp will automatically reverse the face so it faces downward.

I see what you are saying. But I am still getting the issue where the face that I am using for followme produces an inside out solid inconsistently.

With respect to followme, it may depend upon how the winding order / normal direction of the face relates to the follow path.

Think of the first part of follow path as a directional vector.
You’d want the face that follows the path to be facing in the opposite direction (I believe.)

Does it change spontaneously? I thought it depended upon the input for entities.add_face. If I input the face points the same every time shouldn’t it produce a consistent set of vertices.

I doubt it.

See TIG’s words here …

I would seek to be consistent.

But whenever you create something, check it’s validity. That it was actually created.
Many API factory methods will return false and create nothing if there is an error.

Regardless of how and where in 3D you create the face, with regard to followme
ensure that:

• the face is perpendicular to the path
• the face normal is pointing in the opposite direction than the followme path vector

EDIT

• the face is positioned at the beginning of the follow path
The face actually doesn’t need to be touching or “on” the path.
But it may be best if the beginning of the path and the face are on the same plane.
If not, the followme will move the face to the plane where the path begins.

I’ve found that by doing that you sometimes create a new edge that nulls out part of the edges being followed.

# Relevant code

``````# Default code, use or delete...
mod = Sketchup.active_model # Open model
ent = mod.entities # All entities in model
sel = mod.selection # Current selection

face.reverse! unless face.normal.z == 1
e1_dir = edges_to_follow[0].line[1]

min_v = [0,0,0]
d = 1
z = 1

cut_vector = [-d,0,0]
up_vector = [d,0,2*z]
down_vector = [d,0,0]

p " e1 direction = #{e1_dir}"

pts = [ min_v.offset(cut_vector),min_v.offset(down_vector),min_v.offset(up_vector)]

p " cut direction = #{cut.normal}"
# make cut face follow edges
cut.reverse! if cut.normal.samedirection?(e1_dir)
p " cut direction = #{cut.normal}"

cut.followme edges_to_follow
``````

The face#edges method gives you the edges in random order.

The
face#outer_loop
with
loop#edges
Get an array of the edges that define the loop in an ordered sequence.

``````edges_to_follow = face.outer_loop.edges
e1_dir = edges_to_follow[0].line[1]
``````

Then you will get more consequent consistent result.

1 Like

… yes and consistent also.

@cwatts, I posted a link above where TIG shows using the `#outer_loop` method and explains the winding order.

1 Like

Yeah, thanks for that. I noticed however, it still does the flipping back and forth between correct and incorrect even with the outer_loop.edges.

# code

``````# Default code, use or delete...
mod = Sketchup.active_model # Open model
ent = mod.entities # All entities in model
sel = mod.selection # Current selection

face.reverse! unless face.normal.z == 1
e1_dir = edges_to_follow[0].line[1]

min_v = [0,0,0]
d = 1
z = 1

cut_vector = [-d,0,0]
up_vector = [d,0,z]
down_vector = [d,0,0]

p " e1 direction = #{e1_dir}"

pts = [ min_v.offset(cut_vector),min_v.offset(down_vector),min_v.offset(up_vector)]

p " cut direction = #{cut.normal}"
# make cut face follow edges
cut.reverse! if cut.normal.samedirection?(e1_dir)
p " cut direction = #{cut.normal}"

cut.followme edges_to_follow
``````

Edit was to change unless to if in cut.reverse! if cut.normal.samedirection?(e1_dir)

I guess when you crate the cut face, it’s bottom edge is overlapping and split the edge of the base face, and destroy the loop. This is preventing the followme to run through on the full path too.

Try with this: move the cut face in direction of y a little

``````cut_vector = [-d,1,0]
up_vector = [d,1,z]
down_vector = [d,1,0]
``````

Yeah shifting the base fixes that issue (Problem for me is that I collect the followme edges in my big program before I create the cut) but the problem of the faces being inside out still persists. I’m trying to figure it out still but not having a ton of luck.

Okay this example works …

``````def doit
mod = Sketchup.active_model # model reference
#
###
#
ent = mod.entities # All entities in model
#sel = mod.selection # Current selection

face.reverse! unless face.normal.z == 1
pts = [[-1,-1,-1], [-1,12,-1], [12,12,-1], [12,-1,-1]]

e1_dir = edges_to_follow[0].line[1]

min_v = [0,0,0]
d = 1
z = 1

cut_vector = [-d,0,0]
up_vector = [d,0,z]
down_vector = [d,0,0]

p " e1 direction = #{e1_dir}"

#pts = [ min_v.offset(cut_vector),min_v.offset(down_vector),min_v.offset(up_vector)]
pts = [ [-1,-1,0], [1,1,0], [1,1,1] ]

p " cut direction = #{cut.normal}"
# make cut face follow edges
cut.reverse! if cut.normal.samedirection?(e1_dir)
p " cut direction = #{cut.normal}"

cut.followme edges_to_follow

group.entities.erase_entities(edges_to_follow)
#
###
#
mod.commit_operation
#
end
``````

The lesson is that when we use a loose collection of edges, the final vertex is not merged, so followme doesn’t work well.

So instead create a followme face (which merges the beginning and end vertices, and specifically use that face’s `outer_loop.edges` array, which is returned in the correct order.

Also the follow path apparently needs to be the same size as that which the outermost vertex of the cut face will sweep. This bevels the final result at the start and end of the follow loop.

Lastly cleanup the followme face by deleting it’s edges.

This is part of a larger program I am making. Does this mean that I shouldn’t use vectors? It seems like this solution works for this case but it isn’t translating correctly for some reason to my full program.
I will release it at some point soon (planning on it being open source, need to get rid of ip).

You need to be more specific with this question. Use vectors for what ?
(And FTR, I don’t think I said anywhere above not to use vectors, … specifically or generally.)

Oh, … I see why you asked this. I commented out the line where you offset a point (that equals the predefined `ORIGIN`,) with 3 arrays acting as vectors.