Exemplo n.º 1
0
 def SetPoints(self, points):
     """ SetPoints(points)
     
     Set x,y (and optionally z) data. The given argument can be anything
     that can be converted to a pointset. (From version 1.7 this method
     also works with 2D pointsets.)
     
     The data is copied, so changes to original data will not affect 
     the visualized points. If you do want this, use the points property.
     
     """
     
     # Try make it a (copied) pointset (handle masked array)
     if is_Pointset(points):
         points = Pointset(handleInvalidValues(points.data))
     else:
         points = Pointset(handleInvalidValues(points))
    
     # Add z dimension to points if not available
     if points.ndim == 2:
         tmp = points._data, 0.1*np.ones((len(points._data),1), dtype='float32')
         points._data = np.concatenate(tmp,1)
     
     # Store
     self._points = points
Exemplo n.º 2
0
    def _GetLimits(self, *args):
        """ _GetLimits(self, x1, x2, y1, y2, z1, z2)
        
        Get the limits in world coordinates between which the object 
        exists. This is used by the Axes class to set the camera correctly.
        If None is returned, the limits are undefined. 
        
        Inheriting Wobject classes should overload this method. However, they
        can use this method to take all transformations into account by giving
        the cornerpoints of the untransformed object. 
        
        Returns a 3 element tuple of vv.Range instances: xlim, ylim, zlim.
        
        """

        # Examine args
        if not args:
            minx, maxx, miny, maxy, minz, maxz = [], [], [], [], [], []
        elif len(args) == 6:
            minx, maxx, miny, maxy, minz, maxz = tuple([[arg] for arg in args])
        else:
            raise ValueError("_Getlimits expects 0 or 6 arguments.")

        # Get limits of children
        for ob in self.children:
            tmp = ob._GetLimits()
            if tmp is not None:
                limx, limy, limz = tmp
                minx.append(limx.min)
                maxx.append(limx.max)
                miny.append(limy.min)
                maxy.append(limy.max)
                minz.append(limz.min)
                maxz.append(limz.max)

        # Do we have limits?
        if not (minx and maxx and miny and maxy and minz and maxz):
            return None

        # Take min and max
        x1, y1, z1 = tuple([min(val) for val in [minx, miny, minz]])
        x2, y2, z2 = tuple([max(val) for val in [maxx, maxy, maxz]])

        # Make pointset of eight cornerpoints
        pp = Pointset(3)
        for x in [x1, x2]:
            for y in [y1, y2]:
                for z in [z1, z2]:
                    pp.append(x, y, z)

        # Transform these points
        for i in range(len(pp)):
            pp[i] = self.TransformPoint(pp[i], self)

        # Return limits
        xlim = misc.Range(pp[:, 0].min(), pp[:, 0].max())
        ylim = misc.Range(pp[:, 1].min(), pp[:, 1].max())
        zlim = misc.Range(pp[:, 2].min(), pp[:, 2].max())
        return xlim, ylim, zlim
Exemplo n.º 3
0
def getSphere(ndiv=3, radius=1.0):
    # Example taken from the Red book, end of chaper 2.
    
    # Define constants
    X = 0.525731112119133606 
    Z = 0.850650808352039932
    
    # Creta vdata
    vdata = Pointset(3)
    app = vdata.append
    app(-X, 0.0, Z); app(X, 0.0, Z); app(-X, 0.0, -Z); app(X, 0.0, -Z)
    app(0.0, Z, X); app(0.0, Z, -X); app(0.0, -Z, X); app(0.0, -Z, -X)
    app(Z, X, 0.0); app(-Z, X, 0.0); app(Z, -X, 0.0); app(-Z, -X, 0.0)
    
    # Create faces
    tindices = [
        [0,4,1], [0,9,4], [9,5,4], [4,5,8], [4,8,1],    
        [8,10,1], [8,3,10], [5,3,8], [5,2,3], [2,7,3],    
        [7,10,3], [7,6,10], [7,11,6], [11,0,6], [0,1,6], 
        [6,1,10], [9,0,11], [9,11,2], [9,2,5], [7,2,11] ]
    tindices = np.array(tindices, dtype=np.uint32)
    
    # Init vertex array
    vertices = Pointset(3)
    
    # Define function to recursively create vertices and normals
    def drawtri(a, b, c, div):
        if (div<=0):
            vertices.append(a)
            vertices.append(b)
            vertices.append(c)
        else:
            ab = Point(0,0,0)
            ac = Point(0,0,0)
            bc = Point(0,0,0)
            for i in range(3):
                ab[i]=(a[i]+b[i])/2.0;
                ac[i]=(a[i]+c[i])/2.0;
                bc[i]=(b[i]+c[i])/2.0;
            ab = ab.normalize(); ac = ac.normalize(); bc = bc.normalize()
            drawtri(a, ab, ac, div-1)
            drawtri(b, bc, ab, div-1)
            drawtri(c, ac, bc, div-1)
            drawtri(ab, bc, ac, div-1)
    
    # Create vertices
    for i in range(20):
        drawtri(    vdata[int(tindices[i][0])], 
                    vdata[int(tindices[i][1])], 
                    vdata[int(tindices[i][2])], 
                    ndiv )
    
    # Create normals and scale vertices
    normals = vertices.copy()
    vertices *= radius
    
    # Done
    return vertices, normals
Exemplo n.º 4
0
 def _GetLimits(self, *args):
     """ _GetLimits(self, x1, x2, y1, y2, z1, z2)
     
     Get the limits in world coordinates between which the object 
     exists. This is used by the Axes class to set the camera correctly.
     If None is returned, the limits are undefined. 
     
     Inheriting Wobject classes should overload this method. However, they
     can use this method to take all transformations into account by giving
     the cornerpoints of the untransformed object. 
     
     Returns a 3 element tuple of vv.Range instances: xlim, ylim, zlim.
     
     """
     
     # Examine args
     if not args:
         minx, maxx, miny, maxy, minz, maxz = [], [], [], [], [], []            
     elif len(args) == 6:
         minx, maxx, miny, maxy, minz, maxz = tuple([[arg] for arg in args])
     else:
         raise ValueError("_Getlimits expects 0 or 6 arguments.")
     
     # Get limits of children
     for ob in self.children:
         tmp = ob._GetLimits()
         if tmp is not None:
             limx, limy, limz = tmp
             minx.append(limx.min); maxx.append(limx.max)
             miny.append(limy.min); maxy.append(limy.max)
             minz.append(limz.min); maxz.append(limz.max)
     
     # Do we have limits?
     if not (minx and maxx and miny and maxy and minz and maxz):
         return None
     
     # Take min and max
     x1, y1, z1 = tuple([min(val) for val in [minx, miny, minz]])
     x2, y2, z2 = tuple([max(val) for val in [maxx, maxy, maxz]])
     
     # Make pointset of eight cornerpoints
     pp = Pointset(3)
     for x in [x1, x2]:
         for y in [y1, y2]:
             for z in [z1, z2]:
                 pp.append(x,y,z)
     
     # Transform these points
     for i in range(len(pp)):
         pp[i] = self.TransformPoint(pp[i], self)
     
     # Return limits
     xlim = misc.Range( pp[:,0].min(), pp[:,0].max() )
     ylim = misc.Range( pp[:,1].min(), pp[:,1].max() )
     zlim = misc.Range( pp[:,2].min(), pp[:,2].max() )
     return xlim, ylim, zlim
Exemplo n.º 5
0
 def partition(tex_coord1, ver_coord1):
     tex_coord2, ver_coord2 = Pointset(3), Pointset(3)
     for iQuad in range(int(len(tex_coord1)/4)):
         io = iQuad * 4
         for i1 in range(4):
             for i2 in range(4):
                 i3 = (i1 + i2)%4                    
                 tex_coord2.append( 0.5*(tex_coord1[io+i1] + tex_coord1[io+i3]) )
                 ver_coord2.append( 0.5*(ver_coord1[io+i1] + ver_coord1[io+i3]) )
     #print('partition from %i to %i vertices' % (len(tex_coord1), len(tex_coord2)))
     return tex_coord2, ver_coord2
Exemplo n.º 6
0
 def partition(tex_coord1, ver_coord1):
     tex_coord2, ver_coord2 = Pointset(3), Pointset(3)
     for iQuad in range(int(len(tex_coord1)/4)):
         io = iQuad * 4
         for i1 in range(4):
             for i2 in range(4):
                 i3 = (i1 + i2)%4                    
                 tex_coord2.append( 0.5*(tex_coord1[io+i1] + tex_coord1[io+i3]) )
                 ver_coord2.append( 0.5*(ver_coord1[io+i1] + ver_coord1[io+i3]) )
     #print('partition from %i to %i vertices' % (len(tex_coord1), len(tex_coord2)))
     return tex_coord2, ver_coord2
Exemplo n.º 7
0
 def draw_arcs(ax, level, color=(1, 1, 0)):
     arcs = mesh.get_arcs()
     for arc in arcs:
         Y, X = np.transpose(arc)
         Z = np.ones(len(X)) * level
         pp = Pointset(np.transpose([X, Y, Z]))
         vv.plot(pp, lw=1, lc=color, alpha=0.5, ls='-', mew=0, axes=ax)
Exemplo n.º 8
0
def ginput(N=0, axes=None, ms='+', **kwargs):
    """ ginput(N=0, axes=None, ms='+', **kwargs)
    
    Graphical input: select N number of points with the mouse.
    Returns a 2D pointset.
    
    Parameters
    ----------
    N : int
        The maximum number of points to capture. If N=0, will keep capturing
        until the user stops it. The capturing always stops when enter is
        pressed or the mouse is double clicked. In the latter case a final
        point is added.
    axes : Axes instance
        The axes to capture the points in, or the current axes if not given.
    ms : markerStyle
        The marker style to use for the points. See plot.
    
    Any other keyword arguments are passed to plot to show the selected
    points and the lines between them.
    
    """

    # Get axes
    if not axes:
        axes = vv.gca()

    # Get figure
    fig = axes.GetFigure()
    if not fig:
        return

    # Init pointset, helper, and line object
    line = vv.plot(Pointset(2), axes=axes, ms=ms, **kwargs)
    pp = line._points
    ginputHelper.Start(axes, pp, N)

    # Enter a loop
    while ginputHelper.axes:
        fig._ProcessGuiEvents()
        time.sleep(0.1)

    # Remove line object and return points
    pp = Pointset(pp[:, :2])
    line.Destroy()
    return pp
Exemplo n.º 9
0
    def _SliderCalcDots(self, event=None):

        # Init dots
        dots1, dots2 = Pointset(2), Pointset(2)

        # Get width height
        w, h = self.position.size

        # Fill pointsets
        if w > h:
            i = 5
            while i < h - 5:
                dots1.append(2, i)
                dots1.append(5, i)
                dots2.append(-2, i)
                dots2.append(-5, i)
                i += 3
        else:
            i = 5
            while i < w - 5:
                dots1.append(i, 2)
                dots1.append(i, 5)
                dots2.append(i, -2)
                dots2.append(i, -5)
                i += 3

        self._dots1, self._dots2 = dots1, dots2
Exemplo n.º 10
0
 def __init__(self, parent, angs, mags):
     self._angs = angs
     self._mags = mags
     x = mags * np.cos(angs)
     y = mags * np.sin(angs)
     z = np.zeros((np.size(x), 1))
     tmp = x, y, z
     pp = Pointset(np.concatenate(tmp, 1))
     Line.__init__(self, parent, pp)
Exemplo n.º 11
0
    def draw_smoothed_path(ax,
                           pth,
                           radius=1,
                           color=(1, 0, 0),
                           draw_source=False):
        x, y, z = np.transpose(pth)
        if draw_source:
            vv.plot(x, y, z, '--r', axes=ax)
        z_converted = list(map(j.levels.__getitem__,
                               z))  # Переводим координату в уровень
        tck, u = sip.splprep([x, y, z_converted], k=3)
        new_p = sip.splev(np.linspace(0, 1, 200), tck)

        pp = Pointset(3)
        for pt in np.transpose(new_p):
            pp.append((pt[0], pt[1], pt[2]))

        #     line = vv.solidLine(pp, radius, 8, axes=ax)
        #     line = vv.line(pp, radius, 8, axes=ax)
        vv.plot(pp, lw=3, lc=color, alpha=1, ls='-')
Exemplo n.º 12
0
 def _AddLineAndLabel(self, text, yspacing=1.0, twoPoints=True):
     """ Add a line and label to our pool. """
     # get y position
     index = len(self._wobjects)
     y = self._yoffset + yspacing * (index)        
     # create label
     label = Label(self, text)
     label.bgcolor = ''        
     label.position = self._xoffset*2 + twoPoints*self._linelen, y
     deltax, deltay = label.GetVertexLimits()
     #y2 = label.position.h / 2
     y2 = (deltay[1] + deltay[0]) / 2 
     # create 2-element pointset
     pp = Pointset(2)        
     pp.append(self._xoffset, y + y2)
     if twoPoints:
         pp.append(self._xoffset + self._linelen, y + y2)
     # create line
     line = Line(self, pp) # line has no parent        
     # return
     return line, label
Exemplo n.º 13
0
 def TransformPolar(self, radialRange, angRefPos, sense):
     offsetMags = self._mags - radialRange.min
     rangeMags = radialRange.range
     offsetMags[offsetMags > rangeMags] = rangeMags
     tmpang = angRefPos + sense * self._angs
     x = offsetMags * np.cos(tmpang)
     y = offsetMags * np.sin(tmpang)
     z = np.zeros((np.size(x), 1)) + 0.2
     x[offsetMags < 0] = 0
     y[offsetMags < 0] = 0
     tmp = x, y, z
     self._points = Pointset(np.concatenate(tmp, 1))
