Example #1
0
def test_wrap_dateline():
    sinus_crs = geometry.CRS("""PROJCS["unnamed",
                           GEOGCS["Unknown datum based upon the custom spheroid",
                           DATUM["Not specified (based on custom spheroid)", SPHEROID["Custom spheroid",6371007.181,0]],
                           PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],
                           PROJECTION["Sinusoidal"],
                           PARAMETER["longitude_of_center",0],
                           PARAMETER["false_easting",0],
                           PARAMETER["false_northing",0],
                           UNIT["Meter",1]]""")
    albers_crs = geometry.CRS('EPSG:3577')
    geog_crs = geometry.CRS('EPSG:4326')

    wrap = geometry.polygon([(12231455.716333, -5559752.598333),
                             (12231455.716333, -4447802.078667),
                             (13343406.236, -4447802.078667),
                             (13343406.236, -5559752.598333),
                             (12231455.716333, -5559752.598333)],
                            crs=sinus_crs)
    wrapped = wrap.to_crs(geog_crs)
    assert wrapped.type == 'Polygon'
    wrapped = wrap.to_crs(geog_crs, wrapdateline=True)
    # assert wrapped.type == 'MultiPolygon' TODO: these cases are quite hard to implement.
    # hopefully GDAL's CutGeometryOnDateLineAndAddToMulti will be available through py API at some point

    wrap = geometry.polygon([(13343406.236, -5559752.598333),
                             (13343406.236, -4447802.078667),
                             (14455356.755667, -4447802.078667),
                             (14455356.755667, -5559752.598333),
                             (13343406.236, -5559752.598333)],
                            crs=sinus_crs)
    wrapped = wrap.to_crs(geog_crs)
    assert wrapped.type == 'Polygon'
    wrapped = wrap.to_crs(geog_crs, wrapdateline=True)
    # assert wrapped.type == 'MultiPolygon' TODO: same as above

    wrap = geometry.polygon([(14455356.755667, -5559752.598333),
                             (14455356.755667, -4447802.078667),
                             (15567307.275333, -4447802.078667),
                             (15567307.275333, -5559752.598333),
                             (14455356.755667, -5559752.598333)],
                            crs=sinus_crs)
    wrapped = wrap.to_crs(geog_crs)
    assert wrapped.type == 'Polygon'
    wrapped = wrap.to_crs(geog_crs, wrapdateline=True)
    # assert wrapped.type == 'MultiPolygon' TODO: same as above

    wrap = geometry.polygon([(3658653.1976781483, -4995675.379595791),
                             (4025493.916030875, -3947239.249752495),
                             (4912789.243100313, -4297237.125269571),
                             (4465089.861944263, -5313778.16975072),
                             (3658653.1976781483, -4995675.379595791)],
                            crs=albers_crs)
    wrapped = wrap.to_crs(geog_crs)
    assert wrapped.type == 'Polygon'
    assert wrapped.intersects(geometry.line([(0, -90), (0, 90)], crs=geog_crs))
    wrapped = wrap.to_crs(geog_crs, wrapdateline=True)
    assert wrapped.type == 'MultiPolygon'
    assert not wrapped.intersects(
        geometry.line([(0, -90), (0, 90)], crs=geog_crs))
Example #2
0
def test_common_crs():
    assert common_crs([]) is None
    assert common_crs([geometry.point(0, 0, epsg4326),
                       geometry.line([(0, 0), (1, 1)], epsg4326)]) is epsg4326

    with pytest.raises(CRSMismatchError):
        common_crs([geometry.point(0, 0, epsg4326),
                    geometry.line([(0, 0), (1, 1)], epsg3857)])
Example #3
0
def test_wrap_dateline_utm():
    poly = geometry.box(618300, -1876800, 849000, -1642500, 'EPSG:32660')

    wrapped = poly.to_crs(epsg4326)
    assert wrapped.type == 'Polygon'
    assert wrapped.intersects(geometry.line([(0, -90), (0, 90)], crs=epsg4326))
    wrapped = poly.to_crs(epsg4326, wrapdateline=True)
    assert wrapped.type == 'MultiPolygon'
    assert not wrapped.intersects(
        geometry.line([(0, -90), (0, 90)], crs=epsg4326))
Example #4
0
def test_geom_split():
    box = geometry.box(0, 0, 10, 30, epsg4326)
    line = geometry.line([(5, 0), (5, 30)], epsg4326)
    bb = list(box.split(line))
    assert len(bb) == 2
    assert box.contains(bb[0] | bb[1])
    assert (box ^ (bb[0] | bb[1])).is_empty

    with pytest.raises(CRSMismatchError):
        list(box.split(geometry.line([(5, 0), (5, 30)], epsg3857)))
