31. trisurface — Operations on triangulated surfaces.

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.

Methods

shape()

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

getEdges()

Get the edges data.

getFaceEdges()

Get the faces’ edge numbers.

getFaces()

Get the faces’ node 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.

write(fname, ftype=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 ‘gts’ file type is used.

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.

area()

Return the area of the surface

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 returns the center of gravity, the principal axes of inertia, the principal moments of inertia and the inertia tensor.

edgeConnections()

Find the elems connected to edges.

nodeConnections()

Find the elems connected to nodes.

nEdgeConnected()

Find the number of elems connected to edges.

nNodeConnected()

Find the number of elems connected to nodes.

edgeAdjacency()

Find the elems adjacent to elems via an edge.

nEdgeAdjacent()

Find the number of adjacent elems.

nodeAdjacency()

Find the elems adjacent to elems via one or two nodes.

nNodeAdjacent()

Find the number of adjacent elems.

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.

checkBorder()

Return the border of TriSurface as a set of segments.

border()

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.

fillBorder(method='radial', merge=False)

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

If the surface has no border, it is returned unchanged. Else, each singly connected part of the border which forms a closed curve will be filled with triangles, thus effectively creating a closed surface.

There are two methods, corresponding with the methods of the surfaceInsideBorder.

boundaryEdges()

Returns the border edges of a surface, grouped by id property.

boundaryFiller()

Fills the holes of a surface by creating extra faces at the boundary edges. Original surface and boundaries are returned with different id prop.

edgeCosAngles()

Return the cos of the angles over all edges.

The surface should be a manifold (max. 2 elements per edge). Edges with only one element get angles = 1.0.

edgeAngles()

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

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.

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.

reflect(*args, **kargs)

Reflect the Surface in direction dir against plane at pos.

Parameters:

  • dir: int: direction of the reflection (default 0)
  • pos: float: offset of the mirror plane from origin (default 0.0)
  • inplace: boolean: change the coordinates inplace (default False)
  • reverse: boolean: revert the normals of the triangles (default True). Reflection of the coordinates of a 2D Mesh reverses the surface sides. Setting this parameter True will cause an extra reversion. This is what is expected in most surface mirroring operations.
edgeFront(startat=0, okedges=None, front_increment=1)

Generator function returning the frontal elements.

startat is an element number or list of numbers of the starting front. On first call, this function returns the starting front. Each next() call returns the next front. front_increment determines how the property increases at each frontal step. There is an extra increment +1 at each start of a new part. Thus, the start of a new part can always be detected by a front not having the property of the previous plus front_increment.

nodeFront(startat=0, front_increment=1)

Generator function returning the frontal elements.

startat is an element number or list of numbers of the starting front. On first call, this function returns the starting front. Each next() call returns the next front.

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.
partitionByEdgeFront(okedges, firstprop=0, startat=0)

Detect different parts of the surface using a frontal method.

okedges flags the edges where the two adjacent triangles are to be in the same part of the surface. startat is a list of elements that are in the first part. The partitioning is returned as a property type array having a value corresponding to the part number. The lowest property number will be firstprop

partitionByNodeFront(firstprop=0, startat=0)

Detects different parts of the surface using a frontal method.

okedges flags the edges where the two adjacent triangles are to be in the same part of the surface. startat is a list of elements that are in the first part.

The partitioning is returned as a property type array having a value corresponding to the part number. The lowest property number will be firstprop.

partitionByConnection()

Detect the connected parts of a surface.

The surface 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 surface.

The partitioning is returned as a property type array having a value corresponding to the part number. The lowest property number will be firstprop.

partitionByAngle(angle=60.0, firstprop=0, startat=0)

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 a property type array having a value corresponding to the part number. The lowest property number will be firstprop.

splitByConnection()

Split the surface into connected parts.

Returns a list of surfaces that each form a connected part.

largestByConnection()

Return the largest connected part of the surface.

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)

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. 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.20000000000000001, verbose=False)

Smooth the surface.

Returns a TriSurface which is a smoothed version of the original. Three smoothing methods are available: ‘lowpass’, ‘laplace’, and ‘gts’. The first two are built-in, the latter uses the external command gtssmooth.

Parameters:

  • method: ‘lowpass’, ‘laplace’, or ‘gts’
  • 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 to follow to define node neighbourhood

Extra parameters for ‘laplace’:

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

Extra parameters for ‘gts’:

  • verbose: boolean: requests more verbose output of the gtssmooth command

Returns: the smoothed TriSurface

fixNormals()

Fix the orientation of the normals.

Some surface operations may result in improperly oriented normals. This tries to reverse improperly oriented normals so that a single oriented surface is achieved. It only works on a closed surface.

In the current version, this uses the external program admesh, so this should be installed on the machine.

If the surface was a (possibly non-orientable) manifold, the result will be an orientable manifold. This is a necessary condition for the gts methods to be applicable.

check(verbose=False)

Check the surface using gtscheck.

Checks whether the surface is a closed, orientable, non self-intersecting manifold. This is a necessary condition for the use of the gts methods: split, coarsen, refine, boolean.

Returns 0 if the surface passes the tests, nonzero if not. A full report is printed out.

The fixNormals() and reverse() methods may be used to fix the normals of an otherwise correct closed manifold.

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
refine(max_edges=None, min_cost=None, log=False, verbose=False)

Refine the surface using gtsrefine.

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
boolean(surf, op, intersection_curve=False, 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:

  • intersection_curve: boolean: output an OOGL (Geomview) representation of the curve intersection of the surfaces
  • 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

Functions defined in module trisurface

trisurface.areaNormals(x)

Compute the area and normal vectors of a collection of triangles.

x is an (ntri,3,3) array of coordinates.

Returns a tuple of areas,normals. The normal vectors are normalized. The area is always positive.

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

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

If outname is given, it is either ‘.off’ or ‘.gts’ or a filename ending on one of these extensions. If it is only an extension, the stlname will be used with extension changed.

If the outname file exists and its mtime is more recent than the stlname, the outname file is considered uptodate and the conversion programwill 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_off(fn)

Read an OFF surface mesh.

The mesh should consist of only triangles! Returns a nodes,elems 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.read_gambit_neutral(fn)

Read a triangular surface mesh in Gambit neutral format.

The .neu file nodes are numbered from 1! Returns a nodes,elems tuple.

trisurface.write_stla(f, x)

Export an x[n,3,3] float array as an ascii .stl file.

trisurface.write_stlb(f, x)

Export an x[n,3,3] float array as an binary .stl file.

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

(according to 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.surfaceInsideBorder(border, method='radial')

Create a surface inside a closed curve defined by a 2-plex Mesh.

border is a 2-plex Mesh representing a closed polyline.

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

There are two fill methods:

  • ‘radial’: this method adds a central point and connects all border segments with the center to create triangles. It is fast and works well if the border is smooth, nearly convex and nearly planar.
  • ‘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 segments that form the smallest angle. This method is slower, but works also for most complex borders. Also, because it does not create any new points, the returned surface uses the same point coordinate array as the input Mesh.
trisurface.read_error(cnt, line)

Raise an error on reading the stl file.

trisurface.degenerate(area, norm)

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.

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.

trisurface.Sphere(level=4, verbose=False, filename=None)

Create a spherical surface by calling the gtssphere command.

If a filename is given, it is stored under that name, else a temporary file is created. Beware: this may take a lot of time if level is 8 or higher.

Documentation

Previous topic

30. mesh — Finite element meshes in pyFormex.

Next topic

32. geomtools — Basic geometrical operations.

This Page