Merge pull request #3410 from maxGimeno/Kernel_23-Add_suport_for_reflextions-GF

Aff_transformation_2: Add suport for reflections
This commit is contained in:
Laurent Rineau 2019-07-01 11:16:36 +02:00
commit a99269d91d
10 changed files with 346 additions and 14 deletions

View File

@ -37,6 +37,7 @@ template < class R > class Aff_transformation_repC2;
template < class R > class Translation_repC2;
template < class R > class Rotation_repC2;
template < class R > class Scaling_repC2;
template < class R > class Reflection_repC2;
} //namespace CGAL
@ -44,6 +45,7 @@ template < class R > class Scaling_repC2;
#include <CGAL/Cartesian/Translation_rep_2.h>
#include <CGAL/Cartesian/Rotation_rep_2.h>
#include <CGAL/Cartesian/Scaling_rep_2.h>
#include <CGAL/Cartesian/Reflection_rep_2.h>
namespace CGAL {
@ -107,6 +109,11 @@ public:
else
initialize_with(Scaling_repC2<R>(s));
}
Aff_transformationC2(const Reflection, const Line_2& l)
{
initialize_with(Reflection_repC2<R>(l));
}
// The general case:
// a 3x2 matrix for the operations combining rotation, scaling, translation
@ -128,6 +135,7 @@ public:
{
initialize_with(Aff_transformation_repC2<R>(m11/w, m12/w, m21/w, m22/w));
}
Point_2
transform(const Point_2 &p) const

View File

@ -63,6 +63,9 @@ public:
virtual Aff_transformation_2 compose(
const Scaling_repC2<R> &t) const = 0;
virtual Aff_transformation_2 compose(
const Reflection_repC2<R> &t) const = 0;
virtual Aff_transformation_2 inverse() const = 0;
virtual bool is_even() const = 0;
@ -86,6 +89,7 @@ public:
friend class Translation_repC2<R>;
friend class Rotation_repC2<R>;
friend class Scaling_repC2<R>;
friend class Reflection_repC2<R>;
Aff_transformation_repC2()
{}
@ -131,6 +135,7 @@ friend class Scaling_repC2<R>;
Aff_transformation_2 compose(const Translation_repC2<R> &t) const;
Aff_transformation_2 compose(const Rotation_repC2<R> &t) const;
Aff_transformation_2 compose(const Scaling_repC2<R> &t) const;
Aff_transformation_2 compose(const Reflection_repC2<R> &t) const;
bool is_even() const
{
@ -252,6 +257,17 @@ compose(const Scaling_repC2<R> &t) const
t.scalefactor_ * t23);
}
template < class R >
CGAL_KERNEL_LARGE_INLINE
typename Aff_transformation_repC2<R>::Aff_transformation_2
Aff_transformation_repC2<R>::
compose(const Reflection_repC2<R> &r) const
{
return Aff_transformation_2(
r.cosinus_*t11+r.sinus_*t21, r.cosinus_*t12+r.sinus_*t22, r.cosinus_*(t13-r.t.x())+r.sinus_*(t23-r.t.y())+r.t.x(),
r.sinus_*(t11)-r.cosinus_*(t21), r.sinus_*(t12)-r.cosinus_*(t22), r.sinus_*(t13-r.t.x())-r.cosinus_*(t23-r.t.y())+r.t.y());
}
} //namespace CGAL
#endif // CGAL_CARTESIAN_AFF_TRANSFORMATION_REP_2_H

View File

