Inputting a Polyline (extracting its vertices)

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.

I can talk over Skype - I solved this in an interesting way with my Simple DXF

2 Likes

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.

Hi Medeek,

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).

Do you have some sample model to illustrate better what we are talking about?

Here is a model of some of the polyline foundation assemblies (groups) that I will be creating and ultimately editing with this functionality:

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 ?

1 Like

I’m not quite to the edit function yet but in a couple days I will provide more information.

Here is what I have so far. I still need to run more tests in the case of close loops and checking the start point with the previous start point:

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}

		#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 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)

			pti = current_vertex.position
			pti.z = 0
  			@pts_aligned << pti
			@pointcount = @pointcount + 1
		end

	end

I understand the block of code provided by milmandre except for this one line:

current_edge = (current_vertex.edges - [current_edge])[0]

This one has me completely confounded.

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

in case it still confounds…

# current_edge  = ( current_vertex.edges   - [current_edge])  [0]
current_element =   array_of_elements      .shift           .first

clear as mud???

john

john

1 Like

Now I see it. I guess the minus sign was just throwing me there I’ve never tried that syntax before.

Thanks to everyone’s help I’ve solved the problem and Version 1.3.5 is the result:

1 Like