diff --git a/data/projjson.schema.json b/data/projjson.schema.json index bdb97bd5c4..c347b3e1d5 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 700261fa7b..75d679729a 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 909912df9b..c03671672a 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 a92de6ea16..f9445f1b06 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 29b52149f1..142c7ca95a 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 481667b570..dcab094af2 100644 --- a/include/proj/crs.hpp +++ b/include/proj/crs.hpp @@ -1010,6 +1010,11 @@ class PROJ_GCC_DLL BoundCRS final : public CRS, const override; // throw(io::FormattingException) //! @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 11912e3d06..1c85824830 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 0000000000..c347b3e1d5 --- /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 f806639480..9b84c09b08 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 > const&, dropbox::oxygen::nn > const&, dropbox::oxygen::nn > const&) osgeo::proj::crs::BoundCRS::createFromNadgrids(dropbox::oxygen::nn > const&, std::string const&) osgeo::proj::crs::BoundCRS::createFromTOWGS84(dropbox::oxygen::nn > const&, std::vector > const&) +osgeo::proj::crs::BoundCRS::create(osgeo::proj::util::PropertyMap const&, dropbox::oxygen::nn > const&, dropbox::oxygen::nn > const&, dropbox::oxygen::nn > 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 942e2d43be..3e825ff0f0 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(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 ccbb0ffe95..867e08ed8b 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()); - 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()); - 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 fb3c14ae3b..c36aa9b70d 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(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 98ac5aa0fb..0235a0c19f 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(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(obj); + ASSERT_TRUE(boundCRS != nullptr); + EXPECT_EQ(boundCRS->exportToJSON(JSONFormatter::create().get()), json); } // ---------------------------------------------------------------------------