Exemplo n.º 14
0
 def __init__(self, parent):
     Box.__init__(self, parent)
     
     # Set color
     self.bgcolor = 'w'
     
     # How soon the mouse snaps to a node
     self._snapWidth = 5
     
     # The currently selected node (or None if nothing is selected)
     self._selectedNode = None
     
     # The nodes and lines of R,G,B and A
     self._allNodes = [Pointset(2) for i in range(4)]
     self._allLines = [Pointset(2) for i in range(4)]
     
     # Init nodes
     for nodes in self._allNodes:
         nodes.append(0,1)
         nodes.append(1,0)
     self._allNodes[3][0,1] = 0 # alpha is completele ones by default
     
     # Init lines
     for line in self._allLines:
         for i in np.linspace(0,1,256):
             line.append(i,1) # the actual map will be 1-line
     
     # Make lines correct now
     for nodes, line in zip(self._allNodes, self._allLines):
         self._NodesToLine(nodes, line)
     
     # The node and line currently in control
     self._nodes = self._allNodes[3]
     self._line = self._allLines[3] 
     
     # Bind events
     self.eventMotion.Bind(self._OnMotion)
     self.eventMouseUp.Bind(self._OnUp)
     self.eventMouseDown.Bind(self._OnDown)
     self.eventDoubleClick.Bind(self._OnDoubleClick)
Exemplo n.º 15
0
    def SetPoints(self, points):
        """ SetPoints(points)
        
        Set x,y (and optionally z) data. The given argument can be anything
        that can be converted to a pointset. (From version 1.7 this method
        also works with 2D pointsets.)
        
        The data is copied, so changes to original data will not affect
        the visualized points. If you do want this, use the points property.
        
        """

        # Try make it a (copied) pointset (handle masked array)
        if is_Pointset(points):
            points = Pointset(handleInvalidValues(points.data))
        else:
            points = Pointset(handleInvalidValues(points))

        # Add z dimension to points if not available
        if points.ndim == 3:
            pass
        elif points.ndim == 2:
            zz = 0.1 * np.ones((len(points._data), 1), dtype='float32')
            points._data = np.concatenate((points._data, zz), 1)
        elif points.ndim == 1:
            N = len(points._data)
            xx = np.arange(N, dtype='float32').reshape(N, 1)
            zz = 0.1 * np.ones((N, 1), dtype='float32')
            points._data = np.concatenate((xx, points._data, zz), 1)

        # Store
        self._points = points
Exemplo n.º 16
0
def getCircle(angles_cos, angles_sin, a, b):
    """ getCircle(angles_cos, angles_sin, a, b) -> circle_cords
    
    Creates a circle of points around the origin,
    the circle is spanned by the vectors a and b.
    
    """
    X = np.empty((len(angles_cos), 3), dtype=np.float32)
    X[:, 0] = angles_cos * a.x + angles_sin * b.x
    X[:, 1] = angles_cos * a.y + angles_sin * b.y
    X[:, 2] = angles_cos * a.z + angles_sin * b.z

    return Pointset(X)
Exemplo n.º 17
0
 def _NodesToLine(self, nodes, line, update=False):
     """ Convert nodes to a full 256 element line.
     """
     
     # sort nodes
     nn = [n for n in nodes]
     nn.sort(key=lambda n:n.x)
     nodes = Pointset(2)
     for n in nn:
         nodes.append(n)
     
     # interpolate
     xx = np.linspace(0,1,256)
     if nodes:
         yy = np.interp(xx, nodes[:,0], nodes[:,1])
         if np.isnan(yy[-1]): # happens when last two nodes on same pos
             yy[-1] = yy[-2]
         line[:,1] = yy
     else:
         line[:,1] = np.zeros((256,),dtype=np.float32) # no nodes
     
     if update:
         # Create colormap
         map = {}
         for i in range(4):            
             nn = self._allNodes[i]
             tmp = []
             for ii in range(len(nn)):
                 tmp.append((nn[ii,0], 1-nn[ii,1]))
             if tmp:
                 key = 'rgba'[i]
                 map[key] = sorted(tmp, key=lambda x:x[0])
         
         # Apply colormap to all registered objects
         if self.parent:
             for ob in self.parent.GetMapables():
                 ob._SetColormap(map)
                 ob.Draw()
Exemplo n.º 18
0
 def _SliderCalcDots(self, event=None):
     
     # Init dots
     dots1, dots2 = Pointset(2), Pointset(2)
     
     # Get width height
     w,h = self.position.size
     
     # Fill pointsets
     if w > h:
         i = 5
         while i < h-5:
             dots1.append(2,i); dots1.append(5,i)
             dots2.append(-2,i); dots2.append(-5,i)
             i += 3
     else:
         i = 5
         while i < w-5:
             dots1.append(i,2); dots1.append(i,5)
             dots2.append(i,-2); dots2.append(i,-5)
             i += 3
     
     self._dots1, self._dots2 = dots1, dots2
Exemplo n.º 19
0
 def _AddLineAndLabel(self, text, yspacing=1.0, twoPoints=True):
     """ Add a line and label to our pool. """
     # get y position
     index = len(self._wobjects)
     y = self._yoffset + yspacing * (index)
     # create label
     label = Label(self, text)
     label.bgcolor = ''
     label.position = self._xoffset * 2 + twoPoints * self._linelen, y
     deltax, deltay = label.GetVertexLimits()
     #y2 = label.position.h / 2
     y2 = (deltay[1] + deltay[0]) / 2
     # create 2-element pointset
     pp = Pointset(2)
     pp.append(self._xoffset, y + y2)
     if twoPoints:
         pp.append(self._xoffset + self._linelen, y + y2)
     # create line
     line = Line(self, pp)  # line has no parent
     # return
     return line, label
Exemplo n.º 20
0
def plot(data1, data2=None, data3=None,
            lw=1, lc='b', ls="-", mw=7, mc='b', ms='', mew=1, mec='k',
            alpha=1, axesAdjust=True, axes=None, **kwargs):
    """ plot(*args, lw=1, lc='b', ls="-", mw=7, mc='b', ms='', mew=1, mec='k',
            alpha=1, axesAdjust=True, axes=None):
    
    Plot 1, 2 or 3 dimensional data and return the Line object.
    
    Usage
    -----
      * plot(Y, ...) plots a 1D signal, with the values plotted along the y-axis
      * plot(X, Y, ...) also supplies x coordinates
      * plot(X, Y, Z, ...) also supplies z coordinates
      * plot(P, ...) plots using a Point or Pointset instance
    
    Keyword arguments
    -----------------
    (The longer names for the line properties can also be used)
    lw : scalar
        lineWidth. The width of the line. If zero, no line is drawn.
    mw : scalar
        markerWidth. The width of the marker. If zero, no marker is drawn.
    mew : scalar
        markerEdgeWidth. The width of the edge of the marker.
    lc : 3-element tuple or char
        lineColor. The color of the line. A tuple should represent the RGB
        values between 0 and 1. If a char is given it must be
        one of 'rgbmcywk', for reg, green, blue, magenta, cyan, yellow,
        white, black, respectively.
    mc : 3-element tuple or char
        markerColor. The color of the marker. See lineColor.
    mec : 3-element tuple or char
        markerEdgeColor. The color of the edge of the marker.
    ls : string
        lineStyle. The style of the line. (See below)
    ms : string
        markerStyle. The style of the marker. (See below)
    axesAdjust : bool
        If axesAdjust==True, this function will call axes.SetLimits(), set
        the camera type to 2D when plotting 2D data and to 3D when plotting
        3D data. If daspectAuto has not been set yet, it is set to True.
    axes : Axes instance
        Display the image in this axes, or the current axes if not given.
    
    Line styles
    -----------
      * Solid line: '-'
      * Dotted line: ':'
      * Dashed line: '--'
      * Dash-dot line: '-.' or '.-'
      * A line that is drawn between each pair of points: '+'
      * No line: '' or None.
    
    Marker styles
    -------------
      * Plus: '+'
      * Cross: 'x'
      * Square: 's'
      * Diamond: 'd'
      * Triangle (pointing up, down, left, right): '^', 'v', '<', '>'
      * Pentagram star: 'p' or '*'
      * Hexgram: 'h'
      * Point/cirle: 'o' or '.'
      * No marker: '' or None
    
    """
    
    # create a dict from the properties and combine with kwargs
    tmp     = { 'lineWidth':lw,         'lineColor':lc,     'lineStyle':ls,
                'markerWidth':mw,       'markerColor':mc,   'markerStyle':ms,
                'markerEdgeWidth':mew,  'markerEdgeColor':mec}
    for i in tmp:
        if not i in kwargs:
            kwargs[i] = tmp[i]
    
    # init dimension variable
    camDim = 0
    
    ##  create the data
    
    # If one argument is given, and it looks like a pointset stored
    # in a numpy array, use it as such
    if isinstance(data1, np.ndarray) and (data2 is None) and (data3 is None):
        if data1.ndim == 2 and data1.shape[1] in (2,3):
            data1 = Pointset(data1)  # Use shape as given
    
    if is_Pointset(data1):
        pp = data1
    elif is_Point(data1):
        pp = Pointset(data1.ndim)
        pp.append(data1)
    else:
        if data1 is None:
            raise Exception("The first argument cannot be None!")
        data1 = np.asanyarray(data1)
        
        d3 = data3
        if data3 is None:
            data3 = 0.1*np.ones(data1.shape)
            camDim = 2
        else:
            camDim = 3
            data3 = np.asanyarray(data3)
        
        if data2 is None:
            if d3 is not None:
                tmp = "third argument in plot() ignored, as second not given."
                print("Warning: " + tmp)
            # y data is given, xdata must be a range starting from 1
            data2 = data1
            data1 = np.arange(1,data2.shape[0]+1)
            data3 = 0.1*np.ones(data2.shape)
        else:
            data2 = np.asanyarray(data2)
        
        # check dimensions
        L = data1.size
        if L != data2.size or L != data3.size:
            raise Exception("Array dimensions do not match! %i vs %i vs %i" %
                    (data1.size, data2.size, data3.size))
        
        # build points
        data1 = data1.reshape((data1.size,1))
        data2 = data2.reshape((data2.size,1))
        data3 = data3.reshape((data3.size,1))
        
        # Concatenate to a single Nx3 array (take care of masked arrays)
        tmp = data1, data2, data3
        if any([isinstance(d, np.ma.MaskedArray) for d in tmp]):
            pp = np.ma.concatenate(tmp, 1)
        else:
            pp = np.concatenate(tmp, 1)
        
    
    # Process camdim for given points or pointsets
    if not camDim:
        camDim = max(2, pp.ndim)
        
    
    ## create the line
    if axes is None:
        axes = vv.gca()
    l = vv.Line(axes, pp)
    l.lw = kwargs['lineWidth']
    l.lc = kwargs['lineColor']
    l.ls = kwargs['lineStyle']
    l.mw = kwargs['markerWidth']
    l.mc = kwargs['markerColor']
    l.ms = kwargs['markerStyle']
    l.mew = kwargs['markerEdgeWidth']
    l.mec = kwargs['markerEdgeColor']
    l.alpha = alpha
    
    ## done...
    if axesAdjust:
        if axes.daspectAuto is None:
            axes.daspectAuto = True
        axes.cameraType = str(camDim)+'d'
        axes.SetLimits()
    
    axes.Draw()
    return l
Exemplo n.º 21
0
 def _GetCords(self):
     """ _GetCords()
     Get a pointset of the coordinates of the wobject. This is used
     for drawing the quads and lines using a vertex array. 
     """
     
     # Can we reuse buffered coordinates?
     if self._cordsBuffer is not None:
         return self._cordsBuffer
     
     # Get ranges in world coords
     rangex, rangey = self._GetRangesInWorldCords()
     
     # Project two points to use in OnDrawScreen
     screen1 = glu.gluProject(rangex.min, rangey.min, 0)
     screen2 = glu.gluProject(rangex.max, rangey.max, 0)
     
     # Calculate world-distance of a screendistance of self._barwidth
     # and then do drawing here (not in OnDrawScreen), otherwise I won't
     # be able to detect picking!!
     onePixelx = rangex.range / ( screen2[0] - screen1[0] ) 
     onePixely = rangey.range / ( screen2[1] - screen1[1] ) 
     
     # Get coords
     tmp = self._barWidth
     x1, x2, xd = rangex.min, rangex.max, onePixelx*tmp
     y1, y2, yd = rangey.min, rangey.max, onePixely*tmp
     if yd<0:
         y1, y2 = y2, y1 # axis flipped
     
     # Definition of the coordinate indices:
     #
     # 12 11      10 15
     #  4 0 ----- 3 9
     #    |       |
     #    |       |
     #  5 1------ 2 8
     # 13 6       7 14
     #
     
     # Make coords
     pp = Pointset(2)
     #
     pp.append(x1, y1)
     pp.append(x1, y2)
     pp.append(x2, y2)
     pp.append(x2, y1)
     #
     pp.append(x1-xd, y1)
     pp.append(x1-xd, y2)
     pp.append(x1, y2+yd)
     pp.append(x2, y2+yd)
     #
     pp.append(x2+xd, y2)
     pp.append(x2+xd, y1)
     pp.append(x2, y1-yd)
     pp.append(x1, y1-yd)
     #
     pp.append(x1-xd, y1-yd)
     pp.append(x1-xd, y2+yd)
     pp.append(x2+xd, y2+yd)
     pp.append(x2+xd, y1-yd)
     
     # Done
     self._cordsBuffer = pp
     return pp
