def test_shapely_intersection(): """Testing Shapely: Test against prepared geometry intersection bug #603""" # http://trac.osgeo.org/geos/ticket/603 from shapely.geometry import MultiPolygon, box from shapely.prepared import prep from shapely import wkt assert MultiPolygon([box(0, 0, 1, 10), box(40, 0, 41, 10)]).intersects(box(20, 0, 21, 10)) == False assert prep(MultiPolygon([box(0, 0, 1, 10), box(40, 0, 41, 10)])).intersects(box(20, 0, 21, 10)) == False # tile_grid(3857, origin='nw').tile_bbox((536, 339, 10)) tile = box(939258.2035682462, 6731350.458905761, 978393.9620502564, 6770486.217387771) tile = box(978393.9620502554, 6770486.217387772, 1017529.7205322656, 6809621.975869782) # "{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"type":"box_control"},"geometry":{"type":"Polygon","coordinates":[[[1449611.9686912997,6878109.5532215],[1449611.9686912997,6909907.3569881],[1476517.8026477,6909907.3569881],[1476517.8026477,6878109.5532215],[1449611.9686912997,6878109.5532215]]]}},{"type":"Feature","properties":{"type":"box_control"},"geometry":{"type":"Polygon","coordinates":[[[909049.30465869,6435386.285393901],[909049.30465869,6457400.14954],[943293.0933304401,6457400.14954],[943293.0933304401,6435386.285393901],[909049.30465869,6435386.285393901]]]}}]}" coverage = wkt.loads( "MULTIPOLYGON (" "((1449611.9686912996694446 6878109.5532214995473623, " "1449611.9686912996694446 6909907.3569881003350019, " "1476517.8026477000676095 6909907.3569881003350019, " "1476517.8026477000676095 6878109.5532214995473623, " "1449611.9686912996694446 6878109.5532214995473623)), " "((909049.3046586900018156 6435386.2853939011693001, " "909049.3046586900018156 6457400.1495399996638298, " "943293.0933304401114583 6457400.1495399996638298, " "943293.0933304401114583 6435386.2853939011693001, " "909049.3046586900018156 6435386.2853939011693001)))" ) assert prep(coverage).contains(tile) == False assert prep(coverage).intersects(tile) == False
def __init__(self, regions_file=REGIONS_FILE, buffer_file=REGIONS_BUFFER_FILE): self._buffered_shapes = {} self._prepared_shapes = {} self._shapes = {} self._tree_ids = {} self._radii = {} with util.gzip_open(regions_file, 'r') as fd: regions_data = simplejson.load(fd) genc_regions = frozenset([rec.alpha2 for rec in genc.REGIONS]) for feature in regions_data['features']: code = feature['properties']['alpha2'] if code in genc_regions: shape = geometry.shape(feature['geometry']) self._shapes[code] = shape self._prepared_shapes[code] = prepared.prep(shape) self._radii[code] = feature['properties']['radius'] with util.gzip_open(buffer_file, 'r') as fd: buffer_data = simplejson.load(fd) i = 0 envelopes = [] for feature in buffer_data['features']: code = feature['properties']['alpha2'] if code in genc_regions: shape = geometry.shape(feature['geometry']) self._buffered_shapes[code] = prepared.prep(shape) # Collect rtree index entries, and maintain a separate id to # code mapping. We don't use index object support as it # requires un/pickling the object entries on each lookup. if isinstance(shape, geometry.base.BaseMultipartGeometry): # Index bounding box of individual polygons instead of # the multipolygon, to avoid issues with regions crossing # the -180.0/+180.0 longitude boundary. for geom in shape.geoms: envelopes.append((i, geom.envelope.bounds, None)) self._tree_ids[i] = code i += 1 else: envelopes.append((i, shape.envelope.bounds, None)) self._tree_ids[i] = code i += 1 props = index.Property() props.fill_factor = 0.9 props.leaf_capacity = 20 self._tree = index.Index(envelopes, interleaved=True, properties=props) for envelope in envelopes: self._tree.insert(*envelope) self._valid_regions = frozenset(self._shapes.keys())
def __init__(self, json_file=JSON_FILE): self._buffered_shapes = {} self._prepared_shapes = {} self._shapes = {} self._tree_ids = {} self._radii = {} with util.gzip_open(json_file, 'r') as fd: data = simplejson.load(fd) genc_regions = frozenset([rec.alpha2 for rec in genc.REGIONS]) for feature in data['features']: code = feature['properties']['alpha2'] if code in genc_regions: shape = geometry.shape(feature['geometry']) self._shapes[code] = shape self._prepared_shapes[code] = prepared.prep(shape) self._radii[code] = feature['properties']['radius'] i = 0 envelopes = [] for code, shape in self._shapes.items(): # Build up region buffers, to create shapes that include all of # the coastal areas and boundaries of the regions and anywhere # a cell signal could still be recorded. The value is in decimal # degrees (1.0 == ~100km) but calculations don't take projection # / WSG84 into account. # After buffering remove any parts that crosses the -180.0/+180.0 # longitude boundary to the east or west. buffered = (shape.buffer(0.5) .difference(DATELINE_EAST) .difference(DATELINE_WEST)) self._buffered_shapes[code] = prepared.prep(buffered) # Collect rtree index entries, and maintain a separate id to # code mapping. We don't use index object support as it # requires un/pickling the object entries on each lookup. if isinstance(buffered, geometry.base.BaseMultipartGeometry): # Index bounding box of individual polygons instead of # the multipolygon, to avoid issues with regions crossing # the -180.0/+180.0 longitude boundary. for geom in buffered.geoms: envelopes.append((i, geom.envelope.bounds, None)) self._tree_ids[i] = code i += 1 else: envelopes.append((i, buffered.envelope.bounds, None)) self._tree_ids[i] = code i += 1 props = index.Property() props.fill_factor = 0.9 props.leaf_capacity = 20 self._tree = index.Index(envelopes, interleaved=True, properties=props) self._valid_regions = frozenset(self._shapes.keys())
def test_prepare_already_prepared(): polygon = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]) prepared = prep(polygon) # attempt to prepare an already prepared geometry with `prep` result = prep(prepared) assert isinstance(result, PreparedGeometry) assert result.context is polygon # attempt to prepare an already prepared geometry with `PreparedGeometry` result = PreparedGeometry(prepared) assert isinstance(result, PreparedGeometry) assert result.context is polygon
def _rings_to_multi_polygon(self, rings, is_ccw): exterior_rings = [] interior_rings = [] for ring in rings: if ring.is_ccw != is_ccw: interior_rings.append(ring) else: exterior_rings.append(ring) polygon_bits = [] # Turn all the exterior rings into polygon definitions, # "slurping up" any interior rings they contain. for exterior_ring in exterior_rings: polygon = sgeom.Polygon(exterior_ring) prep_polygon = prep(polygon) holes = [] for interior_ring in interior_rings[:]: if prep_polygon.contains(interior_ring): holes.append(interior_ring) interior_rings.remove(interior_ring) polygon_bits.append((exterior_ring.coords, [ring.coords for ring in holes])) # Any left over "interior" rings need "inverting" with respect # to the boundary. if interior_rings: boundary_poly = self.domain x3, y3, x4, y4 = boundary_poly.bounds bx = (x4 - x3) * 0.1 by = (y4 - y3) * 0.1 x3 -= bx y3 -= by x4 += bx y4 += by for ring in interior_rings: polygon = sgeom.Polygon(ring) if polygon.is_valid: x1, y1, x2, y2 = polygon.bounds bx = (x2 - x1) * 0.1 by = (y2 - y1) * 0.1 x1 -= bx y1 -= by x2 += bx y2 += by box = sgeom.box(min(x1, x3), min(y1, y3), max(x2, x4), max(y2, y4)) # Invert the polygon polygon = box.difference(polygon) # Intersect the inverted polygon with the boundary polygon = boundary_poly.intersection(polygon) if not polygon.is_empty: polygon_bits.append(polygon) if polygon_bits: multi_poly = sgeom.MultiPolygon(polygon_bits) else: multi_poly = sgeom.MultiPolygon() return multi_poly
def _set_mapdata(self): self.df_map = pd.DataFrame({ 'poly': [Polygon(points) for points in self.map.seattle], 'name': [hood[self.section_name] for hood in self.map.seattle_info] }) self.hood_polygons = prep(MultiPolygon(list(self.df_map['poly'].values)))
def cover_geometry(tilescheme, geom, zoom): """Covers the provided geometry with tiles. Args: tilescheme: The tile scheme to use. This needs to implement the public protocal of the schemes defined within tiletanic. geom: The geometry we would like to cover. This should be a shapely geometry. zoom: The zoom level of the tiles to cover geom with. Yields: An iterator of Tile objects ((x, y, z) named tuples) that cover the input geometry. """ # Only shapely geometries allowed. if not isinstance(geom, geometry.base.BaseGeometry): raise ValueError("Input 'geom' is not a known shapely geometry type") if geom.is_empty: return # Generate the covering. prep_geom = prepared.prep(geom) if isinstance(geom, (geometry.Polygon, geometry.MultiPolygon)): for tile in _cover_polygonal(tilescheme, Tile(0, 0, 0), prep_geom, geom, zoom): yield tile else: for tile in _cover_geometry(tilescheme, Tile(0, 0, 0), prep_geom, geom, zoom): yield tile
def iter_intersects(self, shapely_geom, geom_mapping, keep_touches=True): """ Return an interator for the unique identifiers of the geometries intersecting the target geometry. :param :class:`shapely.geometry.Geometry` shapely_geom: The geometry to use for subsetting. It is the ``bounds`` attribute fo the geometry that is actually tested. :param dict geom_mapping: The collection of geometries to do the full intersects test on. The keys of the dictionary correspond to the integer unique identifiers. The values are Shapely geometries. :param bool keep_touches: If ``True``, return the unique identifiers of geometries only touching the subset geometry. :returns: Generator yield integer unique identifiers. :rtype: int """ # Create the geometry iterator. If it is a multi-geometry, we want to iterator over those individually. try: itr = iter(shapely_geom) except TypeError: # likely not a multi-geometry itr = [shapely_geom] for shapely_geom_sub in itr: # Return the initial identifiers that intersect with the bounding box using the retree internal method. ids = self._get_intersection_rtree_(shapely_geom_sub) # Prepare the geometry for faster operations. prepared = prep(shapely_geom_sub) _intersects = prepared.intersects _touches = shapely_geom_sub.touches for ii in ids: geom = geom_mapping[ii] if _intersects(geom): if keep_touches == False: if _touches(geom) == False: yield (ii) else: yield (ii)
def _tiles_inside_geom(tilescheme, tiles, geom): """Filters out tiles do not contain the geometry geom Consider the nine adjacent tiles: ------------- | 1 | 2 | 3 | ------------- | 4 | 5 | 6 | ------------- | 7 | 8 | 9 | ------------- if the AOI is 5, _tiles_inside_geom will only return 5. Note that tiletanic.tilecover.cover_geometry returns all 9 tiles Args: tilescheme: The tile scheme to use. tiles: list iterable collection of tiles geom: Shapely Geometry area of interest """ prep_geom = prepared.prep(geom) for t in tiles: coords = tilescheme.bbox(t) tile_geom = geometry.Polygon(((coords.xmin, coords.ymin), (coords.xmax, coords.ymin), (coords.xmax, coords.ymax), (coords.xmin, coords.ymax), (coords.xmin, coords.ymin))) # Touches: The Geometries have at least one boundary point in # common, but no interior points if not prep_geom.touches(tile_geom): yield t
def _get_level_geometries(level): buildings = level.buildings.all() buildings_geom = cascaded_union([building.geometry for building in buildings]) spaces = {space.pk: space for space in level.spaces.all()} holes_geom = [] for space in spaces.values(): if space.outside: space.geometry = space.geometry.difference(buildings_geom) columns = [column.geometry for column in space.columns.all()] if columns: columns_geom = cascaded_union([column.geometry for column in space.columns.all()]) space.geometry = space.geometry.difference(columns_geom) holes = [hole.geometry for hole in space.holes.all()] if holes: space_holes_geom = cascaded_union(holes) holes_geom.append(space_holes_geom.intersection(space.geometry)) space.geometry = space.geometry.difference(space_holes_geom) for building in buildings: building.original_geometry = building.geometry if holes_geom: holes_geom = cascaded_union(holes_geom) holes_geom_prep = prepared.prep(holes_geom) for obj in buildings: if holes_geom_prep.intersects(obj.geometry): obj.geometry = obj.geometry.difference(holes_geom) results = [] results.extend(buildings) for door in level.doors.all(): results.append(door) results.extend(spaces.values()) return results
def clip(coll,igeom): '''Do an intersects + intersection and set weights based on geometry areas. coll :: OcgCollection igeom :: Shapely Polygon or MultiPolygon returns OcgCollection''' ## logic for convenience. just return the provided collection if a NoneType ## is passed for the 'igeom' arugment if igeom is not None: ## take advange of shapely speedups prep_igeom = prepared.prep(igeom) ## the weight array weights = np.empty(coll.gid.shape,dtype=float) weights = np.ma.array(weights,mask=coll.gid.mask) ## do the spatial operation for idx,geom in iter_array(coll.geom_masked, return_value=True): # import ipdb;ipdb.set_trace() if keep(prep_igeom,igeom,geom): # import ipdb;ipdb.set_trace() new_geom = igeom.intersection(geom) weights[idx] = new_geom.area coll.geom[idx] = new_geom ## set maximum weight to one coll.weights = weights/weights.max() return(coll)
def intersects(self,polygon): ## do the initial grid subset grid = self.grid.subset(polygon=polygon) ## a prepared polygon prep_polygon = prepared.prep(polygon) ## the fill arrays geom = np.ones(grid.shape,dtype=object) geom = np.ma.array(geom,mask=True) geom_mask = geom.mask try: row = grid.row.value col = grid.column.value for ii,jj in product(range(row.shape[0]),range(col.shape[0])): pt = Point(col[jj],row[ii]) geom[ii,jj] = pt if prep_polygon.intersects(pt): geom_mask[ii,jj] = False else: geom_mask[ii,jj] = True ## NcGridMatrixDimension correction except AttributeError: _row = grid.row _col = grid.column for ii,jj in iter_array(_row): pt = Point(_col[ii,jj],_row[ii,jj]) geom[ii,jj] = pt if prep_polygon.intersects(pt): geom_mask[ii,jj] = False else: geom_mask[ii,jj] = True ret = self.__class__(grid=grid,geom=geom,uid=grid.uid) return(ret)
def select_values(self,igeom=None,clip=False): ## if an intersection geometry is passed, use it to calculate the weights ## but do not modify the geometry. this weight is used to select values ## to keep for set statistics. ## this is the case of no intersection geometry. basically, requesting ## the entire dataset. if clip and igeom is None: mask = np.zeros(self.value_shape) elif clip and igeom is not None: prep_igeom = prepared.prep(igeom) for ii,geom in enumerate(self.geometry): if keep(prep_igeom,igeom,geom): new_geom = igeom.intersection(geom) weight = new_geom.area/geom.area assert(weight != 0.0) #tdk self.weight[ii] = weight ## it has now been clipped clip = False if not clip: ## loop through the weights determining which values to maintain based ## on weights. idx = [] for ii,weight in enumerate(self.weight): if weight > 0.5: idx.append(ii) elif weight == 0.5: warn('0.5 weight encountered. Removing it.') ## select the data and store in special variable for use by set statistics mask = np.ones(self.value.shape) mask[:,:,idx] = 0 self.value_set = np.ma.masked_array(self.value,mask=mask)
def CreatePointObjects(BasemapTemplate, MapData, ComplaintData): ''' Here we create a community geometry object from the combined community polygons. We've done this to speed up membership checking. We perform the check by creating a mutipolygon from map_points, then filtering using the contains() method, which returns all points that are contains within community_poygons. The results is a pandas series returning NYCPoints, which we'll use to make out maps. ''' # Create Point objects (in a pandas Series) in map coordinates from our DataFrame longitude and latitude values. # Note that the zip function here aggregates the long/lat data for each observation in our compliant data. # The purpose of this code is to convert our latitude and longitude into Basemap cartesian map coordinates MapPoints = pd.Series([Point(BasemapTemplate(MapX, MapY)) for MapX, MapY in zip(ComplaintData['Longitude'], ComplaintData['Latitude'])]) # Creates a MultiPoint object from the list of lat/long values from above. ComplaintPoints = MultiPoint(list(MapPoints.values)) # Use the prep method to give this MultiPolygon object (created from the earlier DataFrame of complaint locations), so that it # has the 'contains' method, which we'll use in the next step. CommunityPolygon = prep(MultiPolygon(list(MapData['poly'].values))) # calculate points that fall within the community boundaries. Here NYCPoints # is a list containing Point objects of all the complaint points contained in # the community polygons. NYCPoints = filter(CommunityPolygon.contains, ComplaintPoints) return (NYCPoints)
def initialize_grid(self, geom): """ """ bounds = geom.bounds (minx, miny, maxx, maxy) = bounds (minx, miny, maxx, maxy) = ( round(np.floor(minx * self.psi)) / self.psi, round(np.floor(miny * self.psi)) / self.psi, round(np.ceil(maxx * self.psi)) / self.psi, round(np.ceil(maxy * self.psi)) / self.psi) clean_bounds = (minx, miny, maxx, maxy) top_left_lon = minx top_left_lat = maxy affine = Affine(self.pixel_size, 0, top_left_lon, 0, -self.pixel_size, top_left_lat) # base_rasterize, base_bounds = self.rasterize_geom(geom) # self.shape = base_rasterize.shape nrows = int(np.ceil( (maxy - miny) / self.pixel_size )) ncols = int(np.ceil( (maxx - minx) / self.pixel_size )) self.shape = (nrows, ncols) self.bounds = clean_bounds self.affine = affine self.topleft = (top_left_lon, top_left_lat) self.grid_box = prep(box(*self.bounds))
def update(self, transect): """ Gather the data near the transect. Depth convert if necessary. Returns nothing. Side effect: sets attributes. Args: transect (LineString): A shapely LineString object. """ Notice.info("Updating " + self.__class__.__name__) b = self.settings.get('fine_buffer') or self.settings['buffer'] prepared = prep(transect.buffer(b)) for horizon, points in self.lookup.items(): l = len(points) points = filter(prepared.contains, points) print horizon, len(points), "of", l, "points" data, coords = [], [] for p in points: coords.append(transect.project(p)) if self.domain.lower() in ['depth', 'd', 'z']: "Depth converting horizon" zpt = self.velocity.time2depthpt(p.z/1000, coords[-1]) data.append(zpt) else: data.append(p.z) self.data[horizon] = np.array(data) self.coords[horizon] = np.array(coords)
def associate_nodes(fargs): """ Find nodes which are within the hull """ cluster, cluster_hull, nodes = fargs # There is no hull for this community, it's been deleted. # Orphan all nodes. if cluster_hull is None: log.info("Missing hull, orphaning all nodes in cluster %i", cluster) output = [topotools.NodeInfo( orphan.id, orphan.lat, orphan.lon, -1) for orphan in nodes] return len(output), output characteristic_size = math.sqrt(cluster_hull.area) allowed_distance = characteristic_size * args.buffer buffered = prep(cluster_hull.buffer(allowed_distance)) output = [] num_orphans = 0 for node in nodes: # check if it is an interior node point = Point((node.lon, node.lat)) orphan = not buffered.contains(point) if orphan: num_orphans += 1 output.append(topotools.NodeInfo( node.id, node.lat, node.lon, -1 if orphan else node.clust)) return num_orphans, output
def run_tests(bbox, service_url, status_path=None): with fiona.open("ne_10m_land.geojson", "r") as source: n = source.next() land_polygon = prep(shape(n["geometry"])) features = [] session = requests.Session() for lon in range(bbox[0], bbox[2]): for lat in range(bbox[1], bbox[3]): test_coords = [] for x_offset in range(1, 4): for y_offset in range(1, 4): test_coords.append((lon + x_offset / 4.0, lat + y_offset / 4.0)) point_on_land = False for coord in test_coords: point = Point(coord[0], coord[1]) if land_polygon.contains(point): point_on_land = True break if not point_on_land: logging.debug("No points on land, %f,%f" % (lon, lat)) continue hgt_filename = "%s%02i%s%03i.hgt" % ("N" if lat > 0 else "S", abs(lat), "W" if lon < 0 else "E", abs(lon)) elevation = test(test_coords, service_url, session=session) logging.debug("%i, %i response:%i" % (lon, lat, elevation)) color = SUCCESS_COLOR if elevation == -9999: logging.info("fail %i,%i" % (lon, lat)) color = ERROR_COLOR elif elevation == 0: logging.info("maybe fail %i,%i" % (lon, lat)) color = POSSIBLE_ERROR_COLOR status_feature = { "type": "Feature", "properties": { "result": elevation, "hgt": hgt_filename, "points": ";".join([",".join([str(f) for f in c]) for c in test_coords]), "fill-opacity": 0.5, "fill": color, "stroke": "#000000", "stroke-width": 1, }, "geometry": { "type": "Polygon", "coordinates": [[[lon, lat], [lon, lat + 1], [lon + 1, lat + 1], [lon + 1, lat], [lon, lat]]], }, } features.append(status_feature) if status_path is not None and len(features) % 100 == 0: write_feature_collection(features, path=status_path) if status_path is not None: write_feature_collection(features, path=status_path)
def load_polygons(cls, filename): feature_collection = json.load(open(filename)) polygons = [] for feature in feature_collection['features']: poly_type = feature['geometry']['type'] if poly_type == 'Polygon': poly = Polygon(feature['geometry']['coordinates'][0]) polygons.append((feature['properties'], prep(poly))) elif poly_type == 'MultiPolygon': polys = [] for coords in feature['geometry']['coordinates']: poly = Polygon(coords[0]) polys.append(poly) polygons.append((feature['properties'], prep(MultiPolygon(polys)))) return polygons
def load_polygons(cls, filename): f = open(filename) polygons = {} cls.i = 0 for line in f: feature = json.loads(line.rstrip()) polygons[cls.i] = prep(cls.polygon_from_geojson(feature)) cls.i += 1 return polygons
def __init__(self, field, filter_value, negation): self.field = field self.filter_value = filter_value self.prepared = prep(self.filter_value) self.negation = negation if negation: self.evaluate = lambda x: not(self._evaluate(x)) else: self.evaluate = self._evaluate
def load_polygons(cls, filename): f = open(filename) polygons = [] for line in f: feature = json.loads(line.rstrip()) poly_type = feature['geometry']['type'] if poly_type == 'Polygon': poly = Polygon(feature['geometry']['coordinates'][0]) polygons.append((feature['properties'], prep(poly))) elif poly_type == 'MultiPolygon': polys = [] for coords in feature['geometry']['coordinates']: poly = Polygon(coords[0]) polys.append(poly) polygons.append((feature['properties'], prep(MultiPolygon(polys)))) return polygons
def intersect(self, **kwargs): """ Intersect a Line or Point Collection and the Shoreline Returns the point of intersection along the coastline Should also return a linestring buffer around the interseciton point so we can calculate the direction to bounce a particle. """ ls = None if "linestring" in kwargs: ls = kwargs.pop('linestring') spoint = Point(ls.coords[0]) epoint = Point(ls.coords[-1]) elif "start_point" and "end_point" in kwargs: spoint = kwargs.pop('start_point') epoint = kwargs.pop('end_point') ls = LineString(list(spoint.coords) + list(epoint.coords)) else: raise TypeError( "must provide a LineString geometry object or (2) Point geometry objects" ) inter = False # If the current point lies outside of our current shapefile index, # re-query the shapefile in a buffer around this point if self._spatial_query_object and not ls.within(self._spatial_query_object): self.index(point=spoint) for element in self._geoms: prepped_element = prep(element) # Test if starting on land if prepped_element.contains(spoint): raise Exception('Starting point on land') inter = ls.intersection(element) if inter: # Return the first point in the linestring, and the linestring that it hit if isinstance(inter, MultiLineString): inter = inter.geoms[0] inter = Point(inter.coords[0]) smaller_int = inter.buffer(self._spatialbuffer) shorelines = element.exterior.intersection(smaller_int) if isinstance(shorelines, LineString): shorelines = [shorelines] else: shorelines = list(shorelines) for shore_segment in shorelines: # Once we find the linestring in the Polygon that was # intersected, break out and return if ls.touches(shore_segment): break return {'point': Point(inter.x, inter.y, 0), 'feature': shore_segment or None} return None
def get_polygon_cached(self, i): poly = self.polygons.get(i, None) if poly is None: data = json.loads(self.polygons_db.Get(self.polygon_key(i))) poly = prep(self.polygon_from_geojson(data)) self.polygons[i] = poly self.cache_misses += 1 else: self.cache_hits += 1 return poly
def tiles_from_geom(self, geometry, zoom): """ Return all tiles intersecting with input geometry. - geometry: shapely geometry - zoom: zoom level """ try: assert geometry.is_valid except AssertionError: try: clean = geometry.buffer(0.0) assert clean.is_valid assert clean.area > 0 geometry = clean except AssertionError: raise IOError( str( "invalid geometry could not be fixed: '%s'" % explain_validity(geometry) ) ) if geometry.almost_equals(geometry.envelope, ROUND): for tile in self.tiles_from_bbox(geometry, zoom): yield tile elif geometry.geom_type == "Point": lon, lat = list(geometry.coords)[0] tilelon = self.left tilelat = self.top tile_x_size = self.tile_x_size(zoom) tile_y_size = self.tile_y_size(zoom) col = -1 row = -1 while tilelon < lon: tilelon += tile_x_size col += 1 while tilelat > lat: tilelat -= tile_y_size row += 1 yield self.tile(zoom, row, col) elif geometry.geom_type in ( "LineString", "MultiLineString", "Polygon", "MultiPolygon", "MultiPoint", "GeometryCollection" ): prepared_geometry = prep( clip_geometry_to_srs_bounds(geometry, self) ) for tile in self.tiles_from_bbox(geometry, zoom): if prepared_geometry.intersects(tile.bbox()): yield tile elif geometry.is_empty: pass else: raise ValueError("ERROR: no valid geometry: %s" % geometry.type)
def country_finder(geo_coord, bbox_hits, polygon_df, m): from shapely.geometry import Point from shapely.prepared import prep inpoint = Point(m(geo_coord.lon,geo_coord.lat)) region=polygon_df[polygon_df['region_name'].isin(bbox_hits)] pgon_list = [idx for idx, pgon in enumerate([prep(pgon) for pgon in region['poly']])\ if pgon.contains(inpoint)] return region.iloc[pgon_list]
def revmatches(): for row,shp in izip(subdict["refdata"].reader.iterRecords(), subdict["refdata"].reader.iterShapes()): #if dict(zip(self.fields, row))["SOV0NAME"] != "Russia": continue #print "...",row[1] #row[4],row[14] print str(row)[:100] prepped = prep(asShape(shp)) # prepares geometry for many intersection tests (maybe only useful if is polygon and other is points, but not sure) bbox = [shp.points[0][0],shp.points[0][1],shp.points[0][0],shp.points[0][1]] if shp.shapeType == pyshp.POINT else shp.bbox ilist = self.spindex.intersection(bbox) for i in ilist: othershp = self.reader.shape(i) if prepped.intersects(asShape(othershp)): yield row,i
def _construct_polygon_map(self, polygon_generator, closest=False): """Turn a (tz, polygon) generator, into our internal mapping.""" self.timezoneNamesToPolygons = collections.defaultdict(list) self.unprepTimezoneNamesToPolygons = collections.defaultdict(list) for (tzname, raw_poly) in polygon_generator: poly = Polygon(tzwhere._raw_poly_to_poly(raw_poly)) self.timezoneNamesToPolygons[tzname].append( prep(poly)) if closest: self.unprepTimezoneNamesToPolygons[tzname].append( poly)
def _construct_shapely_map(self, polygon_generator, forceTZ): """Turn a (tz, polygon) generator, into our internal shapely mapping.""" self.timezoneNamesToPolygons = collections.defaultdict(list) self.unprepTimezoneNamesToPolygons = collections.defaultdict(list) for (tzname, poly) in polygon_generator: poly = Polygon(poly) self.timezoneNamesToPolygons[tzname].append( prep(poly)) if forceTZ: self.unprepTimezoneNamesToPolygons[tzname].append( poly)
def SummarizeByCommunity(MapData, NYCPoints): """Create some additional columns, containing the number of points in each NYC community, and the density per square meter and square kilometer community. Normalizing allows us to compare communities.""" MapData['count'] = MapData['poly'].map(lambda x: int(len(filter(prep(x).contains, NYCPoints)))) MapData['density_m'] = MapData['count'] / MapData['area_m'] MapData['density_km'] = MapData['count'] / MapData['area_km'] # it's easier to work with NaN values when classifying, so replace zeros with NaNs when appropriate. MapData.replace(to_replace={'density_m': {0: np.nan}, 'density_km': {0: np.nan}}, inplace=True) return MapData
def __init__(self): # filterfn = '/home/behry/workspace/eew/reports/data/california_filter_revised.txt' filterfn = '/home/behry/workspace/eew/reports/data/SoCalfilter.txt' lon, lat = np.loadtxt(filterfn, unpack=True) self.p = pyproj.Proj(proj="aea", lat_0='0.00', lon_0='-120', lat_1='34.00', lat_2='40.50', ellps='GRS80', x_0=0.000, y_0=-4000000.000, units='m', datum='NAD83') px, py = self.p(lon, lat) self.points = np.vstack((px, py)).T self.polygon = Polygon(zip(px, py)) self.prepared_polygon = prep(self.polygon) self.lat1 = 31 self.lat2 = 43 self.lon1 = -126 self.lon2 = -114
def poly_count(self, poly_list, points): """ counts how many agents in each polygon in: 1D vector of points from agents2state()/get_state(sensor=location), out: counts of agents in each polygon in poly_list """ counts = [] points = np.array([points[::2], points[1::2]]).T points = MultiPoint(points) for poly in self.poly_list: poly = prep(poly) counts.append(int(len(list(filter(poly.contains, points))))) return counts
def is_occupied(self, poly, auto_register=False): # prepare for multiple checking prepared = prep(poly) # filter hits hits = list(filter(prepared.intersects, self.occupied)) # if we had no hits the area is not occupied if len(hits) == 0: if auto_register: # register box as occupied self.occupied.append(poly.buffer(20, resolution=1)) return False # space is occupied return True
def clip(self, polygon): ## perform an intersects operation first vd = self.intersects(polygon) ## prepare the geometry for intersection prep_igeom = prepared.prep(polygon) ## loop for the intersection geom = vd._geom for ii, jj in iter_array(geom): ref = geom[ii, jj] if not prep_igeom.contains(ref): new_geom = polygon.intersection(ref) geom[ii, jj] = new_geom ret = self.__class__(grid=vd.grid, geom=geom, uid=vd.uid) return (ret)
def get_country(lat, lon, geo_data): """ Determine which country a point lies in """ countries = {} for feature in geo_data["features"]: geom = feature["geometry"] country = feature["properties"]["ADMIN"] countries[country] = prep(shape(geom)) point = Point(lon, lat) for country, geom in countries.items(): if geom.contains(point): return country return "unknown"
def tzNameAt(self, latitude, longitude, forceTZ=False): ''' Let's you lookup for a given latitude and longitude the appropriate timezone. @latitude: latitude @longitude: longitude @forceTZ: If forceTZ is true and you can't find a valid timezone return the closest timezone you can find instead. Only works if the point has the same integer value for its degree than the timezeone ''' if forceTZ: assert self.forceTZ, 'You need to initialize tzwhere with forceTZ' latTzOptions = self.timezoneLatitudeShortcuts[str( (math.floor(latitude / self.SHORTCUT_DEGREES_LATITUDE) * self.SHORTCUT_DEGREES_LATITUDE))] latSet = set(latTzOptions.keys()) lngTzOptions = self.timezoneLongitudeShortcuts[str( (math.floor(longitude / self.SHORTCUT_DEGREES_LONGITUDE) * self.SHORTCUT_DEGREES_LONGITUDE))] lngSet = set(lngTzOptions.keys()) possibleTimezones = lngSet.intersection(latSet) queryPoint = geometry.Point(longitude, latitude) if possibleTimezones: for tzname in possibleTimezones: if isinstance(self.timezoneNamesToPolygons[tzname], COLLECTION_TYPE): self.timezoneNamesToPolygons[tzname] = list( map( lambda p: prepared.prep( geometry.Polygon(p[0], p[1])), self.timezoneNamesToPolygons[tzname])) polyIndices = set(latTzOptions[tzname]).intersection( set(lngTzOptions[tzname])) for polyIndex in polyIndices: poly = self.timezoneNamesToPolygons[tzname][polyIndex] if poly.contains_properly(queryPoint): return tzname if forceTZ: return self.__forceTZ__(possibleTimezones, latTzOptions, lngTzOptions, queryPoint)
def _process_osm_trees_gardens( city_blocks: Set[CityBlock], parks: List[shg.Polygon], fg_elev: utilities.FGElev) -> Dict[e.TreeType, List[Tree]]: suburban_trees = list() town_trees = list() urban_trees = list() for city_block in city_blocks: tree_type = e.map_tree_type_from_settlement_type_garden( city_block.settlement_type) if city_block.type_ is e.BuildingZoneType.special_processing: continue prep_geom = prep(city_block.geometry) my_random_points = _generate_random_tree_points_in_polygon( city_block.geometry, prep_geom, parameters.C2P_TREES_DIST_BETWEEN_TREES_GARDEN, parameters.C2P_TREES_SKIP_RATE_TREES_GARDEN) for point in my_random_points: exclude = False for park in parks: # need to check for parks if point.within(park): exclude = True break if exclude: continue if not _test_point_in_building(point, {city_block}, 2.0): elev = fg_elev.probe_elev((point.x, point.y), False) my_tree = Tree( op.get_next_pseudo_osm_id(op.OSMFeatureType.generic_node), point.x, point.y, elev) if tree_type is e.TreeType.suburban: suburban_trees.append(my_tree) elif tree_type is e.TreeType.town: town_trees.append(my_tree) else: urban_trees.append(my_tree) garden_trees = dict() if suburban_trees: garden_trees[e.TreeType.suburban] = suburban_trees if town_trees: garden_trees[e.TreeType.town] = town_trees if urban_trees: garden_trees[e.TreeType.urban] = urban_trees logging.info('Number of trees added in gardens: %i', len(suburban_trees) + len(town_trees) + len(urban_trees)) return garden_trees
def maxMinDistance(poly, dd): allLines = [] allLines.append(poly.exterior) postLayer = dd.layers[DesignDict.POST] portLayer = dd.layers[DesignDict.PORTS] possiblePosts = postLayer.index.intersection(poly.bounds) possiblePorts = portLayer.index.intersection(poly.bounds) candidatePosts = [] prepPoly = prep(poly) construct = Polygon(poly) for objind in possiblePosts: obj = dd.objects[objind] if prepPoly.contains_properly(obj.shape): candidatePosts.append(obj.shape) for objind in possiblePorts: obj = dd.objects[objind] if prepPoly.contains_properly(obj.shape): candidatePosts.append(obj.shape) logger.debug(str(len(candidatePosts)) + " candidate support posts") for post in candidatePosts: ## subtract the post from the polygon interior construct = construct.difference(post) for interior in construct.interiors: candidatePosts.append(Polygon(interior)) allLines.append(interior) allLines = MultiLineString(allLines) currentPoint = construct.centroid if construct.contains(currentPoint): currentDist = allLines.distance(currentPoint) else: currentDist = None triangles, pconstruct = prepPolygon(construct) points = nRandomTriangleSamples(pconstruct, triangles) for p in points: dist = allLines.distance(p) if dist > currentDist: currentPoint = p currentDist = dist return (currentPoint, currentDist)
def fndshapeindices(shapevertices=None): '''Define the gridpoints that lie within the 'shape' or on its boundary. These points will be included in the sum of emissivities. Kwargs: shapevertices (list) : list of vertex coordinates for trial shape ("shape"). Returns: pCoords (list): coordinates of grid points within or on boundary of shape. ''' polygon = Polygon(shapevertices) prepared_polygon = prep(polygon) bounds = polygon.bounds ll = bounds[:2] ur = bounds[2:] xs = [] ys = [] if (ur[0] - ll[0] < 1) or (ur[1] - ll[1] < 1): return None xx = range(int(np.ceil(ll[0])), int(np.floor(ur[0])) + 1, 1) yy = range(int(np.ceil(ll[1])), int(np.floor(ur[1])) + 1, 1) listpoints = list(itertools.product(xx, yy)) points = MultiPoint(listpoints) try: xvals, yvals = zip(*listpoints) except: print('ll', ll, 'ur', ur) print('vertices', shapevertices) print('xx', xx, 'yy', yy) for ii in range(len(xvals)): if prepared_polygon.intersects(points[ii]): xs.append(xvals[ii]) ys.append(yvals[ii]) ##plot to check #x,y = polygon.exterior.xy #plt.plot(x,y) #plt.show() pCoords = [xs], [ys] return pCoords
def _split_polygon_with_line(poly, splitter): """Split a Polygon with a LineString""" assert(isinstance(poly, Polygon)) assert(isinstance(splitter, LineString)) union = poly.boundary.union(splitter) # greatly improves split performance for big geometries with many # holes (the following contains checks) with minimal overhead # for common cases poly = prep(poly) # some polygonized geometries may be holes, we do not want them # that's why we test if the original polygon (poly) contains # an inner point of polygonized geometry (pg) return [pg for pg in polygonize(union) if poly.contains(pg.representative_point())]
def get_watershed(dataframe, shapefile=None, location_id=None, lat=None, lon=None, singluar_removal=False): ''' add a column with watershed information Args: dataframe: pandas dataframe shapefile (string, dir to an shp file): shape information of watersheds location_id (string): the name of column of location names/ids lat (string): the name of the column of latitude information lon (string): the name of the column of longitude information singular_removal: boolean if true the isolated locations wille be removed. ''' shapefile = WATERSHED_PATH if shapefile is None else shapefile location_id = 'SITENUMBER' if location_id is None else location_id lat = 'LATITUDE' if lat is None else lat lon = 'LONGITUDE' if lon is None else lon lats_and_lons = dataframe.groupby(location_id).first()[[lat, lon ]].reset_index() shapes = [] names = [] for i in fiona.open(shapefile): names.append(i['properties']['NAME']) shapes.append(prep(shape(i['geometry']))) dict_ = {} for idx, row in lats_and_lons.iterrows(): sitenumber, lat, lon = row.values point = Point([lon, lat]) for watershed_name, shape_ in zip(names, shapes): if shape_.contains(point): dict_[sitenumber] = watershed_name break dataframe['WATERSHED'] = dataframe[location_id].map(dict_) if singluar_removal: number_of_obs = dataframe.groupby(['WATERSHED']).count()[key] singular_huc_areas = number_of_obs[number_of_obs <= 1].index dataframe = dataframe[~dataframe.WATERSHED.isin(singular_huc_areas)] return dataframe
def get_neighbors_within_distance( self, agent, distance, center=False, relation="intersects" ): """Return a list of agents within `distance` of `agent`. Distance is measured as a buffer around the agent's shape, set center=True to calculate distance from center. """ if center: shape = agent.shape.center().buffer(distance) else: shape = agent.shape.buffer(distance) possible_neighbors = self._get_rtree_intersections(shape) prepared_shape = prep(shape) for other_agent in possible_neighbors: if getattr(prepared_shape, relation)(other_agent.shape): yield other_agent
def _get_ocean_shapefile(): """ Load the ocean basins shapefile. """ global _OCEAN_SHAPE if _OCEAN_SHAPE is None: try: ocean_shp_fn = pkg_resources.resource_filename( "marc_analysis", "data/ne_110m_ocean.shp") _OCEAN_SHAPE = geopandas.read_file(ocean_shp_fn) _OCEAN_SHAPE = MultiPolygon(_OCEAN_SHAPE.geometry.values.tolist()) _OCEAN_SHAPE = prep(_OCEAN_SHAPE) except OSError: warnings.warn("Unable to locate oceans shapefile; ocean" " point mask is not available") return _OCEAN_SHAPE
def makeMouseBites(self, cuts, diameter, spacing, offset=fromMm(0.25)): """ Take a list of cuts and perform mouse bites. """ bloatedSubstrate = prep(self.boardSubstrate.substrates.buffer(fromMm(0.01))) for cut in cuts: cut = cut.simplify(fromMm(0.001)) # Remove self-intersecting geometry offsetCut = cut.parallel_offset(offset, "left") length = offsetCut.length count = int(length / spacing) + 1 for i in range(count): if count == 1: hole = offsetCut.interpolate(0.5, normalized=True) else: hole = offsetCut.interpolate( i * length / (count - 1) ) if bloatedSubstrate.intersects(hole.buffer(0.8 * diameter / 2)): self.addNPTHole(wxPoint(hole.x, hole.y), diameter)
def create_grid(site_shape: BaseGeometry, center: Point, grid_angle: float, intrarow_spacing: float, interrow_spacing: float, row_phase_offset: float, max_sites: int = None, ) -> [Point]: """ Get a list of coordinates placed along a grid inside a site boundary :param site_shape: Polygon :param center: where to center the grid :param grid_angle: in degrees where 0 is north, increasing clockwise :param intrarow_spacing: distance between turbines along same row :param interrow_spacing: distance between rows :param row_phase_offset: offset of turbines along row from one row to the next :param max_sites: max number of turbines :return: list of coordinates """ grid_lines: [LineString] = make_grid_lines( site_shape, center, grid_angle, interrow_spacing ) phase_offset: float = row_phase_offset * intrarow_spacing prepared_site = prep(site_shape) grid_positions: [Point] = [] for row_number, grid_line in enumerate(grid_lines): length = grid_line.length # generate points along that line with the right phase offset x: float = (phase_offset * row_number) % intrarow_spacing while x <= length: position = grid_line.interpolate(x) if prepared_site.contains(position): if max_sites and len(grid_positions) >= max_sites: break grid_positions.append(position) x += intrarow_spacing if max_sites and len(grid_positions) >= max_sites: break return grid_positions
def remove_duplicates(layer): indices = [] for i in range(0, len(layer)): obj_prep = prep(layer[i]) for j in range(i + 1, len(layer)): obj_comp = layer[j] if j in indices: continue if obj_prep.contains(obj_comp): indices.append(j) for i in sorted(indices, reverse=True): del layer[i] return len(indices)
def clip(self,igeom): ## logic for convenience. just return the provided collection if a NoneType ## is passed for the 'igeom' arugment if igeom is not None: ## take advange of shapely speedups prep_igeom = prepared.prep(igeom) ## the weight array weights = np.zeros(self.spatial.shape,dtype=float) weights = np.ma.array(weights,mask=self.spatial._value_mask) ## do the spatial operation for idx,geom in iter_array(self.spatial.value,return_value=True): if not prep_igeom.contains(geom): # if keep(prep_igeom,igeom,geom): new_geom = igeom.intersection(geom) weights[idx] = new_geom.area self.spatial._value[idx] = new_geom ## set maximum weight to one self.spatial.weights = weights/np.ma.max(weights)
def is_land(x, y, res="110m"): if 'prep' not in globals(): raise ImportError("cartopy is needed to design ocean-only source.") assert (res in ["10m", "50m", "110m"]), "Resolution must be 10m, 50m, 110 m" land_shp_fname = shpreader.natural_earth(resolution=res, category='physical', name='land') land_geom = unary_union(list( shpreader.Reader(land_shp_fname).geometries())) land = prep(land_geom) is_land = np.zeros(len(x)) for i in range(len(x)): is_land[i] = land.contains(sgeom.Point(x[i], y[i])) return is_land
def find_pages_for_polygon(self, polygon): """Find pages within polygon using repeated Geosearch The Geosearch API has no polygon support; only point. To get around this, I first find a collection of circles that together tile the polygon, then for each circle I call the geosearch API. """ # When set to radius=10000, I got an error from the wikipedia API points, radii = geom.find_circles_that_tile_polygon( polygon, radius=10000) titles = set() for point, radius in zip(points, radii): radius = math.ceil(radius) res = self.find_page_titles_around_point(point=point, radius=radius) titles.update(res) # Get wikipedia page metadata for each of the titles I've found above # Occasionally you get a disambiguation error, because the search is by # title? # Note, since I've already found titles that I know exist, I should set # auto_suggest=False pages = [] for title in titles: try: pages.append(wikipedia.page(title, auto_suggest=False)) except wikipedia.WikipediaException: pass # Make sure that all returned articles are within the original polygon # [::-1] because returned as lat, lon. Point requires lon, lat # "To test one polygon containment against a large batch of points, one # should first use the prepared.prep() function" prepared_polygon = prep(polygon) new_pages = [] for page in pages: try: if prepared_polygon.contains(Point(page.coordinates[::-1])): new_pages.append(page) # Occasionally the page won't have a coordinates attribute except KeyError: pass return new_pages
def add_boundary_perimeters(graph, geometries): """Add shared perimeter between nodes and the total geometry boundary. :param graph: NetworkX graph :param df: Geodataframe containing geometry information. :return: The updated graph. """ prepared_boundary = prep(unary_union(geometries).boundary) boundary_nodes = geometries.boundary.apply(prepared_boundary.intersects) for node in graph: graph.nodes[node]["boundary_node"] = bool(boundary_nodes[node]) if boundary_nodes[node]: total_perimeter = geometries[node].boundary.length shared_perimeter = sum(neighbor_data["shared_perim"] for neighbor_data in graph[node].values()) boundary_perimeter = total_perimeter - shared_perimeter graph.nodes[node]["boundary_perim"] = boundary_perimeter
def is_in_grid(self, shp): """Check if arbitrary polygon is within grid bounding box. Args: shp (shape): Returns: Bool whether shp is in grid box. Depends on self.grid_box (shapely prep type) being defined in environment. """ if not hasattr(shp, 'geom_type'): raise Exception("CoreMSR [is_in_grid] : invalid shp given") if not isinstance(self.grid_box, type(prep(Point(0, 0)))): raise Exception("CoreMSR [is_in_grid] : invalid prep_adm0 " "found") return self.grid_box.contains(shp)
def edge_intersects_other_restricted_areas( self, line: LineString, restricted_area_poly: Polygon) -> bool: """ check if a linestring intersects with other as restricted marked polygons which are different from the given restricted_Area_poly :param line: the linestring which shall be checked :param restricted_area_poly: the polygon which shall be excluded :return: true if the linstring don't intesect other restricted polygon and touches the given polygon """ other_restricted_areas = self._get_other_restricted_area_polys( restricted_area_poly) for other_restricted_area in other_restricted_areas: other_areas = self._get_other_restricted_area_polys( other_restricted_area) other_areas.remove(restricted_area_poly) if prep(other_restricted_area).touches( line) and not self._is_restricted_line(line, other_areas): return False return self._is_restricted_line(line, other_restricted_areas)
def revmatches(): for row, shp in izip( subdict["refdata"].reader.iterRecords(), subdict["refdata"].reader.iterShapes()): #if dict(zip(self.fields, row))["SOV0NAME"] != "Russia": continue #print "...",row[1] #row[4],row[14] print str(row)[:100] prepped = prep( asShape(shp) ) # prepares geometry for many intersection tests (maybe only useful if is polygon and other is points, but not sure) bbox = [ shp.points[0][0], shp.points[0][1], shp.points[0][0], shp.points[0][1] ] if shp.shapeType == pyshp.POINT else shp.bbox ilist = self.spindex.intersection(bbox) for i in ilist: othershp = self.reader.shape(i) if prepped.intersects(asShape(othershp)): yield row, i
def filter(self, intersects): """Filter results that intersect a given GeoFeature or Vector. """ try: crs = self.crs vector = intersects.geometry if isinstance(intersects, GeoFeature) else intersects prepared_shape = prep(vector.get_shape(crs)) hits = [] for feature in self: target_shape = feature.geometry.get_shape(crs) if prepared_shape.overlaps(target_shape) or prepared_shape.intersects(target_shape): hits.append(feature) except IndexError: hits = [] return FeatureCollection(hits)
def prepare_earth_geometry(geometry_resolution: str = "50m"): """ Preparations necessary for determining whether a point is over land or water. This code may need to download a ZIP containing Earth geometry data the first time it runs. Code borrowed from https://stackoverflow.com/a/48062502 :param geometry_resolution: The resolution of the NaturalEarth shapereader to use. Valid values are '10m', '50m' or '110m'. Default '50m'. :return: The PreparedGeometry object that can be used for point-land checking. :raises ValueError: If geometry_resolution is not '10m', '50m', or '110m'. """ if geometry_resolution not in ["10m", "50m", "110m"]: raise ValueError("Argument 'geometry_resolution' must be either '10m', '50m', or '110m'.") print("-- Preparing Earth geometry...") land_shp_fname = shpreader.natural_earth(resolution=geometry_resolution, category='physical', name='land') land_geom = unary_union(list(shpreader.Reader(land_shp_fname).geometries())) land = prep(land_geom) print("-- Earth geometry prepared.") return land
def surround_with_holes(geometry, hole_spacing, hole_radius, padding, max_distance): """ Surrounds the given geometry with holes, which are arranged in a square lattice around the structure. This can be used for generating vortex traps like presented in https://doi.org/10.1103/PhysRevApplied.11.064053 :param geometry: The geometry around which the holes are generated :param hole_spacing: Spacing between the holes :param hole_radius: Radius of the holes :param padding: Padding around the geometry :param max_distance: Maximum distance of a hole from the geometry :return: Shapely object, which describes the holes """ geometry = geometric_union(geometry if isinstance(geometry, (tuple, list)) else (geometry,)) buffer_around_waveguide = geometry.buffer(max_distance) area_for_holes = prep(buffer_around_waveguide.difference(geometry.buffer(hole_radius + padding))) area = buffer_around_waveguide.bounds points = (Point(x, y) for x in np.arange(area[0], area[2], hole_spacing) for y in np.arange(area[1], area[3], hole_spacing)) return MultiPolygon([point.buffer(hole_radius) for point in points if area_for_holes.contains(point)])
def prepare(feat): """Prepare geojson feature for further processing in `geopip._shapely.p_in_polygon()` Parameters: feat: Dict[str, Any] Geojson feature (only Polygon and MultiPolygon will be processed). Returns: List[Dict[str, Any]] Prepared shapes for `geopip._shapely.p_in_polygon()` """ if feat['geometry']['type'] in ('Polygon', 'MultiPolygon'): shp = shape(feat['geometry']) return [{ 'shape': prep(shp), 'properties': feat['properties'], 'bounds': shp.bounds, }] else: return []
def minDistInLayer(rule, dd, layerID, thresh): layer = dd.layers[layerID] objs = layer.objs for id1, o1 in objs.items(): bbox = o1.shape.buffer(thresh).bounds candidates = layer.index.intersection(bbox) prepared = None for cind in candidates: o2 = objs[cind] if o1.id < o2.id: if prepared == None: prepared = prep(o1.shape) contained = prepared.contains(o2.shape) or \ o2.shape.contains(o1.shape) if not contained and checkThresh(o1, o2, thresh): (p1, p2) = NearLineSegment.featureToFeature(o1, o2) wit = Witness(Witness.LINE_SEGMENT, (p1, p2)) dd.violations.add(Violation.ofRule(rule, [o1, o2], [wit]))
def geometryvariable_get_mask_from_intersects( gvar, geometry, use_spatial_index=env.USE_SPATIAL_INDEX, keep_touches=False, original_mask=None): # Create the fill array and reference the mask. This is the output geometry value array. if original_mask is None: original_mask = gvar.get_mask(create=True) fill = original_mask.copy() fill.fill(True) ref_fill_mask = fill.reshape(-1) # Track global indices because spatial operations only occur on non-masked values. global_index = np.arange(original_mask.size) global_index = np.ma.array(global_index, mask=original_mask).compressed() # Select the geometry targets. If an original mask is provided, use this. It may be modified to limit the search # area for intersects operations. Useful for speeding up grid subsetting operations. geometry_target = np.ma.array(gvar.get_value(), mask=original_mask).compressed() if use_spatial_index: si = gvar.get_spatial_index(target=geometry_target) # Return the indices of the geometries intersecting the target geometry, and update the mask accordingly. for idx in si.iter_intersects(geometry, geometry_target, keep_touches=keep_touches): ref_fill_mask[global_index[idx]] = False else: # Prepare the polygon for faster spatial operations. prepared = prep(geometry) # We are not keeping touches at this point. Remember the mask is an inverse. for idx, geom in iter_array(geometry_target, return_value=True): bool_value = False if prepared.intersects(geom): if not keep_touches and geometry.touches(geom): bool_value = True else: bool_value = True ref_fill_mask[global_index[idx]] = bool_value return fill
def Filter(options): ''' Rounding http://gis.stackexchange.com/questions/8650/how-to-measure-the-accuracy-of-latitude-and-longitude ''' startTime = time.time() inputData = np.loadtxt(options.inputFileName, delimiter=',', usecols=(0, 1, 2)) outputData = open(options.outputFileName, 'w') lon = inputData[:, 0] lat = inputData[:, 1] height = inputData[:, 2] if options.polyFilter != False: poly = np.loadtxt(options.polyFilter, delimiter=',', usecols=(1, 2)) poly = Polygon(poly) poly = prep(poly) minHeight = float(options.minHeight) maxHeight = float(options.maxHeight) numPoints = inputData.shape[0] for i in range(0, numPoints): pointLon, pointLat, pointHeight = lon[i], lat[i], height[i] if minHeight < pointHeight < maxHeight: if options.polyFilter != False: point = Point(pointLon, pointLat) if poly.contains(point): outputData.write( str(round(pointLon, 8)) + ',' + str(round(pointLat, 8)) + ',' + str(round(pointHeight, 4)) + '\n') else: outputData.write( str(round(pointLon, 8)) + ',' + str(round(pointLat, 8)) + ',' + str(round(pointHeight, 4)) + '\n') outputData.close() #Use np.savetxt('test.out', x, delimiter=',') print(int(time.time() - startTime), ' seconds runtime')