def GenerateMask(tileXPos,tileYPos,tileImageFilePath,geoJSONPath,outputFileName): with open(geoJSONPath) as f: geo_json_features = json.load(f)["features"] tile=geometry.GeometryCollection([geometry.shape(feature["geometry"]).buffer(0) for feature in geo_json_features]) img = Image.open(tileImageFilePath) pixels=img.load() result=geometry.GeometryCollection() for k in features: if geometry.shape(k["geometry"]).intersects(tile): result=result.union(geometry.shape(k["geometry"]).intersection(tile)) if tile. intersects(result): for i in range(0,img.size[0],RAWNESS): for j in range(0,img.size[1],RAWNESS): lat_long=GetLatLongForCoords(GRID_WIDTH*(tileXPos)+i,GRID_HEIGHT*(tileYPos)+j) if result.intersects(geometry.Point(lat_long)): pixels[i,j]=(0,0,0) img.save(outputFileName)
def serialize_as_svg(topo_object, separate=False, include_junctions=False): from IPython.display import SVG, display from shapely import geometry keys = topo_object.keys() if "arcs" in keys: arcs = topo_object["arcs"] if arcs: # dequantize if quantization is applied if "transform" in keys: np_arcs = np_array_from_arcs(arcs) transform = topo_object["transform"] scale = transform["scale"] translate = transform["translate"] np_arcs = dequantize(np_arcs, scale, translate) l_arcs = [] for ls in np_arcs: l_arcs.append(ls[~np.isnan(ls)[:, 0]].tolist()) arcs = l_arcs arcs = [geometry.LineString(arc) for arc in arcs] else: arcs = topo_object["linestrings"] if separate and not include_junctions: for ix, line in enumerate(arcs): svg = line._repr_svg_() print(ix, line.wkt) display(SVG(svg)) elif separate and include_junctions: pts = topo_object["junctions"] for ix, line in enumerate(arcs): svg = geometry.GeometryCollection( [line, geometry.MultiPoint(pts)] )._repr_svg_() print(ix, line.wkt) display(SVG(svg)) elif not separate and include_junctions: pts = topo_object["junctions"] display( geometry.GeometryCollection( [geometry.MultiLineString(arcs), geometry.MultiPoint(pts)] ) ) else: display(geometry.MultiLineString(arcs))
def _calculate_geometry(self, exterior): limited_box = shpl_geom.box(self._limits[0], exterior.bounds[1] * 1.1, self._limits[1], exterior.bounds[3] * 1.1) intersection = limited_box.intersection(exterior) side = _get_inside_direction(exterior) tmp_geometries = [] tmp_interior = shpl_geom.Polygon(exterior) for ageo in intersection.geoms: tmp_geometry = _create_offset_box(ageo, self.thickness, side, symmetric=False) tmp_interior -= tmp_geometry tmp_geometries.append(tmp_geometry) geometry = shpl_geom.GeometryCollection(tmp_geometries) interior = shpl_geom.LinearRing(tmp_interior.exterior) return _refine_interior(interior), geometry
def load_ocean_poly(): with open("OceanGeoJSON_lowres.geojson") as f: ocean_features = json.load(f)["features"] geom = sh.GeometryCollection([ sh.shape(feature["geometry"]).buffer(0) for feature in ocean_features ])[0] return geom
def ocean_geojson(): with open(path_config.LOCAL_DIR + "aux_files/OceanGeoJSON_lowres.geojson") as f: ocean_features = json.load(f)["features"] ocean = sh.GeometryCollection( [sh.shape(feature["geometry"]).buffer(0) for feature in ocean_features] )[0] return ocean
def collect( geometry_list: List[sh_geom.base.BaseGeometry]) -> Optional[sh_geom.base.BaseGeometry]: """ Collect a list of geometries to one geometry. Examples: * if the list contains only Polygon's, returns a MultiPolygon. * if the list contains different types, returns a GeometryCollection. Args: geometry_list (List[sh_geom.base.BaseGeometry]): [description] Raises: Exception: raises an exception if one of the input geometries is of an unknown type. Returns: sh_geom.base.BaseGeometry: the result """ # First remove all None geometries in the input list geometry_list = [geometry for geometry in geometry_list if geometry is not None and geometry.is_empty is False] # If the list is empty or contains only 1 element, it is easy... if geometry_list is None or len(geometry_list) == 0: return None elif len(geometry_list) == 1: return geometry_list[0] # Loop over all elements in the list, and determine the appropriate geometry type to create result_collection_type = GeometryType(geometry_list[0].geom_type).to_multitype for geom in geometry_list: # If it is the same as the collection_geom_type, continue checking if GeometryType(geom.geom_type).to_multitype == result_collection_type: continue else: # If multiple types in the list, result becomes a geometrycollection result_collection_type = GeometryType.GEOMETRYCOLLECTION break # Now we can create the collection # Explode the multi-geometries to single ones singular_geometry_list = [] for geom in geometry_list: if isinstance(geom, sh_geom.base.BaseMultipartGeometry): singular_geometry_list.extend(geom.geoms) else: singular_geometry_list.append(geom) if result_collection_type == GeometryType.MULTIPOINT: return sh_geom.MultiPoint(singular_geometry_list) elif result_collection_type == GeometryType.MULTILINESTRING: return sh_geom.MultiLineString(singular_geometry_list) elif result_collection_type == GeometryType.MULTIPOLYGON: return sh_geom.MultiPolygon(singular_geometry_list) elif result_collection_type == GeometryType.GEOMETRYCOLLECTION: return sh_geom.GeometryCollection(geometry_list) else: raise Exception(f"Unsupported geometry type: {result_collection_type}")
def geom_flatten(obj, geoms=None): geoms, root = ([], True) if geoms is None else (geoms, False) if isinstance(obj, geom.GeometryCollection): for i in obj: geom_flatten(i, geoms) elif type(obj) in {geom.MultiPolygon, geom.MultiPoint, geom.MultiLineString}: geoms.extend(list(obj)) else: geoms.append(obj) if root: return geom.GeometryCollection(geoms)
def test_join_super_function_extract(): data = geometry.GeometryCollection([ geometry.Polygon([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]), geometry.Polygon([[1, 0], [2, 0], [2, 1], [1, 1], [1, 0]]), ]) topo = Join(data).to_dict() assert len(list(topo.keys())) == 9
def test_super_function_extract(self): data = geometry.GeometryCollection([ geometry.Polygon([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]), geometry.Polygon([[1, 0], [2, 0], [2, 1], [1, 1], [1, 0]]) ]) topo = Join(data).to_dict() self.assertEqual(list(topo.keys()), ["type", "linestrings", "bookkeeping_geoms", "objects", "options","bbox", "junctions"])
def test_dedup_super_function(): data = geometry.GeometryCollection([ geometry.Polygon([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]), geometry.Polygon([[1, 0], [2, 0], [2, 1], [1, 1], [1, 0]]), ]) topo = Dedup(data).to_dict() assert len(list(topo.keys())) == 12
def _repr_svg_(self): shply_collection = shpl_geom.GeometryCollection( [self._geometry, *self._featuregeometries]) svg = shply_collection._repr_svg_() return rework_svg(svg, 1000, 250)
def test_shapely_geometrycollection(self): data = geometry.GeometryCollection([ geometry.Polygon([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]), geometry.Polygon([[1, 0], [2, 0], [2, 1], [1, 1], [1, 0]]), ]) topo = Extract(data).to_dict() self.assertEqual(len(topo["objects"]), 1) self.assertEqual(len(topo["bookkeeping_geoms"]), 2) self.assertEqual(len(topo["linestrings"]), 2)
def test_cover_geometry_empty_geoms(tiler): """Empty geometries should return empty iterators.""" assert not cover_geometry(tiler, geometry.Point(), 0) == True assert not cover_geometry(tiler, geometry.MultiPoint(), 0) == True assert not cover_geometry(tiler, geometry.LineString(), 0) == True assert not cover_geometry(tiler, geometry.MultiLineString(), 0) == True assert not cover_geometry(tiler, geometry.Polygon(), 0) == True assert not cover_geometry(tiler, geometry.MultiPolygon(), 0) == True assert not cover_geometry(tiler, geometry.GeometryCollection(), 0) == True
def test_mem(driver_mem, gtype, geoms, ftypes, fields): driver = driver_mem ds = Dataset(allow_none_geometry=1) with ds.acreate_vector('', gtype, ftypes, driver=driver, options=[], sr=SR1['wkt']).close as v: for geom in geoms: v.insert_data(geom, fields) # TESTS 0 assert srs.wkt_same(v.wkt_stored, SR1['wkt']) assert srs.wkt_same(v.wkt_virtual, SR1['wkt']) for ftype, ftype_stored in zip(ftypes, v.fields): for key, value in ftype.items(): assert ftype_stored[key] == value assert v.mode == 'w' assert v.type.lower() == gtype.lower() # TESTS 1 datas = list(v.iter_data()) assert len(datas) == len(geoms) assert len(v) == len(geoms) # assert v.layer in {0, ''} if not sg.GeometryCollection(geoms).is_empty: assert eq(v.bounds, v.bounds_stored, v.extent[[0, 2, 1, 3]], v.extent_stored[[0, 2, 1, 3]], sg.GeometryCollection(geoms).bounds) for geom, data in zip(geoms, datas): if not isinstance(data, tuple): data = (data, ) read_geom, *read_fields = data if read_geom is None or read_geom.is_empty: assert geom.is_empty else: assert (geom ^ read_geom).is_empty, ( geom.wkt, read_geom.wkt, )
def test_extract_shapely_geometrycollection(): data = geometry.GeometryCollection([ geometry.Polygon([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]), geometry.Polygon([[1, 0], [2, 0], [2, 1], [1, 1], [1, 0]]), ]) topo = Extract(data).to_dict() assert len(topo["objects"]) == 1 assert len(topo["bookkeeping_geoms"]) == 2 assert len(topo["linestrings"]) == 2
def test_super_function_hashmap(self): data = geometry.GeometryCollection([ geometry.Polygon([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]), geometry.Polygon([[1, 0], [2, 0], [2, 1], [1, 1], [1, 0]]), ]) topo = Hashmap(data).to_dict() geoms = topo["objects"]["data"]["geometries"][0]["geometries"] self.assertEqual(list(topo.keys()), ["type", "linestrings", "objects", "options", "bbox"]) self.assertEqual(geoms[0]["arcs"], [[-3, 0]]) self.assertEqual(geoms[1]["arcs"], [[1, 2]])
def test_hashmap_super_function(): data = geometry.GeometryCollection([ geometry.Polygon([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]), geometry.Polygon([[1, 0], [2, 0], [2, 1], [1, 1], [1, 0]]), ]) topo = Hashmap(data).to_dict() geoms = topo["objects"]["data"]["geometries"][0]["geometries"] assert len(list(topo.keys())) == 6 assert geoms[0]["arcs"] == [[-3, 0]] assert geoms[1]["arcs"] == [[1, 2]]
def GetUrbanAreas(simplify_deg=1e-3): """Gets the US urban area as a |shapely.GeometryCollection|. Note: Client code should cache it as expensive to load (and not cached here). Args: simplify_deg: if defined, simplify the zone with given tolerance (degrees). Default is 1e-3 which corresponds roughly to 100m in continental US. """ kml_file = os.path.join(CONFIG.GetNtiaDir(), URBAN_AREAS_FILE) zones = _ReadKmlZones(kml_file, root_id_zone='Document', simplify=simplify_deg) urban_areas = sgeo.GeometryCollection( zones.values()) # ops.unary_union(zones.values()) return urban_areas
def compute_footprint_mask_shp(self, kernel_radius, urban_threshold, num_patches=1, buffer_dist=None, transform=None): """ Computes a geometry of the urban footprint of a given raster. Parameters ---------- kernel_radius : numeric The radius (in meters) of the circular kernel used in the convolution. urban_threshold : float from 0 to 1 Proportion of neighboring (within the kernel) urban pixels after which a given pixel is considered urban. num_patches : int, default 1 The number of urban patches that should be featured in the returned urban/non-urban mask. If `None` or a value lower than one is provided, the returned urban/non-urban mask will featuer all the urban patches. buffer_dist : numeric, optional Distance to be buffered around the urban/non-urban mask. If no value is provided, no buffer is applied. transform : Affine, optional An affine transform matrix. Ignored if the instance was initialized with a path to a geotiff. If no transform is available, the geometry features will be generated based on pixel coordinates. Returns ------- urban_mask_geom : GeometryCollection """ urban_mask = self.compute_footprint_mask(kernel_radius, urban_threshold, num_patches=num_patches, buffer_dist=buffer_dist) shapes_kws = {} if hasattr(self, 'transform'): transform = self.transform if transform is not None: shapes_kws['transform'] = transform return geometry.GeometryCollection([ geometry.shape(geom) for geom, val in features.shapes( urban_mask, mask=urban_mask, connectivity=8, **shapes_kws) ])
def GeneratePropertyMask(tileXPos, tileYPos, tileImageFilePath, geoJSONPath, propGeoJSONPath, outputFileName): with open(geoJSONPath) as f: geo_json_features = json.load(f)["features"] with open(propGeoJSONPath) as f: property_geo_json_features = json.load(f)["features"] tile = geometry.GeometryCollection([ geometry.shape(feature["geometry"]).buffer(0) for feature in geo_json_features ]) properties = [ geometry.shape(feature["geometry"]).buffer(0) for feature in property_geo_json_features ] img = Image.open(tileImageFilePath) pixels = img.load() #Run time is super long, loops here is pretty inefficient for property in properties: for i in range(0, img.size[0], RAWNESS): for j in range(0, img.size[1], RAWNESS): current_point = geometry.Point( GetLatLongForCoords(GRID_WIDTH * (tileXPos) + i, GRID_HEIGHT * (tileYPos) + j)) above_point = geometry.Point( GetLatLongForCoords(GRID_WIDTH * (tileXPos) + i, GRID_HEIGHT * (tileYPos) + j + 1)) below_point = geometry.Point( GetLatLongForCoords(GRID_WIDTH * (tileXPos) + i, GRID_HEIGHT * (tileYPos) + j - 1)) before_point = geometry.Point( GetLatLongForCoords(GRID_WIDTH * (tileXPos) + i - 1, GRID_HEIGHT * (tileYPos) + j)) after_point = geometry.Point( GetLatLongForCoords(GRID_WIDTH * (tileXPos) + i + 1, GRID_HEIGHT * (tileYPos) + j)) #TODO how to do this bit? if property.intersects(current_point): pixels[i, j] = (255, 0, 0) img.save(outputFileName)
def GeneratePropertyGeoJson(tileXPos,tileYPos,geoJSONPath,outputFileName): buffer = [] with open(geoJSONPath) as f: geo_json_features = json.load(f)["features"] tile=geometry.GeometryCollection([geometry.shape(feature["geometry"]).buffer(0) for feature in geo_json_features]) for k in properties: if geometry.shape(k["geometry"]).intersects(tile): buffer.append(dict(type="Feature", geometry=k["geometry"], properties=k["properties"])) #Write to file geojson = open(outputFileName, "w") geojson.write(json.dumps({"type": "FeatureCollection","features": buffer}, indent=2) + "\n")
def collection_extract( geometry: Optional[sh_geom.base.BaseGeometry], primitivetype: PrimitiveType) -> Optional[sh_geom.base.BaseGeometry]: """ Extracts the geometries from the input geom that comply with the primitive_type specified and returns them as (Multi)geometry. Args: geometry (sh_geom.base.BaseGeometry): geometry to extract the polygons from. primitivetype (GeometryPrimitiveTypes): the primitive type to extract from the input geom. Raises: Exception: if in_geom is an unsupported geometry type or the primitive type is invalid. Returns: sh_geom.base.BaseGeometry: List of primitive geometries, only containing the primitive type specified. """ # Extract the polygons from the multipolygon, but store them as multipolygons anyway if geometry is None: return None elif isinstance(geometry, sh_geom.Point) or isinstance(geometry, sh_geom.MultiPoint): if primitivetype == PrimitiveType.POINT: return geometry elif isinstance(geometry, sh_geom.LineString) or isinstance(geometry, sh_geom.MultiLineString): if primitivetype == PrimitiveType.LINESTRING: return geometry elif isinstance(geometry, sh_geom.Polygon) or isinstance(geometry, sh_geom.MultiPolygon): if primitivetype == PrimitiveType.POLYGON: return geometry elif isinstance(geometry, sh_geom.GeometryCollection): returngeoms = [] for geometry in sh_geom.GeometryCollection(geometry).geoms: returngeoms.append(collection_extract(geometry, primitivetype=primitivetype)) if len(returngeoms) > 0: return collect(returngeoms) else: raise Exception(f"Invalid/unsupported geometry(type): {geometry}") # Nothing found yet, so return None return None
class TestData: crs_epsg = 31370 point = sh_geom.Point((0, 0)) multipoint = sh_geom.MultiPoint([(0, 0), (10, 10), (20, 20)]) linestring = sh_geom.LineString([(0, 0), (10, 10), (20, 20)]) multilinestring = sh_geom.MultiLineString( [linestring.coords, [(100, 100), (110, 110), (120, 120)]]) polygon_with_island = sh_geom.Polygon( shell=[(0, 0), (0, 10), (1, 10), (10, 10), (10, 0), (0, 0)], holes=[[(2, 2), (2, 8), (8, 8), (8, 2), (2, 2)]]) polygon_no_islands = sh_geom.Polygon(shell=[(100, 100), (100, 110), (110, 110), (110, 100), (100, 100)]) polygon_with_island2 = sh_geom.Polygon( shell=[(20, 20), (20, 30), (21, 30), (30, 30), (30, 20), (20,20)], holes=[[(22, 22), (22, 28), (28, 28), (28, 22), (22, 22)]]) multipolygon = sh_geom.MultiPolygon([polygon_no_islands, polygon_with_island2]) geometrycollection = sh_geom.GeometryCollection([ point, multipoint, linestring, multilinestring, polygon_with_island, multipolygon]) polygon_small_island = sh_geom.Polygon( shell=[(40, 40), (40, 50), (41, 50), (50, 50), (50, 40), (40, 40)], holes=[[(42, 42), (42, 43), (43, 43), (43, 42), (42, 42)]])
def test_super_function_dedup(self): data = geometry.GeometryCollection([ geometry.Polygon([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]), geometry.Polygon([[1, 0], [2, 0], [2, 1], [1, 1], [1, 0]]), ]) topo = Dedup(data).to_dict() self.assertEqual( list(topo.keys()), [ "type", "linestrings", "bookkeeping_geoms", "objects", "options", "bbox", "junctions", "bookkeeping_duplicates", "bookkeeping_arcs", "bookkeeping_shared_arcs", ], )
def load_ocean_shape(geom_name=server_config.OCEAN_GEOJSON): """Read the ocean GeoJSON into memory once, so that it is accessible for all future functions Returns: [Geometry] -- A Shapely geometry produced from a GeoJSON """ geom_path = Path(path_config.LOCAL_DIR) / "aux_files" / geom_name if server_config.VERBOSE: print("Loading Ocean GeoJSON") if not geom_path.exists(): # pylint: disable=no-member src_path = "s3://skytruth-cerulean/aux_files/" + str(geom_name) download_str = f"aws s3 cp {src_path} {geom_path}" # print(download_str) run(download_str, shell=True) with open(path_config.LOCAL_DIR + "aux_files/OceanGeoJSON_lowres.geojson") as f: ocean_features = json.load(f)["features"] geom = sh.GeometryCollection( [sh.shape(feature["geometry"]).buffer(0) for feature in ocean_features] )[0] return geom
def _GeoJsonToShapelyGeometry(geometry): """Returns a |shapely| geometry from a GeoJSON geometry. Args: geometry: A dict or string representing a GeoJSON geometry. Raises: ValueError: If invalid GeoJSON geometry is passed. """ if isinstance(geometry, basestring): geometry = json.loads(geometry) if not isinstance(geometry, dict) or 'type' not in geometry: raise ValueError('Invalid GeoJSON geometry.') if 'geometries' in geometry: return sgeo.GeometryCollection([_GeoJsonToShapelyGeometry(g) for g in geometry['geometries']]) geometry = sgeo.shape(geometry) if isinstance(geometry, sgeo.Polygon) or isinstance(geometry, sgeo.MultiPolygon): geometry = geometry.buffer(0) return geometry
def load_shape(geom_name, as_multipolygon=False): """Read a GeoJSON into memory once, so that it is accessible for all future functions Returns: [Geometry] -- A Shapely geometry produced from a GeoJSON """ geom_path = Path(path_config.LOCAL_DIR) / "aux_files" / geom_name if server_config.VERBOSE: print("Loading GeoJSON:", geom_name) print() if not geom_path.exists(): # pylint: disable=no-member src_path = "s3://skytruth-cerulean/aux_files/" + geom_name download_str = f"aws s3 cp {src_path} {geom_path}" # print(download_str) run(download_str, shell=True) with open(geom_path) as f: geom = json.load(f)["features"] if as_multipolygon: geom = sh.GeometryCollection( [sh.shape(feature["geometry"]).buffer(0) for feature in geom] )[0] return geom
def test_makevalid(): # Test Point point_valid = geometry_util.make_valid(test_helper.TestData.point) assert isinstance(point_valid, sh_geom.Point) # Test MultiPoint multipoint_valid = geometry_util.make_valid(test_helper.TestData.multipoint) assert isinstance(multipoint_valid, sh_geom.MultiPoint) # Test LineString linestring_valid = geometry_util.make_valid(test_helper.TestData.linestring) assert isinstance(linestring_valid, sh_geom.LineString) # Test MultiLineString multilinestring_valid = geometry_util.make_valid(test_helper.TestData.multilinestring) assert isinstance(multilinestring_valid, sh_geom.MultiLineString) # Test Polygon, self-intersecting polygon_invalid = sh_geom.Polygon( shell=[(0, 0), (0, 10), (5, 10), (4, 11), (4, 9), (10, 10), (10, 0), (0,0)], holes=[[(2,2), (2,8), (8,8), (8,2), (2,2)]]) poly_valid = geometry_util.make_valid(polygon_invalid) assert isinstance(poly_valid, sh_geom.MultiPolygon) assert len(poly_valid.geoms) == 2 assert len(poly_valid.geoms[0].interiors) == 1 # Test MultiPolygon multipolygon_invalid = sh_geom.MultiPolygon([polygon_invalid, test_helper.TestData.polygon_no_islands]) multipoly_valid = geometry_util.make_valid(multipolygon_invalid) assert isinstance(multipoly_valid, sh_geom.MultiPolygon) # Test GeometryCollection (as combination of all previous ones) geometrycollection_invalid = sh_geom.GeometryCollection([ test_helper.TestData.point, test_helper.TestData.multipoint, test_helper.TestData.linestring, test_helper.TestData.multilinestring, polygon_invalid, multipolygon_invalid]) geometrycollection_valid = geometry_util.make_valid(geometrycollection_invalid) assert isinstance(geometrycollection_valid, sh_geom.GeometryCollection)
def test_splitLR(box, splitter, two_triangles): split = geo.GeometryCollection(list(ops.splitLR(box, splitter))) assert split.equals(two_triangles)
def two_triangles(): t1 = geo.Polygon(((0, 0), (1, 0), (1, 1))) t2 = geo.Polygon(((0, 0), (0, 1), (1, 1))) return geo.GeometryCollection([t1, t2])