bool FloatPolygon::containsEvenOdd(const FloatPoint& point) const { unsigned crossingCount = 0; for (unsigned i = 0; i < numberOfEdges(); ++i) { const FloatPoint& vertex1 = edgeAt(i).vertex1(); const FloatPoint& vertex2 = edgeAt(i).vertex2(); if (isPointOnLineSegment(vertex1, vertex2, point)) return true; if ((vertex1.y() <= point.y() && vertex2.y() > point.y()) || (vertex1.y() > point.y() && vertex2.y() <= point.y())) { float vt = (point.y() - vertex1.y()) / (vertex2.y() - vertex1.y()); if (point.x() < vertex1.x() + vt * (vertex2.x() - vertex1.x())) ++crossingCount; } } return crossingCount & 1; }
bool FloatPolygon::containsNonZero(const FloatPoint& point) const { int windingNumber = 0; for (unsigned i = 0; i < numberOfEdges(); ++i) { const FloatPoint& vertex1 = edgeAt(i).vertex1(); const FloatPoint& vertex2 = edgeAt(i).vertex2(); if (isPointOnLineSegment(vertex1, vertex2, point)) return true; if (vertex2.y() < point.y()) { if ((vertex1.y() > point.y()) && (leftSide(vertex1, vertex2, point) > 0)) ++windingNumber; } else if (vertex2.y() > point.y()) { if ((vertex1.y() <= point.y()) && (leftSide(vertex1, vertex2, point) < 0)) --windingNumber; } } return windingNumber; }
/*! * @brief returns the intersection of 2 line segments in "inter". if there is more than 1 intersection, the 2nd point is * returned in "intIfLine" * @return 0 if lines do not intersect * 1 if lines intersect in exactly one place * 2 if lines intersect in more than one place *****************************************************************************/ int RecLineSegment2D::getIntersection(const RecLineSegment2D& l2, RecPoint2D& inter, RecPoint2D& intIfLine) const { int numInt=0; double x1, x2, x3, x4; double y1, y2, y3, y4; double n1, n2, d; double u1, u2; double tol = 1.0e-25; /* * set up some variables */ x1 = p1_.x; x2 = p2_.x; x3 = l2.p1_.x; x4 = l2.p2_.x; y1 = p1_.y; y2 = p2_.y; y3 = l2.p1_.y; y4 = l2.p2_.y; /* * bounding box test */ if (MAX(x1, x2) < MIN(x3, x4) || MAX(x3, x4) < MIN(x1, x2)) { return 0; } if (MAX(y1, y2) < MIN(y3, y4) || MAX(y3, y4) < MIN(y1, y2)) { return 0; } /* * set up some variables */ n1 = (x4-x3)*(y1-y3)-(y4-y3)*(x1-x3); n2 = (x2-x1)*(y1-y3)-(y2-y1)*(x1-x3); d = (y4-y3)*(x2-x1)-(x4-x3)*(y2-y1); if (fabs(d) > tol) { /* * parallel or skew case */ u1 = n1 / d; u2 = n2 / d; if (u1 < -tol || u1 >1+tol || u2 < -tol || u2 > 1+tol) { return 0; } if (fabs(u1) <= tol) { inter.x = x1; inter.y = y1; } else if (fabs(u1-1.0) <= tol) { inter.x = x2; inter.y = y2; } else if (fabs(u2) <= tol) { inter.x = x3; inter.y = y3; } else if (fabs(u2-1.0) <= tol) { inter.x = x4; inter.y = y4; } else { inter.x = x1 + u1 * (x2 - x1); inter.y = y1 + u1 * (y2 - y1); } return 1; } /* * case when both lines are coincident */ if (!(fabs(n1) < tol && fabs(n2) < tol)) { return 0; } /* * Check to see if X1 lies in X3-X4 */ if (isPointOnLineSegment(x1, y1, x3, y3, x4, y4)) { inter.x = x1; inter.y = y1; numInt++; } /* * Check to see if X2 lies in X3-X4 */ if (isPointOnLineSegment(x2, y2, x3, y3, x4, y4)) { if (numInt == 0) { inter.x = x2; inter.y = y2; } else { intIfLine.x = x2; intIfLine.y = y2; return 2; } numInt++; } /* * Check to see if X3 lies in X1-X2 */ if (isPointOnLineSegment(x3, y3, x1, y1, x2, y2)) { if (numInt == 0) { inter.x = x3; inter.y = y3; } else { intIfLine.x = x3; intIfLine.y = y3; return 2; } numInt++; } /* * Check to see if X4 lies in X1-X2 */ if (isPointOnLineSegment(x4, y4, x1, y1, x2, y2)) { if (numInt==0) { inter.x = x4; inter.y = y4; } else { intIfLine.x = x4; intIfLine.y = y4; /* * Order in increasing distance to (X1,Y1) */ if (sqrt((x4-x1) * (x4-x1) + (y4-y1) * (y4-y1)) < sqrt((inter.x-x1) * (inter.x-x1) + (inter.y-y1) * (inter.y-y1))) { intIfLine.x = inter.x; intIfLine.y = inter.y; inter.x = x4; inter.y = y4; } } } return 2; }