I haven’t tried this - I’m away from a suitable PC ATM…
It’s a clunky idea, but it might work ?
Once you have the problem_vertex and its position, collect the vertices around the loop [you have the face’s loop and its vertices are always ordered].
Break your collection when the next vertex.position == problem_vertex.position
Next you need to use those collected vertex.positions - try this - form a group [in the problem face’s parent’s entities] which contains a face using those points and explode it, it’s arrival might split the problem face.
Alternatively, delete the bow-tie face, use the collected loop of points AND the loop of the remaining points to add two faces separately.
Note that in any fix their orientation might be somewhat messed up, as the loops will get reversed in one face.
In that case remember the original problem face.normal and reverse the wayward one of new faces’ if its normal is reversed !
Yes, I agree that the brute force method has side effects. Since I don’t know the larger context of what you are attempting, I must leave it up to you to decide of this approach is usable or if TIG’s approach is a better fit.
If that fails, create a temp group with edges perpendicular from each vertex of the face. Then transform the end vertex back to the start so you have a set of zero length vertices. Then explode the temp group.
I don’t see why @ChrisDizon 's snippet works !
But it does !
At first sight it looks like it’ll move all of the face’s vertices to the origin !
The following is a simple one line version, this fixes a specified ‘face’ - which you have after checking for mangled vertices…
A Transformation created by Transformation.new(ORIGIN) will create an identity because it moves the ORIGIN to itself (your snippet implicitly invokes new, as compared to @ChrisDizon’s version which did so explicitly, but the result is the same). It would seem when done this way transform_entities forces the SketchUp engine to reconsider how the edges are assembled into loops, and that heals the bow-tie.
That initialize he uses is “Translates the origin to point.” so it’s a translation that moved zero distance.
The transformation would be the same as Geom::Transformation.new or IDENTITY.
I’m guessing that this is triggering some cleanup/merging just by the act of applying a transformation to the entities (vertices). But I’d have to step through the debugger to learn more.
Getting the vertices from the edges is probably more efficient as well, as there’s less vertex duplication.
I think I’d first collect all vertices from the edges in a Set to deduplicate them, then apply the transformation once per vertex.
And if the fix is so simple and consistent, couldn’t SketchUp’s .add_face() code run its own vertex check, and if there are any mangled vertices do the same - and apply an empty transformation to the vertices to jolt them into seeing sense, and make separate faces, rather than the bow-tie - which I imagine is never wanted [unless line splitting is set off?] !
class NonManifold
def self.auto_fix
non_manifold = Sketchup.active_model.entities.grep(Sketchup::Face).reject { |face| valid?(face) }
fix(non_manifold)
end
def self.valid?(face)
face.vertices.none? do |vrtx|
(vrtx.edges & face.edges).count > 2
end
end
def self.fix(faces)
faces.map(&:vertices).uniq.each do |v|
Sketchup.active_model.entities.transform_entities(IDENTITY, v)
end
end
end
No, it does not
Sketchup.active_model.entities.grep(Sketchup::Edge).flat_map(&:vertices).uniq.each do |v|
Sketchup.active_model.entities.transform_entities(IDENTITY, v)
end