Exemplo n.º 22
0
def solidBox(translation=None, scaling=None, direction=None, rotation=None,
                axesAdjust=True, axes=None):
    """ solidBox(translation=None, scaling=None, direction=None, rotation=None,
                    axesAdjust=True, axes=None)
    
    Creates a solid cube (or box if you scale it) centered at the 
    origin. Returns an OrientableMesh.
    
    Parameters
    ----------
    Note that translation, scaling, and direction can also be given
    using a Point instance.
    translation : (dx, dy, dz), optional
        The translation in world units of the created world object.
    scaling: (sx, sy, sz), optional
        The scaling in world units of the created world object.
    direction: (nx, ny, nz), optional
        Normal vector that indicates the direction of the created world object.
    rotation: scalar, optional
        The anle (in degrees) to rotate the created world object around its
        direction vector.
    axesAdjust : bool
        If True, this function will call axes.SetLimits(), and set
        the camera type to 3D. If daspectAuto has not been set yet, 
        it is set to False.
    axes : Axes instance
        Display the bars in the given axes, or the current axes if not given.
    
    """
    
    # Create vertices of a cube
    pp = Pointset(3)
    # Bottom
    pp.append(-0.5,-0.5,-0.5)
    pp.append(+0.5,-0.5,-0.5)
    pp.append(+0.5,+0.5,-0.5)
    pp.append(-0.5,+0.5,-0.5)
    # Top
    pp.append(-0.5,-0.5,+0.5)
    pp.append(-0.5,+0.5,+0.5)
    pp.append(+0.5,+0.5,+0.5)
    pp.append(+0.5,-0.5,+0.5)
    
    # Init vertices and normals
    vertices = Pointset(3)
    normals = Pointset(3)
    
    # Create vertices
    for i in [3,2,1,0]: # Top
        vertices.append(pp[i]); normals.append(0,0,-1)
    for i in [7,6,5,4]: # Bottom
        vertices.append(pp[i]); normals.append(0,0,+1)
    for i in [5,6,2,3]: # Front
        vertices.append(pp[i]); normals.append(0,+1,0)
    for i in [1,7,4,0]: # Back
        vertices.append(pp[i]); normals.append(0,-1,0)
    for i in [4,5,3,0]: # Left
        vertices.append(pp[i]); normals.append(-1,0,0)
    for i in [2,6,7,1]: # Right
        vertices.append(pp[i]); normals.append(+1,0,0)
    
    
    ## Visualize
    
    # Create axes
    if axes is None:
        axes = vv.gca()
    
    # Create mesh and set orientation
    m = vv.OrientableMesh(axes, vertices, None, normals, verticesPerFace=4)
    #
    if translation is not None:
        m.translation = translation
    if scaling is not None:
        m.scaling = scaling
    if direction is not None:
        m.direction = direction
    if rotation is not None:
        m.rotation = rotation
    
    # Adjust axes
    if axesAdjust:
        if axes.daspectAuto is None:
            axes.daspectAuto = False
        axes.cameraType = '3d'
        axes.SetLimits()
    
    # Done
    axes.Draw()
    return m
Exemplo n.º 23
0
def getSphereWithFaces(ndiv=3, radius=1.0):
    # Example taken from the Red book, end of chaper 2.
    
    # Define constants
    X = 0.525731112119133606 
    Z = 0.850650808352039932
    
    # Creta vdata
    vdata = Pointset(3)
    app = vdata.append
    app(-X, 0.0, Z); app(X, 0.0, Z); app(-X, 0.0, -Z); app(X, 0.0, -Z)
    app(0.0, Z, X); app(0.0, Z, -X); app(0.0, -Z, X); app(0.0, -Z, -X)
    app(Z, X, 0.0); app(-Z, X, 0.0); app(Z, -X, 0.0); app(-Z, -X, 0.0)
    
    # Create faces
    tindices = [
        [0,4,1], [0,9,4], [9,5,4], [4,5,8], [4,8,1],    
        [8,10,1], [8,3,10], [5,3,8], [5,2,3], [2,7,3],    
        [7,10,3], [7,6,10], [7,11,6], [11,0,6], [0,1,6], 
        [6,1,10], [9,0,11], [9,11,2], [9,2,5], [7,2,11] ]
    tindices = np.array(tindices, dtype=np.uint32)
    
    # Init vertex array with existing points, init faces as empty list
    vertices = vdata.copy()
    faces = []
    
    # Define function to recursively create vertices and normals
    def drawtri(ia, ib, ic, div):
        a, b, c = vertices[ia] , vertices[ib], vertices[ic]
        if (div<=0):
            # Store faces here
            faces.extend([ia, ib, ic])
        else:
            # Create new points
            ab = Point(0,0,0)
            ac = Point(0,0,0)
            bc = Point(0,0,0)
            for i in range(3):
                ab[i]=(a[i]+b[i])/2.0;
                ac[i]=(a[i]+c[i])/2.0;
                bc[i]=(b[i]+c[i])/2.0;
            ab = ab.normalize(); ac = ac.normalize(); bc = bc.normalize()
            # Add new points
            i_offset = len(vertices)
            vertices.append(ab)
            vertices.append(ac)
            vertices.append(bc)
            iab, iac, ibc = i_offset+0, i_offset+1, i_offset+2
            #
            drawtri(ia, iab, iac, div-1)
            drawtri(ib, ibc, iab, div-1)
            drawtri(ic, iac, ibc, div-1)
            drawtri(iab, ibc, iac, div-1)
    
    # Create vertices
    for i in range(20):
        drawtri(    int(tindices[i][0]), 
                    int(tindices[i][1]), 
                    int(tindices[i][2]), 
                    ndiv )
    
    # Create normals and scale vertices
    normals = vertices.copy()
    vertices *= radius
    
    # Create faces
    faces = np.array(faces, dtype='uint32')
    
    # Done
    return vertices, faces, normals
Exemplo n.º 24
0
 def OnDraw(self):
     
     # Get colormaps that apply
     par = self.parent
     if par is None:
         return
     elif isinstance(par, (BaseFigure, Axes)):
         mapables = par.FindObjects(Colormapable)
     elif isinstance(par, ColormapEditor):
         mapables = par.GetMapables()
     elif isinstance(par, ClimEditor):
         mapables = par.GetMapables()
     else:
         mapables = []
     
     # Get the last one
     mapable = None
     if mapables:
         mapable = mapables[-1]
     
     
     # get dimensions        
     w,h = self.position.size
     
     # Calc map direction
     if w > h:
         texCords = [0,0,1,1]
     else:
         texCords = [1,0,0,1]
     
     
     # draw plane
     if mapable:
         # Use it's colormap texture
         mapable._EnableColormap()
         # Disable alpha channel (by not blending)
         gl.glDisable(gl.GL_BLEND)
         gl.glColor(1.0, 1.0, 1.0, 1.0)
         # Draw quads
         gl.glBegin(gl.GL_QUADS)
         gl.glTexCoord1f(texCords[0]); gl.glVertex2f(0,0)
         gl.glTexCoord1f(texCords[1]); gl.glVertex2f(0,h)
         gl.glTexCoord1f(texCords[2]); gl.glVertex2f(w,h)
         gl.glTexCoord1f(texCords[3]); gl.glVertex2f(w,0)
         gl.glEnd()
         
         # Clean up
         gl.glEnable(gl.GL_BLEND)
         gl.glFlush()
         mapable._DisableColormap()
     
     # prepare                
     gl.glDisable(gl.GL_LINE_SMOOTH)
     
     # draw edges        
     if self.edgeWidth and self.edgeColor:
         clr = self.edgeColor
         gl.glColor(clr[0], clr[1], clr[2], 1.0)
         gl.glLineWidth(self.edgeWidth)
         #
         gl.glBegin(gl.GL_LINE_LOOP)
         gl.glVertex2f(0,0)
         gl.glVertex2f(0,h)
         gl.glVertex2f(w,h)
         gl.glVertex2f(w,0)
         gl.glEnd()
     
     if hasattr(mapable, 'clim'):
         # Draw ticks
         if w>h:
             p0 = Point(0, h)
             p1 = Point(w, h)
             delta = Point(0,3)
             halign, valign = 0, 0
             xoffset, yoffset = -8, -2
         else:
             p0 = Point(w, h)
             p1 = Point(w, 0)
             delta = Point(3,0)
             halign, valign = -1, 0
             xoffset, yoffset = 5, -8
         
         # Get tickmarks
         ticks, ticksPos, ticksText = GetTicks(p0, p1, mapable.clim)
         
         newLabelPool = {}
         linePieces = Pointset(2)
         for tick, pos, text in zip(ticks, ticksPos, ticksText):
             pos2 = pos + delta
             
             # Add line piece
             linePieces.append(pos); linePieces.append(pos2)
             
             # Create or reuse label
             if tick in self._labelPool:
                 label = self._labelPool.pop(tick)
             else:
                 label = Label(self, ' '+text+' ')
                 label.bgcolor = ''
             
             # Position label and set text alignment
             newLabelPool[tick] = label
             label.halign, label.valign = halign, valign
             label.position.x = pos2.x + xoffset
             label.position.w = 16
             label.position.y = pos2.y + yoffset
         
         # Clean up label pool
         for label in list(self._labelPool.values()):
             label.Destroy()
         self._labelPool = newLabelPool
         
         # Draw line pieces
         # prepare
         gl.glLineWidth(1)
         gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
         gl.glVertexPointerf(linePieces.data)
         gl.glDrawArrays(gl.GL_LINES, 0, len(linePieces))
         gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
     # clean up        
     gl.glEnable(gl.GL_LINE_SMOOTH)
Exemplo n.º 25
0
 def OnDraw(self):
     
     # Draw bg color and edges
     Box.OnDraw(self)
     
     # Margin
     d1 = 2
     d2 = d1+1
     
     # Get normalize limits
     t1, t2 = self._getNormalizedSliderLimits()
     
     # Get widget shape
     w, h = self.position.size
     
     # Calculate real dimensions of patch
     if w > h:
         x1, x2 = max(d2, t1*w), min(w-d1, t2*w)
         y1, y2 = d1, h-d2
         #
         dots1 = self._dots1 + Point(x1, 0)
         dots2 = self._dots2 + Point(x2, 0)
         #
         diff = abs(x1-x2)
         #
         self._label.textAngle = 0
     else:
         x1, x2 = d2, w-d1
         y1, y2 = max(d1, t1*h), min(h-d2, t2*h)
         #
         dots1 = self._dots1 + Point(0, y1)
         dots2 = self._dots2 + Point(0, y2)
         #
         diff = abs(y1-y2)
         #
         self._label.textAngle = -90
     
     # Draw slider bit
     clr = self._bgcolor
     #if max(clr[0], clr[1], clr[2]) < 0.7:
     if clr[0] + clr[1] + clr[2] < 1.5:
         gl.glColor(1, 1, 1, 0.25)
     else:
         gl.glColor(0, 0, 0, 0.25)
     #
     gl.glBegin(gl.GL_POLYGON)
     gl.glVertex2f(x1,y1)
     gl.glVertex2f(x1,y2)
     gl.glVertex2f(x2,y2)
     gl.glVertex2f(x2,y1)
     gl.glEnd()
     
     
     # Draw dots
     if True:
         
         # Prepare
         gl.glColor(0,0,0,1)
         gl.glPointSize(1)
         gl.glDisable(gl.GL_POINT_SMOOTH)
         
         # Draw
         gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
         if isinstance(self, RangeSlider) and diff>5:
             gl.glVertexPointerf(dots1.data)
             gl.glDrawArrays(gl.GL_POINTS, 0, len(dots1))
         if diff>5:
             gl.glVertexPointerf(dots2.data)
             gl.glDrawArrays(gl.GL_POINTS, 0, len(dots2))
         gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
     
     
     if self._showTicks:
         
         # Reset color to black
         gl.glColor(0,0,0,1)
         
         # Draw ticks
         if w>h:
             p0 = Point(0, h)
             p1 = Point(w, h)
             delta = Point(0,3)
             halign, valign = 0, 0
             xoffset, yoffset = -8, -2
         else:
             p0 = Point(w, h)
             p1 = Point(w, 0)
             delta = Point(3,0)
             halign, valign = -1, 0
             xoffset, yoffset = 5, -8
         
         # Get tickmarks
         ticks, ticksPos, ticksText = GetTicks(p0, p1, self._fullRange)
         
         newLabelPool = {}
         linePieces = Pointset(2)
         for tick, pos, text in zip(ticks, ticksPos, ticksText):
             pos2 = pos + delta
             
             # Add line piece
             linePieces.append(pos); linePieces.append(pos2)
             
             # Create or reuse label
             if tick in self._labelPool:
                 label = self._labelPool.pop(tick)
             else:
                 label = Label(self, ' '+text+' ')
                 label.bgcolor = ''
                 label.textColor = self._textColor
             
             # Position label and set text alignment
             newLabelPool[tick] = label
             label.halign, label.valign = halign, valign
             label.position.x = pos2.x + xoffset
             label.position.w = 16
             label.position.y = pos2.y + yoffset
         
         # Clean up label pool
         for label in list(self._labelPool.values()):
             label.Destroy()
         self._labelPool = newLabelPool
         
         # Draw line pieces
         gl.glLineWidth(1)
         gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
         gl.glVertexPointerf(linePieces.data)
         gl.glDrawArrays(gl.GL_LINES, 0, len(linePieces))
         gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
Exemplo n.º 26
0
 def _CreateQuads(self):
     
     axes = self.GetAxes()
     if not axes:
         return
     
     # Store daspect so we can detect it changing
     self._daspectStored = axes.daspect
     self._qcountStored = self._quadPartitionCount(axes.camera)
     
     # Note that we could determine the world coordinates and use
     # them directly here. However, the way that we do it now (using
     # the transformations) is to be preferred, because that way the
     # transformations are applied via the ModelView matrix stack,
     # and can easily be made undone in the raycaster.
     # The -0.5 offset is to center pixels/voxels. This works correctly
     # for anisotropic data.
     #shape = self._texture1._shape
     shape = self._texture1._dataRef.shape
     x0, x1 = -0.5, shape[2]-0.5
     y0, y1 = -0.5, shape[1]-0.5
     z0, z1 = -0.5, shape[0]-0.5
     
     # prepare texture coordinates
     t0, t1 = 0, 1
     
     # I previously swapped coordinates to make sure the right faces
     # were frontfacing. Now I apply culling to achieve the same 
     # result in a better way.
     
     # using glTexCoord* is the same as glMultiTexCoord*(GL_TEXTURE0)
     # Therefore we need to bind the base texture to 0.
     
     # So we draw the six planes of the cube (well not a cube,
     # a 3d rectangle thingy). The inside is only rendered if the 
     # vertex is facing front, so only 3 planes are rendered at a        
     # time...                
     
     
     # Define the 8 corners of the cube.
     tex_coord0, ver_coord0 = Pointset(3), Pointset(3)
     # bottom
     tex_coord0.append((t0,t0,t0)); ver_coord0.append((x0, y0, z0)) # 0
     tex_coord0.append((t1,t0,t0)); ver_coord0.append((x1, y0, z0)) # 1
     tex_coord0.append((t1,t1,t0)); ver_coord0.append((x1, y1, z0)) # 2
     tex_coord0.append((t0,t1,t0)); ver_coord0.append((x0, y1, z0)) # 3
     # top
     tex_coord0.append((t0,t0,t1)); ver_coord0.append((x0, y0, z1)) # 4    
     tex_coord0.append((t0,t1,t1)); ver_coord0.append((x0, y1, z1)) # 5
     tex_coord0.append((t1,t1,t1)); ver_coord0.append((x1, y1, z1)) # 6
     tex_coord0.append((t1,t0,t1)); ver_coord0.append((x1, y0, z1)) # 7
     
     # Unwrap the vertices. 4 vertices per side = 24 vertices
     # Warning: dont mess up the list with indices; theyre carefully
     # chosen to be front facing.
     tex_coord, ver_coord = Pointset(3), Pointset(3)
     for i in [0,1,2,3, 4,5,6,7, 3,2,6,5, 0,4,7,1, 0,3,5,4, 1,7,6,2]:
         tex_coord.append(tex_coord0[i])
         ver_coord.append(ver_coord0[i])
     
     # Function to partition each quad in four smaller quads
     def partition(tex_coord1, ver_coord1):
         tex_coord2, ver_coord2 = Pointset(3), Pointset(3)
         for iQuad in range(int(len(tex_coord1)/4)):
             io = iQuad * 4
             for i1 in range(4):
                 for i2 in range(4):
                     i3 = (i1 + i2)%4                    
                     tex_coord2.append( 0.5*(tex_coord1[io+i1] + tex_coord1[io+i3]) )
                     ver_coord2.append( 0.5*(ver_coord1[io+i1] + ver_coord1[io+i3]) )
         #print('partition from %i to %i vertices' % (len(tex_coord1), len(tex_coord2)))
         return tex_coord2, ver_coord2
     
     # Partition quads in smaller quads?
     for iter in range(self._qcountStored):
         tex_coord, ver_coord = partition(tex_coord, ver_coord)
     
     # Store quads data
     self._quads = tex_coord, ver_coord
Exemplo n.º 27
0
def getSphere(ndiv=3, radius=1.0):
    # Example taken from the Red book, end of chaper 2.

    # Define constants
    X = 0.525731112119133606
    Z = 0.850650808352039932

    # Creta vdata
    vdata = Pointset(3)
    app = vdata.append
    app(-X, 0.0, Z)
    app(X, 0.0, Z)
    app(-X, 0.0, -Z)
    app(X, 0.0, -Z)
    app(0.0, Z, X)
    app(0.0, Z, -X)
    app(0.0, -Z, X)
    app(0.0, -Z, -X)
    app(Z, X, 0.0)
    app(-Z, X, 0.0)
    app(Z, -X, 0.0)
    app(-Z, -X, 0.0)

    # Create faces
    tindices = [[0, 4, 1], [0, 9, 4], [9, 5, 4], [4, 5, 8], [4, 8, 1],
                [8, 10, 1], [8, 3, 10], [5, 3, 8], [5, 2, 3], [2, 7, 3],
                [7, 10, 3], [7, 6, 10], [7, 11, 6], [11, 0, 6], [0, 1, 6],
                [6, 1, 10], [9, 0, 11], [9, 11, 2], [9, 2, 5], [7, 2, 11]]
    tindices = np.array(tindices, dtype=np.uint32)

    # Init vertex array
    vertices = Pointset(3)

    # Define function to recursively create vertices and normals
    def drawtri(a, b, c, div):
        if (div <= 0):
            vertices.append(a)
            vertices.append(b)
            vertices.append(c)
        else:
            ab = Point(0, 0, 0)
            ac = Point(0, 0, 0)
            bc = Point(0, 0, 0)
            for i in range(3):
                ab[i] = (a[i] + b[i]) / 2.0
                ac[i] = (a[i] + c[i]) / 2.0
                bc[i] = (b[i] + c[i]) / 2.0
            ab = ab.normalize()
            ac = ac.normalize()
            bc = bc.normalize()
            drawtri(a, ab, ac, div - 1)
            drawtri(b, bc, ab, div - 1)
            drawtri(c, ac, bc, div - 1)
            drawtri(ab, bc, ac, div - 1)

    # Create vertices
    for i in range(20):
        drawtri(vdata[int(tindices[i][0])], vdata[int(tindices[i][1])],
                vdata[int(tindices[i][2])], ndiv)

    # Create normals and scale vertices
    normals = vertices.copy()
    vertices *= radius

    # Done
    return vertices, normals
Exemplo n.º 28
0
def solidCylinder(translation=None, scaling=None, direction=None, rotation=None,
                    N=16, M=16, axesAdjust=True, axes=None):
    """ solidCylinder(
                translation=None, scaling=None, direction=None, rotation=None,
                N=16, M=16, axesAdjust=True, axes=None)
    
    Creates a cylinder object with quad faces and its base at the origin.
    Returns an OrientableMesh instance.
    
    Parameters
    ----------
    Note that translation, scaling, and direction can also be given
    using a Point instance.
    translation : (dx, dy, dz), optional
        The translation in world units of the created world object.
    scaling: (sx, sy, sz), optional
        The scaling in world units of the created world object.
    direction: (nx, ny, nz), optional
        Normal vector that indicates the direction of the created world object.
    rotation: scalar, optional
        The anle (in degrees) to rotate the created world object around its
        direction vector.
    N : int
        The number of subdivisions around its axis. If smaller
        than 8, flat shading is used instead of smooth shading. 
    M : int
        The number of subdivisions along its axis. If smaller
        than 8, flat shading is used instead of smooth shading. 
    axesAdjust : bool
        If True, this function will call axes.SetLimits(), and set
        the camera type to 3D. If daspectAuto has not been set yet, 
        it is set to False.
    axes : Axes instance
        Display the bars in the given axes, or the current axes if not given.
    
    """
    
    # Note that the number of vertices around the axis is N+1. This
    # would not be necessary per see, but it helps create a nice closed
    # texture when it is mapped. There are N number of faces though.
    # Similarly, to obtain M faces along the axis, we need M+1
    # vertices.
    
    # Quick access
    pi2 = np.pi*2
    cos = np.cos
    sin = np.sin
    sl = N+1
    
    # Calculate vertices, normals and texcords
    vertices = Pointset(3)
    normals = Pointset(3)
    texcords = Pointset(2)
    # Round part
    for m in range(M+1):
        z = 1.0 - float(m)/M # between 0 and 1
        v = float(m)/M
        #
        for n in range(N+1):
            b = pi2 * float(n) / N
            u = float(n) / (N)
            x = cos(b)
            y = sin(b)
            vertices.append(x,y,z)
            normals.append(x,y,0)
            texcords.append(u,v)
    # Top
    for m in range(2):
        for n in range(N+1):
            b = pi2 * float(n) / N
            u = float(n) / (N)
            x = cos(b) * m # todo: check which ones are frontfacing!
            y = sin(b) * m
            vertices.append(x,y,1)
            normals.append(0,0,1)
            texcords.append(u,0)
    # Bottom
    for m in range(2):
        for n in range(N+1):
            b = pi2 * float(n) / N
            u = float(n) / (N)
            x = cos(b) * (1-m)
            y = sin(b) * (1-m)
            vertices.append(x,y,0)
            normals.append(0,0,-1)
            texcords.append(u,1)
    
    # Normalize normals
    normals = normals.normalize()
    
    # Calculate indices
    indices = []
    for j in range(M):
        for i in range(N):
            #indices.extend([j*sl+i, j*sl+i+1, (j+1)*sl+i+1, (j+1)*sl+i])
            indices.extend([(j+1)*sl+i, (j+1)*sl+i+1, j*sl+i+1, j*sl+i])
    j = M+1
    for i in range(N):
        indices.extend([(j+1)*sl+i, (j+1)*sl+i+1, j*sl+i+1, j*sl+i])
    j = M+3
    for i in range(N):
        indices.extend([(j+1)*sl+i, (j+1)*sl+i+1, j*sl+i+1, j*sl+i])
    
    # Make indices a numpy array
    indices = np.array(indices, dtype=np.uint32)
    
    
    ## Visualization
    
    # Create axes 
    if axes is None:
        axes = vv.gca()
    
    # Create mesh
    m = vv.OrientableMesh(axes, vertices, indices, normals, values=texcords,
            verticesPerFace=4)
    #
    if translation is not None:
        m.translation = translation
    if scaling is not None:
        m.scaling = scaling
    if direction is not None:
        m.direction = direction
    if rotation is not None:
        m.rotation = rotation
    
    # Set flat shading?
    if N<8 or M<8:
        m.faceShading = 'flat'
    
    # Adjust axes
    if axesAdjust:
        if axes.daspectAuto is None:
            axes.daspectAuto = False
        axes.cameraType = '3d'
        axes.SetLimits()
    
    # Done
    axes.Draw()
    return m
Exemplo n.º 29
0
 def _DragCalcDots(self, event=None):
     w,h = self.position.size
     dots = Pointset(2)
     #        
     dots.append(3,3); dots.append(3,6); dots.append(3,9)
     dots.append(6,3); dots.append(6,6); dots.append(6,9)
     dots.append(9,3); dots.append(9,6); dots.append(9,9)
     #
     dots.append(w-3, h-3); dots.append(w-3, h-6); dots.append(w-3, h-9)
     dots.append(w-6, h-3); dots.append(w-6, h-6);
     dots.append(w-9, h-3);
     self._dots = dots
Exemplo n.º 30
0
def plot(data1, data2=None, data3=None, 
            lw=1, lc='b', ls="-", mw=7, mc='b', ms='', mew=1, mec='k', 
            alpha=1, axesAdjust=True, axes=None, **kwargs):
    """ plot(*args, lw=1, lc='b', ls="-", mw=7, mc='b', ms='', mew=1, mec='k', 
            alpha=1, axesAdjust=True, axes=None):
    
    Plot 1, 2 or 3 dimensional data and return the Line object.
    
    Usage
    -----
      * plot(Y, ...) plots a 1D signal, with the values plotted along the y-axis
      * plot(X, Y, ...) also supplies x coordinates
      * plot(X, Y, Z, ...) also supplies z coordinates
      * plot(P, ...) plots using a Point or Pointset instance
    
    Keyword arguments
    -----------------
    (The longer names for the line properties can also be used)    
    lw : scalar
        lineWidth. The width of the line. If zero, no line is drawn.
    mw : scalar
        markerWidth. The width of the marker. If zero, no marker is drawn.
    mew : scalar
        markerEdgeWidth. The width of the edge of the marker.    
    lc : 3-element tuple or char
        lineColor. The color of the line. A tuple should represent the RGB
        values between 0 and 1. If a char is given it must be
        one of 'rgbmcywk', for reg, green, blue, magenta, cyan, yellow, 
        white, black, respectively.
    mc : 3-element tuple or char
        markerColor. The color of the marker. See lineColor.
    mec : 3-element tuple or char
        markerEdgeColor. The color of the edge of the marker.    
    ls : string
        lineStyle. The style of the line. (See below)
    ms : string
        markerStyle. The style of the marker. (See below)
    axesAdjust : bool
        If axesAdjust==True, this function will call axes.SetLimits(), set
        the camera type to 2D when plotting 2D data and to 3D when plotting
        3D data. If daspectAuto has not been set yet, it is set to True.
    axes : Axes instance
        Display the image in this axes, or the current axes if not given.
    
    Line styles
    -----------
      * Solid line: '-'
      * Dotted line: ':'
      * Dashed line: '--'
      * Dash-dot line: '-.' or '.-'
      * A line that is drawn between each pair of points: '+'
      * No line: '' or None.
    
    Marker styles
    -------------
      * Plus: '+'
      * Cross: 'x'
      * Square: 's'
      * Diamond: 'd'
      * Triangle (pointing up, down, left, right): '^', 'v', '<', '>'
      * Pentagram star: 'p' or '*'
      * Hexgram: 'h'
      * Point/cirle: 'o' or '.'
      * No marker: '' or None
    
    """
    
    # create a dict from the properties and combine with kwargs
    tmp     = { 'lineWidth':lw,         'lineColor':lc,     'lineStyle':ls,
                'markerWidth':mw,       'markerColor':mc,   'markerStyle':ms,
                'markerEdgeWidth':mew,  'markerEdgeColor':mec}
    for i in tmp:
        if not i in kwargs:
            kwargs[i] = tmp[i]
    
    # init dimension variable
    camDim = 0
    
    ##  create the data
    
    if is_Pointset(data1):
        pp = data1
    elif is_Point(data1):
        pp = Pointset(data1.ndim)
        pp.append(data1)
    else:   
        
        if data1 is None:
            raise Exception("The first argument cannot be None!")
        data1 = np.asanyarray(data1)
        
        d3 = data3
        if data3 is None:
            data3 = 0.1*np.ones(data1.shape)
            camDim = 2
        else:
            camDim = 3
            data3 = np.asanyarray(data3)
        
        if data2 is None:
            if d3 is not None:
                tmp = "third argument in plot() ignored, as second not given."
                print("Warning: " + tmp)
            # y data is given, xdata must be a range starting from 1
            data2 = data1
            data1 = np.arange(1,data2.shape[0]+1)
            data3 = 0.1*np.ones(data2.shape)
        else:
            data2 = np.asanyarray(data2)
        
        # check dimensions
        L = data1.size
        if L != data2.size or L != data3.size:
            raise Exception("Array dimensions do not match! %i vs %i vs %i" % 
                    (data1.size, data2.size, data3.size))
        
        # build points
        data1 = data1.reshape((data1.size,1))
        data2 = data2.reshape((data2.size,1))
        data3 = data3.reshape((data3.size,1))
        
        # Concatenate to a single Nx3 array (take care of masked arrays)
        tmp = data1, data2, data3
        if any([isinstance(d, np.ma.MaskedArray) for d in tmp]):
            pp = np.ma.concatenate(tmp, 1)
        else:
            pp = np.concatenate(tmp, 1)
        
    
    # Process camdim for given points or pointsets
    if not camDim:
        camDim = pp.ndim
        
    
    ## create the line
    if axes is None:
        axes = vv.gca()    
    l = vv.Line(axes, pp)
    l.lw = kwargs['lineWidth']
    l.lc = kwargs['lineColor']
    l.ls = kwargs['lineStyle']
    l.mw = kwargs['markerWidth'] 
    l.mc = kwargs['markerColor'] 
    l.ms = kwargs['markerStyle']
    l.mew = kwargs['markerEdgeWidth']
    l.mec = kwargs['markerEdgeColor']
    l.alpha = alpha
    
    ## done...
    if axesAdjust:
        if axes.daspectAuto is None:
            axes.daspectAuto = True
        axes.cameraType = str(camDim)+'d'
        axes.SetLimits()
    
    axes.Draw()
    return l
