diff --git a/TEST_Geometry2D.cpp b/TEST_Geometry2D.cpp index fbdb6ee..cbc4c87 100644 --- a/TEST_Geometry2D.cpp +++ b/TEST_Geometry2D.cpp @@ -132,6 +132,26 @@ class Test_Geometry2D : public olc::PixelGameEngine return std::visit(dispatch, s1, s2); } + olc::vf2d CheckClosest(const ShapeWrap& s1, const ShapeWrap& s2) + { + const auto dispatch = overloads{ + [](const auto& lhs, const auto& rhs) + { + return closest(make_internal(lhs), make_internal(rhs)); + }, + // Discard not implemented + [](const Ray&, const auto&) { return olc::vf2d{}; }, + [](const auto&, const Ray&) {return olc::vf2d{}; }, + [](const Ray&, const Ray&) {return olc::vf2d{}; }, + [](const Line&, const Rect&) {return olc::vf2d{}; }, + [](const Rect&, const Rect&) {return olc::vf2d{}; }, + [](const Circle&, const Rect&) {return olc::vf2d{}; }, + [](const Triangle&, const Rect&) {return olc::vf2d{}; } + }; + + return std::visit(dispatch, s1, s2); + } + std::vector CheckIntersects(const ShapeWrap& s1, const ShapeWrap& s2) { const auto dispatch = overloads{ @@ -294,6 +314,7 @@ class Test_Geometry2D : public olc::PixelGameEngine std::vector vContains; std::vector vOverlaps; std::vector vIntersections; + std::vector vClosestsPoints; if (nSelectedShapeIndex < vecShapes.size()) { for (size_t i = 0; i < vecShapes.size(); i++) @@ -310,6 +331,13 @@ class Test_Geometry2D : public olc::PixelGameEngine if (CheckOverlaps(vecShapes[nSelectedShapeIndex], vTargetShape)) vOverlaps.push_back(i); + + olc::v_2d c = CheckClosest(vecShapes[nSelectedShapeIndex], vTargetShape); + if (c.mag() > 0.f) { + vClosestsPoints.push_back(c); + vClosestsPoints.push_back(CheckClosest(vTargetShape, vecShapes[nSelectedShapeIndex])); + } + } } @@ -369,6 +397,11 @@ class Test_Geometry2D : public olc::PixelGameEngine for (const auto& intersection : vIntersections) FillCircle(intersection, 3, olc::RED); + // Draw Closests + for (auto i = 0; i < vClosestsPoints.size()/2; i++) + DrawLine(vClosestsPoints[2 * i], vClosestsPoints[2 * i + 1], olc::DARK_GREY); + + if (bRayMode) { DrawShape(ray1, olc::CYAN); diff --git a/olcUTIL_Geometry2D.h b/olcUTIL_Geometry2D.h index 7e3be8a..6add43e 100644 --- a/olcUTIL_Geometry2D.h +++ b/olcUTIL_Geometry2D.h @@ -895,8 +895,31 @@ namespace olc::utils::geom2d template inline olc::v_2d closest(const line& l1, const line& l2) { - // TODO: - return {}; + auto V1 = l1.end - l1.start; + auto V2 = l2.end - l2.start; + auto V21 = l2.start - l1.start; + + auto v22 = V2.dot(V2); + auto v11 = V1.dot(V1); + auto v21 = V2.dot(V1); + auto v21_1 = V21.dot(V1); + auto v21_2 = V21.dot(V2); + auto denom = v21 * v21 - v22 * v11; + + float s, t; + if (denom == 0.f) { + s = 0.f; + t = (v11 * s - v21_1) / v21; + } + else { + s = (v21_2 * v21 - v22 * v21_1) / denom; + t = (-v21_1 * v21 + v11 * v21_2) / denom; + } + + s = std::max(std::min(s, 1.f), 0.f); + t = std::max(std::min(t, 1.f), 0.f); + + return l1.start + s * V1; } // closest(r,l)