Beispiel #1
0
def fishnet(output,
            templateExtent,
            geomType='POLYGON',
            numRows=None,
            numColumns=None,
            cellWidth=None,
            cellHeight=None,
            labeling="NO_LABELS"):
    """
    Create a fishnet - rectangular cells
    
    Use fc or raster to assign a extent to the new fishnet
    """

    import os
    from glass.prop.ext import rst_ext, get_extent
    from glass.prop.ff import vector_formats, raster_formats
    from glass.oss import get_fileformat

    templateFormat = get_fileformat(templateExtent)

    if templateFormat in vector_formats():
        xmin, xmax, ymin, ymax = get_extent(templateExtent, gisApi='arcpy')
    elif templateFormat in raster_formats():
        xmin, xmax, ymin, ymax = rst_ext(templateExtent, gisApi='arcpy')

    else:
        raise ValueError(('Could not identify if observerDataset '
                          'is a raster or a feature class'))

    arcpy.CreateFishnet_management(
        out_feature_class=output,
        origin_coord=' '.join([str(xmin), str(ymin)]),
        y_axis_coord=' '.join([str(xmin), str(ymin + 10.0)]),
        cell_width=cellWidth,
        cell_height=cellHeight,
        number_rows=numRows,
        number_columns=numColumns,
        labels=labeling,
        template=templateExtent,
        geometry_type=geomType)

    return output
Beispiel #2
0
def generate_waterlines(mdt, waterbodies, accumulation_value=500,
                        workspace=None):
    """
    Generate Water Bodies lines
    """
    
    import os
    from glass.oss                    import get_fileformat
    from glass.cpu.arcg.lyr           import rst_lyr
    from glass.prop.ff                import vector_formats, raster_formats
    from glass.spanlst.algebra        import rstcalc
    from glass.cpu.arcg.spanlst.hydro import fill
    from glass.cpu.arcg.spanlst.hydro import flow_accumulation
    from glass.cpu.arcg.spanlst.hydro import flow_direction
    from glass.cpu.arcg.spanlst.hydro import stream_to_feature
    
    workspace = workspace if workspace else \
        os.path.dirname(waterbodies)
    
    raster_format = os.path.splitext(os.path.basename(waterbodies))[1]
    
    arcpy.env.workspace = workspace
    arcpy.env.overwriteOutput = True
    
    fill_rst = fill(mdt, 'flow_raster{}'.format(raster_format),
                    template=mdt)
    
    dire_rst = flow_direction(
        fill_rst, 'direction_raster{}'.format(raster_format),
        template=mdt
    )
    
    flow_acc = flow_accumulation(
        dire_rst, 'flow_raster{}'.format(raster_format),
        template=mdt
    )
    
    # Split water bodies from the other accumulation data
    lyr_flow = rst_lyr(flow_acc)
    
    outFormat = os.path.splitext(os.path.basename(waterbodies))[1]
    rstFormat = raster_formats()
    vecFormat = vector_formats()
    
    waterRst = waterbodies if outFormat in rstFormat else \
        os.path.join(
            workspace,
            os.path.splitext(os.path.basename(waterbodies))[0] + raster_format
        ) if outFormat in vecFormat else None
    
    if not waterRst:
        raise ValueError('Your output is not a raster and is not a vector')
    
    waterRst = rstcalc(
        '{r} > {a}'.format(
            r=os.path.splitext(os.path.basename(flow_acc))[0],
            a=str(accumulation_value)
        ),
        waterRst, template=mdt, api='arcpy'
    )
    
    if outFormat in vecFormat:
        stream_to_feature(waterRst, dire_rst, waterbodies)
        
        return waterbodies
    
    else:
        return waterRst
