Exemple #1
0
 def get_curve(self, spline, matrix):
     segments = []
     pairs = zip(spline.bezier_points, spline.bezier_points[1:])
     if spline.use_cyclic_u:
         pairs = list(pairs) + [
             (spline.bezier_points[-1], spline.bezier_points[0])
         ]
     points = []
     is_first = True
     for p1, p2 in pairs:
         c0 = p1.co
         c1 = p1.handle_right
         c2 = p2.handle_left
         c3 = p2.co
         if self.apply_matrix:
             c0, c1, c2, c3 = [tuple(matrix @ c) for c in [c0, c1, c2, c3]]
         else:
             c0, c1, c2, c3 = [tuple(c) for c in [c0, c1, c2, c3]]
         points.append([c0, c1, c2, c3])
         segment = SvCubicBezierCurve(c0, c1, c2, c3)
         segments.append(segment)
     if self.concat_segments:
         return points, concatenate_curves(segments)
     else:
         return points, segments
Exemple #2
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        curve_s = self.inputs['Curve'].sv_get()
        t_before_s = self.inputs['StartExt'].sv_get()
        t_after_s = self.inputs['EndExt'].sv_get()

        t_before_s = ensure_nesting_level(t_before_s, 2)
        t_after_s = ensure_nesting_level(t_after_s, 2)
        curve_s = ensure_nesting_level(curve_s, 2, data_types=(SvCurve, ))

        start_out = []
        end_out = []
        curve_out = []
        for curves, t_before_i, t_after_i in zip_long_repeat(
                curve_s, t_before_s, t_after_s):
            for curve, t_before, t_after in zip_long_repeat(
                    curves, t_before_i, t_after_i):
                start_extent, end_extent = self.extend_curve(
                    curve, t_before, t_after)
                start_out.append(start_extent)
                end_out.append(end_extent)
                curves = []
                if start_extent is not None:
                    curves.append(start_extent)
                curves.append(curve)
                if end_extent is not None:
                    curves.append(end_extent)
                new_curve = concatenate_curves(curves)
                curve_out.append(new_curve)

        self.outputs['StartExtent'].sv_set(start_out)
        self.outputs['EndExtent'].sv_set(end_out)
        self.outputs['ExtendedCurve'].sv_set(curve_out)
Exemple #3
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        verts_s = self.inputs['Vertices'].sv_get()
        tangent_s = self.inputs['Tangent'].sv_get(default = [[[]]])
        have_tangent = self.inputs['Tangent'].is_linked

        verts_s = ensure_nesting_level(verts_s, 3)
        tangent_s = ensure_nesting_level(tangent_s, 3)
        tangent_s = tangent_s[0] # We can use only one tangent per curve, but let's support a spare pair of []

        curve_out = []
        center_out = []
        radius_out = []
        angle_out = []
        for verts, tangent in zip_long_repeat(verts_s, tangent_s):
            new_curves = []
            new_centers = []
            new_radius = []
            new_angles = []

            if not have_tangent:
                tangent = self.calc_tangent(verts)
            elif not isinstance(tangent, Vector):
                tangent = Vector(tangent)

            if self.is_cyclic:
                verts = verts + [verts[0]]

            for start, end in zip(verts, verts[1:]):
                start = Vector(start)
                end = Vector(end)
                diff = end - start
                if diff.angle(tangent) < 1e-8:
                    curve = SvLine.from_two_points(start, end)
                else:
                    eq = circle_by_start_end_tangent(start, end, tangent)
                    curve = SvCircle.from_equation(eq)
                    _, angle = curve.get_u_bounds()
                    tangent = Vector(curve.tangent(angle))
                    new_centers.append(curve.matrix)
                    new_radius.append(curve.radius)
                    new_angles.append(angle)
                new_curves.append(curve)

            if self.make_nurbs:
                new_curves = [c.to_nurbs() for c in new_curves]
            if self.concat:
                new_curves = [concatenate_curves(new_curves)]
            curve_out.append(new_curves)
            center_out.append(new_centers)
            radius_out.append(new_radius)
            angle_out.append(new_angles)

        self.outputs['Curve'].sv_set(curve_out)
        self.outputs['Center'].sv_set(center_out)
        self.outputs['Radius'].sv_set(radius_out)
        self.outputs['Angle'].sv_set(angle_out)
