def test_invalid_multilinestring(self): with self.assertRaises(ValueError) as cm: geojson.MultiLineString([1], validate=True) self.assertIn('each line must be a list of positions', str(cm.exception)) mls = geojson.MultiLineString([[(10, 5), (20, 1)], []]) self.assertEqual(mls.is_valid, False)
def test_invalid_multilinestring(self): multilinestring = geojson.MultiLineString() multilinestring.coordinates = [[D('100.0'), D('0.0')]] self.assertFalse(multilinestring.is_valid()) multilinestring.coordinates = [[[D('100.0')], [D('101.0'), D('1.0')]], [[D('102.0'), D('2.0')], [D('103.0'), D('3.0')]]] self.assertFalse(multilinestring.is_valid()) multilinestring.coordinates = [] self.assertFalse(multilinestring.is_valid()) multilinestring = geojson.MultiLineString() self.assertFalse(multilinestring.is_valid())
def tryToConvertToPolygon(tags, lines, polygonize, isMultiPolygon = False): """ Creates a Polygon or LineString based on the given lines tags: tags of the base object lines: coordinates (basically nested lists) polygonize: boolean, if True -> tries to convert every Line to Polygon isMultiPolygon: boolean, if each line is an extra polygon else lines = [boundary, holes..] """ # as sometimes tags like "area":"no" exists, which are obviously no polygons tags = {tag: v for tag, v in tags.items() if not v == "no"} # osm-multipolygon: means just as complex area ... but geojson polygons can also handle holes # sometimes they are real multipolygons? (see Dresdener Heide) --> isMultiPolygon if POLYGON_TAGS.intersection(tags) or tags.get("type") == "multipolygon" or polygonize: if isMultiPolygon: # creating a polygon array for each line (only exterior lines, no holes currently) lines = [[line] for line in lines] polygon = geojson.MultiPolygon(lines) else: polygon = geojson.Polygon(lines) if not polygon.errors(): return polygon elif not polygonize: # with polygonize == true it is expected that this wont work every time logging.debug("Could not be converted to a polygon with tags {}".format(tags)) if len(lines) == 1: return geojson.LineString(lines[0], validate=True) else: if LINESTRING_TAGS.intersection(tags): logging.debug("To many lines for a simple line for object with tags: {}".format(tags)) return geojson.MultiLineString(lines, validate=True)
def toGeoJson(data, dtype): """formats all data input to valid geojson """ dtype = dtype.lower() if dtype == "point": collection = [] for i in range(0, len(data)): point = geojson.Point(data[i]) collection.append(geojson.Feature(geometry=point)) collection = geojson.FeatureCollection(collection) # pp.pprint(collection) # valid return collection if dtype == "polygon": polygon = geojson.Polygon(data) # print(polygon) # valid return polygon elif dtype == "linestring": linestring = geojson.LineString(data) # print(linestring) #valid return (linestring) elif dtype == "multilinestring": mls = geojson.MultiLineString(data) # print(mls) # valid return mls else: print("\nBAD ARGUMENT\n")
def convertTOGEOJSON(data, ftype): """ converts coordinates to geojson """ ftype = ftype.lower() if ftype == "point": result_feat = [] for i in range(0, len(data)): point = geojson.Point(data[i]) result_feat.append(geojson.Feature(geometry=point)) result_feat = geojson.FeatureCollection(result_feat) # pp.pprint(collection) # valid return result_feat if ftype == "polygon": polygon = geojson.Polygon(data) # print(polygon) # valid return polygon elif ftype == "linestring": linestring = geojson.LineString(data) # print(linestring) #valid return (linestring) elif ftype == "multilinestring": mls = geojson.MultiLineString(data) # print(mls) # valid return mls else: print("\nwrong argument\n")
def feature_to_polygons(feature): """ given a geoJSON Feature object, convert it into Polygon(s). A Feature object represents a spatially bounded thing. In the GW case, these Features contains MultiLineStrings. We build the polygons from the coordinates of each of those. Parameters: ----------- feature: `geojson.Feature` object for which the coordinates will be folded. Returns: -------- list of geojson.Polygon objects """ # first fold the coordinates, all in one go. # perform the operation on a copy of the feature. folded = fold_coords(feature) # now convert to multiline string mls = geojson.MultiLineString(folded['geometry'], validate=True) if not mls.is_valid: raise ValueError("cannot convert feature geometry %s to valid geojson.MultiLineString"% (repr(feature.coordinates))) # convert each coordinate list of the multilinestring to polygons and return return [to_poly([cc]) for cc in mls['coordinates']]
def _convert_vector_field_to_geojson(self, vertices, vector_field_magnitude, vector_field, scale, cmap): """ Convert a scalar field to a geojson FeatureCollection. Parameters ---------- geo_map : folium.Map Map to which the mesh plot should be added. vertices: 2d numpy array Matrix containing the coordinates of the vertices. The matrix should have as many rows as vertices in the mesh, and two columns. vector_field_magnitude: 1d numpy array Vector containing the magnitude of the field at each vertex. The vector should have as many entries as vertices in the mesh. vector_field: 2d numpy array Matrix containing the value of the field at each vertex. The matrix should have as many rows as vertices in the mesh, and two columns. scale: number Scaling to be applied before drawing arrows. cmap: function Color map to be used. Returns ------- geojson.FeatureCollection A geojson FeatureCollection representing the scalar field. """ multiline_coordinates = dict() multiline_properties = dict() for v in range(vertices.shape[0]): coordinates = [ self.transformer(*vertices[v, :]), self.transformer(*(vertices[v, :] + scale * vector_field[v, :])) ] color = cmap(vector_field_magnitude[v]) # Store current coordinates if color not in multiline_coordinates: multiline_coordinates[color] = list() multiline_coordinates[color].append(coordinates) # Store current properties properties = {"color": color, "weight": 2} if color not in multiline_properties: multiline_properties[color] = properties else: assert multiline_properties[color] == properties multiline_features = list() for color in multiline_coordinates.keys(): multiline = geojson.MultiLineString( coordinates=multiline_coordinates[color]) feature = geojson.Feature(geometry=multiline, properties=multiline_properties[color]) multiline_features.append(feature) return geojson.FeatureCollection(multiline_features)
def needs_reorienting(): coords = [ [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0)], [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)], ] multi_line_string = geojson.MultiLineString(coords, validate=True) feature = geojson.Feature(geometry=multi_line_string, properties={}) return geojson.FeatureCollection([feature])
def build_MultiLineString(G, pathlist): lines = [] for path in pathlist: raw = nodes2coords(G, path) lines.append(raw) data = geojson.MultiLineString(lines) dump = geojson.dumps(data, sort_keys=True) return dump
def grid_lines_for_bbox(x_min, y_min, x_max, y_max, cells_x, cells_y): # top-down lines = list(gen_lines(x_min, x_max, y_min, y_max, cells_x)) # left-right for _from, to in gen_lines(y_min, y_max, x_min, x_max, cells_y): lines.append([_from[::-1], to[::-1]]) # flip coordinates return geojson.MultiLineString(lines)
def test_get_center_point(): assert util.get_center_point( geojson.Feature( geometry=geojson.LineString([[1, 0], [3, 0]]))) == (2.0, 0.0) assert util.get_center_point( geojson.Feature(geometry=geojson.MultiLineString( [[[2, 0], [2, 4]], [[0, 2], [4, 2]]]))) == (2.0, 2.0) assert util.get_center_point( geojson.Feature(geometry=geojson.Point([0, 0]))) == (None, None)
def create_feature(geometry, geo_type, val, feature_id=None, color=(255, 0, 0), weight=10, opacity=1.0, props={}): """ :param geometry: Geometry structure that creates geojson string. Options are: Point: (lng, lat) as tuple MultiPoint: [Point, Point] as array of points Line(string): [Point, Point, Point] as array of points Multiline(string): [Line, Line] as array of lines Polygon without holes: [Point1, Point, Point, Point1] as array of points, first and last point in array are the same point (example makes a triangle). Polygon with hole: [[Point1, Point, Point, Point1], [Point2, Point, Point, Point2]] as array of polygons, second polygon is the hole. Multipolygon: [Polygon, Polygon] as array of polygons (must confirm...?) :param geo_type: string indicating the geometry type, must match id strings from class geojson_geometry :param val: value to put into properties.value for mapping and style color matching :param feature_id: id for the geojson string :param color: a 3 value tuple containing an rgb value :param weight: for lines/polygons, line width; for points, point size :param opacity: opacity of layer in leaflet, 1.0 = 100%, 0 = 0% :returns: dictionary with geojson feature string and a leaflet style created from input parameters """ try: if geo_type == GeojsonGeometry.point: geo = geojson.Point(geometry) elif geo_type == GeojsonGeometry.multipoint: geo = geojson.MultiPoint(geometry) elif geo_type == GeojsonGeometry.line: geo = geojson.LineString(geometry) elif geo_type == GeojsonGeometry.multiline: geo = geojson.MultiLineString(geometry) elif geo_type == GeojsonGeometry.polygon: geo = geojson.Polygon(geometry) elif geo_type == GeojsonGeometry.multipolygon: geo = geojson.MultiPolygon(geometry) else: print("Unsupported geometry type: " + geo_type) return except Exception as e: print(e, "\n probably wrong input data structure for " + geo_type) return style = None # leaflet_style_creator() props['value'] = val geo = geojson.Feature(id=feature_id, geometry=geo, properties=props) ret = {'geojson': geo, 'style': style} return ret
def test_fromgeojsonfeatures_multiline(self): g_f = geojson.Feature() line = geojson.MultiLineString(coordinates=[[[100.0, 0.0], [101.0, 1.0]], [[102.0, 2.0], [103.0, 3.0]]]) g_f['properties'] = {"name": "name", "value": "value"} g_f['geometry'] = line g_fc = geojson.FeatureCollection([g_f]) s_fs = from_geojson_features(g_fc) result = list(s_fs) self.assertEqual(result[0].geometry.parts, [2, 2]) self.assertEqual(result[0].fieldNames, ['name', 'value']) self.assertEqual(result[0].fieldValues, ['name', 'value'])
def _topologize(input_features): r"""Return a FeatureCollection of MultiLineStrings, one for each loop""" loops = _features_to_loops(input_features) features = [] for loop in loops: coords = [ list(geojson.utils.coords(input_features[index])) for index in loop ] multi_line_string = geojson.MultiLineString(coords) features.append(geojson.Feature(geometry=multi_line_string)) return features
def get_domain_geojson(): """ Return the domain as GeoJSON multipath. """ domain = app.comm.project.domain outer_border = domain.border inner_border = domain.inner_border border = geojson.MultiLineString([ [(_i[1], _i[0]) for _i in inner_border], [(_i[1], _i[0]) for _i in outer_border], ]) return flask.jsonify(**border)
def ways2geometry(ways): """ Convert a nested list of coordinates into a GeoJSON object. """ if len(ways) == 1: way = ways[0] highway = way.get('highway') if ((way.get('area', '') == 'yes' and highway == 'pedestrian') or (way.get('leisure') in ['park', 'pitch', 'common'])): # See http://wiki.openstreetmap.org/wiki/Key:area return geojson.Polygon([way['coordinates']]) elif highway: return geojson.LineString(way['coordinates']) else: return geojson.MultiLineString([w['coordinates'] for w in ways])
def __init__(self, geom_type, zoom, m): proj = mapnik.Projection(m.srs) width_of_world_in_pixels = 2**zoom * 256 width_of_world_in_metres = proj.forward(mapnik.Coord( 180, 0)).x - proj.forward(mapnik.Coord(-180, 0)).x width_of_image_in_metres = float( m.width) / width_of_world_in_pixels * width_of_world_in_metres height_of_image_in_metres = float( m.height) / width_of_world_in_pixels * width_of_world_in_metres self.max_x = width_of_image_in_metres self.max_y = height_of_image_in_metres self.min_x = 0 self.min_y = 0 if geom_type == "point": self.geom = geojson.Point((self.max_x / 2, self.max_y / 2)) elif geom_type == "point75": self.geom = geojson.Point((self.max_x * 0.5, self.max_y * 0.75)) elif geom_type == "polygon": self.geom = geojson.Polygon([[(0, 0), (self.max_x, 0), (self.max_x, self.max_y), (0, self.max_y), (0, 0)]]) elif geom_type == "linestring-with-gap": self.geom = geojson.MultiLineString([[ (0, 0.5 * self.max_y), (self.max_x * 0.45, 0.5 * self.max_y), (self.max_x * 0.55, 0.5 * self.max_y), (self.max_x, 0.5 * self.max_y) ]]) elif geom_type == "polygon-with-hole": self.geom = geojson.Polygon([[[0.7 * self.max_x, 0.2 * self.max_y], [0.9 * self.max_x, 0.9 * self.max_y], [0.3 * self.max_x, 0.8 * self.max_y], [0.2 * self.max_x, 0.4 * self.max_y], [0.7 * self.max_y, 0.2 * self.max_y]], [[0.4 * self.max_x, 0.6 * self.max_y], [0.7 * self.max_x, 0.7 * self.max_y], [0.6 * self.max_x, 0.4 * self.max_y], [0.4 * self.max_x, 0.6 * self.max_y]]]) elif geom_type == "linestring": self.geom = geojson.LineString([[0, 0.5 * self.max_y], [self.max_x, 0.5 * self.max_y]]) else: raise MapnikLegendaryError( "Geometry type {} is not supported for legend entries.".format( geom_type))
def download_arcgis(url, gtype, pkey, filename): """ Downloads from an ArcGIS REST API query endpoint and shows a simple progress bar. Endpoint must support pagination. :param url: resource to download :param gtype: geometry type :param pkey: the primary key for the data to download :param filename: destination filename (full path) :returns: Path to file """ features = [] where = pkey + " IS NOT NULL" count = requests.get(url, params={"f": "json", "where": where, "returnCountOnly": True}) count = count.json()["count"] count = int(math.ceil(float(count) / 1000.0)) print("[", end='') num = 0 print_every_iter = int(count) / 50 next_print = 0 while num < count: data = requests.get(url, params={"f": "json", "where": where, "outFields": "*", "returnGeometry": True, "resultRecordCount": 1000, "resultOffset": (num * 1000)}) data = data.json()["features"] num += 1 features += data if num >= next_print: sys.stdout.write("=") sys.stdout.flush() next_print += print_every_iter with open(filename, "wb") as f: processed_features = [] for x in features: if gtype == "point" and 'NaN' in [x["geometry"]["x"], x["geometry"]["y"]]: continue feat = geojson.Feature(id=x["attributes"][pkey], properties=x["attributes"], geometry=geojson.Point((x["geometry"]["x"], x["geometry"]["y"]))\ if gtype == "point" else geojson.MultiLineString(x["geometry"]["paths"])) processed_features.append(feat) processed_features = geojson.FeatureCollection(processed_features) geojson.dump(processed_features, f) print("] Download complete...") return filename
def test_nested_constructors(self): a = [5, 6] b = [9, 10] c = [-5, 12] mp = geojson.MultiPoint([geojson.Point(a), b]) self.assertEqual(mp.coordinates, [a, b]) mls = geojson.MultiLineString([geojson.LineString([a, b]), [a, c]]) self.assertEqual(mls.coordinates, [[a, b], [a, c]]) outer = [a, b, c, a] poly = geojson.Polygon(geojson.MultiPoint(outer)) other = [[1, 1], [1, 2], [2, 1], [1, 1]] poly2 = geojson.Polygon([outer, other]) self.assertEqual(geojson.MultiPolygon([poly, poly2]).coordinates, [[outer], [outer, other]])
def get_features(self, tags): ls = self.wh.geojson_linestrings(properties=tags, as_features=False) if ls: ml = geojson.MultiLineString(ls) mlf = geojson.Feature(geometry=ml, properties=tags) # mlf = self.wh.geojson_linestrings(properties=tags, as_features=True) else: mlf = [] pf = self.nh.geojson_features print(tags.get('name', '')) print('nh len features', len(self.nh.geojson_features)) print('wh len features', len(self.wh.geojson_features)) self.nh.geojson_features = list() self.wh.geojson_features = list() # print('nh len features',len(self.nh.geojson_features)) # print('wh len features',len(self.wh.geojson_features)) return pf, mlf
def dump_geojson(route, relation): """ Writes the route relation as a GeoJSON file. :param route: Name of the route. :param relation: Route relation to dump to GeoJSON. """ features = [] multi_line_string = geojson.MultiLineString([[(node.lon, node.lat) for node in way.nodes] for way in relation.ways]) properties = relation.tags if relation.tags is not None else dict() properties['@id'] = 'relation/' + str(relation.id) features.append( geojson.Feature(geometry=multi_line_string, properties=properties)) with open(OSM_ROUTES_LOCATION + route + ".geojson", "w") as fp: fp.write(geojson.dumps(geojson.FeatureCollection(features)))
def createGeojson(data, name, ulx, uly, lrx, lry, projection): col = ['coordinate', 'type', 'label', 'pix'] df = pd.DataFrame(data, columns=col) geofilename = name + ".geojson" filenameData = geofilename.split("_") features = [] for name, row in df.iterrows(): coords_pol = row['coordinate'] if row['type'] == 'Polygon': if coords_pol[-1] != coords_pol[0]: coords_pol.append(coords_pol[0]) features.append( geojson.Feature(properties={ 'label': row['label'], 'filename': geofilename, 'country': filenameData[0], 'city': filenameData[1], 'image_geocoordinates_upper_left': [ulx, uly], 'image_geocoordinates_lower_right': [lrx, lry], 'pixel_coordinates': row['pix'], 'projection': projection }, geometry=geojson.Polygon([coords_pol]))) elif row['type'] == 'Line': features.append( geojson.Feature(properties={ 'label': row['label'], 'filename': geofilename, 'country': filenameData[0], 'city': filenameData[1], 'image_geocoordinates_upper_left': [ulx, uly], 'image_geocoordinates_lower_right': [lrx, lry], 'pixel_coordinates': row['pix'], 'projection': projection }, geometry=geojson.MultiLineString([coords_pol ]))) f_coll = geojson.FeatureCollection(features) with open(geofilename, 'w') as f: json.dump(f_coll, f, indent=2)
def convert_json_data_to_geodataframe(json_data, spatial_reference='4326'): """Convert raw JSON objects from EDDM to a GeoDataFrame.""" features = [] for feature in json_data: new_feature = {} # Assume the feature is a LineString object. try: new_feature['geometry'] = shapely.geometry.shape( geojson.MultiLineString(feature['geometry']['paths'])) # If the feature is not a LineString, maybe it is a MultiPoint. except KeyError: new_feature['geometry'] = shapely.geometry.shape( geojson.MultiPoint(feature['geometry']['points'])) new_feature['properties'] = feature['attributes'] features.append(new_feature) return gpd.GeoDataFrame.from_features(features, crs=spatial_reference)
def paths_geojson(city): paths = open( 'static/data/' + str(city) + '/footfall/walking_paths_complete.csv', 'r') paths = paths.readlines() json_paths = [] for path in paths: new_path = [] points = path.split(';')[:-1] for point in points: [lng, lat] = point.split(',') new_path.append((float(lat), float(lng))) json_paths.append(new_path) geojson_paths = geojson.MultiLineString(json_paths) geojson_data = geojson.dumps(geojson_paths) output_file = open( 'static/data/' + str(city) + '/footfall/walking_paths.geojson', 'w') output_file.write(geojson_data)
def dump_bboxes(points, filename): fc = geojson.FeatureCollection([]) for st, pts in points.items(): if len(pts) == 0: continue lbot, rtop = bounding_box_naive(pts) llon, llat = lbot rlon, rlat = rtop print(st, lbot, rtop) f = geojson.Feature(geometry=geojson.MultiLineString([[(llat, llon), (rlat, llon), (rlat, rlon), (llat, rlon), (llat, llon)]]), properties={'station_id': st}) fc.features.append(f) with open(filename, "wb") as jfile: gj = geojson.dumps(fc, indent=4).encode("utf8") jfile.write(gj)
def createGeoJSON(self): """ Get list of link geometries and properties to be converted. Input: Vissim object Output: list of links """ features = [] for link in self.data.xpath('./links/link'): geos = [] linkNum = link.attrib['no'] for geo in link.xpath('./geometry/points3D/point3D'): x, y = geo.attrib['x'], geo.attrib['y'] latLng = self.scaledMetersToNode((x, y)) geos.append(latLng) linkNum = link.attrib['no'] laneNum = str(len(link.xpath('./lanes/lane'))) multiLine = geojson.MultiLineString(coordinates=geos) features.append( geojson.Feature(id=linkNum, geometry=multiLine, properties={ 'lane': laneNum, 'id': linkNum })) return geojson.FeatureCollection(features)
def get_border(key, keywords): resjson = get_resjson(key, keywords, 0, 'all') district = resjson["districts"][0] if 'polyline' not in district: return {} cords = district['polyline'].split('|') polylines = [] for cord in cords: lonlats = cord.split(';') polyline = [] for lonlat in lonlats: lon, lat = lonlat.split(',') point = gcj02_to_wgs84(float(lon), float(lat)) polyline.append(point) polylines.append(polyline) geom = geojson.MultiLineString(polylines) # 多边形的拓扑关系不明,故使用线 properties = {'citycode': district['citycode'], 'adcode': district['adcode'], 'name': district['name'], 'level': district['level']} border = {"type": "Feature", "properties": properties, "geometry": geom} return border
def test_valid_multilinestring(self): ls1 = [(3.75, 9.25), (-130.95, 1.52)] ls2 = [(23.15, -34.25), (-1.35, -4.65), (3.45, 77.95)] mls = geojson.MultiLineString([ls1, ls2]) self.assertEqual(is_valid(mls)['valid'], YES)
def test_invalid_multilinestring(self): mls = geojson.MultiLineString([[(10, 5), (20, 1)], []]) self.assertEqual(is_valid(mls)['valid'], NO)
def create_segments_from_json(roads_shp_path, mapfp): data = fiona.open(roads_shp_path) data = util.reproject_records([x for x in data]) # All the line strings are roads roads = [x for x in data if x['geometry'].type == 'LineString'] print("read in {} road segments".format(len(roads))) # unique id did not get included in shapefile, need to add it for adjacency for i, road in enumerate(roads): road['properties']['orig_id'] = int(str(99) + str(i)) # Get the intersection list by excluding anything that's not labeled # as an intersection inters = [ x for x in data if x['geometry'].type == 'Point' and 'intersection' in list(x['properties'].keys()) and x['properties']['intersection'] ] # Initial buffer = 20 meters int_buffers = get_intersection_buffers(inters, 20) non_int_lines, inter_segments = find_non_ints(roads, int_buffers) non_int_w_ids = [] # Allow intersections that don't have osmids, because this # happens when we generate alternate maps from city data # They won't have display names, and this is okay, because # we only use them to map to the osm segments inters_by_id = { x['properties']['osmid'] if 'osmid' in x['properties'] else '0': x['properties']['streets'] if 'streets' in x['properties'] else None for x in inters } for i, l in enumerate(non_int_lines): value = copy.deepcopy(l) value['type'] = 'Feature' value['properties']['id'] = '00' + str(i) value['properties']['inter'] = 0 value['properties']['display_name'] = get_non_intersection_name( l, inters_by_id) non_int_w_ids.append(value) print("extracted {} non-intersection segments".format(len(non_int_w_ids))) # Planarize intersection segments # Turns the list of LineStrings into a MultiLineString union_inter = [] for idx, lines in list(inter_segments['lines'].items()): lines = unary_union(lines) coords = [] for line in lines: coords += [[x for x in line.coords]] name = get_intersection_name(inter_segments['data'][idx]) properties = { 'id': idx, 'data': inter_segments['data'][idx], 'display_name': name } union_inter.append( geojson.Feature( geometry=geojson.MultiLineString(coords), id=idx, properties=properties, )) return non_int_w_ids, union_inter