def test_arc_derivative_1(self): pt1 = (-5, 0, 0) pt2 = (-4, 3, 0) pt3 = (-3, 4, 0) eq = circle_by_three_points(pt1, pt2, pt3) circle = SvCircle.from_equation(eq) dv = circle.tangent(0) expected = np.array([0, 5, 0]) self.assert_numpy_arrays_equal(dv, expected, precision=8)
def test_arc_values_1(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) circle = SvCircle.from_equation(eq) res1 = circle.evaluate(0) self.assert_numpy_arrays_equal(res1, pt1, precision=6) t_max = eq.arc_angle res2 = circle.evaluate(t_max) self.assert_numpy_arrays_equal(res2, pt3, precision=6)
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 extend_curve(curve, t_before, t_after, mode='LINE', len_mode='T', len_resolution=50): def make_line(point, tangent, t_ext, sign): if sign < 0: before_start = point - t_ext * tangent # / np.linalg.norm(tangent_start) return SvLine.from_two_points(before_start, point) else: after_end = point + t_ext * tangent # / np.linalg.norm(tangent_end) return SvLine.from_two_points(point, after_end) u_min, u_max = curve.get_u_bounds() start, end = curve.evaluate(u_min), curve.evaluate(u_max) start_extent, end_extent = None, None is_nurbs = isinstance(curve, SvNurbsCurve) if mode == 'LINE': tangent_start = curve.tangent(u_min) tangent_end = curve.tangent(u_max) if t_before > 0: start_extent = make_line(start, tangent_start, t_before, -1) start_extent = set_length(curve, start_extent, t_before, -1, len_mode=len_mode, len_resolution=len_resolution) if t_after > 0: end_extent = make_line(end, tangent_end, t_after, +1) end_extent = set_length(curve, end_extent, t_after, +1, len_mode=len_mode, len_resolution=len_resolution) elif mode == 'ARC': tangent_start = curve.tangent(u_min) tangent_end = curve.tangent(u_max) second_start = curve.second_derivative(u_min) second_end = curve.second_derivative(u_max) if t_before > 0: if np.linalg.norm(second_start) > 1e-6: eq1 = circle_by_two_derivatives(start, -tangent_start, second_start) start_extent = SvCircle.from_equation(eq1) start_extent = set_length(curve, start_extent, t_before, -1, len_mode=len_mode, len_resolution=len_resolution) if is_nurbs: start_extent = start_extent.to_nurbs() start_extent = reverse_curve(start_extent) else: start_extent = make_line(start, tangent_start, t_before, -1) start_extent = set_length(curve, start_extent, t_before, -1, len_mode=len_mode, len_resolution=len_resolution) if t_after > 0: if np.linalg.norm(second_end) > 1e-6: eq2 = circle_by_two_derivatives(end, tangent_end, second_end) end_extent = SvCircle.from_equation(eq2) else: end_extent = make_line(end, tangent_end, t_after, +1) end_extent = set_length(curve, end_extent, t_after, +1, len_mode=len_mode, len_resolution=len_resolution) elif mode == 'QUAD': tangent_start = curve.tangent(u_min) tangent_end = curve.tangent(u_max) second_start = curve.second_derivative(u_min) second_end = curve.second_derivative(u_max) if t_before > 0: start_extent = SvTaylorCurve(start, [-tangent_start, second_start]) start_extent = set_length(curve, start_extent, t_before, len_mode=len_mode, len_resolution=len_resolution) if is_nurbs: start_extent = start_extent.to_nurbs() start_extent = reverse_curve(start_extent) if t_after > 0: end_extent = SvTaylorCurve(end, [tangent_end, second_end]) end_extent = set_length(curve, end_extent, t_after, len_mode=len_mode, len_resolution=len_resolution) elif mode == 'CUBIC': tangent_start = curve.tangent(u_min) tangent_end = curve.tangent(u_max) second_start = curve.second_derivative(u_min) second_end = curve.second_derivative(u_max) third_start, third_end = curve.third_derivative_array( np.array([u_min, u_max])) if t_before > 0: start_extent = SvTaylorCurve( start, [-tangent_start, second_start, -third_start]) start_extent = set_length(curve, start_extent, t_before, len_mode=len_mode, len_resolution=len_resolution) if is_nurbs: start_extent = start_extent.to_nurbs() start_extent = reverse_curve(start_extent) if t_after > 0: end_extent = SvTaylorCurve(end, [tangent_end, second_end, third_end]) end_extent = set_length(curve, end_extent, t_after, len_mode=len_mode, len_resolution=len_resolution) else: raise Exception("Unsupported mode") if is_nurbs: if start_extent is not None and not isinstance(start_extent, SvNurbsCurve): start_extent = start_extent.to_nurbs( implementation=curve.get_nurbs_implementation()) if end_extent is not None and not isinstance(end_extent, SvNurbsCurve): end_extent = end_extent.to_nurbs( implementation=curve.get_nurbs_implementation()) return start_extent, end_extent