scallop dome pyformex logo

Previous topic

62. tools — tools.py

Next topic

64. turtle — Turtle graphics for pyFormex

[FSF Associate Member]

Valid XHTML 1.0 Transitional

63. trisurface — Operations on triangulated surfaces.

A triangulated surface is a surface consisting solely of triangles. Any surface in space, no matter how complex, can be approximated with a triangulated surface.

Classes defined in module trisurface

class trisurface.TriSurface(*args, **kargs)

A class representing a triangulated 3D surface.

The surface contains ntri triangles, each having 3 vertices with 3 coordinates. The surface can be initialized from one of the following:

  • a (ntri,3,3) shaped array of floats
  • a Formex with plexitude 3
  • a Mesh with plexitude 3
  • an (ncoords,3) float array of vertex coordinates and an (ntri,3) integer array of vertex numbers
  • an (ncoords,3) float array of vertex coordinates, an (nedges,2) integer array of vertex numbers, an (ntri,3) integer array of edges numbers.

Additionally, a keyword argument prop= may be specified to set property values.

nedges()

Return the number of edges of the TriSurface.

nfaces()

Return the number of faces of the TriSurface.

vertices()

Return the coordinates of the nodes of the TriSurface.

shape()

Return the number of points, edges, faces of the TriSurface.

getElemEdges()

Get the faces’ edge numbers.

setCoords(coords)

Change the coords.

setElems(elems)

Change the elems.

setEdgesAndFaces(edges, faces)

Change the edges and faces.

append(S)

Merge another surface with self.

This just merges the data sets, and does not check whether the surfaces intersect or are connected! This is intended mostly for use inside higher level functions.

classmethod read(clas, fn, ftype=None)

Read a surface from file.

If no file type is specified, it is derived from the filename extension. Currently supported file types:

  • .stl (ASCII or BINARY)
  • .gts
  • .off
  • .neu (Gambit Neutral)
  • .smesh (Tetgen)

Gzipped .stl, .gts and .off files are also supported. Their names should be the normal filename with ‘.gz’ appended. These files are uncompressed on the fly during the reading and the uncompressed versions are deleted after reading.

write(fname, ftype=None, color=None)

Write the surface to file.

If no filetype is given, it is deduced from the filename extension. If the filename has no extension, the ‘off’ file type is used. For a file with extension ‘stl’, the ftype may be ‘stla’ or ‘stlb’ to force ascii or binary STL format. The color is only useful for ‘stlb’ format.

avgVertexNormals()

Compute the average normals at the vertices.

areaNormals()

Compute the area and normal vectors of the surface triangles.

The normal vectors are normalized. The area is always positive.

The values are returned and saved in the object.

areas()

Return the areas of all facets

volume()

Return the enclosed volume of the surface.

This will only be correct if the surface is a closed manifold.

curvature(neighbours=1)

Return the curvature parameters at the nodes.

This uses the nodes that are connected to the node via a shortest path of ‘neighbours’ edges. Eight values are returned: the Gaussian and mean curvature, the shape index, the curvedness, the principal curvatures and the principal directions.

inertia()

Return inertia related quantities of the surface.

This computes the inertia properties of the centroids of the triangles, using the triangle area as a weight. The result is therefore different from self.coords.inertia() and usually better suited for the surface, especially if the triangle areas differ a lot.

Returns a tuple with the center of gravity, the principal axes of inertia, the principal moments of inertia and the inertia tensor.

surfaceType()

Check whether the TriSurface is a manifold and if it’s closed.

borderEdges()

Detect the border elements of TriSurface.

The border elements are the edges having less than 2 connected elements. Returns True where edge is on the border.

borderEdgeNrs()

Returns the numbers of the border edges.

borderNodeNrs()

Detect the border nodes of TriSurface.

The border nodes are the vertices belonging to the border edges. Returns a list of vertex numbers.

isManifold()

Check whether the TriSurface is a manifold.

A surface is a manifold if a small sphere exists that cuts the surface to a surface that can continously be deformed to an open disk.

nonManifoldEdges()

Finds edges and faces that are not Manifold.

Returns a tuple of:

  • the edges that connect 3 or more faces,
  • the faces connected to these edges.
isClosedManifold()

Check whether the TriSurface is a closed manifold.

checkBorder()

Return the border of TriSurface.

Returns a list of connectivity tables. Each table holds the subsequent line segments of one continuous contour of the border of the surface.

border(compact=True)

Return the border(s) of TriSurface.

The complete border of the surface is returned as a list of plex-2 Meshes. Each Mesh constitutes a continuous part of the border. By default, the Meshes are compacted. Setting compact=False will return all Meshes with the full surface coordinate sets. This is usefull for filling the border and adding to the surface.

fillBorder(method='radial', dir=None, compact=True)

Fill the border areas of a surface to make it closed.

Returns a list of surfaces, each of which fills a singly connected part of the border of the input surface. Adding these surfaces to the original will create a closed surface. The surfaces will have property values set above those used in the parent surface. If the surface is already closed, an empty list is returned.

There are three methods: ‘radial’, ‘planar’ and ‘border’, corresponding to the methods of the surfaceInsideBorder function.

edgeCosAngles(return_mask=False)

Return the cos of the angles over all edges.

The surface should be a manifold (max. 2 elements per edge). Edges adjacent to only one element get cosangles = 1.0. If return_mask == True, a second return value is a boolean array with the edges that connect two faces.

As a side effect, this method also sets the area, normals, elem_edges and edges attributes.

edgeAngles()

Return the angles over all edges (in degrees). It is the angle (0 to 180) between 2 face normals.

perimeters()

Compute the perimeters of all triangles.

quality()

Compute a quality measure for the triangle schapes.

The quality of a triangle is defined as the ratio of the square root of its surface area to its perimeter relative to this same ratio for an equilateral triangle with the same area. The quality is then one for an equilateral triangle and tends to zero for a very stretched triangle.

aspectRatio()

Return the apect ratio of the triangles of the surface.

The aspect ratio of a triangle is the ratio of the longest edge over the smallest altitude of the triangle.

Equilateral triangles have the smallest edge ratio (2 over square root 3).

smallestAltitude()

Return the smallest altitude of the triangles of the surface.

longestEdge()

Return the longest edge of the triangles of the surface.

shortestEdge()

Return the shortest edge of the triangles of the surface.

stats()

Return a text with full statistics.

distanceOfPoints(X, return_points=False)

Find the distances of points X to the TriSurface.

The distance of a point is either: - the closest perpendicular distance to the facets; - the closest perpendicular distance to the edges; - the closest distance to the vertices.

X is a (nX,3) shaped array of points. If return_points = True, a second value is returned: an array with the closest (foot)points matching X.

degenerate()

Return a list of the degenerate faces according to area and normals.

A face is degenerate if its surface is less or equal to zero or the normal has a nan.

Returns the list of degenerate element numbers in a sorted array.

removeDegenerate(compact=False)

Remove the degenerate elements from a TriSurface.

Returns a TriSurface with all degenerate elements removed. By default, the coords set is unaltered and will still contain all points, even ones that are no longer connected to any element. To reduce the coordinate set, set the compact argument to True or use the compact() method afterwards.

offset(distance=1.0)

Offset a surface with a certain distance.

All the nodes of the surface are translated over a specified distance along their normal vector.

dualMesh(method='median')

Return the dual mesh of a triangulated surface.

It creates a new triangular mesh where all triangles with prop p represent the dual mesh region around the original surface node p. For more info, see http://users.led-inc.eu/~phk/mesh-dualmesh.html.

  • method: ‘median’ or ‘voronoi’.

Returns:

  • method = ‘median’: the Median dual mesh and the area of the region around each node. The sum of the node-based areas is equal to the original surface area.
  • method = ‘voronoi’: the Voronoi polyeders and a None.
featureEdges(angle=60.0)

Return the feature edges of the surface.

