| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 | 
							- 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
 
 
  |