Is there something in the APIs that can find the face on which a non-loop edge was drawn or that it is now contained by? Having searched the APIs and forum pretty extensively, I’m pretty sure the answer is “No,” so I guess I’m looking for some confirmation that I do indeed need to do this kind of face search iteratively myself. Again, it is not a loop edge so it does not appear in all_connected or edges.
I have some script code that draws rounded-end slots on faces based on a pre-selection of one or more edges and the single face on which they lie. What I would like to do is eliminate the need to select the face and instead, determine the face without having to iterate through all the face entities in or below the current context. In a tool where I can explicitly click the rounded-end centers and draw slots one-by-one, I have the PickHelper to determine orientation, but I’m also doing this with existing geometry for larger arrays of slots.
I already do some culling in my code to make sure selected edges actually lie on the selected face using constrain_point, and I alternately cull and draw on a parallel XY plane if no face is selected and the edges lie parallel to the XY plane. So walking faces and doing tests will solve my problem, but I want to code defensively and avoid that oh-no moment when I’m working at the root context and forget that there’s a lot of geometry like an ungrouped mesh in the same context. For now, I think I just need to throw a caution dialog for an unreasonably large number of grep’d faces.
It is hard to really understand your needs without examples or screenshot, but I assume you cant avoid iterations.
One example snippet comes into my mind,
# Returns nil (interpreted false in caller) if no edge find lies on face,
# or the first edge object (interpreted true in caller) lies on a face
def edge_on_face(face, edges)
edges.find{|e|
face.classify_point(e.start.position) == Sketchup::Face::PointInside &&
face.classify_point(e.end.position) == Sketchup::Face::PointInside
}
end
# Parameter: context, default to active context
# Returns Array of Sketchup::Face or []
def faces_with_non_loop_edges(ents = Sketchup.active_model.active_entities)
#find all orphan edges, this includes that nom loop edges inside a face
edges = ents.grep(Sketchup::Edge).select{|e| e.faces.empty?}
# returns empty Array (of faces) since no orphan edges that can lies on
return [] if edges.empty?
# select faces that at least one edge on it
ents.grep(Sketchup::Face).select{|face| edge_on_face(face, edges)}
end
#usage, call the method
faces = faces_with_non_loop_edges
SketchUp Ruby API references:
The #faces method is used to retrieve all of the faces common to the edge.
The #classify_point method is used to determine if a given Point3d is on the referenced Face.
I’m currently doing something similar to your suggestion with my pre-selected face to cull any non-co-planar edges, but rather with a slightly dumber variant which allows endpoints that fall anywhere on the face’s plane. I currently create my slots as grouped objects, so it’s just a get-it-onto-the-correct-plane methodology at the moment with no worry about face containment or intersections with any other entities.
Here’s a snippet that conveys what I’m trying to gather:
def self.matched_edges_and_faces
mod = Sketchup.active_model
sel = mod.selection
ents = mod.active_entities
edges = sel.grep(Sketchup::Edge).select{|e| e.faces.empty?}
faces = ents.grep(Sketchup::Face)
matched = []
# edge can only lie on one face, but a face can contain many edges
while !edges.empty?
face = faces.shift
contained = edges.select{|e| (face.classify_point(e.start.position) == Sketchup::Face::PointInside && face.classify_point(e.end.position) == Sketchup::Face::PointInside)}
if !contained.empty?
matched.push([face,contained])
edges -= contained
end
end
matched
end
This gives me a face for each edge which I can then use to then generate new geometry that is properly oriented to the face(s). In my case, I’m drawing a slot like you would route into sheet material on a CNC. Oddly, I’ve never found a plugin tool to draw slots which I have to visually mock-up fairly often, then program the CNC to route along the centerline.