Beispiel #3
0
def viewshed_by_feat_class2(inRaster,
                            observerDataset,
                            feat_class_folder,
                            output_folder,
                            snapRst=None,
                            visibilityRadius=20000,
                            epsg=3763):
    """
    See for each feature class in a folder if it is possible to see a 
    interest object from all poins in each feature class
    
    Why this method is different from viewshed_by_feat_class?
    viewshed_by_feat_class uses viewshed tool of ArcGIS;
    This one will calculate the visibility point by point, when the script
    identifies that one point is observable from another, it stops.
    
    TO BE MANTAINED?
    """

    import arcpy
    import numpy
    import os

    from glass.oss.ops import create_folder
    from glass.prop.ff import vector_formats, raster_formats
    from glass.cpu.arcg.lyr import feat_lyr
    from glass.prop.rst import get_cell_coord
    from glass.prop.ext import rst_ext
    from glass.prop.rst import rst_shape, rst_distinct, get_nodata, get_cellsize
    from glass.anls.prox.bf import _buffer
    from glass.cpu.arcg.mng.rst.proc import clip_raster
    from glass.cpu.arcg.spanlst.surf import viewshed
    from glass.cpu.arcg.spanlst.rcls import reclassify
    from glass.cpu.arcg._3D.view import line_of_sight
    from glass.to.rst import shp_to_raster
    from glass.to.rst.arcg import array_to_raster
    from glass.to.shp.arcg import geomArray_to_fc
    from glass.fm.rst import toarray_varcmap as rst_to_array

    arcpy.CheckOutExtension('Spatial')
    arcpy.env.overwriteOutput = True

    # Check if observerDataset is a Raster or a Feature Class
    RASTER_FORMATS = raster_formats()
    VECTOR_FORMATS = vector_formats()
    observerFormat = os.path.splitext(observerDataset)[1]

    if observerFormat in VECTOR_FORMATS:
        from glass.cpu.arcg.anls.exct import clip

    elif observerFormat in RASTER_FORMATS:
        from glass.to.shp.arcg import rst_to_pnt
        from glass.to.shp import rst_to_polyg

        # If raster, get CELLSIZE of the observer dataset
        CELLSIZE = get_cellsize(observerDataset, gisApi='arcpy')
        REF_CELLSIZE = 500

        from glass.cpu.arcg.mng.sample import fishnet
        from glass.cpu.arcg.anls.ovlay import erase
        from glass.cpu.arcg.mng.feat import feat_to_pnt

    else:
        raise ValueError(('Could not identify if observerDataset is a raster '
                          'or a feature class'))

    # Create workspace for temporary files
    wTmp = create_folder(os.path.join(output_folder, 'tempfiles'))

    # When clipping the observerDataset (when it is a raster), there is a change
    # of obtaining a raster with more values than the original raster
    # Check values of the observerDataset
    UNIQUEVALUES = []
    if observerFormat in RASTER_FORMATS:
        for line in arcpy.SearchCursor(observerDataset):
            # TODO: Raster could not have attribute table
            value = int(line.getValue("Value"))

            if value not in UNIQUEVALUES:
                UNIQUEVALUES.append(value)

            else:
                continue

    # List feature classes
    arcpy.env.workspace = feat_class_folder
    fclasses = arcpy.ListFeatureClasses()

    for fc in fclasses:
        # Create Buffer
        fcBuffer = _buffer(
            fc,
            visibilityRadius,
            os.path.join(wTmp, os.path.basename(fc)),
        )

        # Clip inRaster
        clipInRst = clip_raster(inRaster,
                                fcBuffer,
                                os.path.join(
                                    wTmp, 'dem_{}{}'.format(
                                        os.path.splitext(
                                            os.path.basename(fc))[0],
                                        os.path.splitext(inRaster)[1])),
                                snap=snapRst,
                                clipGeom=True)

        # Clip observerDataset
        # If Raster, convert to points
        if observerDataset in VECTOR_FORMATS:
            clipObs = clip(
                observerDataset, fcBuffer,
                os.path.join(
                    wTmp, 'obs_{}{}'.format(
                        os.path.splitext(os.path.basename(fc))[0],
                        os.path.splitext(observerDataset)[1])))

        elif observerFormat in RASTER_FORMATS:
            # Clip Raster
            clipTmp = clip_raster(
                observerDataset,
                fcBuffer,
                os.path.join(
                    wTmp, 'obs_{}{}'.format(
                        os.path.splitext(os.path.basename(fc))[0],
                        os.path.splitext(observerDataset)[1])),
                snap=snapRst,
                clipGeom=True)

            # Check if clip has the same values that the original raster
            RST_UNIQUE = rst_distinct(clipTmp, gisApi='arcpy')
            if len(RST_UNIQUE) > len(UNIQUEVALUES):
                # Reclassify raster
                rules = {}
                for v in RST_UNIQUE:
                    if v in UNIQUEVALUES:
                        rules[v] = v
                    else:
                        rules[v] = 'NODATA'

                clipTmp = reclassify(
                    clipTmp,
                    'Value',
                    rules,
                    os.path.join(wTmp,
                                 'r_{}'.format(os.path.basename(clipTmp))),
                    template=clipTmp)

            if CELLSIZE < REF_CELLSIZE:
                # if cellsize if less than REF_CELLSIZE
                # Change cellsize to REF_CELLSIZE:

                # 1) Create fishnet REF_CELLSIZE
                fishNet = fishnet(os.path.join(
                    wTmp, 'fish_{}'.format(os.path.basename(fc))),
                                  clipTmp,
                                  cellWidth=REF_CELLSIZE,
                                  cellHeight=REF_CELLSIZE)

                # 2) Erase areas with NoData Values
                # Raster to shp
                cls_intPolygon = rst_to_polyg(
                    clipTmp,
                    os.path.join(wTmp,
                                 'cls_int_{}'.format(os.path.basename(fc))),
                    gisApi='arcpy')

                # - Erase areas of the fishnet that have nodata values
                # in the raster
                tmpErase = erase(
                    fishNet, cls_intPolygon,
                    os.path.join(wTmp,
                                 'nozones_{}'.format(os.path.basename(fc))))

                trueErase = erase(
                    fishNet, tmpErase,
                    os.path.join(wTmp,
                                 'fishint_{}'.format(os.path.basename(fc))))

                # 3) Convert erased fishnet to points
                clipObs = feat_to_pnt(
                    trueErase,
                    os.path.join(wTmp, 'obs_{}'.format(os.path.basename(fc))),
                    pnt_position="INSIDE")

            else:
                clipObs = rst_to_pnt(
                    clipTmp,
                    os.path.join(wTmp, 'obs_{}'.format(os.path.basename(fc))))

        # Calculate visibility
        # Boundary to raster
        boundRst = shp_to_raster(
            fc,
            'FID',
            CELLSIZE,
            None,
            os.path.join(
                wTmp, '{}_{}'.format(
                    os.path.splitext(os.path.basename(fc))[0],
                    os.path.splitext(observerDataset)[1])),
            snap=clipInRst,
            api='arcpy')

        noDataVal = get_nodata(boundRst, gisApi='arcpy')

        boundArray = rst_to_array(boundRst)

        # Raster to array
        # For each cell, get cell position and create line of sight
        shape = rst_shape(boundRst, gisApi='arcpy')
        xmin, xmax, ymin, ymax = rst_ext(boundRst, gisApi='arcpy2')

        visibilityArray = numpy.zeros((shape[0], shape[1]))

        numpy.copyto(visibilityArray, boundArray, 'unsafe',
                     boundArray == noDataVal)

        for l in range(len(visibilityArray)):
            for c in range(len(visibilityArray[l])):
                if visibilityArray[l][c] == noDataVal:
                    continue

                # Get cell position
                x, y = get_cell_coord(l, c, xmin, ymin, CELLSIZE, CELLSIZE)

                # Get Line of sight
                cursor = arcpy.SearchCursor(clipObs)
                for line in cursor:
                    FID = line.getValue("FID")
                    geom = line.Shape.centroid
                    sightArray = [
                        {
                            "FID": 0,
                            "GEOM": [(x, y), (geom.X, geom.Y)]
                        },
                    ]

                    lineSight = geomArray_to_fc(
                        sightArray,
                        os.path.join(
                            wTmp, 'ls_{}_{}_{}_{}{}'.format(
                                os.path.splitext(os.path.basename(fc))[0],
                                str(l), str(c), str(FID),
                                os.path.splitext(fc)[1])), "POLYLINE", epsg)

                    lineSightRes = line_of_sight(
                        clipInRst, lineSight,
                        os.path.join(
                            wTmp, 'lsr_{}_{}_{}_{}{}'.format(
                                os.path.splitext(os.path.basename(fc))[0],
                                str(l), str(c), str(FID),
                                os.path.splitext(fc)[1])))

                    lyrLineSight = feat_lyr(lineSightRes)

                    cs = arcpy.SearchCursor(lyrLineSight)
                    lnh = cs.next()
                    cnt = 0
                    while cnt == 0:
                        try:
                            vis = lnh.getValue("TarIsVis")
                        except:
                            pass
                        cnt += 1

                    if vis == 1:
                        visibilityArray[l][c] = 1
                        break
                    else:
                        continue

        # Generate Raster with visibility data
        visibilityRst = array_to_raster(
            visibilityArray, xmin, CELLSIZE, CELLSIZE,
            os.path.join(
                output_folder, 'vis_{}{}'.format(
                    os.path.splitext(os.path.basename(fc))[0],
                    os.path.splitext(clipInRst)[1])))

    return output_folder
