Coordinat is a class for a coordinat.
INCLUDEPATH += \ ../../Classes/CppCoordinat SOURCES += \ ../../Classes/CppCoordinat/coordinat.cpp \ ../../Classes/CppCoordinat/coordinat3d.cpp \ ../../Classes/CppCoordinat/coordinat2d.cpp \ ../../Classes/CppCoordinat/constcoordinat2d.cpp HEADERS += \ ../../Classes/CppCoordinat/coordinat.h \ ../../Classes/CppCoordinat/coordinat3d.h \ ../../Classes/CppCoordinat/coordinat2d.h \ ../../Classes/CppCoordinat/constcoordinat2d.h OTHER_FILES += \ ../../Classes/CppCoordinat/Licence.txt
//--------------------------------------------------------------------------- /* Coordinat, coordinat classes Copyright 2013-2015 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- //From http://www.richelbilderbeek.nl/CppCoordinat.htm //--------------------------------------------------------------------------- #ifndef RIBI_CONSTCOORDINAT2D_H #define RIBI_CONSTCOORDINAT2D_H //typedef boost::geometry::model::d2::point_xy<double> ConstCoordinat2D; #ifdef USE_CUSTOM_RIBI_CONSTCOORDINAT2D #include <array> #include <iosfwd> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <boost/checked_delete.hpp> #include <boost/shared_ptr.hpp> #pragma GCC diagnostic pop namespace ribi { ///An immutable X-Y coordinat //Note: I dislike to write this class: I wish there was a library (STL, Boost) //with an alternative. struct ConstCoordinat2D { ConstCoordinat2D( const double x = 0.0, const double y = 0.0 ) noexcept; double GetX() const noexcept { return m_co[0]; } double GetY() const noexcept { return m_co[1]; } private: ConstCoordinat2D(const ConstCoordinat2D&) = delete; ConstCoordinat2D& operator=(const ConstCoordinat2D&) = delete; virtual ~ConstCoordinat2D() noexcept {} friend void boost::checked_delete<>(ConstCoordinat2D*); friend void boost::checked_delete<>(const ConstCoordinat2D*); static const int dimensionality = 2; const std::array<double,dimensionality> m_co; #ifndef NDEBUG static void Test() noexcept; #endif }; double Distance(const ConstCoordinat2D& lhs,const ConstCoordinat2D& rhs) noexcept; double DotProduct( const boost::shared_ptr<const ConstCoordinat2D> v1, const boost::shared_ptr<const ConstCoordinat2D> v2) noexcept; ///Distance to origin double Length(const boost::shared_ptr<const ConstCoordinat2D> v) noexcept; boost::shared_ptr<const ConstCoordinat2D> Scale( const double scalar, const boost::shared_ptr<const ConstCoordinat2D> v ) noexcept; bool operator==(const ConstCoordinat2D& lhs, const ConstCoordinat2D& rhs) noexcept; bool operator<(const ConstCoordinat2D& lhs, const ConstCoordinat2D& rhs) noexcept; std::ostream& operator<<(std::ostream& os, const ConstCoordinat2D& n) noexcept; boost::shared_ptr<const ConstCoordinat2D> operator+( const boost::shared_ptr<const ConstCoordinat2D> v1, const boost::shared_ptr<const ConstCoordinat2D> v2 ) noexcept; boost::shared_ptr<const ConstCoordinat2D> operator-( const boost::shared_ptr<const ConstCoordinat2D> v1, const boost::shared_ptr<const ConstCoordinat2D> v2 ) noexcept; } //~namespace ribi #endif #endif // RIBI_CONSTCOORDINAT2D_H
//--------------------------------------------------------------------------- /* Coordinat, coordinat classes Copyright 2013-2015 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- //From http://www.richelbilderbeek.nl/CppCoordinat.htm //--------------------------------------------------------------------------- #ifdef USE_CUSTOM_RIBI_CONSTCOORDINAT2D #include "constcoordinat2d.h" #include <array> #include <iostream> #include "trace.h" #include "xml.h" ConstCoordinat2D::ConstCoordinat2D(const double x, const double y) noexcept : m_co{ { x,y } } { #ifndef NDEBUG Test(); #endif } double ribi::DotProduct( const boost::shared_ptr<const ConstCoordinat2D> v1, const boost::shared_ptr<const ConstCoordinat2D> v2 ) noexcept { return ( v1->GetX() * v2->GetX()) + ( v1->GetY() * v2->GetY()) ; } double ribi::Distance(const ConstCoordinat2D& lhs,const ConstCoordinat2D& rhs) noexcept { const double dx = lhs.GetX() - rhs.GetX(); const double dy = lhs.GetY() - rhs.GetY(); return std::sqrt( (dx * dx) + (dy * dy) ); } double ribi::Length(const boost::shared_ptr<const ConstCoordinat2D> v) noexcept { const double dx = v->GetX(); const double dy = v->GetY(); return std::sqrt((dx*dx)+(dy*dy)); } boost::shared_ptr<const ConstCoordinat2D> ribi::Scale( const double scalar, const boost::shared_ptr<const ConstCoordinat2D> v) noexcept { const boost::shared_ptr<const ConstCoordinat2D> p( new ConstCoordinat2D( scalar * v->GetX(), scalar * v->GetY() ) ); assert(p); return p; } #ifndef NDEBUG void ConstCoordinat2D::Test() noexcept { { static bool is_tested{false}; if (is_tested) return; is_tested = true; } const TestTimer test_timer(__func__,__FILE__,1.0); } #endif boost::shared_ptr<const ConstCoordinat2D> ribi::operator-( const boost::shared_ptr<const ConstCoordinat2D> v1, const boost::shared_ptr<const ConstCoordinat2D> v2) noexcept { const boost::shared_ptr<const ConstCoordinat2D> p( new ConstCoordinat2D( v1->GetX() - v2->GetX(), v1->GetY() - v2->GetY() ) ); assert(p); return p; } boost::shared_ptr<const ConstCoordinat2D> ribi::operator+( const boost::shared_ptr<const ConstCoordinat2D> v1, const boost::shared_ptr<const ConstCoordinat2D> v2) noexcept { const boost::shared_ptr<const ConstCoordinat2D> p( new ConstCoordinat2D( v1->GetX() + v2->GetX(), v1->GetY() + v2->GetY() ) ); assert(p); return p; } bool ribi::operator==(const ConstCoordinat2D& lhs, const ConstCoordinat2D& rhs) noexcept { return lhs.GetX() == rhs.GetX() && lhs.GetY() == rhs.GetY(); } bool ribi::operator<(const ConstCoordinat2D& lhs, const ConstCoordinat2D& rhs) noexcept { if (lhs.GetX() < rhs.GetX()) return true; if (lhs.GetX() > rhs.GetX()) return false; if (lhs.GetY() < rhs.GetY()) return true; if (lhs.GetY() > rhs.GetY()) return false; return false; } std::ostream& ribi::operator<<(std::ostream& os, const ConstCoordinat2D& n) noexcept { std::stringstream s; s << ribi::xml::ToXml("x",n.GetX()) << ribi::xml::ToXml("y",n.GetY()) ; os << ribi::xml::ToXml("coordinat2d",s.str()); return os; } #endif
//--------------------------------------------------------------------------- /* Coordinat, coordinat classes Copyright 2013-2015 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- //From http://www.richelbilderbeek.nl/CppCoordinat.htm //--------------------------------------------------------------------------- #ifndef RIBI_COORDINAT_H #define RIBI_COORDINAT_H #ifdef USE_CUSTOM_RIBI_COORDINAT #include <cassert> #include "trace.h" ///A normal (x,y) coordinat template <class Length> struct Coordinat { explicit Coordinat(const Length& x, const Length& y) noexcept; const Length& GetX() const noexcept { return m_x; } const Length& GetY() const noexcept { return m_y; } void Translate(const Length& dx, const Length& dy) noexcept; void Translate(const Coordinat& delta) noexcept; private: Length m_x; Length m_y; #ifndef NDEBUG static void Test() noexcept; #endif }; template <class Length> Coordinat::Coordinat(const Length& x, const Length& y) noexcept : m_x { x }, m_y { y } { #ifndef NDEBUG Test(); #endif } template <class Length> void Coordinat::Translate(const Coordinat& delta) noexcept { Translate(delta.GetX(),delta.GetY()); } template <class Length> void Coordinat::Translate(const Length& dx, const Length& dy) noexcept { m_x += dx; m_y += dy; } template <class Length> Coordinat operator+(const Coordinat& lhs, const Coordinat& rhs) noexcept { return Coordinat( lhs.GetX() + rhs.GetX(), lhs.GetY() + rhs.GetY() ); } template <class Length> bool operator==(const Coordinat& lhs, const Coordinat& rhs) noexcept { return lhs.GetX() == rhs.GetX() && lhs.GetY() == rhs.GetY(); } #ifndef NDEBUG template <class Length> void Coordinat::Test() noexcept { { static bool is_tested { false }; if (is_tested) return; is_tested = true; } const TestTimer test_timer(__func__,__FILE__,1.0); { const Coordinat<double> a(0.0,0.0); const Coordinat<double> b(0.0,0.0); assert(a == b); const Coordinat<double> c(a); } } #endif #endif // USE_CUSTOM_RIBI_COORDINAT #endif // RIBI_COORDINAT_H
//--------------------------------------------------------------------------- /* Coordinat, coordinat classes Copyright 2013-2015 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- //From http://www.richelbilderbeek.nl/CppCoordinat.htm //--------------------------------------------------------------------------- #ifdef USE_CUSTOM_RIBI_COORDINAT #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" #include "coordinat.h" #pragma GCC diagnostic pop #endif // USE_CUSTOM_RIBI_COORDINAT
//--------------------------------------------------------------------------- /* Coordinat, coordinat classes Copyright 2013-2015 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- //From http://www.richelbilderbeek.nl/CppCoordinat.htm //--------------------------------------------------------------------------- #ifndef RIBI_COORDINAT2D_H #define RIBI_COORDINAT2D_H //typedef boost::geometry::model::d2::point_xy<double> Coordinat2D; #ifdef USE_CUSTOM_RIBI_COORDINAT2D #include <array> #include <iosfwd> #include <vector> namespace ribi { ///An X-Y coordinat //Note: I dislike to write this class: I wish there was a library (STL, Boost) //with an alternative. struct Coordinat2D { Coordinat2D( const double x = 0.0, const double y = 0.0 ) noexcept; void ChangeX(const double dx) noexcept { m_co[0] += dx; } void ChangeY(const double dy) noexcept { m_co[1] += dy; } double GetX() const noexcept { return m_co[0]; } double GetY() const noexcept { return m_co[1]; } void SetX(const double x) noexcept { m_co[0] = x; } void SetY(const double y) noexcept { m_co[1] = y; } Coordinat2D& operator+=(const Coordinat2D& rhs) noexcept; Coordinat2D& operator-=(const Coordinat2D& rhs) noexcept; private: static const int dimensionality = 2; std::array<double,dimensionality> m_co; #ifndef NDEBUG static void Test() noexcept; #endif }; bool operator==(const Coordinat2D& lhs, const Coordinat2D& rhs) noexcept; bool operator<(const Coordinat2D& lhs, const Coordinat2D& rhs) noexcept; std::ostream& operator<<(std::ostream& os, const Coordinat2D& n) noexcept; ///The dot product double operator*(const Coordinat2D& v1,const Coordinat2D& v2) noexcept; ///Calculate the point in the center of the collection of points Coordinat2D CalcCenter(const std::vector<Coordinat2D>& points) noexcept; double Distance(const Coordinat2D& lhs,const Coordinat2D& rhs) noexcept; ///Distance to origin double Length(const Coordinat2D& v) noexcept; Coordinat2D Scale( const double scalar, const Coordinat2D& v ) noexcept; Coordinat2D operator+( const Coordinat2D& v1, const Coordinat2D& v2) noexcept; Coordinat2D operator*( const double scalar, const Coordinat2D& v) noexcept; Coordinat2D operator-( const Coordinat2D& v1, const Coordinat2D& v2) noexcept; } //~namespace ribi #endif #endif // RIBI_COORDINAT2D_H
//--------------------------------------------------------------------------- /* Coordinat, coordinat classes Copyright 2013-2015 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- //From http://www.richelbilderbeek.nl/CppCoordinat.htm //--------------------------------------------------------------------------- #ifdef USE_CUSTOM_RIBI_COORDINAT3D #include "coordinat2d.h" #include <array> #include <iostream> #include "trace.h" #include "xml.h" ribi::Coordinat2D::Coordinat2D(const double x, const double y) noexcept : m_co{ { x,y } } { #ifndef NDEBUG Test(); #endif } //ribi::Coordinat2D::Coordinat2D(const Coordinat2D& rhs) // : m_co{ { rhs.GetX(), rhs.GetY() } } //{ // assert(*this == rhs); //} //ribi::Coordinat2D& ribi::Coordinat2D::operator=(const Coordinat2D& rhs) //{ // m_co = { rhs.GetX(), rhs.GetY() }; // assert(*this == rhs); // return *this; //} ribi::Coordinat2D& ribi::Coordinat2D::operator+=(const Coordinat2D& rhs) noexcept { m_co[0] += rhs.GetX(); m_co[1] += rhs.GetY(); return *this; } ribi::Coordinat2D& ribi::Coordinat2D::operator-=(const Coordinat2D& rhs) noexcept { m_co[0] -= rhs.GetX(); m_co[1] -= rhs.GetY(); return *this; } double ribi::operator*(const Coordinat2D& v1,const Coordinat2D& v2) noexcept { return ( v1.GetX() * v2.GetX()) + ( v1.GetY() * v2.GetY()) ; } ribi::Coordinat2D ribi::CalcCenter(const std::vector<ribi::Coordinat2D>& points) noexcept { Coordinat2D sum; for (const auto& point: points) { sum += point; } const double n { static_cast<double>(points.size()) }; const Coordinat2D center( sum.GetX() / n, sum.GetY() / n ); return center; } double ribi::Distance(const Coordinat2D& lhs,const Coordinat2D& rhs) noexcept { const double dx = lhs.GetX() - rhs.GetX(); const double dy = lhs.GetY() - rhs.GetY(); return std::sqrt( (dx * dx) + (dy * dy) ); } double ribi::Length(const Coordinat2D& v) noexcept { return std::sqrt( (v.GetX() * v.GetX()) + (v.GetY() * v.GetY())); } ribi::Coordinat2D ribi::Scale( const double scalar, const ribi::Coordinat2D& v ) noexcept { assert(scalar != 0.0); const ribi::Coordinat2D c( v.GetX() / scalar, v.GetY() / scalar ); return c; } #ifndef NDEBUG void ribi::Coordinat2D::Test() noexcept { { static bool is_tested{false}; if (is_tested) return; is_tested = true; } const TestTimer test_timer(__func__,__FILE__,1.0); } #endif ribi::Coordinat2D ribi::operator-( const Coordinat2D& v1, const Coordinat2D& v2) noexcept { return { v1.GetX()-v2.GetX(), v1.GetY()-v2.GetY() }; } ribi::Coordinat2D ribi::operator+( const Coordinat2D& v1, const Coordinat2D& v2) noexcept { return { v1.GetX()+v2.GetX(), v1.GetY()+v2.GetY() }; } ribi::Coordinat2D ribi::operator*( const double scalar, const Coordinat2D& v) noexcept { return Coordinat2D( scalar * v.GetX(), scalar * v.GetY() ); } bool ribi::operator==(const Coordinat2D& lhs, const Coordinat2D& rhs) noexcept { return lhs.GetX() == rhs.GetX() && lhs.GetY() == rhs.GetY(); } bool ribi::operator<(const Coordinat2D& lhs, const Coordinat2D& rhs) noexcept { if (lhs.GetX() < rhs.GetX()) return true; if (lhs.GetX() > rhs.GetX()) return false; if (lhs.GetY() < rhs.GetY()) return true; if (lhs.GetY() > rhs.GetY()) return false; return false; } std::ostream& ribi::operator<<(std::ostream& os, const Coordinat2D& n) noexcept { std::stringstream s; s << ribi::xml::ToXml("x",n.GetX()) << ribi::xml::ToXml("y",n.GetY()) ; os << ribi::xml::ToXml("coordinat2d",s.str()); return os; } #endif
//--------------------------------------------------------------------------- /* Coordinat, coordinat classes Copyright 2013-2015 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- //From http://www.richelbilderbeek.nl/CppCoordinat.htm //--------------------------------------------------------------------------- #ifndef RIBI_COORDINAT3D_H #define RIBI_COORDINAT3D_H //typedef boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> Coordinat3D; #ifdef USE_CUSTOM_RIBI_COORDINAT3D #include <array> #include <iosfwd> #include <vector> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <boost/geometry.hpp> #include <boost/geometry/geometries/point_xy.hpp> #ifndef _WIN32 #include <boost/geometry/geometries/polygon.hpp> #endif #pragma GCC diagnostic pop namespace ribi { ///An X-Y-Z coordinat //Note: I dislike to write this class: I wish there was a library (STL, Boost) //with an alternative. struct Coordinat3D { explicit Coordinat3D( const double x = 0.0, const double y = 0.0, const double z = 0.0 ) noexcept; explicit Coordinat3D( const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& p ) noexcept : Coordinat3D( boost::geometry::get<0>(p), boost::geometry::get<1>(p), boost::geometry::get<2>(p) ) {} void ChangeX(const double dx) noexcept { m_co[0] += dx; } void ChangeY(const double dy) noexcept { m_co[1] += dy; } void ChangeZ(const double dz) noexcept { m_co[2] += dz; } std::string GetVersion() const noexcept; std::vector<std::string> GetVersionHistory() const noexcept; double GetX() const noexcept { return m_co[0]; } double GetY() const noexcept { return m_co[1]; } double GetZ() const noexcept { return m_co[2]; } void SetX(const double x) noexcept { m_co[0] = x; } void SetY(const double y) noexcept { m_co[1] = y; } void SetZ(const double z) noexcept { m_co[2] = z; } boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> ToBoostGeometryPoint() const noexcept { return boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>( m_co[0],m_co[1],m_co[2] ); } Coordinat3D& operator+=(const Coordinat3D& rhs) noexcept; Coordinat3D& operator-=(const Coordinat3D& rhs) noexcept; Coordinat3D& operator/=(const double f); Coordinat3D& operator*=(const double f) noexcept; private: static const int dimensionality = 3; std::array<double,dimensionality> m_co; #ifndef NDEBUG static void Test() noexcept; #endif }; bool operator==(const Coordinat3D& lhs, const Coordinat3D& rhs) noexcept; bool operator<(const Coordinat3D& lhs, const Coordinat3D& rhs) noexcept; std::ostream& operator<<(std::ostream& os, const Coordinat3D& n) noexcept; Coordinat3D operator-( const Coordinat3D& v1, const Coordinat3D& v2) noexcept; Coordinat3D operator+( const Coordinat3D& v1, const Coordinat3D& v2) noexcept; ///Divide all components of the coordinat by f Coordinat3D operator/( const Coordinat3D& c, const double f); ///Multiply all components of the coordinat by f Coordinat3D operator*( const Coordinat3D& c, const double f) noexcept; ///Calculate the point in the center of the collection of points Coordinat3D CalcCenter(const std::vector<Coordinat3D>& points) noexcept; ///Calculate the cross product Coordinat3D CalcCrossProduct( const Coordinat3D& a, const Coordinat3D& b ) noexcept; ///Calculate the cross product double CalcDotProduct( const Coordinat3D& a, const Coordinat3D& b ) noexcept; ///Calculate the normal of a triangle ///The normal will be (0,0,-1) if a,b and c lie in the XY plane and ordered clockwise (when viewed from above) ///The normal will be (0,0, 1) if a,b and c lie in the XY plane and ordered counter-clockwise (when viewed from above) ///I use this convention as it appears to be used most extensively Coordinat3D CalcNormal( const Coordinat3D& a, const Coordinat3D& b, const Coordinat3D& c ) noexcept; ///Calculate the distance between two coordinats double Distance(const Coordinat3D& lhs,const Coordinat3D& rhs) noexcept; ///When viewing a coordinat as a vector from origin, calculate its length double Length(const Coordinat3D& v) noexcept; } //~namespace ribi #endif #endif // RIBI_COORDINAT3D_H
//--------------------------------------------------------------------------- /* Coordinat, coordinat classes Copyright 2013-2015 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- //From http://www.richelbilderbeek.nl/CppCoordinat.htm //--------------------------------------------------------------------------- #ifdef USE_CUSTOM_RIBI_COORDINAT3D #include "coordinat3d.h" #include <array> #include <cmath> #include "trace.h" #include "xml.h" Coordinat3D::Coordinat3D(const double x, const double y, const double z) noexcept : m_co{ { x,y,z } } { #ifndef NDEBUG Test(); #endif } std::string Coordinat3D::GetVersion() const noexcept { return "1.1"; } std::vector<std::string> Coordinat3D::GetVersionHistory() const noexcept { return { "201x-xx-xx: version 1.0: initial version" "2014-03-07: version 1.1: initial versioning" }; } Coordinat3D& Coordinat3D::operator+=(const Coordinat3D& rhs) noexcept { m_co[0] += rhs.GetX(); m_co[1] += rhs.GetY(); m_co[2] += rhs.GetZ(); return *this; } Coordinat3D& Coordinat3D::operator-=(const Coordinat3D& rhs) noexcept { m_co[0] -= rhs.GetX(); m_co[1] -= rhs.GetY(); m_co[2] -= rhs.GetZ(); return *this; } Coordinat3D& Coordinat3D::operator/=(const double f) { assert(f != 0.0); m_co[0] /= f; m_co[1] /= f; m_co[2] /= f; return *this; } Coordinat3D& Coordinat3D::operator*=(const double f) noexcept { m_co[0] *= f; m_co[1] *= f; m_co[2] *= f; return *this; } Coordinat3D ribi::CalcCenter(const std::vector<Coordinat3D>& points) noexcept { Coordinat3D sum; for (const auto& point: points) { sum += point; } const double n { static_cast<double>(points.size()) }; const Coordinat3D center( sum.GetX() / n, sum.GetY() / n, sum.GetZ() / n ); return center; } Coordinat3D ribi::CalcCrossProduct( const Coordinat3D& a, const Coordinat3D& b ) noexcept { return Coordinat3D( (a.GetY() * b.GetZ()) - (a.GetZ() * b.GetY()), (a.GetZ() * b.GetX()) - (a.GetX() * b.GetZ()), (a.GetX() * b.GetY()) - (a.GetY() * b.GetX()) ); } double ribi::CalcDotProduct( const Coordinat3D& a, const Coordinat3D& b ) noexcept { return (a.GetX() * b.GetX()) + (a.GetY() * b.GetY()) + (a.GetZ() * b.GetZ()); } Coordinat3D ribi::CalcNormal( const Coordinat3D& a, const Coordinat3D& b, const Coordinat3D& c ) noexcept { const Coordinat3D u { c - a}; const Coordinat3D v { b - a}; return CalcCrossProduct(u,v); } double ribi::Distance(const Coordinat3D& lhs,const Coordinat3D& rhs) noexcept { const double dx = lhs.GetX() - rhs.GetX(); const double dy = lhs.GetY() - rhs.GetY(); const double dz = lhs.GetZ() - rhs.GetZ(); return std::sqrt( (dx * dx) + (dy * dy) + (dz * dz) ); } double ribi::Length(const Coordinat3D& v) noexcept { return std::sqrt( (v.GetX() * v.GetX()) + (v.GetY() * v.GetY()) + (v.GetZ() * v.GetZ()) ); } #ifndef NDEBUG void Coordinat3D::Test() noexcept { { static bool is_tested{false}; if (is_tested) return; is_tested = true; } const TestTimer test_timer(__func__,__FILE__,1.0); //CalcCenter, one Coordinat3D { assert(CalcCenter( { Coordinat3D() } ) == Coordinat3D()); assert(CalcCenter( { Coordinat3D(1.1,2.2) } ) == Coordinat3D(1.1,2.2)); } //CalcCenter, three Coordinat3D { const Coordinat3D center { CalcCenter( { Coordinat3D(0.0,1.0), Coordinat3D(1.0,2.0), Coordinat3D(2.0,3.0) } ) }; const Coordinat3D expected(1.0,2.0); assert(std::abs(center.GetX() - expected.GetX()) < 0.0001); assert(std::abs(center.GetY() - expected.GetY()) < 0.0001); assert(std::abs(center.GetZ() - expected.GetZ()) < 0.0001); } //CalcCenter, three Coordinat3D { const Coordinat3D center { CalcCenter( { Coordinat3D(-0.0,-1.0,2.0), Coordinat3D(-1.0,-2.0,4.0), Coordinat3D(-2.0,-3.0,6.0) } ) }; const Coordinat3D expected(-1.0,-2.0,4.0); assert(std::abs(center.GetX() - expected.GetX()) < 0.0001); assert(std::abs(center.GetY() - expected.GetY()) < 0.0001); assert(std::abs(center.GetZ() - expected.GetZ()) < 0.0001); } //CalcCrossProduct, XY plane { //Follow https://en.wikipedia.org/wiki/Cross_product //where //- a = {1.0,0.0, 0.0} //- b = {0.0,1.0, 0.0} //- a * b = {0.0,0.0, 1.0} //- b * a = {0.0,0.0,-1.0} const Coordinat3D a(1.0,0.0,0.0); const Coordinat3D b(0.0,1.0,0.0); const Coordinat3D p1 { CalcCrossProduct(a,b) }; const Coordinat3D p1_expected(0.0,0.0,1.0); const Coordinat3D p2 { CalcCrossProduct(b,a) }; const Coordinat3D p2_expected(0.0,0.0,-1.0); assert(std::abs(p1.GetX() - p1_expected.GetX()) < 0.0001); assert(std::abs(p1.GetY() - p1_expected.GetY()) < 0.0001); assert(std::abs(p1.GetZ() - p1_expected.GetZ()) < 0.0001); assert(std::abs(p2.GetX() - p2_expected.GetX()) < 0.0001); assert(std::abs(p2.GetY() - p2_expected.GetY()) < 0.0001); assert(std::abs(p2.GetZ() - p2_expected.GetZ()) < 0.0001); } //CalcDotProduct, XY plane { //From https://en.wikipedia.org/wiki/Dotproduct const Coordinat3D a(1.0, 3.0,-5.0); const Coordinat3D b(4.0,-2.0,-1.0); const double p { CalcDotProduct(a,b) }; const double q { CalcDotProduct(b,a) }; const double e { 3.0 }; assert(std::abs(p - e) < 0.0001); assert(std::abs(q - e) < 0.0001); assert(std::abs(p - q) < 0.0001); } { //From https://en.wikipedia.org/wiki/Dotproduct //'In particular, if A and B are orthogonal, then [...] A dot b = 0' const Coordinat3D a(1.0,0.0,0.0); const Coordinat3D b(0.0,1.0,0.0); const double p { CalcDotProduct(a,b) }; const double q { CalcDotProduct(b,a) }; const double e { 0.0 }; assert(std::abs(p - e) < 0.0001); assert(std::abs(q - e) < 0.0001); assert(std::abs(p - q) < 0.0001); } //CalcNormal, XY plane { /* 0 1 2 3 0 +------X | 1 | A (Z = 1) | |\ 2 | C-B | 3 | Y */ const Coordinat3D normal { CalcNormal( Coordinat3D(1.0,1.0,-1.0), //A Coordinat3D(2.0,2.0,-1.0), //B Coordinat3D(1.0,2.0,-1.0) //C ) }; const Coordinat3D expected(0.0,0.0,-1.0); assert(std::abs(normal.GetX() - expected.GetX()) < 0.0001); assert(std::abs(normal.GetY() - expected.GetY()) < 0.0001); assert(std::abs(normal.GetZ() - expected.GetZ()) < 0.0001); } //CalcNormal, XY plane { /* 0 1 2 3 0 +------X | 1 | A (Z = 1) | |\ 2 | B-C | 3 | Y */ const Coordinat3D normal { CalcNormal( Coordinat3D(1.0,1.0,-1.0), //A Coordinat3D(1.0,2.0,-1.0), //B Coordinat3D(2.0,2.0,-1.0) //C ) }; const Coordinat3D expected(0.0,0.0,1.0); assert(std::abs(normal.GetX() - expected.GetX()) < 0.0001); assert(std::abs(normal.GetY() - expected.GetY()) < 0.0001); assert(std::abs(normal.GetZ() - expected.GetZ()) < 0.0001); } } #endif Coordinat3D ribi::operator-( const Coordinat3D& v1, const Coordinat3D& v2) noexcept { return Coordinat3D( v1.GetX()-v2.GetX(), v1.GetY()-v2.GetY(), v1.GetZ()-v2.GetZ() ); } Coordinat3D ribi::operator+( const Coordinat3D& v1, const Coordinat3D& v2) noexcept { return Coordinat3D( v1.GetX()+v2.GetX(), v1.GetY()+v2.GetY(), v1.GetZ()+v2.GetZ() ); } Coordinat3D ribi::operator/( const Coordinat3D& c, const double f) { assert(f != 0.0); return Coordinat3D( c.GetX() / f, c.GetY() / f, c.GetZ() / f ); } Coordinat3D ribi::operator*( const Coordinat3D& c, const double f) noexcept { return Coordinat3D( c.GetX() * f, c.GetY() * f, c.GetZ() * f ); } bool ribi::operator==(const Coordinat3D& lhs, const Coordinat3D& rhs) noexcept { return lhs.GetX() == rhs.GetX() && lhs.GetY() == rhs.GetY() && lhs.GetZ() == rhs.GetZ(); } bool ribi::operator<(const Coordinat3D& lhs, const Coordinat3D& rhs) noexcept { if (lhs.GetX() < rhs.GetX()) return true; if (lhs.GetX() > rhs.GetX()) return false; if (lhs.GetY() < rhs.GetY()) return true; if (lhs.GetY() > rhs.GetY()) return false; return lhs.GetZ() < rhs.GetZ(); } std::ostream& ribi::operator<<(std::ostream& os, const Coordinat3D& n) noexcept { std::stringstream s; s << ribi::xml::ToXml("x",n.GetX()) << ribi::xml::ToXml("y",n.GetY()) << ribi::xml::ToXml("z",n.GetZ()); os << ribi::xml::ToXml("coordinat3d",s.str()); return os; } #endif