From 3485ce1a8a7aa6122d52073eab91cd6259f7de89 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sun, 11 Sep 2022 12:11:53 +0300 Subject: [PATCH] Fixed trimming and avoided using deprecated code. --- .../ArrangementPainterOstream.cpp | 448 ++++++++---------- .../include/CGAL/Arr_conic_traits_2.h | 54 ++- .../Conic_x_monotone_arc_2.h | 48 +- 3 files changed, 247 insertions(+), 303 deletions(-) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp index 5ab229da8a8..814820208ff 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementPainterOstream.cpp @@ -15,57 +15,48 @@ #include -namespace CGAL -{ -namespace Qt -{ +namespace CGAL { +namespace Qt { -// Instantiation of Arr_segment_traits_2 +// Specialization of `ArrangementPainterOstream` for the segment traits. template ArrangementPainterOstream>& -ArrangementPainterOstream>::operator<<( - const X_monotone_curve_2& curve) -{ +ArrangementPainterOstream>:: +operator<<(const X_monotone_curve_2& curve) { const Point_2& p1 = curve.source(); const Point_2& p2 = curve.target(); Segment_2 seg(p1, p2); // skip segments outside our view QRectF seg_bb = this->convert(seg.bbox()); - if ( - this->clippingRect.isValid() && !this->clippingRect.intersects(seg_bb) && - (!seg.is_horizontal() && !seg.is_vertical())) - { return *this; } + if (this->clippingRect.isValid() && + ! this->clippingRect.intersects(seg_bb) && + ! seg.is_horizontal() && ! seg.is_vertical()) + return *this; this->painterOstream << seg; return *this; } -// Instantiation of Arr_polyline_traits_2 - +// Specialization of `ArrangementPainterOstream` for the polyline traits. template ArrangementPainterOstream>& ArrangementPainterOstream>:: -operator<<(const X_monotone_curve_2& curve) -{ +operator<<(const X_monotone_curve_2& curve) { int cnt = 0; - for (typename X_monotone_curve_2::Subcurve_const_iterator it = - curve.subcurves_begin(); - it != curve.subcurves_end(); ++it) - { - cnt++; + for (auto it = curve.subcurves_begin(); it != curve.subcurves_end(); ++it) { + ++cnt; this->painterOstream << *it; } return *this; } -// Instantiation of Arr_conic_traits_2 -template -auto ArrangementPainterOstream>::visibleParts(X_monotone_curve_2 curve) - -> std::vector -{ +// Specialization of `ArrangementPainterOstream` for the conic traits. +template +auto ArrangementPainterOstream +>:: +visibleParts(X_monotone_curve_2 curve) -> std::vector { // see if we intersect the bottom edge of the viewport Point_2 bottomLeft = this->convert(this->clippingRect.bottomLeft()); Point_2 bottomRight = this->convert(this->clippingRect.bottomRight()); @@ -101,18 +92,16 @@ auto ArrangementPainterOstream rightEndpt.x()) { std::swap(leftEndpt, rightEndpt); } + if (leftEndpt.x() > rightEndpt.x()) std::swap(leftEndpt, rightEndpt); QPointF qendpt1 = this->convert(leftEndpt); QPointF qendpt2 = this->convert(rightEndpt); std::list pointList; - for (unsigned int i = 0; i < intersections.size(); ++i) - { + for (unsigned int i = 0; i < intersections.size(); ++i) { CGAL::Object o = intersections[i]; std::pair pair; - if (CGAL::assign(pair, o)) - { + if (CGAL::assign(pair, o)) { Point_2 pt = pair.first; pointList.push_back(pt); } @@ -120,41 +109,36 @@ auto ArrangementPainterOstreamclippingRect.contains(qendpt1); bool includeRightEndpoint = this->clippingRect.contains(qendpt2); - if (includeLeftEndpoint) { pointList.push_front(leftEndpt); } + if (includeLeftEndpoint) pointList.push_front(leftEndpt); - if (includeRightEndpoint) { pointList.push_back(rightEndpt); } + if (includeRightEndpoint) pointList.push_back(rightEndpt); // TODO: make ArrangementPainterOstream take traits object - Traits traits; - Construct_x_monotone_subcurve_2 construct_x_monotone_subcurve_2{ - &traits}; + auto trim = traits.trim_2_object(); std::vector clippings; - typename std::list::iterator pointListItr = pointList.begin(); - for (unsigned int i = 0; i < pointList.size(); i += 2) - { - typename Traits::Point_2 p1 = *pointListItr++; - typename Traits::Point_2 p2 = *pointListItr++; - X_monotone_curve_2 subcurve = - construct_x_monotone_subcurve_2(curve, p1, p2); - clippings.push_back(subcurve); + auto it = pointList.begin(); + for (unsigned int i = 0; i < pointList.size(); i += 2) { + typename Traits::Point_2 p1 = *it++; + typename Traits::Point_2 p2 = *it++; + auto xcv = trim(curve, p1, p2); + clippings.push_back(xcv); } return clippings; } -template -void ArrangementPainterOstream< - CGAL::Arr_conic_traits_2>:: - filterIntersectionPoints(std::vector& res) -{ +// +template +void ArrangementPainterOstream +>:: +filterIntersectionPoints(std::vector& res) { std::vector> tmp; // filter out the non-intersection point results - for (unsigned int i = 0; i < res.size(); ++i) - { + for (unsigned int i = 0; i < res.size(); ++i) { CGAL::Object obj = res[i]; std::pair pair; - if (CGAL::assign(pair, obj)) { tmp.push_back(pair); } + if (CGAL::assign(pair, obj)) tmp.push_back(pair); } res.clear(); @@ -163,84 +147,76 @@ void ArrangementPainterOstream< std::sort(tmp.begin(), tmp.end(), compare_intersection_point_result); // box up the sorted elements - for (unsigned int i = 0; i < tmp.size(); ++i) - { + for (unsigned int i = 0; i < tmp.size(); ++i) { std::pair pair = tmp[i]; CGAL::Object o = CGAL::make_object(pair); res.push_back(o); } } -template -ArrangementPainterOstream< - CGAL::Arr_conic_traits_2>& -ArrangementPainterOstream>::operator<<(const X_monotone_curve_2& curve) -{ +// +template +ArrangementPainterOstream +>& +ArrangementPainterOstream +>:: +operator<<(const X_monotone_curve_2& curve) { CGAL::Bbox_2 bb = traits.construct_bbox_2_object()(curve); QRectF qbb = this->convert(bb); // quick cull - if (this->clippingRect.isValid() && !this->clippingRect.intersects(qbb)) - { return *this; } + if (this->clippingRect.isValid() && ! this->clippingRect.intersects(qbb)) + return *this; // get number of segments - // QGraphicsView* view = this->scene->views().first(); - // auto pmin = view->mapFromScene(bb.xmin(), bb.ymin()); - // auto pmax = view->mapFromScene(bb.xmax(), bb.ymax()); - // std::cout << "extreme: " - // << pmin.x() << ", " << pmin.y() << "," - // << pmax.x() << ", " << pmax.y() << std::endl; - // // can be negitive due to rotation trasnformation - // size_t n = static_cast(std::abs(xmax - xmin)); - // if (n == 0) { return *this; } - double error = 1; + QGraphicsView* view = this->scene->views().first(); + auto pmin = view->mapFromScene(bb.xmin(), bb.ymin()); + auto pmax = view->mapFromScene(bb.xmax(), bb.ymax()); + double world_xdiff = std::abs(bb.xmax() - bb.xmin()); + double screen_xdiff = std::abs(pmax.x() - pmin.x()); + double error = world_xdiff / screen_xdiff; auto paint_curve = [&](auto&& curve_) { using Approximate_point_2 = typename Traits::Approximate_point_2; - std::vector app_pts; - // app_pts.reserve(n + 1); - // curve_.polyline_approximation(n, std::back_inserter(app_pts)); + std::vector points; auto aprox = traits.approximate_2_object(); - aprox(curve_, error, std::back_inserter(app_pts)); - auto p_curr = app_pts.begin(); - auto end_pts = app_pts.end(); + aprox(curve_, error, std::back_inserter(points)); + auto p_curr = points.begin(); + auto end_pts = points.end(); auto p_next = p_curr + 1; do { QPointF p1(p_curr->x(), p_curr->y()); QPointF p2(p_next->x(), p_next->y()); this->qp->drawLine(p1, p2); - p_curr++; - p_next++; + ++p_curr; + ++p_next; } while (p_next != end_pts); }; if (this->clippingRect.isValid()) { - std::vector visibleParts; - if (this->clippingRect.contains(qbb)) - visibleParts.push_back(curve); - else - visibleParts = this->visibleParts(curve); - for (auto& visiblePart : visibleParts) paint_curve(visiblePart); + if (this->clippingRect.contains(qbb)) { + paint_curve(curve); + return *this; + } + std::vector parts; + parts = this->visibleParts(curve); + for (auto& part : parts) paint_curve(part); + return *this; } - else { - // draw the whole curve - paint_curve(curve); - } - // paint_curve(curve); + // draw the whole curve + paint_curve(curve); return *this; } -// Instantiation of Arr_Bezier_traits_2 -template < - typename RatKernel, typename AlgKernel, typename NtTraits, - typename BoundingTraits> +// Specialization of `ArrangementPainterOstream` for the Bezier traits. +template std::vector> -ArrangementPainterOstream>::getPoints(const X_monotone_curve_2& curve) -{ +ArrangementPainterOstream +>:: +getPoints(const X_monotone_curve_2& curve) { std::pair param_range = curve.parameter_range(); auto&& supporting_curve = curve.supporting_curve(); @@ -256,12 +232,13 @@ ArrangementPainterOstream -auto ArrangementPainterOstream>::operator<<(const X_monotone_curve_2& curve) +// +template +auto ArrangementPainterOstream +>:: +operator<<(const X_monotone_curve_2& curve) -> ArrangementPainterOstream& { auto sampled_points = this->getPoints(curve); @@ -276,57 +253,45 @@ auto ArrangementPainterOstream ArrangementPainterOstream>& -ArrangementPainterOstream>::operator<<( - const X_monotone_curve_2& curve) -{ - if (curve.is_segment()) - { +ArrangementPainterOstream>:: +operator<<(const X_monotone_curve_2& curve) { + if (curve.is_segment()) { Segment_2 seg = curve.segment(); // skip segments outside our view QRectF seg_bb = this->convert(seg.bbox()); - if ( - this->clippingRect.isValid() && - !this->clippingRect.intersects(seg_bb) && + if (this->clippingRect.isValid() && + ! this->clippingRect.intersects(seg_bb) && (!seg.is_horizontal() && !seg.is_vertical())) - { return *this; } + return *this; this->painterOstream << seg; } - else if (curve.is_ray()) - { + else if (curve.is_ray()) { Ray_2 ray = curve.ray(); QLineF qseg = this->convert(ray); - if (qseg.isNull()) - { // it's out of view - return *this; - } + if (qseg.isNull()) return *this; // it's out of view Segment_2 seg = this->convert(qseg); this->painterOstream << seg; } - else // curve.is_line( ) - { + else { + // curve.is_line( ) Line_2 line = curve.line(); QLineF qseg = this->convert(line); - if (qseg.isNull()) - { // it's out of view - return *this; - } + if (qseg.isNull()) return *this; // it's out of view Segment_2 seg = this->convert(qseg); this->painterOstream << seg; } return *this; } -// Instantiation of Arr_algebraic_segment_traits_2 +// Specialization of `ArrangementPainterOstream` for the algebraic traits. template -static bool lies_on_border( - const ArrangementPainterOstream* apo, const QPointF& point) -{ +static bool lies_on_border(const ArrangementPainterOstream* apo, + const QPointF& point) { QGraphicsView* view = apo->getScene()->views().first(); qreal width = view->width(); qreal height = view->height(); @@ -335,26 +300,27 @@ static bool lies_on_border( std::abs(point.y() - height) < tol || point.y() < tol; } +// template -void ArrangementPainterOstream< - CGAL::Arr_algebraic_segment_traits_2>::remapFacadePainter() -{ - this->qp->setTransform(this->getPointsListMapping()); -} +void +ArrangementPainterOstream>:: +remapFacadePainter() +{ this->qp->setTransform(this->getPointsListMapping()); } +// template -QTransform ArrangementPainterOstream< - CGAL::Arr_algebraic_segment_traits_2>::getPointsListMapping() -{ +QTransform +ArrangementPainterOstream>:: +getPointsListMapping() { auto worldTransform = this->qp->transform(); return this->getPointsListMapping(worldTransform); } +// template QTransform ArrangementPainterOstream>:: - getPointsListMapping(const QTransform& worldTransform) -{ +getPointsListMapping(const QTransform& worldTransform) { auto view = this->getView(); QRectF viewport = this->viewportRect(); @@ -377,11 +343,11 @@ ArrangementPainterOstream>:: return QTransform{m11, m12, m21, m22, dx, dy}; } +// template -auto ArrangementPainterOstream>::getPointsList(const X_monotone_curve_2& curve) - -> std::vector -{ +auto ArrangementPainterOstream +>:: +getPointsList(const X_monotone_curve_2& curve) -> std::vector { typedef Curve_renderer_facade Facade; typedef std::pair Coord_2; typedef std::vector Coord_vec_2; @@ -391,11 +357,11 @@ auto ArrangementPainterOstream ArrangementPainterOstream>& ArrangementPainterOstream>:: -operator<<(const X_monotone_curve_2& curve) -{ +operator<<(const X_monotone_curve_2& curve) { this->qp->save(); this->remapFacadePainter(); this->paintCurve(curve); @@ -403,20 +369,19 @@ operator<<(const X_monotone_curve_2& curve) return *this; } +// template -void ArrangementPainterOstream>::paintCurve(const X_monotone_curve_2& curve) -{ +void ArrangementPainterOstream +>:: +paintCurve(const X_monotone_curve_2& curve) { std::vector points = this->getPointsList(curve); - for (auto& vec : points) - { + for (auto& vec : points) { auto vit = vec.begin(); QPainterPath path; QPointF qpt(vit->first, vit->second); path.moveTo(qpt); - for (auto& vit : vec) - { + for (auto& vit : vec) { QPointF qpt_new = QPointF(vit.first, vit.second); if (lies_on_border(this, qpt) && lies_on_border(this, qpt_new)) path.moveTo(qpt_new); @@ -428,10 +393,10 @@ void ArrangementPainterOstream -void ArrangementPainterOstream< - CGAL::Arr_algebraic_segment_traits_2>::setupFacade() -{ +void ArrangementPainterOstream +>::setupFacade() { typedef Curve_renderer_facade Facade; QGraphicsView* view = this->getView(); QRectF viewport = this->viewportRect(); @@ -439,18 +404,16 @@ void ArrangementPainterOstream< Facade::setup(bbox, view->width(), view->height()); } -// Instantiation of Arr_rational_function_traits_2 - -template +// Specialization of `ArrangementPainterOstream` for Arr_rational_function_traits_2 +template constexpr const T& clamp(const T& v, const T& lo, const T& hi) -{ - return (v < lo) ? lo : (hi < v) ? hi : v; -} +{ return (v < lo) ? lo : (hi < v) ? hi : v; } +// template -auto ArrangementPainterOstream>::operator<<(const X_monotone_curve_2& curve) -> Self& -{ +auto ArrangementPainterOstream +>:: +operator<<(const X_monotone_curve_2& curve) -> Self& { QPainterPath painterPath; const QRectF viewport = this->viewportRect(); // overshoot so that the slope would be more accurate @@ -464,8 +427,7 @@ auto ArrangementPainterOstream max_y || y < min_y) - { + if (y > max_y || y < min_y) { double x_ = x; double y_ = clamp(y, min_y, max_y); @@ -473,8 +435,8 @@ auto ArrangementPainterOstream -auto ArrangementPainterOstream>::getPointsList(const X_monotone_curve_2& curve) - -> std::vector -{ +auto ArrangementPainterOstream +>:: +getPointsList(const X_monotone_curve_2& curve) -> std::vector { std::vector points_list; Coord_vec_2* cur_list = nullptr; @@ -527,15 +486,13 @@ auto ArrangementPainterOstream max_y || y < min_y) - { + if (y > max_y || y < min_y) { double x_ = x; double y_ = clamp(y, min_y, max_y); - if (!disconnected) - cur_list->push_back({x_, y_}); - else if ( - (last_y == min_y && y_ == max_y) || (last_y == max_y && y_ == min_y)) + if (!disconnected) cur_list->push_back({x_, y_}); + else if ((last_y == min_y && y_ == max_y) || + (last_y == max_y && y_ == min_y)) { cur_list->push_back({last_x, last_y}); cur_list->push_back({x_, y_}); @@ -545,10 +502,8 @@ auto ArrangementPainterOstreampush_back({last_x, last_y}); @@ -563,12 +518,12 @@ auto ArrangementPainterOstream template -void ArrangementPainterOstream< - CGAL::Arr_rational_function_traits_2>:: - sample_points(const X_monotone_curve_2& curve, Lambda&& lambda) -{ +void ArrangementPainterOstream +>:: +sample_points(const X_monotone_curve_2& curve, Lambda&& lambda) { // TODO: cache maximum and minimal points for each curve, and include them // in the sampled points const QRectF viewport = this->viewportRect(); @@ -578,80 +533,63 @@ void ArrangementPainterOstream< auto&& numer = curve._f.numer(); auto&& denom = curve._f.denom(); - auto eval_at = [&](auto&& x) { - return numer.evaluate(x) / denom.evaluate(x); - }; + auto eval_at = [&](auto&& x) { return numer.evaluate(x) / denom.evaluate(x); }; - if ( // be conservative and prefer this branch to avoid zero division - curve.left_parameter_space_in_x() == ARR_INTERIOR && - curve.left_x().to_interval().second >= min_x) + // be conservative and prefer this branch to avoid zero division + if (curve.left_parameter_space_in_x() == ARR_INTERIOR && + curve.left_x().to_interval().second >= min_x) { min_x = curve.left_x().to_interval().second; - switch (curve.left_parameter_space_in_y()) - { - case ARR_INTERIOR: { - auto left_pt = curve.left().to_double(); - lambda(min_x, left_pt.second); - break; - } - case ARR_TOP_BOUNDARY: { - lambda(min_x, std::numeric_limits::infinity()); - break; - } - case ARR_BOTTOM_BOUNDARY: { - lambda(min_x, -std::numeric_limits::infinity()); - break; - } - default: { - CGAL_error(); - } + switch (curve.left_parameter_space_in_y()) { + case ARR_INTERIOR: { + auto left_pt = curve.left().to_double(); + lambda(min_x, left_pt.second); + break; + } + case ARR_TOP_BOUNDARY: { + lambda(min_x, std::numeric_limits::infinity()); + break; + } + case ARR_BOTTOM_BOUNDARY: { + lambda(min_x, -std::numeric_limits::infinity()); + break; + } + default: { + CGAL_error(); + } } } - else if ( - curve.right_parameter_space_in_x() != ARR_INTERIOR || - min_x < curve.right_x().to_interval().first) - { + else if (curve.right_parameter_space_in_x() != ARR_INTERIOR || + min_x < curve.right_x().to_interval().first) lambda(min_x, CGAL::to_double(eval_at(Rational{min_x}))); - } - else // outside of viewport - { - return; - } + else return; // outside of viewport std::pair last_pt; - if ( // be conservative and prefer this branch to avoid zero division - curve.right_parameter_space_in_x() == ARR_INTERIOR && - curve.right_x().to_interval().first <= max_x) + // be conservative and prefer this branch to avoid zero division + if (curve.right_parameter_space_in_x() == ARR_INTERIOR && + curve.right_x().to_interval().first <= max_x) { max_x = curve.right_x().to_interval().first; - switch (curve.right_parameter_space_in_y()) - { - case ARR_INTERIOR: { - last_pt = {max_x, curve.right().to_double().second}; - break; - } - case ARR_TOP_BOUNDARY: { - last_pt = {max_x, std::numeric_limits::infinity()}; - break; - } - case ARR_BOTTOM_BOUNDARY: { - last_pt = {max_x, -std::numeric_limits::infinity()}; - break; - } - default: { - CGAL_error(); - } + switch (curve.right_parameter_space_in_y()) { + case ARR_INTERIOR: { + last_pt = {max_x, curve.right().to_double().second}; + break; + } + case ARR_TOP_BOUNDARY: { + last_pt = {max_x, std::numeric_limits::infinity()}; + break; + } + case ARR_BOTTOM_BOUNDARY: { + last_pt = {max_x, -std::numeric_limits::infinity()}; + break; + } + default: { CGAL_error(); } } } else if (max_x > min_x) - { last_pt = {max_x, CGAL::to_double(eval_at(Rational{max_x}))}; - } - else // outside of viewport - { - return; - } + else return; // outside of viewport static constexpr int dx_pixel = 1; static constexpr int min_num_points = 20; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index 40c48687b61..3681776bd62 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -2885,39 +2885,43 @@ public: * direction of the arc. */ X_monotone_curve_2 trim(const X_monotone_curve_2& xcv, - const Point_2& ps, - const Point_2& pt) const { + const Point_2& ps, const Point_2& pt) const { // Make sure that both ps and pt lie on the arc. CGAL_precondition(m_traits.contains_point(xcv, ps) && m_traits.contains_point(xcv, pt)); - // Make sure that the endpoints conform with the direction of the arc. - X_monotone_curve_2 res_xcv = xcv; - auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object(); - if (! ((xcv.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT) && - (cmp_xy(ps, pt) == SMALLER)) || - (xcv.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT) && - (cmp_xy(ps, pt) == LARGER)))) - { - // We are allowed to change the direction only in case of a segment. - CGAL_assertion(xcv.orientation() == COLLINEAR); - res_xcv.flip_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT); - } + X_monotone_curve_2 res_xcv = xcv; // make a copy of the current arc - // Make a copy of the current arc and assign its endpoints. auto eq = m_traits.m_alg_kernel->equal_2_object(); - if (! eq(ps, xcv.source())) { - res_xcv.set_source(ps); + auto set_source = [&](const Point_2 ps)->void { + if (! eq(ps, xcv.source())) { + res_xcv.set_source(ps); + if (! ps.is_generating_conic(xcv.id())) + res_xcv.source().set_generating_conic(xcv.id()); + } + }; + auto set_target = [&](const Point_2 pt)->void { + if (! eq(pt, xcv.target())) { + res_xcv.set_target(pt); + if (! pt.is_generating_conic(xcv.id())) + res_xcv.target().set_generating_conic(xcv.id()); + } + }; - if (! ps.is_generating_conic(xcv.id())) - res_xcv.source().set_generating_conic(xcv.id()); + // Make sure that the endpoints conform with the direction of the arc. + auto cmp_xy = m_traits.m_alg_kernel->compare_xy_2_object(); + auto res = cmp_xy(ps, pt); + CGAL_assertion(res != EQUAL); + if ((xcv.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT) && + (res == LARGER)) || + (! xcv.test_flag(X_monotone_curve_2::IS_DIRECTED_RIGHT) && + (res == SMALLER))) { + set_source(pt); + set_target(ps); } - - if (! eq(pt, xcv.target())) { - res_xcv.set_target(pt); - - if (! pt.is_generating_conic(xcv.id())) - res_xcv.target().set_generating_conic(xcv.id()); + else { + set_source(ps); + set_target(pt); } return res_xcv; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index 122da7f7380..6d2bf119bb9 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -695,32 +695,34 @@ public: // Make sure that the endpoints conform with the direction of the arc. Alg_kernel alg_kernel; - Self res_xcv = xcv; - auto cmp_xy = alg_kernel.compare_xy_2_object(); - if (! ((xcv.test_flag(Self::IS_DIRECTED_RIGHT) && - (cmp_xy(ps, pt) == SMALLER)) || - (xcv.test_flag(Self::IS_DIRECTED_RIGHT) && - (cmp_xy(ps, pt) == LARGER)))) - { - // We are allowed to change the direction only in case of a segment. - CGAL_assertion(xcv.orientation() == COLLINEAR); - res_xcv.flip_flag(Self::IS_DIRECTED_RIGHT); - } - - // Make a copy of the current arc and assign its endpoints. + Self res_xcv = xcv; // make a copy of the current arc auto eq = alg_kernel.equal_2_object(); - if (! eq(ps, xcv.source())) { - res_xcv.set_source(ps); + auto set_source = [&](const Point_2 ps)->void { + if (! eq(ps, xcv.source())) { + res_xcv.set_source(ps); + if (! ps.is_generating_conic(xcv.id())) + res_xcv.source().set_generating_conic(xcv.id()); + } + }; + auto set_target = [&](const Point_2 pt)->void { + if (! eq(pt, xcv.target())) { + res_xcv.set_target(pt); + if (! pt.is_generating_conic(xcv.id())) + res_xcv.target().set_generating_conic(xcv.id()); + } + }; - if (! ps.is_generating_conic(xcv.id())) - res_xcv.source().set_generating_conic(xcv.id()); + auto cmp_xy = alg_kernel.compare_xy_2_object(); + auto res = cmp_xy(ps, pt); + CGAL_assertion(res != EQUAL); + if ((xcv.test_flag(Self::IS_DIRECTED_RIGHT) && (res == LARGER)) || + (! xcv.test_flag(Self::IS_DIRECTED_RIGHT) && (res == SMALLER))) { + set_source(pt); + set_target(ps); } - - if (! eq(pt, xcv.target())) { - res_xcv.set_target(pt); - - if (! pt.is_generating_conic(xcv.id())) - res_xcv.target().set_generating_conic(xcv.id()); + else { + set_source(ps); + set_target(pt); } return res_xcv;