Is there a way to find faces found in a z range?

Is there a way to make this only find the faces that have a z value between 0.5 and 90?

issue

zface = cabinet.entities.find {|ent| ent.is_a?(Sketchup::Face) &&    ent.normal == [0, 0, 1]}

main code

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

o_width= 26.0 # outer width 
o_depth= 24.25 # inner depth 

i_width= 22.0 # inner width
i_depth= 23.25 # inner depth

top_opening_width = 18.75
top_opening_depth = 0.5

bottom_opening_width = top_opening_width
bottom_opening_depth = top_opening_depth

top_height= 29 # height of top cavity
bottom_height = 60 # height of bottom cavity

top_opening_height = 26.5
bottom_opening_height = 59.5

cabinet_height = 94
def upright(face)
  if face.normal.z == -1
    face.reverse!
  end
end

pts=[0,0,0],[0,o_depth,0],[o_width,o_depth,0],[o_width,0,0]
# create substrate
cabinet = ents.add_group # add substrate group
#cabinet.name = "cabinet" # name substrate group
cabinet_face = cabinet.entities.add_face pts
upright(cabinet_face)
cabinet_face.pushpull cabinet_height


offset_x = (o_width-i_width) / 2
offset_y = (o_depth-i_depth) / 2

pts=[0,0,0],[0,i_depth,0],[i_width,i_depth,0],[i_width,0,0]
vector_bottom=Geom::Vector3d.new(offset_x,offset_y,3.5)
vector_top = Geom::Vector3d.new(offset_x,offset_y,64)

bottom_main = ents.add_group
#bottom_main.name= "bottom_main"
bottom_face = bottom_main.entities.add_face pts.map{|pt| Geom::Point3d.new(pt)+vector_bottom}
upright(bottom_face)
bottom_face.pushpull bottom_height

top_main = ents.add_group
#top_main.name= "top_main"
top_face = top_main.entities.add_face pts.map{|pt| Geom::Point3d.new(pt)+vector_top}
upright(top_face)
top_face.pushpull top_height

# small jutting peice
w = 1
d = 2.5
pts=[0,0,0],[0,d,0],[w,d,0],[w,0,0]
jut_vector = Geom::Vector3d.new(offset_x,offset_y,0)
jutting_peice = ents.add_group
jutting_face = jutting_peice.entities.add_face pts.map{|pt| Geom::Point3d.new(pt)+jut_vector}
upright(jutting_face)
jutting_face.pushpull cabinet_height

pts=[0,0,0],[0,top_opening_depth,0],[top_opening_width,top_opening_depth,0],[top_opening_width,0,0]
offset_x= 4
vector_top = Geom::Vector3d.new(offset_x,0,64)
top_opening = ents.add_group
#top_opening.name= "top_opening"
top_face2 = top_opening.entities.add_face pts.map{|pt| Geom::Point3d.new(pt)+vector_top}
upright(top_face2)
top_face2.pushpull top_opening_height

vector_bottom=Geom::Vector3d.new(offset_x,0,3.5)
bottom_opening = ents.add_group
#bottom_opening.name= "bottom_opening"
bottom_face2 = bottom_opening.entities.add_face pts.map{|pt| Geom::Point3d.new(pt)+vector_bottom}
upright(bottom_face2)
bottom_face2.pushpull bottom_opening_height

bottom = bottom_opening.union(bottom_main)
#bottom.name = "bottom"
top = top_opening.union(top_main)
#top.name = "top"
cabinet = top.subtract(cabinet)
cabinet = bottom.subtract(cabinet)
cabinet = cabinet.union(jutting_peice)
cabinet.name = "cabinet"
cabinet.material = "blue"
# find a face in the cabinet 
zface = cabinet.entities.find {|ent| ent.is_a?(Sketchup::Face) &&    ent.normal == [0, 0, 1]}

# get the points from the face.
pts = zface.vertices.uniq.map(&:position)

# add shelves
shelf = ents.add_group
shelf_face = shelf.entities.add_face pts
upright(shelf_face)
shelf_face.pushpull 0.5
new_transform = Geom::Transformation.new([0,0,12])
shelf.transformation = new_transform
shelf_copy = shelf.parent.entities.add_instance(shelf.definition, shelf.transformation)

(A small note: the .find is give only one ( the first ) face which fulfill the condition.
If you want to get array of all possible faces therefore .find_all should be used…)
.
To get faces that have a z value between 0.5 and 90, You need to
#1 find one of the vertices of face:

e.g. :

  vertex = face.vertices[0]

#2 Then you need to get this vertex position:

e.g. :

  position = vertex.position

#3 Then you need to get this point z coordinate:

(Note that the above documentation for Point3d is wrong: z = point.x >> z = point.z )
e.g. :

  value_z = position.z

Then you can make a condition about value_z…
So. e.g. the additional conditions can be something like this:

  ent.vertices[0].position.z>0.5 && ent.vertices[0].position.z<90.0 

1 Like

You might also use the #between? method.

faces = cabinet.entities.grep(Sketchup::Face)
zface = faces.find {|face| face.normal.z.between?(0.5, 90.0) }

#between? uses a comparable class’ #<=> method which the SketchUp API defines especially for the Length class to do comparisons within SketchUp’s internal tolerance. (Ie, Geom::Vector3d#z returns a Length class object.)


