conic_arc_2.h
来自「CGAL is a collaborative effort of severa」· C头文件 代码 · 共 2,200 行 · 第 1/5 页
H
2,200 行
xs); found_two_intersection_points = (n_xs == 2); if (! found_two_intersection_points) // The arc is invalid: return; _source = Point_2 (xs[0], -(a*xs[0] + c) / CoNT(b)); _target = Point_2 (xs[1], -(a*xs[1] + c) / CoNT(b)); // Get the conic points whose x-coordinate are in the middle of the // two endpoints. CoNT x_mid = (xs[0] + xs[1]) / 2; CoNT ys[2]; int n_ys; n_ys = _conic_get_y_coordinates (x_mid, ys); CGAL_precondition(n_ys > 0); if (CGAL_NTS compare (CoNT(a)*x_mid + CoNT(b)*ys[0] + CoNT(c), 0) == LARGER) { pmid = Point_2 (x_mid, ys[0]); } else { CGAL_assertion(CGAL_NTS compare (CoNT(a)*x_mid + CoNT(b)*ys[1] + CoNT(c), 0) == LARGER); pmid = Point_2 (x_mid, ys[1]); } } else { CGAL_precondition(CGAL_NTS compare(a, 0) != EQUAL); // Find the intersection of the vertical line x = -c / a: CoNT _x = CoNT(-c) / CoNT(a); CoNT ys[2]; int n_ys; n_ys = _conic_get_y_coordinates (_x, ys); found_two_intersection_points = (n_ys == 2); if (! found_two_intersection_points) // The arc is invalid: return; _source = Point_2 (_x, ys[0]); _target = Point_2 (_x, ys[1]); // Get the conic points whose y-coordinate are in the middle of the // two endpoints. CoNT y_mid = (ys[0] + ys[1]) / 2; CoNT xs[2]; int n_xs; n_xs = _conic_get_x_coordinates (y_mid, xs); CGAL_precondition(n_xs > 0); if (CGAL_NTS compare(CoNT(a)*xs[0] + CoNT(b)*y_mid + CoNT(c), 0) == LARGER) { pmid = Point_2 (xs[0], y_mid); } else { CGAL_assertion(CGAL_NTS compare (CoNT(a)*xs[1] + CoNT(b)*y_mid + CoNT(c), 0) == LARGER); pmid = Point_2 (xs[1], y_mid); } } // 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 Alg_kernel ker; typename Alg_kernel::Orientation_2 orient_f = ker.orientation_2_object(); if (orient_f(_source, pmid, _target) == LEFT_TURN) _orient = CGAL::COUNTERCLOCKWISE; else _orient = CGAL::CLOCKWISE; // Set the arc properties (no need to compute the orientation). _set (false); } /*! * Construct a conic arc which is the full conic: * C: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 * \param r,s,t,u,v,w The coefficients of the conic curve. * \pre The conic C must be an ellipse (so 4rs - t^2 > 0). */ Conic_arc_2 (const CfNT& r, const CfNT& s, const CfNT& t, const CfNT& u, const CfNT& v, const CfNT& w) : _r(r), _s(s), _t(t), _u(u), _v(v), _w(w), _hyper_P(NULL) { // Make sure the given curve is an ellipse. bool is_ellipse = (CGAL_NTS compare(4*r*s - t*t, CfNT(0)) == LARGER); CGAL_precondition(is_ellipse); if (! is_ellipse) // In this case, the arc is invalid. return; // Set the arc to be the full conic (and compute the orientation). _set_full (true); } /*! * Construct a conic arc from the given line segment. * \param seg The line segment. */ Conic_arc_2 (const Int_segment_2& seg) : _hyper_P(NULL) { // Get the coordinates of the endpoints. const Int_point_2 src = seg.source(); const Int_point_2 trg = seg.target(); const CfNT x1 = src.x(), y1 = src.y(); const CfNT x2 = trg.x(), y2 = trg.y(); _source = Point_2 (CoNT(x1),CoNT(y1)); _target = Point_2 (CoNT(x2),CoNT(y2)); // Make sure that the source and the taget are not the same. CGAL_precondition(_source != _target); // The supporting conic is r=s=t=0, and u*x + v*y + w = 0 should hold // for both the source (x1,y1) and the target (x2, y2). const CfNT _zero = 0; const CfNT _one = 1; if (CGAL_NTS compare (x1, x2) == EQUAL) { // The supporting conic is a vertical line, of the form x = CONST. _r = _zero; _s = _zero; _t = _zero; _u = _one; _v = _zero; _w = -x1; } else { // The supporting line is A*x + B*y + C = 0, where: // // A = y2 - y1, B = x1 - x2, C = x2*y1 - x1*y2 // _r = _zero; _s = _zero; _t = _zero; _u = y2 - y1; _v = x1 - x2; _w = x2*y1 - x1*y2; } // The orientation is zero in case of a linear object. _orient = CGAL::COLLINEAR; // Set the arc properties (no need to compute the orientation). _set (false); } /*! * Set a circular arc that lies on a given circle. * \param circ The supporting circle. * \param orient The orientation of the circle. * \param source The source point. * \param target The target point. * \pre The source and the target must be on the conic boundary and must * not be the same. */ Conic_arc_2 (const Int_circle_2& circ, const Orientation& orient, const Point_2& source, const Point_2& target) : _source(source), _target(target), _info(X_MON_UNDEFINED), _hyper_P(NULL) { // 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 Int_point_2 cc = circ.center(); const CfNT x0 = cc.x(), y0 = cc.y(); const CfNT R_sq = circ.squared_radius(); 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_sq - 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_sq; _orient = CGAL::CLOCKWISE; } // Make sure the conic contains the two end-points on its boundary. const bool source_on_boundary = _conic_has_on_boundary(source); CGAL_precondition(source_on_boundary); const bool target_on_boundary = _conic_has_on_boundary(target); CGAL_precondition(target_on_boundary); // Make sure that the source and the target are not the same. const bool source_not_equals_target = (source != target); CGAL_precondition(source_not_equals_target); if (! (source_on_boundary && target_on_boundary && source_not_equals_target)) { // In this case, the arc is invalid. return; } // Set the arc properties (no need to compute the orientation). _set (false); } /*! * Set a circular arc that corresponds a full circle: * \param circ The circle. */ Conic_arc_2 (const Int_circle_2& circ) : _hyper_P(NULL) { // 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 Int_point_2 cc = circ.center(); const CfNT x0 = cc.x(), y0 = cc.y(); const CfNT R_sq = circ.squared_radius(); 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_sq; _orient = CGAL::CLOCKWISE; // Set the arc to be the full conic (no need to compute the orientation). _set_full (false); } /*! * Construct a circular arc from the given three points. * \param p1 The source point of the circular arc. * \param p2 A point between p1 and p3 on the arc. * \param p3 The target point of the circular arc. * \pre The three points must not be collinear. */ Conic_arc_2 (const Int_point_2& p1, const Int_point_2& p2, const Int_point_2& p3) : _info(X_MON_UNDEFINED), _hyper_P(NULL) { // Make sure that the source and the target are not the same. const bool source_not_equals_target = (p1 != p3); CGAL_precondition(source_not_equals_target); if (!source_not_equals_target) { // In this case, the arc is invalid. return; } // Get the coordinates of the points. const CfNT x1 = p1.x(), y1 = p1.y(); const CfNT x2 = p2.x(), y2 = p2.y(); const CfNT x3 = p3.x(), y3 = p3.y(); const CfNT _zero = 0; const CfNT _two = 2; // 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. const bool points_collinear = (CGAL_NTS compare(D, _zero) == EQUAL); CGAL_precondition(!points_collinear); if (points_collinear) { // In this case, the arc is invalid. return; } // 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)); // Set the endpoints. _source = Point_2 (CoNT(x1),CoNT(y1)); _target = Point_2 (CoNT(x3),CoNT(y3)); // 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 Alg_kernel ker; typename Alg_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; // Set the arc properties (no need to compute the orientation). _set (false); } /*! * Construct a conic arc from the given five points, specified by the * points p1, p2, p3, p4 and p5. * \param p1 The source point of the given arc. * \param p2,p3,p4 Points lying on the conic arc, between p1 and p5. * \param p5 The target point of the given arc. * \pre No three points are collinear. */ Conic_arc_2 (const Int_point_2& p1, const Int_point_2& p2, const Int_point_2& p3, const Int_point_2& p4, const Int_point_2& p5) : _info(X_MON_UNDEFINED), _hyper_P(NULL) { // Make sure that the source and the target are not the same. const bool source_not_equals_target = (p1 != p5); CGAL_precondition(source_not_equals_target); if (!source_not_equals_target) { // In this case, the arc is invalid. return; } // Make sure that no three points are collinear. Int_kernel ker; typename Int_kernel::Orientation_2 orient_f = ker.orientation_2_object(); if (orient_f (p1, p2, p3) == CGAL::COLLINEAR || orient_f (p1, p2, p4) == CGAL::COLLINEAR || orient_f (p1, p2, p5) == CGAL::COLLINEAR || orient_f (p1, p3, p4) == CGAL::COLLINEAR || orient_f (p1, p3, p5) == CGAL::COLLINEAR || orient_f (p1, p4, p5) == CGAL::COLLINEAR || orient_f (p2, p3, p4) == CGAL::COLLINEAR || orient_f (p2, p3, p5) == CGAL::COLLINEAR || orient_f (p2, p4, p5) == CGAL::COLLINEAR || orient_f (p3, p4, p5) == CGAL::COLLINEAR) { // Invalid arc: return; } // Get the coordinates of the points. const CfNT x1 = p1.x(), y1 = p1.y(); const CfNT x5 = p5.x(), y5 = p5.y(); // Set a conic curve that passes through the five given point. typename Int_kernel::Conic_2 temp_conic; temp_conic.set (p1, p2, p3, p4, p5); // Get the conic coefficients. _r = temp_conic.r(); _s = temp_conic.s(); _t = temp_conic.t(); _u = temp_conic.u(); _v = temp_conic.v(); _w = temp_conic.w(); // Set the source and target points. _source = Point_2 (CoNT(x1), CoNT(y1)); _target = Point_2 (CoNT(x5), CoNT(y5)); // Determine the orientation: If one of the midpoints forms a left-turn // with the source and the target points, the orientation is positive // (going counterclockwise). // Otherwise, it is negative (going clockwise). const Orientation turn = orient_f(p1, p2, p5); bool same_turn;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?