Feature edges are edges that are prominent features of the geometry. They are either border edges or edges where the normals on the two adjacent triangles differ more than a given angle. The non feature edges then represent edges on a rather smooth surface.

Parameters:

  • angle: The angle by which the normals on adjacent triangles should differ in order for the edge to be marked as a feature.

Returns a boolean array with shape (nedg,) where the feature angles are marked with True.

Note

As a side effect, this also sets the elem_edges and edges attributes, which can be used to get the edge data with the same numbering as used in the returned mask. Thus, the following constructs a Mesh with the feature edges of a surface S:

p = S.featureEdges()
Mesh(S.coords,S.edges[p])
partitionByAngle(angle=60.0, sort='number')

Partition the surface by splitting it at sharp edges.

The surface is partitioned in parts in which all elements can be reach without ever crossing a sharp edge angle. More precisely, any two elements that can be connected by a line not crossing an edge between two elements having their normals differ more than angle (in degrees), will belong to the same part.

The partitioning is returned as an integer array specifying the part number for eacht triangle.

By default the parts are assigned property numbers in decreasing order of the number of triangles in the part. Setting the sort argument to ‘area’ will sort the parts according to decreasing area. Any other value will return the parts unsorted.

Beware that the existence of degenerate elements may cause unexpected results. If unsure, use the removeDegenerate() method first to remove those elements.

cutWithPlane1(p, n, side='', return_intersection=False, atol=0.0)

Cut a surface with a plane.

Cuts the surface with a plane defined by a point p and normal n.

Parameters:

  • p: float, shape (3,): a point in the cutting plane
  • n: float, shape (3,): the normal vector to the plane
  • side: ‘’, ‘+’ or ‘-‘: selector of the returned parts. Default is to return a tuple of two surfaces, with the parts at the positive, resp. negative side of the plane as defined by the normal vector. If a ‘+’ or ‘-‘ is specified, only the corresponding part is returned.

Returns:

A tuple of two TriSurfaces, or a single TriSurface, depending on the value of side. The returned surfaces will have their normals fixed wherever possible. Property values will be set containing the triangle number of the original surface from which the elements resulted.

cutWithPlane(*args, **kargs)

Cut a surface with a plane or a set of planes.

Cuts the surface with one or more plane and returns either one side or both.

Parameters:

  • p,`n`: a point and normal vector defining the cutting plane. p and n can be sequences of points and vector, allowing to cut with multiple planes. Both p and n have shape (3) or (npoints,3).

The parameters are the same as in Formex.CutWithPlane(). The returned surface will have its normals fixed wherever possible.

connectedElements(target, elemlist=None)

Return the elements from list connected with target

intersectionWithPlane(p, n, atol=0.0, sort='number')

Return the intersection lines with plane (p,n).

Returns a plex-2 mesh with the line segments obtained by cutting all triangles of the surface with the plane (p,n) p is a point specified by 3 coordinates. n is the normal vector to a plane, specified by 3 components.

The return value is a plex-2 Mesh where the line segments defining the intersection are sorted to form continuous lines. The Mesh has property numbers such that all segments forming a single continuous part have the same property value.

By default the parts are assigned property numbers in decreasing order of the number of line segments in the part. Setting the sort argument to ‘distance’ will sort the parts according to increasing distance from the point p.

The splitProp() method can be used to get a list of Meshes.

slice(dir=0, nplanes=20)

Intersect a surface with a sequence of planes.

A sequence of nplanes planes with normal dir is constructed at equal distances spread over the bbox of the surface.

The return value is a list of intersectionWithPlane() return values, i.e. a list of Meshes, one for every cutting plane. In each Mesh the simply connected parts are identified by property number.

smooth(method='lowpass', iterations=1, lambda_value=0.5, neighbourhood=1, alpha=0.0, beta=0.2)

Smooth the surface.

Returns a TriSurface which is a smoothed version of the original. Two smoothing methods are available: ‘lowpass’ and ‘laplace’.

Parameters:

  • method: ‘lowpass’ or ‘laplace’
  • iterations: int: number of iterations
  • lambda_value: float: lambda value used in the filters

Extra parameters for ‘lowpass’ and ‘laplace’:

  • neighbourhood: int: maximum number of edges followed in defining the node neighbourhood

Extra parameters for ‘laplace’:

  • alpha, beta: float: parameters for the laplace method.

Returns the smoothed TriSurface

smoothLowPass(iterations=2, lambda_value=0.5, neighbours=1)

Apply a low pass smoothing to the surface.

smoothLaplaceHC(iterations=2, lambda_value=0.5, alpha=0.0, beta=0.2)

Apply Laplace smoothing with shrinkage compensation to the surface.

refine(max_edges=None, min_cost=None, method='gts')

Refine the TriSurface.

Refining a TriSurface means increasing the number of triangles and reducing their size, while keeping the changes to the modeled surface minimal. Construct a refined version of the surface. This uses the external program gtsrefine. The surface should be a closed orientable non-intersecting manifold. Use the check() method to find out.

Parameters:

  • max_edges: int: stop the refining process if the number of edges exceeds this value
  • min_cost: float: stop the refining process if the cost of refining an edge is smaller
  • log: boolean: log the evolution of the cost
  • verbose: boolean: print statistics about the surface
fixNormals(outwards=True)

Fix the orientation of the normals.

Some surface operations may result in improperly oriented normals, switching directions from one triangle to the adjacent one. This method tries to reverse improperly oriented normals so that a singly oriented surface is achieved.

If the surface is a (possibly non-orientable) manifold, the result will be an orientable manifold.

If the surface is a closed manifold, the normals will be oriented to the outside. This is done by computing the volume inside the surface and reversing the normals if that turns out to be negative.

Parameters:

  • outwards: boolean: if True (default), a test is done whether the surface is a closed manifold, and if so, the normals are oriented outwards. Setting this value to False will skip this test and the (possible) reversal of the normals.
check(matched=True, verbose=False)

Check the surface using gtscheck.

Uses gtscheck to check whether the surface is an orientable, non self-intersecting manifold.

This is a necessary condition for using the gts methods: split, coarsen, refine, boolean. (Additionally, the surface should be closed, wich can be checked with isClosedManifold()).

Returns a tuple of:

  • an integer return code with the value:
    • 0: the surface is an orientable, non self-intersecting manifold.
    • 1: the created GTS file is invalid: this should normally not occur.
    • 2: the surface is not an orientable manifold. This may be due to misoriented normals. The fixNormals() and reverse() methods may be used to help fixing the problem in such case.
    • 3: the surface is an orientable manifold but is self-intersecting. The self intersecting triangles are returned as the second return value.
  • the intersecting triangles in the case of a return code 3, else None. If matched==True, intersecting triangles are returned as element indices of self, otherwise as a separate TriSurface object.

If verbose is True, prints the statistics reported by the gtscheck command.

split(base, verbose=False)

Split the surface using gtssplit.

Splits the surface into connected and manifold components. This uses the external program gtssplit. The surface should be a closed orientable non-intersecting manifold. Use the check() method to find out.

This method creates a series of files with given base name, each file contains a single connected manifold.

coarsen(min_edges=None, max_cost=None, mid_vertex=False, length_cost=False, max_fold=1.0, volume_weight=0.5, boundary_weight=0.5, shape_weight=0.0, progressive=False, log=False, verbose=False)

Coarsen the surface using gtscoarsen.

Construct a coarsened version of the surface. This uses the external program gtscoarsen. The surface should be a closed orientable non-intersecting manifold. Use the check() method to find out.

Parameters:

  • min_edges: int: stops the coarsening process if the number of edges was to fall below it
  • max_cost: float: stops the coarsening process if the cost of collapsing an edge is larger
  • mid_vertex: boolean: use midvertex as replacement vertex instead of the default, which is a volume optimized point
  • length_cost: boolean: use length^2 as cost function instead of the default optimized point cost
  • max_fold: float: maximum fold angle in degrees
  • volume_weight: float: weight used for volume optimization
  • boundary_weight: float: weight used for boundary optimization
  • shape_weight: float: weight used for shape optimization
  • progressive: boolean: write progressive surface file
  • log: boolean: log the evolution of the cost
  • verbose: boolean: print statistics about the surface
