Skip to content
Snippets Groups Projects
Commit 2fd12751 authored by Evgueni Tcherniaev's avatar Evgueni Tcherniaev
Browse files

Faster algorithm in GeoPgon::contains()

parent be230037
No related branches found
No related tags found
1 merge request!197Added extent() and contains() methods. Completed implementation of volume calculation for Boolean shapes.
...@@ -99,44 +99,44 @@ void GeoPgon::extent (double& xmin, double& ymin, double& zmin, ...@@ -99,44 +99,44 @@ void GeoPgon::extent (double& xmin, double& ymin, double& zmin,
bool GeoPgon::contains (double x, double y, double z) const bool GeoPgon::contains (double x, double y, double z) const
{ {
#ifndef M_PI
constexpr double M_PI = 3.14159265358979323846;
#endif
if (!isValid ()) return false; if (!isValid ()) return false;
size_t nz = getNPlanes(); size_t nz = getNPlanes();
if (z < getZPlane(0) || z > getZPlane(nz - 1)) return false; if (z < getZPlane(0) || z > getZPlane(nz - 1)) return false;
constexpr double two_PI = 2.0 * M_PI; size_t nsides = getNSides();
double sphi = getSPhi(); double sphi = getSPhi();
double dphi = getDPhi(); double dphi = getDPhi();
if (dphi < two_PI)
{ double dangle = dphi / nsides; // sector angle
GeoTrf::Vector2D r(x, y); double dhalfangle = 0.5 * dangle;
GeoTrf::Vector2D ns(std::sin(sphi), -std::cos(sphi)); double cosHalfAngle = std::cos(dhalfangle);
GeoTrf::Vector2D ne(-std::sin(sphi + dphi), std::cos(sphi + dphi)); double sinHalfAngle = std::sin(dhalfangle);
double ds = ns.dot(r); double cosAngle = (cosHalfAngle + sinHalfAngle) * (cosHalfAngle - sinHalfAngle);
double de = ne.dot(r); double sinAngle = 2.0 * cosHalfAngle * sinHalfAngle;
bool in_wedge = (dphi <= M_PI) ? (ds <= 0 && de <= 0) : (ds <= 0 || de <= 0);
if (!in_wedge) return false;
}
double r = 0.0; double r = 0.0;
if (x * x + y * y > 0.0) double rot = -(sphi + dhalfangle); // initial rotation
double cosRot = std::cos(rot);
double sinRot = std::sin(rot);
bool inwedge = false;
for (size_t iside = 0; iside < nsides; ++iside)
{ {
while (sphi > 0) sphi -= two_PI; double xrot = x * cosRot - y * sinRot;
while (sphi < 0) sphi += two_PI; double yrot = x * sinRot + y * cosRot;
double phi = std::atan2(y, x); double dista = sinHalfAngle * xrot + cosHalfAngle * yrot;
while (phi < sphi) phi += two_PI; double distb = sinHalfAngle * xrot - cosHalfAngle * yrot;
if (dista >= 0.0 && distb >= 0.0)
if (dphi > two_PI) dphi = two_PI; {
int nsides = getNSides(); r = xrot;
double sector = dphi / nsides; inwedge = true;
int iphi = (phi - sphi) / sector; break;
if (iphi == nsides) iphi--; }
double cosTmp = cosRot;
double rot = sphi + sector * (iphi + 0.5); double sinTmp = sinRot;
r = std::cos(rot) * x + std::sin(rot) * y; cosRot = cosTmp * cosAngle + sinTmp * sinAngle;
sinRot = sinTmp * cosAngle - cosTmp * sinAngle;
} }
if (!inwedge) return false;
for (size_t k = 0; k < nz - 1; ++k) for (size_t k = 0; k < nz - 1; ++k)
{ {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment