示例#1
0
 def __init__(self, exp, coeff=None):
     """Create an n-d polynomial"""
     self.exp = at.checkArray(exp, kind='i', ndim=2)
     if coeff is None:
         self.coeff = np.ones(self.nterms)
     else:
         self.coeff = at.checkArray(coeff, (self.nterms, ), 'f', 'i')
示例#2
0
    def lookAt(self, focus=None, eye=None, up=None):
        """Set the Modelview matrix to look at the specified focus point.

        The Modelview matrix is set with the camera positioned at eye
        and looking at the focus points, while the camera up vector is
        in the plane of the camera axis (focus-eye) and the specified
        up vector.

        If any of the arguments is left unspecified, the current value
        will be used.
        """
        if not self.locked:
            if focus is None:
                focus = self.focus
            else:
                focus = at.checkArray(focus, (3, ), 'f')
            if eye is None:
                eye = self.eye
            else:
                eye = at.checkArray(eye, (3, ), 'f')
            if up is None:
                up = self.upvector
            else:
                up = at.normalize(at.checkArray(up, (3, ), 'f'))
            vector = eye - focus
            self.focus = focus
            self.dist = at.length(vector)
            axis2 = at.normalize(vector)
            axis0 = at.normalize(np.cross(up, axis2))
            axis1 = at.normalize(np.cross(axis2, axis0))
            m = Matrix4()
            m.rotate(np.column_stack([axis0, axis1, axis2]))
            m.translate(-eye)
            self.setModelview(m)
示例#3
0
    def index(self, sel):
        """Convert a selector to an index

        sel is either a list of element numbers or a bool array with
        length self.size

        Returns an index array with the selected numbers.
        """
        try:
            sel = at.checkArray(sel, shape=(self.size, ), kind='b')
            sel = np.where(sel)[0]
        except:
            sel = at.checkArray(sel, kind='i')
        return sel
示例#4
0
def normalize(x, w):
    """Normalized coordinates inside a window.

    Parameters:

    - `x`: an (np,nc) array with coordinates.
    - `w`: a (2,nc) array with minimal and width of the window that will
      be mapped to the range -1..1.

    Returns an array with the x values linearly remapped thus that values w[0]
    become -1 and values w[0]+w[1] become +1.
    """
    x = at.checkArray(x, (-1, -1), 'f')
    np, nc = x.shape
    w = at.checkArray(w, (2, nc), 'f', 'i')
    return (x - w[0]) * 2 / w[1] - 1
示例#5
0
 def fromWindow(self, x):
     """Convert window coordinates to  normalized device coordinates"""
     # This is only correct when glDepthRange(0.0, 1.0)
     # We should not change the depth range
     vp = gl_viewport()
     x = at.checkArray(x, (-1, 3), 'f')
     return normalize(x[:, :3], [[vp[0], vp[1], 0], [vp[2], vp[3], 1]])
示例#6
0
    def __init__(self, geometry, fldtype, data, fldname=None):
        """Initialize a Field.

        """
        if not hasattr(geometry,
                       'fieldtypes') or fldtype not in geometry.fieldtypes:
            raise ValueError("Can not add field of type '%s' to a %s" %
                             (fldtype, geometry.__class__.__name__))

        if fldtype == 'node':
            datashape = (geometry.nnodes(), -1)
        elif fldtype == 'elemc':
            datashape = (geometry.nelems(), -1)
        elif fldtype == 'elemn':
            datashape = (geometry.nelems(), geometry.nplex(), -1)
        elif fldtype == 'elemg':
            datashape = (geometry.nelems(), -1, -1)

        scalar = len(data.shape) < len(datashape)
        if scalar:
            datashape = datashape[:-1]
        data = at.checkArray(data, shape=datashape)

        if fldname is None:
            fldname = next(Field._autoname)

        # All data seem OK, store them
        self.geometry = geometry
        self.fldname = fldname
        self.fldtype = fldtype
        self.data = data
        self.scalar = scalar
