예제 #1
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        curve1_s = self.inputs['Curve1'].sv_get()
        curve2_s = self.inputs['Curve2'].sv_get()

        curve1_s = ensure_nesting_level(curve1_s, 2, data_types=(SvCurve, ))
        curve2_s = ensure_nesting_level(curve2_s, 2, data_types=(SvCurve, ))

        points_out = []
        t1_out = []
        t2_out = []

        for curve1s, curve2s in zip_long_repeat(curve1_s, curve2_s):
            new_points = []
            new_t1 = []
            new_t2 = []
            for curve1, curve2 in self.match(curve1s, curve2s):
                curve1 = SvNurbsCurve.to_nurbs(curve1)
                if curve1 is None:
                    raise Exception("Curve1 is not a NURBS")
                curve2 = SvNurbsCurve.to_nurbs(curve2)
                if curve2 is None:
                    raise Exception("Curve2 is not a NURBS")

                if self.implementation == 'SCIPY':
                    t1s, t2s, ps = self.process_native(curve1, curve2)
                else:
                    t1s, t2s, ps = self.process_freecad(curve1, curve2)

                if self.check_intersection:
                    if not ps:
                        raise Exception("Some curves do not intersect!")

                if self.single:
                    if len(ps) >= 1:
                        ps = ps[0]
                        t1s = t1s[0]
                        t2s = t2s[0]

                new_points.append(ps)
                new_t1.append(t1s)
                new_t2.append(t2s)

            if self.split:
                n = len(curve1s)
                new_points = split_by_count(new_points, n)
                new_t1 = split_by_count(new_t1, n)
                new_t1 = transpose_list(new_t1)
                new_t2 = split_by_count(new_t2, n)

            points_out.append(new_points)
            t1_out.append(new_t1)
            t2_out.append(new_t2)

        self.outputs['Intersections'].sv_set(points_out)
        self.outputs['T1'].sv_set(t1_out)
        self.outputs['T2'].sv_set(t2_out)
예제 #2
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        curve_s = self.inputs['Curve'].sv_get()
        field_s = self.inputs['Field'].sv_get()
        coeff_s = self.inputs['Coefficient'].sv_get()

        curve_s = ensure_nesting_level(curve_s, 2, data_types=(SvCurve, ))
        field_s = ensure_nesting_level(field_s,
                                       2,
                                       data_types=(SvVectorField, ))
        coeff_s = ensure_nesting_level(coeff_s, 2)

        curve_out = []
        for curve_i, field_i, coeff_i in zip_long_repeat(
                curve_s, field_s, coeff_s):
            new_curves = []
            for curve, field, coeff in zip_long_repeat(curve_i, field_i,
                                                       coeff_i):
                if self.use_control_points:
                    nurbs = SvNurbsCurve.to_nurbs(curve)
                    if nurbs is not None:
                        control_points = nurbs.get_control_points()
                    else:
                        raise Exception("Curve is not a NURBS!")

                    cpt_xs = control_points[:, 0]
                    cpt_ys = control_points[:, 1]
                    cpt_zs = control_points[:, 2]

                    cpt_dxs, cpt_dys, cpt_dzs = field.evaluate_grid(
                        cpt_xs, cpt_ys, cpt_zs)
                    xs = cpt_xs + coeff * cpt_dxs
                    ys = cpt_ys + coeff * cpt_dys
                    zs = cpt_zs + coeff * cpt_dzs

                    control_points = np.stack((xs, ys, zs)).T

                    knotvector = nurbs.get_knotvector()
                    #old_t_min, old_t_max = curve.get_u_bounds()
                    #knotvector = sv_knotvector.rescale(knotvector, old_t_min, old_t_max)
                    new_curve = SvNurbsCurve.build(
                        nurbs.get_nurbs_implementation(), nurbs.get_degree(),
                        knotvector, control_points, nurbs.get_weights())
                    new_curve.u_bounds = nurbs.u_bounds
                else:
                    new_curve = SvDeformedByFieldCurve(curve, field, coeff)
                new_curves.append(new_curve)

            if self.join:
                curve_out.extend(new_curves)
            else:
                curve_out.append(new_curves)

        self.outputs['Curve'].sv_set(curve_out)
예제 #3
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        u_curves_s = self.inputs['CurvesU'].sv_get()
        v_curves_s = self.inputs['CurvesV'].sv_get()
        intersections_s = self.inputs['Intersections'].sv_get()

        if self.explicit_t_values:
            t1_s = self.inputs['T1'].sv_get()
            t2_s = self.inputs['T2'].sv_get()
        else:
            t1_s = [[[]]]
            t2_s = [[[]]]

        u_curves_s = ensure_nesting_level(u_curves_s, 2, data_types=(SvCurve,))
        v_curves_s = ensure_nesting_level(v_curves_s, 2, data_types=(SvCurve,))
        t1_s = ensure_nesting_level(t1_s, 3)
        t2_s = ensure_nesting_level(t2_s, 3)
        intersections_s = ensure_nesting_level(intersections_s, 4)

        surface_out = []
        for u_curves, v_curves, t1s, t2s, intersections in zip_long_repeat(u_curves_s, v_curves_s, t1_s, t2_s, intersections_s):
            u_curves = [SvNurbsCurve.to_nurbs(c) for c in u_curves]
            if any(c is None for c in u_curves):
                raise Exception("Some of U curves are not NURBS!")
            v_curves = [SvNurbsCurve.to_nurbs(c) for c in v_curves]
            if any(c is None for c in v_curves):
                raise Exception("Some of V curves are not NURBS!")

            if self.explicit_t_values:
                if len(t1s) < len(u_curves):
                    t1s = repeat_last_for_length(t1s, len(u_curves))
                elif len(t1s) > len(u_curves):
                    raise Exception(f"Number of items in T1 input {len(t1s)} > number of U-curves {len(u_curves)}")

                if len(t1s[0]) != len(v_curves):
                    raise Exception(f"Length of items in T1 input {len(t1s[0])} != number of V-curves {len(v_curves)}")

                if len(t2s) < len(v_curves):
                    t2s = repeat_last_for_length(t2s, len(v_curves))
                elif len(t2s) > len(v_curves):
                    raise Exception(f"Number of items in T2 input {len(t2s)} > number of V-curves {len(v_curves)}")

                if len(t2s[0]) != len(u_curves):
                    raise Exception(f"Length of items in T2 input {len(t2s[0])} != number of U-curves {len(u_curves)}")

            if self.explicit_t_values:
                kwargs = {'u_knots': np.array(t1s), 'v_knots': np.array(t2s)}
            else:
                kwargs = dict()
            _, _, _, surface = gordon_surface(u_curves, v_curves, intersections, metric=self.metric, knotvector_accuracy = self.knotvector_accuracy, **kwargs)
            surface_out.append(surface)

        self.outputs['Surface'].sv_set(surface_out)
