aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2021-08-19 10:11:47 +0200
committergithub-actions[bot] <github-actions[bot]@users.noreply.github.com>2021-08-19 08:34:01 +0000
commitdff8e5df3f5e80a88590fc87aca17b39008289cc (patch)
tree0a5e285a6383537a8318a5d2bc01a36ab8ac5e2a
parentb8ab9150834257bcb197ca73b5a81eef7becdbdc (diff)
downloadPROJ-dff8e5df3f5e80a88590fc87aca17b39008289cc.tar.gz
PROJ-dff8e5df3f5e80a88590fc87aca17b39008289cc.zip
Merge pull request #2814 from rouault/fix_2813
BoundCRS: accept importing/exporting in WKT2 and PROJJSON the scope/area/extent/id attributes (fixes #2813)
-rw-r--r--data/projjson.schema.json14
-rw-r--r--docs/source/apps/cct.rst2
-rw-r--r--docs/source/apps/cs2cs.rst2
-rw-r--r--docs/source/apps/projinfo.rst2
-rw-r--r--docs/source/development/reference/functions.rst2
-rw-r--r--include/proj/crs.hpp5
-rw-r--r--include/proj/io.hpp6
-rw-r--r--schemas/v0.3/projjson.schema.json997
-rw-r--r--scripts/reference_exported_symbols.txt1
-rw-r--r--src/iso19111/crs.cpp53
-rw-r--r--src/iso19111/io.cpp54
-rw-r--r--test/unit/test_crs.cpp87
-rw-r--r--test/unit/test_io.cpp127
13 files changed, 1316 insertions, 36 deletions
diff --git a/data/projjson.schema.json b/data/projjson.schema.json
index bdb97bd5..c347b3e1 100644
--- a/data/projjson.schema.json
+++ b/data/projjson.schema.json
@@ -1,7 +1,7 @@
{
- "$id": "https://proj.org/schemas/v0.2/projjson.schema.json",
+ "$id": "https://proj.org/schemas/v0.3/projjson.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
- "description": "Schema for PROJJSON (v0.2.1)",
+ "description": "Schema for PROJJSON (v0.3)",
"$comment": "This file exists both in data/ and in schemas/vXXX/. Keep both in sync. And if changing the value of $id, change PROJJSON_CURRENT_VERSION accordingly in io.cpp",
"oneOf": [
@@ -111,12 +111,20 @@
"bound_crs": {
"type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
"properties": {
"$schema" : { "type": "string" },
"type": { "type": "string", "enum": ["BoundCRS"] },
+ "name": { "type": "string" },
"source_crs": { "$ref": "#/definitions/crs" },
"target_crs": { "$ref": "#/definitions/crs" },
- "transformation": { "$ref": "#/definitions/abridged_transformation" }
+ "transformation": { "$ref": "#/definitions/abridged_transformation" },
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
},
"required" : [ "source_crs", "target_crs", "transformation" ],
"additionalProperties": false
diff --git a/docs/source/apps/cct.rst b/docs/source/apps/cct.rst
index 700261fa..75d67972 100644
--- a/docs/source/apps/cct.rst
+++ b/docs/source/apps/cct.rst
@@ -29,7 +29,7 @@ by :c:func:`proj_create`, provided it expresses a coordinate operation
uniqueness is not guaranteed, heuristics are applied to determine the appropriate best match.
- a OGC URN combining references for concatenated operations
(e.g. "urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,coordinateOperation:EPSG::1618")
- - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.2/projjson.schema.json
+ - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.3/projjson.schema.json
.. versionadded:: 8.0.0
diff --git a/docs/source/apps/cs2cs.rst b/docs/source/apps/cs2cs.rst
index 909912df..c0367167 100644
--- a/docs/source/apps/cs2cs.rst
+++ b/docs/source/apps/cs2cs.rst
@@ -35,7 +35,7 @@ Synopsis
(*added in 6.2*)
- a OGC URN combining references for concatenated operations
(e.g. "urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,coordinateOperation:EPSG::1618")
- - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.2/projjson.schema.json (*added in 6.2*)
+ - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.3/projjson.schema.json (*added in 6.2*)
- a compound CRS made from two object names separated with " + ". e.g. "WGS 84 + EGM96 height" (*added in 7.1*)
.. versionadded:: 6.0.0
diff --git a/docs/source/apps/projinfo.rst b/docs/source/apps/projinfo.rst
index a92de6ea..f9445f1b 100644
--- a/docs/source/apps/projinfo.rst
+++ b/docs/source/apps/projinfo.rst
@@ -55,7 +55,7 @@ Synopsis
(*added in 6.2*)
- a OGC URN combining references for concatenated operations
(e.g. "urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,coordinateOperation:EPSG::1618")
- - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.2/projjson.schema.json (*added in 6.2*)
+ - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.3/projjson.schema.json (*added in 6.2*)
- a compound CRS made from two object names separated with " + ". e.g. "WGS 84 + EGM96 height" (*added in 7.1*)
{object_reference} is a filename preceded by the '@' character. The
diff --git a/docs/source/development/reference/functions.rst b/docs/source/development/reference/functions.rst
index 29b52149..142c7ca9 100644
--- a/docs/source/development/reference/functions.rst
+++ b/docs/source/development/reference/functions.rst
@@ -52,7 +52,7 @@ paragraph for more details.
syntax "EPSG:2393+5717"),
- a OGC URN combining references for concatenated operations
(e.g. "urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,coordinateOperation:EPSG::1618")
- - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.2/projjson.schema.json (*added in 6.2*)
+ - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.3/projjson.schema.json (*added in 6.2*)
- a compound CRS made from two object names separated with " + ". e.g. "WGS 84 + EGM96 height" (*added in 7.1*)
Example call:
diff --git a/include/proj/crs.hpp b/include/proj/crs.hpp
index 481667b5..dcab094a 100644
--- a/include/proj/crs.hpp
+++ b/include/proj/crs.hpp
@@ -1011,6 +1011,11 @@ class PROJ_GCC_DLL BoundCRS final : public CRS,
//! @endcond
PROJ_DLL static BoundCRSNNPtr
+ create(const util::PropertyMap &properties, const CRSNNPtr &baseCRSIn,
+ const CRSNNPtr &hubCRSIn,
+ const operation::TransformationNNPtr &transformationIn);
+
+ PROJ_DLL static BoundCRSNNPtr
create(const CRSNNPtr &baseCRSIn, const CRSNNPtr &hubCRSIn,
const operation::TransformationNNPtr &transformationIn);
diff --git a/include/proj/io.hpp b/include/proj/io.hpp
index 11912e3d..1c858248 100644
--- a/include/proj/io.hpp
+++ b/include/proj/io.hpp
@@ -537,7 +537,11 @@ class PROJ_GCC_DLL JSONFormatter {
// cppcheck-suppress functionStatic
PROJ_INTERNAL bool outputId() const;
- PROJ_INTERNAL bool outputUsage() const;
+ PROJ_INTERNAL bool
+ outputUsage(bool calledBeforeObjectContext = false) const;
+
+ PROJ_INTERNAL static const char *PROJJSON_v0_2;
+ PROJ_INTERNAL static const char *PROJJSON_v0_3;
//! @endcond
diff --git a/schemas/v0.3/projjson.schema.json b/schemas/v0.3/projjson.schema.json
new file mode 100644
index 00000000..c347b3e1
--- /dev/null
+++ b/schemas/v0.3/projjson.schema.json
@@ -0,0 +1,997 @@
+{
+ "$id": "https://proj.org/schemas/v0.3/projjson.schema.json",
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "description": "Schema for PROJJSON (v0.3)",
+ "$comment": "This file exists both in data/ and in schemas/vXXX/. Keep both in sync. And if changing the value of $id, change PROJJSON_CURRENT_VERSION accordingly in io.cpp",
+
+ "oneOf": [
+ { "$ref": "#/definitions/crs" },
+ { "$ref": "#/definitions/datum" },
+ { "$ref": "#/definitions/datum_ensemble" },
+ { "$ref": "#/definitions/ellipsoid" },
+ { "$ref": "#/definitions/prime_meridian" },
+ { "$ref": "#/definitions/single_operation" },
+ { "$ref": "#/definitions/concatenated_operation" }
+ ],
+
+ "definitions": {
+
+ "abridged_transformation": {
+ "type": "object",
+ "properties": {
+ "$schema" : { "type": "string" },
+ "type": { "type": "string", "enum": ["AbridgedTransformation"] },
+ "name": { "type": "string" },
+ "method": { "$ref": "#/definitions/method" },
+ "parameters": {
+ "type": "array",
+ "items": { "$ref": "#/definitions/parameter_value" }
+ },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "required" : [ "name", "method", "parameters" ],
+ "allOf": [
+ { "$ref": "#/definitions/id_ids_mutually_exclusive" }
+ ],
+ "additionalProperties": false
+ },
+
+ "axis": {
+ "type": "object",
+ "properties": {
+ "$schema" : { "type": "string" },
+ "type": { "type": "string", "enum": ["Axis"] },
+ "name": { "type": "string" },
+ "abbreviation": { "type": "string" },
+ "direction": { "type": "string",
+ "enum": [ "north",
+ "northNorthEast",
+ "northEast",
+ "eastNorthEast",
+ "east",
+ "eastSouthEast",
+ "southEast",
+ "southSouthEast",
+ "south",
+ "southSouthWest",
+ "southWest",
+ "westSouthWest",
+ "west",
+ "westNorthWest",
+ "northWest",
+ "northNorthWest",
+ "up",
+ "down",
+ "geocentricX",
+ "geocentricY",
+ "geocentricZ",
+ "columnPositive",
+ "columnNegative",
+ "rowPositive",
+ "rowNegative",
+ "displayRight",
+ "displayLeft",
+ "displayUp",
+ "displayDown",
+ "forward",
+ "aft",
+ "port",
+ "starboard",
+ "clockwise",
+ "counterClockwise",
+ "towards",
+ "awayFrom",
+ "future",
+ "past",
+ "unspecified" ] },
+ "unit": { "$ref": "#/definitions/unit" },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "required" : [ "name", "abbreviation", "direction" ],
+ "allOf": [
+ { "$ref": "#/definitions/id_ids_mutually_exclusive" }
+ ],
+ "additionalProperties": false
+ },
+
+ "bbox": {
+ "type": "object",
+ "properties": {
+ "east_longitude": { "type": "number" },
+ "west_longitude": { "type": "number" },
+ "south_latitude": { "type": "number" },
+ "north_latitude": { "type": "number" }
+ },
+ "required" : [ "east_longitude", "west_longitude",
+ "south_latitude", "north_latitude" ],
+ "additionalProperties": false
+ },
+
+ "bound_crs": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "$schema" : { "type": "string" },
+ "type": { "type": "string", "enum": ["BoundCRS"] },
+ "name": { "type": "string" },
+ "source_crs": { "$ref": "#/definitions/crs" },
+ "target_crs": { "$ref": "#/definitions/crs" },
+ "transformation": { "$ref": "#/definitions/abridged_transformation" },
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "source_crs", "target_crs", "transformation" ],
+ "additionalProperties": false
+ },
+
+ "compound_crs": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string", "enum": ["CompoundCRS"] },
+ "name": { "type": "string" },
+ "components": {
+ "type": "array",
+ "items": { "$ref": "#/definitions/crs" }
+ },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "components" ],
+ "additionalProperties": false
+ },
+
+ "concatenated_operation": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string", "enum": ["ConcatenatedOperation"] },
+ "name": { "type": "string" },
+ "source_crs": { "$ref": "#/definitions/crs" },
+ "target_crs": { "$ref": "#/definitions/crs" },
+ "steps": {
+ "type": "array",
+ "items": { "$ref": "#/definitions/single_operation" }
+ },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "source_crs", "target_crs", "steps" ],
+ "additionalProperties": false
+ },
+
+ "conversion": {
+ "type": "object",
+ "properties": {
+ "$schema" : { "type": "string" },
+ "type": { "type": "string", "enum": ["Conversion"] },
+ "name": { "type": "string" },
+ "method": { "$ref": "#/definitions/method" },
+ "parameters": {
+ "type": "array",
+ "items": { "$ref": "#/definitions/parameter_value" }
+ },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "required" : [ "name", "method" ],
+ "allOf": [
+ { "$ref": "#/definitions/id_ids_mutually_exclusive" }
+ ],
+ "additionalProperties": false
+ },
+
+ "coordinate_system": {
+ "type": "object",
+ "properties": {
+ "$schema" : { "type": "string" },
+ "type": { "type": "string", "enum": ["CoordinateSystem"] },
+ "name": { "type": "string" },
+ "subtype": { "type": "string",
+ "enum": ["Cartesian",
+ "spherical",
+ "ellipsoidal",
+ "vertical",
+ "ordinal",
+ "parametric",
+ "TemporalDateTime",
+ "TemporalCount",
+ "TemporalMeasure"] },
+ "axis": {
+ "type": "array",
+ "items": { "$ref": "#/definitions/axis" }
+ },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "required" : [ "subtype", "axis" ],
+ "allOf": [
+ { "$ref": "#/definitions/id_ids_mutually_exclusive" }
+ ],
+ "additionalProperties": false
+ },
+
+ "crs": {
+ "oneOf": [
+ { "$ref": "#/definitions/bound_crs" },
+ { "$ref": "#/definitions/compound_crs" },
+ { "$ref": "#/definitions/derived_engineering_crs" },
+ { "$ref": "#/definitions/derived_geodetic_crs" },
+ { "$ref": "#/definitions/derived_parametric_crs" },
+ { "$ref": "#/definitions/derived_projected_crs" },
+ { "$ref": "#/definitions/derived_temporal_crs" },
+ { "$ref": "#/definitions/derived_vertical_crs" },
+ { "$ref": "#/definitions/engineering_crs" },
+ { "$ref": "#/definitions/geodetic_crs" },
+ { "$ref": "#/definitions/parametric_crs" },
+ { "$ref": "#/definitions/projected_crs" },
+ { "$ref": "#/definitions/temporal_crs" },
+ { "$ref": "#/definitions/vertical_crs" }
+ ]
+ },
+
+ "datum": {
+ "oneOf": [
+ { "$ref": "#/definitions/geodetic_reference_frame" },
+ { "$ref": "#/definitions/vertical_reference_frame" },
+ { "$ref": "#/definitions/dynamic_geodetic_reference_frame" },
+ { "$ref": "#/definitions/dynamic_vertical_reference_frame" },
+ { "$ref": "#/definitions/temporal_datum" },
+ { "$ref": "#/definitions/parametric_datum" },
+ { "$ref": "#/definitions/engineering_datum" }
+ ]
+ },
+
+ "datum_ensemble": {
+ "type": "object",
+ "properties": {
+ "$schema" : { "type": "string" },
+ "type": { "type": "string", "enum": ["DatumEnsemble"] },
+ "name": { "type": "string" },
+ "members": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string" },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "required" : [ "name" ],
+ "allOf": [
+ { "$ref": "#/definitions/id_ids_mutually_exclusive" }
+ ],
+ "additionalProperties": false
+ }
+ },
+ "ellipsoid": { "$ref": "#/definitions/ellipsoid" },
+ "accuracy": { "type": "string" },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "required" : [ "name", "members", "accuracy" ],
+ "allOf": [
+ { "$ref": "#/definitions/id_ids_mutually_exclusive" }
+ ],
+ "additionalProperties": false
+ },
+
+ "derived_engineering_crs": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string",
+ "enum": ["DerivedEngineeringCRS"] },
+ "name": { "type": "string" },
+ "base_crs": { "$ref": "#/definitions/engineering_crs" },
+ "conversion": { "$ref": "#/definitions/conversion" },
+ "coordinate_system": { "$ref": "#/definitions/coordinate_system" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "base_crs", "conversion", "coordinate_system" ],
+ "additionalProperties": false
+ },
+
+ "derived_geodetic_crs": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string",
+ "enum": ["DerivedGeodeticCRS",
+ "DerivedGeographicCRS"] },
+ "name": { "type": "string" },
+ "base_crs": { "$ref": "#/definitions/geodetic_crs" },
+ "conversion": { "$ref": "#/definitions/conversion" },
+ "coordinate_system": { "$ref": "#/definitions/coordinate_system" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "base_crs", "conversion", "coordinate_system" ],
+ "additionalProperties": false
+ },
+
+ "derived_parametric_crs": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string",
+ "enum": ["DerivedParametricCRS"] },
+ "name": { "type": "string" },
+ "base_crs": { "$ref": "#/definitions/parametric_crs" },
+ "conversion": { "$ref": "#/definitions/conversion" },
+ "coordinate_system": { "$ref": "#/definitions/coordinate_system" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "base_crs", "conversion", "coordinate_system" ],
+ "additionalProperties": false
+ },
+
+ "derived_projected_crs": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string",
+ "enum": ["DerivedProjectedCRS"] },
+ "name": { "type": "string" },
+ "base_crs": { "$ref": "#/definitions/projected_crs" },
+ "conversion": { "$ref": "#/definitions/conversion" },
+ "coordinate_system": { "$ref": "#/definitions/coordinate_system" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "base_crs", "conversion", "coordinate_system" ],
+ "additionalProperties": false
+ },
+
+ "derived_temporal_crs": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string",
+ "enum": ["DerivedTemporalCRS"] },
+ "name": { "type": "string" },
+ "base_crs": { "$ref": "#/definitions/temporal_crs" },
+ "conversion": { "$ref": "#/definitions/conversion" },
+ "coordinate_system": { "$ref": "#/definitions/coordinate_system" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "base_crs", "conversion", "coordinate_system" ],
+ "additionalProperties": false
+ },
+
+ "derived_vertical_crs": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string",
+ "enum": ["DerivedVerticalCRS"] },
+ "name": { "type": "string" },
+ "base_crs": { "$ref": "#/definitions/vertical_crs" },
+ "conversion": { "$ref": "#/definitions/conversion" },
+ "coordinate_system": { "$ref": "#/definitions/coordinate_system" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "base_crs", "conversion", "coordinate_system" ],
+ "additionalProperties": false
+ },
+
+ "dynamic_geodetic_reference_frame": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/geodetic_reference_frame" }],
+ "properties": {
+ "type": { "type": "string", "enum": ["DynamicGeodeticReferenceFrame"] },
+ "name": {},
+ "anchor": {},
+ "ellipsoid": {},
+ "prime_meridian": {},
+ "frame_reference_epoch": { "type": "number" },
+ "deformation_model": { "type": "string" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "ellipsoid", "frame_reference_epoch" ],
+ "additionalProperties": false
+ },
+
+ "dynamic_vertical_reference_frame": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/vertical_reference_frame" }],
+ "properties": {
+ "type": { "type": "string", "enum": ["DynamicVerticalReferenceFrame"] },
+ "name": {},
+ "anchor": {},
+ "frame_reference_epoch": { "type": "number" },
+ "deformation_model": { "type": "string" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "frame_reference_epoch" ],
+ "additionalProperties": false
+ },
+
+ "ellipsoid": {
+ "type": "object",
+ "oneOf":[
+ {
+ "properties": {
+ "$schema" : { "type": "string" },
+ "type": { "type": "string", "enum": ["Ellipsoid"] },
+ "name": { "type": "string" },
+ "semi_major_axis": { "$ref": "#/definitions/value_in_metre_or_value_and_unit" },
+ "semi_minor_axis": { "$ref": "#/definitions/value_in_metre_or_value_and_unit" },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "required" : [ "name", "semi_major_axis", "semi_minor_axis" ],
+ "additionalProperties": false
+ },
+ {
+ "properties": {
+ "$schema" : { "type": "string" },
+ "type": { "type": "string", "enum": ["Ellipsoid"] },
+ "name": { "type": "string" },
+ "semi_major_axis": { "$ref": "#/definitions/value_in_metre_or_value_and_unit" },
+ "inverse_flattening": { "type": "number" },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "required" : [ "name", "semi_major_axis", "inverse_flattening" ],
+ "additionalProperties": false
+ },
+ {
+ "properties": {
+ "$schema" : { "type": "string" },
+ "type": { "type": "string", "enum": ["Ellipsoid"] },
+ "name": { "type": "string" },
+ "radius": { "$ref": "#/definitions/value_in_metre_or_value_and_unit" },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "required" : [ "name", "radius" ],
+ "additionalProperties": false
+ }
+ ],
+ "allOf": [
+ { "$ref": "#/definitions/id_ids_mutually_exclusive" }
+ ]
+ },
+
+ "engineering_crs": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string", "enum": ["EngineeringCRS"] },
+ "name": { "type": "string" },
+ "datum": { "$ref": "#/definitions/engineering_datum" },
+ "coordinate_system": { "$ref": "#/definitions/coordinate_system" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "datum" ],
+ "additionalProperties": false
+ },
+
+ "engineering_datum": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string", "enum": ["EngineeringDatum"] },
+ "name": { "type": "string" },
+ "anchor": { "type": "string" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name" ],
+ "additionalProperties": false
+ },
+
+ "geodetic_crs": {
+ "type": "object",
+ "properties": {
+ "type": { "type": "string", "enum": ["GeodeticCRS", "GeographicCRS"] },
+ "name": { "type": "string" },
+ "datum": {
+ "oneOf": [
+ { "$ref": "#/definitions/geodetic_reference_frame" },
+ { "$ref": "#/definitions/dynamic_geodetic_reference_frame" }
+ ]
+ },
+ "datum_ensemble": { "$ref": "#/definitions/datum_ensemble" },
+ "coordinate_system": { "$ref": "#/definitions/coordinate_system" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name" ],
+ "description": "One and only one of datum and datum_ensemble must be provided",
+ "allOf": [
+ { "$ref": "#/definitions/object_usage" },
+ { "$ref": "#/definitions/one_and_only_one_of_datum_or_datum_ensemble" }
+ ],
+ "additionalProperties": false
+ },
+
+ "geodetic_reference_frame": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string", "enum": ["GeodeticReferenceFrame"] },
+ "name": { "type": "string" },
+ "anchor": { "type": "string" },
+ "ellipsoid": { "$ref": "#/definitions/ellipsoid" },
+ "prime_meridian": { "$ref": "#/definitions/prime_meridian" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "ellipsoid" ],
+ "additionalProperties": false
+ },
+
+ "id": {
+ "type": "object",
+ "properties": {
+ "authority": { "type": "string" },
+ "code": {
+ "oneOf": [ { "type": "string" }, { "type": "integer" } ]
+ }
+ },
+ "required" : [ "authority", "code" ],
+ "additionalProperties": false
+ },
+
+ "ids": {
+ "type": "array",
+ "items": { "$ref": "#/definitions/id" }
+ },
+
+ "method": {
+ "type": "object",
+ "properties": {
+ "$schema" : { "type": "string" },
+ "type": { "type": "string", "enum": ["OperationMethod"]},
+ "name": { "type": "string" },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "required" : [ "name" ],
+ "allOf": [
+ { "$ref": "#/definitions/id_ids_mutually_exclusive" }
+ ],
+ "additionalProperties": false
+ },
+
+ "id_ids_mutually_exclusive": {
+ "not": {
+ "type": "object",
+ "required": [ "id", "ids" ]
+ }
+ },
+
+ "one_and_only_one_of_datum_or_datum_ensemble": {
+ "allOf": [
+ {
+ "not": {
+ "type": "object",
+ "required": [ "datum", "datum_ensemble" ]
+ }
+ },
+ {
+ "oneOf": [
+ { "type": "object", "required": ["datum"] },
+ { "type": "object", "required": ["datum_ensemble"] }
+ ]
+ }
+ ]
+ },
+
+ "object_usage": {
+ "anyOf": [
+ {
+ "type": "object",
+ "properties": {
+ "$schema" : { "type": "string" },
+ "scope": { "type": "string" },
+ "area": { "type": "string" },
+ "bbox": { "$ref": "#/definitions/bbox" },
+ "remarks": { "type": "string" },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "allOf": [
+ { "$ref": "#/definitions/id_ids_mutually_exclusive" }
+ ]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "$schema" : { "type": "string" },
+ "usages": { "$ref": "#/definitions/usages" },
+ "remarks": { "type": "string" },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "allOf": [
+ { "$ref": "#/definitions/id_ids_mutually_exclusive" }
+ ]
+ }
+ ]
+ },
+
+ "parameter_value": {
+ "type": "object",
+ "properties": {
+ "$schema" : { "type": "string" },
+ "type": { "type": "string", "enum": ["ParameterValue"] },
+ "name": { "type": "string" },
+ "value": {
+ "oneOf": [
+ { "type": "string" },
+ { "type": "number" }
+ ]
+ },
+ "unit": { "$ref": "#/definitions/unit" },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "required" : [ "name", "value" ],
+ "allOf": [
+ { "$ref": "#/definitions/id_ids_mutually_exclusive" }
+ ],
+ "additionalProperties": false
+ },
+
+ "parametric_crs": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string", "enum": ["ParametricCRS"] },
+ "name": { "type": "string" },
+ "datum": { "$ref": "#/definitions/parametric_datum" },
+ "coordinate_system": { "$ref": "#/definitions/coordinate_system" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "datum" ],
+ "additionalProperties": false
+ },
+
+ "parametric_datum": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string", "enum": ["ParametricDatum"] },
+ "name": { "type": "string" },
+ "anchor": { "type": "string" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name" ],
+ "additionalProperties": false
+ },
+
+ "prime_meridian": {
+ "type": "object",
+ "properties": {
+ "$schema" : { "type": "string" },
+ "type": { "type": "string", "enum": ["PrimeMeridian"] },
+ "name": { "type": "string" },
+ "longitude": { "$ref": "#/definitions/value_in_degree_or_value_and_unit" },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "required" : [ "name" ],
+ "allOf": [
+ { "$ref": "#/definitions/id_ids_mutually_exclusive" }
+ ],
+ "additionalProperties": false
+ },
+
+ "single_operation": {
+ "oneOf": [
+ { "$ref": "#/definitions/conversion" },
+ { "$ref": "#/definitions/transformation" }
+ ]
+ },
+
+ "projected_crs": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string",
+ "enum": ["ProjectedCRS"] },
+ "name": { "type": "string" },
+ "base_crs": { "$ref": "#/definitions/geodetic_crs" },
+ "conversion": { "$ref": "#/definitions/conversion" },
+ "coordinate_system": { "$ref": "#/definitions/coordinate_system" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "base_crs", "conversion", "coordinate_system" ],
+ "additionalProperties": false
+ },
+
+ "temporal_crs": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string", "enum": ["TemporalCRS"] },
+ "name": { "type": "string" },
+ "datum": { "$ref": "#/definitions/temporal_datum" },
+ "coordinate_system": { "$ref": "#/definitions/coordinate_system" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "datum" ],
+ "additionalProperties": false
+ },
+
+ "temporal_datum": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string", "enum": ["TemporalDatum"] },
+ "name": { "type": "string" },
+ "calendar": { "type": "string" },
+ "time_origin": { "type": "string" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "calendar" ],
+ "additionalProperties": false
+ },
+
+ "transformation": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string", "enum": ["Transformation"] },
+ "name": { "type": "string" },
+ "source_crs": { "$ref": "#/definitions/crs" },
+ "target_crs": { "$ref": "#/definitions/crs" },
+ "interpolation_crs": { "$ref": "#/definitions/crs" },
+ "method": { "$ref": "#/definitions/method" },
+ "parameters": {
+ "type": "array",
+ "items": { "$ref": "#/definitions/parameter_value" }
+ },
+ "accuracy": { "type": "string" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name", "source_crs", "target_crs", "method", "parameters" ],
+ "additionalProperties": false
+ },
+
+ "unit": {
+ "oneOf": [
+ {
+ "type": "string",
+ "enum": ["metre", "degree", "unity"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "type": { "type": "string",
+ "enum": ["LinearUnit", "AngularUnit", "ScaleUnit",
+ "TimeUnit", "ParametricUnit", "Unit"] },
+ "name": { "type": "string" },
+ "conversion_factor": { "type": "number" },
+ "id": { "$ref": "#/definitions/id" },
+ "ids": { "$ref": "#/definitions/ids" }
+ },
+ "required" : [ "type", "name" ],
+ "allOf": [
+ { "$ref": "#/definitions/id_ids_mutually_exclusive" }
+ ],
+ "additionalProperties": false
+ }
+ ]
+ },
+
+ "usages": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "scope": { "type": "string" },
+ "area": { "type": "string" },
+ "bbox": { "$ref": "#/definitions/bbox" }
+ },
+ "additionalProperties": false
+ }
+ },
+
+ "value_and_unit": {
+ "type": "object",
+ "properties": {
+ "value": { "type": "number" },
+ "unit": { "$ref": "#/definitions/unit" }
+ },
+ "required" : [ "value", "unit" ],
+ "additionalProperties": false
+ },
+
+ "value_in_degree_or_value_and_unit": {
+ "oneOf": [
+ { "type": "number" },
+ { "$ref": "#/definitions/value_and_unit" }
+ ]
+ },
+
+ "value_in_metre_or_value_and_unit": {
+ "oneOf": [
+ { "type": "number" },
+ { "$ref": "#/definitions/value_and_unit" }
+ ]
+ },
+
+ "vertical_crs": {
+ "type": "object",
+ "properties": {
+ "type": { "type": "string", "enum": ["VerticalCRS"] },
+ "name": { "type": "string" },
+ "datum": {
+ "oneOf": [
+ { "$ref": "#/definitions/vertical_reference_frame" },
+ { "$ref": "#/definitions/dynamic_vertical_reference_frame" }
+ ]
+ },
+ "datum_ensemble": { "$ref": "#/definitions/datum_ensemble" },
+ "coordinate_system": { "$ref": "#/definitions/coordinate_system" },
+ "geoid_model": {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string" },
+ "interpolation_crs": { "$ref": "#/definitions/crs" },
+ "id": { "$ref": "#/definitions/id" }
+ },
+ "required" : [ "name" ],
+ "additionalProperties": false
+ },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name"],
+ "description": "One and only one of datum and datum_ensemble must be provided",
+ "allOf": [
+ { "$ref": "#/definitions/object_usage" },
+ { "$ref": "#/definitions/one_and_only_one_of_datum_or_datum_ensemble" }
+ ],
+ "additionalProperties": false
+ },
+
+ "vertical_reference_frame": {
+ "type": "object",
+ "allOf": [{ "$ref": "#/definitions/object_usage" }],
+ "properties": {
+ "type": { "type": "string", "enum": ["VerticalReferenceFrame"] },
+ "name": { "type": "string" },
+ "anchor": { "type": "string" },
+ "$schema" : {},
+ "scope": {},
+ "area": {},
+ "bbox": {},
+ "usages": {},
+ "remarks": {},
+ "id": {}, "ids": {}
+ },
+ "required" : [ "name" ],
+ "additionalProperties": false
+ }
+
+ }
+}
diff --git a/scripts/reference_exported_symbols.txt b/scripts/reference_exported_symbols.txt
index f8066394..9b84c09b 100644
--- a/scripts/reference_exported_symbols.txt
+++ b/scripts/reference_exported_symbols.txt
@@ -98,6 +98,7 @@ osgeo::proj::crs::BoundCRS::~BoundCRS()
osgeo::proj::crs::BoundCRS::create(dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::crs::CRS> > const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::crs::CRS> > const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::operation::Transformation> > const&)
osgeo::proj::crs::BoundCRS::createFromNadgrids(dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::crs::CRS> > const&, std::string const&)
osgeo::proj::crs::BoundCRS::createFromTOWGS84(dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::crs::CRS> > const&, std::vector<double, std::allocator<double> > const&)
+osgeo::proj::crs::BoundCRS::create(osgeo::proj::util::PropertyMap const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::crs::CRS> > const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::crs::CRS> > const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::operation::Transformation> > const&)
osgeo::proj::crs::BoundCRS::hubCRS() const
osgeo::proj::crs::BoundCRS::transformation() const
osgeo::proj::crs::CompoundCRS::componentReferenceSystems() const
diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp
index 942e2d43..3e825ff0 100644
--- a/src/iso19111/crs.cpp
+++ b/src/iso19111/crs.cpp
@@ -1217,7 +1217,7 @@ CRSNNPtr CRS::promoteTo3D(const std::string &newName,
try {
transf->getTOWGS84Parameters();
return BoundCRS::create(
- base3DCRS,
+ createProperties(), base3DCRS,
boundCRS->hubCRS()->promoteTo3D(std::string(), dbContext),
transf->promoteTo3D(std::string(), dbContext));
} catch (const io::FormattingException &) {
@@ -5294,27 +5294,50 @@ BoundCRS::transformation() PROJ_PURE_DEFN {
/** \brief Instantiate a BoundCRS from a base CRS, a hub CRS and a
* transformation.
*
+ * @param properties See \ref general_properties.
* @param baseCRSIn base CRS.
* @param hubCRSIn hub CRS.
* @param transformationIn transformation from base CRS to hub CRS.
* @return new BoundCRS.
+ * @since PROJ 8.2
*/
BoundCRSNNPtr
-BoundCRS::create(const CRSNNPtr &baseCRSIn, const CRSNNPtr &hubCRSIn,
+BoundCRS::create(const util::PropertyMap &properties, const CRSNNPtr &baseCRSIn,
+ const CRSNNPtr &hubCRSIn,
const operation::TransformationNNPtr &transformationIn) {
auto crs = BoundCRS::nn_make_shared<BoundCRS>(baseCRSIn, hubCRSIn,
transformationIn);
crs->assignSelf(crs);
const auto &l_name = baseCRSIn->nameStr();
- if (!l_name.empty()) {
- crs->setProperties(util::PropertyMap().set(
- common::IdentifiedObject::NAME_KEY, l_name));
+ if (properties.get(common::IdentifiedObject::NAME_KEY) == nullptr &&
+ !l_name.empty()) {
+ auto newProperties(properties);
+ newProperties.set(common::IdentifiedObject::NAME_KEY, l_name);
+ crs->setProperties(newProperties);
+ } else {
+ crs->setProperties(properties);
}
return crs;
}
// ---------------------------------------------------------------------------
+/** \brief Instantiate a BoundCRS from a base CRS, a hub CRS and a
+ * transformation.
+ *
+ * @param baseCRSIn base CRS.
+ * @param hubCRSIn hub CRS.
+ * @param transformationIn transformation from base CRS to hub CRS.
+ * @return new BoundCRS.
+ */
+BoundCRSNNPtr
+BoundCRS::create(const CRSNNPtr &baseCRSIn, const CRSNNPtr &hubCRSIn,
+ const operation::TransformationNNPtr &transformationIn) {
+ return create(util::PropertyMap(), baseCRSIn, hubCRSIn, transformationIn);
+}
+
+// ---------------------------------------------------------------------------
+
/** \brief Instantiate a BoundCRS from a base CRS and TOWGS84 parameters
*
* @param baseCRSIn base CRS.
@@ -5415,6 +5438,7 @@ void BoundCRS::_exportToWKT(io::WKTFormatter *formatter) const {
formatter->setAbridgedTransformation(true);
d->transformation()->_exportToWKT(formatter);
formatter->setAbridgedTransformation(false);
+ ObjectUsage::baseExportToWKT(formatter);
formatter->endNode();
} else {
@@ -5455,8 +5479,21 @@ void BoundCRS::_exportToJSON(
io::JSONFormatter *formatter) const // throw(io::FormattingException)
{
auto writer = formatter->writer();
- auto objectContext(
- formatter->MakeObjectContext("BoundCRS", !identifiers().empty()));
+ const auto &l_name = nameStr();
+ if ((formatter->outputUsage(true) && !domains().empty()) ||
+ (formatter->outputId() && !identifiers().empty()) ||
+ !remarks().empty() ||
+ (!l_name.empty() && l_name != d->baseCRS()->nameStr())) {
+ // Only upgrades to v0.3 schema if needed
+ formatter->setSchema(io::JSONFormatter::PROJJSON_v0_3);
+ }
+
+ auto objectContext(formatter->MakeObjectContext("BoundCRS", false));
+
+ if (!l_name.empty() && l_name != d->baseCRS()->nameStr()) {
+ writer->AddObjKey("name");
+ writer->Add(l_name);
+ }
writer->AddObjKey("source_crs");
d->baseCRS()->_exportToJSON(formatter);
@@ -5469,6 +5506,8 @@ void BoundCRS::_exportToJSON(
formatter->setAbridgedTransformation(true);
d->transformation()->_exportToJSON(formatter);
formatter->setAbridgedTransformation(false);
+
+ ObjectUsage::baseExportToJSON(formatter);
}
//! @endcond
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index ccbb0ffe..867e08ed 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -89,10 +89,6 @@ using json = nlohmann::json;
//! @cond Doxygen_Suppress
static const std::string emptyString{};
-
-// If changing that value, change it in data/projjson.schema.json as well
-#define PROJJSON_CURRENT_VERSION \
- "https://proj.org/schemas/v0.2/projjson.schema.json"
//! @endcond
#if 0
@@ -109,6 +105,18 @@ template<> nn<std::unique_ptr<NS_PROJ::io::WKTNode, std::default_delete<NS_PROJ:
NS_PROJ_START
namespace io {
+//! @cond Doxygen_Suppress
+const char *JSONFormatter::PROJJSON_v0_2 =
+ "https://proj.org/schemas/v0.2/projjson.schema.json";
+
+const char *JSONFormatter::PROJJSON_v0_3 =
+ "https://proj.org/schemas/v0.3/projjson.schema.json";
+
+// v0.2 is our base version. We only upgrade to 0.3 for usage node in BoundCRS
+#define PROJJSON_DEFAULT_VERSION JSONFormatter::PROJJSON_v0_2
+
+//! @endcond
+
// ---------------------------------------------------------------------------
//! @cond Doxygen_Suppress
@@ -4593,8 +4601,8 @@ BoundCRSNNPtr WKTParser::Private::buildBoundCRS(const WKTNodeNNPtr &node) {
NN_NO_CHECK(targetCRS), nullptr, buildProperties(methodNode),
parameters, values, std::vector<PositionalAccuracyNNPtr>());
- return BoundCRS::create(NN_NO_CHECK(sourceCRS), NN_NO_CHECK(targetCRS),
- transformation);
+ return BoundCRS::create(buildProperties(node), NN_NO_CHECK(sourceCRS),
+ NN_NO_CHECK(targetCRS), transformation);
}
// ---------------------------------------------------------------------------
@@ -5057,7 +5065,8 @@ class JSONParser {
IdentifierNNPtr buildId(const json &j, bool removeInverseOf);
static ObjectDomainPtr buildObjectDomain(const json &j);
- PropertyMap buildProperties(const json &j, bool removeInverseOf = false);
+ PropertyMap buildProperties(const json &j, bool removeInverseOf = false,
+ bool nameRequired = true);
GeographicCRSNNPtr buildGeographicCRS(const json &j);
GeodeticCRSNNPtr buildGeodeticCRS(const json &j);
@@ -5358,13 +5367,17 @@ IdentifierNNPtr JSONParser::buildId(const json &j, bool removeInverseOf) {
// ---------------------------------------------------------------------------
-PropertyMap JSONParser::buildProperties(const json &j, bool removeInverseOf) {
+PropertyMap JSONParser::buildProperties(const json &j, bool removeInverseOf,
+ bool nameRequired) {
PropertyMap map;
- std::string name(getName(j));
- if (removeInverseOf && starts_with(name, "Inverse of ")) {
- name = name.substr(strlen("Inverse of "));
+
+ if (j.contains("name") || nameRequired) {
+ std::string name(getName(j));
+ if (removeInverseOf && starts_with(name, "Inverse of ")) {
+ name = name.substr(strlen("Inverse of "));
+ }
+ map.set(IdentifiedObject::NAME_KEY, name);
}
- map.set(IdentifiedObject::NAME_KEY, name);
if (j.contains("ids")) {
auto idsJ = getArray(j, "ids");
@@ -5782,7 +5795,10 @@ BoundCRSNNPtr JSONParser::buildBoundCRS(const json &j) {
nullptr, buildProperties(methodJ), parameters, values,
std::vector<PositionalAccuracyNNPtr>());
- return BoundCRS::create(sourceCRS, targetCRS, transformation);
+ return BoundCRS::create(buildProperties(j,
+ /* removeInverseOf= */ false,
+ /* nameRequired=*/false),
+ sourceCRS, targetCRS, transformation);
}
// ---------------------------------------------------------------------------
@@ -10529,7 +10545,7 @@ struct JSONFormatter::Private {
bool allowIDInImmediateChild_ = false;
bool omitTypeInImmediateChild_ = false;
bool abridgedTransformation_ = false;
- std::string schema_ = PROJJSON_CURRENT_VERSION;
+ std::string schema_ = PROJJSON_DEFAULT_VERSION;
std::string result_{};
@@ -10580,7 +10596,10 @@ JSONFormatter &JSONFormatter::setIndentationWidth(int width) noexcept {
* If set to empty string, it will not be written.
*/
JSONFormatter &JSONFormatter::setSchema(const std::string &schema) noexcept {
- d->schema_ = schema;
+ // Upgrade only to v0.3 if the default was v0.2
+ if (schema != PROJJSON_v0_3 || d->schema_ == PROJJSON_v0_2) {
+ d->schema_ = schema;
+ }
return *this;
}
@@ -10604,8 +10623,9 @@ bool JSONFormatter::outputId() const { return d->outputIdStack_.back(); }
// ---------------------------------------------------------------------------
-bool JSONFormatter::outputUsage() const {
- return outputId() && d->outputIdStack_.size() == 2;
+bool JSONFormatter::outputUsage(bool calledBeforeObjectContext) const {
+ return outputId() &&
+ d->outputIdStack_.size() == (calledBeforeObjectContext ? 1U : 2U);
}
// ---------------------------------------------------------------------------
diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp
index fb3c14ae..c36aa9b7 100644
--- a/test/unit/test_crs.cpp
+++ b/test/unit/test_crs.cpp
@@ -4411,6 +4411,93 @@ TEST(crs, boundCRS_to_WKT2) {
// ---------------------------------------------------------------------------
+TEST(crs, boundCRS_with_usage) {
+
+ auto wkt =
+ "BOUNDCRS[\n"
+ " SOURCECRS[\n"
+ " PROJCRS[\"Monte Mario / Italy zone 2\",\n"
+ " BASEGEOGCRS[\"Monte Mario\",\n"
+ " DATUM[\"Monte Mario\",\n"
+ " ELLIPSOID[\"International 1924\",6378388,297,\n"
+ " LENGTHUNIT[\"metre\",1]]],\n"
+ " PRIMEM[\"Greenwich\",0,\n"
+ " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
+ " ID[\"EPSG\",4265]],\n"
+ " CONVERSION[\"unnamed\",\n"
+ " METHOD[\"Transverse Mercator\",\n"
+ " ID[\"EPSG\",9807]],\n"
+ " PARAMETER[\"Latitude of natural origin\",0,\n"
+ " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
+ " ID[\"EPSG\",8801]],\n"
+ " PARAMETER[\"Longitude of natural origin\",15,\n"
+ " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
+ " ID[\"EPSG\",8802]],\n"
+ " PARAMETER[\"Scale factor at natural origin\",0.9996,\n"
+ " SCALEUNIT[\"unity\",1],\n"
+ " ID[\"EPSG\",8805]],\n"
+ " PARAMETER[\"False easting\",2520000,\n"
+ " LENGTHUNIT[\"metre\",1],\n"
+ " ID[\"EPSG\",8806]],\n"
+ " PARAMETER[\"False northing\",0,\n"
+ " LENGTHUNIT[\"metre\",1],\n"
+ " ID[\"EPSG\",8807]]],\n"
+ " CS[Cartesian,2],\n"
+ " AXIS[\"x\",east,\n"
+ " ORDER[1],\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " AXIS[\"y\",north,\n"
+ " ORDER[2],\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " ID[\"EPSG\",3004]]],\n"
+ " TARGETCRS[\n"
+ " GEOGCRS[\"WGS 84\",\n"
+ " DATUM[\"World Geodetic System 1984\",\n"
+ " ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n"
+ " LENGTHUNIT[\"metre\",1]]],\n"
+ " PRIMEM[\"Greenwich\",0,\n"
+ " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
+ " CS[ellipsoidal,2],\n"
+ " AXIS[\"geodetic latitude (Lat)\",north,\n"
+ " ORDER[1],\n"
+ " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
+ " AXIS[\"geodetic longitude (Lon)\",east,\n"
+ " ORDER[2],\n"
+ " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
+ " ID[\"EPSG\",4326]]],\n"
+ " ABRIDGEDTRANSFORMATION[\"Transformation from Monte Mario to "
+ "WGS84\",\n"
+ " METHOD[\"Position Vector transformation (geog2D domain)\",\n"
+ " ID[\"EPSG\",9606]],\n"
+ " PARAMETER[\"X-axis translation\",-50.2,\n"
+ " ID[\"EPSG\",8605]],\n"
+ " PARAMETER[\"Y-axis translation\",-50.4,\n"
+ " ID[\"EPSG\",8606]],\n"
+ " PARAMETER[\"Z-axis translation\",84.8,\n"
+ " ID[\"EPSG\",8607]],\n"
+ " PARAMETER[\"X-axis rotation\",-0.69,\n"
+ " ID[\"EPSG\",8608]],\n"
+ " PARAMETER[\"Y-axis rotation\",-2.012,\n"
+ " ID[\"EPSG\",8609]],\n"
+ " PARAMETER[\"Z-axis rotation\",0.459,\n"
+ " ID[\"EPSG\",8610]],\n"
+ " PARAMETER[\"Scale difference\",0.99997192,\n"
+ " ID[\"EPSG\",8611]]],\n"
+ " USAGE[\n"
+ " SCOPE[\"unknown\"],\n"
+ " AREA[\"Italy - Sicily onshore\"],\n"
+ " BBOX[36.59,12.36,38.35,15.71]]]";
+ auto crs =
+ nn_dynamic_pointer_cast<BoundCRS>(WKTParser().createFromWKT(wkt));
+ ASSERT_TRUE(crs != nullptr);
+
+ auto got_wkt = crs->exportToWKT(
+ WKTFormatter::create(WKTFormatter::Convention::WKT2_2019).get());
+ EXPECT_EQ(got_wkt, wkt);
+}
+
+// ---------------------------------------------------------------------------
+
TEST(crs, boundCRS_crs_link) {
{
diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp
index 98ac5aa0..0235a0c1 100644
--- a/test/unit/test_io.cpp
+++ b/test/unit/test_io.cpp
@@ -11891,9 +11891,12 @@ TEST(json_import, compound_crs) {
// ---------------------------------------------------------------------------
TEST(json_import, bound_crs) {
+ // Explicitly check that the version is v0.2 in that circumstance. Might
+ // require adjustments in the future.
auto json =
"{\n"
- " \"$schema\": \"foo\",\n"
+ " \"$schema\": "
+ "\"https://proj.org/schemas/v0.2/projjson.schema.json\",\n"
" \"type\": \"BoundCRS\",\n"
" \"source_crs\": {\n"
" \"type\": \"GeographicCRS\",\n"
@@ -11987,9 +11990,125 @@ TEST(json_import, bound_crs) {
auto obj = createFromUserInput(json, nullptr);
auto boundCRS = nn_dynamic_pointer_cast<BoundCRS>(obj);
ASSERT_TRUE(boundCRS != nullptr);
- EXPECT_EQ(
- boundCRS->exportToJSON(&(JSONFormatter::create()->setSchema("foo"))),
- json);
+ EXPECT_EQ(boundCRS->exportToJSON(JSONFormatter::create().get()), json);
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(json_import, bound_crs_with_name_and_usage) {
+ // Explicitly check that the version is v0.3 in that circumstance. Might
+ // require adjustments in the future.
+ auto json =
+ "{\n"
+ " \"$schema\": "
+ "\"https://proj.org/schemas/v0.3/projjson.schema.json\",\n"
+ " \"type\": \"BoundCRS\",\n"
+ " \"name\": \"my bound crs\",\n"
+ " \"source_crs\": {\n"
+ " \"type\": \"GeographicCRS\",\n"
+ " \"name\": \"unknown\",\n"
+ " \"datum\": {\n"
+ " \"type\": \"GeodeticReferenceFrame\",\n"
+ " \"name\": \"Unknown based on GRS80 ellipsoid\",\n"
+ " \"ellipsoid\": {\n"
+ " \"name\": \"GRS 1980\",\n"
+ " \"semi_major_axis\": 6378137,\n"
+ " \"inverse_flattening\": 298.257222101,\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 7019\n"
+ " }\n"
+ " }\n"
+ " },\n"
+ " \"coordinate_system\": {\n"
+ " \"subtype\": \"ellipsoidal\",\n"
+ " \"axis\": [\n"
+ " {\n"
+ " \"name\": \"Longitude\",\n"
+ " \"abbreviation\": \"lon\",\n"
+ " \"direction\": \"east\",\n"
+ " \"unit\": \"degree\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Latitude\",\n"
+ " \"abbreviation\": \"lat\",\n"
+ " \"direction\": \"north\",\n"
+ " \"unit\": \"degree\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " },\n"
+ " \"target_crs\": {\n"
+ " \"type\": \"GeographicCRS\",\n"
+ " \"name\": \"WGS 84\",\n"
+ " \"datum\": {\n"
+ " \"type\": \"GeodeticReferenceFrame\",\n"
+ " \"name\": \"World Geodetic System 1984\",\n"
+ " \"ellipsoid\": {\n"
+ " \"name\": \"WGS 84\",\n"
+ " \"semi_major_axis\": 6378137,\n"
+ " \"inverse_flattening\": 298.257223563\n"
+ " }\n"
+ " },\n"
+ " \"coordinate_system\": {\n"
+ " \"subtype\": \"ellipsoidal\",\n"
+ " \"axis\": [\n"
+ " {\n"
+ " \"name\": \"Latitude\",\n"
+ " \"abbreviation\": \"lat\",\n"
+ " \"direction\": \"north\",\n"
+ " \"unit\": \"degree\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Longitude\",\n"
+ " \"abbreviation\": \"lon\",\n"
+ " \"direction\": \"east\",\n"
+ " \"unit\": \"degree\"\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 4326\n"
+ " }\n"
+ " },\n"
+ " \"transformation\": {\n"
+ " \"name\": \"unknown to WGS84\",\n"
+ " \"method\": {\n"
+ " \"name\": \"NTv2\",\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 9615\n"
+ " }\n"
+ " },\n"
+ " \"parameters\": [\n"
+ " {\n"
+ " \"name\": \"Latitude and longitude difference file\",\n"
+ " \"value\": \"@foo\",\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 8656\n"
+ " }\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " \"scope\": \"Example only (fictitious).\",\n"
+ " \"area\": \"Description of the extent of the CRS.\",\n"
+ " \"bbox\": {\n"
+ " \"south_latitude\": -90,\n"
+ " \"west_longitude\": -180,\n"
+ " \"north_latitude\": 90,\n"
+ " \"east_longitude\": 180\n"
+ " },\n"
+ " \"id\": {\n"
+ " \"authority\": \"foo\",\n"
+ " \"code\": 1234\n"
+ " }\n"
+ "}";
+ auto obj = createFromUserInput(json, nullptr);
+ auto boundCRS = nn_dynamic_pointer_cast<BoundCRS>(obj);
+ ASSERT_TRUE(boundCRS != nullptr);
+ EXPECT_EQ(boundCRS->exportToJSON(JSONFormatter::create().get()), json);
}
// ---------------------------------------------------------------------------