示例#7
0
def denormalize(x, w):
    """Map normalized coordinates to fit a window

    Parameters:

    - `x`: an (np,nc) array with normalized coordinates.
    - `w`: a (2,nc) array with minimal and width values of the window.

    Returns an array with the x values linearly remapped thus that values -1
    coincide with the minimum window values and +1 with the minimum+width
    values.
    """
    x = at.checkArray(x, (-1, -1), 'f')
    np, nc = x.shape
    w = at.checkArray(w, (2, nc), 'f', 'i')
    return w[0] + (1 + x) * w[1] / 2
示例#8
0
def saneSettings(k):
    """Sanitize sloppy settings for JavaScript output"""
    ok = {}
    try:
        ok['color'] = checkArray(k['color'], (3,), 'f')
    except:
        try:
            c = checkInt(k['color'][0])
            print("COLOR INDEX %s" % c)
            colormap = pf.canvas.settings.colormap
            ok['color'] = colormap[c % len(colormap)]
        except:
            print("Unexpected color: %s" % k['color'])

    try:
        ok['alpha'] = checkFloat(k['alpha'], 0., 1.)
    except:
        pass
    try:
        ok['caption'] = str(k['caption'])
    except:
        pass
    try:
        ok['control'] = intersection(k['control'], controller_format.keys())
    except:
        pass
    return ok
示例#9
0
    def transform(self, x):
        """Transform a vertex using this matrix.

        - `x`: a (3,) or (4,) vector.

        If the vector has length 4, it holds homogeneous coordinates, and
        the result is the dot product of the vector with the Matrix:  x * M.
        If the vector has length 3, the 4th homogeneous coordinate is
        assumed to be 1, and the product is computed in an optimized way.
        """
        try:
            x = at.checkArray(x, (3, ), 'f')
            return np.dot(x, self[:3, :3]) + self[3, :3]
        except:
            x = at.checkArray(x, (4, ), 'f')
            return np.dot(x, self)
示例#10
0
 def __new__(clas,data,mass,ctr):
     """Create a new Tensor instance"""
     ar = Tensor.__new__(clas,data)
     # We need mass and ctr!
     ar.mass = float(mass)
     ar.ctr = Coords(at.checkArray(ctr,shape=(3,),kind='f'))
     return ar
示例#11
0
def convexHull(points):
    """Return the convex hull of a set of points.
    Parameters:

    - `points`: float array (npoints, 2|3): a set of 2D or 3D point coordinates.

    Returns a :class:`Connectivity` containing the indices of the points that constitute the
    convex hull of the given point set. The convex hull is the minimal set of simplices
    enclosing all the points. For a 3D convex hull, the Connectivity will have plexitude 3
    and an eltype 'tri3', while for 2D convex hulls, the Connectivity has plexitude 2 and
    eltype 'line2'.

    This requires SciPy version 0.12.0 or higher. If :func:`scipy.spatial.ConvexHull raises
    an error, an empty connectivity is returned. This happens if all the points of a 3D set
    are in a plane or all the points of a 2D set are on a line.

    """
    software.requireModule('scipy', '0.12.0')
    from scipy.spatial import ConvexHull

    points = at.checkArray(points, ndim=2, kind='f')
    ndim = points.shape[1]
    if ndim not in [2, 3]:
        raise ValueError('Expected 2D or 3D coordinate array')

    try:
        hull = ConvexHull(points).simplices
    except:
        hull = []

    return Connectivity(hull,
                        nplex=ndim,
                        eltype='tri3' if ndim == 3 else 'line2')
示例#12
0
 def __new__(clas,data=None,symmetric=True,cs=None):
     """Create a new Tensor instance"""
     try:
         data = at.checkArray(data,shape=(3,3),kind='f',allow='if')
     except:
         try:
             data = at.checkArray(data,shape=(6,),kind='f',allow='if')
         except:
             raise ValueError("Data should have shape (3,3) or (6,)")
         data = data[Tensor._contracted_index]
     ar = data.view(clas)
     if cs is None:
         cs = CoordSys()
     if not(isinstance(cs,CoordSys)):
         raise ValueError('Wrong Coordinate System')
     ar.cs = cs
     return ar
