Ejemplo n.º 1
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        surface_s = self.inputs['Surface'].sv_get()
        field_s = self.inputs['Field'].sv_get()
        coeff_s = self.inputs['Coefficient'].sv_get()

        surface_out = []
        for surface, field, coeff in zip_long_repeat(surface_s, field_s,
                                                     coeff_s):
            if isinstance(coeff, (list, tuple)):
                coeff = coeff[0]

            if self.use_control_points:
                nurbs = SvNurbsSurface.get(surface)
                if nurbs is not None:
                    control_points = nurbs.get_control_points()
                else:
                    raise Exception("Surface is not a NURBS!")

                m, n, _ = control_points.shape
                control_points = control_points.reshape((m * n, 3))
                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
                control_points = control_points.reshape((m, n, 3))

                new_surface = SvNurbsSurface.build(
                    nurbs.get_nurbs_implementation(), nurbs.get_degree_u(),
                    nurbs.get_degree_v(), nurbs.get_knotvector_u(),
                    nurbs.get_knotvector_v(), control_points,
                    nurbs.get_weights())

            else:
                new_surface = SvDeformedByFieldSurface(
                    surface, field, coeff, by_normal=self.by_normal)
            surface_out.append(new_surface)

        self.outputs['Surface'].sv_set(surface_out)
Ejemplo n.º 2
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        surface_s = self.inputs['Surface'].sv_get()
        knot_s = self.inputs['Knot'].sv_get()
        count_s = self.inputs['Count'].sv_get()

        input_level = get_data_nesting_level(surface_s, data_types=(SvSurface,))
        flat_output = input_level < 2
        surface_s = ensure_nesting_level(surface_s, 2, data_types=(SvSurface,))
        knot_s = ensure_nesting_level(knot_s, 3)
        count_s = ensure_nesting_level(count_s, 3)

        surfaces_out = []
        for surfaces, knots_i, counts_i in zip_long_repeat(surface_s, knot_s, count_s):
            new_surfaces = []
            for surface, knots, counts in zip_long_repeat(surfaces, knots_i, counts_i):
                surface = SvNurbsSurface.get(surface)
                if surface is None:
                    raise Exception("One of surfaces is not NURBS")
                for knot, count in zip_long_repeat(knots, counts):
                    surface = surface.insert_knot(self.direction, knot, count, if_possible=self.if_possible)
                new_surfaces.append(surface)
            if flat_output:
                surfaces_out.extend(new_surfaces)
            else:
                surfaces_out.append(new_surfaces)

        self.outputs['Surface'].sv_set(surfaces_out)
Ejemplo n.º 3
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        surface_s = self.inputs['Surface'].sv_get()

        input_level = get_data_nesting_level(surface_s,
                                             data_types=(SvSurface, ))
        flat_output = input_level < 2
        surface_s = ensure_nesting_level(surface_s,
                                         2,
                                         data_types=(SvSurface, ))

        tolerance = self.tolerance

        surfaces_out = []
        for surfaces in surface_s:
            new_surfaces = []
            for surface in surfaces:
                surface = SvNurbsSurface.get(surface)
                if surface is None:
                    raise Exception("One of surfaces is not NURBS")
                surface = remove_excessive_knots(surface,
                                                 self.direction,
                                                 tolerance=tolerance)
                new_surfaces.append(surface)
            if flat_output:
                surfaces_out.extend(new_surfaces)
            else:
                surfaces_out.append(new_surfaces)

        self.outputs['Surface'].sv_set(surfaces_out)
