<commit_before>"""
.. module:: evaluators
    :platform: Unix, Windows
    :synopsis: NURBS & B-Spline evaluation algorithms

.. moduleauthor:: <NAME> <<EMAIL>>

"""

from . import Abstract
from . import helpers
from . import utilities


class CurveEvaluator(Abstract.Evaluator):
    """ Sequential B-Spline curve evaluation algorithms.

    This evaluator implements the following algorithms from **The NURBS Book**:

    * Algorithm A3.1: CurvePoint
    * Algorithm A3.2: CurveDerivsAlg1

    """

    def __init__(self):
        super(CurveEvaluator, self).__init__()
        self._name = "Curve Evaluator"

    def evaluate_single(self, **kwargs):
        """ Evaluates a single curve point. """
        knot = kwargs.get('knot')
        degree = kwargs.get('degree')
        knot_vector = kwargs.get('knotvector')
        control_points = kwargs.get('ctrlpts')
        dimension = kwargs.get('dimension')

        # Algorithm A3.1
        span = helpers.find_span(knot_vector, len(control_points), knot)
        basis = helpers.basis_function(degree, knot_vector, span, knot)

        crvpt = [0.0 for _ in range(dimension)]
        for i in range(0, degree + 1):
            crvpt[:] = [crvpt + (basis[i] * ctrlpt) for crvpt, ctrlpt in
                        zip(crvpt, control_points[span - degree + i])]

        return crvpt

    def evaluate(self, **kwargs):
        """ Evaluates the curve. """
        knots = kwargs.get('knots')
        degree = kwargs.get('degree')
        knot_vector = kwargs.get('knotvector')
        control_points = kwargs.get('ctrlpts')
        dimension = kwargs.get('dimension')

        # Algorithm A3.1
        spans = helpers.find_spans(knot_vector, len(control_points), knots)
        basis = helpers.basis_functions(degree, knot_vector, spans, knots)

        eval_points = []
        for idx in range(len(knots)):
            crvpt = [0.0 for _ in range(dimension)]
            for i in range(0, degree + 1):
                crvpt[:] = [crv_p + (basis[idx][i] * ctl_p) for crv_p, ctl_p in
                            zip(crvpt, control_points[spans[idx] - degree + i])]

            eval_points.append(crvpt)

        return eval_points

    # Evaluates the curve derivative using "CurveDerivsAlg1" algorithm
    def derivatives_single(self, **kwargs):
        knot = kwargs.get('knot')
        deriv_order = kwargs.get('deriv_order', 0)
        degree = kwargs.get('degree')
        knot_vector = kwargs.get('knotvector')
        control_points = kwargs.get('ctrlpts')
        dimension = kwargs.get('dimension')

        # Algorithm A3.2
        du = min(degree, deriv_order)

        CK = [[None for _ in range(dimension)] for _ in range(deriv_order + 1)]
        for k in range(degree + 1, deriv_order + 1):
            CK[k] = [0.0 for _ in range(dimension)]

        span = helpers.find_span(knot_vector, len(control_points), knot)
        bfunsders = helpers.basis_function_ders(degree, tuple(knot_vector), span, knot, du)

        for k in range(0, du + 1):
            CK[k] = [0.0 for _ in range(dimension)]
            for j in range(0, degree + 1):
                CK[k][:] = [drv + (bfunsders[k][j] * ctrl_pt) for drv, ctrl_pt in
                            zip(CK[k], control_points[span - degree + j])]

        # Return the derivatives
        return CK

    def derivatives(self, **kwargs):
        pass

    def insert_knot(self, **kwargs):
        pass


