Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions requirements-internal.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --cert=None --client-cert=None --index-url=None --pip-args=None requirements-internal.in
#
blinker==1.9.0
# via
# flask
# opengeodeweb-microservice
click==8.3.0
# via
# flask
# opengeodeweb-microservice
fastjsonschema==2.21.1
# via opengeodeweb-microservice
flask==3.1.2
# via
# flask-sqlalchemy
# opengeodeweb-microservice
flask-sqlalchemy==3.1.1
# via opengeodeweb-microservice
greenlet==3.2.4
# via
# opengeodeweb-microservice
# sqlalchemy
itsdangerous==2.2.0
# via
# flask
# opengeodeweb-microservice
jinja2==3.1.6
# via
# flask
# opengeodeweb-microservice
markupsafe==3.0.3
# via
# flask
# jinja2
# opengeodeweb-microservice
# werkzeug
opengeodeweb-microservice==1.0.3
# via -r requirements-internal.in
sqlalchemy==2.0.43
# via
# flask-sqlalchemy
# opengeodeweb-microservice
typing-extensions==4.15.0
# via
# opengeodeweb-microservice
# sqlalchemy
werkzeug==3.1.3
# via
# flask
# opengeodeweb-microservice
2 changes: 1 addition & 1 deletion requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ geode-viewables==3.3.0
flask[async]==3.1.2
flask-cors==6.0.1
werkzeug==3.1.2
flask-sqlalchemy==3.1.1
flask-sqlalchemy==3.1.1
41 changes: 9 additions & 32 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,39 @@
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --output-file=./requirements.txt --pre ./requirements-internal.in ./requirements.in
# pip-compile --output-file=./requirements.txt --pre ./requirements.in
#
asgiref~=3.10
# via flask
blinker~=1.9
# via
# flask
# opengeodeweb-microservice
# via flask
click~=8.3
# via
# flask
# opengeodeweb-microservice
fastjsonschema~=2.21
# via opengeodeweb-microservice
# via flask
flask[async]~=3.1
# via
# -r requirements.in
# flask-cors
# flask-sqlalchemy
# opengeodeweb-microservice
flask-cors==6.0.1
# via -r requirements.in
flask-sqlalchemy==3.1.1
# via
# -r requirements.in
# opengeodeweb-microservice
# via -r requirements.in
geode-common==33.11.0
# via
# -r requirements.in
# geode-viewables
geode-viewables==3.3.0
# via -r requirements.in
greenlet~=3.2
# via
# opengeodeweb-microservice
# sqlalchemy
# via sqlalchemy
itsdangerous~=2.2
# via
# flask
# opengeodeweb-microservice
# via flask
jinja2~=3.1
# via
# flask
# opengeodeweb-microservice
# via flask
markupsafe~=3.0
# via
# flask
# jinja2
# opengeodeweb-microservice
# werkzeug
opengeode-core==15.27.4
# via
Expand All @@ -75,19 +59,12 @@ opengeode-io==7.4.0
# -r requirements.in
# geode-viewables
# opengeode-geosciencesio
opengeodeweb-microservice~=1.0,>=1.0.3
# via -r requirements-internal.in
sqlalchemy~=2.0
# via
# flask-sqlalchemy
# opengeodeweb-microservice
# via flask-sqlalchemy
typing-extensions~=4.15
# via
# opengeodeweb-microservice
# sqlalchemy
# via sqlalchemy
werkzeug==3.1.2
# via
# -r requirements.in
# flask
# flask-cors
# opengeodeweb-microservice
7 changes: 7 additions & 0 deletions src/opengeodeweb_back/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from opengeodeweb_back import utils_functions, app_config
from opengeodeweb_back.routes import blueprint_routes
from opengeodeweb_back.routes.models import blueprint_models
from opengeodeweb_back.routes.create import blueprint_create
from opengeodeweb_microservice.database.connection import init_database


Expand Down Expand Up @@ -51,6 +52,12 @@
name="opengeodeweb_models",
)

app.register_blueprint(
blueprint_create.routes,
url_prefix="/opengeodeweb_back/create",
name="opengeodeweb_create",
)

if FLASK_DEBUG == False:
utils_functions.set_interval(
utils_functions.kill_task, SECONDS_BETWEEN_SHUTDOWNS, app
Expand Down
28 changes: 2 additions & 26 deletions src/opengeodeweb_back/routes/blueprint_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

# Local application imports
from .. import geode_functions, utils_functions

from opengeodeweb_microservice.database.data import Data
from opengeodeweb_microservice.database.connection import get_session
from .models import blueprint_models

routes = flask.Blueprint("routes", __name__, url_prefix="/opengeodeweb_back")
Expand All @@ -36,7 +37,6 @@ def teardown_request(exception):
name=blueprint_models.routes.name,
)


schemas = os.path.join(os.path.dirname(__file__), "schemas")

with open(
Expand Down Expand Up @@ -258,30 +258,6 @@ def save_viewable_file():
)


with open(os.path.join(schemas, "create_point.json"), "r") as file:
create_point_json = json.load(file)