Ejemplo n.º 4
0
def nurbs_taper_sweep(profile,
                      taper,
                      point,
                      direction,
                      scale_base=SvTaperSweepSurface.UNIT):

    axis = LineEquation.from_direction_and_point(direction, point)

    taper_cpts = taper.get_control_points()
    taper_weights = taper.get_weights()

    taper_projections = axis.projection_of_points(taper_cpts)

    control_points = []
    weights = []

    if scale_base == SvTaperSweepSurface.TAPER:
        profile_t_min, profile_t_max = profile.get_u_bounds()
        profile_start = profile.evaluate(profile_t_min)
        profile_start_projection = axis.projection_of_point(profile_start)
        divisor = np.linalg.norm(profile_start - profile_start_projection)
    elif scale_base == SvTaperSweepSurface.PROFILE:
        taper_t_min, taper_t_max = taper.get_u_bounds()
        taper_start = taper.evaluate(taper_t_min)
        taper_start_projection = np.array(
            axis.projection_of_point(taper_start))
        divisor = np.linalg.norm(taper_start_projection - taper_start)
    else:
        divisor = 1.0

    profile_cpts = profile.get_control_points()
    n = len(profile_cpts)
    profile_knotvector = profile.get_knotvector()
    profile_weights = profile.get_weights()

    for taper_control_point, taper_projection, taper_weight in zip(
            taper_cpts, taper_projections, taper_weights):
        radius = np.linalg.norm(taper_control_point - taper_projection)
        if radius < 1e-8:
            parallel_points = np.empty((n, 3))
            parallel_points[:] = taper_projection
        else:
            parallel_points = place_profile(profile_cpts, taper_projection,
                                            radius / divisor)
        parallel_weights = profile_weights * taper_weight

        control_points.append(parallel_points)
        weights.append(parallel_weights)

    control_points = np.array(control_points)
    control_points -= point

    weights = np.array(weights)

    degree_u = taper.get_degree()
    degree_v = profile.get_degree()

    return SvNurbsSurface.build(taper.get_nurbs_implementation(), degree_u,
                                degree_v, taper.get_knotvector(),
                                profile_knotvector, control_points, weights)
Ejemplo n.º 5
0
        def process(self):
            if not any(socket.is_linked for socket in self.outputs):
                return

            solids = self.inputs[0].sv_get()

            faces = []
            faces_add = faces.extend if self.flat_output else faces.append
            wires = []
            wires_add = wires.extend if self.flat_output else wires.append
            face_trims_out = []
            for solid in solids:
                face_surface = []
                outer_wires = []
                for f in solid.Faces:
                    surface = SvSolidFaceSurface(f)
                    if self.nurbs_output:
                        out_surface = SvNurbsSurface.get(surface)
                        if out_surface is None:
                            out_surface = surface
                    else:
                        out_surface = surface
                    face_surface.append(out_surface)
                    outer_wire = []
                    face_trims = []
                    for e in f.OuterWire.Edges:
                        try:
                            if self.nurbs_output:
                                outer_wire.append(
                                    SvSolidEdgeCurve(e).to_nurbs())
                            else:
                                outer_wire.append(SvSolidEdgeCurve(e))
                        except TypeError:
                            pass
                        trim, m, M = f.curveOnSurface(e)
                        if self.nurbs_output:
                            trim = trim.toBSpline(m, M)
                            trim = SvFreeCadNurbsCurve(trim, ndim=2)
                        else:
                            #trim = trim.trim(m, M)
                            trim = SvFreeCadCurve(trim, (m, M), ndim=2)
                        face_trims.append(trim)
                    #face_trims = SvConcatCurve(face_trims)

                    outer_wires.append(outer_wire)
                    face_trims_out.append(face_trims)

                faces_add(face_surface)
                wires_add(outer_wires)

            self.outputs['Solid Faces'].sv_set(faces)
            self.outputs['Outer Wire'].sv_set(wires)
            if 'TrimCurves' in self.outputs:
                self.outputs['TrimCurves'].sv_set(face_trims_out)
Ejemplo n.º 6
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)
Ejemplo n.º 7
0
    def deconstruct(self, surface):
        nurbs = SvNurbsSurface.get(surface)
        if nurbs is None:
            nurbs = surface

        try:
            degree_u = nurbs.get_degree_u()
            degree_v = nurbs.get_degree_v()
        except:
            degree_u = None
            degree_v = None

        if hasattr(nurbs, 'get_knotvector_u'):
            knots_u = nurbs.get_knotvector_u().tolist()
            knots_v = nurbs.get_knotvector_v().tolist()
        else:
            knots_u = []
            knots_v = []

        try:
            points = nurbs.get_control_points()
            n_u, n_v, _ = points.shape
            if self.split_points:
                points = points.tolist()
            else:
                points = points.reshape((n_u * n_v, 3)).tolist()
        except Exception as e:
            points = []
            n_u = n_v = 0

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

        return degree_u, degree_v, knots_u, knots_v, points, n_u, n_v, weights
Ejemplo n.º 8
0
            def get_faces(solid):
                face_surface = []
                outer_wires = []
                trims = []
                for f in solid.Faces:
                    surface = SvSolidFaceSurface(f)
                    if self.nurbs_output:
                        out_surface = SvNurbsSurface.get(surface)
                        if out_surface is None:
                            out_surface = surface
                    else:
                        out_surface = surface
                    face_surface.append(out_surface)
                    outer_wire = []
                    face_trims = []
                    for e in f.OuterWire.Edges:
                        try:
                            if self.nurbs_output:
                                outer_wire.append(SvSolidEdgeCurve(e).to_nurbs())
                            else:
                                outer_wire.append(SvSolidEdgeCurve(e))
                        except TypeError:
                            pass
                        trim,m,M = f.curveOnSurface(e)
                        if self.nurbs_output:
                            trim = trim.toBSpline(m,M)
                            trim = SvFreeCadNurbsCurve(trim, ndim=2)
                        else:
                            #trim = trim.trim(m, M)
                            trim = SvFreeCadCurve(trim, (m,M), ndim=2)
                        face_trims.append(trim)

                    outer_wires.append(outer_wire)
                    trims.append(face_trims)

                return face_surface, outer_wires, trims
Ejemplo n.º 9
0
def surface_to_freecad(sv_surface, make_face=False):
    """
    Convert SvSurface into FreeCAD's Surface.
    The surface must be presentable as NURBS.

    input:
      * sv_surface: SvSurface
      * make_face: if True, create a Part.Face out of the surface and assign it
        to the `face` property of the resulting surface
    output: SvFreeCadNurbsSurface
    """
    nurbs = SvNurbsSurface.get(sv_surface)
    if nurbs is None:
        raise TypeError(f"{sv_surface} is not a NURBS surface")
    sv_fc_nurbs = SvNurbsMaths.build_surface(SvNurbsMaths.FREECAD,
                                             nurbs.get_degree_u(),
                                             nurbs.get_degree_v(),
                                             nurbs.get_knotvector_u(),
                                             nurbs.get_knotvector_v(),
                                             nurbs.get_control_points(),
                                             nurbs.get_weights())
    if make_face:
        sv_fc_nurbs.face = Part.Face(sv_fc_nurbs.surface)
    return sv_fc_nurbs
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
    def get_surface(self, spline, matrix):
        surface_degree_u = spline.order_u - 1
        surface_degree_v = spline.order_v - 1

        spline_points = split_by_count(spline.points, spline.point_count_u)
        if self.apply_matrix:
            control_points = [[list(matrix @ Vector(p.co[:3])) for p in row]
                              for row in spline_points]
        else:
            control_points = [[tuple(p.co) for p in row]
                              for row in spline_points]
        surface_weights = [[p.co[3] for p in row] for row in spline_points]
        if spline.use_cyclic_v:
            for row_idx in range(len(control_points)):
                control_points[row_idx].extend(
                    control_points[row_idx][:spline.order_v])
        if spline.use_cyclic_u:
            control_points.extend(control_points[:spline.order_u])

        # Control points
        n_u_total = len(control_points)
        n_v_total = len(control_points[0])
        if spline.use_cyclic_u:
            knots_u = list(range(n_u_total + spline.order_u))
        else:
            knots_u = sv_knotvector.generate(surface_degree_u,
                                             n_u_total,
                                             clamped=spline.use_endpoint_u)
        self.debug("Auto knots U: %s", knots_u)

        if spline.use_cyclic_v:
            knots_v = list(range(n_v_total + spline.order_v))
        else:
            knots_v = sv_knotvector.generate(surface_degree_v,
                                             n_v_total,
                                             clamped=spline.use_endpoint_v)
        self.debug("Auto knots V: %s", knots_v)

        surface_knotvector_u = knots_u
        surface_knotvector_v = knots_v

        new_surf = SvNurbsSurface.build(self.implementation,
                                        surface_degree_u,
                                        surface_degree_v,
                                        surface_knotvector_u,
                                        surface_knotvector_v,
                                        control_points,
                                        surface_weights,
                                        normalize_knots=True)

        if spline.use_cyclic_u:
            u_min = surface_knotvector_u[surface_degree_u]
            u_max = surface_knotvector_u[-surface_degree_u - 2]
        else:
            if spline.use_endpoint_u:
                u_min = min(surface_knotvector_u)
                u_max = max(surface_knotvector_u)
            else:
                u_min = surface_knotvector_u[surface_degree_u]
                u_max = surface_knotvector_u[-surface_degree_u - 1]
        if spline.use_cyclic_v:
            v_min = surface_knotvector_v[surface_degree_v]
            v_max = surface_knotvector_v[-surface_degree_v - 2]
        else:
            if spline.use_endpoint_v:
                v_min = min(surface_knotvector_v)
                v_max = max(surface_knotvector_v)
            else:
                v_min = surface_knotvector_v[surface_degree_v]
                v_max = surface_knotvector_v[-surface_degree_v - 1]

        new_surf.u_bounds = u_min, u_max
        new_surf.v_bounds = v_min, v_max

        return new_surf
