Beispiel #1
0
def split_flowline(intersectionPoint, flowlines):

    # Convert the flowline to a geometry colelction to be exported
    nhdGeom = flowlines['features'][0]['geometry']
    nhdFlowline = GeometryCollection([shape(nhdGeom)])[0]
    nhdFlowline = LineString([xy[0:2] for xy in list(nhdFlowline[0].coords)
                              ])  # Convert xyz to xy

    # If the intersectionPoint is on the NHD Flowline, split the flowline at the point
    if nhdFlowline.intersects(intersectionPoint) is True:
        NHDFlowlinesCut = split(nhdFlowline, intersectionPoint)

    # If they don't intersect (weird right?), buffer the intersectionPoint and then split the flowline
    if nhdFlowline.intersects(intersectionPoint) is False:
        buffDist = intersectionPoint.distance(nhdFlowline) * 1.01
        buffIntersectionPoint = intersectionPoint.buffer(buffDist)
        NHDFlowlinesCut = split(nhdFlowline, buffIntersectionPoint)
        # print('NHDFlowlinesCut: ', len(NHDFlowlinesCut), NHDFlowlinesCut)

    # If the NHD Flowline was split, then calculate measure
    try:
        NHDFlowlinesCut[1]
    except AssertionError as error:  # If NHDFlowline was not split, then the intersectionPoint is either the first or last point on the NHDFlowline
        startPoint = Point(nhdFlowline[0].coords[0][0],
                           nhdFlowline[0].coords[0][1])
        lastPointID = len(nhdFlowline[0].coords) - 1
        lastPoint = Point(nhdFlowline[0].coords[lastPointID][0],
                          nhdFlowline[0].coords[lastPointID][1])
        if (intersectionPoint == startPoint):
            upstreamFlowline = GeometryCollection()
            downstreamFlowline = NHDFlowlinesCut
            error = 'The point of intersection is the first point on the NHD Flowline.'
        if (intersectionPoint == lastPoint):
            downstreamFlowline = GeometryCollection()
            upstreamFlowline = NHDFlowlinesCut
            error = 'The point of intersection is the last point on the NHD Flowline.'
        if (intersectionPoint != startPoint
                and intersectionPoint != lastPoint):
            error = 'Error: NHD Flowline measure not calculated'
            downstreamFlowline = GeometryCollection()
            upstreamFlowline = GeometryCollection()
        print(error)
    else:
        lastLineID = len(NHDFlowlinesCut) - 1
        upstreamFlowline = NHDFlowlinesCut[0]
        downstreamFlowline = NHDFlowlinesCut[lastLineID]
    print('split NHD Flowline')

    return upstreamFlowline, downstreamFlowline
Beispiel #2
0
def get_reachMeasure(intersectionPoint, flowlines, *raindropPath):
    """Collect NHD Flowline Reach Code and Measure"""
    print('intersectionPoint: ', intersectionPoint)

    # Set Geoid to measure distances in meters
    geod = Geod(ellps="WGS84")

    # Convert the flowline to a geometry colelction to be exported
    nhdGeom = flowlines['features'][0]['geometry']
    nhdFlowline = GeometryCollection([shape(nhdGeom)])[0]

    # Select the stream name from the NHD Flowline
    streamname = flowlines['features'][0]['properties']['gnis_name']
    if streamname == ' ':
        streamname = 'none'

    # Create streamInfo dict and add some data
    streamInfo = {
        'gnis_name':
        streamname,
        'comid':
        flowlines['features'][0]['properties']['comid'],
        # 'lengthkm': flowlines['features'][0]['properties']['lengthkm'],
        'intersectionPoint':
        (intersectionPoint.coords[0][1], intersectionPoint.coords[0][0]),
        'reachcode':
        flowlines['features'][0]['properties']['reachcode']
    }

    # Add more data to the streamInfo dict
    if raindropPath:
        streamInfo['raindropPathDist'] = round(
            geod.geometry_length(raindropPath[0]), 2)

    # If the intersectionPoint is on the NHD Flowline, split the flowline at the point
    if nhdFlowline.intersects(intersectionPoint) is True:
        NHDFlowlinesCut = split(nhdFlowline, intersectionPoint)

    # If they don't intersect (weird right?), buffer the intersectionPoint and then split the flowline
    if nhdFlowline.intersects(intersectionPoint) is False:
        buffDist = intersectionPoint.distance(nhdFlowline) * 1.01
        buffIntersectionPoint = intersectionPoint.buffer(buffDist)
        NHDFlowlinesCut = split(nhdFlowline, buffIntersectionPoint)
        # print('NHDFlowlinesCut: ', len(NHDFlowlinesCut), NHDFlowlinesCut)

    # If the NHD Flowline was split, then calculate measure
    try:
        NHDFlowlinesCut[1]
    except:  # If NHDFlowline was not split, then the intersectionPoint is either the first or last point on the NHDFlowline
        startPoint = Point(nhdFlowline[0].coords[0][0],
                           nhdFlowline[0].coords[0][1])
        lastPointID = len(nhdFlowline[0].coords) - 1
        lastPoint = Point(nhdFlowline[0].coords[lastPointID][0],
                          nhdFlowline[0].coords[lastPointID][1])
        if (intersectionPoint == startPoint):
            streamInfo['measure'] = 100
        if (intersectionPoint == lastPoint):
            streamInfo['measure'] = 0
        if (intersectionPoint != startPoint
                and intersectionPoint != lastPoint):
            print('Error: NHD Flowline measure not calculated')
            streamInfo['measure'] = 'null'
    else:
        lastLineID = len(NHDFlowlinesCut) - 1
        distToOutlet = round(geod.geometry_length(NHDFlowlinesCut[lastLineID]),
                             2)
        flowlineLength = round(geod.geometry_length(nhdFlowline), 2)
        streamInfo['measure'] = round((distToOutlet / flowlineLength) * 100, 2)
    print('calculated measure and reach')

    return streamInfo
