Commit 0ba6002010b090f85010fc4e92c8cca0a34d4784
Committed by
Paulo Henrique Junqueira Amorim
1 parent
897e159b
Exists in
master
Navigation updates (#187)
* Added Camera tracker -improved tracker.py by using const.py * Added tracker file * Tooltip offset * Remove set button from navigation tab * Reduce panel size and cleaning * More cleaning * Updates to code standards * Support to the fourth FTsensor * Support coil's marker * Update to Pose board instead single marker * Minor testing * Support to NDI polaris * invesalius sets ROMs path * dialog to select COM port * dialog to select COM port for polhemus devices * Sensors ID * cleaning wrapper export coordinates * Polaris support working with Visor2 tools and dynamic coregistration * dialog to choose roms files * wrapper texts improvements * improv coils arrows scale * dialog to select COM for polhemus * inv_path upgrade * Removed camera_tracker
Showing
18 changed files
with
381 additions
and
118 deletions
Show diff stats
invesalius/constants.py
@@ -650,14 +650,18 @@ MTC = 1 | @@ -650,14 +650,18 @@ MTC = 1 | ||
650 | FASTRAK = 2 | 650 | FASTRAK = 2 |
651 | ISOTRAKII = 3 | 651 | ISOTRAKII = 3 |
652 | PATRIOT = 4 | 652 | PATRIOT = 4 |
653 | -DEBUGTRACK = 5 | ||
654 | -DISCTRACK = 6 | 653 | +CAMERA = 5 |
654 | +POLARIS = 6 | ||
655 | +DEBUGTRACK = 7 | ||
656 | +DISCTRACK = 8 | ||
655 | DEFAULT_TRACKER = SELECT | 657 | DEFAULT_TRACKER = SELECT |
656 | 658 | ||
659 | +NDICOMPORT = b'COM1' | ||
660 | + | ||
657 | TRACKER = [_("Select tracker:"), _("Claron MicronTracker"), | 661 | TRACKER = [_("Select tracker:"), _("Claron MicronTracker"), |
658 | _("Polhemus FASTRAK"), _("Polhemus ISOTRAK II"), | 662 | _("Polhemus FASTRAK"), _("Polhemus ISOTRAK II"), |
659 | - _("Polhemus PATRIOT"), _("Debug tracker"), | ||
660 | - _("Disconnect tracker")] | 663 | + _("Polhemus PATRIOT"), _("Camera tracker"), |
664 | + _("NDI Polaris"), _("Debug tracker"), _("Disconnect tracker")] | ||
661 | 665 | ||
662 | STATIC_REF = 0 | 666 | STATIC_REF = 0 |
663 | DYNAMIC_REF = 1 | 667 | DYNAMIC_REF = 1 |
@@ -715,13 +719,13 @@ TIPS_OBJ = [_("Select left object fiducial"), | @@ -715,13 +719,13 @@ TIPS_OBJ = [_("Select left object fiducial"), | ||
715 | _("Select object center"), | 719 | _("Select object center"), |
716 | _("Attach sensor to object")] | 720 | _("Attach sensor to object")] |
717 | 721 | ||
718 | -PROBE_NAME = "1Probe" | ||
719 | -REF_NAME = "2Ref" | ||
720 | -OBJ_NAME = "3Coil" | 722 | +MTC_PROBE_NAME = "1Probe" |
723 | +MTC_REF_NAME = "2Ref" | ||
724 | +MTC_OBJ_NAME = "3Coil" | ||
721 | 725 | ||
722 | #OBJECT TRACKING | 726 | #OBJECT TRACKING |
723 | -ARROW_SCALE = 3 | ||
724 | -ARROW_UPPER_LIMIT = 30 | 727 | +ARROW_SCALE = 6 |
728 | +ARROW_UPPER_LIMIT = 15 | ||
725 | #COIL_ANGLES_THRESHOLD = 3 * ARROW_SCALE | 729 | #COIL_ANGLES_THRESHOLD = 3 * ARROW_SCALE |
726 | COIL_ANGLES_THRESHOLD = 3 | 730 | COIL_ANGLES_THRESHOLD = 3 |
727 | COIL_COORD_THRESHOLD = 3 | 731 | COIL_COORD_THRESHOLD = 3 |
invesalius/data/coordinates.py
@@ -21,6 +21,7 @@ from math import sin, cos | @@ -21,6 +21,7 @@ from math import sin, cos | ||
21 | import numpy as np | 21 | import numpy as np |
22 | 22 | ||
23 | import invesalius.data.transformations as tr | 23 | import invesalius.data.transformations as tr |
24 | +import invesalius.constants as const | ||
24 | 25 | ||
25 | from time import sleep | 26 | from time import sleep |
26 | from random import uniform | 27 | from random import uniform |
@@ -40,17 +41,48 @@ def GetCoordinates(trck_init, trck_id, ref_mode): | @@ -40,17 +41,48 @@ def GetCoordinates(trck_init, trck_id, ref_mode): | ||
40 | 41 | ||
41 | coord = None | 42 | coord = None |
42 | if trck_id: | 43 | if trck_id: |
43 | - getcoord = {1: ClaronCoord, | ||
44 | - 2: PolhemusCoord, | ||
45 | - 3: PolhemusCoord, | ||
46 | - 4: PolhemusCoord, | ||
47 | - 5: DebugCoord} | 44 | + getcoord = {const.MTC: ClaronCoord, |
45 | + const.FASTRAK: PolhemusCoord, | ||
46 | + const.ISOTRAKII: PolhemusCoord, | ||
47 | + const.PATRIOT: PolhemusCoord, | ||
48 | + const.CAMERA: CameraCoord, | ||
49 | + const.POLARIS: PolarisCoord, | ||
50 | + const.DEBUGTRACK: DebugCoord} | ||
48 | coord = getcoord[trck_id](trck_init, trck_id, ref_mode) | 51 | coord = getcoord[trck_id](trck_init, trck_id, ref_mode) |
49 | else: | 52 | else: |
50 | print("Select Tracker") | 53 | print("Select Tracker") |
51 | 54 | ||
52 | return coord | 55 | return coord |
53 | 56 | ||
57 | +def PolarisCoord(trck_init, trck_id, ref_mode): | ||
58 | + trck = trck_init[0] | ||
59 | + trck.Run() | ||
60 | + | ||
61 | + probe = trck.probe.decode(const.FS_ENCODE).split(',') | ||
62 | + angles_probe = np.degrees(tr.euler_from_quaternion(probe[2:6], axes='rzyx')) | ||
63 | + trans_probe = np.array(probe[6:9]).astype(float) | ||
64 | + coord1 = np.hstack((trans_probe, angles_probe)) | ||
65 | + | ||
66 | + ref = trck.ref.decode(const.FS_ENCODE).split(',') | ||
67 | + angles_ref = np.degrees(tr.euler_from_quaternion(ref[2:6], axes='rzyx')) | ||
68 | + trans_ref = np.array(ref[6:9]).astype(float) | ||
69 | + coord2 = np.hstack((trans_ref, angles_ref)) | ||
70 | + | ||
71 | + obj = trck.obj.decode(const.FS_ENCODE).split(',') | ||
72 | + angles_obj = np.degrees(tr.euler_from_quaternion(obj[2:6], axes='rzyx')) | ||
73 | + trans_obj = np.array(obj[6:9]).astype(float) | ||
74 | + coord3 = np.hstack((trans_obj, angles_obj)) | ||
75 | + | ||
76 | + coord = np.vstack([coord1, coord2, coord3]) | ||
77 | + Publisher.sendMessage('Sensors ID', probe_id=trck.probeID, ref_id=trck.refID, obj_id=trck.objID) | ||
78 | + | ||
79 | + return coord | ||
80 | + | ||
81 | +def CameraCoord(trck_init, trck_id, ref_mode): | ||
82 | + trck = trck_init[0] | ||
83 | + coord, probeID, refID = trck.Run() | ||
84 | + Publisher.sendMessage('Sensors ID', probe_id=probeID, ref_id=refID) | ||
85 | + return coord | ||
54 | 86 | ||
55 | def ClaronCoord(trck_init, trck_id, ref_mode): | 87 | def ClaronCoord(trck_init, trck_id, ref_mode): |
56 | trck = trck_init[0] | 88 | trck = trck_init[0] |
@@ -214,7 +246,7 @@ def DebugCoord(trk_init, trck_id, ref_mode): | @@ -214,7 +246,7 @@ def DebugCoord(trk_init, trck_id, ref_mode): | ||
214 | coord4 = np.array([uniform(1, 200), uniform(1, 200), uniform(1, 200), | 246 | coord4 = np.array([uniform(1, 200), uniform(1, 200), uniform(1, 200), |
215 | uniform(-180.0, 180.0), uniform(-180.0, 180.0), uniform(-180.0, 180.0)]) | 247 | uniform(-180.0, 180.0), uniform(-180.0, 180.0), uniform(-180.0, 180.0)]) |
216 | 248 | ||
217 | - Publisher.sendMessage('Sensors ID', probe_id=int(uniform(0, 5)), ref_id=int(uniform(0, 5))) | 249 | + Publisher.sendMessage('Sensors ID', probe_id=int(uniform(0, 5)), ref_id=int(uniform(0, 5)), obj_id=int(uniform(0, 5))) |
218 | 250 | ||
219 | return np.vstack([coord1, coord2, coord3, coord4]) | 251 | return np.vstack([coord1, coord2, coord3, coord4]) |
220 | 252 |
invesalius/data/surface.py
@@ -313,6 +313,7 @@ class SurfaceManager(): | @@ -313,6 +313,7 @@ class SurfaceManager(): | ||
313 | reader = vtk.vtkSTLReader() | 313 | reader = vtk.vtkSTLReader() |
314 | elif filename.lower().endswith('.ply'): | 314 | elif filename.lower().endswith('.ply'): |
315 | reader = vtk.vtkPLYReader() | 315 | reader = vtk.vtkPLYReader() |
316 | + scalar = True | ||
316 | elif filename.lower().endswith('.obj'): | 317 | elif filename.lower().endswith('.obj'): |
317 | reader = vtk.vtkOBJReader() | 318 | reader = vtk.vtkOBJReader() |
318 | elif filename.lower().endswith('.vtp'): | 319 | elif filename.lower().endswith('.vtp'): |
invesalius/data/trackers.py
@@ -16,7 +16,8 @@ | @@ -16,7 +16,8 @@ | ||
16 | # PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais | 16 | # PARTICULAR. Consulte a Licenca Publica Geral GNU para obter mais |
17 | # detalhes. | 17 | # detalhes. |
18 | #-------------------------------------------------------------------------- | 18 | #-------------------------------------------------------------------------- |
19 | - | 19 | +import invesalius.constants as const |
20 | +import invesalius.gui.dialogs as dlg | ||
20 | # TODO: Disconnect tracker when a new one is connected | 21 | # TODO: Disconnect tracker when a new one is connected |
21 | # TODO: Test if there are too many prints when connection fails | 22 | # TODO: Test if there are too many prints when connection fails |
22 | 23 | ||
@@ -32,11 +33,13 @@ def TrackerConnection(tracker_id, trck_init, action): | @@ -32,11 +33,13 @@ def TrackerConnection(tracker_id, trck_init, action): | ||
32 | """ | 33 | """ |
33 | 34 | ||
34 | if action == 'connect': | 35 | if action == 'connect': |
35 | - trck_fcn = {1: ClaronTracker, | ||
36 | - 2: PolhemusTracker, # FASTRAK | ||
37 | - 3: PolhemusTracker, # ISOTRAK | ||
38 | - 4: PolhemusTracker, # PATRIOT | ||
39 | - 5: DebugTracker} | 36 | + trck_fcn = {const.MTC: ClaronTracker, |
37 | + const.FASTRAK: PolhemusTracker, # FASTRAK | ||
38 | + const.ISOTRAKII: PolhemusTracker, # ISOTRAK | ||
39 | + const.PATRIOT: PolhemusTracker, # PATRIOT | ||
40 | + const.CAMERA: CameraTracker, # CAMERA | ||
41 | + const.POLARIS: PolarisTracker, # POLARIS | ||
42 | + const.DEBUGTRACK: DebugTracker} | ||
40 | 43 | ||
41 | trck_init = trck_fcn[tracker_id](tracker_id) | 44 | trck_init = trck_fcn[tracker_id](tracker_id) |
42 | 45 | ||
@@ -58,6 +61,48 @@ def DefaultTracker(tracker_id): | @@ -58,6 +61,48 @@ def DefaultTracker(tracker_id): | ||
58 | # return tracker initialization variable and type of connection | 61 | # return tracker initialization variable and type of connection |
59 | return trck_init, 'wrapper' | 62 | return trck_init, 'wrapper' |
60 | 63 | ||
64 | +def PolarisTracker(tracker_id): | ||
65 | + from wx import ID_OK | ||
66 | + trck_init = None | ||
67 | + dlg_port = dlg.SetNDIconfigs() | ||
68 | + if dlg_port.ShowModal() == ID_OK: | ||
69 | + com_port, PROBE_DIR, REF_DIR, OBJ_DIR = dlg_port.GetValue() | ||
70 | + try: | ||
71 | + import pypolaris | ||
72 | + lib_mode = 'wrapper' | ||
73 | + trck_init = pypolaris.pypolaris() | ||
74 | + | ||
75 | + if trck_init.Initialize(com_port, PROBE_DIR, REF_DIR, OBJ_DIR) != 0: | ||
76 | + trck_init = None | ||
77 | + lib_mode = None | ||
78 | + print('Could not connect to default tracker.') | ||
79 | + else: | ||
80 | + print('Connect to polaris tracking device.') | ||
81 | + | ||
82 | + except: | ||
83 | + lib_mode = 'error' | ||
84 | + trck_init = None | ||
85 | + print('Could not connect to default tracker.') | ||
86 | + else: | ||
87 | + lib_mode = None | ||
88 | + print('Could not connect to default tracker.') | ||
89 | + | ||
90 | + # return tracker initialization variable and type of connection | ||
91 | + return trck_init, lib_mode | ||
92 | + | ||
93 | +def CameraTracker(tracker_id): | ||
94 | + trck_init = None | ||
95 | + try: | ||
96 | + import invesalius.data.camera_tracker as cam | ||
97 | + trck_init = cam.camera() | ||
98 | + trck_init.Initialize() | ||
99 | + print('Connect to camera tracking device.') | ||
100 | + | ||
101 | + except: | ||
102 | + print('Could not connect to default tracker.') | ||
103 | + | ||
104 | + # return tracker initialization variable and type of connection | ||
105 | + return trck_init, 'wrapper' | ||
61 | 106 | ||
62 | def ClaronTracker(tracker_id): | 107 | def ClaronTracker(tracker_id): |
63 | import invesalius.constants as const | 108 | import invesalius.constants as const |
@@ -69,13 +114,13 @@ def ClaronTracker(tracker_id): | @@ -69,13 +114,13 @@ def ClaronTracker(tracker_id): | ||
69 | 114 | ||
70 | lib_mode = 'wrapper' | 115 | lib_mode = 'wrapper' |
71 | trck_init = pyclaron.pyclaron() | 116 | trck_init = pyclaron.pyclaron() |
72 | - trck_init.CalibrationDir = inv_paths.CAL_DIR.encode(const.FS_ENCODE) | ||
73 | - trck_init.MarkerDir = inv_paths.MAR_DIR.encode(const.FS_ENCODE) | 117 | + trck_init.CalibrationDir = inv_paths.MTC_CAL_DIR.encode(const.FS_ENCODE) |
118 | + trck_init.MarkerDir = inv_paths.MTC_MAR_DIR.encode(const.FS_ENCODE) | ||
74 | trck_init.NumberFramesProcessed = 1 | 119 | trck_init.NumberFramesProcessed = 1 |
75 | trck_init.FramesExtrapolated = 0 | 120 | trck_init.FramesExtrapolated = 0 |
76 | - trck_init.PROBE_NAME = const.PROBE_NAME.encode(const.FS_ENCODE) | ||
77 | - trck_init.REF_NAME = const.REF_NAME.encode(const.FS_ENCODE) | ||
78 | - trck_init.OBJ_NAME = const.OBJ_NAME.encode(const.FS_ENCODE) | 121 | + trck_init.PROBE_NAME = const.MTC_PROBE_NAME.encode(const.FS_ENCODE) |
122 | + trck_init.REF_NAME = const.MTC_REF_NAME.encode(const.FS_ENCODE) | ||
123 | + trck_init.OBJ_NAME = const.MTC_OBJ_NAME.encode(const.FS_ENCODE) | ||
79 | trck_init.Initialize() | 124 | trck_init.Initialize() |
80 | 125 | ||
81 | if trck_init.GetIdentifyingCamera(): | 126 | if trck_init.GetIdentifyingCamera(): |
@@ -146,25 +191,38 @@ def PlhWrapperConnection(tracker_id): | @@ -146,25 +191,38 @@ def PlhWrapperConnection(tracker_id): | ||
146 | 191 | ||
147 | def PlhSerialConnection(tracker_id): | 192 | def PlhSerialConnection(tracker_id): |
148 | import serial | 193 | import serial |
194 | + from wx import ID_OK | ||
195 | + trck_init = None | ||
196 | + dlg_port = dlg.SetCOMport() | ||
197 | + if dlg_port.ShowModal() == ID_OK: | ||
198 | + com_port = dlg_port.GetValue() | ||
199 | + try: | ||
200 | + trck_init = serial.Serial(com_port, baudrate=115200, timeout=0.03) | ||
201 | + | ||
202 | + if tracker_id == 2: | ||
203 | + # Polhemus FASTRAK needs configurations first | ||
204 | + trck_init.write(0x02, str.encode("u")) | ||
205 | + trck_init.write(0x02, str.encode("F")) | ||
206 | + elif tracker_id == 3: | ||
207 | + # Polhemus ISOTRAK needs to set tracking point from | ||
208 | + # center to tip. | ||
209 | + trck_init.write(str.encode("u")) | ||
210 | + trck_init.write(str.encode("F")) | ||
211 | + trck_init.write(str.encode("Y")) | ||
212 | + | ||
213 | + trck_init.write(str.encode("P")) | ||
214 | + data = trck_init.readlines() | ||
215 | + if not data: | ||
216 | + trck_init = None | ||
217 | + print('Could not connect to Polhemus serial without error.') | ||
149 | 218 | ||
150 | - trck_init = serial.Serial('COM3', baudrate=115200, timeout=0.03) | ||
151 | - | ||
152 | - if tracker_id == 2: | ||
153 | - # Polhemus FASTRAK needs configurations first | ||
154 | - trck_init.write(0x02, str.encode("u")) | ||
155 | - trck_init.write(0x02, str.encode("F")) | ||
156 | - elif tracker_id == 3: | ||
157 | - # Polhemus ISOTRAK needs to set tracking point from | ||
158 | - # center to tip. | ||
159 | - trck_init.write(str.encode("u")) | ||
160 | - trck_init.write(str.encode("F")) | ||
161 | - trck_init.write(str.encode("Y")) | ||
162 | - | ||
163 | - trck_init.write(str.encode("P")) | ||
164 | - data = trck_init.readlines() | ||
165 | - if not data: | ||
166 | - trck_init = None | ||
167 | - print('Could not connect to Polhemus serial without error.') | 219 | + except: |
220 | + lib_mode = 'error' | ||
221 | + trck_init = None | ||
222 | + print('Could not connect to default tracker.') | ||
223 | + else: | ||
224 | + lib_mode = None | ||
225 | + print('Could not connect to default tracker.') | ||
168 | 226 | ||
169 | return trck_init | 227 | return trck_init |
170 | 228 | ||
@@ -211,13 +269,13 @@ def DisconnectTracker(tracker_id, trck_init): | @@ -211,13 +269,13 @@ def DisconnectTracker(tracker_id, trck_init): | ||
211 | :param trck_init: Initialization variable of tracking device. | 269 | :param trck_init: Initialization variable of tracking device. |
212 | """ | 270 | """ |
213 | 271 | ||
214 | - if tracker_id == 5: | 272 | + if tracker_id == const.DEBUGTRACK: |
215 | trck_init = False | 273 | trck_init = False |
216 | lib_mode = 'debug' | 274 | lib_mode = 'debug' |
217 | print('Debug tracker disconnected.') | 275 | print('Debug tracker disconnected.') |
218 | else: | 276 | else: |
219 | try: | 277 | try: |
220 | - if tracker_id == 3: | 278 | + if tracker_id == const.ISOTRAKII: |
221 | trck_init.close() | 279 | trck_init.close() |
222 | trck_init = False | 280 | trck_init = False |
223 | lib_mode = 'serial' | 281 | lib_mode = 'serial' |
invesalius/data/viewer_volume.py
@@ -172,8 +172,9 @@ class Viewer(wx.Panel): | @@ -172,8 +172,9 @@ class Viewer(wx.Panel): | ||
172 | self._to_show_ball = 0 | 172 | self._to_show_ball = 0 |
173 | self._ball_ref_visibility = False | 173 | self._ball_ref_visibility = False |
174 | 174 | ||
175 | - self.sen1 = False | ||
176 | - self.sen2 = False | 175 | + self.probe = False |
176 | + self.ref = False | ||
177 | + self.obj = False | ||
177 | 178 | ||
178 | self.timer = False | 179 | self.timer = False |
179 | self.index = False | 180 | self.index = False |
@@ -325,8 +326,8 @@ class Viewer(wx.Panel): | @@ -325,8 +326,8 @@ class Viewer(wx.Panel): | ||
325 | self.RemoveBallReference() | 326 | self.RemoveBallReference() |
326 | self.interactor.Render() | 327 | self.interactor.Render() |
327 | 328 | ||
328 | - def OnSensors(self, probe_id, ref_id): | ||
329 | - if not self.sen1: | 329 | + def OnSensors(self, probe_id, ref_id, obj_id=0): |
330 | + if not self.probe: | ||
330 | self.CreateSensorID() | 331 | self.CreateSensorID() |
331 | 332 | ||
332 | if probe_id: | 333 | if probe_id: |
@@ -337,35 +338,49 @@ class Viewer(wx.Panel): | @@ -337,35 +338,49 @@ class Viewer(wx.Panel): | ||
337 | colour2 = (0, 1, 0) | 338 | colour2 = (0, 1, 0) |
338 | else: | 339 | else: |
339 | colour2 = (1, 0, 0) | 340 | colour2 = (1, 0, 0) |
341 | + if obj_id: | ||
342 | + colour3 = (0, 1, 0) | ||
343 | + else: | ||
344 | + colour3 = (1, 0, 0) | ||
340 | 345 | ||
341 | - self.sen1.SetColour(colour1) | ||
342 | - self.sen2.SetColour(colour2) | 346 | + self.probe.SetColour(colour1) |
347 | + self.ref.SetColour(colour2) | ||
348 | + self.obj.SetColour(colour3) | ||
343 | self.Refresh() | 349 | self.Refresh() |
344 | 350 | ||
345 | def CreateSensorID(self): | 351 | def CreateSensorID(self): |
346 | - sen1 = vtku.Text() | ||
347 | - sen1.SetSize(const.TEXT_SIZE_LARGE) | ||
348 | - sen1.SetPosition((const.X, const.Y)) | ||
349 | - sen1.ShadowOff() | ||
350 | - sen1.SetValue("O") | ||
351 | - self.sen1 = sen1 | ||
352 | - self.ren.AddActor(sen1.actor) | ||
353 | - | ||
354 | - sen2 = vtku.Text() | ||
355 | - sen2.SetSize(const.TEXT_SIZE_LARGE) | ||
356 | - sen2.SetPosition((const.X+0.04, const.Y)) | ||
357 | - sen2.ShadowOff() | ||
358 | - sen2.SetValue("O") | ||
359 | - self.sen2 = sen2 | ||
360 | - self.ren.AddActor(sen2.actor) | 352 | + probe = vtku.Text() |
353 | + probe.SetSize(const.TEXT_SIZE_LARGE) | ||
354 | + probe.SetPosition((const.X, const.Y)) | ||
355 | + probe.ShadowOff() | ||
356 | + probe.SetValue("P") | ||
357 | + self.probe = probe | ||
358 | + self.ren.AddActor(probe.actor) | ||
359 | + | ||
360 | + ref = vtku.Text() | ||
361 | + ref.SetSize(const.TEXT_SIZE_LARGE) | ||
362 | + ref.SetPosition((const.X+0.04, const.Y)) | ||
363 | + ref.ShadowOff() | ||
364 | + ref.SetValue("R") | ||
365 | + self.ref = ref | ||
366 | + self.ren.AddActor(ref.actor) | ||
367 | + | ||
368 | + obj = vtku.Text() | ||
369 | + obj.SetSize(const.TEXT_SIZE_LARGE) | ||
370 | + obj.SetPosition((const.X+0.08, const.Y)) | ||
371 | + obj.ShadowOff() | ||
372 | + obj.SetValue("O") | ||
373 | + self.obj = obj | ||
374 | + self.ren.AddActor(obj.actor) | ||
361 | 375 | ||
362 | self.interactor.Render() | 376 | self.interactor.Render() |
363 | 377 | ||
364 | def OnRemoveSensorsID(self): | 378 | def OnRemoveSensorsID(self): |
365 | - if self.sen1: | ||
366 | - self.ren.RemoveActor(self.sen1.actor) | ||
367 | - self.ren.RemoveActor(self.sen2.actor) | ||
368 | - self.sen1 = self.sen2 = False | 379 | + if self.probe: |
380 | + self.ren.RemoveActor(self.probe.actor) | ||
381 | + self.ren.RemoveActor(self.ref.actor) | ||
382 | + self.ren.RemoveActor(self.obj.actor) | ||
383 | + self.probe = self.ref = self.obj = False | ||
369 | self.interactor.Render() | 384 | self.interactor.Render() |
370 | 385 | ||
371 | def OnShowSurface(self, index, visibility): | 386 | def OnShowSurface(self, index, visibility): |
@@ -708,7 +723,7 @@ class Viewer(wx.Panel): | @@ -708,7 +723,7 @@ class Viewer(wx.Panel): | ||
708 | (self.target_coord[0], -self.target_coord[1], self.target_coord[2])) | 723 | (self.target_coord[0], -self.target_coord[1], self.target_coord[2])) |
709 | 724 | ||
710 | # self.txt.SetCoilDistanceValue(target_dist) | 725 | # self.txt.SetCoilDistanceValue(target_dist) |
711 | - self.textSource.SetText('Dist: ' + str("{:06.2f}".format(target_dist)) + ' mm') | 726 | + self.tdist.SetValue('Distance: ' + str("{:06.2f}".format(target_dist)) + ' mm') |
712 | self.ren.ResetCamera() | 727 | self.ren.ResetCamera() |
713 | self.SetCameraTarget() | 728 | self.SetCameraTarget() |
714 | if target_dist > 100: | 729 | if target_dist > 100: |
@@ -819,9 +834,6 @@ class Viewer(wx.Panel): | @@ -819,9 +834,6 @@ class Viewer(wx.Panel): | ||
819 | self.ren2.AddActor(ind) | 834 | self.ren2.AddActor(ind) |
820 | 835 | ||
821 | 836 | ||
822 | - x, y, z = bases.flip_x(coord[0:3]) | ||
823 | - self.tactor.SetPosition(x-20, y-30, z+20) | ||
824 | - | ||
825 | self.Refresh() | 837 | self.Refresh() |
826 | 838 | ||
827 | def OnUpdateTargetCoordinates(self, coord): | 839 | def OnUpdateTargetCoordinates(self, coord): |
@@ -841,27 +853,6 @@ class Viewer(wx.Panel): | @@ -841,27 +853,6 @@ class Viewer(wx.Panel): | ||
841 | self.RemoveTargetAim() | 853 | self.RemoveTargetAim() |
842 | self.aim_actor = None | 854 | self.aim_actor = None |
843 | 855 | ||
844 | - self.textSource = vtk.vtkVectorText() | ||
845 | - mapper = vtk.vtkPolyDataMapper() | ||
846 | - mapper.SetInputConnection(self.textSource.GetOutputPort()) | ||
847 | - tactor = vtk.vtkFollower() | ||
848 | - tactor.SetMapper(mapper) | ||
849 | - tactor.GetProperty().SetColor(1.0, 0.25, 0.0) | ||
850 | - tactor.SetScale(5) | ||
851 | - #tactor.SetPosition(self.target_coord[0]+10, self.target_coord[1]+30, self.target_coord[2]+20) | ||
852 | - self.ren.AddActor(tactor) | ||
853 | - self.tactor = tactor | ||
854 | - tactor.SetCamera(self.ren.GetActiveCamera()) | ||
855 | - | ||
856 | - | ||
857 | - # v3, M_plane_inv = self.Plane(self.target_coord[0:3], self.pTarget) | ||
858 | - # mat4x4 = vtk.vtkMatrix4x4() | ||
859 | - # for i in range(4): | ||
860 | - # mat4x4.SetElement(i, 0, M_plane_inv[i][0]) | ||
861 | - # mat4x4.SetElement(i, 1, M_plane_inv[i][1]) | ||
862 | - # mat4x4.SetElement(i, 2, M_plane_inv[i][2]) | ||
863 | - # mat4x4.SetElement(i, 3, M_plane_inv[i][3]) | ||
864 | - | ||
865 | a, b, g = np.radians(self.target_coord[3:]) | 856 | a, b, g = np.radians(self.target_coord[3:]) |
866 | r_ref = tr.euler_matrix(a, b, g, 'sxyz') | 857 | r_ref = tr.euler_matrix(a, b, g, 'sxyz') |
867 | t_ref = tr.translation_matrix(self.target_coord[:3]) | 858 | t_ref = tr.translation_matrix(self.target_coord[:3]) |
@@ -885,7 +876,6 @@ class Viewer(wx.Panel): | @@ -885,7 +876,6 @@ class Viewer(wx.Panel): | ||
885 | # Transform the polydata | 876 | # Transform the polydata |
886 | transform = vtk.vtkTransform() | 877 | transform = vtk.vtkTransform() |
887 | transform.SetMatrix(m_img_vtk) | 878 | transform.SetMatrix(m_img_vtk) |
888 | - #transform.SetMatrix(mat4x4) | ||
889 | transformPD = vtk.vtkTransformPolyDataFilter() | 879 | transformPD = vtk.vtkTransformPolyDataFilter() |
890 | transformPD.SetTransform(transform) | 880 | transformPD.SetTransform(transform) |
891 | transformPD.SetInputConnection(reader.GetOutputPort()) | 881 | transformPD.SetInputConnection(reader.GetOutputPort()) |
@@ -934,24 +924,24 @@ class Viewer(wx.Panel): | @@ -934,24 +924,24 @@ class Viewer(wx.Panel): | ||
934 | def RemoveTargetAim(self): | 924 | def RemoveTargetAim(self): |
935 | self.ren.RemoveActor(self.aim_actor) | 925 | self.ren.RemoveActor(self.aim_actor) |
936 | self.ren.RemoveActor(self.dummy_coil_actor) | 926 | self.ren.RemoveActor(self.dummy_coil_actor) |
937 | - self.ren.RemoveActor(self.tactor) | ||
938 | self.Refresh() | 927 | self.Refresh() |
939 | 928 | ||
940 | def CreateTextDistance(self): | 929 | def CreateTextDistance(self): |
941 | - txt = vtku.Text() | ||
942 | - txt.SetSize(const.TEXT_SIZE_EXTRA_LARGE) | ||
943 | - txt.SetPosition((0.76, 0.05)) | ||
944 | - txt.ShadowOff() | ||
945 | - txt.BoldOn() | ||
946 | - self.txt = txt | ||
947 | - self.ren2.AddActor(txt.actor) | 930 | + tdist = vtku.Text() |
931 | + tdist.SetSize(const.TEXT_SIZE_LARGE) | ||
932 | + tdist.SetPosition((const.X, 1.03-const.Y)) | ||
933 | + tdist.ShadowOff() | ||
934 | + tdist.BoldOn() | ||
935 | + | ||
936 | + self.ren.AddActor(tdist.actor) | ||
937 | + self.tdist = tdist | ||
948 | 938 | ||
949 | def DisableCoilTracker(self): | 939 | def DisableCoilTracker(self): |
950 | try: | 940 | try: |
951 | self.ren.SetViewport(0, 0, 1, 1) | 941 | self.ren.SetViewport(0, 0, 1, 1) |
952 | self.interactor.GetRenderWindow().RemoveRenderer(self.ren2) | 942 | self.interactor.GetRenderWindow().RemoveRenderer(self.ren2) |
953 | self.SetViewAngle(const.VOL_FRONT) | 943 | self.SetViewAngle(const.VOL_FRONT) |
954 | - self.ren.RemoveActor(self.txt.actor) | 944 | + self.ren.RemoveActor(self.tdist.actor) |
955 | self.CreateTargetAim() | 945 | self.CreateTargetAim() |
956 | self.interactor.Render() | 946 | self.interactor.Render() |
957 | except: | 947 | except: |
invesalius/gui/dialogs.py
@@ -923,11 +923,13 @@ def NavigationTrackerWarning(trck_id, lib_mode): | @@ -923,11 +923,13 @@ def NavigationTrackerWarning(trck_id, lib_mode): | ||
923 | """ | 923 | """ |
924 | Spatial Tracker connection error | 924 | Spatial Tracker connection error |
925 | """ | 925 | """ |
926 | - trck = {1: 'Claron MicronTracker', | ||
927 | - 2: 'Polhemus FASTRAK', | ||
928 | - 3: 'Polhemus ISOTRAK', | ||
929 | - 4: 'Polhemus PATRIOT', | ||
930 | - 5: 'Debug tracker device'} | 926 | + trck = {const.MTC: 'Claron MicronTracker', |
927 | + const.FASTRAK: 'Polhemus FASTRAK', | ||
928 | + const.ISOTRAKII: 'Polhemus ISOTRAK', | ||
929 | + const.PATRIOT: 'Polhemus PATRIOT', | ||
930 | + const.CAMERA: 'CAMERA', | ||
931 | + const.POLARIS: 'NDI Polaris', | ||
932 | + const.DEBUGTRACK: 'Debug tracker device'} | ||
931 | 933 | ||
932 | if lib_mode == 'choose': | 934 | if lib_mode == 'choose': |
933 | msg = _('No tracking device selected') | 935 | msg = _('No tracking device selected') |
@@ -3351,7 +3353,7 @@ class ObjectCalibrationDialog(wx.Dialog): | @@ -3351,7 +3353,7 @@ class ObjectCalibrationDialog(wx.Dialog): | ||
3351 | choice_ref.SetToolTip(tooltip) | 3353 | choice_ref.SetToolTip(tooltip) |
3352 | choice_ref.Bind(wx.EVT_COMBOBOX, self.OnChoiceRefMode) | 3354 | choice_ref.Bind(wx.EVT_COMBOBOX, self.OnChoiceRefMode) |
3353 | choice_ref.Enable(0) | 3355 | choice_ref.Enable(0) |
3354 | - if self.tracker_id == const.MTC or self.tracker_id == const.FASTRAK or self.tracker_id == const.DEBUGTRACK: | 3356 | + if not (self.tracker_id == const.PATRIOT or self.tracker_id == const.ISOTRAKII): |
3355 | choice_ref.Enable(1) | 3357 | choice_ref.Enable(1) |
3356 | 3358 | ||
3357 | # ComboBox for sensor selection for FASTRAK | 3359 | # ComboBox for sensor selection for FASTRAK |
@@ -3778,3 +3780,135 @@ class GoToDialogScannerCoord(wx.Dialog): | @@ -3778,3 +3780,135 @@ class GoToDialogScannerCoord(wx.Dialog): | ||
3778 | def Close(self): | 3780 | def Close(self): |
3779 | wx.Dialog.Close(self) | 3781 | wx.Dialog.Close(self) |
3780 | self.Destroy() | 3782 | self.Destroy() |
3783 | + | ||
3784 | +class SetNDIconfigs(wx.Dialog): | ||
3785 | + def __init__(self, title=_("Setting NDI polaris configs:")): | ||
3786 | + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), -1, title, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT|wx.STAY_ON_TOP) | ||
3787 | + self._init_gui() | ||
3788 | + | ||
3789 | + def serial_ports(self): | ||
3790 | + """ Lists serial port names | ||
3791 | + """ | ||
3792 | + import serial.tools.list_ports | ||
3793 | + if sys.platform.startswith('win'): | ||
3794 | + ports = ([comport.device for comport in serial.tools.list_ports.comports()]) | ||
3795 | + else: | ||
3796 | + raise EnvironmentError('Unsupported platform') | ||
3797 | + return ports | ||
3798 | + | ||
3799 | + def _init_gui(self): | ||
3800 | + self.com_ports = wx.ComboBox(self, -1, style=wx.CB_DROPDOWN|wx.CB_READONLY) | ||
3801 | + row_com = wx.BoxSizer(wx.VERTICAL) | ||
3802 | + row_com.Add(wx.StaticText(self, wx.ID_ANY, "Select the COM port"), 0, wx.TOP|wx.RIGHT,5) | ||
3803 | + row_com.Add(self.com_ports, 0, wx.EXPAND) | ||
3804 | + | ||
3805 | + ports = self.serial_ports() | ||
3806 | + self.com_ports.Append(ports) | ||
3807 | + | ||
3808 | + self.dir_probe = wx.FilePickerCtrl(self, path=inv_paths.NDI_MAR_DIR_REF, style=wx.FLP_USE_TEXTCTRL|wx.FLP_SMALL, | ||
3809 | + wildcard="Rom files (*.rom)|*.rom", message="Select probe's rom file") | ||
3810 | + row_probe = wx.BoxSizer(wx.VERTICAL) | ||
3811 | + row_probe.Add(wx.StaticText(self, wx.ID_ANY, "Set probe's rom file"), 0, wx.TOP|wx.RIGHT, 5) | ||
3812 | + row_probe.Add(self.dir_probe, 0, wx.EXPAND|wx.ALIGN_CENTER) | ||
3813 | + | ||
3814 | + self.dir_ref = wx.FilePickerCtrl(self, path=inv_paths.NDI_MAR_DIR_REF, style=wx.FLP_USE_TEXTCTRL|wx.FLP_SMALL, | ||
3815 | + wildcard="Rom files (*.rom)|*.rom", message="Select reference's rom file") | ||
3816 | + row_ref = wx.BoxSizer(wx.VERTICAL) | ||
3817 | + row_ref.Add(wx.StaticText(self, wx.ID_ANY, "Set reference's rom file"), 0, wx.TOP | wx.RIGHT, 5) | ||
3818 | + row_ref.Add(self.dir_ref, 0, wx.EXPAND|wx.ALIGN_CENTER) | ||
3819 | + | ||
3820 | + self.dir_obj = wx.FilePickerCtrl(self, path=inv_paths.NDI_MAR_DIR_OBJ, style=wx.FLP_USE_TEXTCTRL|wx.FLP_SMALL, | ||
3821 | + wildcard="Rom files (*.rom)|*.rom", message="Select object's rom file") | ||
3822 | + #self.dir_probe.Bind(wx.EVT_FILEPICKER_CHANGED, self.Selected) | ||
3823 | + row_obj = wx.BoxSizer(wx.VERTICAL) | ||
3824 | + row_obj.Add(wx.StaticText(self, wx.ID_ANY, "Set object's rom file"), 0, wx.TOP|wx.RIGHT, 5) | ||
3825 | + row_obj.Add(self.dir_obj, 0, wx.EXPAND|wx.ALIGN_CENTER) | ||
3826 | + | ||
3827 | + # self.goto_orientation.SetSelection(cb_init) | ||
3828 | + | ||
3829 | + btn_ok = wx.Button(self, wx.ID_OK) | ||
3830 | + btn_ok.SetHelpText("") | ||
3831 | + btn_ok.SetDefault() | ||
3832 | + | ||
3833 | + btn_cancel = wx.Button(self, wx.ID_CANCEL) | ||
3834 | + btn_cancel.SetHelpText("") | ||
3835 | + | ||
3836 | + btnsizer = wx.StdDialogButtonSizer() | ||
3837 | + btnsizer.AddButton(btn_ok) | ||
3838 | + btnsizer.AddButton(btn_cancel) | ||
3839 | + btnsizer.Realize() | ||
3840 | + | ||
3841 | + main_sizer = wx.BoxSizer(wx.VERTICAL) | ||
3842 | + | ||
3843 | + main_sizer.Add((5, 5)) | ||
3844 | + main_sizer.Add(row_com, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 5) | ||
3845 | + main_sizer.Add((5, 5)) | ||
3846 | + main_sizer.Add(row_probe, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 5) | ||
3847 | + main_sizer.Add((5, 5)) | ||
3848 | + main_sizer.Add(row_ref, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 5) | ||
3849 | + main_sizer.Add((5, 5)) | ||
3850 | + main_sizer.Add(row_obj, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 5) | ||
3851 | + main_sizer.Add((15, 15)) | ||
3852 | + main_sizer.Add(btnsizer, 0, wx.EXPAND) | ||
3853 | + main_sizer.Add((5, 5)) | ||
3854 | + | ||
3855 | + self.SetSizer(main_sizer) | ||
3856 | + main_sizer.Fit(self) | ||
3857 | + | ||
3858 | + self.CenterOnParent() | ||
3859 | + | ||
3860 | + def GetValue(self): | ||
3861 | + return self.com_ports.GetString(self.com_ports.GetSelection()).encode(const.FS_ENCODE), \ | ||
3862 | + self.dir_probe.GetPath().encode(const.FS_ENCODE),\ | ||
3863 | + self.dir_ref.GetPath().encode(const.FS_ENCODE), \ | ||
3864 | + self.dir_obj.GetPath().encode(const.FS_ENCODE) | ||
3865 | + | ||
3866 | +class SetCOMport(wx.Dialog): | ||
3867 | + def __init__(self, title=_("Select COM port")): | ||
3868 | + wx.Dialog.__init__(self, wx.GetApp().GetTopWindow(), -1, title, style=wx.DEFAULT_DIALOG_STYLE|wx.FRAME_FLOAT_ON_PARENT|wx.STAY_ON_TOP) | ||
3869 | + self._init_gui() | ||
3870 | + | ||
3871 | + def serial_ports(self): | ||
3872 | + """ Lists serial port names | ||
3873 | + """ | ||
3874 | + import serial.tools.list_ports | ||
3875 | + if sys.platform.startswith('win'): | ||
3876 | + ports = ([comport.device for comport in serial.tools.list_ports.comports()]) | ||
3877 | + else: | ||
3878 | + raise EnvironmentError('Unsupported platform') | ||
3879 | + return ports | ||
3880 | + | ||
3881 | + def _init_gui(self): | ||
3882 | + self.com_ports = wx.ComboBox(self, -1, style=wx.CB_DROPDOWN|wx.CB_READONLY) | ||
3883 | + ports = self.serial_ports() | ||
3884 | + self.com_ports.Append(ports) | ||
3885 | + | ||
3886 | + # self.goto_orientation.SetSelection(cb_init) | ||
3887 | + | ||
3888 | + btn_ok = wx.Button(self, wx.ID_OK) | ||
3889 | + btn_ok.SetHelpText("") | ||
3890 | + btn_ok.SetDefault() | ||
3891 | + | ||
3892 | + btn_cancel = wx.Button(self, wx.ID_CANCEL) | ||
3893 | + btn_cancel.SetHelpText("") | ||
3894 | + | ||
3895 | + btnsizer = wx.StdDialogButtonSizer() | ||
3896 | + btnsizer.AddButton(btn_ok) | ||
3897 | + btnsizer.AddButton(btn_cancel) | ||
3898 | + btnsizer.Realize() | ||
3899 | + | ||
3900 | + main_sizer = wx.BoxSizer(wx.VERTICAL) | ||
3901 | + | ||
3902 | + main_sizer.Add((5, 5)) | ||
3903 | + main_sizer.Add(self.com_ports, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 5) | ||
3904 | + main_sizer.Add((5, 5)) | ||
3905 | + main_sizer.Add(btnsizer, 0, wx.EXPAND) | ||
3906 | + main_sizer.Add((5, 5)) | ||
3907 | + | ||
3908 | + self.SetSizer(main_sizer) | ||
3909 | + main_sizer.Fit(self) | ||
3910 | + | ||
3911 | + self.CenterOnParent() | ||
3912 | + | ||
3913 | + def GetValue(self): | ||
3914 | + return self.com_ports.GetString(self.com_ports.GetSelection()) | ||
3781 | \ No newline at end of file | 3915 | \ No newline at end of file |
invesalius/gui/task_navigator.py
@@ -453,7 +453,7 @@ class NeuronavigationPanel(wx.Panel): | @@ -453,7 +453,7 @@ class NeuronavigationPanel(wx.Panel): | ||
453 | if hasattr(evt, 'GetSelection'): | 453 | if hasattr(evt, 'GetSelection'): |
454 | choice = evt.GetSelection() | 454 | choice = evt.GetSelection() |
455 | else: | 455 | else: |
456 | - choice = 6 | 456 | + choice = const.DISCTRACK |
457 | 457 | ||
458 | if self.trk_init: | 458 | if self.trk_init: |
459 | trck = self.trk_init[0] | 459 | trck = self.trk_init[0] |
@@ -462,7 +462,7 @@ class NeuronavigationPanel(wx.Panel): | @@ -462,7 +462,7 @@ class NeuronavigationPanel(wx.Panel): | ||
462 | 462 | ||
463 | # Conditions check if click was on current selection and if any other tracker | 463 | # Conditions check if click was on current selection and if any other tracker |
464 | # has been initialized before | 464 | # has been initialized before |
465 | - if trck and choice != 6: | 465 | + if trck and choice != const.DISCTRACK: |
466 | self.ResetTrackerFiducials() | 466 | self.ResetTrackerFiducials() |
467 | Publisher.sendMessage('Update status text in GUI', | 467 | Publisher.sendMessage('Update status text in GUI', |
468 | label=_("Disconnecting tracker...")) | 468 | label=_("Disconnecting tracker...")) |
@@ -480,7 +480,7 @@ class NeuronavigationPanel(wx.Panel): | @@ -480,7 +480,7 @@ class NeuronavigationPanel(wx.Panel): | ||
480 | else: | 480 | else: |
481 | ctrl.SetSelection(self.tracker_id) | 481 | ctrl.SetSelection(self.tracker_id) |
482 | print("Tracker connected!") | 482 | print("Tracker connected!") |
483 | - elif choice == 6: | 483 | + elif choice == const.DISCTRACK: |
484 | if trck: | 484 | if trck: |
485 | self.ResetTrackerFiducials() | 485 | self.ResetTrackerFiducials() |
486 | Publisher.sendMessage('Update status text in GUI', | 486 | Publisher.sendMessage('Update status text in GUI', |
invesalius/inv_paths.py
@@ -49,9 +49,14 @@ else: | @@ -49,9 +49,14 @@ else: | ||
49 | ) | 49 | ) |
50 | 50 | ||
51 | # Navigation paths | 51 | # Navigation paths |
52 | -CAL_DIR = INV_TOP_DIR.joinpath("navigation", "mtc_files", "CalibrationFiles") | ||
53 | -MAR_DIR = INV_TOP_DIR.joinpath("navigation", "mtc_files", "Markers") | ||
54 | -OBJ_DIR = INV_TOP_DIR.joinpath("navigation", "objects") | 52 | +OBJ_DIR = str(INV_TOP_DIR.joinpath("navigation", "objects")) |
53 | + | ||
54 | +MTC_CAL_DIR = str(INV_TOP_DIR.joinpath("navigation", "mtc_files", "CalibrationFiles")) | ||
55 | +MTC_MAR_DIR = str(INV_TOP_DIR.joinpath("navigation", "mtc_files", "Markers")) | ||
56 | + | ||
57 | +NDI_MAR_DIR_PROBE = str(INV_TOP_DIR.joinpath("navigation", "ndi_files", "Markers", "8700340.rom")) | ||
58 | +NDI_MAR_DIR_REF = str(INV_TOP_DIR.joinpath("navigation", "ndi_files", "Markers", "8700339.rom")) | ||
59 | +NDI_MAR_DIR_OBJ = str(INV_TOP_DIR.joinpath("navigation", "ndi_files", "Markers", "8700338.rom")) | ||
55 | 60 | ||
56 | # MAC App | 61 | # MAC App |
57 | if not os.path.exists(ICON_DIR): | 62 | if not os.path.exists(ICON_DIR): |
@@ -0,0 +1,39 @@ | @@ -0,0 +1,39 @@ | ||
1 | + | ||
2 | +[Marker] | ||
3 | +FacetsCount=1 | ||
4 | +SliderControlledXpointsCount=0 | ||
5 | +Name=3Coil_big | ||
6 | + | ||
7 | +[Facet1] | ||
8 | +VectorsCount=2 | ||
9 | + | ||
10 | +[Facet1V1] | ||
11 | +EndPos(0,0)=-12.130921665071337 | ||
12 | +EndPos(0,1)=4.771099944171531e-005 | ||
13 | +EndPos(0,2)=-1.6777868612989378e-016 | ||
14 | +EndPos(1,0)=12.131083622124752 | ||
15 | +EndPos(1,1)=1.0800131569805988e-004 | ||
16 | +EndPos(1,2)=-2.4831245547224282e-015 | ||
17 | + | ||
18 | +[Facet1V2] | ||
19 | +EndPos(0,0)=-12.143021882072084 | ||
20 | +EndPos(0,1)=-16.190735690907974 | ||
21 | +EndPos(0,2)=-1.3422294890391503e-015 | ||
22 | +EndPos(1,0)=-12.130921665071337 | ||
23 | +EndPos(1,1)=4.771099944171531e-005 | ||
24 | +EndPos(1,2)=-1.6777868612989378e-016 | ||
25 | + | ||
26 | +[Tooltip2MarkerXf] | ||
27 | +Scale=1. | ||
28 | +S0=0. | ||
29 | +R0,0=1. | ||
30 | +R1,0=0. | ||
31 | +R2,0=0. | ||
32 | +S1=0. | ||
33 | +R0,1=0. | ||
34 | +R1,1=1. | ||
35 | +R2,1=0. | ||
36 | +S2=0. | ||
37 | +R0,2=0. | ||
38 | +R1,2=0. | ||
39 | +R2,2=1. |
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type