bool LineIntersection(const CIPoint& A1, const CIPoint& A2, const CIPoint& B1, const CIPoint& B2, CXPoint* X, double *ta, double *tb) { double x21 = A2.x - A1.x; double y21 = A2.y - A1.y; double x31 = B1.x - A1.x; double y13 = A1.y - B1.y; double x43 = B2.x - B1.x; double y43 = B2.y - B1.y; double del = x21 * y43 - x43 * y21; if (FEqual(del, 0)) { X->x = NaN; X->y = NaN; return false; } *ta = (x43 * y13 + x31 * y43) / del; *tb = (x21 * y13 + x31 * y21) / del; X->x = A1.x + *ta * x21; X->y = A1.y + *ta * y21; return (*ta>=0 && *ta<=1 && *tb>=0 && *tb<=1); }
bool LineIntersection(const CXPoint& A1, const CXPoint& A2, const CXPoint& B1, const CXPoint& B2, CXPoint* X) { double x21 = A2.x - A1.x; double y21 = A2.y - A1.y; double x31 = B1.x - A1.x; double y13 = A1.y - B1.y; double x43 = B2.x - B1.x; double y43 = B2.y - B1.y; double del = x21 * y43 - x43 * y21; if (FEqual(del, 0)) { X->x = NaN; X->y = NaN; return false; } double a = (x43 * y13 + x31 * y43) / del; double b = (x21 * y13 + x31 * y21) / del; X->x = A1.x + a * x21; X->y = A1.y + a * y21; return (a>=0 && a<=1 && b>=0 && b<=1); }
double CXVector::LinearDependent(const CXVector& rs) const { if ((FEqual(rs.x,0) && !FEqual(x,0))) return 0; if ((FEqual(rs.y,0) && !FEqual(y,0))) return 0; return FEqual(x / rs.x, y / rs.y) ? x / rs.x : 0; }
EarClipper::VertexList::iterator EarClipper::RayCastFromMaxInteriorPointToOuterPolygon(const FVector2& maxInteriorPoint, FVector2& intersectionPointOnEdge, VertexList::iterator& pointOnEdgeWithMaximumXIter) { //a) Call the vertex on the hole with the maximum x coordinate P. Call the ray { P, (1,0) } R. Intersect R // with the edges of the outer polygon. Find the edge whose intersection is closest to P. Call this edge E. // If R goes through E entirely, then the mutually visible vertex is the endpoint on E closest to P. Otherwise, // if R goes through one of the endpoints of E, then the mutually visible vertex is this endpoint. Otherwise, // R intersects the line segment at a point other than the endpoints (see b) VertexList::iterator verticesEnd = vertices.end(); VertexList::iterator mutuallyVisibleVertexIter = verticesEnd; VertexList::iterator possibleMutuallyVisibleVertex = verticesEnd; Line2D_t rayFromMaxVertex(maxInteriorPoint, Vec2D::XAxis(), true); float minDistance = std::numeric_limits<float>::max(); LineSegment2D_t lineSegmentOnOuterPolygon; FVector2 intersectionPoint1, intersectionPoint2; VertexList::iterator pointOnThisEdgeWithMaximumXIter = verticesEnd; for (VertexList::iterator vertexIterator = vertices.begin(); vertexIterator != verticesEnd; ++vertexIterator) { VertexList::iterator nextVertexIterator = vertexIterator.next(); lineSegmentOnOuterPolygon.P1 = *(vertexIterator->point); lineSegmentOnOuterPolygon.P2 = *(nextVertexIterator->point); IntersectionType intersection = rayFromMaxVertex.LineSegmentIntersection(lineSegmentOnOuterPolygon, intersectionPoint1, intersectionPoint2, EXPERIMENTAL_TOLERANCE); if ((intersection == IntersectionType::LineSegment) || (intersection == IntersectionType::Point)) { possibleMutuallyVisibleVertex = vertexIterator; bool rayHitEndPointOfEdge = true; if (lineSegmentOnOuterPolygon.P1.x > lineSegmentOnOuterPolygon.P2.x) { pointOnThisEdgeWithMaximumXIter = vertexIterator; } else { pointOnThisEdgeWithMaximumXIter = nextVertexIterator; } if (intersection == IntersectionType::LineSegment) { if (lineSegmentOnOuterPolygon.P1.x < lineSegmentOnOuterPolygon.P2.x) { possibleMutuallyVisibleVertex = vertexIterator; } else { possibleMutuallyVisibleVertex = nextVertexIterator; } } else if (intersection == IntersectionType::Point) { if (intersectionPoint1 == lineSegmentOnOuterPolygon.P1) { possibleMutuallyVisibleVertex = vertexIterator; } else if (intersectionPoint1 == lineSegmentOnOuterPolygon.P2) { possibleMutuallyVisibleVertex = nextVertexIterator; } else { rayHitEndPointOfEdge = false; } } float distance = rayHitEndPointOfEdge ? (possibleMutuallyVisibleVertex->point->x - maxInteriorPoint.x) : (intersectionPoint1.x - maxInteriorPoint.x); bool sameishDistance = FEqual(distance, minDistance); if ((distance < minDistance) || sameishDistance) { bool takeThisVertex = true; if (sameishDistance) { const FVector2* beforeMutuallyVisibleVertex = possibleMutuallyVisibleVertex.previous()->point; takeThisVertex = (GetConvexOrReflexVertexType(beforeMutuallyVisibleVertex, possibleMutuallyVisibleVertex->point, &maxInteriorPoint) == VertexType::Convex); } if (takeThisVertex) { if (rayHitEndPointOfEdge) { mutuallyVisibleVertexIter = possibleMutuallyVisibleVertex; } else { mutuallyVisibleVertexIter = verticesEnd; pointOnEdgeWithMaximumXIter = pointOnThisEdgeWithMaximumXIter; intersectionPointOnEdge = intersectionPoint1; } minDistance = distance; } } } } return mutuallyVisibleVertexIter; }