conic_arc_2_core.h

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

H
2,297
字号
      }      if (_r == _zero && arc._r != _zero)      {	n_ys = arc._y_coordinates_of_intersections_with (*this,							 ys);      }      else      {	n_ys = _y_coordinates_of_intersections_with (arc,						     ys);      }          // Perform the pairing process od the x and y coordinates.      n_points = _pair_intersection_points (arc,					    xs, n_xs,					    ys, n_ys,					    ipts);#ifdef CGAL_CONIC_ARC_USE_CACHING      if (inter_list_P != NULL &&	  (_info & DEGREE_MASK) != DEGREE_1)      {	inter.n_points = n_points;		for (k = 0; k < n_points; k++)	  inter.ps[k] = ipts[k];	inter_list_P->push_front(inter);      }    #endif // (of ifdef CGAL_CONIC_ARC_USE_CACHING)    }    // Go over all intersection points between the two base conics and return    // only those located on both arcs.    int      n = 0;    int      i;    for (i = 0; i < n_points; i++)    {      // Check for an exact point.      if (contains_point(ipts[i]) &&	  arc.contains_point(ipts[i]))      {	ps[n] = ipts[i];	n++;      }    }    return (n);  }  /*!   * Check whether the two arcs overlap, and if so - compute the overlapping   * portions.   * \param arc The other conic arc.   * \param ovlp_arc The output overlapping sub-arc.   *                 This area should be allocated to the size of 2.   * \return The number of overlapping sub-arcs.   */  int overlaps (const Self& arc,		Self* ovlp_arcs) const  {    // Two arcs can overlap only if their base conics are identical.    if (! this->has_same_base_conic (arc))      return (0);    // If the two arcs are completely equal, return one of them as the    // overlapping arc.    int       orient1 = _orient;    int       orient2 = arc._orient;    bool      same_or = (orient1 == orient2);    bool      identical = false;    if (orient1 == 0)    {      // That mean both arcs are really segments, so they are identical      // if their endpoints are the same.      if ((_source.equals(arc._source) && _target.equals(arc._target)) ||	  (_source.equals(arc._target) && _target.equals(arc._source)))	identical = true;    }    else    {      // If those are really curves of degree 2, than the points curves      // are identical only if their source and target are the same and the      // orientation is the same, or vice-versa if the orientation is opposite.      if ((same_or && 	   _source.equals(arc._source) && _target.equals(arc._target)) ||	  (!same_or && 	   _source.equals(arc._target) && _target.equals(arc._source)))	identical = true;    }    if (identical)    {      ovlp_arcs[0] = arc;      return (1);    }    // In case one of the arcs is a full conic, return the whole other conic.    if (arc.is_full_conic())    {      ovlp_arcs[0] = *this;      return (1);    }    else if (is_full_conic())    {      ovlp_arcs[0] = arc;      return (1);    }    // In case the other arc has an opposite orientation, switch its source    // and target (notice that in case of segments, when the orientation is 0,    // we make sure the two segments have the same direction).    const Point_2 *arc_sourceP;    const Point_2 *arc_targetP;    if (orient1 == 0)      orient1 = (_source.compare_lex_xy(_target) 		 == LARGER) ? 1 : -1;    if (orient2 == 0)      orient2 = (arc._source.compare_lex_xy(arc._target) 		 == LARGER) ? 1 : -1;    // Check the overlap cases:    if (orient1 == orient2)    {      arc_sourceP = &(arc._source);      arc_targetP = &(arc._target);    }    else    {      arc_sourceP = &(arc._target);      arc_targetP = &(arc._source);    }    if (_is_strictly_between_endpoints(*arc_sourceP))    {      if (_is_strictly_between_endpoints(*arc_targetP))      {	// Check the next special case (when there are 2 overlapping arcs):	if (arc._is_strictly_between_endpoints(_source) &&            arc._is_strictly_between_endpoints(_target))	{	  ovlp_arcs[0] = Self(*this,_source, *arc_targetP);	  ovlp_arcs[1] = Self(*this, *arc_sourceP, _target);	  return (2);	}	// Case 1 - *this:     +----------->             //            arc:       +=====>	ovlp_arcs[0] = Self(*this, *arc_sourceP,*arc_targetP);	return (1);      }      else      {	// Case 2 - *this:     +----------->             //            arc:               +=====>	ovlp_arcs[0] = Self(*this, *arc_sourceP, _target);	return (1);      }    }    else if (_is_strictly_between_endpoints(*arc_targetP))    {      // Case 3 - *this:     +----------->           //            arc:   +=====>      ovlp_arcs[0] = Self(*this, _source, *arc_targetP);      return (1);    }    else if (arc._is_between_endpoints(_source) &&             arc._is_between_endpoints(_target) &&	     (arc._is_strictly_between_endpoints(_source) ||              arc._is_strictly_between_endpoints(_target)))    {      // Case 4 - *this:     +----------->           //            arc:   +================>      ovlp_arcs[0] = *this;      return (1);    }        // If we reached here, there are no overlaps:    return (0);  }	  /*!   * Check whether the arc is facing up or facing down.   * \return LARGER if the arcs is facing up, or SMALLER if it is facing down.   *         If the arc is a line segment, EQUAL is returned.   */  Comparison_result facing () const  {    if ((_info & FACING_MASK) == 0)      return (EQUAL);    else if ((_info & FACING_UP) != 0)      return (LARGER);    else      return (SMALLER);  } protected:  /*!   * Set the properties of a conic arc (for the usage of the constructors).   * \param comp_orient Should we compute the orientation of the given curve.   * \param circ_data_P The center and radius of the base circle   *                    (only if the arc lies on a circle).   */  void _set (const bool& comp_orient,	     Circular_arc_data *circ_data_P = NULL)  {    // Initialize the information bits.    _info = X_MON_UNDEFINED;    // Set the orientation of conic arc.    typename Cartesian<CfNT>::Conic_2   temp_conic (_r, _s, _t, _u, _v, _w);    if (comp_orient)    {      // Compute the orientation.      _orient = temp_conic.orientation();    }    else if (_orient != temp_conic.orientation())    {      // If the computed orientation does not match the current value,      // multiply all conic coefficients by -1 (negate the curve).      _r = - _r;      _s = - _s;      _t = - _t;      _u = - _u;      _v = - _v;      _w = - _w;    }    // Find the degree and make sure the conic is not invalid.    const CfNT _zero = 0;    int        deg;     if (_r != _zero || _s != _zero || _t != _zero)    {      // In case one of the coefficients of x^2,y^2 or xy is not zero, the      // degree is 2.      deg = 2;      CGAL_assertion (_orient != CGAL::COLLINEAR);    }    else if (_u != _zero || _v != _zero)    {      // In case of a line - the degree is 1.      deg = 1;      _orient = CGAL::COLLINEAR;    }    else    {      // Empty conic!      deg = 0;    }    CGAL_precondition(deg > 0);    // Store the degree information.    _info = _info | deg;    // In case the base conic is a hyperbola, build the hyperbolic data    // (this happens when (4rs - t^2) < 0).    if (deg == 2 && 4*_r*_s < _t*_t)    {      _info = _info | IS_HYPERBOLA;      _build_hyperbolic_arc_data ();    }    // In case the base conic is a circle, set the circular data.    else if (deg == 2 && circ_data_P != NULL)    {      _info = _info | IS_CIRCLE;      _data.circ_P = circ_data_P;    }    else    {      _data.hyper_P = NULL;    }    // In case of a non-degenerate parabola or a hyperbola, make sure     // the arc is not infinite.    if (deg == 2 && 4*_r*_s <= _t*_t)    {      CGAL_precondition_code(      const CoNT       _two = 2;      const Point_2    p_mid ((_source.x() + _target.x()) / _two,                              (_source.y() + _target.y()) / _two);      Point_2          ps[2];      bool  finite_at_x = (get_points_at_x(p_mid, ps) > 0);      bool  finite_at_y = (get_points_at_y(p_mid, ps) > 0);      );      CGAL_precondition(finite_at_x && finite_at_y);    }    // If we reached here, the conic arc is legal: Get a new id for the conic.    _conic_id = _get_new_conic_id();    _source.set_generating_conics (_conic_id);    _target.set_generating_conics (_conic_id);    // Check whether the conic is x-monotone.    if (is_x_monotone())    {      _info = (_info & ~X_MON_UNDEFINED) | X_MONOTONE;      // In case the conic is od degree 2, determine where is it facing.      if ((_info & DEGREE_MASK) == DEGREE_2)	_set_facing();    }    else    {      _info = (_info & ~X_MON_UNDEFINED);    }    return;  }  /*!   * Set the properties of a conic arc that is really a full curve   * (that is, an ellipse).   * \param comp_orient Should we compute the orientation of the given curve.   * \param circ_data_P The center and radius of the base circle   *                    (only if the arc is a full circle).   */  void _set_full (const bool& comp_orient,		  Circular_arc_data *circ_data_P = NULL)  {    // Initialize the information bits.    _info = 0;    // Set the orientation of conic arc.    typename Cartesian<CfNT>::Conic_2   temp_conic (_r, _s, _t, _u, _v, _w);    if (comp_orient)    {      // Compute the orientation.      _orient = temp_conic.orientation();    }    else if (_orient != temp_conic.orientation())    {      // If the computed orientation does not match the current value,      // multiply all conic coefficients by -1 (negate the curve).      _r = - _r;      _s = - _s;      _t = - _t;      _u = - _u;      _v = - _v;      _w = - _w;    }    // Make sure the conic is a non-degenerate ellipse:    // The coefficients should satisfy (4rs - t^2) > 0.    CGAL_precondition(4*_r*_s > _t*_t);    // Set the information: a full conic, which is obvoiusly not x-monotone.    _info = DEGREE_2 | FULL_CONIC;    // Check if the conic is really a circle.    if (circ_data_P != NULL)    {      _info = _info | IS_CIRCLE;      _data.circ_P = circ_data_P;    }    else    {      _data.hyper_P = NULL;    }    // Assign one of the vertical tangency points as both the source and    // the target of the conic arc.    Point_2    vpts[2];    int        n_vpts;    if (circ_data_P != NULL)    {      vpts[0] = Point_2 (CoNT(circ_data_P->x0 + circ_data_P->r), 			 CoNT(circ_data_P->y0));    }    else    {      n_vpts = _conic_vertical_tangency_points (vpts);      CGAL_assertion(n_vpts > 0);      CGAL_assertion(_conic_has_on_boundary(vpts[0]));    }    // If we reached here, the conic arc is legal: Get a new id for the conic.    _conic_id = _get_new_conic_id();    _source.set_generating_conics (_conic_id);    _target.set_generating_conics (_conic_id);    return;  }  /*!   * Build the data for hyperbolic arc, contaning the characterization of the   * hyperbolic branch the arc is placed on.   */  void _build_hyperbolic_arc_data ()  {    // Let phi be the rotation angle of the conic from its canonic form.    // We can write:    //     //                          t    //  sin(2*phi) = -----------------------    //                sqrt((r - s)^2 + t^2)    //     //                        r - s    //  cos(2*phi) = -----------------------    //                sqrt((r - s)^2 + t^2)    //    const int   or_fact = (_orient == CGAL::CLOCKWISE) ? -1 : 1;    const CoNT  r = or_fact * CoNT(_r);    const CoNT  s = or_fact * CoNT(_s);    const CoNT  t = or_fact * CoNT(_t);    const CoNT  cos_2phi = (r - s) / CGAL::sqrt((r-s)*(r-s) + t*t);    const CoNT  _zero = 0;    const CoNT  _one = 1;    const CoNT  _two = 2;    CoNT        sin_phi;    CoNT        cos_phi;    // Calculate sin(phi) and cos(phi) according to the half-angle formulae:    //     //  sin(phi)^2 = 0.5 * (1 - cos(2*phi))    //  cos(phi)^2 = 0.5 * (1 + cos(2*phi))    if (t == _zero)    {      // sin(2*phi) == 0, so phi = 0 or phi = PI/2      if (cos_2phi > _zero)      {	// phi = 0.	sin_phi = _zero;	cos_phi = _one;      }      else      {	// phi = PI.	sin_phi = _zero;	cos_phi = -_one;      }    }    else if (t > _zero)    {      // sin(2*phi) > 0 so 0 < phi < PI/2.      sin_phi = CGAL::sqrt((_one + cos_2phi) / _two);      cos_phi = CGAL::sqrt((_one - cos_2phi) / _two);    }    else    {      // sin(2*phi) < 0 so PI/2 < phi < PI.      sin_phi = CGAL::sqrt((_one + cos_2phi) / _two);      cos_phi = -CGAL::sqrt((_one - cos_2phi) / _two);    }        // Calculate the center (x0, y0) of the conic, given by the formulae:    //

⌨️ 快捷键说明

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