Example #5
0
def test_wrap_dateline():
    albers_crs = epsg3577
    geog_crs = epsg4326

    wrap = geometry.polygon([(3658653.1976781483, -4995675.379595791),
                             (4025493.916030875, -3947239.249752495),
                             (4912789.243100313, -4297237.125269571),
                             (4465089.861944263, -5313778.16975072),
                             (3658653.1976781483, -4995675.379595791)], crs=albers_crs)
    wrapped = wrap.to_crs(geog_crs)
    assert wrapped.type == 'Polygon'
    assert wrapped.intersects(geometry.line([(0, -90), (0, 90)], crs=geog_crs))
    wrapped = wrap.to_crs(geog_crs, wrapdateline=True)
    assert wrapped.type == 'MultiPolygon'
    assert not wrapped.intersects(geometry.line([(0, -90), (0, 90)], crs=geog_crs))
Example #6
0
def test_multigeom():
    p1, p2 = (0, 0), (1, 2)
    p3, p4 = (3, 4), (5, 6)
    b1 = geometry.box(*p1, *p2, epsg4326)
    b2 = geometry.box(*p3, *p4, epsg4326)
    bb = multigeom([b1, b2])
    assert bb.type == 'MultiPolygon'
    assert bb.crs is b1.crs
    assert len(list(bb)) == 2

    g1 = geometry.line([p1, p2], None)
    g2 = geometry.line([p3, p4], None)
    gg = multigeom(iter([g1, g2, g1]))
    assert gg.type == 'MultiLineString'
    assert gg.crs is g1.crs
    assert len(list(gg)) == 3

    g1 = geometry.point(*p1, epsg3857)
    g2 = geometry.point(*p2, epsg3857)
    g3 = geometry.point(*p3, epsg3857)
    gg = multigeom(iter([g1, g2, g3]))
    assert gg.type == 'MultiPoint'
    assert gg.crs is g1.crs
    assert len(list(gg)) == 3
    assert list(gg)[0] == g1
    assert list(gg)[1] == g2
    assert list(gg)[2] == g3

    # can't mix types
    with pytest.raises(ValueError):
        multigeom([geometry.line([p1, p2], None), geometry.point(*p1, None)])

    # can't mix CRSs
    with pytest.raises(CRSMismatchError):
        multigeom([
            geometry.line([p1, p2], epsg4326),
            geometry.line([p3, p4], epsg3857)
        ])

    # only some types are supported on input
    with pytest.raises(ValueError):
        multigeom([gg])
Example #7
0
def test_wrap_dateline_sinusoidal(pts):
    sinus_crs = geometry.CRS("""PROJCS["unnamed",
                           GEOGCS["Unknown datum based upon the custom spheroid",
                           DATUM["Not specified (based on custom spheroid)", SPHEROID["Custom spheroid",6371007.181,0]],
                           PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],
                           PROJECTION["Sinusoidal"],
                           PARAMETER["longitude_of_center",0],
                           PARAMETER["false_easting",0],
                           PARAMETER["false_northing",0],
                           UNIT["Meter",1]]""")

    wrap = geometry.polygon(pts, crs=sinus_crs)
    wrapped = wrap.to_crs(epsg4326)
    assert wrapped.type == 'Polygon'
    wrapped = wrap.to_crs(epsg4326, wrapdateline=True)
    assert wrapped.type == 'MultiPolygon'
    assert not wrapped.intersects(geometry.line([(0, -90), (0, 90)], crs=epsg4326))
Example #8
0
def test_ops():
    box1 = geometry.box(10, 10, 30, 30, crs=epsg4326)
    box2 = geometry.box(20, 10, 40, 30, crs=epsg4326)
    box3 = geometry.box(20, 10, 40, 30, crs=epsg4326)
    box4 = geometry.box(40, 10, 60, 30, crs=epsg4326)
    no_box = None

    assert box1 != box2
    assert box2 == box3
    assert box3 != no_box

    union1 = box1.union(box2)
    assert union1.area == 600.0

    inter1 = box1.intersection(box2)
    assert bool(inter1)
    assert inter1.area == 200.0

    inter2 = box1.intersection(box4)
    assert not bool(inter2)
    assert inter2.is_empty
    # assert not inter2.is_valid  TODO: what's going on here?

    diff1 = box1.difference(box2)
    assert diff1.area == 200.0

    symdiff1 = box1.symmetric_difference(box2)
    assert symdiff1.area == 400.0

    # test segmented
    line = geometry.line([(0, 0), (0, 5), (10, 5)], epsg4326)
    line2 = line.segmented(2)
    assert line.crs is line2.crs
    assert line.length == line2.length
    assert len(line.coords) < len(line2.coords)

    # test interpolate
    pt = line.interpolate(1)
    assert pt.crs is line.crs
    assert pt.coords[0] == (0, 1)

    assert pt.interpolate(3) is None