예제 #4
0
 def test_curve_3436(self):
     points = [(0.0, 0.0, 0.0), (0.5, 0.0, 0.5), (1.0, 0.0, 0.0)]
     ts = np.array([0, 0.5, 1, 1.61803397])
     #ts = self.ts
     degree = 2
     knotvector = [0, 0, 0, 1, 1, 1]
     weights = [1, 1, 1]
     geomdl_curve = SvNurbsCurve.build('GEOMDL', degree, knotvector, points,
                                       weights)
     native_curve = SvNurbsCurve.build('NATIVE', degree, knotvector, points,
                                       weights)
     p1s = geomdl_curve.evaluate_array(ts)
     p2s = native_curve.evaluate_array(ts)
     #print("NATIVE:", p2s)
     self.assert_numpy_arrays_equal(p1s, p2s, precision=8)
예제 #5
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        curve_s = self.inputs['Curve'].sv_get()

        input_level = get_data_nesting_level(curve_s, data_types=(SvCurve,))
        flat_output = input_level < 2
        curve_s = ensure_nesting_level(curve_s, 2, data_types=(SvCurve,))

        tolerance = self.tolerance

        curves_out = []
        for curves in curve_s:
            new_curves = []
            for curve in curves:
                curve = SvNurbsCurve.to_nurbs(curve)
                if curve is None:
                    raise Exception("One of curves is not NURBS")
                curve = remove_excessive_knots(curve, tolerance=tolerance)
                new_curves.append(curve)
            if flat_output:
                curves_out.extend(new_curves)
            else:
                curves_out.append(new_curves)

        self.outputs['Curve'].sv_set(curves_out)
예제 #6
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        curve_s = self.inputs['Curve'].sv_get()
        knot_s = self.inputs['Knot'].sv_get()
        count_s = self.inputs['Count'].sv_get()

        input_level = get_data_nesting_level(curve_s, data_types=(SvCurve, ))
        flat_output = input_level < 2
        curve_s = ensure_nesting_level(curve_s, 2, data_types=(SvCurve, ))
        knot_s = ensure_nesting_level(knot_s, 3)
        count_s = ensure_nesting_level(count_s, 3)

        curves_out = []
        for curves, knots_i, counts_i in zip_long_repeat(
                curve_s, knot_s, count_s):
            new_curves = []
            for curve, knots, counts in zip_long_repeat(
                    curves, knots_i, counts_i):
                curve = SvNurbsCurve.to_nurbs(curve)
                if curve is None:
                    raise Exception("One of curves is not NURBS")
                for knot, count in zip_long_repeat(knots, counts):
                    curve = curve.insert_knot(knot,
                                              count,
                                              if_possible=self.if_possible)
                new_curves.append(curve)
            if flat_output:
                curves_out.extend(new_curves)
            else:
                curves_out.append(new_curves)

        self.outputs['Curve'].sv_set(curves_out)
예제 #7
0
 def to_nurbs(self, implementation=SvNurbsCurve.NATIVE):
     knotvector = sv_knotvector.generate(3, 4)
     control_points = np.array([self.p0, self.p1, self.p2, self.p3])
     return SvNurbsCurve.build(implementation,
                               degree=3,
                               knotvector=knotvector,
                               control_points=control_points)
예제 #8
0
    def deconstruct(self, curve):
        nurbs = SvNurbsCurve.to_nurbs(curve)
        if nurbs is None:
            nurbs = curve

        try:
            degree = nurbs.get_degree()
        except:
            degree = None

        if hasattr(nurbs, 'get_knotvector'):
            knots = nurbs.get_knotvector().tolist()
        else:
            knots = []

        try:
            points = nurbs.get_control_points().tolist()
        except Exception as e:
            points = []

        if hasattr(nurbs, 'get_weights'):
            weights = nurbs.get_weights().tolist()
        else:
            weights = []

        return degree, knots, points, weights
