Search in sources :

Example 1 with CRS

use of org.apache.sis.referencing.CRS in project geotoolkit by Geomatys.

the class DistanceSpliteratorTest method testPolyline.

private void testPolyline(final CoordinateReferenceSystem crs, final boolean isOrthodromic, final boolean parallel) throws IOException, FactoryException {
    final DistanceSpliterator.Builder builder = DistanceSpliterator.builder().setCrs(crs);
    final Travel t = fromSegments(crs);
    builder.setPolyline(t.polyline);
    final Spliterator.OfDouble ds = isOrthodromic ? builder.buildOrthodromic() : builder.buildLoxodromic();
    final int ptNumber = t.polyline.size();
    final AtomicInteger count = new AtomicInteger();
    final double totalDistance = StreamSupport.doubleStream(ds, parallel).peek(whatever -> count.incrementAndGet()).sum();
    Assert.assertEquals("Number of treated segments", ptNumber - 1, count.get());
    org.junit.Assert.assertEquals("Computed distance", isOrthodromic ? t.orthodromicDistance : t.loxodromicDistance, // meter to kilometer
    totalDistance / 1000, isOrthodromic ? EngineTest.EPSI : EngineTest.LOXODROMIC_ERROR);
}
Also used : CoordinateSequence(org.locationtech.jts.geom.CoordinateSequence) CRS(org.apache.sis.referencing.CRS) Assert(org.geotoolkit.test.Assert) CoordinateOperation(org.opengis.referencing.operation.CoordinateOperation) Coordinate(org.locationtech.jts.geom.Coordinate) IOException(java.io.IOException) UnaryOperator(java.util.function.UnaryOperator) Test(org.junit.Test) CoordinateArraySequence(org.locationtech.jts.geom.impl.CoordinateArraySequence) List(java.util.List) MathTransform(org.opengis.referencing.operation.MathTransform) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) StreamSupport(java.util.stream.StreamSupport) CommonCRS(org.apache.sis.referencing.CommonCRS) Spliterator(java.util.Spliterator) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) FactoryException(org.opengis.util.FactoryException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Spliterator(java.util.Spliterator)

Example 2 with CRS

use of org.apache.sis.referencing.CRS in project geotoolkit by Geomatys.

the class GeometryTransformer method getCoordinates.

/**
 * Check that given geometry is a primitive geometry (implements {@link WithCoordinates}), and
 * get its points.
 * @param source The geometry to extract points from.
 * @return Found points, never null, but can be empty.
 * @throws UnconvertibleObjectException If the given geometry does not implement {@link WithCoordinates}.
 */
private Spliterator<Coordinate> getCoordinates(final Object source) throws UnconvertibleObjectException {
    List<Double> values = null;
    if (source instanceof WithCoordinates) {
        final Coordinates coords = ((WithCoordinates) source).getCoordinates();
        if (coords != null) {
            /* HACK : In GML 3, coordinates are just a list of decimal values.
                 * The grouping by coordinate is done using "srsDimension" attribute
                 * on parent geometry type. However, with GML 2, there's another
                 * possibility : Coordinates use two distinct separators : one for
                 * decimal value separation, and another for coordinate separation.
                 * To manage both ways, we first check if coordinates object has
                 * succeeded in splitting underlying decimals in coordinates. If
                 * it does (return arrays with more than one element), we use
                 * that approach. Otherwise, we fallback on standard way which
                 * will try to determine manually the number of dimensions.
                 */
            Iterator<double[]> it = coords.points().iterator();
            if (it.hasNext() && it.next().length > 1) {
                return coords.points().map(GeometryTransformer::toCoordinate).spliterator();
            } else {
                values = coords.getValues();
            }
        } else if (source instanceof Point) {
            DirectPosition dp = ((Point) source).getPos();
            if (dp != null) {
                return Stream.of(convertDirectPosition(dp)).spliterator();
            } else
                // recognized object, but no value. Empty geometry
                return Spliterators.emptySpliterator();
        }
    }
    // TODO : below conditions should be removed when proper abstraction is setup on GML geometry definition.
    if (values == null) {
        final boolean isLineString = source instanceof org.geotoolkit.gml.xml.LineString;
        final boolean isLineStringSegment = source instanceof org.geotoolkit.gml.xml.LineStringSegment;
        if (isLineString || isLineStringSegment) {
            final DirectPositionList posList;
            if (isLineString) {
                posList = ((org.geotoolkit.gml.xml.LineString) source).getPosList();
            } else {
                posList = ((org.geotoolkit.gml.xml.LineStringSegment) source).getPosList();
            }
            if (posList != null) {
                values = posList.getValue();
            } else {
                final List<? extends DirectPosition> pList;
                if (isLineString) {
                    pList = ((org.geotoolkit.gml.xml.LineString) source).getPos();
                } else {
                    pList = ((org.geotoolkit.gml.xml.LineStringSegment) source).getPos();
                }
                if (pList != null) {
                    return pList.stream().map(GeometryTransformer::convertDirectPosition).filter(Objects::nonNull).spliterator();
                } else {
                    // We've identified a line, but there's no data in it
                    values = Collections.EMPTY_LIST;
                }
            }
        } else if (source instanceof org.geotoolkit.gml.xml.LinearRing) {
            // Note : do not check "getCoordinates", because it should have been done above.
            values = asDoubles(() -> ((org.geotoolkit.gml.xml.LinearRing) source).getPosList());
        } else if (source instanceof org.geotoolkit.gml.xml.v311.GeodesicStringType) {
            values = asDoubles(() -> ((org.geotoolkit.gml.xml.v311.GeodesicStringType) source).getPosList());
        } else if (source instanceof org.geotoolkit.gml.xml.v321.GeodesicStringType) {
            values = asDoubles(() -> ((org.geotoolkit.gml.xml.v321.GeodesicStringType) source).getPosList());
        } else if (source instanceof Curve) {
            CurveSegmentArrayProperty segments = ((Curve) source).getSegments();
            if (segments != null) {
                final List<? extends AbstractCurveSegment> curveSegments = segments.getAbstractCurveSegment();
                if (curveSegments != null) {
                    return curveSegments.stream().flatMap(seg -> StreamSupport.stream(getCoordinates(seg), false)).spliterator();
                }
            }
            // If we arrive here, we've got an empty curve.
            values = Collections.EMPTY_LIST;
        } else if (source instanceof ArcByCenterPointType) {
            final ArcByCenterPointType arc = (ArcByCenterPointType) source;
            org.opengis.geometry.DirectPosition dp = arc.getPos();
            if (dp == null) {
                PointPropertyType pp = arc.getPointProperty();
                if (pp == null) {
                    pp = arc.getPointRep();
                }
                if (pp == null) {
                    throw new UnconvertibleObjectException("Not enough information to build an arc.");
                }
                final Geometry point = new GeometryTransformer(pp.getPoint(), this).get();
                dp = JTS.toEnvelope(point).getLowerCorner();
            }
            CoordinateReferenceSystem crs = dp.getCoordinateReferenceSystem();
            if (crs == null) {
                crs = getSrsName().map(this::findCRS).orElseThrow(() -> new UnconvertibleObjectException("Cannot create an arc without its coordinate reference system"));
                final GeneralDirectPosition gdp = new GeneralDirectPosition(dp);
                gdp.setCoordinateReferenceSystem(crs);
                dp = gdp;
            }
            try {
                final Measure startAngle, endAngle;
                // If we miss a start or end angle, it means we're in presence of a circle.
                if (arc.getStartAngle() == null || arc.getEndAngle() == null) {
                    startAngle = new Measure(0, Units.DEGREE);
                    endAngle = new Measure(360, Units.DEGREE);
                } else {
                    startAngle = asMeasure(arc.getStartAngle());
                    endAngle = asMeasure(arc.getEndAngle());
                }
                final Coordinate[] coordinates = drawArc(dp, asMeasure(arc.getRadius()), startAngle, endAngle, ARC_PRECISION);
                return Spliterators.spliterator(coordinates, Spliterator.ORDERED);
            } catch (TransformException ex) {
                throw new UnconvertibleObjectException("Cannot draw an arc.", ex);
            }
        } else if (source instanceof org.geotoolkit.gml.xml.v311.ArcByCenterPointType) {
            // TODO : factorize with above case
            final org.geotoolkit.gml.xml.v311.ArcByCenterPointType arc = (org.geotoolkit.gml.xml.v311.ArcByCenterPointType) source;
            org.opengis.geometry.DirectPosition dp = arc.getPos();
            if (dp == null) {
                org.geotoolkit.gml.xml.v311.PointPropertyType pp = arc.getPointProperty();
                if (pp == null) {
                    pp = arc.getPointRep();
                }
                if (pp == null) {
                    throw new UnconvertibleObjectException("Not enough information to build an arc.");
                }
                final Geometry point = new GeometryTransformer(pp.getPoint(), this).get();
                dp = JTS.toEnvelope(point).getLowerCorner();
            }
            CoordinateReferenceSystem crs = dp.getCoordinateReferenceSystem();
            if (crs == null) {
                crs = getSrsName().map(this::findCRS).orElseThrow(() -> new UnconvertibleObjectException("Cannot create an arc without its coordinate reference system"));
                final GeneralDirectPosition gdp = new GeneralDirectPosition(dp);
                gdp.setCoordinateReferenceSystem(crs);
                dp = gdp;
            }
            try {
                final Measure startAngle, endAngle;
                // If we miss a start or end angle, it means we're in presence of a circle.
                if (arc.getStartAngle() == null || arc.getEndAngle() == null) {
                    startAngle = new Measure(0, Units.DEGREE);
                    endAngle = new Measure(360, Units.DEGREE);
                } else {
                    startAngle = asMeasure(arc.getStartAngle());
                    endAngle = asMeasure(arc.getEndAngle());
                }
                final Coordinate[] coordinates = drawArc(dp, asMeasure(arc.getRadius()), startAngle, endAngle, ARC_PRECISION);
                return Spliterators.spliterator(coordinates, Spliterator.ORDERED);
            } catch (TransformException ex) {
                throw new UnconvertibleObjectException("Cannot draw an arc.", ex);
            }
        }
    }
    if (values != null) {
        if (values.isEmpty()) {
            return Spliterators.emptySpliterator();
        }
        return new CoordinateSpliterator(values, getCoordinateDimension());
    }
    throw new UnconvertibleObjectException("Cannot extract coordinates from source geometry.");
}
Also used : Measure(org.apache.sis.internal.jaxb.gml.Measure) Unit(javax.measure.Unit) CRS(org.apache.sis.referencing.CRS) GeodeticCalculator(org.apache.sis.referencing.GeodeticCalculator) Spliterators(java.util.Spliterators) NoSuchAuthorityCodeException(org.opengis.referencing.NoSuchAuthorityCodeException) Coordinate(org.locationtech.jts.geom.Coordinate) MeasureType(org.geotoolkit.gml.xml.v321.MeasureType) PolygonPatchType(org.geotoolkit.gml.xml.v321.PolygonPatchType) Envelope(org.geotoolkit.gml.xml.Envelope) Matcher(java.util.regex.Matcher) SingleCRS(org.opengis.referencing.crs.SingleCRS) GeometryProperty(org.geotoolkit.gml.xml.GeometryProperty) Map(java.util.Map) Ring(org.geotoolkit.gml.xml.Ring) TransformException(org.opengis.referencing.operation.TransformException) MultiLineString(org.locationtech.jts.geom.MultiLineString) AxesConvention(org.apache.sis.referencing.cs.AxesConvention) AbstractCRS(org.apache.sis.referencing.crs.AbstractCRS) Logger(java.util.logging.Logger) MultiSurface(org.geotoolkit.gml.xml.MultiSurface) Objects(java.util.Objects) Cache(org.apache.sis.util.collection.Cache) List(java.util.List) Stream(java.util.stream.Stream) UnconvertibleObjectException(org.apache.sis.util.UnconvertibleObjectException) Polygon(org.locationtech.jts.geom.Polygon) Optional(java.util.Optional) Geometry(org.locationtech.jts.geom.Geometry) SurfaceType(org.geotoolkit.gml.xml.v321.SurfaceType) Pattern(java.util.regex.Pattern) Spliterator(java.util.Spliterator) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) FactoryException(org.opengis.util.FactoryException) MultiPolygon(org.locationtech.jts.geom.MultiPolygon) Coordinates(org.geotoolkit.gml.xml.Coordinates) PointProperty(org.geotoolkit.gml.xml.PointProperty) ArgumentChecks(org.apache.sis.util.ArgumentChecks) DoubleFunction(java.util.function.DoubleFunction) LinearRing(org.locationtech.jts.geom.LinearRing) HashMap(java.util.HashMap) DirectPositionList(org.geotoolkit.gml.xml.DirectPositionList) Function(java.util.function.Function) Supplier(java.util.function.Supplier) CurveProperty(org.geotoolkit.gml.xml.CurveProperty) MultiGeometry(org.geotoolkit.gml.xml.MultiGeometry) ArrayList(java.util.ArrayList) Angle(javax.measure.quantity.Angle) AbstractGeometry(org.geotoolkit.gml.xml.AbstractGeometry) Length(javax.measure.quantity.Length) GeneralDirectPosition(org.apache.sis.geometry.GeneralDirectPosition) AbstractCurveSegment(org.geotoolkit.gml.xml.AbstractCurveSegment) WithCoordinates(org.geotoolkit.gml.xml.WithCoordinates) AxisDirections(org.apache.sis.internal.referencing.AxisDirections) PointPropertyType(org.geotoolkit.gml.xml.v321.PointPropertyType) CurveSegmentArrayProperty(org.geotoolkit.gml.xml.CurveSegmentArrayProperty) StreamSupport(java.util.stream.StreamSupport) Point(org.geotoolkit.gml.xml.Point) NoSuchElementException(java.util.NoSuchElementException) DirectPosition(org.opengis.geometry.DirectPosition) Units(org.apache.sis.measure.Units) GeometryFactory(org.locationtech.jts.geom.GeometryFactory) Iterator(java.util.Iterator) PolygonProperty(org.geotoolkit.gml.xml.PolygonProperty) JTS(org.geotoolkit.geometry.jts.JTS) AbstractSurface(org.geotoolkit.gml.xml.AbstractSurface) Consumer(java.util.function.Consumer) MultiCurve(org.geotoolkit.gml.xml.MultiCurve) GeometryCollection(org.locationtech.jts.geom.GeometryCollection) LineString(org.locationtech.jts.geom.LineString) AbstractMap(java.util.AbstractMap) ArcByCenterPointType(org.geotoolkit.gml.xml.v321.ArcByCenterPointType) Curve(org.geotoolkit.gml.xml.Curve) AbstractRingProperty(org.geotoolkit.gml.xml.AbstractRingProperty) MultiPoint(org.locationtech.jts.geom.MultiPoint) SurfaceProperty(org.geotoolkit.gml.xml.SurfaceProperty) Collections(java.util.Collections) LineStringProperty(org.geotoolkit.gml.xml.LineStringProperty) AbstractRing(org.geotoolkit.gml.xml.AbstractRing) GeneralDirectPosition(org.apache.sis.geometry.GeneralDirectPosition) DirectPosition(org.opengis.geometry.DirectPosition) GeneralDirectPosition(org.apache.sis.geometry.GeneralDirectPosition) CurveSegmentArrayProperty(org.geotoolkit.gml.xml.CurveSegmentArrayProperty) UnconvertibleObjectException(org.apache.sis.util.UnconvertibleObjectException) ArcByCenterPointType(org.geotoolkit.gml.xml.v321.ArcByCenterPointType) Measure(org.apache.sis.internal.jaxb.gml.Measure) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) DirectPosition(org.opengis.geometry.DirectPosition) Coordinates(org.geotoolkit.gml.xml.Coordinates) WithCoordinates(org.geotoolkit.gml.xml.WithCoordinates) MultiCurve(org.geotoolkit.gml.xml.MultiCurve) Curve(org.geotoolkit.gml.xml.Curve) TransformException(org.opengis.referencing.operation.TransformException) Point(org.geotoolkit.gml.xml.Point) MultiPoint(org.locationtech.jts.geom.MultiPoint) Geometry(org.locationtech.jts.geom.Geometry) MultiGeometry(org.geotoolkit.gml.xml.MultiGeometry) AbstractGeometry(org.geotoolkit.gml.xml.AbstractGeometry) MultiLineString(org.locationtech.jts.geom.MultiLineString) LineString(org.locationtech.jts.geom.LineString) DirectPositionList(org.geotoolkit.gml.xml.DirectPositionList) Coordinate(org.locationtech.jts.geom.Coordinate) WithCoordinates(org.geotoolkit.gml.xml.WithCoordinates) PointPropertyType(org.geotoolkit.gml.xml.v321.PointPropertyType)

