Determine whether the point (x, y) is located inside of the polygon (xpl, ypl).
136 {
137
138 inside = false;
139 edge = false;
140 const unsigned int npl = xpl.size();
141 if (ypl.size() != npl) return;
142
143 if (npl < 2) {
144 return;
145 } else if (npl == 2) {
146 edge = OnLine(xpl[0], ypl[0], xpl[1], ypl[1], x, y);
147 return;
148 }
149
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));
154
155
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);
160
161
162 if (fabs(xmax - xmin) <= epsx) {
163 if (y >= ymin - epsy && y <= ymax + epsy &&
164 fabs(xmax + xmin - 2 * x) <= epsx) {
165 edge = true;
166 } else {
167 edge = false;
168 }
169 }
else if (
fabs(ymax - ymin) <= epsy) {
170 if (x >= xmin - epsx && x <= xmax + epsx &&
171 fabs(ymax + ymin - 2 * y) <= epsy) {
172 edge = true;
173 } else {
174 edge = false;
175 }
176 }
177
178 double xinf = xmin -
fabs(xmax - xmin);
179 double yinf = ymin -
fabs(ymax - ymin);
180
181 unsigned int nIter = 0;
182 bool ok = false;
183 while (!ok && nIter < 100) {
184 ok = true;
185
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;
189
190 if (OnLine(xpl[j], ypl[j], xpl[jj], ypl[jj], x, y)) {
191 edge = true;
192 return;
193 }
194
195 double xc = 0., yc = 0.;
196 if (Crossing(x, y, xinf, yinf, xpl[j], ypl[j], xpl[jj], ypl[jj], xc,
197 yc)) {
198 ++nCross;
199 }
200
201 if (OnLine(x, y, xinf, yinf, xpl[j], ypl[j])) {
204 ok = false;
205 break;
206 }
207 }
208 if (ok) {
209
210 if (nCross != 2 * (nCross / 2)) inside = true;
211 return;
212 }
213 ++nIter;
214 }
215
216 std::cerr << "Polygon::Inside:\n Warning. Unable to verify "
217 << "whether a point is internal; setting to edge.\n";
218 inside = false;
219 edge = true;
220}
double RndmUniform()
Draw a random number uniformly distributed in the range [0, 1).
DoubleAc fabs(const DoubleAc &f)