24template <
class LeftNumber,
class LeftLabel,
class RightNumber,
class RightLabel>
26 return left.
x() * right.
x() + left.
y() * right.
y();
32template <
class Po
intType,
class LabelType>
33template <
class ResultNumber>
35 return ResultNumber{};
38template <
class Po
intType,
class LabelType>
43template <
class Po
intType,
class LabelType>
48template <
class Po
intType,
class LabelType>
49template <
class ApproximateNumber>
51 return min().template distance<ApproximateNumber>(
max());
54template <
class Po
intType,
class LabelType>
56 return min().distanceL1(
max());
59template <
class Po
intType,
class LabelType>
61 return min().distanceLInf(
max());
64template <
class Po
intType,
class LabelType>
65template <
class ResultNumber>
67 const auto dy = detail::asNumber<ResultNumber>(
max().
y()) - detail::asNumber<ResultNumber>(
min().
y());
68 const auto dx = detail::asNumber<ResultNumber>(
max().
x()) - detail::asNumber<ResultNumber>(
min().
x());
72template <
class Po
intType,
class LabelType>
77template <
class Po
intType,
class LabelType>
78template <
class ResultNumber>
81 (detail::asNumber<ResultNumber>(
min().
x()) + detail::asNumber<ResultNumber>(
max().
x())) /
static_cast<ResultNumber
>(2),
82 (detail::asNumber<ResultNumber>(
min().
y()) + detail::asNumber<ResultNumber>(
max().
y())) /
static_cast<ResultNumber
>(2)
86template <
class Po
intType,
class LabelType>
87template <
class ResultNumber>
92template <
class Po
intType,
class LabelType>
93template <
class OtherShape>
97 return shape.interiorContains(witness);
107template <
class Po
intType,
class LabelType>
108template <
class ResultNumber>
110 return ResultNumber{};
113template <
class Po
intType,
class LabelType>
118template <
class Po
intType,
class LabelType>
123template <
class Po
intType,
class LabelType>
124template <
class ApproximateNumber>
126 return source().template distance<ApproximateNumber>(
target());
129template <
class Po
intType,
class LabelType>
134template <
class Po
intType,
class LabelType>
139template <
class Po
intType,
class LabelType>
140template <
class ResultNumber>
142 const auto dy = detail::asNumber<ResultNumber>(
target().
y()) - detail::asNumber<ResultNumber>(
source().
y());
143 const auto dx = detail::asNumber<ResultNumber>(
target().
x()) - detail::asNumber<ResultNumber>(
source().
x());
147template <
class Po
intType,
class LabelType>
152template <
class Po
intType,
class LabelType>
153template <
class ResultNumber>
156 (detail::asNumber<ResultNumber>(
source().
x()) + detail::asNumber<ResultNumber>(
target().
x())) /
static_cast<ResultNumber
>(2),
157 (detail::asNumber<ResultNumber>(
source().
y()) + detail::asNumber<ResultNumber>(
target().
y())) /
static_cast<ResultNumber
>(2));
160template <
class Po
intType,
class LabelType>
161template <
class ResultNumber>
166template <
class Po
intType,
class LabelType>
167template <
class OtherShape>
170 return asSegment().pointInsideInteriorContainedIn(shape);
176template <
class Po
intType,
class LabelType>
177template <
class ResultNumber>
179 return ResultNumber{};
182template <
class Po
intType,
class LabelType>
187template <
class Po
intType,
class LabelType>
188template <
class ResultNumber>
190 const auto dy = detail::asNumber<ResultNumber>(
max().
y()) - detail::asNumber<ResultNumber>(
min().
y());
191 const auto dx = detail::asNumber<ResultNumber>(
max().
x()) - detail::asNumber<ResultNumber>(
min().
x());
195template <
class Po
intType,
class LabelType>
196template <
class ResultNumber>
201template <
class Po
intType,
class LabelType>
202template <
class OtherShape>
211template <
class Po
intType,
class LabelType>
212template <
class ResultNumber>
214 return ResultNumber{};
217template <
class Po
intType,
class LabelType>
222template <
class Po
intType,
class LabelType>
223template <
class ResultNumber>
225 const auto dy = detail::asNumber<ResultNumber>(
target().
y()) - detail::asNumber<ResultNumber>(
source().
y());
226 const auto dx = detail::asNumber<ResultNumber>(
target().
x()) - detail::asNumber<ResultNumber>(
source().
x());
230template <
class Po
intType,
class LabelType>
231template <
class ResultNumber>
236template <
class Po
intType,
class LabelType>
237template <
class OtherShape>
240 return asLine().pointInsideInteriorContainedIn(shape);
246template <
class Po
intType,
class LabelType>
247template <
class ResultNumber>
249 return ResultNumber{};
252template <
class Po
intType,
class LabelType>
257template <
class Po
intType,
class LabelType>
258template <
class ResultNumber>
260 const auto dy = detail::asNumber<ResultNumber>(
target().
y()) - detail::asNumber<ResultNumber>(
source().
y());
261 const auto dx = detail::asNumber<ResultNumber>(
target().
x()) - detail::asNumber<ResultNumber>(
source().
x());
265template <
class Po
intType,
class LabelType>
266template <
class ResultNumber>
271template <
class Po
intType,
class LabelType>
272template <
class OtherShape>
282template <
class Po
intType,
class LabelType>
283template <
class ResultNumber>
287 return static_cast<ResultNumber
>(
width()) *
static_cast<ResultNumber
>(
height());
290template <
class Po
intType,
class LabelType>
292 const auto rectangle_area =
area();
293 return rectangle_area + rectangle_area;
296template <
class Po
intType,
class LabelType>
302template <
class Po
intType,
class LabelType>
303template <
class ResultNumber>
307 (detail::asNumber<ResultNumber>(
min().
x()) + detail::asNumber<ResultNumber>(
max().
x())) /
static_cast<ResultNumber
>(2),
308 (detail::asNumber<ResultNumber>(
min().
y()) + detail::asNumber<ResultNumber>(
max().
y())) /
static_cast<ResultNumber
>(2));
311template <
class Po
intType,
class LabelType>
312template <
class ResultNumber>
317template <
class Po
intType,
class LabelType>
323template <
class Po
intType,
class LabelType>
324template <
class ResultNumber>
329template <
class Po
intType,
class LabelType>
330template <
class ResultNumber>
335template <
class Po
intType,
class LabelType>
336template <
class OtherShape>
340 return shape.interiorContains(witness);
350template <
class Po
intType,
class LabelType>
355template <
class Po
intType,
class LabelType>
356template <
class ResultNumber>
359 return detail::asNumber<ResultNumber>(area2) /
static_cast<ResultNumber
>(2);
362template <
class Po
intType,
class LabelType>
363template <
class ResultNumber>
365 const ResultNumber three =
static_cast<ResultNumber
>(3);
367 (detail::asNumber<ResultNumber>(
a().
x()) +
368 detail::asNumber<ResultNumber>(
b().
x()) +
369 detail::asNumber<ResultNumber>(
c().
x())) / three,
370 (detail::asNumber<ResultNumber>(
a().
y()) +
371 detail::asNumber<ResultNumber>(
b().
y()) +
372 detail::asNumber<ResultNumber>(
c().
y())) / three);
375template <
class Po
intType,
class LabelType>
380template <
class Po
intType,
class LabelType>
399template <
class Po
intType,
class LabelType>
400template <
class ResultNumber>
403 p = (p/2 + points_[2])/2;
407template <
class Po
intType,
class LabelType>
408template <
class OtherShape>
412 return shape.interiorContains(witness);
419template <
class Po
intType,
class LabelType>
425 const auto ab =
b() -
a();
426 const auto ac =
c() -
a();
427 const auto bc =
c() -
b();
441template <
class Po
intType,
class LabelType>
447 const auto ab =
b() -
a();
448 const auto ac =
c() -
a();
449 const auto bc =
c() -
b();
458template <
class Po
intType,
class LabelType>
465 using Squared = detail::promoted_number_t<NumberType>;
470 return ab == bc || bc == ca || ca == ab;
476template <
class Po
intType,
class LabelType>
477template <
class ResultNumber>
479 const auto dy = detail::asNumber<ResultNumber>(
target().
y()) - detail::asNumber<ResultNumber>(
source().
y());
480 const auto dx = detail::asNumber<ResultNumber>(
target().
x()) - detail::asNumber<ResultNumber>(
source().
x());
484template <
class Po
intType,
class LabelType>
485template <
class ResultNumber>
487 const ResultNumber
x =
static_cast<ResultNumber
>(
source().x());
488 const ResultNumber
y =
static_cast<ResultNumber
>(
source().y());
489 const ResultNumber one =
static_cast<ResultNumber
>(1);
500 return {
x + one,
y - one};
503template <
class Po
intType,
class LabelType>
504template <
class OtherShape>
515template <
class Po
intType,
class LabelType>
517 if (points_.size() < 3) {
521 for (std::size_t i = 0; i < points_.size(); ++i) {
522 const auto& p1 = points_[i];
523 const auto& p2 = points_[(i + 1) % points_.size()];
524 sum += p1.x() * p2.y() - p2.x() * p1.y();
526 return pgl::detail::abs(sum);
529template <
class Po
intType,
class LabelType>
530template <
class ResultNumber>
532 ResultNumber result =
static_cast<ResultNumber
>(
twiceArea());
533 return result / ResultNumber(2);
536template <
class Po
intType,
class LabelType>
537template <
class ResultNumber>
539 if (points_.empty()) {
542 if (points_.size() == 1) {
546 if (points_.size() == 2 || area_twice ==
NumberType(0)) {
553 for (std::size_t i = 0; i < points_.size(); ++i) {
554 const auto& p1 = points_[i];
555 const auto& p2 = points_[(i + 1) % points_.size()];
556 const auto cross = p1.x() * p2.y() - p2.x() * p1.y();
557 cx += (p1.x() + p2.x()) * cross;
558 cy += (p1.y() + p2.y()) * cross;
560 return Point<ResultNumber>(cx / (ResultNumber(3) * area_twice), cy / (ResultNumber(3) * area_twice))
564template <
class Po
intType,
class LabelType>
565template <
class ResultNumber>
567 if (points_.empty()) {
572 for (
const auto&
vertex : points_) {
573 cx += detail::asNumber<ResultNumber>(
vertex.x());
574 cy += detail::asNumber<ResultNumber>(
vertex.y());
576 return Point<ResultNumber>(cx /
static_cast<ResultNumber
>(points_.size()), cy /
static_cast<ResultNumber
>(points_.size()))
580template <
class Po
intType,
class LabelType>
581template <
class ResultNumber>
583 if (points_.empty()) {
586 if (points_.size() == 1) {
589 if (points_.size() == 2) {
601template <
class Po
intType,
class LabelType>
602template <
class OtherShape>
606 return shape.interiorContains(witness);
613template <
class Po
intType,
class LabelType>
614constexpr std::vector<std::pair<std::size_t, std::size_t>>
616 const std::size_t n =
size();
617 std::vector<std::pair<std::size_t, std::size_t>> pairs;
622 pairs.emplace_back(0, 1);
626 const auto next = [n](std::size_t v) {
return v + 1 == n ? std::size_t{0} : v + 1; };
633 using Coord = detail::promoted_number_t<NumberType>;
634 const auto edgeCross = [
this, n](std::size_t i, std::size_t j) {
635 const auto pi = (*this)[i];
636 const auto pi1 = (*this)[i + 1 == n ? std::size_t{0} : i + 1];
637 const auto pj = (*this)[j];
638 const auto pj1 = (*this)[j + 1 == n ? std::size_t{0} : j + 1];
639 const Coord eix = detail::asNumber<Coord>(pi1.x()) - detail::asNumber<Coord>(pi.x());
640 const Coord eiy = detail::asNumber<Coord>(pi1.y()) - detail::asNumber<Coord>(pi.y());
641 const Coord ejx = detail::asNumber<Coord>(pj1.x()) - detail::asNumber<Coord>(pj.x());
642 const Coord ejy = detail::asNumber<Coord>(pj1.y()) - detail::asNumber<Coord>(pj.y());
643 return eix * ejy - eiy * ejx;
650 const std::size_t j0 = 0;
654 const auto isStart = [i0](std::size_t a, std::size_t b) {
655 return (a == i0 && b == j0) || (a == j0 && b == i0);
657 const auto emit = [&pairs, &isStart](std::size_t a, std::size_t b) {
663 pairs.emplace_back(std::min(a, b), std::max(a, b));
666 pairs.emplace_back(std::min(i0, j0), std::max(i0, j0));
671 const auto c = edgeCross(i, j);
679 const std::size_t i2 = next(i);
680 const std::size_t j2 = next(j);
686 if (i == j0 && j == i0) {
695template <
class Po
intType,
class LabelType>
697 const std::size_t n =
size();
710 (*
this)[pairs.front().second]);
711 for (
const auto& [i, j] : pairs) {
712 const auto pi = (*this)[i];
713 const auto pj = (*this)[j];
715 if (bestSquared < squared) {
716 bestSquared = squared;
723template <
class Po
intType,
class LabelType>
726 const std::size_t n =
size();
735 using Coord = detail::promoted_number_t<NumberType>;
740 using Wide = std::conditional_t<
741 std::floating_point<NumberType>, Coord,
747 const auto next = [n](std::size_t v) {
return v + 1 == n ? std::size_t{0} : v + 1; };
748 const auto difference = [
this](std::size_t a, std::size_t b) {
749 const auto pa = (*this)[a];
750 const auto pb = (*this)[b];
751 return Vec{detail::asNumber<Coord>(pa.x()) - detail::asNumber<Coord>(pb.x()),
752 detail::asNumber<Coord>(pa.y()) - detail::asNumber<Coord>(pb.y())};
754 const auto edgeVector = [&](std::size_t i) {
return difference(next(i), i); };
755 const auto dot = [](
const Vec& u,
const Vec& w) {
return u.x * w.x + u.y * w.y; };
756 const auto cross = [](
const Vec& u,
const Vec& w) {
return u.x * w.y - u.y * w.x; };
765 std::size_t right = 0;
767 std::size_t left = 0;
768 const auto advance = [&](std::size_t& support,
auto better) {
769 while (better(
difference(next(support), support))) {
770 support = next(support);
773 const auto advanceRight = [&](
const Vec& u) {
774 advance(right, [&](
const Vec& step) {
return dot(u, step) > 0; });
776 const auto advanceTop = [&](
const Vec& u) {
777 advance(top, [&](
const Vec& step) {
return cross(u, step) > 0; });
779 const auto advanceLeft = [&](
const Vec& u) {
780 advance(left, [&](
const Vec& step) {
return dot(u, step) < 0; });
786 const Vec u = edgeVector(0);
800 std::size_t bestEdge = 0, bestRight = 0, bestTop = 0, bestLeft = 0;
801 Wide bestWidth(0), bestHeight(0), bestSquaredLength(1);
802 for (std::size_t i = 0; i < n; ++i) {
803 const Vec u = edgeVector(i);
808 const Coord low = dot(u,
difference(left, i));
809 const Coord high = dot(u,
difference(right, i));
810 const Coord width = high - low;
811 const Coord height = cross(u,
difference(top, i));
812 const Coord squaredLength = dot(u, u);
814 const Wide wideWidth = detail::asNumber<Wide>(width);
815 const Wide wideHeight = detail::asNumber<Wide>(height);
816 const Wide wideSquaredLength = detail::asNumber<Wide>(squaredLength);
817 if (i == 0 || wideWidth * wideHeight * bestSquaredLength <
818 bestWidth * bestHeight * wideSquaredLength) {
823 bestWidth = wideWidth;
824 bestHeight = wideHeight;
825 bestSquaredLength = wideSquaredLength;
833 const PointType base = (*this)[bestEdge];
834 const PointType tip = (*this)[next(bestEdge)];
836 const PointType across = along.rotated90();
837 const PointType topSupport = (*this)[bestTop];
838 const PointType rightSupport = (*this)[bestRight];
839 const PointType leftSupport = (*this)[bestLeft];
864template <
class Po
intType,
class LabelType>
865constexpr std::pair<std::size_t, std::size_t>
867 using NumberType =
typename PointType::NumberType;
868 const std::size_t n = convex.
size();
872 using Coord = promoted_number_t<NumberType>;
879 using Wide = std::conditional_t<
880 std::floating_point<NumberType>, Coord,
886 const auto next = [n](std::size_t v) {
return v + 1 == n ? std::size_t{0} : v + 1; };
887 const auto difference = [&convex](std::size_t a, std::size_t b) {
888 const auto pa = convex[a];
889 const auto pb = convex[b];
890 return Vec{asNumber<Coord>(pa.x()) - asNumber<Coord>(pb.x()),
891 asNumber<Coord>(pa.y()) - asNumber<Coord>(pb.y())};
893 const auto edgeVector = [&](std::size_t i) {
return difference(next(i), i); };
894 const auto dot = [](
const Vec& u,
const Vec& w) {
return u.x * w.x + u.y * w.y; };
895 const auto cross = [](
const Vec& u,
const Vec& w) {
return u.x * w.y - u.y * w.x; };
898 const auto advance = [&](
auto better) {
899 while (better(difference(next(top), top))) {
903 const auto advanceTop = [&](
const Vec& u) {
904 advance([&](
const Vec& step) {
return cross(u, step) > Coord(0); });
912 const Vec u = edgeVector(0);
913 advance([&](
const Vec& step) {
return dot(u, step) > Coord(0); });
922 std::size_t bestEdge = 0, bestTop = 0;
923 Wide bestSquaredHeight(0), bestSquaredLength(1);
925 for (std::size_t i = 0; i < n; ++i) {
926 const Vec u = edgeVector(i);
929 const Coord squaredLength = dot(u, u);
930 if (squaredLength == Coord(0)) {
936 const Coord height = cross(u, difference(top, i));
938 const Wide wideHeight = asNumber<Wide>(height);
939 const Wide wideSquaredHeight = wideHeight * wideHeight;
940 const Wide wideSquaredLength = asNumber<Wide>(squaredLength);
941 if (!found || wideSquaredHeight * bestSquaredLength <
942 bestSquaredHeight * wideSquaredLength) {
946 bestSquaredHeight = wideSquaredHeight;
947 bestSquaredLength = wideSquaredLength;
950 return {bestEdge, bestTop};
965template <
class Number,
class Po
intType,
class LabelType>
966constexpr std::pair<Number, Number>
968 const std::size_t n = convex.size();
969 const auto base = convex[
edge];
970 const auto tip = convex[
edge + 1 == n ? std::size_t{0} :
edge + 1];
971 const auto support = convex[top];
973 const Number ux = asNumber<Number>(tip.x()) - asNumber<Number>(base.x());
974 const Number uy = asNumber<Number>(tip.y()) - asNumber<Number>(base.y());
975 const Number vx = asNumber<Number>(support.x()) - asNumber<Number>(base.x());
976 const Number vy = asNumber<Number>(support.y()) - asNumber<Number>(base.y());
978 const Number squaredLength = ux * ux + uy * uy;
979 if (squaredLength == Number(0)) {
984 return {Number(0), Number(1)};
986 return {ux * vy - uy * vx, squaredLength};
991template <
class Po
intType,
class LabelType>
994 const std::size_t n =
size();
1001 const auto [bestEdge, bestTop] = detail::minimumWidthSupport(*
this);
1007 const PointType base = (*this)[bestEdge];
1008 const PointType tip = (*this)[bestEdge + 1 == n ? std::size_t{0} : bestEdge + 1];
1010 const PointType topSupport = (*this)[bestTop];
1017template <
class Po
intType,
class LabelType>
1018template <
class ResultNumber>
1021 return ResultNumber{};
1024 const auto [bestEdge, bestTop] = detail::minimumWidthSupport(*
this);
1025 const auto [height, squaredLength] =
1026 detail::minimumWidthFraction<ResultNumber>(*
this, bestEdge, bestTop);
1027 return height * height / squaredLength;
1030template <
class Po
intType,
class LabelType>
1031template <
class ApproximateNumber>
1034 return ApproximateNumber{};
1037 const auto [bestEdge, bestTop] = detail::minimumWidthSupport(*
this);
1038 const auto [height, squaredLength] =
1039 detail::minimumWidthFraction<ApproximateNumber>(*
this, bestEdge, bestTop);
1042 return height / std::sqrt(squaredLength);
1048template <
class Po
intType,
class LabelType>
1049template <
class ResultNumber>
1051 const std::size_t n =
size();
1073 std::optional<PointType> q;
1074 for (std::size_t i = 2; i + 1 < n; ++i) {
1077 if (!q.has_value() || v < *q) {
1083 if (q.has_value()) {
1092template <
class Po
intType,
class LabelType>
1093template <
class OtherShape>
1097 return shape.interiorContains(witness);
1107template <
class Po
intType,
class LabelType>
1108template <
class ResultNumber>
1116 const auto accumulate = [&](
const PolygonType& ring) {
1117 for (
const auto&
vertex : ring) {
1118 cx += detail::asNumber<ResultNumber>(
vertex.x());
1119 cy += detail::asNumber<ResultNumber>(
vertex.y());
1123 for (
const auto&
hole : holes_) {
1126 return Point<ResultNumber>(cx / detail::asNumber<ResultNumber>(n), cy / detail::asNumber<ResultNumber>(n));
1129template <
class Po
intType,
class LabelType>
1130template <
class ResultNumber>
1146 const auto accumulate = [&](
const PolygonType& ring,
int sign) {
1147 const auto ringTwiceArea =
static_cast<ResultNumber
>(ring.
twiceArea());
1149 const ResultNumber weight = ringTwiceArea * detail::asNumber<ResultNumber>(sign);
1150 cx += ringCentroid.x() * weight;
1151 cy += ringCentroid.y() * weight;
1153 accumulate(outer_, 1);
1154 for (
const auto&
hole : holes_) {
1155 accumulate(
hole, -1);
1157 const auto denominator =
static_cast<ResultNumber
>(netTwiceArea);
1164template <
class Po
intType,
class LabelType>
1165template <
class ResultNumber>
1173 for (
const auto&
component : components_) {
1175 const auto weight =
static_cast<ResultNumber
>(
component.vertexCount());
1176 cx += componentCentroid.x() * weight;
1177 cy += componentCentroid.y() * weight;
1179 return Point<ResultNumber>(cx / detail::asNumber<ResultNumber>(n), cy / detail::asNumber<ResultNumber>(n));
1182template <
class Po
intType,
class LabelType>
1183template <
class ResultNumber>
1200 for (
const auto&
component : components_) {
1201 const auto weight =
static_cast<ResultNumber
>(
component.twiceArea());
1203 cx += componentCentroid.x() * weight;
1204 cy += componentCentroid.y() * weight;
1206 const auto denominator =
static_cast<ResultNumber
>(netTwiceArea);
1213template <
class Po
intType,
class LabelType,
class Storage>
1214template <
class ApproximateNumber>
1216 ApproximateNumber total{};
1217 for (std::size_t i = 1; i < points_.size(); ++i) {
1218 total += points_[i - 1].template distance<ApproximateNumber>(points_[i]);
1223template <
class Po
intType,
class LabelType,
class Storage>
1225 decltype(std::declval<PointType>().distanceL1(std::declval<PointType>())) total{};
1226 for (std::size_t i = 1; i < points_.size(); ++i) {
1227 total += points_[i - 1].distanceL1(points_[i]);
1232template <
class Po
intType,
class LabelType,
class Storage>
1234 decltype(std::declval<PointType>().distanceLInf(std::declval<PointType>())) total{};
1235 for (std::size_t i = 1; i < points_.size(); ++i) {
1236 total += points_[i - 1].distanceLInf(points_[i]);
1241template <
class Po
intType,
class LabelType,
class Storage>
1242template <
class ResultNumber>
1255template <
class Po
intType,
class LabelType>
1256template <
class ApproximateNumber>
1258 ApproximateNumber total{};
1259 for (std::size_t i = 1; i < points_.size(); ++i) {
1260 total += points_[i - 1].template distance<ApproximateNumber>(points_[i]);
1265template <
class Po
intType,
class LabelType>
1267 decltype(std::declval<PointType>().distanceL1(std::declval<PointType>())) total{};
1268 for (std::size_t i = 1; i < points_.size(); ++i) {
1269 total += points_[i - 1].distanceL1(points_[i]);
1274template <
class Po
intType,
class LabelType>
1276 decltype(std::declval<PointType>().distanceLInf(std::declval<PointType>())) total{};
1277 for (std::size_t i = 1; i < points_.size(); ++i) {
1278 total += points_[i - 1].distanceLInf(points_[i]);
1283template <
class Po
intType,
class LabelType>
1284template <
class ResultNumber>
1294template <
class Po
intType,
class LabelType,
class Storage>
1295template <
class OtherShape>
1299 return shape.interiorContains(witness);
1311template <
class Po
intType,
class LabelType>
1312template <
class ResultNumber>
1315 return ResultNumber{};
1318 throw std::logic_error(
"HalfplaneIntersection::twiceArea requires a bounded region");
1323template <
class Po
intType,
class LabelType>
1324template <
class ResultNumber>
1327 return ResultNumber{};
1330 throw std::logic_error(
"HalfplaneIntersection::area requires a bounded region");
1335template <
class Po
intType,
class LabelType>
1336template <
class ResultNumber>
1342 throw std::logic_error(
"HalfplaneIntersection::centroid requires a bounded region");
1348template <
class Po
intType,
class LabelType>
1349template <
class ResultNumber>
1351 if (empty_ || halfplanes_.empty()) {
1354 if (halfplanes_.size() == 1) {
1366 bool anchored =
false;
1367 for (std::size_t i = 0; i <
size(); ++i) {
1370 anchorX =
static_cast<NumberType>(v.x() < 0 ? -std::floor(-v.x()) : std::floor(v.x()));
1371 anchorY =
static_cast<NumberType>(v.y() < 0 ? -std::floor(-v.y()) : std::floor(v.y()));
1377 anchorX =
static_cast<NumberType>(halfplanes_[0].source().
x());
1378 anchorY =
static_cast<NumberType>(halfplanes_[0].source().
y());
1381 const PointType lo(anchorX - margin, anchorY - margin);
1382 const PointType hi(anchorX + margin, anchorY + margin);
1390 if (clipped.
empty()) {
1393 detail::asNumber<ResultNumber>(halfplanes_[0].source().
y()));
1398template <
class Po
intType,
class LabelType>
1399template <
class OtherShape>
1401 const OtherShape& shape)
const {
1404 using Exact = std::conditional_t<std::is_floating_point_v<NumberType>, double,
Rational<BigInt>>;
Arbitrary precision signed integer.
Definition bigint.hpp:157
Exact rational number class template.
Definition rational.hpp:106
Minkowski sums of two shapes, and the operator+ that spells them.
Definition arrangement.hpp:67
HalfplaneIntersection() -> HalfplaneIntersection< Point<>, NoLabel >
Definition halfplaneintersection.hpp:2308
@ y
Definition intervaltree.hpp:24
@ x
Definition intervaltree.hpp:24
@ edge
Definition bitmatrix.hpp:37
@ vertex
Definition bitmatrix.hpp:37
Rational< BigInt > ERational
Exact, overflow-free result used when integral coordinates require fractions.
Definition rational.hpp:1151
constexpr std::partial_ordering dotSign(const Point< ANumber, ALabel > &a, const Point< BNumber, BLabel > &b)
Tells if the angle between two vectors is acute, right, or obtuse.
Definition orientation.hpp:688
Convex() -> Convex< Point<>, NoLabel >
Definition convex.hpp:3311
constexpr auto orientationDeterminant(const Point< ANumber, ALabel > &a, const Point< BNumber, BLabel > &b, const Point< CNumber, CLabel > &c)
Returns the signed orientation determinant of three points.
Definition orientation.hpp:518
Disk() -> Disk< Point<>, NoLabel >
Deduces a default disk with Point<> boundary points and no label.
Definition disk.hpp:1691
constexpr auto operator*(const Transformation< Number > &transformation, const ShapeT &shape)
Applies a transformation to any supported shape.
Definition transformations.hpp:2200
Exact low-level orientation and incircle predicates.
Closed convex polygon stored by its vertices.
Definition convex.hpp:170
constexpr auto twiceArea() const
Computes twice the area of the convex polygon.
Definition measures.hpp:516
constexpr Point< ResultNumber > pointInside() const
Returns a point inside the convex polygon.
Definition measures.hpp:582
constexpr Point< ResultNumber > verticesCentroid() const
Computes the centroid of the vertex set.
Definition measures.hpp:566
constexpr HalfplaneIntersection< PointType > asHalfplaneIntersection() const
Returns the convex polygon as a half-plane intersection.
Definition convex.hpp:672
constexpr auto squaredDistance(const OtherPoint &point) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:791
auto difference(const Shape< OtherPoint > &other) const
Returns the regularized set difference of the two shapes (A ∖ B), re-dispatching through the wrapper'...
Definition convex.hpp:2538
PointType::NumberType NumberType
Definition convex.hpp:172
constexpr size_t maxIndex() const
Returns the index of the maximum vertex (rightmost and highest in case of ties).
Definition predicates.hpp:1022
constexpr auto area() const
Computes the area of the convex polygon.
Definition measures.hpp:531
constexpr bool interiorContains(const EmptyShape< EmptyPoint > &) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition convex.hpp:1340
constexpr ResultNumber squaredMinimumWidth() const
Returns the squared minimum width of the convex polygon.
Definition measures.hpp:1019
ApproximateNumber minimumWidth() const
Returns the minimum width of the convex polygon.
Definition measures.hpp:1032
constexpr HalfplaneIntersection< PointType > smallestEnclosingSlab() const
Returns the narrowest slab containing the convex polygon.
Definition measures.hpp:993
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether some point in this shape's relative interior lies in the strict interior of shape.
Definition measures.hpp:603
constexpr Point< ResultNumber > centroid() const
Computes the centroid of the convex polygon.
Definition measures.hpp:538
constexpr Segment< PointType > diameter() const
Returns a segment realizing the diameter (the farthest vertex pair).
Definition measures.hpp:696
constexpr std::vector< std::pair< std::size_t, std::size_t > > antipodalPairs() const
Returns every antipodal vertex-index pair, via rotating calipers.
Definition measures.hpp:615
size_t size() const
Returns the number of vertices in the convex polygon.
Definition convex.hpp:840
constexpr HalfplaneIntersection< PointType > smallestEnclosingRectangle() const
Returns the smallest-area rectangle containing the convex polygon.
Definition measures.hpp:725
PointType_ PointType
Definition convex.hpp:171
Closed Euclidean disk stored by boundary points plus optional disk label.
Definition disk.hpp:66
Intersection of closed half-planes; convex but possibly unbounded or empty.
Definition halfplaneintersection.hpp:244
Halfplane< PointType > HalfplaneType
Definition halfplaneintersection.hpp:248
constexpr bool empty() const
Returns whether the region is the empty set.
Definition halfplaneintersection.hpp:649
constexpr bool vertexExists(std::size_t i) const
Returns whether the half-plane pair (i, i+1) (cyclically) defines a vertex of the region.
Definition halfplaneintersection.hpp:854
constexpr auto area() const
Returns the area of the region.
Definition measures.hpp:1325
constexpr bool isBounded() const
Returns whether the region is bounded.
Definition halfplaneintersection.hpp:811
PointType_ PointType
Definition halfplaneintersection.hpp:245
PointType::NumberType NumberType
Definition halfplaneintersection.hpp:246
constexpr Convex< Point< ResultNumber, typename PointType::LabelType > > asConvex() const
Returns the region as a convex polygon.
Definition halfplaneintersection.hpp:955
constexpr std::size_t size() const
Returns the number of stored (non-redundant) half-planes.
Definition halfplaneintersection.hpp:596
friend struct HalfplaneIntersection
Definition halfplaneintersection.hpp:2308
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether an exact interior witness of this region lies in the interior of the given shape.
Definition measures.hpp:1400
constexpr auto twiceArea() const
Returns twice the area of the region.
Definition measures.hpp:1313
constexpr bool insert(const OtherHalfplane &other)
Intersects the region with one more half-plane.
Definition halfplaneintersection.hpp:509
constexpr Point< ResultNumber > centroid() const
Returns the centroid of the region.
Definition measures.hpp:1337
constexpr Point< ResultNumber > pointInside() const
Returns a representative point of the region: a point of its interior when the region is full-dimensi...
Definition measures.hpp:1350
Closed half-plane defined by an oriented boundary line.
Definition halfplane.hpp:51
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether some point in this shape's relative interior lies in the strict interior of shape.
Definition measures.hpp:505
constexpr Point< ResultNumber > pointInside() const
Returns a point inside the halfplane.
Definition measures.hpp:486
constexpr const PointType & target() const
Returns the target boundary point.
Definition halfplane.hpp:193
constexpr const PointType & source() const
Returns the source boundary point.
Definition halfplane.hpp:181
constexpr ResultNumber slope() const
Returns the slope of the boundary line.
Definition measures.hpp:478
constexpr Point< ResultNumber > pointInside() const
Returns a point inside the line.
Definition measures.hpp:197
constexpr const PointType & max() const
Returns the largest stored defining point.
Definition line.hpp:189
constexpr const PointType & min() const
Returns the smallest stored defining point.
Definition line.hpp:180
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether some point in this shape's relative interior lies in the strict interior of shape.
Definition measures.hpp:203
PointType::NumberType NumberType
Definition line.hpp:54
constexpr ResultNumber slope() const
Returns the slope of the line.
Definition measures.hpp:189
constexpr ResultNumber area() const
Returns the area of the line.
Definition measures.hpp:178
constexpr NumberType twiceArea() const
Returns twice the area of the line.
Definition measures.hpp:183
PointType_ PointType
Definition monotonechain.hpp:147
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether some point in this shape's relative interior lies in the strict interior of shape.
Definition measures.hpp:1296
constexpr std::size_t size() const
Returns the number of vertices in the chain.
Definition monotonechain.hpp:393
constexpr auto lengthLInf() const
Computes the Chebyshev (LInf) length of the chain.
Definition measures.hpp:1233
constexpr bool interiorContains(const OtherPoint &point) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition interiorcontains.hpp:1371
constexpr Point< ResultNumber > pointInside() const
Returns a point inside the chain.
Definition measures.hpp:1243
ApproximateNumber length() const
Computes the Euclidean length of the chain (the sum of its edge lengths).
Definition measures.hpp:1215
constexpr auto lengthL1() const
Computes the Manhattan (L1) length of the chain.
Definition measures.hpp:1224
constexpr ResultNumber slope() const
Returns the slope of the line.
Definition measures.hpp:224
constexpr Point< ResultNumber > pointInside() const
Returns a point inside the oriented line.
Definition measures.hpp:232
constexpr NumberType twiceArea() const
Returns twice the area of the line.
Definition measures.hpp:218
constexpr const PointType & target() const
Returns the target defining point.
Definition orientedline.hpp:195
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether some point in this shape's relative interior lies in the strict interior of shape.
Definition measures.hpp:238
constexpr ResultNumber area() const
Returns the area of the line.
Definition measures.hpp:213
constexpr Line< PointType > asLine() const
Returns the line without orientation.
Definition orientedline.hpp:321
PointType::NumberType NumberType
Definition orientedline.hpp:55
constexpr const PointType & source() const
Returns the source defining point.
Definition orientedline.hpp:183
ApproximateNumber length() const
Returns the Euclidean length.
Definition measures.hpp:125
PointType::NumberType NumberType
Definition orientedsegment.hpp:46
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether some point in this shape's relative interior lies in the strict interior of shape.
Definition measures.hpp:168
constexpr auto lengthL1() const
Returns the Manhattan length.
Definition measures.hpp:130
constexpr ResultNumber slope() const
Returns the slope of the segment.
Definition measures.hpp:141
constexpr const PointType & source() const
Returns the source endpoint.
Definition orientedsegment.hpp:178
constexpr auto lengthLInf() const
Returns the Chebyshev length.
Definition measures.hpp:135
constexpr Point< ResultNumber > pointInside() const
Returns a point inside the segment.
Definition measures.hpp:162
constexpr ResultNumber area() const
Returns the area of the segment.
Definition measures.hpp:109
constexpr const PointType & target() const
Returns the target endpoint.
Definition orientedsegment.hpp:190
constexpr Segment< PointType > asSegment() const
Returns the segment without orientation.
Definition orientedsegment.hpp:322
constexpr NumberType twiceArea() const
Returns twice the area of the segment.
Definition measures.hpp:114
constexpr auto squaredLength() const
Returns the squared Euclidean length.
Definition measures.hpp:119
constexpr Point< ResultNumber > midpoint() const
Returns the midpoint of the segment.
Definition measures.hpp:154
constexpr auto squaredDistance(const OtherPoint &point) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:178
constexpr Segment< PointType > diameter() const
Returns an unordered segment defining the diameter.
Definition measures.hpp:148
Two-dimensional point with optional label payload.
Definition point.hpp:129
constexpr const NumberType & x() const
Returns the x coordinate.
Definition point.hpp:193
constexpr const NumberType & y() const
Returns the y coordinate.
Definition point.hpp:205
constexpr bool interiorContains(const EmptyShape< EmptyPoint > &) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition point.hpp:471
constexpr Point< ResultNumber > centroid() const
Computes the area-weighted centroid of the set.
Definition measures.hpp:1184
constexpr ResultNumber twiceArea() const
Computes twice the area of the set.
Definition polygonset.hpp:625
typename PointType::NumberType NumberType
Definition polygonset.hpp:167
constexpr Point< ResultNumber > verticesCentroid() const
Computes the centroid of the vertex set over every ring of every component.
Definition measures.hpp:1166
constexpr std::size_t vertexCount() const
Returns the total number of vertices over every ring of every component.
Definition polygonset.hpp:377
constexpr bool empty() const
Tests whether the set has no components at all.
Definition polygonset.hpp:485
constexpr const ComponentType & component(std::size_t index) const
Accesses a component by index.
Definition polygonset.hpp:271
constexpr ResultNumber twiceArea() const
Computes twice the area of the region.
Definition polygonwithholes.hpp:577
constexpr const PolygonType & hole(std::size_t index) const
Accesses a hole by index.
Definition polygonwithholes.hpp:196
typename PointType::NumberType NumberType
Definition polygonwithholes.hpp:91
constexpr Point< ResultNumber > verticesCentroid() const
Computes the centroid of the vertex set over all rings.
Definition measures.hpp:1109
constexpr Point< ResultNumber > centroid() const
Computes the area-weighted centroid of the region.
Definition measures.hpp:1131
Polygon< PointType > PolygonType
Definition polygonwithholes.hpp:93
constexpr bool empty() const
Tests whether the region has no outer boundary at all.
Definition polygonwithholes.hpp:430
constexpr std::size_t vertexCount() const
Returns the total number of vertices over all rings.
Definition polygonwithholes.hpp:279
constexpr Point< ResultNumber > pointInside() const
Returns a point strictly inside the (simple) polygon.
Definition measures.hpp:1050
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether some point in this shape's relative interior lies in the strict interior of shape.
Definition measures.hpp:1094
constexpr bool interiorContains(const EmptyShape< EmptyPoint > &) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition polygon.hpp:1537
constexpr std::size_t size() const
Returns the number of vertices in the polygon.
Definition polygon.hpp:259
constexpr ResultNumber twiceArea() const
Computes twice the (unsigned) area of the polygon via the shoelace formula.
Definition polygon.hpp:273
PointType_ PointType
Definition polygon.hpp:60
constexpr PointType get(std::ptrdiff_t index) const
Cyclic access: same as operator[] but index is taken modulo size(); negative indices wrap from the en...
Definition polygon.hpp:169
constexpr Point< ResultNumber > verticesCentroid() const
Computes the centroid of the vertex set (the average of the vertices).
Definition polygon.hpp:892
constexpr auto lengthLInf() const
Computes the Chebyshev (LInf) length of the polyline.
Definition measures.hpp:1275
PointType_ PointType
Definition polyline.hpp:70
ApproximateNumber length() const
Computes the Euclidean length of the polyline (the sum of its edge lengths).
Definition measures.hpp:1257
constexpr auto lengthL1() const
Computes the Manhattan (L1) length of the polyline.
Definition measures.hpp:1266
constexpr Point< ResultNumber > pointInside() const
Returns a point inside the polyline.
Definition measures.hpp:1285
constexpr std::size_t size() const
Returns the number of vertices in the polyline.
Definition polyline.hpp:388
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether some point in this shape's relative interior lies in the strict interior of shape.
Definition measures.hpp:273
constexpr ResultNumber area() const
Returns the area of the ray.
Definition measures.hpp:248
PointType::NumberType NumberType
Definition ray.hpp:53
constexpr const PointType & target() const
Returns the second stored point defining the direction.
Definition ray.hpp:193
constexpr ResultNumber slope() const
Returns the slope of the supporting line.
Definition measures.hpp:259
constexpr NumberType twiceArea() const
Returns twice the area of the ray.
Definition measures.hpp:253
constexpr Point< ResultNumber > pointInside() const
Returns a point inside the ray.
Definition measures.hpp:267
constexpr const PointType & source() const
Returns the source point of the ray.
Definition ray.hpp:181
constexpr ResultNumber area() const
Returns the rectangle area.
Definition measures.hpp:284
constexpr Point< ResultNumber > midpoint() const
Returns the midpoint of the rectangle.
Definition measures.hpp:304
constexpr Point< ResultNumber > pointInside() const
Returns a point inside the rectangle.
Definition measures.hpp:331
constexpr auto height() const
Returns the rectangle height.
Definition rectangle.hpp:378
constexpr Point< ResultNumber > centroid() const
Returns the centroid of the rectangle.
Definition measures.hpp:313
constexpr const PointType & min() const
Returns the minimum corner (min x, min y).
Definition rectangle.hpp:347
constexpr bool empty() const
Returns whether the rectangle is the empty set of points.
Definition rectangle.hpp:290
constexpr Point< ResultNumber > center() const
Returns the center of the rectangle.
Definition measures.hpp:325
constexpr auto twiceArea() const
Returns twice the rectangle area.
Definition measures.hpp:291
constexpr bool interiorContains(const EmptyShape< EmptyPoint > &) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition rectangle.hpp:862
constexpr Disk< PointType, NoLabel > circumcircle() const
Returns the circumcircle of the rectangle.
Definition measures.hpp:318
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether some point in this shape's relative interior lies in the strict interior of shape.
Definition measures.hpp:337
constexpr const PointType & max() const
Returns the maximum corner (max x, max y).
Definition rectangle.hpp:359
constexpr auto width() const
Returns the rectangle width.
Definition rectangle.hpp:368
constexpr Segment< PointType > diameter() const
Returns a segment defining a diameter.
Definition measures.hpp:297
Unoriented closed segment between two endpoints plus optional segment label.
Definition segment.hpp:58
constexpr auto lengthLInf() const
Returns the Chebyshev length.
Definition measures.hpp:60
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether some point in this shape's relative interior lies in the strict interior of shape.
Definition measures.hpp:94
constexpr auto lengthL1() const
Returns the Manhattan length.
Definition measures.hpp:55
constexpr ResultNumber slope() const
Returns the slope of the segment.
Definition measures.hpp:66
constexpr Point< ResultNumber > midpoint() const
Returns the midpoint of the segment.
Definition measures.hpp:79
constexpr const PointType & max() const
Returns the largest stored endpoint.
Definition segment.hpp:199
ApproximateNumber length() const
Returns the Euclidean length.
Definition measures.hpp:50
constexpr const PointType & min() const
Returns the smallest stored endpoint.
Definition segment.hpp:190
PointType::NumberType NumberType
Definition segment.hpp:60
constexpr ResultNumber area() const
Returns the area of the segment.
Definition measures.hpp:34
constexpr auto squaredDistance(const OtherPoint &point) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:100
constexpr Point< ResultNumber > pointInside() const
Returns a point inside the segment.
Definition measures.hpp:88
constexpr NumberType twiceArea() const
Returns twice the area of the segment.
Definition measures.hpp:39
constexpr Segment diameter() const
Returns a segment defining the diameter.
Definition measures.hpp:73
constexpr auto squaredLength() const
Returns the squared Euclidean length.
Definition measures.hpp:44
constexpr Segment()=default
Creates the degenerate segment (0,0)--(0,0).
constexpr bool interiorContains(const EmptyShape< EmptyPoint > &) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition segment.hpp:736
Closed triangle stored by three vertices.
Definition triangle.hpp:53
constexpr Disk< PointType, NoLabel > circumcircle() const
Returns the circumcircle of the triangle.
Definition measures.hpp:376
constexpr const PointType & b() const
Returns the second vertex.
Definition triangle.hpp:217
constexpr bool isIsosceles() const
Tests whether two sides have the same length.
Definition measures.hpp:459
constexpr const PointType & a() const
Returns the first vertex.
Definition triangle.hpp:208
constexpr bool isRectangle() const
Tests whether the triangle has a right angle.
Definition measures.hpp:420
constexpr Segment< PointType > diameter() const
Returns a segment defining the diameter.
Definition measures.hpp:381
constexpr bool pointInsideInteriorContainedIn(const OtherShape &shape) const
Tests whether some point in this shape's relative interior lies in the strict interior of shape.
Definition measures.hpp:409
constexpr auto squaredDistance(const OtherPoint &point) const
Returns the squared Euclidean distance to the given shape.
Definition distance.hpp:670
constexpr bool isObtuse() const
Tests whether the triangle has an obtuse angle.
Definition measures.hpp:442
constexpr ResultNumber area() const
Returns the non-negative area of the triangle.
Definition measures.hpp:357
constexpr NumberType twiceArea() const
Returns twice the area of the triangle.
Definition measures.hpp:351
constexpr bool isDegenerate() const
Tests whether the three vertices are collinear.
Definition predicates.hpp:223
constexpr Point< ResultNumber > pointInside() const
Returns a point inside the triangle.
Definition measures.hpp:401
PointType::NumberType NumberType
Definition triangle.hpp:57
constexpr const PointType & c() const
Returns the third vertex.
Definition triangle.hpp:226
constexpr bool interiorContains(const EmptyShape< EmptyPoint > &) const
Tests whether this shape's interior contains the other shape (A∖∂A ⊇ B).
Definition triangle.hpp:806
constexpr Point< ResultNumber > centroid() const
Returns the arithmetic centroid.
Definition measures.hpp:364