gts_refine(max_edges=None, min_cost=None, log=False, verbose=False)

Refine the TriSurface.

Refining a TriSurface means increasing the number of triangles and reducing their size, while keeping the changes to the modeled surface minimal. Construct a refined version of the surface. This uses the external program gtsrefine. The surface should be a closed orientable non-intersecting manifold. Use the check() method to find out.

Parameters:

  • max_edges: int: stop the refining process if the number of edges exceeds this value
  • min_cost: float: stop the refining process if the cost of refining an edge is smaller
  • log: boolean: log the evolution of the cost
  • verbose: boolean: print statistics about the surface
gts_smooth(iterations=1, lambda_value=0.5, verbose=False)

Smooth the surface using gtssmooth.

Smooth a surface by applying iterations of a Laplacian filter. This uses the external program gtssmooth. The surface should be a closed orientable non-intersecting manifold. Use the check() method to find out.

Parameters:

  • lambda_value: float: Laplacian filter parameter
  • iterations: int: number of iterations
  • verbose: boolean: print statistics about the surface

See also: smoothLowPass(), smoothLaplaceHC()

inside(pts, method='gts', tol=0.0)

Test which of the points pts are inside the surface.

Parameters:

  • pts: a Coords or compatible.
  • method: string: method to be used for the detection. Depending on the software you have installed the following are possible:
    • ‘gts’: provided by pyformex-extra
    • ‘vtk’: provided by python-vtk
  • tol: only available for method ‘vtk’

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().

tetgen(quality=True, volume=None, filename=None, format='.off')

Create a tetrahedral mesh inside the surface

  • surfacefile: a file representing a surface. It can be an .off or .stl file (or other?)
  • quality: if True, the output will be a quality mesh The circumradius-to-shortest-edge ratio can be constrained by specifying a float value for quality (default is 2.0) - volume: float: applies a maximum tetrahedron volume constraint
  • outputdir: if specified, the results surface model and the tet model files will be placed in this directory. Else, a temporary directory will be used.

If the creation of the tetrahedral model is succesful, the resulting tetrahedral mesh is returned.

boolean(surf, op, check=False, verbose=False)

Perform a boolean operation with another surface.

Boolean operations between surfaces are a basic operation in free surface modeling. Both surfaces should be closed orientable non-intersecting manifolds. Use the check() method to find out.

The boolean operations are set operations on the enclosed volumes: union(‘+’), difference(‘-‘) or intersection(‘*’).

Parameters:

  • surf: a closed manifold surface
  • op: boolean operation: one of ‘+’, ‘-‘ or ‘*’.
  • check: boolean: check that the surfaces are not self-intersecting; if one of them is, the set of self-intersecting faces is written (as a GtsSurface) on standard output
  • verbose: boolean: print statistics about the surface

Returns: a closed manifold TriSurface

intersection(surf, check=False, verbose=False)

Return the intersection curve of two surfaces.

Boolean operations between surfaces are a basic operation in free surface modeling. Both surfaces should be closed orientable non-intersecting manifolds. Use the check() method to find out.

Parameters:

  • surf: a closed manifold surface
  • check: boolean: check that the surfaces are not self-intersecting; if one of them is, the set of self-intersecting faces is written (as a GtsSurface) on standard output
  • verbose: boolean: print statistics about the surface

Returns: a list of intersection curves.

scaledJacobian(scaled=True, blksize=100000)

Compute a quality measure for volume meshes.

Parameters:

  • scaled: if False returns the Jacobian at the corners of each element. If True, returns a quality metrics, being the minimum value of the scaled Jacobian in each element (at one corner, the Jacobian divided by the volume of a perfect brick).
  • blksize: int: to reduce the memory required for large meshes, the Mesh is split in blocks with this number of elements. If not positive, all elements are handled at once.

If scaled is True each tet or hex element gets a value between -1 and 1. Acceptable elements have a positive scaled Jacobian. However, good quality requires a minimum of 0.2. Quadratic meshes are first converted to linear. If the mesh contain mainly negative Jacobians, it probably has negative volumes and can be fixed with the correctNegativeVolumes.

addNoise(*args, **kargs)

Apply ‘addNoise’ transformation to the Geometry object.

See coords.Coords.addNoise() for details.

affine(*args, **kargs)

Apply ‘affine’ transformation to the Geometry object.

See coords.Coords.affine() for details.

align(*args, **kargs)

Apply ‘align’ transformation to the Geometry object.

See coords.Coords.align() for details.

bump(*args, **kargs)

Apply ‘bump’ transformation to the Geometry object.

See coords.Coords.bump() for details.

bump1(*args, **kargs)

Apply ‘bump1’ transformation to the Geometry object.

See coords.Coords.bump1() for details.

bump2(*args, **kargs)

Apply ‘bump2’ transformation to the Geometry object.

See coords.Coords.bump2() for details.

centered(*args, **kargs)

Apply ‘centered’ transformation to the Geometry object.

See coords.Coords.centered() for details.

cylindrical(*args, **kargs)

Apply ‘cylindrical’ transformation to the Geometry object.

See coords.Coords.cylindrical() for details.

egg(*args, **kargs)

Apply ‘egg’ transformation to the Geometry object.

See coords.Coords.egg() for details.

flare(*args, **kargs)

Apply ‘flare’ transformation to the Geometry object.

See coords.Coords.flare() for details.

hyperCylindrical(*args, **kargs)

Apply ‘hyperCylindrical’ transformation to the Geometry object.

See coords.Coords.hyperCylindrical() for details.

isopar(*args, **kargs)

Apply ‘isopar’ transformation to the Geometry object.

See coords.Coords.isopar() for details.

map(*args, **kargs)

Apply ‘map’ transformation to the Geometry object.

See coords.Coords.map() for details.

map1(*args, **kargs)

Apply ‘map1’ transformation to the Geometry object.

See coords.Coords.map1() for details.

mapd(*args, **kargs)

Apply ‘mapd’ transformation to the Geometry object.

See coords.Coords.mapd() for details.

position(*args, **kargs)

Apply ‘position’ transformation to the Geometry object.

See coords.Coords.position() for details.

projectOnCylinder(*args, **kargs)

Apply ‘projectOnCylinder’ transformation to the Geometry object.

See coords.Coords.projectOnCylinder() for details.

projectOnPlane(*args, **kargs)

Apply ‘projectOnPlane’ transformation to the Geometry object.

See coords.Coords.projectOnPlane() for details.

projectOnSphere(*args, **kargs)

Apply ‘projectOnSphere’ transformation to the Geometry object.

See coords.Coords.projectOnSphere() for details.

replace(*args, **kargs)

Apply ‘replace’ transformation to the Geometry object.

See coords.Coords.replace() for details.

rollAxes(*args, **kargs)

Apply ‘rollAxes’ transformation to the Geometry object.

See coords.Coords.rollAxes() for details.

rot(*args, **kargs)

Apply ‘rotate’ transformation to the Geometry object.

See coords.Coords.rotate() for details.

rotate(*args, **kargs)

Apply ‘rotate’ transformation to the Geometry object.

See coords.Coords.rotate() for details.

scale(*args, **kargs)

Apply ‘scale’ transformation to the Geometry object.

See coords.Coords.scale() for details.

shear(*args, **kargs)

Apply ‘shear’ transformation to the Geometry object.

See coords.Coords.shear() for details.

spherical(*args, **kargs)

Apply ‘spherical’ transformation to the Geometry object.

See coords.Coords.spherical() for details.

superSpherical(*args, **kargs)

Apply ‘superSpherical’ transformation to the Geometry object.

See coords.Coords.superSpherical() for details.

swapAxes(*args, **kargs)

Apply ‘swapAxes’ transformation to the Geometry object.

See coords.Coords.swapAxes() for details.

