├── .gitignore
├── CONTRIBUTORS
├── LICENSE
├── README.md
├── VERSION
├── __init__.py
├── controller
├── __init__.py
├── controller.py
├── controller_detector.py
├── controller_filter.py
├── controller_options.py
├── controller_scene.py
└── controller_stream.py
├── core
├── __init__.py
├── color.py
├── hdr_graphics_view_base.py
├── hdr_image.py
├── highlighter_base.py
├── logger.py
├── messages.py
├── plot_2d.py
├── plot_2d_xy.py
├── plot_figure_base.py
├── plot_rgb.py
├── plugin.py
├── point.py
├── pyside2_uic.py
└── vector.py
├── detector
├── __init__.py
└── detector.py
├── emca.py
├── filter
├── __init__.py
├── filter.py
└── filter_settings.py
├── model
├── __init__.py
├── camera_data.py
├── contribution_data.py
├── intersection_data.py
├── mesh_data.py
├── model.py
├── options_data.py
├── path_data.py
├── pixel_data.py
├── render_info.py
└── user_data.py
├── plugins
├── __init__.py
├── plugin_intersection_data
│ ├── __init__.py
│ ├── intersection_data_plot_2d.py
│ ├── intersection_data_plot_3d.py
│ ├── intersection_data_plot_rgb.py
│ ├── plot_list_item.py
│ ├── plugin_intersection_data_plots.py
│ └── ui
│ │ └── plugin_plots.ui
├── plugin_spherical_view
│ ├── __init__.py
│ ├── plugin_spherical_view.py
│ ├── spherical_graphics_view.py
│ ├── ui
│ │ ├── spherical_view.ui
│ │ └── spherical_view_image.ui
│ └── view_spherical_view_image.py
├── plugins_handler.py
└── plugins_view_container.py
├── renderer
├── __init__.py
├── camera.py
├── mesh.py
├── path.py
├── renderer.py
├── rubberband.py
├── scene_renderer.py
├── shape.py
└── sphere.py
├── requirements.txt
├── resources
├── breeze_resources.py
├── dark.qss
├── dark
│ ├── branch_closed-on.svg
│ ├── branch_closed.svg
│ ├── branch_open-on.svg
│ ├── branch_open.svg
│ ├── checkbox_checked.svg
│ ├── checkbox_checked_disabled.svg
│ ├── checkbox_indeterminate.svg
│ ├── checkbox_indeterminate_disabled.svg
│ ├── checkbox_unchecked.svg
│ ├── checkbox_unchecked_disabled.svg
│ ├── close-hover.svg
│ ├── close-pressed.svg
│ ├── close.svg
│ ├── down_arrow-hover.svg
│ ├── down_arrow.svg
│ ├── down_arrow_disabled.svg
│ ├── hmovetoolbar.svg
│ ├── hsepartoolbar.svg
│ ├── left_arrow.svg
│ ├── left_arrow_disabled.svg
│ ├── radio_checked.svg
│ ├── radio_checked_disabled.svg
│ ├── radio_unchecked.svg
│ ├── radio_unchecked_disabled.svg
│ ├── right_arrow.svg
│ ├── right_arrow_disabled.svg
│ ├── sizegrip.svg
│ ├── spinup_disabled.svg
│ ├── stylesheet-branch-end-closed.svg
│ ├── stylesheet-branch-end-open.svg
│ ├── stylesheet-branch-end.svg
│ ├── stylesheet-branch-more.svg
│ ├── stylesheet-vline.svg
│ ├── transparent.svg
│ ├── undock-hover.svg
│ ├── undock.svg
│ ├── up_arrow-hover.svg
│ ├── up_arrow.svg
│ ├── up_arrow_disabled.svg
│ ├── vmovetoolbar.svg
│ └── vsepartoolbars.svg
├── emca.png
├── light.qss
├── light
│ ├── branch_closed-on.svg
│ ├── branch_closed.svg
│ ├── branch_open-on.svg
│ ├── branch_open.svg
│ ├── checkbox_checked-hover.svg
│ ├── checkbox_checked.svg
│ ├── checkbox_checked_disabled.svg
│ ├── checkbox_indeterminate-hover.svg
│ ├── checkbox_indeterminate.svg
│ ├── checkbox_indeterminate_disabled.svg
│ ├── checkbox_unchecked-hover.svg
│ ├── checkbox_unchecked_disabled.svg
│ ├── close-hover.svg
│ ├── close-pressed.svg
│ ├── close.svg
│ ├── down_arrow-hover.svg
│ ├── down_arrow.svg
│ ├── down_arrow_disabled.svg
│ ├── hmovetoolbar.svg
│ ├── hsepartoolbar.svg
│ ├── left_arrow.svg
│ ├── left_arrow_disabled.svg
│ ├── radio_checked-hover.svg
│ ├── radio_checked.svg
│ ├── radio_checked_disabled.svg
│ ├── radio_unchecked-hover.svg
│ ├── radio_unchecked_disabled.svg
│ ├── right_arrow.svg
│ ├── right_arrow_disabled.svg
│ ├── sizegrip.svg
│ ├── spinup_disabled.svg
│ ├── stylesheet-branch-end-closed.svg
│ ├── stylesheet-branch-end-open.svg
│ ├── stylesheet-branch-end.svg
│ ├── stylesheet-branch-more.svg
│ ├── stylesheet-vline.svg
│ ├── transparent.svg
│ ├── undock-hover.svg
│ ├── undock.svg
│ ├── up_arrow-hover.svg
│ ├── up_arrow.svg
│ ├── up_arrow_disabled.svg
│ ├── vmovetoolbar.svg
│ └── vsepartoolbars.svg
└── options.ini
├── server
├── CMakeLists.txt
├── LICENSE
├── README.md
├── include
│ └── emca
│ │ ├── dataapi.h
│ │ ├── datatypes.h
│ │ ├── emcaserver.h
│ │ ├── heatmapdata.h
│ │ ├── messages.h
│ │ ├── pathdata.h
│ │ ├── platform.h
│ │ ├── plugin.h
│ │ ├── renderinterface.h
│ │ ├── scenedata.h
│ │ └── stream.h
└── src
│ ├── dataapi.cpp
│ ├── emcaserver.cpp
│ ├── heatmapdata.cpp
│ └── pathdata.cpp
├── stream
├── __init__.py
├── socket_stream.py
├── socket_stream_client.py
└── stream.py
└── view
├── __init__.py
├── ui
├── about.ui
├── connect.ui
├── detector.ui
├── emca.ui
├── filter.ui
├── options.ui
├── pixel_data.ui
├── render_image.ui
├── render_info.ui
├── render_scene.ui
└── render_scene_options.ui
├── view_main
├── __init__.py
├── main_view.py
├── pixel_icon.py
├── popup_messages.py
├── view_about.py
├── view_connect_settings.py
├── view_detector_settings.py
├── view_emca.py
├── view_filter_settings.py
├── view_options_settings.py
└── view_render_settings.py
├── view_pixel_data
├── __init__.py
└── view_pixel_data.py
├── view_render_image
├── __init__.py
├── hdr_graphics_view.py
└── view_render_image.py
├── view_render_scene
├── __init__.py
├── view_render_scene.py
└── view_render_scene_options.py
└── view_sample_contribution
├── __init__.py
├── view_sample_contribution_plot.py
├── view_sample_depth_plot.py
└── view_sample_lum_plot.py
/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__
2 | *.pyc
3 | /resources/options.ini
4 | emca_debug.log
5 | /server/build
6 | CMakeLists.txt.user
7 |
--------------------------------------------------------------------------------
/CONTRIBUTORS:
--------------------------------------------------------------------------------
1 | Christoph Kreisl
2 | Lukas Ruppert
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Christoph Kreisl
4 | Copyright (c) 2021 Lukas Ruppert
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/VERSION:
--------------------------------------------------------------------------------
1 | 1.0.0
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cgtuebingen/emca/560975bddc1b6176fe25029acb13d7806c8ab35b/__init__.py
--------------------------------------------------------------------------------
/controller/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cgtuebingen/emca/560975bddc1b6176fe25029acb13d7806c8ab35b/controller/__init__.py
--------------------------------------------------------------------------------
/controller/controller_detector.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from core.messages import StateMsg
27 | import logging
28 | import typing
29 |
30 | from model.model import Model
31 | from view.view_main.main_view import MainView
32 |
33 | from typing import TYPE_CHECKING
34 | if TYPE_CHECKING:
35 | from controller.controller import Controller
36 | else:
37 | from typing import Any as Controller
38 |
39 | class ControllerDetector(object):
40 |
41 | """
42 | ControllerDetector
43 | Handles the core logic of the detector which is used to determine high variance sample contributions.
44 | Two methods are currently used.
45 | 1.) based on standard deviation
46 | 2.) ESD by Rosner
47 | """
48 |
49 | def __init__(self, parent : Controller, model : Model, view : MainView):
50 | self._controller_main = parent
51 | self._model = model
52 | self._view = view
53 | # init detector view with values from detector class
54 | self._view.view_detector.init_values(model.detector)
55 |
56 | def handle_state_msg(self, tpl : typing.Tuple[StateMsg, typing.Any]):
57 | """
58 | Handle current state, messages mostly received from thread,
59 | which listens on the socket pipeline for incoming messages
60 | """
61 | msg = tpl[0]
62 | if msg is StateMsg.DATA_PIXEL:
63 | # check if detector is enabled and run outlier detection
64 | if self._model.detector.is_active:
65 | self.run_detector()
66 |
67 | def update_and_run_detector(self, m, alpha, k, pre_filter, is_default, is_active):
68 | """
69 | Saves all user changes of the detector
70 | :param m:
71 | :param alpha:
72 | :param k:
73 | :param pre_filter:
74 | :param is_default:
75 | :param is_active:
76 | :return:
77 | """
78 | self._model.detector.update_values(m, alpha, k, pre_filter, is_default, is_active)
79 | # run detector if sample contribution data is available
80 | if self._model.final_estimate_data.data_loaded:
81 | self.run_detector()
82 | else:
83 | self._view.view_popup.error_no_final_estimate_data("")
84 |
85 | def run_detector(self):
86 | """
87 | Only runs the detector if the checkbox for the detector is active,
88 | moreover the final estimate data is needed in order to detector outliers
89 | :return:
90 | """
91 | detector = self._model.detector
92 | if detector.is_active:
93 | data = self._model.final_estimate_data.mean
94 | path_outliers_indices = detector.run_outlier_detection(data=data)
95 | if len(path_outliers_indices) > 0:
96 | self._controller_main.update_path(path_outliers_indices, False)
97 | else:
98 | self._view.view_popup.error_outlier_detector_no_outliers_detected("")
99 | else:
100 | self._view.view_popup.error_detector_not_enabled("")
101 |
102 |
--------------------------------------------------------------------------------
/controller/controller_scene.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | import typing
27 | from PySide2.QtCore import Slot
28 | from core.messages import StateMsg
29 | from model.model import Model
30 | from view.view_main.main_view import MainView
31 |
32 | from typing import TYPE_CHECKING
33 | if TYPE_CHECKING:
34 | from controller.controller import Controller
35 | else:
36 | from typing import Any as Controller
37 |
38 | class ControllerRenderScene(object):
39 |
40 | """
41 | ControllerRenderScene
42 | Handles the interaction and logic with the RenderScene and RenderSceneOptions View.
43 | """
44 |
45 | def __init__(self, parent : Controller, model : Model, view : MainView):
46 | self._controller_main = parent
47 | self._model = model
48 | self._view = view
49 |
50 | def handle_state_msg(self, tpl : typing.Tuple[StateMsg, typing.Any]):
51 | """
52 | Handle current state, messages mostly received from thread,
53 | which listens on the socket pipeline for incoming messages
54 | """
55 | msg = tpl[0]
56 | if msg is StateMsg.DATA_INFO:
57 | self._controller_main.stream.request_camera_data()
58 | # automatically request scene data once render info is available
59 | if self._model.options_data.auto_scene_load:
60 | self._controller_main.stream.request_scene_data()
61 | elif msg is StateMsg.DATA_CAMERA:
62 | self._view.view_render_scene.scene_renderer.load_camera(tpl[1])
63 | elif msg is StateMsg.DATA_MESH:
64 | self._view.view_render_scene.scene_renderer.load_mesh(tpl[1])
65 | elif msg is StateMsg.DATA_SCENE_INFO:
66 | self._view.view_render_scene.scene_renderer.process_scene_info(tpl[1])
67 |
68 | @Slot(bool)
69 | def reset_camera_position(self, clicked : bool):
70 | """
71 | Reset the camera position to its default origin position
72 | """
73 | self._view.view_render_scene.scene_renderer.reset_camera_position()
74 |
75 | def reset_path_options(self):
76 | self._view.view_render_scene.scene_renderer.reset_path_options()
77 |
78 | def reset_scene_options(self):
79 | self._view.view_render_scene.scene_renderer.reset_scene_options()
80 |
81 | def reset_heatmap_options(self):
82 | self._view.view_render_scene.scene_renderer.reset_heatmap_options()
83 |
84 | def update_path_options(self, path_options : typing.Dict[str, typing.Any]):
85 | self._view.view_render_scene.scene_renderer.path_options = path_options
86 | self._view.view_render_scene_options.load_path_options(path_options)
87 |
88 | def update_scene_options(self, scene_options : typing.Dict[str, typing.Any]):
89 | self._view.view_render_scene.scene_renderer.scene_options = scene_options
90 | self._view.view_render_scene_options.load_scene_options(scene_options)
91 |
92 | def update_heatmap_options(self, heatmap_options : typing.Dict[str, typing.Any]):
93 | self._view.view_render_scene.scene_renderer.heatmap_options = heatmap_options
94 | self._view.view_render_scene_options.load_heatmap_options(heatmap_options)
95 |
--------------------------------------------------------------------------------
/core/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cgtuebingen/emca/560975bddc1b6176fe25029acb13d7806c8ab35b/core/__init__.py
--------------------------------------------------------------------------------
/core/highlighter_base.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from matplotlib.figure import Figure
27 | from matplotlib.axes import Axes
28 | from matplotlib.widgets import RectangleSelector
29 | import numpy as np
30 | import logging
31 |
32 |
33 | rectprops = dict(
34 | facecolor='white',
35 | edgecolor='white',
36 | alpha=0.2,
37 | fill=True)
38 |
39 |
40 | class HighlighterBase(object):
41 |
42 | def __init__(self, figure : Figure, axes : Axes, callback):
43 | self.fig = figure
44 | self.axes = axes
45 | self.canvas = self.fig.canvas
46 |
47 | self._cid_toggle = self.fig.canvas.mpl_connect('key_press_event', self.key_press_event)
48 | self._cid_release = self.fig.canvas.mpl_connect('key_release_event', self.key_release_event)
49 | self._cid_pick = self.fig.canvas.mpl_connect('pick_event', self.pick_event)
50 |
51 | self._rs = []
52 | self._active = False
53 | self._hold_shift = False
54 | self.callback_send_update_path = callback
55 |
56 | def add_rectangle_selector(self, axes : Axes, select_func):
57 | rs = RectangleSelector(axes, select_func, useblit=True, rectprops=rectprops)
58 | self._rs.append(rs)
59 |
60 | def clear_rectangle_selectors(self):
61 | self._rs.clear()
62 |
63 | def delete_highlighter(self):
64 | del self.highlighters
65 | self.highlighters = None
66 |
67 | def pick_event(self, event):
68 | if self.callback_send_update_path is None:
69 | return
70 | ind = event.ind
71 | if self._hold_shift:
72 | self.callback_send_update_path(np.array([ind[0]]), True)
73 | else:
74 | self.callback_send_update_path(np.array([ind[0]]), False)
75 |
76 | def key_press_event(self, event):
77 | if event.key in ['R', 'r']:
78 | logging.info("Pressed key R")
79 | self._active = not self._active
80 | self.enable_rectangle_selector(self._active)
81 | self.enable_pick_event_selector(not self._active)
82 | if event.key == 'shift':
83 | logging.info("Shift press")
84 | self._hold_shift = True
85 |
86 | def key_release_event(self, event):
87 | if event.key == 'shift':
88 | logging.info("Shift release")
89 | self._hold_shift = False
90 |
91 | def enable_rectangle_selector(self, enable : bool):
92 | for rs in self._rs:
93 | rs.set_active(enable)
94 |
95 | def enable_pick_event_selector(self, enable : bool):
96 | if enable:
97 | logging.info("connect pick event")
98 | self._cid_pick = self.fig.canvas.mpl_connect('pick_event', self.pick_event)
99 | else:
100 | logging.info("disconnect pick event")
101 | self.fig.canvas.mpl_disconnect(self._cid_pick)
102 |
103 | def enable_multi_selection(self, enabled : bool):
104 | if enabled:
105 | self._cid_toggle = self.fig.canvas.mpl_connect('key_press_event', self.key_press_event)
106 | self._cid_release = self.fig.canvas.mpl_connect('key_release_event', self.key_release_event)
107 | else:
108 | self.fig.canvas.mpl_disconnect(self._cid_toggle)
109 | self.fig.canvas.mpl_disconnect(self._cid_release)
110 |
111 | def overwrite_pick_event(self, func_callback):
112 | self._cid_pick = self.fig.canvas.mpl_connect('pick_event', func_callback)
113 |
114 | def inside(self, event1, event2, x, y):
115 | x0, x1 = sorted([event1.xdata, event2.xdata])
116 | y0, y1 = sorted([event1.ydata, event2.ydata])
117 | return (x > x0) & (x < x1) & (y > y0) & (y < y1)
118 |
--------------------------------------------------------------------------------
/core/logger.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | import logging
27 |
28 |
29 | FORMATTER = '%(asctime)s - %(name)s - %(levelname)s - [%(module)s] - %(message)s'
30 | LOGNAME = 'emca_debug.log'
31 |
32 |
33 | def InitLogSystem():
34 | """
35 | Init the log system
36 | :return:
37 | """
38 | # set up logger system
39 | logger = logging.getLogger()
40 | logger.setLevel(logging.INFO)
41 | fh = logging.FileHandler(LOGNAME, mode='w')
42 | fh.setLevel(logging.INFO)
43 | ch = logging.StreamHandler()
44 | ch.setLevel(logging.INFO)
45 | formatter = logging.Formatter(FORMATTER)
46 | fh.setFormatter(formatter)
47 | ch.setFormatter(formatter)
48 | logger.addHandler(fh)
49 | logger.addHandler(ch)
50 |
--------------------------------------------------------------------------------
/core/messages.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from enum import Enum
27 |
28 | class StateMsg(Enum):
29 | DISCONNECT = 0
30 | CONNECT = 1
31 | SERVER_ERROR = 2
32 | DATA_IMAGE = 3
33 | DATA_PIXEL = 4
34 | DATA_CAMERA = 5
35 | DATA_SCENE_INFO = 6
36 | DATA_MESH = 7
37 | DATA_INFO = 8
38 | DATA_NOT_VALID = 9
39 | DATA_3D_PATHS = 10
40 | DATA_DETECTOR = 11
41 | UPDATE_PLUGIN = 12
42 | SUPPORTED_PLUGINS = 13
43 | QUIT = 14
44 |
45 |
46 | class ServerMsg(Enum):
47 | # connection management (0x000x)
48 | EMCA_HELLO = 0x0001
49 | EMCA_SUPPORTED_PLUGINS = 0x0002
50 | EMCA_DISCONNECT = 0x000E
51 | EMCA_QUIT = 0x000F
52 |
53 | # requests from the client (0x001x)
54 | EMCA_REQUEST_RENDER_INFO = 0x0011
55 | EMCA_REQUEST_RENDER_IMAGE = 0x0012
56 | EMCA_REQUEST_RENDER_PIXEL = 0x0013
57 | EMCA_REQUEST_CAMERA = 0x0014
58 | EMCA_REQUEST_SCENE = 0x0015
59 |
60 | # responses to the client (0x002x)
61 | EMCA_RESPONSE_RENDER_INFO = 0x0021
62 | EMCA_RESPONSE_RENDER_IMAGE = 0x0022
63 | EMCA_RESPONSE_RENDER_PIXEL = 0x0023
64 | EMCA_RESPONSE_CAMERA = 0x0024
65 | EMCA_RESPONSE_SCENE = 0x0025
66 |
67 | @staticmethod
68 | def get_server_msg(flag):
69 | return {
70 | # connection management (0x000x)
71 | 0x0001: ServerMsg.EMCA_HELLO,
72 | 0x0002: ServerMsg.EMCA_SUPPORTED_PLUGINS,
73 | 0x000E: ServerMsg.EMCA_DISCONNECT,
74 | 0x000F: ServerMsg.EMCA_QUIT,
75 |
76 | # requests from the client (0x001x)
77 | 0x0011: ServerMsg.EMCA_REQUEST_RENDER_INFO,
78 | 0x0012: ServerMsg.EMCA_REQUEST_RENDER_IMAGE,
79 | 0x0013: ServerMsg.EMCA_REQUEST_RENDER_PIXEL,
80 | 0x0014: ServerMsg.EMCA_REQUEST_CAMERA,
81 | 0x0015: ServerMsg.EMCA_REQUEST_SCENE,
82 |
83 | # responses to the client (0x002x)
84 | 0x0021: ServerMsg.EMCA_RESPONSE_RENDER_INFO,
85 | 0x0022: ServerMsg.EMCA_RESPONSE_RENDER_IMAGE,
86 | 0x0023: ServerMsg.EMCA_RESPONSE_RENDER_PIXEL,
87 | 0x0024: ServerMsg.EMCA_RESPONSE_CAMERA,
88 | 0x0025: ServerMsg.EMCA_RESPONSE_SCENE
89 | }.get(flag, None)
90 |
91 |
92 | class ShapeType(Enum):
93 | TriangleMesh = 0
94 | SphereMesh = 1
95 |
--------------------------------------------------------------------------------
/core/plot_2d_xy.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | import matplotlib.pyplot as plt
27 | import numpy as np
28 | from core.plot_figure_base import FigureBase
29 | from core.highlighter_base import HighlighterBase
30 |
31 |
32 | class ScatterPlot2DXY(FigureBase):
33 |
34 | def __init__(self, callback=None, title=None):
35 | figure, axes = plt.subplots(figsize=(5, 5), nrows=2, ncols=2,
36 | gridspec_kw={"width_ratios":(9, 1), "height_ratios":(1, 9), "hspace":0.05, "wspace":0.05, "left":0.1, "right":0.95, "top":0.92, "bottom":0.08},
37 | constrained_layout=True)
38 | FigureBase.__init__(self, figure, axes)
39 | self.highlighter = HighlighterBase(figure, axes, callback)
40 |
41 | self.line = None
42 | self.x = None
43 | self.hist_x = None
44 | self.hist_y = None
45 |
46 | for ax in self.axes.flatten():
47 | ax.spines['top'].set_visible(False)
48 | ax.spines['right'].set_visible(False)
49 |
50 | self.axes[0, 0].set_axis_off()
51 | self.axes[0, 0].add_artist(self.axes[0, 0].patch)
52 | self.axes[0, 0].patch.set_zorder(-1)
53 |
54 | self.axes[0, 1].set_axis_off()
55 |
56 | self.axes[1, 1].set_axis_off()
57 | self.axes[1, 1].add_artist(self.axes[1, 1].patch)
58 | self.axes[1, 1].patch.set_zorder(-1)
59 |
60 | self.axes[1, 0].xaxis.set_ticks_position('bottom')
61 | self.axes[1, 0].yaxis.set_ticks_position('left')
62 |
63 | self.axes[0, 0].set_title(title, color=self.color_title)
64 |
65 | self.plot_2d([], [], [])
66 |
67 | self.highlighter.add_rectangle_selector(self.axes[1, 0], self.select)
68 | self.highlighter.enable_rectangle_selector(False)
69 |
70 | def clear(self):
71 | if self.line is not None:
72 | self.line.remove()
73 | self.line = None
74 | if self.hist_x is not None and self.hist_y is not None:
75 | self.hist_x.remove()
76 | self.hist_y.remove()
77 | self.hist_x = None
78 | self.hist_y = None
79 |
80 | for ax in self.figure.axes:
81 | ax.relim()
82 |
83 | def plot_2d(self, x, y, z):
84 | self.clear()
85 |
86 | self.x = x
87 | self.line = self.axes[1, 0].scatter(y, z, color=self.color_dots, picker=True, pickradius=5, alpha=self.alpha_dots)
88 | _, _, self.hist_y = self.axes[0, 0].hist(y, bins=10, color=self.color_dots, orientation='vertical')
89 | _, _, self.hist_x = self.axes[1, 1].hist(z, bins=10, color=self.color_dots, orientation='horizontal')
90 |
91 | self.redraw()
92 |
93 | def set_title(self, title):
94 | self.axes[0, 0].set_title(title, color=self.color_title)
95 |
96 | self.redraw()
97 |
98 | # point selection
99 | def select(self, mousedown, mouseup):
100 | mask = self.highlighter.inside(mousedown, mouseup, self.line.get_offsets()[:,0], self.line.get_offsets()[:,1])
101 | self.highlighter.callback_send_update_path(np.int32(self.line.get_offsets()[mask,0]), self.highlighter._hold_shift)
102 |
103 | # point highlighting
104 | def highlight(self, path_indices : np.ndarray):
105 | """
106 | Highlight the given indices
107 | """
108 | mask = np.isin(self.x, path_indices)
109 | self.line.set_color(np.where(mask, 'yellow', self.color_dots))
110 |
111 | self.redraw()
112 |
113 |
--------------------------------------------------------------------------------
/core/plot_figure_base.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | import matplotlib.pyplot as plt
27 | from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
28 | from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolBar
29 | from PySide2.QtWidgets import QSizePolicy
30 | from PySide2.QtCore import Qt
31 | import numpy as np
32 | import logging
33 |
34 | plt.rcParams.update({
35 | 'ytick.color': 'white',
36 | 'xtick.color': 'white',
37 | 'axes.labelcolor': 'white',
38 | 'axes.edgecolor': 'white'
39 | })
40 |
41 |
42 | class FigureBase(FigureCanvas):
43 |
44 | def __init__(self, figure, axes):
45 | FigureCanvas.__init__(self, figure)
46 | FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
47 | FigureCanvas.updateGeometry(self)
48 | self.RGBA = '#31363b'
49 | self.plot_facecolor = '#232629'
50 | self.figure.patch.set_facecolor(self.RGBA)
51 | self.axes = axes
52 | self.setFocusPolicy(Qt.ClickFocus)
53 | self.setFocus()
54 |
55 | if isinstance(self.axes, np.ndarray):
56 | for ax in self.figure.axes:
57 | ax.set_facecolor(self.plot_facecolor)
58 | else:
59 | self.axes.set_facecolor(self.plot_facecolor)
60 |
61 | self.alpha_dots = 0.7
62 | self.color_dots = '#eff0f1'
63 | self.color_title = 'white'
64 | self.color_axes = 'white'
65 |
66 | def create_navigation_toolbar(self, parent=None):
67 | return NavigationToolBar(self, parent)
68 |
69 | def apply_theme(self, theme : str):
70 | if theme == 'light':
71 | self.RGBA = '#EFF0F1'
72 | self.plot_facecolor = '#EFF0F1'
73 | self.color_axes = 'black'
74 | self.color_title = 'black'
75 | self.color_dots = 'blue'
76 | else:
77 | self.RGBA = '#31363b'
78 | self.plot_facecolor = '#232629'
79 | self.color_axes = 'white'
80 | self.color_title = 'white'
81 | self.color_dots = '#eff0f1'
82 | self.figure.patch.set_facecolor(self.RGBA)
83 | if isinstance(self.axes, np.ndarray):
84 | for ax in self.figure.axes:
85 | ax.set_facecolor(self.plot_facecolor)
86 | ax.tick_params(axis='x', colors=self.color_axes)
87 | ax.tick_params(axis='y', colors=self.color_axes)
88 | for spine in ['left', 'right', 'bottom', 'top']:
89 | ax.spines[spine].set_color(self.color_axes)
90 | else:
91 | self.axes.set_facecolor(self.plot_facecolor)
92 | self.axes.tick_params(axis='x', colors=self.color_axes)
93 | self.axes.tick_params(axis='y', colors=self.color_axes)
94 | for spine in ['left', 'right', 'bottom', 'top']:
95 | self.axes.spines[spine].set_color(self.color_axes)
96 | self.redraw()
97 |
98 | def clear(self):
99 | if isinstance(self.axes, np.ndarray):
100 | for ax in self.figure.axes:
101 | ax.clear()
102 | else:
103 | self.axes.clear()
104 | self.redraw()
105 |
106 | def redraw(self):
107 | #logging.info("redraw requested")
108 | self.figure.canvas.draw_idle()
109 |
--------------------------------------------------------------------------------
/detector/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cgtuebingen/emca/560975bddc1b6176fe25029acb13d7806c8ab35b/detector/__init__.py
--------------------------------------------------------------------------------
/emca.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from PySide2.QtWidgets import QApplication
27 | from PySide2.QtCore import QFile, QTextStream, QCoreApplication
28 | from PySide2.QtCore import Qt
29 | from core.logger import InitLogSystem
30 | import sys
31 | import os
32 |
33 | from model.model import Model
34 | from view.view_main.main_view import MainView
35 | from controller.controller import Controller
36 | from renderer.scene_renderer import SceneRenderer
37 | import resources.breeze_resources
38 |
39 |
40 | class EMCAClient(object):
41 |
42 | """
43 | Explorer of Monte Carlo based Algorithms - Client
44 | """
45 |
46 | def __init__(self):
47 | self.controller = Controller(Model(), MainView())
48 | self.controller.init_scene_renderer(SceneRenderer())
49 |
50 | def load_theme(self, qt_app):
51 | theme = self.controller.options.get_theme()
52 | theme_files = os.path.abspath(os.path.join(os.path.dirname(__file__), 'resources', '{}.qss'.format(theme)))
53 | file = QFile(theme_files)
54 | file.open(QFile.ReadOnly | QFile.Text)
55 | text_stream = QTextStream(file)
56 | qt_app.setStyleSheet(text_stream.readAll())
57 | self.controller.options.set_theme(theme)
58 |
59 | def start(self):
60 | """
61 | Starts and opens the GUI of EMCA
62 | :return:
63 | """
64 | self.controller.display_view()
65 |
66 |
67 | if __name__ == '__main__':
68 | if sys.version_info < (3, 7):
69 | print("Using Python 3.7 or newer is highly recommended.")
70 |
71 | QCoreApplication.setAttribute(Qt.AA_ShareOpenGLContexts)
72 | InitLogSystem()
73 | app = QApplication(sys.argv)
74 | emca_client = EMCAClient()
75 | emca_client.load_theme(app)
76 | emca_client.start()
77 | sys.exit(app.exec_())
78 |
--------------------------------------------------------------------------------
/filter/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cgtuebingen/emca/560975bddc1b6176fe25029acb13d7806c8ab35b/filter/__init__.py
--------------------------------------------------------------------------------
/model/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cgtuebingen/emca/560975bddc1b6176fe25029acb13d7806c8ab35b/model/__init__.py
--------------------------------------------------------------------------------
/model/camera_data.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from core.vector import Vec3f
27 | from core.point import Point3f
28 | from stream.stream import Stream
29 | # import logging
30 |
31 |
32 | class CameraData(object):
33 |
34 | """
35 | Camera Data
36 | Holds information about the camera data
37 | Will be used by the renderer interface to initialise the camera for the 3D scene viewer
38 | """
39 |
40 | def __init__(self):
41 | self._position = Point3f(0, 0, 0)
42 | self._direction = Vec3f(1, 0, 0)
43 | self._up = Vec3f(0, 0, 1)
44 | self._near_clip = 5.0
45 | self._far_clip = 15.0
46 | self._fov = 45.0
47 |
48 | def deserialize(self, stream : Stream):
49 | """
50 | Deserializes all camera information from the socket stream
51 | :param stream: SocketStream
52 | :return:
53 | """
54 | self._position = stream.read_point3f()
55 | self._direction = stream.read_vec3f()
56 | self._up = stream.read_vec3f()
57 | self._near_clip = stream.read_float()
58 | self._far_clip = stream.read_float()
59 | self._fov = stream.read_float()
60 |
61 | # logging.info(self.to_string())
62 |
63 | @property
64 | def position(self) -> Point3f:
65 | """
66 | Returns the camera's 3D position in world space
67 | :return:
68 | """
69 | return self._position
70 |
71 | @property
72 | def direction(self) -> Vec3f:
73 | """
74 | Returns the camera viewing direction
75 | :return:
76 | """
77 | return self._direction
78 |
79 | @property
80 | def up(self) -> Vec3f:
81 | """
82 | Returns the camera up vector
83 | :return:
84 | """
85 | return self._up
86 |
87 | @property
88 | def near_clip(self) -> float:
89 | """
90 | Returns the camera near clip value
91 | :return:
92 | """
93 | return self._near_clip
94 |
95 | @property
96 | def far_clip(self) -> float:
97 | """
98 | Returns the camera far clip value
99 | :return:
100 | """
101 | return self._far_clip
102 |
103 | @property
104 | def fov(self) -> float:
105 | """
106 | Returns the camera the field of view angle
107 | :return:
108 | """
109 | return self._fov
110 |
111 | def to_string(self) -> str:
112 | """
113 | Returns all camera information within a string
114 | :return:
115 | """
116 | return 'position = {} \n' \
117 | 'direction = {} \n' \
118 | 'up = {} \n' \
119 | 'neaClip = {} \n' \
120 | 'farClip = {} \n' \
121 | 'fov = {} \n'.format(self._position.to_string(),
122 | self._direction.to_string(),
123 | self._up.to_string(),
124 | self._near_clip,
125 | self._far_clip,
126 | self._fov)
127 |
128 |
129 |
--------------------------------------------------------------------------------
/model/intersection_data.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from core.point import Point3f
27 | from core.color import Color4f
28 | from stream.stream import Stream
29 | from model.user_data import UserData
30 |
31 | import typing
32 |
33 |
34 | class IntersectionData(UserData):
35 |
36 | """
37 | IntersectionData
38 | Represents one intersection point of a traced path through the scene.
39 | Holds information about the intersection, more precisely the intersection position, the intersection index,
40 | if a next event estimation was set, if a intersection position was set and current estimate information at this point.
41 | """
42 |
43 | def __init__(self, stream : Stream):
44 | super().__init__(stream)
45 |
46 | self._depth_idx = stream.read_uint()
47 |
48 | # position
49 | self._pos = None
50 | if stream.read_bool():
51 | self._pos = stream.read_point3f()
52 |
53 | # next event estimation position
54 | self._pos_ne = None
55 | self._visible_ne = None
56 | if stream.read_bool():
57 | self._pos_ne = stream.read_point3f()
58 | self._visible_ne = stream.read_bool()
59 |
60 | # the incident radiance estimate of the entire path evaluated up to this point
61 | self._li = None
62 | if stream.read_bool():
63 | self._li = stream.read_color4f()
64 |
65 | # emission
66 | self._le = None
67 | if stream.read_bool():
68 | self._le = stream.read_color4f()
69 |
70 | @property
71 | def depth_idx(self) -> typing.Optional[int]:
72 | """
73 | Returns the current depth index (intersection index)
74 | """
75 | return self._depth_idx
76 |
77 | @property
78 | def is_ne_visible(self) -> typing.Optional[bool]:
79 | """
80 | Returns if the next estimation is occluded
81 | """
82 | return self._visible_ne
83 |
84 | @property
85 | def pos(self) -> typing.Optional[Point3f]:
86 | """
87 | Returns the intersection position
88 | """
89 | return self._pos
90 |
91 | @property
92 | def pos_ne(self) -> typing.Optional[Point3f]:
93 | """
94 | Returns the position of the next event estimation
95 | """
96 | return self._pos_ne
97 |
98 | @property
99 | def li(self) -> typing.Optional[Color4f]:
100 | """
101 | Returns the current estimate at this intersection / path position
102 | """
103 | return self._li
104 |
105 | @property
106 | def le(self) -> typing.Optional[Color4f]:
107 | """
108 | Returns the emission at this intersection / path position
109 | """
110 | return self._le
111 |
112 |
--------------------------------------------------------------------------------
/model/path_data.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from core.color import Color4f
27 | from core.point import Point3f
28 | import typing
29 | from stream.stream import Stream
30 | from model.intersection_data import IntersectionData
31 | from model.user_data import UserData
32 |
33 | class PathData(UserData):
34 |
35 | """
36 | PathData
37 | Represents one traced path with added user data
38 | """
39 |
40 | def __init__(self, stream : Stream):
41 | super().__init__(stream)
42 | self._sample_idx = stream.read_uint()
43 | self._path_depth = stream.read_uint()
44 | self._path_origin = stream.read_point3f()
45 |
46 | self._final_estimate = None
47 | if stream.read_bool():
48 | self._final_estimate = stream.read_color4f()
49 |
50 | self._dict_intersections = {}
51 | self._intersection_count = stream.read_uint()
52 | for i in range(0, self._intersection_count):
53 | intersection = IntersectionData(stream)
54 | self._dict_intersections[intersection.depth_idx] = intersection
55 |
56 | @property
57 | def final_estimate(self) -> Color4f:
58 | """
59 | Returns the Final Estimate value of this path
60 | """
61 | return self._final_estimate
62 |
63 | @property
64 | def sample_idx(self) -> int:
65 | """
66 | Returns the samples index which indicates the path index
67 | """
68 | return self._sample_idx
69 |
70 | @property
71 | def path_origin(self) -> Point3f:
72 | """
73 | Returns the path origin
74 | """
75 | return self._path_origin
76 |
77 | @property
78 | def path_depth(self) -> int:
79 | """
80 | Returns the path depth (amount of bounces and containing vertices)
81 | """
82 | return self._path_depth
83 |
84 | @property
85 | def intersections(self) -> typing.Dict[int, IntersectionData]:
86 | """
87 | Returns the a dict containing all path vertices
88 | """
89 | return self._dict_intersections
90 |
91 | @property
92 | def intersection_count(self) -> int:
93 | """
94 | Returns the amount of vertices (intersections)
95 | """
96 | return self._intersection_count
97 |
98 | def valid_depth(self) -> bool:
99 | """
100 | Checks if the path depth is valid
101 | """
102 | return self._path_depth is not None
103 |
104 | def to_string(self) -> str:
105 | return "SampleIdx = {}\n" \
106 | "PathDepth = {}\n" \
107 | "PathOrigin = {}\n" \
108 | "FinalEstimate = {}\n" \
109 | "ShowPath = {}\n" \
110 | "Intersections = {}\n" \
111 | "IntersectionCount = {}".format(self._sample_idx, self._path_depth, self._path_origin,
112 | self._final_estimate, self._dict_intersections,
113 | self._intersection_count)
114 |
--------------------------------------------------------------------------------
/model/pixel_data.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | import typing
27 | from stream.stream import Stream
28 | from model.path_data import PathData
29 | import numpy as np
30 | import logging
31 |
32 |
33 | class PixelData(object):
34 |
35 | """
36 | RenderData
37 | Represents information about one pixel.
38 | The data is computed on the server side in the pixel re-rendering step.
39 | Containing all information about all traced paths through this pixel with all user added information.
40 | """
41 |
42 | def __init__(self):
43 | # {sample_index / path_index : PathData}
44 | self._dict_paths = {} # ordered dict (since Python 3.7)
45 |
46 | def deserialize(self, stream : Stream):
47 | """
48 | Deserialize a DataView object from the socket stream
49 | """
50 | sample_count = stream.read_uint()
51 | self._dict_paths.clear()
52 | logging.info("SampleCount: {}".format(sample_count))
53 | # deserialize the amount of paths which were traced through the selected pixel
54 | for sample in range(sample_count):
55 | path_data = PathData(stream)
56 | # append deserialized path to dict
57 | self._dict_paths[path_data.sample_idx] = path_data
58 |
59 | @property
60 | def dict_paths(self) -> typing.Dict[int, PathData]:
61 | """
62 | Returns a dict containing all traced paths through the pixel
63 | """
64 | return self._dict_paths
65 |
66 | def get_indices(self) -> np.ndarray:
67 | """
68 | Returns all path indices as numpy array
69 | """
70 | return np.array(list(self._dict_paths.keys()))
71 |
72 | def to_string(self) -> str:
73 | """
74 | Returns a string with class information
75 | """
76 | return 'number of paths = {}'.format(len(self._dict_paths))
77 |
78 | def clear(self):
79 | """
80 | Clears the data
81 | """
82 | self._dict_paths.clear()
83 |
--------------------------------------------------------------------------------
/model/render_info.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from stream.stream import Stream
27 |
28 |
29 | class RenderInfo(object):
30 |
31 | """
32 | RenderInfo
33 | Holds general information about the rendered scene,
34 | such as scene name, sample count and the path where the final rendered result is saved
35 | """
36 |
37 | def __init__(self):
38 | self._renderer_name = None
39 | self._scene_name = None
40 | self._sample_count = None
41 |
42 | def deserialize(self, stream : Stream):
43 | """
44 | Deserialize a Render Info object from the socket stream
45 | :param stream: SocketStream
46 | :return:
47 | """
48 | self._renderer_name = self.str_or_not_set(stream.read_string())
49 | self._scene_name = self.str_or_not_set(stream.read_string())
50 | self._sample_count = stream.read_uint()
51 |
52 | @staticmethod
53 | def str_or_not_set(s : str) -> str:
54 | """
55 | Returns the non-empty string or "not set'
56 | """
57 | if s == "":
58 | return "not set"
59 | else:
60 | return s
61 |
62 | @property
63 | def renderer_name(self) -> str:
64 | """
65 | Returns the renderer name
66 | """
67 | return self._renderer_name
68 |
69 | @property
70 | def scene_name(self) -> str:
71 | """
72 | Returns the scene name
73 | """
74 | return self._scene_name
75 |
76 | @property
77 | def sample_count(self) -> int:
78 | """
79 | Returns the amount of used samples to render the scene
80 | """
81 | if self._sample_count is not None:
82 | return self._sample_count
83 | else:
84 | return 0
85 |
86 | @sample_count.setter
87 | def sample_count(self, sample_count : int):
88 | """
89 | Setter function, sets the sample count
90 | """
91 | self._sample_count = sample_count
92 |
93 | def to_string(self) -> str:
94 | """
95 | Returns a string containing information about the class
96 | """
97 | return 'renderer_name = {} \n' \
98 | 'scene_name = {} \n' \
99 | 'sampleCount = {}'.format(self._renderer_name,
100 | self._scene_name,
101 | self._sample_count)
102 |
--------------------------------------------------------------------------------
/model/user_data.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | import typing
27 | from stream.stream import Stream
28 |
29 |
30 | class UserData(object):
31 |
32 | """
33 | UserData
34 | Handles general data types which can be added by the user during the path tracing algorithm,
35 | in order to debug the system.
36 | Supported data types boolean, float, double, integer, point2i, point2f, point3i, point3f, color4f and vectors
37 | """
38 |
39 | def __init__(self, stream : Stream):
40 | # handle default data types
41 | self._data = {}
42 |
43 | num_items = stream.read_uint()
44 | for i in range(num_items):
45 | key = stream.read_string()
46 | type_identifier = stream.read_char()
47 | if ord(type_identifier) > ord('0') and ord(type_identifier) <= ord('9'):
48 | type_identifier = type_identifier+stream.read_char()
49 | type_identifier = type_identifier.decode("utf-8")
50 |
51 | if type_identifier == '?':
52 | self._data[key] = stream.read_bool()
53 | elif type_identifier == 'f':
54 | self._data[key] = stream.read_float()
55 | elif type_identifier == 'd':
56 | self._data[key] = stream.read_double()
57 | elif type_identifier == 'i':
58 | self._data[key] = stream.read_int()
59 | elif type_identifier == '2i':
60 | self._data[key] = stream.read_point2i()
61 | elif type_identifier == '2f':
62 | self._data[key] = stream.read_point2f()
63 | elif type_identifier == '3i':
64 | self._data[key] = stream.read_point3i()
65 | elif type_identifier == '3f':
66 | self._data[key] = stream.read_point3f()
67 | elif type_identifier == '4f':
68 | self._data[key] = stream.read_color4f()
69 | elif type_identifier == 's':
70 | self._data[key] = stream.read_string()
71 | else:
72 | raise Exception('unknown type '+type_identifier)
73 |
74 | @property
75 | def data(self) -> typing.Dict[str, typing.Any]:
76 | """
77 | Returns a data dict with set information
78 | """
79 | return self._data
80 |
--------------------------------------------------------------------------------
/plugins/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from plugins.plugin_intersection_data.plugin_intersection_data_plots import IntersectionData
27 | from plugins.plugin_spherical_view.plugin_spherical_view import SphericalView
28 |
29 | # In order to initialize your plugin, import your plugin here and add it to __all__ list.
30 |
31 | __all__ = [
32 | 'IntersectionData',
33 | 'SphericalView',
34 | ]
35 |
--------------------------------------------------------------------------------
/plugins/plugin_intersection_data/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cgtuebingen/emca/560975bddc1b6176fe25029acb13d7806c8ab35b/plugins/plugin_intersection_data/__init__.py
--------------------------------------------------------------------------------
/plugins/plugin_intersection_data/intersection_data_plot_2d.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from core.plot_2d import ScatterPlot2D
27 | import numpy as np
28 | import logging
29 |
30 |
31 | class IntersectionDataPlot2D(ScatterPlot2D):
32 |
33 | def __init__(self, parent=None):
34 | ScatterPlot2D.__init__(self, None)
35 | self.parent = parent
36 | # overwrite pick event since we work on vertices not on paths
37 | self.highlighter.overwrite_pick_event(self.handle_pick)
38 | self.highlighter.enable_multi_selection(False)
39 |
40 | def handle_pick(self, event):
41 | ind = event.ind
42 |
43 | path_idx = self.parent.current_path_index()
44 | x_data_ax1 = np.int32(self.line.get_offsets().data[:,0])
45 |
46 | self.parent.send_select_intersection(path_idx, x_data_ax1[ind[0]])
47 |
48 | def select_intersection(self, its_idx):
49 | self.highlight([its_idx])
50 |
51 | def plot(self, name, values, xmin=None, xmax=None):
52 | x_list = values['its']
53 | y_list = values['value']
54 |
55 | self.plot_2d(x_list, y_list)
56 | if xmin is not None and xmax is not None:
57 | self.axes[0].set_xlim(xmin, xmax)
58 | self.axes[0].set_xticks(x_list)
59 | self.axes[0].set_title(name, color=self.color_title)
60 | self.axes[0].set_ylabel(name, color=self.color_title)
61 | #self.axes.set_xlabel('path depth', color=self.color_title)
62 |
63 |
--------------------------------------------------------------------------------
/plugins/plugin_intersection_data/intersection_data_plot_3d.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from core.plot_2d_xy import ScatterPlot2DXY
27 | import logging
28 |
29 |
30 | class IntersectionDataPlot3D(ScatterPlot2DXY):
31 |
32 | def __init__(self, parent=None):
33 | ScatterPlot2DXY.__init__(self, None)
34 | self.parent = parent
35 | # overwrite pick event since we work on vertices not on paths
36 | self.highlighter.overwrite_pick_event(self.handle_pick)
37 | self.highlighter.enable_multi_selection(False)
38 |
39 | def handle_pick(self, event):
40 | ind = event.ind
41 |
42 | path_idx = self.parent.current_path_index()
43 |
44 | self.parent.send_select_intersection(path_idx, self.x[ind[0]])
45 |
46 | def select_intersection(self, its_idx):
47 | self.highlight([its_idx])
48 |
49 | def prepare_plot_data(self, values):
50 | x_list = values['its']
51 | points = values['value']
52 |
53 | y_list = points[:,0]
54 | z_list = points[:,1]
55 |
56 | return x_list, y_list, z_list
57 |
58 | def plot(self, name, values, xmin=None, xmax=None):
59 | x, y, z = self.prepare_plot_data(values)
60 | self.plot_2d(x, y, z)
61 | #if xmin is not None and xmax is not None:
62 | #self.axes.set_xlim(xmin, xmax)
63 | self.set_title(name)
64 | #self.axes.set_xlabel('path depth', color=self.color_title)
65 | #self.axes.set_ylabel('x', color=self.color_title)
66 | #self.axes.set_zlabel('y', color=self.color_title)
67 | #self.axes.set_xticks(x)
68 |
--------------------------------------------------------------------------------
/plugins/plugin_intersection_data/intersection_data_plot_rgb.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from core.plot_rgb import RGBScatterPlot
27 | import numpy as np
28 |
29 |
30 | class IntersectionDataPlotRGB(RGBScatterPlot):
31 |
32 | def __init__(self, parent=None):
33 | RGBScatterPlot.__init__(self, None)
34 | self.parent = parent
35 | self.highlighter.enable_multi_selection(False)
36 | self.highlighter.overwrite_pick_event(self.handle_pick)
37 |
38 | def handle_pick(self, event):
39 | ind = event.ind
40 |
41 | path_idx = self.parent.current_path_index()
42 | x_data_ax1 = np.int32(self.r_line.get_offsets().data[:,0])
43 |
44 | self.parent.send_select_intersection(path_idx, x_data_ax1[ind[0]])
45 |
46 | def select_intersection(self, its_idx):
47 | self.highlight([its_idx])
48 |
49 | def plot(self, name, values, xmin=None, xmax=None):
50 | x_list = values['its']
51 | points = values['value']
52 |
53 | red_list = points[:,0]
54 | green_list = points[:,1]
55 | blue_list = points[:,2]
56 |
57 | self.plot_rgb(x_list, red_list, green_list, blue_list)
58 | for ax in self.figure.axes:
59 | #ax.set_xlabel('path depth', color=self.color_title)
60 | ax.set_xticks(x_list)
61 | ax.set_xlim(xmin, xmax)
62 |
--------------------------------------------------------------------------------
/plugins/plugin_intersection_data/plot_list_item.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from PySide2.QtWidgets import QListWidgetItem
27 |
28 |
29 | class PlotListItem(QListWidgetItem):
30 |
31 | def __init__(self, name, list_widget, plot_data, xmin, xmax, plot_canvas, widget_idx):
32 | QListWidgetItem.__init__(self, name, list_widget)
33 |
34 | self._name = name
35 | self._plot_data = plot_data
36 | self._xmin = xmin
37 | self._xmax = xmax
38 | self._plot_canvas = plot_canvas
39 | self._widget_idx = widget_idx
40 |
41 | @property
42 | def name(self):
43 | return self._name
44 |
45 | @property
46 | def plot_data(self):
47 | return self._plot_data
48 |
49 | @property
50 | def xmin(self):
51 | return self._xmin
52 |
53 | @property
54 | def xmax(self):
55 | return self._xmax
56 |
57 | @property
58 | def plot_canvas(self):
59 | return self._plot_canvas
60 |
61 | @property
62 | def widget_idx(self):
63 | return self._widget_idx
64 |
--------------------------------------------------------------------------------
/plugins/plugin_intersection_data/ui/plugin_plots.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | uirenderdatahistograms
4 |
5 |
6 | true
7 |
8 |
9 |
10 | 0
11 | 0
12 | 773
13 | 517
14 |
15 |
16 |
17 |
18 | 0
19 | 0
20 |
21 |
22 |
23 |
24 | 514
25 | 517
26 |
27 |
28 |
29 | Vertex Data Plots
30 |
31 |
32 |
33 | QLayout::SetMinimumSize
34 |
35 | -
36 |
37 |
38 | QLayout::SetMinimumSize
39 |
40 |
-
41 |
42 |
43 | QLayout::SetMinimumSize
44 |
45 |
-
46 |
47 |
48 |
49 | 0
50 | 0
51 |
52 |
53 |
54 | QAbstractScrollArea::AdjustToContents
55 |
56 |
57 |
58 | -
59 |
60 |
61 |
62 | 0
63 | 0
64 |
65 |
66 |
67 | QAbstractScrollArea::AdjustToContents
68 |
69 |
70 |
71 |
72 |
73 | -
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/plugins/plugin_spherical_view/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cgtuebingen/emca/560975bddc1b6176fe25029acb13d7806c8ab35b/plugins/plugin_spherical_view/__init__.py
--------------------------------------------------------------------------------
/plugins/plugin_spherical_view/plugin_spherical_view.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from core.plugin import Plugin, PluginType
27 | from model.pixel_data import PixelData
28 | from plugins.plugin_spherical_view.view_spherical_view_image import ViewSphericalViewImage
29 | from core.point import Point2i
30 | from core.pyside2_uic import loadUi
31 | import io
32 | import os
33 | import logging
34 |
35 |
36 | class SphericalView(Plugin):
37 |
38 | """
39 | SphericalView Plugins (mitsuba)
40 | PluginType is ServerPlugin since data is generated on server side
41 | """
42 |
43 | def __init__(self):
44 | Plugin.__init__(self, "SphericalView", 66, PluginType.SERVER_PLUGIN)
45 | ui_filepath = os.path.abspath(os.path.join(os.path.dirname(__file__), 'ui', 'spherical_view.ui'))
46 | loadUi(ui_filepath, self)
47 |
48 | self._path = None
49 | self._pixel_data = None
50 | self._render_size = Point2i(256, 128)
51 | self._sample_count = 16
52 | self._integrator = "path"
53 |
54 | self._spherical_view = ViewSphericalViewImage(self)
55 | self.hdrImage.addWidget(self._spherical_view)
56 |
57 | def apply_theme(self, theme):
58 | pass
59 |
60 | def prepare_new_data(self):
61 | self._spherical_view.clear()
62 | self._spherical_view.enable_buttons(False)
63 |
64 | def update_path_indices(self, indices):
65 | pass
66 |
67 | def select_path(self, index):
68 | pass
69 |
70 | def select_intersection(self, path_idx, its_idx):
71 | if self._pixel_data:
72 | dict_paths = self._pixel_data.dict_paths
73 | self._spherical_view.select_intersection(dict_paths, path_idx, its_idx)
74 |
75 | def serialize(self, stream):
76 | logging.info("Serialize in: {}".format(self.name))
77 | if self._spherical_view.pos is not None:
78 | self._render_size.x = self.sbWidth.value()
79 | self._render_size.y = self.sbHeight.value()
80 | self._sample_count = int(self.sbSampleCount.value())
81 | self._integrator = self.integrator.text()
82 | # send package id
83 | stream.write_short(self.flag)
84 | # send point / data
85 | stream.write_float(self._spherical_view.pos.x)
86 | stream.write_float(self._spherical_view.pos.y)
87 | stream.write_float(self._spherical_view.pos.z)
88 | # send amount of samples
89 | stream.write_int(self._sample_count)
90 | # send render size
91 | stream.write_int(self._render_size.x)
92 | stream.write_int(self._render_size.y)
93 | # send integrator
94 | stream.write_string(self._integrator)
95 |
96 | def deserialize(self, stream):
97 | logging.info("Deserialize in: {}".format(self.name))
98 | size = stream.read_int()
99 | if size > 0:
100 | self._path = io.BytesIO(stream.read(size))
101 | else:
102 | self._path = None
103 |
104 | def update_view(self):
105 | if self._path is None:
106 | logging.error("Path is None")
107 | return
108 | if self._spherical_view.load_hdr_image(self._path):
109 | if not self._spherical_view.is_btn_enabled:
110 | self._spherical_view.enable_buttons(True)
111 | self._spherical_view.update_hightlights()
112 |
113 | def init_pixel_data(self, pixel_data : PixelData):
114 | self._pixel_data = pixel_data
115 |
--------------------------------------------------------------------------------
/plugins/plugin_spherical_view/ui/spherical_view.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | uiSphericalView
4 |
5 |
6 | true
7 |
8 |
9 | Tool Plots
10 |
11 |
12 |
13 | QLayout::SetMinimumSize
14 |
15 | -
16 |
17 |
18 | -
19 |
20 |
-
21 |
22 |
23 | Image width:
24 |
25 |
26 | sbWidth
27 |
28 |
29 |
30 | -
31 |
32 |
33 | 1
34 |
35 |
36 | 1920
37 |
38 |
39 | 256
40 |
41 |
42 |
43 | -
44 |
45 |
46 | Image height:
47 |
48 |
49 | sbHeight
50 |
51 |
52 |
53 | -
54 |
55 |
56 | 1
57 |
58 |
59 | 1080
60 |
61 |
62 | 128
63 |
64 |
65 |
66 | -
67 |
68 |
69 | Integrator:
70 |
71 |
72 | integrator
73 |
74 |
75 |
76 | -
77 |
78 |
79 | path
80 |
81 |
82 |
83 | -
84 |
85 |
86 | SampleCount:
87 |
88 |
89 | sbSampleCount
90 |
91 |
92 |
93 | -
94 |
95 |
96 | 1
97 |
98 |
99 | 999999999
100 |
101 |
102 | 16
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | sbWidth
112 | sbHeight
113 | integrator
114 | sbSampleCount
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/plugins/plugin_spherical_view/ui/spherical_view_image.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | uiSphericalView
4 |
5 |
6 | true
7 |
8 |
9 |
10 | 0
11 | 0
12 | 480
13 | 280
14 |
15 |
16 |
17 |
18 | 480
19 | 280
20 |
21 |
22 |
23 | Tool Plots
24 |
25 |
26 |
27 | QLayout::SetMinimumSize
28 |
29 |
30 | 0
31 |
32 |
33 | 0
34 |
35 |
36 | 0
37 |
38 |
39 | 0
40 |
41 | -
42 |
43 |
44 | -
45 |
46 |
-
47 |
48 |
49 | exposure
50 |
51 |
52 | -500
53 |
54 |
55 | 500
56 |
57 |
58 | Qt::Horizontal
59 |
60 |
61 | QSlider::TicksBelow
62 |
63 |
64 | 100
65 |
66 |
67 |
68 | -
69 |
70 |
71 | Falsecolor
72 |
73 |
74 |
75 |
76 |
77 | -
78 |
79 |
-
80 |
81 |
82 | false
83 |
84 |
85 | Save
86 |
87 |
88 |
89 | -
90 |
91 |
92 | false
93 |
94 |
95 | Fit View
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/renderer/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cgtuebingen/emca/560975bddc1b6176fe25029acb13d7806c8ab35b/renderer/__init__.py
--------------------------------------------------------------------------------
/renderer/rubberband.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | import vtk
27 | import logging
28 |
29 |
30 | class RubberBandInteractor(vtk.vtkInteractorStyleRubberBandPick):
31 |
32 | """
33 | RubberBandInteractor
34 | Allows a rubber band selector by clicking the 'r' key within the 3D renderer scene view.
35 | The selected vertex and its corresponding path will be automatically be visualized within all other views.
36 | """
37 |
38 | def __init__(self, parent=None):
39 | super().__init__()
40 |
41 | self.AddObserver("KeyPressEvent", self.key_press_event)
42 |
43 | def key_press_event(self, obj, event):
44 | """
45 | Handles key input for the 3D scene viewer.
46 | Moves the camera within the scene
47 | :param obj:
48 | :param event:
49 | :return:
50 | """
51 | key = self.GetInteractor().GetKeySym()
52 | camera = self.GetDefaultRenderer().GetActiveCamera()
53 |
54 | if key == 'Up':
55 | camera.move_forward()
56 | elif key == 'Left':
57 | camera.move_left()
58 | elif key == 'Right':
59 | camera.move_right()
60 | elif key == 'Down':
61 | camera.move_backward()
62 | elif key == '8':
63 | camera.move_up()
64 | elif key == '4':
65 | camera.pan_left()
66 | elif key == '6':
67 | camera.pan_right()
68 | elif key == '2':
69 | camera.move_down()
70 |
71 | self.GetDefaultRenderer().ResetCameraClippingRange()
72 | self.GetInteractor().Render()
73 |
--------------------------------------------------------------------------------
/renderer/shape.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from core.color import Color4f
27 |
28 | import numpy as np
29 | import vtk
30 |
31 | class Shape(vtk.vtkActor):
32 |
33 | def __init__(self,
34 | mesh_poly_data : vtk.vtkPolyData,
35 | color_diffuse : Color4f = Color4f(1, 1, 1),
36 | color_specular : Color4f = Color4f(0, 0, 0)):
37 | super().__init__()
38 |
39 | self._mapper = vtk.vtkPolyDataMapper()
40 | # use setter function - this sets the mapper inputs
41 | self.poly_data = mesh_poly_data
42 | self.SetMapper(self._mapper)
43 |
44 | # set default lighting options
45 | self.GetProperty().SetLighting(True)
46 | self.GetProperty().LightingOn()
47 | self.GetProperty().SetShading(True)
48 | self.GetProperty().ShadingOn()
49 | self.GetProperty().SetDiffuseColor(color_diffuse[0:3])
50 | self.GetProperty().SetDiffuse(1)
51 | if not np.allclose(color_specular, Color4f(0,0,0)):
52 | self.GetProperty().SetSpecularColor(color_specular[0:3])
53 | self.GetProperty().SetSpecular(np.mean(np.array(color_specular))/np.mean(np.array(color_specular+color_diffuse)))
54 | self.GetProperty().SetAmbient(0)
55 |
56 | @property
57 | def poly_data(self) -> vtk.vtkPolyData:
58 | return self._poly_data
59 |
60 | @poly_data.setter
61 | def poly_data(self, poly_data : vtk.vtkPolyData):
62 | self._poly_data = poly_data
63 |
64 | if isinstance(self._poly_data, vtk.vtkAlgorithmOutput):
65 | self._mapper.SetInputConnection(self._poly_data)
66 | else:
67 | self._mapper.SetInputData(self._poly_data)
68 |
69 | @property
70 | def mapper(self) -> vtk.vtkPolyDataMapper:
71 | return self._mapper
72 |
73 | @property
74 | def opacity(self) -> float:
75 | """
76 | Returns the current opacity of the object
77 | """
78 | return self.GetProperty().GetOpacity()
79 |
80 | @opacity.setter
81 | def opacity(self, value : float):
82 | """
83 | Sets the opacity of the object
84 | """
85 | self.GetProperty().SetOpacity(value)
86 |
87 | @property
88 | def color(self) -> Color4f:
89 | """
90 | Returns the actual color of the object
91 | :return: list
92 | """
93 | return Color4f(self.GetProperty().GetColor())
94 |
95 | @color.setter
96 | def color(self, color : Color4f):
97 | """
98 | Sets the current color of the object
99 | """
100 | self.GetProperty().SetColor(color)
101 |
102 | @property
103 | def color_diffuse(self) -> Color4f:
104 | """
105 | Returns the current diffuse color of the object
106 | """
107 | return Color4f(self.GetProperty().GetDiffuseColor())
108 |
109 | @color_diffuse.setter
110 | def color_diffuse(self, color_diffuse : Color4f):
111 | """
112 | Sets the diffuse color of the object
113 | """
114 | self.GetProperty().SetDiffuseColor(color_diffuse)
115 |
116 | @property
117 | def color_specular(self) -> Color4f:
118 | """
119 | Return the current specular color of the object
120 | """
121 | return Color4f(self.GetProperty().GetSpecularColor())
122 |
123 | @color_specular.setter
124 | def color_specular(self, color_specular : Color4f):
125 | """
126 | Sets the specular color of the object
127 | """
128 | self.GetProperty.SetSpecularColor(color_specular)
129 |
--------------------------------------------------------------------------------
/renderer/sphere.py:
--------------------------------------------------------------------------------
1 | """
2 | MIT License
3 |
4 | Copyright (c) 2020 Christoph Kreisl
5 | Copyright (c) 2021 Lukas Ruppert
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | """
25 |
26 | from renderer.shape import Shape
27 | import vtk
28 | import logging
29 |
30 |
31 | class Sphere(Shape):
32 |
33 | """
34 | Sphere
35 | Represents a vtk Sphere object within the 3D scene
36 | """
37 |
38 | def __init__(self, center, radius, theta_resolution=20, phi_resolution=20):
39 |
40 | self._center = center
41 | self._radius = radius
42 |
43 | sphere = vtk.vtkSphereSource()
44 | # center (x,y,z)
45 | sphere.SetCenter(list(center))
46 | sphere.SetRadius(radius)
47 | sphere.SetThetaResolution(theta_resolution)
48 | sphere.SetPhiResolution(phi_resolution)
49 |
50 | # get poly data
51 | mesh_poly_data = sphere.GetOutputPort()
52 |
53 | super().__init__(mesh_poly_data)
54 |
55 | @property
56 | def radius(self):
57 | return self._radius
58 |
59 | @radius.setter
60 | def radius(self, radius):
61 | self._radius = radius
62 |
63 | @property
64 | def center(self):
65 | return self._center
66 |
67 | @center.setter
68 | def center(self, center):
69 | self._center = center
70 |
71 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | Imath
2 | numpy>=1.18.2
3 | scipy>=1.1.0
4 | matplotlib>=3.2.1
5 | OpenEXR>=1.3.2
6 | Pillow>=7.1.2
7 | PySide2>=5.14.2.1
8 | vtk>=9.0.0
9 |
--------------------------------------------------------------------------------
/resources/dark/branch_closed-on.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/branch_closed.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/branch_open-on.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/branch_open.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/checkbox_checked.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/dark/checkbox_checked_disabled.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/dark/checkbox_indeterminate.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/resources/dark/checkbox_indeterminate_disabled.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/resources/dark/checkbox_unchecked.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/dark/checkbox_unchecked_disabled.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/dark/close-hover.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/close-pressed.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/close.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/down_arrow-hover.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/down_arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/down_arrow_disabled.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/hmovetoolbar.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/dark/hsepartoolbar.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/left_arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/left_arrow_disabled.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/radio_checked.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/dark/radio_checked_disabled.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/dark/radio_unchecked.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/dark/radio_unchecked_disabled.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/dark/right_arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/right_arrow_disabled.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/sizegrip.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/spinup_disabled.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/stylesheet-branch-end-closed.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/dark/stylesheet-branch-end-open.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/dark/stylesheet-branch-end.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/dark/stylesheet-branch-more.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/dark/stylesheet-vline.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/transparent.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/dark/undock-hover.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/dark/undock.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/up_arrow-hover.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/up_arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/up_arrow_disabled.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/dark/vmovetoolbar.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/resources/dark/vsepartoolbars.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/resources/emca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cgtuebingen/emca/560975bddc1b6176fe25029acb13d7806c8ab35b/resources/emca.png
--------------------------------------------------------------------------------
/resources/light/branch_closed-on.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/branch_closed.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/branch_open-on.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/branch_open.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/checkbox_checked-hover.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/light/checkbox_checked.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/light/checkbox_checked_disabled.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/light/checkbox_indeterminate-hover.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/resources/light/checkbox_indeterminate.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/resources/light/checkbox_indeterminate_disabled.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/resources/light/checkbox_unchecked-hover.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/light/checkbox_unchecked_disabled.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/light/close-hover.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/close-pressed.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/close.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/down_arrow-hover.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/down_arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/down_arrow_disabled.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/hmovetoolbar.svg:
--------------------------------------------------------------------------------
1 |
5 |
6 |
--------------------------------------------------------------------------------
/resources/light/hsepartoolbar.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/left_arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/left_arrow_disabled.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/radio_checked-hover.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/light/radio_checked.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/light/radio_checked_disabled.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/light/radio_unchecked-hover.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/light/radio_unchecked_disabled.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/light/right_arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/right_arrow_disabled.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/sizegrip.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/spinup_disabled.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/stylesheet-branch-end-closed.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/light/stylesheet-branch-end-open.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/light/stylesheet-branch-end.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/light/stylesheet-branch-more.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/resources/light/stylesheet-vline.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/transparent.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/resources/light/undock-hover.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/resources/light/undock.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/up_arrow-hover.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/up_arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/up_arrow_disabled.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/resources/light/vmovetoolbar.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/resources/light/vsepartoolbars.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/resources/options.ini:
--------------------------------------------------------------------------------
1 | [Theme]
2 | theme = dark
3 |
4 | [Options]
5 | auto_connect = True
6 | auto_scene_load = True
7 | auto_rendered_image_load = True
8 |
9 | [Last]
10 | hostname = localhost
11 | port = 50013
12 |
13 |
--------------------------------------------------------------------------------
/server/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.10.2)
2 | project(emca
3 | DESCRIPTION "Explorer of Monte Carlo based Algorithms (Server)"
4 | LANGUAGES CXX)
5 |
6 | # Set a default build configuration (Release)
7 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
8 | message(STATUS "Setting build type to 'Release' as none was specified.")
9 | set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
10 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
11 | "MinSizeRel" "RelWithDebInfo")
12 | endif()
13 |
14 | include(GNUInstallDirs)
15 |
16 | set(CMAKE_CXX_STANDARD 17)
17 |
18 | option(EMCA_BUILD_SHARED "Build EMCA as a shared library?" ON)
19 |
20 | # Set library type
21 | if (EMCA_BUILD_SHARED)
22 | set(EMCA_LIBRARY_TYPE "SHARED")
23 | else()
24 | set(EMCA_LIBRARY_TYPE "STATIC")
25 | endif()
26 |
27 | add_library(${PROJECT_NAME} ${EMCA_LIBRARY_TYPE}
28 | src/emcaserver.cpp
29 | src/dataapi.cpp
30 | src/pathdata.cpp
31 | src/heatmapdata.cpp)
32 |
33 | # atomic library needed for 16 byte atomic read/write
34 | target_link_libraries(${PROJECT_NAME} PUBLIC atomic)
35 |
36 | target_include_directories(${PROJECT_NAME} PUBLIC
37 | $
38 | $
39 | PRIVATE src)
40 |
41 | set_target_properties(${PROJECT_NAME} PROPERTIES
42 | VERSION "1.0.0"
43 | SOVERSION 1)
44 |
45 | install(TARGETS ${PROJECT_NAME} EXPORT EMCAConfig
46 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
47 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
48 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
49 |
50 | install(DIRECTORY include/${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
51 | install(EXPORT EMCAConfig DESTINATION share/EMCALib/cmake)
52 |
53 | export(TARGETS ${PROJECT_NAME} FILE EMCAConfig.cmake)
54 |
--------------------------------------------------------------------------------
/server/LICENSE:
--------------------------------------------------------------------------------
1 | Licensed to the Apache Software Foundation (ASF) under one
2 | or more contributor license agreements. See the NOTICE file
3 | distributed with this work for additional information
4 | regarding copyright ownership. The ASF licenses this file
5 | to you under the Apache License, Version 2.0 (the
6 | "License"); you may not use this file except in compliance
7 | with the License. You may obtain a copy of the License at
8 |
9 | http://www.apache.org/licenses/LICENSE-2.0
10 |
11 | Unless required by applicable law or agreed to in writing,
12 | software distributed under the License is distributed on an
13 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | KIND, either express or implied. See the License for the
15 | specific language governing permissions and limitations
16 | under the License.
--------------------------------------------------------------------------------
/server/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # EMCA - Server Library
4 |
5 |
6 |
7 | ## About
8 | EMCA comes with a server and client part. All files within this folder represents the server part which must be connected to the specific render system. The server files are compiled as shared library which can be then easily included into your project.
9 |
10 | ## Table of contents
11 | * [About](#about)
12 | * [Build](#build)
13 | * [License](#license)
14 |
15 |
16 |
17 | ## Build
18 | For compiling the shared library we provide a CMakeLists.txt file.
19 |
20 | ```
21 | mkdir build
22 | cd build
23 | cmake ..
24 | make -j4
25 | sudo make install
26 | ```
27 |
28 | Make sure that the path to the emca shared library is defined in **LD_LIBRARY_PATH**.
29 |
30 |
31 |
32 | ## License
33 | The shared library comes with the Apache License 2.0.
34 |
35 | (c) Christoph Kreisl
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/server/include/emca/datatypes.h:
--------------------------------------------------------------------------------
1 | /*
2 | EMCA - Explorer of Monte Carlo based Alorithms (Shared Server Library)
3 | comes with an Apache License 2.0
4 | (c) Christoph Kreisl 2020
5 | (c) Lukas Ruppert 2021
6 |
7 | Licensed to the Apache Software Foundation (ASF) under one
8 | or more contributor license agreements. See the NOTICE file
9 | distributed with this work for additional information
10 | regarding copyright ownership. The ASF licenses this file
11 | to you under the Apache License, Version 2.0 (the
12 | "License"); you may not use this file except in compliance
13 | with the License. You may obtain a copy of the License at
14 |
15 | http://www.apache.org/licenses/LICENSE-2.0
16 |
17 | Unless required by applicable law or agreed to in writing,
18 | software distributed under the License is distributed on an
19 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20 | KIND, either express or implied. See the License for the
21 | specific language governing permissions and limitations
22 | under the License.
23 | */
24 |
25 | #ifndef INCLUDE_EMCA_DATATYPES_H_
26 | #define INCLUDE_EMCA_DATATYPES_H_
27 |
28 | #include "platform.h"
29 | #include "stream.h"
30 |
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | EMCA_NAMESPACE_BEGIN
37 |
38 | template struct TArray {
39 | static constexpr size_t dim = N;
40 | std::array p {};
41 |
42 | std::enable_if_t<(dim > 0), T> x() const { return p[0]; }
43 | std::enable_if_t<(dim > 1), T> y() const { return p[1]; }
44 | std::enable_if_t<(dim > 2), T> z() const { return p[2]; }
45 |
46 | std::enable_if_t<(dim > 0), T> norm() const { return std::sqrt(std::accumulate(p.begin(), p.end(), T(0), [](T sum, T element) -> T { return sum+element*element; })); }
47 | std::enable_if_t<(dim == 3), T> dot(const TArray& other) const { return x()*other.x()+y()*other.y()+z()*other.z(); }
48 |
49 | void serialize(Stream *stream) const {
50 | stream->writeArray(p.data(), dim);
51 | }
52 | };
53 |
54 | template struct TPoint2 : public TArray {
55 | using TArray::dim;
56 | using TArray::p;
57 |
58 | TPoint2() = default;
59 | TPoint2(T x, T y) {
60 | p[0] = x;
61 | p[y] = y;
62 | }
63 | };
64 |
65 | template struct TVec3 : public TArray {
66 | using TArray::dim;
67 | using TArray::p;
68 |
69 | TVec3() = default;
70 | TVec3(T x, T y, T z) {
71 | p[0] = x;
72 | p[1] = y;
73 | p[2] = z;
74 | }
75 |
76 | TVec3& operator*=(T scale) { p[0]*=scale; p[1]*=scale; p[2]*=scale; return *this; }
77 | T normalize() { const float norm = this->norm(); *this *= 1.0f/norm; return norm; }
78 | TVec3 operator*(T scale) { TVec3 copy{*this}; copy*=scale; return copy; }
79 | };
80 |
81 | template
82 | TVec3 cross(const TVec3& a, const TVec3& b) {
83 | return {a.y()*b.z()-a.z()*b.y(), a.z()*b.x()-a.x()*b.z(), a.x()*b.y()-a.y()*b.x()};
84 | }
85 |
86 | template struct TPoint3 : public TArray {
87 | using TArray::dim;
88 | using TArray::p;
89 | using TArray::x;
90 | using TArray::y;
91 | using TArray::z;
92 |
93 | TPoint3() = default;
94 | TPoint3(T x, T y, T z) {
95 | p[0] = x;
96 | p[1] = y;
97 | p[2] = z;
98 | }
99 |
100 | TVec3 operator-(const TPoint3& other) const {
101 | return TVec3{x()-other.x(), y()-other.y(), z()-other.z()};
102 | }
103 | TPoint3 operator+(const TVec3& other) const {
104 | return TPoint3{x()+other.x(), y()+other.y(), z()+other.z()};
105 | }
106 | };
107 |
108 | template struct TColor4 {
109 | static constexpr int dim = 4;
110 | std::array c {};
111 |
112 | TColor4() = default;
113 | TColor4(T r, T g, T b, T a=1) : c{r, g, b, a} {}
114 |
115 | T r() const { return c[0]; }
116 | T g() const { return c[1]; }
117 | T b() const { return c[2]; }
118 | T a() const { return c[3]; }
119 |
120 | void serialize(Stream *stream) const {
121 | stream->writeArray(c.data(), dim);
122 | }
123 | };
124 |
125 | typedef TPoint2 Point2i;
126 | typedef TPoint2 Point2f;
127 | typedef TPoint3 Point3i;
128 | typedef TPoint3 Point3f;
129 | typedef TVec3 Vec3u;
130 | typedef TVec3 Vec3f;
131 | typedef TColor4 Color4f;
132 |
133 | EMCA_NAMESPACE_END
134 |
135 | #endif /* INCLUDE_EMCA_DATATYPES_H_ */
136 |
--------------------------------------------------------------------------------
/server/include/emca/emcaserver.h:
--------------------------------------------------------------------------------
1 | /*
2 | EMCA - Explorer of Monte Carlo based Alorithms (Shared Server Library)
3 | comes with an Apache License 2.0
4 | (c) Christoph Kreisl 2020
5 | (c) Lukas Ruppert 2021
6 |
7 | Licensed to the Apache Software Foundation (ASF) under one
8 | or more contributor license agreements. See the NOTICE file
9 | distributed with this work for additional information
10 | regarding copyright ownership. The ASF licenses this file
11 | to you under the Apache License, Version 2.0 (the
12 | "License"); you may not use this file except in compliance
13 | with the License. You may obtain a copy of the License at
14 |
15 | http://www.apache.org/licenses/LICENSE-2.0
16 |
17 | Unless required by applicable law or agreed to in writing,
18 | software distributed under the License is distributed on an
19 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20 | KIND, either express or implied. See the License for the
21 | specific language governing permissions and limitations
22 | under the License.
23 | */
24 |
25 | #ifndef INCLUDE_EMCA_EMCASERVER_H_
26 | #define INCLUDE_EMCA_EMCASERVER_H_
27 |
28 | #include
29 |
30 | #include "platform.h"
31 | #include "stream.h"
32 | #include "renderinterface.h"
33 | #include "dataapi.h"
34 | #include "plugin.h"
35 | #include "stream.h"
36 |
37 | #include
38 |
39 | EMCA_NAMESPACE_BEGIN
40 |
41 | class EMCAServer {
42 | public:
43 | EMCAServer(RenderInterface* renderer, DataApi* dataApi);
44 | ~EMCAServer() { stop(); }
45 |
46 | /// runs the main TCP server that communicates with the client.
47 | /// does not return until the server is shut down.
48 | void run(uint16_t port=50013);
49 |
50 | /// disconnect the current client
51 | void disconnect();
52 | /// stop the TCP server
53 | void stop();
54 |
55 | private:
56 | // implementation of the binary protocol between server and client
57 | // changes made here require similar changes on the client side
58 | // these functions call into the renderer where necessary to provide the requested data
59 | void respondSupportedPlugins();
60 | void respondRenderInfo();
61 | void respondRenderImage();
62 | void respondCameraData();
63 | void respondSceneData();
64 | void respondRenderPixel();
65 | bool respondPluginRequest(short id);
66 |
67 | RenderInterface* m_renderer {nullptr};
68 | DataApi* m_dataApi {nullptr};
69 |
70 | typedef int socket_t;
71 |
72 | class SocketStream final : public Stream {
73 | public:
74 | SocketStream(socket_t client_socket) : m_clientSocket(client_socket) {}
75 |
76 | private:
77 | void write(const void *ptr, size_t size);
78 | void read(void *ptr, size_t size);
79 |
80 | socket_t m_clientSocket; // not owned - will not be closed on destruction
81 | };
82 |
83 | socket_t m_clientSocket {-1};
84 | socket_t m_serverSocket {-1};
85 | std::unique_ptr m_stream;
86 |
87 | std::vector m_mesh_data;
88 | };
89 |
90 | EMCA_NAMESPACE_END
91 |
92 | #endif /* INCLUDE_EMCA_EMCASERVER_H_ */
93 |
--------------------------------------------------------------------------------
/server/include/emca/messages.h:
--------------------------------------------------------------------------------
1 | /*
2 | EMCA - Explorer of Monte Carlo based Alorithms (Shared Server Library)
3 | comes with an Apache License 2.0
4 | (c) Christoph Kreisl 2020
5 | (c) Lukas Ruppert 2021
6 |
7 | Licensed to the Apache Software Foundation (ASF) under one
8 | or more contributor license agreements. See the NOTICE file
9 | distributed with this work for additional information
10 | regarding copyright ownership. The ASF licenses this file
11 | to you under the Apache License, Version 2.0 (the
12 | "License"); you may not use this file except in compliance
13 | with the License. You may obtain a copy of the License at
14 |
15 | http://www.apache.org/licenses/LICENSE-2.0
16 |
17 | Unless required by applicable law or agreed to in writing,
18 | software distributed under the License is distributed on an
19 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20 | KIND, either express or implied. See the License for the
21 | specific language governing permissions and limitations
22 | under the License.
23 | */
24 |
25 | #ifndef INCLUDE_EMCA_MESSAGES_H_
26 | #define INCLUDE_EMCA_MESSAGES_H_
27 |
28 | #include "platform.h"
29 |
30 | EMCA_NAMESPACE_BEGIN
31 |
32 | // message identifiers for the TCP protocol
33 | enum Message {
34 | // connection management (0x000x)
35 | EMCA_HELLO = 0x0001,
36 | EMCA_SUPPORTED_PLUGINS = 0x0002,
37 | EMCA_DISCONNECT = 0x000E,
38 | EMCA_QUIT = 0x000F,
39 |
40 | // requests from the client (0x001x)
41 | EMCA_REQUEST_RENDER_INFO = 0x0011,
42 | EMCA_REQUEST_RENDER_IMAGE = 0x0012,
43 | EMCA_REQUEST_RENDER_PIXEL = 0x0013,
44 | EMCA_REQUEST_CAMERA = 0x0014,
45 | EMCA_REQUEST_SCENE = 0x0015,
46 |
47 | // responses to the client (0x002x)
48 | EMCA_RESPONSE_RENDER_INFO = 0x0021,
49 | EMCA_RESPONSE_RENDER_IMAGE = 0x0022,
50 | EMCA_RESPONSE_RENDER_PIXEL = 0x0023,
51 | EMCA_RESPONSE_CAMERA = 0x0024,
52 | EMCA_RESPONSE_SCENE = 0x0025,
53 | };
54 |
55 | // shape types that can be transferred to the client
56 | enum ShapeType
57 | {
58 | TriangleMesh = 0,
59 | SphereMesh = 1
60 | };
61 |
62 | EMCA_NAMESPACE_END
63 |
64 | #endif /* INCLUDE_EMCA_MESSAGES_H_ */
65 |
--------------------------------------------------------------------------------
/server/include/emca/platform.h:
--------------------------------------------------------------------------------
1 | /*
2 | EMCA - Explorer of Monte Carlo based Alorithms (Shared Server Library)
3 | comes with an Apache License 2.0
4 | (c) Christoph Kreisl 2020
5 | (c) Lukas Ruppert 2021
6 |
7 | Licensed to the Apache Software Foundation (ASF) under one
8 | or more contributor license agreements. See the NOTICE file
9 | distributed with this work for additional information
10 | regarding copyright ownership. The ASF licenses this file
11 | to you under the Apache License, Version 2.0 (the
12 | "License"); you may not use this file except in compliance
13 | with the License. You may obtain a copy of the License at
14 |
15 | http://www.apache.org/licenses/LICENSE-2.0
16 |
17 | Unless required by applicable law or agreed to in writing,
18 | software distributed under the License is distributed on an
19 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20 | KIND, either express or implied. See the License for the
21 | specific language governing permissions and limitations
22 | under the License.
23 | */
24 |
25 | #ifndef INCLUDE_EMCA_PLATFORM_H_
26 | #define INCLUDE_EMCA_PLATFORM_H_
27 |
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include