From 52fced52d38c61f9ad5d6e317f16bd7f8272260d Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Wed, 21 Oct 2026 14:27:22 +0200 Subject: [PATCH 01/10] feat(edgesAttributes): Mesh edges get their own actor as points so attributes colors only edges not the polygons, polyhedra, ... --- .../object/object_methods.py | 93 +++++++++++++--- .../edges_attribute_vertex_protocols.py | 5 +- .../rpc/mesh/mesh_protocols.py | 39 +++++-- src/opengeodeweb_viewer/vtk_pipeline.py | 6 ++ src/opengeodeweb_viewer/vtk_protocol.py | 10 ++ .../polygons_edges_attribute_then_color.jpeg | Bin 0 -> 19611 bytes .../polygons_edges_hidden_with_object.jpeg | Bin 0 -> 1072 bytes .../polygons_edges_shared_scalar_bar.jpeg | Bin 0 -> 14287 bytes .../polygons_edges_vertex_attribute.jpeg | Bin 0 -> 19490 bytes .../test_edges_attribute_vertex_protocols.py | 101 ++++++++++++++++++ 10 files changed, 233 insertions(+), 21 deletions(-) create mode 100644 tests/data/images/mesh/edges/polygons_edges_attribute_then_color.jpeg create mode 100644 tests/data/images/mesh/edges/polygons_edges_hidden_with_object.jpeg create mode 100644 tests/data/images/mesh/edges/polygons_edges_shared_scalar_bar.jpeg create mode 100644 tests/data/images/mesh/edges/polygons_edges_vertex_attribute.jpeg diff --git a/src/opengeodeweb_viewer/object/object_methods.py b/src/opengeodeweb_viewer/object/object_methods.py index 85dc1f54..43020018 100644 --- a/src/opengeodeweb_viewer/object/object_methods.py +++ b/src/opengeodeweb_viewer/object/object_methods.py @@ -59,6 +59,10 @@ def remove_object(self, data_id: str) -> None: renderer.RemoveViewProp(pipeline.points_scalar_bar) for size_actor in pipeline.points_size_actors.values(): renderer.RemoveActor(size_actor.actor) + if pipeline.edges_actor is not None: + renderer.RemoveActor(pipeline.edges_actor) + if pipeline.edges_scalar_bar is not None: + renderer.RemoveViewProp(pipeline.edges_scalar_bar) renderer.RemoveViewProp(pipeline.scalar_bar) for bar in pipeline.scalar_bars.values(): renderer.RemoveViewProp(bar) @@ -68,13 +72,15 @@ def remove_object(self, data_id: str) -> None: def set_visibility(self, data_id: str, *, visibility: bool) -> None: pipeline = self.get_vtk_pipeline(data_id) pipeline.actor.SetVisibility(visibility) - self.set_points_actors_visibility(pipeline, visibility=visibility) + self.set_style_actors_visibility(pipeline, visibility=visibility) if not visibility: pipeline.scalar_bar.VisibilityOff() for bar in pipeline.scalar_bars.values(): bar.VisibilityOff() if pipeline.points_scalar_bar is not None: pipeline.points_scalar_bar.VisibilityOff() + if pipeline.edges_scalar_bar is not None: + pipeline.edges_scalar_bar.VisibilityOff() else: if ( pipeline.mapper.GetScalarVisibility() @@ -82,6 +88,7 @@ def set_visibility(self, data_id: str, *, visibility: bool) -> None: ): pipeline.scalar_bar.VisibilityOn() self.update_points_scalar_bar_visibility(pipeline) + self.update_edges_scalar_bar_visibility(pipeline) for style in pipeline.block_styles.values(): if style.get("name"): for bar in pipeline.scalar_bars.values(): @@ -90,11 +97,13 @@ def set_visibility(self, data_id: str, *, visibility: bool) -> None: break self.update_scalar_bars_layout() - def set_points_actors_visibility(self, pipeline: VtkPipeline, *, visibility: bool) -> None: + def set_style_actors_visibility(self, pipeline: VtkPipeline, *, visibility: bool) -> None: if pipeline.points_actor is not None: pipeline.points_actor.SetVisibility(visibility and pipeline.points_visibility) for size_actor in pipeline.points_size_actors.values(): size_actor.actor.SetVisibility(visibility) + if pipeline.edges_actor is not None: + pipeline.edges_actor.SetVisibility(visibility and pipeline.edges_visibility) def set_opacity(self, data_id: str, opacity: float) -> None: actor = self.get_vtk_pipeline(data_id).actor @@ -110,23 +119,42 @@ def set_color(self, data_id: str, color: ColorClassProtocol) -> None: def set_edges_visibility(self, data_id: str, *, visibility: bool) -> None: if self.get_viewer_data(data_id).viewer_elements_type == "edges": self.set_visibility(data_id, visibility=visibility) - else: - actor = self.get_vtk_pipeline(data_id).actor - actor.GetProperty().SetEdgeVisibility(visibility) + return + pipeline = self.get_vtk_pipeline(data_id) + if pipeline.edges_actor is None: + pipeline.actor.GetProperty().SetEdgeVisibility(visibility) + return + pipeline.edges_visibility = visibility + pipeline.edges_actor.SetVisibility(pipeline.actor.GetVisibility() and visibility) + self.update_edges_scalar_bar_visibility(pipeline) + self.update_scalar_bars_layout() def set_edges_width(self, data_id: str, width: float) -> None: - actor = self.get_vtk_pipeline(data_id).actor + pipeline = self.get_vtk_pipeline(data_id) if self.get_viewer_data(data_id).viewer_elements_type == "edges": - actor.GetProperty().SetLineWidth(width) - else: - actor.GetProperty().SetEdgeWidth(width) + pipeline.actor.GetProperty().SetLineWidth(width) + return + pipeline.actor.GetProperty().SetEdgeWidth(width) + if pipeline.edges_actor is not None: + pipeline.edges_actor.GetProperty().SetLineWidth(width) def set_edges_color(self, data_id: str, color: ColorClassProtocol) -> None: if self.get_viewer_data(data_id).viewer_elements_type == "edges": self.set_color(data_id, color) - else: - actor = self.get_vtk_pipeline(data_id).actor - actor.GetProperty().SetEdgeColor([color.red / 255, color.green / 255, color.blue / 255]) + return + pipeline = self.get_vtk_pipeline(data_id) + rgb = [color.red / 255, color.green / 255, color.blue / 255] + pipeline.actor.GetProperty().SetEdgeColor(rgb) + if pipeline.edges_actor is None or pipeline.edges_mapper is None: + return + # A constant color replaces the edges attribute and its scalar bar + pipeline.edges_mapper.ScalarVisibilityOff() + pipeline.edges_actor.GetProperty().SetColor(rgb) + pipeline.edges_actor.GetProperty().SetOpacity(color.alpha) + if pipeline.edges_scalar_bar is not None: + pipeline.edges_scalar_bar.SetLookupTable(None) + self.update_edges_scalar_bar_visibility(pipeline) + self.update_scalar_bars_layout() def set_points_visibility(self, data_id: str, *, visibility: bool) -> None: if self.get_viewer_data(data_id).viewer_elements_type == "points": @@ -186,6 +214,47 @@ def update_points_scalar_bar_visibility(self, pipeline: VtkPipeline) -> None: and bar.GetLookupTable() is not None ) + def ensure_edges_actor(self, pipeline: VtkPipeline) -> vtkActor: + # Edges get their own actor so their scalars stay independent from the polygons + if pipeline.edges_actor is not None: + return pipeline.edges_actor + mapper = vtkDataSetMapper() + mapper.SetInputConnection(pipeline.filter.GetOutputPort()) + mapper.ScalarVisibilityOff() + mapper.SetResolveCoincidentTopologyLineOffsetParameters(0, -4) + actor = vtkActor() + actor.SetMapper(mapper) + actor.PickableOff() + main_property = pipeline.actor.GetProperty() + edges_property = actor.GetProperty() + edges_property.SetRepresentationToWireframe() + edges_property.SetLineWidth(main_property.GetEdgeWidth()) + edges_property.SetColor(*main_property.GetEdgeColor()) + pipeline.edges_visibility = bool(main_property.GetEdgeVisibility()) + actor.SetVisibility(pipeline.actor.GetVisibility() and pipeline.edges_visibility) + main_property.EdgeVisibilityOff() + scalar_bar = vtkScalarBarActor() + scalar_bar.VisibilityOff() + render_window = self.getView("-1") + renderer = render_window.GetRenderers().GetFirstRenderer() + renderer.AddActor(actor) + renderer.AddViewProp(scalar_bar) + pipeline.edges_mapper = mapper + pipeline.edges_actor = actor + pipeline.edges_scalar_bar = scalar_bar + return actor + + def update_edges_scalar_bar_visibility(self, pipeline: VtkPipeline) -> None: + # An edges scalar bar only holds a lookup table when it differs from the polygons one + bar = pipeline.edges_scalar_bar + if bar is None: + return + bar.SetVisibility( + pipeline.actor.GetVisibility() + and pipeline.edges_visibility + and bar.GetLookupTable() is not None + ) + def set_points_color(self, data_id: str, color: ColorClassProtocol) -> None: if self.get_viewer_data(data_id).viewer_elements_type == "points": self.set_color(data_id, color) diff --git a/src/opengeodeweb_viewer/rpc/mesh/edges/attribute/vertex/edges_attribute_vertex_protocols.py b/src/opengeodeweb_viewer/rpc/mesh/edges/attribute/vertex/edges_attribute_vertex_protocols.py index 5e48b17f..74c11aef 100644 --- a/src/opengeodeweb_viewer/rpc/mesh/edges/attribute/vertex/edges_attribute_vertex_protocols.py +++ b/src/opengeodeweb_viewer/rpc/mesh/edges/attribute/vertex/edges_attribute_vertex_protocols.py @@ -22,5 +22,8 @@ def __init__(self) -> None: def set_mesh_edges_vertex_attribute( self, params: schemas.Attribute ) -> schemas.AttributeResponse: - self.display_attribute_on_vertices(params.id, params) + if self.get_viewer_data(params.id).viewer_elements_type == "edges": + self.display_attribute_on_vertices(params.id, params) + else: + self.display_attribute_on_edges(params.id, params) return schemas.AttributeResponse() diff --git a/src/opengeodeweb_viewer/rpc/mesh/mesh_protocols.py b/src/opengeodeweb_viewer/rpc/mesh/mesh_protocols.py index 238e0239..4ed89f8f 100644 --- a/src/opengeodeweb_viewer/rpc/mesh/mesh_protocols.py +++ b/src/opengeodeweb_viewer/rpc/mesh/mesh_protocols.py @@ -8,6 +8,7 @@ # Third party imports from opengeodeweb_microservice.schemas import get_schemas_dict from vtkmodules.vtkIOXML import vtkXMLGenericDataObjectReader, vtkXMLImageDataReader +from vtkmodules.vtkRenderingAnnotation import vtkScalarBarActor from vtkmodules.vtkRenderingCore import ( vtkDataSetMapper, vtkTexture, @@ -114,9 +115,33 @@ def display_attribute_on_vertices(self, data_id: str, attribute: AttributeProtoc def display_attribute_on_points(self, data_id: str, attribute: AttributeProtocol) -> None: pipeline = self.get_vtk_pipeline(data_id) self.ensure_points_actor(pipeline) - mapper = pipeline.points_mapper - if mapper is None: + if pipeline.points_mapper is None: return + self.display_attribute_on_style_mapper( + data_id, pipeline.points_mapper, pipeline.points_scalar_bar, attribute + ) + self.update_points_scalar_bar_visibility(pipeline) + self.update_scalar_bars_layout() + + def display_attribute_on_edges(self, data_id: str, attribute: AttributeProtocol) -> None: + pipeline = self.get_vtk_pipeline(data_id) + self.ensure_edges_actor(pipeline) + if pipeline.edges_mapper is None: + return + self.display_attribute_on_style_mapper( + data_id, pipeline.edges_mapper, pipeline.edges_scalar_bar, attribute + ) + self.update_edges_scalar_bar_visibility(pipeline) + self.update_scalar_bars_layout() + + def display_attribute_on_style_mapper( + self, + data_id: str, + mapper: vtkDataSetMapper, + scalar_bar: vtkScalarBarActor | None, + attribute: AttributeProtocol, + ) -> None: + pipeline = self.get_vtk_pipeline(data_id) # Field data mode avoids touching the active scalars shared with the polygons mapper.ScalarVisibilityOn() mapper.SetScalarModeToUsePointFieldData() @@ -124,7 +149,7 @@ def display_attribute_on_points(self, data_id: str, attribute: AttributeProtocol if self.shares_polygons_color_map(data_id, attribute): # Same color map as the polygons: reuse their scalar bar instead of adding one lut = pipeline.mapper.GetLookupTable() - points_bar_lut = None + bar_lut = None else: lut = create_color_transfer_function( attribute.points, @@ -134,15 +159,13 @@ def display_attribute_on_points(self, data_id: str, attribute: AttributeProtocol attribute.no_data_color, ) lut.SetRange(attribute.minimum, attribute.maximum) - points_bar_lut = lut + bar_lut = lut mapper.SetLookupTable(lut) mapper.SetScalarRange(attribute.minimum, attribute.maximum) mapper.UseLookupTableScalarRangeOff() mapper.InterpolateScalarsBeforeMappingOn() - if pipeline.points_scalar_bar is not None: - pipeline.points_scalar_bar.SetLookupTable(points_bar_lut) - self.update_points_scalar_bar_visibility(pipeline) - self.update_scalar_bars_layout() + if scalar_bar is not None: + scalar_bar.SetLookupTable(bar_lut) def shares_polygons_color_map(self, data_id: str, attribute: AttributeProtocol) -> bool: pipeline = self.get_vtk_pipeline(data_id) diff --git a/src/opengeodeweb_viewer/vtk_pipeline.py b/src/opengeodeweb_viewer/vtk_pipeline.py index e7f00a9f..b1f5b9a0 100644 --- a/src/opengeodeweb_viewer/vtk_pipeline.py +++ b/src/opengeodeweb_viewer/vtk_pipeline.py @@ -248,11 +248,17 @@ class VtkPipeline: # One points actor per distinct size, since point size is an actor property points_size_actors: dict[float, PointsSizeActor] = field(default_factory=dict) points_block_styles: dict[int, ModelPointsStyle] = field(default_factory=dict) + edges_mapper: vtkDataSetMapper | None = None + edges_actor: vtkActor | None = None + edges_scalar_bar: vtkScalarBarActor | None = None + edges_visibility: bool = False def connect_mappers(self) -> None: self.mapper.SetInputConnection(self.filter.GetOutputPort()) if self.points_mapper is not None: self.points_mapper.SetInputConnection(self.filter.GetOutputPort()) + if self.edges_mapper is not None: + self.edges_mapper.SetInputConnection(self.filter.GetOutputPort()) def extract_blocks(self, multiblock: vtkDataObject | None) -> list[vtkDataObject | None]: if not isinstance(multiblock, vtkMultiBlockDataSet): diff --git a/src/opengeodeweb_viewer/vtk_protocol.py b/src/opengeodeweb_viewer/vtk_protocol.py index 93a42115..22781eab 100644 --- a/src/opengeodeweb_viewer/vtk_protocol.py +++ b/src/opengeodeweb_viewer/vtk_protocol.py @@ -527,6 +527,16 @@ def visible_scalar_bars( points_attr_name = pipeline.points_mapper.GetArrayName() visible_bars.append((points_bar, points_attr_name, data_id, pipeline)) + edges_bar = pipeline.edges_scalar_bar + if ( + edges_bar is not None + and pipeline.edges_mapper is not None + and edges_bar.GetVisibility() + and edges_bar.GetLookupTable() is not None + ): + edges_attr_name = pipeline.edges_mapper.GetArrayName() + visible_bars.append((edges_bar, edges_attr_name, data_id, pipeline)) + for attr_name, bar in pipeline.scalar_bars.items(): if bar.GetVisibility() and bar.GetLookupTable() is not None: visible_bars.append((bar, attr_name, data_id, pipeline)) diff --git a/tests/data/images/mesh/edges/polygons_edges_attribute_then_color.jpeg b/tests/data/images/mesh/edges/polygons_edges_attribute_then_color.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..d8825dbeaf754369daef9c6856170a669a2e70e0 GIT binary patch literal 19611 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 Xhn$pUZBlU__7fr@3I6~h{{a8l*n+oH literal 0 HcmV?d00001 diff --git a/tests/data/images/mesh/edges/polygons_edges_hidden_with_object.jpeg b/tests/data/images/mesh/edges/polygons_edges_hidden_with_object.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..35b6a3d48a33a5b247cedb58137770255ba7d5f3 GIT binary patch literal 1072 zcmeH^I}XAy5JYFZ0!4_zmf!$Tr%ay$DH2=?ZW7LdI0T=DBXEOd9R-m@N+?pox>|d@ zpLu%G2mG$s79auIf!?vPY+S@5<0{y1Js~7anF`l%ffA@^EUQt`jG0|8;sWi^8|Fed zFWz=5pY7LQ&-T$Y-!<)MrX^-2CoU_aB6JmpN+D#kGx3MEd{$ literal 0 HcmV?d00001 diff --git a/tests/data/images/mesh/edges/polygons_edges_shared_scalar_bar.jpeg b/tests/data/images/mesh/edges/polygons_edges_shared_scalar_bar.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..8812def651502e153c012f2ea48784321e9e74e5 GIT binary patch literal 14287 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 QhHVd1^?UVD{JZwQ083JgQUCw| literal 0 HcmV?d00001 diff --git a/tests/data/images/mesh/edges/polygons_edges_vertex_attribute.jpeg b/tests/data/images/mesh/edges/polygons_edges_vertex_attribute.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..362141206a82ec3b29e82351938d177df84450f7 GIT binary patch literal 19490 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 None: + dataset_factory(data_id=mesh_id, viewable_file="hat.vtp", viewer_elements_type="polygons") + server.call( + VtkMeshView.mesh_prefix + VtkMeshView.mesh_schemas_dict["register"]["rpc"], + [{"id": mesh_id, "name": "hat.vtp"}], + ) + server.call( + VtkMeshEdgesView.mesh_edges_prefix + + VtkMeshEdgesView.mesh_edges_schemas_dict["visibility"]["rpc"], + [{"id": mesh_id, "visibility": True}], + ) + server.call( + VtkMeshEdgesView.mesh_edges_prefix + + VtkMeshEdgesView.mesh_edges_schemas_dict["width"]["rpc"], + [{"id": mesh_id, "width": 4}], + ) + + +def set_edges_vertex_attribute(server: ServerMonitor, attribute: dict[str, object]) -> None: + server.call( + VtkMeshEdgesAttributeVertexView.mesh_edges_attribute_vertex_prefix + + VtkMeshEdgesAttributeVertexView.mesh_edges_attribute_vertex_schemas_dict["attribute"][ + "rpc" + ], + [{"id": mesh_id, **attribute}], + ) + + +def test_polygons_edges_vertex_attribute( + server: ServerMonitor, dataset_factory: Callable[..., str] +) -> None: + + register_hat_with_edges(server, dataset_factory) + set_edges_vertex_attribute(server, HAT_ATTRIBUTE) + # Polygons keep their constant color, only the edges are colored + assert server.compare_image("mesh/edges/polygons_edges_vertex_attribute.jpeg") + + +def test_polygons_edges_shared_scalar_bar( + server: ServerMonitor, dataset_factory: Callable[..., str] +) -> None: + + register_hat_with_edges(server, dataset_factory) + server.call( + VtkMeshPolygonsAttributeVertexView.mesh_polygons_attribute_vertex_prefix + + VtkMeshPolygonsAttributeVertexView.mesh_polygons_attribute_vertex_schemas_dict[ + "attribute" + ]["rpc"], + [{"id": mesh_id, **HAT_ATTRIBUTE}], + ) + set_edges_vertex_attribute(server, HAT_ATTRIBUTE) + # Same attribute and color map: one scalar bar only + assert server.compare_image("mesh/edges/polygons_edges_shared_scalar_bar.jpeg") + + +def test_polygons_edges_attribute_then_color( + server: ServerMonitor, dataset_factory: Callable[..., str] +) -> None: + + register_hat_with_edges(server, dataset_factory) + set_edges_vertex_attribute(server, HAT_ATTRIBUTE) + server.call( + VtkMeshEdgesView.mesh_edges_prefix + + VtkMeshEdgesView.mesh_edges_schemas_dict["color"]["rpc"], + [{"id": mesh_id, "color": {"red": 255, "green": 0, "blue": 0, "alpha": 1.0}}], + ) + # Red edges, no edges scalar bar + assert server.compare_image("mesh/edges/polygons_edges_attribute_then_color.jpeg") + + +def test_polygons_edges_hidden_with_object( + server: ServerMonitor, dataset_factory: Callable[..., str] +) -> None: + + register_hat_with_edges(server, dataset_factory) + set_edges_vertex_attribute(server, HAT_ATTRIBUTE) + server.call( + VtkMeshView.mesh_prefix + VtkMeshView.mesh_schemas_dict["visibility"]["rpc"], + [{"id": mesh_id, "visibility": False}], + ) + # Empty scene: no edges, no scalar bar + assert server.compare_image("mesh/edges/polygons_edges_hidden_with_object.jpeg") From 37ae50cff8371cf86728097b01ac08e76d872a8d Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Wed, 21 Oct 2026 14:29:54 +0200 Subject: [PATCH 02/10] set_edges_width sets the main actor LineWidth (only edges and wireframe use it on these meshes) --- src/opengeodeweb_viewer/object/object_methods.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/opengeodeweb_viewer/object/object_methods.py b/src/opengeodeweb_viewer/object/object_methods.py index 43020018..cf4ea842 100644 --- a/src/opengeodeweb_viewer/object/object_methods.py +++ b/src/opengeodeweb_viewer/object/object_methods.py @@ -134,7 +134,8 @@ def set_edges_width(self, data_id: str, width: float) -> None: if self.get_viewer_data(data_id).viewer_elements_type == "edges": pipeline.actor.GetProperty().SetLineWidth(width) return - pipeline.actor.GetProperty().SetEdgeWidth(width) + # VTK draws polygon edges with the line width, the edge width property is not rendered + pipeline.actor.GetProperty().SetLineWidth(width) if pipeline.edges_actor is not None: pipeline.edges_actor.GetProperty().SetLineWidth(width) @@ -228,7 +229,7 @@ def ensure_edges_actor(self, pipeline: VtkPipeline) -> vtkActor: main_property = pipeline.actor.GetProperty() edges_property = actor.GetProperty() edges_property.SetRepresentationToWireframe() - edges_property.SetLineWidth(main_property.GetEdgeWidth()) + edges_property.SetLineWidth(main_property.GetLineWidth()) edges_property.SetColor(*main_property.GetEdgeColor()) pipeline.edges_visibility = bool(main_property.GetEdgeVisibility()) actor.SetVisibility(pipeline.actor.GetVisibility() and pipeline.edges_visibility) From 414c6138ab1d746fe87d82b35e4036f793dfa87e Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Wed, 21 Oct 2026 14:33:06 +0200 Subject: [PATCH 03/10] feat(modelEdges): Model edges can be style per block --- .../object/object_methods.py | 5 + .../rpc/model/edges/model_edges_protocols.py | 7 +- .../rpc/model/edges/schemas/__init__.py | 1 + .../rpc/model/edges/schemas/width.json | 25 ++++ .../rpc/model/edges/schemas/width.py | 31 ++++ .../rpc/model/model_protocols.py | 141 +++++++++++++++++- src/opengeodeweb_viewer/vtk_pipeline.py | 93 ++++++++---- tests/data/images/model/edges/width.jpeg | Bin 0 -> 30290 bytes .../model/edges/test_model_edges_protocols.py | 12 ++ 9 files changed, 280 insertions(+), 35 deletions(-) create mode 100644 src/opengeodeweb_viewer/rpc/model/edges/schemas/width.json create mode 100644 src/opengeodeweb_viewer/rpc/model/edges/schemas/width.py create mode 100644 tests/data/images/model/edges/width.jpeg diff --git a/src/opengeodeweb_viewer/object/object_methods.py b/src/opengeodeweb_viewer/object/object_methods.py index cf4ea842..0986a8c3 100644 --- a/src/opengeodeweb_viewer/object/object_methods.py +++ b/src/opengeodeweb_viewer/object/object_methods.py @@ -61,6 +61,8 @@ def remove_object(self, data_id: str) -> None: renderer.RemoveActor(size_actor.actor) if pipeline.edges_actor is not None: renderer.RemoveActor(pipeline.edges_actor) + for width_actor in pipeline.edges_width_actors.values(): + renderer.RemoveActor(width_actor.actor) if pipeline.edges_scalar_bar is not None: renderer.RemoveViewProp(pipeline.edges_scalar_bar) renderer.RemoveViewProp(pipeline.scalar_bar) @@ -104,6 +106,8 @@ def set_style_actors_visibility(self, pipeline: VtkPipeline, *, visibility: bool size_actor.actor.SetVisibility(visibility) if pipeline.edges_actor is not None: pipeline.edges_actor.SetVisibility(visibility and pipeline.edges_visibility) + for width_actor in pipeline.edges_width_actors.values(): + width_actor.actor.SetVisibility(visibility) def set_opacity(self, data_id: str, opacity: float) -> None: actor = self.get_vtk_pipeline(data_id).actor @@ -279,6 +283,7 @@ def set_blocks_visibility( for block_id in block_ids: visibility_attributes.SetBlockVisibility(blocks[block_id], visibility) pipeline.update_points_size_actors() + pipeline.update_edges_width_actors() dataset = mapper.GetInputDataObject(0, 0) if not isinstance(dataset, vtkMultiBlockDataSet): return diff --git a/src/opengeodeweb_viewer/rpc/model/edges/model_edges_protocols.py b/src/opengeodeweb_viewer/rpc/model/edges/model_edges_protocols.py index fedec8d5..314ced91 100644 --- a/src/opengeodeweb_viewer/rpc/model/edges/model_edges_protocols.py +++ b/src/opengeodeweb_viewer/rpc/model/edges/model_edges_protocols.py @@ -20,5 +20,10 @@ def __init__(self) -> None: @typed_rpc(model_edges_prefix, schemas.visibility_route) def set_model_edges_visibility(self, params: schemas.Visibility) -> schemas.VisibilityResponse: - self.set_edges_visibility(params.id, visibility=params.visibility) + self.set_model_edges_visibility_on_all(params.id, visibility=params.visibility) return schemas.VisibilityResponse() + + @typed_rpc(model_edges_prefix, schemas.width_route) + def set_model_edges_width(self, params: schemas.Width) -> schemas.WidthResponse: + self.set_model_edges_width_on_all(params.id, params.width) + return schemas.WidthResponse() diff --git a/src/opengeodeweb_viewer/rpc/model/edges/schemas/__init__.py b/src/opengeodeweb_viewer/rpc/model/edges/schemas/__init__.py index cbc73c09..e667a494 100644 --- a/src/opengeodeweb_viewer/rpc/model/edges/schemas/__init__.py +++ b/src/opengeodeweb_viewer/rpc/model/edges/schemas/__init__.py @@ -1 +1,2 @@ +from .width import * from .visibility import * diff --git a/src/opengeodeweb_viewer/rpc/model/edges/schemas/width.json b/src/opengeodeweb_viewer/rpc/model/edges/schemas/width.json new file mode 100644 index 00000000..7fd55c44 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/edges/schemas/width.json @@ -0,0 +1,25 @@ +{ + "rpc": "width", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "width": { + "type": "number" + } + }, + "required": [ + "id", + "width" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } +} diff --git a/src/opengeodeweb_viewer/rpc/model/edges/schemas/width.py b/src/opengeodeweb_viewer/rpc/model/edges/schemas/width.py new file mode 100644 index 00000000..b2776647 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/edges/schemas/width.py @@ -0,0 +1,31 @@ +from pathlib import Path +from opengeodeweb_microservice.schemas import Route, load_schema +from dataclasses_json import DataClassJsonMixin +from opengeodeweb_microservice.schemas import print_dataclass +from dataclasses import dataclass + + +@dataclass +class Width(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + id: str + width: float + + +@dataclass +class WidthResponse(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + pass + + +width_route = Route( + schema=load_schema(Path(__file__)), + params=Width, + response=WidthResponse, +) + +__all__ = ["Width", "WidthResponse", "width_route"] diff --git a/src/opengeodeweb_viewer/rpc/model/model_protocols.py b/src/opengeodeweb_viewer/rpc/model/model_protocols.py index 3f4d5731..8d6b58de 100644 --- a/src/opengeodeweb_viewer/rpc/model/model_protocols.py +++ b/src/opengeodeweb_viewer/rpc/model/model_protocols.py @@ -31,6 +31,8 @@ ) from opengeodeweb_viewer.vtk_pipeline import ( BlockStyle, + EdgesWidthActor, + ModelEdgesStyle, ModelPointsStyle, PointsSizeActor, VtkPipeline, @@ -62,6 +64,8 @@ class ColorResult(TypedDict): POINTS_COMPONENT_TYPES = ("lines", "surfaces", "blocks") +# Lines are edges themselves and corners have none, so only these components get an edges style +EDGES_COMPONENT_TYPES = ("surfaces", "blocks") class VtkModelView(VtkObjectView): @@ -124,13 +128,19 @@ def apply_color( def setup_model_color_map(self, pipeline: VtkPipeline) -> None: # Points attributes join the polygons ones, so identical color maps share one scalar bar - displayed_styles = [ - (str(block_id), style) for block_id, style in pipeline.block_styles.items() - ] + [ - (f"{block_id} points", points_style.attribute) - for block_id, points_style in pipeline.points_block_styles.items() - if points_style.attribute is not None and points_style.visibility - ] + displayed_styles = ( + [(str(block_id), style) for block_id, style in pipeline.block_styles.items()] + + [ + (f"{block_id} points", points_style.attribute) + for block_id, points_style in pipeline.points_block_styles.items() + if points_style.attribute is not None and points_style.visibility + ] + + [ + (f"{block_id} edges", edges_style.attribute) + for block_id, edges_style in pipeline.edges_block_styles.items() + if edges_style.attribute is not None and edges_style.visibility + ] + ) active_attrs: dict[str, BlockStyle] = {} for block_id, style in displayed_styles: if style["name"]: @@ -343,6 +353,123 @@ def set_model_points_size_on_all(self, data_id: str, size: float) -> None: style.size = size self.sync_points_size_actors(pipeline) + def ensure_model_edges_styles(self, pipeline: VtkPipeline) -> dict[int, ModelEdgesStyle]: + # Components edges leave the main actor once styled individually + if pipeline.edges_block_styles: + return pipeline.edges_block_styles + main_property = pipeline.actor.GetProperty() + red, green, blue = main_property.GetEdgeColor() + for block_id, component_type in pipeline.block_component_types().items(): + if component_type in EDGES_COMPONENT_TYPES: + pipeline.edges_block_styles[block_id] = ModelEdgesStyle( + width=main_property.GetEdgeWidth(), + visibility=bool(main_property.GetEdgeVisibility()), + color=(red, green, blue), + ) + main_property.EdgeVisibilityOff() + return pipeline.edges_block_styles + + def sync_edges_width_actors(self, pipeline: VtkPipeline) -> None: + renderer = self.get_renderer() + widths = {style.width for style in pipeline.edges_block_styles.values()} + for width in list(pipeline.edges_width_actors): + if width not in widths: + renderer.RemoveActor(pipeline.edges_width_actors.pop(width).actor) + for width in widths - pipeline.edges_width_actors.keys(): + mapper = vtkCompositePolyDataMapper() + mapper.SetInputDataObject(pipeline.mapper.GetInputDataObject(0, 0)) + mapper.ScalarVisibilityOn() + mapper.SetColorModeToMapScalars() + mapper.SetResolveCoincidentTopologyLineOffsetParameters(0, -4) + actor = vtkActor() + actor.SetMapper(mapper) + actor.PickableOff() + actor.SetVisibility(pipeline.actor.GetVisibility()) + edges_property = actor.GetProperty() + edges_property.SetRepresentationToWireframe() + edges_property.SetLineWidth(width) + pipeline.edges_width_actors[width] = EdgesWidthActor(mapper=mapper, actor=actor) + renderer.AddActor(actor) + pipeline.update_edges_width_actors() + + def component_edges_styles( + self, data_id: str, component_type: str, block_ids: list[int] + ) -> list[ModelEdgesStyle]: + pipeline = self.get_vtk_pipeline(data_id) + styles = self.ensure_model_edges_styles(pipeline) + component_types = pipeline.block_component_types() + return [ + styles[block_id] + for block_id in block_ids + if block_id in styles and component_types.get(block_id) == component_type + ] + + def set_component_edges_visibility( + self, data_id: str, component_type: str, block_ids: list[int], *, visibility: bool + ) -> None: + for style in self.component_edges_styles(data_id, component_type, block_ids): + style.visibility = visibility + pipeline = self.get_vtk_pipeline(data_id) + self.sync_edges_width_actors(pipeline) + self.setup_model_color_map(pipeline) + + def set_component_edges_color( + self, data_id: str, component_type: str, block_ids: list[int], color: ColorProtocol + ) -> None: + for style in self.component_edges_styles(data_id, component_type, block_ids): + style.color = (color.red / 255, color.green / 255, color.blue / 255) + style.opacity = color.alpha + style.attribute = None + pipeline = self.get_vtk_pipeline(data_id) + self.sync_edges_width_actors(pipeline) + self.setup_model_color_map(pipeline) + + def set_component_edges_attribute( + self, + data_id: str, + component_type: str, + block_ids: list[int], + attribute: AttributeProtocol, + ) -> None: + for style in self.component_edges_styles(data_id, component_type, block_ids): + style.attribute = BlockStyle( + name=attribute.name, + attribute_location="point", + points=attribute.points, + minimum=attribute.minimum, + maximum=attribute.maximum, + item=attribute.item, + no_data_color=attribute.no_data_color, + ) + pipeline = self.get_vtk_pipeline(data_id) + self.sync_edges_width_actors(pipeline) + self.setup_model_color_map(pipeline) + + def set_component_edges_width( + self, data_id: str, component_type: str, block_ids: list[int], width: float + ) -> None: + for style in self.component_edges_styles(data_id, component_type, block_ids): + style.width = width + self.sync_edges_width_actors(self.get_vtk_pipeline(data_id)) + + def set_model_edges_visibility_on_all(self, data_id: str, *, visibility: bool) -> None: + pipeline = self.get_vtk_pipeline(data_id) + if not pipeline.edges_block_styles: + self.set_edges_visibility(data_id, visibility=visibility) + return + for style in pipeline.edges_block_styles.values(): + style.visibility = visibility + self.sync_edges_width_actors(pipeline) + self.setup_model_color_map(pipeline) + + def set_model_edges_width_on_all(self, data_id: str, width: float) -> None: + # The main actor line width would also resize the lines, so edges always use their styles + pipeline = self.get_vtk_pipeline(data_id) + pipeline.actor.GetProperty().SetEdgeWidth(width) + for style in self.ensure_model_edges_styles(pipeline).values(): + style.width = width + self.sync_edges_width_actors(pipeline) + @typed_rpc(model_prefix, schemas.register_route) def register_model(self, params: schemas.Register) -> schemas.RegisterResponse: data_id = params.id diff --git a/src/opengeodeweb_viewer/vtk_pipeline.py b/src/opengeodeweb_viewer/vtk_pipeline.py index b1f5b9a0..2d5815cd 100644 --- a/src/opengeodeweb_viewer/vtk_pipeline.py +++ b/src/opengeodeweb_viewer/vtk_pipeline.py @@ -2,6 +2,7 @@ # Standard library imports import math +from collections.abc import Mapping from dataclasses import dataclass, field from typing import Literal, TypedDict, cast @@ -222,6 +223,26 @@ class ModelPointsStyle: attribute: BlockStyle | None = None +@dataclass +class EdgesWidthActor: + mapper: vtkCompositePolyDataMapper + actor: vtkActor + + +@dataclass +class ModelEdgesStyle: + width: float + visibility: bool + color: tuple[float, float, float] | None = None + opacity: float = 1.0 + attribute: BlockStyle | None = None + + +def style_actor_key(style: ModelPointsStyle | ModelEdgesStyle) -> float: + # Points actors are split by size, edges actors by width + return style.size if isinstance(style, ModelPointsStyle) else style.width + + @dataclass class VtkPipeline: reader: vtkXMLReader @@ -252,6 +273,9 @@ class VtkPipeline: edges_actor: vtkActor | None = None edges_scalar_bar: vtkScalarBarActor | None = None edges_visibility: bool = False + # One edges actor per distinct width, since line width is an actor property + edges_width_actors: dict[float, EdgesWidthActor] = field(default_factory=dict) + edges_block_styles: dict[int, ModelEdgesStyle] = field(default_factory=dict) def connect_mappers(self) -> None: self.mapper.SetInputConnection(self.filter.GetOutputPort()) @@ -506,37 +530,49 @@ def block_component_types(self) -> dict[int, str]: iterator.GoToNextItem() return component_types + def update_style_actor_attributes( + self, + mapper: vtkCompositePolyDataMapper, + styles: Mapping[int, ModelPointsStyle | ModelEdgesStyle], + actor_key: float, + ) -> None: + # A block shows in a style actor only when it is visible and its style matches the actor + main_mapper = cast("vtkCompositePolyDataMapper", self.mapper) + attributes = main_mapper.GetCompositeDataDisplayAttributes() + actor_attributes = vtkCompositeDataDisplayAttributes() + for block_id, block in enumerate(self.block_data_sets): + if not isinstance(block, vtkDataSet): + continue + style = styles.get(block_id) + block_visibility = not attributes.HasBlockVisibility( + block + ) or attributes.GetBlockVisibility(block) + visible = ( + style is not None + and style_actor_key(style) == actor_key + and style.visibility + and block_visibility + ) + actor_attributes.SetBlockVisibility(block, visible) + if not visible or style is None: + continue + if style.color is not None: + actor_attributes.SetBlockColor(block, list(style.color)) + actor_attributes.SetBlockOpacity(block, style.opacity) + self.set_block_point_attribute(actor_attributes, block, style.attribute) + mapper.SetCompositeDataDisplayAttributes(actor_attributes) + mapper.Modified() + def update_points_size_actors(self) -> None: - # A block shows its points in the actor of its size, only when the block is visible - mapper = cast("vtkCompositePolyDataMapper", self.mapper) - attributes = mapper.GetCompositeDataDisplayAttributes() for size, size_actor in self.points_size_actors.items(): - size_actor_attributes = vtkCompositeDataDisplayAttributes() - for block_id, block in enumerate(self.block_data_sets): - if not isinstance(block, vtkDataSet): - continue - style = self.points_block_styles.get(block_id) - block_visibility = not attributes.HasBlockVisibility( - block - ) or attributes.GetBlockVisibility(block) - visible = ( - style is not None - and style.size == size - and style.visibility - and block_visibility - ) - size_actor_attributes.SetBlockVisibility(block, visible) - if not visible or style is None: - continue - if style.color is not None: - size_actor_attributes.SetBlockColor(block, list(style.color)) - size_actor_attributes.SetBlockOpacity(block, style.opacity) - self.set_points_block_attribute(size_actor_attributes, block, style.attribute) - size_actor.mapper.SetCompositeDataDisplayAttributes(size_actor_attributes) - size_actor.mapper.Modified() + self.update_style_actor_attributes(size_actor.mapper, self.points_block_styles, size) + + def update_edges_width_actors(self) -> None: + for width, width_actor in self.edges_width_actors.items(): + self.update_style_actor_attributes(width_actor.mapper, self.edges_block_styles, width) @staticmethod - def set_points_block_attribute( + def set_block_point_attribute( attributes: vtkCompositeDataDisplayAttributes, block: vtkDataSet, attribute: BlockStyle | None, @@ -592,6 +628,7 @@ def sync_block_display_attributes(self, new_blocks: list[vtkDataObject | None]) self.sync_mapper_display_attributes(mapper, self.block_data_sets, new_blocks) self.block_data_sets = new_blocks self.update_points_size_actors() + self.update_edges_width_actors() for block_id in self.block_styles: self.update_block_colors(block_id) @@ -608,6 +645,8 @@ def sync_composite_pipeline(self, dataset: vtkDataObject) -> None: self.mapper.SetInputDataObject(dataset) for size_actor in self.points_size_actors.values(): size_actor.mapper.SetInputDataObject(dataset) + for width_actor in self.edges_width_actors.values(): + width_actor.mapper.SetInputDataObject(dataset) if self.pick_mapper and isinstance(dataset, vtkMultiBlockDataSet): mapper = cast("vtkCompositePolyDataMapper", self.mapper) attributes = mapper.GetCompositeDataDisplayAttributes() diff --git a/tests/data/images/model/edges/width.jpeg b/tests/data/images/model/edges/width.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..86d9bdb3dbe34befec2fc379d745a39ff20bce29 GIT binary patch literal 30290 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�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 literal 0 HcmV?d00001 diff --git a/tests/model/edges/test_model_edges_protocols.py b/tests/model/edges/test_model_edges_protocols.py index 48da9422..bcf19870 100644 --- a/tests/model/edges/test_model_edges_protocols.py +++ b/tests/model/edges/test_model_edges_protocols.py @@ -24,3 +24,15 @@ def test_edges_visibility(server: ServerMonitor, dataset_factory: Callable[..., [{"id": model_id, "visibility": True}], ) assert server.compare_image("model/edges/visibility.jpeg") + + +def test_edges_width(server: ServerMonitor, dataset_factory: Callable[..., str]) -> None: + + test_edges_visibility(server, dataset_factory) + + server.call( + VtkModelEdgesView.model_edges_prefix + + VtkModelEdgesView.model_edges_schemas_dict["width"]["rpc"], + [{"id": model_id, "width": 6}], + ) + assert server.compare_image("model/edges/width.jpeg") From 52a80781f763f85c7f13b9f8ecfe2a6c554e2305 Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Wed, 21 Oct 2026 14:34:53 +0200 Subject: [PATCH 04/10] Surfaces and blocks edges can be styled per component type and per component --- pyproject.toml | 2 + .../rpc/model/blocks/edges/__init__.py | 0 .../edges/model_blocks_edges_protocols.py | 38 +++++++ .../model/blocks/edges/schemas/__init__.py | 3 + .../rpc/model/blocks/edges/schemas/color.json | 62 ++++++++++ .../rpc/model/blocks/edges/schemas/color.py | 44 ++++++++ .../blocks/edges/schemas/visibility.json | 33 ++++++ .../model/blocks/edges/schemas/visibility.py | 33 ++++++ .../rpc/model/blocks/edges/schemas/width.json | 33 ++++++ .../rpc/model/blocks/edges/schemas/width.py | 33 ++++++ .../rpc/model/surfaces/edges/__init__.py | 0 .../edges/model_surfaces_edges_protocols.py | 38 +++++++ .../model/surfaces/edges/schemas/__init__.py | 3 + .../model/surfaces/edges/schemas/color.json | 62 ++++++++++ .../rpc/model/surfaces/edges/schemas/color.py | 44 ++++++++ .../surfaces/edges/schemas/visibility.json | 33 ++++++ .../surfaces/edges/schemas/visibility.py | 33 ++++++ .../model/surfaces/edges/schemas/width.json | 33 ++++++ .../rpc/model/surfaces/edges/schemas/width.py | 33 ++++++ src/opengeodeweb_viewer/rpc/protocols.py | 4 + .../model/edges/blocks_edges_color.jpeg | Bin 0 -> 31178 bytes .../model/edges/surface_edges_width.jpeg | Bin 0 -> 28583 bytes .../model/edges/surfaces_edges_color.jpeg | Bin 0 -> 30372 bytes .../model/edges/surfaces_edges_explode.jpeg | Bin 0 -> 33931 bytes .../edges/surfaces_edges_hidden_blocks.jpeg | Bin 0 -> 8307 bytes .../model/edges/surfaces_edges_opacity.jpeg | Bin 0 -> 28391 bytes .../edges/width_after_component_width.jpeg | Bin 0 -> 31101 bytes .../model/edges/test_model_edges_protocols.py | 106 +++++++++++++++++- 28 files changed, 669 insertions(+), 1 deletion(-) create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/__init__.py create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/model_blocks_edges_protocols.py create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/__init__.py create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/color.json create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/color.py create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/visibility.json create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/visibility.py create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/width.json create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/width.py create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/__init__.py create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/model_surfaces_edges_protocols.py create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/__init__.py create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/color.json create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/color.py create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/visibility.json create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/visibility.py create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/width.json create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/width.py create mode 100644 tests/data/images/model/edges/blocks_edges_color.jpeg create mode 100644 tests/data/images/model/edges/surface_edges_width.jpeg create mode 100644 tests/data/images/model/edges/surfaces_edges_color.jpeg create mode 100644 tests/data/images/model/edges/surfaces_edges_explode.jpeg create mode 100644 tests/data/images/model/edges/surfaces_edges_hidden_blocks.jpeg create mode 100644 tests/data/images/model/edges/surfaces_edges_opacity.jpeg create mode 100644 tests/data/images/model/edges/width_after_component_width.jpeg diff --git a/pyproject.toml b/pyproject.toml index f3cb8e58..02de3cbc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,11 +61,13 @@ where = ["src"] "opengeodeweb_viewer.rpc.model.surfaces.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.surfaces.points.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.surfaces.points.attribute.vertex.schemas" = ["*.json"] +"opengeodeweb_viewer.rpc.model.surfaces.edges.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.surfaces.attribute.polygon.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.surfaces.attribute.vertex.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.blocks.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.blocks.points.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.blocks.points.attribute.vertex.schemas" = ["*.json"] +"opengeodeweb_viewer.rpc.model.blocks.edges.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.blocks.attribute.polyhedron.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.blocks.attribute.vertex.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.viewer.schemas" = ["*.json"] diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/__init__.py b/src/opengeodeweb_viewer/rpc/model/blocks/edges/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/model_blocks_edges_protocols.py b/src/opengeodeweb_viewer/rpc/model/blocks/edges/model_blocks_edges_protocols.py new file mode 100644 index 00000000..26595563 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/blocks/edges/model_blocks_edges_protocols.py @@ -0,0 +1,38 @@ +# Standard library imports +from pathlib import Path + +# Third party imports +from opengeodeweb_microservice.schemas import get_schemas_dict + +# Local application imports +from opengeodeweb_viewer.rpc.model.model_protocols import VtkModelView +from opengeodeweb_viewer.typed_rpc import typed_rpc + +from . import schemas + + +class VtkModelBlocksEdgesView(VtkModelView): + model_blocks_edges_prefix = "opengeodeweb_viewer.model.blocks.edges." + model_blocks_edges_schemas_dict = get_schemas_dict(Path(__file__).parent / "schemas") + + def __init__(self) -> None: + super().__init__() + + @typed_rpc(model_blocks_edges_prefix, schemas.visibility_route) + def set_model_blocks_edges_visibility( + self, params: schemas.Visibility + ) -> schemas.VisibilityResponse: + self.set_component_edges_visibility( + params.id, "blocks", params.block_ids, visibility=params.visibility + ) + return schemas.VisibilityResponse() + + @typed_rpc(model_blocks_edges_prefix, schemas.color_route) + def set_model_blocks_edges_color(self, params: schemas.Color) -> schemas.ColorResponse: + self.set_component_edges_color(params.id, "blocks", params.block_ids, params.color) + return schemas.ColorResponse() + + @typed_rpc(model_blocks_edges_prefix, schemas.width_route) + def set_model_blocks_edges_width(self, params: schemas.Width) -> schemas.WidthResponse: + self.set_component_edges_width(params.id, "blocks", params.block_ids, params.width) + return schemas.WidthResponse() diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/__init__.py b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/__init__.py new file mode 100644 index 00000000..cfe6b7ea --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/__init__.py @@ -0,0 +1,3 @@ +from .width import * +from .visibility import * +from .color import * diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/color.json b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/color.json new file mode 100644 index 00000000..54fcb685 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/color.json @@ -0,0 +1,62 @@ +{ + "rpc": "color", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "color": { + "type": "object", + "properties": { + "red": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "green": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "blue": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "alpha": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "required": [ + "red", + "green", + "blue", + "alpha" + ], + "additionalProperties": false + } + }, + "required": [ + "id", + "block_ids", + "color" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } +} diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/color.py b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/color.py new file mode 100644 index 00000000..68d42901 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/color.py @@ -0,0 +1,44 @@ +from pathlib import Path +from opengeodeweb_microservice.schemas import Route, load_schema +from dataclasses_json import DataClassJsonMixin +from opengeodeweb_microservice.schemas import print_dataclass +from dataclasses import dataclass +from typing import List + + +@dataclass +class ColorClass(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + alpha: float + blue: int + green: int + red: int + + +@dataclass +class Color(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + block_ids: List[int] + color: ColorClass + id: str + + +@dataclass +class ColorResponse(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + pass + + +color_route = Route( + schema=load_schema(Path(__file__)), + params=Color, + response=ColorResponse, +) + +__all__ = ["ColorClass", "Color", "ColorResponse", "color_route"] diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/visibility.json b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/visibility.json new file mode 100644 index 00000000..77b18063 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/visibility.json @@ -0,0 +1,33 @@ +{ + "rpc": "visibility", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "visibility": { + "type": "boolean" + } + }, + "required": [ + "id", + "block_ids", + "visibility" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } +} diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/visibility.py b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/visibility.py new file mode 100644 index 00000000..1b9616b0 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/visibility.py @@ -0,0 +1,33 @@ +from pathlib import Path +from opengeodeweb_microservice.schemas import Route, load_schema +from dataclasses_json import DataClassJsonMixin +from opengeodeweb_microservice.schemas import print_dataclass +from dataclasses import dataclass +from typing import List + + +@dataclass +class Visibility(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + block_ids: List[int] + id: str + visibility: bool + + +@dataclass +class VisibilityResponse(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + pass + + +visibility_route = Route( + schema=load_schema(Path(__file__)), + params=Visibility, + response=VisibilityResponse, +) + +__all__ = ["Visibility", "VisibilityResponse", "visibility_route"] diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/width.json b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/width.json new file mode 100644 index 00000000..d98585fe --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/width.json @@ -0,0 +1,33 @@ +{ + "rpc": "width", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "width": { + "type": "number" + } + }, + "required": [ + "id", + "block_ids", + "width" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } +} diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/width.py b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/width.py new file mode 100644 index 00000000..c1231a48 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/blocks/edges/schemas/width.py @@ -0,0 +1,33 @@ +from pathlib import Path +from opengeodeweb_microservice.schemas import Route, load_schema +from dataclasses_json import DataClassJsonMixin +from opengeodeweb_microservice.schemas import print_dataclass +from dataclasses import dataclass +from typing import List + + +@dataclass +class Width(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + block_ids: List[int] + id: str + width: float + + +@dataclass +class WidthResponse(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + pass + + +width_route = Route( + schema=load_schema(Path(__file__)), + params=Width, + response=WidthResponse, +) + +__all__ = ["Width", "WidthResponse", "width_route"] diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/__init__.py b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/model_surfaces_edges_protocols.py b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/model_surfaces_edges_protocols.py new file mode 100644 index 00000000..6aa01870 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/model_surfaces_edges_protocols.py @@ -0,0 +1,38 @@ +# Standard library imports +from pathlib import Path + +# Third party imports +from opengeodeweb_microservice.schemas import get_schemas_dict + +# Local application imports +from opengeodeweb_viewer.rpc.model.model_protocols import VtkModelView +from opengeodeweb_viewer.typed_rpc import typed_rpc + +from . import schemas + + +class VtkModelSurfacesEdgesView(VtkModelView): + model_surfaces_edges_prefix = "opengeodeweb_viewer.model.surfaces.edges." + model_surfaces_edges_schemas_dict = get_schemas_dict(Path(__file__).parent / "schemas") + + def __init__(self) -> None: + super().__init__() + + @typed_rpc(model_surfaces_edges_prefix, schemas.visibility_route) + def set_model_surfaces_edges_visibility( + self, params: schemas.Visibility + ) -> schemas.VisibilityResponse: + self.set_component_edges_visibility( + params.id, "surfaces", params.block_ids, visibility=params.visibility + ) + return schemas.VisibilityResponse() + + @typed_rpc(model_surfaces_edges_prefix, schemas.color_route) + def set_model_surfaces_edges_color(self, params: schemas.Color) -> schemas.ColorResponse: + self.set_component_edges_color(params.id, "surfaces", params.block_ids, params.color) + return schemas.ColorResponse() + + @typed_rpc(model_surfaces_edges_prefix, schemas.width_route) + def set_model_surfaces_edges_width(self, params: schemas.Width) -> schemas.WidthResponse: + self.set_component_edges_width(params.id, "surfaces", params.block_ids, params.width) + return schemas.WidthResponse() diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/__init__.py b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/__init__.py new file mode 100644 index 00000000..cfe6b7ea --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/__init__.py @@ -0,0 +1,3 @@ +from .width import * +from .visibility import * +from .color import * diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/color.json b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/color.json new file mode 100644 index 00000000..54fcb685 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/color.json @@ -0,0 +1,62 @@ +{ + "rpc": "color", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "color": { + "type": "object", + "properties": { + "red": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "green": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "blue": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "alpha": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "required": [ + "red", + "green", + "blue", + "alpha" + ], + "additionalProperties": false + } + }, + "required": [ + "id", + "block_ids", + "color" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } +} diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/color.py b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/color.py new file mode 100644 index 00000000..68d42901 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/color.py @@ -0,0 +1,44 @@ +from pathlib import Path +from opengeodeweb_microservice.schemas import Route, load_schema +from dataclasses_json import DataClassJsonMixin +from opengeodeweb_microservice.schemas import print_dataclass +from dataclasses import dataclass +from typing import List + + +@dataclass +class ColorClass(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + alpha: float + blue: int + green: int + red: int + + +@dataclass +class Color(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + block_ids: List[int] + color: ColorClass + id: str + + +@dataclass +class ColorResponse(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + pass + + +color_route = Route( + schema=load_schema(Path(__file__)), + params=Color, + response=ColorResponse, +) + +__all__ = ["ColorClass", "Color", "ColorResponse", "color_route"] diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/visibility.json b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/visibility.json new file mode 100644 index 00000000..77b18063 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/visibility.json @@ -0,0 +1,33 @@ +{ + "rpc": "visibility", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "visibility": { + "type": "boolean" + } + }, + "required": [ + "id", + "block_ids", + "visibility" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } +} diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/visibility.py b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/visibility.py new file mode 100644 index 00000000..1b9616b0 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/visibility.py @@ -0,0 +1,33 @@ +from pathlib import Path +from opengeodeweb_microservice.schemas import Route, load_schema +from dataclasses_json import DataClassJsonMixin +from opengeodeweb_microservice.schemas import print_dataclass +from dataclasses import dataclass +from typing import List + + +@dataclass +class Visibility(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + block_ids: List[int] + id: str + visibility: bool + + +@dataclass +class VisibilityResponse(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + pass + + +visibility_route = Route( + schema=load_schema(Path(__file__)), + params=Visibility, + response=VisibilityResponse, +) + +__all__ = ["Visibility", "VisibilityResponse", "visibility_route"] diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/width.json b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/width.json new file mode 100644 index 00000000..d98585fe --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/width.json @@ -0,0 +1,33 @@ +{ + "rpc": "width", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "width": { + "type": "number" + } + }, + "required": [ + "id", + "block_ids", + "width" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } +} diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/width.py b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/width.py new file mode 100644 index 00000000..c1231a48 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/schemas/width.py @@ -0,0 +1,33 @@ +from pathlib import Path +from opengeodeweb_microservice.schemas import Route, load_schema +from dataclasses_json import DataClassJsonMixin +from opengeodeweb_microservice.schemas import print_dataclass +from dataclasses import dataclass +from typing import List + + +@dataclass +class Width(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + block_ids: List[int] + id: str + width: float + + +@dataclass +class WidthResponse(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + pass + + +width_route = Route( + schema=load_schema(Path(__file__)), + params=Width, + response=WidthResponse, +) + +__all__ = ["Width", "WidthResponse", "width_route"] diff --git a/src/opengeodeweb_viewer/rpc/protocols.py b/src/opengeodeweb_viewer/rpc/protocols.py index 098dfb78..9cf8f034 100644 --- a/src/opengeodeweb_viewer/rpc/protocols.py +++ b/src/opengeodeweb_viewer/rpc/protocols.py @@ -35,6 +35,7 @@ from .model.blocks.attribute.vertex.blocks_attribute_vertex_protocols import ( VtkModelBlocksAttributeVertexView, ) +from .model.blocks.edges.model_blocks_edges_protocols import VtkModelBlocksEdgesView from .model.blocks.model_blocks_protocols import VtkModelBlocksView from .model.blocks.points.attribute.vertex.blocks_points_attribute_vertex_protocols import ( VtkModelBlocksPointsAttributeVertexView, @@ -63,6 +64,7 @@ from .model.surfaces.attribute.vertex.surfaces_attribute_vertex_protocols import ( VtkModelSurfacesAttributeVertexView, ) +from .model.surfaces.edges.model_surfaces_edges_protocols import VtkModelSurfacesEdgesView from .model.surfaces.model_surfaces_protocols import VtkModelSurfacesView from .model.surfaces.points.attribute.vertex.surfaces_points_attribute_vertex_protocols import ( VtkModelSurfacesPointsAttributeVertexView, @@ -106,4 +108,6 @@ VtkModelLinesPointsAttributeVertexView, VtkModelSurfacesPointsAttributeVertexView, VtkModelBlocksPointsAttributeVertexView, + VtkModelSurfacesEdgesView, + VtkModelBlocksEdgesView, ) diff --git a/tests/data/images/model/edges/blocks_edges_color.jpeg b/tests/data/images/model/edges/blocks_edges_color.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..3c40907790d4f2c38544bf0d61a60c9cd2d4b4a2 GIT binary patch literal 31178 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 x+!>+QX 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 OZ(#3Ce!hl1tN#b#gK|y) literal 0 HcmV?d00001 diff --git a/tests/data/images/model/edges/surfaces_edges_color.jpeg b/tests/data/images/model/edges/surfaces_edges_color.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..2b61086d8918b0394299d7446c2663bc30e4c494 GIT binary patch literal 30372 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