toCylindrical(*args, **kargs)

Apply ‘toCylindrical’ transformation to the Geometry object.

See coords.Coords.toCylindrical() for details.

toSpherical(*args, **kargs)

Apply ‘toSpherical’ transformation to the Geometry object.

See coords.Coords.toSpherical() for details.

transformCS(*args, **kargs)

Apply ‘transformCS’ transformation to the Geometry object.

See coords.Coords.transformCS() for details.

translate(*args, **kargs)

Apply ‘translate’ transformation to the Geometry object.

See coords.Coords.translate() for details.

trl(*args, **kargs)

Apply ‘translate’ transformation to the Geometry object.

See coords.Coords.translate() for details.

elementToNodal(val)

Compute nodal values from element values.

Given scalar values defined on elements, finds the average values at the nodes. Returns the average values at the (maxnodenr+1) nodes. Nodes not occurring in elems will have all zero values. NB. It now works with scalar. It could be extended to vectors.

nodalToElement(val)

Compute element values from nodal values.

Given scalar values defined on nodes, finds the average values at elements. NB. It now works with scalar. It could be extended to vectors.

setProp(prop=None, blocks=None)

Create or destroy the property array for the Geometry.

A property array is a rank-1 integer array with dimension equal to the number of elements in the Geometry. Each element thus has its own property number. These numbers can be used for any purpose. They play an import role when creating new geometry: new elements inherit the property number of their parent element. Properties are also preserved on most geometrical transformations.

Because elements with different property numbers can be drawn in different colors, the property numbers are also often used to impose color.

Parameters:

  • prop: a single integer value or a list/array of integer values. If the number of passed values is less than the number of elements, they wil be repeated. If you give more, they will be ignored.

    The special value ‘range’ will set the property numbers equal to the element number.

    A value None (default) removes the properties from the Geometry.

  • blocks: a single integer value or a list/array of integer values. If the number of passed values is less than the length of prop, they wil be repeated. If you give more, they will be ignored. Every prop will be repeated the corresponding number of times specified in blocks.

setType(eltype=None)

Set the eltype from a character string.

This function allows the user to change the element type of the Mesh. The input is a character string with the name of one of the element defined in elements.py. The function will only allow to set a type matching the plexitude of the Mesh.

This method is seldom needed, because the applications should normally set the element type at creation time.

elType()

Return the element type of the Mesh.

elName()

Return the element name of the Mesh.

toProp(prop)

Converts the argument into a legal set of properties for the object.

The conversion involves resizing the argument to a 1D array of length self.nelems(), and converting the data type to integer.

setNormals(normals=None)

Set/Remove the normals of the mesh.

copy()

Return a deep copy of the Geometry object.

The returned object is an exact copy of the input, but has all of its data independent of the former.

splitProp(prop=None)

Partition a Geometry (Formex/Mesh) according to the values in prop.

Parameters:

  • prop: an int array with length self.nelems(), or None. If None, the prop attribute of the Geometry is used.

Returns a list of Geometry objects of the same type as the input. Each object contains all the elements having the same value of prop. The number of objects in the list is equal to the number of unique values in prop. The list is sorted in ascending order of their prop value.

It prop is None and the the object has no prop attribute, an empty list is returned.

getProp()

Return the properties as a numpy array (ndarray)

maxProp()

Return the highest property value used, or None

propSet()

Return a list with unique property values.

resized(size=1.0, tol=1e-05)

Return a copy of the Geometry scaled to the given size.

size can be a single value or a list of three values for the three coordinate directions. If it is a single value, all directions are scaled to the same size. Directions for which the geometry has a size smaller than tol times the maximum size are not rescaled.

shallowCopy(prop=None)

Return a shallow copy.

A shallow copy of a Mesh is a Mesh object using the same data arrays as the original Mesh. The only thing that can be changed is the property array. This is a convenient method to use the same Mesh with different property attributes.

toFormex()

Convert a Mesh to a Formex.

The Formex inherits the element property numbers and eltype from the Mesh. Node property numbers however can not be translated to the Formex data model.

toMesh()

Convert to a Mesh.

This just returns the Mesh object itself. It is provided as a convenience for use in functions that want work on different Geometry types.

toSurface()

Convert a Mesh to a TriSurface.

Only Meshes of level 2 (surface) and 3 (volume) can be converted to a TriSurface. For a level 3 Mesh, the border Mesh is taken first. A level 2 Mesh is converted to element type ‘tri3’ and then to a TriSurface. The resulting TriSurface is only fully equivalent with the input Mesh if the latter has element type ‘tri3’.

On success, returns a TriSurface corresponding with the input Mesh. If the Mesh can not be converted to a TriSurface, an error is raised.

toCurve()

Convert a Mesh to a Curve.

If the element type is one of ‘line*’ types, the Mesh is converted to a Curve. The type of the returned Curve is dependent on the element type of the Mesh:

  • ‘line2’: PolyLine,
  • ‘line3’: BezierSpline (degree 2),
  • ‘line4’: BezierSpline (degree 3)

This is equivalent with

self.toFormex().toCurve()

Any other type will raise an exception.

info()

Return short info about the Mesh.

This includes only the shape of the coords and elems arrays.

report(full=True)

Create a report on the Mesh shape and size.

The report always contains the number of nodes, number of elements, plexitude, dimensionality, element type, bbox and size. If full==True(default), it also contains the nodal coordinate list and element connectivity table. Because the latter can be rather bulky, they can be switched off. (Though numpy will limit the printed output).

TODO: We should add an option here to let numpy print the full tables.

centroids()

Return the centroids of all elements of the Mesh.

The centroid of an element is the point whose coordinates are the mean values of all points of the element. The return value is a Coords object with nelems points.

bboxes()

Returns the bboxes of all elements in the Mesh.

Returns a coords with shape (nelems,2,3). Along the axis 1 are stored the minimal and maximal values of the Coords in each of the elements of the Mesh.

getCoords()

Get the coords data.

Returns the full array of coordinates stored in the Mesh object. Note that this may contain points that are not used in the mesh. compact() will remove the unused points.

webgl(S, name, caption=None)

Create a WebGL model of a surface

  • S: TriSurface
  • name: basename of the output files
  • caption: text to use as caption
getElems()

Get the elems data.

Returns the element connectivity data as stored in the object.

getLowerEntities(level=-1, unique=False)

Get the entities of a lower dimensionality.

If the element type is defined in the elements module, this returns a Connectivity table with the entities of a lower dimensionality. The full list of entities with increasing dimensionality 0,1,2,3 is:

['points', 'edges', 'faces', 'cells' ]

If level is negative, the dimensionality returned is relative to that of the caller. If it is positive, it is taken absolute. Thus, for a Mesh with a 3D element type, getLowerEntities(-1) returns the faces, while for a 2D element type, it returns the edges. For both meshes however, getLowerEntities(+1) returns the edges.

By default, all entities for all elements are returned and common entities will appear multiple times. Specifying unique=True will return only the unique ones.

The return value may be an empty table, if the element type does not have the requested entities (e.g. the ‘point’ type). If the eltype is not defined, or the requested entity level is outside the range 0..3, the return value is None.

getNodes()

Return the set of unique node numbers in the Mesh.

This returns only the node numbers that are effectively used in the connectivity table. For a compacted Mesh, it is equivalent to arange(self.nelems). This function also stores the result internally so that future requests can return it without the need for computing it again.

getPoints()

Return the nodal coordinates of the Mesh.

This returns only those points that are effectively used in the connectivity table. For a compacted Mesh, it is equal to the coords attribute.

getEdges()

Return the unique edges of all the elements in the Mesh.

This is a convenient function to create a table with the element edges. It is equivalent to self.getLowerEntities(1,unique=True), but this also stores the result internally so that future requests can return it without the need for computing it again.

getFaces()

Return the unique faces of all the elements in the Mesh.

This is a convenient function to create a table with the element faces. It is equivalent to self.getLowerEntities(2,unique=True), but this also stores the result internally so that future requests can return it without the need for computing it again.

