def unify_curves(curves):
    curves = [curve.reparametrize(0.0, 1.0) for curve in curves]

    dst_knots = defaultdict(int)
    for curve in curves:
        m = sv_knotvector.to_multiplicity(curve.get_knotvector())
        for u, count in m:
            u = round(u, 6)
            dst_knots[u] = max(dst_knots[u], count)

    result = []
    #     for i, curve1 in enumerate(curves):
    #         for j, curve2 in enumerate(curves):
    #             if i != j:
    #                 curve1 = curve1.to_knotvector(curve2)
    #         result.append(curve1)

    for curve in curves:
        diffs = []
        kv = np.round(curve.get_knotvector(), 6)
        ms = dict(sv_knotvector.to_multiplicity(kv))
        for dst_u, dst_multiplicity in dst_knots.items():
            src_multiplicity = ms.get(dst_u, 0)
            diff = dst_multiplicity - src_multiplicity
            diffs.append((dst_u, diff))
        #print(f"Src {ms}, dst {dst_knots} => diff {diffs}")

        for u, diff in diffs:
            if diff > 0:
                curve = curve.insert_knot(u, diff)
        result.append(curve)

    return result
Exemple #2
0
    def build(cls,
              implementation,
              degree_u,
              degree_v,
              knotvector_u,
              knotvector_v,
              control_points,
              weights=None,
              normalize_knots=False):
        control_points = np.asarray(control_points)
        m, n, _ = control_points.shape
        if weights is None:
            weights = np.ones((m, n))
        weights = np.asarray(weights)
        if normalize_knots:
            knotvector_u = sv_knotvector.normalize(knotvector_u)
            knotvector_v = sv_knotvector.normalize(knotvector_v)

        pts = [[Base.Vector(*t) for t in row] for row in control_points]

        ms_u = sv_knotvector.to_multiplicity(knotvector_u)
        knots_u = [p[0] for p in ms_u]
        mults_u = [p[1] for p in ms_u]
        ms_v = sv_knotvector.to_multiplicity(knotvector_v)
        knots_v = [p[0] for p in ms_v]
        mults_v = [p[1] for p in ms_v]

        surface = Part.BSplineSurface()
        surface.buildFromPolesMultsKnots(pts, mults_u, mults_v, knots_u,
                                         knots_v, False, False, degree_u,
                                         degree_v, weights.tolist())
        return SvFreeCadNurbsSurface(surface)
Exemple #3
0
    def concatenate(self, curve2, tolerance=1e-6):
        curve1 = self
        curve2 = SvNurbsCurve.to_nurbs(curve2)
        if curve2 is None:
            raise UnsupportedCurveTypeException("second curve is not NURBS")

        c1_end = curve1.get_u_bounds()[1]
        c2_start = curve2.get_u_bounds()[0]
        pt1 = curve1.evaluate(c1_end)
        pt2 = curve2.evaluate(c2_start)
        dpt = np.linalg.norm(pt1 - pt2)
        if dpt > tolerance:
            raise UnsupportedCurveTypeException(
                f"Curve end points do not match: C1({c1_end}) = {pt1} != C2({c2_start}) = {pt2}, distance={dpt}"
            )

        cp1 = curve1.get_control_points()[-1]
        cp2 = curve2.get_control_points()[0]
        if np.linalg.norm(cp1 - cp2) > tolerance:
            raise UnsupportedCurveTypeException(
                "End control points do not match")

        w1 = curve1.get_weights()[-1]
        w2 = curve1.get_weights()[0]
        if w1 != w2:
            raise UnsupportedCurveTypeException(
                "Weights at endpoints do not match")

        p1, p2 = curve1.get_degree(), curve2.get_degree()
        if p1 > p2:
            curve2 = curve2.elevate_degree(delta=p1 - p2)
        elif p2 > p1:
            curve1 = curve1.elevate_degree(delta=p2 - p1)
        p = curve1.get_degree()

        kv1 = curve1.get_knotvector()
        kv2 = curve2.get_knotvector()
        kv1_end_multiplicity = sv_knotvector.to_multiplicity(kv1)[-1][1]
        kv2_start_multiplicity = sv_knotvector.to_multiplicity(kv2)[0][1]
        if kv1_end_multiplicity != p + 1:
            raise UnsupportedCurveTypeException(
                f"End knot multiplicity of the first curve ({kv1_end_multiplicity}) is not equal to degree+1 ({p+1})"
            )
        if kv2_start_multiplicity != p + 1:
            raise UnsupportedCurveTypeException(
                f"Start knot multiplicity of the second curve ({kv2_start_multiplicity}) is not equal to degree+1 ({p+1})"
            )

        knotvector = sv_knotvector.concatenate(kv1, kv2, join_multiplicity=p)
        #print(f"Concat KV: {kv1} + {kv2} => {knotvector}")
        weights = np.concatenate(
            (curve1.get_weights(), curve2.get_weights()[1:]))
        control_points = np.concatenate(
            (curve1.get_control_points(), curve2.get_control_points()[1:]))

        return SvNurbsCurve.build(self.get_nurbs_implementation(), p,
                                  knotvector, control_points, weights)