示例#13
0
    def __init__(self,oab=None,points=None,rot=None,trl=None):
        """Initialize the CoordSys"""
        if oab is not None:
            oab = at.checkArray(oab,(3,3),'f')
            rot = at.rotmat(oab)
            trl = oab[0]
        elif points is not None:
            points = at.checkArray(points,(4,3),'f')
            rot = at.normalize(points[:3] - points[3])
            trl = points[3]
        else:
            if rot is None:
                rot = np.eye(3, 3)
            if trl is None:
                trl = np.zeros((3,))

        self.rot = rot
        self.trl = trl
示例#14
0
 def __new__(clas, data=None):
     """Create a new Matrix instance"""
     if data is None:
         data = np.eye(4, 4)
     else:
         data = at.checkArray(data, (4, 4), 'f')
     ar = data.view(clas)
     ar._gl = None
     return ar
示例#15
0
def write_stl_bin(fn, x, color=None):
    """Write a binary stl.

    Parameters:

    - `x`: (ntri,4,3) float array describin ntri triangles.
      The first item of each triangle is the normal, the other
      three are the vertices.
    - `color`: (4,) int array with values in the range 0..255. These are
      the red, green, blue and alpha components of the color. This is a
      single color for all the triangles, and will be stored in the header
      of the STL file.
    """
    x = checkArray(x, shape=(-1, 4, 3), kind='f')
    if color is not None:
        #color = checkArray(color, shape=(4,), kind='i').astype(np.uint8)
        color = checkArray(color, shape=(4, ), kind='u',
                           allow='i').astype(np.uint8)

    def addTriangle(i):
        x[i].tofile(fil)
        fil.write('\x00\x00')

    print("Writing binary STL %s" % fn)
    ver = pf.fullVersion()
    if len(ver) > 50:
        ver = ver[:50]
    if color is None:
        color = ''
    else:
        color = "COLOR=%4s" % color.tostring()
        print("Adding %s to the header" % color)

    with open(fn, 'wb') as fil:
        head = "%-50s%-30s" % (ver, color)
        fil.write(head)
        ntri = x.shape[0]
        print("Number of triangles: %s" % ntri)
        np.array(ntri).astype(np.int32).tofile(fil)
        x = x.astype(np.float32)
        [addTriangle(i) for i in range(ntri)]
    print("Finished writing binary STL, %s bytes" % utils.fileSize(fn))
示例#16
0
    def rotate(self, angle, axis=None):
        """Rotate a Matrix4.

        The rotation can be specified by

        - an angle and axis,
        - a 3x3 rotation matrix,
        - a 4x4 trtransformation matrix (Matrix4).

        Parameters:

        - `angle`: float: the rotation angle. A 3x3 or 4x4 matrix may be
           give instead, to directly specify the roation matrix.
        - `axis`: int or (3,) float: the axis to rotate around

        Changes the Matrix in place and also returns the result.

        Example:

        >>> Matrix4().rotate(90.,[0.,1.,0.])
        matrix([[ 0.,  0., -1.,  0.],
                [ 0.,  1.,  0.,  0.],
                [ 1.,  0.,  0.,  0.],
                [ 0.,  0.,  0.,  1.]])

        """
        ## !! TRANSPOSE!!
        ## x^2(1-c)+c     xy(1-c)-zs     xz(1-c)+ys     0
        ##  yx(1-c)+zs     y^2(1-c)+c     yz(1-c)-xs     0
        ##  xz(1-c)-ys     yz(1-c)+xs     z^2(1-c)+c     0
        ##       0              0               0        1

        try:
            rot = at.checkArray(angle, (4, 4), 'f')[:3, :3]
        except:
            try:
                rot = at.checkArray(angle, (3, 3), 'f')
            except:
                angle = at.checkFloat(angle)
                rot = np.matrix(at.rotationMatrix(angle, axis))
        self.rot = rot * self.rot
        return self
