hyper_segment_2.h

来自「CGAL is a collaborative effort of severa」· C头文件 代码 · 共 731 行 · 第 1/2 页

H
731
字号
// Copyright (c) 1999  Tel-Aviv University (Israel).// All rights reserved.//// This file is part of CGAL (www.cgal.org); you may redistribute it under// the terms of the Q Public License version 1.0.// See the file LICENSE.QPL distributed with CGAL.//// 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.//// $Source: /CVSROOT/CGAL/Packages/Arrangement/include/CGAL/Arrangement_2/Hyper_segment_2.h,v $// $Revision: 1.5 $ $Date: 2004/07/19 14:39:24 $// $Name:  $//// Author(s)     : Ron Wein <wein@post.tau.ac.il>#ifndef CGAL_HYPER_SEGMENT_2_H#define CGAL_HYPER_SEGMENT_2_H#include <CGAL/basic.h>#include <CGAL/Cartesian.h>#include <CGAL/Bbox_2.h>#include <fstream>class CGAL::Window_stream;CGAL_BEGIN_NAMESPACE/*! * Representation of a segment of a simplified canonical hyperbola,  * given by the equation: *    a*x^2 + b*y2 + c*x + d = 0 * * We consider the upper part of the hyprobola (y > 0), thus the following * holds: *    y = sqrt(A*x^2 + B*x + C) * * The end-points of the hyperbolic segment are defined by x_min and x_max.  */template <class Kernel_>class Hyper_segment_2{protected:  typedef Hyper_segment_2<Kernel_>      Self;        public:  typedef Kernel_                       Kernel;  typedef typename Kernel::FT           NT;      typedef typename Kernel::Point_2      Point_2;private:  bool          _is_seg;      // Is this hyper-segment actaully a line segment.  NT            _A;           // The coefficients of the equation of   NT            _B;           // the underlying canonical hyperbola:  NT            _C;           //   y = sqrt (A*x^2 + B*x + C)  Point_2       _source;      // The hyperbolic segment source.  Point_2       _target;      // The hyperbolic segment target. public:  /*!   * Default constructor.   */  Hyper_segment_2 () :    _is_seg(true)  {}  /*!   * Construct a hyperbolic segment which lies on the canocial hyperbola:   *    a*x^2 + b*y2 + c*x + d = 0   * And bounded by x-min and x-max.   * \param a The coefficient of x^2 in the equation of the hyperbola.   * \param b The coefficient of y^2 in the equation of the hyperbola.   * \param c The coefficient of x in the equation of the hyperbola.   * \param d The free coefficient in the equation of the hyperbola.   * \param x_min The x-coordinate of the leftmost end-point of the segment.   * \param x_max The x-coordinate of the righttmost end-point of the segment.   * \pre (a > 0) and (b < 0) -- to make sure this is indeed a hyperbola.   *      Furthermore, x_max > x_min.   */  Hyper_segment_2 (const NT& a, const NT& b, const NT& c, const NT& d,		   const NT& x_min, const NT& x_max) :    _is_seg(false)  {    CGAL_precondition_code (static const NT  _zero = 0;);    CGAL_precondition(_compare (a, _zero) == LARGER);    CGAL_precondition(_compare (b, _zero) == SMALLER);    CGAL_precondition(_compare (x_min, x_max) == SMALLER);    // Set the normalized coefficients of the hyperbola.    _A = -(a/b);    _B = -(c/b);    _C = -(d/b);    // Set the end-points.    bool  source_ok = _get_point_at_x (x_min, _source);    bool  target_ok = _get_point_at_x (x_max, _target);    if (! (source_ok && target_ok))    {      CGAL_assertion (source_ok);      CGAL_assertion (target_ok);    }    // Check that both end-points lie on the same hyperbolic branch.    /*    CGAL_assertion_code (      NT                xs[2];      int               n = _solve_quadratic_equation (_A, _B, _C,						       xs[0], xs[1]);      Comparison_result res1;      Comparison_result res2;      int               i;      CGAL_assertion (n == 2);      for (i = 0; i < 2; i++)      {	res1 = _compare (x_min, xs[i]);	res2 = _compare (x_max, xs[i]);	CGAL_assertion (res1 == EQUAL || res2 == EQUAL || res1 == res2);      }    );    */  }  /*!   * Construct a degenerate hyperbolic segment defined by a line segment.   * \param ps The source point of the segment.   * \param pt The target point of the segment.   * \pre The segment is not vertical -- that is, x(ps) does not equal x(pt).   *      Furthermore, both points should lie above the x-axis.   */  Hyper_segment_2 (const Point_2& ps, const Point_2& pt) :    _is_seg(true)  {    // Make sure that the two points do not define a vertical segment.    Comparison_result comp_x = _compare (ps.x(), pt.x());    CGAL_precondition(comp_x != EQUAL);    // Make sure that both points are above the x-axis.    CGAL_precondition_code (static const NT  _zero = 0;);    CGAL_precondition(_compare (ps.y(), _zero) == LARGER);    CGAL_precondition(_compare (pt.y(), _zero) == LARGER);    // Find the line (y = a*x + b)  that connects the two points.    const NT  denom = ps.x() - pt.x();    const NT  a = (ps.y() - pt.y()) / denom;    const NT  b = (ps.x()*pt.y() - pt.x()*ps.y()) / denom;    // Set the underlying hyperbola to be the pair of lines:    //  y^2 = (a*x + b)^2 = (a^2)*x^2 + (2ab)*x + b^2    _A = a*a;    _B = 2*a*b;    _C = b*b;    // Set the source and target point.    if (comp_x != LARGER)    {      _source = ps;      _target = pt;    }    else    {      _source = pt;      _target = ps;    }  }  /*!   * Access the hyperblic coeffcients.   */  const NT& A () const {return (_A);}  const NT& B () const {return (_B);}  const NT& C () const {return (_C);}  /*!   * Get the source of the hyper-segment.   * \return The source point.   */  const Point_2& source () const  {    return (_source);  }  /*!   * Get the target of the hyper-segment.   * \return The target point.   */  const Point_2& target () const  {    return (_target);  }  /*!    * Check whether the hyper-segment is actually a line segment.   * \return (true) if the underlying hyperbola is actually a line segment.   */  bool is_linear () const  {    return (_is_seg);  }  /*!   * Check if the two hyper-segments are equal.   * \param seg The compares hyper-segments.   * \return (true) if seg equals (*this) or if it is its flipped version.   */  bool is_equal (const Self& seg) const  {    if (this == &seg)      return (true);    // The underlying hyperbola must be the same:    if (! _has_same_base_hyperbola(seg))      return (false);    // Compare the source and target.    if (_compare (_source.x(), seg._source.x()) &&	_compare (_target.x(), seg._target.x()))      return (true);    else if (_compare (_source.x(), seg._target.x()) &&	     _compare (_target.x(), seg._source.x()))      return (true);        return (false);  }  /*!   * Get a bounding box for the hyper-segment.   * \return A bounding box.   */  Bbox_2 bbox () const  {    // Use the source and target to find the exterme coordinates.    double  x1 = CGAL::to_double(_source.x());    double  y1 = CGAL::to_double(_source.y());    double  x2 = CGAL::to_double(_target.x());    double  y2 = CGAL::to_double(_target.y());    double  x_min, x_max;    double  y_min, y_max;    if (x1 < x2)    {      x_min = x1;      x_max = x2;    }    else    {      x_min = x2;      x_max = x1;    }    if (y1 < y2)    {      y_min = y1;      y_max = y2;    }    else    {      y_min = y2;      y_max = y1;    }    // Try to check if any extreme points are contained in our segment.    if (_A != 0)    {      // The x-coordinate of the extreme point is given by:      double  x_ext = CGAL::to_double(-_B / (2*_A));      if (x_min < x_ext && x_ext < x_max)      {	// The y-value at the extreme point is given by:	double   y_ext = (CGAL::to_double(_A)*x_ext + 			  CGAL::to_double(_B))*x_ext + CGAL::to_double(_C);	if (y_ext > 0)	  y_ext = CGAL::sqrt(y_ext);	else	  y_ext = 0;	if (y_ext < y_min)	  y_min = y_ext;	else if (y_ext > y_max)	  y_max = y_ext;      }    }    // Return the resulting bounding box.    return (Bbox_2 (x_min, y_min, x_max, y_max));  }  /*!   * Check if the given point is in the x-range of the hyper-segment.   * \param q The query point.   * \return (true) if q is in the x-range of the hyper-segment.   */  bool point_is_in_x_range (const Point_2& q) const  {    Comparison_result res1 = _compare (q.x(), _source.x());    Comparison_result res2 = _compare (q.x(), _target.x());        return ((res1 == EQUAL) || (res2 == EQUAL) || (res1 != res2));  }  /*!   * Check the position of the query point with respect to the hyper-segment.   * \param q The query point.   * \return SMALLER if q lies under the hyper-segment;   *         LARGER if it lies above the hyper-segment;   *         EQUAL if q lies on the hyper-segment.   * \pre q is in the x-range of the hyper-segment.   */  Comparison_result point_position (const Point_2& q) const  {    CGAL_precondition(point_is_in_x_range (q));     // Substitute q's x-coordinate into the equation of the hyperbola and    // compare the result.    return (_compare (q.y(),		      CGAL::sqrt(_A*q.x()*q.x() + _B*q.x() + _C)));  }  /*!   * Return a flipped hyper-segment.   * \return The flipped hyper-segment.   */  Self flip () const  {    Self     flipped (*this);    flipped._source = _target;    flipped._target = _source;    return (flipped);  }  /*!   * Compare the y-coordinates of two hyper-segments at a given x-coordinate.   * \param seg The other segment.   * \param q The point (a placeholder for the x-coordinate).   * \return SMALLER if (*this) is below seg at q;   *         LARGER if it is above seg at q;   *         EQUAL if the two hyper-segment intersect at this x-coordinate.   * \pre q is in the x-range of both hyper-segments.   */  Comparison_result compare_y_at_x (const Self& seg,				    const Point_2& q) const  {    CGAL_precondition(this->point_is_in_x_range(q));    CGAL_precondition(seg.point_is_in_x_range(q));      // Compare y1 = A1*x^2 + B1*x + C1     //     and y2 = A2*x^2 + B2*x + C2:    return (_compare (_A*q.x()*q.x() + _B*q.x() + _C,		      seg._A*q.x()*q.x() + seg._B*q.x() + seg._C));  }  /*!

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?