diff --git a/opengeodeweb_back_schemas.json b/opengeodeweb_back_schemas.json index fa968937..74df356d 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", 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 607a5bfa..f325aa71 100644 --- a/src/opengeodeweb_back/routes/create/blueprint_create.py +++ b/src/opengeodeweb_back/routes/create/blueprint_create.py @@ -11,6 +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, +) routes = flask.Blueprint("create", __name__, url_prefix="/create") schemas_dict = get_schemas_dict(os.path.join(os.path.dirname(__file__), "schemas")) @@ -62,3 +65,31 @@ 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..0673c797 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,32 @@ 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) + )