class CurveEvaluator2(CurveEvaluator):
    """ Sequential B-Spline curve evaluation algorithms.

    This evaluator implements the following algorithms from **The NURBS Book**:

    * Algorithm A3.1: CurvePoint
    * Algorithm A3.3: CurveDerivCpts
    * Algorithm A3.4: CurveDerivsAlg2

    """

    def __init__(self):
        super(CurveEvaluator2, self).__init__()
        self._name = "Curve Evaluator using A3.4 CurveDerivsAlg2"

    # Computes the control points of all derivative curves up to and including the d-th derivative
    def _derivatives_ctrlpts(self, **kwargs):
        """ Computes the control points of all derivative curves up to and including the {degree}-th derivative.

        Output is PK[k][i], i-th control point of the k-th derivative curve where 0 <= k <= degree and r1 <= i <= r2-k

        :param order: derivative order
        :type order: integer
        :param r1: minimum span
        :type r1: integer
        :param r2: maximum span
        :type r2: integer
        :return: PK, a 2D list of control points
        :rtype: list
        """
        r1 = kwargs.get('r1', 0)  # minimum span
        r2 = kwargs.get('r2', 0)  # maximum span
        deriv_order = kwargs.get('deriv_order', 0)
        degree = kwargs.get('degree')
        knot_vector = kwargs.get('knotvector')
        control_points = kwargs.get('ctrlpts')
        dimension = kwargs.get('dimension')

        # Algorithm A3.3
        r = r2 - r1
        PK = [[[None for _ in range(dimension)] for _ in range(r + 1)] for _ in range(deriv_order + 1)]
        for i in range(0, r + 1):
            PK[0][i][:] = [elem for elem in control_points[r1 + i]]

        for k in range(1, deriv_order + 1):
            tmp = degree - k + 1
            for i in range(0, r - k + 1):
                PK[k][i][:] = [tmp * (elem1 - elem2) / (
                    knot_vector[r1 + i + degree + 1] - knot_vector[r1 + i + k]) for elem1, elem2
                               in zip(PK[k - 1][i + 1], PK[k - 1][i])]

        # Return a 2-dimensional list of control points
        return PK

    # Evaluates the curve derivative using "CurveDerivsAlg2" algorithm
    def derivatives_single(self, **kwargs):
        """ Evaluates n-th order curve derivatives at the given parameter value. """
        knot = kwargs.get('knot')
        deriv_order = kwargs.get('deriv_order')
        degree = kwargs.get('degree')
        knot_vector = kwargs.get('knotvector')
        control_points = kwargs.get('ctrlpts')
        dimension = kwargs.get('dimension')

        # Algorithm A3.4
        du = min(degree, deriv_order)

        CK = [[None for _ in range(dimension)] for _ in range(deriv_order + 1)]
        for k in range(degree + 1, deriv_order + 1):
            CK[k] = [0.0 for _ in range(dimension)]

        span = helpers.find_span(knot_vector, len(control_points), knot)
        bfuns = helpers.basis_function_all(degree, tuple(knot_vector), span, knot)
        PK = self._derivatives_ctrlpts(order=du, r1=(span - degree), r2=span, **kwargs)

        for k in range(0, du + 1):
            CK[k] = [0.0 for _ in range(dimension)]
            for j in range(0, degree - k + 1):
                CK[k][:] = [elem + (bfuns[j][degree - k] * drv_ctrlpt) for elem, drv_ctrlpt in
                            zip(CK[k], PK[k][j])]

        # Return the derivatives
        return CK


class NURBSCurveEvaluator(CurveEvaluator):
    """ Sequential NURBS curve evaluation algorithms.

    This evaluator implements the following algorithms from **The NURBS Book**:

    * Algorithm A4.1: CurvePoint
    * Algorithm A4.2: RatCurveDerivs

    """

    def __init__(self):
        super(NURBSCurveEvaluator, self).__init__()
        self._name = "NURBS Curve Evaluator"

    def evaluate_single(self, **kwargs):
        """ Evaluates a single curve point. """<commit_msg>Forgot to change variable names after updating evaluators<commit_after>"""
.. module:: evaluators
    :platform: Unix, Windows
    :synopsis: NURBS & B-Spline evaluation algorithms

.. moduleauthor:: <NAME> <<EMAIL>>

"""