예제 #9
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        vertices_s = self.inputs['ControlPoints'].sv_get()
        has_weights = self.inputs['Weights'].is_linked
        weights_s = self.inputs['Weights'].sv_get(default = [[1.0]])
        knots_s = self.inputs['Knots'].sv_get(default = [[]])
        degree_s = self.inputs['Degree'].sv_get()

        curves_out = []
        knots_out = []
        for vertices, weights, knots, degree in zip_long_repeat(vertices_s, weights_s, knots_s, degree_s):
            if isinstance(degree, (tuple, list)):
                degree = degree[0]

            n_source = len(vertices)
            fullList(weights, n_source)
            if self.knot_mode == 'AUTO' and self.is_cyclic:
                vertices = vertices + vertices[:degree]
                weights = weights + weights[:degree]
            n_total = len(vertices)

            # Set degree
            curve_degree = degree

            if has_weights and self.surface_mode == 'NURBS':
                curve_weights = weights
            else:
                curve_weights = None

            # Set knot vector
            if self.knot_mode == 'AUTO':
                if self.is_cyclic:
                    self.debug("N: %s, degree: %s", n_total, degree)
                    knots = list(range(n_total + degree + 1))
                else:
                    knots = sv_knotvector.generate(curve_degree, n_total)
                self.debug('Auto knots: %s', knots)
                curve_knotvector = knots
            else:
                self.debug('Manual knots: %s', knots)
                curve_knotvector = knots

            new_curve = SvNurbsCurve.build(self.implementation, degree, curve_knotvector, vertices, curve_weights, normalize_knots = self.normalize_knots)
            curve_knotvector = new_curve.get_knotvector().tolist()
            if self.knot_mode == 'AUTO' and self.is_cyclic:
                u_min = curve_knotvector[degree]
                u_max = curve_knotvector[-degree-1]
                new_curve.u_bounds = u_min, u_max
            else:
                u_min = min(curve_knotvector)
                u_max = max(curve_knotvector)
                new_curve.u_bounds = (u_min, u_max)
            curves_out.append(new_curve)
            knots_out.append(curve_knotvector)

        self.outputs['Curve'].sv_set(curves_out)
        self.outputs['Knots'].sv_set(knots_out)
예제 #10
0
 def to_nurbs(self, curves):
     result = []
     for i,c in enumerate(curves):
         nurbs = SvNurbsCurve.to_nurbs(c)
         if nurbs is None:
             raise Exception(f"Curve #{i} - {c} - can not be converted to NURBS!")
         result.append(nurbs)
     return result
예제 #11
0
 def to_nurbs(self, implementation=SvNurbsCurve.NATIVE):
     knotvector = sv_knotvector.generate(1, 2)
     u_min, u_max = self.get_u_bounds()
     p1 = self.evaluate(u_min)
     p2 = self.evaluate(u_max)
     control_points = np.array([p1, p2])
     return SvNurbsCurve.build(implementation,
                               degree=1,
                               knotvector=knotvector,
                               control_points=control_points)
예제 #12
0
    def test_outside_sphere_3(self):
        cpts = np.array([[-2, 5, 0], [2, 5, 0]])
        degree = 1
        knotvector = sv_knotvector.generate(degree, len(cpts))
        curve = SvNurbsCurve.build(SvNurbsCurve.NATIVE, degree, knotvector,
                                   cpts)

        result = curve.is_strongly_outside_sphere(np.array([0, 0, 0]), 1)
        expected_result = True
        self.assertEquals(result, expected_result)
예제 #13
0
파일: splines.py 프로젝트: wassimj/sverchok
    def to_nurbs(self, implementation=SvNurbsCurve.NATIVE):
        control_points = self.spline.get_control_points()
        degree = self.spline.get_degree()
        n_points = degree + 1
        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_nurbs_curves(segments)
예제 #14
0
def scipy_nurbs_approximate(points,
                            weights=None,
                            metric='DISTANCE',
                            degree=3,
                            filter_doubles=None,
                            smoothing=None,
                            is_cyclic=False):
    points = np.asarray(points)
    if weights is not None and len(points) != len(weights):
        raise Exception("Number of weights must be equal to number of points")
    if filter_doubles is not None:
        good = np.where(
            np.linalg.norm(np.diff(points, axis=0), axis=1) > filter_doubles)
        points = np.r_[points[good], points[-1][np.newaxis]]
        if weights is not None:
            weights = np.r_[weights[good], weights[-1]]
    if is_cyclic:
        if (points[0] != points[-1]).any():
            points = np.vstack((points, points[0]))
            if weights is not None:
                weights = np.insert(weights, -1, weights[0])
    points_orig = points
    points = points.T

    kwargs = dict()
    if weights is not None:
        kwargs['w'] = np.asarray(weights)
    if metric is not None:
        tknots = Spline.create_knots(points.T, metric)
        if len(tknots) != len(points.T):
            raise Exception(
                f"Number of T knots ({len(tknots)}) is not equal to number of points ({len(points.T)})"
            )
        kwargs['u'] = tknots
    if degree is not None:
        kwargs['k'] = degree
    if smoothing is not None:
        kwargs['s'] = smoothing
    if is_cyclic:
        kwargs['per'] = 1

    tck, u = interpolate.splprep(points, **kwargs)
    knotvector = tck[0]
    control_points = np.stack(tck[1]).T
    degree = tck[2]
    curve = SvNurbsCurve.build(SvNurbsCurve.NATIVE, degree, knotvector,
                               control_points)
    if is_cyclic:
        curve = curve.cut_segment(0.0, 1.00)
    #curve.u_bounds = (0.0, 1.0)
    return curve