Example 3 with CRS

use of org.apache.sis.referencing.CRS in project geotoolkit by Geomatys.

the class AbstractCoverageSymbolizerRenderer method extractSlice.

private static GridGeometry extractSlice(GridGeometry fullArea, GridGeometry areaOfInterest, final int[] margin, boolean applyResolution) throws DataStoreException, TransformException, FactoryException {
    double[] resolution = areaOfInterest.getResolution(true);
    if (fullArea.isDefined(GridGeometry.RESOLUTION)) {
        CoordinateReferenceSystem crsarea = areaOfInterest.getCoordinateReferenceSystem();
        CoordinateReferenceSystem crsdata = fullArea.getCoordinateReferenceSystem();
        if (CRS.isHorizontalCRS(crsarea) && CRS.isHorizontalCRS(crsdata)) {
            // we are dealing with simple 2D rendering, preserve the canvas grid geometry.
            if (margin != null && Arrays.stream(margin).anyMatch(value -> value != 0)) {
                try {
                    // try to adjust margin
                    // TODO : we should use a GridCoverageResource.subset with a margin value but this isn't implemented yet
                    Envelope env = fullArea.getEnvelope();
                    double[] est = CoverageUtilities.estimateResolution(env, fullArea.getResolution(true), areaOfInterest.getCoordinateReferenceSystem());
                    margin[0] = (int) Math.ceil(margin[0] * (est[0] / resolution[0]));
                    margin[1] = (int) Math.ceil(margin[1] * (est[1] / resolution[1]));
                    areaOfInterest = areaOfInterest.derive().margin(margin).build();
                    // Force rebuilding envelope. Not sure it is really needed however.
                    areaOfInterest = new GridGeometry(areaOfInterest.getExtent(), PixelInCell.CELL_CENTER, areaOfInterest.getGridToCRS(PixelInCell.CELL_CENTER), areaOfInterest.getCoordinateReferenceSystem());
                    return areaOfInterest;
                } catch (Exception e) {
                    LOGGER.log(Level.WARNING, "Cannot compute adapted margin. Artifacts may appear on tile borders");
                    LOGGER.log(Level.FINE, "Details about margin computation failure", e);
                }
            }
        }
    } else {
    // we have no way to apply margin
    // must wait for GridCoverageResource.subset with a margin
    }
    // HACK : This method cannot manage incomplete grid geometries, so we have to skip
    if (!fullArea.isDefined(GridGeometry.ENVELOPE | GridGeometry.GRID_TO_CRS | GridGeometry.EXTENT)) {
        return areaOfInterest;
    }
    // on displayed area
    Envelope canvasEnv = areaOfInterest.getEnvelope();
    if (!applyResolution)
        resolution = null;
    // ///// HACK FOR 0/360 /////////////////////////////////////////////
    try {
        Map.Entry<Envelope, double[]> entry = solveWrapAround(fullArea, canvasEnv, resolution);
        if (entry != null) {
            canvasEnv = entry.getKey();
            resolution = applyResolution ? entry.getValue() : null;
        }
    } catch (ProjectionException ex) {
        // mays happen when displaying an area partialy outside
        // computation area of coverage crs
        LOGGER.log(Level.INFO, ex.getMessage(), ex);
    }
    // ///// HACK FOR 0/360 /////////////////////////////////////////////
    GridGeometry slice = fullArea;
    try {
        GridDerivation derivation = fullArea.derive().rounding(GridRoundingMode.ENCLOSING);
        if (margin != null && margin.length > 0)
            derivation = derivation.margin(margin);
        slice = derivation.subgrid(canvasEnv, resolution).sliceByRatio(1, 0, 1).build();
    } catch (DisjointExtentException ex) {
        throw new DisjointCoverageDomainException(ex.getMessage(), ex);
    } catch (IllegalGridGeometryException ex) {
        throw new DisjointCoverageDomainException(ex.getMessage(), ex);
    }
    return slice;
}
Also used : ProjectionException(org.apache.sis.referencing.operation.projection.ProjectionException) Arrays(java.util.Arrays) PixelIterator(org.apache.sis.image.PixelIterator) CRS(org.apache.sis.referencing.CRS) PixelInCell(org.opengis.referencing.datum.PixelInCell) Point(java.awt.Point) GridCoverageStack(org.geotoolkit.coverage.grid.GridCoverageStack) Envelope(org.opengis.geometry.Envelope) GridCoverage2D(org.apache.sis.coverage.grid.GridCoverage2D) SingleCRS(org.opengis.referencing.crs.SingleCRS) AbstractEnvelope(org.apache.sis.geometry.AbstractEnvelope) DisjointCoverageDomainException(org.geotoolkit.coverage.io.DisjointCoverageDomainException) GridDerivation(org.apache.sis.coverage.grid.GridDerivation) Map(java.util.Map) TransformException(org.opengis.referencing.operation.TransformException) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope) Utilities(org.apache.sis.util.Utilities) BufferedImage(java.awt.image.BufferedImage) RenderedImage(java.awt.image.RenderedImage) ResampleBorderComportement(org.geotoolkit.image.interpolation.ResampleBorderComportement) PassThroughTransform(org.apache.sis.referencing.operation.transform.PassThroughTransform) Logger(java.util.logging.Logger) List(java.util.List) ProjectedCoverage(org.geotoolkit.display2d.primitive.ProjectedCoverage) Envelopes(org.apache.sis.geometry.Envelopes) InterpolationCase(org.geotoolkit.image.interpolation.InterpolationCase) WritablePixelIterator(org.apache.sis.image.WritablePixelIterator) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) FactoryException(org.opengis.util.FactoryException) InterpolatedTransform(org.apache.sis.referencing.operation.transform.InterpolatedTransform) GridGeometry(org.apache.sis.coverage.grid.GridGeometry) MathTransforms(org.apache.sis.referencing.operation.transform.MathTransforms) BufferedImages(org.geotoolkit.image.BufferedImages) ArgumentChecks(org.apache.sis.util.ArgumentChecks) NoninvertibleTransformException(org.opengis.referencing.operation.NoninvertibleTransformException) ProjectedCRS(org.opengis.referencing.crs.ProjectedCRS) ArrayList(java.util.ArrayList) Level(java.util.logging.Level) RenderingContext2D(org.geotoolkit.display2d.canvas.RenderingContext2D) MatrixSIS(org.apache.sis.referencing.operation.matrix.MatrixSIS) ResampleDescriptor(org.geotoolkit.processing.coverage.resample.ResampleDescriptor) Raster(java.awt.image.Raster) ProcessException(org.geotoolkit.process.ProcessException) IllegalGridGeometryException(org.apache.sis.coverage.grid.IllegalGridGeometryException) CommonCRS(org.apache.sis.referencing.CommonCRS) DataStoreException(org.apache.sis.storage.DataStoreException) ResampleProcess(org.geotoolkit.processing.coverage.resample.ResampleProcess) GridCoverageResource(org.apache.sis.storage.GridCoverageResource) Matrix(org.opengis.referencing.operation.Matrix) Hashtable(java.util.Hashtable) ReducedGridCoverage(org.geotoolkit.coverage.ReducedGridCoverage) MapLayer(org.apache.sis.portrayal.MapLayer) CoordinateOperation(org.opengis.referencing.operation.CoordinateOperation) AbstractMap(java.util.AbstractMap) GridCoverage(org.apache.sis.coverage.grid.GridCoverage) MathTransform(org.opengis.referencing.operation.MathTransform) WritableRaster(java.awt.image.WritableRaster) DisjointExtentException(org.apache.sis.coverage.grid.DisjointExtentException) GridExtent(org.apache.sis.coverage.grid.GridExtent) CachedSymbolizer(org.geotoolkit.display2d.style.CachedSymbolizer) Symbolizer(org.opengis.style.Symbolizer) GridRoundingMode(org.apache.sis.coverage.grid.GridRoundingMode) CoverageUtilities(org.geotoolkit.internal.coverage.CoverageUtilities) GridGeometry(org.apache.sis.coverage.grid.GridGeometry) DisjointExtentException(org.apache.sis.coverage.grid.DisjointExtentException) Envelope(org.opengis.geometry.Envelope) AbstractEnvelope(org.apache.sis.geometry.AbstractEnvelope) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope) ProjectionException(org.apache.sis.referencing.operation.projection.ProjectionException) DisjointCoverageDomainException(org.geotoolkit.coverage.io.DisjointCoverageDomainException) TransformException(org.opengis.referencing.operation.TransformException) FactoryException(org.opengis.util.FactoryException) NoninvertibleTransformException(org.opengis.referencing.operation.NoninvertibleTransformException) ProcessException(org.geotoolkit.process.ProcessException) IllegalGridGeometryException(org.apache.sis.coverage.grid.IllegalGridGeometryException) DataStoreException(org.apache.sis.storage.DataStoreException) DisjointExtentException(org.apache.sis.coverage.grid.DisjointExtentException) ProjectionException(org.apache.sis.referencing.operation.projection.ProjectionException) GridDerivation(org.apache.sis.coverage.grid.GridDerivation) IllegalGridGeometryException(org.apache.sis.coverage.grid.IllegalGridGeometryException) DisjointCoverageDomainException(org.geotoolkit.coverage.io.DisjointCoverageDomainException) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) Map(java.util.Map) AbstractMap(java.util.AbstractMap)

