Commit 3e4ed11ddd539f45e2800e17665c4f4bff817166

Authored by Thiago Franco de Moraes
Committed by GitHub
1 parent ccf02f83
Exists in master

Create border closed (#149)

* Created a function to pad image

* taking padding in consideration when converting to vtk

* Better normals computation

* Added option to close border holes
invesalius/data/converters.py
@@ -21,7 +21,7 @@ import numpy @@ -21,7 +21,7 @@ import numpy
21 import vtk 21 import vtk
22 from vtk.util import numpy_support 22 from vtk.util import numpy_support
23 23
24 -def to_vtk(n_array, spacing, slice_number, orientation): 24 +def to_vtk(n_array, spacing, slice_number, orientation, origin=(0, 0, 0), padding=(0, 0, 0)):
25 25
26 if orientation == "SAGITTAL": 26 if orientation == "SAGITTAL":
27 orientation = "SAGITAL" 27 orientation = "SAGITAL"
@@ -32,20 +32,22 @@ def to_vtk(n_array, spacing, slice_number, orientation): @@ -32,20 +32,22 @@ def to_vtk(n_array, spacing, slice_number, orientation):
32 dy, dx = n_array.shape 32 dy, dx = n_array.shape
33 dz = 1 33 dz = 1
34 34
  35 + px, py, pz = padding
  36 +
35 v_image = numpy_support.numpy_to_vtk(n_array.flat) 37 v_image = numpy_support.numpy_to_vtk(n_array.flat)
36 38
37 if orientation == 'AXIAL': 39 if orientation == 'AXIAL':
38 - extent = (0, dx -1, 0, dy -1, slice_number, slice_number + dz - 1) 40 + extent = (0 - px , dx -1 - px, 0 - py, dy - 1 - py, slice_number - pz, slice_number + dz - 1 - pz)
39 elif orientation == 'SAGITAL': 41 elif orientation == 'SAGITAL':
40 dx, dy, dz = dz, dx, dy 42 dx, dy, dz = dz, dx, dy
41 - extent = (slice_number, slice_number + dx - 1, 0, dy - 1, 0, dz - 1) 43 + extent = (slice_number - px, slice_number + dx - 1 - px, 0 - py, dy - 1 - py, 0 - pz, dz - 1 - pz)
42 elif orientation == 'CORONAL': 44 elif orientation == 'CORONAL':
43 dx, dy, dz = dx, dz, dy 45 dx, dy, dz = dx, dz, dy
44 - extent = (0, dx - 1, slice_number, slice_number + dy - 1, 0, dz - 1) 46 + extent = (0 - px, dx - 1 - px, slice_number - py, slice_number + dy - 1 - py, 0 - pz, dz - 1 - pz)
45 47
46 # Generating the vtkImageData 48 # Generating the vtkImageData
47 image = vtk.vtkImageData() 49 image = vtk.vtkImageData()
48 - image.SetOrigin(0, 0, 0) 50 + image.SetOrigin(origin)
49 image.SetSpacing(spacing) 51 image.SetSpacing(spacing)
50 image.SetDimensions(dx, dy, dz) 52 image.SetDimensions(dx, dy, dz)
51 # SetNumberOfScalarComponents and SetScalrType were replaced by 53 # SetNumberOfScalarComponents and SetScalrType were replaced by
invesalius/data/imagedata_utils.py
@@ -751,3 +751,22 @@ def imgnormalize(data, srange=(0, 255)): @@ -751,3 +751,22 @@ def imgnormalize(data, srange=(0, 255)):
751 datan = datan.astype(numpy.int16) 751 datan = datan.astype(numpy.int16)
752 752
753 return datan 753 return datan
  754 +
  755 +
  756 +def pad_image(image, pad_value, pad_bottom, pad_top):
  757 + dz, dy, dx = image.shape
  758 + z_iadd = 0
  759 + z_eadd = 0
  760 + if pad_bottom:
  761 + z_iadd = 1
  762 + dz += 1
  763 + if pad_top:
  764 + z_eadd = 1
  765 + dz += 1
  766 + new_shape = dz, dy + 2, dx + 2
  767 +
  768 + paded_image = numpy.empty(shape=new_shape, dtype=image.dtype)
  769 + paded_image[:] = pad_value
  770 + paded_image[z_iadd: z_iadd + image.shape[0], 1:-1, 1:-1] = image
  771 +
  772 + return paded_image
invesalius/data/surface.py
@@ -538,6 +538,8 @@ class SurfaceManager(): @@ -538,6 +538,8 @@ class SurfaceManager():
538 fill_holes = surface_parameters['options']['fill'] 538 fill_holes = surface_parameters['options']['fill']
539 keep_largest = surface_parameters['options']['keep_largest'] 539 keep_largest = surface_parameters['options']['keep_largest']
540 540
  541 + fill_border_holes = surface_parameters['options'].get('fill_border_holes', True)
  542 +
541 mode = 'CONTOUR' # 'GRAYSCALE' 543 mode = 'CONTOUR' # 'GRAYSCALE'
542 min_value, max_value = mask.threshold_range 544 min_value, max_value = mask.threshold_range
543 colour = mask.colour[:3] 545 colour = mask.colour[:3]
@@ -598,7 +600,7 @@ class SurfaceManager(): @@ -598,7 +600,7 @@ class SurfaceManager():
598 smooth_relaxation_factor, 600 smooth_relaxation_factor,
599 smooth_iterations, language, flip_image, 601 smooth_iterations, language, flip_image,
600 algorithm != 'Default', algorithm, 602 algorithm != 'Default', algorithm,
601 - imagedata_resolution), 603 + imagedata_resolution, fill_border_holes),
602 callback=lambda x: filenames.append(x)) 604 callback=lambda x: filenames.append(x))
603 605
604 while len(filenames) != n_pieces: 606 while len(filenames) != n_pieces:
@@ -659,7 +661,7 @@ class SurfaceManager(): @@ -659,7 +661,7 @@ class SurfaceManager():
659 smooth_relaxation_factor, 661 smooth_relaxation_factor,
660 smooth_iterations, language, flip_image, 662 smooth_iterations, language, flip_image,
661 algorithm != 'Default', algorithm, 663 algorithm != 'Default', algorithm,
662 - imagedata_resolution), 664 + imagedata_resolution, fill_border_holes),
663 callback=lambda x: filenames.append(x), 665 callback=lambda x: filenames.append(x),
664 error_callback=functools.partial(self._on_callback_error, 666 error_callback=functools.partial(self._on_callback_error,
665 dialog=sp)) 667 dialog=sp))
@@ -673,7 +675,7 @@ class SurfaceManager(): @@ -673,7 +675,7 @@ class SurfaceManager():
673 smooth_relaxation_factor, 675 smooth_relaxation_factor,
674 smooth_iterations, language, flip_image, 676 smooth_iterations, language, flip_image,
675 algorithm != 'Default', algorithm, 677 algorithm != 'Default', algorithm,
676 - imagedata_resolution), 678 + imagedata_resolution, fill_border_holes),
677 callback=lambda x: filenames.append(x)) 679 callback=lambda x: filenames.append(x))
678 680
679 while len(filenames) != n_pieces: 681 while len(filenames) != n_pieces:
invesalius/data/surface_process.py
@@ -14,7 +14,7 @@ import vtk @@ -14,7 +14,7 @@ import vtk
14 import invesalius.i18n as i18n 14 import invesalius.i18n as i18n
15 import invesalius.data.converters as converters 15 import invesalius.data.converters as converters
16 from invesalius.data import cy_mesh 16 from invesalius.data import cy_mesh
17 -# import invesalius.data.imagedata_utils as iu 17 +import invesalius.data.imagedata_utils as iu
18 18
19 import weakref 19 import weakref
20 from scipy import ndimage 20 from scipy import ndimage
@@ -45,15 +45,25 @@ def create_surface_piece(filename, shape, dtype, mask_filename, mask_shape, @@ -45,15 +45,25 @@ def create_surface_piece(filename, shape, dtype, mask_filename, mask_shape,
45 mask_dtype, roi, spacing, mode, min_value, max_value, 45 mask_dtype, roi, spacing, mode, min_value, max_value,
46 decimate_reduction, smooth_relaxation_factor, 46 decimate_reduction, smooth_relaxation_factor,
47 smooth_iterations, language, flip_image, 47 smooth_iterations, language, flip_image,
48 - from_binary, algorithm, imagedata_resolution): 48 + from_binary, algorithm, imagedata_resolution, fill_border_holes):
  49 +
  50 + pad_bottom = (roi.start == 0)
  51 + pad_top = (roi.stop >= shape[0])
  52 +
  53 + if fill_border_holes:
  54 + padding = (1, 1, pad_bottom)
  55 + else:
  56 + padding = (0, 0, 0)
  57 +