Exemple #4
0
    def build_2d(cls, degree, knotvector, control_points, weights=None):
        n = len(control_points)
        if weights is None:
            weights = np.ones((n,))

        pts = [Base.Vector2d(t[0], t[1]) for t in control_points]
        ms = sv_knotvector.to_multiplicity(knotvector)
        knots = [p[0] for p in ms]
        mults = [p[1] for p in ms]

        curve = Geom2d.BSplineCurve2d()
        curve.buildFromPolesMultsKnots(pts, mults, knots, False, degree, weights)
        return SvFreeCadNurbsCurve(curve, ndim=2)
Exemple #5
0
 def remove_knot(self, u, count=1, tolerance=1e-4):
     curve = SvFreeCadNurbsCurve(self.curve.copy(), self.ndim)  # copy
     ms = sv_knotvector.to_multiplicity(self.get_knotvector())
     idx = None
     M = None
     for i, (u1, m) in enumerate(ms):
         if u1 == u:
             idx = i
             M = m - count
             break
     if idx is not None:
         curve.curve.removeKnot(idx + 1, M, tolerance)
     return curve
Exemple #6
0
 def remove_knot(self,
                 direction,
                 parameter,
                 count=1,
                 if_possible=False,
                 tolerance=1e-6):
     surface = SvFreeCadNurbsSurface(self.surface.copy())
     if direction == 'U':
         ms = sv_knotvector.to_multiplicity(self.get_knotvector_u())
     else:
         ms = sv_knotvector.to_multiplicity(self.get_knotvector_v())
     idx = None
     M = None
     for i, (u1, m) in enumerate(ms):
         if u1 == parameter:
             idx = i
             M = m - count
             break
     if idx is not None:
         if direction == 'U':
             surface.surface.removeUKnot(idx + 1, M, tolerance)
         else:
             surface.surface.removeVKnot(idx + 1, M, tolerance)
     return surface
Exemple #7
0
    def build(cls, implementation, degree, knotvector, control_points, weights=None, normalize_knots=False):
        n = len(control_points)
        if weights is None:
            weights = np.ones((n,))

        if normalize_knots:
            knotvector = sv_knotvector.normalize(knotvector)

        pts = [Base.Vector(t[0], t[1], t[2]) for t in control_points]
        ms = sv_knotvector.to_multiplicity(knotvector)
        knots = [p[0] for p in ms]
        mults = [p[1] for p in ms]

        curve = Part.BSplineCurve()
        curve.buildFromPolesMultsKnots(pts, mults, knots, False, degree, weights)
        return SvFreeCadNurbsCurve(curve)
Exemple #8
0
 def remove_knot(self, u, count=1, tolerance=1e-4, if_possible=False):
     curve = SvFreeCadNurbsCurve(self.curve.copy(), self.ndim)  # copy
     ms = sv_knotvector.to_multiplicity(self.get_knotvector())
     idx = None
     M = None
     for i, (u1, m) in enumerate(ms):
         if u1 == u:
             idx = i
             if count == 'ALL':
                 M = 0
             elif count == 'ALL_BUT_ONE':
                 M = 1
             else:
                 M = m - count
             break
     if idx is not None:
         curve.curve.removeKnot(idx + 1, M, tolerance)
     return curve
Exemple #9
0
 def test_to_multiplicity_4(self):
     kv = np.array([0, 0, 0, 0.3, 0.7, 1, 1, 1, 1.5, 1.7], dtype=np.float64)
     result = sv_knotvector.to_multiplicity(kv)
     expected = [(0, 3), (0.3, 1), (0.7, 1), (1, 3), (1.5, 1), (1.7, 1)]
     self.assert_sverchok_data_equal(result, expected)
Exemple #10
0
def unify_curves(curves, method='UNIFY', accuracy=6):
    tolerance = 10**(-accuracy)
    curves = [curve.reparametrize(0.0, 1.0) for curve in curves]

    if method == 'UNIFY':
        dst_knots = KnotvectorDict(accuracy)
        for i, curve in enumerate(curves):
            m = sv_knotvector.to_multiplicity(curve.get_knotvector(),
                                              tolerance**2)
            #print(f"Curve #{i}: degree={curve.get_degree()}, cpts={len(curve.get_control_points())}, {m}")
            for u, count in m:
                dst_knots.update(i, u, count)

        result = []
        #     for i, curve1 in enumerate(curves):
        #         for j, curve2 in enumerate(curves):
        #             if i != j:
        #                 curve1 = curve1.to_knotvector(curve2)
        #         result.append(curve1)

        for idx, curve in enumerate(curves):
            diffs = []
            #kv = np.round(curve.get_knotvector(), accuracy)
            #curve = curve.copy(knotvector = kv)
            #print('next curve', curve.get_knotvector())
            ms = dict(
                sv_knotvector.to_multiplicity(curve.get_knotvector(),
                                              tolerance**2))
            for dst_u, dst_multiplicity in dst_knots.items():
                src_multiplicity = ms.get(dst_u, 0)
                diff = dst_multiplicity - src_multiplicity
                #print(f"C#{idx}: U = {dst_u}, was = {src_multiplicity}, need = {dst_multiplicity}, diff = {diff}")
                diffs.append((dst_u, diff))
            #print(f"Src {ms}, dst {dst_knots} => diff {diffs}")

            for u, diff in diffs:
                if diff > 0:
                    curve = curve.insert_knot(u, diff)


#                     if u in dst_knots.skip_insertions[idx]:
#                         pass
#                         print(f"C: skip insertion T = {u}")
#                     else:
#                         #kv = curve.get_knotvector()
#                         print(f"C: Insert T = {u} x {diff}")
#                         curve = curve.insert_knot(u, diff)
            result.append(curve)

        return result

    elif method == 'AVERAGE':
        kvs = [len(curve.get_control_points()) for curve in curves]
        max_kv, min_kv = max(kvs), min(kvs)
        if max_kv != min_kv:
            raise Exception(
                f"Knotvector averaging is not applicable: Curves have different number of control points: {kvs}"
            )

        knotvectors = np.array([curve.get_knotvector() for curve in curves])
        knotvector_u = knotvectors.mean(axis=0)

        result = [curve.copy(knotvector=knotvector_u) for curve in curves]
        return result
Exemple #11
0
def unify_nurbs_surfaces(surfaces):
    # Unify surface degrees

    degrees_u = [surface.get_degree_u() for surface in surfaces]
    degrees_v = [surface.get_degree_v() for surface in surfaces]

    degree_u = max(degrees_u)
    degree_v = max(degrees_v)

    surfaces = [
        surface.elevate_degree(SvNurbsSurface.U, target=degree_u)
        for surface in surfaces
    ]
    surfaces = [
        surface.elevate_degree(SvNurbsSurface.V, target=degree_v)
        for surface in surfaces
    ]

    # Unify surface knotvectors

    dst_knots_u = defaultdict(int)
    dst_knots_v = defaultdict(int)
    for surface in surfaces:
        m_u = sv_knotvector.to_multiplicity(surface.get_knotvector_u())
        m_v = sv_knotvector.to_multiplicity(surface.get_knotvector_v())

        for u, count in m_u:
            u = round(u, 6)
            dst_knots_u[u] = max(dst_knots_u[u], count)

        for v, count in m_v:
            v = round(v, 6)
            dst_knots_v[v] = max(dst_knots_v[v], count)

    result = []
    for surface in surfaces:
        diffs_u = []
        kv_u = np.round(surface.get_knotvector_u(), 6)
        ms_u = dict(sv_knotvector.to_multiplicity(kv_u))
        for dst_u, dst_multiplicity in dst_knots_u.items():
            src_multiplicity = ms_u.get(dst_u, 0)
            diff = dst_multiplicity - src_multiplicity
            diffs_u.append((dst_u, diff))

        for u, diff in diffs_u:
            if diff > 0:
                surface = surface.insert_knot(SvNurbsSurface.U, u, diff)

        diffs_v = []
        kv_v = np.round(surface.get_knotvector_v(), 6)
        ms_v = dict(sv_knotvector.to_multiplicity(kv_v))
        for dst_v, dst_multiplicity in dst_knots_v.items():
            src_multiplicity = ms_v.get(dst_v, 0)
            diff = dst_multiplicity - src_multiplicity
            diffs_v.append((dst_v, diff))

        for v, diff in diffs_v:
            if diff > 0:
                surface = surface.insert_knot(SvNurbsSurface.V, v, diff)

        result.append(surface)

    return result
Exemple #12
0
    def concatenate(self, curve2, tolerance=1e-6, remove_knots=False):
        curve1 = self
        curve2 = SvNurbsCurve.to_nurbs(curve2)
        if curve2 is None:
            raise UnsupportedCurveTypeException("second curve is not NURBS")

        c1_end = curve1.get_u_bounds()[1]
        c2_start = curve2.get_u_bounds()[0]
        if sv_knotvector.is_clamped(curve1.get_knotvector(),
                                    curve1.get_degree(),
                                    check_start=True,
                                    check_end=False):
            pt1 = curve1.get_control_points()[-1]
        else:
            pt1 = curve1.evaluate(c1_end)
        if sv_knotvector.is_clamped(curve2.get_knotvector(),
                                    curve2.get_degree(),
                                    check_start=False,
                                    check_end=True):
            pt2 = curve2.get_control_points()[0]
        else:
            pt2 = curve2.evaluate(c2_start)
        dpt = np.linalg.norm(pt1 - pt2)
        if dpt > tolerance:
            raise UnsupportedCurveTypeException(
                f"Curve end points do not match: C1({c1_end}) = {pt1} != C2({c2_start}) = {pt2}, distance={dpt}"
            )

        cp1 = curve1.get_control_points()[-1]
        cp2 = curve2.get_control_points()[0]
        if np.linalg.norm(cp1 - cp2) > tolerance:
            raise UnsupportedCurveTypeException(
                "End control points do not match")

        w1 = curve1.get_weights()[-1]
        w2 = curve2.get_weights()[0]
        if abs(w1 - w2) > tolerance:
            raise UnsupportedCurveTypeException(
                f"Weights at endpoints do not match: {w1} != {w2}")

        p1, p2 = curve1.get_degree(), curve2.get_degree()
        if p1 > p2:
            curve2 = curve2.elevate_degree(delta=p1 - p2)
        elif p2 > p1:
            curve1 = curve1.elevate_degree(delta=p2 - p1)
        p = curve1.get_degree()

        kv1 = curve1.get_knotvector()
        kv2 = curve2.get_knotvector()
        kv1_end_multiplicity = sv_knotvector.to_multiplicity(kv1)[-1][1]
        kv2_start_multiplicity = sv_knotvector.to_multiplicity(kv2)[0][1]
        if kv1_end_multiplicity != p + 1:
            raise UnsupportedCurveTypeException(
                f"End knot multiplicity of the first curve ({kv1_end_multiplicity}) is not equal to degree+1 ({p+1})"
            )
        if kv2_start_multiplicity != p + 1:
            raise UnsupportedCurveTypeException(
                f"Start knot multiplicity of the second curve ({kv2_start_multiplicity}) is not equal to degree+1 ({p+1})"
            )

        knotvector = sv_knotvector.concatenate(kv1, kv2, join_multiplicity=p)
        #print(f"Concat KV: {kv1} + {kv2} => {knotvector}")
        weights = np.concatenate(
            (curve1.get_weights(), curve2.get_weights()[1:]))
        control_points = np.concatenate(
            (curve1.get_control_points(), curve2.get_control_points()[1:]))

        result = SvNurbsCurve.build(self.get_nurbs_implementation(), p,
                                    knotvector, control_points, weights)
        if remove_knots is not None:
            if remove_knots == True:
                remove_knots = p - 1
            join_point = kv1[-1]
            result = result.remove_knot(join_point,
                                        count=remove_knots,
                                        if_possible=True)
        return result