Beispiel #1
0
def feat_to_pnt(inShp, outPnt, epsg=None):
    """
    Get Centroid from each line in a PolyLine Feature Class
    """

    import os
    from osgeo import ogr
    from gasp.prop.ff import drv_name
    from gasp.mng.fld import ogr_copy_fields
    from gasp.mng.fld import lst_fld

    # TODO: check if geometry is correct

    # Open data
    polyData = ogr.GetDriverByName(drv_name(outPnt)).Open(inShp)

    polyLyr = polyData.GetLayer()

    # Get SRS for the output
    if not epsg:
        from gasp.prop.prj import get_shp_sref
        srs = get_shp_sref(polyLyr)

    else:
        from gasp.prop.prj import get_sref_from_epsg
        srs = get_sref_from_epsg(epsg)

    # Create output
    pntData = ogr.GetDriverByName(drv_name(outPnt)).CreateDataSource(outPnt)

    pntLyr = pntData.CreateLayer(os.path.splitext(os.path.basename(outPnt))[0],
                                 srs,
                                 geom_type=ogr.wkbPoint)

    # Copy fields from input to output
    fields = lst_fld(polyLyr)
    ogr_copy_fields(polyLyr, pntLyr)

    pntLyrDefn = pntLyr.GetLayerDefn()
    for feat in polyLyr:
        geom = feat.GetGeometryRef()

        pnt = geom.Centroid()

        new_feat = ogr.Feature(pntLyrDefn)
        new_feat.SetGeometry(pnt)

        for fld in fields:
            new_feat.SetField(fld, feat.GetField(fld))

        pntLyr.CreateFeature(new_feat)

        new_feat.Destroy()

    del pntLyr
    del polyLyr
    pntData.Destroy()
    polyData.Destroy()

    return outPnt
Beispiel #2
0
def ogr_select_by_location(shp, boundary_filter, filtered_output):
    """
    Filter a shp using the location of a boundary_filter shp
    
    For now the boundary must have only one feature
    
    Writes the filter on a new shp
    """

    import os
    from osgeo import ogr
    from gasp.prop.ff import drv_name
    from gasp.prop.feat import get_geom_type
    from gasp.mng.gen import copy_feat
    from gasp.mng.fld import ogr_copy_fields

    # Open main data
    dtSrc = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0)
    lyr = dtSrc.GetLayer()

    # Get filter geom
    filter_shp = ogr.GetDriverByName(drv_name(boundary_filter)).Open(
        boundary_filter, 0)
    filter_lyr = filter_shp.GetLayer()

    c = 0
    for f in filter_lyr:
        if c:
            break
        geom = f.GetGeometryRef()
        c += 1

    filter_shp.Destroy()

    # Apply filter
    lyr.SetSpatialFilter(geom)

    # Copy filter objects to a new shape
    out = ogr.GetDriverByName(
        drv_name(filtered_output)).CreateDataSource(filtered_output)

    outLyr = out.CreateLayer(os.path.splitext(
        os.path.basename(filtered_output))[0],
                             geom_type=get_geom_type(shp,
                                                     gisApi='ogr',
                                                     name=None,
                                                     py_cls=True))

    # Copy fields
    ogr_copy_fields(lyr, outLyr)

    copy_feat(lyr,
              outLyr,
              outDefn=outLyr.GetLayerDefn(),
              only_geom=False,
              gisApi='ogrlyr')
