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
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
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_
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