def fitSphere(coords, c='r', alpha=1, wire=1, legend=None): ''' Fits a sphere to a set of points. Extra info is stored in actor.radius, actor.center, actor.residue [**Example1**](https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/fitspheres1.py) [**Example2**](https://github.com/marcomusy/vtkplotter/blob/master/examples/advanced/fitspheres2.py) ''' coords = np.array(coords) n = len(coords) A = np.zeros((n, 4)) A[:, :-1] = coords*2 A[:, 3] = 1 f = np.zeros((n, 1)) x = coords[:, 0] y = coords[:, 1] z = coords[:, 2] f[:, 0] = x*x + y*y + z*z C, residue, rank, sv = np.linalg.lstsq(A, f) # solve AC=f if rank < 4: return None t = (C[0]*C[0]) + (C[1]*C[1]) + (C[2]*C[2]) + C[3] radius = np.sqrt(t)[0] center = np.array([C[0][0], C[1][0], C[2][0]]) if len(residue): residue = np.sqrt(residue[0])/n else: residue = 0 s = vs.sphere(center, radius, c, alpha, wire=wire, legend=legend) s.info['radius'] = radius s.info['center'] = center s.info['residue'] = residue return s
def fitSphere(coords, c='r', alpha=1, wire=1, legend=None): ''' Fits a sphere to a set of points. Extra info is stored in actor.radius, actor.center, actor.residue ''' coords = np.array(coords) n = len(coords) A = np.zeros((n, 4)) A[:, :-1] = coords * 2 A[:, 3] = 1 f = np.zeros((n, 1)) x = coords[:, 0] y = coords[:, 1] z = coords[:, 2] f[:, 0] = x * x + y * y + z * z C, residue, rank, sv = np.linalg.lstsq(A, f, rcond=None) # solve AC=f if rank < 4: return None t = (C[0] * C[0]) + (C[1] * C[1]) + (C[2] * C[2]) + C[3] radius = np.sqrt(t)[0] center = np.array([C[0][0], C[1][0], C[2][0]]) if len(residue): residue = np.sqrt(residue[0]) / n else: residue = 0 s = vs.sphere(center, radius, c, alpha, wire=wire, legend=legend) setattr(s, 'radius', radius) setattr(s, 'center', center) setattr(s, 'residue', residue) return s
def myloop(*event): global counts # this is needed because counts is being modified: counts += 0.1 # reference 'actor' is not modified so doesnt need to be global # (internal properties of the object are, but python doesn't know..) actor.pos([0, counts / 20, 0]).color(counts) # move cube and change color rp = [u(-1, 1), u(0, 1), u(-1, 1)] # a random position s = sphere(rp, r=0.05, c='blue 0.2') vp.render(s, resetcam=True) # show() would cause exiting the loop # waste cpu time to slow down program for i in range(100000): sin(i) printc('#', end='')
# Generate a time sequence of 3D shapes (from a sphere to a tetrahedron) # as noisy cloud points, and smooth it with Moving Least Squares (smoothMLS3D). # This make a simultaneus fit in 4D (space+time). # smoothMLS3D method returns a vtkActor where points are color coded # in bins of fitted time. # Data itself can suggest a meaningful time separation based on the spatial # distribution of points. # The nr neighbours in the local 4D fitting must be specified. # import numpy as np from vtkplotter import Plotter from vtkplotter.shapes import sphere from vtkplotter.analysis import smoothMLS3D vp = Plotter(N=2, axes=0) # generate uniform points on sphere (tol separates points by 2% of actor size) cc = sphere(res=200).clean(tol=0.02).coordinates() a, b, noise = .2, .4, .1 # some random warping paramenters, and noise factor for i in range(5): # generate a time sequence of 5 shapes cs = cc + a * i * cc**2 + b * i * cc**3 # warp sphere in weird ways # set absolute time of points actor, and add 1% noise on positions vp.points(cs, c=i, alpha=0.5).gaussNoise(1.0).time(0.2 * i) vp.show(at=0, zoom=1.4) # show input clouds as func(time) asse = smoothMLS3D(vp.actors, neighbours=50) vp.addScalarBar3D(asse, at=1, pos=(-2, 0, -1)) # color indicates fitted time vp.show(asse, at=1, zoom=1.4, axes=4, interactive=1)