/usr/share/pyshared/matplotlib/tri/triangulation.py is in python-matplotlib 1.1.1~rc1+git20120423-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | import matplotlib.delaunay as delaunay
import matplotlib._tri as _tri
import numpy as np
class Triangulation(object):
"""
An unstructured triangular grid consisting of npoints points and
ntri triangles. The triangles can either be specified by the user
or automatically generated using a Delaunay triangulation.
Read-only attributes:
*x*: array of shape (npoints).
x-coordinates of grid points.
*y*: array of shape (npoints).
y-coordinates of grid points.
*triangles*: integer array of shape (ntri,3).
For each triangle, the indices of the three points that make
up the triangle, ordered in an anticlockwise manner.
*mask*: optional boolean array of shape (ntri).
Which triangles are masked out.
*edges*: integer array of shape (?,2).
All edges of non-masked triangles. Each edge is the start
point index and end point index. Each edge (start,end and
end,start) appears only once.
*neighbors*: integer array of shape (ntri,3).
For each triangle, the indices of the three triangles that
share the same edges, or -1 if there is no such neighboring
triangle. neighbors[i,j] is the triangle that is the neighbor
to the edge from point index triangles[i,j] to point index
triangles[i,(j+1)%3].
"""
def __init__(self, x, y, triangles=None, mask=None):
"""
Create a Triangulation object.
The first two arguments must be:
*x*, *y*: arrays of shape (npoints).
Point coordinates.
Optional arguments (args or keyword args):
*triangles*: integer array of shape (ntri,3).
For each triangle, the indices of the three points that make
up the triangle. If the points are ordered in a clockwise
manner, they are converted to anticlockwise.
If not specified, matplotlib.delaunay is used to create a
Delaunay triangulation of the points.
*mask*: optional boolean array of shape (ntri).
Which triangles are masked out.
"""
self.x = np.asarray(x, dtype=np.float64)
self.y = np.asarray(y, dtype=np.float64)
if self.x.shape != self.y.shape or len(self.x.shape) != 1:
raise ValueError("x and y must be equal-length 1-D arrays")
self.mask = None
self._edges = None
self._neighbors = None
if triangles is None:
# No triangulation specified, so use matplotlib.delaunay.
dt = delaunay.Triangulation(self.x, self.y)
self.triangles = np.asarray(dt.triangle_nodes, dtype=np.int32)
if mask is None:
self._edges = np.asarray(dt.edge_db, dtype=np.int32)
# Delaunay triangle_neighbors uses different edge indexing,
# so convert.
neighbors = np.asarray(dt.triangle_neighbors, dtype=np.int32)
self._neighbors = np.roll(neighbors, 1, axis=1)
else:
# Triangulation specified.
self.triangles = np.asarray(triangles, dtype=np.int32)
if self.triangles.ndim != 2 or self.triangles.shape[1] != 3:
raise ValueError('triangles must be a (?,3) array')
if self.triangles.max() >= len(self.x):
raise ValueError('triangles max element is out of bounds')
if self.triangles.min() < 0:
raise ValueError('triangles min element is out of bounds')
if mask is not None:
self.mask = np.asarray(mask, dtype=np.bool)
if len(self.mask.shape) != 1 or \
self.mask.shape[0] != self.triangles.shape[0]:
raise ValueError('mask array must have same length as '
'triangles array')
# Underlying C++ object is not created until first needed.
self._cpp_triangulation = None
@property
def edges(self):
if self._edges is None:
self._edges = self.get_cpp_triangulation().get_edges()
return self._edges
def get_cpp_triangulation(self):
"""
Return the underlying C++ Triangulation object, creating it
if necessary.
"""
if self._cpp_triangulation is None:
self._cpp_triangulation = _tri.Triangulation(
self.x, self.y, self.triangles, self.mask, self._edges,
self._neighbors)
return self._cpp_triangulation
def get_masked_triangles(self):
"""
Return an array of triangles that are not masked.
"""
if self.mask is not None:
return self.triangles.compress(1-self.mask, axis=0)
else:
return self.triangles
@staticmethod
def get_from_args_and_kwargs(*args, **kwargs):
"""
Return a Triangulation object from the args and kwargs, and
the remaining args and kwargs with the consumed values removed.
There are two alternatives: either the first argument is a
Triangulation object, in which case it is returned, or the args
and kwargs are sufficient to create a new Triangulation to
return. In the latter case, see Triangulation.__init__ for
the possible args and kwargs.
"""
if isinstance(args[0], Triangulation):
triangulation = args[0]
args = args[1:]
else:
x = args[0]
y = args[1]
args = args[2:] # Consumed first two args.
# Check triangles in kwargs then args.
triangles = kwargs.pop('triangles', None)
from_args = False
if triangles is None and len(args) > 0:
triangles = args[0]
from_args = True
if triangles is not None:
try:
triangles = np.asarray(triangles, dtype=np.int32)
except ValueError:
triangles = None
if triangles is not None and (triangles.ndim != 2 or
triangles.shape[1] != 3):
triangles = None
if triangles is not None and from_args:
args = args[1:] # Consumed first item in args.
# Check for mask in kwargs.
mask = kwargs.pop('mask', None)
triangulation = Triangulation(x, y, triangles, mask)
return triangulation, args, kwargs
@property
def neighbors(self):
if self._neighbors is None:
self._neighbors = self.get_cpp_triangulation().get_neighbors()
return self._neighbors
def set_mask(self, mask):
"""
Set or clear the mask array. This is either None, or a boolean
array of shape (ntri).
"""
if mask is None:
self.mask = None
else:
self.mask = np.asarray(mask, dtype=np.bool)
if len(self.mask.shape) != 1 or \
self.mask.shape[0] != self.triangles.shape[0]:
raise ValueError('mask array must have same length as '
'triangles array')
# Set mask in C++ Triangulation.
if self._cpp_triangulation is not None:
self._cpp_triangulation.set_mask(self.mask)
# Clear derived fields so they are recalculated when needed.
self._edges = None
self._neighbors = None
|