Example #9
0
def vector_to_crs(point, vector, original_crs, destination_crs):
    """
    Transform a vector (in the tangent space of a particular point) to a new CRS

    Expects point and vector to each be a 2-tuple in the original CRS.
    Returns a pair of 2-tuples (transformed point and vector).
    Order of coordinates is specified by the CRS (or the OGR library).
    """
    # pylint: disable=zip-builtin-not-iterating
    # theoretically should use infinitesimal displacement
    # i.e. jacobian of the transformation
    # but here just use a finite displatement (for convenience of implementation)
    original_line = line([point, tuple(map(sum, zip(point, vector)))], crs=original_crs)
    transformed_line = original_line.to_crs(destination_crs)

    transformed_point, transformed_end = transformed_line.points

    # take difference (i.e. remove origin offset)
    transformed_vector = tuple(map(lambda x: x[1] - x[0], zip(*transformed_line.points)))
    return transformed_point, transformed_vector
Example #10
0
def line(params, fp=None):
    """Handles line-based algorithms e.g. ndvi_transect and dispatches
    the right function.
    :param Dictionary params: dictionary with xmin,xmax,ymin,ymax,type
    :param file object params: optional file object to save plots are other bulky files
    :return: raw HTTP response (json or image/*)

    NOTE: line can potentially be any multipoint LINESTRING but we
    start with xmin,xmax,ymin,ymax
    """
    from datacube.utils import geometry

    if not ('xmin' in params) or not ('xmax' in params) \
       or not ('ymin' in params) or not ('ymax' in params):
        return error("Line requires xmin,xmax,ymin,ymax")
    xmin = float(params["xmin"])
    xmax = float(params["xmax"])
    ymin = float(params["ymin"])
    ymax = float(params["ymax"])
    # NOTE: you can use a line with multiple points here
    line = geometry.line([(xmin, ymin), (xmax, ymax)], 'EPSG:4326')
    if (line.type != 'LineString'):
        return error("ndvi_transect: line not LINESTRING")

    query = {'geopolygon': line}
    if ('time_begin' in params) and ('time_end' in params):
        if (not isdate(params['time_begin'])) or (not isdate(
                params['time_end'])):
            return error("Invalid time specified")
        query['time'] = (params['time_begin'], params['time_end'])
    if params['type'] == 'ndvi_transect':
        if not fp:
            return error("ndvi_transet needs a pre-allocated file")
        return ndvi_transect(query, fp)
    else:
        return error("Supported line-processing types: ndvi_transect")
Example #11
0
def test_ops():
    box1 = geometry.box(10, 10, 30, 30, crs=epsg4326)
    box2 = geometry.box(20, 10, 40, 30, crs=epsg4326)
    box3 = geometry.box(20, 10, 40, 30, crs=epsg4326)
    box4 = geometry.box(40, 10, 60, 30, crs=epsg4326)
    no_box = None

    assert box1 != box2
    assert box2 == box3
    assert box3 != no_box

    union1 = box1.union(box2)
    assert union1.area == 600.0

    with pytest.raises(geometry.CRSMismatchError):
        box1.union(box2.to_crs(epsg3857))

    inter1 = box1.intersection(box2)
    assert bool(inter1)
    assert inter1.area == 200.0

    inter2 = box1.intersection(box4)
    assert not bool(inter2)
    assert inter2.is_empty
    # assert not inter2.is_valid  TODO: what's going on here?

    diff1 = box1.difference(box2)
    assert diff1.area == 200.0

    symdiff1 = box1.symmetric_difference(box2)
    assert symdiff1.area == 400.0

    # test segmented
    line = geometry.line([(0, 0), (0, 5), (10, 5)], epsg4326)
    line2 = line.segmented(2)
    assert line.crs is line2.crs
    assert line.length == line2.length
    assert len(line.coords) < len(line2.coords)
    poly = geometry.polygon([(0, 0), (0, 5), (10, 5)], epsg4326)
    poly2 = poly.segmented(2)
    assert poly.crs is poly2.crs
    assert poly.length == poly2.length
    assert poly.area == poly2.area
    assert len(poly.geom.exterior.coords) < len(poly2.geom.exterior.coords)

    poly2 = poly.exterior.segmented(2)
    assert poly.crs is poly2.crs
    assert poly.length == poly2.length
    assert len(poly.geom.exterior.coords) < len(poly2.geom.coords)

    # test interpolate
    pt = line.interpolate(1)
    assert pt.crs is line.crs
    assert pt.coords[0] == (0, 1)
    assert isinstance(pt.coords, list)

    with pytest.raises(TypeError):
        pt.interpolate(3)

    # test array interface
    assert line.__array_interface__ is not None
    assert np.array(line).shape == (3, 2)

    # test simplify
    poly = geometry.polygon([(0, 0), (0, 5), (10, 5)], epsg4326)
    assert poly.simplify(100) == poly

    # test iteration
    poly_2_parts = geometry.Geometry(
        {
            "type":
            "MultiPolygon",
            "coordinates": [[[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0],
                              [102.0, 3.0], [102.0, 2.0]]],
                            [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
                              [100.0, 1.0], [100.0, 0.0]],
                             [[100.2, 0.2], [100.8, 0.2], [100.8, 0.8],
                              [100.2, 0.8], [100.2, 0.2]]]]
        }, 'EPSG:4326')
    pp = list(poly_2_parts)
    assert len(pp) == 2
    assert all(p.crs == poly_2_parts.crs for p in pp)

    # test transform
    assert geometry.point(
        0, 0,
        epsg4326).transform(lambda x, y: (x + 1, y + 2)) == geometry.point(
            1, 2, epsg4326)

    # test sides
    box = geometry.box(1, 2, 11, 22, epsg4326)
    ll = list(geometry.sides(box))
    assert all(l.crs is epsg4326 for l in ll)
    assert len(ll) == 4
    assert ll[0] == geometry.line([(1, 2), (1, 22)], epsg4326)
    assert ll[1] == geometry.line([(1, 22), (11, 22)], epsg4326)
    assert ll[2] == geometry.line([(11, 22), (11, 2)], epsg4326)
    assert ll[3] == geometry.line([(11, 2), (1, 2)], epsg4326)