Beispiel #3
0
def project(inShp, outShp, outEPSG, inEPSG=None, gisApi='ogr', sql=None):
    """
    Project Geodata using GIS
    
    API's Available:
    * arcpy
    * ogr
    * ogr2ogr;
    * pandas
    """
    import os
    
    if gisApi == 'arcpy':
        """
        Execute Data Management > Data Transformations > Projection
        """
        
        import arcpy
        from gasp.cpu.arcg.lyr import feat_lyr
        from gasp.web.srorg    import get_wkt_esri
        
        layer   = feat_lyr(inShp)
        srs_obj = get_wkt_esri(outEPSG)
        
        arcpy.Project_management(layer, outShp, srs_obj)
    
    elif gisApi == 'ogr':
        """
        Using ogr Python API
        """
        
        if not inEPSG:
            raise ValueError(
                'To use ogr API, you should specify the EPSG Code of the'
                ' input data using inEPSG parameter'
            )
        
        from osgeo          import ogr
        from gasp.prop.feat import get_geom_type
        from gasp.prop.ff   import drv_name
        from gasp.mng.fld   import ogr_copy_fields
        from gasp.prop.prj  import get_sref_from_epsg
        from gasp.oss       import get_filename
        
        def copyShp(out, outDefn, lyr_in, trans):
            for f in lyr_in:
                g = f.GetGeometryRef()
                g.Transform(trans)
                new = ogr.Feature(outDefn)
                new.SetGeometry(g)
                for i in range(0, outDefn.GetFieldCount()):
                    new.SetField(outDefn.GetFieldDefn(i).GetNameRef(), f.GetField(i))
                out.CreateFeature(new)
                new.Destroy()
                f.Destroy()
        
        # ####### #
        # Project #
        # ####### #
        transP = get_trans_param(inEPSG, outEPSG)
        
        inData = ogr.GetDriverByName(
            drv_name(inShp)).Open(inShp, 0)
        
        inLyr = inData.GetLayer()
        out = ogr.GetDriverByName(
            drv_name(outShp)).CreateDataSource(outShp)
        
        outlyr = out.CreateLayer(
            get_filename(outShp), get_sref_from_epsg(outEPSG),
            geom_type=get_geom_type(
                inShp, name=None, py_cls=True, gisApi='ogr'
            )
        )
        
        # Copy fields to the output
        ogr_copy_fields(inLyr, outlyr)
        # Copy/transform features from the input to the output
        outlyrDefn = outlyr.GetLayerDefn()
        copyShp(outlyr, outlyrDefn, inLyr, transP)
        
        inData.Destroy()
        out.Destroy()
    
    elif gisApi == 'ogr2ogr':
        """
        Transform SRS of any OGR Compilant Data. Save the transformed data
        in a new file
    
        TODO: DB - only works with sqlite
        """
        
        if not inEPSG:
            raise ValueError('To use ogr2ogr, you must specify inEPSG')
        
        from gasp         import exec_cmd
        from gasp.prop.ff import drv_name
        
        cmd = (
            'ogr2ogr -f "{}" {} {}{} -s_srs EPSG:{} -t_srs:{}'
        ).format(
            drv_name(outShp), outShp, inShp,
            '' if not sql else ' -dialect sqlite -sql "{}"'.format(sql),
            str(inEpsg), str(outEpsg)
        )
        
        outcmd = exec_cmd(cmd)
    
    elif gisApi == 'pandas':
        # Test if input Shp is GeoDataframe
        from geopandas import GeoDataFrame as gdf
        
        if type(inShp) == gdf:
            # Is DataFrame
            df = inShp
        
        else:
            # Assuming is file
            if os.path.exists(inShp):
                # Is File 
                from gasp.fm import tbl_to_obj
                
                df = tbl_to_obj(inShp)
            else:
                raise ValueError((
                    "For pandas API, inShp must be file or GeoDataFrame"
                ))
        
        # Project df
        newDf = df.to_crs({'init' : 'epsg:{}'.format(str(outEPSG))})
        
        if outShp:
            # Try to save as file
            from gasp.to.shp import df_to_shp
            
            return df_to_shp(df, outShp)
        
        else:
            return newDf
    
    else:
        raise ValueError('Sorry, API {} is not available'.format(gisApi))
    
    return outShp
Beispiel #4
0
def polyline_to_points(inShp, outShp, attr=None, epsg=None):
    """
    Polyline vertex to Points
    
    TODO: See if works with Polygons
    """

    import os
    from osgeo import ogr
    from gasp.prop.ff import drv_name
    from gasp.mng.fld import ogr_copy_fields

    # Open Input
    polyData = ogr.GetDriverByName(drv_name(inShp)).Open(inShp)

    polyLyr = polyData.GetLayer()

    # Get SRS for the output
    if not epsg:
        from gasp.prop.prj import get_shp_sref
        srs = get_shp_sref(polyLyr)

    else:
        from gasp.prop.prj import get_sref_from_epsg
        srs = get_sref_from_epsg(epsg)

    # Create Output
    pntData = ogr.GetDriverByName(drv_name(outShp)).CreateDataSource(outShp)

    pntLyr = pntData.CreateLayer(os.path.splitext(os.path.basename(outShp))[0],
                                 srs,
                                 geom_type=ogr.wkbPoint)

    # Copy fields from input to output
    if attr:
        if attr == 'ALL':
            attr = None
        else:
            attr = [attr] if type(attr) != list else attr

        ogr_copy_fields(polyLyr, pntLyr, __filter=attr)

    # Polyline Vertex to Point Feature Class
    pntLyrDefn = pntLyr.GetLayerDefn()
    for feat in polyLyr:
        geom = feat.GetGeometryRef()

        # Get point count
        nrPnt = geom.GetPointCount()

        # Add point to a new feature
        for p in range(nrPnt):
            x, y, z = geom.GetPoint(p)

            new_point = ogr.Geometry(ogr.wkbPoint)
            new_point.AddPoint(x, y)

            new_feature = ogr.Feature(pntLyrDefn)
            new_feature.SetGeometry(new_point)

            if attr:
                for at in attr:
                    new_feature.SetField(at, feat.GetField(at))

            pntLyr.CreateFeature(new_feature)

            new_feature.Destroy()

    del pntLyr
    del polyLyr
    pntData.Destroy()
    polyData.Destroy()

    return outShp
