Search in sources :

Example 16 with OGCGeometry

use of com.esri.core.geometry.ogc.OGCGeometry in project presto by prestodb.

the class GeoFunctions method stDistance.

@SqlNullable
@Description("Returns the 2-dimensional cartesian minimum distance (based on spatial ref) between two geometries in projected units")
@ScalarFunction("ST_Distance")
@SqlType(DOUBLE)
public static Double stDistance(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlType(GEOMETRY_TYPE_NAME) Slice right) {
    OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left);
    OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right);
    verifySameSpatialReference(leftGeometry, rightGeometry);
    return leftGeometry.isEmpty() || rightGeometry.isEmpty() ? null : leftGeometry.distance(rightGeometry);
}
Also used : OGCGeometry(com.esri.core.geometry.ogc.OGCGeometry) SqlNullable(com.facebook.presto.spi.function.SqlNullable) ScalarFunction(com.facebook.presto.spi.function.ScalarFunction) Description(com.facebook.presto.spi.function.Description) SqlType(com.facebook.presto.spi.function.SqlType)

Example 17 with OGCGeometry

use of com.esri.core.geometry.ogc.OGCGeometry in project presto by prestodb.

the class SphericalGeoFunctions method stSphericalCentroid.

@SqlNullable
@Description("Returns the Point value that is the mathematical centroid of a Spherical Geography")
@ScalarFunction("ST_Centroid")
@SqlType(SPHERICAL_GEOGRAPHY_TYPE_NAME)
public static Slice stSphericalCentroid(@SqlType(SPHERICAL_GEOGRAPHY_TYPE_NAME) Slice input) {
    OGCGeometry geometry = EsriGeometrySerde.deserialize(input);
    if (geometry.isEmpty()) {
        return null;
    }
    // TODO: add support for other types e.g. POLYGON
    validateSphericalType("ST_Centroid", geometry, EnumSet.of(POINT, MULTI_POINT));
    if (geometry instanceof OGCPoint) {
        return input;
    }
    OGCGeometryCollection geometryCollection = (OGCGeometryCollection) geometry;
    for (int i = 0; i < geometryCollection.numGeometries(); i++) {
        OGCGeometry g = geometryCollection.geometryN(i);
        validateSphericalType("ST_Centroid", g, EnumSet.of(POINT));
        Point p = (Point) g.getEsriGeometry();
        checkLongitude(p.getX());
        checkLatitude(p.getY());
    }
    Point centroid;
    if (geometryCollection.numGeometries() == 1) {
        centroid = (Point) geometryCollection.geometryN(0).getEsriGeometry();
    } else {
        double x3DTotal = 0;
        double y3DTotal = 0;
        double z3DTotal = 0;
        for (int i = 0; i < geometryCollection.numGeometries(); i++) {
            CartesianPoint cp = new CartesianPoint((Point) geometryCollection.geometryN(i).getEsriGeometry());
            x3DTotal += cp.getX();
            y3DTotal += cp.getY();
            z3DTotal += cp.getZ();
        }
        double centroidVectorLength = Math.sqrt(x3DTotal * x3DTotal + y3DTotal * y3DTotal + z3DTotal * z3DTotal);
        if (centroidVectorLength == 0.0) {
            throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("Unexpected error. Average vector length adds to zero (%f, %f, %f)", x3DTotal, y3DTotal, z3DTotal));
        }
        centroid = new CartesianPoint(x3DTotal / centroidVectorLength, y3DTotal / centroidVectorLength, z3DTotal / centroidVectorLength).asSphericalPoint();
    }
    return EsriGeometrySerde.serialize(new OGCPoint(centroid, geometryCollection.getEsriSpatialReference()));
}
Also used : OGCGeometry(com.esri.core.geometry.ogc.OGCGeometry) OGCPoint(com.esri.core.geometry.ogc.OGCPoint) OGCGeometryCollection(com.esri.core.geometry.ogc.OGCGeometryCollection) CartesianPoint(com.facebook.presto.geospatial.SphericalGeographyUtils.CartesianPoint) PrestoException(com.facebook.presto.spi.PrestoException) CartesianPoint(com.facebook.presto.geospatial.SphericalGeographyUtils.CartesianPoint) OGCPoint(com.esri.core.geometry.ogc.OGCPoint) Point(com.esri.core.geometry.Point) CartesianPoint(com.facebook.presto.geospatial.SphericalGeographyUtils.CartesianPoint) OGCPoint(com.esri.core.geometry.ogc.OGCPoint) Point(com.esri.core.geometry.Point) SqlNullable(com.facebook.presto.spi.function.SqlNullable) ScalarFunction(com.facebook.presto.spi.function.ScalarFunction) Description(com.facebook.presto.spi.function.Description) SqlType(com.facebook.presto.spi.function.SqlType)

