Specific Edge Selection of a Group

So here is another interesting but seemingly challenging algorithm question.

I have the group below (wall cladding - dutch lap). Notice that it has a lot of 3D geometry, it is not just a texture.

In this case I am trying to hide the edges at the perimeter of the wall only.

I can easily hide all the edges given the group, using this piece of code I am currently using:

``````all_clad_edges = group_clad.entities.grep(Sketchup::Edge)
edgei.hidden = true
end
``````

I know the dimensions of the wall panel (width and height) and all of the x, y, z data so Iâ€™m thinking there should be a way to select or find just those edges along the perimeterâ€¦

I think that if you can write down a clear, precise definition of what you mean by â€śperimeterâ€ť the exercise will lead you to the required logic for your code.

1 Like

Off the top I think if I can find the four faces that define the top, bottom and two sides of the panel I can then run through all the edges and see which ones are common to any of these four faces.

Actually Iâ€™m making this problem too hard, just get the four faces and then use the edges method to gather all the edges that are bounding these four faces.

Okay, easy. Think first about the right-side edges in your images. They all will have the same `x` and `y`, but some edges differing `z` coordinates.

``````right_side_edges = all_clad_edges.select do |edge|
pt1 = edge.start.position
pt2 = edge.end.position
p1.x == x && pt1.y == y && pt2.x == x && pt2.y == y
end
``````

EDIT: hmmm â€¦ perhaps not true ? The horizontal edges have the same x and z, but different y value.

1 Like

Perhaps the face method is more robust. Although there are more than 4 faces per board.
Select the ones you want by the face normal vectors.

1 Like

Correct, there are more than four faces however there are only ever four faces that define the perimeter of the cladding: top, bottom, left and right.

I think this is the best way to go. I just need to figure out a good robust way of finding them, which actually shouldnâ€™t be too hard since I know the x,y dimensions of the panel.

So here is my first crack at a â€śrobustâ€ť algorithm.

I do know the x,y of the panel but there could be situations in the future that I do not.

1. Take the bounding box of the group, get the min and max of this bounding box.
2. Find the two vertices at these min and max positions.
3. Find the faces that use these two vertices, there should only ever be 3 faces per vertex.
4. Reject the face thatâ€™s normal is in the Y direction. (The panel is always drawn along the X axis).
5. The remaining four faces define the perimeter.
6. Use the edges method to gather all the edges for each face.
7. Add the four arrays to create one array and also eliminate redundant edges.
8. Cycle through this array and hide each edge.

This actually seems very simple, when broken down this way, am I missing anything?

Try â€¦

``````all_clad_faces = group_clad.entities.grep(Sketchup::Face)
# Hide perimeter_faces:
next unless face.normal.parallel?(X_AXIS) || face.normal.parallel?(Z_AXIS)
face.edges.each { |edge| edge.hidden= true }
end
``````

You might need to have references for the group x_axis and y_axis if not aligned to the model axis.

``````all_clad_faces = group_clad.entities.grep(Sketchup::Face)
# Hide perimeter_faces:
x_axis, y_axis = gt.xaxis, gt.yaxis
next unless face.normal.parallel?(x_axis) || face.normal.parallel?(y_axis)
face.edges.each { |edge| edge.hidden= true }
end
``````

â€¦ depends upon whether `face.normal` returns a vector per the internal group axis or not.
It also may depend upon what the current edit context (`active_path`) is.

1 Like

Does this not work?

`all_clad_vertex = group_clad.entities.grep(Sketchup::Vertex)`

This does work:

`all_clad_edges = group_clad.entities.grep(Sketchup::Edge)`

How do I get all of the vertices in a group?

P.S.
I donâ€™t see a way to do this so I will adjust accordingly.

Here is my code thus far and it seems to work for rectangular walls:

``````                all_clad_faces = group_clad.entities.grep(Sketchup::Face)

bbg = backface.bounds
bb_min = bbg.min
bb_max = bbg.max

min_x = bb_min.x.round(6)
min_z = bb_min.z.round(6)
max_x = bb_max.x.round(6)
max_z = bb_max.z.round(6)

vmin = all_clad_vertex.find{ |v| (v.position.x.round(6) == min_x) && (v.position.z.round(6) == min_z) }
vmax = all_clad_vertex.find{ |v| (v.position.x.round(6) == max_x) && (v.position.z.round(6) == max_z) }

if vmin && vmax
minfaces = vmin.faces
maxfaces = vmax.faces

minfaces.each do |face|
unless face.normal.parallel?(Y_AXIS)
face.edges.each { |edge| edge.hidden = true }
end
end

maxfaces.each do |face|
unless face.normal.parallel?(Y_AXIS)
face.edges.each { |edge| edge.hidden = true }
end
end

else
puts "Could not find min and max vertices of cladding, hidden clad lines aborted."
end
``````

Like so â€¦

``````verts = group_clad.entities.grep(Sketchup::Edge).flat_map(&:vertices).uniq
``````

ADD: It also works for faces because: `Face#vertices` exists.

1 Like

I will keep this small chunk of code for future reference. Iâ€™m surprised one cannot simply grep for the vertices though. I am still learning.

Thatâ€™s because vertices are used by geometry but arenâ€™t themselves geometry. You can get them from an entity, but there is no collection you can grep for them.

1 Like

In addition to what Steve said, think of vertices as second order properties of higher order geometry objects.

2 Likes

I donâ€™t think my algorithm is 100% bullet proof yet but it does the job for now. The trick was to grab the back face of the cladding which will always be a single face with its normal vector in the positive Y direction. Once I have that it isnâ€™t too hard to grab strategic vertices on that face along the perimeter and then find the perimeter faces themselves.

I guess I mostly solved this one myself but it certainly helped to bounce ideas back and forth. Sometimes that is all that is needed to take the blinders off and then see a novel solution that was not immediately apparent.

Once again thank-you Dan, your help is duly noted and much appreciated.

1 Like