from . import Abstract
from . import helpers
from . import utilities


class CurveEvaluator(Abstract.Evaluator):
    """ Sequential B-Spline curve evaluation algorithms.

    This evaluator implements the following algorithms from **The NURBS Book**:

    * Algorithm A3.1: CurvePoint
    * Algorithm A3.2: CurveDerivsAlg1

    """

    def __init__(self):
        super(CurveEvaluator, self).__init__()
        self._name = "Curve Evaluator"

    def evaluate_single(self, **kwargs):
        """ Evaluates a single curve point. """
        knot = kwargs.get('knot')
        degree = kwargs.get('degree')
        knot_vector = kwargs.get('knotvector')
        control_points = kwargs.get('ctrlpts')
        dimension = kwargs.get('dimension')

        # Algorithm A3.1
        span = helpers.find_span(knot_vector, len(control_points), knot)
        basis = helpers.basis_function(degree, knot_vector, span, knot)

        crvpt = [0.0 for _ in range(dimension)]
        for i in range(0, degree + 1):
            crvpt[:] = [crv_p + (basis[i] * ctl_p) for crv_p, ctl_p in
                        zip(crvpt, control_points[span - degree + i])]

        return crvpt

    def evaluate(self, **kwargs):
        """ Evaluates the curve. """
        knots = kwargs.get('knots')
        degree = kwargs.get('degree')
        knot_vector = kwargs.get('knotvector')
        control_points = kwargs.get('ctrlpts')
        dimension = kwargs.get('dimension')

        # Algorithm A3.1
        spans = helpers.find_spans(knot_vector, len(control_points), knots)
        basis = helpers.basis_functions(degree, knot_vector, spans, knots)

        eval_points = []
        for idx in range(len(knots)):
            crvpt = [0.0 for _ in range(dimension)]
            for i in range(0, degree + 1):
                crvpt[:] = [crv_p + (basis[idx][i] * ctl_p) for crv_p, ctl_p in
                            zip(crvpt, control_points[spans[idx] - degree + i])]

            eval_points.append(crvpt)

        return eval_points

    # Evaluates the curve derivative using "CurveDerivsAlg1" algorithm
    def derivatives_single(self, **kwargs):
        knot = kwargs.get('knot')
        deriv_order = kwargs.get('deriv_order', 0)
        degree = kwargs.get('degree')
        knot_vector = kwargs.get('knotvector')
        control_points = kwargs.get('ctrlpts')
        dimension = kwargs.get('dimension')

        # Algorithm A3.2
        du = min(degree, deriv_order)

        CK = [[None for _ in range(dimension)] for _ in range(deriv_order + 1)]
        for k in range(degree + 1, deriv_order + 1):
            CK[k] = [0.0 for _ in range(dimension)]

        span = helpers.find_span(knot_vector, len(control_points), knot)
        bfunsders = helpers.basis_function_ders(degree, tuple(knot_vector), span, knot, du)

        for k in range(0, du + 1):
            CK[k] = [0.0 for _ in range(dimension)]
            for j in range(0, degree + 1):
                CK[k][:] = [drv + (bfunsders[k][j] * ctl_pt) for drv, ctl_pt in
                            zip(CK[k], control_points[span - degree + j])]

        # Return the derivatives
        return CK

    def derivatives(self, **kwargs):
        pass

    def insert_knot(self, **kwargs):
        pass