示例#17
0
    def toEye(self, x):
        """Transform a vertex from world to eye coordinates.

        This transforms the vertex using the current Modelview matrix.

        It is equivalent with multiplying the homogeneous
        coordinates with the Modelview matrix, but is done here
        in an optimized way.
        """
        x = at.checkArray(x, (-1, 3), 'f')
        return np.dot(x, self.modelview[:3, :3]) + self.modelview[3, :3]
示例#18
0
    def focus(self, vector):
        """Set the camera reference point (the focus point).

        The focus is the point the camer is looking at. It is a point on
        the camera's optical axis.

        - `vector`: (3,) float array: the global coordinates of the focus.

        """
        if not self.locked:
            self._focus = at.checkArray(vector, (3, ), 'f')
            self.viewChanged = True
示例#19
0
    def toWorld(self, x):
        """Transform a vertex from eye to world coordinates.

        This transforms the vertex using the inverse of the
        current Modelview matrix.

        It is equivalent with multiplying the homogeneous
        coordinates with the inverse Modelview matrix, but is done
        here in an optimized way.
        """
        x = at.checkArray(x, (3, ), 'f') + [0., 0., self.dist]
        return np.dot(x, self.rot.T) + self.focus
示例#20
0
    def evalAtoms(self, x):
        """Evaluate the monomials at the given points

        x is an (npoints,ndim) array of points where the polynomial is to
        be evaluated. The result is an (npoints,nterms) array of values.
        """
        x = at.checkArray(x, (-1, self.ndim), 'f', 'i')
        symbol = 'xyz'
        g = dict([(symbol[i], x[:, i]) for i in range(self.ndim)])
        atoms = self.atoms(symbol)
        aa = np.zeros((len(x), len(atoms)), at.Float)
        for k, a in enumerate(atoms):
            aa[:, k] = eval(a, g)
        return aa
示例#21
0
    def evalAtoms1(self, x):
        """Evaluate the monomials at the given points

        x is an (npoints,ndim) array of points where the polynomial is to
        be evaluated. The result is an (npoints,nterms) array of values.
        """
        x = at.checkArray(x, (-1, self.ndim), 'f', 'i')
        maxd = self.degrees()
        mon = [at.powers(x[:, j], maxd[j]) for j in range(self.ndim)]
        terms = [[mon[j][e[j]] for j in range(self.ndim)] for e in self.exp]
        terms = np.dstack([
            np.column_stack([mon[j][e[j]] for j in range(self.ndim)])
            for e in self.exp
        ])
        return terms.prod(axis=1)
示例#22
0
def tetrahedral_volume(x):
    """Compute the volume of tetrahedrons.

    - `x`: an (ntet,4,3) shaped float array, representing ntet tetrahedrons.

    Returns an (ntet,) shaped array with the volume of the tetrahedrons.
    Depending on the ordering of the points, this volume may be positive
    or negative. It will be positive if point 4 is on the side of the positive
    normal formed by the first 3 points.
    """
    x = at.checkArray(x,shape=(-1,4,3),kind='f')
    a, b, c = [ x[:,i,:] - x[:,3,:] for i in range(3) ]
    d = np.cross(b, c)
    e = (a*d).sum(axis=-1)
    return -e / 6
示例#23
0
    def translateTo(self,ref,toG=False):
        """Return the inertia tensor around axes translated to the reference
        point ref.

        Parameters:

        - `ref`: arraylike (3,). The new reference point coordinates.
        - `toG`: bool. If False (default) the inertia tensor is translated to the
          the  new reference point, otherwise it will be translated to its center
          of mass

        """

        trl = at.checkArray(ref,shape=(3,),kind='f') - self.ctr
        return self.translate(self,trl,toG=toG)