Beispiel #5
0
def eachfeat_to_newshp(inShp, outFolder, epsg=None):
    """
    Export each feature in inShp to a new/single File
    """

    import os
    from osgeo import ogr
    from gasp.prop.ff import drv_name
    from gasp.prop.feat import get_geom_type
    from gasp.mng.fld import lst_fld
    from gasp.mng.fld import ogr_copy_fields
    from gasp.oss import get_fileformat, get_filename

    inDt = ogr.GetDriverByName(drv_name(inShp)).Open(inShp)

    lyr = inDt.GetLayer()

    # Get SRS for the output
    if not epsg:
        from gasp.prop.prj import get_shp_sref
        srs = get_shp_sref(lyr)

    else:
        from gasp.prop.prj import get_sref_from_epsg
        srs = get_sref_from_epsg(epsg)

    # Get fields name
    fields = lst_fld(lyr)

    # Get Geometry type
    geomCls = get_geom_type(inShp, gisApi='ogr', name=None, py_cls=True)

    # Read features and create a new file for each feature
    RESULT_SHP = []
    for feat in lyr:
        # Create output
        newShp = os.path.join(
            outFolder, "{}_{}{}".format(get_filename(inShp),
                                        str(feat.GetFID()),
                                        get_fileformat(inShp)))

        newData = ogr.GetDriverByName(
            drv_name(newShp)).CreateDataSource(newShp)

        newLyr = newData.CreateLayer(str(get_filename(newShp)),
                                     srs,
                                     geom_type=geomCls)

        # Copy fields from input to output
        ogr_copy_fields(lyr, newLyr)

        newLyrDefn = newLyr.GetLayerDefn()

        # Create new feature
        newFeat = ogr.Feature(newLyrDefn)

        # Copy geometry
        geom = feat.GetGeometryRef()
        newFeat.SetGeometry(geom)

        # Set fields attributes
        for fld in fields:
            newFeat.SetField(fld, feat.GetField(fld))

        # Save feature
        newLyr.CreateFeature(newFeat)

        newFeat.Destroy()

        del newLyr
        newData.Destroy()
        RESULT_SHP.append(newShp)

    return RESULT_SHP