getCells()

Return the cells of the elements.

This is a convenient function to create a table with the element cells. It is equivalent to self.getLowerEntities(3,unique=True), but this also stores the result internally so that future requests can return it without the need for computing it again.

getFreeEntities(level=-1, return_indices=False)

Return the border of the Mesh.

Returns a Connectivity table with the free entities of the specified level of the Mesh. Free entities are entities that are only connected with a single element.

If return_indices==True, also returns an (nentities,2) index for inverse lookup of the higher entity (column 0) and its local lower entity number (column 1).

getFreeEntitiesMesh(level=-1, compact=True)

Return a Mesh with lower entities.

Returns a Mesh representing the lower entities of the specified level. If the Mesh has property numbers, the lower entities inherit the property of the element to which they belong.

By default, the resulting Mesh is compacted. Compaction can be switched off by setting compact=False.

getBorder(return_indices=False)

Return the border of the Mesh.

This returns a Connectivity table with the border of the Mesh. The border entities are of a lower hierarchical level than the mesh itself. These entities become part of the border if they are connected to only one element.

If return_indices==True, it returns also an (nborder,2) index for inverse lookup of the higher entity (column 0) and its local border part number (column 1).

This is a convenient shorthand for

self.getFreeEntities(level=-1,return_indices=return_indices)
getBorderMesh(compact=True)

Return a Mesh with the border elements.

The returned Mesh is of the next lower hierarchical level and contains all the free entitites of that level. If the Mesh has property numbers, the border elements inherit the property of the element to which they belong.

By default, the resulting Mesh is compacted. Compaction can be switched off by setting compact=False.

This is a convenient shorthand for

self.getFreeEntitiesMesh(level=-1,compact=compact)
getBorderElems()

Return the elements that are on the border of the Mesh.

This returns a list with the numbers of the elements that are on the border of the Mesh. Elements are considered to be at the border if they contain at least one complete element of the border Mesh (i.e. an element of the first lower hierarchical level). Thus, in a volume Mesh, elements only touching the border by a vertex or an edge are not considered border elements.

getBorderNodes()

Return the nodes that are on the border of the Mesh.

This returns a list with the numbers of the nodes that are on the border of the Mesh.

peel(nodal=False)

Return a Mesh with the border elements removed.

If nodal is True all elements connected to a border node are removed. If nodal is False, it is a convenient shorthand for

self.cselect(self.getBorderElems())
getFreeEdgesMesh(compact=True)

Return a Mesh with the free edge elements.

The returned Mesh is of the hierarchical level 1 (no mather what the level of the parent Mesh is) and contains all the free entitites of that level. If the Mesh has property numbers, the border elements inherit the property of the element to which they belong.

By default, the resulting Mesh is compacted. Compaction can be switched off by setting compact=False.

This is a convenient shorthand for

self.getFreeEntitiesMesh(level=1,compact=compact)
adjacency(level=0, diflevel=-1)

Create an element adjacency table.

Two elements are said to be adjacent if they share a lower entity of the specified level. The level is one of the lower entities of the mesh.

Parameters:

  • level: hierarchy of the geometric items connecting two elements: 0 = node, 1 = edge, 2 = face. Only values of a lower hierarchy than the elements of the Mesh itself make sense.
  • diflevel: if >= level, and smaller than the hierarchy of self.elems, elements that have a connection of this level are removed. Thus, in a Mesh with volume elements, self.adjacency(0,1) gives the adjacency of elements by a node but not by an edge.

Returns an Adjacency with integers specifying for each element its neighbours connected by the specified geometrical subitems.

frontWalk(level=0, startat=0, frontinc=1, partinc=1, maxval=-1)

Visit all elements using a frontal walk.

In a frontal walk a forward step is executed simultanuously from all the elements in the current front. The elements thus reached become the new front. An element can be reached from the current element if both are connected by a lower entity of the specified level. Default level is ‘point’.

Parameters:

  • level: hierarchy of the geometric items connecting two elements: 0 = node, 1 = edge, 2 = face. Only values of a lower hierarchy than the elements of the Mesh itself make sense. There are no connections on the upper level.

The remainder of the parameters are like in Adjacency.frontWalk().

Returns an array of integers specifying for each element in which step the element was reached by the walker.

maskedEdgeFrontWalk(mask=None, startat=0, frontinc=1, partinc=1, maxval=-1)

Perform a front walk over masked edge connections.

This is like frontWalk(level=1), but allows to specify a mask to select the edges that are used as connectors between elements.

Parameters:

  • mask: Either None or a boolean array or index flagging the nodes which are to be considered connectors between elements. If None, all nodes are considered connections.

The remainder of the parameters are like in Adjacency.frontWalk().

partitionByConnection(level=0, startat=0, sort='number', nparts=-1)

Detect the connected parts of a Mesh.

The Mesh is partitioned in parts in which all elements are connected. Two elements are connected if it is possible to draw a continuous (poly)line from a point in one element to a point in the other element without leaving the Mesh. The partitioning is returned as a integer array having a value for ech element corresponding to the part number it belongs to.

By default the parts are sorted in decreasing order of the number of elements. If you specify nparts, you may wish to switch off the sorting by specifying sort=’‘.

splitByConnection(level=0, startat=0, sort='number')

Split the Mesh into connected parts.

Returns a list of Meshes that each form a connected part. By default the parts are sorted in decreasing order of the number of elements.

largestByConnection(level=0)

Return the largest connected part of the Mesh.

This is equivalent with, but more efficient than

self.splitByConnection(level)[0]
growSelection(sel, mode='node', nsteps=1)

Grow a selection of a surface.

p is a single element number or a list of numbers. The return value is a list of element numbers obtained by growing the front nsteps times. The mode argument specifies how a single frontal step is done:

  • ‘node’ : include all elements that have a node in common,
  • ‘edge’ : include all elements that have an edge in common.
nodeConnections()

Find and store the elems connected to nodes.

nNodeConnected()

Find the number of elems connected to nodes.

edgeConnections()

Find and store the elems connected to edges.

nEdgeConnected()

Find the number of elems connected to edges.

nodeAdjacency()

Find the elems adjacent to each elem via one or more nodes.

nNodeAdjacent()

Find the number of elems which are adjacent by node to each elem.

edgeAdjacency()

Find the elems adjacent to elems via an edge.

nEdgeAdjacent()

Find the number of adjacent elems.

nonManifoldNodes()

Return the non-manifold nodes of a Mesh.

Non-manifold nodes are nodes where subparts of a mesh of level >= 2 are connected by a node but not by an edge.

Returns an integer array with a sorted list of non-manifold node numbers. Possibly empty (always if the dimensionality of the Mesh is lower than 2).

nonManifoldEdgeNodes()

Return the non-manifold edge nodes of a Mesh.

Non-manifold edges are edges where subparts of a mesh of level 3 are connected by an edge but not by an face.

Returns an integer array with a sorted list of numbers of nodes on the non-manifold edges. Possibly empty (always if the dimensionality of the Mesh is lower than 3).

fuse(**kargs)

Fuse the nodes of a Meshes.

All nodes that are within the tolerance limits of each other are merged into a single node.

The merging operation can be tuned by specifying extra arguments that will be passed to Coords:fuse().

matchCoords(mesh, **kargs)

Match nodes of Mesh with nodes of self.

This is a convenience function equivalent to:

self.coords.match(mesh.coords,**kargs)

See also Coords.match()

matchCentroids(mesh, **kargs)

Match elems of Mesh with elems of self.

self and Mesh are same eltype meshes and are both without duplicates.

Elems are matched by their centroids.

compact()

Remove unconnected nodes and renumber the mesh.

Returns a mesh where all nodes that are not used in any element have been removed, and the nodes are renumbered to a compacter scheme.

Example:

>>> x = Coords([[i] for i in arange(5)])
>>> M = Mesh(x,[[0,2],[1,4],[4,2]])
>>> M = M.compact()
>>> print(M.coords)
[[ 0.  0.  0.]
 [ 1.  0.  0.]
 [ 2.  0.  0.]
 [ 4.  0.  0.]]
>>> print(M.elems)
[[0 2]
 [1 3]
 [3 2]]
>>> M = Mesh(x,[[0,2],[1,3],[3,2]])
>>> M = M.compact()
>>> print(M.coords)
[[ 0.  0.  0.]
 [ 1.  0.  0.]
 [ 2.  0.  0.]
 [ 3.  0.  0.]]
>>> print(M.elems)
[[0 2]
 [1 3]
 [3 2]]
select(selected, compact=True)

Return a Mesh only holding the selected elements.

Parameters:

  • selected: an object that can be used as an index in the elems array, such as
    • a single element number
    • a list, or array, of element numbers
    • a bool array of length self.nelems(), where True values flag the elements to be selected
  • compact: boolean. If True (default), the returned Mesh will be compacted, i.e. the unused nodes are removed and the nodes are renumbered from zero. If False, returns the node set and numbers unchanged.

Returns a Mesh (or subclass) with only the selected elements.

See cselect() for the complementary operation.

cselect(selected, compact=True)

Return a mesh without the selected elements.

Parameters:

  • selected: an object that can be used as an index in the elems array, such as
    • a single element number
    • a list, or array, of element numbers
    • a bool array of length self.nelems(), where True values flag the elements to be selected
  • compact: boolean. If True (default), the returned Mesh will be compacted, i.e. the unused nodes are removed and the nodes are renumbered from zero. If False, returns the node set and numbers unchanged.

Returns a Mesh with all but the selected elements.

This is the complimentary operation of select().

avgNodes(nodsel, wts=None)

Create average nodes from the existing nodes of a mesh.

nodsel is a local node selector as in selectNodes() Returns the (weighted) average coordinates of the points in the selector as (nelems*nnod,3) array of coordinates, where nnod is the length of the node selector. wts is a 1-D array of weights to be attributed to the points. Its length should be equal to that of nodsel.

meanNodes(nodsel)

Create nodes from the existing nodes of a mesh.

nodsel is a local node selector as in selectNodes() Returns the mean coordinates of the points in the selector as (nelems*nnod,3) array of coordinates, where nnod is the length of the node selector.

addNodes(newcoords, eltype=None)

Add new nodes to elements.

newcoords is an (nelems,nnod,3) or`(nelems*nnod,3)` array of coordinates. Each element gets exactly nnod extra nodes from this array. The result is a Mesh with plexitude self.nplex() + nnod.

addMeanNodes(nodsel, eltype=None)

Add new nodes to elements by averaging existing ones.

nodsel is a local node selector as in selectNodes() Returns a Mesh where the mean coordinates of the points in the selector are added to each element, thus increasing the plexitude by the length of the items in the selector. The new element type should be set to correct value.

selectNodes(nodsel, eltype=None)

Return a mesh with subsets of the original nodes.

nodsel is an object that can be converted to a 1-dim or 2-dim array. Examples are a tuple of local node numbers, or a list of such tuples all having the same length. Each row of nodsel holds a list of local node numbers that should be retained in the new connectivity table.

withProp(val)

Return a Mesh which holds only the elements with property val.

val is either a single integer, or a list/array of integers. The return value is a Mesh holding all the elements that have the property val, resp. one of the values in val. The returned Mesh inherits the matching properties.

If the Mesh has no properties, a copy with all elements is returned.

withoutProp(val)

Return a Mesh without the elements with property val.

This is the complementary method of Mesh.withProp(). val is either a single integer, or a list/array of integers. The return value is a Mesh holding all the elements that do not have the property val, resp. one of the values in val. The returned Mesh inherits the matching properties.

If the Mesh has no properties, a copy with all elements is returned.

connectedTo(nodes)

Return a Mesh with the elements connected to the specified node(s).

nodes: int or array_like, int.

Return a Mesh with all the elements from the original that contain at least one of the specified nodes.

notConnectedTo(nodes)

Return a Mesh with the elements not connected to the given node(s).

nodes: int or array_like, int.

Returns a Mesh with all the elements from the original that do not contain any of the specified nodes.

hits(entities, level)

Count the lower entities from a list connected to the elements.

entities: a single number or a list/array of entities level: 0 or 1 or 2 if entities are nodes or edges or faces, respectively.

The numbering of the entities corresponds to self.insertLevel(level). Returns an (nelems,) shaped int array with the number of the entities from the list that are contained in each of the elements. This method can be used in selector expressions like:

self.select(self.hits(entities,level) > 0)
splitRandom(n, compact=True)

Split a Mesh in n parts, distributing the elements randomly.

Returns a list of n Mesh objects, constituting together the same Mesh as the original. The elements are randomly distributed over the subMeshes.

By default, the Meshes are compacted. Compaction may be switched off for efficiency reasons.

reverse(sel=None)

Return a Mesh where the elements have been reversed.

Reversing an element has the following meaning:

  • for 1D elements: reverse the traversal direction,
  • for 2D elements: reverse the direction of the positive normal,
  • for 3D elements: reverse inside and outside directions of the element’s border surface. This also changes the sign of the elementt’s volume.

The reflect() method by default calls this method to undo the element reversal caused by the reflection operation.

Parameters:

-sel: a selector (index or True/False array)

reflect(dir=0, pos=0.0, reverse=True, **kargs)

Reflect the coordinates in one of the coordinate directions.

Parameters:

  • dir: int: direction of the reflection (default 0)
  • pos: float: offset of the mirror plane from origin (default 0.0)
  • reverse: boolean: if True, the Mesh.reverse() method is called after the reflection to undo the element reversal caused by the reflection of its coordinates. This will in most cases have the desired effect. If not however, the user can set this to False to skip the element reversal.
convert(totype, fuse=False)

Convert a Mesh to another element type.

Converting a Mesh from one element type to another can only be done if both element types are of the same dimensionality. Thus, 3D elements can only be converted to 3D elements.

The conversion is done by splitting the elements in smaller parts and/or by adding new nodes to the elements.

Not all conversions between elements of the same dimensionality are possible. The possible conversion strategies are implemented in a table. New strategies may be added however.

The return value is a Mesh of the requested element type, representing the same geometry (possibly approximatively) as the original mesh.

If the requested conversion is not implemented, an error is raised.

Warning

Conversion strategies that add new nodes may produce double nodes at the common border of elements. The fuse() method can be used to merge such coincident nodes. Specifying fuse=True will also enforce the fusing. This option become the default in future.

convertRandom(choices)

Convert choosing randomly between choices

Returns a Mesh obtained by converting the current Mesh by a randomly selected method from the available conversion type for the current element type.

subdivide(*ndiv, **kargs)

Subdivide the elements of a Mesh.

Parameters:

  • ndiv: specifies the number (and place) of divisions (seeds) along the edges of the elements. Accepted type and value depend on the element type of the Mesh. Currently implemented:
    • ‘tri3’: ndiv is a single int value specifying the number of divisions (of equal size) for each edge.
    • ‘quad4’: ndiv is a sequence of two int values nx,ny, specifying the number of divisions along the first, resp. second parametric direction of the element
    • ‘hex8’: ndiv is a sequence of three int values nx,ny,nz specifying the number of divisions along the first, resp. second and the third parametric direction of the element
  • fuse: bool, if True (default), the resulting Mesh is completely fused. If False, the Mesh is only fused over each individual element of the original Mesh.

Returns a Mesh where each element is replaced by a number of smaller elements of the same type.

Note

This is currently only implemented for Meshes of type ‘tri3’ and ‘quad4’ and ‘hex8’ and for the derived class ‘TriSurface’.

reduceDegenerate(eltype=None)

Reduce degenerate elements to lower plexitude elements.

This will try to reduce the degenerate elements of the mesh to elements of a lower plexitude. If a target element type is given, only the matching reduce scheme is tried. Else, all the target element types for which a reduce scheme from the Mesh eltype is available, will be tried.

