diff --git a/CHANGES.md b/CHANGES.md index 09985212..0805c707 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,8 @@ ## vx.x.x * Use os.path.join to create all filepaths, previously in some cases we were forcing "\" or "/" to be in some paths +* More efficient pointcloud creation by not shifting the pointcloud to the make such that point0 is one point of the + created cloud. Point0 is simply added as first point of the cloud even if it does not lie on the regular grid. ## v22.3.0 * Fix bug with size of 'overlap' spinboxes expanding in the vertical direction diff --git a/src/idvc/dvc_interface.py b/src/idvc/dvc_interface.py index e6aed7f1..805a73ca 100644 --- a/src/idvc/dvc_interface.py +++ b/src/idvc/dvc_interface.py @@ -2938,7 +2938,10 @@ def createPointCloud(self, **kwargs): self.pointCloud = pointCloud else: pointCloud = self.pointCloud - + # instead of translating the point cloud so that point0 is in the point cloud + # we add point0 to the point cloud. + if hasattr(self, 'point0'): + pointCloud.SetPoint0(self.point0_world_coords) v = self.vis_widget_2D.frame.viewer orientation = v.getSliceOrientation() pointCloud.SetOrientation(orientation) @@ -3056,6 +3059,7 @@ def createPointCloud(self, **kwargs): # Mask the point cloud with the eroded mask if not self.pointCloudCreated: polydata_masker = cilMaskPolyData() + polydata_masker.AddObserver(vtk.vtkCommand.ProgressEvent, partial(getProgress, progress_callback=progress_callback)) # save reference self.polydata_masker = polydata_masker else: @@ -3104,29 +3108,12 @@ def createPointCloud(self, **kwargs): mm = mask_data.GetScalarComponentAsDouble(int(self.point0_sampled_image_coords[0]),int(self.point0_sampled_image_coords[1]), int(self.point0_sampled_image_coords[2]), 0) - if int(mm) == 1: #if point0 is in the mask - #print("POINT 0 IN MASK") - #Translate pointcloud so that point 0 is in the cloud - if hasattr(self, 'point0'): - pointCloud_points = [] - pointCloud_distances = [] - #print("Point 0: ", self.point0_world_coords) - for i in range (0, pointCloud.GetNumberOfPoints()): - current_point = pointCloud.GetPoints().GetPoint(i) - pointCloud_points.append(current_point) - pointCloud_distances.append((self.point0_world_coords[0]-current_point[0])**2+(self.point0_world_coords[1]-current_point[1])**2+(self.point0_world_coords[2]-current_point[2])**2) - - lowest_distance_index = pointCloud_distances.index(min(pointCloud_distances)) - - #print("The point closest to point 0 is:", pointCloud_points[lowest_distance_index]) - - pointCloud_Translation = (self.point0_world_coords[0]-pointCloud_points[lowest_distance_index][0],self.point0_world_coords[1]-pointCloud_points[lowest_distance_index][1],self.point0_world_coords[2]-pointCloud_points[lowest_distance_index][2]) - - #print("Translation from it is:", pointCloud_Translation) - - transform.Translate(pointCloud_Translation) - #else: - #print("POINT 0 NOT IN MASK") + if int(mm) == 1: + #if point0 is in the mask and it has been added as first point to the point cloud + remove_point0 = False + else: + # should remove point0 from the mask + remove_point0 = True if self.pointCloudCreated: t_filter = self.t_filter @@ -3145,7 +3132,7 @@ def createPointCloud(self, **kwargs): # polydata_masker.Modified() message_callback.emit('Applying mask to pointcloud') polydata_masker.Update() - + message_callback.emit('Applying mask to pointcloud. Done') #print("Points in mask now: ", polydata_masker) self.reader = reader @@ -3174,7 +3161,8 @@ def createPointCloud(self, **kwargs): count += 1 message_callback.emit('Saving pointcloud') - np.savetxt(os.path.join(tempfile.tempdir, filename), array, '%d\t%.3f\t%.3f\t%.3f', delimiter=';') + start = 0 if remove_point0 is False else 1 + np.savetxt(tempfile.tempdir + "/" + filename, array[start:], '%d\t%.3f\t%.3f\t%.3f', delimiter=';') self.roi = filename return True diff --git a/src/idvc/pointcloud_conversion.py b/src/idvc/pointcloud_conversion.py index 0935a51e..6d53c7fd 100644 --- a/src/idvc/pointcloud_conversion.py +++ b/src/idvc/pointcloud_conversion.py @@ -83,10 +83,20 @@ def __init__(self): self._SliceNumber = 0 self._Mode = self.CUBE self._SubVolumeRadius = 1 #: Radius of the subvolume in voxels + self._Point0 = None def GetPoints(self): '''Returns the Points''' return self._Points + + def SetPoint0(self, value): + if not isinstance(value, list): + raise ValueError('Point0 must be a list. Got', value) + if len(value) != 3: + raise ValueError('Point0 must be a list of 3 elements. Got', value) + self._Point0 = value + self.Modified() + def SetMode(self, value): '''Sets the shape mode''' if not value in [self.CIRCLE, self.SQUARE, self.CUBE, self.SPHERE]: @@ -227,6 +237,8 @@ def CreatePoints2D(self, point_spacing , sliceno, image_data, orientation): # print ("dimensions : ", image_dimensions) # print ("point spacing ", point_spacing) + if self._Point0 is not None: + vtkPointCloud.InsertNextPoint(*self._Point0) #label orientation axis as a, with plane being viewed labelled as bc # reduce to 2D on the proper orientation @@ -293,6 +305,9 @@ def CreatePoints3D(self, point_spacing , image_data, orientation, sliceno): image_origin = list ( image_data.GetOrigin() ) image_dimensions = list ( image_data.GetDimensions() ) + if self._Point0 is not None: + vtkPointCloud.InsertNextPoint(*self._Point0) + # the total number of points on X and Y axis max_x = image_dimensions[0] * image_spacing[0] / point_spacing[0] max_y = image_dimensions[1] * image_spacing[1] / point_spacing[1]