Example 18 with OGCGeometry

use of com.esri.core.geometry.ogc.OGCGeometry in project presto by prestodb.

the class SphericalGeoFunctions method stSphericalArea.

@SqlNullable
@Description("Returns the area of a geometry on the Earth's surface using spherical model")
@ScalarFunction("ST_Area")
@SqlType(DOUBLE)
public static Double stSphericalArea(@SqlType(SPHERICAL_GEOGRAPHY_TYPE_NAME) Slice input) {
    OGCGeometry geometry = EsriGeometrySerde.deserialize(input);
    if (geometry.isEmpty()) {
        return null;
    }
    validateSphericalType("ST_Area", geometry, EnumSet.of(POLYGON, MULTI_POLYGON));
    Polygon polygon = (Polygon) geometry.getEsriGeometry();
    // See https://www.movable-type.co.uk/scripts/latlong.html
    // and http://osgeo-org.1560.x6.nabble.com/Area-of-a-spherical-polygon-td3841625.html
    // and https://www.element84.com/blog/determining-if-a-spherical-polygon-contains-a-pole
    // for the underlying Maths
    double sphericalExcess = 0.0;
    int numPaths = polygon.getPathCount();
    for (int i = 0; i < numPaths; i++) {
        double sign = polygon.isExteriorRing(i) ? 1.0 : -1.0;
        sphericalExcess += sign * Math.abs(computeSphericalExcess(polygon, polygon.getPathStart(i), polygon.getPathEnd(i)));
    }
    // isExteriorRing returns false for the exterior ring
    return Math.abs(sphericalExcess * EARTH_RADIUS_M * EARTH_RADIUS_M);
}
Also used : OGCGeometry(com.esri.core.geometry.ogc.OGCGeometry) Polygon(com.esri.core.geometry.Polygon) CartesianPoint(com.facebook.presto.geospatial.SphericalGeographyUtils.CartesianPoint) OGCPoint(com.esri.core.geometry.ogc.OGCPoint) Point(com.esri.core.geometry.Point) SqlNullable(com.facebook.presto.spi.function.SqlNullable) ScalarFunction(com.facebook.presto.spi.function.ScalarFunction) Description(com.facebook.presto.spi.function.Description) SqlType(com.facebook.presto.spi.function.SqlType)

Example 19 with OGCGeometry

use of com.esri.core.geometry.ogc.OGCGeometry in project presto by prestodb.

the class SphericalGeoFunctions method toSphericalGeography.

@Description("Converts a Geometry object to a SphericalGeography object")
@ScalarFunction("to_spherical_geography")
@SqlType(SPHERICAL_GEOGRAPHY_TYPE_NAME)
public static Slice toSphericalGeography(@SqlType(GEOMETRY_TYPE_NAME) Slice input) {
    // "every point in input is in range" <=> "the envelope of input is in range"
    Envelope envelope = deserializeEnvelope(input);
    if (!envelope.isEmpty()) {
        checkLatitude(envelope.getYMin());
        checkLatitude(envelope.getYMax());
        checkLongitude(envelope.getXMin());
        checkLongitude(envelope.getXMax());
    }
    OGCGeometry geometry = EsriGeometrySerde.deserialize(input);
    if (geometry.is3D()) {
        throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Cannot convert 3D geometry to a spherical geography");
    }
    GeometryCursor cursor = geometry.getEsriGeometryCursor();
    while (true) {
        com.esri.core.geometry.Geometry subGeometry = cursor.next();
        if (subGeometry == null) {
            break;
        }
        if (!GEOMETRY_TYPES_FOR_SPHERICAL_GEOGRAPHY.contains(subGeometry.getType())) {
            throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Cannot convert geometry of this type to spherical geography: " + subGeometry.getType());
        }
    }
    return input;
}
Also used : OGCGeometry(com.esri.core.geometry.ogc.OGCGeometry) GeometryCursor(com.esri.core.geometry.GeometryCursor) PrestoException(com.facebook.presto.spi.PrestoException) Geometry(com.esri.core.geometry.Geometry) EsriGeometrySerde.deserializeEnvelope(com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserializeEnvelope) Envelope(com.esri.core.geometry.Envelope) ScalarFunction(com.facebook.presto.spi.function.ScalarFunction) Description(com.facebook.presto.spi.function.Description) SqlType(com.facebook.presto.spi.function.SqlType)