Exemplo n.º 31
0
    if axes is None:
        axes = vv.gca()
    
    # Create mesh object
    m = vv.Mesh(axes, baseMesh)
    
    # Adjust axes
    if axesAdjust:
        if axes.daspectAuto is None:
            axes.daspectAuto = False
        axes.cameraType = '3d'
        axes.SetLimits()
    
    # Return
    axes.Draw()
    return m
    
    
    
if __name__ == '__main__': 
    # Create series of points
    pp = Pointset(3)
    pp.append(0,1,0)
    pp.append(3,2,1)
    pp.append(4,5,2)
    pp.append(2,3,1)
    pp.append(0,4,0)
    #pp.append(0,1,0) # Circular
    # Make a surface-line with varying diameter
    m = vv.solidLine(pp, [0.1, 0.2, 0.3, 0.1, 0.2], 8)
Exemplo n.º 32
0
def solidBox(translation=None,
             scaling=None,
             direction=None,
             rotation=None,
             axesAdjust=True,
             axes=None):
    """ solidBox(translation=None, scaling=None, direction=None, rotation=None,
                    axesAdjust=True, axes=None)
    
    Creates a solid cube (or box if you scale it) centered at the 
    origin. Returns an OrientableMesh.
    
    Parameters
    ----------
    Note that translation, scaling, and direction can also be given
    using a Point instance.
    translation : (dx, dy, dz), optional
        The translation in world units of the created world object.
    scaling: (sx, sy, sz), optional
        The scaling in world units of the created world object.
    direction: (nx, ny, nz), optional
        Normal vector that indicates the direction of the created world object.
    rotation: scalar, optional
        The anle (in degrees) to rotate the created world object around its
        direction vector.
    axesAdjust : bool
        If True, this function will call axes.SetLimits(), and set
        the camera type to 3D. If daspectAuto has not been set yet, 
        it is set to False.
    axes : Axes instance
        Display the bars in the given axes, or the current axes if not given.
    
    """

    # Create vertices of a cube
    pp = Pointset(3)
    # Bottom
    pp.append(-0.5, -0.5, -0.5)
    pp.append(+0.5, -0.5, -0.5)
    pp.append(+0.5, +0.5, -0.5)
    pp.append(-0.5, +0.5, -0.5)
    # Top
    pp.append(-0.5, -0.5, +0.5)
    pp.append(-0.5, +0.5, +0.5)
    pp.append(+0.5, +0.5, +0.5)
    pp.append(+0.5, -0.5, +0.5)

    # Init vertices and normals
    vertices = Pointset(3)
    normals = Pointset(3)

    # Create vertices
    for i in [3, 2, 1, 0]:  # Top
        vertices.append(pp[i])
        normals.append(0, 0, -1)
    for i in [7, 6, 5, 4]:  # Bottom
        vertices.append(pp[i])
        normals.append(0, 0, +1)
    for i in [5, 6, 2, 3]:  # Front
        vertices.append(pp[i])
        normals.append(0, +1, 0)
    for i in [1, 7, 4, 0]:  # Back
        vertices.append(pp[i])
        normals.append(0, -1, 0)
    for i in [4, 5, 3, 0]:  # Left
        vertices.append(pp[i])
        normals.append(-1, 0, 0)
    for i in [2, 6, 7, 1]:  # Right
        vertices.append(pp[i])
        normals.append(+1, 0, 0)

    ## Visualize

    # Create axes
    if axes is None:
        axes = vv.gca()

    # Create mesh and set orientation
    m = vv.OrientableMesh(axes, vertices, None, normals, verticesPerFace=4)
    #
    if translation is not None:
        m.translation = translation
    if scaling is not None:
        m.scaling = scaling
    if direction is not None:
        m.direction = direction
    if rotation is not None:
        m.rotation = rotation

    # Adjust axes
    if axesAdjust:
        if axes.daspectAuto is None:
            axes.daspectAuto = False
        axes.cameraType = '3d'
        axes.SetLimits()

    # Done
    axes.Draw()
    return m
Exemplo n.º 33
0
 def _CreateQuads(self):
     
     axes = self.GetAxes()
     if not axes:
         return
     
     # Store daspect so we can detect it changing
     self._daspectStored = axes.daspect
     self._qcountStored = self._quadPartitionCount(axes.camera)
     
     # Note that we could determine the world coordinates and use
     # them directly here. However, the way that we do it now (using
     # the transformations) is to be preferred, because that way the
     # transformations are applied via the ModelView matrix stack,
     # and can easily be made undone in the raycaster.
     # The -0.5 offset is to center pixels/voxels. This works correctly
     # for anisotropic data.
     #shape = self._texture1._shape
     shape = self._texture1._dataRef.shape
     x0, x1 = -0.5, shape[2]-0.5
     y0, y1 = -0.5, shape[1]-0.5
     z0, z1 = -0.5, shape[0]-0.5
     
     # prepare texture coordinates
     t0, t1 = 0, 1
     
     # I previously swapped coordinates to make sure the right faces
     # were frontfacing. Now I apply culling to achieve the same 
     # result in a better way.
     
     # using glTexCoord* is the same as glMultiTexCoord*(GL_TEXTURE0)
     # Therefore we need to bind the base texture to 0.
     
     # So we draw the six planes of the cube (well not a cube,
     # a 3d rectangle thingy). The inside is only rendered if the 
     # vertex is facing front, so only 3 planes are rendered at a        
     # time...                
     
     
     # Define the 8 corners of the cube.
     tex_coord0, ver_coord0 = Pointset(3), Pointset(3)
     # bottom
     tex_coord0.append((t0,t0,t0)); ver_coord0.append((x0, y0, z0)) # 0
     tex_coord0.append((t1,t0,t0)); ver_coord0.append((x1, y0, z0)) # 1
     tex_coord0.append((t1,t1,t0)); ver_coord0.append((x1, y1, z0)) # 2
     tex_coord0.append((t0,t1,t0)); ver_coord0.append((x0, y1, z0)) # 3
     # top
     tex_coord0.append((t0,t0,t1)); ver_coord0.append((x0, y0, z1)) # 4    
     tex_coord0.append((t0,t1,t1)); ver_coord0.append((x0, y1, z1)) # 5
     tex_coord0.append((t1,t1,t1)); ver_coord0.append((x1, y1, z1)) # 6
     tex_coord0.append((t1,t0,t1)); ver_coord0.append((x1, y0, z1)) # 7
     
     # Unwrap the vertices. 4 vertices per side = 24 vertices
     # Warning: dont mess up the list with indices; theyre carefully
     # chosen to be front facing.
     tex_coord, ver_coord = Pointset(3), Pointset(3)
     for i in [0,1,2,3, 4,5,6,7, 3,2,6,5, 0,4,7,1, 0,3,5,4, 1,7,6,2]:
         tex_coord.append(tex_coord0[i])
         ver_coord.append(ver_coord0[i])
     
     # Function to partition each quad in four smaller quads
     def partition(tex_coord1, ver_coord1):
         tex_coord2, ver_coord2 = Pointset(3), Pointset(3)
         for iQuad in range(int(len(tex_coord1)/4)):
             io = iQuad * 4
             for i1 in range(4):
                 for i2 in range(4):
                     i3 = (i1 + i2)%4                    
                     tex_coord2.append( 0.5*(tex_coord1[io+i1] + tex_coord1[io+i3]) )
                     ver_coord2.append( 0.5*(ver_coord1[io+i1] + ver_coord1[io+i3]) )
         #print('partition from %i to %i vertices' % (len(tex_coord1), len(tex_coord2)))
         return tex_coord2, ver_coord2
     
     # Partition quads in smaller quads?
     for iter in range(self._qcountStored):
         tex_coord, ver_coord = partition(tex_coord, ver_coord)
     
     # Store quads data
     self._quads = tex_coord, ver_coord
Exemplo n.º 34
0
 def OnDraw(self):
     
     # Draw bg color and edges
     Box.OnDraw(self)
     
     # Margin
     d1 = 2
     d2 = d1+1
     
     # Get normalize limits        
     t1, t2 = self._getNormalizedSliderLimits()
     
     # Get widget shape
     w, h = self.position.size
     
     # Calculate real dimensions of patch
     if w > h:
         x1, x2 = max(d2, t1*w), min(w-d1, t2*w)            
         y1, y2 = d1, h-d2
         #
         dots1 = self._dots1 + Point(x1, 0)
         dots2 = self._dots2 + Point(x2, 0)
         #
         diff = abs(x1-x2)
         #
         self._label.textAngle = 0
     else:            
         x1, x2 = d2, w-d1
         y1, y2 = max(d1, t1*h), min(h-d2, t2*h)
         #
         dots1 = self._dots1 + Point(0, y1)
         dots2 = self._dots2 + Point(0, y2)
         #
         diff = abs(y1-y2)
         #
         self._label.textAngle = -90
     
     # Draw slider bit
     clr = self._frontColor
     gl.glColor(clr[0], clr[1], clr[2], 1.0)            
     #
     gl.glBegin(gl.GL_POLYGON)
     gl.glVertex2f(x1,y1)
     gl.glVertex2f(x1,y2)
     gl.glVertex2f(x2,y2)
     gl.glVertex2f(x2,y1)
     gl.glEnd()
     
     
     # Draw dots
     if True:
         
         # Prepare
         gl.glColor(0,0,0,1)
         gl.glPointSize(1)
         gl.glDisable(gl.GL_POINT_SMOOTH)
         
         # Draw
         gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
         if isinstance(self, RangeSlider) and diff>5:
             gl.glVertexPointerf(dots1.data)
             gl.glDrawArrays(gl.GL_POINTS, 0, len(dots1))
         if diff>5:
             gl.glVertexPointerf(dots2.data)
             gl.glDrawArrays(gl.GL_POINTS, 0, len(dots2))
         gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
     
     
     if self._showTicks:
         
         # Reset color to black
         gl.glColor(0,0,0,1)
         
         # Draw ticks
         if w>h:
             p0 = Point(0, h)
             p1 = Point(w, h)
             delta = Point(0,3)
             halign, valign = 0, 0
             xoffset, yoffset = -8, -2
         else:
             p0 = Point(w, h)
             p1 = Point(w, 0)
             delta = Point(3,0)
             halign, valign = -1, 0
             xoffset, yoffset = 5, -8
         
         # Get tickmarks
         ticks, ticksPos, ticksText = GetTicks(p0, p1, self._fullRange)
         
         newLabelPool = {}
         linePieces = Pointset(2)
         for tick, pos, text in zip(ticks, ticksPos, ticksText):
             pos2 = pos + delta
             
             # Add line piece
             linePieces.append(pos); linePieces.append(pos2)
             
             # Create or reuse label
             if tick in self._labelPool:
                 label = self._labelPool.pop(tick)
             else:
                 label = Label(self, ' '+text+' ')
                 label.bgcolor = ''
             
             # Position label and set text alignment
             newLabelPool[tick] = label
             label.halign, label.valign = halign, valign
             label.position.x = pos2.x + xoffset
             label.position.w = 16
             label.position.y = pos2.y + yoffset
         
         # Clean up label pool
         for label in list(self._labelPool.values()):
             label.Destroy()
         self._labelPool = newLabelPool
         
         # Draw line pieces
         gl.glLineWidth(1)
         gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
         gl.glVertexPointerf(linePieces.data)
         gl.glDrawArrays(gl.GL_LINES, 0, len(linePieces))
         gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
Exemplo n.º 35
0
    def _GetCords(self):
        """ _GetCords()
        Get a pointset of the coordinates of the wobject. This is used
        for drawing the quads and lines using a vertex array. 
        """

        # Can we reuse buffered coordinates?
        if self._cordsBuffer is not None:
            return self._cordsBuffer

        # Get ranges in world coords
        rangex, rangey = self._GetRangesInWorldCords()

        # Project two points to use in OnDrawScreen
        screen1 = glu.gluProject(rangex.min, rangey.min, 0)
        screen2 = glu.gluProject(rangex.max, rangey.max, 0)

        # Calculate world-distance of a screendistance of self._barwidth
        # and then do drawing here (not in OnDrawScreen), otherwise I won't
        # be able to detect picking!!
        onePixelx = rangex.range / (screen2[0] - screen1[0])
        onePixely = rangey.range / (screen2[1] - screen1[1])

        # Get coords
        tmp = self._barWidth
        x1, x2, xd = rangex.min, rangex.max, onePixelx * tmp
        y1, y2, yd = rangey.min, rangey.max, onePixely * tmp
        if yd < 0:
            y1, y2 = y2, y1  # axis flipped

        # Definition of the coordinate indices:
        #
        # 12 11      10 15
        #  4 0 ----- 3 9
        #    |       |
        #    |       |
        #  5 1------ 2 8
        # 13 6       7 14
        #

        # Make coords
        pp = Pointset(2)
        #
        pp.append(x1, y1)
        pp.append(x1, y2)
        pp.append(x2, y2)
        pp.append(x2, y1)
        #
        pp.append(x1 - xd, y1)
        pp.append(x1 - xd, y2)
        pp.append(x1, y2 + yd)
        pp.append(x2, y2 + yd)
        #
        pp.append(x2 + xd, y2)
        pp.append(x2 + xd, y1)
        pp.append(x2, y1 - yd)
        pp.append(x1, y1 - yd)
        #
        pp.append(x1 - xd, y1 - yd)
        pp.append(x1 - xd, y2 + yd)
        pp.append(x2 + xd, y2 + yd)
        pp.append(x2 + xd, y1 - yd)

        # Done
        self._cordsBuffer = pp
        return pp
