Revision 3811e436d20487a95a0429f329916be9e3cf4042 authored by Dmitry Yu. Naumov on 15 August 2021, 16:31:34 UTC, committed by Dmitry Yu. Naumov on 15 August 2021, 16:31:34 UTC
detail error message for unknown element See merge request ogs/ogs!3739
TemplatePoint.h
/**
* \file
* \author Thomas Fischer
* \date 2010-01-28
* \brief Definition of the TemplatePoint class.
*
* \copyright
* Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#pragma once
#include "mathlib_export.h"
// STL
#include <algorithm>
#include <array>
#include <cassert>
#include <cmath>
#include <istream>
#include <iterator>
#include <utility>
namespace MathLib
{
/**
* \ingroup GeoLib
*
* \brief class-template for points can be instantiated by a numeric type.
* \tparam T the coordinate type
*/
template <typename T, std::size_t DIM = 3> class TemplatePoint
{
public:
/** default constructor with zero coordinates */
TemplatePoint();
/** constructor - constructs a TemplatePoint object
*
* @param x std::array containing the coordinates of the point
*/
explicit TemplatePoint(std::array<T, DIM> x);
/** virtual destructor */
virtual ~TemplatePoint() = default;
TemplatePoint(TemplatePoint const&) = default;
TemplatePoint& operator=(TemplatePoint const&) = default;
/** \brief const access operator
* The access to the point coordinates is like the access to a field. Code example:
* \code
* Point<double> point (1.0, 2.0, 3.0);
* double sqrNrm2 = point[0] * point[0] + point[1] * point[1] + point[2] + point[2];
* \endcode
*/
const T& operator[] (std::size_t idx) const
{
assert (idx < DIM);
return x_[idx];
}
/** \brief access operator (see book Effektiv C++ programmieren - subsection 1.3.2 ).
* \sa const T& operator[] (std::size_t idx) const
*/
T& operator[] (std::size_t idx)
{
return const_cast<T&> (static_cast<const TemplatePoint&> (*this)[idx]);
}
/** returns an array containing the coordinates of the point */
const T* getCoords() const { return x_.data(); }
T* getCoords() { return x_.data(); }
/** write point coordinates into stream (used from operator<<)
* \param os a standard output stream
*/
virtual void write (std::ostream &os) const
{
std::copy(x_.cbegin(), x_.cend(), std::ostream_iterator<T>(os, " "));
}
/** read point coordinates into stream (used from operator>>) */
virtual void read (std::istream &is)
{
std::copy(std::istream_iterator<T>(is), std::istream_iterator<T>(),
x_.begin());
}
private:
std::array<T, DIM> x_;
};
template <typename T, std::size_t DIM>
TemplatePoint<T, DIM>::TemplatePoint() : x_({{0}})
{}
template <typename T, std::size_t DIM>
TemplatePoint<T, DIM>::TemplatePoint(std::array<T, DIM> x) : x_(std::move(x))
{}
/** Equality of TemplatePoint's up to an epsilon.
*/
template <typename T, std::size_t DIM>
bool operator==(TemplatePoint<T,DIM> const& a, TemplatePoint<T,DIM> const& b)
{
T const sqr_dist(sqrDist(a,b));
auto const eps = std::numeric_limits<T>::epsilon();
return (sqr_dist < eps*eps);
}
template <typename T, std::size_t DIM>
bool operator< (TemplatePoint<T,DIM> const& a, TemplatePoint<T,DIM> const& b)
{
for (std::size_t i = 0; i < DIM; ++i)
{
if (a[i] > b[i]) {
return false;
}
if (a[i] < b[i])
{
return true;
}
// continue with next dimension, because a[0] == b[0]
}
// The values in all dimenisions are equal.
return false;
}
/**
* Lexicographic comparison of points taking an epsilon into account.
*
* @param a first input point.
* @param b second input point.
* @param eps tolerance used in comparison of coordinates.
*
* @return true, if a is smaller then or equal to b according to the following
* test \f$ |a_i - b_i| > \epsilon \cdot \min (|a_i|, |b_i|) \f$ \b and
* \f$ |a_i - b_i| > \epsilon \f$ for all coordinates \f$ 0 \le i < \textrm{DIM} \f$.
*/
template <typename T, std::size_t DIM>
bool lessEq(TemplatePoint<T, DIM> const& a, TemplatePoint<T, DIM> const& b,
double eps = std::numeric_limits<double>::epsilon())
{
auto coordinateIsLargerEps = [&eps](T const u, T const v) -> bool
{
return std::abs(u - v) > eps * std::min(std::abs(v), std::abs(u)) &&
std::abs(u - v) > eps;
};
for (std::size_t i = 0; i < DIM; ++i)
{
// test a relative and an absolute criterion
if (coordinateIsLargerEps(a[i], b[i]))
{
return static_cast<bool>(a[i] <= b[i]);
}
// a[i] ~= b[i] up to an epsilon. Compare next dimension.
}
// all coordinates are equal up to an epsilon.
return true;
}
/** overload the output operator for class Point */
template <typename T, std::size_t DIM>
std::ostream& operator<< (std::ostream &os, const TemplatePoint<T,DIM> &p)
{
p.write (os);
return os;
}
/** overload the input operator for class Point */
template <typename T, std::size_t DIM>
std::istream& operator>> (std::istream &is, TemplatePoint<T,DIM> &p)
{
p.read (is);
return is;
}
} // end namespace MathLib
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...