Example 20 with OGCGeometry

use of com.esri.core.geometry.ogc.OGCGeometry in project presto by prestodb.

the class SphericalGeoFunctions method stSphericalLength.

@SqlNullable
@Description("Returns the great-circle length in meters of a linestring or multi-linestring on Earth's surface")
@ScalarFunction("ST_Length")
@SqlType(DOUBLE)
public static Double stSphericalLength(@SqlType(SPHERICAL_GEOGRAPHY_TYPE_NAME) Slice input) {
    OGCGeometry geometry = EsriGeometrySerde.deserialize(input);
    if (geometry.isEmpty()) {
        return null;
    }
    validateSphericalType("ST_Length", geometry, EnumSet.of(LINE_STRING, MULTI_LINE_STRING));
    MultiPath lineString = (MultiPath) geometry.getEsriGeometry();
    double sum = 0;
    // sum up paths on (multi)linestring
    for (int path = 0; path < lineString.getPathCount(); path++) {
        if (lineString.getPathSize(path) < 2) {
            continue;
        }
        // sum up distances between adjacent points on this path
        int pathStart = lineString.getPathStart(path);
        Point prev = lineString.getPoint(pathStart);
        for (int i = pathStart + 1; i < lineString.getPathEnd(path); i++) {
            Point next = lineString.getPoint(i);
            sum += greatCircleDistance(prev.getY(), prev.getX(), next.getY(), next.getX());
            prev = next;
        }
    }
    return sum * 1000;
}
Also used : OGCGeometry(com.esri.core.geometry.ogc.OGCGeometry) MultiPath(com.esri.core.geometry.MultiPath) CartesianPoint(com.facebook.presto.geospatial.SphericalGeographyUtils.CartesianPoint) OGCPoint(com.esri.core.geometry.ogc.OGCPoint) Point(com.esri.core.geometry.Point) CartesianPoint(com.facebook.presto.geospatial.SphericalGeographyUtils.CartesianPoint) OGCPoint(com.esri.core.geometry.ogc.OGCPoint) Point(com.esri.core.geometry.Point) SqlNullable(com.facebook.presto.spi.function.SqlNullable) ScalarFunction(com.facebook.presto.spi.function.ScalarFunction) Description(com.facebook.presto.spi.function.Description) SqlType(com.facebook.presto.spi.function.SqlType)

Aggregations

OGCGeometry (com.esri.core.geometry.ogc.OGCGeometry)66 SqlType (com.facebook.presto.spi.function.SqlType)22 Description (com.facebook.presto.spi.function.Description)21 ScalarFunction (com.facebook.presto.spi.function.ScalarFunction)21 SqlNullable (com.facebook.presto.spi.function.SqlNullable)14 Point (com.esri.core.geometry.Point)12 ExecException (org.apache.pig.backend.executionengine.ExecException)12 DataByteArray (org.apache.pig.data.DataByteArray)8 Geometry (com.esri.core.geometry.Geometry)7 OGCPoint (com.esri.core.geometry.ogc.OGCPoint)7 Envelope (com.esri.core.geometry.Envelope)6 OGCConcreteGeometryCollection (com.esri.core.geometry.ogc.OGCConcreteGeometryCollection)6 OGCGeometryCollection (com.esri.core.geometry.ogc.OGCGeometryCollection)6 ArrayList (java.util.ArrayList)6 Slice (io.airlift.slice.Slice)5 GeometryCursor (com.esri.core.geometry.GeometryCursor)4 MultiPoint (com.esri.core.geometry.MultiPoint)4 OGCMultiPoint (com.esri.core.geometry.ogc.OGCMultiPoint)4 Tuple (org.apache.pig.data.Tuple)4 Page (com.facebook.presto.common.Page)3