Hello everybody,
I was wondering if it is possible to create a point feature from an xy table which contains coordinates in different coordinate systems if the table has a column containing the epsg-code for each row. Same goes for z-value and a column containing information about the vertical reference.
I know i can split the table by coordinate system, create point features for each and then merge but I was wondering if there is a possibility to to this in a single operation, basically choose the coordinate system by attribute.
Thanks is advance
Solved! Go to Solution.
Not out of the box, but it's possible with a little Python.
This is only for x and y, because I have no clue about vertical reference.
def xy_to_point_enhanced(in_table, x_field, y_field, epsg_field, out_fc, out_epsg):
"""Converts tabular coordinates into a point feature class, analogous to XY Table To Point. coordinates can be from different coordinate systems.
in_table: str, path to the input table or table name in map
x_field, y_field, epsg_field: str, names of the coordinate fields and the field that contains the epsg code
out_fc: str, path of the output point feature class
out_epsg: epsg code of the output feature class
"""
from pathlib import Path
import arcpy
out_ws = str(Path(out_fc).parent)
out_name = str(Path(out_fc).name)
out_sr = arcpy.SpatialReference(out_epsg)
in_fields = arcpy.ListFields(in_table)
# create output feature class
arcpy.management.CreateFeatureclass(out_ws, out_name, "POINT", spatial_reference=out_sr)
for f in in_fields:
if f.type not in ["OID", "GlobalID"]:
arcpy.management.AddField(out_fc, f.name, f.type)
# fill output feature class
field_names = [f.name for f in in_fields]
with arcpy.da.InsertCursor(out_fc, field_names + ["SHAPE@"]) as icur:
with arcpy.da.SearchCursor(in_table, field_names) as scur:
for row in scur:
row_dict = dict(zip(field_names, row))
# create a point geometry from the input coordinates
in_sr = arcpy.SpatialReference(row_dict[epsg_field])
in_point = arcpy.PointGeometry(arcpy.Point(row_dict[x_field], row_dict[y_field]), in_sr)
# project the point geometry to the output coordinate system
out_point = in_point.projectAs(out_sr)
# insert the row values and the new geometry into the feature class
icur.insertRow(list(row) + [out_point])
# and then you can call it like this
xy_to_point_enhanced("TestTable", "X", "Y", "EPSG", "memory/TestPoints", 25832)
Splitting by coordinate system and projecting to a common one and merging the resultant bits is the way to go. You would probably want to script it if you have numerous ones or you have to do it on a regular basis
Not out of the box, but it's possible with a little Python.
This is only for x and y, because I have no clue about vertical reference.
def xy_to_point_enhanced(in_table, x_field, y_field, epsg_field, out_fc, out_epsg):
"""Converts tabular coordinates into a point feature class, analogous to XY Table To Point. coordinates can be from different coordinate systems.
in_table: str, path to the input table or table name in map
x_field, y_field, epsg_field: str, names of the coordinate fields and the field that contains the epsg code
out_fc: str, path of the output point feature class
out_epsg: epsg code of the output feature class
"""
from pathlib import Path
import arcpy
out_ws = str(Path(out_fc).parent)
out_name = str(Path(out_fc).name)
out_sr = arcpy.SpatialReference(out_epsg)
in_fields = arcpy.ListFields(in_table)
# create output feature class
arcpy.management.CreateFeatureclass(out_ws, out_name, "POINT", spatial_reference=out_sr)
for f in in_fields:
if f.type not in ["OID", "GlobalID"]:
arcpy.management.AddField(out_fc, f.name, f.type)
# fill output feature class
field_names = [f.name for f in in_fields]
with arcpy.da.InsertCursor(out_fc, field_names + ["SHAPE@"]) as icur:
with arcpy.da.SearchCursor(in_table, field_names) as scur:
for row in scur:
row_dict = dict(zip(field_names, row))
# create a point geometry from the input coordinates
in_sr = arcpy.SpatialReference(row_dict[epsg_field])
in_point = arcpy.PointGeometry(arcpy.Point(row_dict[x_field], row_dict[y_field]), in_sr)
# project the point geometry to the output coordinate system
out_point = in_point.projectAs(out_sr)
# insert the row values and the new geometry into the feature class
icur.insertRow(list(row) + [out_point])
# and then you can call it like this
xy_to_point_enhanced("TestTable", "X", "Y", "EPSG", "memory/TestPoints", 25832)
Thanks a lot, I'm going to try it like this
sadly I wasn't able to get it to work, seems to be a conflict with the ObjectID-field. After trying for the last two hours I keep getting either error.
ERROR 000012: OBJECTID ist bereits vorhanden.
or
WARNING 000012: ObjectID ist bereits vorhanden.
ERROR 000800: Der Wert ist kein Mitglied von Text | Float (einfache Genauigkeit) | Double (doppelte Genauigkeit) | Short (kleine Ganzzahl) | Long (große Ganzzahl) | Datum | Blob (Binärdaten) | Raster-Bilddaten | GUID (Globally Unique Identifier).
Fehler beim Ausführen von (AddField).
I'm not much of a programmer, so I dont really know how do go from here apart from somehow trying to get rid of the ObjectID in my input table .. as the field is generated automatically this idea proved fruitless to far..
I tested it on a table without ObjectID field...
I edited the code in my original comment, so that it skips copying ObjectID and GlobalID fields (line 20).
To follow up on my error message from a few weeks ago. I finally got some time to dive a bit into my problem and found that it didn't work with the text field-type for the epsg-field as the expression
row_dict[epsg_field] returned the referency system like this: "31467" instead of 31467 which is what arcpy.SpatialReference() seemst to expect.
Changing the epgs-field type to long fixed the problem. Works like a charm now, thanks again.
Hey, thanks for taking the time. Unfortunately I am still getting a runtime error:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "<string>", line 21, in xy_to_point_enhanced
File "C:\Program Files\ArcGIS\Pro\Resources\ArcPy\arcpy\arcobjects\mixins.py", line 942, in __init__
self._arc_object.createFromFile(item, vcs)
RuntimeError: SpatialReference: Error in CreateFromFile
I feel like this might be specific to my computer/installation, might try it out on another machine.
Still thank you and have a great day aswell!
Hi @Maps-Berlin I know it's been awhile, but I had the same error ... and it was because I misspelled the spatial reference.
Based on your code it looks like that's "out_epsg". I'm sure you've worked it out by now, but I hope you're having a good day.