Example 4 with CRS

use of org.apache.sis.referencing.CRS in project geotoolkit by Geomatys.

the class RenderingRoutines method prepareQuery.

/**
 * Creates an optimal query to send to the datastore, knowing which properties are knowned and
 * the appropriate bounding box to filter.
 */
public static Query prepareQuery(final RenderingContext2D renderingContext, FeatureSet fs, final MapLayer layer, final Set<String> styleRequieredAtts, final List<Rule> rules, double symbolsMargin) throws PortrayalException {
    final FeatureType schema;
    try {
        schema = fs.getType();
    } catch (DataStoreException ex) {
        throw new PortrayalException(ex.getMessage(), ex);
    }
    // Note: do not use layer boundary to define the target bbox, because it can be expensive.
    // Anyway, the target resource will be better to determine clipping between rendering boundaries and its own.
    final Envelope bbox = optimizeBBox(renderingContext, fs, symbolsMargin);
    final CoordinateReferenceSystem layerCRS = FeatureExt.getCRS(schema);
    final RenderingHints hints = renderingContext.getRenderingHints();
    /*
         * To restrict queried values to the rendering area, we must identify what geometries are used by the style.
         * For each applied symbol, there are 3 possible cases:
         * - if the rule uses default geometries, they will be added to the geometry property list after the loop
         * - The geometric expression is a value reference, we can safely register it in geometric properties. The
         *   reference xpath is unwrapped in a set to ensure we won't create any doublon filters.
         * - If the geometry property is a complex expression(Ex: a value computed from non geometric fields), we keep
         *   it as is to apply a filter directly upon it. Note that even if it's an expression derived from geometric
         *   fields, we cannot apply spatial filter on them, because the expression could drastically change topology.
         *   For example, if the expression is 'buffer', the result geometry would be larger than any of its operands.
         *   TODO: such cases are maybe manageable by replacing bbox filter by a distance filter based upon the buffer
         *   distance. But would it do more good than harm ?
         */
    boolean isDefaultGeometryNeeded = rules == null || rules.isEmpty();
    final Set<String> geomProperties = new HashSet<>();
    final Set<Expression> complexProperties = new HashSet<>();
    if (rules != null) {
        for (Rule r : rules) {
            for (Symbolizer s : r.symbolizers()) {
                final Expression expGeom = s.getGeometry();
                if (isNil(expGeom))
                    isDefaultGeometryNeeded = true;
                else if (expGeom instanceof ValueReference)
                    geomProperties.add(((ValueReference) expGeom).getXPath());
                else
                    complexProperties.add(expGeom);
            }
        }
    }
    if (isDefaultGeometryNeeded) {
        try {
            final PropertyType defaultGeometry = FeatureExt.getDefaultGeometry(schema);
            final String geomName = Features.getLinkTarget(defaultGeometry).orElseGet(() -> defaultGeometry.getName().toString());
            geomProperties.add(geomName);
        } catch (PropertyNotFoundException e) {
            throw new PortrayalException("Default geometry cannot be determined. " + "However, it is needed to properly define filtering rules.");
        } catch (IllegalStateException e) {
            // If there's multiple geometric properties, and no primary one, we will use them all
            schema.getProperties(true).stream().filter(p -> !Features.getLinkTarget(p).isPresent()).filter(AttributeConvention::isGeometryAttribute).map(p -> p.getName().toString()).forEach(geomProperties::add);
        }
    }
    if (!complexProperties.isEmpty()) {
        LOGGER.fine("A style rule uses complex geometric properties. It can severly affect performance");
    }
    final Optional<Filter> spatialFilter = Stream.concat(geomProperties.stream().map(FILTER_FACTORY::property), complexProperties.stream()).<Filter>map(expression -> FILTER_FACTORY.bbox(expression, bbox)).reduce(FILTER_FACTORY::or);
    Filter userFilter = null;
    // concatenate geographic filter with data filter if there is one
    if (layer != null) {
        Query query = layer.getQuery();
        if (query instanceof FeatureQuery) {
            userFilter = ((FeatureQuery) query).getSelection();
        }
    }
    Filter filter;
    if (spatialFilter.isPresent()) {
        if (userFilter == null)
            filter = spatialFilter.get();
        else
            // Note: we give priority to the spatial filter here, because it is our main use case: rendering is driven
            // by bounding box.
            filter = FILTER_FACTORY.and(spatialFilter.get(), userFilter);
    } else if (userFilter == null) {
        throw new PortrayalException("No spatial filter can be determined from style rules, and no user filter specified." + "We refuse dataset full-scan. To authorize it, manually specify Filter 'INCLUDE' on your map layer.");
    } else {
        LOGGER.warning("Spatial filter cannot be determined for rendering. However, user has provided a custom filter that we'll use as sole filtering policy");
        filter = userFilter;
    }
    final Set<String> copy = new HashSet<>();
    final FeatureType expected;
    final String[] atts;
    if (styleRequieredAtts == null) {
        // all properties are requiered
        expected = schema;
        atts = null;
    } else {
        final Set<String> attributs = styleRequieredAtts;
        copy.addAll(attributs);
        copy.addAll(geomProperties);
        try {
            // always include the identifier if it exist
            schema.getProperty(AttributeConvention.IDENTIFIER);
            copy.add(AttributeConvention.IDENTIFIER);
        } catch (PropertyNotFoundException ex) {
        // no id, ignore it
        }
        atts = copy.toArray(new String[copy.size()]);
        // then we reduce it to the first parent property.
        for (int i = 0; i < atts.length; i++) {
            String attName = atts[i];
            int index = attName.indexOf('/');
            if (index == 0) {
                // remove all xpath elements
                // remove first slash
                attName = attName.substring(1);
                final Pattern pattern = Pattern.compile("(\\{[^\\{\\}]*\\})|(\\[[^\\[\\]]*\\])|/{1}");
                final Matcher matcher = pattern.matcher(attName);
                final StringBuilder sb = new StringBuilder();
                int position = 0;
                while (matcher.find()) {
                    final String match = matcher.group();
                    sb.append(attName.substring(position, matcher.start()));
                    position = matcher.end();
                    if (match.charAt(0) == '/') {
                        // we don't query precisely sub elements
                        position = attName.length();
                        break;
                    } else if (match.charAt(0) == '{') {
                        sb.append(match);
                    } else if (match.charAt(0) == '[') {
                    // strip indexes or xpath searches
                    }
                }
                sb.append(attName.substring(position));
                atts[i] = sb.toString();
            }
        }
        try {
            expected = new ViewMapper(schema, atts).getMappedType();
        } catch (MismatchedFeatureException ex) {
            throw new PortrayalException(ex);
        }
    }
    // combine the filter with rule filters----------------------------------
    if (rules != null) {
        List<Filter<Object>> rulefilters = new ArrayList<>();
        for (Rule rule : rules) {
            if (rule.isElseFilter()) {
                // we can't append styling filters, an else rule match all features
                rulefilters = null;
                break;
            }
            final Filter rf = rule.getFilter();
            if (rf == null || rf == Filter.include()) {
                // we can't append styling filters, this rule matchs all features.
                rulefilters = null;
                break;
            }
            rulefilters.add(rf);
        }
        if (rulefilters != null) {
            final Filter combined;
            if (rulefilters.size() == 1) {
                // we can optimze here, since we pass the filter on the query, we can remove
                // the filter on the rule.
                final MutableRule mr = StyleUtilities.copy(rules.get(0));
                mr.setFilter(null);
                rules.set(0, mr);
                combined = rulefilters.get(0);
            } else {
                combined = FILTER_FACTORY.or(rulefilters);
            }
            if (filter != Filter.include()) {
                filter = FILTER_FACTORY.and(filter, combined);
            } else {
                filter = combined;
            }
        }
    }
    // optimize the filter---------------------------------------------------
    filter = FilterUtilities.prepare(filter, Feature.class, expected);
    final Hints queryHints = new Hints();
    final org.geotoolkit.storage.feature.query.Query qb = new org.geotoolkit.storage.feature.query.Query();
    qb.setTypeName(schema.getName());
    qb.setSelection(filter);
    qb.setProperties(atts);
    // resampling and ignore flag only works when we know the layer crs
    if (layerCRS != null) {
        // add resampling -------------------------------------------------------
        Boolean resample = (hints == null) ? null : (Boolean) hints.get(GO2Hints.KEY_GENERALIZE);
        if (!Boolean.FALSE.equals(resample)) {
            // we only disable resampling if it is explictly specified
            double[] res = renderingContext.getResolution(layerCRS);
            // adjust with the generalization factor
            final Number n = (hints == null) ? null : (Number) hints.get(GO2Hints.KEY_GENERALIZE_FACTOR);
            final double factor;
            if (n != null) {
                factor = n.doubleValue();
            } else {
                factor = GO2Hints.GENERALIZE_FACTOR_DEFAULT.doubleValue();
            }
            res[0] *= factor;
            res[1] *= factor;
            qb.setResolution(res);
            try {
                res = renderingContext.getResolution(CRS.forCode("EPSG:3395"));
                res[0] *= factor;
                res[1] *= factor;
                qb.setLinearResolution(Quantities.create(res[0], Units.METRE));
            } catch (FactoryException ex) {
                throw new PortrayalException(ex.getMessage(), ex);
            }
        }
    // add ignore flag ------------------------------------------------------
    // TODO this is efficient but erases values, when plenty of then are to be rendered
    // we should find another way to handle this
    // if(!GO2Utilities.visibleMargin(rules, 1.01f, renderingContext)){
    // //style does not expend itself further than the feature geometry
    // //that mean geometries smaller than a pixel will not be renderer or barely visible
    // queryHints.put(Hints.KEY_IGNORE_SMALL_FEATURES, renderingContext.getResolution(layerCRS));
    // }
    }
    // add reprojection -----------------------------------------------------
    // we don't reproject, the reprojection may produce curves but JTS can not represent those.
    // so we generate those curves in java2d shapes by doing the transformation ourself.
    // TODO wait for a new geometry implementation
    // qb.setCRS(renderingContext.getObjectiveCRS2D());
    // set the acumulated hints
    qb.setHints(queryHints);
    return qb;
}
Also used : Expression(org.opengis.filter.Expression) Hints(org.geotoolkit.factory.Hints) Envelope2D(org.apache.sis.geometry.Envelope2D) CRS(org.apache.sis.referencing.CRS) PortrayalException(org.geotoolkit.display.PortrayalException) RenderingHints(java.awt.RenderingHints) Envelope(org.opengis.geometry.Envelope) GeographicBoundingBox(org.opengis.metadata.extent.GeographicBoundingBox) FeatureType(org.opengis.feature.FeatureType) Matcher(java.util.regex.Matcher) ValueReference(org.opengis.filter.ValueReference) TransformException(org.opengis.referencing.operation.TransformException) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope) Feature(org.opengis.feature.Feature) Utilities(org.apache.sis.util.Utilities) MutableFeatureTypeStyle(org.geotoolkit.style.MutableFeatureTypeStyle) MismatchedFeatureException(org.opengis.feature.MismatchedFeatureException) Set(java.util.Set) FeatureIterator(org.geotoolkit.storage.feature.FeatureIterator) Literal(org.opengis.filter.Literal) FilterUtilities(org.geotoolkit.filter.FilterUtilities) List(java.util.List) Stream(java.util.stream.Stream) ProjectedFeature(org.geotoolkit.display2d.primitive.ProjectedFeature) FeatureExt(org.geotoolkit.feature.FeatureExt) Optional(java.util.Optional) Pattern(java.util.regex.Pattern) Rule(org.opengis.style.Rule) Envelopes(org.apache.sis.geometry.Envelopes) Query(org.apache.sis.storage.Query) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) FactoryException(org.opengis.util.FactoryException) MutableRule(org.geotoolkit.style.MutableRule) ViewMapper(org.geotoolkit.feature.ViewMapper) GO2Utilities(org.geotoolkit.display2d.GO2Utilities) ProjectedObject(org.geotoolkit.display2d.primitive.ProjectedObject) STYLE_FACTORY(org.geotoolkit.display2d.GO2Utilities.STYLE_FACTORY) FeatureQuery(org.apache.sis.storage.FeatureQuery) FILTER_FACTORY(org.geotoolkit.display2d.GO2Utilities.FILTER_FACTORY) FeatureTypeStyle(org.opengis.style.FeatureTypeStyle) ArrayList(java.util.ArrayList) Level(java.util.logging.Level) HashSet(java.util.HashSet) RenderingContext2D(org.geotoolkit.display2d.canvas.RenderingContext2D) LOGGER(org.geotoolkit.display2d.GO2Utilities.LOGGER) DataStoreException(org.apache.sis.storage.DataStoreException) CanvasMonitor(org.geotoolkit.display.canvas.control.CanvasMonitor) FeatureStoreRuntimeException(org.geotoolkit.storage.feature.FeatureStoreRuntimeException) GO2Hints(org.geotoolkit.display2d.GO2Hints) MutableStyle(org.geotoolkit.style.MutableStyle) Units(org.apache.sis.measure.Units) MapLayer(org.apache.sis.portrayal.MapLayer) Iterator(java.util.Iterator) Quantities(org.apache.sis.measure.Quantities) IOException(java.io.IOException) Features(org.apache.sis.feature.Features) PropertyNotFoundException(org.opengis.feature.PropertyNotFoundException) StyleUtilities(org.geotoolkit.style.StyleUtilities) PropertyType(org.opengis.feature.PropertyType) AttributeConvention(org.apache.sis.internal.feature.AttributeConvention) FeatureSet(org.apache.sis.storage.FeatureSet) Closeable(java.io.Closeable) Filter(org.opengis.filter.Filter) Symbolizer(org.opengis.style.Symbolizer) FeatureType(org.opengis.feature.FeatureType) PropertyNotFoundException(org.opengis.feature.PropertyNotFoundException) Query(org.apache.sis.storage.Query) FeatureQuery(org.apache.sis.storage.FeatureQuery) Hints(org.geotoolkit.factory.Hints) RenderingHints(java.awt.RenderingHints) GO2Hints(org.geotoolkit.display2d.GO2Hints) Matcher(java.util.regex.Matcher) FactoryException(org.opengis.util.FactoryException) ArrayList(java.util.ArrayList) PropertyType(org.opengis.feature.PropertyType) FeatureQuery(org.apache.sis.storage.FeatureQuery) Envelope(org.opengis.geometry.Envelope) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope) Feature(org.opengis.feature.Feature) ProjectedFeature(org.geotoolkit.display2d.primitive.ProjectedFeature) RenderingHints(java.awt.RenderingHints) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) HashSet(java.util.HashSet) ValueReference(org.opengis.filter.ValueReference) Pattern(java.util.regex.Pattern) DataStoreException(org.apache.sis.storage.DataStoreException) FILTER_FACTORY(org.geotoolkit.display2d.GO2Utilities.FILTER_FACTORY) ViewMapper(org.geotoolkit.feature.ViewMapper) Symbolizer(org.opengis.style.Symbolizer) MutableRule(org.geotoolkit.style.MutableRule) Expression(org.opengis.filter.Expression) Filter(org.opengis.filter.Filter) MismatchedFeatureException(org.opengis.feature.MismatchedFeatureException) Rule(org.opengis.style.Rule) MutableRule(org.geotoolkit.style.MutableRule) PortrayalException(org.geotoolkit.display.PortrayalException)

