Esri / ArcREST

python package for REST API (AGS, AGOL, webmap JSON, etc..)
Apache License 2.0
192 stars 155 forks source link

Setting feature geometry equal to another feature #200

Closed DShokes closed 8 years ago

DShokes commented 8 years ago

I tried feature1.set_value('geometry', feature2.get_value('geometry')) and it returned True. I was expecting to see the feature1 object updated, but feature1.get_value('geometry') didn't change. This works for attribute fields.

Could this be fixed by adding an elif to the set_value function? Such as:

def set_value(self, field_name, value):
        """ sets an attribute value for a given field name """
        if field_name in self.fields:
            if not value is None:
                self._dict['attributes'][field_name] = _unicode_convert(value)
                self._json = json.dumps(self._dict, default=_date_handler)
            else:
                pass
        elif field_name.upper() in ['SHAPE', 'SHAPE@', "GEOMETRY"]:
            if isinstance(value, AbstractGeometry):
                if isinstance(value, Point):
                    self._dict['geometry'] = {
                    "x" : value.asDictionary['x'],
                    "y" : value.asDictionary['y']
                    }
                elif isinstance(value, MultiPoint):
                    self._dict['geometry'] = {
                        "points" : value.asDictionary['points']
                    }
                elif isinstance(value, Polyline):
                    self._dict['geometry'] = {
                        "paths" : value.asDictionary['paths']
                    }
                elif isinstance(value, Polygon):
                    self._dict['geometry'] = {
                        "rings" : value.asDictionary['rings']
                    }
                else:
                    return False
                self._json = json.dumps(self._dict, default=_date_handler)
            elif arcpyFound and isinstance(value, arcpy.Geometry):
                if isinstance(value, arcpy.PointGeometry):
                    self.set_value( field_name, Point(value,value.spatialReference.factoryCode))
                elif isinstance(value, arcpy.Multipoint):
                    self.set_value( field_name,  MultiPoint(value,value.spatialReference.factoryCode))

                elif isinstance(value, arcpy.Polyline):
                    self.set_value( field_name,  Polyline(value,value.spatialReference.factoryCode))

                elif isinstance(value, arcpy.Polygon):
                    self.set_value( field_name, Polygon(value,value.spatialReference.factoryCode))

            elif isinstance(value, dict): # Here is the added elif
                if "x" in value and "y" in value:
                    self._dict['geometry'] = {
                    "x" : value['x'],
                    "y" : value['y']
                    }
                elif "points" in value:
                    self._dict['geometry'] = {
                        "points" : value['points']
                    }
                elif "paths" in value:
                    self._dict['geometry'] = {
                        "paths" : value['paths']
                    }
                elif "rings" in value:
                    self._dict['geometry'] = {
                        "rings" : value.['rings']
                    }
                else:
                    return False
                self._json = json.dumps(self._dict, default=_date_handler)
        else:
            return False
        return True

The alternative is accessing private variables: feature1._dict['geometry'] = feature2.get_value('geometry')

achapkowski commented 8 years ago

in honor of our 200 th issue.

Strongbad Email

DShokes commented 8 years ago

Oh man, it's been over a decade since I've thought of Homestar. Techno always stuck with me.

DShokes commented 8 years ago

I found that my workaround results in wrong geometries when the feature object has a different spatial reference. Here is an example: I'd like to add a feature with

"spatialReference":{"wkid":102100,"latestWkid":3857}

to a layer with a different spatial reference, such as

"spatialReference":{"wkt":"PROJCS[\"HENNEPIN COUNTY\",GEOGCS[\"GCS_User_Defined\",DATUM[\"D_User_Defined\",SPHEROID[\"User_Defined_Spheroid\",6378418.941,298.2572242549207]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Lambert_Conformal_Conic\"],PARAMETER[\"False_Easting\",500000.0],PARAMETER[\"False_Northing\",100000.0],PARAMETER[\"Central_Meridian\",-93.38333333333334],PARAMETER[\"Standard_Parallel_1\",44.88333333333333],PARAMETER[\"Standard_Parallel_2\",45.13333333333333],PARAMETER[\"Latitude_Of_Origin\",44.79111111111111],UNIT[\"Foot_US\",0.3048006096012192]]"}

The REST API allows you to add features like

[{"attributes":{"OBJECTID":1,"LASTUPDATE":1461686409131},"geometry":{"x":-10400546.7493,"y":5605711.085699998,"spatialReference":{"wkid":102100,"latestWkid":3857}}}]

The service automatically projects the geometry to its own spatial reference. Here is the resulting added feature with adjust geometry:

{"objectIdFieldName":"OBJECTID","globalIdFieldName":"GlobalID","geometryType":"esriGeometryPoint","spatialReference":{"wkt":"PROJCS[\"HENNEPIN COUNTY\",GEOGCS[\"GCS_User_Defined\",DATUM[\"D_User_Defined\",SPHEROID[\"User_Defined_Spheroid\",6378418.941,298.2572242549207]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Lambert_Conformal_Conic\"],PARAMETER[\"False_Easting\",500000.0],PARAMETER[\"False_Northing\",100000.0],PARAMETER[\"Central_Meridian\",-93.38333333333334],PARAMETER[\"Standard_Parallel_1\",44.88333333333333],PARAMETER[\"Standard_Parallel_2\",45.13333333333333],PARAMETER[\"Latitude_Of_Origin\",44.79111111111111],UNIT[\"Foot_US\",0.3048006096012192]]"},"fields":[{"name":"LASTUPDATE","type":"esriFieldTypeDate","alias":"Last Update Date","sqlType":"sqlTypeOther","length":8,"domain":null,"defaultValue":null}],"features":[{"attributes":{"LASTUPDATE":1461766044828},"geometry":{"x":487983.95996925281,"y":139517.29996988285}}]}

ArcREST feature objects returned from a query have a feature._wkid, but feature.geometry.spatialReferenceis None and not editable.

This might explain some of the trouble copying/inserting geometries that I'm seeing.

DShokes commented 8 years ago

248