예제 #15
0
        def process(self):
            if not any(socket.is_linked for socket in self.outputs):
                return

            curves_s = self.inputs['Curve'].sv_get()
            point_s = self.inputs['Point'].sv_get()
            normal_s = self.inputs['Normal'].sv_get()
            curves_s = ensure_nesting_level(curves_s,
                                            2,
                                            data_types=(SvCurve, ))

            points_out = []
            t_out = []

            tolerance = 10**(-self.accuracy)

            for curves, points, normals in zip_long_repeat(
                    curves_s, point_s, normal_s):
                new_points = []
                new_ts = []
                for curve, point, normal in zip_long_repeat(
                        curves, points, normals):
                    method = EQUATION
                    if self.use_nurbs:
                        c = SvNurbsCurve.to_nurbs(curve)
                        if c is not None:
                            curve = c
                            method = NURBS

                    plane = PlaneEquation.from_normal_and_point(normal, point)
                    ps = intersect_curve_plane(curve,
                                               plane,
                                               method=method,
                                               init_samples=self.samples,
                                               tolerance=tolerance)
                    ts = [p[0] for p in ps]
                    points = [p[1].tolist() for p in ps]

                    if self.join:
                        new_points.extend(points)
                        new_ts.extend(ts)
                    else:
                        new_points.append(points)
                        new_ts.append(ts)

                points_out.append(new_points)
                t_out.append(new_ts)

            self.outputs['Point'].sv_set(points_out)
            self.outputs['T'].sv_set(t_out)
예제 #16
0
        def _cast_nurbs(self, curve, center, direction, radius, coeff):
            curve = SvNurbsCurve.to_nurbs(curve)
            if curve is None:
                raise Exception("Provided curve is not a NURBS")
            if self.form == 'PLANE':
                target = PlaneEquation.from_normal_and_point(direction, center)
            elif self.form == 'SPHERE':
                target = SphereEquation(center, radius)
            elif self.form == 'CYLINDER':
                target = CylinderEquation.from_point_direction_radius(center, direction, radius)
            else:
                raise Exception("Unsupported target form")

            return cast_nurbs_curve(curve, target, coeff=coeff)
예제 #17
0
    def cut(self, face_surface, sv_curves, point, vector):
        # face_surface : SvFreeCadNurbsSurface
        nurbs = [SvNurbsCurve.to_nurbs(curve) for curve in sv_curves]
        if any(c is None for c in nurbs):
            raise Exception("One of curves is not a NURBS!")
        fc_nurbs_curves = [SvFreeCadNurbsCurve.from_any_nurbs(c) for c in nurbs]
        fc_nurbs = [c.curve for c in fc_nurbs_curves]
        if self.projection_type in {'PARALLEL', 'PERSPECTIVE', 'ORTHO'}:
            try:
                fc_edges = [Part.Edge(c) for c in fc_nurbs]
            except Exception as e:
                raise Exception(f"Can't build edges from {fc_nurbs}: {e}")
        fc_face = Part.Face(face_surface.surface)

        if self.projection_type == 'PARALLEL':
            vector = Base.Vector(*vector)
            projections = [fc_face.makeParallelProjection(edge, vector) for edge in fc_edges]
            projections = [p.Edges for p in projections]
        elif self.projection_type == 'PERSPECTIVE':
            point = Base.Vector(*point)
            projections = [fc_face.makePerspectiveProjection(edge, point).Edges for edge in fc_edges]
        elif self.projection_type == 'ORTHO':
            projections = [fc_face.project(fc_edges).Edges]
        else: # UV
            uv_curves = [c.to_2d() for c in fc_nurbs_curves]
            fc_nurbs_2d = [c.curve for c in uv_curves]
            projections = [[c.toShape(face_surface.surface) for c in fc_nurbs_2d]]

        projections = sum(projections, [])
        if not projections:
            words = f"along {vector}" if self.projection_type == 'PARALLEL' else f"from {point}"
            raise Exception(f"Projection {words} of {sv_curves} onto {face_surface} is empty for some reason")
        try:
            wire = Part.Wire(projections)
        except Exception as e:
            ps = [SvFreeCadNurbsCurve(p.Curve) for p in projections]
            raise Exception(f"Can't make a valid Wire out of curves {sv_curves} projected onto {face_surface}:\n{e}\nProjections are: {ps}")

        cut_fc_face = Part.Face(face_surface.surface, wire)
        cut_face_surface = SvFreeCadNurbsSurface(face_surface.surface, face=cut_fc_face) 

        if self.projection_type != 'UV':
            uv_curves = []
            for edge in cut_fc_face.OuterWire.Edges:
                trim,m,M = cut_fc_face.curveOnSurface(edge)
                trim = SvFreeCadCurve(trim, (m,M), ndim=2)
                uv_curves.append(trim)

        projections = [SvSolidEdgeCurve(p) for p in projections]
        return uv_curves, projections, cut_face_surface
예제 #18
0
    def test_bezier_to_taylor_2(self):
        cpts = np.array([[0, 0, 0], [1, 0, 0], [1, 1, 0], [2, 1, 0]],
                        dtype=np.float64)
        degree = 3
        knotvector = sv_knotvector.generate(degree, len(cpts))
        knotvector += 1.0
        curve = SvNurbsCurve.build(SvNurbsCurve.NATIVE, degree, knotvector,
                                   cpts)

        taylor = curve.bezier_to_taylor()
        nurbs = taylor.to_nurbs()

        self.assert_numpy_arrays_equal(nurbs.get_control_points(),
                                       cpts,
                                       precision=8)
예제 #19
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        curve_s = self.inputs['Curve'].sv_get()
        init_cuts_s = self.inputs['InitCuts'].sv_get()
        tolerance_s = self.inputs['Tolerance'].sv_get()

        curve_s = ensure_nesting_level(curve_s, 2, data_types=(SvCurve, ))
        init_cuts_s = ensure_nesting_level(init_cuts_s, 2)
        tolerance_s = ensure_nesting_level(tolerance_s, 2)

        need_verts = self.outputs['Vertices'].is_linked

        verts_out = []
        edges_out = []
        ts_out = []

        for params in zip_long_repeat(curve_s, init_cuts_s, tolerance_s):
            new_verts = []
            new_edges = []
            new_ts = []
            for curve, init_cuts, tolerance in zip_long_repeat(*params):
                curve = SvNurbsCurve.to_nurbs(curve)
                if curve is None:
                    raise Exception("Curve is not NURBS")
                ts = curve.calc_linear_segment_knots(splits=init_cuts,
                                                     tolerance=tolerance)
                new_ts.append(ts.tolist())
                if need_verts:
                    verts = curve.evaluate_array(ts)
                    new_verts.append(verts.tolist())
                n = len(ts)
                edges = [(i, i + 1) for i in range(n - 1)]
                new_edges.append(edges)

            if self.join:
                verts_out.extend(new_verts)
                edges_out.extend(new_edges)
                ts_out.extend(new_ts)
            else:
                verts_out.append(new_verts)
                edges_out.append(new_edges)
                ts_out.append(new_ts)

        self.outputs['Vertices'].sv_set(verts_out)
        self.outputs['Edges'].sv_set(edges_out)
        self.outputs['T'].sv_set(ts_out)
