1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
#include <iostream> // std::cout, std::endl
#include <cmath> // sqrt()
typedef double POINT[3];
class PLANE
{
double A; // Plane can be defined as
double B; // "Ax + By + Cz + D = 0"
double C;
double D;
public:
void init(POINT p1, POINT p2, POINT p3); // Create a plane from 3 points
bool isAbove(POINT p); // Tests whether a point is above, in front, or to the right of a plane
};
class POLYGON6 // 6 sided polygon (a cube will be our test object)
{
PLANE plane[6];
public:
// Defined with 8 points. Could be less, but I'm just being casual right now.
POLYGON6(POINT p1, POINT p2, POINT p3, POINT p4, POINT p5, POINT p6, POINT p7, POINT p8);
bool isInPoly(POINT p);
};
////////////////////////////////////////////////////
///////////// PLANE member functions ///////////////
////////////////////////////////////////////////////
void PLANE::init(POINT p1, POINT p2, POINT p3)
{
A = p1[1]*(p2[2] - p3[2]) + p2[1]*(p3[2] - p1[2]) + p3[1]*(p1[2] - p2[2]);
B = p1[2]*(p2[0] - p3[0]) + p2[2]*(p3[0] - p1[0]) + p3[2]*(p1[0] - p2[0]);
C = p1[0]*(p2[1] - p3[1]) + p2[0]*(p3[1] - p1[1]) + p3[0]*(p1[1] - p2[1]);
D = -1 * (p1[0]*(p2[1]*p3[2] - p3[1]*p2[2]) + p2[0]*(p3[1]*p1[2] - p1[1]*p3[2]) + p3[0]*(p1[1]*p2[2] - p2[1]*p1[2]));
}
bool PLANE::isAbove(POINT p)
{
// Method:
// Find the Z-intercept (D) for the parallel plane that the test point lies on.
// This can be done by using the same A, B and C coefficients
// If the parallel plane's D is below this one, it's considered below.
// Take the absolute value of D to avoid problems with upside-down planes.
double NewD = -1*(A*p[0] + B*p[1] + C*p[2]);
return !(abs(NewD) < abs(D));
}
////////////////////////////////////////////////////
///////////// POLYGON6 member functions ////////////
////////////////////////////////////////////////////
POLYGON6::POLYGON6(POINT p1, POINT p2, POINT p3, POINT p4, POINT p5, POINT p6, POINT p7, POINT p8)
{
plane[0].init(p1, p2, p3); // Front 3
plane[1].init(p1, p3, p4);
plane[2].init(p1, p4, p2);
plane[3].init(p8, p7, p5); // Back 3
plane[4].init(p8, p5, p6);
plane[5].init(p8, p6, p7);
}
bool POLYGON6::isInPoly(POINT p)
{
int above = 0;
for (int i = 0; i < 6; ++i)
if (plane[i].isAbove(p)) above++;
else above--;
if (above) return false; // return false if non-zero. It's not balanced between all planes
return true; // return true if zero, it's positive of just as many planes as it is negative.
}
////////////////////////////////////////////////////
///////////// main : ie test function //////////////
////////////////////////////////////////////////////
int main()
{
POINT p1 = {0,0,0};
POINT p2 = {1,0,0};
POINT p3 = {0,1,0};
POINT p4 = {0,0,1};
POINT p5 = {1,1,0};
POINT p6 = {1,0,1};
POINT p7 = {0,1,1};
POINT p8 = {1,1,1};
POLYGON6 poly(p1, p2, p3, p4, p5, p6, p7, p8);
POINT test1 = {0.5, 0.5, 0.5}; // should return true
POINT test2 = {2.0, 2.0, 2.0}; // should return false
std::cout << (poly.isInPoly(test1)? "yes" : "no") << std::endl;
std::cout << (poly.isInPoly(test2)? "yes" : "no") << std::endl;
}
|