From 06c2478539535669ba8aa45cce9e676d177cffdd Mon Sep 17 00:00:00 2001 From: "Brian.Dyke" Date: Mon, 19 May 2014 13:26:45 -0400 Subject: [PATCH] CM-MERGE:OB13.5.5-8 into 14.1.2 Former-commit-id: 8d67230c49c6a7a1aa9a1f94996de8b6c0c01470 --- .../com/raytheon/viz/warngen/gis/Area.java | 16 +++----- .../raytheon/viz/warngen/gis/PolygonUtil.java | 39 ++++++++++++++++++- .../viz/warngen/gui/WarngenLayer.java | 6 ++- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java index a2a4297696..c91606ecea 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/Area.java @@ -48,9 +48,7 @@ import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.viz.warngen.gui.WarngenLayer; import com.raytheon.viz.warngen.util.Abbreviation; import com.vividsolutions.jts.geom.Geometry; -import com.vividsolutions.jts.geom.PrecisionModel; import com.vividsolutions.jts.geom.prep.PreparedGeometry; -import com.vividsolutions.jts.precision.SimpleGeometryPrecisionReducer; /** * Area @@ -77,7 +75,7 @@ import com.vividsolutions.jts.precision.SimpleGeometryPrecisionReducer; * May 2, 2013 1963 jsanchez Updated method to determine partOfArea. * Aug 19, 2013 2177 jsanchez Used portionsUtil to calculate area portion descriptions. * Apr 29, 2014 3033 jsanchez Updated method to retrieve files in localization. - * May 16, 2014 DR 17365 D. Friedman Reduce warning area precision to avoid topology errors. + * May 16, 2014 DR 17365 D. Friedman Reduce precision of warning area to avoid topology errors. * * * @author chammack @@ -87,8 +85,6 @@ public class Area { private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(Area.class); - private static final double REDUCED_PRECISION_SCALE = 1000000000.0; - /** * If an area greater than this percentage of the area is covered, no * direction is included @@ -297,16 +293,14 @@ public class Area { WarngenLayer warngenLayer) throws VizException { Map areasMap = new HashMap(); - Geometry simplifiedArea = null; try { - simplifiedArea = (new SimpleGeometryPrecisionReducer(new PrecisionModel( - REDUCED_PRECISION_SCALE))).reduce(warnArea); + Geometry precisionReducedArea = PolygonUtil.reducePrecision(warnArea); + if (precisionReducedArea.isValid()) { + warnArea = precisionReducedArea; + } } catch (Exception e) { // ignore } - if (simplifiedArea != null && simplifiedArea.isValid()) { - warnArea = simplifiedArea; - } String hatchedAreaSource = config.getHatchedAreaSource() .getAreaSource(); diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PolygonUtil.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PolygonUtil.java index 38b92f8d66..318708af9b 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PolygonUtil.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gis/PolygonUtil.java @@ -47,13 +47,16 @@ import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.CoordinateSequence; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineSegment; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.geom.PrecisionModel; import com.vividsolutions.jts.geom.prep.PreparedGeometry; import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; +import com.vividsolutions.jts.precision.SimpleGeometryPrecisionReducer; /** * Utility for polygon operations @@ -81,6 +84,7 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; * 10/18/2013 DR 16632 Qinglu Lin Catch exception thrown when coords length is less than 4 and doing createLinearRing(coords). * 01/09/2014 DR 16974 D. Friedman Improve followup redraw-from-hatched-area polygons. * 04/15/2014 DR 17247 D. Friedman Prevent some invalid coordinates in adjustVertex. + * 05/16/2014 DR 17365 D. Friedman Prevent some Coordinate reuse. Add reducePrecision. * * * @author mschenke @@ -99,6 +103,8 @@ public class PolygonUtil { private MathTransform latLonToContour, contourToLatLon; + private static final PrecisionModel REDUCED_PRECISION = new PrecisionModel(10000000000.0); + public PolygonUtil(WarngenLayer layer, int nx, int ny, int maxVertices, IExtent localExtent, MathTransform localToLatLon) throws Exception { this.layer = layer; @@ -127,9 +133,15 @@ public class PolygonUtil { * hatched area. If it does, that intersection can be used instead of * generating a new contour. */ - if (oldWarningPolygon != null) { + if (oldWarningPolygon != null && oldWarningPolygon.isValid() + && origPolygon.isValid()) { try { - Geometry intersection = origPolygon.intersection(oldWarningPolygon); + /* + * Create a clone to ensure we do not use a Coordinate from + * oldWarningPolygon. + */ + Geometry intersection = (Geometry) origPolygon + .intersection(oldWarningPolygon).clone(); if (intersection instanceof Polygon) { Polygon polygonIntersection = (Polygon) intersection; if (polygonIntersection.isValid() && @@ -1657,4 +1669,27 @@ public class PolygonUtil { } return slope; } + + /** Creates a copy of a Geometry with reduced precision to reduce the chance of topology errors when used + * in intersection operations. + * + * @param g + * @return a new Geometry that is a copy of given Geometry with reduced + * precision. References to user data are copied. If there are GeometryCollection + * objects, user data is copied for each element. + */ + static public Geometry reducePrecision(Geometry g) { + Geometry result; + if (g instanceof GeometryCollection) { + Geometry[] list = new Geometry[g.getNumGeometries()]; + for (int i = 0; i < list.length; ++i) { + list[i] = reducePrecision(g.getGeometryN(i)); + } + GeometryFactory gf = new GeometryFactory(); + result = gf.createGeometryCollection(list); + } else + result = SimpleGeometryPrecisionReducer.reduce(g, REDUCED_PRECISION); + result.setUserData(g.getUserData()); + return result; + } } diff --git a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java index 66e7c5f4fd..106fc2eec0 100644 --- a/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java +++ b/cave/com.raytheon.viz.warngen/src/com/raytheon/viz/warngen/gui/WarngenLayer.java @@ -196,6 +196,7 @@ import com.vividsolutions.jts.io.WKTReader; * 01/09/2014 DR 16974 D. Friedman Improve followup redraw-from-hatched-area polygons. * 04/15/2014 DR 17247 D. Friedman Rework error handling in AreaHatcher. * 04/28,2014 3033 jsanchez Properly handled back up configuration (*.xml) files. Set backupSite to null when backup site is not selected. + * 05/16/2014 DR 17365 D. Friedman Check if moved vertex results in polygon valid in both lat/lon and local coordinates. * * * @author mschenke @@ -2734,7 +2735,10 @@ public class WarngenLayer extends AbstractStormTrackResource { } if (!intersectFlag) { - state.setWarningPolygon(gf.createPolygon(ring, null)); + Polygon p = gf.createPolygon(ring, null); + if (p.isValid() && latLonToLocal(p).isValid()) { + state.setWarningPolygon(p); + } } } catch (Exception e) {