Exemplo n.º 36
0
    def Compile(self, textObject):
        """ Create a series of glyphs from the text in the textObject.
        From these Glyphs. Also the relative vertices are calculated,
        which are then corrected
        for angle and alignment in Position().
        """
        FontManager.Compile(self, textObject)

        # make invalid first
        textObject.Invalidate()

        # Get font object
        font = self.GetFont(textObject.fontName)

        # clear glyphs
        glyphs = []

        # Create reference character (used in Position)
        textObject._xglyph = Glyph(font, 'X', textObject.fontSize)

        # Get text string with escaped text converted to Unicode
        tt = self.ConvertEscapedText(textObject.text)

        # build list of glyphs, take sub/super scripting into account.
        escape = False
        styles = []
        style = None  # Style to set
        for i in range(len(tt)):
            c = tt[i]
            if escape:
                g = Glyph(font, c, textObject.fontSize, styles)
                glyphs.append(g)
                escape = False
            elif c == '{':
                # Append style to the list
                if style:
                    styles.append(style)
                    style = None
            elif c == '}':
                # Remove style
                if styles:
                    styles.pop()
            elif c == '^':
                style = MiniStyle(2)
            elif c == '_':
                style = MiniStyle(1)
            elif c == '\x06':
                style = MiniStyle(0, False, True)
            elif c == '\x07':
                style = MiniStyle(0, True, False)
            elif c == '\\' and i + 1 < len(tt) and tt[i + 1] in ['_^\x06\x07']:
                escape = True
            else:
                # create glyph (with new style (or not))
                g = Glyph(font, c, textObject.fontSize, styles + [style])
                glyphs.append(g)
                style = None

        # build arrays with vertices and coordinates
        x1, y1, z = 0, 0, 0
        vertices = Pointset(3)
        texCords = Pointset(2)
        for g in glyphs:
            x2 = x1 + g.sizex
            y2 = g.sizey
            #y2 = y1 - g.sizey
            dy = g.dy

            # append texture coordinates
            texCords.append(g.s1, g.t1)
            texCords.append(g.s2, g.t1)
            texCords.append(g.s2, g.t2)
            texCords.append(g.s1, g.t2)

            # set skewing for position
            skew = textObject.fontSize * g.skewFactor

            # append vertices
            vertices.append(x1 + skew, y1 + dy, z)
            vertices.append(x2 + skew, y1 + dy, z)
            vertices.append(x2, y2 + dy, z)
            vertices.append(x1, y2 + dy, z)

            # prepare for next glyph
            x1 = x1 + g.width + 1

        # Scale text according to global text size property
        fig = textObject.GetFigure()
        if fig:
            vertices *= fig._relativeFontSize

        # store calculations
        textObject._SetCompiledData(vertices, texCords)
Exemplo n.º 37
0
def getSphereWithFaces(ndiv=3, radius=1.0):
    # Example taken from the Red book, end of chaper 2.

    # Define constants
    X = 0.525731112119133606
    Z = 0.850650808352039932

    # Creta vdata
    vdata = Pointset(3)
    app = vdata.append
    app(-X, 0.0, Z)
    app(X, 0.0, Z)
    app(-X, 0.0, -Z)
    app(X, 0.0, -Z)
    app(0.0, Z, X)
    app(0.0, Z, -X)
    app(0.0, -Z, X)
    app(0.0, -Z, -X)
    app(Z, X, 0.0)
    app(-Z, X, 0.0)
    app(Z, -X, 0.0)
    app(-Z, -X, 0.0)

    # Create faces
    tindices = [[0, 4, 1], [0, 9, 4], [9, 5, 4], [4, 5, 8], [4, 8, 1],
                [8, 10, 1], [8, 3, 10], [5, 3, 8], [5, 2, 3], [2, 7, 3],
                [7, 10, 3], [7, 6, 10], [7, 11, 6], [11, 0, 6], [0, 1, 6],
                [6, 1, 10], [9, 0, 11], [9, 11, 2], [9, 2, 5], [7, 2, 11]]
    tindices = np.array(tindices, dtype=np.uint32)

    # Init vertex array with existing points, init faces as empty list
    vertices = vdata.copy()
    faces = []

    # Define function to recursively create vertices and normals
    def drawtri(ia, ib, ic, div):
        a, b, c = vertices[ia], vertices[ib], vertices[ic]
        if (div <= 0):
            # Store faces here
            faces.extend([ia, ib, ic])
        else:
            # Create new points
            ab = Point(0, 0, 0)
            ac = Point(0, 0, 0)
            bc = Point(0, 0, 0)
            for i in range(3):
                ab[i] = (a[i] + b[i]) / 2.0
                ac[i] = (a[i] + c[i]) / 2.0
                bc[i] = (b[i] + c[i]) / 2.0
            ab = ab.normalize()
            ac = ac.normalize()
            bc = bc.normalize()
            # Add new points
            i_offset = len(vertices)
            vertices.append(ab)
            vertices.append(ac)
            vertices.append(bc)
            iab, iac, ibc = i_offset + 0, i_offset + 1, i_offset + 2
            #
            drawtri(ia, iab, iac, div - 1)
            drawtri(ib, ibc, iab, div - 1)
            drawtri(ic, iac, ibc, div - 1)
            drawtri(iab, ibc, iac, div - 1)

    # Create vertices
    for i in range(20):
        drawtri(int(tindices[i][0]), int(tindices[i][1]), int(tindices[i][2]),
                ndiv)

    # Create normals and scale vertices
    normals = vertices.copy()
    vertices *= radius

    # Create faces
    faces = np.array(faces, dtype='uint32')

    # Done
    return vertices, faces, normals
Exemplo n.º 38
0
 def draw_top_points(ax, paths, color=(1, 1, 0)):
     top_pts = np.array([path_top_point(p) for p in paths])
     pp = Pointset(top_pts)
     vv.plot(pp, ms='.', mc=color, mw='15', ls='', mew=0, axes=ax)
Exemplo n.º 39
0
def lineToMesh(pp, radius, vertex_num, values=None):
    """ lineToMesh(pp, radius, vertex_num, values=None)
    
    From a line, create a mesh that represents the line as a tube with
    given diameter. Returns a BaseMesh instance.
    
    Parameters
    ----------
    pp : 3D Pointset
        The points along the line. If the first and last point are the same,
        the mesh-line is closed.
    radius : scalar
        The radius of the tube that is created. Radius can also be a
        sequence of values (containing a radius for each point).
    vertex_num : int
        The number of vertices to create along the circumference of the tube.
    values : list or numpy array (optional)
        A value per point. Can be Nx1, Nx2, Nx3 or Nx4. A list of scalars
        can also be given. The values are propagated to the mesh vertices
        and supplied as input to the Mesh constructor. This allows for example
        to define the color for the tube.
    
    """

    # we need this quite a bit
    pi = np.pi

    # process radius
    if hasattr(radius, '__len__'):
        if len(radius) != len(pp):
            raise ValueError('Len of radii much match len of points.')
        else:
            radius = np.array(radius, dtype=np.float32)
    else:
        radius = radius * np.ones((len(pp), ), dtype=np.float32)

    # calculate vertex points for 2D circle
    angles = np.arange(0, pi * 2 - 0.0001, pi * 2 / vertex_num)
    angle_cos = np.cos(angles)
    angle_sin = np.sin(angles)
    vertex_num2 = len(angles)  # just to be sure

    # calculate distance between two line pieces (for smooth cylinders)
    dists = pp[1:].distance(pp[:-1])
    bufdist = min(radius.max(), dists.min() / 2.2)

    # check if line is closed
    lclosed = np.all(pp[0] == pp[-1])

    # calculate normal vectors on each line point
    normals = pp[:-1].subtract(pp[1:]).copy()
    if lclosed:
        normals.append(pp[0] - pp[1])
    else:
        normals.append(pp[-2] - pp[-1])
    normals = -1 * normals.normalize()

    # create list to store vertices
    vertices = Pointset(3)
    surfaceNormals = Pointset(3)

    # And a list for the values
    if values is None:
        vvalues = None
    elif isinstance(values, list):
        if len(values) != len(pp):
            raise ValueError('There must be as many values as points.')
        vvalues = Pointset(1)
    elif isinstance(values, np.ndarray):
        if values.ndim != 2:
            raise ValueError('Values must be Nx1, Nx2, Nx3 or Nx4.')
        if values.shape[0] != len(pp):
            raise ValueError('There must be as many values as points.')
        vvalues = Pointset(values.shape[1])
    elif vv.utils.pypoints.is_Pointset(values):
        if values.ndim > 4:
            raise ValueError('Can specify one to four values per point.')
        if len(values) != len(pp):
            raise ValueError('There must be as many values as points.')
        vvalues = Pointset(values.ndim)
    else:
        raise ValueError('Invalid value for values.')

    # Number of triangelized cylinder elements added to plot the 3D line
    n_cylinders = 0

    # Init a and b
    a, b = Point(0, 0, 1), Point(0, 1, 0)

    # Calculate the 3D circle coordinates of the first circle/cylinder
    a, b = getSpanVectors(normals[0], a, b)
    circm = getCircle(angle_cos, angle_sin, a, b)

    # If not a closed line, add half sphere made with 5 cylinders at line start
    if not lclosed:
        for j in range(5, 0, -1):
            # Translate the circle on it's position on the line
            r = (1 - (j / 5.0)**2)**0.5
            circmp = float(r * radius[0]) * circm + (
                pp[0] - (j / 5.0) * bufdist * normals[0])
            # Calc normals
            circmn = (pp[0].subtract(circmp)).normalize()
            # Store the vertex list
            vertices.extend(circmp)
            surfaceNormals.extend(-1 * circmn)
            if vvalues is not None:
                for iv in range(vertex_num2):
                    vvalues.append(values[0])
            n_cylinders += 1

    # Loop through all line pieces
    for i in range(len(pp) - 1):

        ## Create main cylinder between two line points
        # which consists of two connected circles.

        # get normal and point
        normal1 = normals[i]
        point1 = pp[i]

        # calculate the 3D circle coordinates
        a, b = getSpanVectors(normal1, a, b)
        circm = getCircle(angle_cos, angle_sin, a, b)

        # Translate the circle, and store
        circmp = float(radius[i]) * circm + (point1 + bufdist * normal1)
        vertices.extend(circmp)
        surfaceNormals.extend(circm)
        if vvalues is not None:
            for iv in range(vertex_num2):
                vvalues.append(values[i])
        n_cylinders += 1

        # calc second normal and line
        normal2 = normals[i + 1]
        point2 = pp[i + 1]

        # Translate the circle, and store
        circmp = float(radius[i + 1]) * circm + (point2 - bufdist * normal1)
        vertices.extend(circmp)
        surfaceNormals.extend(circm)
        if vvalues is not None:
            for iv in range(vertex_num2):
                vvalues.append(values[i + 1])
        n_cylinders += 1

        ## Create in between circle to smoothly connect line pieces

        if not lclosed and i == len(pp) - 2:
            break

        # get normal and point
        normal12 = (normal1 + normal2).normalize()
        tmp = (point2 + bufdist * normal2) + (point2 - bufdist * normal1)
        point12 = 0.5858 * point2 + 0.4142 * (0.5 * tmp)

        # Calculate the 3D circle coordinates
        a, b = getSpanVectors(normal12, a, b)
        circm = getCircle(angle_cos, angle_sin, a, b)

        # Translate the circle, and store
        circmp = float(radius[i + 1]) * circm + point12
        vertices.extend(circmp)
        surfaceNormals.extend(circm)
        if vvalues is not None:
            for iv in range(vertex_num2):
                vvalues.append(0.5 * (values[i] + values[i + 1]))
        n_cylinders += 1

    # If not a closed line, add half sphere made with 5 cylinders at line start
    # Otherwise add the starting circle to the line end.
    if not lclosed:
        for j in range(0, 6):
            # Translate the circle on it's position on the line
            r = (1 - (j / 5.0)**2)**0.5
            circmp = float(r * radius[-1]) * circm + (
                pp[-1] + (j / 5.0) * bufdist * normals[-1])
            # Calc normals
            circmn = (pp[-1].subtract(circmp)).normalize()
            # Store the vertex list
            vertices.extend(circmp)
            surfaceNormals.extend(-1 * circmn)
            if vvalues is not None:
                for iv in range(vertex_num2):
                    vvalues.append(values[-1])
            n_cylinders += 1
    else:
        # get normal and point
        normal1 = normals[-1]
        point1 = pp[-1]

        # calculate the 3D circle coordinates
        a, b = getSpanVectors(normal1, a, b)
        circm = getCircle(angle_cos, angle_sin, a, b)

        # Translate the circle, and store
        circmp = float(radius[0]) * circm + (point1 + bufdist * normal1)
        vertices.extend(circmp)
        surfaceNormals.extend(circm)
        if vvalues is not None:
            for iv in range(vertex_num2):
                vvalues.append(values[-1])
        n_cylinders += 1

    # almost done, determine quad faces ...

    # define single faces
    #firstFace = [0, 1, vertex_num+1, vertex_num]
    #lastFace = [vertex_num-1, 0, vertex_num, 2*vertex_num-1]
    firstFace = [vertex_num, vertex_num + 1, 1, 0]
    lastFace = [2 * vertex_num - 1, vertex_num, 0, vertex_num - 1]

    # define single round
    oneRound = []
    for i in range(vertex_num - 1):
        oneRound.extend([val + i for val in firstFace])
    oneRound.extend(lastFace)
    oneRound = np.array(oneRound, dtype=np.uint32)

    # calculate face data
    parts = []
    for i in range(n_cylinders - 1):
        parts.append(oneRound + i * vertex_num)
    faces = np.concatenate(parts)
    faces.shape = faces.shape[0] // 4, 4

    # Done!
    return BaseMesh(vertices, faces, surfaceNormals, vvalues)
