36. polygons — Polygon meshes.

This module defines the Polygons class, which can be used to describe discrete geometrical models consisting of polygons.

36.1. Classes defined in module polygons

class polygons.Polygons(coords=None, elems=None, *, prop=None, check=True)[source]

Polygons is a discrete geometrical model consisting of polygons.

The Polygons class is implemented in a similar manner as the Mesh and :class`TriSurface` classes: the coordinates of all the vertices are collected in a single Coords array, and the ‘elements’ (polygons) are defined using indices into that array. While the Mesh and :class`TriSurface` classes store the elements in an Elems array (requiring a fixed plexitude for all elements), the Polygons class uses a Varray so that the polygons can have a variable number of vertices.

Parameters:
  • coords (coords_like) – A 2-dim Coords (or data to initalize it) with the coordinates of all the vertices used to define the polygons.

  • elems (Varray) – A Varray (or data to initalize it) with the indices of the vertices that define each of the polygons. All values in elems should be in the range 0 <= value < len(coords).

  • prop (int array_like, optional) – 1-dim int array with non-negative element property numbers. If provided, setProp() will be called to assign the specified properties.

Examples

A Polygons with a triangle and a square.

>>> P = Polygons(Coords('0123'), [[0,1,2], [0,1,2,3]])
>>> print(P.report())
Polygons: nnodes: 4, nelems: 2, nplex: min 3, max 4, eltype: polygon
  BBox: [0. 0. 0.], [1. 1. 0.]
  Size: [1. 1. 0.]
  Coords: [[0. 0. 0.]
           [1. 0. 0.]
           [1. 1. 0.]
           [0. 1. 0.]]
  Elems: Varray (nrows=2, width=3..4)
           [0 1 2]
           [0 1 2 3]
check()[source]

Check that all polygons have at least length 3

property eltype

Return the element type of the Polygons.

Returns:

str – Always ‘polygon’

elName()[source]

Return the element name of the Polygons.

Returns:

str – Always ‘polygon’

level()[source]

Return the level of dimensionality of the polygons.

Returns:

int – Always 2.

property shape

Return the shape of the elems Varray.

nelems()[source]

Return the number of polygons.

This is the number of ‘rows’ in the elems Varray.

nplex()[source]

Return the plexitude of the polygon elements.

Always returns None, as there is no fixed plexitude of the polygons.

property plex

Return the plexitude of each of the elements

ncoords()[source]

Return the number of points used to define the polygons.

This is the first dimension of the coords array.

Notes

This may be different from the total number of vertices in all the polygons, as polygons may share some vertices.

See also size: The total number of vertices in all the polygons.

property size

Return the total number of polygon vertices.

This is the total number of entries in the elems Varray.

info()[source]

Return short info about the Mesh.

Returns:

str – A string with info about the shape of the coords and elems attributes.

report(full=True)[source]

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.

Note

NumPy normally limits the printed output. You will have to change numpy settings to actually print the full arrays.

shallowCopy(prop=None)[source]

Return a shallow copy.

Parameters:

prop (int array_like, optional) – 1-dim int array with non-negative element property numbers.

Returns:

Polygons – A shallow copy of the Mesh, using the same data arrays for coords and elems. If prop was provided, the new Mesh can have other property numbers. This is a convenient method to use the same Mesh with different property attributes.

classmethod triangleSelector(n)[source]

Return a selector to get triangle fan elements from polygons.

Examples

>>> Polygons.triangleSelector(5)
array([[0, 1, 2],
       [0, 2, 3],
       [0, 3, 4]])
classmethod edgeSelector(n)[source]

Return a selector to get edge elements from polygons.

Examples

>>> Polygons.edgeSelector(5)
array([[0, 1],
       [1, 2],
       [2, 3],
       [3, 4],
       [4, 0]])
triangles(layout='fan')[source]

Return an Elems with the triangles of the polygons

layout = ‘fan’ | ‘strip’ | ‘edglen’

TODO: only ‘fan’ is implemented!

edges(layout='fan')[source]

Return an Elems with the edges of the polygons

layout = ‘fan’ | ‘strip’ | ‘edglen’

TODO: only ‘fan’ is implemented!

