Fixed trimming and avoided using deprecated code.

This commit is contained in:
Efi Fogel 2022-09-11 12:11:53 +03:00
parent 6f103e4de1
commit 3485ce1a8a
3 changed files with 247 additions and 303 deletions

View File

@ -15,57 +15,48 @@
#include <QGraphicsView>
namespace CGAL
{
namespace Qt
{
namespace CGAL {
namespace Qt {
// Instantiation of Arr_segment_traits_2
// Specialization of `ArrangementPainterOstream` for the segment traits.
template <typename Kernel_>
ArrangementPainterOstream<CGAL::Arr_segment_traits_2<Kernel_>>&
ArrangementPainterOstream<CGAL::Arr_segment_traits_2<Kernel_>>::operator<<(
const X_monotone_curve_2& curve)
{
ArrangementPainterOstream<CGAL::Arr_segment_traits_2<Kernel_>>::
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 <typename SegmentTraits>
ArrangementPainterOstream<CGAL::Arr_polyline_traits_2<SegmentTraits>>&
ArrangementPainterOstream<CGAL::Arr_polyline_traits_2<SegmentTraits>>::
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 <typename RatKernel, class AlgKernel, class NtTraits>
auto ArrangementPainterOstream<CGAL::Arr_conic_traits_2<
RatKernel, AlgKernel, NtTraits>>::visibleParts(X_monotone_curve_2 curve)
-> std::vector<X_monotone_curve_2>
{
// Specialization of `ArrangementPainterOstream` for the conic traits.
template <typename RatKernel, typename AlgKernel, typename NtTraits>
auto ArrangementPainterOstream
<CGAL::Arr_conic_traits_2<RatKernel, AlgKernel, NtTraits>>::
visibleParts(X_monotone_curve_2 curve) -> std::vector<X_monotone_curve_2> {
// 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<CGAL::Arr_conic_traits_2<
Point_2 leftEndpt = curve.source();
Point_2 rightEndpt = curve.target();
if (leftEndpt.x() > 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<Point_2> 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<Intersection_point_2, Multiplicity> 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 ArrangementPainterOstream<CGAL::Arr_conic_traits_2<
bool includeLeftEndpoint = this->clippingRect.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<Traits> construct_x_monotone_subcurve_2{
&traits};
auto trim = traits.trim_2_object();
std::vector<X_monotone_curve_2> clippings;
typename std::list<Point_2>::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 <typename RatKernel, class AlgKernel, class NtTraits>
void ArrangementPainterOstream<
CGAL::Arr_conic_traits_2<RatKernel, AlgKernel, NtTraits>>::
filterIntersectionPoints(std::vector<CGAL::Object>& res)
{
//
template <typename RatKernel, typename AlgKernel, typename NtTraits>
void ArrangementPainterOstream
<CGAL::Arr_conic_traits_2<RatKernel, AlgKernel, NtTraits>>::
filterIntersectionPoints(std::vector<CGAL::Object>& res) {
std::vector<std::pair<Intersection_point_2, Multiplicity>> 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<Intersection_point_2, Multiplicity> 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<Intersection_point_2, Multiplicity> pair = tmp[i];
CGAL::Object o = CGAL::make_object(pair);
res.push_back(o);
}
}
template <typename RatKernel, class AlgKernel, class NtTraits>
ArrangementPainterOstream<
CGAL::Arr_conic_traits_2<RatKernel, AlgKernel, NtTraits>>&
ArrangementPainterOstream<CGAL::Arr_conic_traits_2<
RatKernel, AlgKernel, NtTraits>>::operator<<(const X_monotone_curve_2& curve)
{
//
template <typename RatKernel, typename AlgKernel, typename NtTraits>
ArrangementPainterOstream
<CGAL::Arr_conic_traits_2<RatKernel, AlgKernel, NtTraits>>&
ArrangementPainterOstream
<CGAL::Arr_conic_traits_2<RatKernel, AlgKernel, NtTraits>>::
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<size_t>(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<Approximate_point_2> app_pts;
// app_pts.reserve(n + 1);
// curve_.polyline_approximation(n, std::back_inserter(app_pts));
std::vector<Approximate_point_2> 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<X_monotone_curve_2> 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<X_monotone_curve_2> 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 <typename RatKernel, typename AlgKernel, typename NtTraits,
typename BoundingTraits>
std::vector<std::pair<double, double>>
ArrangementPainterOstream<CGAL::Arr_Bezier_curve_traits_2<
RatKernel, AlgKernel, NtTraits,
BoundingTraits>>::getPoints(const X_monotone_curve_2& curve)
{
ArrangementPainterOstream
<CGAL::Arr_Bezier_curve_traits_2<RatKernel, AlgKernel, NtTraits,
BoundingTraits>>::
getPoints(const X_monotone_curve_2& curve) {
std::pair<double, double> param_range = curve.parameter_range();
auto&& supporting_curve = curve.supporting_curve();
@ -256,12 +232,13 @@ ArrangementPainterOstream<CGAL::Arr_Bezier_curve_traits_2<
return sampled_points;
}
template <
typename RatKernel, typename AlgKernel, typename NtTraits,
typename BoundingTraits>
auto ArrangementPainterOstream<CGAL::Arr_Bezier_curve_traits_2<
RatKernel, AlgKernel, NtTraits,
BoundingTraits>>::operator<<(const X_monotone_curve_2& curve)
//
template <typename RatKernel, typename AlgKernel, typename NtTraits,
typename BoundingTraits>
auto ArrangementPainterOstream
<CGAL::Arr_Bezier_curve_traits_2<RatKernel, AlgKernel, NtTraits,
BoundingTraits>>::
operator<<(const X_monotone_curve_2& curve)
-> ArrangementPainterOstream<Traits>&
{
auto sampled_points = this->getPoints(curve);
@ -276,57 +253,45 @@ auto ArrangementPainterOstream<CGAL::Arr_Bezier_curve_traits_2<
return *this;
}
// Instantiation of Arr_linear_traits_2
// Specialization of `ArrangementPainterOstream` for the linear traits.
template <typename Kernel_>
ArrangementPainterOstream<CGAL::Arr_linear_traits_2<Kernel_>>&
ArrangementPainterOstream<CGAL::Arr_linear_traits_2<Kernel_>>::operator<<(
const X_monotone_curve_2& curve)
{
if (curve.is_segment())
{
ArrangementPainterOstream<CGAL::Arr_linear_traits_2<Kernel_>>::
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 <typename Traits>
static bool lies_on_border(
const ArrangementPainterOstream<Traits>* apo, const QPointF& point)
{
static bool lies_on_border(const ArrangementPainterOstream<Traits>* 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 <typename Coefficient_>
void ArrangementPainterOstream<
CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>::remapFacadePainter()
{
this->qp->setTransform(this->getPointsListMapping());
}
void
ArrangementPainterOstream<CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>::
remapFacadePainter()
{ this->qp->setTransform(this->getPointsListMapping()); }
//
template <typename Coefficient_>
QTransform ArrangementPainterOstream<
CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>::getPointsListMapping()
{
QTransform
ArrangementPainterOstream<CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>::
getPointsListMapping() {
auto worldTransform = this->qp->transform();
return this->getPointsListMapping(worldTransform);
}
//
template <typename Coefficient_>
QTransform
ArrangementPainterOstream<CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>::
getPointsListMapping(const QTransform& worldTransform)
{
getPointsListMapping(const QTransform& worldTransform) {
auto view = this->getView();
QRectF viewport = this->viewportRect();
@ -377,11 +343,11 @@ ArrangementPainterOstream<CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>::
return QTransform{m11, m12, m21, m22, dx, dy};
}
//
template <typename Coefficient_>
auto ArrangementPainterOstream<CGAL::Arr_algebraic_segment_traits_2<
Coefficient_>>::getPointsList(const X_monotone_curve_2& curve)
-> std::vector<Coord_vec_2>
{
auto ArrangementPainterOstream
<CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>::
getPointsList(const X_monotone_curve_2& curve) -> std::vector<Coord_vec_2> {
typedef Curve_renderer_facade<CKvA_2> Facade;
typedef std::pair<double, double> Coord_2;
typedef std::vector<Coord_2> Coord_vec_2;
@ -391,11 +357,11 @@ auto ArrangementPainterOstream<CGAL::Arr_algebraic_segment_traits_2<
return points;
}
//
template <typename Coefficient_>
ArrangementPainterOstream<CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>&
ArrangementPainterOstream<CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>::
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 <typename Coefficient_>
void ArrangementPainterOstream<CGAL::Arr_algebraic_segment_traits_2<
Coefficient_>>::paintCurve(const X_monotone_curve_2& curve)
{
void ArrangementPainterOstream
<CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>::
paintCurve(const X_monotone_curve_2& curve) {
std::vector<Coord_vec_2> 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<CGAL::Arr_algebraic_segment_traits_2<
}
}
//
template <typename Coefficient_>
void ArrangementPainterOstream<
CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>::setupFacade()
{
void ArrangementPainterOstream
<CGAL::Arr_algebraic_segment_traits_2<Coefficient_>>::setupFacade() {
typedef Curve_renderer_facade<CKvA_2> 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 <class T>
// Specialization of `ArrangementPainterOstream` for Arr_rational_function_traits_2
template <typename T>
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 <typename AlgebraicKernel_d_1_>
auto ArrangementPainterOstream<CGAL::Arr_rational_function_traits_2<
AlgebraicKernel_d_1_>>::operator<<(const X_monotone_curve_2& curve) -> Self&
{
auto ArrangementPainterOstream
<CGAL::Arr_rational_function_traits_2<AlgebraicKernel_d_1_>>::
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<CGAL::Arr_rational_function_traits_2<
// TODO: this is ugly! clean up these conditions
auto path_filler = [&](double x, double y) {
if (y > 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<CGAL::Arr_rational_function_traits_2<
if (!disconnected) { painterPath.lineTo(x_, y_); }
// connect between two out of range points when they cross different
// boundaries
else if (
(last_y == min_y && y_ == max_y) || (last_y == max_y && y_ == min_y))
else if ((last_y == min_y && y_ == max_y) ||
(last_y == max_y && y_ == min_y))
{
painterPath.moveTo(last_x, last_y);
painterPath.lineTo(x_, y_);
@ -484,15 +446,12 @@ auto ArrangementPainterOstream<CGAL::Arr_rational_function_traits_2<
disconnected = true;
}
else if (first_point)
{
else if (first_point) {
painterPath.moveTo(x, y);
disconnected = false;
}
else
{
if (disconnected)
{
else {
if (disconnected) {
painterPath.moveTo(last_x, last_y);
disconnected = false;
}
@ -507,11 +466,11 @@ auto ArrangementPainterOstream<CGAL::Arr_rational_function_traits_2<
return *this;
}
//
template <typename AlgebraicKernel_d_1_>
auto ArrangementPainterOstream<CGAL::Arr_rational_function_traits_2<
AlgebraicKernel_d_1_>>::getPointsList(const X_monotone_curve_2& curve)
-> std::vector<Coord_vec_2>
{
auto ArrangementPainterOstream
<CGAL::Arr_rational_function_traits_2<AlgebraicKernel_d_1_>>::
getPointsList(const X_monotone_curve_2& curve) -> std::vector<Coord_vec_2> {
std::vector<Coord_vec_2> points_list;
Coord_vec_2* cur_list = nullptr;
@ -527,15 +486,13 @@ auto ArrangementPainterOstream<CGAL::Arr_rational_function_traits_2<
// TODO: this is ugly! clean up these conditions
auto path_filler = [&](double x, double y) {
if (y > 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 ArrangementPainterOstream<CGAL::Arr_rational_function_traits_2<
disconnected = true;
}
else
{
if (disconnected)
{
else {
if (disconnected) {
points_list.emplace_back();
cur_list = &points_list.back();
if (!first_point) cur_list->push_back({last_x, last_y});
@ -563,12 +518,12 @@ auto ArrangementPainterOstream<CGAL::Arr_rational_function_traits_2<
return points_list;
}
//
template <typename AlgebraicKernel_d_1_>
template <typename Lambda>
void ArrangementPainterOstream<
CGAL::Arr_rational_function_traits_2<AlgebraicKernel_d_1_>>::
sample_points(const X_monotone_curve_2& curve, Lambda&& lambda)
{
void ArrangementPainterOstream
<CGAL::Arr_rational_function_traits_2<AlgebraicKernel_d_1_>>::
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<double>::infinity());
break;
}
case ARR_BOTTOM_BOUNDARY: {
lambda(min_x, -std::numeric_limits<double>::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<double>::infinity());
break;
}
case ARR_BOTTOM_BOUNDARY: {
lambda(min_x, -std::numeric_limits<double>::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<double, double> 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<double>::infinity()};
break;
}
case ARR_BOTTOM_BOUNDARY: {
last_pt = {max_x, -std::numeric_limits<double>::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<double>::infinity()};
break;
}
case ARR_BOTTOM_BOUNDARY: {
last_pt = {max_x, -std::numeric_limits<double>::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;

View File

@ -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;

View File

@ -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;