示例#1
0
    def generate_full_geocode_set(cls, nominatim_host, verbose=False):
        from shapely.geometry import shape as Shape, mapping as Mapping
        from shapely.ops import cascaded_union

        country = cls.regenerate_country_geocode(nominatim_host, verbose)
        country = {
            code: {
                'geojson': Mapping(Shape(geo['geojson']).simplify(0.005)),
                'display_name': geo['display_name'],
                'namedetails': geo.get('namedetails', {})
            }
            for code, geo in country.iteritems()
            if geo.get('geojson') and geo.get('display_name')
        }
        with open('cgeo.json', 'wb') as out:
            dump(country, out)
        if exists('cgeo.json.xz'):
            if isfile('cgeo.json.xz'):
                remove('cgeo.json.xz')
            else:
                raise TypeError("cgeo.json.xz exists and is not a file!")
        Command('xz')('-z9', 'cgeo.json')

        regions = cls.regenerate_region_geocode(nominatim_host, verbose)
        regions = {
            ccode: {
                rcode: {
                    'geojson': Mapping(Shape(geo['geojson']).simplify(0.01)),
                    'display_name': geo['display_name'],
                    'namedetails': geo.get('namedetails', {})
                }
                for rcode, geo in region.iteritems()
                if geo.get('geojson') and geo.get('display_name')
            }
            for ccode, region in regions.iteritems()
        }
        with open('rgeo.json', 'wb') as out:
            dump(regions, out)
        if exists('rgeo.json.xz'):
            if isfile('rgeo.json.xz'):
                remove('rgeo.json.xz')
            else:
                raise TypeError("rgeo.json.xz exists and is not a file!")
        Command('xz')('-z9', 'rgeo.json')

        phones = cls.regenerate_phone_geocode(nominatim_host, verbose)
        phones = {
            ccode: {
                acode: cascaded_union(map(Shape, phones[ccode][acode])
                                      ).centroid.coords[0][::-1]
                for acode in phones[ccode]
            }
            for ccode in phones
        }
        with open('pgeo.json', 'wb') as out:
            dump(phones, out)
        if exists('pgeo.json.xz'):
            if isfile('pgeo.json.xz'):
                remove('pgeo.json.xz')
            else:
                raise TypeError("pgeo.json.xz exists and is not a file!")
        Command('xz')('-z9', 'pgeo.json')
示例#2
0
    # Filter for the selected region.
    plzs = {
        plz
        for plz, bundesland in mapping_plz_bundesland.items()
        if bundesland == configuration.RESTRICT_REGION
    }

    # Only keep the geometries for the selected region.
    # Afterwards cache the shape data to avoid repeated conversions.
    geometries = shp.shapeRecords()
    geometries_filtered = [
        geometry for geometry in geometries if geometry.record[0] in plzs
    ]
    for geometry in geometries_filtered:
        setattr(geometry, "boundary", Shape(geometry.shape))

    def is_in_region(lat, lon):
        point = Point(lon, lat)
        for geometry in geometries_filtered:
            if point.within(geometry.boundary):
                return True
        return False

else:
    # No restrictions requested, so provide a dummy implementation.

    def is_in_region(lat, lon):
        return True

示例#3
0
def init():
    global is_done_loading
    def _admin_cc(filename):
        parts = path.basename(filename).split('.', 1)[0].split('-')
        admin, cc = parts if len(parts) == 2 else (parts[0], None)
        admin = int(admin[-1])
        return admin, cc

    nearest_points = {0: [], 1: [], 2: []}
    shapes = {0: [], 1: [], 2: []}
    cc_shapes = {}
    id_regions = {}
    us_states = {}

    files = glob(path.join(GEOJSON_DIR, 'admin*.json'))
    if not files:
        is_done_loading = RuntimeError(
            'Missing GeoJSON files. '
            'In development environments, merge in the "json"'
            'branch. See CONTRIBUTING.md')
        raise is_done_loading

    log.debug('Loading GeoJSON data ...')
    for filename in files:
        admin, cc = _admin_cc(filename)

        with open(filename, encoding='utf-8') as f:
            collection = json.load(f, encoding='utf-8')

        for feature in collection['features']:
            p = feature['properties']
            shape = Shape(feature['geometry'])
            tup = (shape, p)

            # Add representative lat-lon pair if non-existent
            if (np.isnan(p.get('latitude', np.nan)) or
                np.isnan(p.get('longitude', np.nan))):
                try:
                    r = shape.representative_point()
                except ValueError:
                    # For GBR, representative point above fails with:
                    #   ValueError: No Shapely geometry can be created from null value
                    r = shape.centroid
                    if not r.within(shape):
                        max_poly = max([shape] if isinstance(shape, Polygon) else list(shape),
                                       key=lambda polygon: polygon.area)
                        # From https://stackoverflow.com/questions/33311616/find-coordinate-of-closest-point-on-polygon-shapely/33324058#33324058
                        poly_ext = max_poly.exterior
                        dist = poly_ext.project(r)
                        pt = poly_ext.interpolate(dist)
                        r = Point(pt.coords[0])
                assert r.within(shape)
                p.update(latitude=r.y, longitude=r.x)

            # Get representative points for the k-d tree
            points = []
            polygons = (shape,) if isinstance(shape, Polygon) else shape
            for poly in polygons:
                points.append([poly.centroid.y, poly.centroid.x])
                if poly.area > 10:
                    points.extend(xy[::-1]
                                  for xy in poly.simplify(1).exterior.coords)

            nearest_points[admin].extend(points)
            tups = [tup] * len(points)
            shapes[admin].extend(tups)
            id_regions[p['_id']] = tup

            if admin == 0:
                cc_shapes[p['adm0_a3']] = tup

            # Make Admin1 shapes available in Admin2 too. Except for USA
            # which is the country we have explicit Admin2 shapes for
            if admin == 1 and cc not in ADMIN2_COUNTRIES:
                shapes[2].extend(tups)
                nearest_points[2].extend(points)

            if admin == 1 and cc == 'USA':
                us_states[p['hasc'].split('.')[1]] = tup

    kdtree = {admin: KDTree(np.array(centroids))
              for admin, centroids in nearest_points.items()}
    cc_shapes['NUL'] = (None, NUL)  # tuple for Null Island

    assert all(len(nearest_points[admin]) == len(shapes[admin])
               for admin in shapes)

    global SHAPES, CC_SHAPES, KDTREE, ID_REGIONS, US_STATES
    SHAPES, CC_SHAPES, KDTREE, ID_REGIONS, US_STATES = shapes, cc_shapes, kdtree, id_regions, us_states
    is_done_loading = True
    return
示例#4
0
文件: shapes.py 项目: CAN-Group/can
def is_point_within_shape(x: float, y: float, geometry):
    point = Point(x, y)
    shape = Shape(geometry)
    return shape.contains(point)