Select to view content in your preferred language

CENTER LINE BETWEEN TWO POLYLINES

13534
4
Jump to solution
10-20-2015 10:59 PM
francescarusso
Regular Contributor

Does anyone know how to create a centre line between two polylines which are parallel BUT NOT at any points.

I have two cable route which are parallel but sometimes they are not as they have been modify to skip obstacles on the seabed. I need to create a center  line between these two polylines.

I do not have arcinfo.

Thanks a lot

0 Kudos
1 Solution

Accepted Solutions
FC_Basson
MVP Regular Contributor

With a bit of Python coding you should be able to do it.

To create point features from your lines' vertices without an Advanced Licence, you need to iterate the feature parts of each line and write the points to a different feature class.  There is an example how to do this here (Read polyline geometry​) and write to the new feature class with the Insert Cursor. For your situation where the vertices might be far apart, you probably need to break the line features up into equal length smaller segments - for this you can use the positionAlongLine method (find usage instructions on this page) in an iteration to determine how far along the line the point should be.

Once you have your segmented feature points for each line (in different feature classes), you can check which two points from each line points feature class are the closest to one another, take the geometric centre of them and create an array of these points to create a line feature again.

You can try this code to create the centre line points:

import arcpy

# point layers loaded in your dataframe
pnts1 = arcpy.mapping.Layer("line1_pnts")
pnts2 = arcpy.mapping.Layer("line2_pnts")

# create search cursor to iterate through first layer
scur = arcpy.SearchCursor(pnts1)
row = scur.next()

closestPnt = 0
closestPntID = 0
cenPnts = []
ctr=0

while row:   
   shp = row.shape
   geom = shp.getPart()
   print "Geom1 - " + str(row.FID) + ": " + str(geom.X) + ":" + str(geom.Y)
   mindist = 9999
   tmpdist = 9999
    # search cursor for feature in second line point layer
   scur2 = arcpy.SearchCursor(pnts2)
   row2 = scur2.next()
   geom2X = 0
   geom2Y = 0
   while row2:
      shp2 = row2.shape
      geom2 = shp2.getPart()
      # check distance between points first and second layer and find closest point
      tmpdist = shp.distanceTo(shp2)
      if tmpdist < mindist:
         mindist = tmpdist
         closestPnt = shp2
         closesPntID = row2.FID
         geom2X = geom2.X
         geom2Y = geom2.Y
      row2 = scur2.next()
   del scur2
   print "Geom2 - " + str(closesPntID) + ": " + str(closestPnt.getPart().X) + ":" + str(closestPnt.getPart().Y)   
   print "Dist: " + str(mindist)
   if shp != closestPnt:
      # calculate geometric centre of two points closest to each other
      cenX = (geom.X + geom2X) / 2
      cenY = (geom.Y + geom2Y) / 2
      midpnt = arcpy.Point(cenX, cenY)
      # create mid line point
      ptGeometry = arcpy.PointGeometry(point)
      print "Mid1 >> " + str(cenX) + ":" + str(cenY)           
      # add point to array
      cenPnts.append(midpnt)  
   row = scur.next()
   ctr += 1
del scur

# write list of points to new point feature class ("cenlinepnts" - create point feature class and load into dataframe) for centre line
inscur = arcpy.InsertCursor("cenlinepnts")
insrow = inscur.newRow()
for p in cenPnts:
   insrow.shape = p
   inscur.insertRow(insrow)
del inscur

There might be more efficient ways, but for this you don't need an Advanced licence.

View solution in original post

4 Replies
FC_Basson
MVP Regular Contributor

With a bit of Python coding you should be able to do it.

To create point features from your lines' vertices without an Advanced Licence, you need to iterate the feature parts of each line and write the points to a different feature class.  There is an example how to do this here (Read polyline geometry​) and write to the new feature class with the Insert Cursor. For your situation where the vertices might be far apart, you probably need to break the line features up into equal length smaller segments - for this you can use the positionAlongLine method (find usage instructions on this page) in an iteration to determine how far along the line the point should be.

Once you have your segmented feature points for each line (in different feature classes), you can check which two points from each line points feature class are the closest to one another, take the geometric centre of them and create an array of these points to create a line feature again.

You can try this code to create the centre line points:

import arcpy

# point layers loaded in your dataframe
pnts1 = arcpy.mapping.Layer("line1_pnts")
pnts2 = arcpy.mapping.Layer("line2_pnts")

# create search cursor to iterate through first layer
scur = arcpy.SearchCursor(pnts1)
row = scur.next()

closestPnt = 0
closestPntID = 0
cenPnts = []
ctr=0

while row:   
   shp = row.shape
   geom = shp.getPart()
   print "Geom1 - " + str(row.FID) + ": " + str(geom.X) + ":" + str(geom.Y)
   mindist = 9999
   tmpdist = 9999
    # search cursor for feature in second line point layer
   scur2 = arcpy.SearchCursor(pnts2)
   row2 = scur2.next()
   geom2X = 0
   geom2Y = 0
   while row2:
      shp2 = row2.shape
      geom2 = shp2.getPart()
      # check distance between points first and second layer and find closest point
      tmpdist = shp.distanceTo(shp2)
      if tmpdist < mindist:
         mindist = tmpdist
         closestPnt = shp2
         closesPntID = row2.FID
         geom2X = geom2.X
         geom2Y = geom2.Y
      row2 = scur2.next()
   del scur2
   print "Geom2 - " + str(closesPntID) + ": " + str(closestPnt.getPart().X) + ":" + str(closestPnt.getPart().Y)   
   print "Dist: " + str(mindist)
   if shp != closestPnt:
      # calculate geometric centre of two points closest to each other
      cenX = (geom.X + geom2X) / 2
      cenY = (geom.Y + geom2Y) / 2
      midpnt = arcpy.Point(cenX, cenY)
      # create mid line point
      ptGeometry = arcpy.PointGeometry(point)
      print "Mid1 >> " + str(cenX) + ":" + str(cenY)           
      # add point to array
      cenPnts.append(midpnt)  
   row = scur.next()
   ctr += 1
del scur

# write list of points to new point feature class ("cenlinepnts" - create point feature class and load into dataframe) for centre line
inscur = arcpy.InsertCursor("cenlinepnts")
insrow = inscur.newRow()
for p in cenPnts:
   insrow.shape = p
   inscur.insertRow(insrow)
del inscur

There might be more efficient ways, but for this you don't need an Advanced licence.

francescarusso
Regular Contributor

Thank you very much for your reply. I will have a look to this solution.

Cheers,

Francesca

0 Kudos
ChrisDonohue__GISP
MVP Alum

Another possibility is to use some of the Cartography tools, like Merge Divided Roads or Collapse Dual LInes to Centerlines:

ArcGIS Help 10.1

ArcGIS Help 10.1

One caution - I would definitely check the output closely, as I found found at times both tools to occasionally produce small areas of bizarre results for no apparent reason.  As one example, on a long curve it created a centerline that cut across one of the input curve line segments - a "shortcut" - instead of between the curved segments as expected.

Chris Donohue, GISP

francescarusso
Regular Contributor

Thank you Chris for your reply, but if I understand well this Cartography specific tool is available with the advanced licence which I do not have.

Thank you anyway.

Cheers,

Francesca

0 Kudos