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 + -
显示快捷键?