Ejemplo n.º 12
0
    def process(self):
        vertices_s = self.inputs['ControlPoints'].sv_get()
        has_weights = self.inputs['Weights'].is_linked
        weights_s = self.inputs['Weights'].sv_get(default=[[1.0]])
        u_size_s = self.inputs['USize'].sv_get()
        knots_u_s = self.inputs['KnotsU'].sv_get(default=[[]])
        knots_v_s = self.inputs['KnotsV'].sv_get(default=[[]])
        degree_u_s = self.inputs['DegreeU'].sv_get()
        degree_v_s = self.inputs['DegreeV'].sv_get()

        if self.input_mode == '1D':
            vertices_s = ensure_nesting_level(vertices_s, 3)
        else:
            vertices_s = ensure_nesting_level(vertices_s, 4)

        surfaces_out = []
        inputs = zip_long_repeat(vertices_s, weights_s, knots_u_s, knots_v_s,
                                 degree_u_s, degree_v_s, u_size_s)
        for vertices, weights, knots_u, knots_v, degree_u, degree_v, u_size in inputs:
            if isinstance(degree_u, (tuple, list)):
                degree_u = degree_u[0]
            if isinstance(degree_v, (tuple, list)):
                degree_v = degree_v[0]
            if isinstance(u_size, (list, tuple)):
                u_size = u_size[0]

            if self.surface_mode != 'NURBS':
                weights = None

            if self.surface_mode == 'NURBS':
                if self.input_mode == '1D':
                    weights = repeat_last_for_length(weights,
                                                     len(vertices),
                                                     deepcopy=True)
                else:
                    if isinstance(weights[0], (int, float)):
                        weights = [weights]
                    weights = repeat_last_for_length(weights,
                                                     len(vertices),
                                                     deepcopy=True)
                    for verts_u, weights_u in zip(vertices, weights):
                        fullList_deep_copy(weights_u, len(verts_u))

            if self.input_mode == '1D':
                n_v = u_size
                n_u = len(vertices) // n_v

                vertices = split_by_count(vertices, n_u)
                if self.surface_mode == 'NURBS':
                    weights = split_by_count(weights, n_u)

            if self.knot_mode == 'AUTO':
                if self.is_cyclic_v:
                    for row_idx in range(len(vertices)):
                        vertices[row_idx].extend(vertices[row_idx][:degree_v +
                                                                   1])
                        if self.surface_mode == 'NURBS':
                            weights[row_idx].extend(
                                weights[row_idx][:degree_v + 1])
                if self.is_cyclic_u:
                    vertices.extend(vertices[:degree_u + 1])
                    if self.surface_mode == 'NURBS':
                        weights.extend(weights[:degree_u + 1])
                self.debug("UxV: %s x %s", len(vertices), len(vertices[0]))

            n_u_total = len(vertices)
            n_v_total = len(vertices[0])

            if self.knot_mode == 'AUTO':
                if self.is_cyclic_u:
                    knots_u = list(range(n_u_total + degree_u + 1))
                else:
                    knots_u = sv_knotvector.generate(degree_u, n_u_total)
                self.debug("Auto knots U: %s", knots_u)
                surf_knotvector_u = knots_u

                if self.is_cyclic_v:
                    knots_v = list(range(n_v_total + degree_v + 1))
                else:
                    knots_v = sv_knotvector.generate(degree_v, n_v_total)
                self.debug("Auto knots V: %s", knots_v)
                surf_knotvector_v = knots_v
            else:
                surf_knotvector_u = knots_u
                surf_knotvector_v = knots_v

            new_surf = SvNurbsSurface.build(self.implementation, degree_u,
                                            degree_v, surf_knotvector_u,
                                            surf_knotvector_v, vertices,
                                            weights, self.normalize_knots)
            surf_knotvector_u = new_surf.get_knotvector_u().tolist()
            surf_knotvector_v = new_surf.get_knotvector_v().tolist()
            if self.is_cyclic_u:
                u_min = surf_knotvector_u[degree_u]
                u_max = surf_knotvector_u[-degree_u - 2]
                new_surf.u_bounds = u_min, u_max
                #print("U:",new_surf.u_bounds)
            else:
                u_min = min(surf_knotvector_u)
                u_max = max(surf_knotvector_u)
                new_surf.u_bounds = u_min, u_max
            if self.is_cyclic_v:
                v_min = surf_knotvector_v[degree_v]
                v_max = surf_knotvector_v[-degree_v - 2]
                new_surf.v_bounds = v_min, v_max
                #print("V:",new_surf.v_bounds)
            else:
                v_min = min(surf_knotvector_v)
                v_max = max(surf_knotvector_v)
                new_surf.v_bounds = v_min, v_max
            surfaces_out.append(new_surf)

        self.outputs['Surface'].sv_set(surfaces_out)