Exemple #4
0
    def make_curve(self, vertices, radiuses):
        if self.cyclic:
            last_fillet = calc_fillet(vertices[-1], vertices[0], vertices[1],
                                      radiuses[0])
            prev_edge_start = last_fillet.p2
            radiuses = radiuses[1:] + [radiuses[0]]
            corners = list(zip(vertices, vertices[1:], vertices[2:], radiuses))
            corners.append(
                (vertices[-2], vertices[-1], vertices[0], radiuses[-1]))
            corners.append(
                (vertices[-1], vertices[0], vertices[1], radiuses[0]))
        else:
            prev_edge_start = vertices[0]
            corners = zip(vertices, vertices[1:], vertices[2:], radiuses)

        curves = []
        centers = []
        for v1, v2, v3, radius in corners:
            fillet = calc_fillet(v1, v2, v3, radius)
            if fillet is not None:
                edge_direction = np.array(
                    fillet.p1) - np.array(prev_edge_start)
                edge_len = np.linalg.norm(edge_direction)
                edge = SvLine(prev_edge_start, edge_direction / edge_len)
                edge.u_bounds = (0.0, edge_len)
                arc = fillet.get_curve()
                prev_edge_start = fillet.p2
                curves.append(edge)
                curves.append(arc)
                centers.append(fillet.matrix)
            else:
                edge = SvLine.from_two_points(prev_edge_start, v2)
                prev_edge_start = v2
                curves.append(edge)

        if not self.cyclic:
            edge_direction = np.array(vertices[-1]) - np.array(prev_edge_start)
            edge_len = np.linalg.norm(edge_direction)
            edge = SvLine(prev_edge_start, edge_direction / edge_len)
            edge.u_bounds = (0.0, edge_len)
            curves.append(edge)

        if self.make_nurbs:
            if self.concat:
                curves = [
                    curve.to_nurbs().elevate_degree(target=2)
                    for curve in curves
                ]
            else:
                curves = [curve.to_nurbs() for curve in curves]
        if self.concat:
            concat = concatenate_curves(curves,
                                        scale_to_unit=self.scale_to_unit)
            return concat, centers
        else:
            return curves, centers
Exemple #5
0
    def build_tangent_curve(cls,
                            points,
                            tangents,
                            cyclic=False,
                            concat=False,
                            as_nurbs=False):
        """
        Build cubic Bezier curve spline, which goes through specified `points',
        having specified `tangents' at these points.

        inputs:
        * points, tangents: lists of 3-tuples
        * cyclic: whether the curve should be closed (cyclic)
        * concat: whether to concatenate all curve segments into single Curve object

        outputs: tuple:
        * list of curve control points - list of lists of 3-tuples
        * list of generated curves; if concat == True, then this list will contain single curve.
        """
        new_curves = []
        new_controls = []

        pairs = list(zip_long_repeat(points, tangents))
        segments = list(zip(pairs, pairs[1:]))
        if cyclic:
            segments.append((pairs[-1], pairs[0]))

        for pair1, pair2 in segments:
            point1, tangent1 = pair1
            point2, tangent2 = pair2
            point1, tangent1 = np.array(point1), np.array(tangent1)
            point2, tangent2 = np.array(point2), np.array(tangent2)
            tangent1, tangent2 = tangent1 / 2.0, tangent2 / 2.0
            curve = SvCubicBezierCurve(point1, point1 + tangent1,
                                       point2 - tangent2, point2)
            curve_controls = [
                curve.p0.tolist(),
                curve.p1.tolist(),
                curve.p2.tolist(),
                curve.p3.tolist()
            ]
            if as_nurbs:
                curve = curve.to_nurbs()
            new_curves.append(curve)
            new_controls.append(curve_controls)
        if concat:
            new_curve = concatenate_curves(new_curves)
            new_curves = [new_curve]
            if as_nurbs:
                new_controls = new_curve.get_control_points().tolist()

        return new_controls, new_curves
