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
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)
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)
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
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
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)
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)
def to_nurbs(self, implementation=None): return concatenate_curves( [self.arc1.to_nurbs(), self.arc2.to_nurbs()], allow_generic=False)
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
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)
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)