| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- # @version 0.2.0
- from geojson import Point, LineString, Polygon, MultiPolygon, Feature, FeatureCollection
- from geojson import dumps as geodumps
- from csv import reader as csvreader
- #import json
- from pprint import pprint # For pretty-printing JSON
- #import sys
- #import urllib.request, urllib.parse, urllib.error
- # Inputs
- csvFileName = 'all-pois-italy.csv'
- # Function to convert SPARQL query results to GeoJSON FeatureCollection
- def sparql2geojs(csv):
- rows = 0
- header = False
- features = {}
- for row in csv:
- if header is False:
- header = True
- continue
- #pprint(result)
- featureId = row[0]
- feature = features.get(featureId)
- # SPARQL endpoint returns one POI more that once, if it has more than one property
- if feature is None:
- feature = createGeoJSONFeature(row)
- features[featureId] = feature
- else:
- updateGeoJSONFeature(feature, row)
- rows += 1
- if rows % 1000 == 0:
- print(rows, ' lines processed')
- return FeatureCollection(list(features.values()))
- # Supplementary function to convert one result to a GeoJSON feature
- def createGeoJSONFeature(row):
- # each result from the SPARQL query comes with just one property-value pair
- props = {row[1]:row[2]}
- id = row[0] # ID of the feature is its URI
- geom = parseWKT(row[3])
- #pprint(geom.get('type'))
- #if geom.get('type').upper() == "POINT":
- #pprint(Feature(geometry = Point(coords), id = id, properties = props))
- return Feature(geometry = geom, id = id, properties = props)
- #elif geom.get('type').upper() == "MULTIPOLYGON":
- #pprint(Feature(geometry = MultiPolygon(coords), id = id, properties = props))
- #return Feature(geometry = MultiPolygon(coords), id = id, properties = props)
- # Supplementary function to update one GeoJSON feature if it already exists
- def updateGeoJSONFeature(feature, result):
- # Case 1: property does not exist in features's properties
- if result[1] not in feature['properties'].keys():
- feature['properties'][result[1]] = result[2]
- else: # Case 2: property already exists, hence it has more than 1 value
- pass
- # Supplementary function to parse WKT Literal.
- # It is further extended by specific functions for specific geometry types
- def parseWKT(wktLiteral):
- type = wktLiteral.split("(")[0]
- if type.strip() == "POINT":
- wktCoords = wktLiteral[len(type):].replace("(", "").replace(")", "")
- return Point(parseWKTPoint(wktCoords))
- elif type.strip() == "LINESTRING":
- wktCoords = wktLiteral[len(type):]
- return LineString(parseWKTLineString(wktCoords))
- elif type.strip() == "POLYGON":
- wktCoords = wktLiteral[len(type)+1:-1]
- return Polygon(parseWKTPolygon(wktCoords))
- elif type.strip() == "MULTIPOLYGON":
- wktCoords = wktLiteral[len(type)+1:-1]
- return MultiPolygon(parseWKTMultiPolygon(wktCoords))
- # # find polygons first ...
- # parts = wktLiteral[15:].replace(')))', '').split(')),') #[15:] will intentionally left two ( in the beginning
- # print(len(parts))
- # coords = []
- # for part in parts:
- # # ... then rings of the polygons ...
- # rings = part.split('),')
- # print(len(rings))
- # polygon = [] # this must be converted into tuple later on, but tuples are immutable
- # for r in rings:
- # # ... and finally points of the rings
- # points = part[2:].split(',')
- # pprint(points)
- # ring = []
- # for point in points:
- # if len(point) > 1:
- # pprint(point)
- # ring.append( (float(point.split(' ')[0]), float(point.split(' ')[1])) )
- # polygon.append(ring)
- # coords.append( tuple(polygon) )
- # TODO: other geometry types support
- else:
- print("Unsupported geometry type {}! Will produce empty point object without coordinates!".format(type))
- return Point([])
- # Supplementary function to parse WKT Point geometry to its GeoJSON equivalent.
- def parseWKTPoint(wktLiteral):
- lonLat = wktLiteral.split(" ")
- return (float(lonLat[0]), float(lonLat[1]))
- # Supplementary function to parse WKT LineString geometry to its GeoJSON equivalent.
- def parseWKTLineString(wktLiteral):
- lineString = []
- points = wktLiteral.replace("(", "").replace(")", "").split(",")
- for point in points:
- lineString.append(parseWKTPoint(point.strip()))
- return lineString
- # Supplementary function to parse WKT Polygon geometry to its GeoJSON equivalent.
- def parseWKTPolygon(wktLiteral):
- polygon = []
- rings = wktLiteral.split(",(")
- for ring in rings:
- polygon.append(parseWKTLineString(ring))
- return polygon
- # Supplementary function to parse WKT MultiPolygon geometry to its GeoJSON equivalent.
- def parseWKTMultiPolygon(wktLiteral):
- multipolygon = []
- polygons = wktLiteral.split(",((")
- for polygon in polygons:
- multipolygon.append(parseWKTPolygon(polygon))
- return multipolygon
- # Executional part
- with open(csvFileName, encoding='utf-8') as csvfile:
- filereader = csvreader(csvfile)
- print('File read, parsing ...')
- geojs = sparql2geojs(filereader)
- #pprint(js)
- #pprint(geojs)
- print(geojs.is_valid)
- print(geojs.errors())
- # uncomment following lines if you want to save the output into a file
- print("Saving GeoJSON file ...")
- outFileName = csvFileName.split(".")[0]
- with open(outFileName + ".geojson", 'w') as out:
- out.write(geodumps(geojs))
|