Commit dca44b9bc7a095f9bf4d7f3f3e9edaf70fe16e4f
Committed by
GitHub
1 parent
011095a8
Exists in
master
Now the Canvas does not have direct access to the measurements, it is responsibi…
…lity of the viewer to add to the canvas what it needs to render.(#43) Better doc The canvas does not have direct access to the measurements More generic code. The canvas only receives the renderers not the viewer.
Showing
2 changed files
with
68 additions
and
19 deletions
Show diff stats
invesalius/data/measures.py
... | ... | @@ -575,7 +575,7 @@ class LinearMeasure(object): |
575 | 575 | points = [] |
576 | 576 | for p in self.points: |
577 | 577 | coord.SetValue(p) |
578 | - cx, cy = coord.GetComputedDisplayValue(canvas.viewer.slice_data.renderer) | |
578 | + cx, cy = coord.GetComputedDisplayValue(canvas.evt_renderer) | |
579 | 579 | # canvas.draw_circle((cx, cy), 2.5) |
580 | 580 | points.append((cx, cy)) |
581 | 581 | |
... | ... | @@ -835,7 +835,8 @@ class AngularMeasure(object): |
835 | 835 | points = [] |
836 | 836 | for p in self.points: |
837 | 837 | coord.SetValue(p) |
838 | - cx, cy = coord.GetComputedDisplayValue(canvas.viewer.slice_data.renderer) | |
838 | + cx, cy = coord.GetComputedDoubleDisplayValue(canvas.evt_renderer) | |
839 | + print cx, cy | |
839 | 840 | # canvas.draw_circle((cx, cy), 2.5) |
840 | 841 | points.append((cx, cy)) |
841 | 842 | ... | ... |
invesalius/data/viewer_slice.py
... | ... | @@ -148,15 +148,30 @@ class ContourMIPConfig(wx.Panel): |
148 | 148 | |
149 | 149 | |
150 | 150 | class CanvasRendererCTX: |
151 | - def __init__(self, viewer): | |
152 | - self.viewer = viewer | |
153 | - self.canvas_renderer = viewer.slice_data.canvas_renderer | |
151 | + def __init__(self, evt_renderer, canvas_renderer): | |
152 | + """ | |
153 | + A Canvas to render over a vtktRenderer. | |
154 | + | |
155 | + Params: | |
156 | + evt_renderer: a vtkRenderer which this class is going to watch for | |
157 | + any render event to update the canvas content. | |
158 | + canvas_renderer: the vtkRenderer where the canvas is going to be | |
159 | + added. | |
160 | + | |
161 | + This class uses wx.GraphicsContext to render to a vtkImage. | |
162 | + | |
163 | + TODO: Verify why in Windows the color are strange when using transparency. | |
164 | + TODO: Add support to evento (ex. click on a square) | |
165 | + """ | |
166 | + self.canvas_renderer = canvas_renderer | |
167 | + self.evt_renderer = evt_renderer | |
154 | 168 | self._size = self.canvas_renderer.GetSize() |
169 | + self.draw_list = [] | |
155 | 170 | self.gc = None |
156 | 171 | self.last_cam_modif_time = -1 |
157 | 172 | self.modified = True |
158 | 173 | self._init_canvas() |
159 | - viewer.slice_data.renderer.AddObserver("StartEvent", self.OnPaint) | |
174 | + evt_renderer.AddObserver("StartEvent", self.OnPaint) | |
160 | 175 | |
161 | 176 | def _init_canvas(self): |
162 | 177 | w, h = self._size |
... | ... | @@ -203,7 +218,7 @@ class CanvasRendererCTX: |
203 | 218 | self._size = size |
204 | 219 | self._resize_canvas(w, h) |
205 | 220 | |
206 | - cam_modif_time = self.viewer.cam.GetMTime() | |
221 | + cam_modif_time = self.evt_renderer.GetActiveCamera().GetMTime() | |
207 | 222 | if (not self.modified) and cam_modif_time == self.last_cam_modif_time: |
208 | 223 | return |
209 | 224 | |
... | ... | @@ -233,10 +248,8 @@ class CanvasRendererCTX: |
233 | 248 | gc.Scale(1, -1) |
234 | 249 | |
235 | 250 | modified = False |
236 | - for (m, mr) in self.viewer.measures.get(self.viewer.orientation, self.viewer.slice_data.number): | |
237 | - if not m.visible: | |
238 | - continue | |
239 | - mr.draw_to_canvas(gc, self) | |
251 | + for d in self.draw_list: | |
252 | + d.draw_to_canvas(gc, self) | |
240 | 253 | modified = True |
241 | 254 | |
242 | 255 | gc.Destroy() |
... | ... | @@ -250,6 +263,30 @@ class CanvasRendererCTX: |
250 | 263 | self._cv_image.Modified() |
251 | 264 | self.modified = False |
252 | 265 | |
266 | + def calc_text_size(self, text, font=None): | |
267 | + """ | |
268 | + Given an unicode text and a font returns the width and height of the | |
269 | + rendered text in pixels. | |
270 | + | |
271 | + Params: | |
272 | + text: An unicode text. | |
273 | + font: An wxFont. | |
274 | + | |
275 | + Returns: | |
276 | + A tuple with width and height values in pixels | |
277 | + """ | |
278 | + if self.gc is None: | |
279 | + return None | |
280 | + gc = self.gc | |
281 | + | |
282 | + if font is None: | |
283 | + font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) | |
284 | + | |
285 | + _font = gc.CreateFont(font) | |
286 | + gc.SetFont(_font) | |
287 | + w, h = gc.GetTextExtent(text) | |
288 | + return w, h | |
289 | + | |
253 | 290 | def draw_line(self, pos0, pos1, arrow_start=False, arrow_end=False, colour=(255, 0, 0, 128), width=2, style=wx.SOLID): |
254 | 291 | """ |
255 | 292 | Draw a line from pos0 to pos1 |
... | ... | @@ -1224,7 +1261,7 @@ class Viewer(wx.Panel): |
1224 | 1261 | self.cam = self.slice_data.renderer.GetActiveCamera() |
1225 | 1262 | self.__build_cross_lines() |
1226 | 1263 | |
1227 | - self.canvas = CanvasRendererCTX(self) | |
1264 | + self.canvas = CanvasRendererCTX(self.slice_data.renderer, self.slice_data.canvas_renderer) | |
1228 | 1265 | |
1229 | 1266 | # Set the slice number to the last slice to ensure the camera if far |
1230 | 1267 | # enough to show all slices. |
... | ... | @@ -1341,6 +1378,16 @@ class Viewer(wx.Panel): |
1341 | 1378 | self.interactor.Render() |
1342 | 1379 | |
1343 | 1380 | def UpdateCanvas(self, evt=None): |
1381 | + for (m, mr) in self.measures.get(self.orientation, self.slice_data.number): | |
1382 | + try: | |
1383 | + self.canvas.draw_list.remove(mr) | |
1384 | + except ValueError: | |
1385 | + pass | |
1386 | + | |
1387 | + for (m, mr) in self.measures.get(self.orientation, self.slice_data.number): | |
1388 | + if m.visible: | |
1389 | + self.canvas.draw_list.append(mr) | |
1390 | + | |
1344 | 1391 | self.canvas.modified = True |
1345 | 1392 | self.interactor.Render() |
1346 | 1393 | |
... | ... | @@ -1530,14 +1577,15 @@ class Viewer(wx.Panel): |
1530 | 1577 | for actor in self.actors_by_slice_number[index]: |
1531 | 1578 | self.slice_data.renderer.AddActor(actor) |
1532 | 1579 | |
1533 | - # for (m, mr) in self.measures.get(self.orientation, self.slice_data.number): | |
1534 | - # for actor in mr.GetActors(): | |
1535 | - # self.slice_data.renderer.RemoveActor(actor) | |
1580 | + for (m, mr) in self.measures.get(self.orientation, self.slice_data.number): | |
1581 | + try: | |
1582 | + self.canvas.draw_list.remove(mr) | |
1583 | + except ValueError: | |
1584 | + pass | |
1536 | 1585 | |
1537 | - # for (m, mr) in self.measures.get(self.orientation, index): | |
1538 | - # mr.renderer = self.slice_data.renderer | |
1539 | - # for actor in mr.GetActors(): | |
1540 | - # self.slice_data.renderer.AddActor(actor) | |
1586 | + for (m, mr) in self.measures.get(self.orientation, index): | |
1587 | + if m.visible: | |
1588 | + self.canvas.draw_list.append(mr) | |
1541 | 1589 | |
1542 | 1590 | if self.slice_._type_projection == const.PROJECTION_NORMAL: |
1543 | 1591 | self.slice_data.SetNumber(index) | ... | ... |