2015-02-19 13:28:36 +11:00
|
|
|
/*
|
2018-08-04 15:14:06 +10:00
|
|
|
* 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/.
|
2015-02-19 13:28:36 +11:00
|
|
|
*
|
2018-04-20 15:05:29 +10:00
|
|
|
* Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
|
2015-02-19 13:28:36 +11:00
|
|
|
*/
|
|
|
|
|
2018-04-20 15:05:29 +10:00
|
|
|
#pragma once
|
2015-02-19 13:28:36 +11:00
|
|
|
|
2015-10-14 15:32:53 +11:00
|
|
|
#include "../point.hpp"
|
|
|
|
#include "../vector.hpp"
|
2018-03-13 22:36:24 +11:00
|
|
|
#include "../matrix.hpp"
|
2015-02-19 13:28:36 +11:00
|
|
|
|
2018-08-05 14:42:02 +10:00
|
|
|
namespace cruft::geom {
|
2018-03-13 23:27:37 +11:00
|
|
|
/// represents an S dimensional plane in parametric form: ax + by + cz + d = 0
|
2015-02-19 13:28:36 +11:00
|
|
|
template <size_t S, typename T>
|
|
|
|
struct plane {
|
2018-03-13 22:36:24 +11:00
|
|
|
plane () = default;
|
2018-08-05 14:42:02 +10:00
|
|
|
plane (cruft::point<S,T> base, cruft::vector<S,T> normal);
|
2015-02-19 13:28:36 +11:00
|
|
|
|
2018-08-05 14:42:02 +10:00
|
|
|
explicit plane (cruft::vector<S+1,T> _coefficients):
|
2018-03-13 22:36:24 +11:00
|
|
|
coefficients (_coefficients)
|
|
|
|
{ ; }
|
|
|
|
|
2018-08-05 14:42:02 +10:00
|
|
|
cruft::vector<S+1,T> coefficients;
|
2015-02-19 13:28:36 +11:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-04-20 15:05:29 +10:00
|
|
|
typedef plane<2,float> plane2f;
|
|
|
|
typedef plane<3,float> plane3f;
|
|
|
|
|
|
|
|
inline plane3f
|
2018-08-05 14:42:02 +10:00
|
|
|
make_plane (cruft::point3f a, cruft::point3f b, cruft::point3f c)
|
2018-04-20 15:05:29 +10:00
|
|
|
{
|
|
|
|
return plane3f (a, normalised (cross (b - a, c - a)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-13 22:36:24 +11:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
/// returns the normal for a plane
|
|
|
|
template <size_t S, typename T>
|
2018-08-05 14:42:02 +10:00
|
|
|
cruft::vector<S,T>
|
2018-03-13 22:36:24 +11:00
|
|
|
normal (plane<S,T> p)
|
|
|
|
{
|
|
|
|
return p.coefficients.template redim<S> ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
/// normalises a plane's parametric form
|
|
|
|
///
|
|
|
|
/// useful only after manually modifying the coefficients (as in default
|
|
|
|
/// construction and piecewise initialisation). a plane will otherwise be
|
|
|
|
/// assumed to be in normal form.
|
|
|
|
template <size_t S, typename T>
|
|
|
|
plane<S,T>
|
|
|
|
normalised (plane<S,T> p)
|
|
|
|
{
|
|
|
|
const auto mag = norm (normal (p));
|
|
|
|
CHECK_NEZ (mag);
|
|
|
|
return plane<S,T> (p.coefficients / mag);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-20 15:05:48 +10:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
/// calculates the distance from a plane to a point.
|
|
|
|
///
|
|
|
|
/// positive distances are in front of the plane, negative is behind;
|
2018-05-07 11:48:32 +10:00
|
|
|
///
|
|
|
|
/// NOTE: `distance2` is _not_ the squared distance. It is the
|
|
|
|
/// unnormalised distance. It needs to be divided by the norm of the
|
|
|
|
/// plane normal.
|
2018-04-20 15:05:48 +10:00
|
|
|
template <size_t S, typename T>
|
|
|
|
T
|
2018-05-07 11:48:32 +10:00
|
|
|
distance2 (plane<S,T> p, point<S,T> q)
|
|
|
|
{
|
|
|
|
return dot (p.coefficients, q.template redim<S+1> (1));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <size_t S, typename T>
|
|
|
|
T
|
|
|
|
distance2 (point<S,T> p, plane<S,T> q)
|
2018-04-20 15:05:48 +10:00
|
|
|
{
|
2018-05-07 11:48:32 +10:00
|
|
|
return -distance2 (q, p);
|
|
|
|
}
|
2015-02-19 13:28:36 +11:00
|
|
|
|
2018-05-07 11:48:32 +10:00
|
|
|
|
|
|
|
template <size_t S, typename T>
|
|
|
|
T
|
|
|
|
distance (plane<S,T> p, point<S,T> q)
|
|
|
|
{
|
|
|
|
return distance2 (p, q) / norm (normal (p));
|
2018-04-20 15:05:48 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <size_t S, typename T>
|
|
|
|
T
|
|
|
|
distance (point<S,T> p, plane<S,T> q)
|
|
|
|
{
|
|
|
|
return -distance (q, p);
|
|
|
|
}
|
2018-04-23 15:41:58 +10:00
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
template <size_t S, typename T>
|
|
|
|
auto
|
2018-08-05 14:42:02 +10:00
|
|
|
furthest (plane<S,T> p, const std::vector<cruft::point<S,T>> &cloud)
|
2018-04-23 15:41:58 +10:00
|
|
|
{
|
|
|
|
T maxd = -INFINITY;
|
|
|
|
auto best = cloud.begin ();
|
|
|
|
|
|
|
|
for (auto q = cloud.begin (), last = cloud.end (); q != last; ++q) {
|
|
|
|
if (auto d = distance (p, *q); d > maxd) {
|
|
|
|
maxd = d;
|
|
|
|
best = q;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return std::make_tuple (best, maxd);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <size_t S, typename T>
|
|
|
|
auto
|
2018-08-05 14:42:02 +10:00
|
|
|
furthest (plane<S,T>, std::vector<cruft::point<S,T>> &&) = delete;
|
2018-04-20 15:05:48 +10:00
|
|
|
}
|