Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,3 @@ werkzeug==3.1.8
# flask
# flask-cors

opengeodeweb-microservice==1.*,>=1.2.2
45 changes: 32 additions & 13 deletions src/opengeodeweb_back/routes/blueprint_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,23 +257,42 @@ def extract_valid_attribute_values(
attribute_name: str,
item_index: int,
) -> tuple[list[float], bool]:
attribute_ids_matching_name = attribute_manager.attribute_ids_matching_name(
attribute_name
)
if not isinstance(attribute_ids_matching_name, list):
return [], False
component_attribute = attribute_manager.find_generic_attribute(
attribute_ids_matching_name[0]
)
if component_attribute is None:
attribute_ids = attribute_manager.attribute_ids_matching_name(attribute_name)
if not isinstance(attribute_ids, list):
return [], False
if not component_attribute.is_genericable():
attribute = attribute_manager.find_generic_attribute(attribute_ids[0])
if (
attribute is None
or not attribute.is_genericable()
or not attribute.properties().transferable
):
return [], False

nb_items = attribute.nb_items()
default_values = getattr(attribute, "default_values", None)
no_value = default_values().no_value if default_values else None
if no_value is None and (
"Point" in attribute.type() or "Vector" in attribute.type()
):
no_value = [0.0] * nb_items

value_getter = getattr(
attribute,
"value",
lambda element_index: [
attribute.generic_item_value(element_index, i) for i in range(nb_items)
],
)

valid_values: list[float] = []
has_nan = False
for element_index in range(attribute_manager.nb_elements()):
value = component_attribute.generic_item_value(element_index, item_index)
if value is None or math.isnan(value):
value = attribute.generic_item_value(element_index, item_index)
if (
value is None
or math.isnan(value)
or (no_value is not None and value_getter(element_index) == no_value)
):
has_nan = True
else:
valid_values.append(value)
Expand All @@ -293,7 +312,7 @@ def attributes_metadata(
attribute_name = attribute.name()
if attribute_name is None:
continue
if not attribute.is_genericable():
if not attribute.is_genericable() or not attribute.properties().transferable:
continue
nb_items = attribute.nb_items()
min_values, max_values = [], []
Expand Down
46 changes: 46 additions & 0 deletions tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os

# Third party imports
import opengeode as og
from werkzeug.datastructures import FileStorage
from flask.testing import FlaskClient
from werkzeug.test import TestResponse
Expand All @@ -13,6 +14,7 @@
from opengeodeweb_microservice.database.data import Data
from opengeodeweb_microservice.database.connection import get_session
from opengeodeweb_back import geode_functions, test_utils
from opengeodeweb_back.routes.blueprint_routes import extract_valid_attribute_values
from opengeodeweb_back.geode_objects.geode_polygonal_surface3d import (
GeodePolygonalSurface3D,
)
Expand Down Expand Up @@ -744,3 +746,47 @@ def get_full_data() -> test_utils.JsonData:
return {"id": model_id, "component_ids": block_ids}

test_utils.test_route_wrong_params(client, route, get_full_data)


def test_extract_valid_attribute_values_with_sentinel_no_value() -> None:
mesh = og.TriangulatedSurface3D.create()
builder = og.TriangulatedSurfaceBuilder3D.create(mesh)
vertex_0 = builder.create_point(og.Point3D([0, 0, 0]))
vertex_1 = builder.create_point(og.Point3D([1, 0, 0]))
builder.create_triangle([vertex_0, vertex_1, vertex_0])

attribute_manager = mesh.vertex_attribute_manager()
values_config = og.AttributeValuesDouble()
values_config.no_value = -999.0
attribute_id = attribute_manager.create_attribute_variable_double(
"variable_double", values_config, og.AttributeProperties()
)
attribute = attribute_manager.find_attribute_variable_double(attribute_id)
attribute.set_value(vertex_0, -999.0)
attribute.set_value(vertex_1, 42.0)

valid_values, has_nan = extract_valid_attribute_values(
attribute_manager, "variable_double", 0
)
assert has_nan is True
assert valid_values == [42.0]


def test_extract_valid_attribute_values_with_non_transferable_attribute() -> None:
mesh = og.TriangulatedSurface3D.create()
builder = og.TriangulatedSurfaceBuilder3D.create(mesh)
vertex_0 = builder.create_point(og.Point3D([0, 0, 0]))
builder.create_triangle([vertex_0, vertex_0, vertex_0])

attribute_manager = mesh.vertex_attribute_manager()
properties = og.AttributeProperties()
properties.transferable = False
attribute_manager.create_attribute_variable_double(
"internal_attribute", og.AttributeValuesDouble(), properties
)

valid_values, has_nan = extract_valid_attribute_values(
attribute_manager, "internal_attribute", 0
)
assert has_nan is False
assert valid_values == []
Loading