def geom_to_bbox(geom, min_area=0): from kartograph.geometry import BBox from shapely.geometry import MultiPolygon if True or min_area == 0 or not isinstance(geom, MultiPolygon): # if no minimum area ratio is set or the geometry # is not a multipart geometry, we simply use the # full bbox minx, miny, maxx, maxy = geom.bounds return BBox(width=maxx - minx, height=maxy - miny, left=minx, top=miny) else: # for multipart geometry we use only the bbox of # the 'biggest' sub-geometries, depending on min_area bbox = BBox() areas = [] bb = [] for polygon in geom.geoms: areas.append(polygon.area) max_a = max(areas) for i in range(len(geom.geoms)): a = areas[i] if a < max_a * min_area: # ignore this sub polygon since it is too small continue bb.append(geom.geoms[i].bounds) for b in bb: bbox.update((b[0], b[2])) bbox.update((b[1], b[2])) bbox.update((b[0], b[3])) bbox.update((b[1], b[3])) return bbox
def shape2polygon(shp, ignore_holes=False, min_area=False, proj=None): """ converts a shapefile polygon to geometry.MultiPolygon """ # from kartograph.geometry import MultiPolygon from shapely.geometry import Polygon, MultiPolygon from kartograph.geometry.utils import is_clockwise parts = shp.parts[:] parts.append(len(shp.points)) exteriors = [] holes = [] for j in range(len(parts) - 1): pts = shp.points[parts[j]:parts[j + 1]] if shp.shapeType == 15: # remove z-coordinate from PolygonZ contours (not supported) for k in range(len(pts)): pts[k] = pts[k][:2] if proj: project_coords(pts, proj) cw = is_clockwise(pts) if cw: exteriors.append(pts) else: holes.append(pts) if ignore_holes: holes = None if len(exteriors) == 1: poly = Polygon(exteriors[0], holes) elif len(exteriors) > 1: # use multipolygon, but we need to assign the holes to the right # exteriors from kartograph.geometry import BBox used_holes = set() polygons = [] for ext in exteriors: bbox = BBox() my_holes = [] for pt in ext: bbox.update(pt) for h in range(len(holes)): if h not in used_holes: hole = holes[h] if bbox.check_point(hole[0]): # this is a very weak test but it should be sufficient used_holes.add(h) my_holes.append(hole) polygons.append(Polygon(ext, my_holes)) if min_area: # compute maximum area max_area = 0 for poly in polygons: max_area = max(max_area, poly.area) # filter out polygons that are below min_area * max_area polygons = [poly for poly in polygons if poly.area >= min_area * max_area] poly = MultiPolygon(polygons) else: raise KartographError('shapefile import failed - no outer polygon found') return poly
def shape2polygon(shp, ignore_holes=False, min_area=False, proj=None): """ converts a shapefile polygon to geometry.MultiPolygon """ # ignore_holes=True # from kartograph.geometry import MultiPolygon from shapely.geometry import Polygon, MultiPolygon from kartograph.geometry.utils import is_clockwise parts = shp.parts[:] parts.append(len(shp.points)) exteriors = [] rep_point = None holes = [] # print 'shp.the_feat_name={0}'.format(shp.the_feat_name) # print 'shp.represenative_points={0}'.format(shp.representative_point()) for j in range(len(parts) - 1): pts = shp.points[parts[j]:parts[j + 1]] if shp.shapeType == 15: # remove z-coordinate from PolygonZ contours (not supported) for k in range(len(pts)): pts[k] = pts[k][:2] if proj and shp.alreadyProj is False: project_coords(pts, proj, rep_point=rep_point) if shp.bounding: # print 'Already proj, proj exists' shp.alreadyProj = True elif shp.alreadyProj is False: if shp.bounding: shp.alreadyProj = True #else: # print 'shp.bounding={0}'.format(shp.bounding) # print 'Already proj, no proj exists' cw = is_clockwise(pts) if cw: exteriors.append(pts) else: holes.append(pts) if ignore_holes: print 'ignoring holes' holes = None # if len(holes) > 0: # print '\tThere are {0} holes'.format(len(holes)) if len(exteriors) == 1: # print 'Single polygon, {0}'.format(shp.the_feat_name) poly = Polygon(exteriors[0], holes) elif len(exteriors) > 1: # print 'Multipolygon, {0}'.format(shp.the_feat_name) # use multipolygon, but we need to assign the holes to the right # exteriors from kartograph.geometry import BBox used_holes = set() polygons = [] for ext in exteriors: bbox = BBox() my_holes = [] for pt in ext: bbox.update(pt) for h in range(len(holes)): if h not in used_holes: hole = holes[h] if bbox.check_point(hole[0]): # this is a very weak test but it should be sufficient used_holes.add(h) my_holes.append(hole) polygons.append(Polygon(ext, my_holes)) if min_area: # compute maximum area max_area = 0 for poly in polygons: max_area = max(max_area, poly.area) # filter out polygons that are below min_area * max_area polygons = [ poly for poly in polygons if poly.area >= min_area * max_area ] poly = MultiPolygon(polygons) else: # return None raise KartographError( 'shapefile import failed - no outer polygon found') # print 'poly={0}'.format(poly) return poly