Garfield++ 3.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
Garfield::Polygon Namespace Reference

Functions

void Inside (const std::vector< double > &xpl, const std::vector< double > &ypl, const double x, const double y, bool &inside, bool &edge)
 
double Area (const std::vector< double > &xp, const std::vector< double > &yp)
 Determine the (signed) area of a polygon.
 

Function Documentation

◆ Area()

double Garfield::Polygon::Area ( const std::vector< double > &  xp,
const std::vector< double > &  yp 
)

Determine the (signed) area of a polygon.

Definition at line 222 of file Polygon.cc.

222 {
223
224 double f = 0.;
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];
229 }
230 return 0.5 * f;
231}

Referenced by Garfield::ComponentNeBem2d::AddRegion().

◆ Inside()

void Garfield::Polygon::Inside ( const std::vector< double > &  xpl,
const std::vector< double > &  ypl,
const double  x,
const double  y,
bool &  inside,
bool &  edge 
)

Determine whether the point (x, y) is located inside of the polygon (xpl, ypl).

Definition at line 135 of file Polygon.cc.

136 {
137 // Initial settings.
138 inside = false;
139 edge = false;
140 const unsigned int npl = xpl.size();
141 if (ypl.size() != npl) return;
142 // Special treatment for few points.
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 // Determine the range of the data.
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 // Set tolerances.
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 // Ensure that we have a range.
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 // Choose a point at "infinity".
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 // Loop over the edges counting intersections.
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 // Flag points located on one of the edges.
190 if (OnLine(xpl[j], ypl[j], xpl[jj], ypl[jj], x, y)) {
191 edge = true;
192 return;
193 }
194 // Count mid-line intersects.
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 // Ensure that the testing line doesn't cross a corner.
201 if (OnLine(x, y, xinf, yinf, xpl[j], ypl[j])) {
202 xinf = xmin - ::Garfield::RndmUniform() * fabs(xmax - xinf);
203 yinf = ymin - ::Garfield::RndmUniform() * fabs(ymax - yinf);
204 ok = false;
205 break;
206 }
207 }
208 if (ok) {
209 // Set the INSIDE flag.
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).
Definition: Random.hh:14
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:615

Referenced by Garfield::ComponentNeBem2d::ElectricField(), and Garfield::ComponentNeBem2d::GetMedium().