418 lines
13 KiB
C
418 lines
13 KiB
C
|
// Copyright (c) 1999-2003 ETH Zurich (Switzerland).
|
||
|
// All rights reserved.
|
||
|
//
|
||
|
// This file is part of CGAL (www.cgal.org).
|
||
|
//
|
||
|
// $URL: https://github.com/CGAL/cgal/blob/v5.1/Bounding_volumes/include/CGAL/Min_quadrilateral_traits_2.h $
|
||
|
// $Id: Min_quadrilateral_traits_2.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 Hoffmann <hoffmann@inf.ethz.ch> and
|
||
|
// Emo Welzl <emo@inf.ethz.ch>
|
||
|
|
||
|
#ifndef CGAL_MIN_QUADRILATERAL_TRAITS_2_H
|
||
|
#define CGAL_MIN_QUADRILATERAL_TRAITS_2_H 1
|
||
|
|
||
|
#include <CGAL/license/Bounding_volumes.h>
|
||
|
|
||
|
|
||
|
#include <CGAL/basic.h>
|
||
|
#include <CGAL/Optimisation/assertions.h>
|
||
|
#include <CGAL/Point_2.h>
|
||
|
#include <CGAL/Direction_2.h>
|
||
|
#include <CGAL/Polygon_2.h>
|
||
|
#include <CGAL/intersections.h>
|
||
|
#include <CGAL/utility.h>
|
||
|
#include <functional>
|
||
|
#include <vector>
|
||
|
|
||
|
namespace CGAL {
|
||
|
|
||
|
namespace Optimisation {
|
||
|
template < class Kernel_ >
|
||
|
struct Min_rectangle_2 {
|
||
|
typedef Kernel_ Kernel;
|
||
|
typedef typename Kernel::Point_2 Point_2;
|
||
|
typedef typename Kernel::Direction_2 Direction_2;
|
||
|
|
||
|
Min_rectangle_2(const Point_2& q1,
|
||
|
const Direction_2& e,
|
||
|
const Point_2& q2,
|
||
|
const Point_2& q3,
|
||
|
const Point_2& q4)
|
||
|
: p1(q1), p2(q2), p3(q3), p4(q4), d(e)
|
||
|
{}
|
||
|
|
||
|
Point_2 p1, p2, p3, p4;
|
||
|
Direction_2 d;
|
||
|
};
|
||
|
|
||
|
template < class Kernel_ >
|
||
|
struct Min_parallelogram_2 {
|
||
|
typedef Kernel_ Kernel;
|
||
|
typedef typename Kernel::Point_2 Point_2;
|
||
|
typedef typename Kernel::Direction_2 Direction_2;
|
||
|
|
||
|
Min_parallelogram_2(const Point_2& q1, const Direction_2& e1,
|
||
|
const Point_2& q2, const Direction_2& e2,
|
||
|
const Point_2& q3, const Point_2& q4)
|
||
|
: p1(q1), p2(q2), p3(q3), p4(q4), d1(e1), d2(e2)
|
||
|
{}
|
||
|
|
||
|
Point_2 p1, p2, p3, p4;
|
||
|
Direction_2 d1, d2;
|
||
|
};
|
||
|
|
||
|
template < class Kernel >
|
||
|
std::ostream& operator<<(std::ostream& o,
|
||
|
const Min_parallelogram_2<Kernel>& p)
|
||
|
{
|
||
|
if (p.d1 == p.d2)
|
||
|
o << "Dirs equal!\n";
|
||
|
return o << "Para(\t" << p.p1 << ",\n"
|
||
|
<< p.d1 << ",\n"
|
||
|
<< p.p2 << ",\n"
|
||
|
<< p.d2 << ",\n"
|
||
|
<< p.p3 << ",\n"
|
||
|
<< p.p4 << ")";
|
||
|
}
|
||
|
} // namespace Optimisation
|
||
|
|
||
|
template < class K_ >
|
||
|
struct Min_quadrilateral_default_traits_2 {
|
||
|
// types inherited from Kernel
|
||
|
typedef K_ Kernel;
|
||
|
typedef typename Kernel::RT RT;
|
||
|
typedef typename Kernel::Point_2 Point_2;
|
||
|
typedef typename Kernel::Vector_2 Vector_2;
|
||
|
typedef typename Kernel::Direction_2 Direction_2;
|
||
|
typedef typename Kernel::Line_2 Line_2;
|
||
|
|
||
|
// predicates and constructions inherited from Kernel
|
||
|
typedef typename Kernel::Equal_2 Equal_2;
|
||
|
typedef typename Kernel::Less_xy_2 Less_xy_2;
|
||
|
typedef typename Kernel::Less_yx_2 Less_yx_2;
|
||
|
typedef typename Kernel::Has_on_negative_side_2 Has_on_negative_side_2;
|
||
|
typedef typename Kernel::Compare_angle_with_x_axis_2
|
||
|
Compare_angle_with_x_axis_2;
|
||
|
typedef typename Kernel::Construct_vector_2 Construct_vector_2;
|
||
|
typedef typename Kernel::Construct_direction_2 Construct_direction_2;
|
||
|
typedef typename Kernel::Construct_line_2 Construct_line_2;
|
||
|
typedef typename Kernel::Construct_perpendicular_vector_2
|
||
|
Construct_perpendicular_vector_2;
|
||
|
typedef typename Kernel::Construct_opposite_direction_2
|
||
|
Construct_opposite_direction_2;
|
||
|
|
||
|
// used for expensive precondition checks only:
|
||
|
typedef typename Kernel::Orientation_2 Orientation_2;
|
||
|
|
||
|
protected:
|
||
|
// used internally
|
||
|
Construct_line_2 line;
|
||
|
typename Kernel::Intersect_2 isec;
|
||
|
|
||
|
public:
|
||
|
// new types
|
||
|
typedef Optimisation::Min_rectangle_2<Kernel> Rectangle_2;
|
||
|
typedef Optimisation::Min_parallelogram_2<Kernel> Parallelogram_2;
|
||
|
typedef Triple<Point_2,Direction_2,Point_2> Strip_2;
|
||
|
|
||
|
// new predicates
|
||
|
struct Area_less_rectangle_2
|
||
|
: public CGAL::cpp98::binary_function< Rectangle_2, Rectangle_2, bool >
|
||
|
{
|
||
|
RT
|
||
|
area_numerator(const Rectangle_2& r, Cartesian_tag) const
|
||
|
{
|
||
|
return
|
||
|
(r.d.dx() * (r.p3.y() - r.p1.y()) + r.d.dy() * (r.p1.x() - r.p3.x())) *
|
||
|
(r.d.dy() * (r.p2.y() - r.p4.y()) + r.d.dx() * (r.p2.x() - r.p4.x()));
|
||
|
}
|
||
|
|
||
|
RT
|
||
|
area_denominator(const Rectangle_2& r, Cartesian_tag) const
|
||
|
{ return CGAL_NTS square(r.d.dx()) + CGAL_NTS square(r.d.dy()); }
|
||
|
|
||
|
RT
|
||
|
area_numerator(const Rectangle_2& r, Homogeneous_tag) const
|
||
|
{
|
||
|
return
|
||
|
(r.d.dx() * (r.p3.hy() * r.p1.hw() - r.p1.hy() * r.p3.hw()) +
|
||
|
r.d.dy() * (r.p1.hx() * r.p3.hw() - r.p3.hx() * r.p1.hw())) *
|
||
|
(r.d.dy() * (r.p2.hy() * r.p4.hw() - r.p4.hy() * r.p2.hw()) +
|
||
|
r.d.dx() * (r.p2.hx() * r.p4.hw() - r.p4.hx() * r.p2.hw()));
|
||
|
}
|
||
|
|
||
|
RT
|
||
|
area_denominator(const Rectangle_2& r, Homogeneous_tag) const
|
||
|
{
|
||
|
return r.p1.hw() * r.p2.hw() * r.p3.hw() * r.p4.hw() *
|
||
|
(CGAL_NTS square(r.d.dx()) + CGAL_NTS square(r.d.dy()));
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
operator()(const Rectangle_2& p, const Rectangle_2& q) const
|
||
|
{
|
||
|
typedef typename Kernel::Rep_tag Rep_tag;
|
||
|
Rep_tag tag CGAL_SUNPRO_INITIALIZE(= Rep_tag());
|
||
|
return area_numerator(p, tag) * area_denominator(q, tag) <
|
||
|
area_denominator(p, tag) * area_numerator(q, tag);
|
||
|
}
|
||
|
};
|
||
|
struct Area_less_parallelogram_2
|
||
|
: public CGAL::cpp98::binary_function< Parallelogram_2,
|
||
|
Parallelogram_2,
|
||
|
bool >
|
||
|
{
|
||
|
RT
|
||
|
area_numerator(const Parallelogram_2& r, Cartesian_tag) const
|
||
|
{
|
||
|
return
|
||
|
(r.d1.dx() * (r.p3.y() - r.p1.y()) -
|
||
|
r.d1.dy() * (r.p3.x() - r.p1.x())) *
|
||
|
(r.d2.dx() * (r.p4.y() - r.p2.y()) -
|
||
|
r.d2.dy() * (r.p4.x() - r.p2.x()));
|
||
|
}
|
||
|
|
||
|
RT
|
||
|
area_denominator(const Parallelogram_2& r, Cartesian_tag) const
|
||
|
{ return r.d1.dx() * r.d2.dy() - r.d1.dy() * r.d2.dx(); }
|
||
|
|
||
|
RT
|
||
|
area_numerator(const Parallelogram_2& r, Homogeneous_tag) const
|
||
|
{
|
||
|
return
|
||
|
(r.d1.dx() * (r.p3.hy() * r.p1.hw() - r.p1.hy() * r.p3.hw()) -
|
||
|
r.d1.dy() * (r.p3.hx() * r.p1.hw() - r.p1.hx() * r.p3.hw())) *
|
||
|
(r.d2.dx() * (r.p4.hy() * r.p2.hw() - r.p2.hy() * r.p4.hw()) -
|
||
|
r.d2.dy() * (r.p4.hx() * r.p2.hw() - r.p2.hx() * r.p4.hw()));
|
||
|
}
|
||
|
|
||
|
RT
|
||
|
area_denominator(const Parallelogram_2& r, Homogeneous_tag) const
|
||
|
{
|
||
|
return r.p1.hw() * r.p2.hw() * r.p3.hw() * r.p4.hw() *
|
||
|
(r.d1.dx() * r.d2.dy() - r.d1.dy() * r.d2.dx());
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
operator()(const Parallelogram_2& p, const Parallelogram_2& q) const
|
||
|
{
|
||
|
typedef typename Kernel::Rep_tag Rep_tag;
|
||
|
Rep_tag tag CGAL_SUNPRO_INITIALIZE(= Rep_tag());
|
||
|
return area_numerator(p, tag) * area_denominator(q, tag) <
|
||
|
area_denominator(p, tag) * area_numerator(q, tag);
|
||
|
}
|
||
|
};
|
||
|
struct Width_less_strip_2
|
||
|
: public CGAL::cpp98::binary_function< Strip_2, Strip_2, bool >
|
||
|
{
|
||
|
RT
|
||
|
width_numerator(const Strip_2& r, Cartesian_tag) const
|
||
|
{
|
||
|
return CGAL_NTS square(
|
||
|
r.second.dx() * (r.third.y() - r.first.y()) +
|
||
|
r.second.dy() * (r.first.x() - r.third.x()));
|
||
|
}
|
||
|
|
||
|
RT
|
||
|
width_denominator(const Strip_2& r, Cartesian_tag) const
|
||
|
{ return CGAL_NTS square(r.second.dx()) + CGAL_NTS square(r.second.dy()); }
|
||
|
|
||
|
RT
|
||
|
width_numerator(const Strip_2& r, Homogeneous_tag) const
|
||
|
{
|
||
|
return CGAL_NTS square(
|
||
|
r.second.dx() *
|
||
|
(r.third.hy() * r.first.hw() - r.first.hy() * r.third.hw()) +
|
||
|
r.second.dy() *
|
||
|
(r.first.hx() * r.third.hw() - r.third.hx() * r.first.hw()));
|
||
|
}
|
||
|
|
||
|
RT
|
||
|
width_denominator(const Strip_2& r, Homogeneous_tag) const {
|
||
|
return CGAL_NTS square(r.first.hw() * r.third.hw()) *
|
||
|
(CGAL_NTS square(r.second.dx()) + CGAL_NTS square(r.second.dy()));
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
operator()(const Strip_2& p, const Strip_2& q) const
|
||
|
{
|
||
|
typedef typename Kernel::Rep_tag Rep_tag;
|
||
|
Rep_tag tag CGAL_SUNPRO_INITIALIZE(= Rep_tag());
|
||
|
return width_numerator(p, tag) * width_denominator(q, tag) <
|
||
|
width_denominator(p, tag) * width_numerator(q, tag);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// new constructions
|
||
|
struct Construct_vector_from_direction_2
|
||
|
: public CGAL::cpp98::unary_function<Direction_2,Vector_2>
|
||
|
{
|
||
|
Vector_2 operator()(const Direction_2& d) const { return d.vector(); }
|
||
|
};
|
||
|
struct Construct_rectangle_2
|
||
|
{
|
||
|
Rectangle_2
|
||
|
operator()(const Point_2& p1,
|
||
|
const Direction_2& d1,
|
||
|
const Point_2& p2,
|
||
|
const Point_2& p3,
|
||
|
const Point_2& p4) const
|
||
|
{ return Rectangle_2(p1, d1, p2, p3, p4); }
|
||
|
};
|
||
|
template < class OutputIterator >
|
||
|
OutputIterator
|
||
|
copy_rectangle_vertices_2(const Rectangle_2& r, OutputIterator o) const
|
||
|
{
|
||
|
return copy_parallelogram_vertices_2(
|
||
|
construct_parallelogram_2_object()(
|
||
|
r.p1,
|
||
|
r.d,
|
||
|
r.p2,
|
||
|
construct_direction_2_object()(
|
||
|
construct_perpendicular_vector_2_object()(
|
||
|
construct_vector_from_direction_2_object()(r.d),
|
||
|
CLOCKWISE)),
|
||
|
r.p3,
|
||
|
r.p4),
|
||
|
o);
|
||
|
}
|
||
|
struct Construct_parallelogram_2
|
||
|
{
|
||
|
Parallelogram_2
|
||
|
operator()(const Point_2& p1,
|
||
|
const Direction_2& d1,
|
||
|
const Point_2& p2,
|
||
|
const Direction_2& d2,
|
||
|
const Point_2& p3,
|
||
|
const Point_2& p4) const
|
||
|
{ return Parallelogram_2(p1, d1, p2, d2, p3, p4); }
|
||
|
};
|
||
|
template < class OutputIterator >
|
||
|
OutputIterator
|
||
|
copy_parallelogram_vertices_2(
|
||
|
const Parallelogram_2& r, OutputIterator o) const
|
||
|
{
|
||
|
Point_2 tmp;
|
||
|
Line_2 tmpl;
|
||
|
Object tmpo;
|
||
|
|
||
|
tmpo = isec(line(r.p1, r.d1), line(r.p2, r.d2));
|
||
|
if (assign(tmp, tmpo)) {
|
||
|
*o++ = tmp;
|
||
|
} else {
|
||
|
CGAL_optimisation_assertion_code(bool test1 =)
|
||
|
assign(tmpl, tmpo);
|
||
|
CGAL_optimisation_assertion(test1);
|
||
|
*o++ = r.p1;
|
||
|
}
|
||
|
tmpo = isec(line(r.p3, r.d1), line(r.p2, r.d2));
|
||
|
if (assign(tmp, tmpo)) {
|
||
|
*o++ = tmp;
|
||
|
} else {
|
||
|
CGAL_optimisation_assertion_code(bool test1 =)
|
||
|
assign(tmpl, tmpo);
|
||
|
CGAL_optimisation_assertion(test1);
|
||
|
*o++ = r.p2;
|
||
|
}
|
||
|
tmpo = isec(line(r.p3, r.d1), line(r.p4, r.d2));
|
||
|
if (assign(tmp, tmpo)) {
|
||
|
*o++ = tmp;
|
||
|
} else {
|
||
|
CGAL_optimisation_assertion_code(bool test1 =)
|
||
|
assign(tmpl, tmpo);
|
||
|
CGAL_optimisation_assertion(test1);
|
||
|
*o++ = r.p3;
|
||
|
}
|
||
|
tmpo = isec(line(r.p1, r.d1), line(r.p4, r.d2));
|
||
|
if (assign(tmp, tmpo)) {
|
||
|
*o++ = tmp;
|
||
|
} else {
|
||
|
CGAL_optimisation_assertion_code(bool test1 =)
|
||
|
assign(tmpl, tmpo);
|
||
|
CGAL_optimisation_assertion(test1);
|
||
|
*o++ = r.p3;
|
||
|
}
|
||
|
return o;
|
||
|
}
|
||
|
struct Construct_strip_2
|
||
|
{
|
||
|
Strip_2
|
||
|
operator()(const Point_2& p1,
|
||
|
const Direction_2& d1,
|
||
|
const Point_2& p2) const
|
||
|
{ return Strip_2(p1, d1, p2); }
|
||
|
};
|
||
|
template < class OutputIterator >
|
||
|
OutputIterator
|
||
|
copy_strip_lines_2(const Strip_2& r, OutputIterator o) const
|
||
|
{
|
||
|
*o++ = line(r.first, r.second);
|
||
|
*o++ = line(r.third, r.second);
|
||
|
return o;
|
||
|
}
|
||
|
|
||
|
Equal_2 equal_2_object() const { return Equal_2(); }
|
||
|
Less_xy_2 less_xy_2_object() const { return Less_xy_2(); }
|
||
|
Less_yx_2 less_yx_2_object() const { return Less_yx_2(); }
|
||
|
|
||
|
Has_on_negative_side_2 has_on_negative_side_2_object() const
|
||
|
{ return Has_on_negative_side_2(); }
|
||
|
|
||
|
Compare_angle_with_x_axis_2 compare_angle_with_x_axis_2_object() const
|
||
|
{ return Compare_angle_with_x_axis_2(); }
|
||
|
|
||
|
Area_less_rectangle_2 area_less_rectangle_2_object() const
|
||
|
{ return Area_less_rectangle_2(); }
|
||
|
|
||
|
Area_less_parallelogram_2 area_less_parallelogram_2_object() const
|
||
|
{ return Area_less_parallelogram_2(); }
|
||
|
|
||
|
Width_less_strip_2 width_less_strip_2_object() const
|
||
|
{ return Width_less_strip_2(); }
|
||
|
|
||
|
Construct_vector_2 construct_vector_2_object() const
|
||
|
{ return Construct_vector_2(); }
|
||
|
|
||
|
Construct_vector_from_direction_2
|
||
|
construct_vector_from_direction_2_object() const
|
||
|
{ return Construct_vector_from_direction_2(); }
|
||
|
|
||
|
Construct_perpendicular_vector_2
|
||
|
construct_perpendicular_vector_2_object() const
|
||
|
{ return Construct_perpendicular_vector_2(); }
|
||
|
|
||
|
Construct_direction_2 construct_direction_2_object() const
|
||
|
{ return Construct_direction_2(); }
|
||
|
|
||
|
Construct_opposite_direction_2
|
||
|
construct_opposite_direction_2_object() const
|
||
|
{ return Construct_opposite_direction_2(); }
|
||
|
|
||
|
Construct_line_2 construct_line_2_object() const
|
||
|
{ return Construct_line_2(); }
|
||
|
|
||
|
Construct_rectangle_2 construct_rectangle_2_object() const
|
||
|
{ return Construct_rectangle_2(); }
|
||
|
|
||
|
Construct_parallelogram_2 construct_parallelogram_2_object() const
|
||
|
{ return Construct_parallelogram_2(); }
|
||
|
|
||
|
Construct_strip_2 construct_strip_2_object() const
|
||
|
{ return Construct_strip_2(); }
|
||
|
|
||
|
Orientation_2 orientation_2_object() const { return Orientation_2(); }
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
} //namespace CGAL
|
||
|
|
||
|
#endif // ! (CGAL_MIN_QUADRILATERAL_TRAITS_2_H)
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
// ** EOF
|
||
|
// ----------------------------------------------------------------------------
|