Пример #1
0
def dislinPlot(xvals, yvals, ylimit):

    # Set the plot output file format
    dislin.metafl(plot_filetype)

    # Dislin routine initialization
    dislin.disini()

    # Set the font type on graph
    dislin.complx()

    # Set the Graph color
    dislin.color(plot_color)

    # Fix the position of axes on graph area
    dislin.axspos(axes_pos_x, axes_pos_y)

    # Fix the length of axes on graph area
    dislin.axslen(axes_len_l, axes_len_h)

    # Set name of axes
    dislin.name(x_axis_name, 'X')
    dislin.name(y_axis_name, 'Y')

    # Num of digits after decimal point ; "-2" refers automatic selection
    dislin.labdig(-2, 'X')

    # Num of ticks on axes b/w values
    dislin.ticks(x_axis_ticks, 'X')
    dislin.ticks(y_axis_ticks, 'Y')

    # Plot title text
    dislin.titlin('y_axis_name vs x_axis_name', 1)

    # Plot details; xlower., xupper., x1stlabel., xstep., ylower., yupper., y1stlabel., ystep
    dislin.graf(0., float(data_samples), 0., float(x_step), 0., float(ylimit),
                0., float(y_step))

    # Write title on plot
    dislin.title()

    # Curve changes if called multiple times
    dislin.chncrv('NONE')

    # Plot the Curve
    dislin.curve(xvals, yvals, data_samples)

    # Dislin routine conclusion
    dislin.disfin()
Пример #2
0
def myplot(id):
    xa = -180.
    xe = 180.
    xor = -180.
    xstp = 60.

    ya = -90.
    ye = 90.
    yor = -90.
    ystp = 30.

    isel = dislin.gwglis(id_lis)
    dislin.setxid(id_draw, 'widget')
    dislin.metafl('xwin')
    dislin.disini()
    dislin.erase()
    dislin.complx()

    if (isel >= 4 and isel <= 7):
        dislin.noclip()
    elif (isel == 2):
        ya = -85
        ye = 85
        yor = -60
    elif (isel >= 8 and isel <= 10):
        ya = 0
        ye = 90
        yor = 0

    dislin.labdig(-1, 'xy')
    dislin.name('Longitude', 'x')
    dislin.name('Latitude', 'y')
    dislin.projct(cl2[isel - 1])
    dislin.titlin(cl1[isel - 1] + 'Projection', 3)
    dislin.htitle(50)
    dislin.grafmp(xa, xe, xor, xstp, ya, ye, yor, ystp)
    dislin.title()
    dislin.gridmp(1, 1)
    dislin.color('green')
    dislin.world()
    dislin.unit(0)
    dislin.disfin()
Пример #3
0
for i in range(0, n):
    x = i * stepx
    for j in range(0, m):
        y = j * stepy
        zmat[i * m + j] = 2 * math.sin(x * fpi) * math.sin(y * fpi)

dislin.metafl('cons')
dislin.setpag('da4p')
dislin.disini()
dislin.pagera()
dislin.complx()

dislin.titlin(ctit1, 2)
dislin.titlin(ctit2, 4)

dislin.axspos(200, 2600)
dislin.axslen(1800, 1800)

dislin.name('X-axis', 'X')
dislin.name('Y-axis', 'Y')
dislin.name('Z-axis', 'Z')

dislin.view3d(-5., -5., 4., 'ABS')
dislin.graf3d(0., 360., 0., 90., 0., 360., 0., 90., -3., 3., -3., 1.)
dislin.height(50)
dislin.title()

dislin.color('green')
dislin.surmat(zmat, n, m, 1, 1)
dislin.disfin()
Пример #4
0
#! /usr/bin/env python
import dislin

dislin.metafl('xwin')
dislin.disini()
dislin.pagera()
dislin.complx()

dislin.axspos(400, 1850)
dislin.axslen(2400, 1400)

dislin.name('Longitude', 'X')
dislin.name('Latitude', 'Y')
dislin.titlin('World Coastlines and Lakes', 3)

