def test_circle_1(self): circle = SvCircle(Matrix(), 1.0) circle.u_bounds = (0, pi / 6) nurbs = circle.to_nurbs() cpts = nurbs.get_control_points() expected_cpts = np.array([[1.0, 0.0, 0.0], [1.0, 0.26794919, 0.0], [0.8660254, 0.5, 0.0]]) self.assert_numpy_arrays_equal(cpts, expected_cpts, precision=6)
def test_circle_2(self): circle = SvCircle(Matrix(), 1.0) t_max = pi + 0.3 circle.u_bounds = (0, t_max) nurbs = circle.to_nurbs() ts = np.array([0, pi / 2, pi, t_max]) points = nurbs.evaluate_array(ts) expected_points = circle.evaluate_array(ts) self.assert_numpy_arrays_equal(points, expected_points, precision=6)
def get_circular_arc(self): center = np.array(self.center) normal = np.array(self.normal) p1 = np.array(self.p1) circle = SvCircle(center = center, normal = -normal, vectorx = p1 - center) circle.u_bounds = (0.0, self.angle) #circle.u_bounds = (-self.angle, 0.0) return circle
def test_arc_2(self): pt1 = (-5, 0, 0) pt2 = (-4, 3, 0) pt3 = (-3, 4, 0) eq = circle_by_three_points(pt1, pt2, pt3) matrix = eq.get_matrix() arc = SvCircle(matrix, eq.radius) arc.u_bounds = (0.0, eq.arc_angle) nurbs = arc.to_nurbs() u_min, u_max = nurbs.get_u_bounds() self.assertEquals(u_min, 0, "U_min") self.assertEquals(u_max, eq.arc_angle, "U_max") startpoint = nurbs.evaluate(u_min) self.assert_sverchok_data_equal(startpoint.tolist(), pt1, precision=8) endpoint = nurbs.evaluate(u_max) self.assert_sverchok_data_equal(endpoint.tolist(), pt3, precision=8)
def nurbs_revolution_surface(curve, origin, axis, v_min=0, v_max=2 * pi, global_origin=True): my_control_points = curve.get_control_points() my_weights = curve.get_weights() control_points = [] weights = [] any_circle = SvCircle(Matrix(), 1) any_circle.u_bounds = (v_min, v_max) any_circle = any_circle.to_nurbs() # all circles with given (v_min, v_max) # actually always have the same knotvector # and the same number of control points n = len(any_circle.get_control_points()) circle_knotvector = any_circle.get_knotvector() circle_weights = any_circle.get_weights() # TODO: vectorize with numpy? Or better let it so for better readability? for my_control_point, my_weight in zip(my_control_points, my_weights): eq = CircleEquation3D.from_axis_point(origin, axis, my_control_point) if abs(eq.radius) < 1e-8: parallel_points = np.empty((n, 3)) parallel_points[:] = np.array(eq.center) #[np.newaxis].T else: circle = SvCircle.from_equation(eq) circle.u_bounds = (v_min, v_max) nurbs_circle = circle.to_nurbs() parallel_points = nurbs_circle.get_control_points() parallel_weights = circle_weights * my_weight control_points.append(parallel_points) weights.append(parallel_weights) control_points = np.array(control_points) if global_origin: control_points = control_points - origin weights = np.array(weights) degree_u = curve.get_degree() degree_v = 2 # circle return SvNurbsSurface.build(curve.get_nurbs_implementation(), degree_u, degree_v, curve.get_knotvector(), circle_knotvector, control_points, weights)
def test_arc_3(self): pt1 = np.array((-4, 2, 0)) pt2 = np.array((0, 2.5, 0)) pt3 = np.array((4, 2, 0)) eq = circle_by_three_points(pt1, pt2, pt3) #matrix = eq.get_matrix() arc = SvCircle(center=np.array(eq.center), vectorx=np.array(pt1 - eq.center), normal=eq.normal) arc.u_bounds = (0.0, eq.arc_angle) nurbs = arc.to_nurbs() u_min, u_max = nurbs.get_u_bounds() self.assertEquals(u_min, 0, "U_min") self.assertEquals(u_max, eq.arc_angle, "U_max") startpoint = nurbs.evaluate(u_min) self.assert_sverchok_data_equal(startpoint.tolist(), pt1, precision=6) endpoint = nurbs.evaluate(u_max) self.assert_sverchok_data_equal(endpoint.tolist(), pt3, precision=6)
def calc(point_a, point_b, tangent_a, tangent_b, p, planar_tolerance=1e-6): xx = point_b - point_a xx /= np.linalg.norm(xx) tangent_normal = np.cross(tangent_a, tangent_b) volume = np.dot(xx, tangent_normal) if abs(volume) > planar_tolerance: raise Exception( f"Provided tangents are not coplanar, volume={volume}") zz_a = np.cross(tangent_a, xx) zz_b = np.cross(tangent_b, xx) zz = (zz_a + zz_b) zz /= np.linalg.norm(zz) yy = np.cross(zz, xx) c = np.linalg.norm(point_b - point_a) * 0.5 tangent_a /= np.linalg.norm(tangent_a) tangent_b /= np.linalg.norm(tangent_b) to_center_a = np.cross(zz, tangent_a) to_center_b = -np.cross(zz, tangent_b) matrix_inv = np.stack((xx, yy, zz)) matrix = np.linalg.inv(matrix_inv) # TODO: sin(arccos(...)) = ... alpha = acos(np.dot(tangent_a, xx)) beta = acos(np.dot(tangent_b, xx)) if np.dot(tangent_a, yy) > 0: alpha = -alpha if np.dot(tangent_b, yy) > 0: beta = -beta #print("A", alpha, "B", beta) omega = (alpha + beta) * 0.5 r1 = c / (sin(alpha) + sin(omega) / p) r2 = c / (sin(beta) + p * sin(omega)) #print("R1", r1, "R2", r2) theta1 = 2 * arg(cexp(-1j * alpha) + cexp(-1j * omega) / p) theta2 = 2 * arg(cexp(1j * beta) + p * cexp(1j * omega)) #print("T1", theta1, "T2", theta2) vectorx_a = r1 * to_center_a center1 = point_a + vectorx_a center2 = point_b + r2 * to_center_b arc1 = SvCircle( #radius = r1, center=center1, normal=-zz, vectorx=point_a - center1) if theta1 > 0: arc1.u_bounds = (0.0, theta1) else: theta1 = -theta1 arc1.u_bounds = (0.0, theta1) arc1.set_normal(-arc1.normal) junction = arc1.evaluate(theta1) #print("J", junction) arc2 = SvCircle( #radius = r2, center=center2, normal=-zz, vectorx=junction - center2) if theta2 > 0: arc2.u_bounds = (0.0, theta2) else: theta2 = -theta2 arc2.u_bounds = (0.0, theta2) arc2.set_normal(-arc2.normal) curve = SvBiArc(arc1, arc2) curve.p = p curve.junction = junction return curve