Beispiel #6
0
def connect_points_to_near_line(inPnt,
                                nearLines,
                                outLines,
                                tollerance=1000,
                                nearLinesWpnt=None):
    """
    Connect all points to the nearest line in the perpendicular
    """

    import os
    import numpy as np
    from osgeo import ogr
    from shapely.geometry import LineString, Point
    from gasp.prop.ff import drv_name
    from gasp.prop.feat import get_geom_type

    # Check Geometries
    inPntGeom = get_geom_type(inPnt, gisApi='ogr')
    nearLinesGeom = get_geom_type(nearLines, gisApi='ogr')

    if inPntGeom != 'POINT' or \
       nearLinesGeom != 'LINESTRING':
        raise ValueError('This method supports only LINESTRINGS')

    # Open inLines
    shpPnt = ogr.GetDriverByName(drv_name(inPnt)).Open(inPnt)

    # Get Layer
    lyrPnt = shpPnt.GetLayer()

    # Open near
    shpNear = ogr.GetDriverByName(drv_name(nearLines)).Open(nearLines)

    # Create Output
    outSrc = ogr.GetDriverByName(drv_name(outLines)).CreateDataSource(outLines)

    outLyr = outSrc.CreateLayer(os.path.splitext(
        os.path.basename(outLines))[0],
                                geom_type=ogr.wkbLineString)

    if nearLinesWpnt:
        newPointsInLines = {}

    lineDefn = outLyr.GetLayerDefn()
    # For each point in 'inLines', find the near point on the
    # the 'nearLines' layer
    for feat in lyrPnt:
        FID = feat.GetFID()
        # Get Geometry
        pnt = feat.GetGeometryRef()

        x, y = pnt.GetX(), pnt.GetY()

        # Get point buffer
        bufPnt = draw_buffer(pnt, tollerance)

        # Apply a spatial filter based on the buffer
        # to restrict the nearLines Layer
        lyrNear = shpNear.GetLayer()

        lyrNear.SetSpatialFilter(bufPnt)

        # For line in the filtered 'nearLyr'
        # Find point in the perpendicular
        dist = 0
        for __feat in lyrNear:
            __FID = __feat.GetFID()
            __geom = __feat.GetGeometryRef()

            points = __geom.GetPointCount()

            for _p in range(points - 1):
                # Get line segment
                x1, y1, z1 = __geom.GetPoint(_p)
                x2, y2, z2 = __geom.GetPoint(_p + 1)

                # Create Shapely Geometries
                lnh = LineString([(x1, y1), (x2, y2)])

                pnt = Point(x, y)

                # Get distance between point and line
                # Get near point of the line
                d = pnt.distance(lnh)
                npnt = lnh.interpolate(lnh.project(pnt))

                if not dist:
                    dist = [d, npnt.x, npnt.y]
                    LINE_FID = __FID

                else:
                    if d < dist[0]:
                        dist = [d, npnt.x, npnt.y]
                        LINE_FID = __FID

        # Write a new line
        line = ogr.Geometry(ogr.wkbLineString)
        line.AddPoint(x, y)
        line.AddPoint(dist[1], dist[2])

        new_feature = ogr.Feature(lineDefn)
        new_feature.SetGeometry(line)

        outLyr.CreateFeature(new_feature)

        new_feature.Destroy()

        if nearLinesWpnt:
            if LINE_FID not in newPointsInLines:
                newPointsInLines[LINE_FID] = [Point(dist[1], dist[2])]
            else:
                newPointsInLines[LINE_FID].append(Point(dist[1], dist[2]))

        del lyrNear

    outSrc.Destroy()
    shpPnt.Destroy()
    shpNear.Destroy()

    if nearLinesWpnt:
        from gasp.mng.fld import ogr_copy_fields
        from shapely.ops import split as lnhSplit

        shpNear = ogr.GetDriverByName(drv_name(nearLines)).Open(nearLines)

        updateLines = ogr.GetDriverByName(
            drv_name(nearLinesWpnt)).CreateDataSource(nearLinesWpnt)

        upLnhLyr = updateLines.CreateLayer(get_filename(nearLinesWpnt),
                                           geom_type=ogr.wkbLineString)

        # Create shpNear Layer Again
        lyrNear = shpNear.GetLayer()

        # Copy fields
        ogr_copy_fields(lyrNear, upLnhLyr)

        # Out lyr definition
        upDefn = upLnhLyr.GetLayerDefn()
        for feat in lyrNear:
            LINE_FID = feat.GetFID()
            print LINE_FID

            geom = feat.GetGeometryRef()

            new_feature = ogr.Feature(upDefn)

            if LINE_FID not in newPointsInLines:
                # Copy line to updateLines layer
                new_feature.SetGeometry(geom)

            else:
                # Copy to Shapely Line String
                points = geom.GetPointCount()

                lstPnt = []
                for _p in range(points):
                    x1, y1, z1 = geom.GetPoint(_p)
                    lstPnt.append((x1, y1))

                shplyLnh = LineString(lstPnt)
                # For new point:
                # Line split and reconstruction
                for pnt in newPointsInLines[LINE_FID]:
                    try:
                        splitted = lnhSplit(shplyLnh, pnt)
                    except:
                        shpTstL = ogr.GetDriverByName(
                            "ESRI Shapefile").CreateDataSource(
                                r'D:\gis\xyz\lnht.shp')

                        shpL = shpTstL.CreateLayer('lnht',
                                                   geom_type=ogr.wkbLineString)

                        shpTstP = ogr.GetDriverByName(
                            "ESRI Shapefile").CreateDataSource(
                                r'D:\gis\xyz\pntt.shp')

                        shpP = shpTstL.CreateLayer('pntt',
                                                   geom_type=ogr.wkbPoint)

                        defnL = shpL.GetLayerDefn()
                        defnP = shpP.GetLayerDefn()

                        featL = ogr.Feature(defnL)
                        featP = ogr.Feature(defnP)

                        geomL = ogr.Geometry(ogr.wkbLineString)
                        for i in list(shplyLnh.coords):
                            geomL.AddPoint(i[0], i[1])
                        geomP = ogr.Geometry(ogr.wkbPoint)
                        print list(pnt.coords)
                        geomP.AddPoint(
                            list(pnt.coords)[0][0],
                            list(pnt.coords)[0][1])

                        featL.SetGeometry(geomL)
                        featP.SetGeometry(geomP)

                        shpL.CreateFeature(featL)
                        shpP.CreateFeature(featP)

                        shpTstL.Destroy()
                        shpTstP.Destroy()

                        return pnt, shplyLnh

                    c = 0
                    for l in splitted:
                        if not c:
                            newLnh = list(l.coords)
                        else:
                            newlnh += list(l.coords)[1:]
                        c += 1

                    shplyLnh = LineString(newLnh)

                # Finally copy line to updateLines Layer
                gLine = ogr.Geometry(ogr.wkbLineString)
                for __pnt in list(shplyLnh.coords):
                    gLine.AddPoint(__pnt[0], __pnt[1])

            for i in range(0, upDefn.GetFieldCount()):
                new_feature.SetField(
                    upDefn.GetFieldDefn(i).GetNameRef(), feat.GetField(i))

            upLnhLyr.CreateFeature(new_feature)

            new_feature.Destroy()

    shpNear.Destroy()

    return outLines