64 std::size_t requestedLevels)
67 if (potential.
empty() || potential.
width() < 2u || potential.
height() < 2u || requestedLevels == 0u) {
74 if (!(range > 1.0e-12f)) {
78 bool onlyExtremes =
true;
79 const float eps = std::max(1.0e-7f, std::fabs(range) * 1.0e-6f);
80 for (std::size_t y = 0; y < potential.
height() && onlyExtremes; ++y) {
81 for (std::size_t x = 0; x < potential.
width(); ++x) {
82 const float v = potential(x, y);
83 if (std::fabs(v - out.
minimum) > eps && std::fabs(v - out.
maximum) > eps) {
94 const std::size_t count = std::max<std::size_t>(1u, requestedLevels);
95 for (std::size_t i = 0; i < count; ++i) {
96 const float f =
static_cast<float>(i + 1u) /
static_cast<float>(count + 1u);
101 for (std::size_t li = 0; li < out.
levels.size(); ++li) {
102 const float level = out.
levels[li];
103 for (std::size_t y = 0; y + 1u < potential.
height(); ++y) {
104 for (std::size_t x = 0; x + 1u < potential.
width(); ++x) {
105 const float v0 = potential(x, y);
106 const float v1 = potential(x + 1u, y);
107 const float v2 = potential(x + 1u, y + 1u);
108 const float v3 = potential(x, y + 1u);
111 if (v0 > level) mask |= 1;
112 if (v1 > level) mask |= 2;
113 if (v2 > level) mask |= 4;
114 if (v3 > level) mask |= 8;
115 if (mask == 0 || mask == 15)
continue;
117 const P2 p0 = {
static_cast<float>(potential.
xCoordinate(x)),
119 const P2 p1 = {
static_cast<float>(potential.
xCoordinate(x + 1u)),
121 const P2 p2 = {
static_cast<float>(potential.
xCoordinate(x + 1u)),
122 static_cast<float>(potential.
yCoordinate(y + 1u)) };
123 const P2 p3 = {
static_cast<float>(potential.
xCoordinate(x)),
124 static_cast<float>(potential.
yCoordinate(y + 1u)) };
127 edge[0] = interpolate(p0, p1, v0, v1, level);
128 edge[1] = interpolate(p1, p2, v1, v2, level);
129 edge[2] = interpolate(p2, p3, v2, v3, level);
130 edge[3] = interpolate(p3, p0, v3, v0, level);
133 case 1:
case 14: addSegment(out, edge[3], edge[0], level);
break;
134 case 2:
case 13: addSegment(out, edge[0], edge[1], level);
break;
135 case 3:
case 12: addSegment(out, edge[3], edge[1], level);
break;
136 case 4:
case 11: addSegment(out, edge[1], edge[2], level);
break;
137 case 6:
case 9: addSegment(out, edge[0], edge[2], level);
break;
138 case 7:
case 8: addSegment(out, edge[3], edge[2], level);
break;
140 const float center = 0.25f * (v0 + v1 + v2 + v3);
141 if (center > level) {
142 addSegment(out, edge[3], edge[2], level);
143 addSegment(out, edge[0], edge[1], level);
145 addSegment(out, edge[3], edge[0], level);
146 addSegment(out, edge[2], edge[1], level);
151 const float center = 0.25f * (v0 + v1 + v2 + v3);
152 if (center > level) {
153 addSegment(out, edge[3], edge[0], level);
154 addSegment(out, edge[2], edge[1], level);
156 addSegment(out, edge[3], edge[2], level);
157 addSegment(out, edge[0], edge[1], level);