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

Skip to content

Commit 5bad764

Browse files
committed
Merge pull request #6450 from mdboom/slow-path
PRF: Speed up point_in_path and friends
2 parents e2549cd + aef86ad commit 5bad764

File tree

7 files changed

+74
-78
lines changed

7 files changed

+74
-78
lines changed

lib/matplotlib/tests/test_path.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ def test_contains_points_negative_radius():
3939
expected = [True, False, False]
4040
result = path.contains_points(points, radius=-0.5)
4141

42-
assert result.dtype == np.bool
4342
assert np.all(result == expected)
4443

4544

src/_backend_agg.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -961,13 +961,13 @@ inline void RendererAgg::_draw_path_collection_generic(GCAgg &gc,
961961
typename PathGenerator::path_iterator path = path_generator(i);
962962

963963
if (Ntransforms) {
964-
typename TransformArray::sub_t subtrans = transforms[i % Ntransforms];
965-
trans = agg::trans_affine(subtrans(0, 0),
966-
subtrans(1, 0),
967-
subtrans(0, 1),
968-
subtrans(1, 1),
969-
subtrans(0, 2),
970-
subtrans(1, 2));
964+
int it = i % Ntransforms;
965+
trans = agg::trans_affine(transforms(it, 0, 0),
966+
transforms(it, 1, 0),
967+
transforms(it, 0, 1),
968+
transforms(it, 1, 1),
969+
transforms(it, 0, 2),
970+
transforms(it, 1, 2));
971971
trans *= master_transform;
972972
} else {
973973
trans = master_transform;
@@ -989,13 +989,13 @@ inline void RendererAgg::_draw_path_collection_generic(GCAgg &gc,
989989
trans *= agg::trans_affine_translation(0.0, (double)height);
990990

991991
if (Nfacecolors) {
992-
typename ColorArray::sub_t facecolor = facecolors[i % Nfacecolors];
993-
face.second = agg::rgba(facecolor(0), facecolor(1), facecolor(2), facecolor(3));
992+
int ic = i % Nfacecolors;
993+
face.second = agg::rgba(facecolors(ic, 0), facecolors(ic, 1), facecolors(ic, 2), facecolors(ic, 3));
994994
}
995995

996996
if (Nedgecolors) {
997-
typename ColorArray::sub_t edgecolor = edgecolors[i % Nedgecolors];
998-
gc.color = agg::rgba(edgecolor(0), edgecolor(1), edgecolor(2), edgecolor(3));
997+
int ic = i % Nedgecolors;
998+
gc.color = agg::rgba(edgecolors(ic, 0), edgecolors(ic, 1), edgecolors(ic, 2), edgecolors(ic, 3));
999999

10001000
if (Nlinewidths) {
10011001
gc.linewidth = linewidths(i % Nlinewidths);
@@ -1274,8 +1274,8 @@ inline void RendererAgg::draw_gouraud_triangles(GCAgg &gc,
12741274
bool has_clippath = render_clippath(gc.clippath.path, gc.clippath.trans);
12751275

12761276
for (int i = 0; i < points.dim(0); ++i) {
1277-
typename PointArray::sub_t point = points[i];
1278-
typename ColorArray::sub_t color = colors[i];
1277+
typename PointArray::sub_t point = points.subarray(i);
1278+
typename ColorArray::sub_t color = colors.subarray(i);
12791279

12801280
_draw_gouraud_triangle(point, color, trans, has_clippath);
12811281
}

src/_image.h

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,12 @@ Image *from_color_array(ArrayType &array, bool isoutput)
126126

127127
for (size_t rownum = 0; rownum < (size_t)array.dim(0); rownum++) {
128128
for (size_t colnum = 0; colnum < (size_t)array.dim(1); colnum++) {
129-
typename ArrayType::sub_t::sub_t color = array[rownum][colnum];
130-
131-
r = color(0);
132-
g = color(1);
133-
b = color(2);
129+
r = array(rownum, colnum, 0);
130+
g = array(rownum, colnum, 1);
131+
b = array(rownum, colnum, 2);
134132

135133
if (rgba) {
136-
alpha = color(3);
134+
alpha = array(rownum, colnum, 3);
137135
}
138136

139137
*buffer++ = int(255 * r); // red
@@ -164,13 +162,12 @@ Image *frombyte(ArrayType &array, bool isoutput)
164162

165163
for (size_t rownum = 0; rownum < (size_t)array.dim(0); rownum++) {
166164
for (size_t colnum = 0; colnum < (size_t)array.dim(1); colnum++) {
167-
typename ArrayType::sub_t::sub_t color = array[rownum][colnum];
168-
r = color(0);
169-
g = color(1);
170-
b = color(2);
165+
r = array(rownum, colnum, 0);
166+
g = array(rownum, colnum, 1);
167+
b = array(rownum, colnum, 2);
171168

172169
if (rgba) {
173-
alpha = color(3);
170+
alpha = array(rownum, colnum, 3);
174171
}
175172

176173
*buffer++ = r; // red
@@ -295,13 +292,12 @@ Image *pcolor(CoordinateArray &x,
295292
a10 = (1.0 - alpha) * beta;
296293
a11 = 1.0 - a00 - a01 - a10;
297294

298-
typename ColorArray::sub_t::sub_t start00 = d[rowstart[i]][colstart[j]];
299-
typename ColorArray::sub_t::sub_t start01 = d[rowstart[i]][colstart[j] + 1];
300-
typename ColorArray::sub_t::sub_t start10 = d[rowstart[i] + 1][colstart[j]];
301-
typename ColorArray::sub_t::sub_t start11 = d[rowstart[i] + 1][colstart[j] + 1];
302295
for (size_t k = 0; k < 4; ++k) {
303296
position[k] =
304-
start00(k) * a00 + start01(k) * a01 + start10(k) * a10 + start11(k) * a11;
297+
d(rowstart[i], colstart[j], k) * a00 +
298+
d(rowstart[i], colstart[j] + 1, k) * a01 +
299+
d(rowstart[i] + 1, colstart[j], k) * a10 +
300+
d(rowstart[i] + 1, colstart[j] + 1, k) * a11;
305301
}
306302
position += 4;
307303
}

src/_path.h

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "path_converters.h"
2020
#include "_backend_agg_basic_types.h"
21+
#include "numpy_cpp.h"
2122

2223
struct XY
2324
{
@@ -79,7 +80,7 @@ struct XY
7980
template <class PathIterator, class PointArray, class ResultArray>
8081
void point_in_path_impl(PointArray &points, PathIterator &path, ResultArray &inside_flag)
8182
{
82-
bool yflag1;
83+
uint8_t yflag1;
8384
double vtx0, vty0, vtx1, vty1;
8485
double tx, ty;
8586
double sx, sy;
@@ -89,13 +90,13 @@ void point_in_path_impl(PointArray &points, PathIterator &path, ResultArray &ins
8990

9091
size_t n = points.size();
9192

92-
std::vector<bool> yflag0(n);
93-
std::vector<bool> subpath_flag(n);
93+
std::vector<uint8_t> yflag0(n);
94+
std::vector<uint8_t> subpath_flag(n);
9495

9596
path.rewind(0);
9697

9798
for (i = 0; i < n; ++i) {
98-
inside_flag[i] = false;
99+
inside_flag[i] = 0;
99100
}
100101

101102
unsigned code = 0;
@@ -112,13 +113,13 @@ void point_in_path_impl(PointArray &points, PathIterator &path, ResultArray &ins
112113
sy = vty0 = vty1 = y;
113114

114115
for (i = 0; i < n; ++i) {
115-
ty = points[i][1];
116+
ty = points(i, 1);
116117

117118
if (std::isfinite(ty)) {
118119
// get test bit for above/below X axis
119120
yflag0[i] = (vty0 >= ty);
120121

121-
subpath_flag[i] = false;
122+
subpath_flag[i] = 0;
122123
}
123124
}
124125

@@ -135,8 +136,8 @@ void point_in_path_impl(PointArray &points, PathIterator &path, ResultArray &ins
135136
}
136137

137138
for (i = 0; i < n; ++i) {
138-
tx = points[i][0];
139-
ty = points[i][1];
139+
tx = points(i, 0);
140+
ty = points(i, 1);
140141

141142
if (!(std::isfinite(tx) && std::isfinite(ty))) {
142143
continue;
@@ -164,7 +165,7 @@ void point_in_path_impl(PointArray &points, PathIterator &path, ResultArray &ins
164165
// Haigh-Hutchinson's different polygon inclusion
165166
// tests.
166167
if (((vty1 - ty) * (vtx0 - vtx1) >= (vtx1 - tx) * (vty0 - vty1)) == yflag1) {
167-
subpath_flag[i] = subpath_flag[i] ^ true;
168+
subpath_flag[i] ^= 1;
168169
}
169170
}
170171

@@ -183,8 +184,8 @@ void point_in_path_impl(PointArray &points, PathIterator &path, ResultArray &ins
183184

184185
all_done = true;
185186
for (i = 0; i < n; ++i) {
186-
tx = points[i][0];
187-
ty = points[i][1];
187+
tx = points(i, 0);
188+
ty = points(i, 1);
188189

189190
if (!(std::isfinite(tx) && std::isfinite(ty))) {
190191
continue;
@@ -196,8 +197,8 @@ void point_in_path_impl(PointArray &points, PathIterator &path, ResultArray &ins
196197
subpath_flag[i] = subpath_flag[i] ^ true;
197198
}
198199
}
199-
inside_flag[i] = inside_flag[i] || subpath_flag[i];
200-
if (inside_flag[i] == false) {
200+
inside_flag[i] |= subpath_flag[i];
201+
if (inside_flag[i] == 0) {
201202
all_done = false;
202203
}
203204
}
@@ -232,21 +233,23 @@ inline void points_in_path(PointArray &points,
232233
transformed_path_t trans_path(path, trans);
233234
no_nans_t no_nans_path(trans_path, true, path.has_curves());
234235
curve_t curved_path(no_nans_path);
235-
contour_t contoured_path(curved_path);
236-
contoured_path.width(r);
237-
238-
point_in_path_impl(points, contoured_path, result);
236+
if (r != 0.0) {
237+
contour_t contoured_path(curved_path);
238+
contoured_path.width(r);
239+
point_in_path_impl(points, contoured_path, result);
240+
} else {
241+
point_in_path_impl(points, curved_path, result);
242+
}
239243
}
240244

241245
template <class PathIterator>
242246
inline bool point_in_path(
243247
double x, double y, const double r, PathIterator &path, agg::trans_affine &trans)
244248
{
245-
std::vector<double> point;
246-
std::vector<std::vector<double> > points;
247-
point.push_back(x);
248-
point.push_back(y);
249-
points.push_back(point);
249+
npy_intp shape[] = {1, 2};
250+
numpy::array_view<double, 2> points(shape);
251+
points(0, 0) = x;
252+
points(0, 1) = y;
250253

251254
int result[1];
252255
result[0] = 0;
@@ -285,11 +288,10 @@ template <class PathIterator>
285288
inline bool point_on_path(
286289
double x, double y, const double r, PathIterator &path, agg::trans_affine &trans)
287290
{
288-
std::vector<double> point;
289-
std::vector<std::vector<double> > points;
290-
point.push_back(x);
291-
point.push_back(y);
292-
points.push_back(point);
291+
npy_intp shape[] = {1, 2};
292+
numpy::array_view<double, 2> points(shape);
293+
points(0, 0) = x;
294+
points(0, 1) = y;
293295

294296
int result[1];
295297
result[0] = 0;
@@ -385,13 +387,13 @@ void get_path_collection_extents(agg::trans_affine &master_transform,
385387
for (i = 0; i < N; ++i) {
386388
typename PathGenerator::path_iterator path(paths(i % Npaths));
387389
if (Ntransforms) {
388-
typename TransformArray::sub_t subtrans = transforms[i % Ntransforms];
389-
trans = agg::trans_affine(subtrans(0, 0),
390-
subtrans(1, 0),
391-
subtrans(0, 1),
392-
subtrans(1, 1),
393-
subtrans(0, 2),
394-
subtrans(1, 2));
390+
size_t ti = i % Ntransforms;
391+
trans = agg::trans_affine(transforms(ti, 0, 0),
392+
transforms(ti, 1, 0),
393+
transforms(ti, 0, 1),
394+
transforms(ti, 1, 1),
395+
transforms(ti, 0, 2),
396+
transforms(ti, 1, 2));
395397
} else {
396398
trans = master_transform;
397399
}
@@ -437,13 +439,13 @@ void point_in_path_collection(double x,
437439
typename PathGenerator::path_iterator path = paths(i % Npaths);
438440

439441
if (Ntransforms) {
440-
typename TransformArray::sub_t subtrans = transforms[i % Ntransforms];
441-
trans = agg::trans_affine(subtrans(0, 0),
442-
subtrans(1, 0),
443-
subtrans(0, 1),
444-
subtrans(1, 1),
445-
subtrans(0, 2),
446-
subtrans(1, 2));
442+
size_t ti = i % Ntransforms;
443+
trans = agg::trans_affine(transforms(ti, 0, 0),
444+
transforms(ti, 1, 0),
445+
transforms(ti, 0, 1),
446+
transforms(ti, 1, 1),
447+
transforms(ti, 0, 2),
448+
transforms(ti, 1, 2));
447449
trans *= master_transform;
448450
} else {
449451
trans = master_transform;
@@ -771,8 +773,7 @@ int count_bboxes_overlapping_bbox(agg::rect_d &a, BBoxArray &bboxes)
771773

772774
size_t num_bboxes = bboxes.size();
773775
for (size_t i = 0; i < num_bboxes; ++i) {
774-
typename BBoxArray::sub_t bbox_b = bboxes[i];
775-
b = agg::rect_d(bbox_b(0, 0), bbox_b(0, 1), bbox_b(1, 0), bbox_b(1, 1));
776+
b = agg::rect_d(bboxes(i, 0, 0), bboxes(i, 0, 1), bboxes(i, 1, 0), bboxes(i, 1, 1));
776777

777778
if (b.x2 < b.x1) {
778779
std::swap(b.x1, b.x2);

src/_path_wrapper.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ static PyObject *Py_points_in_path(PyObject *self, PyObject *args, PyObject *kwd
9393
}
9494

9595
npy_intp dims[] = { (npy_intp)points.size() };
96-
numpy::array_view<bool, 1> results(dims);
96+
numpy::array_view<uint8_t, 1> results(dims);
9797

9898
CALL_CPP("points_in_path", (points_in_path(points, r, path, trans, results)));
9999

@@ -152,7 +152,7 @@ static PyObject *Py_points_on_path(PyObject *self, PyObject *args, PyObject *kwd
152152
}
153153

154154
npy_intp dims[] = { (npy_intp)points.size() };
155-
numpy::array_view<bool, 1> results(dims);
155+
numpy::array_view<uint8_t, 1> results(dims);
156156

157157
CALL_CPP("points_on_path", (points_on_path(points, r, path, trans, results)));
158158

src/_png.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ static PyObject *Py_write_png(PyObject *self, PyObject *args, PyObject *kwds)
9191
int channels = buffer.dim(2);
9292
std::vector<png_bytep> row_pointers(height);
9393
for (png_uint_32 row = 0; row < (png_uint_32)height; ++row) {
94-
row_pointers[row] = (png_bytep)buffer[row].data();
94+
row_pointers[row] = (png_bytep)&buffer(row, 0, 0);
9595
}
9696

9797
FILE *fp = NULL;

src/numpy_cpp.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ class array_view_accessors<AV, T, 2>
284284
self->m_strides[1] * j);
285285
}
286286

287-
sub_t operator[](npy_intp i) const
287+
sub_t subarray(npy_intp i) const
288288
{
289289
const AVC *self = static_cast<const AVC *>(this);
290290

@@ -318,7 +318,7 @@ class array_view_accessors<AV, T, 3>
318318
self->m_strides[1] * j + self->m_strides[2] * k);
319319
}
320320

321-
sub_t operator[](npy_intp i) const
321+
sub_t subarray(npy_intp i) const
322322
{
323323
const AVC *self = static_cast<const AVC *>(this);
324324

0 commit comments

Comments
 (0)