예제 #20
0
def curve_to_freecad_nurbs(sv_curve):
    """
    Convert SvCurve to FreeCAD's NURBS curve.
    Raise an exception if it is not possible.

    input: SvCurve
    output: SvFreeCadNurbsCurve
    """
    nurbs = SvNurbsCurve.to_nurbs(sv_curve)
    if nurbs is None:
        raise TypeError(f"{sv_curve} is not a NURBS curve")
    fc_curve = SvNurbsMaths.build_curve(SvNurbsMaths.FREECAD,
                nurbs.get_degree(),
                nurbs.get_knotvector(),
                nurbs.get_control_points(),
                nurbs.get_weights())
    return fc_curve
예제 #21
0
    def get_curve(self, spline, matrix):
        curve_degree = spline.order_u - 1
        if self.apply_matrix:
            vertices = [
                tuple(matrix @ Vector(p.co[:3])) for p in spline.points
            ]
        else:
            vertices = [tuple(p.co)[:3] for p in spline.points]
        weights = [tuple(p.co)[3] for p in spline.points]
        if spline.use_cyclic_u:
            vertices = vertices + vertices[:curve_degree + 1]
            weights = weights + weights[:curve_degree + 1]
        n_total = len(vertices)
        curve_ctrlpts = vertices
        curve_weights = weights
        if spline.use_cyclic_u:
            knots = list(range(n_total + curve_degree + 1))
        else:
            knots = sv_knotvector.generate(curve_degree,
                                           n_total,
                                           clamped=spline.use_endpoint_u)
        self.debug('Auto knots: %s', knots)
        curve_knotvector = knots

        new_curve = SvNurbsCurve.build(self.implementation, curve_degree,
                                       curve_knotvector, curve_ctrlpts,
                                       curve_weights)
        if spline.use_cyclic_u:
            u_min = curve_knotvector[curve_degree]
            u_max = curve_knotvector[-curve_degree - 2]
            new_curve = new_curve.cut_segment(u_min, u_max)
            #new_curve.u_bounds = u_min, u_max
        else:
            if spline.use_endpoint_u:
                u_min = min(curve_knotvector)
                u_max = max(curve_knotvector)
            else:
                u_min = curve_knotvector[curve_degree]
                u_max = curve_knotvector[-curve_degree - 1]
            new_curve.u_bounds = (u_min, u_max)

        return new_curve
예제 #22
0
    def test_bezier_to_taylor_1(self):
        cpts = np.array([[0, 0, 0], [1, 0, 0], [1, 1, 0], [2, 1, 0]],
                        dtype=np.float64)
        degree = 3
        knotvector = sv_knotvector.generate(degree, len(cpts))
        curve = SvNurbsCurve.build(SvNurbsCurve.NATIVE, degree, knotvector,
                                   cpts)

        taylor = curve.bezier_to_taylor()
        coeffs = taylor.get_coefficients()

        self.assert_numpy_arrays_equal(coeffs[0],
                                       np.array([0, 0, 0, 1]),
                                       precision=8)
        self.assert_numpy_arrays_equal(coeffs[1],
                                       np.array([3, 0, 0, 0]),
                                       precision=8)
        self.assert_numpy_arrays_equal(coeffs[2],
                                       np.array([-3, 3, 0, 0]),
                                       precision=8)
        self.assert_numpy_arrays_equal(coeffs[3],
                                       np.array([2, -2, 0, 0]),
                                       precision=8)
예제 #23
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        curves_s = self.inputs['Curves'].sv_get()
        degrees_s = self.inputs['DegreeV'].sv_get()

        curves_s = ensure_nesting_level(curves_s, 3, data_types=(SvCurve, ))
        degrees_s = ensure_nesting_level(degrees_s, 2)

        surface_out = []
        curves_out = []
        v_curves_out = []
        for curves_i, degrees in zip_long_repeat(curves_s, degrees_s):
            new_surfaces = []
            new_curves = []
            new_v_curves = []
            for curves, degree_v in zip_long_repeat(curves_i, degrees):
                curves = [SvNurbsCurve.to_nurbs(c) for c in curves]
                if any(c is None for c in curves):
                    raise Exception("Some of curves are not NURBS!")
                unified_curves, v_curves, new_surface = simple_loft(
                    curves,
                    degree_v=degree_v,
                    knots_u=self.u_knots_mode,
                    metric=self.metric,
                    implementation=self.nurbs_implementation)
                new_surfaces.append(new_surface)
                new_curves.extend(unified_curves)
                new_v_curves.extend(v_curves)
            surface_out.append(new_surfaces)
            curves_out.append(new_curves)
            v_curves_out.append(new_v_curves)

        self.outputs['Surface'].sv_set(surface_out)
        self.outputs['UnifiedCurves'].sv_set(curves_out)
        self.outputs['VCurves'].sv_set(v_curves_out)
