Beispiel #1
0
def sector(r, t, nr, nt, h=0., diag=None):
    """Constructs a Formex which is a sector of a circle/cone.

    A sector with radius r and angle t is modeled by dividing the
    radius in nr parts and the angle in nt parts and then creating
    straight line segments.
    If a nonzero value of h is given, a conical surface results with its
    top at the origin and the base circle of the cone at z=h.
    The default is for all points to be in the (x,y) plane.


    By default, a plex-4 Formex results. The central quads will collapse
    into triangles.
    If diag='up' or diag = 'down', all quads are divided by an up directed
    diagonal and a plex-3 Formex results.
    """
    r = float(r)
    t = float(t)
    p = Formex(regularGrid([0., 0., 0.], [r, 0., 0.], [nr, 0, 0],swapaxes=True).reshape(-1, 3))
    if h != 0.:
        p = p.shear(2, 0, h / r)
    q = p.rotate(t / nt)
    if isinstance(diag, str):
        diag = diag[0]
    if diag == 'u':
        F = connect([p, p, q], bias=[0, 1, 1]) + \
            connect([p, q, q], bias=[1, 2, 1])
    elif diag == 'd':
        F = connect([q, p, q], bias=[0, 1, 1]) + \
            connect([p, p, q], bias=[1, 2, 1])
    else:
        F = connect([p, p, q, q], bias=[0, 1, 1, 0])

    F = Formex.concatenate([F.rotate(i * t / nt) for i in range(nt)])
    return F
Beispiel #2
0
def Cube():
    """Create the surface of a cube

    Returns a TriSurface representing the surface of a unit cube.
    Each face of the cube is represented by two triangles.
    """
    from pyformex.trisurface import TriSurface
    back = Formex('3:012934')
    fb = back.reverse() + back.translate(2, 1)
    faces = fb + fb.rollAxes(1) + fb.rollAxes(2)
    return TriSurface(faces)
Beispiel #3
0
def boxes(x):
    """Create a set of cuboid boxes.

    `x`: Coords with shape (nelems,2,3), usually with x[:,0,:] < x[:,1,:]

    Returns a Formex with shape (nelems,8,3) and of type 'hex8',
    where each element is the cuboid box which has x[:,0,:]
    as its minimum coordinates and x[:,1,:] as the maximum ones.
    Note that the elements may be degenerate or reverted if the minimum
    coordinates are not smaller than the maximum ones.

    This function can be used to visualize the bboxes() of a geometry.
    """
    x = Coords(x).reshape(-1, 2, 3)
    i = [[0, 0, 0],
         [1, 0, 0],
         [1, 1, 0],
         [0, 1, 0],
         [0, 0, 1],
         [1, 0, 1],
         [1, 1, 1],
         [0, 1, 1]]

    j = [0, 1, 2]

    return Formex(x[:, i, j], eltype='hex8')
Beispiel #4
0
def boxes2d(x):
    """Create a set of rectangular boxes.

    Parameters:

    - `x`: Coords with shape (nelems,2,3), usually with x[:,0,:] < x[:,1,:]
      and x[:,:,2] == 0.

    Returns a Formex with shape (nelems,4,3) and of type 'quad4',
    where each element is the rectangular box which has x[:,0,:]
    as its minimum coordinates and x[:,1,:] as the maximum ones.
    Note that the elements may be degenerate or reverted if the minimum
    coordinates are not smaller than the maximum ones.

    This function is a 2D version of :meth:`bboxes`.
    """
    x = Coords(x).reshape(-1, 2, 3)
    i = [[0, 0, 0],
         [1, 0, 0],
         [1, 1, 0],
         [0, 1, 0]]

    j = [0, 1, 2]

    return Formex(x[:, i, j], eltype='quad4')
Beispiel #5
0
def line(p1=[0., 0., 0.], p2=[1., 0., 0.], n=1):
    """Return a Formex which is a line between two specified points.

    p1: first point, p2: second point
    The line is split up in n segments.
    """
    return Formex([[p1, p2]]).divide(n)
