Exemplo n.º 1
0
class SvConstPipeSurface(SvSurface):
    __description__ = "Pipe"

    def __init__(self, curve, radius, algorithm = FRENET, resolution=50):
        self.curve = curve
        self.radius = radius
        self.circle = SvCircle(Matrix(), radius)
        self.algorithm = algorithm
        self.normal_delta = 0.001
        self.u_bounds = self.circle.get_u_bounds()
        if algorithm in {FRENET, ZERO, TRACK_NORMAL}:
            self.calculator = DifferentialRotationCalculator(curve, algorithm, resolution)

    def get_u_min(self):
        return self.u_bounds[0]

    def get_u_max(self):
        return self.u_bounds[1]

    def get_v_min(self):
        return self.curve.get_u_bounds()[0]

    def get_v_max(self):
        return self.curve.get_u_bounds()[1]

    def evaluate(self, u, v):
        return self.evaluate_array(np.array([u]), np.array([v]))[0]

    def get_matrix(self, tangent):
        return MathutilsRotationCalculator.get_matrix(tangent, scale=1.0,
                axis=2,
                algorithm = self.algorithm,
                scale_all=False)

    def get_matrices(self, ts):
        if self.algorithm in {FRENET, ZERO, TRACK_NORMAL}:
            return self.calculator.get_matrices(ts)
        elif self.algorithm in {HOUSEHOLDER, TRACK, DIFF}:
            tangents = self.curve.tangent_array(ts)
            matrices = np.vectorize(lambda t : self.get_matrix(t), signature='(3)->(3,3)')(tangents)
            return matrices
        else:
            raise Exception("Unsupported algorithm")

    def evaluate_array(self, us, vs):
        profile_vectors = self.circle.evaluate_array(us)
        u_min, u_max = self.circle.get_u_bounds()
        v_min, v_max = self.curve.get_u_bounds()
        profile_vectors = np.transpose(profile_vectors[np.newaxis], axes=(1, 2, 0))
        extrusion_start = self.curve.evaluate(v_min)
        extrusion_points = self.curve.evaluate_array(vs)
        extrusion_vectors = extrusion_points - extrusion_start

        matrices = self.get_matrices(vs)

        profile_vectors = (matrices @ profile_vectors)[:,:,0]
        result = extrusion_vectors + profile_vectors
        result = result + extrusion_start
        return result
Exemplo n.º 2
0
 def test_arc_1(self):
     circle = SvCircle(Matrix(), 1.0)
     t_min = 0.1
     t_max = 1.4
     pt1 = circle.evaluate(t_max)
     nurbs = circle._arc_to_nurbs(t_min, t_max)
     pt2 = nurbs.evaluate(t_max)
     self.assert_numpy_arrays_equal(pt1, pt2, precision=8)
Exemplo n.º 3
0
 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)
Exemplo n.º 4
0
 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)
Exemplo n.º 5
0
 def __init__(self, curve, radius, algorithm = FRENET, resolution=50):
     self.curve = curve
     self.radius = radius
     self.circle = SvCircle(Matrix(), radius)
     self.algorithm = algorithm
     self.normal_delta = 0.001
     self.u_bounds = self.circle.get_u_bounds()
     if algorithm in {FRENET, ZERO, TRACK_NORMAL}:
         self.calculator = DifferentialRotationCalculator(curve, algorithm, resolution)
Exemplo n.º 6
0
    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
Exemplo n.º 7
0
 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)
Exemplo n.º 8
0
 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)
Exemplo n.º 9
0
 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)
Exemplo n.º 10
0
 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)
Exemplo n.º 11
0
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)
Exemplo n.º 12
0
    def test_circle_equal_1(self):
        circle1 = SvCircle(Matrix(), 1.0)
        x = np.array([1, 0, 0])
        origin = np.array([0, 0, 0])
        z = np.array([0, 0, 1])
        circle2 = SvCircle(center=origin, normal=z, vectorx=x)

        ts = np.linspace(0, pi / 2, num=50)

        pts1 = circle1.evaluate_array(ts)
        pts2 = circle2.evaluate_array(ts)
        self.assert_numpy_arrays_equal(pts1, pts2, precision=8)
Exemplo n.º 13
0
    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
Exemplo n.º 14
0
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