Exemple #6
0
 def to_nurbs(self, implementation=SvNurbsCurve.NATIVE):
     control_points = self.spline.get_control_points()
     degree = 3 if isinstance(self.spline, CubicSpline) else 1
     n_points = 4 if isinstance(self.spline, CubicSpline) else 2
     knotvector = sv_knotvector.generate(degree, n_points)
     t_segments = self.spline.get_t_segments()
     segments = [
         SvNurbsCurve.build(implementation, degree, knotvector, points)
         for points in control_points
     ]
     segments = [
         reparametrize_curve(segment, t_min, t_max)
         for segment, (t_min, t_max) in zip(segments, t_segments)
     ]
     #         pairs = [f"#{i}: {t_min}-{t_max}: {segment.evaluate(t_min)} -- {segment.evaluate(t_max)}" for i, (segment, (t_min, t_max)) in enumerate(zip(segments, t_segments))]
     #         pairs = ", ".join(pairs)
     #         print(f"S: {pairs}")
     return concatenate_curves(segments, allow_generic=False)
Exemple #7
0
        def process(self):
            if not any(socket.is_linked for socket in self.outputs):
                return

            curve_s = self.inputs['Curves'].sv_get()
            if isinstance(curve_s[0], SvCurve):
                curve_s = [curve_s]

            curves_out = []
            for curves in curve_s:
                if self.check:
                    self.run_check(curves)
                if self.all_nurbs:
                    curves = self.to_nurbs(curves)
                new_curve = concatenate_curves(curves, allow_generic=not self.all_nurbs)
                curves_out.append(new_curve)

            self.outputs['Curve'].sv_set(curves_out)
Exemple #8
0
 def to_nurbs(self, implementation=None):
     return concatenate_curves(
         [self.arc1.to_nurbs(), self.arc2.to_nurbs()], allow_generic=False)
