Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) Coordinat

 

STLQt CreatorLubuntu

 

Coordinat is a class for a coordinat.

Technical facts

 

 

 

 

 

 

./CppCoordinat/CppCoordinat.pri

 

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

 

 

 

 

 

./CppCoordinat/constcoordinat2d.h

 

//---------------------------------------------------------------------------
/*
Coordinat, coordinat classes
Copyright (C) 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

 

 

 

 

 

./CppCoordinat/constcoordinat2d.cpp

 

//---------------------------------------------------------------------------
/*
Coordinat, coordinat classes
Copyright (C) 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

 

 

 

 

 

./CppCoordinat/coordinat.h

 

//---------------------------------------------------------------------------
/*
Coordinat, coordinat classes
Copyright (C) 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

 

 

 

 

 

./CppCoordinat/coordinat.cpp

 

//---------------------------------------------------------------------------
/*
Coordinat, coordinat classes
Copyright (C) 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

 

 

 

 

 

./CppCoordinat/coordinat2d.h

 

//---------------------------------------------------------------------------
/*
Coordinat, coordinat classes
Copyright (C) 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

 

 

 

 

 

./CppCoordinat/coordinat2d.cpp

 

//---------------------------------------------------------------------------
/*
Coordinat, coordinat classes
Copyright (C) 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

 

 

 

 

 

./CppCoordinat/coordinat3d.h

 

//---------------------------------------------------------------------------
/*
Coordinat, coordinat classes
Copyright (C) 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

 

 

 

 

 

./CppCoordinat/coordinat3d.cpp

 

//---------------------------------------------------------------------------
/*
Coordinat, coordinat classes
Copyright (C) 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

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml