def test_ellipsoid_certain_points(self): """ Ellipsoid using vectorized calculations """ N = 10 _x = make_vector4(0, 0, 1) xa = repeat_vect4(N, _x) m = np.eye(4) # makeMatrix4( 1,0,0,0, 0,1,0,0, 0,0,1,0 ) m[0, 0] = 1 ga2 = repeat_vect4(N, make_vector4(0, 0, -1)) self.ellipsoid_point_and_gradient_vectorized(m, xa, ga2) m = np.eye(4) self.ellipsoid_point_and_gradient_vectorized(m, repeat_vect4(N, make_vector4(0, 1, 0)), repeat_vect4(N, make_vector4(0, -1, 0))) m = np.eye(4) self.ellipsoid_point_and_gradient_vectorized(m, repeat_vect4(N, make_vector4(1, 0, 0)), repeat_vect4(N, make_vector4(-1, 0, 0))) xa = repeat_vect4(N, make_vector4(0, 0, 2)) m = np.eye(4) m[2, 2] = 2 self.ellipsoid_point_and_gradient_vectorized(m, xa, repeat_vect4(N, make_vector4(0, 0, -1))) xa = repeat_vect4(N, make_vector4(2, 0, 0)) m = np.eye(4) m[0, 0] = 2 self.ellipsoid_point_and_gradient_vectorized(m, xa, repeat_vect4(N, make_vector4(-1, 0, 0))) xa = repeat_vect4(N, make_vector4(0, 2, 0)) m = np.eye(4) m[0, 0] = 2 m[1, 1] = 2 m[2, 2] = 2 self.ellipsoid_point_and_gradient_vectorized(m, xa, repeat_vect4(N, make_vector4(0, -2, 0)))
def get_all_examples(types_list): """ types_list i.e. [1] or [2] or [2,3] or [1,3] r [1,2,3] """ usable_examples = [] i = 0 for e in examples: if examples[e] in types_list: usable_examples += [e] # print("e=", e) if examples[e] in [1]: iobj = make_example_nonvec(e) # print("**********************") x = make_vector4(0.5, 0.5, 0.5) g = iobj.implicitGradient(x) v = iobj.implicitFunction(x) if examples[e] in [2]: iobj = make_example_vectorized(e) x = vectorized.repeat_vect4(1, make_vector4(0.5, 0.5, 0.5)) g = iobj.implicitGradient(x) v = iobj.implicitFunction(x) i += 1 assert i > 0 return usable_examples
def cube_example(scale=1.): iobj = vectorized.UnitCube1() iobj_ = nonvec.UnitCube1() iobj = vectorized.Transformed(iobj) \ .move(-0.1 * scale, -0.1 * scale, -0.1 * scale) .resize(3 * scale) \ .rotate(-20, along=make_vector4(1, 1, 1), units="deg") .move(0.2 * scale, 0, 0) iobj_ = nonvec.Transformed(iobj_) \ .move(-0.1 * scale, -0.1 * scale, -0.1 * scale) .resize(3 * scale) \ .rotate(-20, along=make_vector4(1, 1, 1), units="deg") .move(0.2 * scale, 0, 0) return (iobj, iobj_)
def make_uv(w, u): w = w / np.linalg.norm(w[0:3]); w[3] = 1 u = u / np.linalg.norm(u[0:3]); u[3] = 1 # print w, "u=",u assert np.linalg.norm(np.cross(w[:3], u[:3])) > 0.000000001 # cannot be parallel v3 = np.cross(w[:3], u[:3]) v3 = v3 / np.linalg.norm(v3[:3]) v = make_vector4(v3[0], v3[1], v3[2]) u3 = np.cross(v[:3], w[:3]) u3 = u3 / np.linalg.norm(u3[:3]) u = make_vector4(u3[0], u3[1], u3[2]) # return w, u return u
def twisted_cube_example(ns=vectorized): from twist_z import TwistZ # Create a cube scale = 1 cube = vectorized.UnitCube1(size=2) # rotate cube rotated_cube = \ iobj = ns.Transformed(cube) iobj \ .move(-0.2 * scale, -0.2 * scale, 0) \ .resize(0.9) iobj.rotate(45, along=make_vector4(1, 0, 0), units="deg") iobj.rotate(45, along=make_vector4(0, 1, 0), units="deg") twisted_object = TwistZ(iobj, 0.2) return twisted_object
def cyl1(): SCALE = 8. # mm radius = 0.5 * SCALE c_len = 2 * SCALE A = make_vector4(0, 0, -c_len / 2.0) # bug: aa is wrong w = make_vector4(0, 1, 0) w = w / np.linalg.norm(w[0:3]); w[3] = 1 u = make_vector4(1, 0, 0) c = SimpleCylinder(A, w, u, radius, radius, c_len) (RANGE_MIN, RANGE_MAX, STEPSIZE) = (-16, +32, 1.92 * 0.2 * 10 / 2.0) return c, (RANGE_MIN, RANGE_MAX, STEPSIZE)
def cage_rods(rod_r, rod_len, cage_r, N): import math un = None for i in range(N): th = i / float(N) * np.pi * 2 x, y = cage_r * math.sin(th), cage_r * math.cos(th) A = make_vector4(x, y, -rod_len / 2.) w = make_vector4(0, 0, 1) u = make_vector4(1, 0, 0) c = SimpleCylinder(A, w, u, rod_r, rod_r, rod_len) if un is None: un = c else: un = vectorized.CrispUnion(un, c) return un
def check_gradient_function(self, iobj_vec, tolerance=NUMERICAL_GRADIENT_TOLERANCE, iobj_nonvec=None, objname=None): """testing the gradient on 100 random points """ assert (-1)*-tolerance > 0, "should be a number" if not iobj_vec is None: from vectorized import ImplicitFunctionVectorized assert issubclass(type(iobj_vec), ImplicitFunctionVectorized) import vectorized assert vectorized.is_implicit_type(iobj_vec) if not iobj_nonvec is None: from nonvec import ImplicitFunctionPointwise assert issubclass(type(iobj_nonvec), ImplicitFunctionPointwise) import nonvec assert nonvec.is_implicit_type(iobj_nonvec) for i in range(100): radius = 10 # 10/5 x = make_random_vector(radius, 1, type="randn") # [0:3] x = x * np.random.randn() * 5 x[3]=1 self.check_gradient_function_point1(iobj_vec, x, tolerance, iobj_nonvec, objname) x = make_vector4(0, 2, 0) self.check_gradient_function_point1(iobj_vec, x, tolerance, iobj_nonvec, objname)
def side(x, y, z): p0 = (make_vector4(x, y, z) + 0.0) p0 = p0 / 2.0 * size # n0 points inwards n0 = -make_vector4(x, y, z) n0 = n0 self.p0 += [p0] self.n0 += [n0] self.p0[-1][3] = 1 self.n0[-1][3] = 1 def norm2(v): return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] #print(norm2(self.n0[-1][0:3])) assert norm2(self.n0[-1][0:3]) - 1 == 0.0
def french_fries_vectorized(scale): def rod(): c = vectorized.UnitCube1() m2 = np.eye(4) * scale m2[0, 0] = 0.1 * scale m2[1, 1] = 0.1 * scale m2[0:3, 3] = [+0.1 / 2.0 * 2 * scale, +0.1 / 2.0 * 2 * scale, + 1.0 / 2.0 * 2 * scale] m2[3, 3] = 1 iobj = vectorized.Transformed(c, m2) # .move(-0.1/2.0, -0.1/2.0, -1.0/2.0) iobj \ .move(-0.2 * scale, -0.2 * scale, 0) \ .resize(2) \ .rotate(10, along=make_vector4(1, 1, 0), units="deg") \ .move(0.5 * scale, 0, 0) return iobj u = None for i in range(18): c = rod().rotate(-30 * i, along=make_vector4(0, 0, 1), units="deg") if u is None: u = c else: u = vectorized.CrispUnion(u, c) return u
def side(x, y, z): p0 = (make_vector4(x, y, z) + 0.0) p0 = p0 / 2.0 * size n0 = -make_vector4(x, y, z) n0 = n0 self.p0 += [p0] self.n0 += [n0] self.p0[-1][3] = 1 self.n0[-1][3] = 1 #print(self.p0[-1]) check_vector4(self.p0[-1]) check_vector4(self.n0[-1]) def norm2(v): return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] assert norm2(self.n0[-1][0:3]) - 1 == 0.0
def cyl4(scale): """ Makes a nice cage with spiral bars. Don't change. """ cage = cage_rods(rod_r=1, rod_len=20, cage_r=10, N=20) from twist_z import TwistZ t = TwistZ(cage, 0.02) # cycles per mm # 0.06 is too much 0.02 is reasonable base_cyl = SimpleCylinder( make_vector4(0, 0, -10), # A make_vector4(0, 0, -1), # w make_vector4(1, 0, 0), 11., 11., 1.) ifunc = vectorized.CrispUnion(base_cyl, t) # (RANGE_MIN, RANGE_MAX, STEPSIZE) = (-32, +32, 1.92 / 4.0) #15 sec! 2.5 millions voxels (RANGE_MIN, RANGE_MAX, STEPSIZE) = (-32 / 2, +32 / 2, 1.92 / 4.0) # 2.5 sec! return ifunc #, (RANGE_MIN, RANGE_MAX, STEPSIZE)
def test_bisection(prop, num_pairs, max_iter_count): import example_objects iobj = example_objects.make_example_vectorized("first_csg") from basic_types import make_vector4 func_test_bisection_p(iobj, make_vector4(1, 1, 1), make_vector4(0, 0, 0), prop, max_iter_count=max_iter_count) if VERBOSE: print("=============") func_test_bisection_p(iobj, make_vector4(10, 10, 10), make_vector4(0, 0, 0), prop, max_iter_count=max_iter_count) if VERBOSE: print("=============") counter = 0 while counter < num_pairs: from basic_types import make_random_vector_vectorized x1 = make_random_vector_vectorized(1, 90 / 10, 3, "randn", normalize=False) x2 = make_random_vector_vectorized(1, 90 / 10, 3, "randn", normalize=False) f1 = iobj.implicitFunction(x1) f2 = iobj.implicitFunction(x2) if f1 * f2 < 0 and f1 < 0: func_test_bisection_p(iobj, x1[0, :], x2[0, :], prop, max_iter_count=max_iter_count) if VERBOSE: print("======================") import sys sys.stdout.flush() counter += 1
def rcube_vec(scale, rotated=True): d = vectorized.UnitCube1(size=2.0 * scale) iobj = vectorized.Transformed(d) iobj \ .move(-0.2 * scale, -0.2 * scale, 0) \ .resize(0.9) if rotated: iobj.rotate(10 * 2, along=make_vector4(1, 1, 1), units="deg") return iobj
def slow_grid__dont_use(): """ #Slow way: """ vgrid = xx for i in range(len(rng)): for j in range(len(rng)): for k in range(len(rng)): x_ = make_vector4(rng[i], rng[j], rng[k]) #vgrid[i,j,k] = i>1 and j>1 and k>1 and i<len(rng)-1 and j<len(rng)-1 and k<len(rng)-1 #iobj.implicitFunction( x ) vgrid[i, j, k] = iobj.implicitFunction(x_)
def test_gradients_using_numerical_gradient(self): def blend2(): m1 = np.eye(4) * 1 m1[0:3, 3] = [0, 1, 0] m1[3, 3] = 1 m2 = np.eye(4) * 2 m2[0:3, 3] = [2.5, 0, 0] m2[3, 3] = 1 iobj_v = vectorized.SimpleBlend(vectorized.Ellipsoid(m1), vectorized.Ellipsoid(m2)) return iobj_v iobj_v = blend2() self.check_gradient_function(iobj_v, objname="blend2") #examples_list = ["sphere_example", "ell_example1", "blend_example2"] examples_list = example_objects.get_all_examples([3]) for example_name in examples_list: (iobj_v, io_) = example_objects.make_example_pair(example_name) self.check_gradient_function(iobj_v, iobj_nonvec=io_, objname=example_name) #examples_list = example_objects.get_all_examples([3]) #print(examples_list) examples_list = example_objects.get_all_examples([3]) #examples_list = ["sphere_example", "ell_example1", "blend_example2"] for example_name in examples_list: (iobj_v, io_) = example_objects.make_example_pair(example_name) self.check_equal_vec_nonvec(iobj_v, io_, objname=example_name) examples_list = example_objects.get_all_examples([1]) for example_name in examples_list: io_ = example_objects.make_example_nonvec(example_name) self.check_gradient_function(None, iobj_nonvec=io_, objname=example_name) examples_list = example_objects.get_all_examples([2]) for example_name in examples_list: print("example_name = ",example_name) iobj_vev = example_objects.make_example_vectorized(example_name) self.check_gradient_function(iobj_vev, iobj_nonvec=None, objname=example_name) """ numerical """ x = make_vector4(0, 2, 0) g2 = numerical_utils.numerical_gradient(iobj_v, x, is_vectorized=True) g = iobj_v.implicitGradient(repeat_vect4(1, x)) np.set_printoptions(formatter={'all': lambda x: ''+("%2.19f" % (x,))}) err = np.sum(np.abs(g - g2), axis=1) err_max = np.max(np.abs(g - g2), axis=1) err_rel = np.sum(np.abs(g - g2), axis=1) / np.mean(np.abs(g)) print(err, err_max, err_rel) #print(err) self.assertTrue(np.all(err < NUMERICAL_GRADIENT_TOLERANCE))
def rods_row(N=6, rod_len=10.): from basic_types import make_vector4 from vectorized import SimpleCylinder rod_r = 1. cage_r = 10. delta_d = 0.4 #return cage_rods(rod_r, rod_len, cage_r, N), (-32 / 2, +32 / 2, 1.92 / 4.0) #x, y = cage_r * math.sin(th), cage_r * math.cos(th) #A = make_vector4(x, y, -rod_len / 2.) A = make_vector4(-rod_r * 2 * (N / 2), 0, -rod_len / 2.) w = make_vector4(0, 0, 1) u = make_vector4(1, 0, 0) rod = SimpleCylinder(A, w, u, rod_r, rod_r, rod_len) ifunc = Tile1D(rod, start=A[:3] - np.array([1., 0., 0.]) * rod_r, direction=np.array([1., 0, 0]) * (2 * rod_r + delta_d), tilecount=N) (RANGE_MIN, RANGE_MAX, STEPSIZE) = (-10., +10., 0.2 * 2) return ifunc, (RANGE_MIN, RANGE_MAX, STEPSIZE)
def bowl_hole(): """ Bowl with holes """ big_radius = 3 big_radius2 = 2.7 # +0.3-0.001 m_big = np.eye(4) * big_radius m_big[0:3, 3] = [0, 0, 0] m_big[3, 3] = 1 iobj = nonvec.Ellipsoid(m_big) m_big2 = np.eye(4) * big_radius2 m_big2[0:3, 3] = [0, 0, 0] m_big2[3, 3] = 1 iobj = nonvec.CrispSubtract(iobj, nonvec.Ellipsoid(m_big2)) m_big3 = np.eye(4) * 10 m_big3[0:3, 3] = [0, 0, 10] m_big3[3, 3] = 1 iobj = nonvec.CrispSubtract(iobj, nonvec.Ellipsoid(m_big3)) for i in range(0, 15): m_small = np.eye(4) * 0.6 if False: unsat = True while unsat: c = make_random_vector(big_radius, 1)[0:3] unsat = c[2] > 0 # th0 = (i/15.0)*(3.1415926536*2) # th = 5*th0 z0 = (i / 15.0) * big_radius # z0 = np.sqrt(1-(float(i)/15.0)**2) * big_radius # print(z0) # th = i * np.pi*2 * 5/ 4.45 # th = (np.pi*2) * float(i) * 4.0 / 5.0 # th = (np.pi*2) * float(i) * (1.0/5.0 * 1.0/2.0 * 1.0/5.0) * 5 NN = float(8) # th = (np.pi*2) * float(i) * (1.0/5.0 + 1.0/5.0 * 1.0/2.0 * 1.0/5.0) th = (np.pi * 2) * float(i) * (1.0 / NN + 1.0 / NN * 1.0 / NN / 2.0) c = make_vector4(np.cos(th) * big_radius, np.sin(th) * big_radius, -z0) c = normalize_vector(c) * big_radius c[3] = 1 # print( np.sqrt(np.dot(c,c)) ) m_small[0:3, 3] = c[0:3] m_small[3, 3] = 1 small_obj = nonvec.Ellipsoid(m_small) iobj = nonvec.CrispSubtract(iobj, small_obj) # iobj = nonvec.CrispUnion( iobj, small_obj ) return iobj
def test_ellipsoid_random_points(self): """Testing hundreds of random points on a sphere of size RADIUS=3""" for i in range(0, 100): RADIUS = 3 POW = 4 # higher POW will get points more toward parallel to axes rcenter = make_random_vector(1000, 1.0)[0:3] r0 = make_random_vector(RADIUS, POW)[0:3] r = r0 + rcenter assert r.shape[0] == 3 x = make_vector4(r[0], r[1], r[2]) m = np.eye(4) * RADIUS m[0:3, 3] = rcenter[0:3] m[3, 3] = 1 expected_grad = make_vector4(-r0[0], -r0[1], -r0[2]) check_vector4(expected_grad) self.ellipsoid_point_and_gradient(m, x, expected_grad)
def rod(): c = nonvec.UnitCube1() m2 = np.eye(4) m2[0, 0] = 0.1 m2[1, 1] = 0.1 iobj = nonvec.Transformed(c, m2) iobj \ .move(-0, -0.3, -1.0) \ .resize(2) \ .rotate(40, along=make_vector4(1, 1, 0), units="deg") \ .move(0.5, 0, 0) return iobj
def cube_with_cylinders(SCALE): SCALE = 2. # mm sz1 = 2.5 radius = 0.5 * SCALE c_len = 2 * SCALE A = make_vector4(-c_len/2.0, 0, 0) #A = make_vector4(0, 0, c_len / 2.0) # bug: aa is wrong w = make_vector4(1,0 , 0) w = w / np.linalg.norm(w[0:3]); w[3] = 1 u = make_vector4(0, 1, 0) cyl = SimpleCylinder(A, w, u, radius, radius, c_len) A2 = make_vector4(0, -c_len/2.0, 0) #A = make_vector4(0, 0, c_len / 2.0) # bug: aa is wrong w2 = make_vector4(1,0 , 0) w2 = w / np.linalg.norm(w[0:3]); w[3] = 1 u2 = make_vector4(0, 1, 0) cyl_2 = SimpleCylinder(A2, u2, w2, radius, radius, c_len) cube = vectorized.UnitCube1(size=sz1) union = vectorized.CrispSubtract(cube, cyl_2) final_object = vectorized.CrispUnion(union,cyl) # (RANGE_MIN, RANGE_MAX, STEPSIZE) = (-3, +5, 0.2) return final_object
def rod(): c = nonvec.UnitCube1() m2 = np.eye(4) m2[0, 0] = 0.1 m2[1, 1] = 0.1 m2[0:3, 3] = [+0.1 / 2.0 * 2, +0.1 / 2.0 * 2, +1.0 / 2.0 * 2] iobj = nonvec.Transformed(c, m2) iobj \ .move(-0.2, -0.2, 0) \ .resize(2) \ .rotate(10, along=make_vector4(1, 1, 0), units="deg") \ .move(0.5, 0, 0) return iobj
def vectors_parallel_and_direction(v1, v2): #check_vector3(v1) #check_vector3(v2) #print(v1.shape) assert v1.shape == (3,) , str(v1.shape) assert v2.shape == (3,) , str(v2.shape) cross_prod = np.cross(v1[0:3], v2[0:3]) inner_prod = np.dot(np.transpose(v1[0:3]), v2[0:3]) are_parallel1 = almost_equal4(make_vector4_numpy(cross_prod), make_vector4(0, 0, 0), TOLERANCE) are_directed = (inner_prod > 0) #no tolerance is needed are_parallel2 = np.allclose(cross_prod, np.array([0, 0, 0]), atol=TOLERANCE) return (are_parallel1 and are_parallel2, are_directed)
def rod(): c = vectorized.UnitCube1() m2 = np.eye(4) * scale m2[0, 0] = 0.1 * scale m2[1, 1] = 0.1 * scale m2[0:3, 3] = [+0.1 / 2.0 * 2 * scale, +0.1 / 2.0 * 2 * scale, + 1.0 / 2.0 * 2 * scale] m2[3, 3] = 1 iobj = vectorized.Transformed(c, m2) # .move(-0.1/2.0, -0.1/2.0, -1.0/2.0) iobj \ .move(-0.2 * scale, -0.2 * scale, 0) \ .resize(2) \ .rotate(10, along=make_vector4(1, 1, 0), units="deg") \ .move(0.5 * scale, 0, 0) return iobj
def error_i(verts, iobj, type='sqr'): n = verts.shape[0] print(n) e = np.zeros((n, )) for i in range(n): v = verts[i, :] v = make_vector4(v[0], v[1], v[2]) # inefficient #check_vector4(v) e[i] = iobj.implicitFunction(v) #print(np.mean(np.abs(e[i]))) #print(np.max(np.abs(e[i]))) if type == 'sqr': return np.sqrt(np.mean(e[i]**2)) elif type == 'abs': return np.mean(np.abs(e[i])) else: raise "wrong type"
def make_grid_pointwise(iobj, rng): """ An inefficient implementation kept for histotrical reasons""" assert rng.size < 200 (xx, yy, zz) = np.meshgrid(rng, rng, rng) vgrid = xx aany = False for i in range(len(rng)): for j in range(len(rng)): for k in range(len(rng)): x = make_vector4(rng[i], rng[j], rng[k]) vgrid[i, j, k] = iobj.implicitFunction(x) if vgrid[i, j, k] > 0: aany = True assert aany, "No point detected" return vgrid
def rods(): def rod(): c = nonvec.UnitCube1() m2 = np.eye(4) m2[0, 0] = 0.1 m2[1, 1] = 0.1 iobj = nonvec.Transformed(c, m2) iobj \ .move(-0, -0.3, -1.0) \ .resize(2) \ .rotate(40, along=make_vector4(1, 1, 0), units="deg") \ .move(0.5, 0, 0) return iobj u = None for i in range(17): c = rod().rotate(-30 * i, along=make_vector4(0, 0, 1), units="deg") if u is None: u = c else: u = nonvec.CrispUnion(u, c) return u
def optimize_vertex(vert, iobj, radius_of_max_change): v = make_vector4(vert[0], vert[1], vert[2]) # inefficient check_vector4(v) #f = iobj.implicitFunction(v) #g = iobj.implicitGradient(v) #v += g * np.random.rand() * radius_of_max_change * 2 #v[3] = 1 iterations = 2 #14 for i in range(iterations): f = iobj.implicitFunction(v) g = iobj.implicitGradient(v) tau = 0.1 # * 3 a = 1 z_force = -tau * a * f * g v += z_force v[3] = 1 return v[0:3]
def rdice_(ns=nonvec, scale=1., rotated=True): # m = np.eye(4) # m[0:3, 3] = [0, 0, 0] # m[2, 2] = 0.8 # m[1, 2] = -0.4 d = dice(scale, ns=ns) MOON = True if MOON: # Accompanying moon for the dice! (satelite) m1 = np.eye(4) * .3 m1[0:3, 3] = [1.1, 1.1, 0] m1[3, 3] = 1 s = vectorized.Ellipsoid(m1) return ns.CrispUnion(d, s) return d iobj = ns.Transformed(d) iobj \ .move(-0.2 * scale, -0.2 * scale, 0) \ .resize(0.9) iobj.rotate(20, along=make_vector4(1, 1, 1), units="deg") return iobj
def french_fries(): def rod(): c = nonvec.UnitCube1() m2 = np.eye(4) m2[0, 0] = 0.1 m2[1, 1] = 0.1 m2[0:3, 3] = [+0.1 / 2.0 * 2, +0.1 / 2.0 * 2, +1.0 / 2.0 * 2] iobj = nonvec.Transformed(c, m2) iobj \ .move(-0.2, -0.2, 0) \ .resize(2) \ .rotate(10, along=make_vector4(1, 1, 0), units="deg") \ .move(0.5, 0, 0) return iobj u = None for i in range(18): c = rod().rotate(-30 * i, along=make_vector4(0, 0, 1), units="deg") if u is None: u = c else: u = nonvec.CrispUnion(u, c) return u