diff options
Diffstat (limited to 'public/bower_components/jvectormap/converter/simplifier.py')
-rw-r--r-- | public/bower_components/jvectormap/converter/simplifier.py | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/public/bower_components/jvectormap/converter/simplifier.py b/public/bower_components/jvectormap/converter/simplifier.py new file mode 100644 index 0000000..18ad9da --- /dev/null +++ b/public/bower_components/jvectormap/converter/simplifier.py @@ -0,0 +1,205 @@ +import argparse +import sys +import os +from osgeo import ogr +from osgeo import osr +import anyjson +import shapely.geometry +import shapely.ops +import codecs +import time + + +format = '%.8f %.8f' +tolerance = 0.01 +infile = '/Users/kirilllebedev/Maps/50m-admin-0-countries/ne_50m_admin_0_countries.shp' +outfile = 'map.shp' + +# Open the datasource to operate on. +in_ds = ogr.Open( infile, update = 0 ) +in_layer = in_ds.GetLayer( 0 ) +in_defn = in_layer.GetLayerDefn() + + +# Create output file with similar information. +shp_driver = ogr.GetDriverByName( 'ESRI Shapefile' ) +if os.path.exists('map.shp'): + shp_driver.DeleteDataSource( outfile ) +shp_ds = shp_driver.CreateDataSource( outfile ) +shp_layer = shp_ds.CreateLayer( in_defn.GetName(), + geom_type = in_defn.GetGeomType(), + srs = in_layer.GetSpatialRef() ) + +in_field_count = in_defn.GetFieldCount() +for fld_index in range(in_field_count): + src_fd = in_defn.GetFieldDefn( fld_index ) + fd = ogr.FieldDefn( src_fd.GetName(), src_fd.GetType() ) + fd.SetWidth( src_fd.GetWidth() ) + fd.SetPrecision( src_fd.GetPrecision() ) + shp_layer.CreateField( fd ) + + +# Load geometries +geometries = [] +for feature in in_layer: + geometry = feature.GetGeometryRef() + geometryType = geometry.GetGeometryType() + + if geometryType == ogr.wkbPolygon or geometryType == ogr.wkbMultiPolygon: + shapelyGeometry = shapely.wkb.loads( geometry.ExportToWkb() ) + #if not shapelyGeometry.is_valid: + #buffer to fix selfcrosses + #shapelyGeometry = shapelyGeometry.buffer(0) + if shapelyGeometry: + geometries.append(shapelyGeometry) +in_layer.ResetReading() + +start = int(round(time.time() * 1000)) +# Simplification +points = [] +connections = {} +counter = 0 +for geom in geometries: + counter += 1 + polygons = [] + + if isinstance(geom, shapely.geometry.Polygon): + polygons.append(geom) + else: + for polygon in geom: + polygons.append(polygon) + + for polygon in polygons: + if polygon.area > 0: + lines = [] + lines.append(polygon.exterior) + for line in polygon.interiors: + lines.append(line) + + for line in lines: + for i in range(len(line.coords)-1): + indexFrom = i + indexTo = i+1 + pointFrom = format % line.coords[indexFrom] + pointTo = format % line.coords[indexTo] + if pointFrom == pointTo: + continue + if not (pointFrom in connections): + connections[pointFrom] = {} + connections[pointFrom][pointTo] = 1 + if not (pointTo in connections): + connections[pointTo] = {} + connections[pointTo][pointFrom] = 1 +print int(round(time.time() * 1000)) - start + +simplifiedLines = {} +pivotPoints = {} +def simplifyRing(ring): + coords = list(ring.coords)[0:-1] + simpleCoords = [] + + isPivot = False + pointIndex = 0 + while not isPivot and pointIndex < len(coords): + pointStr = format % coords[pointIndex] + pointIndex += 1 + isPivot = ((len(connections[pointStr]) > 2) or (pointStr in pivotPoints)) + pointIndex = pointIndex - 1 + + if not isPivot: + simpleRing = shapely.geometry.LineString(coords).simplify(tolerance) + if len(simpleRing.coords) <= 2: + return None + else: + pivotPoints[format % coords[0]] = True + pivotPoints[format % coords[-1]] = True + simpleLineKey = format % coords[0]+':'+format % coords[1]+':'+format % coords[-1] + simplifiedLines[simpleLineKey] = simpleRing.coords + return simpleRing + else: + points = coords[pointIndex:len(coords)] + points.extend(coords[0:pointIndex+1]) + iFrom = 0 + for i in range(1, len(points)): + pointStr = format % points[i] + if ((len(connections[pointStr]) > 2) or (pointStr in pivotPoints)): + line = points[iFrom:i+1] + lineKey = format % line[-1]+':'+format % line[-2]+':'+format % line[0] + if lineKey in simplifiedLines: + simpleLine = simplifiedLines[lineKey] + simpleLine = list(reversed(simpleLine)) + else: + simpleLine = shapely.geometry.LineString(line).simplify(tolerance).coords + lineKey = format % line[0]+':'+format % line[1]+':'+format % line[-1] + simplifiedLines[lineKey] = simpleLine + simpleCoords.extend( simpleLine[0:-1] ) + iFrom = i + if len(simpleCoords) <= 2: + return None + else: + return shapely.geometry.LineString(simpleCoords) + + +def simplifyPolygon(polygon): + simpleExtRing = simplifyRing(polygon.exterior) + if simpleExtRing is None: + return None + simpleIntRings = [] + for ring in polygon.interiors: + simpleIntRing = simplifyRing(ring) + if simpleIntRing is not None: + simpleIntRings.append(simpleIntRing) + return shapely.geometry.Polygon(simpleExtRing, simpleIntRings) + + +results = [] +for geom in geometries: + polygons = [] + simplePolygons = [] + + if isinstance(geom, shapely.geometry.Polygon): + polygons.append(geom) + else: + for polygon in geom: + polygons.append(polygon) + + for polygon in polygons: + simplePolygon = simplifyPolygon(polygon) + if not (simplePolygon is None or simplePolygon._geom is None): + simplePolygons.append(simplePolygon) + + if len(simplePolygons) > 0: + results.append(shapely.geometry.MultiPolygon(simplePolygons)) + else: + results.append(None) + + +# Process all features in input layer. +in_feat = in_layer.GetNextFeature() +counter = 0 +while in_feat is not None: + if results[counter] is not None: + out_feat = ogr.Feature( feature_def = shp_layer.GetLayerDefn() ) + out_feat.SetFrom( in_feat ) + out_feat.SetGeometryDirectly( + ogr.CreateGeometryFromWkb( + shapely.wkb.dumps( + results[counter] + ) + ) + ) + shp_layer.CreateFeature( out_feat ) + out_feat.Destroy() + else: + print 'geometry is too small: '+in_feat.GetField(16) + + in_feat.Destroy() + in_feat = in_layer.GetNextFeature() + counter += 1 + + +# Cleanup +shp_ds.Destroy() +in_ds.Destroy() + +print int(round(time.time() * 1000)) - start
\ No newline at end of file |