arcgis-python-api icon indicating copy to clipboard operation
arcgis-python-api copied to clipboard

support for z-aware geometry when using pyshp

Open dkoerner opened this issue 5 years ago • 2 comments

Looking at anaconda3\Lib\site-packages\arcgis\features\geo\_io\fileops.py I see that GIS.content.import_data does not support z-aware points, at least when using pyshp:

        GEOMTYPELOOKUP = {
            "Polygon" : shapefile.POLYGON,
            "Point" : shapefile.POINT,
            "Polyline" : shapefile.POLYLINE,
            'null' : shapefile.NULL
        }

Is there a way to publish z-aware features using pyshp?

dkoerner avatar Mar 19 '19 14:03 dkoerner

here the code snippet for anaconda3\Lib\site-packages\arcgis\features\geo\_io\fileops.py which adds support for importing z-aware points:

        if idx > -1:
            geom_type = df.loc[idx][geom_field].type
            if df.loc[idx][geom_field].hasZ == True:
                GEOMTYPELOOKUP["Point"] = shapefile.POINTZ
        #shpfile = shapefile.Writer(out_fc, GEOMTYPELOOKUP[geom_type]) # pyshp 2.1
        shpfile = shapefile.Writer(GEOMTYPELOOKUP[geom_type]) # pyshp 1.2.11
        shpfile.autoBalance = 1
        dfields = []
        cfields = []
        for c in df.columns:
            idx = df[c].first_valid_index()
            if not idx is None and idx > -1:
                if isinstance(df[c].loc[idx],
                              Geometry):
                    geom_field = (c, "GEOMETRY")
                else:
                    cfields.append(c)
                    if isinstance(df[c].loc[idx], (str)):
                        shpfile.field(name=c, size=255)
                    elif isinstance(df[c].loc[idx], (int)):
                        shpfile.field(name=c, fieldType="N", size=5)
                    elif isinstance(df[c].loc[idx], (np.int, np.int32, np.int64)):
                        shpfile.field(name=c, fieldType="N", size=10)
                    elif isinstance(df[c].loc[idx], (np.float, np.float64)):
                        shpfile.field(name=c, fieldType="F", size=19, decimal=11)
                    elif isinstance(df[c].loc[idx], (datetime.datetime, np.datetime64)) or \
                         df[c].dtype.name == 'datetime64[ns]':
                        shpfile.field(name=c, fieldType="D", size=8)
                        dfields.append(c)
                    elif isinstance(df[c].loc[idx], (bool, np.bool)):
                        shpfile.field(name=c, fieldType="L", size=1)
            del c
            del idx
        for idx, row in df.iterrows():
            geom = row[df.spatial._name]
            if geom.type == "Polygon":
                shpfile.poly(geom['rings'])
            elif geom.type == "Polyline":
                shpfile.line(geom['paths'])
            elif geom.type == "Point":
                if geom.hasZ == True:
                    shpfile.point(x=geom.x, y=geom.y, z=geom.z, shapeType=shapefile.POINTZ)
                else:
                    shpfile.point(x=geom.x, y=geom.y)
            else:
                shpfile.null()
            row = row[cfields].tolist()
            for fld in dfields:
                idx = df[cfields].columns.tolist().index(fld)
                if row[idx]:
                    row[idx] = row[idx].to_pydatetime()
            shpfile.record(*row)
            del idx
            del row
            del geom
        
        # uncomment this only for pyshp 1.2.11
        shpfile.save(out_fc)
        ##shpfile.close() # pyshp 2.1

dkoerner avatar Mar 19 '19 14:03 dkoerner

@dkoerner I'll take a look. thanks for the suggestion.

achapkowski avatar Mar 19 '19 15:03 achapkowski

This issue is older and will be closed in an effort to remove stale issues. Please feel free to reopen if needed.

nanaeaubry avatar Sep 16 '22 05:09 nanaeaubry