dislin.labels('MAP', 'XY')
dislin.labdig(-1, 'XY')
dislin.grafmp(-180., 180., -180., 90., -90., 90., -90., 30.)

dislin.gridmp(1, 1)
dislin.color('green')
dislin.world()

dislin.color('foreground')
dislin.height(50)
dislin.title()
dislin.disfin()
Пример #5
0
dislin.pagera()
dislin.complx()

dislin.height(50)
nl = dislin.nlmess(ctit)
dislin.messag(ctit, (2970 - nl) / 2, 200)

nx0 = 335
ny0 = 350

iclr = 0
for i in range(0, 3):
    ny = ny0 + i * 600
    for j in range(0, 6):
        nx = nx0 + j * 400
        ii = i * 6 + j
        dislin.shdpat(ii)
        iclr = iclr + 1
        dislin.setclr(iclr)
        for k in range(0, 4):
            ixp[k] = ix[k] + nx
            iyp[k] = iy[k] + ny

        dislin.areaf(ixp, iyp, 4)
        nl = dislin.nlnumb(ii, -1)
        nx = nx + (300 - nl) / 2
        dislin.color('foreground')
        dislin.number(ii, -1, nx, ny + 460)

dislin.disfin()
Пример #6
0
class Srf:
    '''Construct a NURB surface structure, and check the format.
    
 The NURB surface is represented by a 4 dimensional b-spline.

 INPUT:

    cntrl  - Control points, homogeneous coordinates (wx,wy,wz,w)
        For a surface [dim,nu,nv] matrix
            where nu  is along the u direction and
            nv  is along the v direction.
            dim is the dimension valid options are:
            2 .... (x,y)        2D cartesian coordinates
            3 .... (x,y,z)      3D cartesian coordinates   
            4 .... (wx,wy,wz,w) 4D homogeneous coordinates

    uknots - Knot sequence along the parametric u direction.
    vknots - Knot sequence along the paramteric v direction.

 NOTES:

    Its assumed that the input knot sequences span the
    interval [0.0,1.0] and are clamped to the control
    points at the end by a knot multiplicity equal to
    the spline order.'''
    def __init__(self, cntrl, uknots, vknots):
        self._bezier = None
        cntrl = numerix.asarray(cntrl, numerix.Float)
        (dim, nu, nv) = cntrl.shape
        if dim < 2 or dim > 4:
            raise NURBSError, 'Illegal control point format'
        elif dim < 4:
            self.cntrl = numerix.zeros((4, nu, nv), numerix.Float)
            self.cntrl[0:dim, :, :] = cntrl
            self.cntrl[-1, :, :] = numerix.ones((nu, nv), numerix.Float)
        else:
            self.cntrl = cntrl

        # Force the u knot sequence to be a vector in ascending order
        # and normalise between [0.0,1.0]
        uknots = numerix.sort(numerix.asarray(uknots, numerix.Float))
        nku = uknots.shape[0]
        uknots = (uknots - uknots[0]) / (uknots[-1] - uknots[0])
        if uknots[0] == uknots[-1]:
            raise NURBSError, 'Illegal uknots sequence'
        self.uknots = uknots

        # Force the v knot sequence to be a vector in ascending order
        # and normalise between [0.0,1.0]
        vknots = -numerix.sort(-numerix.asarray(vknots, numerix.Float))
        nkv = vknots.shape[0]
        vknots = (vknots - vknots[0]) / (vknots[-1] - vknots[0])
        if vknots[0] == vknots[-1]:
            raise NURBSError, 'Illegal vknots sequence'
        self.vknots = vknots

        # Spline Degree
        self.degree = [nku - nu - 1, nkv - nv - 1]
        if self.degree[0] < 0 or self.degree[1] < 0:
            raise NURBSError, 'NURBS order must be a positive integer'

    def trans(self, mat):
        "Apply the 4D transform matrix to the NURB control points."
        for v in range(self.cntrl.shape[2]):
            self.cntrl[:, :, v] = numerix.dot(mat, self.cntrl[:, :, v])

    def swapuv(self):
        "Swap u and v parameters."
        self.cntrl = numerix.transpose(self.cntrl, (0, 2, 1))
        temp = self.uknots[:]
        self.uknots = self.vknots[:]
        self.vknots = temp
        udegree, vdegree = self.degree
        self.degree[0] = vdegree
        self.degree[1] = udegree

    def reverse(self):
        "Reverse evaluation directions."
        coefs = self.cntrl[:, :, ::-1]
        self.cntrl = coefs[:, ::-1, :]
        self.uknots = 1. - self.uknots[::-1]
        self.vknots = 1. - self.vknots[::-1]

    def extractV(self, u):
        "Extract curve in v-direction at parameter u."
        if numerix.any(u < 0.) or numerix.any(u > 1.):
            raise NURBSError, 'Out of parameter range [0,1]'
        if u == 0.:
            cntrl = self.cntrl[:, 0, :]
            knots = self.vknots[:]
        elif u == 1.:
            cntrl = self.cntrl[:, -1, :]
            knots = self.vknots[:]
        else:
            uknots = numerix.repeat(
                numerix.asarray([u], numerix.Float),
                [self.degree[1] * (self.cntrl.shape[2] + 1)])
            coefs = numerix.transpose(self.cntrl, (0, 2, 1))
            coefs = numerix.resize(
                coefs, (4 * self.cntrl.shape[2], self.cntrl.shape[1]))
            coefs, knots = bspkntins(self.degree[0], coefs, self.uknots,
                                     uknots)
            coefs = numerix.resize(coefs,
                                   (4, self.cntrl.shape[2], coefs.shape[1]))
            cntrl = numerix.transpose(coefs, (0, 2, 1))
            i = 0
            j = knots[0]
            for k in knots[1:]:
                if k == u:
                    break
                elif k != j:
                    i += 1
                    j = k
        return Crv.Crv(cntrl[:, i, :], self.vknots[:])

    def extractU(self, v):
        "Extract curve in u-direction at parameter v."
        if numerix.any(v < 0.) or numerix.any(v > 1.):
            raise NURBSError, 'Out of parameter range [0,1]'
        if v == 0.:
            cntrl = self.cntrl[:, :, 0]
            knots = self.uknots[:]
        elif v == 1.:
            cntrl = self.cntrl[:, :, -1]
            knots = self.uknots[:]
        else:
            vknots = numerix.repeat(
                numerix.asarray([v], numerix.Float),
                [self.degree[0] * (self.cntrl.shape[1] + 1)])
            coefs = numerix.resize(
                self.cntrl, (4 * self.cntrl.shape[1], self.cntrl.shape[2]))
            coefs, knots = bspkntins(self.degree[1], coefs, self.vknots,
                                     vknots)
            cntrl = numerix.resize(coefs,
                                   (4, self.cntrl.shape[1], coefs.shape[1]))
            i = 0
            j = knots[0]
            for k in knots[1:]:
                if k == v:
                    break
                elif k != j:
                    i += 1
                    j = k
        return Crv.Crv(cntrl[:, :, i], self.uknots[:])

    def kntins(self, uknots, vknots=None):
        """Insert new knots into the surface
	uknots - knots to be inserted along u direction
	vknots - knots to be inserted along v direction
	NOTE: No knot multiplicity will be increased beyond the order of the spline"""
        if len(vknots):
            # Force the v knot sequence to be a vector in ascending order
            vknots = numerix.sort(numerix.asarray(vknots, numerix.Float))
            if numerix.any(vknots < 0.) or numerix.any(vknots > 1.):
                raise NURBSError, 'Illegal vknots sequence'
            coefs = numerix.resize(
                self.cntrl, (4 * self.cntrl.shape[1], self.cntrl.shape[2]))
            coefs, self.vknots = bspkntins(self.degree[1], coefs, self.vknots,
                                           vknots)
            self.cntrl = numerix.resize(
                coefs, (4, self.cntrl.shape[1], coefs.shape[1]))
        if len(uknots):
            # Force the u knot sequence to be a vector in ascending order
            uknots = numerix.sort(numerix.asarray(uknots, numerix.Float))
            if numerix.any(uknots < 0.) or numerix.any(uknots > 1.):
                raise NURBSError, 'Illegal uknots sequence'
            coefs = numerix.transpose(self.cntrl, (0, 2, 1))
            coefs = numerix.resize(
                coefs, (4 * self.cntrl.shape[2], self.cntrl.shape[1]))
            coefs, self.uknots = bspkntins(self.degree[0], coefs, self.uknots,
                                           uknots)
            coefs = numerix.resize(coefs,
                                   (4, self.cntrl.shape[2], coefs.shape[1]))
            self.cntrl = numerix.transpose(coefs, (0, 2, 1))

    def degelev(self, utimes, vtimes=None):
        """Degree elevate the surface.
	utimes - degree elevate utimes along u direction.
	vtimes - degree elevate vtimes along v direction."""
        if vtimes:
            if vtimes < 0:
                raise NURBSError, 'Degree must be positive'
            coefs = numerix.resize(
                self.cntrl, (4 * self.cntrl.shape[1], self.cntrl.shape[2]))
            coefs, vknots, nh = bspdegelev(self.degree[1], coefs, self.vknots,
                                           vtimes)
            coefs = coefs[:, :nh + 1]
            self.vknots = vknots[:nh + self.degree[1] + vtimes + 2]
            self.degree[1] += vtimes
            self.cntrl = numerix.resize(
                coefs, (4, self.cntrl.shape[1], coefs.shape[1]))
        if utimes:
            if utimes < 0:
                raise NURBSError, 'Degree must be positive'
            coefs = numerix.transpose(self.cntrl, (0, 2, 1))
            coefs = numerix.resize(
                coefs, (4 * self.cntrl.shape[2], self.cntrl.shape[1]))
            coefs, uknots, nh = bspdegelev(self.degree[0], coefs, self.uknots,
                                           utimes)
            coefs = coefs[:, :nh + 1]
            self.uknots = uknots[:nh + self.degree[0] + utimes + 2]
            self.degree[0] += utimes
            coefs = numerix.resize(coefs,
                                   (4, self.cntrl.shape[2], coefs.shape[1]))
            self.cntrl = numerix.transpose(coefs, (0, 2, 1))

    def bezier(self, update=None):
        "Decompose surface to bezier patches and return overlaping control points."
        if update or not self._bezier:
            cntrl = numerix.resize(
                self.cntrl, (4 * self.cntrl.shape[1], self.cntrl.shape[2]))
            cntrl = bspbezdecom(self.degree[1], cntrl, self.vknots)
            cntrl = numerix.resize(cntrl,
                                   (4, self.cntrl.shape[1], cntrl.shape[1]))
            temp1 = cntrl.shape[1]
            temp2 = cntrl.shape[2]
            cntrl = numerix.transpose(cntrl, (0, 2, 1))
            cntrl = numerix.resize(cntrl, (4 * temp2, temp1))
            cntrl = bspbezdecom(self.degree[0], cntrl, self.uknots)
            cntrl = numerix.resize(cntrl, (4, temp2, cntrl.shape[1]))
            self._bezier = numerix.transpose(cntrl, (0, 2, 1))
        return self._bezier

    def bounds(self):
        "Return the bounding box for the surface."
        w = self.cntrl[3, :, :]
        cx = numerix.sort(numerix.ravel(self.cntrl[0, :, :] / w))
        cy = numerix.sort(numerix.ravel(self.cntrl[1, :, :] / w))
        cz = numerix.sort(numerix.ravel(self.cntrl[2, :, :] / w))
        return numerix.asarray([cx[0], cy[0], cz[0], cx[-1], cy[-1], cz[-1]],
                               numerix.Float)

    def pnt3D(self, ut, vt=None):
        """Evaluate parametric point[s] and return 3D cartesian coordinate[s]
	If only ut is given then we will evaluate at scattered points.
	ut(0,:) represents the u direction.
	ut(1,:) represents the v direction.
	If both parameters are given then we will evaluate over a [u,v] grid."""
        val = self.pnt4D(ut, vt)
        if len(val.shape) < 3:
            return val[0:3, :] / numerix.resize(val[-1, :], (3, val.shape[1]))
        else:  #FIX!
            return val[0:3, :, :] / numerix.resize(
                val[-1, :, :], (3, val.shape[1], val.shape[2]))

    def pnt4D(self, ut, vt=None):
        """Evaluate parametric point[s] and return 4D homogeneous coordinates.
	If only ut is given then we will evaluate at scattered points.
	ut(0,:) represents the u direction.
	ut(1,:) represents the v direction.
	If both parameters are given then we will evaluate over a [u,v] grid."""
        ut = numerix.asarray(ut, numerix.Float)
        if numerix.any(ut < 0.) or numerix.any(ut > 1.):
            raise NURBSError, 'NURBS curve parameter out of range [0,1]'

        if vt:  #FIX!
            # Evaluate over a [u,v] grid
            vt = numerix.asarray(vt, numerix.Float)
            if numerix.any(vt < 0.) or numerix.any(vt > 1.):
                raise NURBSError, 'NURBS curve parameter out of range [0,1]'

            val = numerix.resize(
                self.cntrl, (4 * self.cntrl.shape[1], self.cntrl.shape[2]))
            val = bspeval(self.degree[1], val, self.vknots, vt)
            val = numerix.resize(val, (4, self.cntrl.shape[1], vt.shape[0]))

            val = numerix.transpose(val, (0, 2, 1))

            val = numerix.resize(self.cntrl,
                                 (4 * vt.shape[0], self.cntrl.shape[1]))
            val = bspeval(self.degree[0], val, self.uknots, ut)
            val = numerix.resize(val, (4, vt.shape[0], ut.shape[0]))

            return numerix.transpose(val, (0, 2, 1))

        # Evaluate at scattered points
        nt = ut.shape[1]
        uval = numerix.resize(self.cntrl,
                              (4 * self.cntrl.shape[1], self.cntrl.shape[2]))
        uval = bspeval(self.degree[1], uval, self.vknots, ut[1, :])
        uval = numerix.resize(uval, (4, self.cntrl.shape[1], nt))

        val = numerix.zeros((4, nt), numerix.Float)
        for v in range(nt):
            val[:, v] = bspeval(
                self.degree[0],
                numerix.resize(uval[:, :, v], (4, self.cntrl.shape[1])),
                self.uknots, (ut[0, v], ))[:, 0]
        return val

    def plot(self, n=50, iso=8):
        """A simple plotting function based on dislin for debugging purpose.
	n = number of subdivisions. iso = number of iso line to plot in each dir.
	TODO: plot ctrl poins and knots."""
        try:
            import dislin
        except ImportError, value:
            print 'dislin plotting library not available'
            return

        maxminx = numerix.sort(
            numerix.ravel(self.cntrl[0, :, :]) /
            numerix.ravel(self.cntrl[3, :, :]))
        minx = maxminx[0]
        maxx = maxminx[-1]
        if minx == maxx:
            minx -= 1.
            maxx += 1.

        maxminy = numerix.sort(
            numerix.ravel(self.cntrl[1, :, :]) /
            numerix.ravel(self.cntrl[3, :, :]))
        miny = maxminy[0]
        maxy = maxminy[-1]
        if miny == maxy:
            miny -= 1.
            maxy += 1.

        maxminz = numerix.sort(
            numerix.ravel(self.cntrl[2, :, :]) /
            numerix.ravel(self.cntrl[3, :, :]))
        minz = maxminz[0]
        maxz = maxminz[-1]
        if minz == maxz:
            minz -= 1.
            maxz += 1.

        dislin.metafl('cons')
        dislin.disini()
        dislin.hwfont()
        dislin.pagera()
        dislin.name('X-axis', 'X')
        dislin.name('Y-axis', 'Y')
        dislin.name('Z-axis', 'Z')
        dislin.graf3d(minx, maxx, 0, abs((maxx - minx) / 4.), miny, maxy, 0,
                      abs((maxy - miny) / 4.), minz, maxz, 0,
                      abs((maxz - minz) / 4.))

        dislin.color('yellow')
        pnts0 = self.pnt3D([
            numerix.arange(n + 1, typecode=numerix.Float) / n,
            numerix.zeros(n + 1, numerix.Float)
        ])
        pnts1 = self.pnt3D([
            numerix.arange(n + 1, typecode=numerix.Float) / n,
            numerix.ones(n + 1, numerix.Float)
        ])
        pnts2 = self.pnt3D([
            numerix.zeros(n + 1, numerix.Float),
            numerix.arange(n + 1, typecode=numerix.Float) / n
        ])
        pnts3 = self.pnt3D([
            numerix.ones(n + 1, numerix.Float),
            numerix.arange(n + 1, typecode=numerix.Float) / n
        ])
        dislin.curv3d(pnts0[0, :], pnts0[1, :], pnts0[2, :], n + 1)
        dislin.curv3d(pnts1[0, :], pnts1[1, :], pnts1[2, :], n + 1)
        dislin.curv3d(pnts2[0, :], pnts2[1, :], pnts2[2, :], n + 1)
        dislin.curv3d(pnts3[0, :], pnts3[1, :], pnts3[2, :], n + 1)

        dislin.color('red')
        step = 1. / iso
        for uv in numerix.arange(step, 1., step):
            pnts = self.pnt3D([
                numerix.arange(n + 1, typecode=numerix.Float) / n,
                numerix.zeros(n + 1, numerix.Float) + uv
            ])
            dislin.curv3d(pnts[0, :], pnts[1, :], pnts[2, :], n + 1)
            pnts = self.pnt3D([
                numerix.zeros(n + 1, numerix.Float) + uv,
                numerix.arange(n + 1, typecode=numerix.Float) / n
            ])
            dislin.curv3d(pnts[0, :], pnts[1, :], pnts[2, :], n + 1)

        dislin.disfin()