print_tables()[source]

Print all the tables

property vertices

Return all vertices of all polygons.

Returns:

Coords – The coordinates of all vertices of all polygons, in the order of the elems data.

Examples

>>> P = Polygons(Coords('0123'), [[0,1,2], [0,1,2,3]])
>>> P.vertices
Coords([[0., 0., 0.],
        [1., 0., 0.],
        [1., 1., 0.],
        [0., 0., 0.],
        [1., 0., 0.],
        [1., 1., 0.],
        [0., 1., 0.]])
vectors()[source]

Return vectors along all edges of all polygons.

Returns:

Coords – The vectors along all the edges of all polygons, in the order of the elems data. The vectors point from each vertex to the next vertex in the polygon.

Examples

>>> P = Polygons(Coords('0123'), [[0,1,2], [0,1,2,3]])
>>> P.vectors()
Coords([[ 1.,  0.,  0.],
        [ 0.,  1.,  0.],
        [-1., -1.,  0.],
        [ 1.,  0.,  0.],
        [ 0.,  1.,  0.],
        [-1.,  0.,  0.],
        [ 0., -1.,  0.]])
vectorPairs()[source]

Compute vector pairs along the edges at each vertex of the polygons.

Returns:

  • vec1 (float array (nel, nplex, 3)) – The vectors from each vertex to the previous vertex in the polygon.

  • vec2 (float array (nel, nplex, 3)) – The vectors from each vertex to the next vertex in the polygon.

Examples

>>> P = Polygons(Coords('0123'), [[0,1,2], [0,1,2,3]])
>>> v1, v2 = P.vectorPairs()
>>> print(v1)
[[-1. -1.  0.]
 [ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0. -1.  0.]
 [ 1.  0.  0.]
 [ 0.  1.  0.]
 [-1.  0.  0.]]
>>> print(v2)
[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [-1. -1.  0.]
 [ 1.  0.  0.]
 [ 0.  1.  0.]
 [-1.  0.  0.]
 [ 0. -1.  0.]]
property vnormals

Return normals at vertices of polygons.

Returns:

normals (float array (self.size,3)) – The unit normals on the two edges ending at each vertex.

Examples

>>> P = Polygons(Coords('0123'), [[0,1,2], [0,1,2,3]])
>>> n = P.vnormals
>>> print(n.round(2)+0.)
[[0. 0. 1.]
 [0. 0. 1.]
 [0. 0. 1.]
 [0. 0. 1.]
 [0. 0. 1.]
 [0. 0. 1.]
 [0. 0. 1.]]
property angles

Compute internal angles at vertices of polygons.

Returns:

angles (float array (nel, nplex)) – The internal angles made by the two polygon edges at the vertex.

Examples

>>> P = Polygons(Coords('0123'), [[0,1,2], [0,1,2,3]])
>>> a = P.angles
>>> print(a)
[45. 90. 45. 90. 90. 90. 90.]
property fnormals

Compute mean face normals of polygons.

Returns:

fnormals (float array (self.nelems, 3)) – For each polygon, the mean of the normals at all its vertices.

Examples

>>> P = Polygons(Coords('0123'), [[0,1,2], [0,1,2,3], [2,1,0]])
>>> f = P.fnormals
>>> print(f)
[[ 0.  0.  1.]
 [ 0.  0.  1.]
 [ 0.  0. -1.]]
avg_normals(weights='angle', full=False, treshold=None)[source]

Compute averaged normals at the nodes of a Polygons.

Parameters:
  • coords (float array_like (ncoords, 3)) – Array with the coordinates of the nodes

  • elems (int array_like (nelems, nplex, 3)) – Definitions of the polygons in terms of the nodes. All polygons should have the same plexitude.

  • weights (float array_like | ‘angle’ | None) – Weights to apply to the polygon normals at a node during averaging. The default ‘angle’ will weigh the contribution of the polygons by the angle their edges make at the node. Custom values should be an array with shape (nelems, nplex). Specifying None will result in giving the same weight to all normals.

  • full (bool, optional) – If False (default), unique averaged normals at the nodes are returned. If True, the averaged normals are returned for each vertex of each polygon. This is mainly intended for rendering purposes.

  • treshold (float, optional) – Only used with full=True. If provided, element vertex normals making an angle with the averaged normal having a cosinus smaller than treshold, will be returned as the original normal. This allows the rendering of feature edges.

