public void setBuffer(double buffer) { this.buffer = buffer; this.buf = Math.max(buffer, Math.max(bounds.getWidth() * buffer, bounds.getHeight() * buffer)); }
public boolean canSimplify(Envelope envelope) { return envelope.getWidth() < spanX && envelope.getHeight() < spanY; }
/** * Creates a new transform. * * @param env the envelope defining one coordinate system * @param xSize the number of cells along the X axis of the grid * @param ySize the number of cells along the Y axis of the grid */ public GridTransform(Envelope env, int xSize, int ySize) { this.env = env; this.xSize = xSize; this.ySize = ySize; dx = env.getWidth() / (xSize - 1); dy = env.getHeight() / (ySize - 1); }
@Override public void filter(Geometry geom) { int cross; if (geom instanceof LineString) {//note: LinearRing extends LineString if (geom.getEnvelopeInternal().getWidth() < 180) return;//can't possibly cross the dateline cross = unwrapDateline((LineString) geom); } else if (geom instanceof Polygon) { if (geom.getEnvelopeInternal().getWidth() < 180) return;//can't possibly cross the dateline cross = unwrapDateline((Polygon) geom); } else { // The only other JTS subclass of Geometry is a Point, which can't cross anything. // If the geom is something custom, we don't know what else to do but return. return; } crossings[0] = Math.max(crossings[0], cross); } });//geom.apply()
private Envelope intersection(Envelope e1, Envelope e2) { Envelope r = e1.intersection(e2); if (r.getWidth() < 0) return null; if (r.getHeight() < 0) return null; return r; }
double calcPolygonAlignOrthoAngle(Geometry geometry) { Envelope envelope = geometry.getEnvelopeInternal(); if (envelope.getHeight() > envelope.getWidth()) { return -(Math.PI / 2); } else { return 0; } }
/** * TODO summary sentence for worldToScreenTransform ... * * @param bounds * @param rectangle * @return */ public static AffineTransform worldToScreenTransform(Envelope mapExtent, Rectangle screenSize) { double scaleX = screenSize.getWidth() / mapExtent.getWidth(); double scaleY = screenSize.getHeight() / mapExtent.getHeight(); double tx = -mapExtent.getMinX() * scaleX; double ty = (mapExtent.getMinY() * scaleY) + screenSize.getHeight(); AffineTransform at = new AffineTransform(scaleX, 0.0d, 0.0d, -scaleY, tx, ty); return at; } /**
/** * Sets up the affine transform * * <p>((Taken from the old LiteRenderer)) * * @param mapExtent the map extent * @param paintArea the size of the rendering output area * @return a transform that maps from real world coordinates to the screen * @deprecated Uses the alternative based on <code>ReferencedEnvelope</code> that doe not assume * anything on axes order. */ public static AffineTransform worldToScreenTransform(Envelope mapExtent, Rectangle paintArea) { double scaleX = paintArea.getWidth() / mapExtent.getWidth(); double scaleY = paintArea.getHeight() / mapExtent.getHeight(); double tx = -mapExtent.getMinX() * scaleX; double ty = (mapExtent.getMinY() * scaleY) + paintArea.getHeight(); AffineTransform at = new AffineTransform(scaleX, 0.0d, 0.0d, -scaleY, tx, ty); AffineTransform originTranslation = AffineTransform.getTranslateInstance(paintArea.x, paintArea.y); originTranslation.concatenate(at); return originTranslation != null ? originTranslation : at; }
/** * Converts a JTS Envelope into an equivalent {@link Rectangle2D} * * @param envelope The source envelope */ public static Rectangle2D toRectangle2D(Envelope envelope) { if (envelope == null) { return null; } return new Rectangle2D.Double( envelope.getMinX(), envelope.getMinY(), envelope.getWidth(), envelope.getHeight()); }
public SimpleFeatureCollection subCollection(Filter filter) { // split out the spatial part of the filter SpatialIndexFeatureCollection ret = new SpatialIndexFeatureCollection(schema); Envelope env = new Envelope(); env = (Envelope) filter.accept(ExtractBoundsFilterVisitor.BOUNDS_VISITOR, env); if (LOGGER.isLoggable(Level.FINEST) && Double.isInfinite(env.getWidth())) { LOGGER.fine("Found no spatial element in " + filter); LOGGER.fine("Just going to iterate"); } for (Iterator<SimpleFeature> iter = (Iterator<SimpleFeature>) index.query(env).iterator(); iter.hasNext(); ) { SimpleFeature sample = iter.next(); if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("Looking at " + sample); } if (filter.evaluate(sample)) { if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.finest("accepting " + sample); } ret.add(sample); } } return ret; }
Geometry widestGeometry(GeometryCollection gc) { if (gc.isEmpty()) { return gc; } Geometry widest = gc.getGeometryN(0); for (int i = 1; i < gc.getNumGeometries(); i++) { Geometry curr = gc.getGeometryN(i); if (curr.getEnvelopeInternal().getWidth() > widest.getEnvelopeInternal().getWidth()) { widest = curr; } } return widest; }
private int getNumSides(Envelope env) { return (int) (10 * (env.getWidth() + env.getHeight())); }
/** * Returns a high precision and more accurate bounding box of the <code>Shape</code> than the * <code>getBounds</code> method. Note that there is no guarantee that the returned {@link * Rectangle2D} is the smallest bounding box that encloses the <code>Shape</code>, only that the * <code>Shape</code> lies entirely within the indicated <code>Rectangle2D</code>. The bounding * box returned by this method is usually tighter than that returned by the <code>getBounds * </code> method and never fails due to overflow problems since the return value can be an * instance of the <code>Rectangle2D</code> that uses double precision values to store the * dimensions. * * @return an instance of <code>Rectangle2D</code> that is a high-precision bounding box of the * <code>Shape</code>. * @see #getBounds */ public Rectangle2D getBounds2D() { Envelope env = geometry.getEnvelopeInternal(); return new Rectangle2D.Double( env.getMinX(), env.getMinY(), env.getWidth(), env.getHeight()); }
private double[] getTranslationFactors(Polygon reference, Polygon displaced) { // compare the two envelopes Envelope re = reference.getEnvelopeInternal(); Envelope de = displaced.getEnvelopeInternal(); double dw = Math.abs(re.getWidth() - de.getWidth()); double dh = Math.abs(re.getHeight() - de.getHeight()); if (dw > EPS * re.getWidth() || dh > EPS * re.getWidth()) { // this was not just a translation return null; } // compute the translation double dx = de.getMinX() - re.getMinX(); double dy = de.getMinY() - re.getMinY(); Polygon cloned = (Polygon) displaced.copy(); cloned.apply(AffineTransformation.translationInstance(-dx, -dy)); if (1 - new HausdorffSimilarityMeasure().measure(cloned, reference) > EPS) { return null; } else { return new double[] {dx, dy}; } }
private Rectangle2D getCurvedLabelBounds( LineStringCursor cursor, double startOrdinate, double endOrdinate, double bufferSize) { LineString cut = cursor.getSubLineString(startOrdinate, endOrdinate); Envelope e = cut.getEnvelopeInternal(); e.expandBy(bufferSize); return new Rectangle2D.Double(e.getMinX(), e.getMinY(), e.getWidth(), e.getHeight()); }
@Override public void filter(Geometry geom) { if (geom != postProcessed && geom.getEnvelopeInternal().getWidth() > 40000000) { fail("The geometry did not get rewrapped properly"); } } });
@Test public void circle() throws Exception { double radius = SQUARE_ENV.getWidth() / 2; Polygon p = builder.circle( SQUARE_ENV.getMinX() + radius, SQUARE_ENV.getMinY() + radius, radius, getNumSides(SQUARE_ENV)); assertBounds(SQUARE_ENV, p.getEnvelopeInternal(), 0.01); }
@Test public void testUTMDatelineWrapping() throws Exception { CoordinateReferenceSystem crs = CRS.decode("EPSG:32601", true); ReferencedEnvelope re = new ReferencedEnvelope(300000, 409800, 5890200, 6000000, crs); MathTransform mt = CRS.findMathTransform(crs, WGS84); Geometry geom = JTS.toGeometry(re); ReferencedEnvelope targetReferenceEnvelope = new ReferencedEnvelope(-180, 180, -90, 90, WGS84); ProjectionHandler ph = ProjectionHandlerFinder.getHandler(targetReferenceEnvelope, crs, true); Geometry preProcessed = ph.preProcess(geom); Geometry transformed = JTS.transform(preProcessed, mt); Geometry postProcessed = ph.postProcess(mt.inverse(), transformed); // sits across the dateline and it's "small" (used to cover the entire planet) Envelope ppEnvelope = postProcessed.getGeometryN(0).getEnvelopeInternal(); assertTrue(ppEnvelope.contains(180, 54)); // the original width is 109km, at this latitude one degree of longitude is only 65km assertEquals(1.7, ppEnvelope.getWidth(), 0.1); }
/** Given {@code geoms} which has already been checked for being in world * bounds, return the minimal longitude range of the bounding box. */ protected Rectangle computeGeoBBox(Geometry geoms) { final Envelope env = geoms.getEnvelopeInternal();//for minY & maxY (simple) if (ctx.isGeo() && env.getWidth() > 180 && geoms.getNumGeometries() > 1) { // This is ShapeCollection's bbox algorithm BBoxCalculator bboxCalc = new BBoxCalculator(ctx); for (int i = 0; i < geoms.getNumGeometries(); i++ ) { Envelope envI = geoms.getGeometryN(i).getEnvelopeInternal(); bboxCalc.expandXRange(envI.getMinX(), envI.getMaxX()); if (bboxCalc.doesXWorldWrap()) break; // can't grow any bigger } return new RectangleImpl(bboxCalc.getMinX(), bboxCalc.getMaxX(), env.getMinY(), env.getMaxY(), ctx); } else { return new RectangleImpl(env.getMinX(), env.getMaxX(), env.getMinY(), env.getMaxY(), ctx); } }
public void testSimplification() throws Exception { SimpleFeatureSource fs = dataStore.getFeatureSource(tname("road")); if (fs.getSupportedHints().contains(Hints.GEOMETRY_SIMPLIFICATION) == false) return; SimpleFeatureCollection fColl = fs.getFeatures(); Geometry original = null; try (SimpleFeatureIterator iterator = fColl.features()) { if (iterator.hasNext()) { original = (Geometry) iterator.next().getDefaultGeometry(); } } double width = original.getEnvelope().getEnvelopeInternal().getWidth(); Query query = new Query(); Hints hints = new Hints(Hints.GEOMETRY_SIMPLIFICATION, width / 2); query.setHints(hints); Geometry simplified = null; fColl = fs.getFeatures(query); try (SimpleFeatureIterator iterator = fColl.features()) { if (iterator.hasNext()) simplified = (Geometry) iterator.next().getDefaultGeometry(); } assertTrue(original.getNumPoints() >= simplified.getNumPoints()); }