Example #12
0
    def to_crs(self, new_crs):
        grid = self.layer.grids[new_crs]
        skip_x_xform = False
        skip_y_xform = False
        if self.crs != new_crs:
            if not self.subsetted.x and not self.subsetted.y:
                # Neither axis subsetted
                self.min.x = self.layer.ranges["bboxes"][new_crs]["left"]
                self.max.x = self.layer.ranges["bboxes"][new_crs]["right"]
                self.min.y = self.layer.ranges["bboxes"][new_crs]["bottom"]
                self.max.y = self.layer.ranges["bboxes"][new_crs]["top"]
                self.crs = new_crs
            elif not self.subsetted.x or not self.subsetted.y:
                # One axis subsetted
                if self.subsetted.x:
                    self.min.y = self.layer.ranges["bboxes"][self.crs]["bottom"]
                    self.max.y = self.layer.ranges["bboxes"][self.crs]["top"]
                    skip_y_xform = True
                if self.subsetted.y:
                    self.min.x = self.layer.ranges["bboxes"][self.crs]["left"]
                    self.max.x = self.layer.ranges["bboxes"][self.crs]["right"]
                    skip_x_xform = True
            else:
                # Both axes subsetted
                pass

        if self.crs != new_crs:
            is_point = False
            # Prepare geometry for transformation
            old_crs_obj = self.cfg.crs(self.crs)
            if self.is_slice("x") and self.is_slice("y"):
                geom = geometry.point(self.min.x, self.min.y, old_crs_obj)
                is_point = True
            elif self.is_slice("x") or self.is_slice("y"):
                geom = geometry.line(
                    (
                        (self.min.x, self.min.y),
                        (self.max.x, self.max.y)
                    ), old_crs_obj)
            else:
                geom = geometry.polygon(
                    (
                        (self.min.x, self.min.y),
                        (self.min.x, self.max.y),
                        (self.max.x, self.max.y),
                        (self.max.x, self.min.y),
                        (self.min.x, self.min.y),
                    ),
                    old_crs_obj
                )
            new_crs_obj = self.cfg.crs(new_crs)
            grid = self.layer.grids[new_crs]
            if is_point:
                prj_pt = geom.to_crs(new_crs_obj)
                x, y = prj_pt.coords[0]
                self.min.set(x, y)
                self.max.set(x + grid["resolution"][0],
                             y + grid["resolution"][1])
                self.size.set(1, 1)
            else:
                proj_geom = geom.to_crs(new_crs_obj)
                bbox = proj_geom.boundingbox
                if skip_x_xform:
                    self.min.x = self.layer.ranges["bboxes"][new_crs]["left"]
                    self.max.x = self.layer.ranges["bboxes"][new_crs]["right"]
                else:
                    self.min.x = bbox.left
                    self.max.x = bbox.right
                if skip_y_xform:
                    self.min.y = self.layer.ranges["bboxes"][new_crs]["bottom"]
                    self.max.y = self.layer.ranges["bboxes"][new_crs]["top"]
                else:
                    self.min.y = bbox.bottom
                    self.max.y = bbox.top

                self.quantise_to_resolution(grid)
            self.crs = new_crs
        else:
            self.quantise_to_resolution(grid)