Beispiel #6
0
def triangle():
    """An equilateral triangle with base [0,1] on axis 0.

    Returns an equilateral triangle with side length 1.
    The first point is the origin, the second points is on the axis 0.
    The return value is a plex-3 Formex.
    """
    return Formex([[[0., 0., 0.], [1., 0., 0.], [0.5, 0.5 * sqrt(3.), 0.]]])
Beispiel #7
0
 def __init__(self,
              x1,
              y1,
              x2,
              y2,
              nx=1,
              ny=1,
              lighting=False,
              rendertype=2,
              **kargs):
     F = Formex([[[x1,y1],[x1,y2]]]).replic(nx+1,step=float(x2-x1)/nx,dir=0) + \
         Formex([[[x1,y1],[x2,y1]]]).replic(ny+1,step=float(y2-y1)/ny,dir=1)
     Actor.__init__(self,
                    F,
                    rendertype=rendertype,
                    lighting=lighting,
                    **kargs)
Beispiel #8
0
def sphere3(nx, ny, r=1, bot=-90., top=90.):
    """Return a sphere consisting of surface triangles

    A sphere with radius r is modeled by the triangles formed by a regular
    grid of nx longitude circles, ny latitude circles and their diagonals.

    The two sets of triangles can be distinguished by their property number:
    1: horizontal at the bottom, 2: horizontal at the top.

    The sphere caps can be cut off by specifying top and bottom latitude
    angles (measured in degrees from 0 at north pole to 180 at south pole.
    """
    base = Formex([[[0, 0, 0], [1, 0, 0], [1, 1, 0]],
                   [[1, 1, 0], [0, 1, 0], [0, 0, 0]]],
                  [1, 2])
    grid = base.replic2(nx, ny, 1, 1)
    s = float(top - bot) / ny
    return grid.translate([0, bot / s, 1]).spherical(scale=[360. / nx, s, r])
Beispiel #9
0
def sphere2(nx, ny, r=1, bot=-90, top=90):
    """Return a sphere consisting of line elements.

    A sphere with radius r is modeled by a regular grid of nx
    longitude circles, ny latitude circles and their diagonals.

    The 3 sets of lines can be distinguished by their property number:
    1: diagonals, 2: meridionals, 3: horizontals.

    The sphere caps can be cut off by specifying top and bottom latitude
    angles (measured in degrees from 0 at north pole to 180 at south pole.
    """
    base = Formex('l:543', [1, 2, 3])           # single cell
    d = base.select([0]).replic2(nx, ny, 1, 1)   # all diagonals
    m = base.select([1]).replic2(nx, ny, 1, 1)   # all meridionals
    h = base.select([2]).replic2(nx, ny + 1, 1, 1)  # all horizontals
    grid = m + d + h
    s = float(top - bot) / ny
    return grid.translate([0, bot / s, 1]).spherical(scale=[360. / nx, s, r])
Beispiel #10
0
def shape(name):
    """Return a Formex with one of the predefined named shapes.

    This is a convenience function returning a plex-2 Formex constructed
    from one of the patterns defined in the simple.Pattern dictionary.
    Currently, the following pattern names are defined:
    'line', 'angle', 'square', 'plus', 'cross', 'diamond', 'rtriangle', 'cube',
    'star', 'star3d'.
    See the Pattern example.
    """
    return Formex(Pattern[name])
Beispiel #11
0
 def __init__(self,
              n=(1.0, 0.0, 0.0),
              P=(0.0, 0.0, 0.0),
              sz=(1., 1., 0.),
              color='white',
              alpha=0.5,
              mode='flatwire',
              linecolor='black',
              **kargs):
     """A plane perpendicular to the x-axis at the origin."""
     from pyformex.formex import Formex
     F = Formex('4:0123').replic2(2, 2).centered().scale(sz).rotate(
         90., 1).rotate(at.rotMatrix(n)).trl(P)
     F.attrib(mode=mode,
              lighting=False,
              color=color,
              alpha=alpha,
              linecolor=linecolor)
     print("kargs")
     print(kargs)
     Actor.__init__(self, F, **kargs)
Beispiel #12
0
def read_gts_intersectioncurve(fn):
    import re
    from pyformex.formex import Formex
    RE = re.compile("^VECT 1 2 0 2 0 (?P<data>.*)$")
    r = []
    for line in open(fn, 'r'):
        m = RE.match(line)
        if m:
            r.append(m.group('data'))
    nelems = len(r)
    x = fromstring('\n'.join(r), sep=' ').reshape(-1, 2, 3)
    F = Formex(x)
    return F