Ejemplo n.º 13
0
def gordon_surface(u_curves,
                   v_curves,
                   intersections,
                   metric='POINTS',
                   u_knots=None,
                   v_knots=None,
                   knotvector_accuracy=6,
                   reparametrize_tolerance=1e-2):
    """
    Generate a NURBS surface from a net of NURBS curves, by use of Gordon's algorithm.

    :param u_curves - list of NURBS curves along U direciton (length N)
    :param v_curves - list of NURBS curves along V direcion (length M)
    :param intersections - np.array of shape (N, M, 3): points of curves intersection
    :param metric - metric function that can be used to calculate T values of curves
                    intersections from their positions.
    :param u_knots - np.array, T values of curves intersection for each curve from u_curves
    :param v_knots - np.array, T values of curves intersection for each curve from v_curves

    return value: a NURBS surface.

    See also: The NURBS Book, 2nd ed., p.10.5.
    """

    if not u_curves or not v_curves:
        raise Exception("U or V curves are not provided")

    if (u_knots is None) != (v_knots is None):
        raise Exception(
            "u_knots and v_knots must be either both provided or both omited")

    if any(c.is_rational() for c in u_curves):
        raise Exception(
            "Some of U-curves are rational. Rational curves are not supported for Gordon surface."
        )
    if any(c.is_rational() for c in v_curves):
        raise Exception(
            "Some of V-curves are rational. Rational curves are not supported for Gordon surface."
        )

    intersections = np.array(intersections)

    if u_knots is not None:
        loft_u_kwargs = loft_v_kwargs = interpolate_kwargs = {
            'metric': 'POINTS'
        }

        u_curves = [
            reparametrize_by_segments(c, knots, reparametrize_tolerance)
            for c, knots in zip(u_curves, u_knots)
        ]
        v_curves = [
            reparametrize_by_segments(c, knots, reparametrize_tolerance)
            for c, knots in zip(v_curves, v_knots)
        ]
        #print("U", u_curves)
        #print("V", v_curves)

    else:
        loft_u_kwargs = loft_v_kwargs = interpolate_kwargs = {'metric': metric}

    u_curves = unify_curves_degree(u_curves)
    u_curves = unify_curves(u_curves,
                            accuracy=knotvector_accuracy)  #, method='AVERAGE')
    v_curves = unify_curves_degree(v_curves)
    v_curves = unify_curves(v_curves,
                            accuracy=knotvector_accuracy)  #, method='AVERAGE')

    u_curves_degree = u_curves[0].get_degree()
    v_curves_degree = v_curves[0].get_degree()
    n = len(intersections)
    m = len(intersections[0])

    loft_v_degree = min(len(u_curves) - 1, v_curves_degree)
    loft_u_degree = min(len(v_curves) - 1, u_curves_degree)

    _, _, lofted_v = simple_loft(u_curves,
                                 degree_v=loft_v_degree,
                                 knotvector_accuracy=knotvector_accuracy,
                                 **loft_v_kwargs)
    _, _, lofted_u = simple_loft(v_curves,
                                 degree_v=loft_u_degree,
                                 knotvector_accuracy=knotvector_accuracy,
                                 **loft_u_kwargs)
    lofted_u = lofted_u.swap_uv()

    int_degree_u = min(m - 1, u_curves_degree)
    int_degree_v = min(n - 1, v_curves_degree)
    interpolated = interpolate_nurbs_surface(int_degree_u, int_degree_v,
                                             intersections,
                                             **interpolate_kwargs)
    interpolated = interpolated.swap_uv()
    #print(f"Loft.U: {lofted_u}")
    #print(f"Loft.V: {lofted_v}")
    #print(f"Interp: {interpolated}")
    #print(f"        {interpolated.get_knotvector_u()}")
    #print(f"        {interpolated.get_knotvector_v()}")

    lofted_u, lofted_v, interpolated = unify_nurbs_surfaces(
        [lofted_u, lofted_v, interpolated],
        knotvector_accuracy=knotvector_accuracy)

    control_points = lofted_u.get_control_points() + \
                        lofted_v.get_control_points() - \
                        interpolated.get_control_points()

    surface = SvNurbsSurface.build(SvNurbsSurface.NATIVE,
                                   interpolated.get_degree_u(),
                                   interpolated.get_degree_v(),
                                   interpolated.get_knotvector_u(),
                                   interpolated.get_knotvector_v(),
                                   control_points,
                                   weights=None)
    #print(f"Result: {surface}")

    return lofted_u, lofted_v, interpolated, surface
Ejemplo n.º 14
0
    def make_surface(self, face, degree_u, degree_v, vertices, planes,
                     vert_weights, tangent_weights, face_weight,
                     edge_weights_dict, edge_planes_dict):
        """
        V0 ------ [E01] --- [E0C] --- [E02] --- V1
        |          |         |        |         |
        |          |         |        |         |
        |          |         |        |         |
        [E11] --- [F1] ---- [E0F] --- [F2] --- [E21]
        |          |         |        |         |
        |          |         |        |         |
        |          |         |        |         |
        [E1C] --- [E1F] --- [CC] --- [E2F] --- [E2C]
        |          |         |        |         |
        |          |         |        |         |
        |          |         |        |         |
        [E12] --- [F3] ---- [E3F] --- [F4] --- [E22]
        |          |         |        |         |
        |          |         |        |         |
        |          |         |        |         |
        V3 ------ [E31] --- [E3C] --- [E32] --- V2
        """
        tangent_weights = [w / 3.0 for w in tangent_weights]
        vertices = [Vector(v) for v in vertices]

        def mk_edge_point(i, j):
            return (vertices[j] -
                    vertices[i]) * tangent_weights[i] + vertices[i]

        def mk_face_corner_point(i, j, k):
            dv1 = (vertices[j] - vertices[i]) * tangent_weights[i]
            dv2 = (vertices[k] - vertices[i]) * tangent_weights[i]
            #m = face_weight
            return planes[i].projection_of_point(vertices[i] + dv1 + dv2)

        # edge planes
        e0p = edge_planes_dict[(face[0], face[1])]
        e1p = edge_planes_dict[(face[0], face[3])]
        e2p = edge_planes_dict[(face[1], face[2])]
        e3p = edge_planes_dict[(face[2], face[3])]

        def mk_edge_center_point(ep1, ep2):
            return (ep1 + ep2) / 2.0

        def mk_face_edge_point(edge_plane, edge_point, edge_vec, vec1, vec2):
            length = (vec1.length + vec2.length) / 2.0
            vec = edge_plane.normal.cross(edge_vec)
            #print("EV: %s, N: %s, L: %s, Res: %s" % (edge_vec, edge_plane.normal, length, vec))
            vec = length * vec.normalized()
            return edge_point + vec

        e01 = planes[0].projection_of_point(mk_edge_point(0, 1))
        e02 = planes[1].projection_of_point(mk_edge_point(1, 0))
        e11 = planes[0].projection_of_point(mk_edge_point(0, 3))
        e21 = planes[1].projection_of_point(mk_edge_point(1, 2))
        f1 = mk_face_corner_point(0, 1, 3)
        f2 = mk_face_corner_point(1, 0, 2)
        e12 = planes[3].projection_of_point(mk_edge_point(3, 0))
        e31 = planes[3].projection_of_point(mk_edge_point(3, 2))
        e32 = planes[2].projection_of_point(mk_edge_point(2, 3))
        e22 = planes[2].projection_of_point(mk_edge_point(2, 1))
        f3 = mk_face_corner_point(3, 0, 2)
        f4 = mk_face_corner_point(2, 3, 1)

        e0c = mk_edge_center_point(e01, e02)
        e1c = mk_edge_center_point(e11, e12)
        e2c = mk_edge_center_point(e21, e22)
        e3c = mk_edge_center_point(e31, e32)

        e0f = mk_face_edge_point(e0p, e0c, (vertices[1] - vertices[0]),
                                 (f1 - e01), (f2 - e02))
        e1f = mk_face_edge_point(e1p, e1c, (vertices[0] - vertices[3]),
                                 (f3 - e12), (f1 - e11))
        e2f = mk_face_edge_point(e2p, e2c, (vertices[2] - vertices[1]),
                                 (f2 - e21), (f4 - e22))
        e3f = mk_face_edge_point(e3p, e3c, (vertices[3] - vertices[2]),
                                 (f3 - e31), (f4 - e32))

        cc = center([f1, e0f, f2, e2f, f4, e3f, f3, e1f])

        control_points = [[vertices[0], e01, e0c, e02, vertices[1]],
                          [e11, f1, e0f, f2, e21], [e1c, e1f, cc, e2f, e2c],
                          [e12, f3, e3f, f4, e22],
                          [vertices[3], e31, e3c, e32, vertices[2]]]

        # edge point weights
        e0w = edge_weights_dict[(face[0], face[1])]
        e1w = edge_weights_dict[(face[0], face[3])]
        e2w = edge_weights_dict[(face[1], face[2])]
        e3w = edge_weights_dict[(face[2], face[3])]

        weights = [[vert_weights[0], e0w, e0w, e0w, vert_weights[1]],
                   [e1w, face_weight, face_weight, face_weight, e2w],
                   [e1w, face_weight, face_weight, face_weight, e2w],
                   [e1w, face_weight, face_weight, face_weight, e2w],
                   [vert_weights[3], e3w, e3w, e3w, vert_weights[2]]]

        new_surf = SvNurbsSurface.build(self.implementation, degree_u,
                                        degree_v,
                                        sv_knotvector.generate(degree_u, 5),
                                        sv_knotvector.generate(degree_v, 5),
                                        np.array(control_points),
                                        np.array(weights))
        return new_surf, control_points, weights
Ejemplo n.º 15
0
def coons_surface(curve1, curve2, curve3, curve4, use_nurbs=NURBS_IF_POSSIBLE):
    curves = [curve1, curve2, curve3, curve4]
    nurbs_curves = [SvNurbsCurve.to_nurbs(c) for c in curves]
    if use_nurbs == GENERIC:
        return SvCoonsSurface(*curves)
    if any(c is None for c in nurbs_curves):
        if use_nurbs == NURBS_ONLY:
            raise UnsupportedCurveTypeException("Some of curves are not NURBS")
        else:
            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()

        nurbs_curves[0], nurbs_curves[2] = unify_curves(
            [nurbs_curves[0], nurbs_curves[2]])
        nurbs_curves[1], nurbs_curves[3] = unify_curves(
            [nurbs_curves[1], nurbs_curves[3]])

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

        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()

        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)

        ruled1, ruled2, bilinear = unify_nurbs_surfaces(
            [ruled1, ruled2, bilinear])
        knotvector_u = ruled1.get_knotvector_u()
        knotvector_v = ruled1.get_knotvector_v()

        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:
        if use_nurbs == NURBS_ONLY:
            raise
        else:
            info("Can't create a native Coons surface from curves %s: %s",
                 curves, e)
            return SvCoonsSurface(*curves)