Algorithm to trim non-solid geometry

I’m wondering if anyone knows of a ‘simple’ formula to trim geometry along two planes.

I’m thinking rather than do all the calcualtions it might be easier to draw the dormer as a square ‘shed’, and then trim it to the roof plane.

Basicly something like @Fredo6 Visuhole.

Found a few clues here:

There is nothing simple here, especially if you deal with multi-level grouping. And anyway, not a formula… You have to deal with the way Sketchup manages entities through operations, noting that the entities will change when you cut them by a plane.

In your case, you need first to make sure that you get all entities resulting from the intersection with the 2 planes. Then, it’s relatively easy to check for each one if they are between the 2 planes so that you can eliminate them.

Now reconstructing and filling the cut section is much more tricky. And there are other odysseys when you have edges right on the cut planes.

2 Likes

OK I think I’m about half way there. I figured out how to create a solid group containing the cut out area, and then using entities.intersect_with to split the faces.

Now I’m trying to use Geom.point_in_polygon2D to remove all the edges that are inside the polygon area of the cut.

Wow! Quite a few minutes per line of code!

def trim_dormer(inst, mid_point, height, depth)
  t = Time.now
  Sketchup.active_model.start_operation('Trim Dormer', true)
  ce = inst.definition.entities
  x = ce.grep(Sketchup::Edge).map { |e| [e.end.position.x, e.start.position.x].min }.min - 1
  x1 = ce.grep(Sketchup::Edge).map { |e| [e.end.position.x, e.start.position.x].max }.max + 1
  parent_ent = inst.parent.is_a?(Sketchup::ComponentInstance) ? inst.parent.definition.entities : inst.parent.entities
  g = parent_ent.add_group
  g.transformation = inst.transformation
  ge = g.entities
  points =
    [
      Geom::Point3d.new(x, depth + 1, -1),
      Geom::Point3d.new(x, -1, -1),
      Geom::Point3d.new(x, 0, 0),
      Geom::Point3d.new(x, mid_point.y, mid_point.z),
      Geom::Point3d.new(x, depth, height),
      Geom::Point3d.new(x, depth + 1, height + 1)
    ]
  f = ge.add_face(points)
  f.pushpull(0 - (x1 - x))
  ce.intersect_with(false, inst.transformation, ce, inst.transformation, false, g)
  parent_ent.erase_entities(g)
  polygon = points.map { |pt| Geom::Point3d.new(pt.y, pt.z, 0) }
  edges = ce.grep(Sketchup::Edge).select do |e|
    pt1 = e.start.position
    pt2 = e.end.position
    (Geom.point_in_polygon_2D(Geom::Point3d.new(pt1.y, pt1.z, 0), polygon, false) ||
    Geom.point_in_polygon_2D(Geom::Point3d.new(pt2.y, pt2.z, 0), polygon, false))
  end
  ce.erase_entities(edges)
  Sketchup.active_model.commit_operation
  p "#{Time.now - t} seconds to trim dormer."
end

2 Likes