def _OnMouseMotion(self, event): # Handle or pass? if not (self._interact_down and self._screenVec): return # Get vector relative to reference position refPos = vv.Point(self._refPos) pos = vv.Point(event.x, event.y) vec = pos - refPos # Length of reference vector, and its normalized version screenVec = vv.Point(self._screenVec) L = screenVec.norm() V = screenVec.normalize() # Number of indexes to change n = vec.dot(V) / L # Apply! # scale of 100 is approximately half the height of a stent #delta = (self._refZ + n*50.0) - self.translation.z #self.translation += vv.Point(0, 0, delta) self.performMeasurements(self._refZ + n*50, True) if self._slider is not None: self._slider._range.max = float(self._refZ + n*50) self._slider._limitRangeAndSetText() self._slider.Draw()
def fit_cirlce(pp, warnIfIllDefined=True): """ fit_cirlce(pp, warnIfIllDefined=True) Calculate the circle (x - c.x)**2 + (y - x.y)**2 = c.r**2 From the set of points pp. Returns a point instance with an added attribute "r" specifying the radius. In case the three points are on a line, the algorithm will fail, and return 0 for x,y and r. This waring can be suppressed. The solution is a Least Squares fit. The method as describes in [1] is called Modified Least Squares (MLS) and poses a closed form solution which is very robust. [1] Dale Umbach and Kerry N. Jones 2000 A Few Methods for Fitting Circles to Data IEEE Transactions on Instrumentation and Measurement """ # Init error point ce = vv.Point(0,0) ce.r = 0.0 def cov(a, b): n = len(a) Ex = a.sum() / n Ey = b.sum() / n return ( (a-Ex)*(b-Ey) ).sum() / (n-1) # Get x and y elements X = pp[:,0] Y = pp[:,1] # In the paper there is a factor n*(n-1) in all equations below. However, # this factor is removed by devision in the equations in the following cell A = cov(X,X) B = cov(X,Y) C = cov(Y,Y) D = 0.5 * ( cov(X,Y**2) + cov(X,X**2) ) E = 0.5 * ( cov(Y,X**2) + cov(Y,Y**2) ) # Calculate denumerator denum = A*C - B*B if denum==0: if warnIfIllDefined: print "Warning: can not fit a circle to the given points." return ce # Calculate point c = vv.Point( (D*C-B*E)/denum, (A*E-B*D)/denum ) # Calculate radius c.r = c.distance(pp).sum() / len(pp) # Done return c
def onClick(event): if event.button == 2 and vv.KEY_SHIFT in event.modifiers: # Get clicked location in NDC w, h = event.owner.position.size x, y = 2 * event.x / w - 1, -2 * event.y / h + 1 # Apply inverse camera transform to get two points on the clicked line M = np.linalg.inv(get_camera_matrix(event.owner)) p1 = vv.Point(np.dot((x, y, -100, 1), M)[:3]) p2 = vv.Point(np.dot((x, y, +100, 1), M)[:3]) # Calculate center point and vector pm = 0.5 * (p1 + p2) vec = (p2 - p1).normalize() # Prepare for searching in two directions pp = [pm - vec, pm + vec] status = 0 if sample(vol, pm) is None else 1 status = [status, status] hit = None max_sample = -999999 step = min(vol.sampling) # Look in two directions simulaneously, search for volume, collect samples for i in range(10000): # Safe while-loop for j in (0, 1): if status[j] < 2: s = sample(vol, pp[j]) inside = s is not None if inside: if s > max_sample: max_sample, hit = s, pp[j] if status[j] == 0: status[j] = 1 status[ not j] = 2 # stop looking in other direction else: if status[j] == 1: status[j] = 2 pp[j] += (j * 2 - 1) * step * vec if status[0] == 2 and status[1] == 2: break else: print('Warning: ray casting to collect samples did not stop' ) # clicking outside the volume # Draw pp2 = vv.Pointset(3) text = 'No point inside volume selected.' if hit: pp2.append(hit) ii = vol.point_to_index(hit) text = 'At z=%1.1f, y=%1.1f, x=%1.1f -> X[%i, %i, %i] -> %1.2f' % ( hit.z, hit.y, hit.x, ii[0], ii[1], ii[2], max_sample) line.SetPoints(pp2) label.text = text return True # prevent default mouse action
def arrows(points, vectors, head=(0.2, 1.0), **kwargs): if 'ls' in kwargs: raise ValueError('Cannot set line style for arrows.') ppd = vv.Pointset(pp.ndim) for i in range(len(points)): p1 = points[i] # source point v1 = vectors[i] # THE vector v1_norm = v1.norm() p2 = p1 + v1 # destination point if v1_norm: pn = v1.normal() * v1_norm * abs(head[0]) # normal vector else: pn = vv.Point(0, 0) ph1 = p1 + v1 * head[1] ph2 = ph1 - v1 * head[0] # Add stick ppd.append(p1) ppd.append(p2) # Add arrowhead ppd.append(ph1) ppd.append(ph2 + pn) ppd.append(ph1) ppd.append(ph2 - pn) return vv.plot(ppd, ls='+', **kwargs)
def __init__(self, xy, v): #global w """:param xy: Initial position, :param v: Initial velocity. """ # cast inputs as 2-d numpy arrays self.xy = xy.reshape((1,3)) #np.array(xy) self.v = v.reshape((1,3)) #np.array(v) # generate sphere data and colors. self.object = vv.solidSphere(vv.Point(self.xy), scaling=(0.05, 0.05, 0.05)) self.object.faceColor = [random(), random(), random()] self.trans = self.object.transformations[0]
def _CalculateDonut(self, N=32, M=32, thickness=0.2): # Quick access pi2 = np.pi*2 cos = np.cos sin = np.sin sl = M+1 # Calculate vertices, normals and texcords vertices = vv.Pointset(3) normals = vv.Pointset(3) texcords = vv.Pointset(2) # Cone for n in range(N+1): v = float(n)/N a = pi2 * v # Obtain outer and center position of "tube" po = vv.Point(sin(a), cos(a), 0) pc = po * (1.0-0.5*thickness) # Create two vectors that span the the circle orthogonal to the tube p1 = (pc-po) p2 = vv.Point(0, 0, 0.5*thickness) # Sample around tube for m in range(M+1): u = float(m) / (M) b = pi2 * (u) dp = cos(b) * p1 + sin(b) * p2 vertices.append(pc+dp) normals.append(dp.normalize()) texcords.append(v,u) # Calculate indices indices = [] for j in range(N): for i in range(M): indices.extend([(j+1)*sl+i, (j+1)*sl+i+1, j*sl+i+1, j*sl+i]) # Make indices a numpy array indices = np.array(indices, dtype=np.uint32) return vertices, indices, normals, texcords
def draw_error_ellipsoid_visvis(mu, covariance_matrix, stdev=1, z_offset=0, color_ellipsoid="g", pt_size=5): """ @brief Plot the error (uncertainty) ellipsoid using a 3D covariance matrix for a given standard deviation @param mu: The mean vector @param covariance_matrix: the 3x3 covariance matrix @param stdev: The desire standard deviation value to draw the uncertainty ellipsoid for. Default is 1. """ import visvis as vv # Step 1: make a unit n-sphere u = np.linspace(0.0, 2.0 * np.pi, 30) v = np.linspace(0.0, np.pi, 30) x_sph = np.outer(np.cos(u), np.sin(v)) y_sph = np.outer(np.sin(u), np.sin(v)) z_sph = np.outer(np.ones_like(u), np.cos(v)) X_sphere = np.dstack((x_sph, y_sph, z_sph)) # Step 2: apply the following linear transformation to get the points of your ellipsoid (Y): C = np.linalg.cholesky(covariance_matrix) ellipsoid_pts = mu + stdev * np.dot(X_sphere, C) x = ellipsoid_pts[..., 0] y = ellipsoid_pts[..., 1] z = ellipsoid_pts[..., 2] + z_offset # plot ellipsoid_surf = vv.surf(x, y, z) # Get axes # ellipsoid_surf = vv.grid(x, y, z) ellipsoid_surf.faceShading = "smooth" ellipsoid_surf.faceColor = color_ellipsoid # ellipsoid_surf.edgeShading = "plain" # ellipsoid_surf.edgeColor = color_ellipsoid ellipsoid_surf.diffuse = 0.9 ellipsoid_surf.specular = 0.9 mu_pt = vv.Point(mu[0], mu[1], mu[2] + z_offset) pt_mu = vv.plot(mu_pt, ms='.', mc="k", mw=pt_size, ls='', mew=0, axesAdjust=True)
def calculatePulsation(self, contour, deltas): """ Given the contour points and their motion vectors, calculate the minimum and maximum of the area and circumference. """ # Init areas = [] circs = [] # For each time instance in the motion ... for delta in deltas: # Get closed contour points for this motion phase pp = contour + delta pp.append(pp[0]) # Get a point in the centre cp = vv.Point(0,0,0) for p in pp[:-1]: cp += p cp *= 1.0 / (len(pp)-1) # Area if True: area = 0.0 for i in range(len(contour)): # Get triangle points and lengths of the sides p1, p2 = pp[i], pp[i+1] a, b, c = cp.distance(p1), cp.distance(p2), p1.distance(p2) # Approximate area of this triangle area += 0.5 * 0.5*(a+b) * c areas.append(float(area)) # Circumference if True: circ = 0.0 for i in range(len(contour)): # Get triangle points and length between them p1, p2 = pp[i], pp[i+1] circ += p1.distance(p2) circs.append(float(circ)) # Post process: look for smallest and largest return min(areas), max(areas), min(circs), max(circs)
def calculateMotionMagnitude(self, contour, deltas): """ Calculate the mean motion magnitude (i.e. amplitude in principal direction). """ # Init a list that contains the mean z-position for each time unit # Note that this is a relative z-position, but that doesnt matter meanPositions = vv.Pointset(3) # delta is a pointset, there is such a pointsets for each time unit for delta in deltas: meanPosition = vv.Point(0,0,0) for p in delta: meanPosition += p meanPosition *= 1.0 / len(delta) meanPositions.append(meanPosition) return self._calculateMagnitude(meanPositions)
# Apply the deform to the images im_forward = deform_forward.apply_deformation(im) im_forward2 = deform_forward2.apply_deformation(im) im_backward = deform_backward.apply_deformation(im) im_backward2 = deform_backward2.apply_deformation(im) # Calculate vectors vecstep = 20 pp = vv.Pointset(2) vvf, vvb = vv.Pointset(2), vv.Pointset(2) vvf2, vvb2 = vv.Pointset(2), vv.Pointset(2) for y in np.arange(0, im.shape[0], vecstep): for x in np.arange(0, im.shape[1], vecstep): # Center point p1 = vv.Point(x, y) pp.append(p1) # Vector for forward deform = deform_forward vvf.append(vv.Point(deform[1][y, x], deform[0][y, x])) deform = deform_forward2 vvf2.append(vv.Point(deform[1][y, x], deform[0][y, x])) # Vector for backward deform = deform_backward vvb.append(vv.Point(deform[1][y, x], deform[0][y, x])) deform = deform_backward2 vvb2.append(vv.Point(deform[1][y, x], deform[0][y, x])) # Show f = vv.figure(1)