Returns:

normals (float array) – (ncoords, 3) The unit normals at the nodes, obtained by (weighted) averaging the normals on the polygons attached to that node. The default full=False returns an array with shape (ncoords, 3). With full=True, an array with shape (nelems, nplex, 3) is returned.

Examples

This example is the surface of a unit cube. Notice that the average normals come out nicely symmetric, even without weights, because all polygons have the same angles at the nodes.

>>> from pyformex.simple import Cube
>>> M = Cube()
>>> P = Polygons(M.coords, M.elems)
>>> print(P.avg_normals())
[[-0.5774 -0.5774 -0.5774]
 [ 0.5774 -0.5774 -0.5774]
 [ 0.5774  0.5774 -0.5774]
 [-0.5774  0.5774 -0.5774]
 [-0.5774 -0.5774  0.5774]
 [ 0.5774 -0.5774  0.5774]
 [ 0.5774  0.5774  0.5774]
 [-0.5774  0.5774  0.5774]]
>>> print(P.avg_normals(weights=None))
[[-0.5774 -0.5774 -0.5774]
 [ 0.5774 -0.5774 -0.5774]
 [ 0.5774  0.5774 -0.5774]
 [-0.5774  0.5774 -0.5774]
 [-0.5774 -0.5774  0.5774]
 [ 0.5774 -0.5774  0.5774]
 [ 0.5774  0.5774  0.5774]
 [-0.5774  0.5774  0.5774]]
classmethod concatenate(polys)[source]

Concatenate a list of Polygons.

Parameters:

polys (list of Polygons) – A list of Polygons instance to be concatenated to a single one.

Notes

The concatenation itself does not fuse the vertices that happen to be (nearly) conincident. You may want to call the fuse() method.

If any of the Polygons has property numbers, the resulting Polygons will inherit the properties. In that case, any elements from Polygons without properties will be assigned property 0. If all input objects are without properties, so will be the result.

Examples

>>> M0 = Mesh(eltype='quad4')
>>> P0 = Polygons(M0.coords, M0.elems)
>>> P1 = Polygons(M0.coords.trl(0, 1.), [[0,1,2],[0,2,3]])
>>> P = Polygons.concatenate([P0,P1])
>>> print(P.coords)
[[0. 0. 0.]
[1. 0. 0.]
[1. 1. 0.]
[0. 1. 0.]
[1. 0. 0.]
[2. 0. 0.]
[2. 1. 0.]
[1. 1. 0.]]
>>> print(P.elems)
Varray (nrows=3, width=3..4)
  [0 1 2 3]
  [4 5 6]
  [4 6 7]
>>> P = P.fuse()
>>> print(P.coords)
[[0. 0. 0.]
 [0. 1. 0.]
 [1. 0. 0.]
 [1. 1. 0.]
 [2. 0. 0.]
 [2. 1. 0.]]
>>> print(P.elems)
Varray (nrows=3, width=3..4)
  [0 2 3 1]
  [2 4 5]
  [2 5 3]
fuse(nodes=None, **kargs)[source]

Fuse the nodes of a Polygons.

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

Parameters:
  • nodes (int array_like, optional) – A list of node numbers. If provided, only these nodes will be involved in the fuse operation.

  • **kargs – Extra arguments for tuning the fuse operation are passed to the coords.Coords:fuse() method.

  • Examples (see concatenate()) –

compact()[source]

Remove unconnected nodes and renumber the Polygons.

Returns:

Polygons – The input object, where any unconnected nodes have been removed and the nodes are renumbered to a compacter scheme.

Notes

This changes the object in-place.

If the node-numbering has been changed, the object will have an attribute ‘oldnumbers’ which is an int array giving the old node number for in the position of the new node number.

Examples

>>> x = Coords([[i] for i in np.arange(5)])
>>> P = Polygons(x, [[0,1,2],[2,3,1,0]])
>>> print(P.coords)
[[0. 0. 0.]
 [1. 0. 0.]
 [2. 0. 0.]
 [3. 0. 0.]
 [4. 0. 0.]]