You also do not need to create extra literal vector arrays for the common model axes, like [0, 0, 1] because they are already defined globally as X_AXIS, Y_AXIS and Z_AXIS. (See the API doc page for the constants defined in the TopLevel Namespace.)

Also beware that because SketchUp uses floating point representation for numbers, exact comparison of values is risky. I’ve even found an example some years ago in which y=x, y==x failed because one of values had been saved out of the floating point accelerator (80-bit) into an ordinary register (64-bit) and lost trailing bits! I had quite an argument with a Microsoft engineer over whether that was a semantic failure in their compiler (my opinion) vs an acceptable floating point behavior (his opinion). That’s the reason why many SketchUp Ruby API classes have their own comparison operators that include a tolerance.

1 Like

Thanks, I figured it out with your suggestion. I was trying to grab the points from the face at the bottom and use those to make shelves.

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

o_width= 26.0 # outer width 
o_depth= 24.25 # inner depth 

i_width= 22.0 # inner width
i_depth= 23.25 # inner depth

top_opening_width = 18.75
top_opening_depth = 0.5
top_opening_height = 26.5

bottom_opening_width = top_opening_width
bottom_opening_depth = top_opening_depth
bottom_opening_height = 59.5

top_height= 29 # height of top cavity
bottom_height = 60 # height of bottom cavity

cabinet_height = 94
def upright(face)
  if face.normal.z == -1
    face.reverse!
  end
end

pts=[0,0,0],[0,o_depth,0],[o_width,o_depth,0],[o_width,0,0]
# create substrate
cabinet = ents.add_group # add substrate group
#cabinet.name = "cabinet" # name substrate group
cabinet_face = cabinet.entities.add_face pts
upright(cabinet_face)
cabinet_face.pushpull cabinet_height


offset_x = (o_width-i_width) / 2
offset_y = (o_depth-i_depth) / 2

pts=[0,0,0],[0,i_depth,0],[i_width,i_depth,0],[i_width,0,0]
vector_bottom=Geom::Vector3d.new(offset_x,offset_y,3.5)
vector_top = Geom::Vector3d.new(offset_x,offset_y,64)

bottom_main = ents.add_group
#bottom_main.name= "bottom_main"
bottom_face = bottom_main.entities.add_face pts.map{|pt| Geom::Point3d.new(pt)+vector_bottom}
upright(bottom_face)
bottom_face.pushpull bottom_height

top_main = ents.add_group
#top_main.name= "top_main"
top_face = top_main.entities.add_face pts.map{|pt| Geom::Point3d.new(pt)+vector_top}
upright(top_face)
top_face.pushpull top_height

# small jutting peice
w = 1
d = 2.5
pts=[0,0,0],[0,d,0],[w,d,0],[w,0,0]
jut_vector = Geom::Vector3d.new(offset_x,offset_y,0)
jutting_peice = ents.add_group
jutting_face = jutting_peice.entities.add_face pts.map{|pt| Geom::Point3d.new(pt)+jut_vector}
upright(jutting_face)
jutting_face.pushpull cabinet_height

pts=[0,0,0],[0,top_opening_depth,0],[top_opening_width,top_opening_depth,0],[top_opening_width,0,0]
offset_x= 4
vector_top = Geom::Vector3d.new(offset_x,0,64)
top_opening = ents.add_group
#top_opening.name= "top_opening"
top_face2 = top_opening.entities.add_face pts.map{|pt| Geom::Point3d.new(pt)+vector_top}
upright(top_face2)
top_face2.pushpull top_opening_height

vector_bottom=Geom::Vector3d.new(offset_x,0,3.5)
bottom_opening = ents.add_group
#bottom_opening.name= "bottom_opening"
bottom_face2 = bottom_opening.entities.add_face pts.map{|pt| Geom::Point3d.new(pt)+vector_bottom}
upright(bottom_face2)
bottom_face2.pushpull bottom_opening_height

bottom = bottom_opening.union(bottom_main)
#bottom.name = "bottom"
top = top_opening.union(top_main)
#top.name = "top"
cabinet = top.subtract(cabinet)
cabinet = bottom.subtract(cabinet)
cabinet = cabinet.union(jutting_peice)
cabinet.name = "cabinet"
cabinet.material = "blue"
# find a face in the cabinet 
zface = cabinet.entities.find {|ent| ent.is_a?(Sketchup::Face) &&    ent.normal == [0, 0, 1] && ent.vertices[0].position.z.between?(0.5,60)}

# get the points for the face.
pts = zface.vertices.uniq.map(&:position)

# add shelves
shelf = ents.add_group
shelf_face = shelf.entities.add_face pts
upright(shelf_face)
shelf_face.pushpull 0.5
new_transform = Geom::Transformation.new([0,0,24])
shelf.transformation = new_transform
shelf2 = shelf.parent.entities.add_instance(shelf.definition, shelf.transformation)
shelf2.transformation = Geom::Transformation.new([0,0,36])
shelf3 = shelf.parent.entities.add_instance(shelf.definition, shelf.transformation)
shelf3.transformation = Geom::Transformation.new([0,0,48])
shelf4 = shelf.parent.entities.add_instance(shelf.definition, shelf.transformation)
shelf4.transformation = Geom::Transformation.new([0,0,69.5])
shelf5 = shelf.parent.entities.add_instance(shelf.definition, shelf.transformation)
shelf5.transformation = Geom::Transformation.new([0,0,78.5])