Beispiel #13
0
def setTriade(on=None,pos='lb',siz=50,triade=None):
    """Toggle the display of the global axes on or off.

    This is a convenient feature to display the global axes
    directions with rotating actor at fixed viewport size and
    position.

    Parameters:

    - `on`: boolean. If True, the global axes triade is displayed. If
      False, it is removed. The default (None) toggles between on and off.
      The remaining parameters are only used on enabling the triade.
    - `pos`: string of two characters. The characters define the horizontal
      (one of 'l', 'c', or 'r') and vertical (one of 't', 'c', 'b') position
      on the camera's viewport. Default is left-bottom.
    - `siz`: size (in pixels) of the triade.
    - `triade`: None, Geometry or str: defines the Geometry to be used for
      representing the global axes.

      If None: use the previously set triade, or set a default if no
      previous.

      If Geometry: use this to represent the axes. To be useful and properly
      displayed, the Geometry's bbox should be around [(-1,-1,-1),(1,1,1)].
      Drawing attributes may be set on the Geometry to influence
      the appearence. This allows to fully customize the Triade.

      If str: use one of the predefined Triade Geometries. Currently, the
      following are available:

      - 'axes': axes and coordinate planes as in :class:`candy.Axes`
      - 'man': a model of a man as in data file 'man.pgf'

    """
    if on is None:
        on = not pf.canvas.hasTriade()
    if on:
        if triade is None and pf.canvas.triade is None:
            triade = 'axes'
        if triade == 'axes':
            from pyformex import candy
            triade = candy.Axes(reverse=False)
        elif triade == 'man':
            triade = Formex.read(os.path.join(pf.cfg['datadir'],'man.pgf'))
            print(type(triade))
            print(triade.attrib)
        pf.canvas.setTriade(pos,siz,triade)
    else:
        pf.canvas.removeTriade()
    pf.canvas.update()
    pf.app.processEvents()
Beispiel #14
0
def inside(self,pts,atol='auto',multi=True):
    """Test which of the points pts are inside the surface.

    Parameters:

    - `pts`: a (usually 1-plex) Formex or a data structure that can be used
      to initialize a Formex.

    Returns an integer array with the indices of the points that are
    inside the surface. The indices refer to the onedimensional list
    of points as obtained from pts.points().
    """
    from pyformex.formex import Formex
    if not isinstance(pts, Formex):
        pts = Formex(pts)

    if atol == 'auto':
        atol = pts.dsize()*0.001

    # determine bbox of common space of surface and points
    bb = bboxIntersection(self, pts)
    if (bb[0] > bb[1]).any():
        # No bbox intersection: no points inside
        return array([], dtype=Int)

    # Limit the points to the common part
    # Add point numbers as property, to allow return of original numbers
    pts.setProp(arange(pts.nelems()))
    pts = pts.clip(testBbox(pts, bb, atol=atol))

    ins = zeros((3, pts.nelems()), dtype=bool)
    if pf.scriptMode == 'script' or not multi:
        for i in range(3):
            dirs = roll(arange(3), -i)[1:]
            # clip the surface perpendicular to the shooting direction
            # !! gtsinside seems to fail sometimes when using clipping
            S = self#.clip(testBbox(self,bb,dirs=dirs,atol=atol),compact=False)
            # find inside points shooting in direction i
            ok = gtsinside(S, pts, dir=i)
            ins[i, ok] = True
    else:
        tasks = [(gtsinside, (self, pts, i)) for i in range(3)]
        ind = multitask(tasks, 3)
        for i in range(3):
            ins[i, ind[i]] = True

    ok = where(ins.sum(axis=0) > 1)[0]
    return pts.prop[ok]
