mirror of https://github.com/CGAL/cgal
Fixed trimming and avoided using deprecated code.
This commit is contained in:
parent
6f103e4de1
commit
3485ce1a8a
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue