Hi!
I have a shapefile with polygons, but I want to transform these objects into points (example: I have the polygons with are the physical borders of a subset of school, I want to have point rather than the polygon of the building).
What can I use?
- feature to points doesn't suit me because it creates a new output, while I would like to keep the information I have in my original shapefile.
-I tried add geometry attributes, it runs successfully, but it doesn't not add the geometry attributes!!! Do you know why it happens?
Do you have other solutions?
Thank you!!
In support of what Dan Patterson has been saying:
Did you try the toolbox I posted earlier to create a new point featureclass from the polygons? It shouldn't be difficult.
Feature to Point (Data Management) should work for you (Requires ArcGIS Desktop Advanced license). The attributes of the input features will be maintained in the output feature class. In case of multipart polygon, the centroid might lie outside the polygon.
I will say "Give it a try".
In case you do not have access to an Advance license you could create a tool that does this for you with a Basic license.(sorry for the Spanish interface)
The code beneath looks like this:
#-------------------------------------------------------------------------------
# Name: FeatureToPoint.py
# Purpose: Convertir feature a punto
#
# Author: xbakker
#
# Created: 02/03/2015
#-------------------------------------------------------------------------------
import arcpy
import os
import math
def main():
# parameters
fc_in = arcpy.GetParameterAsText(0)
fc_out = arcpy.GetParameterAsText(1)
method = arcpy.GetParameterAsText(2) # CENTROID, INSIDE
# fld para poder hacer el join con la entrada
fld_oid_in = "ORIG_FID"
# geometria de salida
geomtype = "POINT"
sr = arcpy.Describe(fc_in).spatialReference
# recreate fc_out based on fc_lines (in)
ws_name, fc_name = os.path.split(fc_out)
createFeatureClass(fc_out, fc_in, geomtype, sr)
# add OID field
arcpy.AddField_management(fc_out, fld_oid_in, "LONG")
# cursors:
cnt = 0
flds_out = ("SHAPE@", fld_oid_in)
with arcpy.da.InsertCursor(fc_out, flds_out) as curs_out:
flds_in =("SHAPE@", "OID@")
with arcpy.da.SearchCursor(fc_in, flds_in) as curs:
for row in curs:
feat = row[0]
oid = row[1]
# get point based on method
pnt = getPoint(feat, method)
# store point
cnt += 1
if cnt % 100 == 0:
arcpy.AddMessage("Procesando feature: {0}".format(cnt))
curs_out.insertRow((pnt, oid, ))
arcpy.AddMessage("{0} features procesados...".format(cnt))
def getPoint(feat, method):
"""Convertir feature a punto dependiendo del metodo y tipo de geometria"""
pnt = None
if method == "CENTROID" and feat.type == 'polygon':
pnt = feat.centroid
elif method == "CENTROID" and feat.type == 'polyline':
pnt = CentroidPolyline(feat)
elif method == "CENTROID" and feat.type == 'multipoint':
# average x and y coordinates of all the points in the multipoint feature
pnt = CentriodMultiPoint(feat)
elif method == "INSIDE" and feat.type == 'polygon':
pnt = feat.labelPoint
elif method == "INSIDE" and feat.type == 'polyline':
pntg = feat.positionAlongLine(0.5, True)
pnt = pntg.firstPoint
elif method == "INSIDE" and feat.type == 'multipoint':
pnt = InsideMultiPoint(feat)
return pnt
def InsideMultiPoint(feat):
# punto mas cercano al centroid
pnt_c = CentriodMultiPoint(feat)
min_dist = 999999
for pnt_mp in feat:
dist = getDistance(pnt_mp, pnt_c)
if dist < min_dist:
pnt = arcpy.Point(pnt_mp.X, pnt_mp.Y)
min_dist = dist
return pnt
def CentriodMultiPoint(multipoint):
lst_x = []
lst_y = []
for pnt in multipoint:
lst_x.append(pnt.X)
lst_y.append(pnt.Y)
return arcpy.Point(sum(lst_x)/float(len(lst_x)), sum(lst_y)/float(len(lst_y)))
def CentroidPolyline(polyline):
"""weighted average x and y coordinates of the midpoints of all line segments in the line feature
where the weight of a particular midpoint is the length of the correspondent line segment"""
lst_x = []
lst_y = []
lst_length = []
for part in polyline:
prev_pnt = None
for pnt_part in part:
if prev_pnt is None:
# skip
prev_pnt = arcpy.Point(pnt_part.X, pnt_part.Y)
else:
dist = getDistance(pnt_part, prev_pnt)
line = arcpy.Polyline(arcpy.Array([prev_pnt, pnt_part]))
mid_pnt = line.positionAlongLine(0.5, True)
lst_x.append(mid_pnt.firstPoint.X * dist)
lst_y.append(mid_pnt.firstPoint.Y * dist)
lst_length.append(dist)
sum_dist = sum(lst_length)
sum_x = sum(lst_x)
sum_y = sum(lst_y)
x = sum_x / sum_dist
y = sum_y / sum_dist
return arcpy.Point(x, y)
def createFeatureClass(fc_out, fc_in, geomtype, sr):
ws_name, fc_name = os.path.split(fc_out)
arcpy.CreateFeatureclass_management(ws_name, fc_name, geomtype, spatial_reference=sr)
def getDistance(pnt1, pnt2):
return math.hypot(pnt1.X - pnt2.X, pnt1.Y - pnt2.Y)
if __name__ == '__main__':
main()
I fogot to ask something in my previous reply.
Summing up: I added two fields in the original feature class (contening polygons), I calculated the X and Y coordinates of the centroid, I created a XY event by going to data management tools, layers and table views, make xy event. When I open the attribute table, I find two fields with the shape, and the geometry is polygon. (see attachment). Why is that happening? I can visualize points on the map.
This is very strange. When you use XY events they will always create point geometry.