Exemple #1
0
def geometry(obj, tp_arcs, transform=None):
    """
    Converts a topology object to a geometry object.
    
    The topology object is a dict with 'type' and 'arcs' items, such as
    -- {'type': "LineString", 'arcs': [0, 1, 2]}
    """
    if obj["type"] == "GeometryCollection":
        geometries = [geometry(feat, tp_arcs) for feat in obj["geometries"]]
        return {"type": obj["type"], "geometries": geometries}

    if obj["type"] == "MultiPoint":
        scale = transform["scale"]
        translate = transform["translate"]
        coords = obj["coordinates"]
        point_coords = dequantize(np.array(coords), scale, translate).tolist()
        return {"type": obj["type"], "coordinates": point_coords}

    if obj["type"] == "Point":
        scale = transform["scale"]
        translate = transform["translate"]
        coords = [obj["coordinates"]]

        point_coord = dequantize(np.array(coords), scale, translate).tolist()
        return {"type": obj["type"], "coordinates": point_coord[0]}

    else:
        return {"type": obj["type"], "coordinates": coordinates(obj["arcs"], tp_arcs)}
def get_gridcell_geometry():
    """
    Calculates the grid cell area and dimensions.

    The length expressions are derived from the haversine formula:
        hav(d/r)= hav(lat2-lat1) + cos(lat1) * cos(lat2) * hav(lon2-lon1)
    See: http://math.stackexchange.com/a/479459

    The expression for the area comes from:  http://gis.stackexchange.com/a/29743
    See also: https://badc.nerc.ac.uk/help/coordinates/cell-surf-area.html
    """
    # FIXME: these 3 lines should be a get_lat_lon() function
    latnrs, lonnrs = get_latnrs_lonnrs()
    with netCDF4.MFDataset("%s/*.sp.nc" %
                           wam2layers_config.data_dir) as dataset:
        latitude = dataset.variables['latitude'][latnrs]

    geometry = collections.namedtuple(
        'geometry', ['area', 'top_length', 'bottom_length', 'side_length'])

    grid_size = np.abs(latitude[0] - latitude[1])

    tops = np.radians(np.minimum(latitude + 0.5 * grid_size, +90))
    bottoms = np.radians(np.maximum(latitude - 0.5 * grid_size, -90))

    grid_size = np.radians(grid_size)

    # define the haversine and inverse haversine functions:
    hav = lambda x: np.sin(x / 2)**2
    inv_hav = lambda x: 2 * np.arcsin(np.sqrt(x))

    # For the "side" length, lon2 = lon1, then: hav(lon2-lon1) = 0, and the
    # haversine formula becomes: hav(d/r) = hav(lat2-lat1)
    # i.e.: d = r * (lat2-lat1)
    side_length = AUTHALIC_EARTH_RADIUS * grid_size

    # For the top and bottom lengths, lat2 = lat1, then:
    #    hav(lat2-lat1) = 0
    #    cos(lat1)*cos(lat2) = cos(lat1)**2
    # and the haversine formula becomes: hav(d/r) = cos(lat1)**2 * hav(lon2-lon1)
    # i.e.: d = r * inv_hav(cos(lat1)**2 * hav(lon2-lon1))
    top_length = AUTHALIC_EARTH_RADIUS * inv_hav(
        np.cos(tops)**2 * hav(grid_size))
    bottom_length = AUTHALIC_EARTH_RADIUS * inv_hav(
        np.cos(bottoms)**2 * hav(grid_size))

    area = (AUTHALIC_EARTH_RADIUS**2 * grid_size *
            np.abs(np.sin(tops) - np.sin(bottoms)))

    return geometry(area[np.newaxis, :, np.newaxis], top_length[np.newaxis, :,
                                                                np.newaxis],
                    bottom_length[np.newaxis, :, np.newaxis], side_length)
Exemple #3
0
def serialize_as_geojson(
    topo_object,
    fp=None,
    pretty=False,
    indent=4,
    maxlinelength=88,
    validate=False,
    objectname="data",
):
    from shapely.geometry import asShape

    # prepare arcs from topology object
    arcs = topo_object["arcs"]
    transform = None
    if "transform" in topo_object.keys():
        transform = topo_object["transform"]
        scale = transform["scale"]
        translate = transform["translate"]

    if arcs:
        np_arcs = np_array_from_arcs(arcs)
        # dequantize if quantization is applied
        np_arcs = dequantize(np_arcs, scale, translate)
    else:
        np_arcs = None

    # select object member from topology object
    features = topo_object["objects"][objectname]["geometries"]

    # prepare geojson featurecollection
    fc = {"type": "FeatureCollection", "features": []}

    # fill the featurecollection with geometry object members
    for index, feature in enumerate(features):
        f = {"id": index, "type": "Feature"}
        if "properties" in feature.keys():
            f["properties"] = feature["properties"].copy()

        # the transform is only used in cases of points or multipoints
        geommap = geometry(feature, np_arcs, transform)
        if validate:
            geom = asShape(geommap).buffer(0)
            assert geom.is_valid
            f["geometry"] = geom.__geo_interface__
        else:
            f["geometry"] = geommap

        fc["features"].append(f)
    return fc