From 831fa1dfad49a6f2eecb1d454f78cf038ff2c08d Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Tue, 19 May 2026 11:55:15 +0200 Subject: [PATCH 1/3] feat(create-surface): new blueprint to create polygonal surface --- opengeodeweb_back_schemas.json | 57 +++++++++++++++++++ .../routes/create/blueprint_create.py | 30 ++++++++++ .../routes/create/schemas/__init__.py | 1 + .../create/schemas/polygonal_surface.json | 37 ++++++++++++ .../create/schemas/polygonal_surface.py | 23 ++++++++ tests/test_create_routes.py | 44 ++++++++++++++ 6 files changed, 192 insertions(+) create mode 100644 src/opengeodeweb_back/routes/create/schemas/polygonal_surface.json create mode 100644 src/opengeodeweb_back/routes/create/schemas/polygonal_surface.py diff --git a/opengeodeweb_back_schemas.json b/opengeodeweb_back_schemas.json index fa968937..43402b12 100644 --- a/opengeodeweb_back_schemas.json +++ b/opengeodeweb_back_schemas.json @@ -1,6 +1,62 @@ { "opengeodeweb_back": { "create": { + "polygonal_surface": { + "$id": "opengeodeweb_back/create/polygonal_surface", + "route": "/polygonal_surface", + "methods": [ + "POST" + ], + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "points": { + "type": "array", + "items": { + "title": "PolygonalSurfacePoint", + "type": "object", + "properties": { + "x": { + "type": "number" + }, + "y": { + "type": "number" + }, + "z": { + "type": "number" + } + }, + "required": [ + "x", + "y", + "z" + ], + "additionalProperties": false + }, + "minItems": 3 + }, + "polygons": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 3 + }, + "minItems": 1 + } + }, + "required": [ + "name", + "points", + "polygons" + ], + "additionalProperties": false + }, "point_set": { "$id": "opengeodeweb_back/create/point_set", "route": "/point_set", @@ -102,6 +158,7 @@ "additionalProperties": false } }, + "models": {}, "vertex_attribute_names": { "$id": "opengeodeweb_back/vertex_attribute_names", "route": "/vertex_attribute_names", diff --git a/src/opengeodeweb_back/routes/create/blueprint_create.py b/src/opengeodeweb_back/routes/create/blueprint_create.py index 607a5bfa..a9b697fb 100644 --- a/src/opengeodeweb_back/routes/create/blueprint_create.py +++ b/src/opengeodeweb_back/routes/create/blueprint_create.py @@ -11,6 +11,7 @@ import opengeodeweb_back.routes.create.schemas as schemas from opengeodeweb_back.geode_objects.geode_point_set3d import GeodePointSet3D from opengeodeweb_back.geode_objects.geode_edged_curve3d import GeodeEdgedCurve3D +from opengeodeweb_back.geode_objects.geode_polygonal_surface3d import GeodePolygonalSurface3D routes = flask.Blueprint("create", __name__, url_prefix="/create") schemas_dict = get_schemas_dict(os.path.join(os.path.dirname(__file__), "schemas")) @@ -62,3 +63,32 @@ def edged_curve() -> flask.Response: edged_curve_obj ) return flask.make_response(result, 200) + + +@routes.route( + schemas_dict["polygonal_surface"]["route"], + methods=schemas_dict["polygonal_surface"]["methods"], +) +def polygonal_surface() -> flask.Response: + """Endpoint to create a polygonal surface in 3D space.""" + json_data = utils_functions.validate_request( + flask.request, schemas_dict["polygonal_surface"] + ) + params = schemas.PolygonalSurface.from_dict(json_data) + + polygonal_surface_obj = GeodePolygonalSurface3D() + builder = polygonal_surface_obj.builder() + builder.set_name(params.name) + for point in params.points: + builder.create_point(opengeode.Point3D([point.x, point.y, point.z])) + + for polygon in params.polygons: + builder.create_polygon(polygon) + + builder.compute_polygon_adjacencies() + + result = utils_functions.generate_native_viewable_and_light_viewable_from_object( + polygonal_surface_obj + ) + return flask.make_response(result, 200) + diff --git a/src/opengeodeweb_back/routes/create/schemas/__init__.py b/src/opengeodeweb_back/routes/create/schemas/__init__.py index a663b1cf..7660bebd 100644 --- a/src/opengeodeweb_back/routes/create/schemas/__init__.py +++ b/src/opengeodeweb_back/routes/create/schemas/__init__.py @@ -1,2 +1,3 @@ +from .polygonal_surface import * from .point_set import * from .edged_curve import * diff --git a/src/opengeodeweb_back/routes/create/schemas/polygonal_surface.json b/src/opengeodeweb_back/routes/create/schemas/polygonal_surface.json new file mode 100644 index 00000000..9984b9cd --- /dev/null +++ b/src/opengeodeweb_back/routes/create/schemas/polygonal_surface.json @@ -0,0 +1,37 @@ +{ + "route": "/polygonal_surface", + "methods": ["POST"], + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "points": { + "type": "array", + "items": { + "title": "PolygonalSurfacePoint", + "type": "object", + "properties": { + "x": { "type": "number" }, + "y": { "type": "number" }, + "z": { "type": "number" } + }, + "required": ["x", "y", "z"], + "additionalProperties": false + }, + "minItems": 3 + }, + "polygons": { + "type": "array", + "items": { + "type": "array", + "items": { "type": "integer" }, + "minItems": 3 + }, + "minItems": 1 + } + }, + "required": ["name", "points", "polygons"], + "additionalProperties": false +} diff --git a/src/opengeodeweb_back/routes/create/schemas/polygonal_surface.py b/src/opengeodeweb_back/routes/create/schemas/polygonal_surface.py new file mode 100644 index 00000000..e751f072 --- /dev/null +++ b/src/opengeodeweb_back/routes/create/schemas/polygonal_surface.py @@ -0,0 +1,23 @@ +from dataclasses_json import DataClassJsonMixin +from dataclasses import dataclass +from typing import List + + +@dataclass +class PolygonalSurfacePoint(DataClassJsonMixin): + def __post_init__(self) -> None: + print(self, flush=True) + + x: float + y: float + z: float + + +@dataclass +class PolygonalSurface(DataClassJsonMixin): + def __post_init__(self) -> None: + print(self, flush=True) + + name: str + points: List[PolygonalSurfacePoint] + polygons: List[List[int]] diff --git a/tests/test_create_routes.py b/tests/test_create_routes.py index 75f9def7..7164bd00 100644 --- a/tests/test_create_routes.py +++ b/tests/test_create_routes.py @@ -23,6 +23,20 @@ def curve_data() -> test_utils.JsonData: } +@pytest.fixture +def surface_data() -> test_utils.JsonData: + return { + "name": "test_surface", + "points": [ + {"x": 0.0, "y": 0.0, "z": 0.0}, + {"x": 1.0, "y": 0.0, "z": 0.0}, + {"x": 1.0, "y": 1.0, "z": 0.0}, + {"x": 0.0, "y": 1.0, "z": 0.0}, + ], + "polygons": [[0, 1, 2, 3]], + } + + def test_create_point(client: FlaskClient, point_data: test_utils.JsonData) -> None: """Test the creation of a point with valid data.""" route: str = "/opengeodeweb_back/create/point_set" @@ -108,3 +122,33 @@ def test_create_curve(client: FlaskClient, curve_data: test_utils.JsonData) -> N # Test with missing parameters test_utils.test_route_wrong_params(client, route, lambda: copy.deepcopy(curve_data)) + + +def test_create_polygonal_surface( + client: FlaskClient, surface_data: test_utils.JsonData +) -> None: + """Test the creation of a polygonal surface with valid data.""" + route: str = "/opengeodeweb_back/create/polygonal_surface" + + # Test with all required data + response = client.post(route, json=surface_data) + assert response.status_code == 200 + + # Verify response data + response_data = response.get_json() + assert "viewable_file" in response_data + assert "id" in response_data + assert "name" in response_data + assert "native_file" in response_data + assert "viewer_type" in response_data + assert "geode_object_type" in response_data + + assert response_data["name"] == surface_data["name"] + assert response_data["viewer_type"] == "mesh" + assert response_data["geode_object_type"] == "PolygonalSurface3D" + + # Test with missing parameters + test_utils.test_route_wrong_params( + client, route, lambda: copy.deepcopy(surface_data) + ) + From 49e52c1ce75fc6625c03fd674e78e3a05b78fcb2 Mon Sep 17 00:00:00 2001 From: MaxNumerique <144453705+MaxNumerique@users.noreply.github.com> Date: Tue, 19 May 2026 09:56:17 +0000 Subject: [PATCH 2/3] Apply prepare changes --- commitlint.config.js | 5 +++-- opengeodeweb_back_schemas.json | 1 - requirements.txt | 1 - src/opengeodeweb_back/routes/create/blueprint_create.py | 5 +++-- tests/test_create_routes.py | 1 - 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/commitlint.config.js b/commitlint.config.js index a397334b..0c07c264 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -14,6 +14,7 @@ const Configuration = { "type-empty": [0], "type-enum": [2, "always", ["feat", "fix", "perf"]], }, -} + defaultIgnores: false, +}; -export default Configuration +export default Configuration; diff --git a/opengeodeweb_back_schemas.json b/opengeodeweb_back_schemas.json index 43402b12..74df356d 100644 --- a/opengeodeweb_back_schemas.json +++ b/opengeodeweb_back_schemas.json @@ -158,7 +158,6 @@ "additionalProperties": false } }, - "models": {}, "vertex_attribute_names": { "$id": "opengeodeweb_back/vertex_attribute_names", "route": "/vertex_attribute_names", diff --git a/requirements.txt b/requirements.txt index e1e3eab1..3a4eb2d3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -60,4 +60,3 @@ werkzeug==3.1.8 # flask # flask-cors -opengeodeweb-microservice==1.*,>=1.1.3 diff --git a/src/opengeodeweb_back/routes/create/blueprint_create.py b/src/opengeodeweb_back/routes/create/blueprint_create.py index a9b697fb..f325aa71 100644 --- a/src/opengeodeweb_back/routes/create/blueprint_create.py +++ b/src/opengeodeweb_back/routes/create/blueprint_create.py @@ -11,7 +11,9 @@ import opengeodeweb_back.routes.create.schemas as schemas from opengeodeweb_back.geode_objects.geode_point_set3d import GeodePointSet3D from opengeodeweb_back.geode_objects.geode_edged_curve3d import GeodeEdgedCurve3D -from opengeodeweb_back.geode_objects.geode_polygonal_surface3d import GeodePolygonalSurface3D +from opengeodeweb_back.geode_objects.geode_polygonal_surface3d import ( + GeodePolygonalSurface3D, +) routes = flask.Blueprint("create", __name__, url_prefix="/create") schemas_dict = get_schemas_dict(os.path.join(os.path.dirname(__file__), "schemas")) @@ -91,4 +93,3 @@ def polygonal_surface() -> flask.Response: polygonal_surface_obj ) return flask.make_response(result, 200) - diff --git a/tests/test_create_routes.py b/tests/test_create_routes.py index 7164bd00..0673c797 100644 --- a/tests/test_create_routes.py +++ b/tests/test_create_routes.py @@ -151,4 +151,3 @@ def test_create_polygonal_surface( test_utils.test_route_wrong_params( client, route, lambda: copy.deepcopy(surface_data) ) - From 54b2b6f35d2875740c4c902f183f895e525a9f52 Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Tue, 19 May 2026 12:57:23 +0200 Subject: [PATCH 3/3] trigger