@ -0,0 +1,208 @@
// Copyright (c) 2018
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 3 of the License,
// or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0+
//
//
// Author(s) : Maxime Gimeno
#ifndef CGAL_CARTESIAN_REFLECTION_REP_2_H
#define CGAL_CARTESIAN_REFLECTION_REP_2_H
#include <cmath>
namespace CGAL {
template < class R >
class Reflection_repC2: public Aff_transformation_rep_baseC2<R>
{
friend class Translation_repC2<R>;
friend class Rotation_repC2<R>;
friend class Scaling_repC2<R>;
friend class Aff_transformation_repC2<R>;
public:
typedef Aff_transformation_rep_baseC2<R> Aff_t_base;
typedef typename Aff_t_base::FT FT;
typedef typename Aff_t_base::Point_2 Point_2;
typedef typename Aff_t_base::Vector_2 Vector_2;
typedef typename Aff_t_base::Direction_2 Direction_2;
typedef typename CGAL::Line_2<R> Line_2;
typedef typename Aff_t_base::Aff_transformation_2 Aff_transformation_2;
typedef Aff_transformation_repC2<R> Transformation;
typedef Reflection_repC2<R> Reflection;
typedef Scaling_repC2<R> Scaling;
typedef Rotation_repC2<R> Rotation;
typedef Translation_repC2<R> Translation;
Reflection_repC2(const Line_2 &l)
{
if(l.a() == 0)
t = -Vector_2(0, l.c()/l.b());
else
t = -Vector_2(l.c()/l.a(),0);
Vector_2 l_to_v = l.to_vector();
FT scal = l_to_v.x(); //Projection of l_to_v on Ox. = |L|*cos(a)
FT det = l_to_v.y();// = |L|*sin(a)
sinus_ = 2*det*scal/l_to_v.squared_length(); //sin(2a) = 2*sin(a)*cos(a)
FT sq_cos = scal*scal/l_to_v.squared_length(); //cos(a)*cos(a)
cosinus_ = 2*sq_cos-1;
}
~Reflection_repC2()
{}
Point_2 transform(const Point_2 &p) const
{
return Point_2(
cosinus_*p.x()+sinus_*p.y()-cosinus_*t.x()-sinus_*t.y()+t.x(),
sinus_*p.x()-cosinus_*p.y()-sinus_*t.x()+cosinus_*t.y()+t.y());
}
Vector_2 transform(const Vector_2 &p) const
{
return Vector_2(
cosinus_*p.x()+sinus_*p.y()-cosinus_*t.x()-sinus_*t.y()+t.x(),
sinus_*p.x()-cosinus_*p.y()-sinus_*t.x()+cosinus_*t.y()+t.y());
}
Direction_2 transform(const Direction_2 &d) const
{
return transform(d.vector()).direction();
}
Aff_transformation_2 operator*(const Aff_t_base &t) const
{
return t.compose(*this);
}
Aff_transformation_2 compose(const Translation &tr) const
{
return Aff_transformation_2(cosinus_, sinus_, t13()+tr.translationvector_.x(),
sinus_, -cosinus_, t23()+tr.translationvector_.y());
}
Aff_transformation_2 compose(const Scaling &s) const
{
return Aff_transformation_2(s.scalefactor_ * cosinus_,
s.scalefactor_ * sinus_,
s.scalefactor_ * t13(),
s.scalefactor_ * sinus_,
-s.scalefactor_ * cosinus_,
s.scalefactor_ * t23());
}
Aff_transformation_2 compose(const Transformation &tr) const
{
return Aff_transformation_2(
tr.t11*cosinus_+tr.t12*sinus_,
tr.t11*sinus_-tr.t12*cosinus_,
tr.t11*t13()+tr.t12*t23()+tr.t13,
tr.t21*cosinus_+tr.t22*sinus_,
tr.t21*sinus_-tr.t22*cosinus_,
tr.t21*t13()+tr.t22*t23()+tr.t23);
}
Aff_transformation_2 compose(const Rotation &r) const
{
return Aff_transformation_2(
r.cosinus_*cosinus_-r.sinus_*sinus_,
r.cosinus_*sinus_+r.sinus_*cosinus_,
r.cosinus_*t13()
-r.sinus_*t23(),
r.sinus_*cosinus_+r.cosinus_*sinus_,
r.sinus_*sinus_-r.cosinus_*cosinus_,
r.sinus_*t13()
+r.cosinus_*t23());
}
Aff_transformation_2 compose(const Reflection &r) const
{
return Aff_transformation_2(
cosinus_*r.cosinus_+sinus_*r.sinus_,
r.cosinus_*sinus_-r.sinus_*cosinus_,
r.cosinus_*(t13()-r.t.x()) + r.sinus_*(t23()-r.t.y())+r.t.x(),
r.sinus_*cosinus_ - r.cosinus_*sinus_,
r.sinus_*sinus_+r.cosinus_*cosinus_,
r.sinus_*(t13()-r.t.x()) -r.cosinus_*(t23()-r.t.y())+r.t.y());
}
Aff_transformation_2 inverse() const
{
return Aff_transformation_2(cartesian(0,0), cartesian(0,1), cartesian(0,2),
cartesian(1,0), cartesian(1,1), cartesian(1,2));
}
bool is_even() const
{
return true;
}
FT cartesian(int i, int j) const
{
switch (i)
{
case 0: switch (j)
{
case 0: return cosinus_;
case 1: return sinus_;
default: return FT(0);
}
case 1: switch (j)
{
case 0: return sinus_;
case 1: return -cosinus_;
default: return FT(0);
}
case 2: switch (j)
{
case 0: return FT(0);
case 1: return FT(0);
default: return FT(1);
}
}
return FT(0);
}
std::ostream &print(std::ostream &os) const
{
os << "Aff_transformationC2(" << sinus_ << ", " << cosinus_ << "; "<< t <<")";
return os;
}
//convevience functions for composition
FT t13()const
{
return FT(-cosinus_*t.x()-sinus_*t.y()+t.x());
}
FT t23()const
{
return FT(-sinus_*t.x()+cosinus_*t.y()+t.y());
}
private:
Vector_2 t;
FT sinus_, cosinus_;
};
} //namespace CGAL
#endif // CGAL_CARTESIAN_REFLECTION_REP_2_H

