Option<Vec2> Intersection::get(const Ray& a, const LineSegment& b) { auto bdir = b.pointB() - b.pointA(); auto blen = bdir.length(); bdir /= blen; const auto dt = a.m_direction.x * bdir.y - bdir.x * a.m_direction.y; if (aeq(dt, 0.0f)) return nullptr; const auto dx = a.m_point.x - b.pointA().x; const auto dy = a.m_point.y - b.pointA().y; auto u = (a.m_direction.x * dy - a.m_direction.y * dx) / dt; auto t = (bdir.x * dy - bdir.y * dx) / dt; auto pt = a.sampleAlongRay(t); if (aeq(pt, a.m_point)) { pt = a.m_point; t = 0; } if (aeq(pt, b.pointA())) { pt = b.pointA(); u = 0; } if (aeq(pt, b.pointB())) { pt = b.pointB(); u = blen; } assert(aeq(pt, b.pointA() + bdir * u)); return t < 0 || u < 0 || u > blen ? nullptr : (Option<Vec2>)pt; }
Option<Vec2> Intersection::get(const LineSegment& a, const LineSegment& b) { auto Intersection = get(a.containingLine(), b.containingLine()); if (!Intersection) return nullptr; if (aeq(Intersection.value(), a.pointA())) Intersection = a.pointA(); if (aeq(Intersection.value(), a.pointB())) Intersection = a.pointB(); if (aeq(Intersection.value(), b.pointA())) Intersection = b.pointA(); if (aeq(Intersection.value(), b.pointB())) Intersection = b.pointB(); auto dirA = a.pointB() - a.pointA(); const auto dirALen = dirA.length(); dirA /= dirALen; auto dirB = b.pointB() - b.pointA(); const auto dirBLen = dirB.length(); dirB /= dirBLen; const auto t = dot(Intersection.value() - a.pointA(), dirA); const auto u = dot(Intersection.value() - b.pointA(), dirB); if (t >= 0 && u >= 0 && t <= dirALen && u <= dirBLen) return Intersection; else return nullptr; }