nqXR{)|puKP+~~g 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 None: @@ -36,3 +48,95 @@ def test_edges_width(server: ServerMonitor, dataset_factory: Callable[..., str]) [{"id": model_id, "width": 6}], ) assert server.compare_image("model/edges/width.jpeg") + + +def call_surfaces_edges(server: ServerMonitor, route: str, params: dict[str, object]) -> None: + view = VtkModelSurfacesEdgesView + server.call( + view.model_surfaces_edges_prefix + view.model_surfaces_edges_schemas_dict[route]["rpc"], + [{"id": model_id, **params}], + ) + + +def test_surfaces_edges_color(server: ServerMonitor, dataset_factory: Callable[..., str]) -> None: + + test_model_cube_side_view(server, dataset_factory) + call_surfaces_edges(server, "visibility", {"block_ids": surfaces_ids, "visibility": True}) + call_surfaces_edges(server, "width", {"block_ids": surfaces_ids, "width": 3}) + call_surfaces_edges( + server, + "color", + {"block_ids": surfaces_ids, "color": {"red": 255, "green": 0, "blue": 0, "alpha": 1.0}}, + ) + assert server.compare_image("model/edges/surfaces_edges_color.jpeg") + + +def test_surface_edges_width(server: ServerMonitor, dataset_factory: Callable[..., str]) -> None: + + test_surfaces_edges_color(server, dataset_factory) + call_surfaces_edges(server, "width", {"block_ids": [45], "width": 8}) + assert server.compare_image("model/edges/surface_edges_width.jpeg") + + +def test_surfaces_edges_opacity(server: ServerMonitor, dataset_factory: Callable[..., str]) -> None: + + test_surfaces_edges_color(server, dataset_factory) + call_surfaces_edges( + server, + "color", + {"block_ids": surfaces_ids, "color": {"red": 255, "green": 0, "blue": 0, "alpha": 0.2}}, + ) + assert server.compare_image("model/edges/surfaces_edges_opacity.jpeg") + + +def test_surfaces_edges_hidden_blocks( + server: ServerMonitor, dataset_factory: Callable[..., str] +) -> None: + + test_surfaces_edges_color(server, dataset_factory) + server.call( + VtkModelSurfacesView.model_surfaces_prefix + + VtkModelSurfacesView.model_surfaces_schemas_dict["visibility"]["rpc"], + [{"id": model_id, "block_ids": surfaces_ids, "visibility": False}], + ) + # Hidden surfaces take their edges with them + assert server.compare_image("model/edges/surfaces_edges_hidden_blocks.jpeg") + + +def test_surfaces_edges_explode(server: ServerMonitor, dataset_factory: Callable[..., str]) -> None: + + test_surfaces_edges_color(server, dataset_factory) + server.call( + VtkViewerView.viewer_prefix + VtkViewerView.viewer_schemas_dict["explode"]["rpc"], + [{"ids": [model_id], "explode_factor": 1.0}], + ) + assert server.compare_image("model/edges/surfaces_edges_explode.jpeg") + + +def test_model_edges_width_after_component_width( + server: ServerMonitor, dataset_factory: Callable[..., str] +) -> None: + + test_surface_edges_width(server, dataset_factory) + server.call( + VtkModelEdgesView.model_edges_prefix + + VtkModelEdgesView.model_edges_schemas_dict["width"]["rpc"], + [{"id": model_id, "width": 1}], + ) + # Model width overrides every component width, block 45 included + assert server.compare_image("model/edges/width_after_component_width.jpeg") + + +def test_blocks_edges_color(server: ServerMonitor, dataset_factory: Callable[..., str]) -> None: + + test_model_cube_side_view(server, dataset_factory) + view = VtkModelBlocksEdgesView + for route, params in ( + ("visibility", {"visibility": True}), + ("color", {"color": {"red": 0, "green": 0, "blue": 255, "alpha": 1.0}}), + ): + server.call( + view.model_blocks_edges_prefix + view.model_blocks_edges_schemas_dict[route]["rpc"], + [{"id": model_id, "block_ids": blocks_ids, **params}], + ) + assert server.compare_image("model/edges/blocks_edges_color.jpeg") From d54797b18be7550b247e3ea6f72fc207ca768dc0 Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Wed, 21 Oct 2026 14:36:02 +0200 Subject: [PATCH 05/10] feat(edgesModel): Support model edges only vertex attributes --- opengeodeweb_viewer_schemas.json | 478 +++++ opengeodeweb_viewer_typed_schemas.d.ts | 1848 +++++++++-------- pyproject.toml | 2 + .../model/blocks/edges/attribute/__init__.py | 0 .../blocks/edges/attribute/vertex/__init__.py | 0 ...blocks_edges_attribute_vertex_protocols.py | 30 + .../attribute/vertex/schemas/__init__.py | 1 + .../attribute/vertex/schemas/attribute.json | 88 + .../attribute/vertex/schemas/attribute.py | 51 + .../surfaces/edges/attribute/__init__.py | 0 .../edges/attribute/vertex/__init__.py | 0 .../attribute/vertex/schemas/__init__.py | 1 + .../attribute/vertex/schemas/attribute.json | 88 + .../attribute/vertex/schemas/attribute.py | 51 + ...rfaces_edges_attribute_vertex_protocols.py | 30 + src/opengeodeweb_viewer/rpc/protocols.py | 8 + .../model/edges/surfaces_edges_attribute.jpeg | Bin 0 -> 30635 bytes .../model/edges/test_model_edges_protocols.py | 31 + 18 files changed, 1890 insertions(+), 817 deletions(-) create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/__init__.py create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/__init__.py create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/blocks_edges_attribute_vertex_protocols.py create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/schemas/__init__.py create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/schemas/attribute.json create mode 100644 src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/schemas/attribute.py create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/__init__.py create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/__init__.py create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/schemas/__init__.py create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/schemas/attribute.json create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/schemas/attribute.py create mode 100644 src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/surfaces_edges_attribute_vertex_protocols.py create mode 100644 tests/data/images/model/edges/surfaces_edges_attribute.jpeg diff --git a/opengeodeweb_viewer_schemas.json b/opengeodeweb_viewer_schemas.json index f7453617..ea2f50ba 100644 --- a/opengeodeweb_viewer_schemas.json +++ b/opengeodeweb_viewer_schemas.json @@ -1673,6 +1673,232 @@ } } }, + "edges": { + "attribute": { + "vertex": { + "attribute": { + "$id": "opengeodeweb_viewer.model.blocks.edges.attribute.vertex.attribute", + "rpc": "attribute", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "name": { + "type": "string", + "minLength": 1 + }, + "item": { + "type": "integer", + "minimum": 0 + }, + "points": { + "type": "array", + "description": "Flat array of [value, r, g, b, ...]", + "items": { + "type": "number" + }, + "minItems": 8 + }, + "minimum": { + "type": "number" + }, + "maximum": { + "type": "number" + }, + "no_data_color": { + "type": "object", + "properties": { + "red": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "green": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "blue": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "alpha": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "required": [ + "red", + "green", + "blue", + "alpha" + ], + "additionalProperties": false + } + }, + "required": [ + "id", + "block_ids", + "name", + "item", + "points", + "minimum", + "maximum" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } + } + } + }, + "width": { + "$id": "opengeodeweb_viewer.model.blocks.edges.width", + "rpc": "width", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "width": { + "type": "number" + } + }, + "required": [ + "id", + "block_ids", + "width" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } + }, + "visibility": { + "$id": "opengeodeweb_viewer.model.blocks.edges.visibility", + "rpc": "visibility", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "visibility": { + "type": "boolean" + } + }, + "required": [ + "id", + "block_ids", + "visibility" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } + }, + "color": { + "$id": "opengeodeweb_viewer.model.blocks.edges.color", + "rpc": "color", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "color": { + "type": "object", + "properties": { + "red": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "green": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "blue": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "alpha": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "required": [ + "red", + "green", + "blue", + "alpha" + ], + "additionalProperties": false + } + }, + "required": [ + "id", + "block_ids", + "color" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } + } + }, "points": { "attribute": { "vertex": { @@ -2312,6 +2538,32 @@ } }, "edges": { + "width": { + "$id": "opengeodeweb_viewer.model.edges.width", + "rpc": "width", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "width": { + "type": "number" + } + }, + "required": [ + "id", + "width" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } + }, "visibility": { "$id": "opengeodeweb_viewer.model.edges.visibility", "rpc": "visibility", @@ -3295,6 +3547,232 @@ } } }, + "edges": { + "attribute": { + "vertex": { + "attribute": { + "$id": "opengeodeweb_viewer.model.surfaces.edges.attribute.vertex.attribute", + "rpc": "attribute", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "name": { + "type": "string", + "minLength": 1 + }, + "item": { + "type": "integer", + "minimum": 0 + }, + "points": { + "type": "array", + "description": "Flat array of [value, r, g, b, ...]", + "items": { + "type": "number" + }, + "minItems": 8 + }, + "minimum": { + "type": "number" + }, + "maximum": { + "type": "number" + }, + "no_data_color": { + "type": "object", + "properties": { + "red": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "green": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "blue": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "alpha": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "required": [ + "red", + "green", + "blue", + "alpha" + ], + "additionalProperties": false + } + }, + "required": [ + "id", + "block_ids", + "name", + "item", + "points", + "minimum", + "maximum" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } + } + } + }, + "width": { + "$id": "opengeodeweb_viewer.model.surfaces.edges.width", + "rpc": "width", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "width": { + "type": "number" + } + }, + "required": [ + "id", + "block_ids", + "width" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } + }, + "visibility": { + "$id": "opengeodeweb_viewer.model.surfaces.edges.visibility", + "rpc": "visibility", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "visibility": { + "type": "boolean" + } + }, + "required": [ + "id", + "block_ids", + "visibility" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } + }, + "color": { + "$id": "opengeodeweb_viewer.model.surfaces.edges.color", + "rpc": "color", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "color": { + "type": "object", + "properties": { + "red": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "green": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "blue": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "alpha": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "required": [ + "red", + "green", + "blue", + "alpha" + ], + "additionalProperties": false + } + }, + "required": [ + "id", + "block_ids", + "color" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } + } + }, "points": { "attribute": { "vertex": { diff --git a/opengeodeweb_viewer_typed_schemas.d.ts b/opengeodeweb_viewer_typed_schemas.d.ts index 22d42bcc..aace786d 100644 --- a/opengeodeweb_viewer_typed_schemas.d.ts +++ b/opengeodeweb_viewer_typed_schemas.d.ts @@ -2,1261 +2,1292 @@ import type json from "./opengeodeweb_viewer_schemas.json"; export interface GenericRegisterParams { - id: string; - name: string; + id: string; + name: string; } -export interface GenericRegisterResponse { -} +export interface GenericRegisterResponse {} export interface GenericDeregisterParams { - id: string; + id: string; } -export interface GenericDeregisterResponse { -} +export interface GenericDeregisterResponse {} export interface MeshCellsAttributeCellAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshCellsAttributeCellAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshCellsAttributeCellAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshCellsAttributeCellAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshCellsAttributeCellAttributeResponse { -} +export interface MeshCellsAttributeCellAttributeResponse {} export interface MeshCellsAttributeVertexAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshCellsAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshCellsAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshCellsAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshCellsAttributeVertexAttributeResponse { -} +export interface MeshCellsAttributeVertexAttributeResponse {} export interface MeshCellsVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface MeshCellsVisibilityResponse { -} +export interface MeshCellsVisibilityResponse {} export interface MeshCellsColorParams { - color: MeshCellsColorParamsColor; - id: string; + color: MeshCellsColorParamsColor; + id: string; } export interface MeshCellsColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshCellsColorResponse { -} +export interface MeshCellsColorResponse {} export interface MeshEdgesAttributeEdgeAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshEdgesAttributeEdgeAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshEdgesAttributeEdgeAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshEdgesAttributeEdgeAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshEdgesAttributeEdgeAttributeResponse { -} +export interface MeshEdgesAttributeEdgeAttributeResponse {} export interface MeshEdgesAttributeVertexAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshEdgesAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshEdgesAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshEdgesAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshEdgesAttributeVertexAttributeResponse { -} +export interface MeshEdgesAttributeVertexAttributeResponse {} export interface MeshEdgesWidthParams { - id: string; - width: number; + id: string; + width: number; } -export interface MeshEdgesWidthResponse { -} +export interface MeshEdgesWidthResponse {} export interface MeshEdgesVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface MeshEdgesVisibilityResponse { -} +export interface MeshEdgesVisibilityResponse {} export interface MeshEdgesColorParams { - color: MeshEdgesColorParamsColor; - id: string; + color: MeshEdgesColorParamsColor; + id: string; } export interface MeshEdgesColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshEdgesColorResponse { -} +export interface MeshEdgesColorResponse {} export interface MeshPointsAttributeVertexAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshPointsAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshPointsAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshPointsAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPointsAttributeVertexAttributeResponse { -} +export interface MeshPointsAttributeVertexAttributeResponse {} export interface MeshPointsVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } export interface MeshPointsVisibilityResponse { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } export interface MeshPointsSizeParams { - id: string; - size: number; + id: string; + size: number; } -export interface MeshPointsSizeResponse { -} +export interface MeshPointsSizeResponse {} export interface MeshPointsColorParams { - color: MeshPointsColorParamsColor; - id: string; + color: MeshPointsColorParamsColor; + id: string; } export interface MeshPointsColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPointsColorResponse { -} +export interface MeshPointsColorResponse {} export interface MeshPolygonsAttributePolygonAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshPolygonsAttributePolygonAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshPolygonsAttributePolygonAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshPolygonsAttributePolygonAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPolygonsAttributePolygonAttributeResponse { -} +export interface MeshPolygonsAttributePolygonAttributeResponse {} export interface MeshPolygonsAttributeVertexAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshPolygonsAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshPolygonsAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshPolygonsAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPolygonsAttributeVertexAttributeResponse { -} +export interface MeshPolygonsAttributeVertexAttributeResponse {} export interface MeshPolygonsVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface MeshPolygonsVisibilityResponse { -} +export interface MeshPolygonsVisibilityResponse {} export interface MeshPolygonsColorParams { - color: MeshPolygonsColorParamsColor; - id: string; + color: MeshPolygonsColorParamsColor; + id: string; } export interface MeshPolygonsColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPolygonsColorResponse { -} +export interface MeshPolygonsColorResponse {} export interface MeshPolyhedraAttributePolyhedronAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshPolyhedraAttributePolyhedronAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshPolyhedraAttributePolyhedronAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshPolyhedraAttributePolyhedronAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPolyhedraAttributePolyhedronAttributeResponse { -} +export interface MeshPolyhedraAttributePolyhedronAttributeResponse {} export interface MeshPolyhedraAttributeVertexAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshPolyhedraAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshPolyhedraAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshPolyhedraAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPolyhedraAttributeVertexAttributeResponse { -} +export interface MeshPolyhedraAttributeVertexAttributeResponse {} export interface MeshPolyhedraVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface MeshPolyhedraVisibilityResponse { -} +export interface MeshPolyhedraVisibilityResponse {} export interface MeshPolyhedraColorParams { - color: MeshPolyhedraColorParamsColor; - id: string; + color: MeshPolyhedraColorParamsColor; + id: string; } export interface MeshPolyhedraColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPolyhedraColorResponse { -} +export interface MeshPolyhedraColorResponse {} export interface MeshVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface MeshVisibilityResponse { -} +export interface MeshVisibilityResponse {} export interface MeshRegisterParams { - id: string; - name: string; + id: string; + name: string; } -export interface MeshRegisterResponse { -} +export interface MeshRegisterResponse {} export interface MeshHighlightParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface MeshHighlightResponse { -} +export interface MeshHighlightResponse {} export interface MeshDeregisterParams { - id: string; + id: string; } -export interface MeshDeregisterResponse { -} +export interface MeshDeregisterResponse {} export interface MeshColorParams { - color: MeshColorParamsColor; - id: string; + color: MeshColorParamsColor; + id: string; } export interface MeshColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshColorResponse { -} +export interface MeshColorResponse {} export interface MeshApplyTexturesParams { - id: string; - textures: MeshApplyTexturesParamsTexture[]; + id: string; + textures: MeshApplyTexturesParamsTexture[]; } export interface MeshApplyTexturesParamsTexture { - id: string; - texture_name: string; + id: string; + texture_name: string; } -export interface MeshApplyTexturesResponse { -} +export interface MeshApplyTexturesResponse {} export interface ModelBlocksAttributePolyhedronAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelBlocksAttributePolyhedronAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelBlocksAttributePolyhedronAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelBlocksAttributePolyhedronAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelBlocksAttributePolyhedronAttributeResponse { -} +export interface ModelBlocksAttributePolyhedronAttributeResponse {} export interface ModelBlocksAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelBlocksAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelBlocksAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelBlocksAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; +} + +export interface ModelBlocksAttributeVertexAttributeResponse {} + +export interface ModelBlocksEdgesAttributeVertexAttributeParams { + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelBlocksEdgesAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } -export interface ModelBlocksAttributeVertexAttributeResponse { +export interface ModelBlocksEdgesAttributeVertexAttributeParamsNoDataColor { + alpha: number; + blue: number; + green: number; + red: number; } +export interface ModelBlocksEdgesAttributeVertexAttributeResponse {} + +export interface ModelBlocksEdgesWidthParams { + block_ids: number[]; + id: string; + width: number; +} + +export interface ModelBlocksEdgesWidthResponse {} + +export interface ModelBlocksEdgesVisibilityParams { + block_ids: number[]; + id: string; + visibility: boolean; +} + +export interface ModelBlocksEdgesVisibilityResponse {} + +export interface ModelBlocksEdgesColorParams { + block_ids: number[]; + color: ModelBlocksEdgesColorParamsColor; + id: string; +} + +export interface ModelBlocksEdgesColorParamsColor { + alpha: number; + blue: number; + green: number; + red: number; +} + +export interface ModelBlocksEdgesColorResponse {} + export interface ModelBlocksPointsAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelBlocksPointsAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelBlocksPointsAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelBlocksPointsAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelBlocksPointsAttributeVertexAttributeResponse { -} +export interface ModelBlocksPointsAttributeVertexAttributeResponse {} export interface ModelBlocksPointsVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelBlocksPointsVisibilityResponse { -} +export interface ModelBlocksPointsVisibilityResponse {} export interface ModelBlocksPointsSizeParams { - block_ids: number[]; - id: string; - size: number; + block_ids: number[]; + id: string; + size: number; } -export interface ModelBlocksPointsSizeResponse { -} +export interface ModelBlocksPointsSizeResponse {} export interface ModelBlocksPointsColorParams { - block_ids: number[]; - color: ModelBlocksPointsColorParamsColor; - id: string; + block_ids: number[]; + color: ModelBlocksPointsColorParamsColor; + id: string; } export interface ModelBlocksPointsColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelBlocksPointsColorResponse { -} +export interface ModelBlocksPointsColorResponse {} export interface ModelBlocksVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelBlocksVisibilityResponse { -} +export interface ModelBlocksVisibilityResponse {} export interface ModelBlocksColorParams { - block_ids: number[]; - collection_id?: string; - color?: ModelBlocksColorParamsColor; - color_mode: ColorMode; - id: string; + block_ids: number[]; + collection_id?: string; + color?: ModelBlocksColorParamsColor; + color_mode: ColorMode; + id: string; } export interface ModelBlocksColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export type ColorMode = "constant" | "random"; export interface ModelBlocksColorResponse { - colors: ModelBlocksColorResponseColor[]; + colors: ModelBlocksColorResponseColor[]; } export interface ModelBlocksColorResponseColor { - color: PurpleColorRGBA; - geode_id: string; - viewer_id: number; + color: PurpleColorRGBA; + geode_id: string; + viewer_id: number; } export interface PurpleColorRGBA { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export interface ModelCornersAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelCornersAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelCornersAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelCornersAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelCornersAttributeVertexAttributeResponse { -} +export interface ModelCornersAttributeVertexAttributeResponse {} export interface ModelCornersVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelCornersVisibilityResponse { -} +export interface ModelCornersVisibilityResponse {} export interface ModelCornersColorParams { - block_ids: number[]; - collection_id?: string; - color?: ModelCornersColorParamsColor; - color_mode: ColorMode; - id: string; + block_ids: number[]; + collection_id?: string; + color?: ModelCornersColorParamsColor; + color_mode: ColorMode; + id: string; } export interface ModelCornersColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export interface ModelCornersColorResponse { - colors: ModelCornersColorResponseColor[]; + colors: ModelCornersColorResponseColor[]; } export interface ModelCornersColorResponseColor { - color: FluffyColorRGBA; - geode_id: string; - viewer_id: number; + color: FluffyColorRGBA; + geode_id: string; + viewer_id: number; } export interface FluffyColorRGBA { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelEdgesVisibilityParams { - id: string; - visibility: boolean; +export interface ModelEdgesWidthParams { + id: string; + width: number; } -export interface ModelEdgesVisibilityResponse { +export interface ModelEdgesWidthResponse {} + +export interface ModelEdgesVisibilityParams { + id: string; + visibility: boolean; } +export interface ModelEdgesVisibilityResponse {} + export interface ModelLinesAttributeEdgeAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelLinesAttributeEdgeAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelLinesAttributeEdgeAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelLinesAttributeEdgeAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelLinesAttributeEdgeAttributeResponse { -} +export interface ModelLinesAttributeEdgeAttributeResponse {} export interface ModelLinesAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelLinesAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelLinesAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelLinesAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelLinesAttributeVertexAttributeResponse { -} +export interface ModelLinesAttributeVertexAttributeResponse {} export interface ModelLinesPointsAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelLinesPointsAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelLinesPointsAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelLinesPointsAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelLinesPointsAttributeVertexAttributeResponse { -} +export interface ModelLinesPointsAttributeVertexAttributeResponse {} export interface ModelLinesPointsVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelLinesPointsVisibilityResponse { -} +export interface ModelLinesPointsVisibilityResponse {} export interface ModelLinesPointsSizeParams { - block_ids: number[]; - id: string; - size: number; + block_ids: number[]; + id: string; + size: number; } -export interface ModelLinesPointsSizeResponse { -} +export interface ModelLinesPointsSizeResponse {} export interface ModelLinesPointsColorParams { - block_ids: number[]; - color: ModelLinesPointsColorParamsColor; - id: string; + block_ids: number[]; + color: ModelLinesPointsColorParamsColor; + id: string; } export interface ModelLinesPointsColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelLinesPointsColorResponse { -} +export interface ModelLinesPointsColorResponse {} export interface ModelLinesVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelLinesVisibilityResponse { -} +export interface ModelLinesVisibilityResponse {} export interface ModelLinesColorParams { - block_ids: number[]; - collection_id?: string; - color?: ModelLinesColorParamsColor; - color_mode: ColorMode; - id: string; + block_ids: number[]; + collection_id?: string; + color?: ModelLinesColorParamsColor; + color_mode: ColorMode; + id: string; } export interface ModelLinesColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export interface ModelLinesColorResponse { - colors: ModelLinesColorResponseColor[]; + colors: ModelLinesColorResponseColor[]; } export interface ModelLinesColorResponseColor { - color: TentacledColorRGBA; - geode_id: string; - viewer_id: number; + color: TentacledColorRGBA; + geode_id: string; + viewer_id: number; } export interface TentacledColorRGBA { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export interface ModelPointsVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface ModelPointsVisibilityResponse { -} +export interface ModelPointsVisibilityResponse {} export interface ModelPointsSizeParams { - id: string; - size: number; + id: string; + size: number; } -export interface ModelPointsSizeResponse { -} +export interface ModelPointsSizeResponse {} export interface ModelVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface ModelVisibilityResponse { -} +export interface ModelVisibilityResponse {} export interface ModelRegisterParams { - id: string; - name: string; + id: string; + name: string; } -export interface ModelRegisterResponse { -} +export interface ModelRegisterResponse {} export interface ModelHighlightParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelHighlightResponse { -} +export interface ModelHighlightResponse {} export interface ModelGetBlocksBoundsParams { - block_ids: number[]; - id: string; + block_ids: number[]; + id: string; } export interface ModelGetBlocksBoundsResponse { - bounds: number[]; + bounds: number[]; } export interface ModelDeregisterParams { - id: string; + id: string; } -export interface ModelDeregisterResponse { -} +export interface ModelDeregisterResponse {} export interface ModelSurfacesAttributePolygonAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelSurfacesAttributePolygonAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelSurfacesAttributePolygonAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelSurfacesAttributePolygonAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelSurfacesAttributePolygonAttributeResponse { -} +export interface ModelSurfacesAttributePolygonAttributeResponse {} export interface ModelSurfacesAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelSurfacesAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelSurfacesAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelSurfacesAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; +} + +export interface ModelSurfacesAttributeVertexAttributeResponse {} + +export interface ModelSurfacesEdgesAttributeVertexAttributeParams { + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelSurfacesEdgesAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; +} + +export interface ModelSurfacesEdgesAttributeVertexAttributeParamsNoDataColor { + alpha: number; + blue: number; + green: number; + red: number; +} + +export interface ModelSurfacesEdgesAttributeVertexAttributeResponse {} + +export interface ModelSurfacesEdgesWidthParams { + block_ids: number[]; + id: string; + width: number; } -export interface ModelSurfacesAttributeVertexAttributeResponse { +export interface ModelSurfacesEdgesWidthResponse {} + +export interface ModelSurfacesEdgesVisibilityParams { + block_ids: number[]; + id: string; + visibility: boolean; } +export interface ModelSurfacesEdgesVisibilityResponse {} + +export interface ModelSurfacesEdgesColorParams { + block_ids: number[]; + color: ModelSurfacesEdgesColorParamsColor; + id: string; +} + +export interface ModelSurfacesEdgesColorParamsColor { + alpha: number; + blue: number; + green: number; + red: number; +} + +export interface ModelSurfacesEdgesColorResponse {} + export interface ModelSurfacesPointsAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelSurfacesPointsAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelSurfacesPointsAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelSurfacesPointsAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelSurfacesPointsAttributeVertexAttributeResponse { -} +export interface ModelSurfacesPointsAttributeVertexAttributeResponse {} export interface ModelSurfacesPointsVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelSurfacesPointsVisibilityResponse { -} +export interface ModelSurfacesPointsVisibilityResponse {} export interface ModelSurfacesPointsSizeParams { - block_ids: number[]; - id: string; - size: number; + block_ids: number[]; + id: string; + size: number; } -export interface ModelSurfacesPointsSizeResponse { -} +export interface ModelSurfacesPointsSizeResponse {} export interface ModelSurfacesPointsColorParams { - block_ids: number[]; - color: ModelSurfacesPointsColorParamsColor; - id: string; + block_ids: number[]; + color: ModelSurfacesPointsColorParamsColor; + id: string; } export interface ModelSurfacesPointsColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelSurfacesPointsColorResponse { -} +export interface ModelSurfacesPointsColorResponse {} export interface ModelSurfacesVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelSurfacesVisibilityResponse { -} +export interface ModelSurfacesVisibilityResponse {} export interface ModelSurfacesColorParams { - block_ids: number[]; - collection_id?: string; - color?: ModelSurfacesColorParamsColor; - color_mode: ColorMode; - id: string; + block_ids: number[]; + collection_id?: string; + color?: ModelSurfacesColorParamsColor; + color_mode: ColorMode; + id: string; } export interface ModelSurfacesColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export interface ModelSurfacesColorResponse { - colors: ModelSurfacesColorResponseColor[]; + colors: ModelSurfacesColorResponseColor[]; } export interface ModelSurfacesColorResponseColor { - color: StickyColorRGBA; - geode_id: string; - viewer_id: number; + color: StickyColorRGBA; + geode_id: string; + viewer_id: number; } export interface StickyColorRGBA { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export interface ModelSurfacesApplyTexturesParams { - id: string; - textures: ModelSurfacesApplyTexturesParamsTexture[]; + id: string; + textures: ModelSurfacesApplyTexturesParamsTexture[]; } export interface ModelSurfacesApplyTexturesParamsTexture { - texture_file_name: string; - texture_name: string; + texture_file_name: string; + texture_name: string; } -export interface ModelSurfacesApplyTexturesResponse { -} +export interface ModelSurfacesApplyTexturesResponse {} -export interface ReleaseDatabaseParams { -} +export interface ReleaseDatabaseParams {} -export interface ReleaseDatabaseResponse { -} +export interface ReleaseDatabaseResponse {} -export interface KillParams { -} +export interface KillParams {} -export interface KillResponse { -} +export interface KillResponse {} -export interface ImportProjectParams { -} +export interface ImportProjectParams {} -export interface ImportProjectResponse { -} +export interface ImportProjectResponse {} export interface ViewerUpdateDataParams { - id: string; + id: string; } -export interface ViewerUpdateDataResponse { -} +export interface ViewerUpdateDataResponse {} export interface ViewerUpdateCameraParams { - camera_options: CameraOptions; - [property: string]: any; + camera_options: CameraOptions; + [property: string]: any; } export interface CameraOptions { - clipping_range: number[]; - focal_point: number[]; - position: number[]; - view_angle: number; - view_up: number[]; - [property: string]: any; + clipping_range: number[]; + focal_point: number[]; + position: number[]; + view_angle: number; + view_up: number[]; + [property: string]: any; } -export interface ViewerUpdateCameraResponse { -} +export interface ViewerUpdateCameraResponse {} export interface ViewerThresholdParams { - attribute?: AttributeClass; - ids: string[]; + attribute?: AttributeClass; + ids: string[]; } export interface AttributeClass { - item: number; - location: Location; - maximum: number; - minimum: number; - name: string; + item: number; + location: Location; + maximum: number; + minimum: number; + name: string; } export type Location = "point" | "cell"; -export interface ViewerThresholdResponse { -} +export interface ViewerThresholdResponse {} export interface ViewerTakeScreenshotParams { - filename: string; - include_background: boolean; - output_extension: OutputExtension; + filename: string; + include_background: boolean; + output_extension: OutputExtension; } export type OutputExtension = "png" | "jpg"; export interface ViewerTakeScreenshotResponse { - /** - * Image file content, sent as binary - */ - blob: any; + /** + * Image file content, sent as binary + */ + blob: any; } export interface ViewerSliceParams { - ids: string[]; - slices: Slice[]; + ids: string[]; + slices: Slice[]; } export interface Slice { - axis: number; - index: number; + axis: number; + index: number; } export interface ViewerSliceResponse { - max_indices: number[]; + max_indices: number[]; } export interface ViewerShrinkParams { - ids: string[]; - shrink_factor: number; + ids: string[]; + shrink_factor: number; } -export interface ViewerShrinkResponse { -} +export interface ViewerShrinkResponse {} export interface ViewerSetZScalingParams { - z_scale: number; + z_scale: number; } -export interface ViewerSetZScalingResponse { -} +export interface ViewerSetZScalingResponse {} export interface ViewerSetBackgroundColorParams { - color: ViewerSetBackgroundColorParamsColor; + color: ViewerSetBackgroundColorParamsColor; } export interface ViewerSetBackgroundColorParamsColor { - b: number; - g: number; - r: number; + b: number; + g: number; + r: number; } -export interface ViewerSetBackgroundColorResponse { -} +export interface ViewerSetBackgroundColorResponse {} export interface ViewerRulerParams { - points: Array; + points: Array; } export interface ViewerRulerResponse { - distance: number; - point1: number[]; - point2?: number[]; + distance: number; + point1: number[]; + point2?: number[]; } -export interface ViewerResetVisualizationParams { -} +export interface ViewerResetVisualizationParams {} -export interface ViewerResetVisualizationResponse { -} +export interface ViewerResetVisualizationResponse {} -export interface ViewerResetRulerParams { -} +export interface ViewerResetRulerParams {} -export interface ViewerResetRulerResponse { -} +export interface ViewerResetRulerResponse {} -export interface ViewerResetCameraParams { -} +export interface ViewerResetCameraParams {} -export interface ViewerResetCameraResponse { -} +export interface ViewerResetCameraResponse {} -export interface ViewerRenderParams { -} +export interface ViewerRenderParams {} -export interface ViewerRenderResponse { -} +export interface ViewerRenderResponse {} export interface ViewerPreviewPointsParams { - closed?: boolean; - points: Point[]; - style: Style; + closed?: boolean; + points: Point[]; + style: Style; } export interface Point { - x: number; - y: number; - z: number; + x: number; + y: number; + z: number; } export type Style = "points" | "curve" | "surface"; -export interface ViewerPreviewPointsResponse { -} +export interface ViewerPreviewPointsResponse {} export interface ViewerPickedIDSParams { - ids: string[]; - x: number; - y: number; + ids: string[]; + x: number; + y: number; } export interface ViewerPickedIDSResponse { - array_ids: string[]; - viewer_id?: number; + array_ids: string[]; + viewer_id?: number; } export interface ViewerPickColormapParams { - x: number; - y: number; - [property: string]: any; + x: number; + y: number; + [property: string]: any; } export interface ViewerPickColormapResponse { - data_id?: string; + data_id?: string; } export interface ViewerHighlightParams { - field_type: PickedFieldType; - ids: string[]; - x: number; - y: number; + field_type: PickedFieldType; + ids: string[]; + x: number; + y: number; } export type PickedFieldType = "CELL" | "POINT"; export interface ViewerHighlightResponse { - attributes?: { [key: string]: number[] | number }; - field_type?: PickedFieldType; - geode_id?: string; - id?: string; - picked_id?: number; + attributes?: { [key: string]: number[] | number }; + field_type?: PickedFieldType; + geode_id?: string; + id?: string; + picked_id?: number; } export interface ViewerGridScaleParams { - visibility: boolean; + visibility: boolean; } -export interface ViewerGridScaleResponse { -} +export interface ViewerGridScaleResponse {} export interface ViewerGetPointPositionParams { - x: number; - y: number; + x: number; + y: number; } export interface ViewerGetPointPositionResponse { - x: number; - y: number; - z: number; + x: number; + y: number; + z: number; } export interface ViewerExplodeParams { - explode_factor: number; - ids: string[]; + explode_factor: number; + ids: string[]; } -export interface ViewerExplodeResponse { -} +export interface ViewerExplodeResponse {} export interface ViewerClippingPlanesParams { - ids: string[]; - planes: Plane[]; + ids: string[]; + planes: Plane[]; } export interface Plane { - normal: number[]; - origin: number[]; + normal: number[]; + origin: number[]; } -export interface ViewerClippingPlanesResponse { -} +export interface ViewerClippingPlanesResponse {} export interface ViewerAxesParams { - visibility: boolean; + visibility: boolean; } -export interface ViewerAxesResponse { -} +export interface ViewerAxesResponse {} export interface ErrorResponse { - code: number; - description: string; - name: string; + code: number; + description: string; + name: string; } // `__params` and `__response` only exist at type level, to infer request/response types from a schema. @@ -1269,192 +1300,375 @@ export type TypedSchema = { export interface Schemas { readonly opengeodeweb_viewer: { readonly generic: { - readonly register: (typeof json)["opengeodeweb_viewer"]["generic"]["register"] & TypedSchema; - readonly deregister: (typeof json)["opengeodeweb_viewer"]["generic"]["deregister"] & TypedSchema; + readonly register: (typeof json)["opengeodeweb_viewer"]["generic"]["register"] & + TypedSchema; + readonly deregister: (typeof json)["opengeodeweb_viewer"]["generic"]["deregister"] & + TypedSchema; }; readonly mesh: { readonly cells: { readonly attribute: { readonly cell: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["attribute"]["cell"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["attribute"]["cell"]["attribute"] & + TypedSchema< + MeshCellsAttributeCellAttributeParams, + MeshCellsAttributeCellAttributeResponse + >; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["attribute"]["vertex"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + MeshCellsAttributeVertexAttributeParams, + MeshCellsAttributeVertexAttributeResponse + >; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["visibility"] & TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["color"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["visibility"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["color"] & + TypedSchema; }; readonly edges: { readonly attribute: { readonly edge: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["attribute"]["edge"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["attribute"]["edge"]["attribute"] & + TypedSchema< + MeshEdgesAttributeEdgeAttributeParams, + MeshEdgesAttributeEdgeAttributeResponse + >; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["attribute"]["vertex"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + MeshEdgesAttributeVertexAttributeParams, + MeshEdgesAttributeVertexAttributeResponse + >; }; }; - readonly width: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["width"] & TypedSchema; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["visibility"] & TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["color"] & TypedSchema; + readonly width: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["width"] & + TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["visibility"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["color"] & + TypedSchema; }; readonly points: { readonly attribute: { readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["attribute"]["vertex"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + MeshPointsAttributeVertexAttributeParams, + MeshPointsAttributeVertexAttributeResponse + >; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["visibility"] & TypedSchema; - readonly size: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["size"] & TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["color"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["visibility"] & + TypedSchema; + readonly size: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["size"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["color"] & + TypedSchema; }; readonly polygons: { readonly attribute: { readonly polygon: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["attribute"]["polygon"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["attribute"]["polygon"]["attribute"] & + TypedSchema< + MeshPolygonsAttributePolygonAttributeParams, + MeshPolygonsAttributePolygonAttributeResponse + >; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["attribute"]["vertex"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + MeshPolygonsAttributeVertexAttributeParams, + MeshPolygonsAttributeVertexAttributeResponse + >; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["visibility"] & TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["color"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["visibility"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["color"] & + TypedSchema; }; readonly polyhedra: { readonly attribute: { readonly polyhedron: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["attribute"]["polyhedron"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["attribute"]["polyhedron"]["attribute"] & + TypedSchema< + MeshPolyhedraAttributePolyhedronAttributeParams, + MeshPolyhedraAttributePolyhedronAttributeResponse + >; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["attribute"]["vertex"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + MeshPolyhedraAttributeVertexAttributeParams, + MeshPolyhedraAttributeVertexAttributeResponse + >; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["visibility"] & TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["color"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["visibility"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["color"] & + TypedSchema; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["visibility"] & TypedSchema; - readonly register: (typeof json)["opengeodeweb_viewer"]["mesh"]["register"] & TypedSchema; - readonly highlight: (typeof json)["opengeodeweb_viewer"]["mesh"]["highlight"] & TypedSchema; - readonly deregister: (typeof json)["opengeodeweb_viewer"]["mesh"]["deregister"] & TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["color"] & TypedSchema; - readonly apply_textures: (typeof json)["opengeodeweb_viewer"]["mesh"]["apply_textures"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["visibility"] & + TypedSchema; + readonly register: (typeof json)["opengeodeweb_viewer"]["mesh"]["register"] & + TypedSchema; + readonly highlight: (typeof json)["opengeodeweb_viewer"]["mesh"]["highlight"] & + TypedSchema; + readonly deregister: (typeof json)["opengeodeweb_viewer"]["mesh"]["deregister"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["color"] & + TypedSchema; + readonly apply_textures: (typeof json)["opengeodeweb_viewer"]["mesh"]["apply_textures"] & + TypedSchema; }; readonly model: { readonly blocks: { readonly attribute: { readonly polyhedron: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["attribute"]["polyhedron"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["attribute"]["polyhedron"]["attribute"] & + TypedSchema< + ModelBlocksAttributePolyhedronAttributeParams, + ModelBlocksAttributePolyhedronAttributeResponse + >; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["attribute"]["vertex"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + ModelBlocksAttributeVertexAttributeParams, + ModelBlocksAttributeVertexAttributeResponse + >; }; }; + readonly edges: { + readonly attribute: { + readonly vertex: { + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["edges"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + ModelBlocksEdgesAttributeVertexAttributeParams, + ModelBlocksEdgesAttributeVertexAttributeResponse + >; + }; + }; + readonly width: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["edges"]["width"] & + TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["edges"]["visibility"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["edges"]["color"] & + TypedSchema; + }; readonly points: { readonly attribute: { readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["attribute"]["vertex"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + ModelBlocksPointsAttributeVertexAttributeParams, + ModelBlocksPointsAttributeVertexAttributeResponse + >; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["visibility"] & TypedSchema; - readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["size"] & TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["color"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["visibility"] & + TypedSchema; + readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["size"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["color"] & + TypedSchema; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["visibility"] & TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["color"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["visibility"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["color"] & + TypedSchema; }; readonly corners: { readonly attribute: { readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["corners"]["attribute"]["vertex"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["corners"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + ModelCornersAttributeVertexAttributeParams, + ModelCornersAttributeVertexAttributeResponse + >; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["corners"]["visibility"] & TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["corners"]["color"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["corners"]["visibility"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["corners"]["color"] & + TypedSchema; }; readonly edges: { - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["edges"]["visibility"] & TypedSchema; + readonly width: (typeof json)["opengeodeweb_viewer"]["model"]["edges"]["width"] & + TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["edges"]["visibility"] & + TypedSchema; }; readonly lines: { readonly attribute: { readonly edge: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["attribute"]["edge"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["attribute"]["edge"]["attribute"] & + TypedSchema< + ModelLinesAttributeEdgeAttributeParams, + ModelLinesAttributeEdgeAttributeResponse + >; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["attribute"]["vertex"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + ModelLinesAttributeVertexAttributeParams, + ModelLinesAttributeVertexAttributeResponse + >; }; }; readonly points: { readonly attribute: { readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["attribute"]["vertex"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + ModelLinesPointsAttributeVertexAttributeParams, + ModelLinesPointsAttributeVertexAttributeResponse + >; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["visibility"] & TypedSchema; - readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["size"] & TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["color"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["visibility"] & + TypedSchema; + readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["size"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["color"] & + TypedSchema; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["visibility"] & TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["color"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["visibility"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["color"] & + TypedSchema; }; readonly points: { - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["points"]["visibility"] & TypedSchema; - readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["points"]["size"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["points"]["visibility"] & + TypedSchema; + readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["points"]["size"] & + TypedSchema; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["visibility"] & TypedSchema; - readonly register: (typeof json)["opengeodeweb_viewer"]["model"]["register"] & TypedSchema; - readonly highlight: (typeof json)["opengeodeweb_viewer"]["model"]["highlight"] & TypedSchema; - readonly get_blocks_bounds: (typeof json)["opengeodeweb_viewer"]["model"]["get_blocks_bounds"] & TypedSchema; - readonly deregister: (typeof json)["opengeodeweb_viewer"]["model"]["deregister"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["visibility"] & + TypedSchema; + readonly register: (typeof json)["opengeodeweb_viewer"]["model"]["register"] & + TypedSchema; + readonly highlight: (typeof json)["opengeodeweb_viewer"]["model"]["highlight"] & + TypedSchema; + readonly get_blocks_bounds: (typeof json)["opengeodeweb_viewer"]["model"]["get_blocks_bounds"] & + TypedSchema; + readonly deregister: (typeof json)["opengeodeweb_viewer"]["model"]["deregister"] & + TypedSchema; readonly surfaces: { readonly attribute: { readonly polygon: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["attribute"]["polygon"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["attribute"]["polygon"]["attribute"] & + TypedSchema< + ModelSurfacesAttributePolygonAttributeParams, + ModelSurfacesAttributePolygonAttributeResponse + >; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["attribute"]["vertex"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + ModelSurfacesAttributeVertexAttributeParams, + ModelSurfacesAttributeVertexAttributeResponse + >; + }; + }; + readonly edges: { + readonly attribute: { + readonly vertex: { + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["edges"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + ModelSurfacesEdgesAttributeVertexAttributeParams, + ModelSurfacesEdgesAttributeVertexAttributeResponse + >; + }; }; + readonly width: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["edges"]["width"] & + TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["edges"]["visibility"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["edges"]["color"] & + TypedSchema; }; readonly points: { readonly attribute: { readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["attribute"]["vertex"]["attribute"] & TypedSchema; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["attribute"]["vertex"]["attribute"] & + TypedSchema< + ModelSurfacesPointsAttributeVertexAttributeParams, + ModelSurfacesPointsAttributeVertexAttributeResponse + >; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["visibility"] & TypedSchema; - readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["size"] & TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["color"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["visibility"] & + TypedSchema; + readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["size"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["color"] & + TypedSchema; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["visibility"] & TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["color"] & TypedSchema; - readonly apply_textures: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["apply_textures"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["visibility"] & + TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["color"] & + TypedSchema; + readonly apply_textures: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["apply_textures"] & + TypedSchema; }; }; - readonly release_database: (typeof json)["opengeodeweb_viewer"]["release_database"] & TypedSchema; - readonly kill: (typeof json)["opengeodeweb_viewer"]["kill"] & TypedSchema; - readonly import_project: (typeof json)["opengeodeweb_viewer"]["import_project"] & TypedSchema; + readonly release_database: (typeof json)["opengeodeweb_viewer"]["release_database"] & + TypedSchema; + readonly kill: (typeof json)["opengeodeweb_viewer"]["kill"] & + TypedSchema; + readonly import_project: (typeof json)["opengeodeweb_viewer"]["import_project"] & + TypedSchema; readonly viewer: { - readonly update_data: (typeof json)["opengeodeweb_viewer"]["viewer"]["update_data"] & TypedSchema; - readonly update_camera: (typeof json)["opengeodeweb_viewer"]["viewer"]["update_camera"] & TypedSchema; - readonly threshold: (typeof json)["opengeodeweb_viewer"]["viewer"]["threshold"] & TypedSchema; - readonly take_screenshot: (typeof json)["opengeodeweb_viewer"]["viewer"]["take_screenshot"] & TypedSchema; - readonly slice: (typeof json)["opengeodeweb_viewer"]["viewer"]["slice"] & TypedSchema; - readonly shrink: (typeof json)["opengeodeweb_viewer"]["viewer"]["shrink"] & TypedSchema; - readonly set_z_scaling: (typeof json)["opengeodeweb_viewer"]["viewer"]["set_z_scaling"] & TypedSchema; - readonly set_background_color: (typeof json)["opengeodeweb_viewer"]["viewer"]["set_background_color"] & TypedSchema; - readonly ruler: (typeof json)["opengeodeweb_viewer"]["viewer"]["ruler"] & TypedSchema; - readonly reset_visualization: (typeof json)["opengeodeweb_viewer"]["viewer"]["reset_visualization"] & TypedSchema; - readonly reset_ruler: (typeof json)["opengeodeweb_viewer"]["viewer"]["reset_ruler"] & TypedSchema; - readonly reset_camera: (typeof json)["opengeodeweb_viewer"]["viewer"]["reset_camera"] & TypedSchema; - readonly render: (typeof json)["opengeodeweb_viewer"]["viewer"]["render"] & TypedSchema; - readonly preview_points: (typeof json)["opengeodeweb_viewer"]["viewer"]["preview_points"] & TypedSchema; - readonly picked_ids: (typeof json)["opengeodeweb_viewer"]["viewer"]["picked_ids"] & TypedSchema; - readonly pick_colormap: (typeof json)["opengeodeweb_viewer"]["viewer"]["pick_colormap"] & TypedSchema; - readonly highlight: (typeof json)["opengeodeweb_viewer"]["viewer"]["highlight"] & TypedSchema; - readonly grid_scale: (typeof json)["opengeodeweb_viewer"]["viewer"]["grid_scale"] & TypedSchema; - readonly get_point_position: (typeof json)["opengeodeweb_viewer"]["viewer"]["get_point_position"] & TypedSchema; - readonly explode: (typeof json)["opengeodeweb_viewer"]["viewer"]["explode"] & TypedSchema; - readonly clipping_planes: (typeof json)["opengeodeweb_viewer"]["viewer"]["clipping_planes"] & TypedSchema; - readonly axes: (typeof json)["opengeodeweb_viewer"]["viewer"]["axes"] & TypedSchema; + readonly update_data: (typeof json)["opengeodeweb_viewer"]["viewer"]["update_data"] & + TypedSchema; + readonly update_camera: (typeof json)["opengeodeweb_viewer"]["viewer"]["update_camera"] & + TypedSchema; + readonly threshold: (typeof json)["opengeodeweb_viewer"]["viewer"]["threshold"] & + TypedSchema; + readonly take_screenshot: (typeof json)["opengeodeweb_viewer"]["viewer"]["take_screenshot"] & + TypedSchema; + readonly slice: (typeof json)["opengeodeweb_viewer"]["viewer"]["slice"] & + TypedSchema; + readonly shrink: (typeof json)["opengeodeweb_viewer"]["viewer"]["shrink"] & + TypedSchema; + readonly set_z_scaling: (typeof json)["opengeodeweb_viewer"]["viewer"]["set_z_scaling"] & + TypedSchema; + readonly set_background_color: (typeof json)["opengeodeweb_viewer"]["viewer"]["set_background_color"] & + TypedSchema; + readonly ruler: (typeof json)["opengeodeweb_viewer"]["viewer"]["ruler"] & + TypedSchema; + readonly reset_visualization: (typeof json)["opengeodeweb_viewer"]["viewer"]["reset_visualization"] & + TypedSchema; + readonly reset_ruler: (typeof json)["opengeodeweb_viewer"]["viewer"]["reset_ruler"] & + TypedSchema; + readonly reset_camera: (typeof json)["opengeodeweb_viewer"]["viewer"]["reset_camera"] & + TypedSchema; + readonly render: (typeof json)["opengeodeweb_viewer"]["viewer"]["render"] & + TypedSchema; + readonly preview_points: (typeof json)["opengeodeweb_viewer"]["viewer"]["preview_points"] & + TypedSchema; + readonly picked_ids: (typeof json)["opengeodeweb_viewer"]["viewer"]["picked_ids"] & + TypedSchema; + readonly pick_colormap: (typeof json)["opengeodeweb_viewer"]["viewer"]["pick_colormap"] & + TypedSchema; + readonly highlight: (typeof json)["opengeodeweb_viewer"]["viewer"]["highlight"] & + TypedSchema; + readonly grid_scale: (typeof json)["opengeodeweb_viewer"]["viewer"]["grid_scale"] & + TypedSchema; + readonly get_point_position: (typeof json)["opengeodeweb_viewer"]["viewer"]["get_point_position"] & + TypedSchema; + readonly explode: (typeof json)["opengeodeweb_viewer"]["viewer"]["explode"] & + TypedSchema; + readonly clipping_planes: (typeof json)["opengeodeweb_viewer"]["viewer"]["clipping_planes"] & + TypedSchema; + readonly axes: (typeof json)["opengeodeweb_viewer"]["viewer"]["axes"] & + TypedSchema; }; }; } diff --git a/pyproject.toml b/pyproject.toml index 02de3cbc..95b9d21c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,12 +62,14 @@ where = ["src"] "opengeodeweb_viewer.rpc.model.surfaces.points.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.surfaces.points.attribute.vertex.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.surfaces.edges.schemas" = ["*.json"] +"opengeodeweb_viewer.rpc.model.surfaces.edges.attribute.vertex.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.surfaces.attribute.polygon.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.surfaces.attribute.vertex.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.blocks.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.blocks.points.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.blocks.points.attribute.vertex.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.blocks.edges.schemas" = ["*.json"] +"opengeodeweb_viewer.rpc.model.blocks.edges.attribute.vertex.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.blocks.attribute.polyhedron.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.model.blocks.attribute.vertex.schemas" = ["*.json"] "opengeodeweb_viewer.rpc.viewer.schemas" = ["*.json"] diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/__init__.py b/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/__init__.py b/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/blocks_edges_attribute_vertex_protocols.py b/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/blocks_edges_attribute_vertex_protocols.py new file mode 100644 index 00000000..bbee371e --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/blocks_edges_attribute_vertex_protocols.py @@ -0,0 +1,30 @@ +# Standard library imports +from pathlib import Path + +# Third party imports +from opengeodeweb_microservice.schemas import get_schemas_dict + +# Local application imports +from opengeodeweb_viewer.rpc.model.model_protocols import VtkModelView +from opengeodeweb_viewer.typed_rpc import typed_rpc + +from . import schemas + + +class VtkModelBlocksEdgesAttributeVertexView(VtkModelView): + model_blocks_edges_attribute_vertex_prefix = ( + "opengeodeweb_viewer.model.blocks.edges.attribute.vertex." + ) + model_blocks_edges_attribute_vertex_schemas_dict = get_schemas_dict( + Path(__file__).parent / "schemas" + ) + + def __init__(self) -> None: + super().__init__() + + @typed_rpc(model_blocks_edges_attribute_vertex_prefix, schemas.attribute_route) + def set_model_blocks_edges_vertex_attribute( + self, params: schemas.Attribute + ) -> schemas.AttributeResponse: + self.set_component_edges_attribute(params.id, "blocks", params.block_ids, params) + return schemas.AttributeResponse() diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/schemas/__init__.py b/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/schemas/__init__.py new file mode 100644 index 00000000..a563b254 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/schemas/__init__.py @@ -0,0 +1 @@ +from .attribute import * diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/schemas/attribute.json b/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/schemas/attribute.json new file mode 100644 index 00000000..bf36e3b9 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/schemas/attribute.json @@ -0,0 +1,88 @@ +{ + "rpc": "attribute", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "name": { + "type": "string", + "minLength": 1 + }, + "item": { + "type": "integer", + "minimum": 0 + }, + "points": { + "type": "array", + "description": "Flat array of [value, r, g, b, ...]", + "items": { + "type": "number" + }, + "minItems": 8 + }, + "minimum": { + "type": "number" + }, + "maximum": { + "type": "number" + }, + "no_data_color": { + "type": "object", + "properties": { + "red": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "green": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "blue": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "alpha": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "required": [ + "red", + "green", + "blue", + "alpha" + ], + "additionalProperties": false + } + }, + "required": [ + "id", + "block_ids", + "name", + "item", + "points", + "minimum", + "maximum" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } +} diff --git a/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/schemas/attribute.py b/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/schemas/attribute.py new file mode 100644 index 00000000..3c07a38b --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/blocks/edges/attribute/vertex/schemas/attribute.py @@ -0,0 +1,51 @@ +from pathlib import Path +from opengeodeweb_microservice.schemas import Route, load_schema +from dataclasses_json import DataClassJsonMixin +from opengeodeweb_microservice.schemas import print_dataclass +from dataclasses import dataclass +from typing import List, Optional + + +@dataclass +class NoDataColor(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + alpha: float + blue: int + green: int + red: int + + +@dataclass +class Attribute(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + block_ids: List[int] + id: str + item: int + maximum: float + minimum: float + name: str + points: List[float] + """Flat array of [value, r, g, b, ...]""" + + no_data_color: Optional[NoDataColor] = None + + +@dataclass +class AttributeResponse(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + pass + + +attribute_route = Route( + schema=load_schema(Path(__file__)), + params=Attribute, + response=AttributeResponse, +) + +__all__ = ["NoDataColor", "Attribute", "AttributeResponse", "attribute_route"] diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/__init__.py b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/__init__.py b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/schemas/__init__.py b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/schemas/__init__.py new file mode 100644 index 00000000..a563b254 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/schemas/__init__.py @@ -0,0 +1 @@ +from .attribute import * diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/schemas/attribute.json b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/schemas/attribute.json new file mode 100644 index 00000000..bf36e3b9 --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/schemas/attribute.json @@ -0,0 +1,88 @@ +{ + "rpc": "attribute", + "type": "object", + "properties": { + "id": { + "type": "string", + "minLength": 32, + "maxLength": 32 + }, + "block_ids": { + "type": "array", + "items": { + "type": "integer" + }, + "minItems": 1 + }, + "name": { + "type": "string", + "minLength": 1 + }, + "item": { + "type": "integer", + "minimum": 0 + }, + "points": { + "type": "array", + "description": "Flat array of [value, r, g, b, ...]", + "items": { + "type": "number" + }, + "minItems": 8 + }, + "minimum": { + "type": "number" + }, + "maximum": { + "type": "number" + }, + "no_data_color": { + "type": "object", + "properties": { + "red": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "green": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "blue": { + "type": "integer", + "minimum": 0, + "maximum": 255 + }, + "alpha": { + "type": "number", + "minimum": 0, + "maximum": 1 + } + }, + "required": [ + "red", + "green", + "blue", + "alpha" + ], + "additionalProperties": false + } + }, + "required": [ + "id", + "block_ids", + "name", + "item", + "points", + "minimum", + "maximum" + ], + "additionalProperties": false, + "response": { + "type": "object", + "properties": {}, + "required": [], + "additionalProperties": false + } +} diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/schemas/attribute.py b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/schemas/attribute.py new file mode 100644 index 00000000..3c07a38b --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/schemas/attribute.py @@ -0,0 +1,51 @@ +from pathlib import Path +from opengeodeweb_microservice.schemas import Route, load_schema +from dataclasses_json import DataClassJsonMixin +from opengeodeweb_microservice.schemas import print_dataclass +from dataclasses import dataclass +from typing import List, Optional + + +@dataclass +class NoDataColor(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + alpha: float + blue: int + green: int + red: int + + +@dataclass +class Attribute(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + block_ids: List[int] + id: str + item: int + maximum: float + minimum: float + name: str + points: List[float] + """Flat array of [value, r, g, b, ...]""" + + no_data_color: Optional[NoDataColor] = None + + +@dataclass +class AttributeResponse(DataClassJsonMixin): + def __post_init__(self) -> None: + print_dataclass(self) + + pass + + +attribute_route = Route( + schema=load_schema(Path(__file__)), + params=Attribute, + response=AttributeResponse, +) + +__all__ = ["NoDataColor", "Attribute", "AttributeResponse", "attribute_route"] diff --git a/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/surfaces_edges_attribute_vertex_protocols.py b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/surfaces_edges_attribute_vertex_protocols.py new file mode 100644 index 00000000..0854aa3b --- /dev/null +++ b/src/opengeodeweb_viewer/rpc/model/surfaces/edges/attribute/vertex/surfaces_edges_attribute_vertex_protocols.py @@ -0,0 +1,30 @@ +# Standard library imports +from pathlib import Path + +# Third party imports +from opengeodeweb_microservice.schemas import get_schemas_dict + +# Local application imports +from opengeodeweb_viewer.rpc.model.model_protocols import VtkModelView +from opengeodeweb_viewer.typed_rpc import typed_rpc + +from . import schemas + + +class VtkModelSurfacesEdgesAttributeVertexView(VtkModelView): + model_surfaces_edges_attribute_vertex_prefix = ( + "opengeodeweb_viewer.model.surfaces.edges.attribute.vertex." + ) + model_surfaces_edges_attribute_vertex_schemas_dict = get_schemas_dict( + Path(__file__).parent / "schemas" + ) + + def __init__(self) -> None: + super().__init__() + + @typed_rpc(model_surfaces_edges_attribute_vertex_prefix, schemas.attribute_route) + def set_model_surfaces_edges_vertex_attribute( + self, params: schemas.Attribute + ) -> schemas.AttributeResponse: + self.set_component_edges_attribute(params.id, "surfaces", params.block_ids, params) + return schemas.AttributeResponse() diff --git a/src/opengeodeweb_viewer/rpc/protocols.py b/src/opengeodeweb_viewer/rpc/protocols.py index 9cf8f034..9fd934cc 100644 --- a/src/opengeodeweb_viewer/rpc/protocols.py +++ b/src/opengeodeweb_viewer/rpc/protocols.py @@ -35,6 +35,9 @@ from .model.blocks.attribute.vertex.blocks_attribute_vertex_protocols import ( VtkModelBlocksAttributeVertexView, ) +from .model.blocks.edges.attribute.vertex.blocks_edges_attribute_vertex_protocols import ( + VtkModelBlocksEdgesAttributeVertexView, +) from .model.blocks.edges.model_blocks_edges_protocols import VtkModelBlocksEdgesView from .model.blocks.model_blocks_protocols import VtkModelBlocksView from .model.blocks.points.attribute.vertex.blocks_points_attribute_vertex_protocols import ( @@ -64,6 +67,9 @@ from .model.surfaces.attribute.vertex.surfaces_attribute_vertex_protocols import ( VtkModelSurfacesAttributeVertexView, ) +from .model.surfaces.edges.attribute.vertex.surfaces_edges_attribute_vertex_protocols import ( + VtkModelSurfacesEdgesAttributeVertexView, +) from .model.surfaces.edges.model_surfaces_edges_protocols import VtkModelSurfacesEdgesView from .model.surfaces.model_surfaces_protocols import VtkModelSurfacesView from .model.surfaces.points.attribute.vertex.surfaces_points_attribute_vertex_protocols import ( @@ -110,4 +116,6 @@ VtkModelBlocksPointsAttributeVertexView, VtkModelSurfacesEdgesView, VtkModelBlocksEdgesView, + VtkModelSurfacesEdgesAttributeVertexView, + VtkModelBlocksEdgesAttributeVertexView, ) diff --git a/tests/data/images/model/edges/surfaces_edges_attribute.jpeg b/tests/data/images/model/edges/surfaces_edges_attribute.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..b4de0b78698807df1154e38c771ecc9786d2ff00 GIT binary patch literal 30635 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 None: + + test_surfaces_edges_color(server, dataset_factory) + view = VtkModelSurfacesEdgesAttributeVertexView + server.call( + view.model_surfaces_edges_attribute_vertex_prefix + + view.model_surfaces_edges_attribute_vertex_schemas_dict["attribute"]["rpc"], + [ + { + "id": model_id, + "block_ids": surfaces_ids, + "name": "unique vertices", + "item": 0, + "points": [0.0, 0.0, 0.0, 1.0, 663.0, 1.0, 0.0, 0.0], + "minimum": 0.0, + "maximum": 663.0, + } + ], + ) + assert server.compare_image("model/edges/surfaces_edges_attribute.jpeg") + + def test_surfaces_edges_opacity(server: ServerMonitor, dataset_factory: Callable[..., str]) -> None: test_surfaces_edges_color(server, dataset_factory) From 3ad11138943ea467816794c394f966a77669a5f4 Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Wed, 21 Oct 2026 15:15:58 +0200 Subject: [PATCH 06/10] fix(meshPoints): Constant color replaces the points attribute Once a vertex attribute had created the dedicated points actor, switching back to a constant color only set the main actor VertexColor: points kept the attribute colors and its scalar bar --- .../object/object_methods.py | 19 +++++++++++++----- .../polygons_points_attribute_then_color.jpeg | Bin 0 -> 22690 bytes .../test_points_attribute_vertex_protocols.py | 14 +++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 tests/data/images/mesh/points/polygons_points_attribute_then_color.jpeg diff --git a/src/opengeodeweb_viewer/object/object_methods.py b/src/opengeodeweb_viewer/object/object_methods.py index 0986a8c3..eaffceac 100644 --- a/src/opengeodeweb_viewer/object/object_methods.py +++ b/src/opengeodeweb_viewer/object/object_methods.py @@ -263,11 +263,20 @@ def update_edges_scalar_bar_visibility(self, pipeline: VtkPipeline) -> None: def set_points_color(self, data_id: str, color: ColorClassProtocol) -> None: if self.get_viewer_data(data_id).viewer_elements_type == "points": self.set_color(data_id, color) - else: - actor = self.get_vtk_pipeline(data_id).actor - actor.GetProperty().SetVertexColor( - [color.red / 255, color.green / 255, color.blue / 255] - ) + return + pipeline = self.get_vtk_pipeline(data_id) + rgb = [color.red / 255, color.green / 255, color.blue / 255] + pipeline.actor.GetProperty().SetVertexColor(rgb) + if pipeline.points_actor is None or pipeline.points_mapper is None: + return + # A constant color replaces the points attribute and its scalar bar + pipeline.points_mapper.ScalarVisibilityOff() + pipeline.points_actor.GetProperty().SetColor(rgb) + pipeline.points_actor.GetProperty().SetOpacity(color.alpha) + if pipeline.points_scalar_bar is not None: + pipeline.points_scalar_bar.SetLookupTable(None) + self.update_points_scalar_bar_visibility(pipeline) + self.update_scalar_bars_layout() def set_blocks_visibility( self, data_id: str, block_ids: list[int], *, visibility: bool diff --git a/tests/data/images/mesh/points/polygons_points_attribute_then_color.jpeg b/tests/data/images/mesh/points/polygons_points_attribute_then_color.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..6839d6faa1c5edca6e298117d648eb549f6cec7e GIT binary patch literal 22690 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 Trgefi9w6nG{_ej0XX<|d5q!B> literal 0 HcmV?d00001 diff --git a/tests/mesh/points/attribute/vertex/test_points_attribute_vertex_protocols.py b/tests/mesh/points/attribute/vertex/test_points_attribute_vertex_protocols.py index 4b05efc3..868a3179 100644 --- a/tests/mesh/points/attribute/vertex/test_points_attribute_vertex_protocols.py +++ b/tests/mesh/points/attribute/vertex/test_points_attribute_vertex_protocols.py @@ -490,3 +490,17 @@ def test_polygons_points_shared_scalar_bar( [attribute], ) assert server.compare_image("mesh/points/polygons_points_shared_scalar_bar.jpeg") + + +def test_polygons_points_attribute_then_color( + server: ServerMonitor, dataset_factory: Callable[..., str] +) -> None: + + test_polygons_points_vertex_attribute(server, dataset_factory) + server.call( + VtkMeshPointsView.mesh_points_prefix + + VtkMeshPointsView.mesh_points_schemas_dict["color"]["rpc"], + [{"id": mesh_id, "color": {"red": 255, "green": 0, "blue": 0, "alpha": 1.0}}], + ) + # Red points, no points scalar bar + assert server.compare_image("mesh/points/polygons_points_attribute_then_color.jpeg") From 56b56b8afb069294065e8b32904d91229a6da503 Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Wed, 21 Oct 2026 15:21:48 +0200 Subject: [PATCH 07/10] fix : when a scalarbar for points is the same for edges attribute => only one --- .../object/object_methods.py | 51 +++++++++--------- .../rpc/mesh/mesh_protocols.py | 22 +++++--- src/opengeodeweb_viewer/vtk_pipeline.py | 7 +++ ...ns_points_and_edges_shared_scalar_bar.jpeg | Bin 0 -> 19495 bytes .../test_edges_attribute_vertex_protocols.py | 26 +++++++++ 5 files changed, 76 insertions(+), 30 deletions(-) create mode 100644 tests/data/images/mesh/edges/polygons_points_and_edges_shared_scalar_bar.jpeg diff --git a/src/opengeodeweb_viewer/object/object_methods.py b/src/opengeodeweb_viewer/object/object_methods.py index eaffceac..2ed5fdf0 100644 --- a/src/opengeodeweb_viewer/object/object_methods.py +++ b/src/opengeodeweb_viewer/object/object_methods.py @@ -89,8 +89,7 @@ def set_visibility(self, data_id: str, *, visibility: bool) -> None: and pipeline.mapper.GetLookupTable() is not None ): pipeline.scalar_bar.VisibilityOn() - self.update_points_scalar_bar_visibility(pipeline) - self.update_edges_scalar_bar_visibility(pipeline) + self.update_style_scalar_bars_visibility(pipeline) for style in pipeline.block_styles.values(): if style.get("name"): for bar in pipeline.scalar_bars.values(): @@ -130,7 +129,7 @@ def set_edges_visibility(self, data_id: str, *, visibility: bool) -> None: return pipeline.edges_visibility = visibility pipeline.edges_actor.SetVisibility(pipeline.actor.GetVisibility() and visibility) - self.update_edges_scalar_bar_visibility(pipeline) + self.update_style_scalar_bars_visibility(pipeline) self.update_scalar_bars_layout() def set_edges_width(self, data_id: str, width: float) -> None: @@ -158,7 +157,8 @@ def set_edges_color(self, data_id: str, color: ColorClassProtocol) -> None: pipeline.edges_actor.GetProperty().SetOpacity(color.alpha) if pipeline.edges_scalar_bar is not None: pipeline.edges_scalar_bar.SetLookupTable(None) - self.update_edges_scalar_bar_visibility(pipeline) + pipeline.edges_color_map_key = None + self.update_style_scalar_bars_visibility(pipeline) self.update_scalar_bars_layout() def set_points_visibility(self, data_id: str, *, visibility: bool) -> None: @@ -169,7 +169,7 @@ def set_points_visibility(self, data_id: str, *, visibility: bool) -> None: if pipeline.points_actor is not None: pipeline.points_visibility = visibility pipeline.points_actor.SetVisibility(visibility) - self.update_points_scalar_bar_visibility(pipeline) + self.update_style_scalar_bars_visibility(pipeline) self.update_scalar_bars_layout() else: pipeline.actor.GetProperty().SetVertexVisibility(visibility) @@ -208,15 +208,28 @@ def ensure_points_actor(self, pipeline: VtkPipeline) -> vtkActor: pipeline.points_scalar_bar = scalar_bar return actor - def update_points_scalar_bar_visibility(self, pipeline: VtkPipeline) -> None: - # A points scalar bar only holds a lookup table when it differs from the polygons one - bar = pipeline.points_scalar_bar - if bar is None: + def update_style_scalar_bars_visibility(self, pipeline: VtkPipeline) -> None: + # Points and edges bars only hold a lookup table when they differ from the polygons one + points_bar = pipeline.points_scalar_bar + points_bar_visible = ( + points_bar is not None + and pipeline.actor.GetVisibility() + and pipeline.points_visibility + and points_bar.GetLookupTable() is not None + ) + if points_bar is not None: + points_bar.SetVisibility(points_bar_visible) + edges_bar = pipeline.edges_scalar_bar + if edges_bar is None: return - bar.SetVisibility( + # Edges showing the same attribute as the points reuse the points bar + edges_bar.SetVisibility( pipeline.actor.GetVisibility() - and pipeline.points_visibility - and bar.GetLookupTable() is not None + and pipeline.edges_visibility + and edges_bar.GetLookupTable() is not None + and not ( + points_bar_visible and pipeline.edges_color_map_key == pipeline.points_color_map_key + ) ) def ensure_edges_actor(self, pipeline: VtkPipeline) -> vtkActor: @@ -249,17 +262,6 @@ def ensure_edges_actor(self, pipeline: VtkPipeline) -> vtkActor: pipeline.edges_scalar_bar = scalar_bar return actor - def update_edges_scalar_bar_visibility(self, pipeline: VtkPipeline) -> None: - # An edges scalar bar only holds a lookup table when it differs from the polygons one - bar = pipeline.edges_scalar_bar - if bar is None: - return - bar.SetVisibility( - pipeline.actor.GetVisibility() - and pipeline.edges_visibility - and bar.GetLookupTable() is not None - ) - def set_points_color(self, data_id: str, color: ColorClassProtocol) -> None: if self.get_viewer_data(data_id).viewer_elements_type == "points": self.set_color(data_id, color) @@ -275,7 +277,8 @@ def set_points_color(self, data_id: str, color: ColorClassProtocol) -> None: pipeline.points_actor.GetProperty().SetOpacity(color.alpha) if pipeline.points_scalar_bar is not None: pipeline.points_scalar_bar.SetLookupTable(None) - self.update_points_scalar_bar_visibility(pipeline) + pipeline.points_color_map_key = None + self.update_style_scalar_bars_visibility(pipeline) self.update_scalar_bars_layout() def set_blocks_visibility( diff --git a/src/opengeodeweb_viewer/rpc/mesh/mesh_protocols.py b/src/opengeodeweb_viewer/rpc/mesh/mesh_protocols.py index 4ed89f8f..88570857 100644 --- a/src/opengeodeweb_viewer/rpc/mesh/mesh_protocols.py +++ b/src/opengeodeweb_viewer/rpc/mesh/mesh_protocols.py @@ -21,7 +21,7 @@ AttributeProtocol, create_color_transfer_function, ) -from opengeodeweb_viewer.vtk_pipeline import VtkPipeline +from opengeodeweb_viewer.vtk_pipeline import ColorMapKey, VtkPipeline from . import schemas @@ -117,10 +117,10 @@ def display_attribute_on_points(self, data_id: str, attribute: AttributeProtocol self.ensure_points_actor(pipeline) if pipeline.points_mapper is None: return - self.display_attribute_on_style_mapper( + pipeline.points_color_map_key = self.display_attribute_on_style_mapper( data_id, pipeline.points_mapper, pipeline.points_scalar_bar, attribute ) - self.update_points_scalar_bar_visibility(pipeline) + self.update_style_scalar_bars_visibility(pipeline) self.update_scalar_bars_layout() def display_attribute_on_edges(self, data_id: str, attribute: AttributeProtocol) -> None: @@ -128,10 +128,10 @@ def display_attribute_on_edges(self, data_id: str, attribute: AttributeProtocol) self.ensure_edges_actor(pipeline) if pipeline.edges_mapper is None: return - self.display_attribute_on_style_mapper( + pipeline.edges_color_map_key = self.display_attribute_on_style_mapper( data_id, pipeline.edges_mapper, pipeline.edges_scalar_bar, attribute ) - self.update_edges_scalar_bar_visibility(pipeline) + self.update_style_scalar_bars_visibility(pipeline) self.update_scalar_bars_layout() def display_attribute_on_style_mapper( @@ -140,7 +140,8 @@ def display_attribute_on_style_mapper( mapper: vtkDataSetMapper, scalar_bar: vtkScalarBarActor | None, attribute: AttributeProtocol, - ) -> None: + ) -> ColorMapKey | None: + # Returns the attribute of the dedicated scalar bar, None when sharing the polygons one pipeline = self.get_vtk_pipeline(data_id) # Field data mode avoids touching the active scalars shared with the polygons mapper.ScalarVisibilityOn() @@ -166,6 +167,15 @@ def display_attribute_on_style_mapper( mapper.InterpolateScalarsBeforeMappingOn() if scalar_bar is not None: scalar_bar.SetLookupTable(bar_lut) + if bar_lut is None: + return None + return ( + attribute.name, + attribute.item, + attribute.minimum, + attribute.maximum, + tuple(attribute.points), + ) def shares_polygons_color_map(self, data_id: str, attribute: AttributeProtocol) -> bool: pipeline = self.get_vtk_pipeline(data_id) diff --git a/src/opengeodeweb_viewer/vtk_pipeline.py b/src/opengeodeweb_viewer/vtk_pipeline.py index 2d5815cd..3ba2242d 100644 --- a/src/opengeodeweb_viewer/vtk_pipeline.py +++ b/src/opengeodeweb_viewer/vtk_pipeline.py @@ -208,6 +208,10 @@ class BlockStyle(TypedDict): no_data_color: ColorClassProtocol | None +# Attribute name, item, range and color map points: equal keys mean identical scalar bars +ColorMapKey = tuple[str, int, float, float, tuple[float, ...]] + + @dataclass class PointsSizeActor: mapper: vtkCompositePolyDataMapper @@ -273,6 +277,9 @@ class VtkPipeline: edges_actor: vtkActor | None = None edges_scalar_bar: vtkScalarBarActor | None = None edges_visibility: bool = False + # Attribute shown by the points and edges dedicated scalar bars, None when they have none + points_color_map_key: ColorMapKey | None = None + edges_color_map_key: ColorMapKey | None = None # One edges actor per distinct width, since line width is an actor property edges_width_actors: dict[float, EdgesWidthActor] = field(default_factory=dict) edges_block_styles: dict[int, ModelEdgesStyle] = field(default_factory=dict) diff --git a/tests/data/images/mesh/edges/polygons_points_and_edges_shared_scalar_bar.jpeg b/tests/data/images/mesh/edges/polygons_points_and_edges_shared_scalar_bar.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..474429f95064464f8f894658779099483b60e4b2 GIT binary patch literal 19495 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 V22il`;~Lx?f%2i*zxsDi|JhE+T1o%_ literal 0 HcmV?d00001 diff --git a/tests/mesh/edges/attribute/vertex/test_edges_attribute_vertex_protocols.py b/tests/mesh/edges/attribute/vertex/test_edges_attribute_vertex_protocols.py index ae4b451c..c523dce0 100644 --- a/tests/mesh/edges/attribute/vertex/test_edges_attribute_vertex_protocols.py +++ b/tests/mesh/edges/attribute/vertex/test_edges_attribute_vertex_protocols.py @@ -8,6 +8,10 @@ # Third party imports from opengeodeweb_viewer.rpc.mesh.mesh_protocols import VtkMeshView +from opengeodeweb_viewer.rpc.mesh.points.attribute.vertex.points_attribute_vertex_protocols import ( + VtkMeshPointsAttributeVertexView, +) +from opengeodeweb_viewer.rpc.mesh.points.points_protocols import VtkMeshPointsView from opengeodeweb_viewer.rpc.mesh.polygons.attribute.vertex import ( polygons_attribute_vertex_protocols, ) @@ -448,3 +452,25 @@ def test_polygons_edges_hidden_with_object( ) # Empty scene: no edges, no scalar bar assert server.compare_image("mesh/edges/polygons_edges_hidden_with_object.jpeg") + + +def test_polygons_points_and_edges_shared_scalar_bar( + server: ServerMonitor, dataset_factory: Callable[..., str] +) -> None: + + register_hat_with_edges(server, dataset_factory) + server.call( + VtkMeshPointsView.mesh_points_prefix + + VtkMeshPointsView.mesh_points_schemas_dict["visibility"]["rpc"], + [{"id": mesh_id, "visibility": True}], + ) + server.call( + VtkMeshPointsAttributeVertexView.mesh_points_attribute_vertex_prefix + + VtkMeshPointsAttributeVertexView.mesh_points_attribute_vertex_schemas_dict["attribute"][ + "rpc" + ], + [{"id": mesh_id, **HAT_ATTRIBUTE}], + ) + set_edges_vertex_attribute(server, HAT_ATTRIBUTE) + # Same attribute and color map on points and edges: one scalar bar only + assert server.compare_image("mesh/edges/polygons_points_and_edges_shared_scalar_bar.jpeg") From 2c05d836d58214602ec734b5266911b75d6ed7cc Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Wed, 21 Oct 2026 15:38:31 +0200 Subject: [PATCH 08/10] Restore model scalar bars from displayed attributes --- src/opengeodeweb_viewer/object/object_methods.py | 6 ------ .../rpc/model/model_protocols.py | 5 ++++- tests/model/edges/test_model_edges_protocols.py | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/opengeodeweb_viewer/object/object_methods.py b/src/opengeodeweb_viewer/object/object_methods.py index 2ed5fdf0..473c2dcc 100644 --- a/src/opengeodeweb_viewer/object/object_methods.py +++ b/src/opengeodeweb_viewer/object/object_methods.py @@ -90,12 +90,6 @@ def set_visibility(self, data_id: str, *, visibility: bool) -> None: ): pipeline.scalar_bar.VisibilityOn() self.update_style_scalar_bars_visibility(pipeline) - for style in pipeline.block_styles.values(): - if style.get("name"): - for bar in pipeline.scalar_bars.values(): - if bar.GetLookupTable() is not None: - bar.VisibilityOn() - break self.update_scalar_bars_layout() def set_style_actors_visibility(self, pipeline: VtkPipeline, *, visibility: bool) -> None: diff --git a/src/opengeodeweb_viewer/rpc/model/model_protocols.py b/src/opengeodeweb_viewer/rpc/model/model_protocols.py index 8d6b58de..c5023d55 100644 --- a/src/opengeodeweb_viewer/rpc/model/model_protocols.py +++ b/src/opengeodeweb_viewer/rpc/model/model_protocols.py @@ -179,7 +179,7 @@ def setup_model_color_map(self, pipeline: VtkPipeline) -> None: no_data_color = style["no_data_color"] lut = create_color_transfer_function(points, minimum, maximum, item, no_data_color) bar.SetLookupTable(lut) - bar.VisibilityOn() + bar.SetVisibility(pipeline.actor.GetVisibility()) for name, bar in pipeline.scalar_bars.items(): if name not in active_attrs: bar.VisibilityOff() @@ -514,6 +514,9 @@ def deregister_model(self, params: schemas.Deregister) -> schemas.DeregisterResp @typed_rpc(model_prefix, schemas.visibility_route) def set_model_visibility(self, params: schemas.Visibility) -> schemas.VisibilityResponse: self.set_visibility(params.id, visibility=params.visibility) + if params.visibility: + # Bars come back from the displayed attributes, hidden components' ones stay hidden + self.setup_model_color_map(self.get_vtk_pipeline(params.id)) return schemas.VisibilityResponse() @typed_rpc(model_prefix, schemas.highlight_route) diff --git a/tests/model/edges/test_model_edges_protocols.py b/tests/model/edges/test_model_edges_protocols.py index a801f04a..30da532d 100644 --- a/tests/model/edges/test_model_edges_protocols.py +++ b/tests/model/edges/test_model_edges_protocols.py @@ -8,6 +8,7 @@ from opengeodeweb_viewer.rpc.model.edges.model_edges_protocols import ( VtkModelEdgesView, ) +from opengeodeweb_viewer.rpc.model.model_protocols import VtkModelView from opengeodeweb_viewer.rpc.model.surfaces.edges.attribute.vertex import ( surfaces_edges_attribute_vertex_protocols, ) @@ -109,6 +110,20 @@ def test_surfaces_edges_attribute( assert server.compare_image("model/edges/surfaces_edges_attribute.jpeg") +def test_surfaces_edges_attribute_model_hidden_then_shown( + server: ServerMonitor, dataset_factory: Callable[..., str] +) -> None: + + test_surfaces_edges_attribute(server, dataset_factory) + for visibility in (False, True): + server.call( + VtkModelView.model_prefix + VtkModelView.model_schemas_dict["visibility"]["rpc"], + [{"id": model_id, "visibility": visibility}], + ) + # The edges scalar bar comes back with the model + assert server.compare_image("model/edges/surfaces_edges_attribute.jpeg") + + def test_surfaces_edges_opacity(server: ServerMonitor, dataset_factory: Callable[..., str]) -> None: test_surfaces_edges_color(server, dataset_factory) From d8ddaa147f2691648727dc056cb7e19fd7fcf01b Mon Sep 17 00:00:00 2001 From: MaxNumerique Date: Wed, 21 Oct 2026 15:40:19 +0200 Subject: [PATCH 09/10] Points/edges decided once, when their attribute was set, whether to reuse the polygons scalar bar: switching the polygons to a constant color left the edges colored with no bar, and setting the edges attribute before the identicalpolygons one gave two bars --- .../object/object_methods.py | 62 +++++++++++------- .../rpc/mesh/mesh_protocols.py | 51 +++++--------- ...olygons_color_after_shared_scalar_bar.jpeg | Bin 0 -> 19490 bytes .../test_edges_attribute_vertex_protocols.py | 36 ++++++++++ 4 files changed, 92 insertions(+), 57 deletions(-) create mode 100644 tests/data/images/mesh/edges/polygons_color_after_shared_scalar_bar.jpeg diff --git a/src/opengeodeweb_viewer/object/object_methods.py b/src/opengeodeweb_viewer/object/object_methods.py index 473c2dcc..5c3b1a83 100644 --- a/src/opengeodeweb_viewer/object/object_methods.py +++ b/src/opengeodeweb_viewer/object/object_methods.py @@ -14,7 +14,7 @@ # Local application imports from opengeodeweb_viewer.utils_functions import ColorClassProtocol -from opengeodeweb_viewer.vtk_pipeline import VtkPipeline +from opengeodeweb_viewer.vtk_pipeline import ColorMapKey, VtkPipeline from opengeodeweb_viewer.vtk_protocol import VtkView logger = logging.getLogger(__name__) @@ -107,11 +107,15 @@ def set_opacity(self, data_id: str, opacity: float) -> None: actor.GetProperty().SetOpacity(opacity) def set_color(self, data_id: str, color: ColorClassProtocol) -> None: - mapper = self.get_vtk_pipeline(data_id).mapper - mapper.ScalarVisibilityOff() - actor = self.get_vtk_pipeline(data_id).actor + pipeline = self.get_vtk_pipeline(data_id) + pipeline.mapper.ScalarVisibilityOff() + actor = pipeline.actor actor.GetProperty().SetColor([color.red / 255, color.green / 255, color.blue / 255]) actor.GetProperty().SetOpacity(color.alpha) + # Points and edges bars that reused the polygons one now show their own + pipeline.scalar_bar.VisibilityOff() + self.update_style_scalar_bars_visibility(pipeline) + self.update_scalar_bars_layout() def set_edges_visibility(self, data_id: str, *, visibility: bool) -> None: if self.get_viewer_data(data_id).viewer_elements_type == "edges": @@ -202,29 +206,43 @@ def ensure_points_actor(self, pipeline: VtkPipeline) -> vtkActor: pipeline.points_scalar_bar = scalar_bar return actor + @staticmethod + def polygons_color_map_key(pipeline: VtkPipeline) -> ColorMapKey | None: + mapper = pipeline.mapper + if not mapper.GetScalarVisibility() or mapper.GetLookupTable() is None: + return None + minimum, maximum = mapper.GetScalarRange() + return ( + mapper.GetArrayName(), + mapper.GetArrayComponent(), + minimum, + maximum, + tuple(pipeline.color_map_points), + ) + def update_style_scalar_bars_visibility(self, pipeline: VtkPipeline) -> None: - # Points and edges bars only hold a lookup table when they differ from the polygons one - points_bar = pipeline.points_scalar_bar + # Points and edges bars show only when no visible bar already holds the same attribute + visible = bool(pipeline.actor.GetVisibility()) + polygons_key = self.polygons_color_map_key(pipeline) points_bar_visible = ( - points_bar is not None - and pipeline.actor.GetVisibility() + visible and pipeline.points_visibility - and points_bar.GetLookupTable() is not None + and pipeline.points_color_map_key is not None + and pipeline.points_color_map_key != polygons_key ) - if points_bar is not None: - points_bar.SetVisibility(points_bar_visible) - edges_bar = pipeline.edges_scalar_bar - if edges_bar is None: - return - # Edges showing the same attribute as the points reuse the points bar - edges_bar.SetVisibility( - pipeline.actor.GetVisibility() - and pipeline.edges_visibility - and edges_bar.GetLookupTable() is not None - and not ( - points_bar_visible and pipeline.edges_color_map_key == pipeline.points_color_map_key + if pipeline.points_scalar_bar is not None: + pipeline.points_scalar_bar.SetVisibility(points_bar_visible) + if pipeline.edges_scalar_bar is not None: + pipeline.edges_scalar_bar.SetVisibility( + visible + and pipeline.edges_visibility + and pipeline.edges_color_map_key is not None + and pipeline.edges_color_map_key != polygons_key + and not ( + points_bar_visible + and pipeline.edges_color_map_key == pipeline.points_color_map_key + ) ) - ) def ensure_edges_actor(self, pipeline: VtkPipeline) -> vtkActor: # Edges get their own actor so their scalars stay independent from the polygons diff --git a/src/opengeodeweb_viewer/rpc/mesh/mesh_protocols.py b/src/opengeodeweb_viewer/rpc/mesh/mesh_protocols.py index 88570857..16d01c77 100644 --- a/src/opengeodeweb_viewer/rpc/mesh/mesh_protocols.py +++ b/src/opengeodeweb_viewer/rpc/mesh/mesh_protocols.py @@ -118,7 +118,7 @@ def display_attribute_on_points(self, data_id: str, attribute: AttributeProtocol if pipeline.points_mapper is None: return pipeline.points_color_map_key = self.display_attribute_on_style_mapper( - data_id, pipeline.points_mapper, pipeline.points_scalar_bar, attribute + pipeline.points_mapper, pipeline.points_scalar_bar, attribute ) self.update_style_scalar_bars_visibility(pipeline) self.update_scalar_bars_layout() @@ -129,46 +129,36 @@ def display_attribute_on_edges(self, data_id: str, attribute: AttributeProtocol) if pipeline.edges_mapper is None: return pipeline.edges_color_map_key = self.display_attribute_on_style_mapper( - data_id, pipeline.edges_mapper, pipeline.edges_scalar_bar, attribute + pipeline.edges_mapper, pipeline.edges_scalar_bar, attribute ) self.update_style_scalar_bars_visibility(pipeline) self.update_scalar_bars_layout() def display_attribute_on_style_mapper( self, - data_id: str, mapper: vtkDataSetMapper, scalar_bar: vtkScalarBarActor | None, attribute: AttributeProtocol, - ) -> ColorMapKey | None: - # Returns the attribute of the dedicated scalar bar, None when sharing the polygons one - pipeline = self.get_vtk_pipeline(data_id) + ) -> ColorMapKey: # Field data mode avoids touching the active scalars shared with the polygons mapper.ScalarVisibilityOn() mapper.SetScalarModeToUsePointFieldData() mapper.ColorByArrayComponent(attribute.name, attribute.item) - if self.shares_polygons_color_map(data_id, attribute): - # Same color map as the polygons: reuse their scalar bar instead of adding one - lut = pipeline.mapper.GetLookupTable() - bar_lut = None - else: - lut = create_color_transfer_function( - attribute.points, - attribute.minimum, - attribute.maximum, - attribute.item, - attribute.no_data_color, - ) - lut.SetRange(attribute.minimum, attribute.maximum) - bar_lut = lut + lut = create_color_transfer_function( + attribute.points, + attribute.minimum, + attribute.maximum, + attribute.item, + attribute.no_data_color, + ) + lut.SetRange(attribute.minimum, attribute.maximum) mapper.SetLookupTable(lut) mapper.SetScalarRange(attribute.minimum, attribute.maximum) mapper.UseLookupTableScalarRangeOff() mapper.InterpolateScalarsBeforeMappingOn() + # Whether this bar shows or reuses an identical one is decided on each visibility update if scalar_bar is not None: - scalar_bar.SetLookupTable(bar_lut) - if bar_lut is None: - return None + scalar_bar.SetLookupTable(lut) return ( attribute.name, attribute.item, @@ -177,18 +167,6 @@ def display_attribute_on_style_mapper( tuple(attribute.points), ) - def shares_polygons_color_map(self, data_id: str, attribute: AttributeProtocol) -> bool: - pipeline = self.get_vtk_pipeline(data_id) - mapper = pipeline.mapper - return bool( - mapper.GetScalarVisibility() - and mapper.GetLookupTable() is not None - and mapper.GetArrayName() == attribute.name - and mapper.GetArrayComponent() == attribute.item - and tuple(mapper.GetScalarRange()) == (attribute.minimum, attribute.maximum) - and pipeline.color_map_points == list(attribute.points) - ) - def display_attribute_on_cells(self, data_id: str, attribute: AttributeProtocol) -> None: pipeline = self.get_vtk_pipeline(data_id) name = attribute.name @@ -207,6 +185,8 @@ def display_scalar_range(self, data_id: str, minimum: float, maximum: float) -> data.mapper.SetScalarRange(minimum, maximum) data.mapper.GetLookupTable().SetRange(minimum, maximum) data.mapper.UseLookupTableScalarRangeOff() + self.update_style_scalar_bars_visibility(data) + self.update_scalar_bars_layout() def setup_color_map(self, data_id: str, attribute: AttributeProtocol) -> None: data = self.get_vtk_pipeline(data_id) @@ -225,6 +205,7 @@ def setup_color_map(self, data_id: str, attribute: AttributeProtocol) -> None: data.scalar_bar.SetLookupTable(lut) data.scalar_bar.VisibilityOn() + self.update_style_scalar_bars_visibility(data) self.update_scalar_bars_layout() @typed_rpc(mesh_prefix, schemas.highlight_route) diff --git a/tests/data/images/mesh/edges/polygons_color_after_shared_scalar_bar.jpeg b/tests/data/images/mesh/edges/polygons_color_after_shared_scalar_bar.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..362141206a82ec3b29e82351938d177df84450f7 GIT binary patch literal 19490 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 None: + server.call( + VtkMeshPolygonsAttributeVertexView.mesh_polygons_attribute_vertex_prefix + + VtkMeshPolygonsAttributeVertexView.mesh_polygons_attribute_vertex_schemas_dict[ + "attribute" + ]["rpc"], + [{"id": mesh_id, **HAT_ATTRIBUTE}], + ) + + +def test_polygons_edges_shared_scalar_bar_edges_first( + server: ServerMonitor, dataset_factory: Callable[..., str] +) -> None: + + register_hat_with_edges(server, dataset_factory) + set_edges_vertex_attribute(server, HAT_ATTRIBUTE) + set_polygons_vertex_attribute(server) + # Same picture as when the polygons attribute comes first: one scalar bar only + assert server.compare_image("mesh/edges/polygons_edges_shared_scalar_bar.jpeg") + + +def test_polygons_color_after_shared_scalar_bar( + server: ServerMonitor, dataset_factory: Callable[..., str] +) -> None: + + test_polygons_edges_shared_scalar_bar(server, dataset_factory) + server.call( + VtkMeshPolygonsView.mesh_polygons_prefix + + VtkMeshPolygonsView.mesh_polygons_schemas_dict["color"]["rpc"], + [{"id": mesh_id, "color": {"red": 255, "green": 255, "blue": 255, "alpha": 1.0}}], + ) + # Polygons back to a constant color: the edges keep their attribute and get their own bar + assert server.compare_image("mesh/edges/polygons_color_after_shared_scalar_bar.jpeg") From 08549e36bb2513fcc53b59a73c31f92c205c8967 Mon Sep 17 00:00:00 2001 From: MaxNumerique <144453705+MaxNumerique@users.noreply.github.com> Date: Thu, 22 Oct 2026 07:16:52 +0000 Subject: [PATCH 10/10] Apply prepare changes --- opengeodeweb_viewer_typed_schemas.d.ts | 1879 ++++++++++++------------ requirements.txt | 1 - 2 files changed, 905 insertions(+), 975 deletions(-) diff --git a/opengeodeweb_viewer_typed_schemas.d.ts b/opengeodeweb_viewer_typed_schemas.d.ts index 5102e4d4..f646a1fd 100644 --- a/opengeodeweb_viewer_typed_schemas.d.ts +++ b/opengeodeweb_viewer_typed_schemas.d.ts @@ -2,1293 +2,1386 @@ import type json from "./opengeodeweb_viewer_schemas.json"; export interface GenericRegisterParams { - id: string; - name: string; + id: string; + name: string; } -export interface GenericRegisterResponse {} +export interface GenericRegisterResponse { +} export interface GenericDeregisterParams { - id: string; + id: string; } -export interface GenericDeregisterResponse {} +export interface GenericDeregisterResponse { +} export interface MeshCellsAttributeCellAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshCellsAttributeCellAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshCellsAttributeCellAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshCellsAttributeCellAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshCellsAttributeCellAttributeResponse {} +export interface MeshCellsAttributeCellAttributeResponse { +} export interface MeshCellsAttributeVertexAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshCellsAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshCellsAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshCellsAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshCellsAttributeVertexAttributeResponse {} +export interface MeshCellsAttributeVertexAttributeResponse { +} export interface MeshCellsVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface MeshCellsVisibilityResponse {} +export interface MeshCellsVisibilityResponse { +} export interface MeshCellsColorParams { - color: MeshCellsColorParamsColor; - id: string; + color: MeshCellsColorParamsColor; + id: string; } export interface MeshCellsColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshCellsColorResponse {} +export interface MeshCellsColorResponse { +} export interface MeshEdgesAttributeEdgeAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshEdgesAttributeEdgeAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshEdgesAttributeEdgeAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshEdgesAttributeEdgeAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshEdgesAttributeEdgeAttributeResponse {} +export interface MeshEdgesAttributeEdgeAttributeResponse { +} export interface MeshEdgesAttributeVertexAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshEdgesAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshEdgesAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshEdgesAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshEdgesAttributeVertexAttributeResponse {} +export interface MeshEdgesAttributeVertexAttributeResponse { +} export interface MeshEdgesWidthParams { - id: string; - width: number; + id: string; + width: number; } -export interface MeshEdgesWidthResponse {} +export interface MeshEdgesWidthResponse { +} export interface MeshEdgesVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface MeshEdgesVisibilityResponse {} +export interface MeshEdgesVisibilityResponse { +} export interface MeshEdgesColorParams { - color: MeshEdgesColorParamsColor; - id: string; + color: MeshEdgesColorParamsColor; + id: string; } export interface MeshEdgesColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshEdgesColorResponse {} +export interface MeshEdgesColorResponse { +} export interface MeshPointsAttributeVertexAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshPointsAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshPointsAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshPointsAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPointsAttributeVertexAttributeResponse {} +export interface MeshPointsAttributeVertexAttributeResponse { +} export interface MeshPointsVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } export interface MeshPointsVisibilityResponse { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } export interface MeshPointsSizeParams { - id: string; - size: number; + id: string; + size: number; } -export interface MeshPointsSizeResponse {} +export interface MeshPointsSizeResponse { +} export interface MeshPointsColorParams { - color: MeshPointsColorParamsColor; - id: string; + color: MeshPointsColorParamsColor; + id: string; } export interface MeshPointsColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPointsColorResponse {} +export interface MeshPointsColorResponse { +} export interface MeshPolygonsAttributePolygonAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshPolygonsAttributePolygonAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshPolygonsAttributePolygonAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshPolygonsAttributePolygonAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPolygonsAttributePolygonAttributeResponse {} +export interface MeshPolygonsAttributePolygonAttributeResponse { +} export interface MeshPolygonsAttributeVertexAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshPolygonsAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshPolygonsAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshPolygonsAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPolygonsAttributeVertexAttributeResponse {} +export interface MeshPolygonsAttributeVertexAttributeResponse { +} export interface MeshPolygonsVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface MeshPolygonsVisibilityResponse {} +export interface MeshPolygonsVisibilityResponse { +} export interface MeshPolygonsColorParams { - color: MeshPolygonsColorParamsColor; - id: string; + color: MeshPolygonsColorParamsColor; + id: string; } export interface MeshPolygonsColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPolygonsColorResponse {} +export interface MeshPolygonsColorResponse { +} export interface MeshPolyhedraAttributePolyhedronAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshPolyhedraAttributePolyhedronAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshPolyhedraAttributePolyhedronAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshPolyhedraAttributePolyhedronAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPolyhedraAttributePolyhedronAttributeResponse {} +export interface MeshPolyhedraAttributePolyhedronAttributeResponse { +} export interface MeshPolyhedraAttributeVertexAttributeParams { - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: MeshPolyhedraAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: MeshPolyhedraAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface MeshPolyhedraAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPolyhedraAttributeVertexAttributeResponse {} +export interface MeshPolyhedraAttributeVertexAttributeResponse { +} export interface MeshPolyhedraVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface MeshPolyhedraVisibilityResponse {} +export interface MeshPolyhedraVisibilityResponse { +} export interface MeshPolyhedraColorParams { - color: MeshPolyhedraColorParamsColor; - id: string; + color: MeshPolyhedraColorParamsColor; + id: string; } export interface MeshPolyhedraColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshPolyhedraColorResponse {} +export interface MeshPolyhedraColorResponse { +} export interface MeshVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface MeshVisibilityResponse {} +export interface MeshVisibilityResponse { +} export interface MeshRegisterParams { - id: string; - name: string; + id: string; + name: string; } -export interface MeshRegisterResponse {} +export interface MeshRegisterResponse { +} export interface MeshHighlightParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface MeshHighlightResponse {} +export interface MeshHighlightResponse { +} export interface MeshDeregisterParams { - id: string; + id: string; } -export interface MeshDeregisterResponse {} +export interface MeshDeregisterResponse { +} export interface MeshColorParams { - color: MeshColorParamsColor; - id: string; + color: MeshColorParamsColor; + id: string; } export interface MeshColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface MeshColorResponse {} +export interface MeshColorResponse { +} export interface MeshApplyTexturesParams { - id: string; - textures: MeshApplyTexturesParamsTexture[]; + id: string; + textures: MeshApplyTexturesParamsTexture[]; } export interface MeshApplyTexturesParamsTexture { - id: string; - texture_name: string; + id: string; + texture_name: string; } -export interface MeshApplyTexturesResponse {} +export interface MeshApplyTexturesResponse { +} export interface ModelBlocksAttributePolyhedronAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelBlocksAttributePolyhedronAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelBlocksAttributePolyhedronAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelBlocksAttributePolyhedronAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelBlocksAttributePolyhedronAttributeResponse {} +export interface ModelBlocksAttributePolyhedronAttributeResponse { +} export interface ModelBlocksAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelBlocksAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelBlocksAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelBlocksAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelBlocksAttributeVertexAttributeResponse {} +export interface ModelBlocksAttributeVertexAttributeResponse { +} export interface ModelBlocksEdgesAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelBlocksEdgesAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelBlocksEdgesAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelBlocksEdgesAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelBlocksEdgesAttributeVertexAttributeResponse {} +export interface ModelBlocksEdgesAttributeVertexAttributeResponse { +} export interface ModelBlocksEdgesWidthParams { - block_ids: number[]; - id: string; - width: number; + block_ids: number[]; + id: string; + width: number; } -export interface ModelBlocksEdgesWidthResponse {} +export interface ModelBlocksEdgesWidthResponse { +} export interface ModelBlocksEdgesVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelBlocksEdgesVisibilityResponse {} +export interface ModelBlocksEdgesVisibilityResponse { +} export interface ModelBlocksEdgesColorParams { - block_ids: number[]; - color: ModelBlocksEdgesColorParamsColor; - id: string; + block_ids: number[]; + color: ModelBlocksEdgesColorParamsColor; + id: string; } export interface ModelBlocksEdgesColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelBlocksEdgesColorResponse {} +export interface ModelBlocksEdgesColorResponse { +} export interface ModelBlocksPointsAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelBlocksPointsAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelBlocksPointsAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelBlocksPointsAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelBlocksPointsAttributeVertexAttributeResponse {} +export interface ModelBlocksPointsAttributeVertexAttributeResponse { +} export interface ModelBlocksPointsVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelBlocksPointsVisibilityResponse {} +export interface ModelBlocksPointsVisibilityResponse { +} export interface ModelBlocksPointsSizeParams { - block_ids: number[]; - id: string; - size: number; + block_ids: number[]; + id: string; + size: number; } -export interface ModelBlocksPointsSizeResponse {} +export interface ModelBlocksPointsSizeResponse { +} export interface ModelBlocksPointsColorParams { - block_ids: number[]; - color: ModelBlocksPointsColorParamsColor; - id: string; + block_ids: number[]; + color: ModelBlocksPointsColorParamsColor; + id: string; } export interface ModelBlocksPointsColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelBlocksPointsColorResponse {} +export interface ModelBlocksPointsColorResponse { +} export interface ModelBlocksVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelBlocksVisibilityResponse {} +export interface ModelBlocksVisibilityResponse { +} export interface ModelBlocksColorParams { - block_ids: number[]; - collection_id?: string; - color?: ModelBlocksColorParamsColor; - color_mode: ColorMode; - id: string; + block_ids: number[]; + collection_id?: string; + color?: ModelBlocksColorParamsColor; + color_mode: ColorMode; + id: string; } export interface ModelBlocksColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export type ColorMode = "constant" | "random"; export interface ModelBlocksColorResponse { - colors: ModelBlocksColorResponseColor[]; + colors: ModelBlocksColorResponseColor[]; } export interface ModelBlocksColorResponseColor { - color: PurpleColorRGBA; - geode_id: string; - viewer_id: number; + color: PurpleColorRGBA; + geode_id: string; + viewer_id: number; } export interface PurpleColorRGBA { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export interface ModelCornersAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelCornersAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelCornersAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelCornersAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelCornersAttributeVertexAttributeResponse {} +export interface ModelCornersAttributeVertexAttributeResponse { +} export interface ModelCornersVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelCornersVisibilityResponse {} +export interface ModelCornersVisibilityResponse { +} export interface ModelCornersColorParams { - block_ids: number[]; - collection_id?: string; - color?: ModelCornersColorParamsColor; - color_mode: ColorMode; - id: string; + block_ids: number[]; + collection_id?: string; + color?: ModelCornersColorParamsColor; + color_mode: ColorMode; + id: string; } export interface ModelCornersColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export interface ModelCornersColorResponse { - colors: ModelCornersColorResponseColor[]; + colors: ModelCornersColorResponseColor[]; } export interface ModelCornersColorResponseColor { - color: FluffyColorRGBA; - geode_id: string; - viewer_id: number; + color: FluffyColorRGBA; + geode_id: string; + viewer_id: number; } export interface FluffyColorRGBA { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export interface ModelEdgesWidthParams { - id: string; - width: number; + id: string; + width: number; } -export interface ModelEdgesWidthResponse {} +export interface ModelEdgesWidthResponse { +} export interface ModelEdgesVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface ModelEdgesVisibilityResponse {} +export interface ModelEdgesVisibilityResponse { +} export interface ModelLinesAttributeEdgeAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelLinesAttributeEdgeAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelLinesAttributeEdgeAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelLinesAttributeEdgeAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelLinesAttributeEdgeAttributeResponse {} +export interface ModelLinesAttributeEdgeAttributeResponse { +} export interface ModelLinesAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelLinesAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelLinesAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelLinesAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelLinesAttributeVertexAttributeResponse {} +export interface ModelLinesAttributeVertexAttributeResponse { +} export interface ModelLinesPointsAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelLinesPointsAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelLinesPointsAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelLinesPointsAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelLinesPointsAttributeVertexAttributeResponse {} +export interface ModelLinesPointsAttributeVertexAttributeResponse { +} export interface ModelLinesPointsVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelLinesPointsVisibilityResponse {} +export interface ModelLinesPointsVisibilityResponse { +} export interface ModelLinesPointsSizeParams { - block_ids: number[]; - id: string; - size: number; + block_ids: number[]; + id: string; + size: number; } -export interface ModelLinesPointsSizeResponse {} +export interface ModelLinesPointsSizeResponse { +} export interface ModelLinesPointsColorParams { - block_ids: number[]; - color: ModelLinesPointsColorParamsColor; - id: string; + block_ids: number[]; + color: ModelLinesPointsColorParamsColor; + id: string; } export interface ModelLinesPointsColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelLinesPointsColorResponse {} +export interface ModelLinesPointsColorResponse { +} export interface ModelLinesVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelLinesVisibilityResponse {} +export interface ModelLinesVisibilityResponse { +} export interface ModelLinesColorParams { - block_ids: number[]; - collection_id?: string; - color?: ModelLinesColorParamsColor; - color_mode: ColorMode; - id: string; + block_ids: number[]; + collection_id?: string; + color?: ModelLinesColorParamsColor; + color_mode: ColorMode; + id: string; } export interface ModelLinesColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export interface ModelLinesColorResponse { - colors: ModelLinesColorResponseColor[]; + colors: ModelLinesColorResponseColor[]; } export interface ModelLinesColorResponseColor { - color: TentacledColorRGBA; - geode_id: string; - viewer_id: number; + color: TentacledColorRGBA; + geode_id: string; + viewer_id: number; } export interface TentacledColorRGBA { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export interface ModelPointsVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface ModelPointsVisibilityResponse {} +export interface ModelPointsVisibilityResponse { +} export interface ModelPointsSizeParams { - id: string; - size: number; + id: string; + size: number; } -export interface ModelPointsSizeResponse {} +export interface ModelPointsSizeResponse { +} export interface ModelVisibilityParams { - id: string; - visibility: boolean; + id: string; + visibility: boolean; } -export interface ModelVisibilityResponse {} +export interface ModelVisibilityResponse { +} export interface ModelRegisterParams { - id: string; - name: string; + id: string; + name: string; } -export interface ModelRegisterResponse {} +export interface ModelRegisterResponse { +} export interface ModelHighlightParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelHighlightResponse {} +export interface ModelHighlightResponse { +} export interface ModelGetBlocksBoundsParams { - block_ids: number[]; - id: string; + block_ids: number[]; + id: string; } export interface ModelGetBlocksBoundsResponse { - bounds: number[]; + bounds: number[]; } export interface ModelDeregisterParams { - id: string; + id: string; } -export interface ModelDeregisterResponse {} +export interface ModelDeregisterResponse { +} export interface ModelSurfacesAttributePolygonAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelSurfacesAttributePolygonAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelSurfacesAttributePolygonAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelSurfacesAttributePolygonAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelSurfacesAttributePolygonAttributeResponse {} +export interface ModelSurfacesAttributePolygonAttributeResponse { +} export interface ModelSurfacesAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelSurfacesAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelSurfacesAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelSurfacesAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelSurfacesAttributeVertexAttributeResponse {} +export interface ModelSurfacesAttributeVertexAttributeResponse { +} export interface ModelSurfacesEdgesAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelSurfacesEdgesAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelSurfacesEdgesAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelSurfacesEdgesAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelSurfacesEdgesAttributeVertexAttributeResponse {} +export interface ModelSurfacesEdgesAttributeVertexAttributeResponse { +} export interface ModelSurfacesEdgesWidthParams { - block_ids: number[]; - id: string; - width: number; + block_ids: number[]; + id: string; + width: number; } -export interface ModelSurfacesEdgesWidthResponse {} +export interface ModelSurfacesEdgesWidthResponse { +} export interface ModelSurfacesEdgesVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelSurfacesEdgesVisibilityResponse {} +export interface ModelSurfacesEdgesVisibilityResponse { +} export interface ModelSurfacesEdgesColorParams { - block_ids: number[]; - color: ModelSurfacesEdgesColorParamsColor; - id: string; + block_ids: number[]; + color: ModelSurfacesEdgesColorParamsColor; + id: string; } export interface ModelSurfacesEdgesColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelSurfacesEdgesColorResponse {} +export interface ModelSurfacesEdgesColorResponse { +} export interface ModelSurfacesPointsAttributeVertexAttributeParams { - block_ids: number[]; - id: string; - item: number; - maximum: number; - minimum: number; - name: string; - no_data_color?: ModelSurfacesPointsAttributeVertexAttributeParamsNoDataColor; - /** - * Flat array of [value, r, g, b, ...] - */ - points: number[]; + block_ids: number[]; + id: string; + item: number; + maximum: number; + minimum: number; + name: string; + no_data_color?: ModelSurfacesPointsAttributeVertexAttributeParamsNoDataColor; + /** + * Flat array of [value, r, g, b, ...] + */ + points: number[]; } export interface ModelSurfacesPointsAttributeVertexAttributeParamsNoDataColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelSurfacesPointsAttributeVertexAttributeResponse {} +export interface ModelSurfacesPointsAttributeVertexAttributeResponse { +} export interface ModelSurfacesPointsVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelSurfacesPointsVisibilityResponse {} +export interface ModelSurfacesPointsVisibilityResponse { +} export interface ModelSurfacesPointsSizeParams { - block_ids: number[]; - id: string; - size: number; + block_ids: number[]; + id: string; + size: number; } -export interface ModelSurfacesPointsSizeResponse {} +export interface ModelSurfacesPointsSizeResponse { +} export interface ModelSurfacesPointsColorParams { - block_ids: number[]; - color: ModelSurfacesPointsColorParamsColor; - id: string; + block_ids: number[]; + color: ModelSurfacesPointsColorParamsColor; + id: string; } export interface ModelSurfacesPointsColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } -export interface ModelSurfacesPointsColorResponse {} +export interface ModelSurfacesPointsColorResponse { +} export interface ModelSurfacesVisibilityParams { - block_ids: number[]; - id: string; - visibility: boolean; + block_ids: number[]; + id: string; + visibility: boolean; } -export interface ModelSurfacesVisibilityResponse {} +export interface ModelSurfacesVisibilityResponse { +} export interface ModelSurfacesColorParams { - block_ids: number[]; - collection_id?: string; - color?: ModelSurfacesColorParamsColor; - color_mode: ColorMode; - id: string; + block_ids: number[]; + collection_id?: string; + color?: ModelSurfacesColorParamsColor; + color_mode: ColorMode; + id: string; } export interface ModelSurfacesColorParamsColor { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export interface ModelSurfacesColorResponse { - colors: ModelSurfacesColorResponseColor[]; + colors: ModelSurfacesColorResponseColor[]; } export interface ModelSurfacesColorResponseColor { - color: StickyColorRGBA; - geode_id: string; - viewer_id: number; + color: StickyColorRGBA; + geode_id: string; + viewer_id: number; } export interface StickyColorRGBA { - alpha: number; - blue: number; - green: number; - red: number; + alpha: number; + blue: number; + green: number; + red: number; } export interface ModelSurfacesApplyTexturesParams { - id: string; - textures: ModelSurfacesApplyTexturesParamsTexture[]; + id: string; + textures: ModelSurfacesApplyTexturesParamsTexture[]; } export interface ModelSurfacesApplyTexturesParamsTexture { - texture_file_name: string; - texture_name: string; + texture_file_name: string; + texture_name: string; } -export interface ModelSurfacesApplyTexturesResponse {} +export interface ModelSurfacesApplyTexturesResponse { +} -export interface ReleaseDatabaseParams {} +export interface ReleaseDatabaseParams { +} -export interface ReleaseDatabaseResponse {} +export interface ReleaseDatabaseResponse { +} -export interface KillParams {} +export interface KillParams { +} -export interface KillResponse {} +export interface KillResponse { +} -export interface ImportProjectParams {} +export interface ImportProjectParams { +} -export interface ImportProjectResponse {} +export interface ImportProjectResponse { +} export interface ViewerUpdateDataParams { - id: string; + id: string; } -export interface ViewerUpdateDataResponse {} +export interface ViewerUpdateDataResponse { +} export interface ViewerUpdateCameraParams { - camera_options: CameraOptions; - [property: string]: any; + camera_options: CameraOptions; + [property: string]: any; } export interface CameraOptions { - clipping_range: number[]; - focal_point: number[]; - position: number[]; - view_angle: number; - view_up: number[]; - [property: string]: any; + clipping_range: number[]; + focal_point: number[]; + position: number[]; + view_angle: number; + view_up: number[]; + [property: string]: any; } -export interface ViewerUpdateCameraResponse {} +export interface ViewerUpdateCameraResponse { +} export interface ViewerThresholdParams { - attribute?: AttributeClass; - ids: string[]; + attribute?: AttributeClass; + ids: string[]; } export interface AttributeClass { - item: number; - location: Location; - maximum: number; - minimum: number; - name: string; + item: number; + location: Location; + maximum: number; + minimum: number; + name: string; } export type Location = "point" | "cell"; -export interface ViewerThresholdResponse {} +export interface ViewerThresholdResponse { +} export interface ViewerTakeScreenshotParams { - filename: string; - include_background: boolean; - output_extension: OutputExtension; + filename: string; + include_background: boolean; + output_extension: OutputExtension; } export type OutputExtension = "png" | "jpg"; export interface ViewerTakeScreenshotResponse { - /** - * Image file content, sent as binary - */ - blob: any; + /** + * Image file content, sent as binary + */ + blob: any; } export interface ViewerSliceParams { - ids: string[]; - slices: Slice[]; + ids: string[]; + slices: Slice[]; } export interface Slice { - axis: number; - index: number; + axis: number; + index: number; } export interface ViewerSliceResponse { - max_indices: number[]; + max_indices: number[]; } export interface ViewerShrinkParams { - ids: string[]; - shrink_factor: number; + ids: string[]; + shrink_factor: number; } -export interface ViewerShrinkResponse {} +export interface ViewerShrinkResponse { +} export interface ViewerSetZScalingParams { - z_scale: number; + z_scale: number; } -export interface ViewerSetZScalingResponse {} +export interface ViewerSetZScalingResponse { +} export interface ViewerSetBackgroundColorParams { - color: ViewerSetBackgroundColorParamsColor; + color: ViewerSetBackgroundColorParamsColor; } export interface ViewerSetBackgroundColorParamsColor { - b: number; - g: number; - r: number; + b: number; + g: number; + r: number; } -export interface ViewerSetBackgroundColorResponse {} +export interface ViewerSetBackgroundColorResponse { +} export interface ViewerRulerParams { - points: Array; + points: Array; } export interface ViewerRulerResponse { - distance: number; - point1: number[]; - point2?: number[]; + distance: number; + point1: number[]; + point2?: number[]; } -export interface ViewerResetVisualizationParams {} +export interface ViewerResetVisualizationParams { +} -export interface ViewerResetVisualizationResponse {} +export interface ViewerResetVisualizationResponse { +} -export interface ViewerResetRulerParams {} +export interface ViewerResetRulerParams { +} -export interface ViewerResetRulerResponse {} +export interface ViewerResetRulerResponse { +} -export interface ViewerResetCameraParams {} +export interface ViewerResetCameraParams { +} -export interface ViewerResetCameraResponse {} +export interface ViewerResetCameraResponse { +} -export interface ViewerRenderParams {} +export interface ViewerRenderParams { +} -export interface ViewerRenderResponse {} +export interface ViewerRenderResponse { +} export interface ViewerPreviewPointsParams { - closed?: boolean; - points: Point[]; - style: Style; + closed?: boolean; + points: Point[]; + style: Style; } export interface Point { - x: number; - y: number; - z: number; + x: number; + y: number; + z: number; } export type Style = "points" | "curve" | "surface"; -export interface ViewerPreviewPointsResponse {} +export interface ViewerPreviewPointsResponse { +} export interface ViewerPickedIDSParams { - ids: string[]; - x: number; - y: number; + ids: string[]; + x: number; + y: number; } export interface ViewerPickedIDSResponse { - array_ids: string[]; - viewer_id?: number; + array_ids: string[]; + viewer_id?: number; } export interface ViewerPickColormapParams { - x: number; - y: number; - [property: string]: any; + x: number; + y: number; + [property: string]: any; } export interface ViewerPickColormapResponse { - block_ids?: number[]; - data_id?: string; + block_ids?: number[]; + data_id?: string; } export interface ViewerHighlightParams { - field_type: PickedFieldType; - ids: string[]; - x: number; - y: number; + field_type: PickedFieldType; + ids: string[]; + x: number; + y: number; } export type PickedFieldType = "CELL" | "POINT"; export interface ViewerHighlightResponse { - attributes?: { [key: string]: number[] | number }; - field_type?: PickedFieldType; - geode_id?: string; - id?: string; - picked_id?: number; + attributes?: { [key: string]: number[] | number }; + field_type?: PickedFieldType; + geode_id?: string; + id?: string; + picked_id?: number; } export interface ViewerGridScaleParams { - visibility: boolean; + visibility: boolean; } -export interface ViewerGridScaleResponse {} +export interface ViewerGridScaleResponse { +} export interface ViewerGetPointPositionParams { - x: number; - y: number; + x: number; + y: number; } export interface ViewerGetPointPositionResponse { - x: number; - y: number; - z: number; + x: number; + y: number; + z: number; } export interface ViewerExplodeParams { - explode_factor: number; - ids: string[]; + explode_factor: number; + ids: string[]; } -export interface ViewerExplodeResponse {} +export interface ViewerExplodeResponse { +} export interface ViewerClippingPlanesParams { - ids: string[]; - planes: Plane[]; + ids: string[]; + planes: Plane[]; } export interface Plane { - normal: number[]; - origin: number[]; + normal: number[]; + origin: number[]; } -export interface ViewerClippingPlanesResponse {} +export interface ViewerClippingPlanesResponse { +} export interface ViewerAxesParams { - visibility: boolean; + visibility: boolean; } -export interface ViewerAxesResponse {} +export interface ViewerAxesResponse { +} export interface ErrorResponse { - code: number; - description: string; - name: string; + code: number; + description: string; + name: string; } // `__params` and `__response` only exist at type level, to infer request/response types from a schema. @@ -1301,375 +1394,213 @@ export type TypedSchema = { export interface Schemas { readonly opengeodeweb_viewer: { readonly generic: { - readonly register: (typeof json)["opengeodeweb_viewer"]["generic"]["register"] & - TypedSchema; - readonly deregister: (typeof json)["opengeodeweb_viewer"]["generic"]["deregister"] & - TypedSchema; + readonly register: (typeof json)["opengeodeweb_viewer"]["generic"]["register"] & TypedSchema; + readonly deregister: (typeof json)["opengeodeweb_viewer"]["generic"]["deregister"] & TypedSchema; }; readonly mesh: { readonly cells: { readonly attribute: { readonly cell: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["attribute"]["cell"]["attribute"] & - TypedSchema< - MeshCellsAttributeCellAttributeParams, - MeshCellsAttributeCellAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["attribute"]["cell"]["attribute"] & TypedSchema; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - MeshCellsAttributeVertexAttributeParams, - MeshCellsAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["visibility"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["color"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["visibility"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["cells"]["color"] & TypedSchema; }; readonly edges: { readonly attribute: { readonly edge: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["attribute"]["edge"]["attribute"] & - TypedSchema< - MeshEdgesAttributeEdgeAttributeParams, - MeshEdgesAttributeEdgeAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["attribute"]["edge"]["attribute"] & TypedSchema; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - MeshEdgesAttributeVertexAttributeParams, - MeshEdgesAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; - readonly width: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["width"] & - TypedSchema; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["visibility"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["color"] & - TypedSchema; + readonly width: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["width"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["visibility"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["edges"]["color"] & TypedSchema; }; readonly points: { readonly attribute: { readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - MeshPointsAttributeVertexAttributeParams, - MeshPointsAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["visibility"] & - TypedSchema; - readonly size: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["size"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["color"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["visibility"] & TypedSchema; + readonly size: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["size"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["points"]["color"] & TypedSchema; }; readonly polygons: { readonly attribute: { readonly polygon: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["attribute"]["polygon"]["attribute"] & - TypedSchema< - MeshPolygonsAttributePolygonAttributeParams, - MeshPolygonsAttributePolygonAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["attribute"]["polygon"]["attribute"] & TypedSchema; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - MeshPolygonsAttributeVertexAttributeParams, - MeshPolygonsAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["visibility"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["color"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["visibility"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["polygons"]["color"] & TypedSchema; }; readonly polyhedra: { readonly attribute: { readonly polyhedron: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["attribute"]["polyhedron"]["attribute"] & - TypedSchema< - MeshPolyhedraAttributePolyhedronAttributeParams, - MeshPolyhedraAttributePolyhedronAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["attribute"]["polyhedron"]["attribute"] & TypedSchema; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - MeshPolyhedraAttributeVertexAttributeParams, - MeshPolyhedraAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["visibility"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["color"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["visibility"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["polyhedra"]["color"] & TypedSchema; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["visibility"] & - TypedSchema; - readonly register: (typeof json)["opengeodeweb_viewer"]["mesh"]["register"] & - TypedSchema; - readonly highlight: (typeof json)["opengeodeweb_viewer"]["mesh"]["highlight"] & - TypedSchema; - readonly deregister: (typeof json)["opengeodeweb_viewer"]["mesh"]["deregister"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["color"] & - TypedSchema; - readonly apply_textures: (typeof json)["opengeodeweb_viewer"]["mesh"]["apply_textures"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["mesh"]["visibility"] & TypedSchema; + readonly register: (typeof json)["opengeodeweb_viewer"]["mesh"]["register"] & TypedSchema; + readonly highlight: (typeof json)["opengeodeweb_viewer"]["mesh"]["highlight"] & TypedSchema; + readonly deregister: (typeof json)["opengeodeweb_viewer"]["mesh"]["deregister"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["mesh"]["color"] & TypedSchema; + readonly apply_textures: (typeof json)["opengeodeweb_viewer"]["mesh"]["apply_textures"] & TypedSchema; }; readonly model: { readonly blocks: { readonly attribute: { readonly polyhedron: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["attribute"]["polyhedron"]["attribute"] & - TypedSchema< - ModelBlocksAttributePolyhedronAttributeParams, - ModelBlocksAttributePolyhedronAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["attribute"]["polyhedron"]["attribute"] & TypedSchema; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - ModelBlocksAttributeVertexAttributeParams, - ModelBlocksAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; readonly edges: { readonly attribute: { readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["edges"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - ModelBlocksEdgesAttributeVertexAttributeParams, - ModelBlocksEdgesAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["edges"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; - readonly width: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["edges"]["width"] & - TypedSchema; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["edges"]["visibility"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["edges"]["color"] & - TypedSchema; + readonly width: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["edges"]["width"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["edges"]["visibility"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["edges"]["color"] & TypedSchema; }; readonly points: { readonly attribute: { readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - ModelBlocksPointsAttributeVertexAttributeParams, - ModelBlocksPointsAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["visibility"] & - TypedSchema; - readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["size"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["color"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["visibility"] & TypedSchema; + readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["size"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["points"]["color"] & TypedSchema; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["visibility"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["color"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["visibility"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["blocks"]["color"] & TypedSchema; }; readonly corners: { readonly attribute: { readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["corners"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - ModelCornersAttributeVertexAttributeParams, - ModelCornersAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["corners"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["corners"]["visibility"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["corners"]["color"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["corners"]["visibility"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["corners"]["color"] & TypedSchema; }; readonly edges: { - readonly width: (typeof json)["opengeodeweb_viewer"]["model"]["edges"]["width"] & - TypedSchema; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["edges"]["visibility"] & - TypedSchema; + readonly width: (typeof json)["opengeodeweb_viewer"]["model"]["edges"]["width"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["edges"]["visibility"] & TypedSchema; }; readonly lines: { readonly attribute: { readonly edge: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["attribute"]["edge"]["attribute"] & - TypedSchema< - ModelLinesAttributeEdgeAttributeParams, - ModelLinesAttributeEdgeAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["attribute"]["edge"]["attribute"] & TypedSchema; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - ModelLinesAttributeVertexAttributeParams, - ModelLinesAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; readonly points: { readonly attribute: { readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - ModelLinesPointsAttributeVertexAttributeParams, - ModelLinesPointsAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["visibility"] & - TypedSchema; - readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["size"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["color"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["visibility"] & TypedSchema; + readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["size"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["points"]["color"] & TypedSchema; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["visibility"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["color"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["visibility"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["lines"]["color"] & TypedSchema; }; readonly points: { - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["points"]["visibility"] & - TypedSchema; - readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["points"]["size"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["points"]["visibility"] & TypedSchema; + readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["points"]["size"] & TypedSchema; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["visibility"] & - TypedSchema; - readonly register: (typeof json)["opengeodeweb_viewer"]["model"]["register"] & - TypedSchema; - readonly highlight: (typeof json)["opengeodeweb_viewer"]["model"]["highlight"] & - TypedSchema; - readonly get_blocks_bounds: (typeof json)["opengeodeweb_viewer"]["model"]["get_blocks_bounds"] & - TypedSchema; - readonly deregister: (typeof json)["opengeodeweb_viewer"]["model"]["deregister"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["visibility"] & TypedSchema; + readonly register: (typeof json)["opengeodeweb_viewer"]["model"]["register"] & TypedSchema; + readonly highlight: (typeof json)["opengeodeweb_viewer"]["model"]["highlight"] & TypedSchema; + readonly get_blocks_bounds: (typeof json)["opengeodeweb_viewer"]["model"]["get_blocks_bounds"] & TypedSchema; + readonly deregister: (typeof json)["opengeodeweb_viewer"]["model"]["deregister"] & TypedSchema; readonly surfaces: { readonly attribute: { readonly polygon: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["attribute"]["polygon"]["attribute"] & - TypedSchema< - ModelSurfacesAttributePolygonAttributeParams, - ModelSurfacesAttributePolygonAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["attribute"]["polygon"]["attribute"] & TypedSchema; }; readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - ModelSurfacesAttributeVertexAttributeParams, - ModelSurfacesAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; readonly edges: { readonly attribute: { readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["edges"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - ModelSurfacesEdgesAttributeVertexAttributeParams, - ModelSurfacesEdgesAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["edges"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; - readonly width: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["edges"]["width"] & - TypedSchema; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["edges"]["visibility"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["edges"]["color"] & - TypedSchema; + readonly width: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["edges"]["width"] & TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["edges"]["visibility"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["edges"]["color"] & TypedSchema; }; readonly points: { readonly attribute: { readonly vertex: { - readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["attribute"]["vertex"]["attribute"] & - TypedSchema< - ModelSurfacesPointsAttributeVertexAttributeParams, - ModelSurfacesPointsAttributeVertexAttributeResponse - >; + readonly attribute: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["attribute"]["vertex"]["attribute"] & TypedSchema; }; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["visibility"] & - TypedSchema; - readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["size"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["color"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["visibility"] & TypedSchema; + readonly size: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["size"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["points"]["color"] & TypedSchema; }; - readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["visibility"] & - TypedSchema; - readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["color"] & - TypedSchema; - readonly apply_textures: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["apply_textures"] & - TypedSchema; + readonly visibility: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["visibility"] & TypedSchema; + readonly color: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["color"] & TypedSchema; + readonly apply_textures: (typeof json)["opengeodeweb_viewer"]["model"]["surfaces"]["apply_textures"] & TypedSchema; }; }; - readonly release_database: (typeof json)["opengeodeweb_viewer"]["release_database"] & - TypedSchema; - readonly kill: (typeof json)["opengeodeweb_viewer"]["kill"] & - TypedSchema; - readonly import_project: (typeof json)["opengeodeweb_viewer"]["import_project"] & - TypedSchema; + readonly release_database: (typeof json)["opengeodeweb_viewer"]["release_database"] & TypedSchema; + readonly kill: (typeof json)["opengeodeweb_viewer"]["kill"] & TypedSchema; + readonly import_project: (typeof json)["opengeodeweb_viewer"]["import_project"] & TypedSchema; readonly viewer: { - readonly update_data: (typeof json)["opengeodeweb_viewer"]["viewer"]["update_data"] & - TypedSchema; - readonly update_camera: (typeof json)["opengeodeweb_viewer"]["viewer"]["update_camera"] & - TypedSchema; - readonly threshold: (typeof json)["opengeodeweb_viewer"]["viewer"]["threshold"] & - TypedSchema; - readonly take_screenshot: (typeof json)["opengeodeweb_viewer"]["viewer"]["take_screenshot"] & - TypedSchema; - readonly slice: (typeof json)["opengeodeweb_viewer"]["viewer"]["slice"] & - TypedSchema; - readonly shrink: (typeof json)["opengeodeweb_viewer"]["viewer"]["shrink"] & - TypedSchema; - readonly set_z_scaling: (typeof json)["opengeodeweb_viewer"]["viewer"]["set_z_scaling"] & - TypedSchema; - readonly set_background_color: (typeof json)["opengeodeweb_viewer"]["viewer"]["set_background_color"] & - TypedSchema; - readonly ruler: (typeof json)["opengeodeweb_viewer"]["viewer"]["ruler"] & - TypedSchema; - readonly reset_visualization: (typeof json)["opengeodeweb_viewer"]["viewer"]["reset_visualization"] & - TypedSchema; - readonly reset_ruler: (typeof json)["opengeodeweb_viewer"]["viewer"]["reset_ruler"] & - TypedSchema; - readonly reset_camera: (typeof json)["opengeodeweb_viewer"]["viewer"]["reset_camera"] & - TypedSchema; - readonly render: (typeof json)["opengeodeweb_viewer"]["viewer"]["render"] & - TypedSchema; - readonly preview_points: (typeof json)["opengeodeweb_viewer"]["viewer"]["preview_points"] & - TypedSchema; - readonly picked_ids: (typeof json)["opengeodeweb_viewer"]["viewer"]["picked_ids"] & - TypedSchema; - readonly pick_colormap: (typeof json)["opengeodeweb_viewer"]["viewer"]["pick_colormap"] & - TypedSchema; - readonly highlight: (typeof json)["opengeodeweb_viewer"]["viewer"]["highlight"] & - TypedSchema; - readonly grid_scale: (typeof json)["opengeodeweb_viewer"]["viewer"]["grid_scale"] & - TypedSchema; - readonly get_point_position: (typeof json)["opengeodeweb_viewer"]["viewer"]["get_point_position"] & - TypedSchema; - readonly explode: (typeof json)["opengeodeweb_viewer"]["viewer"]["explode"] & - TypedSchema; - readonly clipping_planes: (typeof json)["opengeodeweb_viewer"]["viewer"]["clipping_planes"] & - TypedSchema; - readonly axes: (typeof json)["opengeodeweb_viewer"]["viewer"]["axes"] & - TypedSchema; + readonly update_data: (typeof json)["opengeodeweb_viewer"]["viewer"]["update_data"] & TypedSchema; + readonly update_camera: (typeof json)["opengeodeweb_viewer"]["viewer"]["update_camera"] & TypedSchema; + readonly threshold: (typeof json)["opengeodeweb_viewer"]["viewer"]["threshold"] & TypedSchema; + readonly take_screenshot: (typeof json)["opengeodeweb_viewer"]["viewer"]["take_screenshot"] & TypedSchema; + readonly slice: (typeof json)["opengeodeweb_viewer"]["viewer"]["slice"] & TypedSchema; + readonly shrink: (typeof json)["opengeodeweb_viewer"]["viewer"]["shrink"] & TypedSchema; + readonly set_z_scaling: (typeof json)["opengeodeweb_viewer"]["viewer"]["set_z_scaling"] & TypedSchema; + readonly set_background_color: (typeof json)["opengeodeweb_viewer"]["viewer"]["set_background_color"] & TypedSchema; + readonly ruler: (typeof json)["opengeodeweb_viewer"]["viewer"]["ruler"] & TypedSchema; + readonly reset_visualization: (typeof json)["opengeodeweb_viewer"]["viewer"]["reset_visualization"] & TypedSchema; + readonly reset_ruler: (typeof json)["opengeodeweb_viewer"]["viewer"]["reset_ruler"] & TypedSchema; + readonly reset_camera: (typeof json)["opengeodeweb_viewer"]["viewer"]["reset_camera"] & TypedSchema; + readonly render: (typeof json)["opengeodeweb_viewer"]["viewer"]["render"] & TypedSchema; + readonly preview_points: (typeof json)["opengeodeweb_viewer"]["viewer"]["preview_points"] & TypedSchema; + readonly picked_ids: (typeof json)["opengeodeweb_viewer"]["viewer"]["picked_ids"] & TypedSchema; + readonly pick_colormap: (typeof json)["opengeodeweb_viewer"]["viewer"]["pick_colormap"] & TypedSchema; + readonly highlight: (typeof json)["opengeodeweb_viewer"]["viewer"]["highlight"] & TypedSchema; + readonly grid_scale: (typeof json)["opengeodeweb_viewer"]["viewer"]["grid_scale"] & TypedSchema; + readonly get_point_position: (typeof json)["opengeodeweb_viewer"]["viewer"]["get_point_position"] & TypedSchema; + readonly explode: (typeof json)["opengeodeweb_viewer"]["viewer"]["explode"] & TypedSchema; + readonly clipping_planes: (typeof json)["opengeodeweb_viewer"]["viewer"]["clipping_planes"] & TypedSchema; + readonly axes: (typeof json)["opengeodeweb_viewer"]["viewer"]["axes"] & TypedSchema; }; }; } diff --git a/requirements.txt b/requirements.txt index cf63d0c6..8d21d552 100644 --- a/requirements.txt +++ b/requirements.txt @@ -63,4 +63,3 @@ wslink==2.6.0 yarl==1.* # via aiohttp -opengeodeweb-microservice==1.*,>=1.3.2