163 const Quadrilateral &inputQ,
const size_t y_start,
const size_t y_end,
164 const size_t x_start,
const size_t x_end, std::vector<AreaInfo> &areaInfos) {
172 V2D ll = inputQ[0], ul = inputQ[1], ur = inputQ[2], lr = inputQ[3];
173 const double mBot = (lr.Y() - ll.
Y()) / (lr.X() - ll.
X());
174 const double cBot = ll.
Y() - mBot * ll.
X();
175 const double mTop = (ur.Y() - ul.Y()) / (ur.X() - ul.X());
176 const double cTop = ul.Y() - mTop * ul.X();
179 if (ll.
X() < xAxis[x_start]) {
180 ll =
V2D(xAxis[x_start], mBot * xAxis[x_start] + cBot);
181 ul =
V2D(xAxis[x_start], mTop * xAxis[x_start] + cTop);
183 if (lr.X() > xAxis[x_end]) {
184 lr =
V2D(xAxis[x_end], mBot * xAxis[x_end] + cBot);
185 ur =
V2D(xAxis[x_end], mTop * xAxis[x_end] + cTop);
188 const size_t nx = x_end - x_start;
189 const size_t ny = y_end - y_start;
190 const double ll_x(ll.
X()), ll_y(ll.
Y()), ul_y(ul.Y());
191 const double lr_x(lr.X()), lr_y(lr.Y()), ur_y(ur.Y());
193 if (nx == 1 && ny == 1 && (ll_y >= yAxis[y_start] && ll_y <= yAxis[y_start + 1]) &&
194 (ul_y >= yAxis[y_start] && ul_y <= yAxis[y_start + 1]) &&
195 (ur_y >= yAxis[y_start] && ur_y <= yAxis[y_start + 1]) &&
196 (lr_y >= yAxis[y_start] && lr_y <= yAxis[y_start + 1])) {
197 areaInfos.emplace_back(x_start, y_start, 0.5 * polyArea(ll, ul, ur, lr, ll));
202 const double NaN = std::numeric_limits<double>::quiet_NaN();
203 const double DBL_EPS = std::numeric_limits<double>::epsilon();
204 std::vector<double> leftLim((nx + 1) * (ny + 1), NaN);
205 std::vector<double> rightLim((nx + 1) * (ny + 1), NaN);
206 auto x0_it = xAxis.begin() + x_start;
207 auto x1_it = xAxis.begin() + x_end + 1;
208 auto y0_it = yAxis.begin() + y_start;
209 auto y1_it = yAxis.begin() + y_end + 1;
210 const size_t ymax = (y_end == yAxis.size()) ? ny : (ny + 1);
211 if ((mTop >= 0 && mBot >= 0) || (mTop < 0 && mBot < 0)) {
214 double left_val, right_val;
215 for (
size_t yj = 0; yj < ymax; ++yj) {
216 const size_t yjx = yj * nx;
219 left_val = (yAxis[yj + y_start] - cTop) / mTop;
220 right_val = (yAxis[yj + y_start] - cBot) / mBot;
222 left_val = (yAxis[yj + y_start] - cBot) / mBot;
223 right_val = (yAxis[yj + y_start] - cTop) / mTop;
225 if (left_val < ll_x || left_val > lr_x)
227 if (right_val < ll_x || right_val > lr_x)
229 auto left_it = std::upper_bound(x0_it, x1_it, left_val);
231 if (left_it != x1_it) {
232 li = left_it - x0_it - 1;
233 leftLim[li + yjx] = left_val;
234 }
else if (yAxis[yj + y_start] < ul_y) {
236 leftLim[li + yjx] = ll_x;
238 auto right_it = std::upper_bound(x0_it, x1_it, right_val);
239 if (right_it != x1_it) {
240 rightLim[right_it - x0_it - 1 + yjx] = right_val;
241 }
else if (yAxis[yj + y_start] < ur_y && nx > 0) {
242 right_it = x1_it - 1;
243 rightLim[nx - 1 + yjx] = lr_x;
246 if (left_it < right_it && right_it != x1_it) {
247 for (
auto x_it = left_it; x_it != right_it; ++x_it) {
248 leftLim[li + 1 + yjx] = *x_it;
249 rightLim[li++ + yjx] = *x_it;
255 const size_t y2 = std::upper_bound(y0_it, y1_it, (mTop >= 0) ? ll_y : lr_y) - y0_it;
256 const size_t y3 = std::upper_bound(y0_it, y1_it, (mTop >= 0) ? ul_y : ur_y) - y0_it;
258 for (
size_t yj = 0; yj < ymax; ++yj) {
259 const size_t yjx = yj * nx;
261 val = (yAxis[yj + y_start] - cBot) / mBot;
262 }
else if (yj < y3) {
263 val = (mTop >= 0) ? ll_x : lr_x;
265 val = (yAxis[yj + y_start] - cTop) / mTop;
267 if (val < ll_x || val > lr_x)
269 auto left_it = (mTop >= 0) ? std::upper_bound(x0_it, x1_it, val) : (x0_it + 1);
270 auto right_it = (mTop >= 0) ? (x1_it - 1) : std::upper_bound(x0_it, x1_it, val);
271 if (left_it == x1_it)
273 if (right_it == x1_it)
275 size_t li = (left_it > x0_it) ? (left_it - x0_it - 1) : 0;
276 size_t ri = (right_it > x0_it) ? (right_it - x0_it - 1) : 0;
277 leftLim[li + yjx] = (mTop >= 0) ? val : ll_x;
278 rightLim[ri + yjx] = (mTop >= 0) ? lr_x : val;
279 if (left_it < right_it && right_it != x1_it) {
280 for (
auto x_it = left_it; x_it != right_it; x_it++) {
281 leftLim[li + 1 + yjx] = *x_it;
282 rightLim[li++ + yjx] = *x_it;
289 const size_t LL_IN = 1 << 1;
290 const size_t UL_IN = 1 << 2;
291 const size_t UR_IN = 1 << 3;
292 const size_t LR_IN = 1 << 4;
295 V2D nll(ll), nul(ul), nur, nlr, l0, r0, l1, r1;
298 areaInfos.reserve(nx * ny);
300 for (
size_t xi = x_start; xi < x_end; ++xi) {
301 const size_t xj = xi - x_start;
307 if (xi == (x_end - 1)) {
311 nlr =
V2D(xAxis[xi + 1], mBot * xAxis[xi + 1] + cBot);
312 nur =
V2D(xAxis[xi + 1], mTop * xAxis[xi + 1] + cTop);
315 for (
size_t yi = y_start; yi < y_end; ++yi) {
316 yj0 = (yi - y_start) * nx;
317 yj1 = (yi - y_start + 1) * nx;
319 if (yAxis[yi] > std::max(nll.Y(), nlr.
Y()) && yAxis[yi + 1] < std::min(nul.Y(), nur.
Y())) {
320 areaInfos.emplace_back(xi, yi, (nlr.
X() - nll.X()) * (yAxis[yi + 1] - yAxis[yi]));
322 }
else if (yAxis[yi + 1] >= std::min(nll.Y(), nlr.
Y()) && yAxis[yi] <= std::max(nul.Y(), nur.
Y())) {
324 if (nll.Y() >= yAxis[yi] && nll.Y() <= yAxis[yi + 1])
326 if (nul.Y() >= yAxis[yi] && nul.Y() <= yAxis[yi + 1])
328 if (nur.
Y() >= yAxis[yi] && nur.
Y() <= yAxis[yi + 1])
330 if (nlr.
Y() >= yAxis[yi] && nlr.
Y() <= yAxis[yi + 1])
332 l0 =
V2D(leftLim[xj + yj0], yAxis[yi]);
333 r0 =
V2D(rightLim[xj + yj0], yAxis[yi]);
334 l1 =
V2D(leftLim[xj + yj1], yAxis[yi + 1]);
335 r1 =
V2D(rightLim[xj + yj1], yAxis[yi + 1]);
344 area = polyArea(l1, r1, r0, l0, l1);
350 area = polyArea(nll, l1, r1, r0, l0, nll);
352 area = polyArea(nll, l1, r1, nll);
356 area = polyArea(l1, r1, r0, l0, nul, l1);
358 area = polyArea(r0, l0, nul, r0);
362 area = polyArea(nur, r0, l0, l1, r1, nur);
364 area = polyArea(nur, r0, l0, nur);
368 area = polyArea(r0, l0, l1, r1, nlr, r0);
370 area = polyArea(l1, r1, nlr, l1);
373 case (LL_IN | UL_IN):
376 area = polyArea(nll, nul, l1, r1, r0, l0, nll);
378 area = polyArea(nll, nul, l1, r1, nll);
379 }
else if (mBot < 0) {
380 area = polyArea(nll, nul, r0, l0, nll);
383 case (UR_IN | LR_IN):
386 area = polyArea(nur, nlr, r0, l0, l1, r1, nur);
388 area = polyArea(nur, nlr, r0, l0, nur);
389 }
else if (mTop < 0) {
390 area = polyArea(nur, nlr, l1, r1, nur);
393 case (UL_IN | UR_IN):
394 area = polyArea(nul, nur, r0, l0, nul);
396 case (LL_IN | LR_IN):
397 area = polyArea(nlr, nll, l1, r1, nlr);
399 case (LL_IN | UR_IN):
400 area = polyArea(nll, l1, r1, nur, r0, l0, nll);
402 case (UL_IN | LR_IN):
403 area = polyArea(nul, l1, r1, nlr, r0, l0, nul);
406 case (UL_IN | UR_IN | LR_IN):
407 area = polyArea(nul, nur, nlr, r0, l0, nul);
409 case (LL_IN | UR_IN | LR_IN):
410 area = polyArea(nll, l1, r1, nur, nlr, nll);
412 case (LL_IN | UL_IN | LR_IN):
413 area = polyArea(nlr, nll, nul, l1, r1, nlr);
415 case (LL_IN | UL_IN | UR_IN):
416 area = polyArea(nul, nur, r0, l0, nll, nul);
419 case (LL_IN | UL_IN | UR_IN | LR_IN):
420 area = polyArea(nll, nul, nur, nlr, nll);
424 areaInfos.emplace_back(xi, yi, 0.5 * area);