예제 #24
0
 def to_nurbs(self, implementation=SvNurbsCurve.NATIVE):
     t_min, t_max = self.get_u_bounds()
     if t_min < 0 or t_max > 2 * pi:
         raise UnsupportedCurveTypeException(
             f"Can't transform a circle arc out of 0-2pi bound ({t_min} - {t_max}) to NURBS"
         )
     control_points = np.array([[1, 0, 0], [1, 1, 0], [0, 1, 0], [-1, 1, 0],
                                [-1, 0, 0], [-1, -1, 0], [0, -1, 0],
                                [1, -1, 0], [1, 0, 0]])
     control_points = self.radius * control_points
     control_points = np.apply_along_axis(lambda v: self.matrix @ v, 1,
                                          control_points)
     sqrt22 = sqrt(2.0) / 2.0
     weights = np.array([1, sqrt22, 1, sqrt22, 1, sqrt22, 1, sqrt22, 1])
     pi2 = pi / 2.0
     pi32 = 3 * pi / 2.0
     knotvector = np.array(
         [0, 0, 0, pi2, pi2, pi, pi, pi32, pi32, 2 * pi, 2 * pi, 2 * pi])
     degree = 2
     curve = SvNurbsCurve.build(implementation, degree, knotvector,
                                control_points, weights)
     if t_min != 0 or t_max != 2 * pi:
         curve = curve_segment(curve, t_min, t_max)
     return curve
예제 #25
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        path_s = self.inputs['Path'].sv_get()
        profile_s = self.inputs['Profile'].sv_get()
        if self.explicit_v:
            v_s = self.inputs['V'].sv_get()
            v_s = ensure_nesting_level(v_s, 3)
        else:
            v_s = [[[]]]
        profiles_count_s = self.inputs['VSections'].sv_get()
        resolution_s = self.inputs['Resolution'].sv_get()
        normal_s = self.inputs['Normal'].sv_get()

        path_s = ensure_nesting_level(path_s, 2, data_types=(SvCurve,))
        profile_s = ensure_nesting_level(profile_s, 3, data_types=(SvCurve,))
        resolution_s = ensure_nesting_level(resolution_s, 2)
        normal_s = ensure_nesting_level(normal_s, 3)
        profiles_count_s = ensure_nesting_level(profiles_count_s, 2)

        surfaces_out = []
        curves_out = []
        v_curves_out = []
        for params in zip_long_repeat(path_s, profile_s, v_s, profiles_count_s, resolution_s, normal_s):
            new_surfaces = []
            new_curves = []
            new_v_curves = []
            new_profiles = []
            for path, profiles, vs, profiles_count, resolution, normal in zip_long_repeat(*params):
                path = SvNurbsCurve.to_nurbs(path)
                if path is None:
                    raise Exception("Path is not a NURBS curve!")
                profiles = [SvNurbsCurve.to_nurbs(profile) for profile in profiles]
                if any(p is None for p in profiles):
                    raise Exception("Some of profiles are not NURBS curves!")
                if self.explicit_v:
                    ts = np.array(vs)
                else:
                    ts = None
                _, unified_curves, v_curves, surface = nurbs_sweep(path, profiles,
                                    ts = ts,
                                    min_profiles = profiles_count,
                                    algorithm = self.algorithm,
                                    knots_u = self.u_knots_mode,
                                    metric = self.metric,
                                    implementation = self.nurbs_implementation,
                                    resolution = resolution,
                                    normal = np.array(normal))
                new_surfaces.append(surface)
                new_curves.extend(unified_curves)
                new_v_curves.extend(v_curves)
            surfaces_out.append(new_surfaces)
            curves_out.append(new_curves)
            v_curves_out.append(new_v_curves)

        self.outputs['Surface'].sv_set(surfaces_out)
        if 'AllProfiles' in self.outputs:
            self.outputs['AllProfiles'].sv_set(curves_out)
        if 'VCurves' in self.outputs:
            self.outputs['VCurves'].sv_set(v_curves_out)
예제 #26
0
 def to_nurbs(self, implementation=SvNurbsCurve.NATIVE):
     knotvector = sv_knotvector.generate(self.degree, len(self.points))
     return SvNurbsCurve.build(implementation,
                               degree=self.degree,
                               knotvector=knotvector,
                               control_points=self.points)
예제 #27
0
 def check_nurbs(*curves):
     return [SvNurbsCurve.to_nurbs(c) for c in curves]
