conic_arc_2_core.h

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

H
2,297
字号
  {    // Produce the correponding conic: if the circle centre is (x0,y0)    // and it radius is R, that its equation is:    //   x^2 + y^2 - 2*x0*x - 2*y0*y + (x0^2 + y0^2 - R^2) = 0    // Since this equation describes a curve with a negative (clockwise)     // orientation, we multiply it by -1 if necessary to obtain a positive    // (counterclockwise) orientation.    const CfNT _zero = 0;    if (orient == CGAL::COUNTERCLOCKWISE)    {      const CfNT _minus_one = -1;      const CfNT _two       = 2;      _r = _minus_one;      _s = _minus_one;      _t = _zero;      _u = _two*x0;      _v = _two*y0;      _w = R*R - x0*x0 - y0*y0;      _orient = CGAL::COUNTERCLOCKWISE;    }    else    {      const CfNT _one       = 1;      const CfNT _minus_two = -2;      _r = _one;      _s = _one;      _t = _zero;      _u = _minus_two*x0;      _v = _minus_two*y0;      _w = x0*x0 + y0*y0 - R*R;      _orient = CGAL::CLOCKWISE;    }    // Make sure the circle contains the two endpoints on its boundary.    CGAL_precondition(_conic_has_on_boundary(source));    CGAL_precondition(_conic_has_on_boundary(target));    // Make sure that the source and the taget are not the same.    CGAL_precondition(source != target);          // Prepare the auxiliary data structure.    Circular_arc_data    *circ_data_P = new Circular_arc_data;    circ_data_P->x0 = CoNT(x0);    circ_data_P->y0 = CoNT(y0);    circ_data_P->r = CoNT(R);    // Set the arc properties (no need to compute the orientation).    _set (false, circ_data_P);  }  /*!   * Set a circular arc that corresponds to the full circle:   *   C: (x - x0)^2 + (y - y0)^2 = R^2   */   Conic_arc_2 (const CfNT& x0, const CfNT& y0,	       const CfNT& R)  {    // Produce the correponding conic: if the circle centre is (x0,y0)    // and it radius is R, that its equation is:    //   x^2 + y^2 - 2*x0*x - 2*y0*y + (x0^2 + y0^2 - R^2) = 0    // Note that this equation describes a curve with a negative (clockwise)     // orientation.    const CfNT _zero = 0;    const CfNT _one       = 1;    const CfNT _minus_two = -2;    _r = _one;    _s = _one;    _t = _zero;    _u = _minus_two*x0;    _v = _minus_two*y0;    _w = x0*x0 + y0*y0 - R*R;    _orient = CGAL::CLOCKWISE;    // Prepare the auxiliary data structure.    Circular_arc_data    *circ_data_P = new Circular_arc_data;    circ_data_P->x0 = CoNT(x0);    circ_data_P->y0 = CoNT(y0);    circ_data_P->r = CoNT(R);    // Set the arc to be the full conic (no need to compute the orientation).    _set_full (false, circ_data_P);  }  /*!   * Construct a circular arc from the given three points, specified by the   * coordinates (x1,y1), (x2,y2) and (x3, y3).   * (x1,y1) is the arc source and (x3,y3) is the arc target.   * \pre The three points must not be collinear.   */  Conic_arc_2 (const CfNT& x1, const CfNT& y1,	       const CfNT& x2, const CfNT& y2,	       const CfNT& x3, const CfNT& y3,	       const bool& ) :    _source(CoNT(x1),CoNT(y1)),    _target(CoNT(x3),CoNT(y3)),    _info(X_MON_UNDEFINED)  {    const CfNT _zero = 0;    const CfNT _two  = 2;        // Make sure that the source and the taget are not the same.    CGAL_precondition(_source != _target);          // Compute the lines: A1*x + B1*y + C1 = 0,    //               and: A2*x + B2*y + C2 = 0,    // where:    const CfNT A1 = _two*(x1 - x2);    const CfNT B1 = _two*(y1 - y2);    const CfNT C1 = y2*y2 - y1*y1 + x2*x2 - x1*x1;    const CfNT A2 = _two*(x2 - x3);    const CfNT B2 = _two*(y2 - y3);    const CfNT C2 = y3*y3 - y2*y2 + x3*x3 - x2*x2;    // Compute the coordinates of the intersection point between the    // two lines, given by (Nx / D, Ny / D), where:    const CfNT Nx = B1*C2 - B2*C1;    const CfNT Ny = A2*C1 - A1*C2;    const CfNT D = A1*B2 - A2*B1;    // Make sure the three points are not collinear.    CGAL_precondition_code(    const bool points_collinear = (D == _zero);    );    CGAL_precondition(!points_collinear);    // The equation of the underlying circle is given by:    _r = D*D;    _s = D*D;    _t = _zero;    _u = -_two*D*Nx;    _v = -_two*D*Ny;    _w = Nx*Nx + Ny*Ny - ((D*x2 - Nx)*(D*x2 - Nx) + (D*y2 - Ny)*(D*y2 - Ny));    // Determine the orientation: If the mid-point forms a left-turn with    // the source and the target points, the orientation is positive (going    // counterclockwise).    // Otherwise, it is negative (going clockwise).    static Kernel                  ker;    typename Kernel::Orientation_2 orient_f = ker.orientation_2_object();    Point_2                        pmid = Point_2(CoNT(x2), CoNT(y2));        if (orient_f(_source, pmid, _target) == LEFT_TURN)      _orient = CGAL::COUNTERCLOCKWISE;    else      _orient = CGAL::CLOCKWISE;    // Prepare the auxiliary data structure.    Circular_arc_data    *circ_data_P = new Circular_arc_data;    circ_data_P->x0 = CoNT(Nx) / CoNT(D);    circ_data_P->y0 = CoNT(Ny) / CoNT(D);    circ_data_P->r =       CGAL::sqrt (CoNT((D*x2 - Nx)*(D*x2 - Nx) + (D*y2 - Ny)*(D*y2 - Ny)) /		  CoNT(D*D));    // Set the arc properties (no need to compute the orientation).    _set (false, circ_data_P);  }  /*!   * Destructor.   */  virtual ~Conic_arc_2 ()  {    if ((_info & IS_HYPERBOLA) != 0)      delete _data.hyper_P;    else if ((_info & IS_CIRCLE) != 0)      delete _data.circ_P;    _data.hyper_P = NULL;  }  /*!   * Assignment operator.   * \param arc The copied arc.   */  const Self& operator= (const Self& arc)  {    if (this == &arc)      return (*this);    // Free any existing data.    if ((_info & IS_HYPERBOLA) != 0)      delete _data.hyper_P;    else if ((_info & IS_CIRCLE) != 0)      delete _data.circ_P;    _data.hyper_P = NULL;    // Copy the arc's attributes.    _r = arc._r;    _s = arc._s;    _t = arc._t;    _u = arc._u;    _v = arc._v;    _w = arc._w;    _orient = arc._orient;    _conic_id = arc._conic_id;    _source = arc._source;    _target = arc._target;    _info = arc._info;    // Duplicate the data for hyperbolic or circular arcs.    if ((arc._info & IS_HYPERBOLA) != 0)    {      _data.hyper_P = new Hyperbolic_arc_data (*(arc._data.hyper_P));    }    else if ((arc._info & IS_CIRCLE) != 0)    {      _data.circ_P = new Circular_arc_data (*(arc._data.circ_P));    }    return (*this);  }  /*!    * Get the coefficients of the underlying conic.   */  const CfNT& r () const {return (_r);}  const CfNT& s () const {return (_s);}  const CfNT& t () const {return (_t);}  const CfNT& u () const {return (_u);}  const CfNT& v () const {return (_v);}  const CfNT& w () const {return (_w);}  /*!   * Get the arc's source.   * \return The source point.   */  const Point_2& source () const  {    return (_source);  }  /*!   * Get the arc's target.   * \return The target point.   */  const Point_2& target () const  {    return (_target);  }  /*!   * Check whether the two arcs are the same (have the same graph).   * \param arc The compared arc.   * \return (true) if the two arcs are equal.   */  bool equals (const Self& arc) const  {    // Check if (*this) and arc are really the same object:    if (this == &arc)      return (true);    // Check whether all arc features are the same.    if (_orient == arc._orient)    {      // Same orientation: The base conics must be the same and the sources      // and targets must be equal.      return (this->has_same_base_conic(arc) &&	      _source.equals(arc._source) &&	      _target.equals(arc._target));    }    else    {      // Opposite orientation: The base conics must be the same and the sources      // and targets must be flipped.      return (this->has_same_base_conic(arc) &&	      _source.equals(arc._target) &&	      _target.equals(arc._source));    }  }  /*!   * Check whether the two arcs have the same base conic.   * \param arc The compared arc.   * \return (true) if the two base conics are the same (have the same graph).   */  bool has_same_base_conic (const Self& arc) const  {    // In case the two arcs originiat from the same base conic:    if (_conic_id == arc._conic_id)      return (true);        // Check whether arc equals (*this) up to a constant factor.    const CfNT _zero = 0;    CfNT       factor1 = 1, factor2 = 1;    if (CGAL_NTS compare(_r, _zero) != EQUAL)      factor1 = _r;    else if (CGAL_NTS compare(_s, _zero) != EQUAL)      factor1 = _s;    else if (CGAL_NTS compare(_t, _zero) != EQUAL)      factor1 = _t;    else if (CGAL_NTS compare(_u, _zero) != EQUAL)      factor1 = _u;    else if (CGAL_NTS compare(_v, _zero) != EQUAL)      factor1 = _v;    else if (CGAL_NTS compare(_w, _zero) != EQUAL)      factor1 = _w;    if (CGAL_NTS compare(arc._r, _zero) != EQUAL)      factor2 = arc._r;    else if (CGAL_NTS compare(arc._s, _zero) != EQUAL)      factor2 = arc._s;    else if (CGAL_NTS compare(arc._t, _zero) != EQUAL)      factor2 = arc._t;    else if (CGAL_NTS compare(arc._u, _zero) != EQUAL)      factor2 = arc._u;    else if (CGAL_NTS compare(arc._v, _zero) != EQUAL)      factor2 = arc._v;    else if (CGAL_NTS compare(arc._w, _zero) != EQUAL)      factor2 = arc._w;    return (CGAL_NTS compare (_r * factor2, arc._r * factor1) == EQUAL && 	    CGAL_NTS compare (_s * factor2, arc._s * factor1) == EQUAL &&	    CGAL_NTS compare (_t * factor2, arc._t * factor1) == EQUAL &&	    CGAL_NTS compare (_u * factor2, arc._u * factor1) == EQUAL &&	    CGAL_NTS compare (_v * factor2, arc._v * factor1) == EQUAL &&	    CGAL_NTS compare (_w * factor2, arc._w * factor1) == EQUAL);  }  /*!   * Check whether the arc is a full conic (i.e. a non-degenerate ellipse).   * \return (true) if the arc represents a full conic.   */  bool is_full_conic () const  {    return ((_info & FULL_CONIC) != 0);  }  /*!   * Check whether the arc is a circular arc.   * \return (true) if the underlying conic curve is a circle.   */  bool is_circular() const  {    return ((_info & IS_CIRCLE) != 0);  }    /*!   * Check whether the arc is a line segment.   * \return (true) if the underlying conic curve is of degree 1.   */  bool is_segment () const  {    return ((_info & DEGREE_MASK) == 1);  }  /*!   * Check whether the arc is a vertical segment.   * \return (true) if the arc is a vertical segment.   */  bool is_vertical_segment () const  {    // A vertical segment is contained in the degenerate conic: u*x + w = 0.    const CfNT _zero = 0;    return ((_info & DEGREE_MASK) == 1 && 	    CGAL_NTS compare(_v, _zero) == EQUAL);  }  /*!   * Get a bounding box for the conic arc.   * \return The bounding box.   */  Bbox_2 bbox () const  {    // Use the source and target to initialize the exterme points.    bool   source_left =       CGAL::to_double(_source.x()) < CGAL::to_double(_target.x());    double x_min = source_left ?      CGAL::to_double(_source.x()) : CGAL::to_double(_target.x());    double x_max = source_left ?      CGAL::to_double(_target.x()) : CGAL::to_double(_source.x());    bool   source_down =       CGAL::to_double(_source.y()) < CGAL::to_double(_target.y());    double y_min = source_down ?      CGAL::to_double(_source.y()) : CGAL::to_double(_target.y());    double y_max = source_down ?      CGAL::to_double(_target.y()) : CGAL::to_double(_source.y());    // Go over the vertical tangency points and try to update the x-points.    Point_2 tps[2];    int        n_tps;    int        i;    n_tps = vertical_tangency_points (tps);    for (i = 0; i < n_tps; i++)    {      if (CGAL::to_double(tps[i].x()) < x_min)	x_min = CGAL::to_double(tps[i].x());      if (CGAL::to_double(tps[i].x()) > x_max)	x_max = CGAL::to_double(tps[i].x());    }    // Go over the horizontal tangency points and try to update the y-points.    n_tps = horizontal_tangency_points (tps);    for (i = 0; i < n_tps; i++)    {      if (CGAL::to_double(tps[i].y()) < y_min)	y_min = CGAL::to_double(tps[i].y());      if (CGAL::to_double(tps[i].y()) > y_max)	y_max = CGAL::to_double(tps[i].y());    }        // Return the resulting bounding box.    return (Bbox_2 (x_min, y_min, x_max, y_max));  }  /*!   * Check whether the given point is on the conic arc.   * \param q The query point.   * \return (true) if the arc contains the point q.   */  bool contains_point (const Point_2& q) const  {     // Check whether the conic contains the point (x,y).    if (q.is_generating_conic_id(_conic_id) ||	_conic_has_on_boundary(q))    {      // If the point is on the conic boundary, it is contained in the arc      // either if the arc is a full conic, or if it is between the two      // endpoints of the arc.            return (is_full_conic() || _is_between_endpoints(q));    }    // If the point is not on the conic boundary, it cannot be on the arc.    return (false);  }  /*!   * Calculate the vertical tangency points of the arc.   * \param vpts The vertical tangency points -- should be allocated at the    * size of 2).   * \return The number of vertical tangency points.   */  int vertical_tangency_points (Point_2* vpts) const  {    // No vertical tangency points for segments or for x-monotone curves:    if ((_info & DEGREE_MASK) < 2 ||	(_info & X_MON_UNDEFINED) == X_MONOTONE)    {      return (0);    }    // Calculate the vertical tangency points of the conic.    Point_2 ps[2];    int     n;    n = _conic_vertical_tangency_points (ps);

⌨️ 快捷键说明

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