Exemple #9
0
    def process(self):

        # upgrades older versions of ProfileMK3 to the version that has self.file_pointer
        if self.filename and not self.file_pointer:
            text = self.get_bpy_data_from_name(self.filename, bpy.data.texts)
            if text:
                self.file_pointer = text

        if not any(o.is_linked for o in self.outputs):
            return

        sync_pointer_and_stored_name(self, "file_pointer", "filename")

        profile = self.load_profile()
        optional_inputs = self.get_optional_inputs(profile)

        var_names = self.get_variables()
        self.debug("Var_names: %s; optional: %s", var_names, optional_inputs)
        inputs = self.get_input()

        result_vertices = []
        result_edges = []
        result_knots = []
        result_names = []
        result_curves = []

        if var_names:
            input_values = []
            for name in var_names:
                try:
                    input_values.append(inputs[name])
                except KeyError as e:
                    name = e.args[0]
                    if name not in optional_inputs:
                        if name in self.inputs:
                            raise SvNoDataError(self.inputs[name])
                        else:
                            self.adjust_sockets()
                            raise SvNoDataError(self.inputs[name])
                    else:
                        input_values.append([None])
            parameters = match_long_repeat(input_values)
        else:
            parameters = [[[]]]

        input_names = [
            socket.name for socket in self.inputs if socket.is_linked
        ]

        for values in zip(*parameters):
            variables = dict(zip(var_names, values))
            curves_form = Interpreter.NURBS if self.nurbs_out else None
            interpreter = Interpreter(self,
                                      input_names,
                                      curves_form=curves_form,
                                      z_axis=self.selected_axis)
            interpreter.interpret(profile, variables)
            verts = self.extend_out_verts(interpreter.vertices)
            result_vertices.append(verts)
            result_edges.append(interpreter.edges)
            knots = self.extend_out_verts(interpreter.knots)
            result_knots.append(knots)
            result_names.append([[name] for name in interpreter.knotnames])
            all_curves = interpreter.curves
            if self.concat_curves:
                new_curves = []
                for curves in self.group_curves(all_curves):
                    if self.nurbs_out:
                        curves = unify_curves_degree(curves)
                    curve = concatenate_curves(curves)
                    new_curves.append(curve)
                result_curves.append(new_curves)
            else:
                result_curves.append(all_curves)

        self.outputs['Vertices'].sv_set(result_vertices)
        self.outputs['Edges'].sv_set(result_edges)
        self.outputs['Knots'].sv_set(result_knots)
        self.outputs['KnotNames'].sv_set(result_names)
        if 'Curve' in self.outputs:
            self.outputs['Curve'].sv_set(result_curves)
    def make_curve(self, size_x, size_y, radiuses):
        r1, r2, r3, r4 = radiuses[:4]
        p1 = Vector((r1, 0, 0))
        p2 = Vector((size_x - r2, 0, 0))
        p3 = Vector((size_x, r2, 0))
        p4 = Vector((size_x, size_y - r3, 0))
        p5 = Vector((size_x - r3, size_y, 0))
        p6 = Vector((r4, size_y, 0))
        p7 = Vector((0, size_y - r4, 0))
        p8 = Vector((0, r1, 0))

        c1 = Vector((r1, r1, 0))
        c2 = Vector((size_x - r2, r2, 0))
        c3 = Vector((size_x - r3, size_y - r3, 0))
        c4 = Vector((r4, size_y - r4, 0))

        if self.center:
            center = Vector((size_x / 2.0, size_y / 2.0, 0))
            p1 -= center
            p2 -= center
            p3 -= center
            p4 -= center
            p5 -= center
            p6 -= center
            p7 -= center
            p8 -= center

            c1 -= center
            c2 -= center
            c3 -= center
            c4 -= center

        def make_arc(center, radius, angle):
            matrix = Matrix.Translation(center) @ Matrix.Rotation(
                angle, 4, 'Z')
            circle = SvCircle(matrix, radius)
            circle.u_bounds = (0, pi / 2)
            return circle

        curves = []
        if r1 > 0:
            curves.append(make_arc(c1, r1, pi))
        if (p2 - p1).length > 0:
            curves.append(SvLine.from_two_points(p1, p2))
        if r2 > 0:
            curves.append(make_arc(c2, r2, 3 * pi / 2))
        if (p4 - p3).length > 0:
            curves.append(SvLine.from_two_points(p3, p4))
        if r3 > 0:
            curves.append(make_arc(c3, r3, 0))
        if (p6 - p5).length > 0:
            curves.append(SvLine.from_two_points(p5, p6))
        if r4 > 0:
            curves.append(make_arc(c4, r4, pi / 2))
        if (p8 - p7).length > 0:
            curves.append(SvLine.from_two_points(p7, p8))

        if self.make_nurbs:
            curves = [curve.to_nurbs() for curve in curves]
        curve = concatenate_curves(curves, scale_to_unit=self.scale_to_unit)
        return (c1, c2, c3, c4), curve