Пример #7
0
class Crv:
    '''Construct a NURB curve and check the format.
    
 The NURB curve is represented by a 4 dimensional b-spline.

 INPUT:

    cntrl  - Control points, homogeneous coordinates (wx,wy,wz,w)
            [dim,nu] matrix
            dim is the dimension valid options are:
            2 .... (x,y)        2D cartesian coordinates
            3 .... (x,y,z)      3D cartesian coordinates   
            4 .... (wx,wy,wz,w) 4D homogeneous coordinates

    uknots - Knot sequence along the parametric u direction.

 NOTES:

    Its assumed that the input knot sequences span the
    interval [0.0,1.0] and are clamped to the control
    points at the end by a knot multiplicity equal to
    the spline order.'''

    def __init__(self, cntrl, uknots):
        self._bezier = None
        # Force the u knot sequence to be a vector in ascending order
        # and normalise between [0.0,1.0]
        uknots = np.sort(np.asarray(uknots, np.float))
        nku = uknots.shape[0]
        uknots = (uknots - uknots[0])/(uknots[-1] - uknots[0])
        if uknots[0] == uknots[-1]:
            raise NURBSError, 'Illegal uknots sequence'
        self.uknots = uknots
        cntrl = np.asarray(cntrl, np.float)
        (dim, nu) = cntrl.shape
        if dim < 2 or dim > 4:
            raise NURBSError, 'Illegal control point format'
        elif dim < 4:
            self.cntrl = np.zeros((4, nu), np.float)
            self.cntrl[0:dim,:] = cntrl
            self.cntrl[-1,:] = np.ones((nu,))
        else:
            self.cntrl = cntrl
        # Spline degree
        self.degree = nku - nu - 1
        if self.degree < 0:
            raise NURBSError, 'NURBS order must be a positive integer'

    def trans(self, mat):
        "Apply the 4D transform matrix to the NURB control points."
        self.cntrl = np.dot(mat, self.cntrl)

    def reverse(self):
        "Reverse evaluation direction"
        self.cntrl = self.cntrl[:,::-1]
        self.uknots = 1 - self.uknots[::-1]
        
    def kntins(self, uknots):
        """Insert new knots into the curve
	NOTE: No knot multiplicity will be increased beyond the order of the spline"""
        if len(uknots):
            uknots = np.sort(np.asarray(uknots, np.float))
            if np.less(uknots, 0.) or np.greater(uknots, 1.):
                raise NURBSError, 'NURBS curve parameter out of range [0,1]'
            self.cntrl, self.uknots = bspkntins(self.degree, self.cntrl, self.uknots, uknots)

    def degelev(self, degree):
        "Degree elevate the curve"
        if degree < 0:
            raise NURBSError, 'degree must be a positive number'
        if degree > 0:
            cntrl, uknots, nh = bspdegelev(self.degree, self.cntrl, self.uknots, degree)
            self.cntrl = cntrl[:,:nh + 1]
            self.uknots = uknots[:nh + self.degree + degree + 2]
            self.degree += degree

    def bezier(self, update = None):
        "Decompose curve to bezier segments and return overlaping control points"
        if update or not self._bezier:
            self._bezier = bspbezdecom(self.degree, self.cntrl, self.uknots)
        return self._bezier

    def bounds(self):
        "Return the boundingbox for the curve"
        ww = np.resize(self.cntrl[-1,:], (3, self.cntrl.shape[1]))
        cntrl = np.sort(self.cntrl[0:3,:]/ww)
        return np.asarray([cntrl[0,0], cntrl[1,0], cntrl[2,0],
                                cntrl[0,-1], cntrl[1,-1], cntrl[2,-1]], np.float)
                                
    def pnt3D(self, ut):
        "Evaluate parametric point[s] and return 3D cartesian coordinate[s]"
        val = self.pnt4D(ut)
        return val[0:3,:]/np.resize(val[-1,:], (3, val.shape[1]))

    def pnt4D(self, ut):
        "Evaluate parametric point[s] and return 4D homogeneous coordinates"
        ut = np.asarray(ut, np.float)
        if np.less(ut, 0.) or np.greater(ut, 1.):
            raise NURBSError, 'NURBS curve parameter out of range [0,1]'
        return bspeval(self.degree, self.cntrl, self.uknots, ut)
                
    def plot(self, n = 25):
        """A simple plotting function for debugging purpose
	n = number of subdivisions.
	Depends on the dislin plotting library."""
        try:
            import dislin
        except ImportError, value:
            print 'dislin plotting library not available'
            return

        pnts = self.pnt3D(np.arange(n + 1, typecode = np.float)/n)
        knots = self.pnt3D(self.uknots)

        maxminx = np.sort(self.cntrl[0,:]/self.cntrl[3,:])
        minx = maxminx[0]
        maxx = maxminx[-1]
        if minx == maxx:
            minx -= 1.
            maxx += 1.
        maxminy = np.sort(self.cntrl[1,:]/self.cntrl[3,:])
        miny = maxminy[0]
        maxy = maxminy[-1]
        if miny == maxy:
            miny -= 1.
            maxy += 1.
        maxminz = np.sort(self.cntrl[2,:]/self.cntrl[3,:])
        minz = maxminz[0]
        maxz = maxminz[-1]
        if minz == maxz:
            minz -= 1.
            maxz += 1.
            
        dislin.metafl('cons')
        dislin.disini()
        dislin.hwfont()
        dislin.pagera()
        dislin.name('X-axis', 'X')
        dislin.name('Y-axis', 'Y')
        dislin.name('Z-axis', 'Z')
        dislin.graf3d(minx, maxx, 0 , abs((maxx-minx)/4.),
                      miny, maxy, 0 , abs((maxy-miny)/4.),
                      minz, maxz, 0 , abs((maxz-minz)/4.))
        dislin.color('yellow')
        dislin.curv3d(pnts[0,:], pnts[1,:], pnts[2,:], n+1)
        dislin.color('red')
        dislin.dashm()
        dislin.curv3d(self.cntrl[0,:]/self.cntrl[3,:], self.cntrl[1,:]/self.cntrl[3,:],
                      self.cntrl[2,:]/self.cntrl[3,:], self.cntrl.shape[1])
        dislin.color('white')
        dislin.incmrk(-1)
        dislin.marker(8)
        dislin.curv3d(knots[0,:], knots[1,:], knots[2,:], knots.shape[1])
        dislin.disfin()