Beispiel #15
0
    def __init__(self,val,pos,prefix='',**kargs):
        # Make sure we have strings
        val = [ str(i) for i in val ]
        pos = at.checkArray(pos,shape=(len(val),-1))
        if len(val) != pos.shape[0]:
            raise ValueError("val and pos should have same length")

        # concatenate all strings
        val = [ prefix+str(v) for v in val ]
        cs = at.cumsum([0,] + [ len(v) for v in val ])
        val = ''.join(val)
        nc = cs[1:] - cs[:-1]

        pos = [ at.multiplex(p,n,0) for p,n in zip(pos,nc) ]
        pos = np.concatenate(pos,axis=0)
        pos = at.multiplex(pos,4,1)

        # Create the grids for the strings
        F = Formex('4:0123')
        grid = Formex.concatenate([ F.replic(n) for n in nc ])

        # Create a text with the concatenation
        Text.__init__(self,val,pos=pos,grid=grid,**kargs)
Beispiel #16
0
    def readFormex(self, nelems, nplex, props, eltype, sep):
        """Read a Formex from a pyFormex geometry file.

        The coordinate array for nelems*nplex points is read from the file.
        If present, the property numbers for nelems elements are read.
        From the coords and props a Formex is created and returned.
        """
        ndim = 3
        f = at.readArray(self.fil, at.Float, (nelems, nplex, ndim), sep=sep)
        if props:
            p = at.readArray(self.fil, at.Int, (nelems,), sep=sep)
        else:
            p = None
        return Formex(f, p, eltype)
Beispiel #17
0
def connectCurves(curve1, curve2, n):
    """Connect two curves to form a surface.

    curve1, curve2 are plex-2 Formices with the same number of elements.
    The two curves are connected by a surface of quadrilaterals, with n
    elements in the direction between the curves.
    """
    if curve1.nelems() != curve2.nelems():
        raise ValueError("Both curves should have same number of elements")
    # Create the interpolations
    curves = interpolate(curve1, curve2, n).split(curve1.nelems())
    quads = [connect([c1, c1, c2, c2], nodid=[0, 1, 1, 0])
             for c1, c2 in zip(curves[:-1], curves[1:])]
    return Formex.concatenate(quads)
Beispiel #18
0
def rectangle(nx=1, ny=1, b=None, h=None, bias=0., diag=None):
    """Return a Formex representing a rectangular surface.

    The rectangle has a size(b,h) divided into (nx,ny) cells.

    The default b/h values are equal to nx/ny, resulting in a modular grid.
    The rectangle lies in the (x,y) plane, with one corner at [0,0,0].
    By default, the elements are quads. By setting diag='u','d' of 'x',
    diagonals are added in /, resp. \ and both directions, to form triangles.
    """
    if diag == 'x':
        base = Formex([[[0.0, 0.0, 0.0], [1.0, -1.0, 0.0], [1.0, 1.0, 0.0]]]).rosette(4, 90.).translate([-1.0, -1.0, 0.0]).scale(0.5)
    else:
        base = Formex({'u': '3:012934', 'd': '3:016823'}.get(diag, '4:0123'))
    if b is None:
        sx = 1.
    else:
        sx = float(b) / nx
    if h is None:
        sy = 1.
    else:
        sy = float(h) / ny
    return base.replic2(nx, ny, bias=bias).scale([sx, sy, 0.])
Beispiel #19
0
def drawImage3D(image,nx=0,ny=0,pixel='dot'):
    """Draw an image as a colored Formex

    Draws a raster image as a colored Formex. While there are other and
    better ways to display an image in pyFormex (such as using the imageView
    widget), this function allows for interactive handling the image using
    the OpenGL infrastructure.

    Parameters:

    - `image`: a QImage or any data that can be converted to a QImage,
      e.g. the name of a raster image file.
    - `nx`,`ny`: width and height (in cells) of the Formex grid.
      If the supplied image has a different size, it will be rescaled.
      Values <= 0 will be replaced with the corresponding actual size of
      the image.
    - `pixel`: the Formex representing a single pixel. It should be either
      a single element Formex, or one of the strings 'dot' or 'quad'. If 'dot'
      a single point will be used, if 'quad' a unit square. The difference
      will be important when zooming in. The default is 'dot'.

    Returns the drawn Actor.

    See also :func:`drawImage`.
    """
    pf.GUI.setBusy()
    from pyformex.plugins.imagearray import qimage2glcolor, resizeImage
    from pyformex.opengl.colors import GLcolorA

    # Create the colors
    #print("TYPE %s" % type(image))
    if isinstance(image,np.ndarray):
        # undocumented feature: allow direct draw of 2d array
        color = GLcolorA(image)
        nx,ny = color.shape[:2]
        colortable = None
        print(color)
    else:
        image = resizeImage(image, nx, ny)
        nx, ny = image.width(), image.height()
        color, colortable = qimage2glcolor(image)

    # Create a 2D grid of nx*ny elements
    # !! THIS CAN PROBABLY BE DONE FASTER
    if isinstance(pixel, Formex) and pixel.nelems()==1:
        F = pixel
    elif pixel == 'quad':
        F = Formex('4:0123')
    else:
        F = Formex('1:0')
    F = F.replic2(nx, ny).centered()
    F._imageshape_ = (nx,ny)

    # Draw the grid using the image colors
    FA = draw(F, color=color, colormap=colortable, nolight=True)
    pf.GUI.setBusy(False)
    return FA