Beispiel #4
0
def euclidean_distance(shpRst,
                       cellsize,
                       outRst,
                       template=None,
                       boundary=None,
                       snap=None):
    """
    Euclidean distance from Spatial Analyst
    """

    from arcpy import env
    from arcpy.sa import *
    import os

    arcpy.CheckOutExtension('Spatial')

    from glass.prop.ff import vector_formats, raster_formats
    from glass.cpu.arcg.lyr import feat_lyr, rst_lyr

    path_to_output = outRst if not boundary else \
        os.path.join(
            os.path.dirname(outRst),
            '{n}_ext{f}'.format(
                n=os.path.splitext(os.path.basename(outRst))[0],
                f=os.path.splitext(os.path.basename(outRst))[1]
            )
        )

    inputFormat = os.path.splitext(shpRst)[1]
    if inputFormat in vector_formats():
        inLyr = feat_lyr(shpRst)

    elif inputFormat in raster_formats():
        inLyr = rst_lyr(shpRst)

    else:
        raise ValueError(
            'Could not identify if shpRst is a feature class or a raster')

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

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

    outEucDistance = EucDistance(inLyr, "", cellsize, "")
    outEucDistance.save(path_to_output)

    if template: env.extent = tempEnvironment0

    if snap: env.snapRaster = tempSnap

    if boundary:
        from glass.cpu.arcg.mng.rst.proc import clip_raster

        clipLyr = feat_lyr(boundary)

        clip_raster(path_to_output,
                    clipLyr,
                    outRst,
                    template=template,
                    snap=snap)
