Hello, SketchUp Community. I’m beginner to SketchUp and Ruby, and I need your help, please:)
I’ve got groups which represents some template roof tiles, in future I need to replace them with others. So, I wrote a function which determine the bottom face of a tile, and I need to check if that bottom tile’s face is situated on external face, if so, I need to erase it.
This is how it now looks:
vertices = external_face.vertices
face_pts = []
vertices.each {|v|
tmp = [(v.position.x).round, (v.position.y).round, (v.position.z).round]
face_pts.push(tmp)
}
new_group_array.each {|tile|
#RETURNS BOTTOM FACE OF TILE
bottom_face = find_tiles_bottom_face(tile, pushpull_var)
points = []
edges = bottom_face.edges
edges.each {|edge|
temp = [(edge.start.position.x).round, (edge.start.position.y).round, (edge.start.position.z).round]
points.push(temp)}
}
#WANT TO DELETE TILE IF IT'S BOTTOM FACE IS ON EXTERNAL FACE
face_pts.all? {|pt| points.any?{|mp|
if mp == pt
tile.erase!
end
}
external_face.erase!
}
I saw that maybe because I was working with mm, bottom face of tiles is not situated exactly on the level of external face, because of that I rounded values, but it did not help me to see if some tiles a located on external face. I think maybe of some method to check if a specific face is situated above a face, and if that face is external face, I need to erase entire tile.
I also posted .skp file, if that helps.
Thank you much in advance for your help!!! example1.skp (1.6 MB)
Thank you for your answer. I tried this method to check which bottom faces is on external face, but I got just that at least 2 vertices of bottom faces are “PointOnVertex” with external face, and another vertices are “PointNotOnPlane”, and that result are for all tiles from external face, and for most of tiles not from external face
I had something like that:
new_group_array.each {|tile|
#RETURNS BOTTOM FACE OF TILE
bottom_face = find_tiles_bottom_face(tile, pushpull_var)
vertices = bottom_face.vertices
vertices_count = 0
vertices.each {|pt|
result = external_face.classify_point(pt.position)
if result != Sketchup::Face::PointNotOnPlane
vertices_count += 1
end}
p vertices_count
}
So, I though the problem is that bottom faces are not on exact the same Z level, so I brute force to down value of Z bottom_faces until I don’t find a face, if I find a face, so it is situated on external face.
def determine_if_in_area_z_is_given_face(face, points)
for i in 0..1000
p "iteration: #{i}"
p "points: #{points}"
result = face.classify_point(points)
if result == Sketchup::Face::PointInside || result == Sketchup::Face::PointOnEdge
p result
p points
return true
end
points[2] -= 0.0001 #represent value of Z
end
return false
end
tiles_to_delete = []
new_group_array.each {|tile|
#RETURNS BOTTOM FACE OF TILE
bottom_face = find_tiles_bottom_face(tile, pushpull_var)
vertices = bottom_face.vertices
result = -1
result = determine_if_in_area_z_is_given_face(external_face, vertices[0].position)
if result
tiles_to_delete.push(tile)
end}
}
tiles_to_delete.each {|e| e.erase!}
And it really founds at some point, not so far, usually after 40 iterations, that it somehow intersects with external face, but that result are also for tiles who do not have under it external face. So, the result was not that I was expecting.
I’m thinking the solution could be a method, which find if lower of a face, is situated a face. But I don’t know what could be done for that.
Thanks for you reply!
I don’t understand exactly what to do with planes from each face. I tested and saw that all faces from external face, and most of faces from center will have the same plane, and most of faces which are situated on the edges will have another values for plane.
I haven’t been following carefully enough to be clear what your goal is. Comparing the planes obtained from various faces will tell you if those faces are (duh!) co-planar.
This is an interesting subtopic for a coding challenge. SketchUp doesn’t actually have a plane class. Instead it returns an array of the coefficients of the plane equation (Ax + By + Cz + D = 0)
There’s an interesting issue that depends on what the comparison will be used for: the consequence of a small difference in the plane equation coefficients will depend on how large the planar objects being compared are.
Also, I remember that Scott rounded (or truncated) his Floats in the DC extension to 7 decimal places to eliminate floating point errors. I guess they only show up in further decimals ?
And here is a method definition snippet (based on thomthom’s) …
# Test whether the vertex positions of face1 are coplanar with face2,
# within SketchUp’s geometric tolerance.
# @param face1 [Sketchup::Face]
# @param face2 [Sketchup::Face]
# @return [Boolean] True if the two face arguments are coplanar.
def coplanar_faces?(face1, face2)
face1.vertices.map(&:position).all? { |point|
point.on_plane?(face2.plane)
}
end
EDIT: Also note that Thomas previously posted another example from one of his GitHub repos: