dust3d/thirdparty/cgal/CGAL-5.1/include/CGAL/Nef_S2/Sphere_circle.h

175 lines
5.9 KiB
C++

// Copyright (c) 1997-2002 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL: https://github.com/CGAL/cgal/blob/v5.1/Nef_S2/include/CGAL/Nef_S2/Sphere_circle.h $
// $Id: Sphere_circle.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Seel <seel@mpi-sb.mpg.de>
#ifndef CGAL_SPHERE_CIRCLE_H
#define CGAL_SPHERE_CIRCLE_H
#include <CGAL/license/Nef_S2.h>
#include <CGAL/basic.h>
namespace CGAL {
template <class R> class Sphere_segment;
/*{\Manpage{Sphere_circle}{R}{Great circles on the unit sphere}{c}}*/
template <class R_> class Sphere_circle : public R_::Plane_3 {
/*{\Mdefinition An object |\Mvar| of type |\Mname| is an oriented
great circle on the surface of a unit sphere. Such circles correspond
to the intersection of an oriented plane (that contains the origin)
and the surface of $S_2$. The orientation of the great circle is that
of a counterclockwise walk along the circle as seen from the positive
halfspace of the oriented plane.}*/
public:
/*{\Mtypes 5}*/
typedef R_ R;
/*{\Mtypemember representation class.}*/
typedef typename R::RT RT;
/*{\Mtypemember ring type.}*/
typedef std::pair< Sphere_segment<R>,Sphere_segment<R> >
Sphere_segment_pair;
/*{\Mtypemember sphere segment pair.}*/
typedef typename R_::Plane_3 Plane_3;
typedef typename R_::Line_3 Line_3;
typedef typename R_::Point_3 Point_3;
typedef Sphere_circle<R_> Self;
typedef typename R_::Plane_3 Base;
/*{\Mcreation 5}*/
Sphere_circle() : Base() {}
/*{\Mcreate creates some great circle.}*/
Sphere_circle(const Sphere_point<R>& p, const Sphere_point<R>&q)
: Base(Point_3(0,0,0),p,q)
/*{\Mcreate creates a great circle through $p$ and $q$. If $p$ and
$q$ are not antipodal on $S_2$, then this circle is unique and oriented
such that a walk along |\Mvar| meets $p$ just before the shorter segment
between $p$ and $q$. If $p$ and $q$ are antipodal of each other then we
create any great circle that contains $p$ and $q$.}*/
{ Point_3 p1(0,0,0), p4 = CGAL::ORIGIN + ((Base*) this)->orthogonal_vector();
if ( p != q.antipode() ) {
if (R_().orientation_3_object()(p1,Point_3(p),
Point_3(q), p4) != CGAL::POSITIVE )
*this = Self(opposite());
} else {
/* previous method was: *this = Self(Plane_3(p1,q-p));
but p, q don't belong to he plane ((0,0,0), q-p) */
if(!Line_3(p,q).has_on(Point_3(1,0,0)))
*this = Self(Plane_3(p,q,Point_3(1,0,0)));
else
*this = Self(Plane_3(p,q,Point_3(0,1,0)));
/* take one point that doesn't belong to the line (p, q-p) */
}
}
Sphere_circle(const Plane_3& h) : Base(h)
/*{\Mcreate creates the circle of $S_2$ corresponding to the plane
|h|. If |h| does not contain the origin, then |\Mvar| becomes the
circle parallel to |h| containing the origin.}*/
{
if(h.d() != 0) *this = Plane_3(h.a(),h.b(),h.c(),RT(0));
}
Sphere_circle(const RT& x, const RT& y, const RT& z): Base(x,y,z,0) {}
/*{\Mcreate creates the circle orthogonal to the vector $(x,y,z)$.}*/
Sphere_circle(Sphere_circle<R> c, const Sphere_point<R>& p)
/*{\Mcreate creates a great circle orthogonal to $c$ that contains $p$.
\precond $p$ is not part of $c$.}*/
{ CGAL_assertion(!c.has_on(p));
if ( c.has_on_negative_side(p) ) c=c.opposite();
if ( p == c.orthogonal_pole() )
*this = Sphere_circle<R>(Base(Point_3(0,0,0),p,CGAL::ORIGIN+c.base1()));
else
*this = Sphere_circle<R>(Base(Point_3(0,0,0),p,c.orthogonal_pole()));
}
/*{\Moperations 4 2}*/
Sphere_circle<R> opposite() const
/*{\Mop returns the opposite of |\Mvar|.}*/
{ return Base::opposite(); }
bool has_on(const Sphere_point<R>& p) const
/*{\Mop returns true iff |\Mvar| contains |p|.}*/
{ return Base::has_on(p); }
Plane_3 plane() const { return Base(*this); }
/*{\Mop returns the plane supporting |\Mvar|.}*/
Plane_3 plane_through(const Point_3& p) const
/*{\Mop returns the plane parallel to |\Mvar| that
contains point |p|.}*/
{ return Plane_3(p,((Base*) this)->orthogonal_direction()); }
Sphere_point<R> orthogonal_pole() const
/*{\Mop returns the point that is the pole of the
hemisphere left of |\Mvar|.}*/
{ return CGAL::ORIGIN+((Base*) this)->orthogonal_vector(); }
Sphere_segment_pair split_at(const Sphere_point<R>& p) const;
/*{\Mop returns the pair of circle segments that is the result
of splitting |\Mvar| at |p| and |p.antipode()|.}*/
Sphere_segment_pair split_at_xy_plane() const;
/*{\Mop returns the pair of circle segments that is the result
of splitting |\Mvar| at the $x$-$y$-coordinate plane if |\Mvar|
is not part of it. Otherwise |\Mvar| is split at the
$x$-$z$-coordinate plane.}*/
}; // Sphere_circle<R>
/*{\Mtext\headerline{Global functions}}*/
template <class R>
bool equal_as_sets(const CGAL::Sphere_circle<R>& c1,
const CGAL::Sphere_circle<R>& c2)
/*{\Mfunc returns true iff |c1| and |c2| are equal as unoriented
circles.}*/
{ return c1==c2 || c1==c2.opposite(); }
template <class R>
bool equal_not_opposite(const CGAL::Sphere_circle<R>& c1,
const CGAL::Sphere_circle<R>& c2) {
// function should be called to decide whether two circles
// are equal or opposites. returns true iff |c1| and |c2| are equal
if(c1.a() != 0) return CGAL::sign(c1.a()) == CGAL::sign(c2.a());
if(c1.b() != 0) return CGAL::sign(c1.b()) == CGAL::sign(c2.b());
return CGAL::sign(c1.c()) == CGAL::sign(c2.c());
}
template <typename R>
Sphere_point<R> intersection(const Sphere_circle<R>& c1,
const Sphere_circle<R>& c2)
/*{\Mfunc returns one of the two intersection points of
|c1| and |c2|. \precond |c1 != c2| as sets.}*/
{
CGAL_assertion(!equal_as_sets(c1,c2));
typename R::Line_3 lres;
CGAL_NEF_TRACEN("circle_intersection "<<c1<<" "<<c2);
CGAL::Object o = CGAL::intersection(c1.plane(),c2.plane());
if ( !CGAL::assign(lres,o) ) CGAL_error();
return CGAL::ORIGIN + lres.direction().vector();
}
} //namespace CGAL
#endif //CGAL_SPHERE_CIRCLE_H