예제 #28
0
파일: coons.py 프로젝트: wassimj/sverchok
def coons_surface(curve1, curve2, curve3, curve4):
    curves = [curve1, curve2, curve3, curve4]
    nurbs_curves = [SvNurbsCurve.to_nurbs(c) for c in curves]
    if any(c is None for c in nurbs_curves):
        return SvCoonsSurface(*curves)
    try:
        nurbs_curves = [c.reparametrize(0, 1) for c in nurbs_curves]
        degrees = [c.get_degree() for c in nurbs_curves]
        implementation = nurbs_curves[0].get_nurbs_implementation()

        if degrees[0] > degrees[2]:
            nurbs_curves[2] = nurbs_curves[2].elevate_degree(delta=degrees[0] -
                                                             degrees[2])
        if degrees[2] > degrees[0]:
            nurbs_curves[0] = nurbs_curves[0].elevate_degree(delta=degrees[2] -
                                                             degrees[0])
        if degrees[1] > degrees[3]:
            nurbs_curves[3] = nurbs_curves[3].elevate_degree(delta=degrees[1] -
                                                             degrees[3])
        if degrees[3] > degrees[1]:
            nurbs_curves[1] = nurbs_curves[1].elevate_degree(delta=degrees[3] -
                                                             degrees[1])

        degree_u = nurbs_curves[0].get_degree()
        degree_v = nurbs_curves[1].get_degree()

        knotvectors = [c.get_knotvector() for c in nurbs_curves]
        if not sv_knotvector.equal(knotvectors[0], knotvectors[2]):
            nurbs_curves[0], nurbs_curves[2] = unify_two_curves(
                nurbs_curves[0], nurbs_curves[2])
        if not sv_knotvector.equal(knotvectors[1], knotvectors[3]):
            nurbs_curves[1], nurbs_curves[3] = unify_two_curves(
                nurbs_curves[1], nurbs_curves[3])

        nurbs_curves[0] = reverse_curve(nurbs_curves[0])
        nurbs_curves[3] = reverse_curve(nurbs_curves[3])

        ruled1 = nurbs_curves[0].make_ruled_surface(nurbs_curves[2], 0, 1)
        ruled2 = nurbs_curves[1].make_ruled_surface(nurbs_curves[3], 0,
                                                    1).swap_uv()
        ruled1 = ruled1.elevate_degree(SvNurbsSurface.V, target=degree_v)
        ruled2 = ruled2.elevate_degree(SvNurbsSurface.U, target=degree_u)

        diff_1to2 = sv_knotvector.difference(ruled1.get_knotvector_v(),
                                             ruled2.get_knotvector_v())
        diff_2to1 = sv_knotvector.difference(ruled2.get_knotvector_u(),
                                             ruled1.get_knotvector_u())

        for v, count in diff_1to2:
            #print(f"R1: insert V={v} {count} times")
            ruled1 = ruled1.insert_knot(SvNurbsSurface.V, v, count)
        for u, count in diff_2to1:
            #print(f"R2: insert U={u} {count} times")
            ruled2 = ruled2.insert_knot(SvNurbsSurface.U, u, count)
        #print(f"R1: {ruled1.get_control_points().shape}, R2: {ruled2.get_control_points().shape}")

        linear_kv = sv_knotvector.generate(1, 2)

        c1_t_min, c1_t_max = nurbs_curves[0].get_u_bounds()
        c3_t_min, c3_t_max = nurbs_curves[2].get_u_bounds()

        pt1 = nurbs_curves[0].evaluate(c1_t_min)
        pt2 = nurbs_curves[0].evaluate(c1_t_max)
        pt3 = nurbs_curves[2].evaluate(c3_t_min)
        pt4 = nurbs_curves[2].evaluate(c3_t_max)

        w1 = nurbs_curves[0].get_weights()[0]
        w2 = nurbs_curves[0].get_weights()[-1]
        w3 = nurbs_curves[2].get_weights()[0]
        w4 = nurbs_curves[2].get_weights()[-1]

        linear_pts = np.array([[pt1, pt3], [pt2, pt4]])
        linear_weights = np.array([[w1, w3], [w2, w4]])
        #linear_weights = np.array([[1,1], [1,1]])
        bilinear = SvNurbsSurface.build(implementation, 1, 1, linear_kv,
                                        linear_kv, linear_pts, linear_weights)

        bilinear = bilinear.elevate_degree(SvNurbsSurface.U, target=degree_u)
        bilinear = bilinear.elevate_degree(SvNurbsSurface.V, target=degree_v)

        knotvector_u = ruled1.get_knotvector_u()
        knotvector_v = ruled2.get_knotvector_v()
        for u, count in sv_knotvector.get_internal_knots(
                knotvector_u, output_multiplicity=True):
            #print(f"B: insert U={u} {count} times")
            bilinear = bilinear.insert_knot(SvNurbsSurface.U, u, count)
        for v, count in sv_knotvector.get_internal_knots(
                knotvector_v, output_multiplicity=True):
            #print(f"B: insert V={v} {count} times")
            bilinear = bilinear.insert_knot(SvNurbsSurface.V, v, count)

        control_points = ruled1.get_control_points(
        ) + ruled2.get_control_points() - bilinear.get_control_points()
        weights = ruled1.get_weights() + ruled2.get_weights(
        ) - bilinear.get_weights()
        result = SvNurbsSurface.build(implementation, degree_u, degree_v,
                                      knotvector_u, knotvector_v,
                                      control_points, weights)
        return result
    except UnsupportedCurveTypeException as e:
        info("Can't create a native Coons surface from curves %s: %s", curves,
             e)
        return SvCoonsSurface(*curves)
