Subject: Marine Geospatial Ecology Tools (MGET) help
Text archives
From: | "Jason Roberts" <> |
---|---|
To: | "'Arlene Merems'" <> |
Cc: | <> |
Subject: | RE: [mget-help] RE: find nearest feature problem |
Date: | Mon, 27 Jul 2009 16:21:31 -0400 |
Arlene, It was as I suspected. We were bungling the call to Near,
passing 'NOANGLE' rather than 'NO_ANGLE'. I fixed the problem and the tool ran
fine with the data you sent. My apologies for this. To fix this on your own system, please do the following: 1.
Shut down all ArcGIS applications. 2.
Overwrite the file C:\Python25\Lib\site-packages\GeoEco\SpatialAnalysis\Points.py
with the attached Points.py. 3.
Start Arc and try again. This fix will be included in the final release of MGET 0.7, due
to be released tomorrow, providing that the rest of our testing goes well. Best, Jason From: Jason Roberts
[mailto:] Hi Arlene, Thanks for your interest in MGET. I'm sorry you're seeing this
problem. Based on the error message you sent, my guess is that we messed up
MGET's call to ArcGIS's Near tool and did not catch the problem in testing. It
looks like MGET is calling Near with the string 'NOANGLE' rather than
'NO_ANGLE', and ArcGIS is saying that it doesn't know what 'NOANGLE' means
(this is probably what "Input to parameter angle not within domain"
means). Thanks for sending your data. I will try to run the tool using
your data and let you know what I find out. If I am right, the fix should be
very easy and I'll be able to send you a file to patch the tool to work
properly. In the mean time, you may be able to get the tool working by adding
an Angle field to your points and telling the tool to populate it. This will
cause it to pass 'ANGLE' to Near, which should work. My guess is that our test
code always included an Angle field, thus we never tested the tool without one
and did not hit this bug in MGET. Thank you for finding it! Best regards, Jason From: Arlene Merems
[mailto:] Hello,
and thanks for being readily available with tech support! I
am excited to find this great GIS analysis tool for marine data! But having a
problem with the Find Nearest Features tool. It keeps returning error messages.
See error message below. I
have a point file “blackrock.shp” of fish observations and a polygon file
“bpi200_ridge.shp” of a single habitat type (converted from a raster of
multiple habitat types). I want to measure the distance of each fish
observation to this habitat feature. Seems straight forward enough. I created a
field called “dist-ridge” in the fish shapefile as the field to receive the
feature distance value. I tried adding a search radius of 5m and again as
‘unknown’. Those are the only parameters I set. I don’t know why
its not working. Can’t decifer the error message. Can you help? I
attached the point shapefile and the polygon shapefile in case you want to try
it. Thanks!
Arlene Error
message: <class
'GeoEco.ArcGIS.ArcGISError'>: An ArcGIS geoprocessing function failed. This
usually results from a problem with your inputs. Please check them and try
again. Also review any preceding error messages and the detailed error
information that appears at the end of this message. If you suspect the failure
is due to a programming mistake in this tool or ArcGIS, please contact the
author of this tool for assistance. Detailed error information: ArcGIS
Geoprocessor object 0x1E825DA0: Invocation of
Near_analysis(*args=('C:\\Temp\\GeoEcoTemp_meremsa\\tmp0tkne0\\Temp.mdb\\CopiedPoints',
'C:\\Temp\\GeoEcoTemp_meremsa\\tmp0tkne0\\Temp.mdb\\ConvertedLines', '5
Meters', 'NO_LOCATION', 'NOANGLE')) raised ExecuteError: ERROR 000622: Failed
to execute (Near). Parameters are not valid. ERROR 000621:
Input to parameter angle not within domain. Failed to
execute (ArcGISPointsFindNearestFeatures). End Time: Mon
Jul 27 11:57:45 2009 (Elapsed Time: 29.00 seconds) Arlene Merems Oregon Department of Fish and Wildlife Marine Resources Program 2040 SE Marine Science Dr. Newport, OR 97365 ph: 541-867-0300 ext. 246 fax: 541-867-0311 |
#
# Copyright (C) 2007 Jason J. Roberts
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License (available in the file LICENSE.TXT)
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
USA.
import os.path
from GeoEco.DynamicDocString import DynamicDocString
from GeoEco.Internationalization import _
from GeoEco.Logging import Logger, ProgressReporter
class ArcGISPoints(object):
__doc__ = DynamicDocString()
@classmethod
def _InsertPoint(cls, gp, insertCursor, x, y, z=None, m=None,
attributes=None, shapeFieldName=u'Shape'):
# Set the geometry field.
point = gp.CreateObject(u'Point')
point.X = x
point.Y = y
if z is not None:
point.Z = z
if m is not None:
point.M = m
insertCursor.SetValue(shapeFieldName, point)
# If the caller provided any attributes, set them.
if attributes is not None:
for field, value in attributes.items():
insertCursor.SetValue(field, value)
# Insert the row.
insertCursor.InsertRow()
@classmethod
def InsertPoint(cls, insertCursor, x, y, z=None, m=None, attributes=None,
shapeFieldName=u'Shape'):
cls.__doc__.Obj.ValidateMethodInvocation()
# Perform additional parameter validation.
if not insertCursor.IsOpen:
Logger.RaiseException(ValueError(_(u'The insert cursor must be
open.')))
# Insert the point.
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
cls._InsertPoint(gp, insertCursor, x, y, z, m, attributes,
shapeFieldName)
@classmethod
def AppendPointsToFeatureClass(cls, featureClass, coordinates,
hasZ=False, hasM=False, attributes=None):
cls.__doc__.Obj.ValidateMethodInvocation()
# Validate the length of the coordinates list.
if not hasZ and not hasM:
if len(coordinates) % 2 != 0:
Logger.RaiseException(ValueError(_(u'The length of the input
list of point coordinates must be evenly divisible by 2, because each point
must have an X and a Y coordinate.')))
numPoints = len(coordinates) / 2
elif hasZ and not hasM:
if len(coordinates) % 3 != 0:
Logger.RaiseException(ValueError(_(u'The length of the input
list of point coordinates must be evenly divisible by 3, because each point
must have X, Y, and Z coordinates.')))
numPoints = len(coordinates) / 3
elif not hasZ and hasM:
if len(coordinates) % 3 != 0:
Logger.RaiseException(ValueError(_(u'The length of the input
list of point coordinates must be evenly divisible by 3, because each point
must have X and Y coordinates and a measure value.')))
numPoints = len(coordinates) / 3
else:
if len(coordinates) % 4 != 0:
Logger.RaiseException(ValueError(_(u'The length of the input
list of point coordinates must be evenly divisible by 4, because each point
must have X, Y, and Z coordinates and a measure value.')))
numPoints = len(coordinates) / 4
# Validate that the caller provided or did not provide Z or M
# values.
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
describe = gp.Describe(featureClass)
if hasZ and not describe.HasZ:
Logger.RaiseException(ValueError(_(u'The input list of point
coordinates includes Z coordinates but the feature class %(fc)s does not have
Z coordinates. Please specify a different feature class or remove the Z
coordinates from the input list of point coordinates.') % {u'fc':
featureClass}))
if not hasZ and describe.HasZ:
Logger.RaiseException(ValueError(_(u'The input list of point
coordinates does not include Z coordinates but the feature class %(fc)s has Z
coordinates. Please specify a different feature class or add Z coordinates to
the input list of point coordinates.') % {u'fc': featureClass}))
if hasM and not describe.HasM:
Logger.RaiseException(ValueError(_(u'The input list of point
coordinates includes measure values but the feature class %(fc)s does not
have measure values. Please specify a different feature class or remove the
measure values from the input list of point coordinates.') % {u'fc':
featureClass}))
if not hasM and describe.HasM:
Logger.Warning(_(u'The feature class %(fc)s has measure values
but the input list of point coordinates does not include measure values. The
points will be added to the feature class with NULL measure values.') %
{u'fc': featureClass})
# Determine the name of the shape field.
shapeFieldName = describe.ShapeFieldName
# Open an insert cursor to the feature class and insert the points.
Logger.Info(_(u'Inserting %(count)i points into feature class
%(fc)s...') % {u'count': numPoints, u'fc': featureClass})
from GeoEco.DatabaseAccess.ArcGIS import ArcGIS91DatabaseConnection
connection = ArcGIS91DatabaseConnection()
cursor = connection.OpenInsertCursor(featureClass, rowCount=numPoints)
try:
for i in range(numPoints):
if attributes is not None and i < len(attributes):
attrs = attributes[i]
else:
attrs = None
if not hasZ and not hasM:
cls._InsertPoint(gp, cursor, x=coordinates[i*2],
y=coordinates[i*2 + 1], attributes=attrs, shapeFieldName=shapeFieldName)
elif hasZ and not hasM:
cls._InsertPoint(gp, cursor, x=coordinates[i*3],
y=coordinates[i*3 + 1], z=coordinates[i*3 + 2], attributes=attrs,
shapeFieldName=shapeFieldName)
elif not hasZ and hasM:
cls._InsertPoint(gp, cursor, x=coordinates[i*3],
y=coordinates[i*3 + 1], m=coordinates[i*3 + 2], attributes=attrs,
shapeFieldName=shapeFieldName)
else:
cls._InsertPoint(gp, cursor, x=coordinates[i*4],
y=coordinates[i*4 + 1], z=coordinates[i*4 + 2], m=coordinates[i*4 + 3],
attributes=attrs, shapeFieldName=shapeFieldName)
finally:
del cursor
@classmethod
def AppendPointsToFeatureClass2(cls, featureClass, xyCoordinates,
zCoordinates=None, mValues=None, intAttrsToSet=None, intAttrValues=None,
floatAttrsToSet=None, floatAttrValues=None, stringAttrsToSet=None,
stringAttrValues=None, dateAttrsToSet=None, dateAttrValues=None):
cls.__doc__.Obj.ValidateMethodInvocation()
# Parse the coordinates into lists.
coords = []
for i in range(len(xyCoordinates)):
x, y = PointTypeMetadata.ParseFromArcGISString(xyCoordinates[i])
coords.append(x)
coords.append(y)
if zCoordinates is not None:
coords.append(zCoordinates[i])
if mValues is not None:
coords.append(mValues[i])
# Build a dictionary of attributes to set.
attributesDict = {}
if intAttrsToSet is not None:
for i in range(len(intAttrsToSet)):
attributesDict[intAttrsToSet[i]] = intAttrValues[i]
if floatAttrsToSet is not None:
for i in range(len(floatAttrsToSet)):
attributesDict[floatAttrsToSet[i]] = floatAttrValues[i]
if stringAttrsToSet is not None:
for i in range(len(stringAttrsToSet)):
attributesDict[stringAttrsToSet[i]] = stringAttrValues[i]
if dateAttrsToSet is not None:
for i in range(len(dateAttrsToSet)):
attributesDict[dateAttrsToSet[i]] = dateAttrValues[i]
# If the caller provided multiple points, all of them will
# receive the same attribute values. Build a list of attribute
# dictionaries. Each element of the list will point to the
# same dictionary.
if len(attributesDict) > 0:
attributes = []
for i in range(len(xyCoordinates)):
attributes.append(attributesDict)
else:
attributes = None
# Append the points to the feature class.
cls.AppendPointsToFeatureClass(featureClass, coords, zCoordinates is
not None, mValues is not None, attributes)
# Return successfully.
return featureClass
@classmethod
def CreateFeatureClassWithPoints(cls, featureClass, spatialReference,
coordinates, hasZ=False, hasM=False, attributes=None, configKeyword=None,
spatialGrid1=0, spatialGrid2=0, spatialGrid3=0, overwriteExisting=False):
cls.__doc__.Obj.ValidateMethodInvocation()
# Create a temporary directory to hold the output feature
# class while we are constructing it. If the output
# feature class is not a shapefile, create a temporary
# personal geodatabase to hold the feature class.
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
from GeoEco.DataManagement.Directories import TemporaryDirectory
tempDir = TemporaryDirectory()
outputIsShapefile = featureClass.lower().endswith(u'.shp')
if outputIsShapefile:
tempGeoDB = None
tempWorkspace = tempDir.Path
tempExt = u'.shp'
else:
gp.CreatePersonalGDB_management(tempDir.Path, u'Temp.mdb')
tempGeoDB = os.path.join(tempDir.Path, u'Temp.mdb')
tempWorkspace = tempGeoDB
tempExt = u''
try:
# Create the temporary output feature class.
if not hasZ and not hasM:
gp.CreateFeatureClass_management(tempWorkspace, u'Temp',
u'POINT', u'', u'DISABLED', u'DISABLED', spatialReference, configKeyword,
spatialGrid1, spatialGrid2, spatialGrid3)
elif hasZ and not hasM:
gp.CreateFeatureClass_management(tempWorkspace, u'Temp',
u'POINT', u'', u'DISABLED', u'ENABLED', spatialReference, configKeyword,
spatialGrid1, spatialGrid2, spatialGrid3)
elif not hasZ and hasM:
gp.CreateFeatureClass_management(tempWorkspace, u'Temp',
u'POINT', u'', u'ENABLED', u'DISABLED', spatialReference, configKeyword,
spatialGrid1, spatialGrid2, spatialGrid3)
else:
gp.CreateFeatureClass_management(tempWorkspace, u'Temp',
u'POINT', u'', u'ENABLED', u'ENABLED', spatialReference, configKeyword,
spatialGrid1, spatialGrid2, spatialGrid3)
tempFC = os.path.join(tempWorkspace, u'Temp' + tempExt)
# Append the points.
cls.AppendPointsToFeatureClass(tempFC, coordinates, hasZ, hasM,
attributes)
# Extract the output feature class from the temporary
# directory or geodb.
oldLogInfoAsDebug = Logger.GetLogInfoAsDebug()
Logger.SetLogInfoAsDebug(True)
try:
GeoprocessorManager.CopyArcGISObject(tempFC, featureClass,
overwriteExisting, [u'featureclass', u'shapefile'], _(u'feature class'))
finally:
Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
finally:
# If we created a temporary personal geodatabase,
# delete it now. If we do not explicitly delete it
# here, the geoprocessor will keep a handle open
# through MS Access APIs, and the temporary directory
# will not be able to be deleted.
if tempGeoDB is not None:
try:
gp.Delete_management(tempGeoDB)
except:
pass
@classmethod
def CreateFeatureClassWithPoints2(cls, featureClass, spatialReference,
xyCoordinates, zCoordinates=None, mValues=None, configKeyword=None,
spatialGrid1=0, spatialGrid2=0, spatialGrid3=0, overwriteExisting=False):
cls.__doc__.Obj.ValidateMethodInvocation()
# Create a temporary directory to hold the output feature
# class while we are constructing it. If the output
# feature class is not a shapefile, create a temporary
# personal geodatabase to hold the feature class.
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
from GeoEco.DataManagement.Directories import TemporaryDirectory
tempDir = TemporaryDirectory()
outputIsShapefile = featureClass.lower().endswith(u'.shp')
if outputIsShapefile:
tempGeoDB = None
tempWorkspace = tempDir.Path
tempExt = u'.shp'
else:
gp.CreatePersonalGDB_management(tempDir.Path, u'Temp.mdb')
tempGeoDB = os.path.join(tempDir.Path, u'Temp.mdb')
tempWorkspace = tempGeoDB
tempExt = u''
try:
# Create the temporary output feature class.
hasZ = zCoordinates is not None
hasM = mValues is not None
if not hasZ and not hasM:
gp.CreateFeatureClass_management(tempWorkspace, u'Temp',
u'POINT', u'', u'DISABLED', u'DISABLED', spatialReference, configKeyword,
spatialGrid1, spatialGrid2, spatialGrid3)
elif hasZ and not hasM:
gp.CreateFeatureClass_management(tempWorkspace, u'Temp',
u'POINT', u'', u'DISABLED', u'ENABLED', spatialReference, configKeyword,
spatialGrid1, spatialGrid2, spatialGrid3)
elif not hasZ and hasM:
gp.CreateFeatureClass_management(tempWorkspace, u'Temp',
u'POINT', u'', u'ENABLED', u'DISABLED', spatialReference, configKeyword,
spatialGrid1, spatialGrid2, spatialGrid3)
else:
gp.CreateFeatureClass_management(tempWorkspace, u'Temp',
u'POINT', u'', u'ENABLED', u'ENABLED', spatialReference, configKeyword,
spatialGrid1, spatialGrid2, spatialGrid3)
tempFC = os.path.join(tempWorkspace, u'Temp' + tempExt)
# Append the points.
cls.AppendPointsToFeatureClass2(tempFC, xyCoordinates,
zCoordinates, mValues)
# Extract the output feature class from the temporary
# directory or geodb.
oldLogInfoAsDebug = Logger.GetLogInfoAsDebug()
Logger.SetLogInfoAsDebug(True)
try:
GeoprocessorManager.CopyArcGISObject(tempFC, featureClass,
overwriteExisting, [u'featureclass', u'shapefile'], _(u'feature class'))
finally:
Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
finally:
# If we created a temporary personal geodatabase,
# delete it now. If we do not explicitly delete it
# here, the geoprocessor will keep a handle open
# through MS Access APIs, and the temporary directory
# will not be able to be deleted.
if tempGeoDB is not None:
try:
gp.Delete_management(tempGeoDB)
except:
pass
@classmethod
def FindNearestFeatures(cls, pointFeatures, nearFeatures,
searchRadius=None, fidField=None, distanceField=None, angleField=None,
overlappingPolygonDistance=u'Zero', wherePointFeatures=None,
whereNearFeatures=None, nearestFieldsToCopy=None,
destinationPointFields=None):
cls.__doc__.Obj.ValidateMethodInvocation()
try:
# Validate and/or create the point fields.
fidField, distanceField, angleField, nearestFieldsToCopy,
destinationPointFields, fidFieldNullValue, distanceFieldNullValue,
angleFieldNullValue, destinationPointFieldsNullValues, tempJoinFIDField,
tempNearFIDField = cls._ValidateAndCreatePointFields(pointFeatures,
nearFeatures, fidField, distanceField, angleField, nearestFieldsToCopy,
destinationPointFields)
try:
# If the point feature class is empty, return now.
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
if gp.GetCount_management(pointFeatures) <= 0:
Logger.Info(_(u'The point feature class %(points)s is
empty. There is no work to do.') % {u'points': pointFeatures})
return pointFeatures
# Create a temp directory and geodatabase to hold temp
# feature classes.
from GeoEco.DataManagement.Directories import
TemporaryDirectory
tempDir = TemporaryDirectory()
tempGeoDB = os.path.join(tempDir.Path, 'Temp.mdb')
gp.CreatePersonalGDB_management(tempDir.Path, 'Temp')
try:
# Find the near features.
cls._FindNearestFeatures(tempDir=tempDir.Path,
tempGeoDB=tempGeoDB,
pointFeatures=pointFeatures,
tempJoinFIDField=tempJoinFIDField,
tempNearFIDField=tempNearFIDField,
nearFeatures=nearFeatures,
searchRadius=searchRadius,
fidField=fidField,
fidFieldNullValue=fidFieldNullValue,
distanceField=distanceField,
distanceFieldNullValue=distanceFieldNullValue,
angleField=angleField,
angleFieldNullValue=angleFieldNullValue,
overlappingPolygonDistance=overlappingPolygonDistance,
wherePointFeatures=wherePointFeatures,
whereNearFeatures=whereNearFeatures,
nearestFieldsToCopy=nearestFieldsToCopy,
destinationPointFields=destinationPointFields,
destinationPointFieldsNullValues=destinationPointFieldsNullValues,
skipArgumentValidation=True)
# Delete the temp geodatabase. If we do not explicitly
# delete it here, the geoprocessor will keep a handle open
# through MS Access APIs, and the temporary directory will
# not be able to be deleted.
finally:
try:
gp.Delete_management(tempGeoDB)
except:
pass
# Delete the temporary fields that
# _ValidateAndCreatePointFields created in the caller's
# points.
finally:
from GeoEco.DatabaseAccess.ArcGIS import
ArcGIS91DatabaseConnection
conn = ArcGIS91DatabaseConnection()
try:
conn.DeleteField(pointFeatures, tempJoinFIDField)
except:
pass
if fidField is None:
try:
conn.DeleteField(pointFeatures, tempNearFIDField)
except:
pass
except:
Logger.LogExceptionAsError()
raise
# Return successfully.
return pointFeatures
@classmethod
def _ValidateAndCreatePointFields(cls, pointFeatures, nearFeatures,
fidField=None, distanceField=None, angleField=None, nearestFieldsToCopy=None,
destinationPointFields=None):
# Validate that the caller provided a sufficient number and
# combination of field parameters.
if fidField is None and distanceField is None and angleField is None
and nearestFieldsToCopy is None:
Logger.RaiseException(ValueError(_(u'The FID field, distance
field, angle field, and fields to copy parameters cannot all be omitted. You
must specify at least one of these parameters.')))
if nearestFieldsToCopy is not None and fidField is None:
Logger.RaiseException(ValueError(_(u'You specified fields to copy
from the near features but did not specify a field for the FID fo the near
features. In order to copy fields, you must specify a field for the FID.')))
# If the caller provided nearestFieldsToCopy, pointFeatures
# and nearFeatures cannot have the same basename, because we
# have to join them.
if nearestFieldsToCopy is not None and
os.path.basename(pointFeatures) == os.path.basename(nearFeatures):
Logger.RaiseException(ValueError(_(u'You requested that fields be
copied from the near features to the point features, but the point features
and near features have the same base name %(name)s. In order to copy fields
from one to the other, they must have different base names (this constraint
is imposed by the ArcGIS Add Join tool, which is used to implement the
copying).') % {u'name': os.path.basename(pointFeatures)}))
# Validate or create the FID field.
from GeoEco.DatabaseAccess.ArcGIS import ArcGIS91DatabaseConnection
conn = ArcGIS91DatabaseConnection()
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
fidFieldNullValue = 'NULL'
if fidField is not None:
addedField = False
if conn.FieldExists(pointFeatures, fidField):
dt = conn.GetFieldDataType(pointFeatures, fidField)
if dt != u'LONG':
Logger.RaiseException(ValueError(_(u'The field %(field)s
of the point features cannot be used to store the feature ID of the near
feature because it has the data type %(dt)s. This field must have the data
type of LONG. Please specify the name of a different field. If you specify a
non-existing field, it will be created for you.') % {u'field': fidField,
u'dt': dt}))
else:
fidField = conn.AddField(pointFeatures, fidField, u'LONG')
addedField = True
if not conn.FieldIsNullable(pointFeatures, fidField):
fidFieldNullValue = -1
if addedField:
gp.CalculateField_management(pointFeatures, fidField,
str(fidFieldNullValue))
# Validate or create the distance field.
distanceFieldNullValue = 'NULL'
if distanceField is not None:
addedField = False
if conn.FieldExists(pointFeatures, distanceField):
dt = conn.GetFieldDataType(pointFeatures, distanceField)
if dt not in [u'FLOAT', u'DOUBLE']:
Logger.RaiseException(ValueError(_(u'The field %(field)s
of the point features cannot be used to store the distance to the near
feature because it has the data type %(dt)s. This field must have the data
type FLOAT or DOUBLE. Please specify the name of a different field. If you
specify a non-existing field, it will be created for you.') % {u'field':
distanceField, u'dt': dt}))
else:
distanceField = conn.AddField(pointFeatures, distanceField,
u'DOUBLE')
addedField = True
if not conn.FieldIsNullable(pointFeatures, distanceField):
distanceFieldNullValue = -999999999999.
if addedField:
gp.CalculateField_management(pointFeatures,
distanceField, str(distanceFieldNullValue))
# Validate or create the angle field.
angleFieldNullValue = 'NULL'
if angleField is not None:
addedField = False
if conn.FieldExists(pointFeatures, angleField):
dt = conn.GetFieldDataType(pointFeatures, angleField)
if dt not in [u'FLOAT', u'DOUBLE']:
Logger.RaiseException(ValueError(_(u'The field %(field)s
of the point features cannot be used to store the angle to the near feature
because it has the data type %(dt)s. This field must have the data type FLOAT
or DOUBLE. Please specify the name of a different field. If you specify a
non-existing field, it will be created for you.') % {u'field': angleField,
u'dt': dt}))
else:
angleField = conn.AddField(pointFeatures, angleField,
u'DOUBLE')
addedField = True
if not conn.FieldIsNullable(pointFeatures, angleField):
angleFieldNullValue = -9999.
if addedField:
gp.CalculateField_management(pointFeatures, angleField,
str(angleFieldNullValue))
# Validate or create the destination fields.
if destinationPointFields is not None and (nearestFieldsToCopy is
None or len(nearestFieldsToCopy) < len(destinationPointFields)):
Logger.RaiseException(ValueError(_(u'The number of point fields
to receive copied values exceeds the number of near feature fields to copy
values from. For each point field, you must also specify a near feature
field.')))
destinationPointFieldsNullValues = []
if nearestFieldsToCopy is not None:
if destinationPointFields is None:
destinationPointFields = []
if len(destinationPointFields) < len(nearestFieldsToCopy):
destinationPointFields.extend(nearestFieldsToCopy[len(destinationPointFields):])
for i in range(len(nearestFieldsToCopy)):
if nearFeatures is not None:
sourceDT = conn.GetFieldDataType(nearFeatures,
nearestFieldsToCopy[i])
addedField = False
if conn.FieldExists(pointFeatures, destinationPointFields[i]):
destDT = conn.GetFieldDataType(pointFeatures,
destinationPointFields[i])
if nearFeatures is not None and \
(sourceDT == u'SHORT' and destDT not in [u'SHORT',
u'LONG', u'FLOAT', u'DOUBLE', u'TEXT'] or \
sourceDT == u'LONG' and destDT not in [u'LONG',
u'FLOAT', u'DOUBLE', u'TEXT'] or \
sourceDT == u'FLOAT' and destDT not in [u'FLOAT',
u'DOUBLE', u'TEXT'] or \
sourceDT == u'DOUBLE' and destDT not in [u'DOUBLE',
u'TEXT'] or \
sourceDT == u'TEXT' and destDT not in [u'TEXT'] or \
sourceDT == u'DATE' and destDT not in [u'DATE',
u'TEXT']):
Logger.RaiseException(ValueError(_(u'Field %(nf)s of
the near features cannot be copied to field %(pf)s of the point features
because the data types are incompatible: %(ndt)s values cannot be coerced
into %(pdt)s values, at least not without a loss of data. Please specify a
different destination field of the point features. If you specify a
non-existing field, it will be created for you.') % {u'nf':
nearestFieldsToCopy[i], u'pf': destinationPointFields[i], u'ndt': sourceDT,
u'pdt': destDT}))
else:
if nearFeatures is None:
Logger.RaiseException(ValueError(_(u'You specified
that the %(source)s field of the near features should be copied to the
%(dest)s field of the point features, but that point field does not exist. In
this situation, this tool is designed to create the point field
automatically. But you did not provide a near feature class or layer, so the
tool cannot determine what data type should be used to create the field.
Please create the field yourself and try again, or provide a near feature
class or layer that contains the field.') % {u'source':
nearestFieldsToCopy[i], u'dest': destinationPointFields[i]}))
destDT = sourceDT
destinationPointFields[i] = conn.AddField(pointFeatures,
destinationPointFields[i], destDT) # TODO: copy length, precision, etc.
addedField = True
if not conn.FieldIsNullable(pointFeatures,
destinationPointFields[i]):
if destDT == u'SHORT':
destinationPointFieldsNullValues.append(-999)
elif destDT == u'LONG':
destinationPointFieldsNullValues.append(-99999999)
elif destDT in [u'FLOAT', u'DOUBLE']:
destinationPointFieldsNullValues.append(-1e+030)
elif destDT in [u'TEXT']:
destinationPointFieldsNullValues.append('""')
else:
destinationPointFieldsNullValues.append(None)
if addedField:
gp.CalculateField_management(pointFeatures,
destinationPointFields[i], str(destinationPointFieldsNullValues[i]))
else:
destinationPointFieldsNullValues.append('NULL')
if destinationPointFieldsNullValues[i] != 'NULL':
Logger.Warning(_(u'Because field %(field)s of the point
features cannot receive NULL values, the value %(val)s will be stored instead
of NULL.') % {u'field': destinationPointFields[i], u'val':
str(destinationPointFieldsNullValues[i])})
# Create a couple of temporary fields to hold FIDs. We will
# delete these when our processing is complete.
#
# tempJoinFIDField contains a copy of the FID of the point
# features. We need this field so we are assured of a stable
# copy of the original FID that survives geoprocessing
# operations.
#
# tempNearFIDField contains the FID of the near feature. We
# only create this field of the caller did not specify a
# destination FID field. We need this, ultimately, because the
# ArcGIS Calculate Field tool cannot copy a NULL value from
# one field to another. When a near feature is not found
# within the search radius, Near_analysis stores -1 for the
# FID. We need to copy it to the caller's points and THEN set
# it to NULL.
import random
tempJoinFIDField = None
tempNearFIDField = fidField
while tempJoinFIDField is None or conn.FieldExists(pointFeatures,
tempJoinFIDField):
tempJoinFIDField = 'OFID_' + str(random.randint(10000,99999))
conn.AddField(pointFeatures, tempJoinFIDField, 'LONG')
try:
gp.CalculateField_management(pointFeatures, tempJoinFIDField, '['
+ gp.Describe(pointFeatures).OIDFieldName + ']')
if fidField is not None:
tempNearFIDField = fidField
else:
while tempNearFIDField is None or
conn.FieldExists(pointFeatures, tempNearFIDField):
tempNearFIDField = 'NFID_' +
str(random.randint(10000,99999))
conn.AddField(pointFeatures, tempNearFIDField, 'LONG')
except:
try:
conn.DeleteField(pointFeatures, tempJoinFIDField)
except:
pass
raise
# Return successfully.
return fidField, distanceField, angleField, nearestFieldsToCopy,
destinationPointFields, fidFieldNullValue, distanceFieldNullValue,
angleFieldNullValue, destinationPointFieldsNullValues, tempJoinFIDField,
tempNearFIDField
@classmethod
def _FindNearestFeatures(cls, tempDir, tempGeoDB, pointFeatures,
tempJoinFIDField, tempNearFIDField, nearFeatures, searchRadius=None,
fidField=None, fidFieldNullValue=None, distanceField=None,
distanceFieldNullValue=None, angleField=None, angleFieldNullValue=None,
overlappingPolygonDistance=u'Zero', wherePointFeatures=None,
whereNearFeatures=None, nearestFieldsToCopy=None,
destinationPointFields=None, destinationPointFieldsNullValues=None,
skipArgumentValidation=False):
if not skipArgumentValidation:
cls.__doc__.Obj.ValidateMethodInvocation()
# Obtain metadata about the points and near features.
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
pointFeaturesDescribe = gp.Describe(pointFeatures)
pointFeaturesInShapefile = pointFeaturesDescribe.DataType.lower() ==
'shapefile'
pointFeaturesCS =
gp.CreateSpatialReference_management(pointFeatures).split(';')[0]
if GeoprocessorManager.GetArcGISMajorVersion() == 9 and
GeoprocessorManager.GetArcGISMinorVersion() == 1:
pointsAreProjected =
hasattr(pointFeaturesDescribe.SpatialReference, 'Classification')
else:
pointsAreProjected =
pointFeaturesDescribe.SpatialReference.ProjectionCode != 0
nearFeaturesDescribe = gp.Describe(nearFeatures)
nearFeaturesInShapefile = nearFeaturesDescribe.DataType.lower() ==
'shapefile'
nearFeaturesCS =
gp.CreateSpatialReference_management(nearFeatures).split(';')[0]
if GeoprocessorManager.GetArcGISMajorVersion() == 9 and
GeoprocessorManager.GetArcGISMinorVersion() == 1:
nearAreProjected = hasattr(nearFeaturesDescribe.SpatialReference,
'Classification')
else:
nearAreProjected =
nearFeaturesDescribe.SpatialReference.ProjectionCode != 0
# Validate that either the points or the near features are
# projected.
if not pointsAreProjected and not nearAreProjected:
Logger.RaiseException(ValueError(_(u'Neither the point features
(%(points)s) nor the near features (%(near)s) use a projected coordinate
system. One or the other of these must use a projected coordinate system.
Please project one or the other of them and try again.') % {u'points':
pointFeatures, u'near': nearFeatures}))
# Copy the caller's points into the temp geodatabase,
# selecting the points specified by the caller's where clause
# (if any) and only copying the tempJoinFIDField field.
pointsLayer = GeoprocessorManager.GetUniqueLayerName()
fieldInfo = []
visibleFields = [pointFeaturesDescribe.ShapeFieldName,
pointFeaturesDescribe.OIDFieldName, tempJoinFIDField]
fields = gp.ListFields(pointFeatures)
f = fields.Next()
while f is not None:
if f.Name not in visibleFields:
fieldInfo.append(f.Name + ' ' + f.Name + ' HIDDEN')
elif f.Name == tempJoinFIDField:
fieldInfo.append(f.Name + ' ' + f.Name + ' VISIBLE')
f = fields.Next()
fieldInfo = ';'.join(fieldInfo)
gp.MakeFeatureLayer_management(pointFeatures, pointsLayer,
wherePointFeatures, None, fieldInfo)
try:
if gp.GetCount_management(pointsLayer) <= 0:
if wherePointFeatures is None:
Logger.Info(_(u'The point feature class %(points)s is
empty. There is no work to do.') % {u'points': pointFeatures})
else:
Logger.Info(_(u'The where clause %(where)s did not select
any points from feature class %(points)s. There is no work to do.') %
{u'where': wherePointFeatures, u'points': pointFeatures})
return
Logger.Info(_(u'Copying the points.'))
if os.path.splitext(os.path.basename(pointFeatures))[0].lower()
!= 'copiedpoints': # Our temp name has to be different than
pointFeatures, so we can join the two.
copiedPoints = os.path.join(tempGeoDB, 'CopiedPoints')
else:
copiedPoints = os.path.join(tempGeoDB, 'CopiedPoints1')
if gp.Exists(copiedPoints):
gp.Delete(copiedPoints)
gp.CopyFeatures_management(pointsLayer, copiedPoints)
finally:
try:
gp.Delete(pointsLayer)
except:
pass
# If the points are not projected, or are projected but
# not in the near features' coordinate system, project
# them to the near features coordinate system.
#
# Note: Do not try to combine this with the copying step
# above. Unfortunately, for shapefiles, the ArcGIS 9.2
# Project tool ignores the where clause specified to Make
# Feature Layer and projects the entire shapefile, not
# just the features selected by the where clause.
if not pointsAreProjected or pointsAreProjected and nearAreProjected
and pointFeaturesCS.lower() != nearFeaturesCS.lower():
Logger.Info(_(u'Projecting the points to the near features\'
coordinate system.'))
if os.path.splitext(os.path.basename(pointFeatures))[0].lower()
!= 'projectedpoints': # Our temp name has to be different than
pointFeatures, so we can join the two.
projectedPoints = os.path.join(tempGeoDB, 'ProjectedPoints')
else:
projectedPoints = os.path.join(tempGeoDB, 'ProjectedPoints1')
if gp.Exists(projectedPoints):
gp.Delete(projectedPoints)
gp.Project_management(copiedPoints, projectedPoints,
nearFeaturesCS)
# Otherwise, the points are already in the desired coordinate
# system and we can just use the ones that we copied.
else:
projectedPoints = copiedPoints
# We are now going to do any necessary processing with the
# near features prior to running the Near_analysis tool. If
# the near features are a shapefile, we have an important
# constraint: ArcGIS tools such as Select_analysis and
# CopyFeatures_management, when provided a where clause, do
# not assign the FIDs of the output features to those of the
# input shapefile features. They renumber the FIDs starting
# with 0. But we must keep the original FIDs throughout our
# processing because we need Near_analysis to populate the
# NEAR_FID field with the original FIDs. (We got around this
# problem with the point features by requiring the caller to
# copy the FIDs to the tempJoinFIDField field, but we cannot
# do that with the near features because we want to treat them
# as read-only.)
#
# First, project the near features, if necessary. To maximize
# performance and minimize space utilization, we can omit
# fields that are not referenced by the caller's where clause
# (if any).
if not nearAreProjected:
Logger.Info(_(u'Projecting the near features to the points\'
coordinate system.'))
nearFeaturesLayer = GeoprocessorManager.GetUniqueLayerName()
fieldInfo = []
fieldsToIgnore = [pointFeaturesDescribe.ShapeFieldName,
pointFeaturesDescribe.OIDFieldName]
fields = gp.ListFields(nearFeatures)
f = fields.Next()
while f is not None:
if f.Name not in fieldsToIgnore:
if whereNearFeatures is None or f.Name.lower() not in
whereNearFeatures.lower():
fieldInfo.append(f.Name + ' ' + f.Name + ' HIDDEN')
else:
fieldInfo.append(f.Name + ' ' + f.Name + ' VISIBLE')
f = fields.Next()
fieldInfo = ';'.join(fieldInfo)
if not nearFeaturesInShapefile:
gp.MakeFeatureLayer_management(nearFeatures,
nearFeaturesLayer, whereNearFeatures, None, fieldInfo) # If not a
shapefile, Project_management will honor the where clause and maintain
original OBJECTIDs in the output, so we might as well apply whereNearFeatures
else:
gp.MakeFeatureLayer_management(nearFeatures,
nearFeaturesLayer, None, None, fieldInfo) # If a shapefile,
Project_management will ignore the where clause and project all the points
anyway
try:
if nearFeaturesInShapefile:
projectedNearFeatures = os.path.join(tempDir,
'ProjectedNear.shp')
else:
projectedNearFeatures = os.path.join(tempGeoDB,
'ProjectedNear')
if gp.Exists(projectedNearFeatures):
gp.Delete(projectedNearFeatures)
gp.Project_management(nearFeatures, projectedNearFeatures,
pointFeaturesCS)
finally:
try:
gp.Delete(nearFeaturesLayer)
except:
pass
# If we did not need to project the near features, we can just
# use them directly.
else:
projectedNearFeatures = nearFeatures
# Create a feature layer that selects the near features
# specified by the caller's where clause (if any).
convertedNearFeaturesToLines = False
projectedNearLayer = GeoprocessorManager.GetUniqueLayerName()
gp.MakeFeatureLayer_management(projectedNearFeatures,
projectedNearLayer, whereNearFeatures)
try:
# Determine if the near features are empty.
totalNearFeatures = gp.GetCount_management(projectedNearLayer)
if totalNearFeatures <= 0:
if whereNearFeatures is not None:
Logger.Info(_(u'The where clause %(where)s did not select
any features from near feature class %(near)s. All points will be updated
with NULL values (or the equivalent).') % {u'where': whereNearFeatures,
u'near': nearFeatures})
else:
Logger.Info(_(u'The near feature class %(near)s is empty.
All points will be updated with NULL values (or the equivalent).') %
{u'near': nearFeatures})
else:
# The near features are not empty. If they are
# polylines or polygons, we need to do some special
# processing. If they are polygons, we need to convert
# them to polylines, because the ArcGIS 9.2 and lower
# Near_analysis tool cannot operate on polygons. Also,
# regardless of whether the caller provided polylines
# or we got some by converting the caller's polygons,
# we have to work around an apparent bug that exists
# in ArcGIS 9.2 that causes Near_analysis to not work
# right on polylines that contain more than two
# vertices (i.e. polylines that contain multiple line
# segments). With Arc 9.2 SP6, I noticed Near was
# calculating the distance to the wrong polylines.
# This seemed to be rectified if I split the lines
# using the Split Lines at Vertices tool.
#
# So: First call Feature To Line. If the near features
# are polygons, it will convert them to polylines. If
# they are polylines already, it will copy them. In
# both cases, Feature To Line will add a FID field
# that we can reference later, to obtain the FID of
# the original feature (polygon or polyline).
#
# Next: Call Split Lines at Vertices to produce a
# feature class of lines having only two vertices.
#
# TODO: Check whether we can omit these steps with Arc
# 9.3. The 9.3 Near tool appears to have been
# completely rewritten.
if nearFeaturesDescribe.ShapeType.lower() in ['polygon',
'polyline']:
if nearFeaturesDescribe.ShapeType.lower() == 'polygon':
Logger.Info(_(u'Converting the polygons to lines.'))
else:
Logger.Info(_(u'Copying the near features.'))
convertedLinesBeforeSplit = os.path.join(tempGeoDB,
'ConvertedLinesBeforeSplit')
if gp.Exists(convertedLinesBeforeSplit):
gp.Delete(convertedLinesBeforeSplit)
gp.FeatureToLine_management(projectedNearLayer,
convertedLinesBeforeSplit)
Logger.Info(_(u'Splitting the lines to work around a bug
in the ArcGIS Near tool.'))
convertedLines = os.path.join(tempGeoDB, 'ConvertedLines')
if gp.Exists(convertedLines):
gp.Delete(convertedLines)
gp.SplitLine_management(convertedLinesBeforeSplit,
convertedLines)
convertedNearFeaturesToLines = True
Logger.Info(_(u'Finding the near features nearest to the
points.'))
# Run Near_analysis. Run it even if there are no near
# features, so it will add the fields to the point feature
# class.
if angleField is not None:
angleParam = u'ANGLE'
else:
angleParam = u'NO_ANGLE'
if convertedNearFeaturesToLines:
gp.Near_analysis(projectedPoints, convertedLines,
searchRadius, u'NO_LOCATION', angleParam)
else:
gp.Near_analysis(projectedPoints, projectedNearLayer,
searchRadius, u'NO_LOCATION', angleParam)
# Delete the near features layer.
finally:
try:
gp.Delete(projectedNearLayer)
except:
pass
# If the near features are polygons or polylines, we converted
# them to single-segment lines prior to running Near_analysis.
# Near_analysis stored the line FIDs in the NEAR_FID field.
# But we need the FIDs of the original polygons or polylines.
# FeatureToLine_management added them to the lines as an
# attribute. Now, add a field called NEAR_FID2 and populate it
# with the original FIDs.
NEAR_FID_FieldName = 'NEAR_FID'
if convertedNearFeaturesToLines:
# Add NEAR_FID2 to the temporary projected points in the
# geodatabase, initializing it to -1.
from GeoEco.DatabaseAccess.ArcGIS import
ArcGIS91DatabaseConnection
conn = ArcGIS91DatabaseConnection()
NEAR_FID_FieldName = 'NEAR_FID2'
conn.AddField(projectedPoints, 'NEAR_FID2', 'LONG')
gp.CalculateField_management(projectedPoints, 'NEAR_FID2', '-1')
# Join the projected points to the lines and copy the
# original FIDs to NEAR_FID2.
projectedPointsLayer = GeoprocessorManager.GetUniqueLayerName()
gp.MakeFeatureLayer_management(projectedPoints,
projectedPointsLayer)
try:
gp.AddJoin_management(projectedPointsLayer, 'NEAR_FID',
convertedLines, gp.Describe(convertedLines).OIDFieldName, 'KEEP_COMMON')
try:
if gp.GetCount_management(projectedPointsLayer) > 0:
gp.CalculateField_management(projectedPointsLayer,
os.path.basename(projectedPoints) + '.NEAR_FID2', '[ConvertedLines.' +
conn.GetFieldNameAtIndex(convertedLines, 2) + ']')
finally:
gp.RemoveJoin_management(projectedPointsLayer,
'ConvertedLines')
# If the near features are polygons, it is possible
# that some of the points overlap them. We need to
# detect this, for two reasons:
#
# 1) Near_analysis calculated the distance to the edge of
# the polygon. The caller might want us to set the
# distance to zero or negative.
#
# 2) If the caller's polygons shared borders (e.g.
# adjacent cells of a grid), those borders were
# converted to overlapping lines. We don't know which
# line Near_analysis picked as the nearest. If it
# picked the line corresponding to the adjacent
# polygon, it would cause us to obtain the FID and
# other desired fields from that polygon, rather than
# the one that the point overlaps. The caller wants the
# overlapped polygon.
#
# So: intersect the points with the polygons, join the
# resulting feature class back to the points, copy the
# FIDs from the intersecting polygons to the NEAR_FID2
# field fo the points, and adjust the NEAR_DIST field as
# requested by the caller.
if nearFeaturesDescribe.ShapeType.lower() == 'polygon':
Logger.Info(_(u'Intersecting the points with the polygons
to detect points that overlap the polygons.'))
intersectedPoints = os.path.join(tempGeoDB,
'IntersectedPoints')
if gp.Exists(intersectedPoints):
gp.Delete(intersectedPoints)
projectedNearLayer =
GeoprocessorManager.GetUniqueLayerName()
gp.MakeFeatureLayer_management(projectedNearFeatures,
projectedNearLayer, whereNearFeatures)
try:
# Unlike previous releases, the Intersect tool
# in ArcGIS 9.3 will fail with the error
# "ERROR 000953: Extent of the overlay
# operation will be empty." if no points
# intersect the polygons. This problem can be
# avoided by explicitly specifying the Extent
# environment setting. I consider this a bug
# in ArcGIS since it worked in the previous
# release.
if GeoprocessorManager.GetArcGISMajorVersion() > 9 or
GeoprocessorManager.GetArcGISMajorVersion() == 9 and
GeoprocessorManager.GetArcGISMinorVersion() >= 3:
oldExtent = gp.Extent
gp.Extent = 'MAXOF'
try:
gp.Intersect_analysis(projectedPoints + ' #;' +
projectedNearLayer + ' #', intersectedPoints, 'ONLY_FID')
finally:
if GeoprocessorManager.GetArcGISMajorVersion() >
9 or GeoprocessorManager.GetArcGISMajorVersion() == 9 and
GeoprocessorManager.GetArcGISMinorVersion() >= 3:
gp.Extent = oldExtent
finally:
try:
gp.Delete(projectedNearLayer)
except:
pass
gp.AddJoin_management(projectedPointsLayer,
gp.Describe(projectedPoints).OIDFieldName, intersectedPoints,
conn.GetFieldNameAtIndex(intersectedPoints, 2), 'KEEP_COMMON')
try:
if gp.GetCount_management(projectedPointsLayer) > 0:
pointsFCName = os.path.basename(projectedPoints)
gp.CalculateField_management(projectedPointsLayer, pointsFCName +
'.NEAR_FID2', '[IntersectedPoints.' +
conn.GetFieldNameAtIndex(convertedLines, 2) + ']')
if distanceField is not None:
if overlappingPolygonDistance == 'zero':
gp.CalculateField_management(projectedPointsLayer, pointsFCName +
'.NEAR_DIST', '0')
elif overlappingPolygonDistance == 'negative':
gp.CalculateField_management(projectedPointsLayer, pointsFCName +
'.NEAR_DIST', '0 - [' + pointsFCName + '.NEAR_DIST]')
finally:
gp.RemoveJoin_management(projectedPointsLayer,
'IntersectedPoints')
# Delete the projected point features layer that we had to
# create to accomplish the joins.
finally:
try:
gp.Delete(projectedPointsLayer)
except:
pass
# We are now ready to populate the caller's specified fields
# of pointFeatures. Join projectedPoints to pointFeatures on
# tempJoinFIDField.
Logger.Info(_(u'Updating the points\' fields.'))
pointsLayer = GeoprocessorManager.GetUniqueLayerName()
gp.MakeFeatureLayer_management(pointFeatures, pointsLayer)
try:
pointsFCName =
os.path.splitext(os.path.basename(pointFeatures))[0]
projectedPointsFCName = os.path.basename(projectedPoints)
gp.AddJoin_management(pointsLayer, tempJoinFIDField,
projectedPoints, tempJoinFIDField, 'KEEP_COMMON')
try:
# Copy the NEAR_FID (or NEAR_FID2), NEAR_DIST, and
# NEAR_ANGLE to the callers specified fields of
# pointFeatures. If the caller did not specify a
# fidField, we copy NEAR_FID (or NEAR_FID2) to a
# temporary field that we created.
gp.CalculateField_management(pointsLayer, pointsFCName + '.'
+ tempNearFIDField, '[' + projectedPointsFCName + '.' + NEAR_FID_FieldName +
']') # Note: if fidField was specified by the caller, tempNearFIDField
== fidField
if distanceField is not None:
gp.CalculateField_management(pointsLayer, pointsFCName +
'.' + distanceField, '[' + projectedPointsFCName + '.NEAR_DIST]')
if angleField is not None:
gp.CalculateField_management(pointsLayer, pointsFCName +
'.' + angleField, '[' + projectedPointsFCName + '.NEAR_ANGLE]')
# If the caller specified fields to copy from the near
# features to the point features, join the near
# features to pointsLayer on fidField (or
# tempNearFIDField) and copy the fields.
if nearestFieldsToCopy is not None:
gp.SelectLayerByAttribute_management(pointsLayer,
'NEW_SELECTION', pointsFCName + '.' + tempNearFIDField + ' >= 0')
if gp.GetCount_management(pointsLayer) > 0:
nearFCName =
os.path.splitext(os.path.basename(nearFeatures))[0]
gp.AddJoin_management(pointsLayer, tempNearFIDField,
nearFeatures, nearFeaturesDescribe.OIDFieldName, 'KEEP_COMMON')
try:
for i in range(len(nearestFieldsToCopy)):
gp.CalculateField_management(pointsLayer,
destinationPointFields[i], '[' + nearFCName + '.' + nearestFieldsToCopy[i] +
']')
finally:
gp.RemoveJoin_management(pointsLayer, nearFCName)
# At this point, fidField (or tempNearFIDField) of
# pointFeatures has -1 for all points for which there
# was no near feature. Select these points and set
# their various fields to NULL, or the equivalent.
gp.SelectLayerByAttribute_management(pointsLayer,
'NEW_SELECTION', pointsFCName + '.' + tempNearFIDField + ' = -1')
if gp.GetCount_management(pointsLayer) > 0:
if distanceField is not None:
gp.CalculateField_management(pointsLayer,
pointsFCName + '.' + distanceField, str(distanceFieldNullValue))
if angleField is not None:
gp.CalculateField_management(pointsLayer,
pointsFCName + '.' + angleField, str(angleFieldNullValue))
if nearestFieldsToCopy is not None:
for i in range(len(nearestFieldsToCopy)):
gp.CalculateField_management(pointsLayer,
pointsFCName + '.' + destinationPointFields[i],
str(destinationPointFieldsNullValues[i]))
if fidField is not None and fidFieldNullValue != -1:
gp.CalculateField_management(pointsLayer,
pointsFCName + '.' + fidField, str(fidFieldNullValue)) # Not sure if
this must be done last, but doing it anyway, for safety
finally:
gp.RemoveJoin_management(pointsLayer, projectedPointsFCName)
finally:
try:
gp.Delete(pointsLayer)
except:
pass
@classmethod
def FindNearestFeaturesListedInField(cls, pointFeatures,
nearFeaturesField, searchRadius=None, fidField=None, distanceField=None,
angleField=None, overlappingPolygonDistance=u'Zero', wherePointFeatures=None,
whereNearFeaturesField=None, nearestFieldsToCopy=None,
destinationPointFields=None):
cls.__doc__.Obj.ValidateMethodInvocation()
try:
# If the caller did not specify any fields to copy from
# the near features to the point features, validate and/or
# create the point fields now.
#
# If they did specify fields to copy, we can't perform
# this validation until we obtain one of the near feature
# classes or layers, so we can examine the data types of
# the fields.
if nearestFieldsToCopy is None:
fidField, distanceField, angleField, nearestFieldsToCopy,
destinationPointFields, fidFieldNullValue, distanceFieldNullValue,
angleFieldNullValue, destinationPointFieldsNullValues, tempJoinFIDField,
tempNearFIDField = cls._ValidateAndCreatePointFields(pointFeatures,
nearFeatures, fidField, distanceField, angleField, nearestFieldsToCopy,
destinationPointFields)
try:
# Use the Frequency_analysis tool to count the unique
# combinations of near features and where clauses present
# in the caller's table. We must call _FindNearestFeatures
# once with each unique combination.
if whereNearFeaturesField is None:
Logger.Info(_(u'Enumerating the unique near feature
classes listed in the %(field)s field.') % {u'field': nearFeaturesField})
else:
Logger.Info(_(u'Enumerating the unique combinations of
near feature classes listed in the %(field1)s field and where clauses listed
in the %(field2)s field.') % {u'field1': nearFeaturesField, u'field2':
whereNearFeaturesField})
from GeoEco.ArcGIS import GeoprocessorManager
gp = GeoprocessorManager.GetWrappedGeoprocessor()
from GeoEco.DatabaseAccess.ArcGIS import
ArcGIS91DatabaseConnection
conn = ArcGIS91DatabaseConnection()
from GeoEco.DataManagement.Directories import
TemporaryDirectory
tempDir = TemporaryDirectory()
nearFeatureCombos = None
pointsLayer = GeoprocessorManager.GetUniqueLayerName()
gp.MakeFeatureLayer_management(pointFeatures, pointsLayer,
wherePointFeatures)
try:
if gp.GetCount_management(pointsLayer) > 0:
nearFeatureCombos = []
# Run Frequency_analysis to produce DBF file in a
# temp directory.
freqTable = os.path.join(tempDir.Path,
GeoprocessorManager.GetUniqueLayerName() + '.dbf')
if whereNearFeaturesField is None:
gp.Frequency_analysis(pointsLayer, freqTable,
nearFeaturesField)
else:
gp.Frequency_analysis(pointsLayer, freqTable,
nearFeaturesField + ';' + whereNearFeaturesField)
# Read the DBF file and populate nearFeatureCombos.
nfField = conn.GetFieldNameAtIndex(freqTable, 2)
if whereNearFeaturesField is not None:
wcField = conn.GetFieldNameAtIndex(freqTable, 3)
warnedAboutNull = False
cur = conn.OpenSelectCursor(freqTable)
try:
while cur.NextRow():
nf = cur.GetValue(nfField)
if nf is not None:
nf = nf.strip()
if len(nf) <= 0:
nf = None
if nf is None:
if not warnedAboutNull:
Logger.Warning(_(u'At least one point
contains NULL or an empty string in the %(field)s field. These points will be
ignored.') % {u'field': nearFeaturesField})
warnedAboutNull = True
else:
if whereNearFeaturesField is None:
nearFeatureCombos.append([nf, None])
else:
wc = cur.GetValue(wcField) #
Note: do not convert empty strings or sequences of just whitespace to None
here. This will be handled later.
nearFeatureCombos.append([nf, wc])
pass
finally:
del cur
# Sort nearFeatureCombos, so we process them in a
# deterministic order.
nearFeatureCombos.sort()
finally:
try:
gp.Delete(pointsLayer)
except:
pass
# If we didn't get any points with near features, return
# now.
if nearFeatureCombos is None or len(nearFeatureCombos) <= 0:
if nearFeatureCombos is None:
if wherePointFeatures is None:
Logger.Info(_('The point feature class does not
contain any points. There is no work to do.'))
else:
Logger.Info(_('The where clause did not select
any points from the point feature class. There is no work to do.'))
if nearestFieldsToCopy is not None:
Logger.Warning(_(u'You requested that fields be
copied from the near features to the points, but you did not provide any
points. As a consequence, this tool could not examine the data types of those
fields in the near features for the purpose of creating those fields in the
point features, or, if the fields already exist, validating their data types.
The point fields were not checked or created.'))
else:
if wherePointFeatures is None:
Logger.Info(_('The point feature class does not
contain any points that contain a near feature class in the %(field)s field.
There is no work to do.') % {u'field': nearFeaturesField})
else:
Logger.Info(_('The where clause did not select
any points from the point feature class that contain a near feature class in
the %(field)s field. There is no work to do.') % {u'field':
nearFeaturesField})
if nearestFieldsToCopy is not None:
Logger.Warning(_(u'You requested that fields be
copied from the near features to the points, but none of the points contained
near features. As a consequence, this tool could not examine the data types
of those fields in the near features for the purpose of creating those fields
in the point features, or, if the fields already exist, validating their data
types. The point fields were not checked or created.'))
return pointFeatures
# Create a temp geodatabase to hold temp feature classes.
tempGeoDB = os.path.join(tempDir.Path, 'Temp.mdb')
gp.CreatePersonalGDB_management(tempDir.Path, 'Temp')
try:
# Process each unique combination in nearFeatureCombos.
fidFieldNullValue = None
distanceFieldNullValue = None
angleFieldNullValue = None
destinationPointFieldsNullValues = None
for i in range(len(nearFeatureCombos)):
# If the caller asked us to copy fields from the
# near features to the points and this is the
# first time through the loop, we will not have
# validated the point fields yet. Do it now.
if i <= 0 and nearestFieldsToCopy is not None:
if not gp.Exists(nearFeatureCombos[i][0]):
Logger.RaiseException(ValueError(_(u'The near
feature class %(fc)s does not exist.') % {u'fc': nearFeatureCombos[i][0]}))
fidField, distanceField, angleField,
nearestFieldsToCopy, destinationPointFields, fidFieldNullValue,
distanceFieldNullValue, angleFieldNullValue,
destinationPointFieldsNullValues, tempJoinFIDField, tempNearFIDField =
cls._ValidateAndCreatePointFields(pointFeatures, nearFeatureCombos[i][0],
fidField, distanceField, angleField, nearestFieldsToCopy,
destinationPointFields)
# If this is the first time through the loop,
# start the progress reporter.
if i <= 0:
if whereNearFeaturesField is None:
Logger.Info(_(u'Finding nearest features for
%(count)i unique feature classes listed in the %(field)s field.') %
{u'count': len(nearFeatureCombos), u'field': nearFeaturesField})
else:
Logger.Info(_(u'Finding nearest features for
%(count)i unique combinations of near feature classes listed in the
%(field1)s field and where clauses listed in the %(field2)s field.') %
{u'count': len(nearFeatureCombos), u'field1': nearFeaturesField, u'field2':
whereNearFeaturesField})
progressReporter = ProgressReporter()
progressReporter.Start(len(nearFeatureCombos))
# Call _FindNearestFeatures on this combination.
where1 = u'%s = \'%s\'' % (nearFeaturesField,
nearFeatureCombos[i][0])
if whereNearFeaturesField is not None:
if nearFeatureCombos[i][1] is not None:
where1 = u' AND '.join([where1, u'%s =
\'%s\'' % (whereNearFeaturesField, nearFeatureCombos[i][1].replace("'",
"''"))])
else:
where1 = u' AND '.join([where1, u'%s IS NULL'
% whereNearFeaturesField])
if wherePointFeatures is not None:
where1 = u' AND '.join([where1,
wherePointFeatures])
where2 = nearFeatureCombos[i][1]
if where2 is not None and len(where2.strip()) <= 0:
# Now treat empty strings and sequences of whitespace as None. We didn't
want to do it in where1 above, because that would cause us to not select the
proper points.
where2 = None
oldLogInfoAsDebug = Logger.GetLogInfoAsDebug()
Logger.SetLogInfoAsDebug(True)
try:
cls._FindNearestFeatures(tempDir=tempDir.Path,
tempGeoDB=tempGeoDB,
pointFeatures=pointFeatures,
tempJoinFIDField=tempJoinFIDField,
tempNearFIDField=tempNearFIDField,
nearFeatures=nearFeatureCombos[i][0],
searchRadius=searchRadius,
fidField=fidField,
fidFieldNullValue=fidFieldNullValue,
distanceField=distanceField,
distanceFieldNullValue=distanceFieldNullValue,
angleField=angleField,
angleFieldNullValue=angleFieldNullValue,
overlappingPolygonDistance=overlappingPolygonDistance,
wherePointFeatures=where1,
whereNearFeatures=where2,
nearestFieldsToCopy=nearestFieldsToCopy,
destinationPointFields=destinationPointFields,
destinationPointFieldsNullValues=destinationPointFieldsNullValues)
finally:
Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
# Report our progress.
progressReporter.ReportProgress()
if i == 1:
break # TODO: REMOVE
# Delete the temp geodatabase. If we do not explicitly
# delete it here, the geoprocessor will keep a handle
# open through MS Access APIs, and the temporary
# directory will not be able to be deleted.
finally:
try:
pass
#gp.Delete_management(tempGeoDB) # TODO: ENABLE
except:
pass
# Delete the temporary fields that
# _ValidateAndCreatePointFields created in the caller's
# points.
finally:
from GeoEco.DatabaseAccess.ArcGIS import
ArcGIS91DatabaseConnection
conn = ArcGIS91DatabaseConnection()
try:
conn.DeleteField(pointFeatures, tempJoinFIDField) #
DeleteField succeeds silently if the field does not exist.
except:
pass
if fidField is None:
try:
conn.DeleteField(pointFeatures, tempNearFIDField)
except:
pass
except:
Logger.LogExceptionAsError()
raise
# Return successfully.
return pointFeatures
###############################################################################
# Metadata: module
###############################################################################
from GeoEco.ArcGIS import ArcGISDependency, ArcGISProductDependency
from GeoEco.DatabaseAccess import InsertCursor
from GeoEco.Metadata import *
from GeoEco.Types import *
AddModuleMetadata(shortDescription=_(u'Provides methods for general-purpose
operations with points.'))
###############################################################################
# Metadata: ArcGISPoints class
###############################################################################
AddClassMetadata(ArcGISPoints,
shortDescription=_(u'Provides methods for general-purpose operations with
ArcGIS points.'),
isExposedAsCOMServer=True,
comIID=u'{AB7A5328-0568-448B-9F7B-1E969F9F4241}',
comCLSID=u'{E640B02D-4A18-480F-A458-543AA360E153}')
# Public method: ArcGISPoints.InsertPoint
AddMethodMetadata(ArcGISPoints.InsertPoint,
shortDescription=_(u'Inserts a point with an insert cursor opened to an
ArcGIS point feature class.'),
isExposedToPythonCallers=True,
dependencies=[ArcGISDependency(9, 1)])
AddArgumentMetadata(ArcGISPoints.InsertPoint, u'cls',
typeMetadata=ClassOrClassInstanceTypeMetadata(cls=ArcGISPoints),
description=_(u'%s class or an instance of it.') % ArcGISPoints.__name__)
AddArgumentMetadata(ArcGISPoints.InsertPoint, u'insertCursor',
typeMetadata=ClassInstanceTypeMetadata(cls=InsertCursor),
description=_(
u"""Insert cursor opened to the feature class that will receive the
point. The cursor will still be open when this function returns."""))
AddArgumentMetadata(ArcGISPoints.InsertPoint, u'x',
typeMetadata=FloatTypeMetadata(),
description=_(u"""X coordinate of the point."""))
AddArgumentMetadata(ArcGISPoints.InsertPoint, u'y',
typeMetadata=FloatTypeMetadata(),
description=_(u"""Y coordinate of the point."""))
AddArgumentMetadata(ArcGISPoints.InsertPoint, u'z',
typeMetadata=FloatTypeMetadata(canBeNone=True),
description=_(
u"""Z coordinate of the point. Only provide this if the feature class
has Z coordinates."""))
AddArgumentMetadata(ArcGISPoints.InsertPoint, u'm',
typeMetadata=FloatTypeMetadata(canBeNone=True),
description=_(
u"""Meaure value of the point. Only provide this if the feature class
has measure values."""))
AddArgumentMetadata(ArcGISPoints.InsertPoint, u'attributes',
typeMetadata=DictionaryTypeMetadata(keyType=UnicodeStringTypeMetadata(),
valueType=AnyObjectTypeMetadata(), canBeNone=True),
description=_(
u"""Dictionary of polygon attributes (a.k.a. fields) to set before
inserting the point. The dictionary's keys and values are the
attribute's names and values."""))
AddArgumentMetadata(ArcGISPoints.InsertPoint, u'shapeFieldName',
typeMetadata=UnicodeStringTypeMetadata(),
description=_(
u"""Name of the shape field (the geometry field) for the cursor. This
may be obtained from the ShapeFieldName property of object returned by
the geoprocessor's Describe method."""))
# Public method: ArcGISPoints.AppendPointsToFeatureClass
AddMethodMetadata(ArcGISPoints.AppendPointsToFeatureClass,
shortDescription=_(u'Appends points to an existing ArcGIS point feature
class.'),
isExposedToPythonCallers=True,
dependencies=[ArcGISDependency(9, 1)])
CopyArgumentMetadata(ArcGISPoints.InsertPoint, u'cls',
ArcGISPoints.AppendPointsToFeatureClass, u'cls')
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass, u'featureClass',
typeMetadata=ArcGISFeatureClassTypeMetadata(allowedShapeTypes=[u'Point'],
mustExist=True),
description=_(u"""Feature class that will receive the points."""),
arcGISDisplayName=_(u'Point feature class'))
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass, u'coordinates',
typeMetadata=ListTypeMetadata(elementType=FloatTypeMetadata(),
minLength=2, canBeNone=True),
description=_(
u"""List of coordinates for the points to insert. If the points do not
have Z coordinates nor M values, the list must be of the form::
[x1, y1, x2, y2, x3, y3, ... ]
If the points have X, Y and Z coordinates but not M values, the list
must be of the form::
[x1, y1, z1, x2, y2, z2, x3, y3, z3, ... ]
If the points have X and Y coordinates and M values but no Z
coordinates, the list must be of the form::
[x1, y1, m1, x2, y2, m2, x3, y3, m3, ... ]
If the points have X, Y and Z coordinates and M values, the list must
be of the form::
[x1, y1, z1, m1, x2, y2, z2, m2, x3, y3, z3, m3, ... ]
"""))
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass, u'hasZ',
typeMetadata=BooleanTypeMetadata(),
description=_(
u"""Indicates whether or not the input list of coordinates contains Z
coordinates. If it does, you must pass True for this parameter."""))
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass, u'hasM',
typeMetadata=BooleanTypeMetadata(),
description=_(
u"""Indicates whether or not the input list of coordinates contains
measure values. If it does, you must pass True for this
parameter."""))
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass, u'attributes',
typeMetadata=ListTypeMetadata(elementType=DictionaryTypeMetadata(keyType=UnicodeStringTypeMetadata(),
valueType=AnyObjectTypeMetadata(), canBeNone=True), canBeNone=True),
description=_(
u"""List of dictionaries that parallels the list of coordinates. Each
dictionary defines the attributes (a.k.a. fields) to set for a point
before it is inserted. The dictionary's keys and values are the
attribute's names and values."""))
# Public method: ArcGISPoints.AppendPointsToFeatureClass2
AddMethodMetadata(ArcGISPoints.AppendPointsToFeatureClass2,
shortDescription=_(u'Appends points to an existing ArcGIS point feature
class.'),
isExposedToPythonCallers=True,
isExposedByCOM=True,
isExposedAsArcGISTool=True,
arcGISDisplayName=_(u'Append Points'),
arcGISToolCategory=_(u'Spatial Analysis\\Create Points'),
dependencies=[ArcGISDependency(9, 1)])
CopyArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass, u'cls',
ArcGISPoints.AppendPointsToFeatureClass2, u'cls')
CopyArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass,
u'featureClass', ArcGISPoints.AppendPointsToFeatureClass2, u'featureClass')
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2,
u'xyCoordinates',
typeMetadata=ListTypeMetadata(elementType=PointTypeMetadata(),
minLength=1),
description=_(
u"""X and Y coordinates of the points to create.
If you are invoking this tool programmatically, you must specify each
point as a string, as must be done when invoking an ArcGIS tool that
accepts a point as input. For example, to create three points when
invoking this tool from Python, you use the list::
[u'1 2', u'3 4', u'5 6']
"""),
arcGISDisplayName=_(u'Points'))
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2, u'zCoordinates',
typeMetadata=ListTypeMetadata(elementType=FloatTypeMetadata(),
canBeNone=True, mustBeSameLengthAsArgument=u'xyCoordinates'),
description=_(
u"""Z coordinates of the points to create.
If you are invoking this tool programmatically, specify these
coordinates as floating point numbers, not strings as is done with the
xyCoordinates parameter."""),
arcGISDisplayName=_(u'Z coordinates'),
arcGISCategory=_(u'Point options'))
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2, u'mValues',
typeMetadata=ListTypeMetadata(elementType=FloatTypeMetadata(),
canBeNone=True, mustBeSameLengthAsArgument=u'xyCoordinates'),
description=_(
u"""Measure values of the points to create.
If you are invoking this tool programmatically, specify these values
as floating point numbers, not strings as is done with the
xyCoordinates parameter."""),
arcGISDisplayName=_(u'M values'),
arcGISCategory=_(u'Point options'))
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2,
u'intAttrsToSet',
typeMetadata=ListTypeMetadata(elementType=ArcGISFieldTypeMetadata(mustExist=True,
allowedFieldTypes=[u'SHORT', u'LONG']), canBeNone=True),
description=_(
u"""LONG and SHORT integer attributes of the points that should be set
to the values you specify. This parameter specifies the names of the
attributes to set and the Integer Attribute Values parameter specifies
their values. If you create multiple points, they will all receive the
same attribute values.
This parameter is optional. If you do not set a particular attribute,
ArcGIS determines its default value. For shapefiles, it will be 0. For
geodatabases, it will be the default value specified by the database
schema, or NULL if the field is nullable and no default is
specified."""),
arcGISDisplayName=_(u'Integer attributes to set'),
arcGISCategory=_(u'Point options'),
arcGISParameterDependencies=[u'featureClass'])
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2,
u'intAttrValues',
typeMetadata=ListTypeMetadata(elementType=IntegerTypeMetadata(),
canBeNone=True, mustBeSameLengthAsArgument=u'intAttrsToSet'),
description=_(
u"""Values for the LONG and SHORT integer attributes to set for the
points. You must provide a value for each attribute you specified for
the Integer Attributes to Set parameter."""),
arcGISDisplayName=_(u'Integer attribute values'),
arcGISCategory=_(u'Point options'))
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2,
u'floatAttrsToSet',
typeMetadata=ListTypeMetadata(elementType=ArcGISFieldTypeMetadata(mustExist=True,
allowedFieldTypes=[u'FLOAT', u'DOUBLE']), canBeNone=True),
description=_(
u"""FLOAT and DOUBLE attributes of the points that should be set to
the values you specify. This parameter specifies the names of the
parameters to set and the Floating Point Attribute Values parameter
specifies their values. If you create multiple points, they will all
receive the same attribute values.
This parameter is optional. If you do not set a particular attribute,
ArcGIS determines its default value. For shapefiles, it will be 0. For
geodatabases, it will be the default value specified by the database
schema, or NULL if the field is nullable and no default is
specified."""),
arcGISDisplayName=_(u'Floating point attributes to set'),
arcGISCategory=_(u'Point options'),
arcGISParameterDependencies=[u'featureClass'])
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2,
u'floatAttrValues',
typeMetadata=ListTypeMetadata(elementType=FloatTypeMetadata(),
canBeNone=True, mustBeSameLengthAsArgument=u'floatAttrsToSet'),
description=_(
u"""Values for the FLOAT and DOUBLE attributes to set for the points.
You must provide a value for each attribute you specified for the
Floating Point Attributes to Set parameter."""),
arcGISDisplayName=_(u'Floating point attribute values'),
arcGISCategory=_(u'Point options'))
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2,
u'stringAttrsToSet',
typeMetadata=ListTypeMetadata(elementType=ArcGISFieldTypeMetadata(mustExist=True,
allowedFieldTypes=[u'TEXT']), canBeNone=True),
description=_(
u"""TEXT attributes of the points that should be set to the values you
specify. This parameter specifies the names of the parameters to set
and the Text Attribute Values parameter specifies their values. If you
create multiple points, they will all receive the same attribute
values.
This parameter is optional. If you do not set a particular attribute,
ArcGIS determines its default value. For shapefiles, it will be a
zero-length string. For geodatabases, it will be the default value
specified by the database schema, or NULL if the field is nullable and
no default is specified."""),
arcGISDisplayName=_(u'Text attributes to set'),
arcGISCategory=_(u'Point options'),
arcGISParameterDependencies=[u'featureClass'])
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2,
u'stringAttrValues',
typeMetadata=ListTypeMetadata(elementType=UnicodeStringTypeMetadata(),
canBeNone=True, mustBeSameLengthAsArgument=u'stringAttrsToSet'),
description=_(
u"""Values for the TEXT attributes to set for the points. You must
provide a value for each attribute you specified for the Text
Attributes to Set parameter."""),
arcGISDisplayName=_(u'Text attribute values'),
arcGISCategory=_(u'Point options'))
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2,
u'dateAttrsToSet',
typeMetadata=ListTypeMetadata(elementType=ArcGISFieldTypeMetadata(mustExist=True,
allowedFieldTypes=[u'DATE']), canBeNone=True),
description=_(
u"""DATE attributes of the points that should be set to the values you
specify. This parameter specifies the names of the parameters to set
and the Date Attribute Values parameter specifies their values. If you
create multiple points, they will all receive the same attribute
values.
This parameter is optional. If you do not set a particular attribute,
ArcGIS determines its default value. For shapefiles, it will be NULL.
For geodatabases, it will be the default value specified by the
database schema, or NULL if the field is nullable and no default is
specified."""),
arcGISDisplayName=_(u'Date attributes to set'),
arcGISCategory=_(u'Point options'),
arcGISParameterDependencies=[u'featureClass'])
AddArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2,
u'dateAttrValues',
typeMetadata=ListTypeMetadata(elementType=DateTimeTypeMetadata(),
canBeNone=True, mustBeSameLengthAsArgument=u'dateAttrsToSet'),
description=_(
u"""Values for the DATE attributes to set for the points. You must
provide a value for each attribute you specified for the Date
Attributes to Set parameter. Your date may include a time if the
underlying feature class supports it."""),
arcGISDisplayName=_(u'Date attribute values'),
arcGISCategory=_(u'Point options'),
arcGISParameterDependencies=[u'featureClass'])
AddResultMetadata(ArcGISPoints.AppendPointsToFeatureClass2,
u'updatedFeatureClass',
typeMetadata=ArcGISFeatureClassTypeMetadata(),
description=_(u"""Updated feature class containing the new points."""),
arcGISDisplayName=_(u'Updated feature class'),
arcGISParameterDependencies=[u'featureClass'])
# Public method: ArcGISPoints.CreateFeatureClassWithPoints
AddMethodMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
shortDescription=_(u'Creates points in a new ArcGIS point feature
class.'),
isExposedToPythonCallers=True,
dependencies=[ArcGISDependency(9, 1)])
CopyArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass, u'cls',
ArcGISPoints.CreateFeatureClassWithPoints, u'cls')
AddArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'featureClass',
typeMetadata=ArcGISFeatureClassTypeMetadata(deleteIfParameterIsTrue=u'overwriteExisting',
createParentDirectories=True),
description=_(u"""Output point feature class to create."""),
direction = u'Output',
arcGISDisplayName=_(u'Output point feature class'))
AddArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'spatialReference',
typeMetadata=SpatialReferenceTypeMetadata(),
description=_(u'Spatial reference for the output feature class.'),
arcGISDisplayName=_(u'Spatial reference'))
CopyArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass, u'coordinates',
ArcGISPoints.CreateFeatureClassWithPoints, u'coordinates')
CopyArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass, u'hasZ',
ArcGISPoints.CreateFeatureClassWithPoints, u'hasZ')
CopyArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass, u'hasM',
ArcGISPoints.CreateFeatureClassWithPoints, u'hasM')
CopyArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass, u'attributes',
ArcGISPoints.CreateFeatureClassWithPoints, u'attributes')
AddArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'configKeyword',
typeMetadata=UnicodeStringTypeMetadata(canBeNone=True),
description=_(
u"""The configuration keyword that determines the storage parameters
of the table in a Relational Database Management System
(RDBMS)--ArcSDE only."""),
arcGISDisplayName=_(u'Configuration keyword'),
arcGISCategory=_(u'Geodatabase settings for output feature class'))
AddArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'spatialGrid1',
typeMetadata=IntegerTypeMetadata(canBeNone=True, minValue=0),
description=_(
u"""The size of the output feature class's spatial grid index. The
following formats support spatial grid index grids: personal
geodatabase, file geodatabase or ArcSDE geodatabase. If not provided,
or if the value 0 is provided, a valid grid size will be calculated
automatically by ArcGIS."""),
arcGISDisplayName=_(u'Output spatial grid 1'),
arcGISCategory=_(u'Geodatabase settings for output feature class'))
AddArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'spatialGrid2',
typeMetadata=IntegerTypeMetadata(canBeNone=True, minValue=0),
description=_(
u"""The size of the output feature class's second spatial grid index.
The value must be at least three times larger than the first index
grid. The following formats support spatial grid index grids: personal
geodatabase, file geodatabase or ArcSDE geodatabase. Note that
personal geodatabases support only one spatial index grid."""),
arcGISDisplayName=_(u'Output spatial grid 2'),
arcGISCategory=_(u'Geodatabase settings for output feature class'))
AddArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'spatialGrid3',
typeMetadata=IntegerTypeMetadata(canBeNone=True, minValue=0),
description=_(
u"""The size of the output feature class's second spatial grid index.
The value must be at least three times larger than the second index
grid. The following formats support spatial grid index grids: personal
geodatabase, file geodatabase or ArcSDE geodatabase. Note that
personal geodatabases support only one spatial index grid."""),
arcGISDisplayName=_(u'Output spatial grid 3'),
arcGISCategory=_(u'Geodatabase settings for output feature class'))
AddArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'overwriteExisting',
typeMetadata=BooleanTypeMetadata(),
description=_(
u"""If True, the output feature class will be overwritten, if it
exists. If False, a ValueError will be raised if the output feature
class exists."""),
initializeToArcGISGeoprocessorVariable=u'OverwriteOutput')
# Public method: ArcGISPoints.CreateFeatureClassWithPoints2
AddMethodMetadata(ArcGISPoints.CreateFeatureClassWithPoints2,
shortDescription=_(u'Creates points in a new ArcGIS point feature
class.'),
isExposedToPythonCallers=True,
isExposedByCOM=True,
isExposedAsArcGISTool=True,
arcGISDisplayName=_(u'Create Points'),
arcGISToolCategory=_(u'Spatial Analysis\\Create Points'),
dependencies=[ArcGISDependency(9, 1)])
CopyArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints, u'cls',
ArcGISPoints.CreateFeatureClassWithPoints2, u'cls')
CopyArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'featureClass', ArcGISPoints.CreateFeatureClassWithPoints2, u'featureClass')
CopyArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'spatialReference', ArcGISPoints.CreateFeatureClassWithPoints2,
u'spatialReference')
CopyArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2,
u'xyCoordinates', ArcGISPoints.CreateFeatureClassWithPoints2,
u'xyCoordinates')
CopyArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2,
u'zCoordinates', ArcGISPoints.CreateFeatureClassWithPoints2, u'zCoordinates')
CopyArgumentMetadata(ArcGISPoints.AppendPointsToFeatureClass2, u'mValues',
ArcGISPoints.CreateFeatureClassWithPoints2, u'mValues')
CopyArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'configKeyword', ArcGISPoints.CreateFeatureClassWithPoints2,
u'configKeyword')
CopyArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'spatialGrid1', ArcGISPoints.CreateFeatureClassWithPoints2, u'spatialGrid1')
CopyArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'spatialGrid2', ArcGISPoints.CreateFeatureClassWithPoints2, u'spatialGrid2')
CopyArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'spatialGrid3', ArcGISPoints.CreateFeatureClassWithPoints2, u'spatialGrid3')
CopyArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints,
u'overwriteExisting', ArcGISPoints.CreateFeatureClassWithPoints2,
u'overwriteExisting')
# Public method: ArcGISPoints.FindNearestFeatures
AddMethodMetadata(ArcGISPoints.FindNearestFeatures,
shortDescription=_(u'For each point, finds the nearest feature and writes
its ID, distance, angle, and/or values of specified fields to fields of the
point.'),
isExposedToPythonCallers=True,
isExposedByCOM=True,
isExposedAsArcGISTool=True,
arcGISDisplayName=_(u'Find Nearest Features'),
arcGISToolCategory=_(u'Spatial Analysis\\Find Features Nearest to
Points'),
dependencies=[ArcGISDependency(9, 1),
ArcGISProductDependency(u'ArcInfo')])
CopyArgumentMetadata(ArcGISPoints.CreateFeatureClassWithPoints, u'cls',
ArcGISPoints.FindNearestFeatures, u'cls')
AddArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'pointFeatures',
typeMetadata=ArcGISFeatureClassTypeMetadata(allowedShapeTypes=[u'Point'],
mustExist=True),
description=_(
u"""Feature class containing points for which the nearest point, line,
or polygon feature should be found.
You must have an ArcInfo product license to use this tool. This tool
finds the nearest feature using the ArcGIS Near tool, which requires
ArcInfo.
Distances between features are calculated using the Pythagorean
theorem. This is known as Euclidean distance. The nearest feature is
the one with the smallest Euclidean distance.
Either the point features or the near features must be in a projected
coordinate system, so that Euclidean distance may be properly
calculated. If neither is in a projected coordinate system, an error
will be reported. If just one is in a projected coordinate system, the
other will be automatically projected to that system prior to
performing distance calculations. If they are in two different
projected coordinate systems, the points will be automatically
projected to the near feature's coordinate system. An error will be
reported if this is not possible without performing a geographic
transformation (e.g. the features use different datums). In this case,
you must manually project the points or the near features yourself,
prior to running this tool."""),
arcGISDisplayName=_(u'Point features'))
AddArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'nearFeatures',
typeMetadata=ArcGISFeatureClassTypeMetadata(allowedShapeTypes=[u'Point',
u'Polyline', u'Polygon'], mustExist=True), # Do not change this to
ArcGISFeatureLayerTypeMetadata
description=_(
u"""Feature class containing points, lines, or polygons.
This tool is not designed to operate on overlapping near features. If
the near features overlap, the behavior of this tool is undefined. It
may report a strange error, or it may appear to run successfully but
the results may not be correct. Please check the results carefully
when using overlapping near features.
It is ok if the points overlap the near features."""),
arcGISDisplayName=_(u'Near features'))
AddArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'searchRadius',
typeMetadata=LinearUnitTypeMetadata(canBeNone=True),
description=_(
u"""The maximum distance from a point to search for the nearest
feature. If not specified, the search radius is assumed to be
infinite."""),
arcGISDisplayName=_(u'Search radius'))
AddArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'fidField',
typeMetadata=UnicodeStringTypeMetadata(canBeNone=True),
description=_(
u"""Name of the point field that will receive the feature ID of the
nearest feature. In shapefiles, this is the value of the FID field. In
geodatabases, it is the value of the OBJECTID field.
This field must have the LONG data type. This field will be created if
it does not already exist.
If no feature is found within the specified search radius, NULL will
be stored in this field. If the field does not allow NULL (e.g. the
point features are a shapefile), -1 will be stored instead."""),
arcGISDisplayName=_(u'Field to receive nearest feature ID'))
AddArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'distanceField',
typeMetadata=UnicodeStringTypeMetadata(canBeNone=True),
description=_(
u"""Name of the point field that will receive the Euclidean distance
to the nearest feature.
This field must have the FLOAT or DOUBLE data type. This field will be
created with the DOUBLE data type if it does not already exist.
If no feature is found within the specified search radius, NULL will
be stored in this field. If the field does not allow NULL (e.g. the
point features are a shapefile), -999999999999 will be stored instead.
If the field is has the FLOAT data type, it may not be able to store
this value at full precision, so the value may be slightly
different."""),
arcGISDisplayName=_(u'Field to receive nearest feature distance'))
AddArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'angleField',
typeMetadata=UnicodeStringTypeMetadata(canBeNone=True),
description=_(
u"""Name of the point field that will receive the angle to the nearest
feature.
This field must have the FLOAT or DOUBLE data type. This field will be
created with the DOUBLE data type if it does not already exist.
Angles are measured in degrees, where one degree represents 1/360 of a
circle, and fractions of a degree are represented as decimal points.
Angles are measured from 180 to -180; 0 to the east, 90 to the north,
180 (or -180) to the west, and -90 to the south.
If no feature is found within the specified search radius, NULL will
be stored in this field. If the field does not allow NULL (e.g. the
point features are a shapefile), -9999 will be stored instead."""),
arcGISDisplayName=_(u'Field to receive nearest feature angle'))
AddArgumentMetadata(ArcGISPoints.FindNearestFeatures,
u'overlappingPolygonDistance',
typeMetadata=UnicodeStringTypeMetadata(allowedValues=[u'Zero',
u'Positive', u'Negative'], makeLowercase=True),
description=_(
u"""Distance algorithm that should be used for points that overlap
polygons.
This parameter is only used when the input near features are polygons
and you specify a field to receive the distance to the nearest
polygon.
This parameter only applies to points that overlap polygons. It
controls how distance is calculated for those points and may be one of
the following:
* Zero - the distance will be zero. This is the default. This is
appropriate when you want to know that the point intersected the
polygon; for example, when the points represent sightings of marine
animals and the polygons represent land and you want to know far the
animals are from land, with the value 0 meaning the animal is on or
over land.
* Positive - the distance will be positive. This is appropriate when
you want the distance to the polygon edge, regardless of whether the
point overlaps the polygon or not; for example, when the points
represent sightings of marine animals and the polygons represent
land and you want to know how far the animals are from the
shoreline, regardless of whether they are on water or land.
* Negative - the distance will be negative. This is appropriate when
you want the distance to the polygon edge, but need to know whether
the point overlapped the polygon or not. Overlapping points will
have negative distances and positive points will have positive
distances.
When a point does not overlap a polygon, this parameter is ignored and
the distance will be positive.
**WARNING:** If you specify a value for the Search Radius parameter,
points that overlap polygons and are farther than this radius from the
nearest polygon edge will have a distance of zero, regardless of what
distance algorithm you select here. To work around this problem, omit
your search radius. Then, after running this tool, construct a feature
layer that omits points with distances that exceed your desired
radius."""),
arcGISDisplayName=_(u'Distance to use when points overlap polygons'),
arcGISCategory=_(u'Additional options'))
AddArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'wherePointFeatures',
typeMetadata=SQLWhereClauseTypeMetadata(canBeNone=True),
description=_(
u"""SQL WHERE clause expression that specifies the subset of the
points to to use. If this parameter is not provided, all of the points
will be used.
**WARNING:** You should not reference FID, OID, or OBJECTID fields in
this expression. This tool uses the ArcGIS Add Join tool internally.
Add Join suffers some limitations that prevent correct operation when
those fields are referenced. To work around this problem, use the
ArcGIS Select tool to extract your desired points to a new feature
class and use that feature class instead.
The exact syntax of this expression depends on the type of feature
class that contains the near features. ESRI recommends you reference
fields using the following syntax:
* If the points are stored in an ArcInfo coverage or a shapefile,
enclose field names in double quotes in the SQL expression:
"MY_FIELD".
* If the points are stored in personal a geodatabase (.mdb file),
enclose field names in square brackets: [MY_FIELD].
* If the points are stored in an ArcSDE or ArcIMS feature
class, don't enclose field names: MY_FIELD."""),
arcGISDisplayName=_(u'Point features where clause'),
arcGISCategory=_(u'Additional options'),
arcGISParameterDependencies=[u'pointFeatures'])
AddArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'whereNearFeatures',
typeMetadata=SQLWhereClauseTypeMetadata(canBeNone=True),
description=_(
u"""SQL WHERE clause expression that specifies the subset of the near
features to to use. If this parameter is not provided, all of the near
features will be used.
The exact syntax of this expression depends on the type of feature
class that contains the near features. ESRI recommends you reference
fields using the following syntax:
* If the features are stored in an ArcInfo coverage or a shapefile,
enclose field names in double quotes in the SQL expression:
"MY_FIELD".
* If the features are stored in personal a geodatabase (.mdb file),
enclose field names in square brackets: [MY_FIELD].
* If the features are stored in an ArcSDE or ArcIMS feature
class, don't enclose field names: MY_FIELD."""),
arcGISDisplayName=_(u'Near features where clause'),
arcGISCategory=_(u'Additional options'),
arcGISParameterDependencies=[u'nearFeatures'])
AddArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'nearestFieldsToCopy',
typeMetadata=ListTypeMetadata(elementType=ArcGISFieldTypeMetadata(mustExist=True),
canBeNone=True, minLength=1),
description=_(
u"""Fields of the near features to copy to the points.
If you provide this parameter, you must also provide a field to
receive the feature ID of the near feature. An error will be reported
if you provide this parameter but omit that one.
WARNING: This tool uses the ArcGIS Calculate Fields tool to copy the
values from the near features' fields to the points' fields. Calculate
Fields cannot copy database NULL values and will report a strange
warning when asked to do so. As a result, for a given point, if a near
feature field contains NULL, the destination field of the point will
remain unchanged."""),
arcGISDisplayName=_(u'Fields of the near features to copy'),
arcGISCategory=_(u'Additional options'),
arcGISParameterDependencies=[u'nearFeatures'])
AddArgumentMetadata(ArcGISPoints.FindNearestFeatures,
u'destinationPointFields',
typeMetadata=ListTypeMetadata(elementType=UnicodeStringTypeMetadata(canBeNone=True),
canBeNone=True, minLength=1),
description=_(
u"""Names of the point fields to receive values copied from the near
feature fields.
If you omit this parameter, the tool will use the near feature field
names. If the point fields do not already exist, they will be created
using the data type and characteristics of the near feature fields. If
the point fields do already exist, the best results will be obtained
if they same data type and other characteristics as the near feature
fields. If the data type and other characteristics are not the same,
the value will be coerced to the destination field if possible. If
this is not possible, or it would result in a loss of data, an error
will be reported."""),
arcGISDisplayName=_(u'Fields to receive copied values'),
arcGISCategory=_(u'Additional options'))
AddResultMetadata(ArcGISPoints.FindNearestFeatures, u'updatedPointFeatures',
typeMetadata=ArcGISFeatureClassTypeMetadata(allowedShapeTypes=[u'Point']),
description=_(u"""Updated point features."""),
arcGISDisplayName=_(u'Updated point features'))
# Public method: ArcGISPoints._FindNearestFeatures
AddMethodMetadata(ArcGISPoints._FindNearestFeatures,
shortDescription=_(u'This private function implements
FindNearestFeatures.'))
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'cls',
ArcGISPoints._FindNearestFeatures, u'cls')
AddArgumentMetadata(ArcGISPoints._FindNearestFeatures, u'tempDir',
typeMetadata=UnicodeStringTypeMetadata(),
description=_(
u"""Path to the temp directory."""))
AddArgumentMetadata(ArcGISPoints._FindNearestFeatures, u'tempGeoDB',
typeMetadata=UnicodeStringTypeMetadata(),
description=_(
u"""Path to the temp geodatabase."""))
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'pointFeatures',
ArcGISPoints._FindNearestFeatures, u'pointFeatures')
AddArgumentMetadata(ArcGISPoints._FindNearestFeatures, u'tempJoinFIDField',
typeMetadata=UnicodeStringTypeMetadata(),
description=_(
u"""Name of the temp FID field for joining to the point features."""))
AddArgumentMetadata(ArcGISPoints._FindNearestFeatures, u'tempNearFIDField',
typeMetadata=UnicodeStringTypeMetadata(),
description=_(
u"""Name of the temp field of the near feature FID."""))
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'nearFeatures',
ArcGISPoints._FindNearestFeatures, u'nearFeatures')
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'searchRadius',
ArcGISPoints._FindNearestFeatures, u'searchRadius')
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'fidField',
ArcGISPoints._FindNearestFeatures, u'fidField')
AddArgumentMetadata(ArcGISPoints._FindNearestFeatures, u'fidFieldNullValue',
typeMetadata=AnyObjectTypeMetadata(canBeNone=True),
description=_(
u"""Value to be written to fidField to represent NULL."""))
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'distanceField',
ArcGISPoints._FindNearestFeatures, u'distanceField')
AddArgumentMetadata(ArcGISPoints._FindNearestFeatures,
u'distanceFieldNullValue',
typeMetadata=AnyObjectTypeMetadata(canBeNone=True),
description=_(
u"""Value to be written to distanceField to represent NULL."""))
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'angleField',
ArcGISPoints._FindNearestFeatures, u'angleField')
AddArgumentMetadata(ArcGISPoints._FindNearestFeatures, u'angleFieldNullValue',
typeMetadata=AnyObjectTypeMetadata(canBeNone=True),
description=_(
u"""Value to be written to angleField to represent NULL."""))
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures,
u'overlappingPolygonDistance', ArcGISPoints._FindNearestFeatures,
u'overlappingPolygonDistance')
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'wherePointFeatures',
ArcGISPoints._FindNearestFeatures, u'wherePointFeatures')
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'whereNearFeatures',
ArcGISPoints._FindNearestFeatures, u'whereNearFeatures')
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures,
u'nearestFieldsToCopy', ArcGISPoints._FindNearestFeatures,
u'nearestFieldsToCopy')
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures,
u'destinationPointFields', ArcGISPoints._FindNearestFeatures,
u'destinationPointFields')
AddArgumentMetadata(ArcGISPoints._FindNearestFeatures,
u'destinationPointFieldsNullValues',
typeMetadata=ListTypeMetadata(elementType=AnyObjectTypeMetadata(canBeNone=True),
canBeNone=True),
description=_(
u"""Values to be written to the destinationPointFields to represent NULL."""))
AddArgumentMetadata(ArcGISPoints._FindNearestFeatures,
u'skipArgumentValidation',
typeMetadata=BooleanTypeMetadata(),
description=_(
u"""If True, this function will skip the validation of the input
arguments against their GeoEco metadata. For efficiency, it is
intended that FindNearestFeatures will pass True to skip the
validation, because it already performs the validation."""))
# Public method: ArcGISPoints.FindNearestFeaturesListedInField
AddMethodMetadata(ArcGISPoints.FindNearestFeaturesListedInField,
shortDescription=_(u'For each point, using the feature class or layer
listed in a field, finds the nearest feature and writes its ID, distance,
angle, and/or values of specified fields to fields of the point. Use this
tool when you have a single point feature class but need to find distances to
different near feature classes or layers for different points.'),
isExposedToPythonCallers=True,
isExposedByCOM=True,
isExposedAsArcGISTool=True,
arcGISDisplayName=_(u'Find Nearest Features Listed in Field'),
arcGISToolCategory=_(u'Spatial Analysis\\Find Features Nearest to
Points'),
dependencies=[ArcGISDependency(9, 1),
ArcGISProductDependency(u'ArcInfo')])
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'cls',
ArcGISPoints.FindNearestFeaturesListedInField, u'cls')
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'pointFeatures',
ArcGISPoints.FindNearestFeaturesListedInField, u'pointFeatures')
AddArgumentMetadata(ArcGISPoints.FindNearestFeaturesListedInField,
u'nearFeaturesField',
typeMetadata=ArcGISFieldTypeMetadata(mustExist=True,
allowedFieldTypes=[u'TEXT']),
description=_(
u"""Field of the point features that lists the feature classes
containing near features to be used for each point. The near features
may be points, lines, or polygons.
Typically, you use the ArcGIS Calculate Field tool to populate this
field based on the other fields of the points. For example, if your
points represent observations of a marine animal and your near
features are polygons that show monthly sea ice extents, you would use
Calculate Field to compute the path and name of the of the sea ice
polygon feature class using the date that the animal was observed. If
you use a Visual Basic expression with Calculate Field too, the VB
date processing functions will often be useful; these include
DatePart, DateAdd, and DateDiff. If you use a Python expression, the
strptime function and the datetime module will often be useful.
This tool is not designed to operate on overlapping near features. If
the near features overlap, the behavior of this tool is undefined. It
may report a strange error, or it may appear to run successfully but
the results may not be correct. Please check the results carefully
when using overlapping near features.
It is ok if the points overlap the near features.
This tool is designed for efficient processing. Rather than processing
one point at a time, it processes points in batches, where each batch
consists of the points that reference the same near features."""),
arcGISDisplayName=_(u'Field listing near features'),
arcGISParameterDependencies=[u'pointFeatures'])
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'searchRadius',
ArcGISPoints.FindNearestFeaturesListedInField, u'searchRadius')
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'fidField',
ArcGISPoints.FindNearestFeaturesListedInField, u'fidField')
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'distanceField',
ArcGISPoints.FindNearestFeaturesListedInField, u'distanceField')
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'angleField',
ArcGISPoints.FindNearestFeaturesListedInField, u'angleField')
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures,
u'overlappingPolygonDistance', ArcGISPoints.FindNearestFeaturesListedInField,
u'overlappingPolygonDistance')
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures, u'wherePointFeatures',
ArcGISPoints.FindNearestFeaturesListedInField, u'wherePointFeatures')
AddArgumentMetadata(ArcGISPoints.FindNearestFeaturesListedInField,
u'whereNearFeaturesField',
typeMetadata=ArcGISFieldTypeMetadata(canBeNone=True, mustExist=True,
allowedFieldTypes=[u'TEXT']),
description=_(
u"""Field of the point features that contains a SQL WHERE clause
expression that specifies the subset of the near features to to use.
If this parameter is not provided, all of the near features will be
used.
Typically, you use the ArcGIS Calculate Field tool to populate this
field based on the other fields of the points. For example, if your
points represent observations of a marine animal and they all
reference a single feature class that contains a monthly time series
of sea ice polygons, you would use Calculate Field to produce
expressions that selected polygons for the date the animals were
observed.
The exact syntax of WHERE expressions depends on the types of feature
classes that contain the near features. ESRI recommends you reference
fields using the following syntax:
* If the features are stored in an ArcInfo coverages or shapefiles,
enclose field names in double quotes in the SQL expression:
"MY_FIELD".
* If the features are stored in personal geodatabases (.mdb files),
enclose field names in square brackets: [MY_FIELD].
* If the features are stored in ArcSDE or ArcIMS feature
classes, don't enclose field names: MY_FIELD.
"""),
arcGISDisplayName=_(u'Field listing near features where clauses'),
arcGISCategory=_(u'Additional options'),
arcGISParameterDependencies=[u'pointFeatures'])
AddArgumentMetadata(ArcGISPoints.FindNearestFeaturesListedInField,
u'nearestFieldsToCopy',
typeMetadata=ListTypeMetadata(elementType=UnicodeStringTypeMetadata(),
canBeNone=True, minLength=1),
description=_(
u"""Fields of the near features to copy to the points.
The fields you specify must exist in all of the near feature classes
or layers that are processed by the tool. A given field must have the
same data type and other characteristics in all of the feature classes
or layers. An error will be reported if the tool encounters a feature
class or layer that does not include all of the fields, or if the data
types and characteristics are not consistent."""),
arcGISDisplayName=_(u'Fields of the near features to copy'),
arcGISCategory=_(u'Additional options'))
CopyArgumentMetadata(ArcGISPoints.FindNearestFeatures,
u'destinationPointFields', ArcGISPoints.FindNearestFeaturesListedInField,
u'destinationPointFields')
CopyResultMetadata(ArcGISPoints.FindNearestFeatures, u'updatedPointFeatures',
ArcGISPoints.FindNearestFeaturesListedInField, u'updatedPointFeatures')
###############################################################################
# Names exported by this module
###############################################################################
__all__ = ['ArcGISPoints']