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.feat 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 shpextent_to_boundary(inShp, outShp, epsg=None):
    """
    Read one feature class extent and create a boundary with that
    extent
    
    The outFile could be a Feature Class or one Raster Dataset
    """

    import os
    from gasp.oss import get_filename
    from gasp.to.geom import create_point
    from gasp.prop.ext import get_extent

    extent = get_extent(inShp, gisApi='ogr')

    # Create points of the new boundary based on the extent
    boundary_points = [
        create_point(extent[0], extent[3], api='ogr'),
        create_point(extent[1], extent[3], api='ogr'),
        create_point(extent[1], extent[2], api='ogr'),
        create_point(extent[0], extent[2], api='ogr'),
        create_point(extent[0], extent[3], api='ogr')
    ]

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

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

    # Write new file
    shp = ogr.GetDriverByName(drv_name(outShp)).CreateDataSource(outShp)

    lyr = shp.CreateLayer(get_filename(outShp, forceLower=True),
                          srs,
                          geom_type=ogr.wkbPolygon)

    outDefn = lyr.GetLayerDefn()

    feat = ogr.Feature(outDefn)
    ring = ogr.Geometry(ogr.wkbLinearRing)

    for pnt in boundary_points:
        ring.AddPoint(pnt.GetX(), pnt.GetY())

    polygon = ogr.Geometry(ogr.wkbPolygon)
    polygon.AddGeometry(ring)

    feat.SetGeometry(polygon)
    lyr.CreateFeature(feat)

    feat.Destroy()
    shp.Destroy()

    return outShp
Beispiel #3
0
def shp_to_raster(shp,
                  inSource,
                  cellsize,
                  nodata,
                  outRaster,
                  epsg=None,
                  rst_template=None,
                  api='gdal',
                  snap=None):
    """
    Feature Class to Raster
    
    cellsize will be ignored if rst_template is defined
    
    * API's Available:
    - gdal;
    - arcpy;
    - pygrass;
    - grass;
    """

    if api == 'gdal':
        from osgeo import gdal, ogr
        from gasp.prop.ff import drv_name

        if not epsg:
            from gasp.prop.feat import get_shp_sref
            srs = get_shp_sref(shp).ExportToWkt()
        else:
            from gasp.prop.prj import epsg_to_wkt
            srs = epsg_to_wkt(epsg)

        # Get Extent
        dtShp = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0)

        lyr = dtShp.GetLayer()

        if not rst_template:
            x_min, x_max, y_min, y_max = lyr.GetExtent()
            x_res = int((x_max - x_min) / cellsize)
            y_res = int((y_max - y_min) / cellsize)

        else:
            from gasp.fm.rst import rst_to_array

            img_temp = gdal.Open(rst_template)
            geo_transform = img_temp.GetGeoTransform()

            y_res, x_res = rst_to_array(rst_template).shape

        # Create output
        dtRst = gdal.GetDriverByName(drv_name(outRaster)).Create(
            outRaster, x_res, y_res, gdal.GDT_Byte)

        if not rst_template:
            dtRst.SetGeoTransform((x_min, cellsize, 0, y_max, 0, -cellsize))

        else:
            dtRst.SetGeoTransform(geo_transform)
        dtRst.SetProjection(srs)

        bnd = dtRst.GetRasterBand(1)
        bnd.SetNoDataValue(nodata)

        gdal.RasterizeLayer(dtRst, [1], lyr, burn_values=[1])

        del lyr
        dtShp.Destroy()

    elif api == 'arcpy':
        import arcpy

        if rst_template:
            tempEnvironment0 = arcpy.env.extent
            arcpy.env.extent = template

        if snap:
            tempSnap = arcpy.env.snapRaster
            arcpy.env.snapRaster = snap

        obj_describe = arcpy.Describe(shp)
        geom = obj_describe.ShapeType

        if geom == u'Polygon':
            arcpy.PolygonToRaster_conversion(shp, inField, outRaster,
                                             "CELL_CENTER", "NONE", cellsize)

        elif geom == u'Polyline':
            arcpy.PolylineToRaster_conversion(shp, inField, outRaster,
                                              "MAXIMUM_LENGTH", "NONE",
                                              cellsize)

        if rst_template:
            arcpy.env.extent = tempEnvironment0

        if snap:
            arcpy.env.snapRaster = tempSnap

    elif api == 'grass' or api == 'pygrass':
        """
        Vectorial geometry to raster
    
        If source is None, the convertion will be based on the cat field.
    
        If source is a string, the convertion will be based on the field
        with a name equal to the given string.
    
        If source is a numeric value, all cells of the output raster will have
        that same value.
        """

        __USE = "cat" if not inSource else "attr" if type(inSource) == str or \
            type(inSource) == unicode else "val" if type(inSource) == int or \
            type(inSource) == float else None

        if not __USE:
            raise ValueError('\'source\' parameter value is not valid')

        if api == 'pygrass':
            from grass.pygrass.modules import Module

            m = Module("v.to.rast",
                       input=shp,
                       output=outRaster,
                       use=__USE,
                       attribute_column=inSource if __USE == "attr" else None,
                       value=inSource if __USE == "val" else None,
                       overwrite=True,
                       run_=False,
                       quiet=True)

            m()

        else:
            from gasp import exec_cmd

            rcmd = exec_cmd((
                "v.to.rast input={} output={} use={}{} "
                "--overwrite --quiet"
            ).format(
                shp, outRaster, __USE,
                "" if __USE == "cat" else " attribute_column={}".format(inSource) \
                    if __USE == "attr" else " val={}".format(inSource)
            ))

    else:
        raise ValueError('API {} is not available'.format(api))

    return outRaster
