package com.esri.hadoop.hive; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.io.BytesWritable; import com.esri.core.geometry.Geometry; import com.esri.core.geometry.GeometryEngine; import com.esri.core.geometry.SpatialReference; import com.esri.hadoop.hive.GeometryUtils.OGCType; import com.esri.core.geometry.ogc.OGCGeometry; @Description( name = "ST_Union", value = "_FUNC_(ST_Geometry, ST_Geometry, ...) - returns an ST_Geometry as the union of the supplied ST_Geometries", extended = "Example: SELECT ST_AsText(ST_Union(ST_Polygon(1, 1, 1, 4, 4, 4, 4, 1), ST_Polygon(4, 1, 4, 4, 4, 8, 8, 1))) FROM onerow;\n" + "MULTIPOLYGON (((4 1, 8 1, 4 8, 4 4, 1 4, 1 1, 4 1)))") //@HivePdkUnitTests( // cases = { // @HivePdkUnitTest( // query = "SELECT ST_AsText(ST_Union(ST_Point(1.1, 2.2), ST_Point(3.3, 4.4))) FROM onerow", // result = "MULTIPOINT (1.1 2.2, 3.3 4.4)" // ), // @HivePdkUnitTest( // query = "SELECT ST_AsText(ST_Union(ST_Polygon(1, 1, 1, 4, 4, 4, 4, 1), ST_Polygon(4,1, 4,8, 8,1))) FROM onerow", // result = "MULTIPOLYGON (((4 1, 8 1, 4 8, 4 4, 1 4, 1 1, 4 1)))" // ), // @HivePdkUnitTest( // query = "SELECT ST_AsText(ST_Union(ST_Point(1.1, 2.2), ST_Point(3.3, 4.4), ST_Point(5.5, 6.6), ST_Point(1.1, 2.2))) FROM onerow", // result = "MULTIPOINT (1.1 2.2, 3.3 4.4, 5.5 6.6)" // ) // } // ) public class ST_Union extends ST_GeometryProcessing { static final Log LOG = LogFactory.getLog(ST_Union.class.getName()); public BytesWritable evaluate (BytesWritable ... geomrefs){ // validate arguments if (geomrefs == null || geomrefs.length < 2){ LogUtils.Log_VariableArgumentLength(LOG); } int firstWKID = 0; SpatialReference spatialRef = null; // validate spatial references and geometries first for (int i=0;i<geomrefs.length; i++){ BytesWritable geomref = geomrefs[i]; if (geomref == null || geomref.getLength() == 0){ LogUtils.Log_ArgumentsNull(LOG); return null; } if (i==0){ firstWKID = GeometryUtils.getWKID(geomref); if (firstWKID != GeometryUtils.WKID_UNKNOWN) { spatialRef = SpatialReference.create(firstWKID); } } else if (firstWKID != GeometryUtils.getWKID(geomref)){ LogUtils.Log_SRIDMismatch(LOG, geomrefs[0], geomref); return null; } } // now build geometry array to pass to GeometryEngine.union Geometry [] geomsToUnion = new Geometry[geomrefs.length]; for (int i=0;i<geomrefs.length;i++){ //HiveGeometry hiveGeometry = GeometryUtils.geometryFromEsriShape(geomrefs[i]); OGCGeometry ogcGeometry = GeometryUtils.geometryFromEsriShape(geomrefs[i]); // if (i==0){ // get from ogcGeometry rather than re-create above? // spatialRef = hiveGeometry.spatialReference; // } if (ogcGeometry == null){ LogUtils.Log_ArgumentsNull(LOG); return null; } geomsToUnion[i] = ogcGeometry.getEsriGeometry(); } try { Geometry unioned = GeometryEngine.union(geomsToUnion, spatialRef); // we have to infer the type of the differenced geometry because we don't know // if it's going to end up as a single or multi-part geometry OGCType inferredType = GeometryUtils.getInferredOGCType(unioned); return GeometryUtils.geometryToEsriShapeBytesWritable(unioned, firstWKID, inferredType); } catch (Exception e){ LogUtils.Log_ExceptionThrown(LOG, "GeometryEngine.union", e); return null; } } }