49 if from_binary: 58 if from_binary:
50 mask = numpy.memmap(mask_filename, mode='r', 59 mask = numpy.memmap(mask_filename, mode='r',
51 dtype=mask_dtype, 60 dtype=mask_dtype,
52 shape=mask_shape) 61 shape=mask_shape)
53 - a_mask = numpy.array(mask[roi.start + 1: roi.stop + 1,  
54 - 1:, 1:])  
55 - image = converters.to_vtk(a_mask, spacing, roi.start,  
56 - "AXIAL") 62 + if fill_border_holes:
  63 + a_mask = iu.pad_image(mask[roi.start + 1: roi.stop + 1, 1:, 1:], 0, pad_bottom, pad_top)
  64 + else:
  65 + a_mask = numpy.array(mask[roi.start + 1: roi.stop + 1, 1:, 1:])
  66 + image = converters.to_vtk(a_mask, spacing, roi.start, "AXIAL", padding=padding)
57 del a_mask 67 del a_mask
58 else: 68 else:
59 image = numpy.memmap(filename, mode='r', dtype=dtype, 69 image = numpy.memmap(filename, mode='r', dtype=dtype,
@@ -61,16 +71,21 @@ def create_surface_piece(filename, shape, dtype, mask_filename, mask_shape, @@ -61,16 +71,21 @@ def create_surface_piece(filename, shape, dtype, mask_filename, mask_shape,
61 mask = numpy.memmap(mask_filename, mode='r', 71 mask = numpy.memmap(mask_filename, mode='r',
62 dtype=mask_dtype, 72 dtype=mask_dtype,
63 shape=mask_shape) 73 shape=mask_shape)
64 - a_image = numpy.array(image[roi]) 74 + if fill_border_holes:
  75 + a_image = iu.pad_image(image[roi], numpy.iinfo(image.dtype).min, pad_bottom, pad_top)
  76 + else:
  77 + a_image = numpy.array(image[roi])
  78 + # if z_iadd:
  79 + # a_image[0, 1:-1, 1:-1] = image[0]
  80 + # if z_eadd:
  81 + # a_image[-1, 1:-1, 1:-1] = image[-1]
65 82
66 if algorithm == u'InVesalius 3.b2': 83 if algorithm == u'InVesalius 3.b2':
67 - a_mask = numpy.array(mask[roi.start + 1: roi.stop + 1,  
68 - 1:, 1:]) 84 + a_mask = numpy.array(mask[roi.start + 1: roi.stop + 1, 1:, 1:])
69 a_image[a_mask == 1] = a_image.min() - 1 85 a_image[a_mask == 1] = a_image.min() - 1
70 a_image[a_mask == 254] = (min_value + max_value) / 2.0 86 a_image[a_mask == 254] = (min_value + max_value) / 2.0
71 87
72 - image = converters.to_vtk(a_image, spacing, roi.start,  
73 - "AXIAL") 88 + image = converters.to_vtk(a_image, spacing, roi.start, "AXIAL", padding=padding)
74 89
75 gauss = vtk.vtkImageGaussianSmooth() 90 gauss = vtk.vtkImageGaussianSmooth()
76 gauss.SetInputData(image) 91 gauss.SetInputData(image)
@@ -83,8 +98,11 @@ def create_surface_piece(filename, shape, dtype, mask_filename, mask_shape, @@ -83,8 +98,11 @@ def create_surface_piece(filename, shape, dtype, mask_filename, mask_shape,
83 del gauss 98 del gauss
84 del a_mask 99 del a_mask
85 else: 100 else:
86 - image = converters.to_vtk(a_image, spacing, roi.start,  
87 - "AXIAL") 101 + # if z_iadd:
  102 + # origin = -spacing[0], -spacing[1], -spacing[2]
  103 + # else:
  104 + # origin = 0, -spacing[1], -spacing[2]
  105 + image = converters.to_vtk(a_image, spacing, roi.start, "AXIAL", padding=padding)
88 del a_image 106 del a_image
89 107
90 if imagedata_resolution: 108 if imagedata_resolution:
@@ -97,6 +115,11 @@ def create_surface_piece(filename, shape, dtype, mask_filename, mask_shape, @@ -97,6 +115,11 @@ def create_surface_piece(filename, shape, dtype, mask_filename, mask_shape,
97 flip.ReleaseDataFlagOn() 115 flip.ReleaseDataFlagOn()
98 flip.Update() 116 flip.Update()
99 117
  118 + # writer = vtk.vtkXMLImageDataWriter()
  119 + # writer.SetFileName('/tmp/camboja.vti')
  120 + # writer.SetInputData(flip.GetOutput())
  121 + # writer.Write()
  122 +
100 del image 123 del image
101 image = flip.GetOutput() 124 image = flip.GetOutput()
102 del flip 125 del flip
@@ -224,34 +247,34 @@ def join_process_surface(filenames, algorithm, smooth_iterations, smooth_relaxat @@ -224,34 +247,34 @@ def join_process_surface(filenames, algorithm, smooth_iterations, smooth_relaxat
224 247
225 # polydata.SetSource(None) 248 # polydata.SetSource(None)
226 # polydata.DebugOn() 249 # polydata.DebugOn()
227 - else:  
228 - #smoother = vtk.vtkWindowedSincPolyDataFilter()  
229 - send_message('Smoothing ...')  
230 - smoother = vtk.vtkSmoothPolyDataFilter()  
231 - smoother_ref = weakref.ref(smoother)  
232 - # smoother_ref().AddObserver("ProgressEvent", lambda obj,evt:  
233 - # UpdateProgress(smoother_ref(), _("Creating 3D surface...")))  
234 - smoother.SetInputData(polydata)  
235 - smoother.SetNumberOfIterations(smooth_iterations)  
236 - smoother.SetRelaxationFactor(smooth_relaxation_factor)  
237 - smoother.SetFeatureAngle(80)  
238 - #smoother.SetEdgeAngle(90.0)  
239 - #smoother.SetPassBand(0.1)  
240 - smoother.BoundarySmoothingOn()  
241 - smoother.FeatureEdgeSmoothingOn()  
242 - #smoother.NormalizeCoordinatesOn()  
243 - #smoother.NonManifoldSmoothingOn()  
244 - # smoother.ReleaseDataFlagOn()  
245 - # smoother.GetOutput().ReleaseDataFlagOn()  
246 - smoother.Update()  
247 - del polydata  
248 - polydata = smoother.GetOutput()  
249 - #polydata.Register(None)  
250 - # polydata.SetSource(None)  
251 - del smoother  
252 -  
253 -  
254 - if decimate_reduction: 250 + # else:
  251 + # #smoother = vtk.vtkWindowedSincPolyDataFilter()
  252 + # send_message('Smoothing ...')
  253 + # smoother = vtk.vtkSmoothPolyDataFilter()
  254 + # smoother_ref = weakref.ref(smoother)
  255 + # # smoother_ref().AddObserver("ProgressEvent", lambda obj,evt:
  256 + # # UpdateProgress(smoother_ref(), _("Creating 3D surface...")))
  257 + # smoother.SetInputData(polydata)
  258 + # smoother.SetNumberOfIterations(smooth_iterations)
  259 + # smoother.SetRelaxationFactor(smooth_relaxation_factor)
  260 + # smoother.SetFeatureAngle(80)
  261 + # #smoother.SetEdgeAngle(90.0)
  262 + # #smoother.SetPassBand(0.1)
  263 + # smoother.BoundarySmoothingOn()
  264 + # smoother.FeatureEdgeSmoothingOn()
  265 + # #smoother.NormalizeCoordinatesOn()
  266 + # #smoother.NonManifoldSmoothingOn()
  267 + # # smoother.ReleaseDataFlagOn()
  268 + # # smoother.GetOutput().ReleaseDataFlagOn()
  269 + # smoother.Update()
  270 + # del polydata
  271 + # polydata = smoother.GetOutput()
  272 + # #polydata.Register(None)
  273 + # # polydata.SetSource(None)
  274 + # del smoother
  275 +
  276 +
  277 + if not decimate_reduction:
255 print("Decimating", decimate_reduction) 278 print("Decimating", decimate_reduction)
256 send_message('Decimating ...') 279 send_message('Decimating ...')
257 decimation = vtk.vtkQuadricDecimation() 280 decimation = vtk.vtkQuadricDecimation()
@@ -320,9 +343,11 @@ def join_process_surface(filenames, algorithm, smooth_iterations, smooth_relaxat @@ -320,9 +343,11 @@ def join_process_surface(filenames, algorithm, smooth_iterations, smooth_relaxat
320 # normals_ref().AddObserver("ProgressEvent", lambda obj,evt: 343 # normals_ref().AddObserver("ProgressEvent", lambda obj,evt:
321 # UpdateProgress(normals_ref(), _("Creating 3D surface..."))) 344 # UpdateProgress(normals_ref(), _("Creating 3D surface...")))
322 normals.SetInputData(polydata) 345 normals.SetInputData(polydata)
323 - # normals.SetFeatureAngle(80)  
324 - # normals.SplittingOff()  
325 - # normals.AutoOrientNormalsOn() 346 + normals.SetFeatureAngle(80)
  347 + normals.SplittingOn()
  348 + normals.AutoOrientNormalsOn()
  349 + normals.NonManifoldTraversalOn()
  350 + normals.ComputeCellNormalsOn()
326 # normals.GetOutput().ReleaseDataFlagOn() 351 # normals.GetOutput().ReleaseDataFlagOn()
327 normals.Update() 352 normals.Update()
328 del polydata 353 del polydata
@@ -332,22 +357,22 @@ def join_process_surface(filenames, algorithm, smooth_iterations, smooth_relaxat @@ -332,22 +357,22 @@ def join_process_surface(filenames, algorithm, smooth_iterations, smooth_relaxat
332 del normals 357 del normals
333 358
334 359
335 - # Improve performance  
336 - stripper = vtk.vtkStripper()  
337 - # stripper.ReleaseDataFlagOn()  
338 - # stripper_ref = weakref.ref(stripper)  
339 - # stripper_ref().AddObserver("ProgressEvent", lambda obj,evt:  
340 - # UpdateProgress(stripper_ref(), _("Creating 3D surface...")))  
341 - stripper.SetInputData(polydata)  
342 - stripper.PassThroughCellIdsOn()  
343 - stripper.PassThroughPointIdsOn()  
344 - # stripper.GetOutput().ReleaseDataFlagOn()  
345 - stripper.Update()  
346 - del polydata  
347 - polydata = stripper.GetOutput()  
348 - #polydata.Register(None)  
349 - # polydata.SetSource(None)  
350 - del stripper 360 + # # Improve performance
  361 + # stripper = vtk.vtkStripper()
  362 + # # stripper.ReleaseDataFlagOn()
  363 + # # stripper_ref = weakref.ref(stripper)
  364 + # # stripper_ref().AddObserver("ProgressEvent", lambda obj,evt:
  365 + # # UpdateProgress(stripper_ref(), _("Creating 3D surface...")))
  366 + # stripper.SetInputData(polydata)
  367 + # stripper.PassThroughCellIdsOn()
  368 + # stripper.PassThroughPointIdsOn()
  369 + # # stripper.GetOutput().ReleaseDataFlagOn()
  370 + # stripper.Update()
  371 + # del polydata
  372 + # polydata = stripper.GetOutput()
  373 + # #polydata.Register(None)
  374 + # # polydata.SetSource(None)
  375 + # del stripper
351 376
352 send_message('Calculating area and volume ...') 377 send_message('Calculating area and volume ...')
353 measured_polydata = vtk.vtkMassProperties() 378 measured_polydata = vtk.vtkMassProperties()
invesalius/gui/dialogs.py
@@ -1662,7 +1662,10 @@ class SurfaceCreationOptionsPanel(wx.Panel): @@ -1662,7 +1662,10 @@ class SurfaceCreationOptionsPanel(wx.Panel):
1662 (combo_quality, 0, flag_button, 0)]) 1662 (combo_quality, 0, flag_button, 0)])
1663 1663
1664 1664
1665 - # LINES 4 and 5: Checkboxes 1665 + # LINES 4, 5 and 6: Checkboxes
  1666 + check_box_border_holes = wx.CheckBox(self, -1, _("Fill border holes"))
  1667 + check_box_border_holes.SetValue(False)
  1668 + self.check_box_border_holes = check_box_border_holes
1666 check_box_holes = wx.CheckBox(self, -1, _("Fill holes")) 1669 check_box_holes = wx.CheckBox(self, -1, _("Fill holes"))
1667 check_box_holes.SetValue(False) 1670 check_box_holes.SetValue(False)
1668 self.check_box_holes = check_box_holes 1671 self.check_box_holes = check_box_holes
@@ -1673,6 +1676,7 @@ class SurfaceCreationOptionsPanel(wx.Panel): @@ -1673,6 +1676,7 @@ class SurfaceCreationOptionsPanel(wx.Panel):
1673 # Merge all sizers and checkboxes 1676 # Merge all sizers and checkboxes
1674 sizer = wx.BoxSizer(wx.VERTICAL) 1677 sizer = wx.BoxSizer(wx.VERTICAL)
1675 sizer.Add(fixed_sizer, 0, wx.TOP|wx.RIGHT|wx.LEFT|wx.GROW|wx.EXPAND, 5) 1678 sizer.Add(fixed_sizer, 0, wx.TOP|wx.RIGHT|wx.LEFT|wx.GROW|wx.EXPAND, 5)
  1679 + sizer.Add(check_box_border_holes, 0, wx.RIGHT|wx.LEFT, 5)
1676 sizer.Add(check_box_holes, 0, wx.RIGHT|wx.LEFT, 5) 1680 sizer.Add(check_box_holes, 0, wx.RIGHT|wx.LEFT, 5)
1677 sizer.Add(check_box_largest, 0, wx.RIGHT|wx.LEFT, 5) 1681 sizer.Add(check_box_largest, 0, wx.RIGHT|wx.LEFT, 5)
1678 1682
@@ -1687,11 +1691,13 @@ class SurfaceCreationOptionsPanel(wx.Panel): @@ -1687,11 +1691,13 @@ class SurfaceCreationOptionsPanel(wx.Panel):
1687 mask_index = self.combo_mask.GetSelection() 1691 mask_index = self.combo_mask.GetSelection()
1688 surface_name = self.text.GetValue() 1692 surface_name = self.text.GetValue()
1689 quality = const.SURFACE_QUALITY_LIST[self.combo_quality.GetSelection()] 1693 quality = const.SURFACE_QUALITY_LIST[self.combo_quality.GetSelection()]
  1694 + fill_border_holes = self.check_box_border_holes.GetValue()
1690 fill_holes = self.check_box_holes.GetValue() 1695 fill_holes = self.check_box_holes.GetValue()
1691 keep_largest = self.check_box_largest.GetValue() 1696 keep_largest = self.check_box_largest.GetValue()
1692 return {"index": mask_index, 1697 return {"index": mask_index,
1693 "name": surface_name, 1698 "name": surface_name,
1694 "quality": quality, 1699 "quality": quality,
  1700 + "fill_border_holes": fill_border_holes,
1695 "fill": fill_holes, 1701 "fill": fill_holes,
1696 "keep_largest": keep_largest, 1702 "keep_largest": keep_largest,
1697 "overwrite": False} 1703 "overwrite": False}
invesalius/gui/preferences.py
@@ -15,7 +15,7 @@ except ImportError: # if it's not there locally, try the wxPython lib. @@ -15,7 +15,7 @@ except ImportError: # if it's not there locally, try the wxPython lib.
15 class Preferences(wx.Dialog): 15 class Preferences(wx.Dialog):
16 16
17 def __init__( self, parent, id = ID, title = _("Preferences"), size=wx.DefaultSize,\ 17 def __init__( self, parent, id = ID, title = _("Preferences"), size=wx.DefaultSize,\
18 - pos=wx.DefaultPosition, style=wx.DEFAULT_DIALOG_STYLE): 18 + pos=wx.DefaultPosition, style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
19 19
20 try: 20 try:
21 pre = wx.PreDialog() 21 pre = wx.PreDialog()
@@ -36,14 +36,16 @@ class Preferences(wx.Dialog): @@ -36,14 +36,16 @@ class Preferences(wx.Dialog):
36 else: 36 else:
37 self.book = fnb.FlatNotebook(self, wx.ID_ANY, agwStyle=bookStyle) 37 self.book = fnb.FlatNotebook(self, wx.ID_ANY, agwStyle=bookStyle)
38 38
39 - sizer.Add(self.book, 80, wx.EXPAND|wx.ALL) 39 + sizer.Add(self.book, 1, wx.EXPAND|wx.ALL)
40 40
41 self.pnl_viewer2d = Viewer2D(self) 41 self.pnl_viewer2d = Viewer2D(self)
42 self.pnl_viewer3d = Viewer3D(self) 42 self.pnl_viewer3d = Viewer3D(self)
  43 + # self.pnl_surface = SurfaceCreation(self)
43 self.pnl_language = Language(self) 44 self.pnl_language = Language(self)
44 45
45 self.book.AddPage(self.pnl_viewer2d, _("2D Visualization")) 46 self.book.AddPage(self.pnl_viewer2d, _("2D Visualization"))
46 self.book.AddPage(self.pnl_viewer3d, _("3D Visualization")) 47 self.book.AddPage(self.pnl_viewer3d, _("3D Visualization"))
  48 + # self.book.AddPage(self.pnl_surface, _("Surface creation"))
47 self.book.AddPage(self.pnl_language, _("Language")) 49 self.book.AddPage(self.pnl_language, _("Language"))
48 50
49 line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL) 51 line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL)
@@ -59,7 +61,7 @@ class Preferences(wx.Dialog): @@ -59,7 +61,7 @@ class Preferences(wx.Dialog):
59 61
60 btnsizer.Realize() 62 btnsizer.Realize()
61 63
62 - sizer.Add(btnsizer, 10, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP|wx.BOTTOM, 5) 64 + sizer.Add(btnsizer, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP|wx.BOTTOM, 5)
63 65
64 self.SetSizer(sizer) 66 self.SetSizer(sizer)
65 sizer.Fit(self) 67 sizer.Fit(self)
@@ -214,3 +216,21 @@ class Language(wx.Panel): @@ -214,3 +216,21 @@ class Language(wx.Panel):
214 locales = self.lg.GetLocalesKey() 216 locales = self.lg.GetLocalesKey()
215 selection = locales.index(language) 217 selection = locales.index(language)
216 self.cmb_lang.SetSelection(int(selection)) 218 self.cmb_lang.SetSelection(int(selection))
  219 +
  220 +
  221 +
  222 +class SurfaceCreation(wx.Panel):
  223 + def __init__(self, parent):
  224 + wx.Panel.__init__(self, parent)
  225 + self.rb_fill_border = wx.RadioBox(self, -1, "Fill border holes", choices=[_('Yes'), _('No')], style=wx.RA_SPECIFY_COLS | wx.NO_BORDER)
  226 +
  227 + sizer = wx.BoxSizer(wx.VERTICAL)
  228 + sizer.Add(self.rb_fill_border)
  229 +
  230 + self.SetSizerAndFit(sizer)
  231 +
  232 + def GetSelection(self):
  233 + return {}
  234 +
  235 + def LoadSelection(self, values):
  236 + pass