/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2018 Danny Robson */ #pragma once #include "../point.hpp" namespace cruft::geom { /// Represents a line that has a start and an end. /// /// It is not valid to create an unbounded segment by fixing one of the /// points at infinity. template struct segment { cruft::point a; /// The start of the segment. cruft::point b; /// The end of the segment. /// Return a copy of this object with the underlying type casted to /// the specified type. template segment cast (void) const { return { .a = a.template cast (), .b = b.template cast () }; } }; /// Return the squared distance from the closest point of the segment `s` /// to the point `p`. template T distance2 (segment s, point p) { const auto dir = s.b - s.a; const auto t1 = dot (p - s.a, dir); if (t1 < 0) return distance2 (p, s.a); const auto t2 = dot (dir, dir); if (t2 < t1) return distance2 (p, s.b); auto t = t1 / t2; return distance2 (p, s.a + t * dir); } /// Return the distance from a the closest point of the segment `s` to /// the point `p`. template T distance (segment s, point p) { return std::sqrt (distance2 (s, p)); } /// Returns the un-normalised direction of the segment from its start to /// end components. ie, `a' to `b'. template cruft::vector udirection (segment const &val) { return val.b - val.a; } /// Returns the normalised direction of the segment. template cruft::vector ndirection (segment const &val) { return normalised (udirection (val)); } using segment2i = segment<2,int>; using segment3i = segment<3,int>; using segment2f = segment<2,float>; using segment3f = segment<3,float>; }