Erase faces created after intersect_with



hello everyone,
i used intersect_with on a model to create the intersections between 2 faces or more, but now i need to delete the extra faces created after the intersection to get a clean roof.
i tried to get the faces array before and after intersection, make the difference between them and get the new faces created, but instead of the deleting the faces i want it erases the faces below them, as in the picture below, instead of having the A model as a result i get the B model.
how can i return the new faces above to get the A model as a result ?
that’s the code i used:

model = Sketchup.active_model
entities = model.entities
fc=entities.grep(Sketchup::Face).to_a #get all faces before intersection

                     recurse = false 
                     hidden = true
                        IDENTITY, # Transformation for the calling Sketchup::Entities
                        model.entities, # parent (target) Sketchup::Entities
                        IDENTITY, # parent (target) transform
                        model.entities.to_a # Entities to intersect the calling Sketchup::Entities with
 fc2=entities.grep(Sketchup::Face).to_a     #get all faces after intersection
fc.each do |del|
    fc2.delete_at(fc2.index(del).to_i) #delete the faces before intersection from the faces arry after intersection to get the new faces ceated
UI.messagebox("fc2 length #{fc2.size}") 
entities.erase_entities (fc2) #delete the ne faces created

roof intersection.skp (257.8 KB)


I am not where I can check this, but I suspect the bug is that you are assuming that the faces you found before the intersection will be the portions below the ridge after the intersection. Your image B plainly shows this isn’t what is happening. During operations that intersect faces (Including situations where you just add another face that overlaps an existing one) SketchUp makes no promise that it will retain the pre-existing faces or use them for a particular part of the after-intersection geometry. You need a better test, e.g. in your specific example, which faces are higher in z.


yes i tried the which face has higher z but it doesn’t work in cases like the image below, i managed to get the edges added after intersection how can i using this edge get the faces that i need to delete ?
i need to delete the faces A B and C and i managed to get the two edges with the red lines in the picture.


That geometry is more complicated than your first post and will need a more complicated test. I’m not where I can do anything just now, but unless someone else solves it I’ll get back later.


oky thank you so much yes i’ve been working on it for the past 2 days and i can’t seem to find a solution for more complicated models if you or anyone could help it will be great.
thnx again


At the risk of ‘boiling our cabbages twice’…
In a parallel thread I told you to look at my Roof.rb code…
Around lines in the late 400s and 500s there is some code that might help…
But the way you are initially making your faces is not helping you later on…
It is not a simple task to trap for all permutations of a set of intersecting roof planes, and erase just those that are easy to see as being ‘unwanted’…

But consider how you know what’s to go, and try and write some code to mimic that…

Group your new geometry so you only need to intersect and search in the group’s entities…

After the intersection, any face that is wholly above the Z level you sprang the origin faces from is probably one to be erased [C in screenshot copy, ‘blue’ X] - then you search for edges with no faces and erase those…
Any face that is at the Z level but has a horizontal edge at the same level as the original face [like A, ‘red’ X] is also a candidate for erasure…
If you have been keeping a collection of ‘upper’ horizontal edges used by the original faces - start/end positions and also lines/vectors etc then you can also spot others needing erasing like B - ‘magenta’ X.
You can delete an edge and its face goes - then delete other unfaced edges that result, or first delete the face and then the unfaced edges that result…


thank you for your answer, yes i tried the test on the z value but it doesn’t work in some complex cases, what i’m trying to do now is find the center of each edge created after intersection (ones with red line on them) and get the center of each face and use > pt1.vector_to( pt2) between the center of the edge and the center of the face and then delete the face that led to a vector pt1,pt2 with a positive z coordinate.
i’m about to test it and see if it works.


The horizontal top edge of every face plane you add has a unique ‘line’ - face.line - which is an array of a point and a vector.
If you collect those in an array as you add the faces you have a useful crib.
Then intersect all.
There will be faces with a top horizontal edges that have a ‘line’ equivalent to one the remembered array [lines].
Collect all edges in the context.

    if edge.start.position.on_line?(line) && (edge.line[1]==line[1] || edge.line[1]==line[1].reverse)

Then recollect the remaining edges and erase unfaced ones

edges.each{|edge| edge.erase! unless edge.faces[0] }

This should get you some way towards a solution ?


i’ll try your idea and get back to you with the result, as the vector between the intersection line and the face center caused a problem with finding the center of a face


Hi, i know this is an old post, but i am facing a similar situation, i managed to create my geometry, make a plane, intersect that plane with my geometry, now how can i erase the initial plane, and the faces after the plane, i tried bounding the group and erase everything thats not in bound but the bound includes everything, now i got 3 faces meaning i have 3 outerloops? can i choose 2 of those en erase? any ideas? thank youMetal Roof.rb (7.4 KB)


You erase the cutting plane by saving its identity when it is created,@cp = ent.add_face(pts),
then erasing its’ edges which will erase the face as well, entities.erase_entities(@cp.edges).

The ‘extra’ face is created because your code creating the side_edges starts with the -1,0 indexes which means the first and last points are paired. Adding next if j==0 fixes this problem.

Erase the part “beyond” the cutting plane by comparing the cutting planes x coordinate with the edges and erasing it if is greater.


I took a completely different approach and eliminated the need for a ‘cutting plane’…

by adding c_points to an empty group you can use the group bounds…

while group.bounds.width <= base
  # some conditionals... then

those point are then the basis of ones taken forward to…

if group.bounds.width != base.to_l
   pt_lst = gents.to_a.last.position.to_a
   pt     = [base, pt_lst[1], pt_lst[2]]

I also generated a sine wave, so I could try different LOD [levels of detail] i.e. number of segments…

the top is actually less the @nicolas.pojmaevich’s 26, but even 4 [the lowest panel] looks ok…

although they are all exactly base width, my code for clipping sometime produces a fold???

this happens with some combinations of corrugation pitch and number of segments…
I can’t fathom why…

I’ll PM the code if anyone wants to play, but it needs a new topic to discuss further…



@john_drivenupthewall, it seems the machine beat you on this one, what if you add a temp line to the bottom points? that line intersect with the wave an cuts it giving you that exact final point, you’ll need an extra element thou…and clean up…

@sdmitch, can you share the code? i wanna see it, im learning over here…


for now, xmas is long…

I sorted out the sine wave, to better match yours, but then I broke something else…



broke away john…:slight_smile:, im learning html over here… they dont recommend tables for html layout, instead header/section/footer…ok