15bool OnLine(
const double x1,
const double y1,
const double x2,
const double y2,
16 const double u,
const double v) {
18 double epsx = 1.e-10 * std::max({
fabs(x1),
fabs(x2),
fabs(u)});
19 double epsy = 1.e-10 * std::max({
fabs(y1),
fabs(y2),
fabs(v)});
20 epsx = std::max(1.e-10, epsx);
21 epsy = std::max(1.e-10, epsy);
23 if ((
fabs(x1 - u) <= epsx &&
fabs(y1 - v) <= epsy) ||
24 (
fabs(x2 - u) <= epsx &&
fabs(y2 - v) <= epsy)) {
27 }
else if (
fabs(x1 - x2) <= epsx &&
fabs(y1 - y2) <= epsy) {
31 double xc = 0., yc = 0.;
34 const double dx = (x2 - x1);
35 const double dy = (y2 - y1);
36 const double xl = ((u - x1) * dx + (v - y1) * dy) / (dx * dx + dy * dy);
49 const double dx = (x1 - x2);
50 const double dy = (y1 - y2);
51 const double xl = ((u - x2) * dx + (v - y2) * dy) / (dx * dx + dy * dy);
64 if (
fabs(u - xc) < epsx &&
fabs(v - yc) < epsy) {
72bool Crossing(
const double x1,
const double y1,
const double x2,
73 const double y2,
const double u1,
const double v1,
74 const double u2,
const double v2,
double& xc,
double& yc) {
76 std::array<std::array<double, 2>, 2> a;
81 const double det = a[0][0] * a[1][1] - a[1][0] * a[0][1];
88 epsx = std::max(epsx, 1.e-10);
89 epsy = std::max(epsy, 1.e-10);
91 if (OnLine(x1, y1, x2, y2, u1, v1)) {
95 }
else if (OnLine(x1, y1, x2, y2, u2, v2)) {
99 }
else if (OnLine(u1, v1, u2, v2, x1, y1)) {
103 }
else if (OnLine(u1, v1, u2, v2, x2, y2)) {
107 }
else if (
fabs(det) < epsx * epsy) {
112 const double aux = a[1][1];
113 a[1][1] = a[0][0] / det;
115 a[1][0] = -a[1][0] / det;
116 a[0][1] = -a[0][1] / det;
118 xc = a[0][0] * (x1 * y2 - x2 * y1) + a[1][0] * (u1 * v2 - u2 * v1);
119 yc = a[0][1] * (x1 * y2 - x2 * y1) + a[1][1] * (u1 * v2 - u2 * v1);
121 if (OnLine(x1, y1, x2, y2, xc, yc) && OnLine(u1, v1, u2, v2, xc, yc)) {
135void Inside(
const std::vector<double>& xpl,
const std::vector<double>& ypl,
136 const double x,
const double y,
bool& inside,
bool& edge) {
140 const unsigned int npl = xpl.size();
141 if (ypl.size() != npl)
return;
145 }
else if (npl == 2) {
146 edge = OnLine(xpl[0], ypl[0], xpl[1], ypl[1], x, y);
150 const double xmin = *std::min_element(std::begin(xpl), std::end(xpl));
151 const double xmax = *std::max_element(std::begin(xpl), std::end(xpl));
152 const double ymin = *std::min_element(std::begin(ypl), std::end(ypl));
153 const double ymax = *std::max_element(std::begin(ypl), std::end(ypl));
156 double epsx = 1.e-8 * std::max(fabs(xmin), fabs(xmax));
157 double epsy = 1.e-8 * std::max(fabs(ymin), fabs(ymax));
158 epsx = std::max(epsx, 1.e-8);
159 epsy = std::max(epsy, 1.e-8);
162 if (fabs(xmax - xmin) <= epsx) {
163 if (y >= ymin - epsy && y <= ymax + epsy &&
164 fabs(xmax + xmin - 2 * x) <= epsx) {
169 }
else if (fabs(ymax - ymin) <= epsy) {
170 if (x >= xmin - epsx && x <= xmax + epsx &&
171 fabs(ymax + ymin - 2 * y) <= epsy) {
178 double xinf = xmin - fabs(xmax - xmin);
179 double yinf = ymin - fabs(ymax - ymin);
181 unsigned int nIter = 0;
183 while (!ok && nIter < 100) {
186 unsigned int nCross = 0;
187 for (
unsigned int j = 0; j < npl; ++j) {
188 const unsigned int jj = j < npl - 1 ? j + 1 : 0;
190 if (OnLine(xpl[j], ypl[j], xpl[jj], ypl[jj], x, y)) {
195 double xc = 0., yc = 0.;
196 if (Crossing(x, y, xinf, yinf, xpl[j], ypl[j], xpl[jj], ypl[jj], xc,
201 if (OnLine(x, y, xinf, yinf, xpl[j], ypl[j])) {
210 if (nCross != 2 * (nCross / 2)) inside =
true;
216 std::cerr <<
"Polygon::Inside:\n Warning. Unable to verify "
217 <<
"whether a point is internal; setting to edge.\n";
222double Area(
const std::vector<double>& xp,
const std::vector<double>& yp) {
225 const unsigned int n = xp.size();
226 for (
unsigned int i = 0; i < n; ++i) {
227 const unsigned int ii = i < n - 1 ? i + 1 : 0;
228 f += xp[i] * yp[ii] - xp[ii] * yp[i];
double Area(const std::vector< double > &xp, const std::vector< double > &yp)
Determine the (signed) area of a polygon.
void Inside(const std::vector< double > &xpl, const std::vector< double > &ypl, const double x, const double y, bool &inside, bool &edge)
double RndmUniform()
Draw a random number uniformly distributed in the range [0, 1).
DoubleAc fabs(const DoubleAc &f)