Exemplo n.º 40
0
def lineToMesh(pp, radius, vertex_num, values=None):
    """ lineToMesh(pp, radius, vertex_num, values=None)
    
    From a line, create a mesh that represents the line as a tube with 
    given diameter. Returns a BaseMesh instance.
    
    Parameters
    ----------
    pp : 3D Pointset
        The points along the line. If the first and last point are the same,
        the mesh-line is closed.
    radius : scalar
        The radius of the tube that is created. Radius can also be a 
        sequence of values (containing a radius for each point).
    vertex_num : int
        The number of vertices to create along the circumference of the tube. 
    values : list or numpy array (optional)
        A value per point. Can be Nx1, Nx2, Nx3 or Nx4. A list of scalars
        can also be given. The values are propagated to the mesh vertices 
        and supplied as input to the Mesh constructor. This allows for example
        to define the color for the tube.
    
    """
    
    # we need this quite a bit
    pi = np.pi
    
    # process radius
    if hasattr(radius, '__len__'):
        if len(radius) != len(pp):
            raise ValueError('Len of radii much match len of points.')
        else:
            radius = np.array(radius, dtype=np.float32)
    else:
        radius = radius*np.ones((len(pp),), dtype=np.float32)
    
    # calculate vertex points for 2D circle
    angles = np.arange(0, pi*2-0.0001, pi*2/vertex_num)
    angle_cos = np.cos(angles)
    angle_sin = np.sin(angles)
    vertex_num2 = len(angles) # just to be sure
    
    # calculate distance between two line pieces (for smooth cylinders)
    dists = pp[1:].distance(pp[:-1])
    bufdist = min( radius.max(), dists.min()/2.2)
    
    # check if line is closed
    lclosed = np.all(pp[0]==pp[-1])
    
    # calculate normal vectors on each line point    
    normals = pp[:-1].subtract( pp[1:] ).copy()
    if lclosed:        
        normals.append( pp[0]-pp[1] )
    else:        
        normals.append( pp[-2]-pp[-1] )
    normals = -1 * normals.normalize()
    
    # create list to store vertices
    vertices = Pointset(3)
    surfaceNormals = Pointset(3)
    
    # And a list for the values
    if values is None:
        vvalues = None
        nvalues = 0
    elif isinstance(values, list):
        if len(values) != len(pp):
            raise ValueError('There must be as many values as points.')
        vvalues = Pointset(1)
    elif isinstance(values, np.ndarray):
        if values.ndim != 2:
            raise ValueError('Values must be Nx1, Nx2, Nx3 or Nx4.')
        if values.shape[0] != len(pp):
            raise ValueError('There must be as many values as points.')
        vvalues = Pointset(values.shape[1])
    elif vv.utils.pypoints.is_Pointset(values):
        if values.ndim > 4:
            raise ValueError('Can specify one to four values per point.')
        if len(values) != len(pp):
            raise ValueError('There must be as many values as points.')
        vvalues = Pointset(values.ndim)
    else:
        raise ValueError('Invalid value for values.')
    
    # Number of triangelized cylinder elements added to plot the 3D line
    n_cylinders = 0
    
    # Init a and b
    a, b = Point(0,0,1), Point(0,1,0)
    
    # Calculate the 3D circle coordinates of the first circle/cylinder
    a,b = getSpanVectors(normals[0], a, b)
    circm = getCircle(angle_cos, angle_sin, a, b);
    
    # If not a closed line, add half sphere made with 5 cylinders at line start     
    if not lclosed:
        for j in range(5,0,-1):
            # Translate the circle on it's position on the line
            r = (1-(j/5.0)**2)**0.5
            circmp = float(r*radius[0])*circm + (pp[0]-(j/5.0)*bufdist*normals[0])
            # Calc normals
            circmn = ( pp[0].subtract(circmp) ).normalize() 
            # Store the vertex list            
            vertices.extend( circmp )
            surfaceNormals.extend( -1*circmn )
            if vvalues is not None:
                for iv in range(vertex_num2):
                    vvalues.append(values[0])
            n_cylinders += 1
    
    # Loop through all line pieces    
    for i in range(len(pp)-1):
        
        ## Create main cylinder between two line points 
        # which consists of two connected circles.
        
        # get normal and point
        normal1 = normals[i]
        point1 = pp[i]
        
        # calculate the 3D circle coordinates
        a,b = getSpanVectors(normal1, a, b)
        circm = getCircle(angle_cos, angle_sin, a, b)
        
        # Translate the circle, and store
        circmp = float(radius[i])*circm + (point1+bufdist*normal1)        
        vertices.extend( circmp )
        surfaceNormals.extend( circm )
        if vvalues is not None:
            for iv in range(vertex_num2):
                vvalues.append(values[i])
        n_cylinders += 1
        
        # calc second normal and line
        normal2 = normals[i+1]
        point2 = pp[i+1]
        
        # Translate the circle, and store
        circmp = float(radius[i+1])*circm + (point2-bufdist*normal1)
        vertices.extend( circmp )
        surfaceNormals.extend( circm )
        if vvalues is not None:
            for iv in range(vertex_num2):
                vvalues.append(values[i+1])
        n_cylinders += 1
        
        
        ## Create in between circle to smoothly connect line pieces
        
        if not lclosed and i == len(pp)-2:
            break
        
        # get normal and point
        normal12 = (normal1 + normal2).normalize()
        tmp = (point2+bufdist*normal2) + (point2-bufdist*normal1)
        point12 = 0.5858*point2 + 0.4142*(0.5*tmp)
        
        # Calculate the 3D circle coordinates
        a,b = getSpanVectors(normal12, a, b)
        circm = getCircle(angle_cos, angle_sin, a, b);
        
        # Translate the circle, and store
        circmp = float(radius[i+1])*circm + point12
        vertices.extend( circmp )
        surfaceNormals.extend( circm )
        if vvalues is not None:
            for iv in range(vertex_num2):
                vvalues.append( 0.5*(values[i]+values[i+1]) )
        n_cylinders += 1
    
    
    # If not a closed line, add half sphere made with 5 cylinders at line start
    # Otherwise add the starting circle to the line end.
    if not lclosed:
        for j in range(0,6):
            # Translate the circle on it's position on the line
            r = (1-(j/5.0)**2)**0.5
            circmp = float(r*radius[-1])*circm + (pp[-1]+(j/5.0)*bufdist*normals[-1])
            # Calc normals
            circmn = ( pp[-1].subtract(circmp) ).normalize()            
            # Store the vertex list
            vertices.extend( circmp )
            surfaceNormals.extend( -1*circmn )
            if vvalues is not None:
                for iv in range(vertex_num2):
                    vvalues.append(values[-1])
            n_cylinders += 1
    else:
        # get normal and point
        normal1 = normals[-1]
        point1 = pp[-1]
        
        # calculate the 3D circle coordinates        
        a,b = getSpanVectors(normal1, a, b)
        circm = getCircle(angle_cos, angle_sin, a, b)
        
        # Translate the circle, and store
        circmp = float(radius[0])*circm + (point1+bufdist*normal1)        
        vertices.extend( circmp )
        surfaceNormals.extend( circm )
        if vvalues is not None:
            for iv in range(vertex_num2):
                vvalues.append(values[-1])
        n_cylinders += 1
    
    
    # almost done, determine quad faces ...
    
    # define single faces
    #firstFace = [0, 1, vertex_num+1, vertex_num]    
    #lastFace = [vertex_num-1, 0, vertex_num, 2*vertex_num-1]
    firstFace = [vertex_num, vertex_num+1, 1, 0]    
    lastFace = [2*vertex_num-1, vertex_num, 0, vertex_num-1]
    
    # define single round    
    oneRound = []
    for i in range(vertex_num-1):
        oneRound.extend( [val+i for val in firstFace] )
    oneRound.extend(lastFace)
    oneRound = np.array(oneRound, dtype=np.uint32)
    
    # calculate face data
    parts = []
    for i in range(n_cylinders-1):
        parts.append(oneRound+i*vertex_num)
    faces = np.concatenate(parts)
    faces.shape = faces.shape[0]/4, 4
    
    # Done!
    return BaseMesh(vertices, faces, surfaceNormals, vvalues)
Exemplo n.º 41
0
 def draw_critical_points(ax, morse_index, level, color):
     Y, X = mesh.get_critical_points(morse_index)
     Z = np.ones(len(X)) * level
     pp = Pointset(np.transpose([X, Y, Z]))
     vv.plot(pp, ms='.', mc=color, mw='12', ls='', mew=0, axes=ax)
Exemplo n.º 42
0
 def Compile(self, textObject):
     """ Create a series of glyphs from the text in the textObject.
     From these Glyphs. Also the relative vertices are calculated, 
     which are then corrected
     for angle and alignment in Position().
     """
     FontManager.Compile(self, textObject)
     
     # make invalid first
     textObject.Invalidate()
     
     # Get font object
     font = self.GetFont(textObject.fontName)
     
     # clear glyphs
     glyphs = [] 
     
     # Create reference character (used in Position)
     textObject._xglyph = Glyph(font, 'X', textObject.fontSize)     
     
     # Get text string with escaped text converted to Unicode
     tt = self.ConvertEscapedText(textObject.text)
     
     
     # build list of glyphs, take sub/super scripting into account.        
     escape = False
     styles = []
     style = None # Style to set
     for i in range(len(tt)):
         c = tt[i]            
         if escape:                
             g = Glyph(font, c, textObject.fontSize, styles)
             glyphs.append( g )
             escape = False
         elif c=='{':
             # Append style to the list
             if style:
                 styles.append(style)
                 style = None
         elif c=='}':
             # Remove style
             if styles:
                 styles.pop()                    
         elif c=='^':
             style = MiniStyle(2)
         elif c=='_':
             style = MiniStyle(1)
         elif c=='\x06':
             style = MiniStyle(0,False,True)
         elif c=='\x07':
             style = MiniStyle(0,True,False)
         elif c=='\\' and i+1<len(tt) and tt[i+1] in ['_^\x06\x07']:
             escape = True
         else:
             # create glyph (with new style (or not))
             g = Glyph(font, c, textObject.fontSize, styles+[style])
             glyphs.append( g )
             style = None
     
     # build arrays with vertices and coordinates        
     x1, y1, z = 0, 0, 0
     vertices = Pointset(3)
     texCords = Pointset(2)
     for g in glyphs:
         x2 = x1 + g.sizex
         y2 = g.sizey
         #y2 = y1 - g.sizey
         dy = g.dy
         
         # append texture coordinates
         texCords.append(g.s1, g.t1)
         texCords.append(g.s2, g.t1)
         texCords.append(g.s2, g.t2)
         texCords.append(g.s1, g.t2)
         
         # set skewing for position
         skew = textObject.fontSize * g.skewFactor
         
         # append vertices
         vertices.append(x1+skew, y1+dy, z)
         vertices.append(x2+skew, y1+dy, z)
         vertices.append(x2, y2+dy, z)
         vertices.append(x1, y2+dy, z)
         
         # prepare for next glyph
         x1 = x1 + g.width + 1     
     
     # Scale text according to global text size property
     fig = textObject.GetFigure()
     if fig:
         vertices *= fig._relativeFontSize
     
     # store calculations
     textObject._SetCompiledData(vertices, texCords)
Exemplo n.º 43
0
 def _DragCalcDots(self, event=None):
     w, h = self.position.size
     dots = Pointset(2)
     #
     dots.append(3, 3)
     dots.append(3, 6)
     dots.append(3, 9)
     dots.append(6, 3)
     dots.append(6, 6)
     dots.append(6, 9)
     dots.append(9, 3)
     dots.append(9, 6)
     dots.append(9, 9)
     #
     dots.append(w - 3, h - 3)
     dots.append(w - 3, h - 6)
     dots.append(w - 3, h - 9)
     dots.append(w - 6, h - 3)
     dots.append(w - 6, h - 6)
     dots.append(w - 9, h - 3)
     self._dots = dots
Exemplo n.º 44
0
def polarplot(data1,
              data2=None,
              inRadians=False,
              lw=1,
              lc='b',
              ls="-",
              mw=7,
              mc='b',
              ms='',
              mew=1,
              mec='k',
              alpha=1,
              axesAdjust=True,
              axes=None,
              **kwargs):
    """ polarplot(*args, inRadians=False,
            lw=1, lc='b', ls="-", mw=7, mc='b', ms='', mew=1, mec='k',
            alpha=1, axesAdjust=True, axes=None):
    
    Plot 2D polar data, using a polar axis to draw a polar grid. 
    
    Usage
    -----
      * plot(Y, ...) plots a 1D polar signal.
      * plot(X, Y, ...) also supplies angular coordinates
      * plot(P, ...) plots using a Point or Pointset instance
    
    Keyword arguments
    -----------------
    (The longer names for the line properties can also be used)    
    lw : scalar
        lineWidth. The width of the line. If zero, no line is drawn.
    mw : scalar
        markerWidth. The width of the marker. If zero, no marker is drawn.
    mew : scalar
        markerEdgeWidth. The width of the edge of the marker.    
    lc : 3-element tuple or char
        lineColor. The color of the line. A tuple should represent the RGB
        values between 0 and 1. If a char is given it must be
        one of 'rgbmcywk', for reg, green, blue, magenta, cyan, yellow, 
        white, black, respectively.
    mc : 3-element tuple or char
        markerColor. The color of the marker. See lineColor.
    mec : 3-element tuple or char
        markerEdgeColor. The color of the edge of the marker.    
    ls : string
        lineStyle. The style of the line. (See below)
    ms : string
        markerStyle. The style of the marker. (See below)
    axesAdjust : bool
        If axesAdjust==True, this function will call axes.SetLimits(), and set
        the camera type to 2D. 
    axes : Axes instance
        Display the image in this axes, or the current axes if not given.
    
    Line styles
    -----------
      * Solid line: '-'
      * Dotted line: ':'
      * Dashed line: '--'
      * Dash-dot line: '-.' or '.-'
      * A line that is drawn between each pair of points: '+'
      * No line: '' or None.
    
    Marker styles
    -------------
      * Plus: '+'
      * Cross: 'x'
      * Square: 's'
      * Diamond: 'd'
      * Triangle (pointing up, down, left, right): '^', 'v', '<', '>'
      * Pentagram star: 'p' or '*'
      * Hexgram: 'h'
      * Point/cirle: 'o' or '.'
      * No marker: '' or None
    
    Polar axis
    ----------
    This polar axis has a few specialized methods for adjusting the polar
    plot. Access these via vv.gca().axis.    
      * SetLimits(thetaRange, radialRange)
      * thetaRange, radialRange = GetLimits()
      * angularRefPos: Get and Set methods for the relative screen
        angle of the 0 degree polar reference.  Default is 0 degs
        which corresponds to the positive x-axis (y =0)
      * isCW: Get and Set methods for the sense of rotation CCW or
        CW. This method takes/returns a bool (True if the default CW).
    
    Interaction
    -----------
      * Drag mouse up/down to translate radial axis.    
      * Drag mouse left/right to rotate angular ref position.    
      * Drag mouse + shift key up/down to rescale radial axis (min R fixed).
    
    """

    # create a dict from the properties and combine with kwargs
    tmp = {
        'lineWidth': lw,
        'lineColor': lc,
        'lineStyle': ls,
        'markerWidth': mw,
        'markerColor': mc,
        'markerStyle': ms,
        'markerEdgeWidth': mew,
        'markerEdgeColor': mec
    }
    for i in tmp:
        if not i in kwargs:
            kwargs[i] = tmp[i]

    ##  create the data
    if is_Pointset(data1):
        pp = data1
    elif is_Point(data1):
        pp = Pointset(data1.ndim)
        pp.append(data1)
    else:

        if data1 is None:
            raise ValueError("The first argument cannot be None!")
        data1 = makeArray(data1)

        if data2 is None:
            # R data is given, thetadata must be
            # a range starting from 0 degrees
            data2 = data1
            data1 = np.arange(0, data2.shape[0])
        else:
            data2 = makeArray(data2)

        # check dimensions
        L = data1.size
        if L != data2.size:
            raise ValueError("Array dimensions do not match! %i vs %i " %
                             (data1.size, data2.size))

        # build points
        data1 = data1.reshape((data1.size, 1))
        data2 = data2.reshape((data2.size, 1))

    if not inRadians:
        data1 = np.pi * data1 / 180.0

    ## create the line
    if axes is None:
        axes = vv.gca()
    axes.axisType = 'polar'
    fig = axes.GetFigure()

    l = PolarLine(axes, data1, data2)
    l.lw = kwargs['lineWidth']
    l.lc = kwargs['lineColor']
    l.ls = kwargs['lineStyle']
    l.mw = kwargs['markerWidth']
    l.mc = kwargs['markerColor']
    l.ms = kwargs['markerStyle']
    l.mew = kwargs['markerEdgeWidth']
    l.mec = kwargs['markerEdgeColor']
    l.alpha = alpha

    ## almost done...

    # Init axis
    #     axes.axis.SetLimits()

    if axesAdjust:
        if axes.daspectAuto is None:
            axes.daspectAuto = True
        axes.cameraType = '2d'
        axes.SetLimits()

    # Subsribe after-draw event handler
    # (unsubscribe first in case we do multiple plots)
    fig.eventAfterDraw.Unbind(_SetLimitsAfterDraw)
    fig.eventAfterDraw.Bind(_SetLimitsAfterDraw)

    # Return
    axes.Draw()
    return l