@routes.route(create_point_json["route"], methods=create_point_json["methods"])
def create_point():
utils_functions.validate_request(flask.request, create_point_json)
title = flask.request.get_json()["title"]
x = flask.request.get_json()["x"]
y = flask.request.get_json()["y"]
z = flask.request.get_json()["z"]
class_ = geode_functions.geode_object_class("PointSet3D")
PointSet3D = class_.create()
builder = geode_functions.create_builder("PointSet3D", PointSet3D)
builder.create_point(opengeode.Point3D([x, y, z]))
builder.set_name(title)
return flask.make_response(
utils_functions.generate_native_viewable_and_light_viewable_from_object(
"PointSet3D", PointSet3D
),
200,
)


with open(os.path.join(schemas, "texture_coordinates.json"), "r") as file:
texture_coordinates_json = json.load(file)

Expand Down
154 changes: 154 additions & 0 deletions src/opengeodeweb_back/routes/create/blueprint_create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Standard library imports
import json
import os
from typing import Dict, Any, List, TypedDict, cast

# Third party imports
import flask
import opengeode
import werkzeug

# Local application imports
from opengeodeweb_back import geode_functions, utils_functions
from opengeodeweb_microservice.database.data import Data
from opengeodeweb_microservice.database.connection import get_session
from opengeodeweb_back.utils_functions import save_all_viewables_and_return_info

routes = flask.Blueprint("create", __name__, url_prefix="/opengeodeweb_back/create")
schemas = os.path.join(os.path.dirname(__file__), "schemas")

# --- Type definitions for request validation ---
class Point(TypedDict):
x: float
y: float

class CreatePointRequest(TypedDict):
name: str
x: float
y: float
z: float

class CreateAOIRequest(TypedDict):
name: str
points: List[Point]
z: float

# Load schema for point creation
with open(os.path.join(schemas, "create_point.json"), "r") as file:
create_point_json = cast(Dict[str, Any], json.load(file))

@routes.route(
create_point_json["route"],
methods=create_point_json["methods"]
)
def create_point() -> flask.Response:
"""Endpoint to create a single point in 3D space."""
print(f"create_point : {flask.request=}", flush=True)
utils_functions.validate_request(flask.request, create_point_json)

try:
# Extract and validate data from request
request_data = cast(CreatePointRequest, flask.request.json)
name: str = request_data["name"]
x: float = request_data["x"]
y: float = request_data["y"]
z: float = request_data["z"]

# Create the point set
class_ = geode_functions.geode_object_class("PointSet3D")
point_set = class_.create()
builder = geode_functions.create_builder("PointSet3D", point_set)
builder.create_point(opengeode.Point3D([x, y, z])) # type: ignore
builder.set_name(name)

# Save and get info
result = save_all_viewables_and_return_info(
geode_object="PointSet3D",
data=point_set,
)

# Vérifier que binary_light_viewable est présent
if "binary_light_viewable" not in result:
raise ValueError("binary_light_viewable is missing in the result")

# Prepare response
response: Dict[str, Any] = {
"viewable_file_name": result["viewable_file_name"],
"id": result["id"],
"name": name,
"native_file_name": result["native_file_name"],
"object_type": result["object_type"],
"geode_object": result["geode_object"],
"binary_light_viewable": result["binary_light_viewable"],
}

return flask.make_response(response, 200)

except Exception as e:
return flask.make_response({"error": str(e)}, 500)

# Load schema for AOI creation
with open(os.path.join(schemas, "create_aoi.json"), "r") as file:
create_aoi_json = cast(Dict[str, Any], json.load(file))

@routes.route(
create_aoi_json["route"],
methods=create_aoi_json["methods"]
)
def create_aoi() -> flask.Response:
"""Endpoint to create an Area of Interest (AOI) as an EdgedCurve3D."""
print(f"create_aoi : {flask.request=}", flush=True)
utils_functions.validate_request(flask.request, create_aoi_json)

try:
# Extract and validate data from request
request_data = cast(CreateAOIRequest, flask.request.json)
name: str = request_data["name"]
points: List[Point] = request_data["points"]
z: float = request_data["z"]

# Create the edged curve
class_ = geode_functions.geode_object_class("EdgedCurve3D")
edged_curve = class_.create()
builder = geode_functions.create_builder("EdgedCurve3D", edged_curve)
builder.set_name(name)

# Create vertices first
vertex_indices: List[int] = []
for point in points:
vertex_id = builder.create_point(opengeode.Point3D([point["x"], point["y"], z])) # type: ignore
vertex_indices.append(vertex_id)

# Create edges between consecutive vertices and close the loop
num_vertices = len(vertex_indices)
for i in range(num_vertices):
next_i = (i + 1) % num_vertices
edge_id = builder.create_edge()
builder.set_edge_vertex(opengeode.EdgeVertex(edge_id, 0), vertex_indices[i]) # type: ignore
builder.set_edge_vertex(opengeode.EdgeVertex(edge_id, 1), vertex_indices[next_i]) # type: ignore

# Save and get info
result = save_all_viewables_and_return_info(
geode_object="EdgedCurve3D",
data=edged_curve,
)

# Vérifier que binary_light_viewable est présent
if "binary_light_viewable" not in result:
raise ValueError("binary_light_viewable is missing in the result")

# Prepare response
response: Dict[str, Any] = {
"viewable_file_name": result["viewable_file_name"],
"id": result["id"],
"name": name,
"native_file_name": result["native_file_name"],
"object_type": result["object_type"],
"geode_object": result["geode_object"],
"binary_light_viewable": result["binary_light_viewable"],
}

return flask.make_response(response, 200)

except Exception as e:
return flask.make_response({"error": str(e)}, 500)
Loading