diff --git a/CMakeLists.txt b/CMakeLists.txt index e597cd9b..39228462 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -244,6 +244,8 @@ list ( geom/rect.hpp geom/sample.cpp geom/sample.hpp + geom/segment.cpp + geom/segment.hpp geom/sphere.cpp geom/sphere.hpp geom/tri.cpp @@ -501,6 +503,7 @@ if (TESTS) geom/line geom/plane geom/ray + geom/segment geom/sphere hash/checksum hash/crc diff --git a/geom/segment.cpp b/geom/segment.cpp new file mode 100644 index 00000000..10b35bd6 --- /dev/null +++ b/geom/segment.cpp @@ -0,0 +1,20 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2018 Danny Robson + */ + +#include "segment.hpp" + + +/////////////////////////////////////////////////////////////////////////////// diff --git a/geom/segment.hpp b/geom/segment.hpp new file mode 100644 index 00000000..f0474e7f --- /dev/null +++ b/geom/segment.hpp @@ -0,0 +1,58 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2018 Danny Robson + */ + +#pragma once + +#include "../point.hpp" + + +namespace util::geom { + template + struct segment { + util::point a; + util::point b; + }; + + + using segment2f = segment<2,float>; + using segment3f = segment<3,float>; + + + 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); + } + + + template + T + distance (segment s, point p) + { + return std::sqrt (distance2 (s, p)); + } +}; diff --git a/test/geom/segment.cpp b/test/geom/segment.cpp new file mode 100644 index 00000000..de396600 --- /dev/null +++ b/test/geom/segment.cpp @@ -0,0 +1,28 @@ +#include "tap.hpp" + +#include "geom/segment.hpp" + +int +main (int, char**) +{ + util::TAP::logger tap; + + static struct { + util::point3f a, b; + util::point3f q; + float distance; + const char *message; + } const TESTS[] = { + { { 0, 0, 0 }, { 1, 1, 1 }, { 0, 0, 0 }, 0, "origin line, origin point" }, + { { 0, 0, 0 }, { 1, 1, 1 }, { 1, 1, 1 }, 0, "origin line, point on line" }, + { { 0, 1, 0 }, { 1, 1, 0 }, { 0, 0, 0 }, 1, "+x line, unit distance" }, + }; + + for (auto const& t: TESTS) { + util::geom::segment3f s {t.a, t.b}; + auto d = distance (s, t.q); + tap.expect_eq (d, t.distance, "%!", t.message); + } + + return tap.status (); +} \ No newline at end of file