Exemplo n.º 45
0
def solidRing(
    translation=None,
    scaling=None,
    direction=None,
    rotation=None,
    thickness=0.25,
    N=16,
    M=16,
    axesAdjust=True,
    axes=None,
):
    """ solidRing(translation=None, scaling=None, direction=None, rotation=None,
                thickness=0.25, N=16, M=16, axesAdjust=True, axes=None)
    
    Creates a solid ring with quad faces oriented at the origin. 
    Returns an OrientableMesh instance.
    
    Parameters
    ----------
    Note that translation, scaling, and direction can also be given
    using a Point instance.
    translation : (dx, dy, dz), optional
        The translation in world units of the created world object.
    scaling: (sx, sy, sz), optional
        The scaling in world units of the created world object.
    direction: (nx, ny, nz), optional
        Normal vector that indicates the direction of the created world object.
    rotation: scalar, optional
        The anle (in degrees) to rotate the created world object around its
        direction vector.
    thickness : scalar
        The tickness of the ring, represented as a fraction of the radius.
    N : int
        The number of subdivisions around its axis. If smaller
        than 8, flat shading is used instead of smooth shading. 
    M : int
        The number of subdivisions along its axis. If smaller
        than 8, flat shading is used instead of smooth shading. 
    axesAdjust : bool
        If True, this function will call axes.SetLimits(), and set
        the camera type to 3D. If daspectAuto has not been set yet, 
        it is set to False.
    axes : Axes instance
        Display the bars in the given axes, or the current axes if not given.
    
    """

    # Note that the number of vertices around the axis is N+1. This
    # would not be necessary per see, but it helps create a nice closed
    # texture when it is mapped. There are N number of faces though.
    # Similarly, to obtain M faces along the axis, we need M+1
    # vertices.

    # Quick access
    pi2 = np.pi * 2
    cos = np.cos
    sin = np.sin
    sl = M + 1

    # Determine where the stitch is, depending on M
    if M <= 8:
        rotOffset = 0.5 / M
    else:
        rotOffset = 0.0

    # Calculate vertices, normals and texcords
    vertices = Pointset(3)
    normals = Pointset(3)
    texcords = Pointset(2)
    # Cone
    for n in range(N + 1):
        v = float(n) / N
        a = pi2 * v
        # Obtain outer and center position of "tube"
        po = Point(sin(a), cos(a), 0)
        pc = po * (1.0 - 0.5 * thickness)
        # Create two vectors that span the the circle orthogonal to the tube
        p1 = pc - po
        p2 = Point(0, 0, 0.5 * thickness)
        # Sample around tube
        for m in range(M + 1):
            u = float(m) / (M)
            b = pi2 * (u + rotOffset)
            dp = cos(b) * p1 + sin(b) * p2
            vertices.append(pc + dp)
            normals.append(dp.normalize())
            texcords.append(v, u)

    # Calculate indices
    indices = []
    for j in range(N):
        for i in range(M):
            # indices.extend([j*sl+i, j*sl+i+1, (j+1)*sl+i+1, (j+1)*sl+i])
            indices.extend([(j + 1) * sl + i, (j + 1) * sl + i + 1, j * sl + i + 1, j * sl + i])

    # Make indices a numpy array
    indices = np.array(indices, dtype=np.uint32)

    ## Visualize

    # Create axes
    if axes is None:
        axes = vv.gca()

    # Create mesh
    m = vv.OrientableMesh(axes, vertices, indices, normals, values=texcords, verticesPerFace=4)
    #
    if translation is not None:
        m.translation = translation
    if scaling is not None:
        m.scaling = scaling
    if direction is not None:
        m.direction = direction
    if rotation is not None:
        m.rotation = rotation

    # If necessary, use flat shading
    if N < 8 or M < 8:
        m.faceShading = "flat"

    # Adjust axes
    if axesAdjust:
        if axes.daspectAuto is None:
            axes.daspectAuto = False
        axes.cameraType = "3d"
        axes.SetLimits()

    # Done
    axes.Draw()
    return m
Exemplo n.º 46
0
def solidRing(translation=None,
              scaling=None,
              direction=None,
              rotation=None,
              thickness=0.25,
              N=16,
              M=16,
              axesAdjust=True,
              axes=None):
    """ solidRing(translation=None, scaling=None, direction=None, rotation=None,
                thickness=0.25, N=16, M=16, axesAdjust=True, axes=None)
    
    Creates a solid ring with quad faces oriented at the origin. 
    Returns an OrientableMesh instance.
    
    Parameters
    ----------
    Note that translation, scaling, and direction can also be given
    using a Point instance.
    translation : (dx, dy, dz), optional
        The translation in world units of the created world object.
    scaling: (sx, sy, sz), optional
        The scaling in world units of the created world object.
    direction: (nx, ny, nz), optional
        Normal vector that indicates the direction of the created world object.
    rotation: scalar, optional
        The anle (in degrees) to rotate the created world object around its
        direction vector.
    thickness : scalar
        The tickness of the ring, represented as a fraction of the radius.
    N : int
        The number of subdivisions around its axis. If smaller
        than 8, flat shading is used instead of smooth shading. 
    M : int
        The number of subdivisions along its axis. If smaller
        than 8, flat shading is used instead of smooth shading. 
    axesAdjust : bool
        If True, this function will call axes.SetLimits(), and set
        the camera type to 3D. If daspectAuto has not been set yet, 
        it is set to False.
    axes : Axes instance
        Display the bars in the given axes, or the current axes if not given.
    
    """

    # Note that the number of vertices around the axis is N+1. This
    # would not be necessary per see, but it helps create a nice closed
    # texture when it is mapped. There are N number of faces though.
    # Similarly, to obtain M faces along the axis, we need M+1
    # vertices.

    # Quick access
    pi2 = np.pi * 2
    cos = np.cos
    sin = np.sin
    sl = M + 1

    # Determine where the stitch is, depending on M
    if M <= 8:
        rotOffset = 0.5 / M
    else:
        rotOffset = 0.0

    # Calculate vertices, normals and texcords
    vertices = Pointset(3)
    normals = Pointset(3)
    texcords = Pointset(2)
    # Cone
    for n in range(N + 1):
        v = float(n) / N
        a = pi2 * v
        # Obtain outer and center position of "tube"
        po = Point(sin(a), cos(a), 0)
        pc = po * (1.0 - 0.5 * thickness)
        # Create two vectors that span the the circle orthogonal to the tube
        p1 = (pc - po)
        p2 = Point(0, 0, 0.5 * thickness)
        # Sample around tube
        for m in range(M + 1):
            u = float(m) / (M)
            b = pi2 * (u + rotOffset)
            dp = cos(b) * p1 + sin(b) * p2
            vertices.append(pc + dp)
            normals.append(dp.normalize())
            texcords.append(v, u)

    # Calculate indices
    indices = []
    for j in range(N):
        for i in range(M):
            #indices.extend([j*sl+i, j*sl+i+1, (j+1)*sl+i+1, (j+1)*sl+i])
            indices.extend([(j + 1) * sl + i, (j + 1) * sl + i + 1,
                            j * sl + i + 1, j * sl + i])

    # Make indices a numpy array
    indices = np.array(indices, dtype=np.uint32)

    ## Visualize

    # Create axes
    if axes is None:
        axes = vv.gca()

    # Create mesh
    m = vv.OrientableMesh(axes,
                          vertices,
                          indices,
                          normals,
                          values=texcords,
                          verticesPerFace=4)
    #
    if translation is not None:
        m.translation = translation
    if scaling is not None:
        m.scaling = scaling
    if direction is not None:
        m.direction = direction
    if rotation is not None:
        m.rotation = rotation

    # If necessary, use flat shading
    if N < 8 or M < 8:
        m.faceShading = 'flat'

    # Adjust axes
    if axesAdjust:
        if axes.daspectAuto is None:
            axes.daspectAuto = False
        axes.cameraType = '3d'
        axes.SetLimits()

    # Done
    axes.Draw()
    return m
Exemplo n.º 47
0
def solidCone(translation=None,
              scaling=None,
              direction=None,
              rotation=None,
              N=16,
              M=16,
              axesAdjust=True,
              axes=None):
    """ solidCone(translation=None, scaling=None, direction=None, rotation=None,
                    N=16, M=16, axesAdjust=True, axes=None)
    
    Creates a solid cone with quad faces and its base at the origin.
    Returns an OrientableMesh instance.
    
    Parameters
    ----------
    Note that translation, scaling, and direction can also be given
    using a Point instance.
    translation : (dx, dy, dz), optional
        The translation in world units of the created world object.
    scaling: (sx, sy, sz), optional
        The scaling in world units of the created world object.
    direction: (nx, ny, nz), optional
        Normal vector that indicates the direction of the created world object.
    rotation: scalar, optional
        The anle (in degrees) to rotate the created world object around its
        direction vector.
    N : int
        The number of subdivisions around its axis. If smaller
        than 8, flat shading is used instead of smooth shading.
        With N=4, a pyramid is obtained.
    M : int
        The number of subdivisions along its axis. If smaller
        than 8, flat shading is used instead of smooth shading.
    axesAdjust : bool
        If True, this function will call axes.SetLimits(), and set
        the camera type to 3D. If daspectAuto has not been set yet,
        it is set to False.
    axes : Axes instance
        Display the bars in the given axes, or the current axes if not given.
    
    """

    # Note that the number of vertices around the axis is N+1. This
    # would not be necessary per see, but it helps create a nice closed
    # texture when it is mapped. There are N number of faces though.
    # Similarly, to obtain M faces along the axis, we need M+1
    # vertices.

    # Quick access
    pi2 = np.pi * 2
    cos = np.cos
    sin = np.sin
    sl = N + 1

    # Precalculate z component of the normal
    zn = 1.0

    # Calculate vertices, normals and texcords
    vertices = Pointset(3)
    normals = Pointset(3)
    texcords = Pointset(2)
    # Cone
    for m in range(M + 1):
        z = 1.0 - float(m) / M  # between 0 and 1
        v = float(m) / M
        #
        for n in range(N + 1):
            b = pi2 * float(n) / N
            u = float(n) / (N)
            x = cos(b) * (1.0 - z)
            y = sin(b) * (1.0 - z)
            vertices.append(x, y, z)
            normals.append(x, y, zn)
            texcords.append(u, v)
    # Bottom
    for m in range(2):
        for n in range(N + 1):
            b = pi2 * float(n) / N
            u = float(n) / (N)
            x = cos(b) * (1 - m)
            y = sin(b) * (1 - m)
            vertices.append(x, y, 0)
            normals.append(0, 0, -1)
            texcords.append(u, 1)

    # Calculate indices
    indices = []
    for j in range(M):
        for i in range(N):
            #indices.extend([j*sl+i, j*sl+i+1, (j+1)*sl+i+1, (j+1)*sl+i])
            indices.extend([(j + 1) * sl + i, (j + 1) * sl + i + 1,
                            j * sl + i + 1, j * sl + i])
    j = M + 1
    for i in range(N):
        indices.extend([(j + 1) * sl + i, (j + 1) * sl + i + 1, j * sl + i + 1,
                        j * sl + i])

    # Make indices a numpy array
    indices = np.array(indices, dtype=np.uint32)

    ## Visualization

    # Create axes
    if axes is None:
        axes = vv.gca()

    # Create mesh
    m = vv.OrientableMesh(axes,
                          vertices,
                          indices,
                          normals,
                          values=texcords,
                          verticesPerFace=4)
    #
    if translation is not None:
        m.translation = translation
    if scaling is not None:
        m.scaling = scaling
    if direction is not None:
        m.direction = direction
    if rotation is not None:
        m.rotation = rotation

    # Set flat shading?
    if N < 8 or M < 8:
        m.faceShading = 'flat'

    # Adjust axes
    if axesAdjust:
        if axes.daspectAuto is None:
            axes.daspectAuto = False
        axes.cameraType = '3d'
        axes.SetLimits()

    # Done
    axes.Draw()
    return m
Exemplo n.º 48
0
    if axes is None:
        axes = vv.gca()
    
    # Create mesh object
    m = vv.Mesh(axes, baseMesh)
    
    # Adjust axes
    if axesAdjust:
        if axes.daspectAuto is None:
            axes.daspectAuto = False
        axes.cameraType = '3d'
        axes.SetLimits()
    
    # Return
    axes.Draw()
    return m
    
    
    
if __name__ == '__main__':
    # Create series of points
    pp = Pointset(3)
    pp.append(0,1,0)
    pp.append(3,2,1)
    pp.append(4,5,2)
    pp.append(2,3,1)
    pp.append(0,4,0)
    #pp.append(0,1,0) # Circular
    # Make a surface-line with varying diameter
    m = vv.solidLine(pp, [0.1, 0.2, 0.3, 0.1, 0.2], 8)