I’m currently working on a whole new module for the foundation plugin and I am trying to implement a polyline stemwall rather than a polygon or rectangular stemwall (outline) which requires a closed loop.
The initial draw function is fairly simple, the user consecutively picks a bunch of points which then are passed from the tool to my main draw function and the stemwall is drawn, and the points are stored in an array within the attribute library for the assembly (group). I immediately know which is the first point, which is the last point and the points will naturally be in order.
The problem will arise when the user goes to edit this polyline. My intent is to have the plugin create the edges in a temp group via the stored points and then the user can simply edit the edges and then hit the submit button once they have moved, added or deleted the edges they choose to modify.
Once they hit the submit button I somehow have to extract the points from this group of interconnected edges. It’s really not too hard to grab all of the edges in the goup or even to check to make sure that they are connected using some logic and the all_connected method in the Edge class.
My bigger question is how to best determine which two points are the end points of the polyline and also how to get the points so they are in order. This becomes particularly important when I lay out anchor bolts and other features along each segment of this polyline. I also need to come up with some logic to check to see if the user created a closed loop rather than an open polyline (start point will equal end point?).
Strangely I have not come across this specific problem before, up until now it has been single edges or closed loops of edges that I’ve had to deal with.
One thing that I realize will be impossible is determining which end point of the polyline (group of edges) should be labeled as the start or end. This is very important since it determines which side of the polyline is the interior or exterior of the stemwall. I will probably need a specific function or tool that allows the user to toggle this, and essentially re-orders the points in the reverse order.
One thought is to build in some logic that compares the two end points of the new (edited polyline) with the previous start point. Whichever point is closest to the initial start point would then become the new start point and the array of points would be ordered accordingly.
Looks like I’m trying to recreate the wheel on this one.
TIG’s Weld plugin gets right to the heart of the matter where it sorts the vertices and finds the end vertices.
However, I’m not looking to create a curve or anything out of the temp geometry, in fact I will just be deleting it once I extract the information. All I will be doing is extracting the 2D points (x,y) and then storing them in an array in the attribute library.
When reading your post that’s what it pops up in my mind. I hope it answer your question.
#Assuming you already have your edge list using your temp group
edge_set = your_temp_group_edges
#Retrieve the bound polyline vertices by counting the edge vertices occurrence
edge_vertices = edge_set.collect{|e| e.vertices}.flatten
polyline_bounds = edge_vertices.select{|v| edge_vertices.count(v) == 1}
#Initialise the starting vertex and ordered vertices list
current_vertex = polyline_bounds[0]
ordered_vertices = [current_vertex]
#Initialise the current edge value
current_edge = nil
#Jump from vertex to vertex following the edges until reaching the other polyline bound
until current_vertex == polyline_bounds[-1]
#Jump the the next edge
current_edge = (current_vertex.edges - [current_edge])[0]
#Get & store the next vertex of the polyline following the current edge
current_vertex = current_edge.other_vertex(current_vertex)
ordered_vertices << current_vertex
end
This snippet of code is a first shoot (you can surely do better) assuming that the polyline isn’t closed. If it can be, you can pick any point that will act as polyline start and end (the code need to be altered that way).
Ok Medeek, Thomas got some feeling asking you to show us what you like to do. Actually it’s not editing a polyline but geometry. Can you record a video explaining the type of modification you’d like to capture and process ?
Here is the modified code to account for the possibility of close loops:
edge_list = @Temp_outline_group.entities.grep(Sketchup::Edge)
@pts_aligned = []
@pts_aligned_db = []
@pointcount = 0
if edge_list.length == 1
# Only a single edge present
edge0 = edge_list[0]
pt0 = edge0.start.position
pt0.z = 0
@pts_aligned[0] = pt0
pt1 = edge0.end.position
pt1.z = 0
@pts_aligned[1] = pt1
@pointcount = 2
elsif edge_list.length == 0
UI.messagebox("No valid edges found, Action Aborted.")
raise
else
# Multiple edges present
#Retrieve the bound polyline vertices by counting the edge vertices occurrence
edge_vertices = edge_list.collect{|e| e.vertices}.flatten
polyline_bounds = edge_vertices.select{|v| edge_vertices.count(v) == 1}
if polyline_bounds.length == 2
# Points form single polyline
#Initialise the starting vertex and ordered vertices list
current_vertex = polyline_bounds[0]
pt0 = current_vertex.position
pt0.z = 0
@pts_aligned[0] = pt0
@pointcount = @pointcount + 1
#Initialise the current edge value
current_edge = nil
#Jump from vertex to vertex following the edges until reaching the other polyline bound
until current_vertex == polyline_bounds[-1]
#Jump to the next edge
current_edge = (current_vertex.edges - [current_edge])[0]
#Get & store the next vertex of the polyline following the current edge
current_vertex = current_edge.other_vertex(current_vertex)
pti = current_vertex.position
pti.z = 0
@pts_aligned << pti
@pointcount = @pointcount + 1
end
elsif polyline_bounds.length == 0
# Points form polygon
#Initialise the starting vertex and ordered vertices list
current_vertex = edge_vertices[0]
pt0 = current_vertex.position
pt0.z = 0
@pts_aligned[0] = pt0
@pointcount = @pointcount + 1
#Initialise the current edge value
current_edge = nil
#Jump to the next edge
current_edge = (current_vertex.edges - [current_edge])[0]
#Get & store the next vertex of the polyline following the current edge
current_vertex = current_edge.other_vertex(current_vertex)
pti = current_vertex.position
pti.z = 0
@pts_aligned << pti
@pointcount = @pointcount + 1
#Jump from vertex to vertex following the edges until reaching the other polyline bound
until current_vertex == edge_vertices[0]
#Jump to the next edge
current_edge = (current_vertex.edges - [current_edge])[0]
#Get & store the next vertex of the polyline following the current edge
current_vertex = current_edge.other_vertex(current_vertex)
pti = current_vertex.position
pti.z = 0
@pts_aligned << pti
@pointcount = @pointcount + 1
end
puts "#{@pts_aligned}"
else
UI.messagebox("Invalid number of polyline end points were found (#{polyline_bounds.length}), Action Aborted.")
raise
end
end