Skip to content

File Sphere.h

File List > src > Sphere.h

Go to the documentation of this file

// Copyright (c) 2024-2024, Oslandia.
// SPDX-License-Identifier: LGPL-2.0-or-later

#ifndef _SFCGAL_SPHERE_H_
#define _SFCGAL_SPHERE_H_

#include <optional>
#include <vector>

#include <CGAL/Polyhedron_3.h>
#include <CGAL/squared_distance_3.h>

#include "SFCGAL/Kernel.h"
#include "SFCGAL/export.h"
#include "SFCGAL/numeric.h"

namespace SFCGAL {

class SFCGAL_API Sphere {
public:
  Sphere(const Kernel::FT      &radius = 1.0,
         const Kernel::Point_3 &center = Kernel::Point_3(0, 0, 0),
         int num_vertical = 16, int num_horizontal = 32,
         const Kernel::Vector_3 &direction = Kernel::Vector_3(0, 0, 1));

  Sphere(const Sphere &other) = default;

  Sphere &
  operator=(Sphere other);

  ~Sphere() = default;

  inline void
  setRadius(const Kernel::FT &radius)
  {
    m_radius = radius;
    invalidateCache();
  }

  inline void
  setCenter(const Kernel::Point_3 &center)
  {
    m_center = center;
    invalidateCache();
  }

  inline void
  setNumVertical(int num)
  {
    m_num_vertical = num;
    invalidateCache();
  }

  inline void
  setNumHorizontal(int num)
  {
    m_num_horizontal = num;
    invalidateCache();
  }

  inline void
  setDirection(const Kernel::Vector_3 &direction)
  {
    m_direction = normalizeVector(direction);
    invalidateCache();
  }

  inline const Kernel::FT &
  radius() const
  {
    return m_radius;
  }

  inline const Kernel::Point_3 &
  center() const
  {
    return m_center;
  }

  inline int
  numVertical() const
  {
    return m_num_vertical;
  }

  inline int
  numHorizontal() const
  {
    return m_num_horizontal;
  }

  inline const Kernel::Vector_3 &
  direction() const
  {
    return m_direction;
  }

  CGAL::Polyhedron_3<Kernel>
  generatePolyhedron();

  std::vector<Kernel::Point_3>
  generatePoints();

  double
  volume() const
  {
    return CGAL::to_double((4.0 / 3.0) * m_radius * m_radius * m_radius *
                           CGAL_PI);
  }

  double
  area() const
  {
    return CGAL::to_double(4 * m_radius * m_radius * CGAL_PI);
  }

private:
  Kernel::FT                                  m_radius;
  Kernel::Point_3                             m_center;
  int                                         m_num_vertical;
  int                                         m_num_horizontal;
  Kernel::Vector_3                            m_direction;
  std::optional<CGAL::Polyhedron_3<Kernel>>   m_polyhedron;
  std::optional<std::vector<Kernel::Point_3>> m_points;

  void
  invalidateCache();
  CGAL::Polyhedron_3<Kernel>
  generateSpherePolyhedron();
  std::vector<Kernel::Point_3>
  generateSpherePoints();

  // Function to get an orthogonal vector in the XY plane
  static Kernel::Vector_3
  get_orthogonal_vector(const Kernel::Vector_3 &vec)
  {
    if (vec.x() != 0 || vec.y() != 0) {
      return Kernel::Vector_3(-vec.y(), vec.x(), 0);
    } else {
      return Kernel::Vector_3(0, -vec.z(), vec.y());
    }
  }
};

} // namespace SFCGAL

#endif // _SFCGAL_SPHERE_H_