class CurveEvaluator2(CurveEvaluator):
    """ Sequential B-Spline curve evaluation algorithms.

    This evaluator implements the following algorithms from **The NURBS Book**:

    * Algorithm A3.1: CurvePoint
    * Algorithm A3.3: CurveDerivCpts
    * Algorithm A3.4: CurveDerivsAlg2

    """

    def __init__(self):
        super(CurveEvaluator2, self).__init__()
        self._name = "Curve Evaluator using A3.4 CurveDerivsAlg2"

    # Computes the control points of all derivative curves up to and including the d-th derivative
    def _derivatives_ctrlpts(self, **kwargs):
        """ Computes the control points of all derivative curves up to and including the {degree}-th derivative.

        Output is PK[k][i], i-th control point of the k-th derivative curve where 0 <= k <= degree and r1 <= i <= r2-k

        :param order: derivative order
        :type order: integer
        :param r1: minimum span
        :type r1: integer
        :param r2: maximum span
        :type r2: integer
        :return: PK, a 2D list of control points
        :rtype: list
        """
        r1 = kwargs.get('r1', 0)  # minimum span
        r2 = kwargs.get('r2', 0)  # maximum span
        deriv_order = kwargs.get('deriv_order', 0)
        degree = kwargs.get('degree')
        knot_vector = kwargs.get('knotvector')
        control_points = kwargs.get('ctrlpts')
        dimension = kwargs.get('dimension')

        # Algorithm A3.3
        r = r2 - r1
        PK = [[[None for _ in range(dimension)] for _ in range(r + 1)] for _ in range(deriv_order + 1)]
        for i in range(0, r + 1):
            PK[0][i][:] = [elem for elem in control_points[r1 + i]]

        for k in range(1, deriv_order + 1):
            tmp = degree - k + 1
            for i in range(0, r - k + 1):
                PK[k][i][:] = [tmp * (elem1 - elem2) / (
                    knot_vector[r1 + i + degree + 1] - knot_vector[r1 + i + k]) for elem1, elem2
                               in zip(PK[k - 1][i + 1], PK[k - 1][i])]

        # Return a 2-dimensional list of control points
        return PK

    # Evaluates the curve derivative using "CurveDerivsAlg2" algorithm
    def derivatives_single(self, **kwargs):
        """ Evaluates n-th order curve derivatives at the given parameter value. """
        knot = kwargs.get('knot')
        deriv_order = kwargs.get('deriv_order')
        degree = kwargs.get('degree')
        knot_vector = kwargs.get('knotvector')
        control_points = kwargs.get('ctrlpts')
        dimension = kwargs.get('dimension')

        # Algorithm A3.4
        du = min(degree, deriv_order)

        CK = [[None for _ in range(dimension)] for _ in range(deriv_order + 1)]
        for k in range(degree + 1, deriv_order + 1):
            CK[k] = [0.0 for _ in range(dimension)]

        span = helpers.find_span(knot_vector, len(control_points), knot)
        bfuns = helpers.basis_function_all(degree, tuple(knot_vector), span, knot)
        PK = self._derivatives_ctrlpts(order=du, r1=(span - degree), r2=span, **kwargs)

        for k in range(0, du + 1):
            CK[k] = [0.0 for _ in range(dimension)]
            for j in range(0, degree - k + 1):
                CK[k][:] = [elem + (bfuns[j][degree - k] * drv_ctl_p) for elem, drv_ctl_p in
                            zip(CK[k], PK[k][j])]

        # Return the derivatives
        return CK


class NURBSCurveEvaluator(CurveEvaluator):
    """ Sequential NURBS curve evaluation algorithms.

    This evaluator implements the following algorithms from **The NURBS Book**:

    * Algorithm A4.1: CurvePoint
    * Algorithm A4.2: RatCurveDerivs

    """

    def __init__(self):
        super(NURBSCurveEvaluator, self).__init__()
        self._name = "NURBS Curve Evaluator"

    def evaluate_single(self, **kwargs):
        """ Evaluates a single curve point. """
{'fraction_non_alphanumeric': 0.11777625257378174, 'fraction_numerical': 0.014413177762525738, 'mean_word_length': 2.3267123287671234, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4584852', 'n_tokens_mistral': 4789, 'n_tokens_neox': 4539, 'n_words': 1265}