| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826 |
- # Author: vvlachoudis@gmail.com
- # Vasilis Vlachoudis
- # Date: 20-Oct-2015
- # ##########################################################
- # FlatCAM: 2D Post-processing for Manufacturing #
- # File modified: Marius Adrian Stanciu #
- # Date: 3/10/2019 #
- # ##########################################################
- import math
- def norm(v):
- return math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2])
- def normalize_2(v):
- m = norm(v)
- return [v[0]/m, v[1]/m, v[2]/m]
- # ------------------------------------------------------------------------------
- # Convert a B-spline to polyline with a fixed number of segments
- # ------------------------------------------------------------------------------
- def spline2Polyline(xyz, degree, closed, segments, knots):
- """
- :param xyz: DXF spline control points
- :param degree: degree of the Spline curve
- :param closed: closed Spline
- :type closed: bool
- :param segments: how many lines to use for Spline approximation
- :param knots: DXF spline knots
- :return: x,y,z coordinates (each is a list)
- """
- # Check if last point coincide with the first one
- if (Vector(xyz[0]) - Vector(xyz[-1])).length2() < 1e-10:
- # it is already closed, treat it as open
- closed = False
- # FIXME we should verify if it is periodic,.... but...
- # I am not sure :)
- if closed:
- xyz.extend(xyz[:degree])
- knots = None
- else:
- # make base-1
- # knots.insert(0, 0)
- pass
- npts = len(xyz)
- if degree < 1 or degree > 3:
- # print "invalid degree"
- return None, None, None
- # order:
- k = degree+1
- if npts < k:
- # print "not enough control points"
- return None, None, None
- # resolution:
- nseg = segments * npts
- # WARNING: base 1
- b = [0.0]*(npts*3+1) # polygon points
- h = [1.0]*(npts+1) # set all homogeneous weighting factors to 1.0
- p = [0.0]*(nseg*3+1) # returned curved points
- i = 1
- for pt in xyz:
- b[i] = pt[0]
- b[i+1] = pt[1]
- b[i+2] = pt[2]
- i += 3
- # if periodic:
- if closed:
- _rbsplinu(npts, k, nseg, b, h, p, knots)
- else:
- _rbspline(npts, k, nseg, b, h, p, knots)
- x = []
- y = []
- z = []
- for i in range(1, 3*nseg+1, 3):
- x.append(p[i])
- y.append(p[i+1])
- z.append(p[i+2])
- # for i,xyz in enumerate(zip(x,y,z)):
- # print i,xyz
- return x, y, z
- # ------------------------------------------------------------------------------
- # Subroutine to generate a B-spline open knot vector with multiplicity
- # equal to the order at the ends.
- # c = order of the basis function
- # n = the number of defining polygon vertices
- # n+2 = index of x[] for the first occurence of the maximum knot vector value
- # n+order = maximum value of the knot vector -- $n + c$
- # x[] = array containing the knot vector
- # ------------------------------------------------------------------------------
- def _knot(n, order):
- x = [0.0]*(n+order+1)
- for i in range(2, n+order+1):
- if order < i < n+2:
- x[i] = x[i-1] + 1.0
- else:
- x[i] = x[i-1]
- return x
- # ------------------------------------------------------------------------------
- # Subroutine to generate a B-spline uniform (periodic) knot vector.
- #
- # order = order of the basis function
- # n = the number of defining polygon vertices
- # n+order = maximum value of the knot vector -- $n + order$
- # x[] = array containing the knot vector
- # ------------------------------------------------------------------------------
- def _knotu(n, order):
- x = [0]*(n+order+1)
- for i in range(2, n+order+1):
- x[i] = float(i-1)
- return x
- # ------------------------------------------------------------------------------
- # Subroutine to generate rational B-spline basis functions--open knot vector
- # C code for An Introduction to NURBS
- # by David F. Rogers. Copyright (C) 2000 David F. Rogers,
- # All rights reserved.
- # Name: rbasis
- # Subroutines called: none
- # Book reference: Chapter 4, Sec. 4. , p 296
- # c = order of the B-spline basis function
- # d = first term of the basis function recursion relation
- # e = second term of the basis function recursion relation
- # h[] = array containing the homogeneous weights
- # npts = number of defining polygon vertices
- # nplusc = constant -- npts + c -- maximum number of knot values
- # r[] = array containing the rational basis functions
- # r[1] contains the basis function associated with B1 etc.
- # t = parameter value
- # temp[] = temporary array
- # x[] = knot vector
- # ------------------------------------------------------------------------------
- def _rbasis(c, t, npts, x, h, r):
- nplusc = npts + c
- temp = [0.0]*(nplusc+1)
- # calculate the first order non-rational basis functions n[i]
- for i in range(1, nplusc):
- if x[i] <= t < x[i+1]:
- temp[i] = 1.0
- else:
- temp[i] = 0.0
- # calculate the higher order non-rational basis functions
- for k in range(2, c+1):
- for i in range(1, nplusc-k+1):
- # if the lower order basis function is zero skip the calculation
- if temp[i] != 0.0:
- d = ((t-x[i])*temp[i])/(x[i+k-1]-x[i])
- else:
- d = 0.0
- # if the lower order basis function is zero skip the calculation
- if temp[i+1] != 0.0:
- e = ((x[i+k]-t)*temp[i+1])/(x[i+k]-x[i+1])
- else:
- e = 0.0
- temp[i] = d + e
- # pick up last point
- if t >= x[nplusc]:
- temp[npts] = 1.0
- # calculate sum for denominator of rational basis functions
- s = 0.0
- for i in range(1, npts+1):
- s += temp[i]*h[i]
- # form rational basis functions and put in r vector
- for i in range(1, npts+1):
- if s != 0.0:
- r[i] = (temp[i]*h[i])/s
- else:
- r[i] = 0
- # ------------------------------------------------------------------------------
- # Generates a rational B-spline curve using a uniform open knot vector.
- #
- # C code for An Introduction to NURBS
- # by David F. Rogers. Copyright (C) 2000 David F. Rogers,
- # All rights reserved.
- #
- # Name: rbspline.c
- # Subroutines called: _knot, rbasis
- # Book reference: Chapter 4, Alg. p. 297
- #
- # b = array containing the defining polygon vertices
- # b[1] contains the x-component of the vertex
- # b[2] contains the y-component of the vertex
- # b[3] contains the z-component of the vertex
- # h = array containing the homogeneous weighting factors
- # k = order of the B-spline basis function
- # nbasis = array containing the basis functions for a single value of t
- # nplusc = number of knot values
- # npts = number of defining polygon vertices
- # p[,] = array containing the curve points
- # p[1] contains the x-component of the point
- # p[2] contains the y-component of the point
- # p[3] contains the z-component of the point
- # p1 = number of points to be calculated on the curve
- # t = parameter value 0 <= t <= npts - k + 1
- # x[] = array containing the knot vector
- # ------------------------------------------------------------------------------
- def _rbspline(npts, k, p1, b, h, p, x):
- nplusc = npts + k
- nbasis = [0.0]*(npts+1) # zero and re-dimension the basis array
- # generate the uniform open knot vector
- if x is None or len(x) != nplusc+1:
- x = _knot(npts, k)
- icount = 0
- # calculate the points on the rational B-spline curve
- t = 0
- step = float(x[nplusc])/float(p1-1)
- for i1 in range(1, p1+1):
- if x[nplusc] - t < 5e-6:
- t = x[nplusc]
- # generate the basis function for this value of t
- nbasis = [0.0]*(npts+1) # zero and re-dimension the knot vector and the basis array
- _rbasis(k, t, npts, x, h, nbasis)
- # generate a point on the curve
- for j in range(1, 4):
- jcount = j
- p[icount+j] = 0.0
- # Do local matrix multiplication
- for i in range(1, npts+1):
- p[icount+j] += nbasis[i]*b[jcount]
- jcount += 3
- icount += 3
- t += step
- # ------------------------------------------------------------------------------
- # Subroutine to generate a rational B-spline curve using an uniform periodic knot vector
- #
- # C code for An Introduction to NURBS
- # by David F. Rogers. Copyright (C) 2000 David F. Rogers,
- # All rights reserved.
- #
- # Name: rbsplinu.c
- # Subroutines called: _knotu, _rbasis
- # Book reference: Chapter 4, Alg. p. 298
- #
- # b[] = array containing the defining polygon vertices
- # b[1] contains the x-component of the vertex
- # b[2] contains the y-component of the vertex
- # b[3] contains the z-component of the vertex
- # h[] = array containing the homogeneous weighting factors
- # k = order of the B-spline basis function
- # nbasis = array containing the basis functions for a single value of t
- # nplusc = number of knot values
- # npts = number of defining polygon vertices
- # p[,] = array containing the curve points
- # p[1] contains the x-component of the point
- # p[2] contains the y-component of the point
- # p[3] contains the z-component of the point
- # p1 = number of points to be calculated on the curve
- # t = parameter value 0 <= t <= npts - k + 1
- # x[] = array containing the knot vector
- # ------------------------------------------------------------------------------
- def _rbsplinu(npts, k, p1, b, h, p, x=None):
- nplusc = npts + k
- nbasis = [0.0]*(npts+1) # zero and re-dimension the basis array
- # generate the uniform periodic knot vector
- if x is None or len(x) != nplusc+1:
- # zero and re dimension the knot vector and the basis array
- x = _knotu(npts, k)
- icount = 0
- # calculate the points on the rational B-spline curve
- t = k-1
- step = (float(npts)-(k-1))/float(p1-1)
- for i1 in range(1, p1+1):
- if x[nplusc] - t < 5e-6:
- t = x[nplusc]
- # generate the basis function for this value of t
- nbasis = [0.0]*(npts+1)
- _rbasis(k, t, npts, x, h, nbasis)
- # generate a point on the curve
- for j in range(1, 4):
- jcount = j
- p[icount+j] = 0.0
- # Do local matrix multiplication
- for i in range(1, npts+1):
- p[icount+j] += nbasis[i]*b[jcount]
- jcount += 3
- icount += 3
- t += step
- # Accuracy for comparison operators
- _accuracy = 1E-15
- def Cmp0(x):
- """Compare against zero within _accuracy"""
- return abs(x) < _accuracy
- def gauss(A, B):
- """Solve A*X = B using the Gauss elimination method"""
- n = len(A)
- s = [0.0] * n
- X = [0.0] * n
- p = [i for i in range(n)]
- for i in range(n):
- s[i] = max([abs(x) for x in A[i]])
- for k in range(n - 1):
- # select j>=k so that
- # |A[p[j]][k]| / s[p[i]] >= |A[p[i]][k]| / s[p[i]] for i = k,k+1,...,n
- j = k
- ap = abs(A[p[j]][k]) / s[p[j]]
- for i in range(k + 1, n):
- api = abs(A[p[i]][k]) / s[p[i]]
- if api > ap:
- j = i
- ap = api
- if j != k:
- p[k], p[j] = p[j], p[k] # Swap values
- for i in range(k + 1, n):
- z = A[p[i]][k] / A[p[k]][k]
- A[p[i]][k] = z
- for j in range(k + 1, n):
- A[p[i]][j] -= z * A[p[k]][j]
- for k in range(n - 1):
- for i in range(k + 1, n):
- B[p[i]] -= A[p[i]][k] * B[p[k]]
- for i in range(n - 1, -1, -1):
- X[i] = B[p[i]]
- for j in range(i + 1, n):
- X[i] -= A[p[i]][j] * X[j]
- X[i] /= A[p[i]][i]
- return X
- # Vector class
- # Inherits from List
- class Vector(list):
- """Vector class"""
- def __init__(self, x=3, *args):
- """Create a new vector,
- Vector(size), Vector(list), Vector(x,y,z,...)"""
- list.__init__(self)
- if isinstance(x, int) and not args:
- for i in range(x):
- self.append(0.0)
- elif isinstance(x, (list, tuple)):
- for i in x:
- self.append(float(i))
- else:
- self.append(float(x))
- for i in args:
- self.append(float(i))
- # ----------------------------------------------------------------------
- def set(self, x, y, z=None):
- """Set vector"""
- self[0] = x
- self[1] = y
- if z:
- self[2] = z
- # ----------------------------------------------------------------------
- def __repr__(self):
- return "[%s]" % ", ".join([repr(x) for x in self])
- # ----------------------------------------------------------------------
- def __str__(self):
- return "[%s]" % ", ".join([("%15g" % (x)).strip() for x in self])
- # ----------------------------------------------------------------------
- def eq(self, v, acc=_accuracy):
- """Test for equality with vector v within accuracy"""
- if len(self) != len(v):
- return False
- s2 = 0.0
- for a, b in zip(self, v):
- s2 += (a - b) ** 2
- return s2 <= acc ** 2
- def __eq__(self, v):
- return self.eq(v)
- # ----------------------------------------------------------------------
- def __neg__(self):
- """Negate vector"""
- new = Vector(len(self))
- for i, s in enumerate(self):
- new[i] = -s
- return new
- # ----------------------------------------------------------------------
- def __add__(self, v):
- """Add 2 vectors"""
- size = min(len(self), len(v))
- new = Vector(size)
- for i in range(size):
- new[i] = self[i] + v[i]
- return new
- # ----------------------------------------------------------------------
- def __iadd__(self, v):
- """Add vector v to self"""
- for i in range(min(len(self), len(v))):
- self[i] += v[i]
- return self
- # ----------------------------------------------------------------------
- def __sub__(self, v):
- """Subtract 2 vectors"""
- size = min(len(self), len(v))
- new = Vector(size)
- for i in range(size):
- new[i] = self[i] - v[i]
- return new
- # ----------------------------------------------------------------------
- def __isub__(self, v):
- """Subtract vector v from self"""
- for i in range(min(len(self), len(v))):
- self[i] -= v[i]
- return self
- # ----------------------------------------------------------------------
- # Scale or Dot product
- # ----------------------------------------------------------------------
- def __mul__(self, v):
- """scale*Vector() or Vector()*Vector() - Scale vector or dot product"""
- if isinstance(v, list):
- return self.dot(v)
- else:
- return Vector([x * v for x in self])
- # ----------------------------------------------------------------------
- # Scale or Dot product
- # ----------------------------------------------------------------------
- def __rmul__(self, v):
- """scale*Vector() or Vector()*Vector() - Scale vector or dot product"""
- if isinstance(v, Vector):
- return self.dot(v)
- else:
- return Vector([x * v for x in self])
- # ----------------------------------------------------------------------
- # Divide by floating point
- # ----------------------------------------------------------------------
- def __div__(self, b):
- return Vector([x / b for x in self])
- # ----------------------------------------------------------------------
- def __xor__(self, v):
- """Cross product"""
- return self.cross(v)
- # ----------------------------------------------------------------------
- def dot(self, v):
- """Dot product of 2 vectors"""
- s = 0.0
- for a, b in zip(self, v):
- s += a * b
- return s
- # ----------------------------------------------------------------------
- def cross(self, v):
- """Cross product of 2 vectors"""
- if len(self) == 3:
- return Vector(self[1] * v[2] - self[2] * v[1],
- self[2] * v[0] - self[0] * v[2],
- self[0] * v[1] - self[1] * v[0])
- elif len(self) == 2:
- return self[0] * v[1] - self[1] * v[0]
- else:
- raise Exception("Cross product needs 2d or 3d vectors")
- # ----------------------------------------------------------------------
- def length2(self):
- """Return length squared of vector"""
- s2 = 0.0
- for s in self:
- s2 += s ** 2
- return s2
- # ----------------------------------------------------------------------
- def length(self):
- """Return length of vector"""
- s2 = 0.0
- for s in self:
- s2 += s ** 2
- return math.sqrt(s2)
- __abs__ = length
- # ----------------------------------------------------------------------
- def arg(self):
- """return vector angle"""
- return math.atan2(self[1], self[0])
- # ----------------------------------------------------------------------
- def norm(self):
- """Normalize vector and return length"""
- length = self.length()
- if length > 0.0:
- invlen = 1.0 / length
- for i in range(len(self)):
- self[i] *= invlen
- return length
- normalize = norm
- # ----------------------------------------------------------------------
- def unit(self):
- """return a unit vector"""
- v = self.clone()
- v.norm()
- return v
- # ----------------------------------------------------------------------
- def clone(self):
- """Clone vector"""
- return Vector(self)
- # ----------------------------------------------------------------------
- def x(self):
- return self[0]
- def y(self):
- return self[1]
- def z(self):
- return self[2]
- # ----------------------------------------------------------------------
- def orthogonal(self):
- """return a vector orthogonal to self"""
- xx = abs(self.x())
- yy = abs(self.y())
- if len(self) >= 3:
- zz = abs(self.z())
- if xx < yy:
- if xx < zz:
- return Vector(0.0, self.z(), -self.y())
- else:
- return Vector(self.y(), -self.x(), 0.0)
- else:
- if yy < zz:
- return Vector(-self.z(), 0.0, self.x())
- else:
- return Vector(self.y(), -self.x(), 0.0)
- else:
- return Vector(-self.y(), self.x())
- # ----------------------------------------------------------------------
- def direction(self, zero=_accuracy):
- """return containing the direction if normalized with any of the axis"""
- v = self.clone()
- length = v.norm()
- if abs(length) <= zero:
- return "O"
- if abs(v[0] - 1.0) < zero:
- return "X"
- elif abs(v[0] + 1.0) < zero:
- return "-X"
- elif abs(v[1] - 1.0) < zero:
- return "Y"
- elif abs(v[1] + 1.0) < zero:
- return "-Y"
- elif abs(v[2] - 1.0) < zero:
- return "Z"
- elif abs(v[2] + 1.0) < zero:
- return "-Z"
- else:
- # nothing special about the direction, return N
- return "N"
- # ----------------------------------------------------------------------
- # Set the vector directly in polar coordinates
- # @param ma magnitude of vector
- # @param ph azimuthal angle in radians
- # @param th polar angle in radians
- # ----------------------------------------------------------------------
- def setPolar(self, ma, ph, th):
- """Set the vector directly in polar coordinates"""
- sf = math.sin(ph)
- cf = math.cos(ph)
- st = math.sin(th)
- ct = math.cos(th)
- self[0] = ma * st * cf
- self[1] = ma * st * sf
- self[2] = ma * ct
- # ----------------------------------------------------------------------
- def phi(self):
- """return the azimuth angle."""
- if Cmp0(self.x()) and Cmp0(self.y()):
- return 0.0
- return math.atan2(self.y(), self.x())
- # ----------------------------------------------------------------------
- def theta(self):
- """return the polar angle."""
- if Cmp0(self.x()) and Cmp0(self.y()) and Cmp0(self.z()):
- return 0.0
- return math.atan2(self.perp(), self.z())
- # ----------------------------------------------------------------------
- def cosTheta(self):
- """return cosine of the polar angle."""
- ptot = self.length()
- if Cmp0(ptot):
- return 1.0
- else:
- return self.z() / ptot
- # ----------------------------------------------------------------------
- def perp2(self):
- """return the transverse component squared
- (R^2 in cylindrical coordinate system)."""
- return self.x() * self.x() + self.y() * self.y()
- # ----------------------------------------------------------------------
- def perp(self):
- """@return the transverse component
- (R in cylindrical coordinate system)."""
- return math.sqrt(self.perp2())
- # ----------------------------------------------------------------------
- # Return a random 3D vector
- # ----------------------------------------------------------------------
- # @staticmethod
- # def random():
- # cosTheta = 2.0 * random.random() - 1.0
- # sinTheta = math.sqrt(1.0 - cosTheta ** 2)
- # phi = 2.0 * math.pi * random.random()
- # return Vector(math.cos(phi) * sinTheta, math.sin(phi) * sinTheta, cosTheta)
- # #===============================================================================
- # # Cardinal cubic spline class
- # #===============================================================================
- # class CardinalSpline:
- # def __init__(self, A=0.5):
- # # The default matrix is the Catmull-Rom spline
- # # which is equal to Cardinal matrix
- # # for A = 0.5
- # #
- # # Note: Vasilis
- # # The A parameter should be the fraction in t where
- # # the second derivative is zero
- # self.setMatrix(A)
- #
- # #-----------------------------------------------------------------------
- # # Set the matrix according to Cardinal
- # #-----------------------------------------------------------------------
- # def setMatrix(self, A=0.5):
- # self.M = []
- # self.M.append([ -A, 2.-A, A-2., A ])
- # self.M.append([2.*A, A-3., 3.-2.*A, -A ])
- # self.M.append([ -A, 0., A, 0.])
- # self.M.append([ 0., 1., 0, 0.])
- #
- # #-----------------------------------------------------------------------
- # # Evaluate Cardinal spline at position t
- # # @param P list or tuple with 4 points y positions
- # # @param t [0..1] fraction of interval from points 1..2
- # # @param k index of starting 4 elements in P
- # # @return spline evaluation
- # #-----------------------------------------------------------------------
- # def __call__(self, P, t, k=1):
- # T = [t*t*t, t*t, t, 1.0]
- # R = [0.0]*4
- # for i in range(4):
- # for j in range(4):
- # R[i] += T[j] * self.M[j][i]
- # y = 0.0
- # for i in range(4):
- # y += R[i]*P[k+i-1]
- #
- # return y
- #
- # #-----------------------------------------------------------------------
- # # Return the coefficients of a 3rd degree polynomial
- # # f(x) = a t^3 + b t^2 + c t + d
- # # @return [a, b, c, d]
- # #-----------------------------------------------------------------------
- # def coefficients(self, P, k=1):
- # C = [0.0]*4
- # for i in range(4):
- # for j in range(4):
- # C[i] += self.M[i][j] * P[k+j-1]
- # return C
- #
- # #-----------------------------------------------------------------------
- # # Evaluate the value of the spline using the coefficients
- # #-----------------------------------------------------------------------
- # def evaluate(self, C, t):
- # return ((C[0]*t + C[1])*t + C[2])*t + C[3]
- #
- # #===============================================================================
- # # Cubic spline ensuring that the first and second derivative are continuous
- # # adapted from Penelope Manual Appending B.1
- # # It requires all the points (xi,yi) and the assumption on how to deal
- # # with the second derivative on the extremities
- # # Option 1: assume zero as second derivative on both ends
- # # Option 2: assume the same as the next or previous one
- # #===============================================================================
- # class CubicSpline:
- # def __init__(self, X, Y):
- # self.X = X
- # self.Y = Y
- # self.n = len(X)
- #
- # # Option #1
- # s1 = 0.0 # zero based = s0
- # sN = 0.0 # zero based = sN-1
- #
- # # Construct the tri-diagonal matrix
- # A = []
- # B = [0.0] * (self.n-2)
- # for i in range(self.n-2):
- # A.append([0.0] * (self.n-2))
- #
- # for i in range(1,self.n-1):
- # hi = self.h(i)
- # Hi = 2.0*(self.h(i-1) + hi)
- # j = i-1
- # A[j][j] = Hi
- # if i+1<self.n-1:
- # A[j][j+1] = A[j+1][j] = hi
- #
- # if i==1:
- # B[j] = 6.*(self.d(i) - self.d(j)) - hi*s1
- # elif i<self.n-2:
- # B[j] = 6.*(self.d(i) - self.d(j))
- # else:
- # B[j] = 6.*(self.d(i) - self.d(j)) - hi*sN
- #
- #
- # self.s = gauss(A,B)
- # self.s.insert(0,s1)
- # self.s.append(sN)
- # # print ">> s <<"
- # # pprint(self.s)
- #
- # #-----------------------------------------------------------------------
- # def h(self, i):
- # return self.X[i+1] - self.X[i]
- #
- # #-----------------------------------------------------------------------
- # def d(self, i):
- # return (self.Y[i+1] - self.Y[i]) / (self.X[i+1] - self.X[i])
- #
- # #-----------------------------------------------------------------------
- # def coefficients(self, i):
- # """return coefficients of cubic spline for interval i a*x**3+b*x**2+c*x+d"""
- # hi = self.h(i)
- # si = self.s[i]
- # si1 = self.s[i+1]
- # xi = self.X[i]
- # xi1 = self.X[i+1]
- # fi = self.Y[i]
- # fi1 = self.Y[i+1]
- #
- # a = 1./(6.*hi)*(si*xi1**3 - si1*xi**3 + 6.*(fi*xi1 - fi1*xi)) + hi/6.*(si1*xi - si*xi1)
- # b = 1./(2.*hi)*(si1*xi**2 - si*xi1**2 + 2*(fi1 - fi)) + hi/6.*(si - si1)
- # c = 1./(2.*hi)*(si*xi1 - si1*xi)
- # d = 1./(6.*hi)*(si1-si)
- #
- # return [d,c,b,a]
- #
- # #-----------------------------------------------------------------------
- # def __call__(self, i, x):
- # # FIXME should interpolate to find the interval
- # C = self.coefficients(i)
- # return ((C[0]*x + C[1])*x + C[2])*x + C[3]
- #
- # #-----------------------------------------------------------------------
- # # @return evaluation of cubic spline at x using coefficients C
- # #-----------------------------------------------------------------------
- # def evaluate(self, C, x):
- # return ((C[0]*x + C[1])*x + C[2])*x + C[3]
- #
- # #-----------------------------------------------------------------------
- # # Return evaluated derivative at x using coefficients C
- # #-----------------------------------------------------------------------
- # def derivative(self, C, x):
- # a = 3.0*C[0] # derivative coefficients
- # b = 2.0*C[1] # ... for sampling with rejection
- # c = C[2]
- # return (3.0*C[0]*x + 2.0*C[1])*x + C[2]
- #
|