コード例 #1
0
ファイル: utils.py プロジェクト: JanBehrens/kartograph.py
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
コード例 #2
0
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
コード例 #3
0
ファイル: shplayer.py プロジェクト: geoiva/kartograph.py
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
コード例 #4
0
def shape2geometry(shp,
                   ignore_holes=False,
                   min_area=False,
                   bbox=False,
                   proj=None):
    if shp is None:
        return None
    if bbox and shp.shapeType != 1:
        if proj:
            left, top = proj(shp.bbox[0], shp.bbox[1], inverse=True)
            right, btm = proj(shp.bbox[2], shp.bbox[3], inverse=True)
        else:
            left, top, right, btm = shp.bbox
        sbbox = BBox(left=left, top=top, width=right - left, height=btm - top)
        if not bbox.intersects(sbbox):
            # ignore the shape if it's not within the bbox
            return None

    if shp.shapeType in (5, 15):  # multi-polygon
        geom = shape2polygon(shp,
                             ignore_holes=ignore_holes,
                             min_area=min_area,
                             proj=proj)
    elif shp.shapeType in (3, 13):  # line
        geom = shape2line(shp, proj=proj)
    elif shp.shapeType == 1:  # point
        geom = shape2point(shp, proj=proj)
    else:
        raise KartographError('unknown shape type (%d)' % shp.shapeType)
    return geom
コード例 #5
0
 def get_features(self, filter=None, bbox=None, ignore_holes=False, charset='utf-8', min_area=0):
     # Eventually we convert the bbox list into a proper BBox instance
     if bbox is not None and not isinstance(bbox, BBox):
         bbox = BBox(bbox[2] - bbox[0], bbox[3] - bbox[1], bbox[0], bbox[1])
     mode = self.mode
     if mode in ('line', 'polygon'):
         coords = []
     features = []
     for row in self.cr:
         attrs = dict()
         for i in range(len(row)):
             key = self.header[i]
             if key == self.xfield:
                 x = float(row[i])
             elif key == self.yfield:
                 y = float(row[i])
             else:
                 attrs[key] = row[i]
         if self.proj is not None:
             # inverse project coord
             x, y = self.proj(x, y, inverse=True)
         if mode == 'points':
             features.append(create_feature(Point(x, y), attrs))
         else:
             coords.append((x, y))
     if mode == 'line':
         features.append(create_feature(LineString(coords), dict()))
     elif mode == 'polygon':
         features.append(create_feature(Polygon(coords), dict()))
     return features
コード例 #6
0
ファイル: shplayer.py プロジェクト: geoiva/kartograph.py
    def get_features(self, attr=None, filter=None, bbox=None, ignore_holes=False, min_area=False, charset='utf-8'):
        """
        ### Get features
        """
        res = []
        # We will try these encodings..
        known_encodings = ['utf-8', 'latin-1', 'iso-8859-2', 'iso-8859-15']
        try_encodings = [charset]
        for enc in known_encodings:
            if enc != charset:
                try_encodings.append(enc)
        # Eventually we convert the bbox list into a proper BBox instance
        if bbox is not None and not isinstance(bbox, BBox):
            bbox = BBox(bbox[2] - bbox[0], bbox[3] - bbox[1], bbox[0], bbox[1])
        ignored = 0
        for i in range(0, len(self.recs)):
            # Read all record attributes
            drec = {}
            for j in range(len(self.attributes)):
                drec[self.attributes[j]] = self.recs[i][j]
            # For each record that is not filtered..
            if filter is None or filter(drec):
                props = {}
                # ..we try to decode the attributes (shapefile charsets are arbitrary)
                for j in range(len(self.attributes)):
                    val = self.recs[i][j]
                    decoded = False
                    if isinstance(val, str):
                        for enc in try_encodings:
                            try:
                                val = val.decode(enc)
                                decoded = True
                                break
                            except:
                                if verbose:
                                    print 'warning: could not decode "%s" to %s' % (val, enc)
                        if not decoded:
                            raise KartographError('having problems to decode the input data "%s"' % val)
                    if isinstance(val, (str, unicode)):
                        val = val.strip()
                    props[self.attributes[j]] = val

                # Read the shape from the shapefile (can take some time..)..
                shp = self.get_shape(i)

                # ..and convert the raw shape into a shapely.geometry
                geom = shape2geometry(shp, ignore_holes=ignore_holes, min_area=min_area, bbox=bbox, proj=self.proj)
                if geom is None:
                    ignored += 1
                    self.forget_shape(i)
                    continue

                # Finally we construct the map feature and append it to the
                # result list
                feature = create_feature(geom, props)
                res.append(feature)
        if bbox is not None and ignored > 0 and verbose:
            print "-ignoring %d shapes (not in bounds %s )" % (ignored, bbox)
        return res