The result is a list of Meshes of which the last one contains the elements that could not be reduced and may be empty. Property numbers propagate to the children.

splitDegenerate(autofix=True)

Split a Mesh in degenerate and non-degenerate elements.

If autofix is True, the degenerate elements will be tested against known degeneration patterns, and the matching elements will be transformed to non-degenerate elements of a lower plexitude.

The return value is a list of Meshes. The first holds the non-degenerate elements of the original Mesh. The last holds the remaining degenerate elements. The intermediate Meshes, if any, hold elements of a lower plexitude than the original. These may still contain degenerate elements.

removeDuplicate(permutations=True)

Remove the duplicate elements from a Mesh.

Duplicate elements are elements that consist of the same nodes, by default in no particular order. Setting permutations=False will only consider elements with the same nodes in the same order as duplicates.

Returns a Mesh with all duplicate elements removed.

renumber(order='elems')

Renumber the nodes of a Mesh in the specified order.

order is an index with length equal to the number of nodes. The index specifies the node number that should come at this position. Thus, the order values are the old node numbers on the new node number positions.

order can also be a predefined value that will generate the node index automatically:

  • ‘elems’: the nodes are number in order of their appearance in the Mesh connectivity.
  • ‘random’: the nodes are numbered randomly.
  • ‘front’: the nodes are numbered in order of their frontwalk.
renumberElems(order='nodes')

Reorder the elements of a Mesh.

Parameters:

  • order: either a 1-D integer array with a permutation of arange(self.nelems()), specifying the requested order, or one of the following predefined strings:
    • ‘nodes’: order the elements in increasing node number order.
    • ‘random’: number the elements in a random order.
    • ‘reverse’: number the elements in reverse order.

Returns a Mesh equivalent with self but with the elements ordered as specified.

See also: Connectivity.reorder()

reorder(order='nodes')

Reorder the elements of a Mesh.

Parameters:

  • order: either a 1-D integer array with a permutation of arange(self.nelems()), specifying the requested order, or one of the following predefined strings:
    • ‘nodes’: order the elements in increasing node number order.
    • ‘random’: number the elements in a random order.
    • ‘reverse’: number the elements in reverse order.

Returns a Mesh equivalent with self but with the elements ordered as specified.

See also: Connectivity.reorder()

connect(coordslist, div=1, degree=1, loop=False, eltype=None)

Connect a sequence of toplogically congruent Meshes into a hypermesh.

Parameters:

  • coordslist: either a list of Coords objects, or a list of Mesh objects or a single Mesh object.

    If Mesh objects are given, they should (all) have the same element type as self. Their connectivity tables will not be used though. They will only serve to construct a list of Coords objects by taking the coords attribute of each of the Meshes. If only a single Mesh was specified, self.coords will be added as the first Coords object in the list.

    All Coords objects in the coordslist (either specified or constructed from the Mesh objects), should have the exact same shape as self.coords. The number of Coords items in the list should be a multiple of degree, plus 1.

    Each of the Coords in the final coordslist is combined with the connectivity table, element type and property numbers of self to produce a list of toplogically congruent meshes. The return value is the hypermesh obtained by connecting each consecutive slice of (degree+1) of these meshes. The hypermesh has a dimensionality that is one higher than the original Mesh (i.e. points become lines, lines become surfaces, surfaces become volumes). The resulting elements will be of the given degree in the direction of the connection.

    Notice that unless a single Mesh was specified as coordslist, the coords of self are not used. In many cases however self or self.coords will be one of the items in the specified coordslist.

  • degree: degree of the connection. Currently only degree 1 and 2 are supported.

    • If degree is 1, every Coords from the coordslist is connected with hyperelements of a linear degree in the connection direction.

    • If degree is 2, quadratic hyperelements are created from one Coords item and the next two in the list. Note that all Coords items should contain the same number of nodes, even for higher order elements where the intermediate planes contain less nodes.

      Currently, degree=2 is not allowed when coordslist is specified as a single Mesh.

  • loop: if True, the connections with loop around the list and connect back to the first. This is accomplished by adding the first Coords item back at the end of the list.

  • div: Either an integer, or a sequence of float numbers (usually in the range ]0.0..1.0]) or a list of sequences of the same length of the connecting list of coordinates. In the latter case every sequence inside the list can either be a float sequence (usually in the range ]0.0..1.0]) or it contains one integer (e.g [[4],[0.3,1]]). This should only be used for degree==1.

    With this parameter the generated elements can be further subdivided along the connection direction. If an int is given, the connected elements will be divided into this number of elements along the connection direction. If a sequence of float numbers is given, the numbers specify the relative distance along the connection direction where the elements should end. If the last value in the sequence is not equal to 1.0, there will be a gap between the consecutive connections. If a list of sequences is given, every consecutive element of the coordinate list is connected using the corresponding sequence in the list(1-length integer of float sequence specified as before).

  • eltype: the element type of the constructed hypermesh. Normally, this is set automatically from the base element type and the connection degree. If a different element type is specified, a final conversion to the requested element type is attempted.

extrude(n, step=1.0, dir=0, degree=1, eltype=None)

Extrude a Mesh in one of the axes directions.

Returns a new Mesh obtained by extruding the given Mesh over n steps of length step in direction of axis dir.

revolve(n, axis=0, angle=360.0, around=None, loop=False, eltype=None)

Revolve a Mesh around an axis.

Returns a new Mesh obtained by revolving the given Mesh over an angle around an axis in n steps, while extruding the mesh from one step to the next. This extrudes points into lines, lines into surfaces and surfaces into volumes.

sweep(path, eltype=None, **kargs)

Sweep a mesh along a path, creating an extrusion

Returns a new Mesh obtained by sweeping the given Mesh over a path. The returned Mesh has double plexitude of the original.

This method accepts all the parameters of coords.sweepCoords(), with the same meaning. Usually, you will need to at least set the normal parameter. The eltype parameter can be used to set the element type on the returned Meshes.

This operation is similar to the extrude() method, but the path can be any 3D curve.

classmethod concatenate(clas, meshes, **kargs)

Concatenate a list of meshes of the same plexitude and eltype

All Meshes in the list should have the same plexitude. Meshes with plexitude are ignored though, to allow empty Meshes to be added in.

Merging of the nodes can be tuned by specifying extra arguments that will be passed to Coords:fuse().

If any of the meshes has property numbers, the resulting mesh will inherit the properties. In that case, any meshes without properties will be assigned property 0. If all meshes are without properties, so will be the result.

This is a class method, and should be invoked as follows:

Mesh.concatenate([mesh0,mesh1,mesh2])
test(nodes='all', dir=0, min=None, max=None, atol=0.0)

Flag elements having nodal coordinates between min and max.

This function is very convenient in clipping a Mesh in a specified direction. It returns a 1D integer array flagging (with a value 1 or True) the elements having nodal coordinates in the required range. Use where(result) to get a list of element numbers passing the test. Or directly use clip() or cclip() to create the clipped Mesh

The test plane can be defined in two ways, depending on the value of dir. If dir == 0, 1 or 2, it specifies a global axis and min and max are the minimum and maximum values for the coordinates along that axis. Default is the 0 (or x) direction.

Else, dir should be compaitble with a (3,) shaped array and specifies the direction of the normal on the planes. In this case, min and max are points and should also evaluate to (3,) shaped arrays.

nodes specifies which nodes are taken into account in the comparisons. It should be one of the following:

  • a single (integer) point number (< the number of points in the Formex)
  • a list of point numbers
  • one of the special strings: ‘all’, ‘any’, ‘none’

The default (‘all’) will flag all the elements that have all their nodes between the planes x=min and x=max, i.e. the elements that fall completely between these planes. One of the two clipping planes may be left unspecified.

clip(t, compact=True)

Return a Mesh with all the elements where t>0.

t should be a 1-D integer array with length equal to the number of elements of the Mesh. The resulting Mesh will contain all elements where t > 0.