示例#24
0
def reduceAdjacency(adj):
    """Reduce an adjacency table.

    An adjacency table is an integer array where each row lists the numbers
    of the items that are connected to the item with number equal to the row
    index. Rows are padded with -1 values to create rows of equal length.

    A reduced adjacency table is one where each row:

    - does not contain the row index itself,
    - does not contain duplicates,
    - is sorted in ascending order,

    and that has at least one row without -1 value.

    Paramaters:

    - `adj`: an 2-D integer array with value >=0 or -1

    Returns: an integer array with shape (adj.shape[0],maxc), with
    maxc <= adj.shape[1], where row `i` retains the unique non-negative
    numbers of the original array except the value `i`, and is possibly
    padded with -1 values.

    Example:

      >>> a = np.array([[ 0,  0,  0,  1,  2,  5],
      ...               [-1,  0,  1, -1,  1,  3],
      ...               [-1, -1,  0, -1, -1,  2],
      ...               [-1, -1,  1, -1, -1,  3],
      ...               [-1, -1, -1, -1, -1, -1],
      ...               [-1, -1,  0, -1, -1,  5]])
      >>> reduceAdjacency(a)
      array([[ 1,  2,  5],
             [-1,  0,  3],
             [-1, -1,  0],
             [-1, -1,  1],
             [-1, -1, -1],
             [-1, -1,  0]])

    """
    adj = at.checkArray(adj, ndim=2)
    n = adj.shape[0]
    adj[adj == np.arange(n).reshape(n, -1)] = -1  # remove the item i
    adj = sortAdjacency(adj)
    adj[np.where(adj[:, :-1] == adj[:, 1:])] = -1  #remove duplicate items
    adj = sortAdjacency(adj)
    return adj
示例#25
0
def surface_volume_inertia(x,center_only=False):
    """Return the inertia of the volume inside a 3-plex Formex.

    - `x`: an (ntri,3,3) shaped float array, representing ntri triangles.

    This uses the same algorithm as tetrahedral_inertia using [0.,0.,0.]
    as the 4-th point for each tetrahedron.

    Returns a tuple (V,C,I) where V is the total volume,
    C is the center of mass (3,) and I is the inertia tensor (6,) of the
    tetrahedral model.

    Example:

    >>> from .simple import sphere
    >>> S = sphere(4).toFormex()
    >>> V,C,I = surface_volume_inertia(S.coords)
    >>> print(V,C,I)
    4.04701 [-0. -0. -0.] [ 1.58  1.58  1.58 -0.    0.    0.  ]

    """
    def K(x,y):
        x1,x2,x3 = x[:,0], x[:,1], x[:,2]
        y1,y2,y3 = y[:,0], y[:,1], y[:,2]
        return x1 * (y1+y2+y3) + \
               x2 * (   y2+y3) + \
               x3 * (      y3)

    x = at.checkArray(x,shape=(-1,3,3),kind='f')
    v = surface_volume(x)
    V = v.sum()
    c = x.sum(axis=1) / 4.  # 4-th point is 0.,0.,0.
    C = (c*v[:,np.newaxis]).sum(axis=0) / V
    if center_only:
        return V,C

    x -= C
    aa = 2 * K(x,x) * v.reshape(-1,1)
    aa = aa.sum(axis=0)
    a0 = aa[1] + aa[2]
    a1 = aa[0] + aa[2]
    a2 = aa[0] + aa[1]
    x0,x1,x2 = x[...,0],x[...,1],x[...,2]
    a3 = (( K(x1,x2) + K(x2,x1) ) * v).sum(axis=0)
    a4 = (( K(x2,x0) + K(x0,x2) ) * v).sum(axis=0)
    a5 = (( K(x0,x1) + K(x1,x0) ) * v).sum(axis=0)
    I = np.array([a0,a1,a2,a3,a4,a5]) / 20.
    return V,C,I