Exemple #11
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        output_src = self.output_src or self.concat

        curves_out = []
        controls_out = []
        is_first = True
        for curve1, curve2, factor1, factor2, parameter in self.get_inputs():
            _, t_max_1 = curve1.get_u_bounds()
            t_min_2, _ = curve2.get_u_bounds()

            curve1_end = curve1.evaluate(t_max_1)
            curve2_begin = curve2.evaluate(t_min_2)

            smooth = self.smooth_mode

            if smooth == '0':
                new_curve = SvLine.from_two_points(curve1_end, curve2_begin)
                new_controls = [curve1_end, curve2_begin]
            elif smooth == '1':
                tangent_1_end = curve1.tangent(t_max_1)
                tangent_2_begin = curve2.tangent(t_min_2)

                tangent1 = factor1 * tangent_1_end
                tangent2 = factor2 * tangent_2_begin

                new_curve = SvCubicBezierCurve(curve1_end,
                                               curve1_end + tangent1 / 3.0,
                                               curve2_begin - tangent2 / 3.0,
                                               curve2_begin)
                new_controls = [
                    new_curve.p0.tolist(),
                    new_curve.p1.tolist(),
                    new_curve.p2.tolist(),
                    new_curve.p3.tolist()
                ]
            elif smooth == '1b':
                tangent_1_end = curve1.tangent(t_max_1)
                tangent_2_begin = curve2.tangent(t_min_2)

                new_curve = SvBiArc.calc(
                    curve1_end,
                    curve2_begin,
                    tangent_1_end,
                    tangent_2_begin,
                    parameter,
                    planar_tolerance=self.planar_tolerance)

                new_controls = [new_curve.junction.tolist()]
            elif smooth == '2':
                tangent_1_end = curve1.tangent(t_max_1)
                tangent_2_begin = curve2.tangent(t_min_2)
                second_1_end = curve1.second_derivative(t_max_1)
                second_2_begin = curve2.second_derivative(t_min_2)

                new_curve = SvBezierCurve.blend_second_derivatives(
                    curve1_end, tangent_1_end, second_1_end, curve2_begin,
                    tangent_2_begin, second_2_begin)
                new_controls = [p.tolist() for p in new_curve.points]
            elif smooth == '3':
                tangent_1_end = curve1.tangent(t_max_1)
                tangent_2_begin = curve2.tangent(t_min_2)
                second_1_end = curve1.second_derivative(t_max_1)
                second_2_begin = curve2.second_derivative(t_min_2)
                third_1_end = curve1.third_derivative_array(np.array([t_max_1
                                                                      ]))[0]
                third_2_begin = curve2.third_derivative_array(
                    np.array([t_min_2]))[0]

                new_curve = SvBezierCurve.blend_third_derivatives(
                    curve1_end, tangent_1_end, second_1_end, third_1_end,
                    curve2_begin, tangent_2_begin, second_2_begin,
                    third_2_begin)
                new_controls = [p.tolist() for p in new_curve.points]
            else:
                raise Exception("Unsupported smooth level")

            if self.mode == 'N' and not self.cyclic and output_src and is_first:
                curves_out.append(curve1)
            curves_out.append(new_curve)
            if self.mode == 'N' and output_src:
                curves_out.append(curve2)
            controls_out.append(new_controls)

            is_first = False

        if self.concat:
            curves_out = [concatenate_curves(curves_out)]

        self.outputs['Curve'].sv_set(curves_out)
        self.outputs['ControlPoints'].sv_set(controls_out)
Exemple #12
0
    def process(self):
        if not any(o.is_linked for o in self.outputs):
            return

        verts_s = self.inputs['Vertices'].sv_get()
        threshold_s = self.inputs['AngneThreshold'].sv_get()

        verts_s = ensure_nesting_level(verts_s, 4)
        threshold_s = ensure_nesting_level(threshold_s, 2)

        curve_out = []
        for verts_i, threshold_i in zip_long_repeat(verts_s, threshold_s):
            for verts, threshold in zip_long_repeat(verts_i, threshold_i):
                verts = [Vector(v) for v in verts]

                if self.is_cyclic:
                    verts.append(verts[0])

                segments = [[verts[0]]]
                for v1, v2, v3 in zip(verts, verts[1:], verts[2:]):
                    dv1 = v2 - v1
                    dv2 = v2 - v3
                    angle = dv1.angle(dv2)
                    if angle < threshold:
                        segments[-1].append(v2)
                        segment = [v2]
                        segments.append(segment)
                    else:
                        segments[-1].append(v2)
                if not self.is_cyclic:
                    segments[-1].append(verts[-1])

                if self.is_cyclic:
                    v1, v2, v3 = verts[-2], verts[0], verts[1]
                    dv1 = v2 - v1
                    dv2 = v2 - v3
                    angle = dv1.angle(dv2)
                    if angle < threshold:
                        segments[-1].append(verts[-1])
                    else:
                        first_segment = segments[0]
                        segments = segments[1:]
                        segments[-1].extend(first_segment)

                new_curves = [
                    SvSplineCurve.from_points(segment, metric=self.metric)
                    for segment in segments
                ]
                if self.make_nurbs:
                    if self.concat:
                        new_curves = [
                            curve.to_nurbs().elevate_degree(target=3)
                            for curve in new_curves
                        ]
                    else:
                        new_curves = [curve.to_nurbs() for curve in new_curves]
                if self.concat:
                    new_curves = [concatenate_curves(new_curves)]
                curve_out.append(new_curves)

        self.outputs['Curve'].sv_set(curve_out)