Beispiel #5
0
def viewshed_by_feat_class(inRaster,
                           observerDataset,
                           feat_class_folder,
                           output_folder,
                           snapRst=None,
                           visibilityRadius=50000):
    """
    Run viewshed for each feature class in a folder
    
    observerDataset should be a raster or a point/line feature class;
    observerDataset and inRaster should have a major extent than each one
    of the feature class in feat_class_folder
    
    A visibilityRadius is necessary to do a buffer of each feature class.
    Some entity could be outside of the feature class boundary but visible
    from within the same boundary.
    
    Restrictions:
    * ObserverDataset must have a table if a raster;
    
    TO BE MANTAINED?
    """

    import arcpy
    import os

    arcpy.CheckOutExtension('Spatial')

    from glass.oss.ops import create_folder
    from glass.prop.ff import vector_formats, raster_formats
    from glass.prop.rst import get_cellsize, rst_distinct
    from glass.anls.prox.bf import _buffer
    from glass.cpu.arcg.mng.rst.proc import clip_raster
    from glass.cpu.arcg.spanlst.surf import viewshed
    from glass.cpu.arcg.spanlst.rcls import reclassify

    # Check if observerDataset is a Raster or a Feature Class
    # Import methods to clip obserserverDataset
    RASTER_FORMATS = raster_formats()
    VECTOR_FORMATS = vector_formats()
    observerFormat = os.path.splitext(observerDataset)[1]

    if observerFormat in VECTOR_FORMATS:
        from glass.cpu.arcg.anls.exct import clip

    elif observerFormat in RASTER_FORMATS:
        from glass.to.shp.arcg import rst_to_pnt
        from glass.to.shp import rst_to_polyg

        # If Raster, get CELLSIZE of the observer dataset
        CELLSIZE = get_cellsize(observerDataset, gisApi='arcpy')
        REF_CELLSIZE = 500

        from glass.cpu.arcg.mng.sample import fishnet
        from glass.cpu.arcg.anls.ovlay import erase
        from glass.cpu.arcg.mng.feat import feat_to_pnt

    else:
        raise ValueError(('Could not identify if observerDataset '
                          'is a raster or a feature class'))

    # Create workspace for temporary files
    wTmp = create_folder(os.path.join(output_folder, 'tempfiles'))

    # When clipping the observerDataset (when it is a raster), there is a change
    # of obtaining a raster with more values than the original raster
    # Check values of the observerDataset
    UNIQUEVALUES = []
    if observerFormat in RASTER_FORMATS:
        for line in arcpy.SearchCursor(observerDataset):
            value = int(line.getValue("Value"))

            if value not in UNIQUEVALUES:
                UNIQUEVALUES.append(value)

            else:
                continue

    # List feature classes
    arcpy.env.workspace = feat_class_folder
    fclasses = arcpy.ListFeatureClasses()

    for fc in fclasses:
        # Create Buffer
        fcBuffer = _buffer(fc,
                           visibilityRadius,
                           os.path.join(wTmp, os.path.basename(fc)),
                           api='arcpy')
        # Clip inRaster
        clipInRst = clip_raster(inRaster,
                                fcBuffer,
                                os.path.join(
                                    wTmp, 'inrst_{}{}'.format(
                                        os.path.splitext(
                                            os.path.basename(fc))[0],
                                        os.path.splitext(inRaster)[1])),
                                snap=snapRst,
                                clipGeom=True)

        # Clip observerDataset
        # If Raster, convert to points
        if observerFormat in VECTOR_FORMATS:
            clipObs = clip(
                observerDataset, fcBuffer,
                os.path.join(
                    wTmp, 'obs_{}{}'.format(
                        os.path.splitext(os.path.basename(fc))[0],
                        os.path.splitext(observerDataset)[1])))

        elif observerFormat in RASTER_FORMATS:
            # Clip raster
            clipTmp = clip_raster(
                observerDataset,
                fcBuffer,
                os.path.join(
                    wTmp, 'obs_{}{}'.format(
                        os.path.splitext(os.path.basename(fc))[0],
                        os.path.splitext(observerDataset)[1])),
                snap=snapRst,
                clipGeom=None)

            # Check if clip has the same values as the original raster
            RST_UNIQUE = rst_distinct(clipTmp, gisApi='arcpy')
            if len(RST_UNIQUE) > len(UNIQUEVALUES):
                # Reclassify raster
                rules = {}
                for v in RST_UNIQUE:
                    if v in UNIQUEVALUES:
                        rules[v] = v
                    else:
                        rules[v] = 'NODATA'

                clipTmp = reclassify(
                    clipTmp,
                    'Value',
                    rules,
                    os.path.join(wTmp,
                                 'r_{}'.format(os.path.basename(clipTmp))),
                    template=clipTmp)

            if CELLSIZE < REF_CELLSIZE:
                # if cellsize if less than REF_CELLSIZE
                # Change cellsize to REF_CELLSIZE:

                # 1) Create fishnet REF_CELLSIZE
                fishNet = fishnet(os.path.join(
                    wTmp, 'fish_{}'.format(os.path.basename(fc))),
                                  clipTmp,
                                  cellWidth=REF_CELLSIZE,
                                  cellHeight=REF_CELLSIZE)

                # 2) Erase areas with NoData values
                # - Raster to shp
                cls_intPolygon = rst_to_polyg(
                    clipTmp,
                    os.path.join(wTmp,
                                 'cls_int_{}'.format(os.path.basename(fc))),
                    gisApi='arcpy')

                # - Erase areas of the fishnet that agrees with nodata values in the raster
                tmpErase = erase(
                    fishNet, cls_intPolygon,
                    os.path.join(wTmp,
                                 'nozones_{}'.format(os.path.basename(fc))))
                trueErase = erase(
                    fishNet, tmpErase,
                    os.path.join(wTmp,
                                 'fishint_{}'.format(os.path.basename(fc))))

                # 3) Convert erased fishnet to points
                clipObs = feat_to_pnt(
                    trueErase,
                    os.path.join(wTmp, 'obs_{}'.format(os.path.basename(fc))),
                    pnt_position="INSIDE")

            # Else - simple conversion to points
            else:
                clipObs = rst_to_pnt(
                    clipTmp,
                    os.path.join(wTmp, 'obs_{}'.format(os.path.basename(fc))))

        # Run viewshed
        viewshed(
            clipInRst, clipObs,
            os.path.join(
                output_folder, 'vis_{}{}'.format(
                    os.path.splitext(os.path.basename(fc))[0],
                    os.path.splitext(clipInRst)[1])))