コード例 #7
0
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
コード例 #8
0
ファイル: shplayer.py プロジェクト: nosamanuel/kartograph.py
    def get_features(self, attr=None, filter=None, bbox=None, verbose=False):
        """
        returns a list of features matching to the attr -> value pair
        """
        from kartograph.geometry import Feature, BBox
        res = []
        if bbox is not None:
            bbox = BBox(bbox[2] - bbox[0], bbox[3] - bbox[1], bbox[0], bbox[1])
            ignored = 0
        for i in range(0, len(self.recs)):
            drec = {}
            for j in range(len(self.attributes)):
                drec[self.attributes[j]] = self.recs[i][j]
            if filter is None or filter(drec):
                props = {}
                for j in range(len(self.attributes)):
                    val = self.recs[i][j]
                    if isinstance(val, (str, unicode)):
                        val = val.strip()
                    props[self.attributes[j]] = val

                shp = self.get_shape(i)

                if shp.shapeType in (5, 15):  # multi-polygon
                    geom = points2polygon(shp)
                elif shp.shapeType == 3:  # line
                    geom = points2line(shp)
                else:
                    raise KartographError(
                        'unknown shape type (%d) in shapefile %s' %
                        (shp.shapeType, self.shpSrc))

                if bbox is not None and not bbox.intersects(geom.bbox()):
                    ignored += 1
                    continue  # ignore if not within bounds

                feature = Feature(geom, props)
                res.append(feature)
        if bbox is not None and ignored > 0 and verbose:
            print "[%s] ignored %d shapes (not in bounds)" % (basename(
                self.shpSrc), ignored)
        return res
コード例 #9
0
ファイル: shplayer.py プロジェクト: neapel/kartograph.py
    def get_features(self, attr=None, filter=None, bbox=None, verbose=False):
        """
        returns a list of features matching to the attr -> value pair
        """
        from kartograph.geometry import Feature, BBox

        res = []
        if bbox is not None:
            bbox = BBox(bbox[2] - bbox[0], bbox[3] - bbox[1], bbox[0], bbox[1])
            ignored = 0
        for i in range(0, len(self.recs)):
            drec = {}
            for j in range(len(self.attributes)):
                drec[self.attributes[j]] = self.recs[i][j]
            if filter is None or filter(drec):
                props = {}
                for j in range(len(self.attributes)):
                    val = self.recs[i][j]
                    if isinstance(val, (str, unicode)):
                        val = val.strip()
                    props[self.attributes[j]] = val

                shp = self.get_shape(i)

                if shp.shapeType in (5, 15):  # multi-polygon
                    geom = points2polygon(shp)
                elif shp.shapeType == 3:  # line
                    geom = points2line(shp)
                else:
                    raise KartographError("unknown shape type (%d) in shapefile %s" % (shp.shapeType, self.shpSrc))

                if bbox is not None and not bbox.intersects(geom.bbox()):
                    ignored += 1
                    continue  # ignore if not within bounds

                feature = Feature(geom, props)
                res.append(feature)
        if bbox is not None and ignored > 0 and verbose:
            print "[%s] ignored %d shapes (not in bounds)" % (basename(self.shpSrc), ignored)
        return res
コード例 #10
0
ファイル: __init__.py プロジェクト: nosamanuel/kartograph.py
        return (x, y)


for pjname in projections:
    projections[pjname].name = pjname

if __name__ == '__main__':
    import sys
    # some class testing
    #p = LAEA(52.0,10.0)
    #x,y = p.project(50,5)
    #assert (round(x,2),round(y,2)) == (3962799.45, -2999718.85), 'LAEA proj error'
    from kartograph.geometry import BBox

    print Proj.fromXML(Robinson(lat0=3, lon0=4).toXML(), projections)

    Robinson(lat0=3, lon0=4)

    for pj in projections:
        Proj = projections[pj]
        bbox = BBox()
        try:
            proj = Proj(lon0=60)
            print proj.project(0, 0)
            print proj.world_bounds(bbox)
            print proj.toXML()
        except:
            print 'Error', pj
            print sys.exc_info()[0]
            raise
