2

I have two lines with xy values, but no z values. However, I have points with xyz values that intersect with the two lines (see attached image for vizualisation). How can I get the z values from the points to the lines?

I have tried spatial join (join one to many), but with around 400 points for each of the two lines this just results in feature classes with around 400 20km lines with different z values. I would like the lines to be split at each point and assigned a z value, but cannot use Split Line at Point as I only have the Basic licence. I use ArcGIS 10.3.1.

enter image description here

ahmadhanb
  • 40,826
  • 5
  • 51
  • 105
Sil
  • 151
  • 1
  • 12
  • Are the original lines composed of only 2 vertices, the start and end vertex or are composed of more? I ask this as what value do you want the vertices that make up the original line (which may not coincide with your point dataset) to be? – Hornbydd Sep 19 '16 at 13:33
  • Yes, the original lines have start and end vertices in xy values, each line has only one row in its attribute table. So my wish is to have the lines divided based on each point, giving it new start and end vertices in xy values, together with a z value. – Sil Sep 19 '16 at 14:03
  • 1
    An approach to overcome the lack of license issue is to use linear referencing to create the line segments, have a look at the help file. – Hornbydd Sep 19 '16 at 14:10
  • Would multiple polylineZ segments made of points pairs suffice? – FelixIP Sep 19 '16 at 20:19
  • Hornbydd: which of the linear referencing tools do you suggest? I have looked into them all and I cannot seem to get them to create anything with any values. I will continue looking into this though. FelixP: How do I go about transforming the lines to polylineZ segments? Thanks to both of you. – Sil Sep 20 '16 at 06:58
  • I agree with @Hornbydd that linear referencing is likely to be the way to go on this. I recommend to keep experimenting with that. For your question to attract potential answerers with linear referencing skills you would be best to talk about that as an option in your question body and to tag it [tag:linear-referencing]. – PolyGeo Sep 20 '16 at 21:07
  • @Sil if you want others to hear you add @ in front of his/her name – FelixIP Sep 20 '16 at 22:11
  • Best option may be to create new lines using your xyz points as input, the output would be a small number of polylines with xyz geometry. – alphabetasoup Oct 01 '16 at 01:06

1 Answers1

1

I understand that you are Ok with 2 points segments simplification of original lines.

INPUT:

Example data

If you can get to this, using spatial join:

Tables

The script below will do the job:

Script output

Script assumes that layer called “lines3d” is empty PolylineZ layer:

import arcpy
##  input parameters
mxd = arcpy.mapping.MapDocument("CURRENT")
lines2d = arcpy.mapping.ListLayers(mxd,"LINES")[0]
points = arcpy.mapping.ListLayers(mxd,"POINTS")[0]
lines3d = arcpy.mapping.ListLayers(mxd,"lines3D")[0]

d=arcpy.Describe(lines2d)
SR=d.spatialReference
curT=arcpy.da.InsertCursor(lines3d,"Shape@")
## get a list of lines
lineDict={}
with arcpy.da.SearchCursor(lines2d,("Shape@","LineId")) as cursor:
    for shp, lineid in cursor:
        lineDict[lineid]=shp
## shuffle through lines
for entry in lineDict:
    line=lineDict[entry]
    q='"LineId"=%s' %"'"+entry+"'"
    listOfPoints=[]
    with arcpy.da.SearchCursor(points,("Shape@","Z"),q) as cursor:
        for pnt,z in cursor:
            p=pnt.firstPoint
            p.Z=z
            listOfPoints.append([line.measureOnLine(p),p])
##create 2 points segments
    modList=sorted(listOfPoints)
    for i,row in enumerate(modList):
        if i==0:p1=row[1];continue
        p2=row[1]
        pLine=arcpy.Polyline(arcpy.Array([p1,p2]),SR,True)
        p1=p2
        curT.insertRow((pLine,))
del curT

You can overcome a lot of license restrictions if you know Python

Hornbydd
  • 43,380
  • 5
  • 41
  • 81
FelixIP
  • 22,922
  • 3
  • 29
  • 61
  • Use add geometry attributes to derive elevations for ends of individual 3d lines – FelixIP Sep 20 '16 at 22:16
  • Thank you! I do however get this error message:

    Runtime error Traceback (most recent call last): File "<string>", line 22, in <module> RuntimeError: An invalid SQL statement was used. [inbound_elevationpoints]

    Line 22 is:

    for pnt,z in cursor:

    (and "inbound_elevationpoints" is the name of my points)

    – Sil Sep 21 '16 at 09:08
  • A question about the spatial join mentioned above, @Hornbydd, am I meant to use the spatially joined points in the script? Or the spatially joined lines? – Sil Sep 21 '16 at 09:24
  • It seems your points are sitting in database. Try on shape file. – FelixIP Sep 21 '16 at 09:24
  • Points should have lineid assigned – FelixIP Sep 21 '16 at 09:26
  • Aha, shapefiles worked better. Now I however got Runtime error Traceback (most recent call last): File "<string>", line 23, in <module> AttributeError: 'NoneType' object has no attribute 'firstPoint'

    Line 23 is p=pnt.firstPoint

    – Sil Sep 21 '16 at 10:04
  • Just try to repeat what I did in terms of layer naming and tables content – FelixIP Sep 21 '16 at 20:31
  • I used the Repair Geometry tool to identify three points with empty geometries and this solved the issue. The lines3d was then added geometry attributes like you said, and I now have polylines with height data and I am very happy for all your help. – Sil Sep 22 '16 at 06:17
  • I have used this code in many instances with great luck, but I wondered if I could get help with also being able to transfer another field from the point layer to the line (in addition to the z)? How could I go about doing that? Thanks in advance. – Sil Oct 06 '16 at 15:47
  • 1
    See how it's done http://gis.stackexchange.com/questions/125090/assign-point-ids-to-respective-start-and-end-attributes-of-a-polyline/125091#125091 – FelixIP Oct 06 '16 at 19:38