>>> P1 = P.compact()
>>> print(P1.coords)
[[0. 0. 0.]
 [1. 0. 0.]
 [2. 0. 0.]
 [3. 0. 0.]]
>>> print(P1.elems)
Varray (nrows=2, width=3..4)
  [0 1 2]
  [2 3 1 0]
>>> P1 is P
True
>>> print(P.oldnumbers)
None
>>> P = Polygons(x, [[4,1,2],[2,3,1,4]])
>>> P.compact()
<pyformex.polygons.Polygons object at ...>
>>> print(P.coords)
[[1. 0. 0.]
 [2. 0. 0.]
 [3. 0. 0.]
 [4. 0. 0.]]
>>> print(P.elems)
Varray (nrows=2, width=3..4)
  [3 0 1]
  [1 2 0 3]
>>> print(P.oldnumbers)
[1 2 3 4]
reduce(mplex)[source]

Reduce the Polygons to a specified maximum plexitude.

Parameters:

mplex (int) – The maximal plexitude of the output polygons. Thus, with mplex=3 only triangles will results; mplex=4 will yield triangles and quads.

Returns:

Polygons – A Polygons where all of the polygons with more than mplex vertices have been split into smaller ones.

Notes

Splitting a polygon is done along the shortest diagonal.

See also

split

split (and optionally reduce) the Polygons into Mesh objects.

Examples

>>> x = Coords([[i] for i in np.arange(5)])
>>> P = Polygons(x, [[0,1,2],[0,1,2,3],[0,1,2,3,4]])
>>> print(P.reduce(4).elems)
Varray (nrows=4, width=3..4)
  [0 1 2]
  [0 1 2]
  [0 1 2 3]
  [2 3 4 0]
>>> print(P.reduce(3).elems)
Varray (nrows=6, width=3..3)
  [0 1 2]
  [0 1 2]
  [0 1 2]
  [2 3 4]
  [2 3 0]
  [4 0 2]
>>>
split(mplex=None)[source]

Split the Polygons into Meshes of fixed plexitude

Parameters:

mplex (int, optional) – The maximal plexitude of the resulting Meshes. Thus, with mplex=3 only triangles will results; mplex=4 will yield triangles and quads. If needed, polygons will be split up to be smaller that the maximum plexitude. If not provided, the original plexitudes are kept.

Returns:

list of Mesh – A list of Mesh objects with plexitude >= 3. The eltype of the Mesh objects is Tri3, Quad4 or Poly# for plexitudes > 4. All the Mesh objects use the same coords object. The list is sorted in order of increasing plexitude.

Notes

While reducing and splitting the Polygons can also be achieved with self.reduce(mplex).split(), using the mplex argument here is slightly faster.

See also

reduce

reduce the maximum plexitude of the polygons

toSurface(method='reduce')[source]

Convert the Polygons to a TriSurface

Parameters:

method (str) –

The method to use to convert polygons into triangles. One of:

  • ’reduce’: use the reduce() method, splitting the polygons along the shortest diagonals. This is the default.

  • ’fan’: split the polygons into a fan of triangles with apex at the first point. This corresponds to hoe the polygons are rendered.

  • ’prune’: simply removes all non-triangle polygons.

Notes

Currently, the ‘reduce’ method does not retain the ‘prop’ values.

pzf_dict()[source]

Construct common part of all Geometry pzf dicts

36.2. Functions defined in module polygons

polygons.nodalVSum(val, elems, nnod=None)[source]

Compute the nodal sum of values defined at polygon vertices.

This is like arraytools.nodalSum(), but where elems is defined as a Varray and val contains the value in order of that Varray.

Parameters:
  • val (float array (nsize, nval)) – Defines nval values at elems.nsize vertices.

  • elems (Varray) – The node indices of nelems polygons.

  • nnod (int) – The number of nodes. This should be higher than the maximum value in elems. If not specified, it will be set to the highest value in elems + 1.

Returns:

  • sum (float ndarray (nnod, nval)) – The sum of all the values at the same node.

  • cnt (int ndarray (nnod)) – The number of values summed at each node.