Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4fc08fb

Browse files
committed
Corrected duplicate points in delaunay.
1 parent 79deb35 commit 4fc08fb

File tree

2 files changed

+61
-16
lines changed

2 files changed

+61
-16
lines changed

lib/matplotlib/delaunay/triangulate.py

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,29 @@ class Triangulation(object):
6161
6262
hull -- list of point_id's giving the nodes which form the convex hull
6363
of the point set. This list is sorted in counter-clockwise order.
64+
65+
Duplicate points.
66+
If there are no duplicate points, Triangulation stores the specified
67+
x and y arrays and there is no difference between the client's and
68+
Triangulation's understanding of point indices used in edge_db,
69+
triangle_nodes and hull.
70+
71+
If there are duplicate points, they are removed from the stored
72+
self.x and self.y as the underlying delaunay code cannot deal with
73+
duplicates. len(self.x) is therefore equal to len(x) minus the
74+
number of duplicate points. Triangulation's edge_db, triangle_nodes
75+
and hull refer to point indices in self.x and self.y, for internal
76+
consistency within Triangulation and the corresponding Interpolator
77+
classes. Client code must take care to deal with this in one of
78+
two ways:
79+
80+
1. Ignore the x,y it specified in Triangulation's constructor and
81+
use triangulation.x and triangulation.y instead, as these are
82+
consistent with edge_db, triangle_nodes and hull.
83+
84+
2. If using the x,y the client specified then edge_db,
85+
triangle_nodes and hull should be passed through the function
86+
to_client_point_indices() first.
6487
"""
6588
def __init__(self, x, y):
6689
self.x = np.asarray(x, dtype=np.float64)
@@ -70,38 +93,48 @@ def __init__(self, x, y):
7093
raise ValueError("x,y must be equal-length 1-D arrays")
7194

7295
self.old_shape = self.x.shape
73-
j_unique = self._collapse_duplicate_points()
96+
duplicates = self._get_duplicate_point_indices()
7497

75-
if j_unique.shape != self.x.shape:
98+
if len(duplicates) > 0:
7699
warnings.warn(
77100
"Input data contains duplicate x,y points; some values are ignored.",
78101
DuplicatePointWarning,
79102
)
80-
self.j_unique = j_unique
103+
104+
# self.j_unique is the array of non-duplicate indices, in
105+
# increasing order.
106+
self.j_unique = np.delete(np.arange(len(self.x)), duplicates)
81107
self.x = self.x[self.j_unique]
82108
self.y = self.y[self.j_unique]
109+
110+
# Create map of point indices used by delaunay to those used
111+
# by client.
112+
self._client_point_index_map = np.delete(np.arange(self.old_shape[0]),
113+
duplicates)
83114
else:
84115
self.j_unique = None
85-
116+
self._client_point_index_map = None
86117

87118
self.circumcenters, self.edge_db, self.triangle_nodes, \
88119
self.triangle_neighbors = delaunay(self.x, self.y)
89120

90121
self.hull = self._compute_convex_hull()
91122

92-
def _collapse_duplicate_points(self):
93-
"""Generate index array that picks out unique x,y points.
94-
95-
This appears to be required by the underlying delaunay triangulation
96-
code.
123+
def _get_duplicate_point_indices(self):
124+
"""Return array of indices of x,y points that are duplicates of
125+
previous points. Indices are in no particular order.
97126
"""
98-
# Find the indices of the unique entries
127+
# Indices of sorted x,y points.
99128
j_sorted = np.lexsort(keys=(self.x, self.y))
100-
mask_unique = np.hstack([
101-
True,
102-
(np.diff(self.x[j_sorted]) != 0) | (np.diff(self.y[j_sorted]) != 0),
129+
130+
# Mask, in j_sorted order, which is True for duplicate points.
131+
mask_duplicates = np.hstack([
132+
False,
133+
(np.diff(self.x[j_sorted]) == 0) & (np.diff(self.y[j_sorted]) == 0),
103134
])
104-
return j_sorted[mask_unique]
135+
136+
# Array of duplicate point indices, in no particular order.
137+
return j_sorted[mask_duplicates]
105138

106139
def _compute_convex_hull(self):
107140
"""Extract the convex hull from the triangulation information.
@@ -129,6 +162,16 @@ def _compute_convex_hull(self):
129162

130163
return hull
131164

165+
def to_client_point_indices(self, array):
166+
"""Converts any array of point indices used within this class to
167+
refer to point indices within the (x,y) arrays specified in the
168+
constructor before duplicates were removed.
169+
"""
170+
if self._client_point_index_map is not None:
171+
return self._client_point_index_map[array]
172+
else:
173+
return array
174+
132175
def linear_interpolator(self, z, default_value=np.nan):
133176
"""Get an object which can interpolate within the convex hull by
134177
assigning a plane to each triangle.

lib/matplotlib/tri/triangulation.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,11 @@ def __init__(self, x, y, triangles=None, mask=None):
6969
if triangles is None:
7070
# No triangulation specified, so use matplotlib.delaunay.
7171
dt = delaunay.Triangulation(self.x, self.y)
72-
self.triangles = np.asarray(dt.triangle_nodes, dtype=np.int32)
72+
self.triangles = np.asarray(dt.to_client_point_indices(dt.triangle_nodes),
73+
dtype=np.int32)
7374
if mask is None:
74-
self._edges = np.asarray(dt.edge_db, dtype=np.int32)
75+
self._edges = np.asarray(dt.to_client_point_indices(dt.edge_db),
76+
dtype=np.int32)
7577
# Delaunay triangle_neighbors uses different edge indexing,
7678
# so convert.
7779
neighbors = np.asarray(dt.triangle_neighbors, dtype=np.int32)

0 commit comments

Comments
 (0)