Beispiel #20
0
def circle(a1=2., a2=0., a3=360., r=None, n=None, c=None, eltype='line2'):
    """A polygonal approximation of a circle or arc.

    All points generated by this function lie on a circle with unit radius at
    the origin in the x-y-plane.

    - `a1`: the angle enclosed between the start and end points of each line
      segment (dash angle).
    - `a2`: the angle enclosed between the start points of two subsequent line
      segments (module angle). If ``a2==0.0``, `a2` will be taken equal to `a1`.
    - `a3`: the total angle enclosed between the first point of the first
      segment and the end point of the last segment (arc angle).

    All angles are given in degrees and are measured in the direction from
    x- to y-axis. The first point of the first segment is always on the x-axis.

    The default values produce a full circle (approximately).
    If $a3 < 360$, the result is an arc.
    Large values of `a1` and `a2` result in polygons. Thus
    `circle(120.)` is an equilateral triangle and `circle(60.)`
    is regular hexagon.

    Remark that the default a2 == a1 produces a continuous line,
    while a2 > a1 results in a dashed line.

    Three optional arguments can be added to scale and position the circle
    in 3D space:

    - `r`: the radius of the circle
    - `n`: the normal on the plane of the circle
    - `c`: the center of the circle
    """
    if a2 == 0.0:
        a2 = a1
    ns = round(a3/a2)
    a1 *= pi/180.
    if eltype=='line2':
        F = Formex([[[1., 0., 0.], [cos(a1), sin(a1), 0.]]]).rosette(ns, a2, axis=2, point=[0., 0., 0.])
    elif eltype=='line3':
        F = Formex([[[1., 0., 0.], [cos(a1/2.), sin(a1/2.), 0.], [cos(a1), sin(a1), 0.]]], eltype=eltype).rosette(ns, a2, axis=2, point=[0., 0., 0.])
    if r is not None:
        F = F.scale(r)
    if n is not None:
        F = F.swapAxes(0, 2).rotate(rotMatrix(n))
    if c is not None:
        F = F.trl(c)
    return F
Beispiel #21
0
def rect(p1=[0., 0., 0.], p2=[1., 0., 0.], nx=1, ny=1):
    """Return a Formex which is a the circumference of a rectangle.

    p1 and p2 are two opposite corner points of the rectangle.
    The edges of the rectangle are in planes parallel to the z-axis.
    There will always be two opposite edges that are parallel with the x-axis.
    The other two will only be parallel with the y-axis if both points
    have the same z-value, but in any case they will be parallel with the
    y-z plane.

    The edges parallel with the x-axis are divide in nx parts, the other
    ones in ny parts.
    """
    p1 = Coords(p1)
    p2 = Coords(p2)
    p12 = Coords([p2[0], p1[1], p1[2]])
    p21 = Coords([p1[0], p2[1], p2[2]])
    return Formex.concatenate([
        line(p1, p12, nx),
        line(p12, p2, ny),
        line(p2, p21, nx),
        line(p21, p1, ny)
    ])
