Issue #2997 Fix Geostationary projection to work with GeoTools 10.5
Change-Id: Id9f3dc3af07548039509e4121cafd2e02a01453c Former-commit-id:c4a0a4ef6e
[formerly665246d72e
[formerly 2b67417e6128e3cd4cafa5c8f2ac23c10be2b300]] Former-commit-id:665246d72e
Former-commit-id:8aac4d32b1
This commit is contained in:
parent
8a6655cb35
commit
0097799e2c
11 changed files with 604 additions and 150 deletions
|
@ -21,8 +21,15 @@ package com.raytheon.uf.viz.core.maps.rsc;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.geotools.geometry.jts.CoordinateSequenceTransformer;
|
||||
import org.geotools.geometry.jts.DefaultCoordinateSequenceTransformer;
|
||||
import org.geotools.geometry.jts.ReferencedEnvelope;
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.GeometryTransformer;
|
||||
import com.raytheon.uf.common.geospatial.MapUtil;
|
||||
import com.raytheon.uf.common.geospatial.util.EnvelopeIntersection;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
|
@ -37,9 +44,11 @@ import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
|||
import com.raytheon.uf.viz.core.rsc.capabilities.LabelableCapability;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
|
||||
import com.vividsolutions.jts.geom.Envelope;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.impl.PackedCoordinateSequenceFactory;
|
||||
|
||||
/**
|
||||
* TODO Add Description
|
||||
* Base class for database map resources
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -47,7 +56,8 @@ import com.vividsolutions.jts.geom.Envelope;
|
|||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 10, 2011 randerso Initial creation
|
||||
* Aug 10, 2011 randerso Initial creation
|
||||
* Apr 17, 2014 #2997 randerso Moved buildBoundingGeometry up from DbMapResource
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -63,6 +73,13 @@ public abstract class AbstractDbMapResource<T extends AbstractDbMapResourceData,
|
|||
|
||||
protected static final double EXPANSION_FACTOR = 0.25;
|
||||
|
||||
// Unitless fudge factor to adjust performance.
|
||||
// A higher value increases the threshold and reduces the max divisions
|
||||
// passed into EnveleopeIntersection, making it faster but less accurate.
|
||||
// Values < 4 get very slow. Values > 16 start to cause noticeable drop outs
|
||||
// in the map geometry.
|
||||
protected static final double SPEED_UP = 8;
|
||||
|
||||
protected IFont font;
|
||||
|
||||
protected PixelExtent lastExtent;
|
||||
|
@ -206,4 +223,58 @@ public abstract class AbstractDbMapResource<T extends AbstractDbMapResourceData,
|
|||
public String toString() {
|
||||
return this.resourceData.toString();
|
||||
}
|
||||
|
||||
protected Geometry buildBoundingGeometry(PixelExtent extent,
|
||||
double worldToScreenRatio, double kmPerPixel) {
|
||||
// long t0 = System.currentTimeMillis();
|
||||
|
||||
Envelope env = descriptor.pixelToWorld(extent, descriptor.getCRS());
|
||||
org.opengis.geometry.Envelope sourceEnvelope = new ReferencedEnvelope(
|
||||
env, descriptor.getCRS());
|
||||
|
||||
CoordinateReferenceSystem targetCRS = MapUtil
|
||||
.constructEquidistantCylindrical(MapUtil.AWIPS_EARTH_RADIUS,
|
||||
MapUtil.AWIPS_EARTH_RADIUS, 0, 0);
|
||||
|
||||
double[] srcPts = new double[] { -180, -90, 180, 90 };
|
||||
double[] dstPts = new double[srcPts.length];
|
||||
try {
|
||||
MathTransform toEC = MapUtil.getTransformFromLatLon(targetCRS);
|
||||
toEC.transform(srcPts, 0, dstPts, 0, 2);
|
||||
} catch (Exception e) {
|
||||
statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e);
|
||||
}
|
||||
org.opengis.geometry.Envelope targetEnvelope = new ReferencedEnvelope(
|
||||
new Envelope(dstPts[0], dstPts[2], dstPts[1], dstPts[3]),
|
||||
targetCRS);
|
||||
|
||||
double threshold = kmPerPixel * SPEED_UP;
|
||||
int maxHorDivisions = (int) Math.ceil(extent.getWidth() / SPEED_UP
|
||||
/ worldToScreenRatio);
|
||||
int maxVertDivisions = (int) Math.ceil(extent.getHeight() / SPEED_UP
|
||||
/ worldToScreenRatio);
|
||||
|
||||
Geometry g = null;
|
||||
try {
|
||||
g = EnvelopeIntersection.createEnvelopeIntersection(sourceEnvelope,
|
||||
targetEnvelope, threshold, maxHorDivisions,
|
||||
maxVertDivisions);
|
||||
|
||||
CoordinateSequenceTransformer cst = new DefaultCoordinateSequenceTransformer(
|
||||
PackedCoordinateSequenceFactory.DOUBLE_FACTORY);
|
||||
final GeometryTransformer transformer = new GeometryTransformer(cst);
|
||||
MathTransform toLL = MapUtil.getTransformToLatLon(targetCRS);
|
||||
transformer.setMathTransform(toLL);
|
||||
|
||||
g = transformer.transform(g);
|
||||
} catch (Exception e1) {
|
||||
statusHandler
|
||||
.handle(Priority.PROBLEM, e1.getLocalizedMessage(), e1);
|
||||
}
|
||||
|
||||
// long t1 = System.currentTimeMillis();
|
||||
// System.out.println("buildBoundingGeometry took: " + (t1 - t0));
|
||||
return g;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@ import java.util.List;
|
|||
|
||||
import com.raytheon.uf.common.dataquery.db.QueryResult;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.vividsolutions.jts.geom.Envelope;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
|
||||
/**
|
||||
* TODO Add Description
|
||||
* Factory class to retrieve appropriate DbMapQuery implementation
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -35,6 +35,7 @@ import com.vividsolutions.jts.geom.Envelope;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Dec 9, 2011 bsteffen Initial creation
|
||||
* Apr 9, 2014 #2997 randerso Added queryWithinGeometry
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -45,7 +46,7 @@ import com.vividsolutions.jts.geom.Envelope;
|
|||
public class DbMapQueryFactory {
|
||||
|
||||
public interface DbMapQuery {
|
||||
public QueryResult queryWithinEnvelope(Envelope env,
|
||||
public QueryResult queryWithinGeometry(Geometry geom,
|
||||
List<String> columns, List<String> additionalConstraints)
|
||||
throws VizException;
|
||||
|
||||
|
|
|
@ -41,11 +41,9 @@ import org.eclipse.core.runtime.Status;
|
|||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
import org.geotools.geometry.jts.ReferencedEnvelope;
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
|
||||
import com.raytheon.uf.common.dataquery.db.QueryResult;
|
||||
import com.raytheon.uf.common.geospatial.MapUtil;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
|
@ -74,7 +72,6 @@ import com.raytheon.uf.viz.core.rsc.capabilities.ShadeableCapability;
|
|||
import com.raytheon.viz.core.rsc.jts.JTSCompiler;
|
||||
import com.raytheon.viz.core.rsc.jts.JTSCompiler.PointStyle;
|
||||
import com.raytheon.viz.core.spatial.GeometryCache;
|
||||
import com.vividsolutions.jts.geom.Envelope;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.Point;
|
||||
import com.vividsolutions.jts.geom.TopologyException;
|
||||
|
@ -85,7 +82,7 @@ import com.vividsolutions.jts.io.WKBReader;
|
|||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 19, 2009 randerso Initial creation
|
||||
|
@ -95,6 +92,7 @@ import com.vividsolutions.jts.io.WKBReader;
|
|||
* Nov 06, 2013 2361 njensen Prepopulate fields in initInternal
|
||||
* instead of constructor for speed
|
||||
* Feb 18, 2014 2819 randerso Removed unnecessary clones of geometries
|
||||
* Apr 09, 2014 2997 randerso Replaced buildEnvelope with buildBoundingGeometry
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -171,18 +169,18 @@ public class DbMapResource extends
|
|||
|
||||
String shadingField;
|
||||
|
||||
Envelope envelope;
|
||||
Geometry boundingGeom;
|
||||
|
||||
Map<Object, RGB> colorMap;
|
||||
|
||||
Request(IGraphicsTarget target, IMapDescriptor descriptor,
|
||||
DbMapResource rsc, Envelope envelope, String geomField,
|
||||
DbMapResource rsc, Geometry boundingGeom, String geomField,
|
||||
String labelField, String shadingField,
|
||||
Map<Object, RGB> colorMap) {
|
||||
this.target = target;
|
||||
this.descriptor = descriptor;
|
||||
this.rsc = rsc;
|
||||
this.envelope = envelope;
|
||||
this.boundingGeom = boundingGeom;
|
||||
this.geomField = geomField;
|
||||
this.labelField = labelField;
|
||||
this.shadingField = shadingField;
|
||||
|
@ -217,10 +215,10 @@ public class DbMapResource extends
|
|||
|
||||
public Throwable cause;
|
||||
|
||||
public Envelope query;
|
||||
public String table;
|
||||
|
||||
private Result(Envelope query) {
|
||||
this.query = query;
|
||||
private Result(String table) {
|
||||
this.table = table;
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
@ -238,13 +236,13 @@ public class DbMapResource extends
|
|||
}
|
||||
|
||||
public void request(IGraphicsTarget target, IMapDescriptor descriptor,
|
||||
DbMapResource rsc, Envelope query, String geomField,
|
||||
DbMapResource rsc, Geometry boundingGeom, String geomField,
|
||||
String labelField, String shadingField,
|
||||
Map<Object, RGB> colorMap) {
|
||||
if (requestQueue.size() == QUEUE_LIMIT) {
|
||||
requestQueue.poll();
|
||||
}
|
||||
requestQueue.add(new Request(target, descriptor, rsc, query,
|
||||
requestQueue.add(new Request(target, descriptor, rsc, boundingGeom,
|
||||
geomField, labelField, shadingField, colorMap));
|
||||
|
||||
this.cancel();
|
||||
|
@ -265,7 +263,7 @@ public class DbMapResource extends
|
|||
protected IStatus run(IProgressMonitor monitor) {
|
||||
Request req = requestQueue.poll();
|
||||
while (req != null) {
|
||||
Result result = new Result(req.envelope);
|
||||
Result result = new Result(resourceData.getTable());
|
||||
try {
|
||||
String table = resourceData.getTable();
|
||||
if (canceled) {
|
||||
|
@ -302,7 +300,7 @@ public class DbMapResource extends
|
|||
QueryResult mappedResult = DbMapQueryFactory.getMapQuery(
|
||||
resourceData.getTable(),
|
||||
getGeomField(lev[lev.length - 1]))
|
||||
.queryWithinEnvelope(req.envelope, fields,
|
||||
.queryWithinGeometry(req.boundingGeom, fields,
|
||||
constraints);
|
||||
Map<Integer, Geometry> gidMap = new HashMap<Integer, Geometry>(
|
||||
mappedResult.getResultCount() * 2);
|
||||
|
@ -363,11 +361,13 @@ public class DbMapResource extends
|
|||
byte[] wkb = (byte[]) obj;
|
||||
g = wkbReader.read(wkb);
|
||||
} else {
|
||||
statusHandler.handle(Priority.ERROR,
|
||||
statusHandler.handle(
|
||||
Priority.ERROR,
|
||||
"Expected byte[] received "
|
||||
+ obj.getClass().getName()
|
||||
+ ": " + obj.toString()
|
||||
+ "\n query=\"" + req.envelope
|
||||
+ "\n table=\""
|
||||
+ resourceData.getTable()
|
||||
+ "\"");
|
||||
}
|
||||
gidMap.put(gid, g);
|
||||
|
@ -580,19 +580,6 @@ public class DbMapResource extends
|
|||
getLabelFields().toArray(new String[0]));
|
||||
}
|
||||
|
||||
private Envelope buildEnvelope(PixelExtent extent) throws VizException {
|
||||
Envelope env = null;
|
||||
try {
|
||||
Envelope e = descriptor.pixelToWorld(extent, descriptor.getCRS());
|
||||
ReferencedEnvelope ref = new ReferencedEnvelope(e,
|
||||
descriptor.getCRS());
|
||||
env = ref.transform(MapUtil.LATLON_PROJECTION, true);
|
||||
} catch (Exception e) {
|
||||
throw new VizException("Error transforming extent", e);
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
protected String getGeomField(double simpLev) {
|
||||
DecimalFormat df = new DecimalFormat("0.######");
|
||||
String suffix = "_"
|
||||
|
@ -623,20 +610,27 @@ public class DbMapResource extends
|
|||
PaintProperties paintProps) throws VizException {
|
||||
PixelExtent screenExtent = (PixelExtent) paintProps.getView()
|
||||
.getExtent();
|
||||
Rectangle canvasBounds = paintProps.getCanvasBounds();
|
||||
int screenWidth = canvasBounds.width;
|
||||
double worldToScreenRatio = screenExtent.getWidth() / screenWidth;
|
||||
|
||||
int displayWidth = (int) (descriptor.getMapWidth() * paintProps
|
||||
.getZoomLevel());
|
||||
double kmPerPixel = (displayWidth / screenWidth) / 1000.0;
|
||||
|
||||
// compute an estimate of degrees per pixel
|
||||
double yc = screenExtent.getCenter()[1];
|
||||
double x1 = screenExtent.getMinX();
|
||||
double x2 = screenExtent.getMaxX();
|
||||
double x1 = screenExtent.getCenter()[0];
|
||||
double x2 = x1 + 1;
|
||||
double[] c1 = descriptor.pixelToWorld(new double[] { x1, yc });
|
||||
double[] c2 = descriptor.pixelToWorld(new double[] { x2, yc });
|
||||
Rectangle canvasBounds = paintProps.getCanvasBounds();
|
||||
int screenWidth = canvasBounds.width;
|
||||
double dppX = Math.abs(c2[0] - c1[0]) / screenWidth;
|
||||
// System.out.println("c1:" + Arrays.toString(c1) + " c2:"
|
||||
// + Arrays.toString(c2) + " dpp:" + dppX);
|
||||
double dppX = (Math.abs(c2[0] - c1[0]) * screenExtent.getWidth())
|
||||
/ screenWidth;
|
||||
|
||||
double simpLev = getSimpLev(dppX);
|
||||
// System.out.println("c1:" + Arrays.toString(c1) + "\nc2:"
|
||||
// + Arrays.toString(c2) + "\ndpp:" + dppX + "\nsimpLev:"
|
||||
// + simpLev);
|
||||
|
||||
String labelField = getCapability(LabelableCapability.class)
|
||||
.getLabelField();
|
||||
|
@ -655,8 +649,10 @@ public class DbMapResource extends
|
|||
clipToProjExtent(screenExtent).getEnvelope())) {
|
||||
if (!paintProps.isZooming()) {
|
||||
PixelExtent expandedExtent = getExpandedExtent(screenExtent);
|
||||
Envelope query = buildEnvelope(expandedExtent);
|
||||
queryJob.request(aTarget, descriptor, this, query,
|
||||
Geometry boundingGeom = buildBoundingGeometry(expandedExtent,
|
||||
worldToScreenRatio, kmPerPixel);
|
||||
|
||||
queryJob.request(aTarget, descriptor, this, boundingGeom,
|
||||
getGeomField(simpLev), labelField, shadingField,
|
||||
colorMap);
|
||||
lastExtent = expandedExtent;
|
||||
|
@ -670,8 +666,9 @@ public class DbMapResource extends
|
|||
if (result != null) {
|
||||
if (result.failed) {
|
||||
lastExtent = null; // force to re-query when re-enabled
|
||||
throw new VizException("Error processing map query request: "
|
||||
+ result.query, result.cause);
|
||||
throw new VizException(
|
||||
"Error processing map query request for: "
|
||||
+ result.table, result.cause);
|
||||
}
|
||||
if (outlineShape != null) {
|
||||
outlineShape.dispose();
|
||||
|
@ -716,14 +713,11 @@ public class DbMapResource extends
|
|||
(float) (10 * labelMagnification), null);
|
||||
font.setSmoothing(false);
|
||||
}
|
||||
double screenToWorldRatio = paintProps.getView().getExtent()
|
||||
.getWidth()
|
||||
/ paintProps.getCanvasBounds().width;
|
||||
|
||||
double offsetX = getCapability(LabelableCapability.class)
|
||||
.getxOffset() * screenToWorldRatio;
|
||||
.getxOffset() * worldToScreenRatio;
|
||||
double offsetY = getCapability(LabelableCapability.class)
|
||||
.getyOffset() * screenToWorldRatio;
|
||||
.getyOffset() * worldToScreenRatio;
|
||||
RGB color = getCapability(ColorableCapability.class).getColor();
|
||||
IExtent extent = paintProps.getView().getExtent();
|
||||
List<DrawableString> strings = new ArrayList<DrawableString>(
|
||||
|
@ -737,7 +731,7 @@ public class DbMapResource extends
|
|||
.getDensity();
|
||||
double minScreenDistance = Double.MAX_VALUE;
|
||||
if (density > 0) {
|
||||
minScreenDistance = (screenToWorldRatio * BASE_DENSITY_MULT)
|
||||
minScreenDistance = (worldToScreenRatio * BASE_DENSITY_MULT)
|
||||
/ density;
|
||||
}
|
||||
|
||||
|
@ -763,10 +757,10 @@ public class DbMapResource extends
|
|||
IExtent strExtent = new PixelExtent(
|
||||
node.location[0],
|
||||
node.location[0]
|
||||
+ (node.rect.getWidth() * screenToWorldRatio),
|
||||
+ (node.rect.getWidth() * worldToScreenRatio),
|
||||
node.location[1],
|
||||
node.location[1]
|
||||
+ ((node.rect.getHeight() - node.rect.getY()) * screenToWorldRatio));
|
||||
+ ((node.rect.getHeight() - node.rect.getY()) * worldToScreenRatio));
|
||||
|
||||
if ((lastLabel != null) && lastLabel.equals(node.label)) {
|
||||
// check intersection of extents
|
||||
|
|
|
@ -31,10 +31,9 @@ import org.eclipse.core.runtime.IStatus;
|
|||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.geotools.geometry.jts.ReferencedEnvelope;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
|
||||
import com.raytheon.uf.common.dataquery.db.QueryResult;
|
||||
import com.raytheon.uf.common.geospatial.MapUtil;
|
||||
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
|
||||
import com.raytheon.uf.common.pointdata.vadriver.VA_Advanced;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
|
@ -58,7 +57,6 @@ import com.raytheon.uf.viz.core.rsc.capabilities.LabelableCapability;
|
|||
import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
|
||||
import com.raytheon.uf.viz.core.rsc.capabilities.PointCapability;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Envelope;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.Point;
|
||||
import com.vividsolutions.jts.io.WKBReader;
|
||||
|
@ -71,7 +69,8 @@ import com.vividsolutions.jts.io.WKBReader;
|
|||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 19, 2009 randerso Initial creation
|
||||
* Mar 19, 2009 randerso Initial creation
|
||||
* Apr 09, 2014 2997 randerso Replaced buildEnvelope with buildBoundingGeometry
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -163,15 +162,15 @@ public class DbPointMapResource extends
|
|||
|
||||
String goodnessField;
|
||||
|
||||
Envelope env;
|
||||
Geometry boundingGeometry;
|
||||
|
||||
public Request(DbPointMapResource rsc, String labelField,
|
||||
String goodnessField, Envelope env) {
|
||||
String goodnessField, Geometry boundingGeometry) {
|
||||
super();
|
||||
this.rsc = rsc;
|
||||
this.labelField = labelField;
|
||||
this.goodnessField = goodnessField;
|
||||
this.env = env;
|
||||
this.boundingGeometry = boundingGeometry;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -202,12 +201,12 @@ public class DbPointMapResource extends
|
|||
}
|
||||
|
||||
public void request(IGraphicsTarget target, DbPointMapResource rsc,
|
||||
Envelope envelope, String labelField, String goodnessField) {
|
||||
Geometry boundingGeom, String labelField, String goodnessField) {
|
||||
if (requestQueue.size() == QUEUE_LIMIT) {
|
||||
requestQueue.poll();
|
||||
}
|
||||
requestQueue.add(new Request(rsc, labelField, goodnessField,
|
||||
envelope));
|
||||
boundingGeom));
|
||||
|
||||
this.cancel();
|
||||
this.schedule();
|
||||
|
@ -234,8 +233,8 @@ public class DbPointMapResource extends
|
|||
if (req.labelField != null) {
|
||||
columns.add(req.labelField);
|
||||
}
|
||||
if (req.goodnessField != null
|
||||
&& req.goodnessField != req.labelField) {
|
||||
if ((req.goodnessField != null)
|
||||
&& (req.goodnessField != req.labelField)) {
|
||||
columns.add(req.goodnessField);
|
||||
}
|
||||
if (resourceData.getColumns() != null) {
|
||||
|
@ -258,8 +257,8 @@ public class DbPointMapResource extends
|
|||
|
||||
QueryResult results = DbMapQueryFactory.getMapQuery(
|
||||
resourceData.getTable(),
|
||||
resourceData.getGeomField()).queryWithinEnvelope(
|
||||
req.env, columns, constraints);
|
||||
resourceData.getGeomField()).queryWithinGeometry(
|
||||
req.boundingGeometry, columns, constraints);
|
||||
|
||||
long t1 = System.currentTimeMillis();
|
||||
System.out.println("Maps DB query took: " + (t1 - t0)
|
||||
|
@ -285,15 +284,14 @@ public class DbPointMapResource extends
|
|||
statusHandler.handle(Priority.ERROR,
|
||||
"Expected byte[] received "
|
||||
+ geomObj.getClass().getName()
|
||||
+ ": " + geomObj.toString()
|
||||
+ "\n query=\"" + req.env + "\"");
|
||||
+ ": " + geomObj.toString());
|
||||
}
|
||||
|
||||
if (g != null) {
|
||||
String label = "";
|
||||
if (req.labelField != null
|
||||
&& results.getRowColumnValue(c,
|
||||
req.labelField) != null) {
|
||||
if ((req.labelField != null)
|
||||
&& (results.getRowColumnValue(c,
|
||||
req.labelField) != null)) {
|
||||
Object r = results.getRowColumnValue(c,
|
||||
req.labelField);
|
||||
if (r instanceof BigDecimal) {
|
||||
|
@ -395,36 +393,18 @@ public class DbPointMapResource extends
|
|||
queryJob = new MapQueryJob();
|
||||
}
|
||||
|
||||
private void requestData(IGraphicsTarget target, PixelExtent extent)
|
||||
throws VizException {
|
||||
|
||||
Envelope env = null;
|
||||
try {
|
||||
Envelope e = descriptor.pixelToWorld(extent, descriptor.getCRS());
|
||||
ReferencedEnvelope ref = new ReferencedEnvelope(e,
|
||||
descriptor.getCRS());
|
||||
env = ref.transform(MapUtil.LATLON_PROJECTION, true);
|
||||
} catch (Exception e) {
|
||||
throw new VizException("Error transforming extent", e);
|
||||
}
|
||||
|
||||
// add the label field
|
||||
String labelField = getCapability(LabelableCapability.class)
|
||||
.getLabelField();
|
||||
|
||||
queryJob.request(target, this, env, labelField,
|
||||
resourceData.getGoodnessField());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintInternal(IGraphicsTarget aTarget,
|
||||
PaintProperties paintProps) throws VizException {
|
||||
PixelExtent screenExtent = (PixelExtent) paintProps.getView()
|
||||
.getExtent();
|
||||
Rectangle canvasBounds = paintProps.getCanvasBounds();
|
||||
int screenWidth = canvasBounds.width;
|
||||
double worldToScreenRatio = screenExtent.getWidth() / screenWidth;
|
||||
|
||||
int displayWidth = (int) (descriptor.getMapWidth() * paintProps
|
||||
.getZoomLevel());
|
||||
double kmPerPixel = (displayWidth / paintProps.getCanvasBounds().width) / 1000.0;
|
||||
double kmPerPixel = (displayWidth / screenWidth) / 1000.0;
|
||||
|
||||
double magnification = getCapability(MagnificationCapability.class)
|
||||
.getMagnification();
|
||||
|
@ -437,12 +417,16 @@ public class DbPointMapResource extends
|
|||
.getLabelField();
|
||||
boolean isLabeled = labelField != null;
|
||||
if ((isLabeled && !labelField.equals(lastLabelField))
|
||||
|| lastExtent == null
|
||||
|| (lastExtent == null)
|
||||
|| !lastExtent.getEnvelope().contains(
|
||||
clipToProjExtent(screenExtent).getEnvelope())) {
|
||||
if (!paintProps.isZooming()) {
|
||||
PixelExtent expandedExtent = getExpandedExtent(screenExtent);
|
||||
requestData(aTarget, expandedExtent);
|
||||
Geometry boundingGeom = buildBoundingGeometry(expandedExtent,
|
||||
worldToScreenRatio, kmPerPixel);
|
||||
|
||||
queryJob.request(aTarget, this, boundingGeom, labelField,
|
||||
resourceData.getGoodnessField());
|
||||
lastExtent = expandedExtent;
|
||||
lastLabelField = labelField;
|
||||
}
|
||||
|
@ -497,9 +481,9 @@ public class DbPointMapResource extends
|
|||
try {
|
||||
if (node.getDistance() > threshold) {
|
||||
Coordinate c = node.screenLoc;
|
||||
if (c != null && screenExtent.contains(c.x, c.y)) {
|
||||
if ((c != null) && screenExtent.contains(c.x, c.y)) {
|
||||
points.add(new double[] { c.x, c.y, 0.0 });
|
||||
if (isLabeled && magnification != 0) {
|
||||
if (isLabeled && (magnification != 0)) {
|
||||
DrawableString str = new DrawableString(
|
||||
node.label, color);
|
||||
str.setCoordinates(c.x + offsetX, c.y + offsetY);
|
||||
|
|
|
@ -28,10 +28,10 @@ import com.raytheon.uf.viz.core.catalog.DirectDbQuery;
|
|||
import com.raytheon.uf.viz.core.catalog.DirectDbQuery.QueryLanguage;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.maps.rsc.DbMapQueryFactory.DbMapQuery;
|
||||
import com.vividsolutions.jts.geom.Envelope;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
|
||||
/**
|
||||
* TODO Add Description
|
||||
* Default implementation of DbMapQuery
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -42,6 +42,7 @@ import com.vividsolutions.jts.geom.Envelope;
|
|||
* Dec 9, 2011 bsteffen Initial creation
|
||||
* Sep 18, 2012 #1019 randerso cleaned up geometry type query
|
||||
* Jan 30, 2013 #1551 bkowal Refactored
|
||||
* Apr 9, 2014 #2997 randerso Added queryWithinGeometry
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -63,14 +64,14 @@ public class DefaultDbMapQuery implements DbMapQuery {
|
|||
}
|
||||
|
||||
@Override
|
||||
public QueryResult queryWithinEnvelope(Envelope env, List<String> columns,
|
||||
public QueryResult queryWithinGeometry(Geometry geom, List<String> columns,
|
||||
List<String> additionalConstraints) throws VizException {
|
||||
|
||||
/*
|
||||
* Build the query using the common method.
|
||||
*/
|
||||
final String query = MapsQueryUtil.assembleMapsTableQuery(env, columns,
|
||||
additionalConstraints, this.table, this.geomField);
|
||||
final String query = MapsQueryUtil.assembleMapsTableQuery(geom,
|
||||
columns, additionalConstraints, this.table, this.geomField);
|
||||
|
||||
return DirectDbQuery.executeMappedQuery(query.toString(), MAPS,
|
||||
QueryLanguage.SQL);
|
||||
|
|
|
@ -78,6 +78,8 @@ import com.raytheon.uf.viz.core.time.TimeMatchingJob;
|
|||
* frames
|
||||
* Jul 03, 2013 2154 bsteffen Ensure all resource groups get
|
||||
* removed from the time matcher.
|
||||
* Apr 09, 2014 2997 randerso Stopped printing stack trace for
|
||||
* otherwise ignored exception
|
||||
* </pre>
|
||||
*
|
||||
* @author chammack
|
||||
|
@ -182,8 +184,8 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
|
|||
postRemoveListener(rp.getResource());
|
||||
|
||||
TimeMatchingJob.scheduleTimeMatch(AbstractDescriptor.this);
|
||||
if (renderableDisplay != null
|
||||
&& renderableDisplay.getContainer() != null) {
|
||||
if ((renderableDisplay != null)
|
||||
&& (renderableDisplay.getContainer() != null)) {
|
||||
IDisplayPaneContainer container = renderableDisplay
|
||||
.getContainer();
|
||||
for (IDisplayPane pane : container.getDisplayPanes()) {
|
||||
|
@ -198,7 +200,7 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
|
|||
}
|
||||
|
||||
protected void postAddListener(ResourcePair rp) {
|
||||
if (rp.getResource() != null && getTimeMatcher() != null) {
|
||||
if ((rp.getResource() != null) && (getTimeMatcher() != null)) {
|
||||
// We need to run time matching immediately beacuse order
|
||||
// constructed is important for time matching so we must do it now
|
||||
// instead of scheduling since another resource could be added by
|
||||
|
@ -251,8 +253,7 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
|
|||
}
|
||||
ResourceList rl = null;
|
||||
if (resource instanceof IResourceGroup) {
|
||||
rl = ((IResourceGroup) resource)
|
||||
.getResourceList();
|
||||
rl = ((IResourceGroup) resource).getResourceList();
|
||||
} else if (resource.getResourceData() instanceof IResourceGroup) {
|
||||
rl = ((IResourceGroup) resource.getResourceData())
|
||||
.getResourceList();
|
||||
|
@ -364,7 +365,8 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
|
|||
int frameIndex = info.frameIndex;
|
||||
DataTime[] frames = info.frameTimes;
|
||||
if (frameCount <= getNumberOfFrames()) {
|
||||
if (frames != null && frameIndex >= 0 && frames.length > frameIndex) {
|
||||
if ((frames != null) && (frameIndex >= 0)
|
||||
&& (frames.length > frameIndex)) {
|
||||
restoredTime = frames[frameIndex];
|
||||
}
|
||||
limitedNumberOfFrames = frameCount;
|
||||
|
@ -379,7 +381,8 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
|
|||
int frameIndex = info.frameIndex;
|
||||
DataTime[] frames = info.frameTimes;
|
||||
if (limitedNumberOfFrames <= getNumberOfFrames()) {
|
||||
if (frames != null && frameIndex >= 0 && frames.length > frameIndex) {
|
||||
if ((frames != null) && (frameIndex >= 0)
|
||||
&& (frames.length > frameIndex)) {
|
||||
restoredTime = frames[frameIndex];
|
||||
}
|
||||
limitedNumberOfFrames = Integer.MAX_VALUE;
|
||||
|
@ -517,7 +520,8 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
|
|||
|
||||
@Override
|
||||
public void setRenderableDisplay(IRenderableDisplay display) {
|
||||
if (this.renderableDisplay == null || display.getDescriptor() == this) {
|
||||
if ((this.renderableDisplay == null)
|
||||
|| (display.getDescriptor() == this)) {
|
||||
this.renderableDisplay = display;
|
||||
}
|
||||
}
|
||||
|
@ -565,11 +569,11 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
|
|||
String error = null;
|
||||
DataTime[] times = info.frameTimes;
|
||||
int idx = info.frameIndex;
|
||||
if (times == null && idx >= 0) {
|
||||
if ((times == null) && (idx >= 0)) {
|
||||
error = "Index should be less than zero when there are no frame times.";
|
||||
} else if (times != null && idx >= times.length) {
|
||||
} else if ((times != null) && (idx >= times.length)) {
|
||||
error = "Index must be less than the number of frames.";
|
||||
} else if (idx < 0 && times != null && times.length > 0) {
|
||||
} else if ((idx < 0) && (times != null) && (times.length > 0)) {
|
||||
error = "Index must be positive when frames are provided";
|
||||
}
|
||||
if (times != null) {
|
||||
|
@ -612,8 +616,8 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
|
|||
FramesInfo oldInfo = new FramesInfo(oldTimes, oldIdx);
|
||||
oldTime = oldInfo.getCurrentFrame();
|
||||
currTime = currInfo.getCurrentFrame();
|
||||
if ((oldTime != null && oldTime.equals(currTime) == false)
|
||||
|| (currTime != null && currTime.equals(oldTime) == false)) {
|
||||
if (((oldTime != null) && (oldTime.equals(currTime) == false))
|
||||
|| ((currTime != null) && (currTime.equals(oldTime) == false))) {
|
||||
frameChanged = true;
|
||||
}
|
||||
}
|
||||
|
@ -629,7 +633,7 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
|
|||
int idx = frameIndex;
|
||||
if (frames != null) {
|
||||
frames = Arrays.copyOf(frames, frames.length);
|
||||
if (idx < 0 || idx >= frames.length) {
|
||||
if ((idx < 0) || (idx >= frames.length)) {
|
||||
// This only happens for 4-panels with shared time managers.
|
||||
idx = frames.length - 1;
|
||||
}
|
||||
|
@ -727,7 +731,7 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
|
|||
*/
|
||||
@Override
|
||||
public final CoordinateReferenceSystem getCRS() {
|
||||
if (gridGeometry != null && gridGeometry.getEnvelope() != null) {
|
||||
if ((gridGeometry != null) && (gridGeometry.getEnvelope() != null)) {
|
||||
return gridGeometry.getEnvelope().getCoordinateReferenceSystem();
|
||||
} else {
|
||||
return null;
|
||||
|
@ -779,7 +783,7 @@ public abstract class AbstractDescriptor extends ResourceGroup implements
|
|||
try {
|
||||
pixelToWorld.transform(wpixel, 0, output, 0, 1);
|
||||
} catch (TransformException e) {
|
||||
e.printStackTrace();
|
||||
// e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -39,7 +39,7 @@ import com.vividsolutions.jts.io.ParseException;
|
|||
import com.vividsolutions.jts.io.WKBReader;
|
||||
|
||||
/**
|
||||
* TODO Add Description
|
||||
* DbMapQuery implementation using client side cache
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -48,6 +48,7 @@ import com.vividsolutions.jts.io.WKBReader;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Dec 9, 2011 bsteffen Initial creation
|
||||
* Apr 9, 2014 #2997 randerso Added queryWithinGeometry
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -102,8 +103,7 @@ public class CacheDbMapQuery extends DefaultDbMapQuery {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResult queryWithinEnvelope(Envelope env, List<String> columns,
|
||||
private QueryResult queryWithinEnvelope(Envelope env, List<String> columns,
|
||||
List<String> additionalConstraints) throws VizException {
|
||||
fillCache(geomField, columns);
|
||||
List<?> items = tree.query(env);
|
||||
|
@ -116,7 +116,7 @@ public class CacheDbMapQuery extends DefaultDbMapQuery {
|
|||
List<QueryResultRow> rows = new ArrayList<QueryResultRow>();
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
int rowNumber = (Integer) items.get(i);
|
||||
if (validGIDs != null
|
||||
if ((validGIDs != null)
|
||||
&& !validGIDs.contains(data.getRowColumnValue(rowNumber,
|
||||
GID))) {
|
||||
continue;
|
||||
|
@ -135,6 +135,20 @@ public class CacheDbMapQuery extends DefaultDbMapQuery {
|
|||
return new QueryResult(columnNames, rows.toArray(new QueryResultRow[0]));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.core.maps.rsc.DefaultDbMapQuery#queryWithinGeometry
|
||||
* (com.vividsolutions.jts.geom.Geometry, java.util.List, java.util.List)
|
||||
*/
|
||||
@Override
|
||||
public QueryResult queryWithinGeometry(Geometry geom, List<String> columns,
|
||||
List<String> additionalConstraints) throws VizException {
|
||||
return queryWithinEnvelope(geom.getEnvelopeInternal(), columns,
|
||||
additionalConstraints);
|
||||
}
|
||||
|
||||
private List<Integer> getIndices(String constraint) throws VizException {
|
||||
synchronized (constraint2indices) {
|
||||
List<Integer> indices = constraint2indices.get(constraint);
|
||||
|
|
|
@ -21,7 +21,6 @@ package com.raytheon.viz.core.rsc.jts;
|
|||
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.raytheon.uf.common.geospatial.ReferencedGeometry;
|
||||
import com.raytheon.uf.common.geospatial.util.WorldWrapCorrector;
|
||||
|
@ -54,6 +53,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* Oct 24, 2006 chammack Initial Creation.
|
||||
* Feb 14, 2014 2804 mschenke Rewrote to move clipping from GLWireframeShape2D to here
|
||||
* Apr 21, 2014 2997 randerso Improved error handling in handle(ReferencedGeometry, JTSGeometryData)
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -354,7 +354,7 @@ public class JTSCompiler {
|
|||
boolean clipped) throws VizException {
|
||||
if (geom instanceof GeometryCollection) {
|
||||
handleGeometryCollection((GeometryCollection) geom, data, clipped);
|
||||
} else if (clipped == false && data.isClipping()) {
|
||||
} else if ((clipped == false) && data.isClipping()) {
|
||||
geom = complexClip(geom, data.getClippingArea());
|
||||
if (geom.isEmpty() == false) {
|
||||
disposition(geom, data, true);
|
||||
|
@ -469,14 +469,14 @@ public class JTSCompiler {
|
|||
*/
|
||||
public void handle(ReferencedGeometry geom, JTSGeometryData data)
|
||||
throws VizException {
|
||||
if (corrector != null && corrector.needsCorrecting()
|
||||
if ((corrector != null) && corrector.needsCorrecting()
|
||||
&& data.isWorldWrapCorrect()) {
|
||||
try {
|
||||
geom = new ReferencedGeometry(
|
||||
corrector.correct(geom.asLatLon()));
|
||||
} catch (FactoryException e) {
|
||||
throw new VizException("Error creating transform to Lat/Lon", e);
|
||||
} catch (TransformException e) {
|
||||
} catch (Exception e) {
|
||||
throw new VizException(
|
||||
"Error transforming geometry into Lat/Lon", e);
|
||||
}
|
||||
|
@ -487,7 +487,7 @@ public class JTSCompiler {
|
|||
} catch (FactoryException e) {
|
||||
throw new VizException(
|
||||
"Error creating transform to descriptor pixel space", e);
|
||||
} catch (TransformException e) {
|
||||
} catch (Exception e) {
|
||||
throw new VizException(
|
||||
"Error transforming geometry into descriptor pixel space",
|
||||
e);
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
**/
|
||||
package com.raytheon.uf.common.dataplugin.maps.dataaccess.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.vividsolutions.jts.geom.Envelope;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
|
||||
/**
|
||||
* A utility to construct a query that will be used to retrieve information from
|
||||
|
@ -35,7 +35,8 @@ import com.vividsolutions.jts.geom.Envelope;
|
|||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jan 28, 2013 bkowal Initial creation
|
||||
* Jan 28, 2013 bkowal Initial creation
|
||||
* Apr 09, 2014 #2997 randerso Added support to query against a Geometry
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -45,12 +46,47 @@ import com.vividsolutions.jts.geom.Envelope;
|
|||
|
||||
public class MapsQueryUtil {
|
||||
|
||||
/**
|
||||
* PostGIS Spatial Reference ID (EPSG code) for WGS84.
|
||||
*/
|
||||
private static final int WGS84_SRID = 4326;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private MapsQueryUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a query that can be used to query the maps table based on the
|
||||
* provided information.
|
||||
*
|
||||
* @param boundingGeom
|
||||
* used to limit the selected information to a certain
|
||||
* geographical area
|
||||
* @param columns
|
||||
* the list of columns that will be included in the SELECT
|
||||
* statement
|
||||
* @param additionalConstraints
|
||||
* the list of constraints that will become part of the AND
|
||||
* statement
|
||||
* @param table
|
||||
* the table to select data from
|
||||
* @param geomField
|
||||
* the name of the geometry field of interest
|
||||
* @return the query
|
||||
*/
|
||||
public static String assembleMapsTableQuery(Geometry boundingGeom,
|
||||
List<String> columns, List<String> additionalConstraints,
|
||||
String table, String geomField) {
|
||||
|
||||
String geospatialConstraint = "ST_Intersects(the_geom, ST_GeometryFromText('"
|
||||
+ boundingGeom.toText() + "', " + WGS84_SRID + "))";
|
||||
|
||||
return assembleMapsTableQuery(geospatialConstraint, columns,
|
||||
additionalConstraints, table, geomField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a query that can be used to query the maps table based on the
|
||||
* provided information.
|
||||
|
@ -73,24 +109,20 @@ public class MapsQueryUtil {
|
|||
public static String assembleMapsTableQuery(Envelope env,
|
||||
List<String> columns, List<String> additionalConstraints,
|
||||
String table, String geomField) {
|
||||
// add the geospatial constraint
|
||||
if (env != null) {
|
||||
// copy before modifying
|
||||
if (additionalConstraints == null) {
|
||||
additionalConstraints = new ArrayList<String>();
|
||||
} else {
|
||||
additionalConstraints = new ArrayList<String>(
|
||||
additionalConstraints);
|
||||
}
|
||||
// geospatial constraint will be first
|
||||
additionalConstraints.add(0, String.format(
|
||||
"%s && ST_SetSrid('BOX3D(%f %f, %f %f)'::box3d,4326)",
|
||||
geomField, env.getMinX(), env.getMinY(), env.getMaxX(),
|
||||
env.getMaxY()));
|
||||
}
|
||||
|
||||
String geospatialConstraint = String.format(
|
||||
"%s && ST_SetSrid('BOX3D(%f %f, %f %f)'::box3d," + WGS84_SRID
|
||||
+ ")", geomField, env.getMinX(), env.getMinY(),
|
||||
env.getMaxX(), env.getMaxY());
|
||||
return assembleMapsTableQuery(geospatialConstraint, columns,
|
||||
additionalConstraints, table, geomField);
|
||||
}
|
||||
|
||||
private static String assembleMapsTableQuery(String geospatialConstraint,
|
||||
List<String> columns, List<String> additionalConstraints,
|
||||
String table, String geomField) {
|
||||
StringBuilder query = new StringBuilder("SELECT ");
|
||||
if (columns != null && !columns.isEmpty()) {
|
||||
if ((columns != null) && !columns.isEmpty()) {
|
||||
Iterator<String> iter = columns.iterator();
|
||||
query.append(iter.next());
|
||||
while (iter.hasNext()) {
|
||||
|
@ -102,9 +134,19 @@ public class MapsQueryUtil {
|
|||
query.append(" FROM ");
|
||||
query.append(table);
|
||||
|
||||
// add any additional constraints
|
||||
if (additionalConstraints != null && !additionalConstraints.isEmpty()) {
|
||||
// add the geospatial constraint
|
||||
if (geospatialConstraint != null) {
|
||||
query.append(" WHERE ");
|
||||
query.append(geospatialConstraint);
|
||||
}
|
||||
|
||||
// add any additional constraints
|
||||
if ((additionalConstraints != null) && !additionalConstraints.isEmpty()) {
|
||||
if (geospatialConstraint == null) {
|
||||
query.append(" WHERE ");
|
||||
} else {
|
||||
query.append(" AND ");
|
||||
}
|
||||
Iterator<String> iter = additionalConstraints.iterator();
|
||||
query.append(iter.next());
|
||||
while (iter.hasNext()) {
|
||||
|
|
|
@ -0,0 +1,344 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package com.raytheon.uf.common.geospatial;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.geotools.geometry.jts.CoordinateSequenceTransformer;
|
||||
import org.geotools.geometry.jts.DefaultCoordinateSequenceTransformer;
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
import com.vividsolutions.jts.geom.CoordinateSequence;
|
||||
import com.vividsolutions.jts.geom.CoordinateSequenceFactory;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.GeometryCollection;
|
||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||
import com.vividsolutions.jts.geom.LineString;
|
||||
import com.vividsolutions.jts.geom.LinearRing;
|
||||
import com.vividsolutions.jts.geom.MultiLineString;
|
||||
import com.vividsolutions.jts.geom.MultiPoint;
|
||||
import com.vividsolutions.jts.geom.MultiPolygon;
|
||||
import com.vividsolutions.jts.geom.Point;
|
||||
import com.vividsolutions.jts.geom.Polygon;
|
||||
|
||||
/**
|
||||
* Replacement for GeoTools GeometryCoordinateSequenceTransformer that can
|
||||
* handle conversion of polygons containing NaNs.
|
||||
*
|
||||
* Had to copy the entire class and modify it since it was not written to be
|
||||
* subclassed.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Apr 16, 2014 #2997 randerso Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author randerso
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class GeometryTransformer {
|
||||
|
||||
private MathTransform transform = null;
|
||||
|
||||
private CoordinateReferenceSystem crs;
|
||||
|
||||
private CoordinateSequenceTransformer inputCSTransformer = null;
|
||||
|
||||
private CoordinateSequenceTransformer csTransformer = null;
|
||||
|
||||
private GeometryFactory currGeometryFactory = null;
|
||||
|
||||
/**
|
||||
* Creates a transformer which uses the {@link CoordinateSequenceFactory} of
|
||||
* the source geometries.
|
||||
*/
|
||||
public GeometryTransformer() {
|
||||
// the csTransformer is initialized from the first geometry
|
||||
// and the supplied transform
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a transformer which uses a client-specified
|
||||
* {@link CoordinateSequenceTransformer}.
|
||||
* <p>
|
||||
* <b>WARNING:</b> The CoordinateSequenceTransformer must use the same
|
||||
* {@link CoordinateSequenceFactory} as the output GeometryFactory, so that
|
||||
* geometries are constructed consistently.
|
||||
*
|
||||
* @param transformer
|
||||
*/
|
||||
public GeometryTransformer(CoordinateSequenceTransformer transformer) {
|
||||
inputCSTransformer = transformer;
|
||||
csTransformer = transformer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the math transform to be used for transformation
|
||||
*
|
||||
* @param transform
|
||||
*/
|
||||
public void setMathTransform(MathTransform transform) {
|
||||
this.transform = transform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the target coordinate reference system.
|
||||
* <p>
|
||||
* This value is used to set the coordinate reference system of geometries
|
||||
* after they have been transformed.
|
||||
* </p>
|
||||
*
|
||||
* @param crs
|
||||
* The target coordinate reference system.
|
||||
*/
|
||||
public void setCoordinateReferenceSystem(CoordinateReferenceSystem crs) {
|
||||
this.crs = crs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the internal CoordinateSequenceTransformer if not specified
|
||||
* explicitly.
|
||||
*
|
||||
* @param gf
|
||||
* the factory to use
|
||||
*/
|
||||
private void init(GeometryFactory gf) {
|
||||
// don't init if csTransformer already exists
|
||||
if (inputCSTransformer != null) {
|
||||
return;
|
||||
}
|
||||
// don't reinit if gf is the same (the usual case)
|
||||
if (currGeometryFactory == gf) {
|
||||
return;
|
||||
}
|
||||
|
||||
currGeometryFactory = gf;
|
||||
CoordinateSequenceFactory csf = gf.getCoordinateSequenceFactory();
|
||||
csTransformer = new DefaultCoordinateSequenceTransformer(csf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the transform to the provided geometry, creating a new
|
||||
* transformed geometry.
|
||||
*
|
||||
* @param g
|
||||
* the geometry to transform
|
||||
* @return a new transformed geometry
|
||||
* @throws TransformException
|
||||
*/
|
||||
public Geometry transform(Geometry g) throws TransformException {
|
||||
GeometryFactory factory = g.getFactory();
|
||||
Geometry transformed = null;
|
||||
|
||||
// lazily init csTransformer using geometry's CSFactory
|
||||
init(factory);
|
||||
|
||||
if (g instanceof Point) {
|
||||
transformed = transformPoint((Point) g, factory);
|
||||
} else if (g instanceof MultiPoint) {
|
||||
MultiPoint mp = (MultiPoint) g;
|
||||
Point[] points = new Point[mp.getNumGeometries()];
|
||||
|
||||
for (int i = 0; i < points.length; i++) {
|
||||
points[i] = transformPoint((Point) mp.getGeometryN(i), factory);
|
||||
}
|
||||
|
||||
transformed = factory.createMultiPoint(points);
|
||||
} else if (g instanceof LineString) {
|
||||
transformed = transformLineString((LineString) g, factory);
|
||||
} else if (g instanceof MultiLineString) {
|
||||
MultiLineString mls = (MultiLineString) g;
|
||||
LineString[] lines = new LineString[mls.getNumGeometries()];
|
||||
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
lines[i] = transformLineString(
|
||||
(LineString) mls.getGeometryN(i), factory);
|
||||
}
|
||||
|
||||
transformed = factory.createMultiLineString(lines);
|
||||
} else if (g instanceof Polygon) {
|
||||
transformed = transformPolygon((Polygon) g, factory);
|
||||
} else if (g instanceof MultiPolygon) {
|
||||
// changed from original GeoTools implementation
|
||||
// to handle transformPolygon possibly returning LineStrings instead for polygons
|
||||
MultiPolygon mp = (MultiPolygon) g;
|
||||
int n = mp.getNumGeometries();
|
||||
List<Geometry> polygons = new ArrayList<Geometry>(n);
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
polygons.add(transformPolygon((Polygon) mp.getGeometryN(i),
|
||||
factory));
|
||||
}
|
||||
|
||||
transformed = factory.buildGeometry(polygons);
|
||||
} else if (g instanceof GeometryCollection) {
|
||||
GeometryCollection gc = (GeometryCollection) g;
|
||||
Geometry[] geoms = new Geometry[gc.getNumGeometries()];
|
||||
|
||||
for (int i = 0; i < geoms.length; i++) {
|
||||
geoms[i] = transform(gc.getGeometryN(i));
|
||||
}
|
||||
|
||||
transformed = factory.createGeometryCollection(geoms);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported geometry type "
|
||||
+ g.getClass());
|
||||
}
|
||||
|
||||
// copy over user data
|
||||
// do a special check for coordinate reference system
|
||||
transformed.setUserData(g.getUserData());
|
||||
|
||||
if ((g.getUserData() == null)
|
||||
|| (g.getUserData() instanceof CoordinateReferenceSystem)) {
|
||||
// set the new one to be the target crs
|
||||
if (crs != null) {
|
||||
transformed.setUserData(crs);
|
||||
}
|
||||
}
|
||||
|
||||
return transformed;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ls
|
||||
* @param gf
|
||||
* @return transformed lineString
|
||||
* @throws TransformException
|
||||
*/
|
||||
public LineString transformLineString(LineString ls, GeometryFactory gf)
|
||||
throws TransformException {
|
||||
|
||||
// if required, init csTransformer using geometry's CSFactory
|
||||
init(gf);
|
||||
|
||||
CoordinateSequence cs = projectCoordinateSequence(ls
|
||||
.getCoordinateSequence());
|
||||
LineString transformed = null;
|
||||
|
||||
// changed from original GeoTools implementation
|
||||
// to check if CoordinateSequence is closed and return LineString if not
|
||||
if (isClosed(cs)) {
|
||||
transformed = gf.createLinearRing(cs);
|
||||
} else {
|
||||
transformed = gf.createLineString(cs);
|
||||
}
|
||||
|
||||
transformed.setUserData(ls.getUserData());
|
||||
return transformed;
|
||||
}
|
||||
|
||||
// changed from original GeoTools implementation
|
||||
// added function to check if CoordinateSequence
|
||||
// is closed and contains enough points to be a
|
||||
// LinearRing
|
||||
private boolean isClosed(CoordinateSequence cs) {
|
||||
if (cs.size() < 4) {
|
||||
return false;
|
||||
}
|
||||
return cs.getCoordinate(0).equals2D(cs.getCoordinate(cs.size() - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param point
|
||||
* @param gf
|
||||
* @return transformed point
|
||||
*
|
||||
* @throws TransformException
|
||||
*/
|
||||
public Point transformPoint(Point point, GeometryFactory gf)
|
||||
throws TransformException {
|
||||
|
||||
// if required, init csTransformer using geometry's CSFactory
|
||||
init(gf);
|
||||
|
||||
CoordinateSequence cs = projectCoordinateSequence(point
|
||||
.getCoordinateSequence());
|
||||
Point transformed = gf.createPoint(cs);
|
||||
transformed.setUserData(point.getUserData());
|
||||
return transformed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cs
|
||||
* a CoordinateSequence
|
||||
* @return
|
||||
*
|
||||
* @throws TransformException
|
||||
*/
|
||||
private CoordinateSequence projectCoordinateSequence(CoordinateSequence cs)
|
||||
throws TransformException {
|
||||
return csTransformer.transform(cs, transform);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param polygon
|
||||
* @param gf
|
||||
* @return transformed Polygon or MultiLineString if Polygon no longer
|
||||
* closes
|
||||
* @throws TransformException
|
||||
*/
|
||||
public Geometry transformPolygon(Polygon polygon, GeometryFactory gf)
|
||||
throws TransformException {
|
||||
// changed from original GeoTools implementation
|
||||
// to return LineStrings if polygon no longer closed due to NaNs
|
||||
// returned by projection transformation (point outside valid range for projection)
|
||||
LineString[] lineStrings = new LineString[polygon.getNumInteriorRing() + 1];
|
||||
|
||||
lineStrings[0] = transformLineString(polygon.getExteriorRing(), gf);
|
||||
|
||||
for (int i = 1; i < lineStrings.length; i++) {
|
||||
lineStrings[i] = transformLineString(
|
||||
polygon.getInteriorRingN(i - 1), gf);
|
||||
}
|
||||
|
||||
boolean closed = true;
|
||||
for (LineString ls : lineStrings) {
|
||||
if (!ls.isClosed()) {
|
||||
closed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Geometry transformed;
|
||||
if (closed) {
|
||||
LinearRing[] interiors = new LinearRing[lineStrings.length - 1];
|
||||
for (int i = 0; i < interiors.length; i++) {
|
||||
interiors[i] = (LinearRing) lineStrings[i + 1];
|
||||
}
|
||||
transformed = gf.createPolygon((LinearRing) lineStrings[0],
|
||||
interiors);
|
||||
} else {
|
||||
transformed = gf.createMultiLineString(lineStrings);
|
||||
}
|
||||
transformed.setUserData(polygon.getUserData());
|
||||
return transformed;
|
||||
}
|
||||
}
|
|
@ -22,7 +22,6 @@ package com.raytheon.uf.common.geospatial;
|
|||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.geotools.geometry.jts.CoordinateSequenceTransformer;
|
||||
import org.geotools.geometry.jts.DefaultCoordinateSequenceTransformer;
|
||||
import org.geotools.geometry.jts.GeometryCoordinateSequenceTransformer;
|
||||
import org.opengis.referencing.operation.MathTransform;
|
||||
import org.opengis.referencing.operation.TransformException;
|
||||
|
||||
|
@ -39,6 +38,7 @@ import com.vividsolutions.jts.geom.impl.PackedCoordinateSequenceFactory;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* Dec 29, 2008 chammack Initial creation
|
||||
* Feb 18, 2014 #2819 randerso Made transform non-destructive
|
||||
* Apr 16, 2014 #2997 randerso Changed to use our GeometryTransformer
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -100,8 +100,7 @@ public class ReferencedGeometry extends ReferencedObject<Geometry> {
|
|||
protected Geometry transform(MathTransform mt) throws TransformException {
|
||||
CoordinateSequenceTransformer t1 = new DefaultCoordinateSequenceTransformer(
|
||||
PackedCoordinateSequenceFactory.DOUBLE_FACTORY);
|
||||
final GeometryCoordinateSequenceTransformer transformer = new GeometryCoordinateSequenceTransformer(
|
||||
t1);
|
||||
final GeometryTransformer transformer = new GeometryTransformer(t1);
|
||||
transformer.setMathTransform(mt);
|
||||
|
||||
return transformer.transform(this.internalObject);
|
||||
|
|
Loading…
Add table
Reference in a new issue