Issue #2997 Fix Geostationary projection to work with GeoTools 10.5

Change-Id: Id9f3dc3af07548039509e4121cafd2e02a01453c

Former-commit-id: c4a0a4ef6e [formerly 665246d72e [formerly 2b67417e6128e3cd4cafa5c8f2ac23c10be2b300]]
Former-commit-id: 665246d72e
Former-commit-id: 8aac4d32b1
This commit is contained in:
Ron Anderson 2014-04-17 15:42:27 -05:00
parent 8a6655cb35
commit 0097799e2c
11 changed files with 604 additions and 150 deletions

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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 {

View file

@ -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);

View file

@ -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);

View file

@ -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()) {

View file

@ -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;
}
}

View file

@ -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);