Beispiel #3
0
def check_connectivity(feats,
                       feats_end_point,
                       connect_name,
                       uniqueid,
                       tolerance=0.0001,
                       logger=logging):
    """
    checks the connectivity of all features in list "feats" to features in list feats_end_points.
    Connected features are given the same connected_id, based on the
    initialy selected feature.

    Args:
        feats: list of JSON-type features (with 'geometry' and 'properties')
        feats_end_points: features, to which other features should be connected to
        connect_name: name of tag to use to identify connectivity
        uniqueid: key name of identifier for features that all features should be connected to
        tolerance=: tolerance where within elements are assumed to be connected. Is set in ini-file
        logger=logging: reference to logger object for messaging

    Returns:
        feats: list of JSON-type features with 'properties' containing the connected flag (id)
    """
    # first check if each point feature contains a unique id which is non-zero.
    collect_uniqueids = [f['properties'][uniqueid] for f in feats_end_point]
    # check for zeros
    if 0 in collect_uniqueids or None in collect_uniqueids:
        logger.error(
            'Connect features unique id "{:s}" contains zero or null values. Make sure the values in "{:s}" are unique non-zero'
            .format(uniqueid, uniqueid))
        sys.exit(1)
    # check for non-uniqueness
    if len(np.unique(collect_uniqueids)) < len(collect_uniqueids):
        logger.warning(
            'Connect features unique id "{:s}" contains non-unique values. We continue...'
            .format(uniqueid))

    end_name = connect_name + '_points'
    feats_ = copy.copy(feats)
    logger.info('Checking the connectivity...')
    # Build a spatial index to make all faster
    tree_idx = rtree.index.Index()
    # lines_bbox = []
    # for n, l in enumerate(feats_):
    #     print n
    #     if n == 308:
    #         import pdb; pdb.set_trace()
    #     add = l['geometry'].buffer(tolerance).bounds
    #     lines_bbox.append(add)
    #
    lines_bbox = [
        l['geometry'].buffer(tolerance).bounds
        if l['geometry'] is not None else (0., 0., 0., 0.) for l in feats_
    ]  # else None
    # import pdb; pdb.set_trace()

    for i, bbox in enumerate(lines_bbox):
        tree_idx.insert(i, bbox)

    # Create two new properties, needed to check connectivity. Initial value == 0
    for i, feat in enumerate(feats_):
        feat['properties'][connect_name] = 0
        feat['properties'][end_name] = 0
    # make a geometry collection from all end points
    end_geoms = GeometryCollection(
        [f['geometry'] for f in feats_end_point if f['geometry'] is not None])
    # Make a list of the selected elements, for which we need to check the connectivity
    # select_ids = []
    # for idx in np.arange(0, len(feats_)):
    #     print idx
    #     if feats_[idx]['geometry'] is not None:
    #         # import pdb; pdb.set_trace()
    #         if end_geoms.intersects(feats_[idx]['geometry']):
    #             select_ids.append(idx)
    select_ids = [
        idx for idx in np.arange(0, len(feats_))
        if feats_[idx]['geometry'] is not None
        if end_geoms.intersects(feats_[idx]['geometry'])
    ]

    # select_ids = [idx for idx in np.arange(0, len(feats_)) if str(feats_[idx]['properties'][key]) in values]
    # Now start the actual check, looping over the selected elements
    for select_id in select_ids:
        # First set the properties of the selected elements
        feats_[int(select_id)]['properties'][connect_name] = feats_[select_id][
            'properties'][uniqueid]
        feats_[int(select_id)]['properties'][end_name] = 2
        to_check = 1
        endpoints_list = [select_id]
        while to_check > 0:
            for endpoint_id in endpoints_list:
                # Find all elements for which the bounding box connects to the selected element to narrow
                # the number of elements to loop over.
                hits = list(
                    tree_idx.intersection(lines_bbox[int(endpoint_id)],
                                          objects=False))
                for i in hits:
                    # Ugly solution to solve the issue
                    if feats_[i]['properties'][end_name] > 0:
                        feats_[i]['properties'][
                            end_name] = feats_[i]['properties'][end_name] - 1

                    # Check if element is not itself, to overcome the issue of endless loop
                    if feats_[i]['properties'][connect_name] != feats_[
                            select_id]['properties'][uniqueid]:
                        # if feats_[i]['geometry'] != feats_[select_id]['geometry']:  # check if this can be done with i != select_id
                        # Check if elements are disjoint. If disjoint, continue to the next step.
                        if feats_[i]['geometry'] is not None:
                            if feats_[i]['geometry'].disjoint(
                                    feats_[int(endpoint_id)]
                                ['geometry'].buffer(tolerance)):
                                continue
                            else:
                                # If elements are not disjoint, change the properties and add element to the "connected" list.
                                feats_[i]['properties'][end_name] = 15
                                feats_[i]['properties'][connect_name] = feats_[
                                    select_id]['properties'][uniqueid]
                    else:
                        continue
            endpoints_list = [
                j for j, feat in enumerate(feats_)
                if feat['properties'][end_name] > 0
            ]
            to_check = len(endpoints_list)

    return feats_
