From 4c6cddc7d4fe4af3220923b492216f48c6209c51 Mon Sep 17 00:00:00 2001 From: Ron Anderson Date: Wed, 26 Mar 2014 17:35:08 -0500 Subject: [PATCH] Issue #2664 Added support for non-WGS84 shape files Change-Id: Id7ec05ddd6c8ff8b144ef4208db3e052e9693951 Former-commit-id: 143017d2a61b242a7fa5d9ad596cd958cea1df3a --- .../gisdatastore/rsc/DataStoreResource.java | 76 +++++++++++++++---- .../uf/viz/gisdatastore/rsc/ReloadJob.java | 11 ++- .../opt/db/ddl/maps/importShapeFile.sh | 60 ++++++++++++--- 3 files changed, 118 insertions(+), 29 deletions(-) diff --git a/cave/com.raytheon.uf.viz.gisdatastore/src/com/raytheon/uf/viz/gisdatastore/rsc/DataStoreResource.java b/cave/com.raytheon.uf.viz.gisdatastore/src/com/raytheon/uf/viz/gisdatastore/rsc/DataStoreResource.java index 363825fe35..4de7beccc6 100644 --- a/cave/com.raytheon.uf.viz.gisdatastore/src/com/raytheon/uf/viz/gisdatastore/rsc/DataStoreResource.java +++ b/cave/com.raytheon.uf.viz.gisdatastore/src/com/raytheon/uf/viz/gisdatastore/rsc/DataStoreResource.java @@ -50,8 +50,11 @@ import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory2; +import org.opengis.geometry.MismatchedDimensionException; +import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.TransformException; import com.raytheon.uf.common.geospatial.MapUtil; import com.raytheon.uf.common.geospatial.ReferencedCoordinate; @@ -115,6 +118,7 @@ import com.vividsolutions.jts.geom.Point; * Jul 24, 2013 #1908 randerso Update attributes when cropped * Feb 18, 2014 #2819 randerso Removed unnecessary clones of geometries * Mar 11, 2014 #2718 randerso Changes for GeoTools 10.5 + * Mar 25, 2014 #2664 randerso Added support for non-WGS84 shape files * * * @@ -130,7 +134,14 @@ public class DataStoreResource extends static final String ID_ATTRIBUTE_NAME = "Feature.ID"; - private static final int CLICK_TOLERANCE = 3; + /** + * Non-polygonal geometry within CLICK_TOLERANCE screen pixels of the cursor + * will be selected when double clicking in the map. + * + * 10 pixels was selected as it felt about right when trying to select + * individual points in a point based shape file + */ + private static final int CLICK_TOLERANCE = 10; private static final RGB RUBBER_BAND_COLOR = new RGB(0, 255, 0); @@ -430,6 +441,10 @@ public class DataStoreResource extends private SimpleFeatureType schema; + private MathTransform incomingToLatLon; + + private MathTransform latLonToIncoming; + /** * The valid time range for this resource. If null resource is time * agnostic. @@ -594,6 +609,11 @@ public class DataStoreResource extends timer.start(); schema = dataStore.getSchema(typeName); + CoordinateReferenceSystem incomingCrs = schema + .getGeometryDescriptor().getCoordinateReferenceSystem(); + incomingToLatLon = MapUtil.getTransformToLatLon(incomingCrs); + latLonToIncoming = MapUtil.getTransformFromLatLon(incomingCrs); + List attrDesc = schema .getAttributeDescriptors(); @@ -624,7 +644,8 @@ public class DataStoreResource extends } } - private void loadAttributes() { + private void loadAttributes() throws FactoryException, + MismatchedDimensionException, TransformException { ITimer timer = TimeUtil.getTimer(); timer.start(); Query query = new Query(); @@ -643,8 +664,9 @@ public class DataStoreResource extends List geomList = new ArrayList(); PixelExtent extent = clipToProjExtent(projExtent); - Geometry boundingGeom = buildBoundingGeometry(extent, - worldToScreenRatio); + Geometry boundingGeom = JTS.transform( + buildBoundingGeometry(extent, worldToScreenRatio), + latLonToIncoming); flattenGeometry(boundingGeom, geomList); List filterList = new ArrayList(geomList.size()); @@ -674,7 +696,8 @@ public class DataStoreResource extends String id = f.getID(); DisplayAttributes da = getDisplayAttributes(id); Geometry g = (Geometry) f.getAttribute(geomField); - da.setCentroid(g.getCentroid()); + da.setCentroid((Point) JTS.transform(g.getCentroid(), + incomingToLatLon)); attributes[index][0] = id; for (int j = 1; j < attributeNames.length; j++) { @@ -854,8 +877,13 @@ public class DataStoreResource extends if (updateHighlights || updateLabels || updateShading || updateExtent) { if (!paintProps.isZooming()) { PixelExtent expandedExtent = getExpandedExtent(screenExtent); - boundingGeom = buildBoundingGeometry(expandedExtent, - worldToScreenRatio); + try { + boundingGeom = JTS.transform( + buildBoundingGeometry(expandedExtent, + worldToScreenRatio), latLonToIncoming); + } catch (Exception e) { + throw new VizException(e.getLocalizedMessage(), e); + } String geomField = schema.getGeometryDescriptor() .getLocalName(); @@ -1238,7 +1266,12 @@ public class DataStoreResource extends */ public Object[][] getAttributes() { if (attributes == null) { - loadAttributes(); + try { + loadAttributes(); + } catch (Exception e) { + statusHandler.error("Error loading attributes: ", e); + attributes = new Object[0][0]; + } } return attributes; } @@ -1255,6 +1288,20 @@ public class DataStoreResource extends return schema; } + /** + * @return the incomingToLatLon + */ + public MathTransform getIncomingToLatLon() { + return incomingToLatLon; + } + + /** + * @return the latLonToIncoming + */ + public MathTransform getLatLonToIncoming() { + return latLonToIncoming; + } + /** * @param coord * @return @@ -1278,7 +1325,8 @@ public class DataStoreResource extends try { if (polygonal) { GeometryFactory gf = new GeometryFactory(); - Point clickPoint = gf.createPoint(coord.asLatLon()); + Point clickPoint = gf.createPoint(JTS.transform( + coord.asLatLon(), null, latLonToIncoming)); clickFilter = ff.contains(ff.property(geomField), ff.literal(clickPoint)); } else { @@ -1294,9 +1342,10 @@ public class DataStoreResource extends double delta = CLICK_TOLERANCE * worldToScreenRatio; PixelExtent bboxExtent = new PixelExtent(pix.x - delta, pix.x - + delta, pix.y - delta, pix.y + delta); - Geometry clickBox = buildBoundingGeometry(bboxExtent, - worldToScreenRatio); + + delta, pix.y + delta, pix.y - delta); + Geometry clickBox = JTS.transform( + buildBoundingGeometry(bboxExtent, worldToScreenRatio), + latLonToIncoming); List clickGeomList = new ArrayList(); flattenGeometry(clickBox, clickGeomList); List clickFilterList = new ArrayList( @@ -1313,7 +1362,6 @@ public class DataStoreResource extends "Error transforming sample point to lat/lon ", e); } - // query.setFilter(ff.and(clickFilter, boundingFilter)); query.setFilter(clickFilter); SimpleFeatureCollection featureCollection = null; @@ -1397,7 +1445,7 @@ public class DataStoreResource extends DisplayAttributes da = getDisplayAttributes(id); da.setHighlighted(highlighted); updateHighlights = true; - ; + issueRefresh(); } diff --git a/cave/com.raytheon.uf.viz.gisdatastore/src/com/raytheon/uf/viz/gisdatastore/rsc/ReloadJob.java b/cave/com.raytheon.uf.viz.gisdatastore/src/com/raytheon/uf/viz/gisdatastore/rsc/ReloadJob.java index 8c9683006b..697f839864 100644 --- a/cave/com.raytheon.uf.viz.gisdatastore/src/com/raytheon/uf/viz/gisdatastore/rsc/ReloadJob.java +++ b/cave/com.raytheon.uf.viz.gisdatastore/src/com/raytheon/uf/viz/gisdatastore/rsc/ReloadJob.java @@ -22,11 +22,11 @@ import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.factory.CommonFactoryFinder; import org.geotools.factory.GeoTools; +import org.geotools.geometry.jts.JTS; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory2; -import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.viz.core.DrawableString; @@ -58,6 +58,7 @@ import com.vividsolutions.jts.geom.Point; * Jul 24, 2014 #1908 randerso Removed debug sysouts * Feb 18, 2014 #2819 randerso Removed unnecessary clones of geometries * Mar 11, 2014 #2718 randerso Changes for GeoTools 10.5 + * Mar 25, 2014 #2664 randerso Added support for non-WGS84 shape files * * * @@ -246,11 +247,7 @@ class ReloadJob extends Job { req.rsc.getDescriptor().getGridGeometry(), true); } - // TODO: pass the crs on to JTSCompiler to indicate - // projection of shapefile data. SimpleFeatureType schema = req.rsc.getSchema(); - CoordinateReferenceSystem crs = schema.getGeometryDescriptor() - .getCoordinateReferenceSystem(); JTSCompiler jtsCompiler = new JTSCompiler(newShadedShape, newOutlineShape, req.rsc.getDescriptor(), @@ -314,7 +311,9 @@ class ReloadJob extends Job { continue; } - Geometry g = (Geometry) f.getAttribute(req.geomField); + Geometry g = JTS.transform( + (Geometry) f.getAttribute(req.geomField), + req.rsc.getIncomingToLatLon()); if (da.isHighlighted()) { highlightGeoms.add(g); } diff --git a/edexOsgi/build.edex/opt/db/ddl/maps/importShapeFile.sh b/edexOsgi/build.edex/opt/db/ddl/maps/importShapeFile.sh index 937e1cea19..df8caf253e 100644 --- a/edexOsgi/build.edex/opt/db/ddl/maps/importShapeFile.sh +++ b/edexOsgi/build.edex/opt/db/ddl/maps/importShapeFile.sh @@ -17,10 +17,19 @@ # # See the AWIPS II Master Rights File ("Master Rights File.pdf") for # further licensing information. +# +# +# SOFTWARE HISTORY +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 03/25/2014 #2664 randerso Added support for importing non-WGS84 shape files +# ## -if [ $# -lt 3 ] ; then + +function usage() +{ echo - echo usage: `basename $0` shapefile schema table [simplev [dbUser [dbPort [installDir]]]] + echo usage: `basename $0` shapefile schema table [simplev [dbUser [dbPort [installDir [srid]]]]] echo "where: shapefile - pathname of the shape file to be imported" echo " schema - database schema where the shape file is to be imported" echo " table - database table where the shape file is to be imported" @@ -28,11 +37,22 @@ if [ $# -lt 3 ] ; then echo " dbUser - optional database user id" echo " dbPort - optional database port number" echo " installDir- optional directory path to awips installation" - echo "example: `basename $0` uscounties.shp mapdata County 0.064,0.016,0.004,0.001 awips 5432 /awips2" + echo " srid - optional srid of source shape file" + echo "example: `basename $0` uscounties.shp mapdata County 0.064,0.016,0.004,0.001 awips 5432 /awips2" +} + +if [ $# -lt 3 ] ; then + usage exit -1 fi -SHAPEFILEPATH=${1} +SHP_PATH=${1} +SHP_DIR="${SHP_PATH%/*}" # shape file dir +SHP_NAME="${SHP_PATH##*/}" # shape file name with extension +SHP_BASE="${SHP_NAME%.*}" # shape file name without extension +SHP_EXT="${SHP_NAME##*.}" # shape file extension +PRJ_PATH="${SHP_DIR}/${SHP_BASE}.prj" + SCHEMA=`echo "${2}" | tr '[:upper:]' '[:lower:]'` TABLE=`echo "${3}" | tr '[:upper:]' '[:lower:]'` SIMPLEVS=${4} @@ -57,16 +77,38 @@ else PSQLBINDIR=${7}/psql/bin/ fi -SHAPEFILENAME=`basename ${SHAPEFILEPATH}` -echo " Importing ${SHAPEFILENAME} into ${SCHEMA}.${TABLE} ..." +if [ -z $8 ] ; then + if [ -e $PRJ_PATH ] + then + echo + echo "WARNING, found projection file: ${PRJ_PATH}" + echo "It is probable that this shape file is not in EPSG:4326 (WGS 84, unprojected lat/lon) format." + echo "Please determine the correct srid by uploading the .prj file to http://prj2epsg.org/search" + echo "and re-run `basename $0` supplying the correct srid." + usage + exit -1 + fi + + SRID=4326 +else + SRID=${8}:4326 +fi + +if [ ! -r ${SHP_PATH} ]; then + echo + echo "ERROR, file not found or is not readable: ${SHP_PATH}" + exit -1 +fi + +echo " Importing ${SHP_NAME} into ${SCHEMA}.${TABLE} ..." ${PSQLBINDIR}psql -d maps -U ${PGUSER} -q -p ${PGPORT} -c " DELETE FROM public.geometry_columns WHERE f_table_schema = '${SCHEMA}' AND f_table_name = '${TABLE}'; - DELETE from ${SCHEMA}.map_version WHERE table_name='${TABLE}'; + DELETE FROM ${SCHEMA}.map_version WHERE table_name='${TABLE}'; DROP TABLE IF EXISTS ${SCHEMA}.${TABLE} " -${PGBINDIR}shp2pgsql -W LATIN1 -s 4326 -g the_geom -I ${SHAPEFILEPATH} ${SCHEMA}.${TABLE} | ${PSQLBINDIR}psql -d maps -U ${PGUSER} -q -p ${PGPORT} -f - +${PGBINDIR}shp2pgsql -W LATIN1 -s ${SRID} -g the_geom -I ${SHP_PATH} ${SCHEMA}.${TABLE} | ${PSQLBINDIR}psql -d maps -U ${PGUSER} -q -p ${PGPORT} -f - ${PSQLBINDIR}psql -d maps -U ${PGUSER} -q -p ${PGPORT} -c " - INSERT INTO ${SCHEMA}.map_version (table_name, filename) values ('${TABLE}','${SHAPEFILENAME}'); + INSERT INTO ${SCHEMA}.map_version (table_name, filename) values ('${TABLE}','${SHP_NAME}'); SELECT AddGeometryColumn('${SCHEMA}','${TABLE}','the_geom_0','4326',(SELECT type FROM public.geometry_columns WHERE f_table_schema='${SCHEMA}' and f_table_name='${TABLE}' and f_geometry_column='the_geom'),2); UPDATE ${SCHEMA}.${TABLE} SET the_geom_0=ST_Segmentize(the_geom,0.1); CREATE INDEX ${TABLE}_the_geom_0_gist ON ${SCHEMA}.${TABLE} USING gist(the_geom_0);