// Copyright (c) 1999-2003 ETH Zurich (Switzerland). // 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 // 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: GPL-3.0+ // // // Author(s) : Michael Hoffmann and // Emo Welzl #ifndef CGAL_MIN_QUADRILATERAL_TRAITS_2_H #define CGAL_MIN_QUADRILATERAL_TRAITS_2_H 1 #include #include #include #include #include #include #include #include #include #include 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& 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 Rectangle_2; typedef Optimisation::Min_parallelogram_2 Parallelogram_2; typedef Triple 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 { 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 // ----------------------------------------------------------------------------