43inline void Contour(
const double *d,
size_t ilb,
size_t iub,
size_t jlb,
44 size_t jub,
const double *x,
const double *y,
size_t nc,
45 double *z, std::vector<ConrecSegment> &res) {
54 int m1, m2, m3, case_value;
55 double dmin, dmax, x1 = 0, x2 = 0, y1 = 0, y2 = 0;
61 int im[4] = {0, 1, 1, 0}, jm[4] = {0, 0, 1, 1};
62 int castab[3][3][3] = {{{0, 0, 8}, {0, 2, 5}, {7, 6, 9}},
63 {{0, 3, 4}, {1, 3, 1}, {4, 3, 0}},
64 {{9, 6, 7}, {5, 2, 0}, {8, 0, 0}}};
66 size_t ny = jub - jlb + 1;
68 auto xsect = [&](
int p1,
int p2) {
69 return (h[p2] * xh[p1] - h[p1] * xh[p2]) / (h[p2] - h[p1]);
71 auto ysect = [&](
int p1,
int p2) {
72 return (h[p2] * yh[p1] - h[p1] * yh[p2]) / (h[p2] - h[p1]);
75 for (j = (jub - 1); j >= (int)jlb; j--) {
76 for (i = ilb; i <= (int)iub - 1; i++) {
77 temp1 = std::min(d[i * ny + j], d[i * ny + j + 1]);
78 temp2 = std::min(d[(i + 1) * ny + j], d[(i + 1) * ny + j + 1]);
79 dmin = std::min(temp1, temp2);
80 temp1 = std::max(d[i * ny + j], d[i * ny + j + 1]);
81 temp2 = std::max(d[(i + 1) * ny + j], d[(i + 1) * ny + j + 1]);
82 dmax = std::max(temp1, temp2);
83 if (dmax < z[0] || dmin > z[nc - 1]) {
86 for (k = 0; k < nc; k++) {
87 if (z[k] < dmin || z[k] > dmax) {
90 for (m = 4; m >= 0; m--) {
92 h[m] = d[(i + im[m - 1]) * ny + j + jm[m - 1]] - z[k];
93 xh[m] = x[i + im[m - 1]];
94 yh[m] = y[j + jm[m - 1]];
96 h[0] = 0.25 * (h[1] + h[2] + h[3] + h[4]);
97 xh[0] = 0.50 * (x[i] + x[i + 1]);
98 yh[0] = 0.50 * (y[j] + y[j + 1]);
102 }
else if (h[m] < 0.0) {
133 for (m = 1; m <= 4; m++) {
141 if ((case_value = castab[sh[m1] + 1][sh[m2] + 1][sh[m3] + 1]) == 0) {
144 switch (case_value) {
225 double coordMultiplier = 1000,
226 double isoValMultiplier = 1e6) {
227 std::vector<std::pair<std::vector<RDGeom::Point2D>,
double>> res;
228 std::unordered_map<std::tuple<int, int, long>, std::list<size_t>,
tplHash>
231 auto makePointKey = [&coordMultiplier, &isoValMultiplier](
const auto &pt,
233 return std::make_tuple<int, int, long>(
234 std::lround(coordMultiplier * pt.x),
235 std::lround(coordMultiplier * pt.y),
236 std::lround(isoValMultiplier * isoVal));
240 for (
auto i = 0u; i < segments.size(); ++i) {
241 const auto &seg = segments[i];
242 endPointHashes[makePointKey(seg.p1, seg.isoVal)].push_back(i);
243 endPointHashes[makePointKey(seg.p2, seg.isoVal)].push_back(i);
246 boost::dynamic_bitset<> segmentsDone(segments.size());
248 auto isCandidate = [&segmentsDone](
const auto &pr) {
249 return !pr.second.empty() && !segmentsDone[pr.second.front()];
252 std::find_if(endPointHashes.begin(), endPointHashes.end(), isCandidate);
253 while (singlePoint != endPointHashes.end()) {
254 auto segId = singlePoint->second.front();
255 auto currKey = singlePoint->first;
256 auto currVal = segments[segId].isoVal;
257 std::vector<RDGeom::Point2D> contour;
259 segmentsDone.set(segId,
true);
261 const auto seg = segments[segId];
262 auto k1 = makePointKey(seg.p1, seg.isoVal);
263 auto k2 = makePointKey(seg.p2, seg.isoVal);
266 contour.push_back(seg.p1);
267 }
else if (k2 == currKey) {
268 contour.push_back(seg.p2);
272 auto &segs1 = endPointHashes[currKey];
273 segs1.erase(std::find(segs1.begin(), segs1.end(), segId));
275 auto &segs = endPointHashes[endPtKey];
276 segs.erase(std::find(segs.begin(), segs.end(), segId));
280 contour.push_back(seg.p2);
281 }
else if (k2 == currKey) {
282 contour.push_back(seg.p1);
286 segId = segs.front();
289 res.push_back(std::make_pair(contour, currVal));
290 singlePoint = std::find_if(singlePoint, endPointHashes.end(), isCandidate);