예제 #29
0
def intersect_curve_surface(curve,
                            surface,
                            init_samples=10,
                            raycast_samples=10,
                            tolerance=1e-3,
                            maxiter=50,
                            raycast_method='hybr',
                            support_nurbs=False):
    """
    Intersect a curve with a surface.
    dependencies: scipy
    """
    u_min, u_max = curve.get_u_bounds()
    is_nurbs = False
    c = SvNurbsCurve.to_nurbs(curve)
    if c is not None:
        curve = c
        is_nurbs = True

    raycaster = SurfaceRaycaster(surface)
    raycaster.init_bvh(raycast_samples)

    def do_raycast(point, tangent, sign=1):
        good_sign = sign
        raycast = raycaster.raycast([point], [sign * tangent],
                                    method=raycast_method,
                                    on_init_fail=RETURN_NONE)
        if raycast is None:
            good_sign = -sign
            raycast = raycaster.raycast([point], [-sign * tangent],
                                        method=raycast_method,
                                        on_init_fail=RETURN_NONE)
        return good_sign, raycast

    good_ranges = []
    u_range = np.linspace(u_min, u_max, num=init_samples)
    points = curve.evaluate_array(u_range)
    tangents = curve.tangent_array(u_range)
    for u1, u2, p1, p2, tangent1, tangent2 in zip(u_range, u_range[1:], points,
                                                  points[1:], tangents,
                                                  tangents[1:]):
        raycast = raycaster.raycast([p1, p2], [tangent1, -tangent2],
                                    precise=False,
                                    calc_points=False,
                                    on_init_fail=RETURN_NONE)
        if raycast is None:
            continue
        good_ranges.append((u1, u2, raycast.points[0], raycast.points[1]))

    def to_curve(point, curve, u1, u2, raycast=None):
        if support_nurbs and is_nurbs and raycast is not None:
            segment = curve.cut_segment(u1, u2)
            surface_u, surface_v = raycast.us[0], raycast.vs[0]
            point_on_surface = raycast.points[0]
            surface_normal = surface.normal(surface_u, surface_v)
            plane = PlaneEquation.from_normal_and_point(
                surface_normal, point_on_surface)
            r = intersect_curve_plane_nurbs(segment,
                                            plane,
                                            init_samples=2,
                                            tolerance=tolerance,
                                            maxiter=maxiter)
            if not r:
                return None
            else:
                return r[0]
        else:
            ortho = ortho_project_curve(point,
                                        curve,
                                        subdomain=(u1, u2),
                                        init_samples=2,
                                        on_fail=RETURN_NONE)
            if ortho is None:
                return None
            else:
                return ortho.nearest_u, ortho.nearest

    result = []
    for u1, u2, init_p1, init_p2 in good_ranges:

        tangent = curve.tangent(u1)
        point = curve.evaluate(u1)

        i = 0
        sign = 1
        prev_prev_point = None
        prev_point = init_p1
        u_root = None
        point_found = False
        raycast = None
        while True:
            i += 1
            if i > maxiter:
                raise Exception(
                    "Maximum number of iterations is exceeded; last step {} - {} = {}"
                    .format(prev_prev_point, point, step))

            on_curve = to_curve(prev_point, curve, u1, u2, raycast=raycast)
            if on_curve is None:
                break
            u_root, point = on_curve
            if u_root < u1 or u_root > u2:
                break
            step = np.linalg.norm(point - prev_point)
            if step < tolerance and i > 1:
                debug("After ortho: Point {}, prev {}, iter {}".format(
                    point, prev_point, i))
                point_found = True
                break

            prev_point = point
            tangent = curve.tangent(u_root)
            sign, raycast = do_raycast(point, tangent, sign)
            if raycast is None:
                raise Exception(
                    "Iteration #{}: Can't do a raycast with point {}, direction {} onto surface {}"
                    .format(i, point, tangent, surface))
            point = raycast.points[0]
            step = np.linalg.norm(point - prev_point)
            prev_prev_point = prev_point
            prev_point = point

        if point_found:
            result.append((u_root, point))

    return result
예제 #30
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        path1_s = self.inputs['Path1'].sv_get()
        path2_s = self.inputs['Path2'].sv_get()
        profile_s = self.inputs['Profile'].sv_get()
        if self.explicit_v:
            v1_s = self.inputs['V1'].sv_get()
            v1_s = ensure_nesting_level(v1_s, 3)
            v2_s = self.inputs['V2'].sv_get()
            v2_s = ensure_nesting_level(v2_s, 3)
        else:
            v1_s = [[[]]]
            v2_s = [[[]]]
        profiles_count_s = self.inputs['VSections'].sv_get()
        degree_v_s = self.inputs['DegreeV'].sv_get()

        path1_s = ensure_nesting_level(path1_s, 2, data_types=(SvCurve, ))
        path2_s = ensure_nesting_level(path2_s, 2, data_types=(SvCurve, ))
        profile_s = ensure_nesting_level(profile_s, 3, data_types=(SvCurve, ))
        profiles_count_s = ensure_nesting_level(profiles_count_s, 2)
        degree_v_s = ensure_nesting_level(degree_v_s, 2)

        surfaces_out = []
        curves_out = []
        v_curves_out = []
        for params in zip_long_repeat(path1_s, path2_s, profile_s, v1_s, v2_s,
                                      profiles_count_s, degree_v_s):
            new_surfaces = []
            new_curves = []
            new_v_curves = []
            new_profiles = []
            for path1, path2, profiles, vs1, vs2, profiles_count, degree_v in zip_long_repeat(
                    *params):
                path1 = SvNurbsCurve.to_nurbs(path1)
                if path1 is None:
                    raise Exception("Path #1 is not a NURBS curve!")
                path2 = SvNurbsCurve.to_nurbs(path2)
                if path2 is None:
                    raise Exception("Path #2 is not a NURBS curve!")
                profiles = [
                    SvNurbsCurve.to_nurbs(profile) for profile in profiles
                ]
                if any(p is None for p in profiles):
                    raise Exception("Some of profiles are not NURBS curves!")
                if self.explicit_v:
                    ts1 = np.array(vs1)
                    ts2 = np.array(vs2)
                else:
                    ts1 = None
                    ts2 = None
                _, unified_curves, v_curves, surface = nurbs_birail(
                    path1,
                    path2,
                    profiles,
                    ts1=ts1,
                    ts2=ts2,
                    min_profiles=profiles_count,
                    knots_u=self.u_knots_mode,
                    degree_v=degree_v,
                    metric=self.metric,
                    scale_uniform=self.scale_uniform,
                    implementation=self.nurbs_implementation)
                new_surfaces.append(surface)
                new_curves.extend(unified_curves)
                new_v_curves.extend(v_curves)
            surfaces_out.append(new_surfaces)
            curves_out.append(new_curves)
            v_curves_out.append(new_v_curves)

        self.outputs['Surface'].sv_set(surfaces_out)
        self.outputs['AllProfiles'].sv_set(curves_out)
        self.outputs['VCurves'].sv_set(v_curves_out)