示例#26
0
    def __init__(self, data, type):
        """Initialize the UniaxialStrain"""

        data = checkArray(data, shape=(-1, ), kind='f')
        if type == 'nominal':
            data = data + 1.
        elif type == 'log':
            data = np.exp(data)
        elif type == 'green':
            data = sqrt(2 * data + 1.)
        elif type == 'almansi':
            data = 1. / sqrt(1. - 2 * data)
        elif type != 'stretch':
            raise ValueError("Invalid strain type: %s" % type)

        self.data = data
示例#27
0
    def __init__(self, data, type, strain, straintype=None):
        """Initialize the UniaxialStress"""

        data = checkArray(data, shape=(-1, ), kind='f')
        if not isinstance(strain, UniaxialStrain):
            strain = UniaxialStrain(strain, straintype)
        stretch = strain.stretch()
        if type == 'nominal':
            data = data * stretch
        elif type == 'pk2':
            data = data * stretch**2
        elif type != 'cauchy':
            raise ValueError("Invalid stress type: %s" % type)

        self.data = data
        self.strain = strain
示例#28
0
def inverseIndex(ind, sort=False, expand=False):
    """Create the inverse of a 2D index array.

    Parameters:

    - `ind`: a Varray or a 2D index array. A 2D index array is a 2D integer
      array where only nonnegative values are significant and negative
      values are silently ignored.
      While in most cases all values in a row are unique, this is not a
      requirement. Degenerate elements may have the same node number
      appearing multiple times in the same row.
    - `sort`: bool. If True, rows are sorted.
    - `expand`: bool. If True, an :class:`numpy.ndarray` is returned.

    Returns the inverse index, as a Varray (default) or as an ndarray (if
    expand is True). If sort is True, rows are sorted.

    Example:

      >>> a = inverseIndex([[0,1],[0,2],[1,2],[0,3]])
      >>> print(a)
      Varray (4,3)
        [0 1 3]
        [0 2]
        [1 2]
        [3]
      <BLANKLINE>
    """
    if isinstance(ind, Varray):
        ind = ind.toArray()
    ind = at.checkArray(ind, ndim=2, kind='i')
    b = np.resize(np.arange(ind.shape[0]), ind.shape[::-1])
    c = at.stack([ind, b.transpose()]).reshape(2, -1)
    s = c[0].argsort()
    t = c[0][s]
    u = c[1][s]
    v = t.searchsorted(np.arange(t.max() + 1))
    if v[0] > 0:
        # There were negative numbers: remove them
        u = u[v[0]:]
        v -= v[0]
    va = Varray(u, v)
    if sort:
        va.sort()
    if expand:
        return va.toArray()
    return va
示例#29
0
def saveGreyImage(a, f, flip=True):
    """Save a 2D int array as a grey image.

    Parameters:

    - `a`: int array (nx,ny) with values in the range 0..255. These are
      the grey values of the pixels.
    - `f`: filename
    - `flip`: by default, the vertical axis is flipped, so that images are
      stored starting at the top. If your data already have the vertical axis
      downwards, use flip=False.

    """
    a = at.checkArray(a, ndim=2, kind='u', allow='i').astype(np.uint8)
    c = np.flipud(a)
    c = np.dstack([c, c, c])
    im = numpy2qimage(c)
    im.save(f)
示例#30
0
    def translate(self, vector):
        """Translate a 4x4 matrix by a (3,) vector.

        - `vector`: (3,) float array: the translation vector

        Changes the Matrix in place and also returns the result

        Example:

        >>> Matrix4().translate([1.,2.,3.])
        matrix([[ 1.,  0.,  0.,  0.],
                [ 0.,  1.,  0.,  0.],
                [ 0.,  0.,  1.,  0.],
                [ 1.,  2.,  3.,  1.]])
        """
        vector = at.checkArray(vector, (3, ), 'f')
        self.trl += vector * self.rot
        return self