View File

@ -36,6 +36,7 @@ class Rotation_repC2: public Aff_transformation_rep_baseC2<R>
friend class Aff_transformation_repC2<R>;
friend class Translation_repC2<R>;
friend class Scaling_repC2<R>;
friend class Reflection_repC2<R>;
public:
typedef Aff_transformation_rep_baseC2<R> Aff_t_base;
@ -48,6 +49,7 @@ public:
typedef Translation_repC2<R> Translation;
typedef Rotation_repC2<R> Rotation;
typedef Scaling_repC2<R> Scaling;
typedef Reflection_repC2<R> Reflection;
Rotation_repC2() {}
@ -126,6 +128,17 @@ public:
t.scalefactor_*cosinus_);
}
Aff_transformation_2 compose(const Reflection &r) const
{
return Aff_transformation_2(
r.cosinus_*cosinus_+r.sinus_*sinus_,
-r.cosinus_*sinus_+r.sinus_*cosinus_,
r.t13(),
r.sinus_*cosinus_-r.cosinus_*sinus_,
-r.sinus_*sinus_-r.cosinus_*cosinus_
, r.t23());
}
Aff_transformation_2 compose(const Transformation &t) const
{
return Aff_transformation_2(cosinus_*t.t11 + sinus_*t.t12,
@ -135,7 +148,6 @@ public:
-sinus_*t.t21 + cosinus_*t.t22,
t.t23);
}
bool is_even() const
{
return true;

View File

@ -34,6 +34,7 @@ class Scaling_repC2: public Aff_transformation_rep_baseC2<R>
friend class Aff_transformation_repC2<R>;
friend class Translation_repC2<R>;
friend class Rotation_repC2<R>;
friend class Reflection_repC2<R>;
public:
typedef Aff_transformation_rep_baseC2<R> Aff_t_base;
@ -45,6 +46,7 @@ public:
typedef Aff_transformation_repC2<R> Transformation;
typedef Translation_repC2<R> Translation;
typedef Rotation_repC2<R> Rotation;
typedef Reflection_repC2<R> Reflection;
typedef Scaling_repC2<R> Scaling;
Scaling_repC2()
@ -96,6 +98,12 @@ public:
scalefactor_ * t.cosinus_);
}
Aff_transformation_2 compose(const Reflection &r) const
{
return Aff_transformation_2(scalefactor_*r.cosinus_, scalefactor_*r.sinus_,-r.cosinus_*r.t.x()-r.sinus_*r.t.y()+r.t.x(),
scalefactor_*r.sinus_, -scalefactor_*r.cosinus_, -r.sinus_*r.t.x()+r.cosinus_*r.t.y()-r.t.y());
}
Aff_transformation_2 compose(const Scaling &t) const
{
return Aff_transformation_2(SCALING, scalefactor_*t.scalefactor_);

View File

@ -36,6 +36,7 @@ class Translation_repC2 : public Aff_transformation_rep_baseC2<R>
friend class Aff_transformation_repC2<R>;
friend class Rotation_repC2<R>;
friend class Scaling_repC2<R>;
friend class Reflection_repC2<R>;
public:
typedef typename R::FT FT;
@ -43,6 +44,7 @@ public:
typedef Aff_transformation_repC2<R> Transformation;
typedef Translation_repC2<R> Translation;
typedef Rotation_repC2<R> Rotation;
typedef Reflection_repC2<R> Reflection;
typedef Scaling_repC2<R> Scaling;
typedef typename Aff_t_base::Point_2 Point_2;
typedef typename Aff_t_base::Vector_2 Vector_2;
@ -114,6 +116,14 @@ public:
+ t.t22*translationvector_.y()
+ t.t23);
}
Aff_transformation_2 compose(const Reflection &r) const
{
return Aff_transformation_2(r.cosinus_, r.sinus_,
r.cosinus_*(translationvector_.x()-r.t.x())+r.sinus_*(translationvector_.y() - r.t.y()) +r.t.x(),
r.sinus_, -r.cosinus_,
r.sinus_*(translationvector_.x()-r.t.x())-r.cosinus_*(translationvector_.y() - r.t.y())+r.t.y());
}
Aff_transformation_2 inverse() const
{

View File

@ -453,14 +453,12 @@ class Reflection_repH2 : public Aff_transformation_rep_baseH2<R>
virtual Direction_2
transform(const Direction_2 & d) const
{ return transform( Vector_2(d) ).direction(); }
{ return transform( d.vector() ).direction(); }
virtual Aff_transformationH2<R>
inverse() const
{
return Aff_transformationH2<R>(
static_cast< Aff_transformation_rep_baseH2<R>* >
( const_cast< Reflection_repH2<R>*> (this) ) );
return Aff_transformationH2<R>(REFLECTION, l);
}
virtual bool

View File

@ -40,6 +40,7 @@ therefore do not appear in the constructors.
\sa `Rotation`
\sa `Scaling`
\sa `Translation`
\sa `Reflection`
\sa `rational_rotation_approximation_grp`
\cgalHeading{Example}
@ -129,6 +130,12 @@ Aff_transformation_2(const Scaling,
const Kernel::RT &s,
const Kernel::RT &hw = RT(1));
/*!
introduces a reflection by a line `l`.
*/
Aff_transformation_2(const Reflection,
const Line_2<Kernel>& l);
/*!
introduces a general affine transformation in the
\f$3 \times 3\f$ matrix form

View File

@ -121,7 +121,7 @@ _test_cls_aff_transformation_2(const R& )
CGAL::Aff_transformation_2<R> xrefl(-n4, n0, n0,
n0, n4, n0,
n4 );
CGAL::Aff_transformation_2<R> gat4( gat3);
CGAL::Aff_transformation_2<R> gat5( n7, n9,
@ -556,6 +556,7 @@ _test_cls_aff_transformation_2(const R& )
assert( FT( ident.hm(2,1) ) / FT( ident.hm(2,2) ) == FTzero );
assert( FT( ident.hm(2,2) ) / FT( ident.hm(2,2) ) == FTone );
// samples
// cartesian == m
assert( gat1.cartesian(1,2) == gat1.m(1,2) );
@ -582,13 +583,74 @@ _test_cls_aff_transformation_2(const R& )
assert( ident.homogeneous(1,2) == ident.hm(1,2) );
assert( gscale.homogeneous(1,1) == gscale.hm(1,1) );
//tests for reflection
CGAL::Aff_transformation_2<R> refl(CGAL::REFLECTION, CGAL::Line_2<R>(
CGAL::Point_2<R>(1,3),
CGAL::Point_2<R>(2,1)));
CGAL::Point_2<R> p(4,2);
assert(p.transform(refl) == CGAL::Point_2<R>(0,0));
//with translation
CGAL::Aff_transformation_2<R> trans(CGAL::TRANSLATION, CGAL::Vector_2<R>(1,-2));
CGAL::Aff_transformation_2<R> comp1(refl*trans),
comp2(trans*refl);
p1 = p.transform(trans);
p1 = p1.transform(refl);
assert(p1 == CGAL::Point_2<R>(1,-2));
assert(p1 == p.transform(comp1) || nonexact);
p1 = p.transform(refl);
p1 = p1.transform(trans);
assert(p1 == p.transform(comp2));
//with scaling
CGAL::Aff_transformation_2<R> scal(CGAL::SCALING, 2);
comp1 = refl*scal;
comp2 = scal*refl;
p1 = p.transform(scal);
p1 = p1.transform(refl);
assert(p1 == p.transform(comp1));
p1 = p.transform(refl);
p1 = p1.transform(scal);
assert(p1 == p.transform(comp2));
//with rotation
CGAL::Aff_transformation_2<R> rot(CGAL::ROTATION, 1, 0);
comp1 = refl*rot;
comp2 = rot*refl;
p1 = p.transform(rot);
p1 = p1.transform(refl);
assert(p1 == p.transform(comp1));
p1 = p.transform(refl);
p1 = p1.transform(rot);
assert(p1 == p.transform(comp2));
//with reflection
CGAL::Aff_transformation_2<R> refl2(CGAL::REFLECTION, CGAL::Line_2<R>(
CGAL::Point_2<R>(0,0),
CGAL::Point_2<R>(1,1)));
comp1 = refl*refl2;
comp2 = refl2*refl;
p1 = p.transform(refl2);
p1 = p1.transform(refl);
assert(p1 == p.transform(comp1));
p1 = p.transform(refl);
p1 = p1.transform(refl2);
assert(p1 == p.transform(comp2));
//with transformation
CGAL::Aff_transformation_2<R> afft(1,2,3,4,5,6);
comp1 = refl*afft;
comp2 = afft*refl;
p1 = p.transform(afft);
p1 = p1.transform(refl);
assert(p1 == p.transform(comp1));
p1 = p.transform(refl);
p1 = p1.transform(afft);
assert(p1 == p.transform(comp2));
//equality
CGAL::Aff_transformation_2<R> a2(0,1,0,1),
a3(0,1,0,1), a4(0,0,1,1);
assert(a2 == a3);
assert(a3 != a4);
std::cout << "done" << std::endl;
return true;
}

View File

@ -95,16 +95,19 @@ operator>>(std::istream &is, Polygon_2<Traits_P,Container_P>& p)
int n = 0; // number of vertices
is >> n;
typename Traits_P::Point_2 point;
if (is) {
p.erase(p.vertices_begin(),p.vertices_end());
for (int i=0; i<n; i++) {
if(is >> point){
p.push_back(point);
}
p.erase(p.vertices_begin(),p.vertices_end());
for (int i=0; i<n; i++) {
if(is >> point){
p.push_back(point);
}
else
{
return is;
}
}
}
return is;
}