cclip(t, compact=True)

This is the complement of clip, returning a Mesh where t<=0.

clipAtPlane(p, n, nodes='any', side='+')

Return the Mesh clipped at plane (p,n).

This is a convenience function returning the part of the Mesh at one side of the plane (p,n)

levelVolumes()

Return the level volumes of all elements in a Mesh.

The level volume of an element is defined as:

  • the length of the element if the Mesh is of level 1,
  • the area of the element if the Mesh is of level 2,
  • the (signed) volume of the element if the Mesh is of level 3.

The level volumes can be computed directly for Meshes of eltypes ‘line2’, ‘tri3’ and ‘tet4’ and will produce accurate results. All other Mesh types are converted to one of these before computing the level volumes. Conversion may result in approximation of the results. If conversion can not be performed, None is returned.

If succesful, returns an (nelems,) float array with the level volumes of the elements. Returns None if the Mesh level is 0, or the conversion to the level’s base element was unsuccesful.

Note that for level-3 Meshes, negative volumes will be returned for elements having a reversed node ordering.

lengths()

Return the length of all elements in a level-1 Mesh.

For a Mesh with eltype ‘line2’, the lengths are exact. For other eltypes, a conversion to ‘line2’ is done before computing the lengths. This may produce an exact result, an approximated result or no result (if the conversion fails).

If succesful, returns an (nelems,) float array with the lengths. Returns None if the Mesh level is not 1, or the conversion to ‘line2’ does not succeed.

volumes()

Return the signed volume of all the mesh elements

For a ‘tet4’ tetraeder Mesh, the volume of the elements is calculated as 1/3 * surface of base * height.

For other Mesh types the volumes are calculated by first splitting the elements into tetraeder elements.

The return value is an array of float values with length equal to the number of elements. If the Mesh conversion to tetraeder does not succeed, the return value is None.

length()

Return the total length of a Mesh.

Returns the sum of self.lengths(), or 0.0 if the self.lengths() returned None.

area()

Return the total area of a Mesh.

Returns the sum of self.areas(), or 0.0 if the self.areas() returned None.

fixVolumes()

Reverse the elements with negative volume.

Elements with negative volume may result from incorrect local node numbering. This method will reverse all elements in a Mesh of dimensionality 3, provide the volumes of these elements can be computed.

Functions defined in module trisurface

trisurface.stlConvert(stlname, outname=None, binary=False, options='-d')

Transform an .stl file to .off or .gts or binary .stl format.

Parameters:

  • stlname: name of an existing .stl file (either ascii or binary).
  • outname: name of the output file. The extension defines the format and should be one of ‘.off’, ‘.gts’, ‘.stl’, ‘.stla’, or .stlb’. As a convenience, if a file extension only is given (other than ‘.stl’), then the outname will be constructed by changing the extension of the input stlname.
  • binary: if the extension of outname is ‘.stl’, defines whether the output format is a binary or ascii STL format.

If the outname file exists and its mtime is more recent than the stlname, the outname file is considered uptodate and the conversion program will not be run.

The conversion program will be choosen depending on the extension. This uses the external commands ‘admesh’ or ‘stl2gts’.

The return value is a tuple of the output file name, the conversion program exit code (0 if succesful) and the stdout of the conversion program (or a ‘file is already uptodate’ message).

trisurface.read_gts(fn)

Read a GTS surface mesh.

Return a coords,edges,faces tuple.

trisurface.read_stl(fn, intermediate=None)

Read a surface from .stl file.

This is done by first coverting the .stl to .gts or .off format. The name of the intermediate file may be specified. If not, it will be generated by changing the extension of fn to ‘.gts’ or ‘.off’ depending on the setting of the ‘surface/stlread’ config setting.

Return a coords,edges,faces or a coords,elems tuple, depending on the intermediate format.

trisurface.surface_volume(x, pt=None)

Return the volume inside a 3-plex Formex.

  • x: an (ntri,3,3) shaped float array, representing ntri triangles.
  • pt: a point in space. If unspecified, it is taken equal to the center() of the coordinates x.

Returns an (ntri) shaped array with the volume of the tetraeders formed by the triangles and the point pt. If x represents a closed surface, the sum of this array will represent the volume inside the surface.

trisurface.curvature(coords, elems, edges, neighbours=1)

Calculate curvature parameters at the nodes.

Algorithms based on Dong and Wang 2005; Koenderink and Van Doorn 1992. This uses the nodes that are connected to the node via a shortest path of ‘neighbours’ edges. Eight values are returned: the Gaussian and mean curvature, the shape index, the curvedness, the principal curvatures and the principal directions.

trisurface.fillBorder(border, method='radial', dir=None)

Create a surface inside a given closed border line.

The border line is a closed polygonal line and can be specified as one of the following:

  • a closed PolyLine,
  • a 2-plex Mesh, with a Connectivity table such that the elements in order form a closed polyline,
  • a simple Coords specifying the subsequent vertices of the polygonal border line.

The return value is a TriSurface filling the hole inside the border.

There are currently two fill methods available:

  • ‘radial’: this method adds a central point and connects all border segments with the center to create triangles.
  • ‘border’: this method creates subsequent triangles by connecting the endpoints of two consecutive border segments and thus works its way inwards until the hole is closed. Triangles are created at the line segments that form the smallest angle.

The ‘radial’ method produces nice results if the border is relative smooth, nearly convex and nearly planar. It adds an extra point though, which may be unwanted. On irregular 3D borders there is a high change that the result contains intersecting triangles.

This ‘border’ method is slower on large borders, does not introduce any new point and has a better chance of avoiding intersecting triangles on irregular 3D borders.

The resulting surface can be checked for intersecting triangles by the check() method.

Note

Because the ‘border’ does not create any new points, the returned surface will use the same point coordinate array as the input object.

trisurface.read_error(cnt, line)

Raise an error on reading the stl file.

trisurface.read_stla(fn, dtype=<type 'numpy.float32'>, large=False, guess=True)

Read an ascii .stl file into an [n,3,3] float array.

If the .stl is large, read_ascii_large() is recommended, as it is a lot faster.

trisurface.read_ascii_large(fn, dtype=<type 'numpy.float32'>)

Read an ascii .stl file into an [n,3,3] float array.

This is an alternative for read_ascii, which is a lot faster on large STL models. It requires the ‘awk’ command though, so is probably only useful on Linux/UNIX. It works by first transforming the input file to a .nodes file and then reading it through numpy’s fromfile() function.

trisurface.off_to_tet(fn)

Transform an .off model to tetgen (.node/.smesh) format.

trisurface.find_row(mat, row, nmatch=None)

Find all rows in matrix matching given row.

trisurface.find_nodes(nodes, coords)

Find nodes with given coordinates in a node set.

nodes is a (nnodes,3) float array of coordinates. coords is a (npts,3) float array of coordinates.

Returns a (n,) integer array with ALL the node numbers matching EXACTLY ALL the coordinates of ANY of the given points.

trisurface.find_first_nodes(nodes, coords)

Find nodes with given coordinates in a node set.

nodes is a (nnodes,3) float array of coordinates. coords is a (npts,3) float array of coordinates.

Returns a (n,) integer array with THE FIRST node number matching EXACTLY ALL the coordinates of EACH of the given points.

trisurface.find_triangles(elems, triangles)

Find triangles with given node numbers in a surface mesh.

elems is a (nelems,3) integer array of triangles. triangles is a (ntri,3) integer array of triangles to find.

Returns a (ntri,) integer array with the triangles numbers.

trisurface.remove_triangles(elems, remove)

Remove triangles from a surface mesh.

elems is a (nelems,3) integer array of triangles. remove is a (nremove,3) integer array of triangles to remove.

Returns a (nelems-nremove,3) integer array with the triangles of nelems where the triangles of remove have been removed.

trisurface.Rectangle(nx, ny)

Create a plane rectangular surface consisting of a nx,ny grid.

trisurface.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.