Beispiel #22
0
    def __init__(self,text,pos,gravity=None,size=18,width=None,font=None,lineskip=1.0,grid=None,texmode=4,**kargs):
        """Initialize the Text actor."""

        # split the string on newlines
        text = str(text).split('\n')

        # set pos and offset3d depending on pos type (2D vs 3D rendering)
        pos = at.checkArray(pos)
        if pos.shape[-1] == 2:
            rendertype = 2
            pos = [pos[0],pos[1],0.]
            offset3d = None
        else:
            rendertype = 1
            offset3d = Coords(pos)
            pos = [0.,0.,0.]
            if offset3d.ndim > 1:
                if offset3d.shape[0] != len(text[0]):
                    raise ValueError("Length of text(%s) and pos(%s) should match!" % (len(text),len(pos)))
                # Flag vertex offset to shader
                rendertype = -1

        # set the font characteristics
        if font is None:
            font = FontTexture.default(size)
        if isinstance(font,(str,unicode)):
            font = FontTexture(font,size)
        if width is None:
            #print("Font %s / %s" % (font.height,font.width))
            aspect = float(font.width) / font.height
            width = size * aspect
        self.width = width

        # set the alignment
        if gravity is None:
            gravity = 'E'
        alignment = ['0','0','0']
        if 'W' in gravity:
            alignment[0] = '+'
        elif 'E' in gravity:
            alignment[0] = '-'
        if 'S' in gravity:
            alignment[1] = '+'
        elif 'N' in gravity:
            alignment[1] = '-'
        alignment = ''.join(alignment)

        # record the lengths of the lines, join all characters
        # together, create texture coordinates for all characters
        # create a geometry grid for the longest line
        lt = [ len(t) for t in text ]
        text = ''.join(text)
        texcoords = font.texCoords(text)
        if grid is None:
            grid = Formex('4:0123').replic(max(lt))
        grid = grid.scale([width,size,0.])

        # create the actor for the first line
        l = lt[0]
        g = grid.select(range(l)).align(alignment,pos)
        Actor.__init__(self,g,rendertype=rendertype,texture=font,texmode=texmode,texcoords=texcoords[:l],opak=False,ontop=True,offset3d=offset3d,**kargs)

        for k in lt[1:]:
            # lower the canvas y-value
            pos[1] -= font.height * lineskip
            g = grid.select(range(k)).align(alignment,pos)
            C = Actor(g,rendertype=rendertype,texture=font,texmode=texmode,texcoords=texcoords[l:l+k],opak=False,ontop=True,offset3d=offset3d,**kargs)
            self.children.append(C)
            # do next line
            l += k
