Moving the last vertices

819
11
Jump to solution
02-03-2014 10:00 AM
DavidNarkewicz
New Contributor II
Hi All,

I have a feature class made up of lines. Each of these lines are loops. Therefore they have the same beginning and ending xy coordinates. I am looking to move the end vertices for each line a known value away to disconnect each loop. I understand that through editor I can manually change the end vertices for each loop in sketch properties but I am looking for an automated way to move the last/end vertices of each line in my feature class the same known distance.

Example: I move each line's end vertex 5 meters in the x direction and 5 meters in the y direction.

Any guidance would be greatly appreciated.

Thanks!
Tags (2)
1 Solution

Accepted Solutions
XanderBakker
Esri Esteemed Contributor
Hi David,

Try the code below on a copy of your data and see if this is what you want.

import arcpy fc = r'c:\yourFGDB.gdb\yourLines' x_shift = 5 y_shift = 5  # update cursor (be careful with this and try it on a copy of your data) fields = ["SHAPE@"] with arcpy.da.UpdateCursor(fc,fields) as curs:     for row in curs:         geom = row[0]         array = arcpy.Array()         for part in geom:             lastpnt = part[len(part) - 1]             lastpnt.X += x_shift             lastpnt.Y += y_shift             part[len(part) - 1] = lastpnt             array.add(part)         curs.updateRow([arcpy.Polyline(array)])


Kind regards,

Xander

View solution in original post

0 Kudos
11 Replies
RobertBorchert
Frequent Contributor III
If you move the end point of the line it most likely will still be a closed polyline.

You will need to manually split them to break them up.

You could also try the explode function and see if that will get you anywhere.

Here is an off approach fix.

use calculate geometry to calculate the X,Y of the end points of each line.

Then take those x,y locations and create point features from them.  BUFFER those point features into a polygon layer with a 1 inch buffer.  Select all those buffer polygons and clip the polyline layer. 

Now of you have some that are NOT closed you can calculate beginning and ending x,y and and then only create the points on those features that have identical fromx, fromy and tox toy

Sound arduous but the whole thing should take a couple of minutes.  '

I would recommend experimenting on a copy first.

Hi All,

I have a feature class made up of lines. Each of these lines are loops. Therefore they have the same beginning and ending xy coordinates. I am looking to move the end vertices for each line a known value away to disconnect each loop. I understand that through editor I can manually change the end vertices for each loop in sketch properties but I am looking for an automated way to move the last/end vertices of each line in my feature class the same known distance.

Example: I move each line's end vertice 5 meters in the x direction and 5 meters in the y direction.

Any guidance would be greatly appreciated.

Thanks!
0 Kudos
DavidNarkewicz
New Contributor II
If you move the end point of the line it most likely will still be a closed polyline.

You will need to manually split them to break them up.

You could also try the explode function and see if that will get you anywhere.

Here is an off approach fix.

use calculate geometry to calculate the X,Y of the end points of each line.

Then take those x,y locations and create point features from them.  BUFFER those point features into a polygon layer with a 1 inch buffer.  Select all those buffer polygons and clip the polyline layer. 

Now of you have some that are NOT closed you can calculate beginning and ending x,y and and then only create the points on those features that have identical fromx, fromy and tox toy

Sound arduous but the whole thing should take a couple of minutes.  '

I would recommend experimenting on a copy first.



Thank you for the reply. I think I need to be clearer in my original post. Each individual line feature creates a loop. There are numerous independent loops. I am looking for a way to basically take OBJECTID of "1" and move its end vertex 5 meters in the x direction and 5 meters in the y direction (this will change the line from a loop to a single line). Then go to OBJECTID of "2" and move its end vertex 5 meters in the x direction and 5 meters in the y direction. Then go to OBJECTID of "3", then "4", then "5" ... and so one until the end of the data-set. At the end each loop will now be a non-loop with each features end point moved the same distance.

I hope this is a little clearer.
0 Kudos
FilipKrál
Occasional Contributor III
Hi mapping_narkewicz,
Recently I replied to a somewhat similar question regarding inserting vertices into polylines. See if it gives you some idea about accessing geometries of individual features, how to disassembly them and create new polylines from them.

http://forums.arcgis.com/threads/102063-add-a-vertex-to-multiple-polylines

Or alternatively, the following tools might help you to do what you need.
arcpy.FeatureVerticesToPoints_management
arcpy.PointsToLine_management
You would also need to do some calculations to shift the relevant points, like for example in a forum here.

In any case, you may run into problems if the last before last vertex is very close to (or is identical to) the end vertex. You might want to check for that somehow.

Hope this helps,
Filip.
0 Kudos
XanderBakker
Esri Esteemed Contributor
Hi David,

Try the code below on a copy of your data and see if this is what you want.

import arcpy fc = r'c:\yourFGDB.gdb\yourLines' x_shift = 5 y_shift = 5  # update cursor (be careful with this and try it on a copy of your data) fields = ["SHAPE@"] with arcpy.da.UpdateCursor(fc,fields) as curs:     for row in curs:         geom = row[0]         array = arcpy.Array()         for part in geom:             lastpnt = part[len(part) - 1]             lastpnt.X += x_shift             lastpnt.Y += y_shift             part[len(part) - 1] = lastpnt             array.add(part)         curs.updateRow([arcpy.Polyline(array)])


