I am working on a CAD software addon and i needed a solution, where you have to know if a point is inside a polygon or not. I have found some good solutions here (link), but none of them worked, when the polygon had holes in it! I figured it out so i want to share the code if somebody would need it.
struct Point2D
{
double x;
double y;
};
struct PolygonData
{
std::vector<Point2D> coords;
int nSubPolys;
std::vector<int> pends;
};
bool IsPointInsidePolygon(const Point2D& p, const PolygonData& polygonData)
{
double minX = 0.0;
double maxX = 0.0;
double minY = 0.0;
double maxY = 0.0;
for (int i = 0; i < polygonData.pends[1]; i++)
{
minX = std::min(polygonData.coords[i].x, minX);
maxX = std::max(polygonData.coords[i].x, maxX);
minY = std::min(polygonData.coords[i].y, minY);
maxY = std::max(polygonData.coords[i].y, maxY);
}
if (p.x < minX || p.x > maxX || p.y < minY || p.y > maxY)
return false;
// check main polygon
bool inside = false;
for (int i = 0, j = polygonData.pends[0] - 1; i < polygonData.pends[0]; j = i++)
{
if ((polygonData.coords[i].y > p.y) != (polygonData.coords[j].y > p.y) &&
p.x < (polygonData.coords[j].x - polygonData.coords[i].x) * (p.y - polygonData.coords[i].y) /
(polygonData.coords[j].y - polygonData.coords[i].y) + polygonData.coords[i].x)
{
inside = !inside;
}
}
// check subpolygons too if point is inside main polygon
bool subInside = false;
if (inside == true && polygonData.nSubPolys > 1)
{
int ind = 0;
int prevPolySize = polygonData.pends[0];
int actPolySize = 0;
// skip 1st, because its the main polygon himself
for (int ii = 2; ii <= polygonData.nSubPolys; ii++)
{
std::vector<API_Coord> actPolyCoords;
ind = 0;
actPolySize = polygonData.pends[ii] - polygonData.pends[ii - 1];
std::vector<int> pends;
pends.push_back(actPolySize);
for (int jj = prevPolySize; jj < polygonData.pends[ii - 1]; jj++)
{
Point2D actCoord;
actCoords.x = polygonData.coords[jj].x;
actCoords.y = polygonData.coords[jj].y;
actPolyCoords.push_back(actCoord);
ind++;
}
prevPolySize += ind;
if (IsPointInsidePolygon(p, actPolyCoords)) // this is the function with the "old method" (not checking subpolygons)
subInside = true;
}
if (subInside)
inside = false;
}
return inside;
} // IsPontInsidePolygon()
Have tested it and it works for me.
Note: i switched the code back from my API environment to STL, differences may occur.