This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch geoapi-3.1
in repository https://gitbox.apache.org/repos/asf/sis.git

commit b7f39770a226034d9fddcd1593a36db65b33954c
Merge: e3537fc7c1 ccf06de245
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri Aug 14 19:16:38 2026 +0200

    Merge branch 'geoapi-4.0' into geoapi-3.1

 .../apache/sis/buildtools/gradle/Dependency.java   |   3 +-
 .../org/apache/sis/console/HelpCommandTest.java    |   1 +
 .../org.apache.sis.feature/main/module-info.java   |   5 +
 .../sis/coverage/grid/ClippedGridCoverage.java     |   4 +-
 .../apache/sis/coverage/grid/GridCRSBuilder.java   | 156 +++--
 .../org/apache/sis/coverage/grid/GridCoverage.java |  17 +-
 .../apache/sis/coverage/grid/GridCoverage2D.java   | 100 ++-
 .../sis/coverage/grid/GridCoverageBuilder.java     |   6 +-
 .../apache/sis/coverage/grid/GridDerivation.java   |   2 +-
 .../org/apache/sis/coverage/grid/GridExtent.java   | 136 ++--
 .../org/apache/sis/coverage/grid/GridGeometry.java |  43 +-
 .../apache/sis/coverage/grid/ImageRenderer.java    | 121 +---
 .../apache/sis/coverage/grid/SliceGeometry.java    |   3 +-
 .../org/apache/sis/feature/AbstractFeature.java    |   5 -
 .../org/apache/sis/feature/internal/Resources.java |  15 +
 .../sis/feature/internal/Resources.properties      |   3 +
 .../sis/feature/internal/Resources_fr.properties   |   3 +
 .../main/org/apache/sis/image/BandSelectImage.java |   4 +-
 .../apache/sis/image/BandedSampleConverter.java    |   6 +-
 .../main/org/apache/sis/image/ComputedImage.java   |  12 +-
 .../main/org/apache/sis/image/ImageLayout.java     |  38 +-
 .../main/org/apache/sis/image/ImageOverlay.java    |   2 +-
 .../org/apache/sis/image/MultiSourcePrefetch.java  |   5 +-
 .../main/org/apache/sis/image/PlanarImage.java     | 128 ++--
 .../main/org/apache/sis/image/PrefetchedImage.java |   4 +-
 .../org/apache/sis/image/SourceAlignedImage.java   |   2 +-
 .../apache/sis/image/WritableComputedImage.java    |   8 +-
 .../org/apache/sis/image/internal/Summarizer.java  | 275 ++++++++
 .../apache/sis/image/internal}/package-info.java   |  14 +-
 .../image/internal/shared/BatchComputedImage.java  |  27 +-
 .../image/internal/shared/ColorModelFactory.java   |  54 +-
 .../image/internal/shared/DeferredProperty.java    |  47 +-
 .../sis/image/internal/shared/ImageUtilities.java  |  36 +-
 .../sis/image/internal/shared/RasterFactory.java   |  21 +-
 .../sis/image/internal/shared/ReshapedImage.java   | 115 +++-
 .../image/internal/shared/ScaledColorSpace.java    |  13 +-
 .../sis/image/internal/shared/TileOpExecutor.java  |   7 +-
 .../sis/image/internal/shared/TiledImage.java      |   6 +-
 .../image/internal/shared/WritableTiledImage.java  |  16 +-
 ...ervableImage.java => WritableUntiledImage.java} | 272 ++++++--
 .../apache/sis/coverage/grid/GridExtentTest.java   |  57 +-
 .../coverage/grid/ResampledGridCoverageTest.java   |   6 +-
 .../test/org/apache/sis/image/ImageLayoutTest.java |   9 +
 .../test/org/apache/sis/image/TiledImageMock.java  |  71 ++-
 .../image/internal/shared/ReshapedImageTest.java   |   5 +-
 .../org/apache/sis/metadata/AbstractMetadata.java  |   6 +-
 .../main/org/apache/sis/metadata/CacheKey.java     |   9 +-
 .../org/apache/sis/metadata/MetadataCopier.java    |   2 +-
 .../org/apache/sis/metadata/MetadataStandard.java  | 393 ++++++++----
 .../org/apache/sis/metadata/MetadataVisitor.java   |  15 +-
 .../apache/sis/metadata/ModifiableMetadata.java    |  46 +-
 .../org/apache/sis/metadata/PropertyAccessor.java  |   3 +-
 .../main/org/apache/sis/metadata/Pruner.java       |   4 +-
 .../main/org/apache/sis/metadata/StateChanger.java |   2 +-
 .../main/org/apache/sis/metadata/TreeNode.java     |  10 +-
 .../apache/sis/metadata/UnresolvedTypePolicy.java} |  40 +-
 .../apache/sis/metadata/internal/Resources.java    |   5 +
 .../sis/metadata/internal/Resources.properties     |   1 +
 .../sis/metadata/internal/Resources_fr.properties  |   1 +
 .../sis/metadata/internal/shared/Merger.java       |  88 ++-
 .../iso/extent/DefaultGeographicBoundingBox.java   |   2 +-
 .../main/org/apache/sis/metadata/package-info.java |   2 +-
 .../sis/metadata/sql/internal/shared/Dialect.java  |  43 +-
 .../metadata/sql/internal/shared/SQLBuilder.java   |  11 +-
 .../sis/metadata/sql/internal/shared/Supports.java |   7 +-
 .../org/apache/sis/util/iso/DefaultRecordType.java |   2 +-
 .../apache/sis/xml/bind/cat/CodeListAdapter.java   |   2 +-
 .../test/org/apache/sis/metadata/HashCodeTest.java |   4 +-
 .../apache/sis/metadata/InformationMapTest.java    |   1 +
 .../apache/sis/metadata/MetadataStandardTest.java  |  28 +-
 .../test/org/apache/sis/metadata/NameMapTest.java  |   1 +
 .../test/org/apache/sis/metadata/PrunerTest.java   |   1 +
 .../org/apache/sis/metadata/SpecialCasesTest.java  |   1 +
 .../apache/sis/metadata/TreeNodeChildrenTest.java  |   2 +-
 .../test/org/apache/sis/metadata/TypeMapTest.java  |   1 +
 .../sis/metadata/internal/shared/MergerTest.java   |  24 +-
 .../org/apache/sis/map/coverage/RenderingData.java |  24 +-
 .../apache/sis/map/coverage/RenderingDataTest.java | 256 ++++++++
 .../main/module-info.java                          |   1 +
 .../main/org/apache/sis/geometry/Envelopes.java    |  51 +-
 .../org/apache/sis/parameter/MatrixParameters.java |   2 +-
 .../sis/referencing/datum/DatumOrEnsemble.java     |   2 +-
 .../operation/CoordinateOperationContext.java      |   6 +-
 .../operation/CoordinateOperationFinder.java       |  32 +-
 .../referencing/operation/SubOperationInfo.java    |  40 +-
 .../operation/provider/DatumShiftMethod.java       |   6 +-
 .../transform/AbstractLinearTransform.java         |   7 +-
 .../operation/transform/PassThroughTransform.java  |   6 +-
 .../operation/transform/TransformJoiner.java       |  11 +-
 .../org/apache/sis/storage/geotiff/DataSubset.java |   2 +-
 .../org/apache/sis/storage/netcdf/base/Axis.java   |  23 +-
 .../apache/sis/storage/netcdf/base/Variable.java   |   7 +
 .../sis/storage/netcdf/ucar/VariableWrapper.java   |  22 +-
 .../sis/storage/sql/feature/SelectionClause.java   |  77 ++-
 .../storage/sql/feature/SelectionClauseWriter.java |  35 +-
 .../sis/storage/sql/postgis/RasterReader.java      |   4 +-
 .../org/apache/sis/storage/sql/SQLStoreTest.java   |  20 +-
 .../org/apache/sis/storage/gpx/MetadataTest.java   |   8 +-
 .../org/apache/sis/storage/gpx/ReaderTest.java     |  85 ++-
 .../org.apache.sis.storage/main/module-info.java   |   6 +-
 .../main/org/apache/sis/storage/DataStore.java     |   4 +-
 .../main/org/apache/sis/storage/Resource.java      |   4 +-
 .../sis/storage/aggregate/JoinFeatureSet.java      |   7 +-
 .../apache/sis/storage/aggregate/package-info.java |   2 +-
 .../org/apache/sis/storage/esri/RasterStore.java   |  13 +-
 .../sis/storage/event/CascadedStoreEvent.java      |   2 +-
 .../apache/sis/storage/event/StoreListener.java    |   6 +-
 .../apache/sis/storage/event/StoreListeners.java   |  16 +-
 .../sis/storage/metadata/MetadataBuilder.java      |   2 +-
 .../sis/storage/tiling/ArtificiallyTiledImage.java | 261 ++++++++
 .../apache/sis/storage/tiling/ImageTileMatrix.java |   2 +-
 .../apache/sis/storage/tiling/TileReadEvent.java   |  63 +-
 .../sis/storage/tiling/TiledDeferredImage.java     |   2 +-
 .../sis/storage/tiling/TiledGridCoverage.java      |  10 +-
 .../storage/tiling/TiledGridCoverageResource.java  | 547 +++++++++++++---
 .../org/apache/sis/storage/DataStoreTestCase.java  |   4 +-
 .../sis/storage/event/StoreListenersTest.java      |   6 +-
 .../src/org.apache.sis.util/main/module-info.java  |   2 +
 .../main/org/apache/sis/math/Statistics.java       |   3 +
 .../main/org/apache/sis/util/Classes.java          |   9 +-
 .../sis/util/collection/WeakValueHashMap.java      |   4 +-
 .../apache/sis/util/internal/shared/Numerics.java  |   2 +-
 .../main/org/apache/sis/util/resources/Errors.java |   5 +
 .../apache/sis/util/resources/Errors.properties    |   1 +
 .../apache/sis/util/resources/Errors_fr.properties |   1 +
 .../sis/util/resources/IndexedResourceBundle.java  |  14 +-
 .../org/apache/sis/util/resources/Messages.java    |   5 +
 .../apache/sis/util/resources/Messages.properties  |   1 +
 .../sis/util/resources/Messages_fr.properties      |   3 +-
 .../org/apache/sis/util/resources/Vocabulary.java  |  25 +-
 .../sis/util/resources/Vocabulary.properties       |   5 +-
 .../sis/util/resources/Vocabulary_fr.properties    |   7 +-
 .../apache/sis/util/collection/RangeSetTest.java   |   4 +-
 incubator/build.gradle.kts                         |  33 +-
 .../org.apache.sis.geometries.processor.Processor  |  28 -
 .../org.apache.sis.geometry/main/module-info.java  |  30 +-
 .../org/apache/sis/geometries/BoundaryType.java    |   3 +-
 .../sis/geometries/ParametricCurveSurface.java     |   4 -
 .../main/org/apache/sis/geometries/Polygon.java    |   3 +-
 .../main/org/apache/sis/geometries/Sphere.java     |  18 +
 .../geometries/csg/ConstructiveSolidGeometry.java  |  39 +-
 .../sis/geometries/ellipsoidal}/package-info.java  |   6 +-
 .../sis/geometries/math/ArrayFactoryHAT.java       | 255 ++++++++
 .../org/apache/sis/geometries/math/Vector3D.java   |  29 +
 .../geometries/operation/GeometryOperations.java   |  33 +-
 .../geometries/polyhedron/AbstractPolyhedron.java  | 189 ++++++
 .../sis/geometries/polyhedron/Dodecahedron.java    |  90 +++
 .../sis/geometries/polyhedron/Hexahedron.java      |  68 ++
 .../sis/geometries/polyhedron/Icosahedron.java     |  90 +++
 .../sis/geometries/polyhedron/Octahedron.java      |  68 ++
 .../polyhedron/RhombicTriacontahedron.java         | 127 ++++
 .../sis/geometries/polyhedron/Tetrahedron.java     |  62 ++
 .../polyhedron/TruncatedIcosahedron.java           | 176 ++++++
 .../{scene => polyhedron}/package-info.java        |  17 +-
 .../org/apache/sis/geometries/scene/Material.java  | 628 ------------------
 .../sis/geometries/spherical/GreatCircleArc.java   |  79 +++
 .../spherical/SphericalConvexPolygon.java          |  85 +++
 .../geometries/spherical/SphericalTriangle.java    | 183 ++++++
 .../sis/geometries/spherical}/package-info.java    |   6 +-
 .../org/apache/sis/geometries/spirals/Spiral.java  |   2 +-
 .../geometries/splinesurfaces/BSplineSurface.java  |   1 -
 .../sis/{geometries => }/scene/Animation.java      |   2 +-
 .../{geometries => }/scene/AnimationSampler.java   |   2 +-
 .../apache/sis/{geometries => }/scene/Camera.java  |   2 +-
 .../apache/sis/{geometries => }/scene/Model.java   |   3 +-
 .../sis/{geometries => }/scene/MorphTarget.java    |   2 +-
 .../apache/sis/{geometries => }/scene/Sampler.java |   2 +-
 .../sis/{geometries => }/scene/SceneNode.java      |  31 +-
 .../main/org/apache/sis/scene/SceneUtilities.java} |  30 +-
 .../apache/sis/{geometries => }/scene/Skin.java    |   2 +-
 .../apache/sis/{geometries => }/scene/Surface.java |   6 +-
 .../apache/sis/{geometries => }/scene/Texture.java |   2 +-
 .../org/apache/sis/scene/light/Directional.java    | 107 ++++
 .../main/org/apache/sis/scene/light/HDRI.java      | 128 ++++
 .../main/org/apache/sis/scene/light/Light.java     |  77 +++
 .../main/org/apache/sis/scene/light/Point.java     | 131 ++++
 .../main/org/apache/sis/scene/light/Quad.java      | 157 +++++
 .../main/org/apache/sis/scene/light/Ring.java      | 172 +++++
 .../main/org/apache/sis/scene/light/Spot.java      | 154 +++++
 .../org/apache/sis/scene/material/BlinnPhong.java  | 198 ++++++
 .../org/apache/sis/scene/material/Material.java    | 209 ++++++
 .../main/org/apache/sis/scene/material/PBR.java    | 342 ++++++++++
 .../main/org/apache/sis/scene/material/PBRSG.java  | 203 ++++++
 .../sis/{geometries => }/scene/package-info.java   |   2 +-
 .../{geometries => }/scene/physics/Collider.java   |   2 +-
 .../scene/physics/ColliderGeometry.java            |   2 +-
 .../scene/physics/CollisionFilter.java             |   2 +-
 .../sis/{geometries => }/scene/physics/Joint.java  |   4 +-
 .../sis/{geometries => }/scene/physics/Motion.java |   2 +-
 .../scene/physics/PhysicalMaterial.java            |   2 +-
 .../{geometries => }/scene/physics/Trigger.java    |   4 +-
 .../scene/physics/package-info.java                |   2 +-
 .../apache/sis/geometries/math/Vector3DTest.java   | 108 ++++
 .../geometries/spherical/GreatCircleArcTest.java   |  62 ++
 .../spherical/SphericalConvexPolygonTest.java      |  89 +++
 .../spherical/SphericalTriangleTest.java           | 145 +++++
 .../org/apache/sis/scene/SceneUtilitiesTest.java   |  62 ++
 ...g.dggs.DiscreteGlobalGridReferenceSystemFactory |   1 +
 .../main/module-info.java                          |  41 ++
 .../sis/referencing/dggs/DiscreteGlobalGrid.java   | 139 ++++
 .../dggs/DiscreteGlobalGridHierarchy.java          | 135 ++++
 .../dggs/DiscreteGlobalGridReferenceSystem.java    | 157 +++++
 .../DiscreteGlobalGridReferenceSystemFactory.java  |  56 ++
 .../dggs/DiscreteGlobalGridReferenceSystems.java   | 221 +++++++
 .../referencing/dggs/DiscreteGlobalGridSystem.java |  87 +++
 .../sis/referencing/dggs/GridConstraints.java      | 124 ++++
 .../referencing/dggs/PolyhedronOrientation.java    |  56 ++
 .../referencing/dggs/PolyhedronParameters.java}    |  24 +-
 .../sis/referencing/dggs/RefinementLevel.java      |  98 +++
 .../sis/referencing/dggs/RefinementStrategy.java   | 133 ++++
 .../apache/sis/referencing/dggs/SubZoneOrder.java  | 114 ++++
 .../sis/referencing/dggs/ZonalReferenceSystem.java |  47 ++
 .../main/org/apache/sis/referencing/dggs/Zone.java | 230 +++++++
 .../shared/AbstractDiscreteGlobalGrid.java         | 132 ++++
 .../AbstractDiscreteGlobalGridHierarchy.java       |  57 ++
 .../shared/AbstractDiscreteGlobalGridSystem.java   |  55 ++
 .../dggs/internal/shared/AbstractZone.java         | 145 +++++
 .../dggs/internal/shared/AuthalicSphere.java       | 134 ++++
 .../shared/DefaultZonalReferenceSystem.java}       |  35 +-
 .../apache/sis/referencing/dggs/package-info.java  |  35 +
 .../apache/sis/referencing/dggs/s2/S2Coder.java    |  83 +++
 .../org/apache/sis/referencing/dggs/s2/S2Dgg.java  | 138 ++++
 .../org/apache/sis/referencing/dggs/s2/S2Dggh.java |  95 +++
 .../apache/sis/referencing/dggs/s2/S2Dggrs.java    | 131 ++++
 .../org/apache/sis/referencing/dggs/s2/S2Dggs.java |  85 +++
 .../apache/sis/referencing/dggs/s2/S2Factory.java  |  55 ++
 .../org/apache/sis/referencing/dggs/s2/S2Zone.java | 154 +++++
 .../main/org/apache/sis/referencing/rs/Code.java   | 197 ++++++
 .../apache/sis/referencing/rs/CodeOperation.java   | 104 +++
 .../org/apache/sis/referencing/rs/CompoundRS.java  | 207 ++++++
 .../sis/referencing/rs/ReferenceSystems.java       | 264 ++++++++
 .../rs/internal/shared/CodeOperations.java         | 518 +++++++++++++++
 .../apache/sis/referencing/rs}/package-info.java   |   7 +-
 .../sis/storage/coverage/BandedCoverageExt.java}   |  32 +-
 .../storage/coverage/BandedCoverageResource.java   | 226 +++++++
 .../sis/storage/coverage/CoverageUtilities.java    |  65 ++
 .../apache/sis/storage/coverage/FeatureExt.java    | 241 +++++++
 .../dggs/DiscreteGlobalGridCoverageProcessor.java  | 702 +++++++++++++++++++++
 .../storage/dggs/DiscreteGlobalGridGeometry.java   | 400 ++++++++++++
 .../storage/dggs/DiscreteGlobalGridResource.java   | 128 ++++
 .../storage/dggs/DiscreteGlobalGridSystems.java    | 325 ++++++++++
 .../storage/dggs/DiscreteGlobalGridTransform.java  | 411 ++++++++++++
 .../shared/AbstractDiscreteGlobalGridCoverage.java | 164 +++++
 .../shared/ArrayDiscreteGlobalGridCoverage.java    | 171 +++++
 ...ingTiledDiscreteGlobalGridCoverageResource.java | 160 +++++
 .../internal/shared/ComputedZoneIndexList.java     | 162 +++++
 .../FeatureSetAsDiscreteGlobalGridResource.java    | 181 ++++++
 .../shared/GridAsDiscreteGlobalGridResource.java   | 140 ++++
 .../shared/IndexedDiscreteGlobalGridCoverage.java  | 266 ++++++++
 .../shared/MemoryDiscreteGlobalGridResource.java   |  73 +++
 .../shared/RasterDiscreteGlobalGridCoverage.java   | 172 +++++
 .../shared/TiledDiscreteGlobalGridCoverage.java    | 315 +++++++++
 .../TiledDiscreteGlobalGridCoverageResource.java   | 120 ++++
 ...leTiledDiscreteGlobalGridCoverageResource.java} |  15 +-
 .../sis/storage/image/internal/ImageBuilder.java   | 226 +++++++
 .../sis/storage/image/internal/MergeOperator.java} |   7 +-
 .../org/apache/sis/storage/rs/CodeIterator.java    | 125 ++++
 .../org/apache/sis/storage/rs/CodeTransform.java}  |  17 +-
 .../org/apache/sis/storage/rs/CodedCoverage.java   | 204 ++++++
 .../org/apache/sis/storage/rs/CodedCoverages.java  |  60 ++
 .../org/apache/sis/storage/rs/CodedGeometry.java   | 384 +++++++++++
 .../org/apache/sis/storage/rs/CodedResource.java   | 177 ++++++
 .../sis/storage/rs/CompoundCodedGeometry.java      | 103 +++
 .../sis/storage/rs/WritableCodeIterator.java       |  91 +++
 .../rs/internal/shared/AbstractCodedCoverage.java  | 397 ++++++++++++
 .../rs/internal/shared/AddDimCodedCoverage.java    | 201 ++++++
 .../rs/internal/shared/AddDimCodedResource.java    | 108 ++++
 .../rs/internal/shared/ArrayCodedCoverage.java     | 203 ++++++
 .../storage/rs/internal/shared/CodeTransforms.java | 458 ++++++++++++++
 .../internal/shared/CodedCoverageAsFeatureSet.java | 282 +++++++++
 .../rs/internal/shared/CompoundCodedCoverage.java  | 118 ++++
 .../rs/internal/shared/CompoundCodedResource.java  | 254 ++++++++
 .../rs/internal/shared/GridAsCodedResource.java    | 306 +++++++++
 .../rs/internal/shared/MemoryCodedResource.java    |  65 ++
 .../rs/internal/shared/ResampledCodedCoverage.java | 159 +++++
 .../storage/rs/internal/shared/SubTransform.java   |  47 ++
 .../sis/storage/rs/internal/shared/s2/Factory.java | 323 ++++++++++
 .../sis/storage/rs/internal/shared/s2/S2.java      | 268 ++++++++
 .../sis/storage/rs/internal/shared/s2/Wrapper.java |  97 +++
 .../sis/referencing/dggs/AbstractDggrsTest.java    | 252 ++++++++
 .../org/apache/sis/referencing/dggs/s2/S2Test.java |  61 ++
 .../sis/referencing/rs/CodeOperationTest.java      | 175 +++++
 .../rs/ArrayReferencedGridCoverageTest.java        | 184 ++++++
 .../coveragejson/binding/CategoryEncoding.java     |  82 ---
 .../storage/coveragejson/binding/Dictionary.java   |  73 ---
 .../sis/storage/coveragejson/binding/I18N.java     | 125 ----
 .../storage/coveragejson/binding/Parameters.java   |  78 ---
 .../sis/storage/coveragejson/binding/Ranges.java   |  74 ---
 .../org.apache.sis.storage.DataStoreProvider       |   0
 .../main/module-info.java                          |  27 +-
 .../storage/coveragejson/CoverageJsonStore.java    |  17 +-
 .../coveragejson/CoverageJsonStoreProvider.java    |   0
 .../sis/storage/coveragejson/CoverageResource.java |  18 +-
 .../sis/storage/coveragejson/binding/Axe.java      |   9 +-
 .../sis/storage/coveragejson/binding/Axes.java     |  16 +-
 .../sis/storage/coveragejson/binding/Category.java |  10 +-
 .../coveragejson/binding/CategoryEncoding.java}    |  16 +-
 .../sis/storage/coveragejson/binding/Coverage.java |  47 +-
 .../coveragejson/binding/CoverageCollection.java   |  10 +-
 .../coveragejson/binding/CoverageJsonObject.java   |  37 +-
 .../sis/storage/coveragejson/binding/Domain.java   |   7 +-
 .../coveragejson/binding/GeographicCRS.java        |   7 +-
 .../sis/storage/coveragejson/binding/I18N.java     |  77 +++
 .../storage/coveragejson/binding/IdentifierRS.java |  10 +-
 .../sis/storage/coveragejson/binding/NdArray.java  |   7 +-
 .../coveragejson/binding/ObservedProperty.java     |   9 +-
 .../storage/coveragejson/binding/Parameter.java    |   7 +-
 .../coveragejson/binding/ParameterGroup.java       |   7 +-
 .../storage/coveragejson/binding/ProjectedCRS.java |   7 +-
 .../binding/ReferenceSystemConnection.java         |   9 +-
 .../sis/storage/coveragejson/binding/Symbol.java   |   9 +-
 .../coveragejson/binding/TargetConcept.java        |   9 +-
 .../storage/coveragejson/binding/TemporalRS.java   |   7 +-
 .../sis/storage/coveragejson/binding/TileSet.java  |   9 +-
 .../storage/coveragejson/binding/TiledNdArray.java |   9 +-
 .../sis/storage/coveragejson/binding/Unit.java     |   9 +-
 .../storage/coveragejson/binding/VerticalCRS.java  |   7 +-
 .../storage/coveragejson/binding/package-info.java |   0
 .../sis/storage/coveragejson/package-info.java     |   0
 .../org/apache/sis/storage/geojson/GeoJSON.java    | 165 +++++
 .../apache/sis/storage/geojson/GeoJSONMapper.java  | 481 ++++++++++++++
 .../storage/geojson/binding/GeoJSONFeature.java    | 318 ++++++++++
 .../geojson/binding/GeoJSONFeatureCollection.java  | 322 ++++++++++
 .../storage/geojson/binding/GeoJSONGeometry.java   | 134 ++++
 .../geojson/binding/GeoJSONGeometryCollection.java |  84 +++
 .../storage/geojson/binding/GeoJSONLineString.java |  85 +++
 .../geojson/binding/GeoJSONMultiLineString.java    |  85 +++
 .../storage/geojson/binding/GeoJSONMultiPoint.java |  85 +++
 .../geojson/binding/GeoJSONMultiPolygon.java       |  85 +++
 .../sis/storage/geojson/binding/GeoJSONObject.java | 104 +++
 .../sis/storage/geojson/binding/GeoJSONPoint.java  |  88 +++
 .../storage/geojson/binding/GeoJSONPolygon.java    |  85 +++
 .../geojson/binding/JSONFGCircularString.java      |  88 +++
 .../geojson/binding/JSONFGCompoundCurve.java       |  88 +++
 .../storage/geojson/binding/JSONFGCoordRefSys.java | 131 ++++
 .../geojson/binding/JSONFGCurvePolygon.java        |  89 +++
 .../storage/geojson/binding/JSONFGMeasures.java    | 123 ++++
 .../storage/geojson/binding/JSONFGMultiCurve.java  |  89 +++
 .../geojson/binding/JSONFGMultiPolyhedron.java     |  85 +++
 .../storage/geojson/binding/JSONFGMultiPrism.java  |  85 +++
 .../geojson/binding/JSONFGMultiSurface.java        |  88 +++
 .../storage/geojson/binding/JSONFGPolyhedron.java  |  86 +++
 .../sis/storage/geojson/binding/JSONFGPrism.java   | 127 ++++
 .../sis/storage/geojson/binding/JSONFGTime.java    | 124 ++++
 .../sis/storage/geojson/binding}/package-info.java |  12 +-
 .../sis/storage/json/DataTransferObject.java       | 100 +++
 .../movingfeature/binding/MFCoordRefSys.java       | 110 ++++
 .../movingfeature/binding/MFMovingFeature.java     | 277 ++++++++
 .../binding/MFMovingFeatureCollection.java         | 270 ++++++++
 .../binding/MFMovingGeometryBase.java              | 101 +++
 .../binding/MFMovingGeometryCollection.java        |  93 +++
 .../movingfeature/binding/MFMovingLineString.java  |  87 +++
 .../movingfeature/binding/MFMovingPoint.java       |  86 +++
 .../movingfeature/binding/MFMovingPointCloud.java  |  89 +++
 .../movingfeature/binding/MFMovingPolygon.java     |  88 +++
 .../movingfeature/binding/MFOrientation.java       | 103 +++
 .../movingfeature/binding/MFTemporalGeometry.java  | 128 ++++
 .../binding/MFTemporalPrimitiveGeometry.java       | 152 +++++
 .../binding/MFTemporalPropertyGroup.java           |  94 +++
 .../binding/MFTemporalPropertyValue.java           | 186 ++++++
 .../movingfeature/binding}/package-info.java       |  11 +-
 .../main/org/apache/sis/storage/ogcjson/Link.java  | 280 ++++++++
 .../apache/sis/storage/ogcjson}/package-info.java  |   6 +-
 .../coveragejson/CoverageJsonStoreTest.java        |   0
 .../storage/coveragejson/binding/BindingTest.java  |  69 +-
 .../sis/storage/coveragejson/binding/LICENSE.md    |   0
 .../storage/coveragejson/binding/axe_bounds.json   |   0
 .../storage/coveragejson/binding/axe_polygon.json  |   0
 .../storage/coveragejson/binding/axe_regular.json  |   0
 .../storage/coveragejson/binding/axe_tuples.json   |   0
 .../binding/coverage_vertical_profile.json         |   0
 .../binding/coverage_vertical_profile_nocs.json    |   0
 .../coveragejson/binding/coveragecollection.json   |   0
 .../storage/coveragejson/binding/domain_grid.json  |   0
 .../coveragejson/binding/domain_trajectory.json    |   0
 .../coveragejson/binding/domaintype_grid.json      |   0
 .../binding/domaintype_multipoint.json             |   0
 .../binding/domaintype_multipointseries.json       |   0
 .../binding/domaintype_multipolygon.json           |   0
 .../binding/domaintype_multipolygonseries.json     |   0
 .../coveragejson/binding/domaintype_point.json     |   0
 .../binding/domaintype_pointseries.json            |   0
 .../coveragejson/binding/domaintype_polygon.json   |   0
 .../binding/domaintype_polygonseries.json          |   0
 .../coveragejson/binding/domaintype_section.json   |   0
 .../binding/domaintype_trajectory.json             |   0
 .../binding/domaintype_vertical_profile.json       |   0
 .../binding/geographiccrs_longlat.json             |   0
 .../binding/geographiccrs_longlatheight.json       |   0
 .../sis/storage/coveragejson/binding/ndarray.json  |   0
 .../binding/parameter_categoricaldata.json         |   0
 .../binding/parameter_continuousdata.json          |   0
 .../binding/parametergroup_uncertainty.json        |   0
 .../binding/parametergroup_vectorquantity.json     |   0
 .../binding/projectedcrs_britishnationalgrid.json  |   0
 .../binding/reference_system_connection.json       |   0
 .../storage/coveragejson/binding/temporalrs.json   |   0
 .../storage/coveragejson/binding/tiledndarray.json |   0
 .../coveragejson/binding/verticalcrs_navd88.json   |   0
 .../sis/storage/coveragejson/coverage_xyzt.json    |   0
 .../sis/storage/geojson/binding/BindingTest.java}  |  13 +-
 .../storage/geojson/binding/geojson_feature.json   |  10 +
 .../geojson/binding/geojson_featurecollection.json |  48 ++
 .../binding/geojson_geometrycollection.json        |  13 +
 .../geojson/binding/geojson_linestring.json        |   7 +
 .../geojson/binding/geojson_multilinestring.json   |  13 +
 .../geojson/binding/geojson_multipoint.json        |   7 +
 .../geojson/binding/geojson_multipolygon.json      |  30 +
 .../sis/storage/geojson/binding/geojson_point.json |   4 +
 .../storage/geojson/binding/geojson_polygon.json   |  12 +
 .../binding/jsonfg_circularstring_measures.json    |  13 +
 .../binding/jsonfg_circularstring_no_measures.json |   8 +
 .../binding/jsonfg_compoundcurve_measures.json     |  25 +
 .../binding/jsonfg_compoundcurve_no_measures.json  |  20 +
 .../geojson/binding/jsonfg_coordrefsys.json        |  18 +
 .../binding/jsonfg_curvepolygon_measures.json      |  20 +
 .../binding/jsonfg_curvepolygon_no_measures.json   |  15 +
 .../storage/geojson/binding/jsonfg_feature.json    |  49 ++
 .../jsonfg_geometrycollection_measures.json        |  21 +
 .../jsonfg_geometrycollection_no_measures.json     |  16 +
 .../binding/jsonfg_linestring_measures.json        |  12 +
 .../binding/jsonfg_linestring_no_measures.json     |   7 +
 .../binding/jsonfg_multicurve_measures.json        |  25 +
 .../binding/jsonfg_multicurve_no_measures.json     |  20 +
 .../binding/jsonfg_multilinestring_measures.json   |  18 +
 .../jsonfg_multilinestring_no_measures.json        |  13 +
 .../binding/jsonfg_multipoint_measures.json        |  12 +
 .../binding/jsonfg_multipoint_no_measures.json     |   7 +
 .../binding/jsonfg_multipolygon_measures.json      |  35 +
 .../binding/jsonfg_multipolygon_no_measures.json   |  30 +
 .../binding/jsonfg_multipolyhedron_measures.json   |  23 +
 .../jsonfg_multipolyhedron_no_measures.json        |  18 +
 .../binding/jsonfg_multiprism_measures.json        |  27 +
 .../binding/jsonfg_multiprism_no_measures.json     |  22 +
 .../binding/jsonfg_multisurface_measures.json      |  37 ++
 .../binding/jsonfg_multisurface_no_measures.json   |  32 +
 .../geojson/binding/jsonfg_point_measures.json     |   9 +
 .../geojson/binding/jsonfg_point_no_measures.json  |   4 +
 .../geojson/binding/jsonfg_polygon_measures.json   |  17 +
 .../binding/jsonfg_polygon_no_measures.json        |  12 +
 .../binding/jsonfg_polyhedron_measures.json        |  21 +
 .../binding/jsonfg_polyhedron_no_measures.json     |  16 +
 .../geojson/binding/jsonfg_prism_measures.json     |  22 +
 .../geojson/binding/jsonfg_prism_no_measures.json  |  17 +
 .../storage/geojson/binding/jsonfg_time_date.json  |  15 +
 .../geojson/binding/jsonfg_time_interval.json      |  18 +
 .../binding/jsonfg_time_interval_open_end.json     |  18 +
 .../binding/jsonfg_time_interval_open_start.json   |  18 +
 .../geojson/binding/jsonfg_time_timestamp.json     |  15 +
 .../sis/storage/json/AbstractBindingTest.java      |  76 +++
 .../movingfeature/binding/BindingTest.java}        |  13 +-
 netbeans-project/ivy.xml                           |   6 +
 netbeans-project/nbproject/project.properties      |   2 +-
 .../apache/sis/gui/coverage/CoverageCanvas.java    | 211 ++-----
 .../apache/sis/gui/coverage/CoverageControls.java  |   2 +-
 .../apache/sis/gui/coverage/CoverageExplorer.java  |   2 +-
 .../org/apache/sis/gui/coverage/GridControls.java  |   2 +-
 .../main/org/apache/sis/gui/coverage/GridView.java |   2 +-
 .../apache/sis/gui/coverage/RectangleMerger.java   | 111 ++++
 .../sis/gui/coverage/StyledRenderingData.java      |   5 +
 .../apache/sis/gui/coverage/TileReadListener.java  | 327 ++++++++++
 .../org/apache/sis/gui/dataset/WindowHandler.java  |   2 +-
 .../org/apache/sis/gui/internal/LogHandler.java    |   2 +-
 .../apache/sis/gui/internal/ShapeConverter.java    |   5 +-
 .../org/apache/sis/gui/map/EvanescentPane.java     |   1 +
 .../main/org/apache/sis/gui/map/MapCanvas.java     |  40 +-
 .../main/org/apache/sis/gui/map/MultiCanvas.java   |   2 +-
 .../org/apache/sis/gui/map/ValuesFormatter.java    |   7 +-
 .../org/apache/sis/gui/map/ValuesUnderCursor.java  |   2 +-
 .../org/apache/sis/storage/gdal/TiledResource.java |  16 +-
 settings.gradle.kts                                |   1 +
 471 files changed, 28807 insertions(+), 2775 deletions(-)

diff --cc 
endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
index 965cc63358,764ba76372..c692d2cbca
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/SubOperationInfo.java
@@@ -31,7 -31,13 +31,10 @@@ import org.apache.sis.referencing.inter
  import org.apache.sis.referencing.operation.matrix.Matrices;
  import org.apache.sis.referencing.operation.matrix.MatrixSIS;
  import org.apache.sis.referencing.operation.transform.MathTransforms;
+ import org.apache.sis.measure.NumberRange;
+ import org.apache.sis.util.Classes;
+ import org.apache.sis.util.internal.shared.Strings;
  
 -// Specific to the geoapi-4.0 branch:
 -import org.apache.sis.referencing.legacy.DefaultImageCRS;
 -
  
  /**
   * Information about the operation from a source component to a target 
component in {@code CompoundCRS} instances.
diff --cc 
incubator/src/org.apache.sis.referencing.dggs/main/org/apache/sis/referencing/rs/CompoundRS.java
index 0000000000,7e8b8b26ee..c467a7e6f7
mode 000000,100644..100644
--- 
a/incubator/src/org.apache.sis.referencing.dggs/main/org/apache/sis/referencing/rs/CompoundRS.java
+++ 
b/incubator/src/org.apache.sis.referencing.dggs/main/org/apache/sis/referencing/rs/CompoundRS.java
@@@ -1,0 -1,207 +1,207 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ package org.apache.sis.referencing.rs;
+ 
+ import java.util.List;
+ import java.util.ArrayList;
+ import java.util.LinkedList;
+ import java.util.Collections;
+ import java.util.Objects;
 -import org.apache.sis.metadata.iso.DefaultIdentifier;
++import org.apache.sis.referencing.NamedIdentifier;
+ import org.apache.sis.referencing.CRS;
+ import org.apache.sis.referencing.CommonCRS;
+ import org.apache.sis.referencing.gazetteer.ReferencingByIdentifiers;
+ import org.apache.sis.referencing.dggs.DiscreteGlobalGridReferenceSystem;
 -import org.opengis.metadata.Identifier;
++import org.opengis.referencing.ReferenceIdentifier;
+ import org.opengis.referencing.ReferenceSystem;
+ import org.opengis.referencing.crs.CompoundCRS;
+ import org.opengis.referencing.crs.CoordinateReferenceSystem;
+ import org.opengis.referencing.crs.SingleCRS;
+ import org.opengis.util.FactoryException;
+ 
+ 
+ /**
+  * A <abbr>RS</abbr> describing the position of points through two or more 
independent <abbr>RS</abbr>s.
+  * Two <abbr>RS</abbr>s are independent of each other if coordinate values in 
one cannot be converted or
+  * transformed into coordinate values in the other.
+  *
+  * <p>This interface is a generalized version of CompoundCRS.</p>
+  *
+  * @author Johann Sorel (Geomatys)
+  */
+ public final class CompoundRS implements ReferenceSystem {
+ 
 -    private final Identifier name;
++    private final ReferenceIdentifier name;
+     private final List<ReferenceSystem> rss;
+     private final CoordinateReferenceSystem leaningCrs;
+ 
 -    public CompoundRS(Identifier name, List<ReferenceSystem> rss) {
++    public CompoundRS(ReferenceIdentifier name, List<ReferenceSystem> rss) {
+         if (rss.size() < 2) {
+             throw new IllegalArgumentException("Provide at least two systems 
to create a CompoundRS.");
+         }
+ 
+         if (name == null) {
+             final StringBuilder sb = new StringBuilder("CompundLS [");
+             for (int i = 0, n = rss.size(); i < n; i++) {
+                 final ReferenceSystem cdt = rss.get(i);
+                 if (i != 0) sb.append(',');
+                 sb.append(cdt.getName().toString());
+             }
+             sb.append(']');
 -            name = new DefaultIdentifier(sb.toString());
++            name = new NamedIdentifier(null, sb.toString());
+         }
+         this.name = name;
+         this.rss = Collections.unmodifiableList(rss);
+ 
+         final List<CoordinateReferenceSystem> crss = new 
ArrayList<>(rss.size()+1);
+         for (int i = 0; i < rss.size(); i++) {
+             final ReferenceSystem srs = rss.get(i);
+             if (srs instanceof CoordinateReferenceSystem crs) {
+                 crss.add(crs);
+             } else if (srs instanceof DiscreteGlobalGridReferenceSystem 
dggrs) {
+                 crss.add(dggrs.getGridSystem().getCrs());
+             } else if (srs instanceof ReferencingByIdentifiers rbi) {
+                 crss.add(CommonCRS.WGS84.normalizedGeographic());
+             } else {
+                 throw new UnsupportedOperationException("todo");
+             }
+         }
+         try {
+             leaningCrs = 
CRS.compound(crss.toArray(CoordinateReferenceSystem[]::new));
+         } catch (FactoryException ex) {
+             throw new IllegalArgumentException(ex);
+         }
+     }
+ 
+     /**
+      * {@inheritDoc }
+      */
+     @Override
 -    public Identifier getName() {
++    public ReferenceIdentifier getName() {
+         return name;
+     }
+ 
+     /**
+      * Returns the ordered list of <abbr>RS</abbr> components.
+      * The returned list may contain nested compound <abbr>RS</abbr>.
+      * For a list without nesting, as required by ISO 19111, see {@link 
#getSingleComponents()}.
+      *
+      * @return the ordered list of components of this compound 
<abbr>RS</abbr>.
+      */
+     public List<ReferenceSystem> getComponents() {
+         return rss;
+     }
+ 
+     /**
+      * Returns the ordered list of <abbr>CRS</abbr> components, none of which 
itself compound.
+      * If this compound <abbr>CRS</abbr> contains nested compound 
<abbr>CRS</abbr> components,
+      * then those components are flattened recursively in a sequence of 
{@link SingleCRS} objects.
+      *
+      * @return the ordered list of components of this compound 
<abbr>CRS</abbr>, none of which itself compound.
+      *
+      * @since 3.1
+      */
+     public List<ReferenceSystem> getSingleComponents() {
+         var singles = new ArrayList<ReferenceSystem>(5);
+         flatten(singles, new LinkedList<>());   // Linked list is cheap to 
construct and efficient with 0 or 1 element.
+         return Collections.unmodifiableList(singles);
+     }
+ 
+ 
+     public synchronized CoordinateReferenceSystem getLeaningCrs() {
+         return leaningCrs;
+     }
+ 
+     /**
+      * Appends recursively all single components in the given list.
+      *
+      * @param  singles  the list where to add single components.
+      * @param  safety   a safety against infinite recursive method calls.
+      * @throws IllegalStateException if recursive components are detected.
+      */
+     private void flatten(final List<ReferenceSystem> singles, final 
List<Object> safety) {
+         for (ReferenceSystem rs : getComponents()) {
+             if (rs instanceof SingleCRS) {
+                 singles.add((SingleCRS) rs);
+             } else  if (rs instanceof ReferencingByIdentifiers) {
+                 singles.add(rs);
+             } else if (rs instanceof CompoundRS) {
+                 final CompoundRS r = (CompoundRS) rs;
+                 for (Object previous : safety) {
+                     if (previous == this) {
+                         throw new IllegalStateException("Recursive components 
detected.");
+                     }
+                 }
+                 safety.add(this);
+                 singles.addAll(r.getSingleComponents());
+ 
+             } else if (rs instanceof CompoundCRS) {
+                 final CompoundCRS r = (CompoundCRS) rs;
+                 //todo CompoundCRS should be a CompoundRS
+                 for (Object previous : safety) {
+                     if (previous == this) {
+                         throw new IllegalStateException("Recursive components 
detected.");
+                     }
+                 }
+                 safety.add(this);
+                 singles.addAll(r.getSingleComponents());
+             } else {
+                 throw new IllegalArgumentException("Unknown reference system 
type : " + rs.getName());
+             }
+         }
+     }
+ 
+     @Override
+     public String toString() {
+         final StringBuilder sb = new StringBuilder("CompoundRS[ " + 
name.toString()+" ");
+         final List<ReferenceSystem> components = getComponents();
+         for (int i = 0, n = components.size(); i < n; i++) {
+             if (i > 0)sb.append(',');
+             final ReferenceSystem rs = components.get(i);
+             sb.append(rs.toString().replaceAll("\n", "    \n"));
+         }
+         sb.append(']');
+         return sb.toString();
+     }
+ 
+     @Override
+     public int hashCode() {
+         int hash = 5;
+         hash = 23 * hash + Objects.hashCode(this.name);
+         hash = 23 * hash + Objects.hashCode(this.rss);
+         return hash;
+     }
+ 
+     @Override
+     public boolean equals(Object obj) {
+         if (this == obj) {
+             return true;
+         }
+         if (obj == null) {
+             return false;
+         }
+         if (getClass() != obj.getClass()) {
+             return false;
+         }
+         final CompoundRS other = (CompoundRS) obj;
+         if (!Objects.equals(this.name, other.name)) {
+             return false;
+         }
+         return Objects.equals(this.rss, other.rss);
+     }
+ 
+ }
diff --cc 
incubator/src/org.apache.sis.referencing.dggs/main/org/apache/sis/referencing/rs/internal/shared/CodeOperations.java
index 0000000000,00bcba9af7..24e502c6e7
mode 000000,100644..100644
--- 
a/incubator/src/org.apache.sis.referencing.dggs/main/org/apache/sis/referencing/rs/internal/shared/CodeOperations.java
+++ 
b/incubator/src/org.apache.sis.referencing.dggs/main/org/apache/sis/referencing/rs/internal/shared/CodeOperations.java
@@@ -1,0 -1,518 +1,518 @@@
+ /*
+  * Licensed to the Apache Software Foundation (ASF) under one or more
+  * contributor license agreements.  See the NOTICE file distributed with
+  * this work for additional information regarding copyright ownership.
+  * The ASF licenses this file to You under the Apache License, Version 2.0
+  * (the "License"); you may not use this file except in compliance with
+  * the License.  You may obtain a copy of the License at
+  *
+  *     http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+ package org.apache.sis.referencing.rs.internal.shared;
+ 
+ import java.util.Arrays;
+ import org.apache.sis.referencing.CRS;
+ import org.apache.sis.referencing.NamedIdentifier;
+ import org.apache.sis.referencing.gazetteer.ReferencingByIdentifiers;
+ import org.apache.sis.referencing.rs.Code;
+ import org.apache.sis.referencing.rs.CodeOperation;
+ import org.apache.sis.referencing.rs.ReferenceSystems;
+ import org.apache.sis.util.iso.Names;
+ import org.opengis.geometry.DirectPosition;
 -import org.opengis.metadata.Identifier;
++import org.opengis.referencing.ReferenceIdentifier;
+ import org.opengis.referencing.ReferenceSystem;
+ import org.opengis.referencing.crs.CoordinateReferenceSystem;
+ import org.opengis.referencing.gazetteer.Location;
+ import org.opengis.referencing.operation.CoordinateOperation;
+ import org.opengis.referencing.operation.MathTransform;
+ import org.opengis.referencing.operation.NoninvertibleTransformException;
+ import org.opengis.referencing.operation.TransformException;
+ import org.opengis.util.FactoryException;
+ 
+ /**
+  *
+  * @author Johann Sorel (Geomatys)
+  */
+ public final class CodeOperations {
+ 
+     private CodeOperations(){}
+ 
+     public static CodeOperation identity(ReferenceSystem sourceRs, 
ReferenceSystem targetRs) {
+         return new Identity(sourceRs, targetRs);
+     }
+ 
+     public static CodeOperation RbiToCrs(ReferencingByIdentifiers.Coder 
coder) throws FactoryException {
+         return new RbiToCrs(coder);
+     }
+ 
+     public static CodeOperation CrsToRbi(ReferencingByIdentifiers.Coder 
coder) throws FactoryException {
+         return new CrsToRbi(coder);
+     }
+ 
+     public static CodeOperation CrsToCrs(CoordinateOperation op) throws 
FactoryException {
+         return new CrsToCrs(op);
+     }
+ 
+     public static CodeOperation concatenate(CodeOperation op1, CodeOperation 
op2) throws FactoryException {
+         if (op1 instanceof Identity) return op2;
+         if (op2 instanceof Identity) return op1;
+         return new Concatenate(op1, op2);
+     }
+ 
+     public static CodeOperation concatenate(CodeOperation... ops) throws 
FactoryException {
+         if (ops.length == 1) return ops[0];
+         CodeOperation cop = concatenate(ops[0], ops[1]);
+         for (int i = 2; i < ops.length; i++) {
+             cop = concatenate(cop, ops[i]);
+         }
+         return cop;
+     }
+ 
+     public static CodeOperation compound(CodeOperation op1, CodeOperation 
op2) throws FactoryException {
+         return new Compound(op1, op2, null, null);
+     }
+ 
+     public static CodeOperation compound(CodeOperation... ops) throws 
FactoryException {
+         if (ops.length == 1) return ops[0];
+         CodeOperation cop = compound(ops[0], ops[1]);
+         for (int i = 2; i < ops.length; i++) {
+             cop = compound(cop, ops[i], null, null);
+         }
+         return cop;
+     }
+ 
+     public static CodeOperation reorder(ReferenceSystem sourceRs, 
ReferenceSystem targetRs, int[] targetMapping) {
+         return new Reorder(sourceRs, targetRs, targetMapping);
+     }
+ 
+     public static final class Identity implements CodeOperation {
+ 
+         private final ReferenceSystem sourceRs;
+         private final ReferenceSystem targetRs;
+ 
+         public Identity(ReferenceSystem sourceRs, ReferenceSystem targetRs) {
+             this.sourceRs = sourceRs;
+             this.targetRs = targetRs;
+         }
+ 
+         @Override
+         public ReferenceSystem getSourceRS() {
+             return sourceRs;
+         }
+ 
+         @Override
+         public ReferenceSystem getTargetRS() {
+             return targetRs;
+         }
+ 
+         @Override
+         public CodeOperation inverse() throws NoninvertibleTransformException 
{
+             return new Identity(targetRs, sourceRs);
+         }
+ 
+         @Override
+         public Code transform(Code source, Code target) throws 
TransformException {
+             if (target == null) return new Code(targetRs, 
source.getOrdinates());
+             target.setOrdinates(source.getOrdinates());
+             return target;
+         }
+ 
+         @Override
+         public void transform(Code[] source, int soffset, Code[] target, int 
toffset, int nb) throws TransformException {
+             for (int i = 0; i < nb; i++) {
+                 target[toffset+i] = transform(source[soffset+i], 
target[toffset+i]);
+             }
+         }
+ 
+         @Override
 -        public Identifier getName() {
++        public ReferenceIdentifier getName() {
+             return new NamedIdentifier(Names.createLocalName(null, null, 
"Identity"));
+         }
+ 
+         @Override
+         public String toString() {
+             return "Identity";
+         }
+ 
+     }
+ 
+     public static final class Reorder implements CodeOperation {
+ 
+         private final ReferenceSystem sourceRs;
+         private final ReferenceSystem targetRs;
+         private final int[] targetMapping;
+ 
+         public Reorder(ReferenceSystem sourceRs, ReferenceSystem targetRs, 
int[] targetMapping) {
+             this.sourceRs = sourceRs;
+             this.targetRs = targetRs;
+             this.targetMapping = targetMapping;
+         }
+ 
+         @Override
+         public ReferenceSystem getSourceRS() {
+             return sourceRs;
+         }
+ 
+         @Override
+         public ReferenceSystem getTargetRS() {
+             return targetRs;
+         }
+ 
+         public int[] getTargetMapping() {
+             return targetMapping.clone();
+         }
+ 
+         @Override
+         public CodeOperation inverse() throws NoninvertibleTransformException 
{
+             if (targetMapping.length != 
ReferenceSystems.getDimension(sourceRs)) {
+                 throw new NoninvertibleTransformException();
+             }
+             final int[] inv = new int[targetMapping.length];
+             for (int i = 0; i < targetMapping.length; i++) {
+                 inv[targetMapping[i]] = i;
+             }
+             return new Reorder(targetRs, sourceRs, inv);
+         }
+ 
+         @Override
+         public Code transform(Code source, Code target) throws 
TransformException {
+             if (target == null) return new Code(targetRs);
+             target.setOrdinates(source.getOrdinates());
+             return target;
+         }
+ 
+         @Override
+         public void transform(Code[] source, int soffset, Code[] target, int 
toffset, int nb) throws TransformException {
+             for (int i = 0; i < nb; i++) {
+                 target[toffset+i] = transform(source[soffset+i], 
target[toffset+i]);
+             }
+         }
+ 
+         @Override
 -        public Identifier getName() {
++        public ReferenceIdentifier getName() {
+             return new NamedIdentifier(Names.createLocalName(null, null, 
"Reorder"));
+         }
+ 
+         @Override
+         public String toString() {
+             return "Reorder \n  targetMapping : "+ 
Arrays.toString(targetMapping);
+         }
+     }
+ 
+     public static final class RbiToCrs implements CodeOperation {
+ 
+         private final ReferencingByIdentifiers.Coder coder;
+         private final CoordinateReferenceSystem leaningCrs;
+ 
+         public RbiToCrs(ReferencingByIdentifiers.Coder coder, 
CoordinateReferenceSystem leaningCrs) {
+             this.coder = coder;
+             this.leaningCrs = leaningCrs;
+         }
+ 
+         public RbiToCrs(ReferencingByIdentifiers.Coder coder) throws 
FactoryException {
+             this(coder, 
ReferenceSystems.getLeaningCRS(coder.getReferenceSystem()));
+         }
+ 
+         @Override
+         public ReferenceSystem getSourceRS() {
+             return coder.getReferenceSystem();
+         }
+ 
+         @Override
+         public ReferenceSystem getTargetRS() {
+             return leaningCrs;
+         }
+ 
+         @Override
+         public CodeOperation inverse() throws NoninvertibleTransformException 
{
+             return new CrsToRbi(leaningCrs, coder);
+         }
+ 
+         @Override
+         public Code transform(Code source, Code target) throws 
TransformException {
+             final Location location = coder.decode((CharSequence) 
source.getOrdinate(0));
+             if (target == null) target = new Code(leaningCrs, new Object[1]);
+             target.setOrdinate(0, location.getPosition());
+             return target;
+         }
+ 
+         @Override
+         public void transform(Code[] source, int soffset, Code[] target, int 
toffset, int nb) throws TransformException {
+             for (int i = 0; i < nb; i++) {
+                 target[toffset+i] = transform(source[soffset+i], 
target[toffset+i]);
+             }
+         }
+ 
+         @Override
 -        public Identifier getName() {
++        public ReferenceIdentifier getName() {
+             return new NamedIdentifier(Names.createLocalName(null, null, 
getSourceRS().getName().getCode() + " to " + leaningCrs.getName().toString()));
+         }
+ 
+         @Override
+         public String toString() {
+             return "ReferenceByIdentifiers to leaning CRS"
+                     + "\n  Source : " + 
getSourceRS().toString().replaceAll("\n", "\n    ")
+                     + "\n  Target : " + 
getTargetRS().toString().replaceAll("\n", "\n    ");
+         }
+     }
+ 
+     public static final class CrsToCrs implements CodeOperation {
+ 
+         private final CoordinateOperation op;
+         private final MathTransform transform;
+ 
+         public CrsToCrs(CoordinateOperation op) {
+             this.op = op;
+             transform = op.getMathTransform();
+         }
+ 
+         @Override
+         public ReferenceSystem getSourceRS() {
+             return op.getSourceCRS();
+         }
+ 
+         @Override
+         public ReferenceSystem getTargetRS() {
+             return op.getTargetCRS();
+         }
+ 
+         @Override
+         public CodeOperation inverse() throws NoninvertibleTransformException 
{
+             try {
+                 return new CrsToCrs(CRS.findOperation(op.getTargetCRS(), 
op.getSourceCRS(), null));
+             } catch (FactoryException ex) {
+                 throw new NoninvertibleTransformException(ex);
+             }
+         }
+ 
+         @Override
+         public Code transform(Code source, Code target) throws 
TransformException {
+             final DirectPosition dp = transform.transform((DirectPosition) 
source.getOrdinate(0), null);
+             if (target == null) target = new Code(getTargetRS(), new 
Object[1]);
+             target.setOrdinate(0, dp);
+             return target;
+         }
+ 
+         @Override
+         public void transform(Code[] source, int soffset, Code[] target, int 
toffset, int nb) throws TransformException {
+             for (int i = 0; i < nb; i++) {
+                 target[toffset+i] = transform(source[soffset+i], 
target[toffset+i]);
+             }
+         }
+ 
+         @Override
 -        public Identifier getName() {
++        public ReferenceIdentifier getName() {
+             return new NamedIdentifier(Names.createLocalName(null, null, 
getSourceRS().getName().toString() + " to " + 
getTargetRS().getName().getCode()));
+         }
+ 
+         @Override
+         public String toString() {
+             return "Crs to CRS"
+                     + "\n  Source : " + 
getSourceRS().toString().replaceAll("\n", "\n    ")
+                     + "\n  Target : " + 
getTargetRS().toString().replaceAll("\n", "\n    ");
+         }
+     }
+ 
+     public static final class CrsToRbi implements CodeOperation {
+ 
+         private final ReferencingByIdentifiers.Coder coder;
+         private final CoordinateReferenceSystem leaningCrs;
+ 
+         public CrsToRbi(ReferencingByIdentifiers.Coder coder) throws 
FactoryException {
+             this(ReferenceSystems.getLeaningCRS(coder.getReferenceSystem()), 
coder);
+         }
+ 
+         public CrsToRbi(CoordinateReferenceSystem leaningCrs, 
ReferencingByIdentifiers.Coder coder) {
+             this.leaningCrs = leaningCrs;
+             this.coder = coder;
+         }
+ 
+         @Override
+         public ReferenceSystem getSourceRS() {
+             return leaningCrs;
+         }
+ 
+         @Override
+         public ReferenceSystem getTargetRS() {
+             return coder.getReferenceSystem();
+         }
+ 
+         @Override
+         public CodeOperation inverse() throws NoninvertibleTransformException 
{
+             return new RbiToCrs(coder, leaningCrs);
+         }
+ 
+         @Override
+         public Code transform(Code source, Code target) throws 
TransformException {
+             final String code = coder.encode((DirectPosition) 
source.getOrdinate(0));
+             if (target == null) target = new Code(coder.getReferenceSystem(), 
new Object[1]);
+             target.setOrdinate(0, code);
+             return target;
+         }
+ 
+         @Override
+         public void transform(Code[] source, int soffset, Code[] target, int 
toffset, int nb) throws TransformException {
+             for (int i = 0; i < nb; i++) {
+                 target[toffset+i] = transform(source[soffset+i], 
target[toffset+i]);
+             }
+         }
+ 
+         @Override
 -        public Identifier getName() {
++        public ReferenceIdentifier getName() {
+             return new NamedIdentifier(Names.createLocalName(null, null, 
leaningCrs.getName().toString() + " to " + getTargetRS().getName().getCode()));
+         }
+ 
+         @Override
+         public String toString() {
+             return "Leaning CRS to ReferenceByIdentifiers "
+                     + "\n  Source : " + 
getSourceRS().toString().replaceAll("\n", "\n    ")
+                     + "\n  Target : " + 
getTargetRS().toString().replaceAll("\n", "\n    ");
+         }
+     }
+ 
+     public static final class Concatenate implements CodeOperation {
+ 
+         private final CodeOperation op1;
+         private final CodeOperation op2;
+ 
+         public Concatenate(CodeOperation op1, CodeOperation op2) {
+             this.op1 = op1;
+             this.op2 = op2;
+         }
+ 
+         @Override
+         public ReferenceSystem getSourceRS() {
+             return op1.getSourceRS();
+         }
+ 
+         @Override
+         public ReferenceSystem getTargetRS() {
+             return op2.getTargetRS();
+         }
+ 
+         public CodeOperation getOperation1() {
+             return op1;
+         }
+ 
+         public CodeOperation getOperation2() {
+             return op2;
+         }
+ 
+         @Override
+         public CodeOperation inverse() throws NoninvertibleTransformException 
{
+             return new Concatenate(op2.inverse(), op1.inverse());
+         }
+ 
+         @Override
+         public Code transform(Code source, Code target) throws 
TransformException {
+             final Code r = op1.transform(source, null);
+             return op2.transform(r, target);
+         }
+ 
+         @Override
+         public void transform(Code[] source, int soffset, Code[] target, int 
toffset, int nb) throws TransformException {
+             for (int i = 0; i < nb; i++) {
+                 target[toffset+i] = transform(source[soffset+i], 
target[toffset+i]);
+             }
+         }
+ 
+         @Override
 -        public Identifier getName() {
++        public ReferenceIdentifier getName() {
+             return new NamedIdentifier(Names.createLocalName(null, null, 
"Concatenate"));
+         }
+ 
+         @Override
+         public String toString() {
+             return "Concatenate "
+                     + "\n  First : " + op1.toString().replaceAll("\n", "\n    
")
+                     + "\n  Second : " + op2.toString().replaceAll("\n", "\n   
 ");
+         }
+     }
+ 
+     public static final class Compound implements CodeOperation {
+ 
+         private final ReferenceSystem sourceRS;
+         private final ReferenceSystem targetRS;
+         private final CodeOperation op1;
+         private final CodeOperation op2;
+         private final int dim1;
+         private final int dim2;
+         private final int dimRes;
+ 
+         public Compound(CodeOperation op1, CodeOperation op2, ReferenceSystem 
sourceRS, ReferenceSystem targetRS) {
+             this.sourceRS = sourceRS == null ? 
ReferenceSystems.createCompound(op1.getSourceRS(), op2.getSourceRS()) : 
sourceRS;
+             this.targetRS = targetRS == null ? 
ReferenceSystems.createCompound(op1.getTargetRS(), op2.getTargetRS()) : 
sourceRS;
+             this.op1 = op1;
+             this.op2 = op2;
+             this.dim1 = ReferenceSystems.getDimension(op1.getSourceRS());
+             this.dim2 = ReferenceSystems.getDimension(op2.getSourceRS());
+             this.dimRes = ReferenceSystems.getDimension(this.targetRS);
+         }
+ 
+         @Override
+         public ReferenceSystem getSourceRS() {
+             return sourceRS;
+         }
+ 
+         @Override
+         public ReferenceSystem getTargetRS() {
+             return targetRS;
+         }
+ 
+         public CodeOperation getOperation1() {
+             return op1;
+         }
+ 
+         public CodeOperation getOperation2() {
+             return op2;
+         }
+ 
+         @Override
+         public CodeOperation inverse() throws NoninvertibleTransformException 
{
+             return new Compound(op1.inverse(), op2.inverse(), targetRS, 
sourceRS);
+         }
+ 
+         @Override
+         public Code transform(Code source, Code target) throws 
TransformException {
+             final Object[] ordinates = source.getOrdinates();
+             final Code s1 = new Code(op1.getSourceRS(), 
Arrays.copyOfRange(ordinates, 0, dim1));
+             final Code s2 = new Code(op2.getSourceRS(), 
Arrays.copyOfRange(ordinates, dim1, dim1+dim2));
+             final Code r1 = op1.transform(s1, null);
+             final Code r2 = op2.transform(s2, null);
+             if (target == null) target = new Code(targetRS, new 
Object[dimRes]);
+             int k = 0;
+             for (int i = 0, n = r1.getDimension(); i < n; i++) {
+                 target.setOrdinate(k++, r1.getOrdinate(i));
+             }
+             for (int i = 0, n = r2.getDimension(); i < n; i++) {
+                 target.setOrdinate(k++, r2.getOrdinate(i));
+             }
+             return target;
+         }
+ 
+         @Override
+         public void transform(Code[] source, int soffset, Code[] target, int 
toffset, int nb) throws TransformException {
+             for (int i = 0; i < nb; i++) {
+                 target[toffset+i] = transform(source[soffset+i], 
target[toffset+i]);
+             }
+         }
+ 
+         @Override
 -        public Identifier getName() {
++        public ReferenceIdentifier getName() {
+             return new NamedIdentifier(Names.createLocalName(null, null, 
"Compound"));
+         }
+ 
+         @Override
+         public String toString() {
+             return "Compound "
+                     + "\n  First : " + op1.toString().replaceAll("\n", "\n    
")
+                     + "\n  Second : " + op2.toString().replaceAll("\n", "\n   
 ");
+         }
+     }
+ }

Reply via email to