Kind regards,

Xander
0 Kudos
DavidNarkewicz
New Contributor II
Hi David,

Try the code below on a copy of your data and see if this is what you want.

import arcpy
fc = r'c:\yourFGDB.gdb\yourLines'
x_shift = 5
y_shift = 5

# update cursor (be careful with this and try it on a copy of your data)
fields = ["SHAPE@"]
with arcpy.da.UpdateCursor(fc,fields) as curs:
    for row in curs:
        geom = row[0]
        array = arcpy.Array()
        for part in geom:
            lastpnt = part[len(part) - 1]
            lastpnt.X += x_shift
            lastpnt.Y += y_shift
            part[len(part) - 1] = lastpnt
            array.add(part)
        curs.updateRow([arcpy.Polyline(array)])


Kind regards,

Xander


Hi Xander,

That is great! It works perfect. Now I am wondering if I am able to tweak this code a little with your help. Instead of the shift I now have an attribute field in the polyline dataset that has the centroid for each polyline. I have put these as an "XCentroid" and "YCentroid" field which houses their own numbers as a "double". Instead of the shift I would like to replace the last point with the centroid. I tweaked your code to this.

import arcpy
fc = r'c:\yourFGDB.gdb\yourLines'

# update cursor (be careful with this and try it on a copy of your data)
fields = ["SHAPE@","XCentroid","YCentroid"]
with arcpy.da.UpdateCursor(fc,fields) as curs:
    for row in curs:
        geom = row[0]
        x_shift = row[1]
        y_shift = row[2]
        array = arcpy.Array()
        for part in geom:
            lastpnt = part[len(part) - 1]
            lastpnt.X = x_shift
            lastpnt.Y = y_shift
            part[len(part) - 1] = lastpnt
            array.add(part)
        curs.updateRow([arcpy.Polyline(array)])


I get the error: TypeError: sequence size must match size of the row

Any thoughts here?

Thank you for your help!
David
0 Kudos
XanderBakker
Esri Esteemed Contributor
Hi David,

You're nearly there...

I guess the problem is that the row you write should have the same dimensions as the row you read. I renamed the x_shift and y_shift variables to x_new and y_new for readability. I didn't test this, but if I think this could work.


import arcpy
fc = r'c:\yourFGDB.gdb\yourLines'

# update cursor (be careful with this and try it on a copy of your data)
fields = ["SHAPE@","XCentroid","YCentroid"]
with arcpy.da.UpdateCursor(fc,fields) as curs:
    for row in curs:
        geom = row[0]
        x_new = row[1]
        y_new = row[2]
        array = arcpy.Array()
        for part in geom:
            lastpnt = part[len(part) - 1]
            lastpnt.X = x_new
            lastpnt.Y = y_new
            part[len(part) - 1] = lastpnt
            array.add(part)
        curs.updateRow([arcpy.Polyline(array), x_new, y_new])


Kind regards,

Xander
0 Kudos
DavidNarkewicz
New Contributor II
I completely understand the error now. This works solution works perfect! Thank you so much Xander.

Best,
David
0 Kudos
DavidNarkewicz
New Contributor II
Hi David,

You're nearly there...

I guess the problem is that the row you write should have the same dimensions as the row you read. I renamed the x_shift and y_shift variables to x_new and y_new for readability. I didn't test this, but if I think this could work.


import arcpy
fc = r'c:\yourFGDB.gdb\yourLines'

# update cursor (be careful with this and try it on a copy of your data)
fields = ["SHAPE@","XCentroid","YCentroid"]
with arcpy.da.UpdateCursor(fc,fields) as curs:
    for row in curs:
        geom = row[0]
        x_new = row[1]
        y_new = row[2]
        array = arcpy.Array()
        for part in geom:
            lastpnt = part[len(part) - 1]
            lastpnt.X = x_new
            lastpnt.Y = y_new
            part[len(part) - 1] = lastpnt
            array.add(part)
        curs.updateRow([arcpy.Polyline(array), x_new, y_new])


Kind regards,

Xander



Hello Xander,

I am now trying to move the first vertex just like I needed for the last vertex.

I have altered the code to the following:

import arcpy
fc = r'c:\yourFGDB.gdb\yourLines'

# update cursor (be careful with this and try it on a copy of your data)
fields = ["SHAPE@","XCentroid","YCentroid"]
with arcpy.da.UpdateCursor(fc,fields) as curs:
    for row in curs:
        geom = row[0]
        x_new = row[1]
        y_new = row[2]
        array = arcpy.Array()
        for part in geom:
            firstpnt = part[len(part) + 0]
            firstpnt.X = x_new
            firstpnt.Y = y_new
            part[len(part) - 1] = firstpnt
            array.add(part)
        curs.updateRow([arcpy.Polyline(array), x_new, y_new])



How do you queue the first vertex? My assumption of "firstpnt = part[len(part) + 0]" is wrong.

Thank you!

David
0 Kudos
IanMurray
Frequent Contributor
firstpnt = part[len(part) + 0]

needs to be firstpnt = part[0]

that will get the first value.  prior he was doing len(part) - 1 to get the last one since python lists are 0 indexed, so it took the total number of entries( imagine 755 points the first with index 0, so the last would be index 754 and 755 - 1 = 754.)
0 Kudos