diff options
author | Marvin Borner | 2018-07-13 19:06:45 +0200 |
---|---|---|
committer | Marvin Borner | 2018-07-13 19:06:45 +0200 |
commit | 6fcfb7c04d32e1c8b26a312295bf7ac3ec2d2ad7 (patch) | |
tree | dbc87ef16fa01d5d99116de283592b8fe5e02944 /public/bower_components/jvectormap/converter/converter.py | |
parent | dfd839f27146df0ad0494e11734fc7d310c70ebf (diff) |
Fixed many permissions and began admin interface
Diffstat (limited to 'public/bower_components/jvectormap/converter/converter.py')
-rw-r--r-- | public/bower_components/jvectormap/converter/converter.py | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/public/bower_components/jvectormap/converter/converter.py b/public/bower_components/jvectormap/converter/converter.py new file mode 100644 index 0000000..93be1de --- /dev/null +++ b/public/bower_components/jvectormap/converter/converter.py @@ -0,0 +1,299 @@ +# +# jVectorMap version 2.0.4 +# +# Copyright 2011-2013, Kirill Lebedev +# + +import sys +import shapely.geometry +import shapely.wkb +import shapely.affinity +from osgeo import ogr +from osgeo import osr +import json +import codecs +import copy + +class Map: + def __init__(self, name, language): + self.paths = {} + self.name = name + self.language = language + self.width = 0 + self.height = 0 + self.bbox = [] + + def addPath(self, path, code, name): + self.paths[code] = {"path": path, "name": name} + + def getJSCode(self): + map = {"paths": self.paths, "width": self.width, "height": self.height, "insets": self.insets, "projection": self.projection} + return "jQuery.fn.vectorMap('addMap', '"+self.name+"_"+self.projection['type']+"_"+self.language+"',"+json.dumps(map)+');' + + +class Converter: + def __init__(self, config): + args = { + 'buffer_distance': -0.4, + 'simplify_tolerance': 0.2, + 'longitude0': 0, + 'projection': 'mill', + 'name': 'world', + 'width': 900, + 'language': 'en', + 'precision': 2, + 'insets': [] + } + args.update(config) + + self.map = Map(args['name'], args.get('language')) + + if args.get('sources'): + self.sources = args['sources'] + else: + self.sources = [{ + 'input_file': args.get('input_file'), + 'where': args.get('where'), + 'name_field': args.get('name_field'), + 'code_field': args.get('code_field'), + 'input_file_encoding': args.get('input_file_encoding') + }] + + default_source = { + 'where': '', + 'name_field': 0, + 'code_field': 1, + 'input_file_encoding': 'iso-8859-1' + } + + for index in range(len(self.sources)): + for key in default_source: + if self.sources[index].get(key) is None: + self.sources[index][key] = default_source[key] + + self.features = {} + self.width = args.get('width') + self.minimal_area = args.get('minimal_area') + self.longitude0 = float(args.get('longitude0')) + self.projection = args.get('projection') + self.precision = args.get('precision') + self.buffer_distance = args.get('buffer_distance') + self.simplify_tolerance = args.get('simplify_tolerance') + self.for_each = args.get('for_each') + self.emulate_longitude0 = args.get('emulate_longitude0') + if args.get('emulate_longitude0') is None and (self.projection == 'merc' or self.projection =='mill') and self.longitude0 != 0: + self.emulate_longitude0 = True + + if args.get('viewport'): + self.viewport = map(lambda s: float(s), args.get('viewport').split(' ')) + else: + self.viewport = False + + # spatial reference to convert to + self.spatialRef = osr.SpatialReference() + projString = '+proj='+str(self.projection)+' +a=6381372 +b=6381372 +lat_0=0' + if not self.emulate_longitude0: + projString += ' +lon_0='+str(self.longitude0) + self.spatialRef.ImportFromProj4(projString) + + # handle map insets + if args.get('insets'): + self.insets = args.get('insets') + else: + self.insets = [] + + def loadData(self): + for sourceConfig in self.sources: + self.loadDataSource( sourceConfig ) + + def loadDataSource(self, sourceConfig): + source = ogr.Open( sourceConfig['input_file'] ) + layer = source.GetLayer(0) + layer.SetAttributeFilter( sourceConfig['where'].encode('ascii') ) + self.viewportRect = False + + transformation = osr.CoordinateTransformation( layer.GetSpatialRef(), self.spatialRef ) + if self.viewport: + layer.SetSpatialFilterRect( *self.viewport ) + point1 = transformation.TransformPoint(self.viewport[0], self.viewport[1]) + point2 = transformation.TransformPoint(self.viewport[2], self.viewport[3]) + self.viewportRect = shapely.geometry.box(point1[0], point1[1], point2[0], point2[1]) + + layer.ResetReading() + + codes = {} + + if self.emulate_longitude0: + meridian = -180 + self.longitude0 + p1 = transformation.TransformPoint(-180, 89) + p2 = transformation.TransformPoint(meridian, -89) + left = shapely.geometry.box(p1[0], p1[1], p2[0], p2[1]) + p3 = transformation.TransformPoint(meridian, 89) + p4 = transformation.TransformPoint(180, -89) + right = shapely.geometry.box(p3[0], p3[1], p4[0], p4[1]) + + # load features + nextCode = 0 + for feature in layer: + geometry = feature.GetGeometryRef() + geometryType = geometry.GetGeometryType() + + if geometryType == ogr.wkbPolygon or geometryType == ogr.wkbMultiPolygon: + geometry.TransformTo( self.spatialRef ) + shapelyGeometry = shapely.wkb.loads( geometry.ExportToWkb() ) + if not shapelyGeometry.is_valid: + shapelyGeometry = shapelyGeometry.buffer(0, 1) + + if self.emulate_longitude0: + leftPart = shapely.affinity.translate(shapelyGeometry.intersection(left), p4[0] - p3[0]) + rightPart = shapely.affinity.translate(shapelyGeometry.intersection(right), p1[0] - p2[0]) + shapelyGeometry = leftPart.buffer(0.1, 1).union(rightPart.buffer(0.1, 1)).buffer(-0.1, 1) + + if not shapelyGeometry.is_valid: + shapelyGeometry = shapelyGeometry.buffer(0, 1) + shapelyGeometry = self.applyFilters(shapelyGeometry) + if shapelyGeometry: + name = feature.GetFieldAsString(str(sourceConfig.get('name_field'))).decode(sourceConfig.get('input_file_encoding')) + code = feature.GetFieldAsString(str(sourceConfig.get('code_field'))).decode(sourceConfig.get('input_file_encoding')) + if code in codes: + code = '_' + str(nextCode) + nextCode += 1 + codes[code] = name + self.features[code] = {"geometry": shapelyGeometry, "name": name, "code": code} + else: + raise Exception, "Wrong geometry type: "+geometryType + + + def convert(self, outputFile): + print 'Generating '+outputFile + + self.loadData() + + codes = self.features.keys() + main_codes = copy.copy(codes) + self.map.insets = [] + envelope = [] + for inset in self.insets: + insetBbox = self.renderMapInset(inset['codes'], inset['left'], inset['top'], inset['width']) + insetHeight = (insetBbox[3] - insetBbox[1]) * (inset['width'] / (insetBbox[2] - insetBbox[0])) + self.map.insets.append({ + "bbox": [{"x": insetBbox[0], "y": -insetBbox[3]}, {"x": insetBbox[2], "y": -insetBbox[1]}], + "left": inset['left'], + "top": inset['top'], + "width": inset['width'], + "height": insetHeight + }) + envelope.append( + shapely.geometry.box( + inset['left'], inset['top'], inset['left'] + inset['width'], inset['top'] + insetHeight + ) + ) + for code in inset['codes']: + main_codes.remove(code) + + insetBbox = self.renderMapInset(main_codes, 0, 0, self.width) + insetHeight = (insetBbox[3] - insetBbox[1]) * (self.width / (insetBbox[2] - insetBbox[0])) + + envelope.append( shapely.geometry.box( 0, 0, self.width, insetHeight ) ) + mapBbox = shapely.geometry.MultiPolygon( envelope ).bounds + + self.map.width = mapBbox[2] - mapBbox[0] + self.map.height = mapBbox[3] - mapBbox[1] + self.map.insets.append({ + "bbox": [{"x": insetBbox[0], "y": -insetBbox[3]}, {"x": insetBbox[2], "y": -insetBbox[1]}], + "left": 0, + "top": 0, + "width": self.width, + "height": insetHeight + }) + self.map.projection = {"type": self.projection, "centralMeridian": float(self.longitude0)} + + open(outputFile, 'w').write( self.map.getJSCode() ) + + if self.for_each is not None: + for code in codes: + childConfig = copy.deepcopy(self.for_each) + for param in ('input_file', 'output_file', 'where', 'name'): + childConfig[param] = childConfig[param].replace('{{code}}', code.lower()) + converter = Converter(childConfig) + converter.convert(childConfig['output_file']) + + def renderMapInset(self, codes, left, top, width): + envelope = [] + for code in codes: + envelope.append( self.features[code]['geometry'].envelope ) + + bbox = shapely.geometry.MultiPolygon( envelope ).bounds + + scale = (bbox[2]-bbox[0]) / width + + # generate SVG paths + for code in codes: + feature = self.features[code] + geometry = feature['geometry'] + if self.buffer_distance: + geometry = geometry.buffer(self.buffer_distance*scale, 1) + if geometry.is_empty: + continue + if self.simplify_tolerance: + geometry = geometry.simplify(self.simplify_tolerance*scale, preserve_topology=True) + if isinstance(geometry, shapely.geometry.multipolygon.MultiPolygon): + polygons = geometry.geoms + else: + polygons = [geometry] + path = '' + for polygon in polygons: + rings = [] + rings.append(polygon.exterior) + rings.extend(polygon.interiors) + for ring in rings: + for pointIndex in range( len(ring.coords) ): + point = ring.coords[pointIndex] + if pointIndex == 0: + path += 'M'+str( round( (point[0]-bbox[0]) / scale + left, self.precision) ) + path += ','+str( round( (bbox[3] - point[1]) / scale + top, self.precision) ) + else: + path += 'l' + str( round(point[0]/scale - ring.coords[pointIndex-1][0]/scale, self.precision) ) + path += ',' + str( round(ring.coords[pointIndex-1][1]/scale - point[1]/scale, self.precision) ) + path += 'Z' + self.map.addPath(path, feature['code'], feature['name']) + return bbox + + + def applyFilters(self, geometry): + if self.viewportRect: + geometry = self.filterByViewport(geometry) + if not geometry: + return False + if self.minimal_area: + geometry = self.filterByMinimalArea(geometry) + if not geometry: + return False + return geometry + + + def filterByViewport(self, geometry): + try: + return geometry.intersection(self.viewportRect) + except shapely.geos.TopologicalError: + return False + + + def filterByMinimalArea(self, geometry): + if isinstance(geometry, shapely.geometry.multipolygon.MultiPolygon): + polygons = geometry.geoms + else: + polygons = [geometry] + polygons = filter(lambda p: p.area > self.minimal_area, polygons) + return shapely.geometry.multipolygon.MultiPolygon(polygons) + + +args = {} +if len(sys.argv) > 1: + paramsJson = open(sys.argv[1], 'r').read() +else: + paramsJson = sys.stdin.read() +paramsJson = json.loads(paramsJson) + +converter = Converter(paramsJson) +converter.convert(paramsJson['output_file']) |