def _pickFull(self, context): """Perform picking in this item at given widget position. :param PickContext context: Current picking context :return: Object holding the results or None :rtype: Union[None,PickingResult] """ rayObject = context.getPickingSegment(frame=self._getScenePrimitive()) if rayObject is None: return None rayObject = rayObject[:, :3] data = self.getData(copy=False) bins = utils.segmentVolumeIntersect(rayObject, numpy.array(data.shape) - 1) if bins is None: return None # gather bin data offsets = [(i, j, k) for i in (0, 1) for j in (0, 1) for k in (0, 1)] indices = bins[:, numpy.newaxis, :] + offsets binsData = data[indices[:, :, 0], indices[:, :, 1], indices[:, :, 2]] # binsData.shape = nbins, 8 # TODO up-to this point everything can be done once for all isosurfaces # check bin candidates level = self.getLevel() mask = numpy.logical_and( numpy.nanmin(binsData, axis=1) <= level, level <= numpy.nanmax(binsData, axis=1)) bins = bins[mask] binsData = binsData[mask] if len(bins) == 0: return None # No bin candidate # do picking on candidates intersections = [] depths = [] for currentBin, data in zip(bins, binsData): mc = MarchingCubes(data.reshape(2, 2, 2), isolevel=level) points = mc.get_vertices() + currentBin triangles = points[mc.get_indices()] t = glu.segmentTrianglesIntersection(rayObject, triangles)[1] t = numpy.unique(t) # Duplicates happen on triangle edges if len(t) != 0: # Compute intersection points and get closest data point points = t.reshape( -1, 1) * (rayObject[1] - rayObject[0]) + rayObject[0] # Get closest data points by rounding to int intersections.extend(points) depths.extend(t) if len(intersections) == 0: return None # No intersected triangles intersections = numpy.array(intersections)[numpy.argsort(depths)] indices = numpy.transpose(numpy.round(intersections).astype(numpy.int)) return PickingResult(self, positions=intersections, indices=indices)
def _pickFull(self, context): """Perform picking in this item at given widget position. :param PickContext context: Current picking context :return: Object holding the results or None :rtype: Union[None,PickingResult] """ rayObject = context.getPickingSegment(frame=self._getScenePrimitive()) if rayObject is None: return None rayObject = rayObject[:, :3] data = self.getData(copy=False) bins = utils.segmentVolumeIntersect( rayObject, numpy.array(data.shape) - 1) if bins is None: return None # gather bin data offsets = [(i, j, k) for i in (0, 1) for j in (0, 1) for k in (0, 1)] indices = bins[:, numpy.newaxis, :] + offsets binsData = data[indices[:, :, 0], indices[:, :, 1], indices[:, :, 2]] # binsData.shape = nbins, 8 # TODO up-to this point everything can be done once for all isosurfaces # check bin candidates level = self.getLevel() mask = numpy.logical_and(numpy.nanmin(binsData, axis=1) <= level, level <= numpy.nanmax(binsData, axis=1)) bins = bins[mask] binsData = binsData[mask] if len(bins) == 0: return None # No bin candidate # do picking on candidates intersections = [] depths = [] for currentBin, data in zip(bins, binsData): mc = MarchingCubes(data.reshape(2, 2, 2), isolevel=level) points = mc.get_vertices() + currentBin triangles = points[mc.get_indices()] t = utils.segmentTrianglesIntersection(rayObject, triangles)[1] t = numpy.unique(t) # Duplicates happen on triangle edges if len(t) != 0: # Compute intersection points and get closest data point points = t.reshape(-1, 1) * (rayObject[1] - rayObject[0]) + rayObject[0] # Get closest data points by rounding to int intersections.extend(points) depths.extend(t) if len(intersections) == 0: return None # No intersected triangles intersections = numpy.array(intersections)[numpy.argsort(depths)] indices = numpy.transpose(numpy.round(intersections).astype(numpy.int)) return PickingResult(self, positions=intersections, indices=indices)
def _updateScenePrimitive(self): """Update underlying mesh""" self._getScenePrimitive().children = [] data = self.getData(copy=False) if data is None: if self.isAutoLevel(): self._level = float('nan') else: if self.isAutoLevel(): st = time.time() try: level = float(self.getAutoLevelFunction()(data)) except Exception: module_ = self.getAutoLevelFunction().__module__ name = self.getAutoLevelFunction().__name__ _logger.error( "Error while executing iso level function %s.%s", module_, name, exc_info=True) level = float('nan') else: _logger.info( 'Computed iso-level in %f s.', time.time() - st) if level != self._level: self._level = level self._updated(Item3DChangedType.ISO_LEVEL) if not numpy.isfinite(self._level): return st = time.time() vertices, normals, indices = MarchingCubes( data, isolevel=self._level) _logger.info('Computed iso-surface in %f s.', time.time() - st) if len(vertices) == 0: return else: mesh = primitives.Mesh3D(vertices, colors=self._color, normals=normals, mode='triangles', indices=indices) self._getScenePrimitive().children = [mesh]
def _update(self): """Update underlying mesh""" self._group.children = [] if self._data is None: if self.isAutoLevel(): self._level = float('nan') else: if self.isAutoLevel(): st = time.time() try: level = float(self.getAutoLevelFunction()(self._data)) except Exception: module = self.getAutoLevelFunction().__module__ name = self.getAutoLevelFunction().__name__ _logger.error( "Error while executing iso level function %s.%s", module, name, exc_info=True) level = float('nan') else: _logger.info('Computed iso-level in %f s.', time.time() - st) if level != self._level: self._level = level self.sigLevelChanged.emit(level) if numpy.isnan(self._level): return st = time.time() vertices, normals, indices = MarchingCubes(self._data, isolevel=self._level) _logger.info('Computed iso-surface in %f s.', time.time() - st) if len(vertices) == 0: return else: mesh = primitives.Mesh3D(vertices, colors=self._color, normals=normals, mode='triangles', indices=indices) self._group.children = [mesh]
def _computeIsosurface(self): """Compute isosurface for current state. :return: (vertices, normals, indices) arrays :rtype: List[Union[None,numpy.ndarray]] """ data = self.getData(copy=False) if data is None: if self.isAutoLevel(): self._level = float('nan') else: if self.isAutoLevel(): st = time.time() try: level = float(self.getAutoLevelFunction()(data)) except Exception: module_ = self.getAutoLevelFunction().__module__ name = self.getAutoLevelFunction().__name__ _logger.error( "Error while executing iso level function %s.%s", module_, name, exc_info=True) level = float('nan') else: _logger.info( 'Computed iso-level in %f s.', time.time() - st) if level != self._level: self._level = level self._updated(Item3DChangedType.ISO_LEVEL) if numpy.isfinite(self._level): st = time.time() vertices, normals, indices = MarchingCubes( data, isolevel=self._level) _logger.info('Computed iso-surface in %f s.', time.time() - st) if len(vertices) != 0: return vertices, normals, indices return None, None, None