diff --git a/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/GLGeometryObject2D.java b/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/GLGeometryObject2D.java index 2ae8676f91..af129f7afb 100644 --- a/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/GLGeometryObject2D.java +++ b/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/GLGeometryObject2D.java @@ -28,7 +28,6 @@ import java.util.List; import javax.media.opengl.GL; -import com.raytheon.uf.viz.core.IExtent; import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.viz.core.gl.objects.GLVertexBufferObject; @@ -42,7 +41,9 @@ import com.raytheon.viz.core.gl.objects.GLVertexBufferObject; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jun 3, 2011 mschenke Initial creation + * Jun 3, 2011 mschenke Initial creation + * Feb 14, 2014 2804 mschenke Removed ability to clip points outside + * of a defined IExtent * * * @@ -54,8 +55,6 @@ public class GLGeometryObject2D { public static class GLGeometryObjectData { - public IExtent worldExtent; - protected int geometryType; protected int coordType; @@ -97,7 +96,6 @@ public class GLGeometryObject2D { this.data = new GLGeometryObjectData(data.geometryType, data.coordType); this.data.manageIndicies = data.manageIndicies; this.data.mutable = data.mutable; - this.data.worldExtent = data.worldExtent; initialize(); } @@ -249,93 +247,12 @@ public class GLGeometryObject2D { coordBuffer.ensureCapacity(verticesNeeded); } - double[] output = null; - double[] lastOutput = null; - boolean currentlyInBounds = false; - - int curIdx = 0; - // While we haven't gone through entire segment... - while (curIdx < glCoordinates.length) { - // Find next valid point in segment - currentlyInBounds = false; - output = lastOutput = null; - - while (!currentlyInBounds && curIdx < glCoordinates.length) { - lastOutput = output; - output = glCoordinates[curIdx]; - if (data.worldExtent != null) { - if (output == null) { - ++curIdx; - continue; - } - - currentlyInBounds = data.worldExtent.contains(output); - } else { - currentlyInBounds = true; - } - - if (!currentlyInBounds) { - ++curIdx; - } - } - - // We found a starting point... - if (currentlyInBounds) { - // Mark current index - int idx = points; - if (lastOutput != null) { - addToBuffer(coordBuffer, lastOutput); - points++; - addToBuffer(coordBuffer, output); - points++; - } else { - addToBuffer(coordBuffer, output); - points++; - } - ++curIdx; - boolean done = false; - - // Keep going until we run out of screenCoordinates or we find - // one O.B. - while (!done && curIdx < glCoordinates.length) { - lastOutput = output; - output = glCoordinates[curIdx]; - - if (data.worldExtent != null) { - if (output == null) { - ++curIdx; - continue; - } - - currentlyInBounds = data.worldExtent.contains(output); - } else { - currentlyInBounds = true; - } - - if (currentlyInBounds) { - addToBuffer(coordBuffer, output); - points++; - } else { - done = true; - } - - ++curIdx; - } - - if (done) { - // Had to stop early - addToBuffer(coordBuffer, output); - points++; - } - - if (points != idx - && data.manageIndicies - && (data.geometryType != GL.GL_LINES || indicies - .isEmpty())) { - indicies.add(idx); - } - } + int idx = points; + for (double[] coordinate : glCoordinates) { + addToBuffer(coordBuffer, coordinate); + points += 1; } + indicies.add(idx); } public void allocate(int points) { diff --git a/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/internal/GLWireframeShape2D.java b/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/internal/GLWireframeShape2D.java index 5afa348d50..175dcb59d3 100644 --- a/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/internal/GLWireframeShape2D.java +++ b/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/internal/GLWireframeShape2D.java @@ -40,7 +40,6 @@ import com.raytheon.uf.viz.core.IExtent; import com.raytheon.uf.viz.core.IGraphicsTarget.HorizontalAlignment; import com.raytheon.uf.viz.core.IGraphicsTarget.LineStyle; import com.raytheon.uf.viz.core.IGraphicsTarget.VerticalAlignment; -import com.raytheon.uf.viz.core.PixelExtent; import com.raytheon.uf.viz.core.drawables.IFont; import com.raytheon.uf.viz.core.drawables.IWireframeShape; import com.raytheon.uf.viz.core.exception.VizException; @@ -60,7 +59,8 @@ import com.vividsolutions.jts.geom.Coordinate; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * May 27, 2011 mschenke Initial creation + * May 27, 2011 mschenke Initial creation + * Feb 14, 2014 2804 mschenke Removed setting of IExtent for clipping * * * @@ -87,7 +87,6 @@ public class GLWireframeShape2D implements IWireframeShape { geomData = new GLGeometryObjectData(GL.GL_LINE_STRIP, GL.GL_VERTEX_ARRAY); geomData.mutable = mutable; - geomData.worldExtent = new PixelExtent(gridGeometry.getGridRange()); try { worldToTargetGrid = TransformFactory.worldToGrid(gridGeometry, diff --git a/cave/com.raytheon.viz.core/src/com/raytheon/viz/core/rsc/jts/JTSCompiler.java b/cave/com.raytheon.viz.core/src/com/raytheon/viz/core/rsc/jts/JTSCompiler.java index 6937def7b6..7d8090bc2c 100644 --- a/cave/com.raytheon.viz.core/src/com/raytheon/viz/core/rsc/jts/JTSCompiler.java +++ b/cave/com.raytheon.viz.core/src/com/raytheon/viz/core/rsc/jts/JTSCompiler.java @@ -20,9 +20,14 @@ 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; +import com.raytheon.uf.viz.core.IExtent; +import com.raytheon.uf.viz.core.PixelCoverage; +import com.raytheon.uf.viz.core.PixelExtent; import com.raytheon.uf.viz.core.drawables.IDescriptor; import com.raytheon.uf.viz.core.drawables.IShadedShape; import com.raytheon.uf.viz.core.drawables.IWireframeShape; @@ -31,9 +36,12 @@ import com.raytheon.uf.viz.core.map.IMapDescriptor; import com.vividsolutions.jts.geom.Coordinate; 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.Point; import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.geom.prep.PreparedGeometry; +import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; /** * Compile JTS Objects into renderable obs @@ -45,6 +53,7 @@ import com.vividsolutions.jts.geom.Polygon; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Oct 24, 2006 chammack Initial Creation. + * Feb 14, 2014 2804 mschenke Rewrote to move clipping from GLWireframeShape2D to here * * * @@ -59,6 +68,81 @@ public class JTSCompiler { SQUARE, CROSS }; + public static class JTSGeometryData { + + private RGB geometryColor; + + private boolean worldWrapCorrect; + + private PreparedGeometry clippingArea; + + private PointStyle pointStyle; + + protected JTSGeometryData() { + + } + + protected JTSGeometryData(JTSGeometryData data) { + setGeometryColor(data.geometryColor); + setWorldWrapCorrect(data.worldWrapCorrect); + setClippingArea(data.clippingArea); + setPointStyle(data.pointStyle); + } + + public void setGeometryColor(RGB geometryColor) { + this.geometryColor = geometryColor; + } + + public void setWorldWrapCorrect(boolean worldWrapCorrect) { + this.worldWrapCorrect = worldWrapCorrect; + } + + private void setClippingArea(PreparedGeometry clippingArea) { + this.clippingArea = clippingArea; + } + + public void setClippingArea(Polygon clippingArea) { + setClippingArea(PreparedGeometryFactory.prepare(clippingArea)); + } + + public void setClippingExtent(IExtent clippingExtent) { + double[] center = clippingExtent.getCenter(); + PixelCoverage pc = new PixelCoverage(new Coordinate(center[0], + center[1]), clippingExtent.getWidth() + 2, + clippingExtent.getHeight() + 2); + GeometryFactory factory = new GeometryFactory(); + setClippingArea(factory.createPolygon( + factory.createLinearRing(new Coordinate[] { pc.getLl(), + pc.getLr(), pc.getUr(), pc.getUl(), pc.getLl() }), + null)); + } + + public void setPointStyle(PointStyle pointStyle) { + this.pointStyle = pointStyle; + } + + protected RGB getGeometryColor() { + return geometryColor; + } + + protected boolean isWorldWrapCorrect() { + return worldWrapCorrect; + } + + protected PreparedGeometry getClippingArea() { + return clippingArea; + } + + protected boolean isClipping() { + return clippingArea != null; + } + + protected PointStyle getPointStyle() { + return pointStyle; + } + + } + // TODO: parameterize this: also needs to be expressed in screen pixels // rather than arbitrary pixel units private static final double POINT_SIZE = 2.0; @@ -69,10 +153,10 @@ public class JTSCompiler { protected IDescriptor descriptor; - protected PointStyle pointStyle; - private WorldWrapCorrector corrector; + private JTSGeometryData defaultData; + /** * Constructor * @@ -85,11 +169,26 @@ public class JTSCompiler { */ public JTSCompiler(IShadedShape shadedShp, IWireframeShape wireShp, IDescriptor descriptor) { - this(shadedShp, wireShp, descriptor, PointStyle.SQUARE); + this.theShadedShape = shadedShp; + this.theWireframeShape = wireShp; + this.descriptor = descriptor; + if (descriptor instanceof IMapDescriptor) { + this.corrector = new WorldWrapCorrector( + descriptor.getGridGeometry()); + } + JTSGeometryData data = new JTSGeometryData(); + data.setGeometryColor(DEFAULT_COLOR); + data.setClippingExtent(new PixelExtent(descriptor.getGridGeometry() + .getGridRange())); + data.setWorldWrapCorrect(false); + data.setPointStyle(PointStyle.SQUARE); + this.defaultData = data; } /** - * Constructor + * @deprecated Use constructor without {@link PointStyle} and add + * {@link PointStyle} to {@link JTSGeometryData} for a + * {@link Geometry} * * @param shadedShp * the shaded shape object (can be null) @@ -100,242 +199,298 @@ public class JTSCompiler { * @param pointStyle * the pointStyle */ + @Deprecated public JTSCompiler(IShadedShape shadedShp, IWireframeShape wireShp, IDescriptor descriptor, PointStyle pointStyle) { - this.theShadedShape = shadedShp; - this.theWireframeShape = wireShp; - this.descriptor = descriptor; - this.pointStyle = pointStyle; - if (descriptor instanceof IMapDescriptor) { - this.corrector = new WorldWrapCorrector( - descriptor.getGridGeometry()); - } + this(shadedShp, wireShp, descriptor); + this.defaultData.setPointStyle(pointStyle); } - private void handlePolygon(Polygon poly, RGB color) { - - LineString g; - LineString g2; - - Coordinate[] c; - LineString[] rings = null; - - // long tRead1 = System.nanoTime(); - - int numRings; - - g = poly.getExteriorRing(); - c = g.getCoordinates(); - - if (theWireframeShape != null) { - double[][] pts = coordToDouble(c); - theWireframeShape.addLineSegment(pts); - } - - numRings = poly.getNumInteriorRing(); - - if (theShadedShape != null) { - rings = new LineString[numRings + 1]; - rings[0] = g; - } - - // Handle inner rings - for (int k = 0; k < numRings; k++) { - g2 = poly.getInteriorRingN(k); - c = g2.getCoordinates(); - if (theWireframeShape != null) { - double[][] pts = coordToDouble(c); - theWireframeShape.addLineSegment(pts); - } - if (theShadedShape != null) { - rings[k + 1] = g2; - } - } - - if (theShadedShape != null) { - theShadedShape.addPolygonPixelSpace(rings, color); - } - + /** + * @return A new {@link JTSGeometryData} for use with the compiler + */ + public JTSGeometryData createGeometryData() { + return new JTSGeometryData(defaultData); } - private double[][] coordToDouble(Coordinate[] c) { + private static double[][] coordToDouble(Coordinate[] c) { double[][] pts = new double[c.length][3]; for (int i = 0; i < pts.length; i++) { pts[i][0] = c[i].x; pts[i][1] = c[i].y; - pts[i][2] = 0; + pts[i][2] = c[i].z; } return pts; } - private void handleLineString(LineString line, RGB color) { - if (theWireframeShape != null) { - Coordinate[] c = line.getCoordinates(); - double[][] pts = coordToDouble(c); - theWireframeShape.addLineSegment(pts); + /** + * Clips the {@link Geometry} passed in to the clipping area + * + * @param geometry + * @param clippingArea + * @return A clipped Geometry with no parts outside the clippingArea + */ + private static Geometry complexClip(Geometry geometry, + PreparedGeometry clippingArea) { + if (clippingArea.contains(geometry)) { + // Fully contained, don't clip + return geometry; + } else if (clippingArea.intersects(geometry)) { + if (geometry.isValid() == false) { + // Don't try and clip invalid geometries + return geometry; + } + // Intersects, partial clip + return clippingArea.getGeometry().intersection(geometry); + } else { + // No intersection, return empty + return new GeometryFactory() + .createGeometryCollection(new Geometry[0]); } - } - private void handlePoint(Point point, RGB color) { - // make a square point out of each "point" + private void handlePolygon(Polygon poly, JTSGeometryData data) { + int numInteriorRings = poly.getNumInteriorRing(); + LineString[] rings = new LineString[numInteriorRings + 1]; + rings[0] = poly.getExteriorRing(); + for (int k = 0; k < numInteriorRings; k++) { + rings[k + 1] = poly.getInteriorRingN(k); + } - Coordinate[] c = point.getCoordinates(); + if (theWireframeShape != null) { + for (LineString ls : rings) { + handleLineString(ls, data); + } + } - switch (pointStyle) { + if (theShadedShape != null) { + theShadedShape.addPolygonPixelSpace(rings, data.getGeometryColor()); + } + } + + private void handleLineString(LineString line, JTSGeometryData data) { + if (theWireframeShape != null) { + theWireframeShape.addLineSegment(coordToDouble(line + .getCoordinates())); + } + } + + private void handlePoint(Point point, JTSGeometryData data) { + Coordinate coord = point.getCoordinate(); + double[][] ll; + + switch (data.getPointStyle()) { case CROSS: - for (Coordinate coord : c) { - double[][] ll = new double[2][3]; - ll[0][0] = coord.x - POINT_SIZE; - ll[0][1] = coord.y; - ll[0][2] = 0; + ll = new double[2][3]; + ll[0][0] = coord.x - POINT_SIZE; + ll[0][1] = coord.y; + ll[0][2] = 0; - ll[1][0] = coord.x + POINT_SIZE; - ll[1][1] = coord.y; - ll[1][2] = 0; + ll[1][0] = coord.x + POINT_SIZE; + ll[1][1] = coord.y; + ll[1][2] = 0; - if (theWireframeShape != null) { - theWireframeShape.addLineSegment(ll); - } + if (theWireframeShape != null) { + theWireframeShape.addLineSegment(ll); + } - ll[0][0] = coord.x; - ll[0][1] = coord.y - POINT_SIZE; - ll[0][2] = 0; + ll[0][0] = coord.x; + ll[0][1] = coord.y - POINT_SIZE; + ll[0][2] = 0; - ll[1][0] = coord.x; - ll[1][1] = coord.y + POINT_SIZE; - ll[1][2] = 0; + ll[1][0] = coord.x; + ll[1][1] = coord.y + POINT_SIZE; + ll[1][2] = 0; - if (theWireframeShape != null) { - theWireframeShape.addLineSegment(ll); - } + if (theWireframeShape != null) { + theWireframeShape.addLineSegment(ll); } break; default: // use SQUARE - for (Coordinate coord : c) { + ll = new double[5][3]; + // UL + ll[0][0] = coord.x - POINT_SIZE; + ll[0][1] = coord.y - POINT_SIZE; + ll[0][2] = 0; - double[][] ll = new double[5][3]; - // UL - ll[0][0] = coord.x - POINT_SIZE; - ll[0][1] = coord.y - POINT_SIZE; - ll[0][2] = 0; + // UR + ll[1][0] = coord.x - POINT_SIZE; + ll[1][1] = coord.y + POINT_SIZE; + ll[1][2] = 0; - // UR - ll[1][0] = coord.x - POINT_SIZE; - ll[1][1] = coord.y + POINT_SIZE; - ll[1][2] = 0; + // LR + ll[2][0] = coord.x + POINT_SIZE; + ll[2][1] = coord.y + POINT_SIZE; + ll[2][2] = 0; - // LR - ll[2][0] = coord.x + POINT_SIZE; - ll[2][1] = coord.y + POINT_SIZE; - ll[2][2] = 0; + // LL + ll[3][0] = coord.x + POINT_SIZE; + ll[3][1] = coord.y - POINT_SIZE; + ll[3][2] = 0; - // LL - ll[3][0] = coord.x + POINT_SIZE; - ll[3][1] = coord.y - POINT_SIZE; - ll[3][2] = 0; + // Closing point + ll[4] = ll[0]; - // Closing point - ll[4] = ll[0]; - - if (theWireframeShape != null) { - theWireframeShape.addLineSegment(ll); - } + if (theWireframeShape != null) { + theWireframeShape.addLineSegment(ll); } break; } } - private void handleGeometryCollection(GeometryCollection coll, RGB color) - throws VizException { + private void handleGeometryCollection(GeometryCollection coll, + JTSGeometryData data, boolean clipped) throws VizException { int geoms = coll.getNumGeometries(); for (int i = 0; i < geoms; i++) { Geometry g = coll.getGeometryN(i); - disposition(g, color); + disposition(g, data, clipped); } } - private void disposition(Geometry geom, RGB color) throws VizException { - if (geom instanceof Point) { - handlePoint((Point) geom, color); - } else if (geom instanceof GeometryCollection) { - handleGeometryCollection((GeometryCollection) geom, color); + private void disposition(Geometry geom, JTSGeometryData data, + boolean clipped) throws VizException { + if (geom instanceof GeometryCollection) { + handleGeometryCollection((GeometryCollection) geom, data, clipped); + } else if (clipped == false && data.isClipping()) { + geom = complexClip(geom, data.getClippingArea()); + if (geom.isEmpty() == false) { + disposition(geom, data, true); + } + } else if (geom instanceof Point) { + handlePoint((Point) geom, data); } else if (geom instanceof LineString) { - handleLineString((LineString) geom, color); + handleLineString((LineString) geom, data); } else if (geom instanceof Polygon) { - handlePolygon((Polygon) geom, color); + // Polygon is the only type doing complex clipping so it needs to + // know if the Polygon has been clipped already or not + handlePolygon((Polygon) geom, data); } else { throw new VizException("Unknown geometry type: " + geom.getClass().getName()); } } + /** + * @deprecated Use {@link #handle(ReferencedGeometry, JTSGeometryData)} + * @param referencedGeom + * @param color + * @throws VizException + */ + @Deprecated public void handle(ReferencedGeometry referencedGeom, RGB color) throws VizException { - if (color == null) { - color = DEFAULT_COLOR; - } - - Geometry geom; - try { - geom = referencedGeom.asPixel(this.descriptor.getGridGeometry()); - } catch (Exception e) { - throw new VizException("Unable to transform polygon", e); - } - - disposition(geom, color); - + JTSGeometryData data = createGeometryData(); + data.setGeometryColor(color); + handle(referencedGeom, data); } /** - * Handle lat lon based geometries, destructive to the passed in geometry. - * + * @deprecated Use {@link #handle(Geometry, JTSGeometryData)} * @param geom + * @param wrapCorrect * @throws VizException */ - public void handle(Geometry geom) throws VizException { - handle(geom, DEFAULT_COLOR); - } - - /** - * Handle lat lon based geometries, destructive to the passed in geometry. - * - * @param geom - * @param wrapCheck - * @throws VizException - */ + @Deprecated public void handle(Geometry geom, boolean wrapCheck) throws VizException { - handle(geom, DEFAULT_COLOR, wrapCheck); + JTSGeometryData data = createGeometryData(); + data.setWorldWrapCorrect(wrapCheck); + handle(geom, data); } /** - * Handle lat lon based geometries, destructive to the passed in geometry. - * + * @deprecated Use {@link #handle(Geometry, JTSGeometryData)} * @param geom * @param color * @throws VizException */ + @Deprecated public void handle(Geometry geom, RGB color) throws VizException { - handle(geom, color, false); + JTSGeometryData data = createGeometryData(); + data.setGeometryColor(color); + handle(geom, data); } /** - * Handle lat lon based geometries, destructive to the passed in geometry. - * + * @deprecated Use {@link #handle(Geometry, JTSGeometryData)} * @param geom * @param color * @param wrapCorrect * @throws VizException */ + @Deprecated public void handle(Geometry geom, RGB color, boolean wrapCorrect) throws VizException { - if (wrapCorrect && corrector != null) { - geom = corrector.correct(geom); + JTSGeometryData data = createGeometryData(); + data.setGeometryColor(color); + data.setWorldWrapCorrect(wrapCorrect); + handle(new ReferencedGeometry(geom), data); + } + + /** + * Handles a Geometry in lat/lon space + * + * @param geom + * @throws VizException + */ + public void handle(Geometry geom) throws VizException { + handle(geom, defaultData); + } + + /** + * Handles a Geometry in lat/lon space using the geometry data + * + * @param geom + * @param data + * @throws VizException + */ + public void handle(Geometry geom, JTSGeometryData data) throws VizException { + handle(new ReferencedGeometry(geom), data); + } + + /** + * Handles the referenced geometry + * + * @param geom + * @throws VizException + */ + public void handle(ReferencedGeometry geom) throws VizException { + handle(geom, defaultData); + } + + /** + * Handles the referenced geometry using the geometry data + * + * @param geom + * @param data + * @throws VizException + */ + public void handle(ReferencedGeometry geom, JTSGeometryData data) + throws VizException { + 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) { + throw new VizException( + "Error transforming geometry into Lat/Lon", e); + } } - handle(new ReferencedGeometry(geom), color); + try { + disposition(geom.asPixel(descriptor.getGridGeometry()), data, false); + } catch (FactoryException e) { + throw new VizException( + "Error creating transform to descriptor pixel space", e); + } catch (TransformException e) { + throw new VizException( + "Error transforming geometry into descriptor pixel space", + e); + } } } diff --git a/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/util/WorldWrapCorrector.java b/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/util/WorldWrapCorrector.java index 03d62f49ec..c0413d8d67 100644 --- a/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/util/WorldWrapCorrector.java +++ b/edexOsgi/com.raytheon.uf.common.geospatial/src/com/raytheon/uf/common/geospatial/util/WorldWrapCorrector.java @@ -52,6 +52,8 @@ import com.vividsolutions.jts.geom.prep.PreparedGeometryFactory; * May 30, 2013 2028 randerso Changed to return simple geometry or * multi-geometry if possible * Dec 11, 2013 2619 bsteffen Fix rare dateline bug in flattenGeometry. + * Feb 14, 2013 2804 mschenke Added function fo checking if correcting + * needs to occur. * * * @@ -81,6 +83,14 @@ public class WorldWrapCorrector { checker = new WorldWrapChecker(worldEnvelope); } + /** + * @return True if the corrector needs to do correcting on the + * {@link GeneralGridGeometry} it was created with + */ + public boolean needsCorrecting() { + return checker.needsChecking(); + } + /** * Corrects the Geometry passed in to not wrap if geometry does wrap. * Geometry must be in normalized lat/lon space (-180 to 180)