Beispiel #23
0
def tetrahedral_inertia(x,density=None,center_only=False):
    """Return the inertia of the volume of a 4-plex Formex.

    Parameters:

    - `x`: an (ntet,4,3) shaped float array, representing ntet tetrahedrons.
    - `density`: optional mass density (ntet,) per tetrahedron
    - `center_only`: bool. If True, returns only the total volume, total mass
      and center of gravity. This may be used on large models when only these
      quantities are required.

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

    Formulas for inertia were based on F. Tonon, J. Math & Stat, 1(1):8-11,2005

    Example:

    >>> x = Coords([
    ...     [  8.33220, -11.86875,  0.93355 ],
    ...     [  0.75523,   5.00000, 16.37072 ],
    ...     [ 52.61236,   5.00000, -5.38580 ],
    ...     [  2.000000,  5.00000,  3.00000 ],
    ...     ])
    >>> F = Formex([x])
    >>> print(tetrahedral_center(F.coords))
    [ 15.92   0.78   3.73]
    >>> print(tetrahedral_volume(F.coords))
    [ 1873.23]
    >>> print(*tetrahedral_inertia(F.coords))
    1873.23 1873.23 [ 15.92   0.78   3.73] [  43520.32  194711.28  191168.77    4417.66  -46343.16   11996.2 ]

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

    x = at.checkArray(x,shape=(-1,4,3),kind='f')
    v = tetrahedral_volume(x)
    V = v.sum()
    if density:
        v *= density
    c = Formex(x).centroids()
    M = v.sum()
    C = (c*v[:,np.newaxis]).sum(axis=0) / M
    if center_only:
        return V,M,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,M,C,I
Beispiel #24
0
 def __init__(self,pos,tex,size,opak=False,ontop=True,**kargs):
     self.pos = pos
     F = Formex([[[0,0],[1,0],[1,1],[0,1]]]).scale(size).align('000')
     Actor.__init__(self,F,rendertype=1,texture=tex,texmode=4,offset3d=pos,opak=opak,ontop=ontop,lighting=False,**kargs)
Beispiel #25
0
 def __init__(self, x1, y1, x2, y2, **kargs):
     F = Formex([[[x1, y1], [x2, y2]]])
     Actor.__init__(self, F, rendertype=2, **kargs)
Beispiel #26
0
 def __init__(self, data, color=None, linewidth=None, **kargs):
     """Initialize a Lines."""
     F = Formex(data)
     Actor.__init__(self, F, rendertype=2, **kargs)
Beispiel #27
0
def point(x=0., y=0., z=0.):
    """Return a Formex which is a point, by default at the origin.

    Each of the coordinates can be specified and is zero by default.
    """
    return Formex([[[x, y, z]]])
Beispiel #28
0
 def toFormex(self):
     from pyformex.formex import Formex
     x = stack([self.coords, roll(self.coords, -1, axis=0)], axis=1)
     return Formex(x)
Beispiel #29
0
    def area(self):
        """Compute area inside a polygon.

        """
        from pyformex.plugins.section2d import PlaneSection
        return PlaneSection(Formex(self.coords)).sectionChar()['A']
Beispiel #30
0
def Grid(nx=(1, 1, 1),
         ox=(0.0, 0.0, 0.0),
         dx=(1.0, 1.0, 1.0),
         lines='b',
         planes='b',
         linecolor=colors.black,
         planecolor=colors.white,
         alpha=0.3,
         **kargs):
    """Creates a (set of) grid(s) in (some of) the coordinate planes.

    Parameters:

    - `nx`: a list of 3 integers, specifying the number of divisions of the
      grid in the three coordinate directions. A zero value may be specified
      to avoid the grid to extend in that direction. Thus, setting the last
      value to zero will result in a planar grid in the xy-plane.
    - `ox`: a list of 3 floats: the origin of the grid.
    - `dx`: a list of 3 floats: the step size in each coordinate direction.
    - `planes`: one of 'first', 'box', 'all', 'no' (the string can be
      shortened to the first chartacter): specifies how many planes are
      drawn in each direction: 'f' only draws the first, 'b' draws the first
      and the last, resulting in a box, 'a' draws all planes,
      'n' draws no planes.

    Returns a list with up to two Meshes: the planes, and the lines.

    """
    from pyformex import simple
    from pyformex.olist import List
    from pyformex.mesh import Mesh
    G = List()

    planes = planes[:1].lower()
    P = []
    L = []
    for i in range(3):
        n0, n1, n2 = np.roll(nx, i)
        d0, d1, d2 = np.roll(dx, i)
        if n0 * n1:
            if planes != 'n':
                M = simple.rectangle(b=n0 * d0, h=n1 * d1)
                if n2:
                    if planes == 'b':
                        M = M.replic(2, dir=2, step=n2 * d2)
                    elif planes == 'a':
                        M = M.replic(n2 + 1, dir=2, step=d2)
                P.append(M.rollAxes(-i).toMesh())
            if lines != 'n':
                M = Formex('1').scale(n0*d0).replic(n1+1,dir=1,step=d1) + \
                    Formex('2').scale(n1*d1).replic(n0+1,dir=0,step=d0)
                if n2:
                    if lines == 'b':
                        M = M.replic(2, dir=2, step=n2 * d2)
                    elif lines == 'a':
                        M = M.replic(n2 + 1, dir=2, step=d2)

                L.append(M.rollAxes(-i).toMesh())

    if P:
        M = Mesh.concatenate(P)
        M.attrib(name='__grid_planes__',
                 mode='flat',
                 lighting=False,
                 color=planecolor,
                 alpha=alpha,
                 **kargs)
        G.append(M)
    if L:
        M = Mesh.concatenate(L)
        M.attrib(name='__grid_lines__',
                 mode='flat',
                 lighting=False,
                 color=linecolor,
                 alpha=0.6,
                 **kargs)
        G.append(M)

    return G.trl(ox)