diff --git a/CHANGELOG.md b/CHANGELOG.md index 491f40a..9d7eaa5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ # CHANGELOG +## v1.1.0-rc.2 (2024-12-09) + +### Bug Fixes + +- **edit schema**: Rv schema step + ([`7162f00`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/7162f00bdba04d29a84e80d16074dc59d64c6c73)) + + +## v1.1.0-rc.1 (2024-12-04) + + ## v1.0.0 (2024-11-29) @@ -35,16 +46,23 @@ ### Features +- **generic rpcs**: Refactor all classes/tests + ([`563f41b`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/563f41bc0741ab1dae9e5df9244e545e6ba47993)) + +- **generic rpcs**: Refactor all classes/tests + ([`297b005`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/297b0050e4ab47817659021c3a099e715fba6a87)) + +- **get_mouse**: New rpc + ([`94280f3`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/94280f3bc30f03e0c550cd7baf76afd30192c1e3)) + - **new rpcs**: Refactor rpcs ([`c2fb4e7`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/c2fb4e75b83a862267ed4641e41e9344e6a2d70f)) BREAKING CHANGE: change some rpc names in schemas -- **generic rpcs**: Refactor all classes/tests - ([`563f41b`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/563f41bc0741ab1dae9e5df9244e545e6ba47993)) +### BREAKING CHANGES -- **generic rpcs**: Refactor all classes/tests - ([`297b005`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/297b0050e4ab47817659021c3a099e715fba6a87)) +- **new rpcs**: Change some rpc names in schemas ## v0.4.0-rc.1 (2024-11-25) @@ -152,12 +170,12 @@ BREAKING CHANGE: change some rpc names in schemas ### Bug Fixes -- **schemas**: Delete image docker - ([`ebd416b`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/ebd416b5eceaecfce61d3c5e136cc3d6ed36184b)) - - **license**: Add copyleft file ([`a0cfd33`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/a0cfd3335e0b12913947917b631b5e13889a9107)) +- **schemas**: Delete image docker + ([`ebd416b`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/ebd416b5eceaecfce61d3c5e136cc3d6ed36184b)) + ### Chores - **licence**: Happy new year 2024 @@ -165,19 +183,19 @@ BREAKING CHANGE: change some rpc names in schemas ### Features +- **delete_object_pipeline**: Add rpc + ([`5a4df6a`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/5a4df6a5d20451491fe27d89886459d9a38f78cd)) + +Enables an object to be deleted from the viewer + - **schemas**: Remove dockerfile + a few changes ([`e81296a`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/e81296af2510c975c1d98034f269a5c94e4b89f5)) -- **schemas**: Test2 - ([`53dfa45`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/53dfa45953b098f8ecda5d8773e37fe064b4e7e3)) - - **schemas**: Test ([`6088534`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/6088534e990f44559575f2d4631bc731210e2243)) +- **schemas**: Test2 + ([`53dfa45`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/53dfa45953b098f8ecda5d8773e37fe064b4e7e3)) + - **unit tests**: Run server ([`11291b8`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/11291b8e808e52e1f4e6d0ab11b739ffd1542ecb)) - -- **delete_object_pipeline**: Add rpc - ([`5a4df6a`](https://github.com/Geode-solutions/OpenGeodeWeb-Viewer/commit/5a4df6a5d20451491fe27d89886459d9a38f78cd)) - -Enables an object to be deleted from the viewer diff --git a/pyproject.toml b/pyproject.toml index 83e3eb9..66262b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "OpenGeodeWeb-Viewer" -version = "1.0.0" +version = "1.1.0-rc.2" dynamic = ["dependencies"] authors = [ { name="Geode-solutions", email="team-web@geode-solutions.com" }, diff --git a/src/opengeodeweb_viewer/rpc/viewer/schemas/picked_ids.json b/src/opengeodeweb_viewer/rpc/viewer/schemas/picked_ids.json new file mode 100644 index 0000000..7073303 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/viewer/schemas/picked_ids.json @@ -0,0 +1,24 @@ +{ + "rpc": "picked_ids", + "type": "object", + "properties": { + "x": { + "type": "number" + }, + "y": { + "type": "number" + }, + "ids": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "x", + "y", + "ids" + ], + "additionalProperties": false +} \ No newline at end of file diff --git a/src/opengeodeweb_viewer/rpc/viewer/viewer_protocols.py b/src/opengeodeweb_viewer/rpc/viewer/viewer_protocols.py index 32051e7..98c355a 100644 --- a/src/opengeodeweb_viewer/rpc/viewer/viewer_protocols.py +++ b/src/opengeodeweb_viewer/rpc/viewer/viewer_protocols.py @@ -1,5 +1,6 @@ # Standard library imports import json +import math import os from pathlib import Path @@ -14,6 +15,7 @@ from opengeodeweb_viewer.utils_functions import get_schemas_dict, validate_schema from opengeodeweb_viewer.vtk_protocol import VtkView + class VtkViewerView(VtkView): prefix = "opengeodeweb_viewer.viewer." schemas_dict = get_schemas_dict(os.path.join(os.path.dirname(__file__), "schemas")) @@ -23,7 +25,9 @@ def __init__(self): @exportRpc(prefix + schemas_dict["create_visualization"]["rpc"]) def createVisualization(self, params): - print(self.schemas_dict["create_visualization"]["rpc"], f"{params=}", flush=True) + print( + self.schemas_dict["create_visualization"]["rpc"], f"{params=}", flush=True + ) validate_schema(params, self.schemas_dict["create_visualization"]) renderWindow = self.getView("-1") renderer = renderWindow.GetRenderers().GetFirstRenderer() @@ -34,7 +38,9 @@ def createVisualization(self, params): @exportRpc(prefix + schemas_dict["set_background_color"]["rpc"]) def setBackgroundColor(self, params): - print(self.schemas_dict["set_background_color"]["rpc"], f"{params=}", flush=True) + print( + self.schemas_dict["set_background_color"]["rpc"], f"{params=}", flush=True + ) validate_schema(params, self.schemas_dict["set_background_color"]) renderWindow = self.getView("-1") renderer = renderWindow.GetRenderers().GetFirstRenderer() @@ -90,7 +96,7 @@ def takeScreenshot(self, params): else: raise Exception("output_extension not supported") - new_filename = filename + '.' + output_extension + new_filename = filename + "." + output_extension file_path = os.path.join(self.DATA_FOLDER_PATH, new_filename) writer.SetFileName(file_path) writer.SetInputConnection(w2if.GetOutputPort()) @@ -101,7 +107,6 @@ def takeScreenshot(self, params): return {"blob": self.addAttachment(file_content)} - @exportRpc(prefix + schemas_dict["update_data"]["rpc"]) def updateData(self, params): print(self.schemas_dict["update_data"]["rpc"], f"{params=}", flush=True) @@ -142,3 +147,44 @@ def reset(self, params): validate_schema(params, self.schemas_dict["reset"]) renderWindow = self.getView("-1") renderWindow.GetRenderers().GetFirstRenderer().RemoveAllViewProps() + + def computeEpsilon(self, renderer, z): + renderer.SetDisplayPoint(0, 0, z) + renderer.DisplayToWorld() + windowLowerLeft = renderer.GetWorldPoint() + size = renderer.GetRenderWindow().GetSize() + renderer.SetDisplayPoint(size[0], size[1], z) + renderer.DisplayToWorld() + windowUpperRight = renderer.GetWorldPoint() + epsilon = 0 + for i in range(3): + epsilon += (windowUpperRight[i] - windowLowerLeft[i]) * ( + windowUpperRight[i] - windowLowerLeft[i] + ) + return math.sqrt(epsilon) * 0.0125 + + @exportRpc(prefix + schemas_dict["picked_ids"]["rpc"]) + def pickedIds(self, params): + print(self.schemas_dict["picked_ids"]["rpc"], f"{params=}", flush=True) + validate_schema(params, self.schemas_dict["picked_ids"]) + x = params["x"] + y = params["y"] + ids = params["ids"] + + renderWindow = self.getView("-1") + renderer = renderWindow.GetRenderers().GetFirstRenderer() + picker = vtk.vtkWorldPointPicker() + picker.Pick([x, y, 0], renderer) + point = picker.GetPickPosition() + epsilon = self.computeEpsilon(renderer, point[2]) + bbox = vtk.vtkBoundingBox() + bbox.AddPoint(point[0] + epsilon, point[1] + epsilon, point[2] + epsilon) + bbox.AddPoint(point[0] - epsilon, point[1] - epsilon, point[2] - epsilon) + + array_ids = [] + for id in ids: + bounds = self.get_object(id)["actor"].GetBounds() + if bbox.Intersects(bounds): + array_ids.append(id) + + return {"array_ids": array_ids} diff --git a/src/tests/test_viewer_protocols.py b/src/tests/test_viewer_protocols.py index d60b01e..bef7ac1 100644 --- a/src/tests/test_viewer_protocols.py +++ b/src/tests/test_viewer_protocols.py @@ -7,23 +7,37 @@ # Local application imports from .test_mesh_protocols import test_register_mesh + def test_create_visualization(server): - server.call(VtkViewerView.prefix + VtkViewerView.schemas_dict["create_visualization"]["rpc"]) + server.call( + VtkViewerView.prefix + VtkViewerView.schemas_dict["create_visualization"]["rpc"] + ) assert server.compare_image(3, "viewer/create_visualization.jpeg") == True + def test_reset_camera(server): - server.call(VtkViewerView.prefix + VtkViewerView.schemas_dict["reset_camera"]["rpc"]) + server.call( + VtkViewerView.prefix + VtkViewerView.schemas_dict["reset_camera"]["rpc"] + ) assert server.compare_image(3, "viewer/reset_camera.jpeg") == True + def test_set_viewer_background_color(server): - server.call(VtkViewerView.prefix + VtkViewerView.schemas_dict["set_background_color"]["rpc"], [{"red": 0, "green": 0, "blue": 255}]) + server.call( + VtkViewerView.prefix + + VtkViewerView.schemas_dict["set_background_color"]["rpc"], + [{"red": 0, "green": 0, "blue": 255}], + ) assert server.compare_image(3, "viewer/set_background_color.jpeg") == True -def test_get_point_position(server): +def test_get_point_position(server): test_register_mesh(server) - server.call(VtkViewerView.prefix + VtkViewerView.schemas_dict["get_point_position"]["rpc"], [{"x": 0, "y": 0}]) + server.call( + VtkViewerView.prefix + VtkViewerView.schemas_dict["get_point_position"]["rpc"], + [{"x": 0, "y": 0}], + ) response = server.get_response() assert "x" in response["result"] assert "y" in response["result"] @@ -43,7 +57,13 @@ def test_take_screenshot(server): # Take a screenshot with background jpg server.call( VtkViewerView.prefix + VtkViewerView.schemas_dict["take_screenshot"]["rpc"], - [{"filename": "take_screenshot_with_background", "output_extension": "jpg", "include_background": True}], + [ + { + "filename": "take_screenshot_with_background", + "output_extension": "jpg", + "include_background": True, + } + ], ) response = server.get_response() @@ -54,16 +74,24 @@ def test_take_screenshot(server): f.write(blob) f.close() first_image_path = os.path.join(server.test_output_dir, "test.jpg") - second_image_path = os.path.join(server.images_dir_path, "viewer/take_screenshot_with_background.jpg") + second_image_path = os.path.join( + server.images_dir_path, "viewer/take_screenshot_with_background.jpg" + ) assert server.images_diff(first_image_path, second_image_path) == 0.0 # Take a screenshot without background png server.call( VtkViewerView.prefix + VtkViewerView.schemas_dict["take_screenshot"]["rpc"], - [{"filename": "take_screenshot_without_background", "output_extension": "png", "include_background": True}], + [ + { + "filename": "take_screenshot_without_background", + "output_extension": "png", + "include_background": True, + } + ], ) - + response = server.get_response() response = server.get_response() blob = server.get_response() @@ -74,16 +102,24 @@ def test_take_screenshot(server): f.write(blob) f.close() first_image_path = os.path.join(server.test_output_dir, "test.png") - second_image_path = os.path.join(server.images_dir_path, "viewer/take_screenshot_without_background.png") + second_image_path = os.path.join( + server.images_dir_path, "viewer/take_screenshot_without_background.png" + ) assert server.images_diff(first_image_path, second_image_path) == 0.0 # Take a screenshot with background png server.call( VtkViewerView.prefix + VtkViewerView.schemas_dict["take_screenshot"]["rpc"], - [{"filename": "take_screenshot_with_background", "output_extension": "png", "include_background": True}], + [ + { + "filename": "take_screenshot_with_background", + "output_extension": "png", + "include_background": True, + } + ], ) - + response = server.get_response() response = server.get_response() blob = server.get_response() @@ -94,6 +130,32 @@ def test_take_screenshot(server): f.write(blob) f.close() first_image_path = os.path.join(server.test_output_dir, "test.png") - second_image_path = os.path.join(server.images_dir_path, "viewer/take_screenshot_with_background.png") + second_image_path = os.path.join( + server.images_dir_path, "viewer/take_screenshot_with_background.png" + ) assert server.images_diff(first_image_path, second_image_path) == 0.0 + + +def test_picked_ids(server): + + test_register_mesh(server) + + server.call( + VtkViewerView.prefix + VtkViewerView.schemas_dict["picked_ids"]["rpc"], + [{"x": 100, "y": 200, "ids": ["123456789"]}], + ) + response = server.get_response() + + print(f"Response: {response}", flush=True) + + assert "result" in response, f"Key 'result' not found in response: {response}" + + assert ( + "array_ids" in response["result"] + ), f"Key 'array_ids' not found in response['result']: {response['result']}" + + array_ids = response["result"]["array_ids"] + assert isinstance(array_ids, list), f"Expected a list, but got {type(array_ids)}" + assert all(isinstance(id, str) for id in array_ids), "All IDs should be strings" + assert len(array_ids) > 0, "The list of array_ids should not be empty" diff --git a/src/tests/tests_output/test.jpeg b/src/tests/tests_output/test.jpeg index ee7e056..6b2509f 100644 Binary files a/src/tests/tests_output/test.jpeg and b/src/tests/tests_output/test.jpeg differ