Beispiel #4
0
def polylines_from_points(points,
                          polylines,
                          POLYLINE_COLUMN,
                          ORDER_FIELD=None,
                          epsg=None):
    """
    Create a Polyline Table from a Point Table
    
    A given Point Table:
    FID | POLYLINE_ID | ORDER_FIELD
     0  |    P1       |      1
     1  |    P1       |      2
     2  |    P1       |      3
     3  |    P1       |      4
     4  |    P2       |      1
     5  |    P2       |      2
     6  |    P2       |      3
     7  |    P2       |      4
     
    Will be converted into a new Polyline Table:
    FID | POLYLINE_ID
     0  |    P1
     1  |    P2
     
    In the Point Table, the POLYLINE_ID field identifies the Polyline of that point,
    the ORDER FIELD specifies the position (first point, second point, etc.)
    of the point in the polyline.
    
    If no ORDER field is specified, the points will be assigned to polylines
    by reading order.
    """

    import os
    from osgeo import ogr
    from gasp.prop.ff import drv_name
    from gasp.mng.prj import ogr_def_proj
    from gasp.mng.fld import ogr_list_fields_defn
    from gasp.mng.fld import add_fields

    # TODO: check if geometry is correct

    # List all points
    pntSrc = ogr.GetDriverByName(drv_name(points)).Open(points)
    pntLyr = pntSrc.GetLayer()

    lPnt = {}
    cnt = 0
    for feat in pntLyr:
        # Get Point Geom
        geom = feat.GetGeometryRef()
        # Polyline identification
        polyline = feat.GetField(POLYLINE_COLUMN)
        # Get position in the polyline
        order = feat.GetField(ORDER_FIELD) if ORDER_FIELD else cnt

        # Store data
        if polyline not in lPnt.keys():
            lPnt[polyline] = {order: (geom.GetX(), geom.GetY())}

        else:
            lPnt[polyline][order] = (geom.GetX(), geom.GetY())

        cnt += 1

    # Write output
    lineSrc = ogr.GetDriverByName(
        drv_name(polylines)).CreateDataSource(polylines)

    if not epsg:
        from gasp.prop.feat import get_shp_sref
        srs = get_shp_sref(points)

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

    lineLyr = lineSrc.CreateLayer(os.path.splitext(
        os.path.basename(polylines))[0],
                                  srs,
                                  geom_type=ogr.wkbLineString)

    # Create polyline id field
    fields_types = ogr_list_fields_defn(pntLyr)
    add_fields(lineLyr,
               {POLYLINE_COLUMN: fields_types[POLYLINE_COLUMN].keys()[0]})

    polLnhDefns = lineLyr.GetLayerDefn()
    # Write lines
    for polyline in lPnt:
        new_feature = ogr.Feature(polLnhDefns)

        lnh = ogr.Geometry(ogr.wkbLineString)

        pnt_order = lPnt[polyline].keys()
        pnt_order.sort()

        for p in pnt_order:
            lnh.AddPoint(lPnt[polyline][p][0], lPnt[polyline][p][1])

        new_feature.SetField(POLYLINE_COLUMN, polyline)
        new_feature.SetGeometry(lnh)

        lineLyr.CreateFeature(new_feature)

        new_feature = None

    pntSrc.Destroy()
    lineSrc.Destroy()

    return polylines