コード例 #11
0
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
コード例 #12
0
    def get_features(self,
                     attr=None,
                     filter=None,
                     bbox=None,
                     ignore_holes=False,
                     min_area=False,
                     charset='utf-8',
                     bounding=False,
                     bounding_geom=None,
                     contained_geom=None):
        """
        ### Get features
        """
        res = []

        max_intersect = 0
        #if contained_geom is None:
        #    print '\t\tcontained_geom is None'
        #if bounding_geom is None:
        #    print '\t\tbounding_geom is None'
        # We will try these encodings..
        known_encodings = ['utf-8', 'latin-1', 'iso-8859-2', 'iso-8859-15']
        try_encodings = [charset]
        for enc in known_encodings:
            if enc != charset:
                try_encodings.append(enc)
        # Eventually we convert the bbox list into a proper BBox instance
        if bbox is not None and not isinstance(bbox, BBox):
            bbox = BBox(bbox[2] - bbox[0], bbox[3] - bbox[1], bbox[0], bbox[1])
        ignored = 0
        #print 'len(self.recs)={0}'.format(len(self.recs))
        for i in range(0, len(self.recs)):
            # Read all record attributes
            drec = {}
            for j in range(len(self.attributes)):
                drec[self.attributes[j]] = self.recs[i][j]
            # For each record that is not filtered..
            is_nameless = True
            the_feat_name = ''
            #            print drec
            if 'NAME' in drec:
                the_feat_name = drec['NAME']
            elif 'FULLNAME' in drec:
                the_feat_name = drec['FULLNAME']
            if len(the_feat_name.strip()) > 0:
                is_nameless = False
            desired_geom = False
            drec['DESIRED_GEOM'] = False

            if bounding_geom is not None:
                # Check if we want it to intersect
                shp = self.get_shape(i)
                shp.bounding = bounding
                shp.the_feat_name = the_feat_name
                geom = self.get_geom(i,
                                     ignore_holes=ignore_holes,
                                     min_area=min_area,
                                     bbox=bbox,
                                     proj=self.proj)
                #(shape2geometry(shp, ignore_holes=ignore_holes, min_area=min_area, bbox=bbox, proj=self.proj)
                if geom is None:
                    ignored += 1
                    continue
                intersect_geom = bounding_geom.intersection(geom)
                # if intersect_geom.area>0:
                #     print 'intersect_geom.area={0}'.format(intersect_geom.area)
                if intersect_geom.area >= self.intersect_tol * geom.area:
                    desired_geom = True
                # print 'Found intersecting feature {0}'.format(the_feat_name)
            # Check for sufficient intersection to add places automatically
                drec['DESIRED_GEOM'] = desired_geom
            if filter is None or filter(drec):
                #if contained_geom is not None:
                #   print '\tIn for the_feat_name {0}'.format(drec['NAME'])
                props = {}
                # ..we try to decode the attributes (shapefile charsets are arbitrary)
                for j in range(len(self.attributes)):
                    val = self.recs[i][j]
                    decoded = False
                    if isinstance(val, str):
                        for enc in try_encodings:
                            try:
                                val = val.decode(enc)
                                decoded = True
                                break
                            except:
                                if verbose:
                                    print 'warning: could not decode "%s" to %s' % (
                                        val, enc)
                        if not decoded:
                            raise KartographError(
                                'having problems to decode the input data "%s"'
                                % val)
                    if isinstance(val, (str, unicode)):
                        val = val.strip()
                    props[self.attributes[j]] = val

                if bounding_geom is not None:
                    #                    print 'type(bounding_geom)={0}'.format(type(bounding_geom))
                    x = bounding_geom.intersection(geom)
                    if x.area < self.intersect_tol * geom.area:
                        #print 'Name: {0} does not intersect'.format(shp.the_feat_name)
                        ignored += 1
                        self.forget_shape(i)
                        continue
                    else:
                        ignored += 0
#                        print 'Name: {0} intersects'.format(shp.the_feat_name)
                else:
                    # If we didn't already set the shape and geom above, we set it here instead
                    shp = self.get_shape(i)
                    shp.bounding = bounding
                    shp.the_feat_name = the_feat_name
                    # ..and convert the raw shape into a shapely.geometry
                    geom = self.get_geom(i,
                                         ignore_holes=ignore_holes,
                                         min_area=min_area,
                                         bbox=bbox,
                                         proj=self.proj)
                    #shape2geometry(shp, ignore_holes=ignore_holes, min_area=min_area, bbox=bbox, proj=self.proj)
                    if geom is None:
                        ignored += 1
                        continue

                if contained_geom is not None:
                    # Add a circle if no good at the end after we get all the good features
                    #print 'Checking county {0}'.format(drec['NAME'])
                    # Find if it's the most intersecting of the geometries with
                    # contained_geom (which should really be contained_geom but haven't
                    # changed yet)
                    curr_intersect = contained_geom.intersection(geom)
                    if curr_intersect.area == 0:
                        # print '\tfail: curr_intersect.area={0}'.format(curr_intersect.area)
                        ignored += 1
                        self.forget_shape(i)
                        #continue
                    else:
                        # Set this to be the new intersection level
                        #print '\tNew largest area intersection, area={0}'.format(curr_intersect.area)
                        max_intersect = curr_intersect.area
                        feature = create_feature(geom, props)

                        res.append(feature)
                        #continue
                else:
                    #print 'Constructing feature {0}'.format(drec['NAME'])
                    feature = create_feature(geom, props)
                    self.feature = feature
                    res.append(feature)
        if bbox is not None and ignored > 0 and verbose:
            print "-ignoring %d shapes (not in bounds %s )" % (ignored, bbox)
        #self.proj=None
#        print 'res={0}'.format(res)

# Add a feature consisting of a circle around the contained_geom if it's too small
# if contained_geom is not None and bounding_geom is None:
#     highlight_circ=self.get_highlight_circle(res, contained_geom)
#     if highlight_circ is not None:
#         #print('\tAdding a highlight_circ')
#         # Create and append feature
#         curr_props={'STATEFP':'00', 'COUNTYFP': '000', 'NAME': 'HighlightThePlace'}
#         feature=create_feature(highlight_circ, curr_props)
#         res.append(feature)
        return res