Beispiel #4
0
    def getBoundary(self, size_x=512, size_y=512, force=False):
        # Return the img if already loaded
        if (self.img != "N/A"):
            return self.img

        # Find the "shape" of the boundary, if we haven't already
        if (self.boundary == "N/A"):
            self.boundary = self.getFeature()

        # If the "shape" of the boundary cannot be found, that's all we can do
        if (self.boundary == "N/A"):
            return "N/A"

        # Check if the "img" has already been cached, and just open it if it is there
        os.makedirs("cached_property_images", exist_ok=True)

        cache_file = os.path.join(
            "cached_property_images", self.boundary['properties']['LOT'] +
            "_" + self.boundary['properties']['PLAN'] + ".png")

        if (os.path.exists(cache_file) and (force == False)):
            self.img = Image.open(cache_file)
            return self.img

        print("Isolating farm", end='')

        with open(
                os.path.join(
                    "geometries", "geo-x" + str(self.tile_x) + "-y" +
                    str(self.tile_y) + ".geojson")) as f1:
            geo_json_features = json.load(f1)["features"]

        tile = GeometryCollection([
            shape(feature["geometry"]).buffer(0)
            for feature in geo_json_features
        ])

        self.img = Image.new('RGBA', (size_x, size_y))

        count_hit = 0

        result = GeometryCollection()

        if shape(self.boundary["geometry"]).intersects(tile):
            result = result.union(
                shape(self.boundary["geometry"]).intersection(tile))

        if tile.intersects(result):
            for y in range(size_y):
                if (y % 15 == 0):
                    #print("y="+  str(y) + ", hits=" + str(count_hit))
                    print(".", end="")
                for x in range(size_x):
                    lat_long = self.GetLatLongForCoords(y, x)
                    if result.intersects(Point(lat_long)):
                        self.img.putpixel((y, x), (0, 0, 255, 255))  # Blue
                        count_hit += 1

        #print("Hits: " + str(count_hit))

        # Find the border
        for y in range(size_y):
            for x in range(size_x):
                # It is a border if it's not blue...
                if (self.img.getpixel((y, x)) != (0, 0, 255, 255)):
                    # And it has a neighbour that is blue
                    for j in range(y - 1, y + 2):
                        for i in range(x - 1, x + 2):
                            # Check for neighbour out of bounds, don't compare pixel to itself
                            if ((j >= 0) and (j < size_y) and (i >= 0)
                                    and (i < size_x)
                                    and ((j != y) or (i != x))):
                                if (self.img.getpixel(
                                    (j, i)) == (0, 0, 255, 255)):
                                    # This is part of the border!
                                    self.img.putpixel((y, x), (255, 0, 0, 255))

        # Save the image to the cache
        self.img.save(cache_file)

        print(" done")

        return self.img