Example 5 with CRS

use of org.apache.sis.referencing.CRS in project geotoolkit by Geomatys.

the class SimpleUVSource method atOrigin.

@Override
public Optional<UVSource.TimeSet> atOrigin(DirectPosition origin) {
    final Instant time = getTime(origin).orElseThrow(() -> new IllegalArgumentException("Given position should contain time value"));
    final GridGeometry gg = getSourceGeometry();
    final GeneralEnvelope env = new GeneralEnvelope(gg.getEnvelope());
    boolean pointCrossData = subEnvelope(env, CRS::getHorizontalComponent).filter(subEnv -> {
        try {
            final DirectPosition geoloc = CRS.findOperation(origin.getCoordinateReferenceSystem(), subEnv.getCoordinateReferenceSystem(), null).getMathTransform().transform(origin, null);
            return subEnv.contains(geoloc);
        } catch (FactoryException | TransformException e) {
            throw new BackingStoreException("Cannot project source point in grid coverage horizontal system", e);
        }
    }).isPresent();
    // Short-circuit : no horizontal matching. Stop now
    if (!pointCrossData) {
        LOGGER.log(Level.FINE, "[SimpleUVSource] -> Short-circuit: Given origin {0} does not horizontally intersect envelope {1} of data {2}", new Object[] { origin, env, source });
        return Optional.empty();
    }
    final GeneralEnvelope timeEnv = subEnvelope(env, CRS::getTemporalComponent).orElseThrow(() -> new IllegalStateException("Source dataset has no temporal axis"));
    final DefaultTemporalCRS timeCrs = DefaultTemporalCRS.castOrCopy((TemporalCRS) timeEnv.getCoordinateReferenceSystem());
    timeEnv.getLowerCorner().setOrdinate(0, timeCrs.toValue(time));
    final GridDerivation subgrid = gg.derive().rounding(GridRoundingMode.ENCLOSING).subgrid(env);
    // Note: If input data has an elevation, we'll try to freeze it on a slice : either the one specified at origin, or an arbitrary one.
    final GridGeometry subGrid = freezeElevation(env, origin).map(subgrid::slice).orElse(subgrid).build();
    return Optional.of(new TimeSet(subGrid));
}
Also used : SampleDimension(org.apache.sis.coverage.SampleDimension) GridGeometry(org.apache.sis.coverage.grid.GridGeometry) CRS(org.apache.sis.referencing.CRS) Point2D(java.awt.geom.Point2D) MathTransforms(org.apache.sis.referencing.operation.transform.MathTransforms) PixelInCell(org.opengis.referencing.datum.PixelInCell) org.opengis.referencing.operation(org.opengis.referencing.operation) ArgumentChecks(org.apache.sis.util.ArgumentChecks) AffineTransform2D(org.apache.sis.internal.referencing.j2d.AffineTransform2D) Point(java.awt.Point) Function(java.util.function.Function) Envelope(org.opengis.geometry.Envelope) TemporalCRS(org.opengis.referencing.crs.TemporalCRS) Level(java.util.logging.Level) DirectPosition1D(org.apache.sis.geometry.DirectPosition1D) SingleCRS(org.opengis.referencing.crs.SingleCRS) GridDerivation(org.apache.sis.coverage.grid.GridDerivation) Raster(java.awt.image.Raster) AxisDirections(org.apache.sis.internal.referencing.AxisDirections) VerticalCRS(org.opengis.referencing.crs.VerticalCRS) ENCLOSING(org.apache.sis.coverage.grid.GridRoundingMode.ENCLOSING) DataStoreException(org.apache.sis.storage.DataStoreException) BackingStoreException(org.apache.sis.util.collection.BackingStoreException) GridCoverageResource(org.apache.sis.storage.GridCoverageResource) Utilities(org.geotoolkit.processing.science.drift.v2.Utilities) DirectPosition(org.opengis.geometry.DirectPosition) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope) DefaultTemporalCRS(org.apache.sis.referencing.crs.DefaultTemporalCRS) RenderedImage(java.awt.image.RenderedImage) Vector2d(org.geotoolkit.geometry.math.Vector2d) Instant(java.time.Instant) List(java.util.List) GridCoverage(org.apache.sis.coverage.grid.GridCoverage) Optional(java.util.Optional) GridExtent(org.apache.sis.coverage.grid.GridExtent) GridRoundingMode(org.apache.sis.coverage.grid.GridRoundingMode) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) FactoryException(org.opengis.util.FactoryException) PointOutsideCoverageException(org.opengis.coverage.PointOutsideCoverageException) GridGeometry(org.apache.sis.coverage.grid.GridGeometry) DirectPosition(org.opengis.geometry.DirectPosition) CRS(org.apache.sis.referencing.CRS) TemporalCRS(org.opengis.referencing.crs.TemporalCRS) SingleCRS(org.opengis.referencing.crs.SingleCRS) VerticalCRS(org.opengis.referencing.crs.VerticalCRS) DefaultTemporalCRS(org.apache.sis.referencing.crs.DefaultTemporalCRS) Instant(java.time.Instant) BackingStoreException(org.apache.sis.util.collection.BackingStoreException) GridDerivation(org.apache.sis.coverage.grid.GridDerivation) DefaultTemporalCRS(org.apache.sis.referencing.crs.DefaultTemporalCRS) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope)

Aggregations

List (java.util.List)5 CRS (org.apache.sis.referencing.CRS)5 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)5 FactoryException (org.opengis.util.FactoryException)5 ArrayList (java.util.ArrayList)3 Optional (java.util.Optional)3 Level (java.util.logging.Level)3 GeneralEnvelope (org.apache.sis.geometry.GeneralEnvelope)3 DataStoreException (org.apache.sis.storage.DataStoreException)3 ArgumentChecks (org.apache.sis.util.ArgumentChecks)3 Envelope (org.opengis.geometry.Envelope)3 Point (java.awt.Point)2 Raster (java.awt.image.Raster)2 RenderedImage (java.awt.image.RenderedImage)2 IOException (java.io.IOException)2 AbstractMap (java.util.AbstractMap)2 Spliterator (java.util.Spliterator)2 StreamSupport (java.util.stream.StreamSupport)2 GridCoverage (org.apache.sis.coverage.grid.GridCoverage)2 GridDerivation (org.apache.sis.coverage.grid.GridDerivation)2