Beispiel #5
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.feat 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 #6
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.feat 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 #7
0
def create_fishnet(boundary,
                   fishnet,
                   width=None,
                   height=None,
                   rowN=None,
                   colN=None):
    """
    Create a Fishnet
    """

    import os
    from math import ceil
    from gasp.oss import get_filename
    from gasp.prop.ff import drv_name
    from gasp.prop.ext import get_extent
    from gasp.prop.feat import get_shp_sref

    # Get boundary extent
    xmin, xmax, ymin, ymax = [
        float(x) for x in get_extent(boundary, gisApi='ogr')
    ]

    if width and height:
        # Clean width and height
        if type(width) != float:
            try:
                # Convert to float
                width = float(width)
            except:
                raise ValueError(
                    'Width value is not valid. Please give a numeric value')

        if type(height) != float:
            try:
                # Convert to float
                height = float(height)
            except:
                raise ValueError(
                    'Height value is not valid. Please give a numeric value')

        # get rows number
        rows = ceil((ymax - ymin) / height)
        # get columns number
        cols = ceil((xmax - xmin) / width)

    else:
        if rowN and colN:
            rows = int(rowN)
            cols = int(colN)
            width = ceil((xmax - xmin) / rows)
            height = ceil((ymax - ymin) / cols)

        else:
            raise ValueError(
                "You must specify the width and height of fishnet cells or "
                "instead the number of rows and cols of fishnet")

    # Create output file
    if not os.path.exists(os.path.dirname(fishnet)):
        raise ValueError('The path for the output doesn\'t exist')

    out_fishnet = ogr.GetDriverByName(
        drv_name(fishnet)).CreateDataSource(fishnet)
    fishnet_lyr = out_fishnet.CreateLayer(str(get_filename(fishnet)),
                                          srs=get_shp_sref(boundary),
                                          geom_type=ogr.wkbPolygon)

    feat_defn = fishnet_lyr.GetLayerDefn()

    # create grid cells
    # - start grid cell envelope -#
    ringXleftOrigin = xmin
    ringXrightOrigin = xmin + width
    ringYtopOrigin = ymax
    ringYbottomOrigin = ymax - height

    count_cols = 0
    while count_cols < cols:
        count_cols += 1

        # reset envelope for rows
        ringYtop = ringYtopOrigin
        ringYbottom = ringYbottomOrigin
        count_rows = 0

        while count_rows < rows:
            count_rows += 1

            ring = ogr.Geometry(ogr.wkbLinearRing)
            ring.AddPoint(ringXleftOrigin, ringYtop)
            ring.AddPoint(ringXrightOrigin, ringYtop)
            ring.AddPoint(ringXrightOrigin, ringYbottom)
            ring.AddPoint(ringXleftOrigin, ringYbottom)
            ring.AddPoint(ringXleftOrigin, ringYtop)
            poly = ogr.Geometry(ogr.wkbPolygon)
            poly.AddGeometry(ring)

            # add new geom to layer
            out_feature = ogr.Feature(feat_defn)
            out_feature.SetGeometry(poly)
            fishnet_lyr.CreateFeature(out_feature)
            out_feature = None

            # new envelope for next poly
            ringYtop = ringYtop - height
            ringYbottom = ringYbottom - height

        # new envelope for next poly
        ringXleftOrigin = ringXleftOrigin + width
        ringXrightOrigin = ringXrightOrigin + width

    out_fishnet.Destroy()

    return fishnet
Beispiel #8
0
def points_as_grid(boundary,
                   fishnet_pnt,
                   width=None,
                   height=None,
                   nr_cols=None,
                   nr_rows=None):
    """
    Equivalent to the centroid of each cell of a fishnet grid
    """

    import os
    from math import ceil
    from gasp.oss import get_filename
    from gasp.prop.ff import drv_name
    from gasp.prop.ext import get_extent
    from gasp.prop.feat import get_shp_sref

    # Get boundary extent
    xmin, xmax, ymin, ymax = get_extent(boundary, gisApi='ogr')

    # Clean width and height
    if width and height:
        if type(width) != float:
            try:
                # Convert to float
                width = float(width)
            except:
                raise ValueError(
                    'Width value is not valid. Please give a numeric value')

        if type(height) != float:
            try:
                # Convert to float
                height = float(height)
            except:
                raise ValueError(
                    'Height value is not valid. Please give a numeric value')

    else:
        if nr_cols and nr_rows:
            if type(nr_cols) != float:
                try:
                    # convert to float
                    nr_cols = float(nr_cols)
                except:
                    raise ValueError(
                        'Columns number value is not valid. Please give a numeric value'
                    )

            if type(nr_rows) != float:
                try:
                    nr_rows = float(nr_rows)
                except:
                    raise ValueError(
                        'Lines number value is not valid. Please give a numeric value'
                    )

            width = (xmax + xmin) / nr_cols
            height = (ymax + ymin) / nr_rows

        else:
            raise ValueError(
                'Please giver numeric values to with/height or to nr_cols/nr_rows'
            )

    # get rows number
    rows = ceil((ymax - ymin) / height)
    # get columns number
    cols = ceil((xmax - xmin) / width)

    # Create output file
    if not os.path.exists(os.path.dirname(fishnet_pnt)):
        return 'The path for the output doesn\'t exist'

    out_fishnet = ogr.GetDriverByName(
        drv_name(fishnet_pnt)).CreateDataSource(fishnet_pnt)
    fishnet_lyr = out_fishnet.CreateLayer(get_filename(fishnet_pnt),
                                          get_shp_sref(boundary),
                                          geom_type=ogr.wkbPoint)

    feat_defn = fishnet_lyr.GetLayerDefn()

    # create grid cells
    # - start grid cell envelope -#
    ringXleftOrigin = xmin
    ringXrightOrigin = xmin + width
    ringYtopOrigin = ymax
    ringYbottomOrigin = ymax - height

    count_cols = 0
    while count_cols < cols:
        count_cols += 1

        # reset envelope for rows
        ringYtop = ringYtopOrigin
        ringYbottom = ringYbottomOrigin
        count_rows = 0

        while count_rows < rows:
            count_rows += 1

            pnt = ogr.Geometry(ogr.wkbPoint)
            pnt.AddPoint((ringXleftOrigin + ringXrightOrigin) / 2.0,
                         (ringYbottom + ringYtop) / 2.0)

            # add new geom to layer
            out_feature = ogr.Feature(feat_defn)
            out_feature.SetGeometry(pnt)
            fishnet_lyr.CreateFeature(out_feature)
            out_feature = None

            # new envelope for next poly
            ringYtop = ringYtop - height
            ringYbottom = ringYbottom - height

        # new envelope for next poly
        ringXleftOrigin = ringXleftOrigin + width
        ringXrightOrigin = ringXrightOrigin + width

    out_fishnet.Destroy()
Beispiel #9
0
def points_to_boundary(pntShp, outBound, distMeters):
    """
    Create a boundary from Point using a tolerance in meters
    """

    from osgeo import ogr
    from gasp.oss import get_filename
    from gasp.prop.ff import drv_name
    from gasp.to.geom import create_point
    from gasp.prop.feat import get_shp_sref

    SRS = get_shp_sref(pntShp)

    shp = ogr.GetDriverByName(drv_name(pntShp)).Open(pntShp)
    lyr = shp.GetLayer()

    outShp = ogr.GetDriverByName(drv_name(outBound)).CreateDataSource(outBound)
    outLyr = outShp.CreateLayer(get_filename(outBound, forceLower=True),
                                SRS,
                                geom_type=ogr.wkbPolygon)

    outDefn = outLyr.GetLayerDefn()

    for feat in lyr:
        __feat = ogr.Feature(outDefn)
        ring = ogr.Geometry(ogr.wkbLinearRing)

        geom = feat.GetGeometryRef()
        X, Y = geom.GetX(), geom.GetY()

        boundary_points = [
            create_point(X - distMeters, Y + distMeters, api='ogr'),  # Topleft
            create_point(X + distMeters, Y + distMeters,
                         api='ogr'),  # TopRight
            create_point(X + distMeters, Y - distMeters,
                         api='ogr'),  # Lower Right
            create_point(X - distMeters, Y - distMeters,
                         api='ogr'),  # Lower Left
            create_point(X - distMeters, Y + distMeters, api='ogr')
        ]

        for pnt in boundary_points:
            ring.AddPoint(pnt.GetX(), pnt.GetY())

        polygon = ogr.Geometry(ogr.wkbPolygon)
        polygon.AddGeometry(ring)

        __feat.SetGeometry(polygon)

        outLyr.CreateFeature(__feat)

        feat.Destroy()

        __feat = None
        ring = None
        polygon = None

    shp.Destroy()
    outShp.Destroy()

    return outBound