mirror of https://github.com/CGAL/cgal
Cleaned up; Pacify MSVC; suppressed warnings.
This commit is contained in:
parent
6314299598
commit
5ed29f9173
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#ifndef CGAL_DRAW_AOS_ARR_APPROXIMATION_CACHE_H
|
||||
#define CGAL_DRAW_AOS_ARR_APPROXIMATION_CACHE_H
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
|
||||
#include <CGAL/Arr_enums.h>
|
||||
|
|
@ -24,16 +25,14 @@
|
|||
namespace CGAL {
|
||||
namespace draw_aos {
|
||||
|
||||
/**
|
||||
* @brief Cache class for approximating arrangement on surface.
|
||||
/** @brief Cache class for approximating arrangement on surface.
|
||||
*
|
||||
* When iterating over the arrangement dcel, a feature(vertex, halfedge, face) might be visited multiple times.
|
||||
* This cache stores the approximated geometry for each feature to avoid redundant calculations.
|
||||
* @tparam Arrangement
|
||||
*/
|
||||
template <typename Arrangement>
|
||||
class Arr_approximation_cache
|
||||
{
|
||||
class Arr_approximation_cache {
|
||||
using Geom_traits = typename Arrangement::Geometry_traits_2;
|
||||
using Approx_traits = Arr_approximate_traits<Geom_traits>;
|
||||
|
||||
|
|
@ -67,4 +66,5 @@ private:
|
|||
|
||||
} // namespace draw_aos
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#ifndef CGAL_DRAW_AOS_ARR_BOUNDED_APPROXIMATE_FACE_H
|
||||
#define CGAL_DRAW_AOS_ARR_BOUNDED_APPROXIMATE_FACE_H
|
||||
|
||||
#include <iterator>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#ifndef CGAL_DRAW_AOS_ARR_BOUNDED_APPROXIMATE_HALFEDGE_H
|
||||
#define CGAL_DRAW_AOS_ARR_BOUNDED_APPROXIMATE_HALFEDGE_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
|
|
@ -32,16 +33,14 @@
|
|||
namespace CGAL {
|
||||
namespace draw_aos {
|
||||
|
||||
/**
|
||||
* @brief Functor to approximate an x-monotone curve within an bounding box.
|
||||
/** @brief Functor to approximate an x-monotone curve within an bounding box.
|
||||
*
|
||||
* The Approximation is done from xmin to xmax with a given step. For parts outbound the y limits and precedes or
|
||||
* succeeds a part within, the approximation may be skipped but there will be at least one point outside the bbox
|
||||
* for indication.
|
||||
*/
|
||||
template <typename Arrangement>
|
||||
class Arr_bounded_approximate_halfedge
|
||||
{
|
||||
class Arr_bounded_approximate_halfedge {
|
||||
using Geom_traits = typename Arrangement::Geometry_traits_2;
|
||||
using Halfedge_const_handle = typename Arrangement::Halfedge_const_handle;
|
||||
using Gt_point = typename Geom_traits::Point_2;
|
||||
|
|
@ -58,32 +57,31 @@ class Arr_bounded_approximate_halfedge
|
|||
using Boundary_lines = std::array<Approx_line_2, 4>;
|
||||
|
||||
constexpr static bool Has_approximate_xcv_with_bounds =
|
||||
has_approximate_xcv_with_bounds_v<Geom_traits, typename Geom_traits::Approximate_2>;
|
||||
has_approximate_xcv_with_bounds_v<Geom_traits, typename Geom_traits::Approximate_2>;
|
||||
|
||||
private:
|
||||
struct Context : public Bounded_render_context
|
||||
{
|
||||
Context(const Bounded_render_context& ctx, const X_monotone_curve_2& curve, Polyline& polyline)
|
||||
: Bounded_render_context(ctx)
|
||||
, m_polyline(polyline)
|
||||
, m_curve(curve) {}
|
||||
struct Context : public Bounded_render_context {
|
||||
Context(const Bounded_render_context& ctx, const X_monotone_curve_2& curve, Polyline& polyline) :
|
||||
Bounded_render_context(ctx),
|
||||
m_polyline(polyline), m_curve(curve)
|
||||
{}
|
||||
|
||||
// Prevent accidental copying.
|
||||
Context(const Context&) = delete;
|
||||
Context& operator=(const Context&) = delete;
|
||||
|
||||
public:
|
||||
/*!
|
||||
* \brief Insert a point to the polyline if it is within the x-range of the curve
|
||||
/*! \brief Insert a point to the polyline if it is within the x-range of the curve
|
||||
* \note Will be replaced after AosApproximateUnboundedTraits_2 is fully available.
|
||||
* \param pt
|
||||
*/
|
||||
void insert(Point pt) {
|
||||
if(pt.x() < this->xmin()) {
|
||||
if (pt.x() < this->xmin()) {
|
||||
// We need the last point if not yet x-inbound.
|
||||
m_last_pt = pt;
|
||||
return;
|
||||
} else if(pt.x() > this->xmax())
|
||||
return;
|
||||
}
|
||||
else if (pt.x() > this->xmax()) return;
|
||||
|
||||
m_polyline.push_back(pt);
|
||||
m_last_pt = pt;
|
||||
|
|
@ -99,12 +97,11 @@ private:
|
|||
const X_monotone_curve_2& m_curve;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Computes the intersection point between the given boundary side and the line segment from last_pt to pt.
|
||||
/*! \brief Computes the intersection point between the given boundary side and the line segment from last_pt to pt.
|
||||
*/
|
||||
Point boundary_intersection(const Context& ctx, Point pt, Boundary_side side) const {
|
||||
std::optional<double> x, y;
|
||||
const Approx_line_2* line;
|
||||
const Approx_line_2* line = nullptr;
|
||||
switch(side) {
|
||||
case Boundary_side::Left:
|
||||
x = ctx.xmin();
|
||||
|
|
@ -126,41 +123,41 @@ private:
|
|||
CGAL_assertion(false && "Unexpected side of boundary.");
|
||||
}
|
||||
Point inter = std::get<Point>(*CGAL::intersection(Approx_line_2(*ctx.last_pt(), pt), *line));
|
||||
if(x.has_value()) return Point(*x, inter.y());
|
||||
if (x.has_value()) return Point(*x, inter.y());
|
||||
return Point(inter.x(), *y);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Trace approximated curve point in ltr ordering, adding boundary intersections if necessary.
|
||||
/*! \brief Trace approximated curve point in ltr ordering, adding boundary intersections if necessary.
|
||||
*
|
||||
* \note This method will eventually be replaced by AosApproximateUnboundedTraits_2.
|
||||
*/
|
||||
void trace_add(Context& ctx, Point pt) const {
|
||||
if(!ctx.last_pt().has_value()) {
|
||||
if (! ctx.last_pt().has_value()) {
|
||||
ctx.insert(pt);
|
||||
return;
|
||||
}
|
||||
if(ctx.last_pt()->x() < ctx.xmin() && pt.x() >= ctx.xmin())
|
||||
if (ctx.last_pt()->x() < ctx.xmin() && pt.x() >= ctx.xmin())
|
||||
ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Left));
|
||||
if(ctx.last_pt()->y() < ctx.ymin()) {
|
||||
if(pt.y() > ctx.ymin()) ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Bottom));
|
||||
if(pt.y() > ctx.ymax()) ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Top));
|
||||
} else if(ctx.last_pt()->y() > ctx.ymax()) {
|
||||
if(pt.y() < ctx.ymax()) ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Top));
|
||||
if(pt.y() < ctx.ymin()) ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Bottom));
|
||||
} else {
|
||||
if(pt.y() < ctx.ymin())
|
||||
if (ctx.last_pt()->y() < ctx.ymin()) {
|
||||
if (pt.y() > ctx.ymin()) ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Bottom));
|
||||
if (pt.y() > ctx.ymax()) ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Top));
|
||||
}
|
||||
else if (ctx.last_pt()->y() > ctx.ymax()) {
|
||||
if (pt.y() < ctx.ymax()) ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Top));
|
||||
if (pt.y() < ctx.ymin()) ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Bottom));
|
||||
}
|
||||
else {
|
||||
if (pt.y() < ctx.ymin())
|
||||
ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Bottom));
|
||||
else if(pt.y() > ctx.ymax())
|
||||
else if (pt.y() > ctx.ymax())
|
||||
ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Top));
|
||||
}
|
||||
if(ctx.last_pt()->x() <= ctx.xmax() && pt.x() > ctx.xmax())
|
||||
if (ctx.last_pt()->x() <= ctx.xmax() && pt.x() > ctx.xmax())
|
||||
ctx.insert(boundary_intersection(ctx, pt, Boundary_side::Right));
|
||||
ctx.insert(pt);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Check if the point is within the x-range of the curve.
|
||||
/*! \brief Check if the point is within the x-range of the curve.
|
||||
*/
|
||||
static bool is_in_x_range(const Context& ctx, const Gt_point& pt) {
|
||||
const Geom_traits& traits = ctx.m_traits;
|
||||
|
|
@ -170,42 +167,40 @@ private:
|
|||
if constexpr(!has_parameter_space_in_x_2<Geom_traits>::value) {
|
||||
const auto& min_pt = traits.construct_min_vertex_2_object()(curve);
|
||||
const auto& max_pt = traits.construct_max_vertex_2_object()(curve);
|
||||
return traits.compare_x_2_object()(pt, min_pt) != CGAL::SMALLER &&
|
||||
traits.compare_x_2_object()(pt, max_pt) != CGAL::LARGER;
|
||||
return ((traits.compare_x_2_object()(pt, min_pt) != CGAL::SMALLER) &&
|
||||
(traits.compare_x_2_object()(pt, max_pt) != CGAL::LARGER));
|
||||
}
|
||||
|
||||
Comparison_result left_cmp;
|
||||
if(auto left_loc = traits.parameter_space_in_x_2_object()(curve, ARR_MIN_END); left_loc == ARR_INTERIOR)
|
||||
if (auto left_loc = traits.parameter_space_in_x_2_object()(curve, ARR_MIN_END); left_loc == ARR_INTERIOR)
|
||||
left_cmp = traits.compare_x_2_object()(pt, traits.construct_min_vertex_2_object()(curve));
|
||||
else if(left_loc == ARR_LEFT_BOUNDARY)
|
||||
else if (left_loc == ARR_LEFT_BOUNDARY)
|
||||
left_cmp = CGAL::LARGER;
|
||||
else
|
||||
left_cmp = traits.compare_x_on_boundary_2_object()(pt, curve, ARR_MIN_END);
|
||||
if(left_cmp == CGAL::SMALLER) return false;
|
||||
if(left_cmp == CGAL::EQUAL) return true;
|
||||
if (left_cmp == CGAL::SMALLER) return false;
|
||||
if (left_cmp == CGAL::EQUAL) return true;
|
||||
|
||||
Comparison_result right_cmp;
|
||||
if(auto right_loc = traits.parameter_space_in_x_2_object()(curve, ARR_MAX_END); right_loc == ARR_INTERIOR)
|
||||
if (auto right_loc = traits.parameter_space_in_x_2_object()(curve, ARR_MAX_END); right_loc == ARR_INTERIOR)
|
||||
right_cmp = traits.compare_x_2_object()(pt, traits.construct_max_vertex_2_object()(curve));
|
||||
else if(right_loc == ARR_RIGHT_BOUNDARY)
|
||||
else if (right_loc == ARR_RIGHT_BOUNDARY)
|
||||
right_cmp = CGAL::SMALLER;
|
||||
else
|
||||
right_cmp = traits.compare_x_on_boundary_2_object()(pt, curve, ARR_MAX_END);
|
||||
return right_cmp != CGAL::LARGER;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief transform approximated curve points(ltr ordering) in place based on the halfedge, giving correct
|
||||
/*! \brief transform approximated curve points(ltr ordering) in place based on the halfedge, giving correct
|
||||
* ordering, continuity, etc.
|
||||
*/
|
||||
static void transform_polyline(Context& ctx, Polyline& polyline, const Halfedge_const_handle& he) {
|
||||
transform_polyline_impl<Geom_traits>(ctx, polyline, he);
|
||||
}
|
||||
static void transform_polyline(Context& ctx, Polyline& polyline, const Halfedge_const_handle& he)
|
||||
{ transform_polyline_impl<Geom_traits>(ctx, polyline, he); }
|
||||
|
||||
// For planar arrangements, we only need to reverse the polyline if the halfedge is rtl.
|
||||
template <typename Gt, std::enable_if_t<!is_or_derived_from_curved_surf_traits_v<Gt>, int> = 0>
|
||||
static void transform_polyline_impl(Context&, Polyline& polyline, const Halfedge_const_handle& he) {
|
||||
if(he->direction() == CGAL::ARR_LEFT_TO_RIGHT) return;
|
||||
if (he->direction() == CGAL::ARR_LEFT_TO_RIGHT) return;
|
||||
std::reverse(polyline.begin(), polyline.end());
|
||||
}
|
||||
|
||||
|
|
@ -214,21 +209,22 @@ private:
|
|||
using Direction_3 = typename Geom_traits::Direction_3;
|
||||
using Vector_3 = typename Geom_traits::Vector_3;
|
||||
|
||||
if(polyline.size() < 2) return;
|
||||
if (polyline.size() < 2) return;
|
||||
const X_monotone_curve_2& curve = he->curve();
|
||||
const auto& traits = ctx.m_traits;
|
||||
if(curve.is_vertical()) {
|
||||
if (curve.is_vertical()) {
|
||||
Direction_3 normal_dir = curve.is_directed_right() ? curve.normal() : -curve.normal();
|
||||
Direction_3 azimuth_dir(CGAL::cross_product(Vector_3(0, 0, 1), normal_dir.vector()));
|
||||
Approx_nt azimuth = ctx.to_uv(traits.approximate_2_object()(traits.construct_point_2_object()(azimuth_dir))).x();
|
||||
if(azimuth == 0 && he->direction() == ARR_LEFT_TO_RIGHT) azimuth = 2 * CGAL_PI;
|
||||
if (azimuth == 0 && he->direction() == ARR_LEFT_TO_RIGHT) azimuth = 2 * CGAL_PI;
|
||||
std::transform(polyline.begin(), polyline.end(), polyline.begin(),
|
||||
[azimuth](Point pt) { return Point(azimuth, pt.y()); });
|
||||
} else if(polyline.back().x() == 0) {
|
||||
}
|
||||
else if (polyline.back().x() == 0) {
|
||||
// For strictly x-monotone arcs whose target point sits on the boundary, the x should be set to 2 * CGAL_PI
|
||||
polyline.back() = Point(2 * CGAL_PI, polyline.back().y());
|
||||
}
|
||||
if(he->direction() == CGAL::ARR_LEFT_TO_RIGHT) return;
|
||||
if (he->direction() == CGAL::ARR_LEFT_TO_RIGHT) return;
|
||||
std::reverse(polyline.begin(), polyline.end());
|
||||
}
|
||||
|
||||
|
|
@ -242,22 +238,23 @@ private:
|
|||
Polyline& polyline = ctx.m_polyline;
|
||||
auto compare_y_at_x_2 = traits.compare_y_at_x_2_object();
|
||||
|
||||
if(is_in_x_range(ctx, m_top_left)) {
|
||||
if(compare_y_at_x_2(m_top_left, curve) == CGAL::SMALLER) {
|
||||
if (is_in_x_range(ctx, m_top_left)) {
|
||||
if (compare_y_at_x_2(m_top_left, curve) == CGAL::SMALLER) {
|
||||
polyline.insert(polyline.end(), {Approx_traits::Null_point, Point(ctx.xmin(), ctx.ymax())});
|
||||
} else if(compare_y_at_x_2(m_bottom_left, curve) == CGAL::LARGER) {
|
||||
}
|
||||
else if (compare_y_at_x_2(m_bottom_left, curve) == CGAL::LARGER) {
|
||||
polyline.insert(polyline.end(), {Approx_traits::Null_point, Point(ctx.xmin(), ctx.ymin())});
|
||||
}
|
||||
}
|
||||
traits.approximate_2_object()(curve, ctx.m_approx_error,
|
||||
boost::make_function_output_iterator([&ctx, this](Approx_point approx_pt) {
|
||||
ctx.m_polyline.push_back(snap_to_boundary(ctx, ctx.to_uv(approx_pt)));
|
||||
}),
|
||||
boost::make_function_output_iterator([&ctx, this](Approx_point approx_pt)
|
||||
{ ctx.m_polyline.push_back(snap_to_boundary(ctx, ctx.to_uv(approx_pt))); }),
|
||||
ctx.bbox(), true);
|
||||
if(is_in_x_range(ctx, m_top_right)) {
|
||||
if(compare_y_at_x_2(m_top_right, curve) == CGAL::SMALLER) {
|
||||
if (is_in_x_range(ctx, m_top_right)) {
|
||||
if (compare_y_at_x_2(m_top_right, curve) == CGAL::SMALLER) {
|
||||
polyline.insert(polyline.end(), {Point(ctx.xmax(), ctx.ymax()), Approx_traits::Null_point});
|
||||
} else if(compare_y_at_x_2(m_bottom_right, curve) == CGAL::LARGER) {
|
||||
}
|
||||
else if (compare_y_at_x_2(m_bottom_right, curve) == CGAL::LARGER) {
|
||||
polyline.insert(polyline.end(), {Point(ctx.xmax(), ctx.ymin()), Approx_traits::Null_point});
|
||||
}
|
||||
}
|
||||
|
|
@ -266,36 +263,31 @@ private:
|
|||
// If Approximate_2 does not support curve approximation with bounding box
|
||||
template <typename Gt, std::enable_if_t<!has_approximate_xcv_with_bounds_v<Gt, typename Gt::Approximate_2>, int> = 0>
|
||||
void approximate_curve_impl(Context& ctx) const {
|
||||
m_ctx.m_traits.approximate_2_object()(
|
||||
ctx.m_curve, ctx.m_approx_error,
|
||||
boost::make_function_output_iterator([&ctx, this](Approx_point pt) { trace_add(ctx, ctx.to_uv(pt)); }), true);
|
||||
auto approx = m_ctx.m_traits.approximate_2_object();
|
||||
approx(ctx.m_curve, ctx.m_approx_error,
|
||||
boost::make_function_output_iterator([&ctx, this](Approx_point pt) { trace_add(ctx, ctx.to_uv(pt)); }), true);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adjusts a point by snapping it to the nearest boundary to reduce floating-point error.
|
||||
/*! \brief Adjusts a point by snapping it to the nearest boundary to reduce floating-point error.
|
||||
*
|
||||
* \return The adjusted (snapped) point if it lies within snapping tolerance, or the original point otherwise.
|
||||
*/
|
||||
Point snap_to_boundary(const Context& ctx, Point pt) const {
|
||||
Approx_nt x = pt.x(), y = pt.y();
|
||||
if(std::abs(x - ctx.xmin()) < m_ep_left)
|
||||
x = ctx.xmin();
|
||||
else if(std::abs(x - ctx.xmax()) < m_ep_right)
|
||||
x = ctx.xmax();
|
||||
if(std::abs(y - ctx.ymin()) < m_ep_bottom)
|
||||
y = ctx.ymin();
|
||||
else if(std::abs(y - ctx.ymax()) < m_ep_top)
|
||||
y = ctx.ymax();
|
||||
if (std::abs(x - ctx.xmin()) < m_ep_left) x = ctx.xmin();
|
||||
else if (std::abs(x - ctx.xmax()) < m_ep_right) x = ctx.xmax();
|
||||
if (std::abs(y - ctx.ymin()) < m_ep_bottom) y = ctx.ymin();
|
||||
else if (std::abs(y - ctx.ymax()) < m_ep_top) y = ctx.ymax();
|
||||
return Point(x, y);
|
||||
}
|
||||
|
||||
public:
|
||||
Arr_bounded_approximate_halfedge(const Bounded_render_context& ctx)
|
||||
: m_ctx(ctx)
|
||||
, m_top(ctx.top_left(), ctx.top_right())
|
||||
, m_bottom(ctx.bottom_left(), ctx.bottom_right())
|
||||
, m_left(ctx.bottom_left(), ctx.top_left())
|
||||
, m_right(ctx.bottom_right(), ctx.top_right()) {
|
||||
Arr_bounded_approximate_halfedge(const Bounded_render_context& ctx) :
|
||||
m_ctx(ctx),
|
||||
m_left(ctx.bottom_left(), ctx.top_left()),
|
||||
m_right(ctx.bottom_right(), ctx.top_right()),
|
||||
m_bottom(ctx.bottom_left(), ctx.bottom_right()),
|
||||
m_top(ctx.top_left(), ctx.top_right()) {
|
||||
Construct_gt_point_2<Geom_traits> ctr_p;
|
||||
m_top_left = ctr_p(ctx.to_cartesian(ctx.top_left()));
|
||||
m_top_right = ctr_p(ctx.to_cartesian(ctx.top_right()));
|
||||
|
|
@ -314,8 +306,8 @@ public:
|
|||
auto& cache = m_ctx.m_cache.halfedges();
|
||||
auto [iter, inserted] = cache.try_emplace(he, Polyline());
|
||||
Polyline& polyline = iter->second;
|
||||
if(!inserted) return polyline;
|
||||
if(m_ctx.is_cancelled()) return polyline;
|
||||
if (!inserted) return polyline;
|
||||
if (m_ctx.is_cancelled()) return polyline;
|
||||
|
||||
const X_monotone_curve_2& curve = he->curve();
|
||||
Context ctx(m_ctx, curve, polyline);
|
||||
|
|
@ -325,18 +317,19 @@ public:
|
|||
|
||||
// also approximate the twin halfedge
|
||||
auto [twin_iter, twin_inserted] = cache.try_emplace(he->twin(), std::move(poly_copy));
|
||||
if(twin_inserted) transform_polyline(ctx, twin_iter->second, he->twin());
|
||||
if (twin_inserted) transform_polyline(ctx, twin_iter->second, he->twin());
|
||||
// The previous iterator might have been invalidated by the second try_emplace call, so we do an extra lookup.
|
||||
return cache.at(he);
|
||||
}
|
||||
|
||||
private:
|
||||
const Bounded_render_context& m_ctx;
|
||||
Approx_line_2 m_left, m_right, m_top, m_bottom;
|
||||
Approx_line_2 m_left, m_right, m_bottom, m_top;
|
||||
Gt_point m_top_left, m_top_right, m_bottom_left, m_bottom_right;
|
||||
Approx_nt m_ep_left, m_ep_right, m_ep_bottom, m_ep_top;
|
||||
};
|
||||
|
||||
} // namespace draw_aos
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,8 +23,7 @@ namespace CGAL {
|
|||
namespace draw_aos {
|
||||
|
||||
template <typename Arrangement>
|
||||
class Arr_bounded_approximate_vertex
|
||||
{
|
||||
class Arr_bounded_approximate_vertex {
|
||||
using Geom_traits = typename Arrangement::Geometry_traits_2;
|
||||
using Point_2 = typename Geom_traits::Point_2;
|
||||
using Vertex_const_handle = typename Arrangement::Vertex_const_handle;
|
||||
|
|
@ -32,11 +31,9 @@ class Arr_bounded_approximate_vertex
|
|||
using Bounded_render_context = Arr_bounded_render_context<Arrangement>;
|
||||
|
||||
public:
|
||||
Arr_bounded_approximate_vertex(const Bounded_render_context& ctx)
|
||||
: m_ctx(ctx) {}
|
||||
Arr_bounded_approximate_vertex(const Bounded_render_context& ctx) : m_ctx(ctx) {}
|
||||
|
||||
/**
|
||||
* @brief Approximate a vertex within the x-bounded range.
|
||||
/** @brief Approximate a vertex within the x-bounded range.
|
||||
*
|
||||
* The function uses cached values if available.
|
||||
* @precondition: The vertex must have an associated point.
|
||||
|
|
@ -47,7 +44,7 @@ public:
|
|||
const Point_geom& operator()(const Vertex_const_handle& vh) const {
|
||||
auto [iter, inserted] = m_ctx.m_cache.vertices().try_emplace(vh);
|
||||
Point_geom& point = iter->second;
|
||||
if(!inserted) return point;
|
||||
if (! inserted) return point;
|
||||
return point = m_ctx.to_uv(m_ctx.m_traits.approximate_2_object()(vh->point()));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,8 +54,7 @@ namespace draw_aos {
|
|||
* @brief Triangulator for a face of an arrangement within a bounding box.
|
||||
*/
|
||||
template <typename Arrangement>
|
||||
class Arr_bounded_face_triangulator
|
||||
{
|
||||
class Arr_bounded_face_triangulator {
|
||||
using Geom_traits = typename Arrangement::Geometry_traits_2;
|
||||
constexpr static bool Is_on_curved_surface = is_or_derived_from_curved_surf_traits_v<Geom_traits>;
|
||||
|
||||
|
|
@ -74,15 +73,12 @@ class Arr_bounded_face_triangulator
|
|||
|
||||
enum Point_type { Vertex_only, Constraint_only, Vertex_and_constraint };
|
||||
|
||||
/*!
|
||||
* \brief A index wrapper defaulted to invalid.
|
||||
/*! \brief A index wrapper defaulted to invalid.
|
||||
*/
|
||||
class Index
|
||||
{
|
||||
class Index {
|
||||
public:
|
||||
Index() = default;
|
||||
Index(int idx)
|
||||
: m_index(idx) {}
|
||||
Index(int idx) : m_index(idx) {}
|
||||
|
||||
bool is_valid() const { return m_index != Invalid_index; }
|
||||
operator int() const { return m_index; }
|
||||
|
|
@ -111,8 +107,7 @@ public:
|
|||
private:
|
||||
static KPoint to_kpoint(Point pt) { return KPoint(pt.x(), pt.y()); }
|
||||
|
||||
/*!
|
||||
* \brief Offset a point on a specific boundary outward by a given offset.
|
||||
/*! \brief Offset a point on a specific boundary outward by a given offset.
|
||||
*
|
||||
* \pre side != Boundary_side::None
|
||||
*/
|
||||
|
|
@ -120,32 +115,25 @@ private:
|
|||
CGAL_precondition(side != Boundary_side::None);
|
||||
|
||||
switch(side) {
|
||||
case Boundary_side::Left:
|
||||
return Point(pt.x() - offset, pt.y());
|
||||
case Boundary_side::Right:
|
||||
return Point(pt.x() + offset, pt.y());
|
||||
case Boundary_side::Top:
|
||||
return Point(pt.x(), pt.y() + offset);
|
||||
case Boundary_side::Bottom:
|
||||
return Point(pt.x(), pt.y() - offset);
|
||||
default:
|
||||
return pt; // Should not reach here
|
||||
case Boundary_side::Left: return Point(pt.x() - offset, pt.y());
|
||||
case Boundary_side::Right: return Point(pt.x() + offset, pt.y());
|
||||
case Boundary_side::Top: return Point(pt.x(), pt.y() + offset);
|
||||
case Boundary_side::Bottom: return Point(pt.x(), pt.y() - offset);
|
||||
default: return pt; // Should not reach here
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Find the shared boundary side of two points, or None if they are not on the same boundary.
|
||||
/*! \brief Find the shared boundary side of two points, or None if they are not on the same boundary.
|
||||
*/
|
||||
Boundary_side shared_boundary(const Point& pt1, const Point& pt2) const {
|
||||
if(m_ctx.is_on_left(pt1) && m_ctx.is_on_left(pt2)) return Boundary_side::Left;
|
||||
if(m_ctx.is_on_right(pt1) && m_ctx.is_on_right(pt2)) return Boundary_side::Right;
|
||||
if(m_ctx.is_on_bottom(pt1) && m_ctx.is_on_bottom(pt2)) return Boundary_side::Bottom;
|
||||
if(m_ctx.is_on_top(pt1) && m_ctx.is_on_top(pt2)) return Boundary_side::Top;
|
||||
if (m_ctx.is_on_left(pt1) && m_ctx.is_on_left(pt2)) return Boundary_side::Left;
|
||||
if (m_ctx.is_on_right(pt1) && m_ctx.is_on_right(pt2)) return Boundary_side::Right;
|
||||
if (m_ctx.is_on_bottom(pt1) && m_ctx.is_on_bottom(pt2)) return Boundary_side::Bottom;
|
||||
if (m_ctx.is_on_top(pt1) && m_ctx.is_on_top(pt2)) return Boundary_side::Top;
|
||||
return Boundary_side::None;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Add a helper point on the shared boundary of two points if they are on the same boundary side.
|
||||
/*! \brief Add a helper point on the shared boundary of two points if they are on the same boundary side.
|
||||
*
|
||||
* When triangulating a arrangement face within a bounding box, curves outside the bounding box are projected on the
|
||||
* four sides of the bbox. Topological errors could be introduced if several segments are lying on the same side.
|
||||
|
|
@ -155,9 +143,9 @@ private:
|
|||
// Arrangements on curved surfaces currently draws the entire parameter space, so there's no need to add
|
||||
// helper points.
|
||||
if constexpr(Is_on_curved_surface) return;
|
||||
if(from == to) return;
|
||||
if (from == to) return;
|
||||
auto shared_side = shared_boundary(from, to);
|
||||
if(shared_side == Boundary_side::None) return;
|
||||
if (shared_side == Boundary_side::None) return;
|
||||
Point mid = CGAL::midpoint(from, to);
|
||||
m_points.push_back(offset_boundary_point(mid, shared_side, m_offset += 0.1));
|
||||
m_point_types.push_back(Constraint_only);
|
||||
|
|
@ -185,7 +173,7 @@ private:
|
|||
void insert_all_constraints() {
|
||||
auto constraint_filter = [this](int idx) { return m_point_types[idx] != Vertex_only; };
|
||||
auto index_to_point = [this](int idx) -> KPoint { return to_kpoint(m_points[idx]); };
|
||||
for(auto [start_idx, end_idx] : m_cst_ranges) {
|
||||
for (auto [start_idx, end_idx] : m_cst_ranges) {
|
||||
auto indexes_begin = boost::make_counting_iterator<int>(start_idx);
|
||||
auto indexes_end = boost::make_counting_iterator<int>(end_idx);
|
||||
auto filtered_begin = boost::make_filter_iterator(constraint_filter, indexes_begin, indexes_end);
|
||||
|
|
@ -197,14 +185,15 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
Arr_bounded_face_triangulator(const Bounded_render_context& ctx, Face_const_handle fh)
|
||||
: m_ctx(ctx)
|
||||
, m_fh(fh) {}
|
||||
Arr_bounded_face_triangulator(const Bounded_render_context& ctx, Face_const_handle fh) :
|
||||
m_ctx(ctx),
|
||||
m_fh(fh)
|
||||
{}
|
||||
|
||||
void push_back(Point pt) {
|
||||
CGAL_assertion_msg(m_curr_cst_begin.has_value(), "Call start_constraint() before push_back().");
|
||||
|
||||
if(m_points.size() - *m_curr_cst_begin >= 1) add_boundary_helper_point(m_points.back(), pt);
|
||||
if (m_points.size() - *m_curr_cst_begin >= 1) add_boundary_helper_point(m_points.back(), pt);
|
||||
m_points.push_back(pt);
|
||||
m_point_types.push_back(Vertex_and_constraint);
|
||||
}
|
||||
|
|
@ -216,7 +205,7 @@ public:
|
|||
|
||||
int cst_begin = *m_curr_cst_begin;
|
||||
m_curr_cst_begin.reset();
|
||||
if(m_points.size() - cst_begin <= 2) {
|
||||
if (m_points.size() - cst_begin <= 2) {
|
||||
m_points.erase(m_points.begin() + cst_begin, m_points.end());
|
||||
m_point_types.erase(m_point_types.begin() + cst_begin, m_point_types.end());
|
||||
return;
|
||||
|
|
@ -225,24 +214,23 @@ public:
|
|||
m_cst_ranges.emplace_back(cst_begin, m_points.size());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts the triangulator to a triangulated face, moving internal data to the result.
|
||||
/*! \brief Converts the triangulator to a triangulated face, moving internal data to the result.
|
||||
*
|
||||
* \return Triangulated_face
|
||||
*/
|
||||
operator Triangle_soup() && {
|
||||
CGAL_assertion_msg(!m_curr_cst_begin.has_value(), "Call end_constraint() before conversion");
|
||||
|
||||
if(m_points.empty()) return Triangle_soup();
|
||||
if (m_points.empty()) return Triangle_soup();
|
||||
if constexpr(Is_on_curved_surface) {
|
||||
if(auto it = m_ctx.m_face_points.find(m_fh); it != m_ctx.m_face_points.end()) {
|
||||
if (auto it = m_ctx.m_face_points.find(m_fh); it != m_ctx.m_face_points.end()) {
|
||||
m_points.insert(m_points.end(), it->second.begin(), it->second.end());
|
||||
m_point_types.insert(m_point_types.end(), it->second.size(), Vertex_only);
|
||||
}
|
||||
}
|
||||
insert_all_vertices();
|
||||
insert_all_constraints();
|
||||
if(m_ct.number_of_faces() == 0) return Triangle_soup();
|
||||
if (m_ct.number_of_faces() == 0) return Triangle_soup();
|
||||
|
||||
#if defined(CGAL_DRAW_AOS_DEBUG)
|
||||
debug_print(*this);
|
||||
|
|
@ -255,12 +243,12 @@ public:
|
|||
// Collect triangles within the constrained domain.
|
||||
Triangle_soup ts;
|
||||
ts.triangles.reserve(m_ct.number_of_faces());
|
||||
for(auto fit = m_ct.finite_faces_begin(); fit != m_ct.finite_faces_end(); ++fit) {
|
||||
for (auto fit = m_ct.finite_faces_begin(); fit != m_ct.finite_faces_end(); ++fit) {
|
||||
Index v1 = fit->vertex(0)->info();
|
||||
Index v2 = fit->vertex(1)->info();
|
||||
Index v3 = fit->vertex(2)->info();
|
||||
if(!v1.is_valid() || !v2.is_valid() || !v3.is_valid()) continue;
|
||||
if(!get(in_domain, fit)) continue;
|
||||
if (! v1.is_valid() || !v2.is_valid() || !v3.is_valid()) continue;
|
||||
if (! get(in_domain, fit)) continue;
|
||||
ts.triangles.push_back(Triangle{v1, v2, v3});
|
||||
}
|
||||
ts.points = std::move(m_points);
|
||||
|
|
@ -300,20 +288,20 @@ void debug_print(const Arr_bounded_face_triangulator<Arrangement>& triangulator)
|
|||
auto points_path = debug_dir / points_filename;
|
||||
std::ofstream ofs_points(points_path);
|
||||
ofs_index << points_filename << std::endl;
|
||||
for(int i = 0; i < triangulator.m_points.size(); ++i) {
|
||||
if(m_point_types[i] == Point_type::Constraint_only) continue;
|
||||
for (int i = 0; i < triangulator.m_points.size(); ++i) {
|
||||
if (m_point_types[i] == Point_type::Constraint_only) continue;
|
||||
const auto& pt = m_points[i];
|
||||
ofs_points << pt.x() << " " << pt.y() << "\n";
|
||||
}
|
||||
|
||||
int counter = 0;
|
||||
for(auto [start_idx, end_idx] : triangulator.m_cst_ranges) {
|
||||
for (auto [start_idx, end_idx] : triangulator.m_cst_ranges) {
|
||||
auto filename = ccb_constraint_file_name_prefix + "_" + std::to_string(counter++) + ".txt";
|
||||
auto filepath = debug_dir / filename;
|
||||
ofs_index << filename << std::endl;
|
||||
std::ofstream ofs_ccb_constraint(filepath);
|
||||
for(int i = start_idx; i < end_idx; ++i) {
|
||||
if(m_point_types[i] == Point_type::Vertex_only) continue;
|
||||
for (int i = start_idx; i < end_idx; ++i) {
|
||||
if (m_point_types[i] == Point_type::Vertex_only) continue;
|
||||
const auto& pt = m_points[i];
|
||||
ofs_ccb_constraint << pt.x() << " " << pt.y() << "\n";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,21 +25,20 @@
|
|||
namespace CGAL {
|
||||
namespace draw_aos {
|
||||
|
||||
/**
|
||||
* @brief Render arrangement on surface within a bounding box.
|
||||
/** @brief Render arrangement on surface within a bounding box.
|
||||
*/
|
||||
template <typename Arrangement>
|
||||
class Arr_bounded_renderer
|
||||
{
|
||||
class Arr_bounded_renderer {
|
||||
using Geom_traits = typename Arrangement::Geometry_traits_2;
|
||||
using Face_const_handle = typename Arrangement::Face_const_handle;
|
||||
using Render_context = Arr_render_context<Arrangement>;
|
||||
using Approx_cache = Arr_approximation_cache<Arrangement>;
|
||||
|
||||
public:
|
||||
Arr_bounded_renderer(const Render_context& ctx, Bbox_2 bbox)
|
||||
: m_ctx(ctx)
|
||||
, m_bbox(bbox) {}
|
||||
Arr_bounded_renderer(const Render_context& ctx, Bbox_2 bbox) :
|
||||
m_ctx(ctx),
|
||||
m_bbox(bbox)
|
||||
{}
|
||||
|
||||
Approx_cache render() const {
|
||||
Approx_cache cache;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#ifndef CGAL_DRAW_AOS_ARR_COORDINATE_CONVERTER_H
|
||||
#define CGAL_DRAW_AOS_ARR_COORDINATE_CONVERTER_H
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <CGAL/number_type_config.h>
|
||||
|
|
@ -24,33 +25,28 @@
|
|||
namespace CGAL {
|
||||
namespace draw_aos {
|
||||
|
||||
/*!
|
||||
* \brief class handling coordinate conversion between 2D parameterized surface coordinates and cartesian coordinates.
|
||||
/*! \brief class handling coordinate conversion between 2D parameterized surface coordinates and cartesian coordinates.
|
||||
*
|
||||
* \tparam GeomTraits
|
||||
*/
|
||||
template <typename GeomTraits>
|
||||
class Arr_coordinate_converter
|
||||
{
|
||||
class Arr_coordinate_converter {
|
||||
using Geom_traits = GeomTraits;
|
||||
using Approx_traits = Arr_approximate_traits<Geom_traits>;
|
||||
using Approx_point = typename Approx_traits::Approx_point;
|
||||
using Point = typename Approx_traits::Point;
|
||||
|
||||
public:
|
||||
Arr_coordinate_converter(const GeomTraits& traits)
|
||||
: m_traits(traits) {}
|
||||
Arr_coordinate_converter(const GeomTraits& traits) : m_traits(traits) {}
|
||||
|
||||
/*!
|
||||
* \brief Converts a point in cartesian coordinates to parameterized surface coordinates.
|
||||
/*! \brief converts a point in cartesian coordinates to parameterized surface coordinates.
|
||||
*
|
||||
* \param pt
|
||||
* \return Point
|
||||
*/
|
||||
Point to_uv(Approx_point pt) const { return pt; }
|
||||
|
||||
/*!
|
||||
* \brief Converts a point in parameterized surface coordinates to cartesian coordinates.
|
||||
/*! \brief Converts a point in parameterized surface coordinates to cartesian coordinates.
|
||||
*
|
||||
* \param pt
|
||||
* \return Approx_point
|
||||
|
|
@ -61,10 +57,9 @@ private:
|
|||
const GeomTraits& m_traits;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Converter specialization for geodesic arc on sphere traits.
|
||||
/*! \brief Converter specialization for geodesic arc on sphere traits.
|
||||
*
|
||||
* Provides conversions between spherical coordinates and right-handed Cartesian coordinates. Sphercial coordinates are
|
||||
* provides conversions between spherical coordinates and right-handed Cartesian coordinates. Sphercial coordinates are
|
||||
* represented as azimuth ( [0, 2 Pi) ) and polar ( [0, Pi] ) angle in radians. Points on the identification curve have
|
||||
* azimuth == 0. The south pole has polar == 0.
|
||||
*
|
||||
|
|
@ -73,8 +68,7 @@ private:
|
|||
* \tparam atanY
|
||||
*/
|
||||
template <typename Kernel, int atanX, int atanY>
|
||||
class Arr_coordinate_converter<Arr_geodesic_arc_on_sphere_traits_2<Kernel, atanX, atanY>>
|
||||
{
|
||||
class Arr_coordinate_converter<Arr_geodesic_arc_on_sphere_traits_2<Kernel, atanX, atanY>> {
|
||||
using Geom_traits = Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
|
||||
using Approx_traits = Arr_approximate_traits<Geom_traits>;
|
||||
using Approx_point = typename Approx_traits::Approx_point;
|
||||
|
|
@ -82,14 +76,13 @@ class Arr_coordinate_converter<Arr_geodesic_arc_on_sphere_traits_2<Kernel, atanX
|
|||
using Point = typename Approx_traits::Point;
|
||||
|
||||
public:
|
||||
Arr_coordinate_converter(const Geom_traits& traits)
|
||||
: m_traits(traits) {}
|
||||
Arr_coordinate_converter(const Geom_traits& traits) : m_traits(traits) {}
|
||||
|
||||
Point to_uv(Approx_point point) const {
|
||||
if(point.location() == Approx_point::MAX_BOUNDARY_LOC) return Point(0, CGAL_PI);
|
||||
if(point.location() == Approx_point::MIN_BOUNDARY_LOC) return Point(0, 0);
|
||||
Approx_nt azimuth_from_id =
|
||||
std::fmod(std::atan2(point.dy(), point.dx()) - std::atan2(atanY, atanX) + 2 * CGAL_PI, 2 * CGAL_PI);
|
||||
std::fmod(std::atan2(point.dy(), point.dx()) - std::atan2(atanY, atanX) + 2 * CGAL_PI, 2 * CGAL_PI);
|
||||
return Point(azimuth_from_id, std::acos(-point.dz()));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#ifndef CGAL_DRAW_AOS_ARR_FACE_POINT_GENERATOR_H
|
||||
#define CGAL_DRAW_AOS_ARR_FACE_POINT_GENERATOR_H
|
||||
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
|
@ -30,8 +31,7 @@
|
|||
namespace CGAL {
|
||||
namespace draw_aos {
|
||||
|
||||
/*!
|
||||
* \brief Generate face interior points.
|
||||
/*! \brief Generate face interior points.
|
||||
*
|
||||
* \tparam Arrangement
|
||||
*/
|
||||
|
|
@ -39,10 +39,9 @@ template <typename Arrangement, typename = void>
|
|||
class Arr_face_point_generator;
|
||||
|
||||
template <typename Arrangement>
|
||||
class Arr_face_point_generator<
|
||||
Arrangement,
|
||||
std::enable_if_t<!is_or_derived_from_curved_surf_traits_v<typename Arrangement::Geometry_traits_2>>>
|
||||
{
|
||||
class Arr_face_point_generator<Arrangement,
|
||||
std::enable_if_t<!is_or_derived_from_curved_surf_traits_v
|
||||
<typename Arrangement::Geometry_traits_2>>> {
|
||||
using Point_geom = typename Arr_approximate_traits<typename Arrangement::Geometry_traits_2>::Point;
|
||||
using Face_const_handle = typename Arrangement::Face_const_handle;
|
||||
|
||||
|
|
@ -55,8 +54,7 @@ public:
|
|||
|
||||
template <typename Arrangement>
|
||||
class Arr_face_point_generator<Arrangement,
|
||||
std::enable_if_t<is_or_derived_from_agas_v<typename Arrangement::Geometry_traits_2>>>
|
||||
{
|
||||
std::enable_if_t<is_or_derived_from_agas_v<typename Arrangement::Geometry_traits_2>>> {
|
||||
using Geom_traits = typename Arrangement::Geometry_traits_2;
|
||||
using Approx_traits = Arr_approximate_traits<Geom_traits>;
|
||||
using Approx_nt = typename Approx_traits::Approx_nt;
|
||||
|
|
@ -76,8 +74,8 @@ public:
|
|||
std::vector<Gt_point> points;
|
||||
Arr_coordinate_converter<Geom_traits> coords(traits);
|
||||
points.reserve(2 * CGAL_PI / cell_size * CGAL_PI / cell_size);
|
||||
for(Approx_nt x = 0; x < 2 * CGAL_PI; x += cell_size) {
|
||||
for(Approx_nt y = 0; y < CGAL_PI; y += cell_size) {
|
||||
for (Approx_nt x = 0; x < 2 * CGAL_PI; x += cell_size) {
|
||||
for (Approx_nt y = 0; y < CGAL_PI; y += cell_size) {
|
||||
auto pt = coords.to_cartesian(Point(x, y));
|
||||
points.push_back(traits.construct_point_2_object()(pt.dx(), pt.dy(), pt.dz()));
|
||||
}
|
||||
|
|
@ -86,7 +84,7 @@ public:
|
|||
unordered_flat_map<Face_const_handle, std::vector<Point>> face_points;
|
||||
CGAL::locate(arr, points.begin(), points.end(),
|
||||
boost::make_function_output_iterator([&face_points, &traits, &coords](const Query_result& res) {
|
||||
if(!std::holds_alternative<Face_const_handle>(res.second)) return;
|
||||
if (! std::holds_alternative<Face_const_handle>(res.second)) return;
|
||||
Face_const_handle fh = std::get<Face_const_handle>(res.second);
|
||||
auto [it, _] = face_points.try_emplace(fh, std::vector<Point>());
|
||||
it->second.push_back(coords.to_uv(traits.approximate_2_object()(res.first)));
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#ifndef CGAL_DRAW_AOS_ARR_RENDER_CONTEXT_H
|
||||
#define CGAL_DRAW_AOS_ARR_RENDER_CONTEXT_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
|
|
@ -36,23 +37,22 @@
|
|||
namespace CGAL {
|
||||
namespace draw_aos {
|
||||
|
||||
/**
|
||||
* @brief A cancellable context mixin for asynchronous operations. It also tracks elapsed time for performance
|
||||
/** @brief A cancellable context mixin for asynchronous operations. It also tracks elapsed time for performance
|
||||
* profiling.
|
||||
*
|
||||
* The idea is borrowed from golang with a simple implementation.
|
||||
* @see https://pkg.go.dev/context
|
||||
*/
|
||||
class Arr_cancellable_context_mixin
|
||||
{
|
||||
class Arr_cancellable_context_mixin {
|
||||
using Clock = std::chrono::steady_clock;
|
||||
using Duration = Clock::duration;
|
||||
using Time_point = std::chrono::time_point<Clock, Duration>;
|
||||
|
||||
protected:
|
||||
Arr_cancellable_context_mixin()
|
||||
: m_start_time(Clock::now())
|
||||
, m_cancelled(std::make_shared<std::atomic<bool>>(false)) {}
|
||||
Arr_cancellable_context_mixin() :
|
||||
m_start_time(Clock::now()),
|
||||
m_cancelled(std::make_shared<std::atomic<bool>>(false))
|
||||
{}
|
||||
|
||||
public:
|
||||
Time_point start_time() const { return m_start_time; }
|
||||
|
|
@ -70,23 +70,20 @@ private:
|
|||
std::shared_ptr<std::atomic<bool>> m_cancelled;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Boundary context mixin for rendering arrangements within a bounding box.
|
||||
/** @brief Boundary context mixin for rendering arrangements within a bounding box.
|
||||
* Provides extended functionality for checking point-bbox relations.
|
||||
*
|
||||
* @tparam GeomTraits the geometry traits class.
|
||||
*/
|
||||
template <typename GeomTraits>
|
||||
class Arr_bounds_context_mixin
|
||||
{
|
||||
class Arr_bounds_context_mixin {
|
||||
using Geom_traits = GeomTraits;
|
||||
using Approx_traits = Arr_approximate_traits<Geom_traits>;
|
||||
using Point = typename Approx_traits::Point;
|
||||
using Approx_nt = typename Approx_traits::Approx_nt;
|
||||
|
||||
protected:
|
||||
Arr_bounds_context_mixin(const Bbox_2& bbox)
|
||||
: m_bbox(bbox) {}
|
||||
Arr_bounds_context_mixin(const Bbox_2& bbox) : m_bbox(bbox) {}
|
||||
|
||||
public:
|
||||
double xmin() const { return m_bbox.xmin(); }
|
||||
|
|
@ -118,22 +115,22 @@ template <typename GeomTraits>
|
|||
using Arr_parameterization_context_mixin = Arr_coordinate_converter<GeomTraits>;
|
||||
|
||||
template <typename Arrangement>
|
||||
class Arr_render_context : public Arr_cancellable_context_mixin,
|
||||
public Arr_parameterization_context_mixin<typename Arrangement::Geometry_traits_2>
|
||||
{
|
||||
class Arr_render_context :
|
||||
public Arr_cancellable_context_mixin,
|
||||
public Arr_parameterization_context_mixin<typename Arrangement::Geometry_traits_2> {
|
||||
using Cancellable_context_mixin = Arr_cancellable_context_mixin;
|
||||
using Param_context_mixin = Arr_parameterization_context_mixin<typename Arrangement::Geometry_traits_2>;
|
||||
using Geom_traits = typename Arrangement::Geometry_traits_2;
|
||||
using Face_points_map = typename Arr_face_point_generator<Arrangement>::Face_points_map;
|
||||
|
||||
public:
|
||||
Arr_render_context(const Arrangement& arr, double approx_error, Face_points_map& face_points)
|
||||
: Cancellable_context_mixin()
|
||||
, Param_context_mixin(*arr.geometry_traits())
|
||||
, m_arr(arr)
|
||||
, m_traits(*arr.geometry_traits())
|
||||
, m_approx_error(approx_error)
|
||||
, m_face_points(face_points) {
|
||||
Arr_render_context(const Arrangement& arr, double approx_error, Face_points_map& face_points) :
|
||||
Cancellable_context_mixin(),
|
||||
Param_context_mixin(*arr.geometry_traits()),
|
||||
m_arr(arr),
|
||||
m_traits(*arr.geometry_traits()),
|
||||
m_approx_error(approx_error),
|
||||
m_face_points(face_points) {
|
||||
#if defined(CGAL_DRAW_AOS_DEBUG) && defined(CGAL_DRAW_AOS_TRIANGULATOR_DEBUG_FILE_DIR)
|
||||
std::filesystem::path debug_file_dir(CGAL_DRAW_AOS_TRIANGULATOR_DEBUG_FILE_DIR);
|
||||
// clear the index file.
|
||||
|
|
@ -142,9 +139,9 @@ public:
|
|||
}
|
||||
|
||||
public:
|
||||
const double m_approx_error;
|
||||
const Arrangement& m_arr;
|
||||
const Geom_traits& m_traits;
|
||||
const double m_approx_error;
|
||||
const Face_points_map& m_face_points;
|
||||
|
||||
#if defined(CGAL_DRAW_AOS_DEBUG)
|
||||
|
|
@ -153,9 +150,9 @@ public:
|
|||
};
|
||||
|
||||
template <typename Arrangement>
|
||||
class Arr_bounded_render_context : public Arr_render_context<Arrangement>,
|
||||
public Arr_bounds_context_mixin<typename Arrangement::Geometry_traits_2>
|
||||
{
|
||||
class Arr_bounded_render_context :
|
||||
public Arr_render_context<Arrangement>,
|
||||
public Arr_bounds_context_mixin<typename Arrangement::Geometry_traits_2> {
|
||||
using Geom_traits = typename Arrangement::Geometry_traits_2;
|
||||
using Approx_point = typename Geom_traits::Approximate_point_2;
|
||||
using Render_context = Arr_render_context<Arrangement>;
|
||||
|
|
@ -163,10 +160,11 @@ class Arr_bounded_render_context : public Arr_render_context<Arrangement>,
|
|||
using Approx_cache = Arr_approximation_cache<Arrangement>;
|
||||
|
||||
public:
|
||||
Arr_bounded_render_context(const Render_context& ctx, const Bbox_2& bbox, Approx_cache& cache)
|
||||
: Render_context(ctx)
|
||||
, Bounds_context_mixin(bbox)
|
||||
, m_cache(cache) {}
|
||||
Arr_bounded_render_context(const Render_context& ctx, const Bbox_2& bbox, Approx_cache& cache) :
|
||||
Render_context(ctx),
|
||||
Bounds_context_mixin(bbox),
|
||||
m_cache(cache)
|
||||
{}
|
||||
|
||||
public:
|
||||
Approx_cache& m_cache;
|
||||
|
|
@ -174,4 +172,5 @@ public:
|
|||
|
||||
} // namespace draw_aos
|
||||
} // namespace CGAL
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -21,12 +21,7 @@
|
|||
#include <cstdlib>
|
||||
#include <type_traits>
|
||||
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <QtOpenGLWidgets/QtOpenGLWidgets>
|
||||
#include <QtGui/QOpenGLFunctions>
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtGui/QKeyEvent>
|
||||
#include <QWidget>
|
||||
|
||||
#include <CGAL/Qt/Basic_viewer.h>
|
||||
#include <CGAL/Qt/camera.h>
|
||||
|
|
@ -48,8 +43,7 @@
|
|||
namespace CGAL {
|
||||
namespace draw_aos {
|
||||
|
||||
/*!
|
||||
* \brief Viewport helper functions
|
||||
/*! \brief Viewport helper functions
|
||||
*
|
||||
* \tparam Arrangement
|
||||
*/
|
||||
|
|
@ -58,10 +52,9 @@ class Arr_viewport_helpers;
|
|||
|
||||
// Specialization for planar arrangements
|
||||
template <typename Arrangement>
|
||||
class Arr_viewport_helpers<
|
||||
Arrangement,
|
||||
std::enable_if_t<!is_or_derived_from_curved_surf_traits_v<typename Arrangement::Geometry_traits_2>>>
|
||||
{
|
||||
class Arr_viewport_helpers<Arrangement,
|
||||
std::enable_if_t<! is_or_derived_from_curved_surf_traits_v
|
||||
<typename Arrangement::Geometry_traits_2>>> {
|
||||
using Geom_traits = typename Arrangement::Geometry_traits_2;
|
||||
using Approx_traits = Arr_approximate_traits<Geom_traits>;
|
||||
using Approx_point = typename Approx_traits::Approx_point;
|
||||
|
|
@ -70,22 +63,18 @@ class Arr_viewport_helpers<
|
|||
using Local_point = Buffer_for_vao::Local_point;
|
||||
|
||||
protected:
|
||||
Arr_viewport_helpers(const Arrangement& arr)
|
||||
: m_arr(arr) {}
|
||||
Arr_viewport_helpers(const Arrangement& arr) : m_arr(arr) {}
|
||||
|
||||
/*!
|
||||
* \brief Computes a subpixel-level approximation error based on the bounding box and viewport width.
|
||||
/*! \brief Computes a subpixel-level approximation error based on the bounding box and viewport width.
|
||||
*
|
||||
* \param bbox
|
||||
* \param viewport_width width of the viewport in pixels
|
||||
* \return double
|
||||
*/
|
||||
double approximation_error(const Bbox_2& bbox, int viewport_width) const {
|
||||
return bbox.x_span() / viewport_width;
|
||||
}
|
||||
double approximation_error(const Bbox_2& bbox, int viewport_width) const
|
||||
{ return bbox.x_span() / viewport_width; }
|
||||
|
||||
/*!
|
||||
* \brief Computes a parameter space bounding box that contains everything in the arrangement with some margin.
|
||||
/*! \brief Computes a parameter space bounding box that contains everything in the arrangement with some margin.
|
||||
*
|
||||
* \note For arrangement induced by unbounded curves, the bounding box only fits all vertices.
|
||||
* \return Bbox_2
|
||||
|
|
@ -94,28 +83,27 @@ protected:
|
|||
const auto& traits = *m_arr.geometry_traits();
|
||||
Bbox_2 bbox;
|
||||
// Computes a rough bounding box from the vertices.
|
||||
for(const auto& vh : m_arr.vertex_handles()) {
|
||||
for (const auto& vh : m_arr.vertex_handles())
|
||||
bbox += traits.approximate_2_object()(vh->point()).bbox();
|
||||
}
|
||||
|
||||
double approx_error = approximation_error(bbox, 100);
|
||||
// Computes a more precise bounding box from the halfedges.
|
||||
for(const auto& he : m_arr.halfedge_handles()) {
|
||||
traits.approximate_2_object()(
|
||||
he->curve(), approx_error,
|
||||
boost::make_function_output_iterator([this, &bbox](Approx_point pt) { bbox += pt.bbox(); }));
|
||||
auto approx = traits.approximate_2_object();
|
||||
for (const auto& he : m_arr.halfedge_handles()) {
|
||||
approx(he->curve(), approx_error,
|
||||
boost::make_function_output_iterator([&bbox](Approx_point pt) { bbox += pt.bbox(); }));
|
||||
}
|
||||
// Place margin around the bbox.
|
||||
double dx = bbox.x_span() * 0.1;
|
||||
double dy = bbox.y_span() * 0.1;
|
||||
bbox = Bbox_2(bbox.xmin() - dx, bbox.ymin() - dy, bbox.xmax() + dx, bbox.ymax() + dy);
|
||||
// Make sure the bbox is not degenerate.
|
||||
if(bbox.x_span() == 0) bbox += Bbox_2(bbox.xmin() - 1, bbox.ymin(), bbox.xmax() + 1, bbox.ymax());
|
||||
if(bbox.y_span() == 0) bbox += Bbox_2(bbox.xmin(), bbox.ymin() - 1, bbox.xmax(), bbox.ymax() + 1);
|
||||
if (bbox.x_span() == 0) bbox += Bbox_2(bbox.xmin() - 1, bbox.ymin(), bbox.xmax() + 1, bbox.ymax());
|
||||
if (bbox.y_span() == 0) bbox += Bbox_2(bbox.xmin(), bbox.ymin() - 1, bbox.xmax(), bbox.ymax() + 1);
|
||||
return bbox;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Fits the camera to bbox.
|
||||
/*! \brief Fits the camera to bbox.
|
||||
*
|
||||
* \param bbox
|
||||
* \param camera
|
||||
|
|
@ -125,8 +113,7 @@ protected:
|
|||
cam.fitBoundingBox(Vec(bbox.xmin(), bbox.ymin(), 0.0), Vec(bbox.xmax(), bbox.ymax(), 0.0));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Computes parameter space axis aligned bounding box from camera parameters.
|
||||
/*! \brief Computes parameter space axis aligned bounding box from camera parameters.
|
||||
*
|
||||
* \param cam
|
||||
* \return Bbox_2
|
||||
|
|
@ -142,9 +129,9 @@ protected:
|
|||
double xmax = std::numeric_limits<double>::lowest();
|
||||
double ymin = std::numeric_limits<double>::max();
|
||||
double ymax = std::numeric_limits<double>::lowest();
|
||||
for(const QVector4D& corner : clip_space_corners) {
|
||||
for (const QVector4D& corner : clip_space_corners) {
|
||||
QVector4D world = inverse_mvp * corner;
|
||||
if(world.w() != 0.0) world /= world.w();
|
||||
if (world.w() != 0.0) world /= world.w();
|
||||
double x = world.x();
|
||||
double y = world.y();
|
||||
xmin = std::min(xmin, x);
|
||||
|
|
@ -155,8 +142,7 @@ protected:
|
|||
return Bbox_2(xmin, ymin, xmax, ymax);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Converts a parameter space point to a local point of the buffer object.
|
||||
/*! \brief Converts a parameter space point to a local point of the buffer object.
|
||||
*
|
||||
* \param pt
|
||||
* \return Local_point
|
||||
|
|
@ -170,8 +156,7 @@ private:
|
|||
// Spherical arrangement specialization
|
||||
template <typename Arrangement>
|
||||
class Arr_viewport_helpers<Arrangement,
|
||||
std::enable_if_t<is_or_derived_from_agas_v<typename Arrangement::Geometry_traits_2>>>
|
||||
{
|
||||
std::enable_if_t<is_or_derived_from_agas_v<typename Arrangement::Geometry_traits_2>>> {
|
||||
using Geom_traits = typename Arrangement::Geometry_traits_2;
|
||||
using Approx_traits = Arr_approximate_traits<Geom_traits>;
|
||||
using Approx_point = typename Approx_traits::Approx_point;
|
||||
|
|
@ -180,8 +165,7 @@ class Arr_viewport_helpers<Arrangement,
|
|||
using Local_point = Buffer_for_vao::Local_point;
|
||||
|
||||
protected:
|
||||
Arr_viewport_helpers(const Arrangement& arr)
|
||||
: m_arr(arr) {}
|
||||
Arr_viewport_helpers(const Arrangement& arr) : m_arr(arr) {}
|
||||
|
||||
Bbox_2 arr_bbox() const { return Bbox_2(0, 0, 2 * CGAL_PI, CGAL_PI); }
|
||||
|
||||
|
|
@ -195,10 +179,10 @@ protected:
|
|||
|
||||
double approximation_error(const Bbox_2& bbox, int viewport_width) const {
|
||||
// If crossing hemisphere
|
||||
if(bbox.x_span() >= CGAL_PI) return 1.0 / viewport_width;
|
||||
if (bbox.x_span() >= CGAL_PI) return 1.0 / viewport_width;
|
||||
// Otherwise we evalute the error bound with respect to the longest longitude arc
|
||||
double theta =
|
||||
std::abs(bbox.ymin() - CGAL_PI / 2.0) < std::abs(bbox.ymax() - CGAL_PI / 2.0) ? bbox.ymin() : bbox.ymax();
|
||||
std::abs(bbox.ymin() - CGAL_PI / 2.0) < std::abs(bbox.ymax() - CGAL_PI / 2.0) ? bbox.ymin() : bbox.ymax();
|
||||
return bbox.x_span() * std::sin(theta) / viewport_width;
|
||||
}
|
||||
|
||||
|
|
@ -217,8 +201,7 @@ private:
|
|||
* \tparam GSOptions
|
||||
*/
|
||||
template <typename Arrangement, typename GSOptions>
|
||||
class Arr_viewer : public Qt::Basic_viewer, Arr_viewport_helpers<Arrangement>
|
||||
{
|
||||
class Arr_viewer : public Qt::Basic_viewer, Arr_viewport_helpers<Arrangement> {
|
||||
using Basic_viewer = Qt::Basic_viewer;
|
||||
using Helpers = Arr_viewport_helpers<Arrangement>;
|
||||
using Vertex_const_handle = typename Arrangement::Vertex_const_handle;
|
||||
|
|
@ -231,11 +214,10 @@ class Arr_viewer : public Qt::Basic_viewer, Arr_viewport_helpers<Arrangement>
|
|||
using Point_generator = Arr_face_point_generator<Arrangement>;
|
||||
using Faces_point_map = typename Point_generator::Face_points_map;
|
||||
|
||||
struct Render_params
|
||||
{
|
||||
bool operator==(const Render_params& other) const {
|
||||
return bbox == other.bbox && approx_error == other.approx_error;
|
||||
}
|
||||
struct Render_params {
|
||||
bool operator==(const Render_params& other) const
|
||||
{ return bbox == other.bbox && approx_error == other.approx_error; }
|
||||
|
||||
Bbox_2 bbox;
|
||||
double approx_error{0};
|
||||
};
|
||||
|
|
@ -243,9 +225,8 @@ class Arr_viewer : public Qt::Basic_viewer, Arr_viewport_helpers<Arrangement>
|
|||
constexpr static bool Is_on_curved_surface = is_or_derived_from_curved_surf_traits_v<Geom_traits>;
|
||||
|
||||
private:
|
||||
static bool contains(const Bbox_2& bbox, const Point& pt) {
|
||||
return bbox.xmin() <= pt.x() && pt.x() <= bbox.xmax() && bbox.ymin() <= pt.y() && pt.y() <= bbox.ymax();
|
||||
}
|
||||
static bool contains(const Bbox_2& bbox, const Point& pt)
|
||||
{ return bbox.xmin() <= pt.x() && pt.x() <= bbox.xmax() && bbox.ymin() <= pt.y() && pt.y() <= bbox.ymax(); }
|
||||
|
||||
int viewport_width() const {
|
||||
std::array<GLint, 4> viewport;
|
||||
|
|
@ -268,56 +249,53 @@ private:
|
|||
auto cache = renderer.render();
|
||||
|
||||
// add faces
|
||||
for(const auto& [fh, tf] : cache.faces()) {
|
||||
if(!m_gso.draw_face(m_arr, fh)) continue;
|
||||
for (const auto& [fh, tf] : cache.faces()) {
|
||||
if (! m_gso.draw_face(m_arr, fh)) continue;
|
||||
bool colored_face = m_gso.colored_face(m_arr, fh);
|
||||
auto color = colored_face ? m_gso.face_color(m_arr, fh) : CGAL::IO::Color();
|
||||
for(const auto& tri : tf.triangles) {
|
||||
if(colored_face)
|
||||
m_gs.face_begin(color);
|
||||
else
|
||||
m_gs.face_begin();
|
||||
for(const auto i : tri) m_gs.add_point_in_face(this->to_local_point(tf.points[i]));
|
||||
for (const auto& tri : tf.triangles) {
|
||||
if (colored_face) m_gs.face_begin(color);
|
||||
else m_gs.face_begin();
|
||||
for (const auto i : tri) m_gs.add_point_in_face(this->to_local_point(tf.points[i]));
|
||||
m_gs.face_end();
|
||||
}
|
||||
}
|
||||
// add edges
|
||||
for(const auto& [he, polyline] : cache.halfedges()) {
|
||||
if(he->direction() == ARR_RIGHT_TO_LEFT || !m_gso.draw_edge(m_arr, he) || polyline.size() < 2) continue;
|
||||
for (const auto& [he, polyline] : cache.halfedges()) {
|
||||
if (he->direction() == ARR_RIGHT_TO_LEFT || !m_gso.draw_edge(m_arr, he) || polyline.size() < 2) continue;
|
||||
bool colored_edge = m_gso.colored_edge(m_arr, he);
|
||||
auto color = colored_edge ? m_gso.edge_color(m_arr, he) : CGAL::IO::Color();
|
||||
// skip first two if starts with a sep point.
|
||||
int start_idx = Approx_traits::is_null(polyline.front()) ? 2 : 0;
|
||||
// skip last two if ends with a sep point.
|
||||
int end_idx = Approx_traits::is_null(polyline.back()) ? polyline.size() - 2 : polyline.size();
|
||||
for(int i = start_idx; i < end_idx - 1; ++i) {
|
||||
for (int i = start_idx; i < end_idx - 1; ++i) {
|
||||
const auto& src = polyline[i];
|
||||
const auto& tgt = polyline[i + 1];
|
||||
if(Approx_traits::is_null(src) || Approx_traits::is_null(tgt)) continue;
|
||||
if(!contains(bbox, src) || !contains(bbox, tgt)) continue;
|
||||
if(colored_edge)
|
||||
if (Approx_traits::is_null(src) || Approx_traits::is_null(tgt)) continue;
|
||||
if (! contains(bbox, src) || !contains(bbox, tgt)) continue;
|
||||
if (colored_edge)
|
||||
m_gs.add_segment(this->to_local_point(src), this->to_local_point(tgt), color);
|
||||
else
|
||||
m_gs.add_segment(this->to_local_point(src), this->to_local_point(tgt));
|
||||
}
|
||||
}
|
||||
// add vertices
|
||||
for(const auto& [vh, pt] : cache.vertices()) {
|
||||
if(!m_gso.draw_vertex(m_arr, vh) || !contains(bbox, pt)) continue;
|
||||
if(m_gso.colored_vertex(m_arr, vh))
|
||||
for (const auto& [vh, pt] : cache.vertices()) {
|
||||
if (! m_gso.draw_vertex(m_arr, vh) || !contains(bbox, pt)) continue;
|
||||
if (m_gso.colored_vertex(m_arr, vh))
|
||||
m_gs.add_point(this->to_local_point(pt), m_gso.vertex_color(m_arr, vh));
|
||||
else
|
||||
m_gs.add_point(this->to_local_point(pt));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Rerender scene within the given bounding box.
|
||||
|
||||
/*! \brief Rerender scene within the given bounding box.
|
||||
*
|
||||
* \param bbox
|
||||
*/
|
||||
void rerender(const Render_params& params) {
|
||||
if(params == m_last_params) return;
|
||||
if (params == m_last_params) return;
|
||||
m_last_params = params;
|
||||
m_gs.clear();
|
||||
render_arr(params);
|
||||
|
|
@ -325,13 +303,13 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
Arr_viewer(QWidget* parent, const Arrangement& arr, const GSOptions& gso, const char* title, Bbox_2 initial_bbox)
|
||||
: Basic_viewer(parent, m_gs, title)
|
||||
, Helpers(arr)
|
||||
, m_gso(gso)
|
||||
, m_arr(arr)
|
||||
, m_coords(*arr.geometry_traits()) {
|
||||
if(initial_bbox.x_span() == 0 || initial_bbox.y_span() == 0 || Is_on_curved_surface)
|
||||
Arr_viewer(QWidget* parent, const Arrangement& arr, const GSOptions& gso, const char* title, Bbox_2 initial_bbox) :
|
||||
Basic_viewer(parent, m_gs, title),
|
||||
Helpers(arr),
|
||||
m_gso(gso),
|
||||
m_arr(arr),
|
||||
m_coords(*arr.geometry_traits()) {
|
||||
if ((initial_bbox.x_span() == 0) || (initial_bbox.y_span() == 0) || (Is_on_curved_surface))
|
||||
m_initial_bbox = this->arr_bbox();
|
||||
else
|
||||
m_initial_bbox = initial_bbox;
|
||||
|
|
@ -341,7 +319,7 @@ public:
|
|||
Render_params params = compute_render_params();
|
||||
|
||||
#if defined(CGAL_DRAW_AOS_DEBUG)
|
||||
if constexpr(!is_or_derived_from_agas_v<Geom_traits>) {
|
||||
if constexpr(! is_or_derived_from_agas_v<Geom_traits>) {
|
||||
Bbox_2& bbox = params.bbox;
|
||||
double dx = (bbox.xmax() - bbox.xmin()) * 0.1;
|
||||
double dy = (bbox.ymax() - bbox.ymin()) * 0.1;
|
||||
|
|
@ -352,7 +330,7 @@ public:
|
|||
|
||||
rerender(params);
|
||||
|
||||
if(!m_initialized) {
|
||||
if (! m_initialized) {
|
||||
// The initial render must be done with original camera parameters or the width of edges gets exaggerated.
|
||||
// So we fit the camera after initial render.
|
||||
this->fit_camera(m_initial_bbox, *this->camera_);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#ifndef CGAL_DRAW_AOS_TYPE_UTILS_H
|
||||
#define CGAL_DRAW_AOS_TYPE_UTILS_H
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
|
@ -34,8 +35,7 @@ enum class Boundary_side {
|
|||
};
|
||||
|
||||
template <typename, typename = std::void_t<>>
|
||||
struct has_approximate_2_object : std::false_type
|
||||
{};
|
||||
struct has_approximate_2_object : std::false_type {};
|
||||
|
||||
template <typename Gt>
|
||||
struct has_approximate_2_object<Gt, std::void_t<decltype(std::declval<Gt>().approximate_2_object())>> : std::true_type
|
||||
|
|
@ -46,14 +46,13 @@ template <typename Gt>
|
|||
inline constexpr bool has_approximate_2_object_v = has_approximate_2_object<Gt>::value;
|
||||
|
||||
template <typename, typename, typename = std::void_t<>>
|
||||
struct has_approximate_point : std::false_type
|
||||
{};
|
||||
struct has_approximate_point : std::false_type {};
|
||||
|
||||
template <typename Gt, typename A>
|
||||
struct has_approximate_point<Gt,
|
||||
A,
|
||||
std::void_t<decltype(std::declval<A>()(std::declval<const typename Gt::Point_2&>()))>>
|
||||
: std::true_type
|
||||
std::void_t<decltype(std::declval<A>()(std::declval<const typename Gt::Point_2&>()))>> :
|
||||
std::true_type
|
||||
{};
|
||||
|
||||
// Detect whether A has operator()(const Gt::Point_2&)
|
||||
|
|
@ -61,18 +60,17 @@ template <typename Gt, typename A>
|
|||
inline constexpr bool has_approximate_point_v = has_approximate_point<Gt, A>::value;
|
||||
|
||||
template <typename, typename, typename, typename = std::void_t<>>
|
||||
struct has_approximate_xcv : std::false_type
|
||||
{};
|
||||
struct has_approximate_xcv : std::false_type {};
|
||||
|
||||
template <typename Gt, typename A, typename O>
|
||||
struct has_approximate_xcv<
|
||||
Gt,
|
||||
A,
|
||||
O,
|
||||
std::void_t<decltype(std::declval<A&>()(std::declval<const typename Gt::X_monotone_curve_2&>(),
|
||||
std::declval<double>(),
|
||||
std::declval<O>(),
|
||||
std::declval<bool>()))>> : std::true_type
|
||||
struct has_approximate_xcv
|
||||
<Gt,
|
||||
A,
|
||||
O,
|
||||
std::void_t<decltype(std::declval<A&>()(std::declval<const typename Gt::X_monotone_curve_2&>(),
|
||||
std::declval<double>(),
|
||||
std::declval<O>(),
|
||||
std::declval<bool>()))>> : std::true_type
|
||||
{};
|
||||
|
||||
// Detect whether A has operator()(const Gt::X_monotone_curve_2&, double, OutputIterator, bool)?
|
||||
|
|
@ -84,15 +82,15 @@ struct has_approximate_xcv_with_bounds : std::false_type
|
|||
{};
|
||||
|
||||
template <typename Gt, typename A, typename O>
|
||||
struct has_approximate_xcv_with_bounds<
|
||||
Gt,
|
||||
A,
|
||||
O,
|
||||
std::void_t<decltype(std::declval<A&>()(std::declval<const typename Gt::X_monotone_curve_2&>(),
|
||||
std::declval<double>(),
|
||||
std::declval<O>(),
|
||||
std::declval<Bbox_2>(),
|
||||
std::declval<bool>()))>> : std::true_type
|
||||
struct has_approximate_xcv_with_bounds
|
||||
<Gt,
|
||||
A,
|
||||
O,
|
||||
std::void_t<decltype(std::declval<A&>()(std::declval<const typename Gt::X_monotone_curve_2&>(),
|
||||
std::declval<double>(),
|
||||
std::declval<O>(),
|
||||
std::declval<Bbox_2>(),
|
||||
std::declval<bool>()))>> : std::true_type
|
||||
{};
|
||||
|
||||
// Detect whether A has operator()(const X_monotone_curve&, double, OutputIterator, Bbox_2, bool)
|
||||
|
|
@ -102,9 +100,9 @@ inline constexpr bool has_approximate_xcv_with_bounds_v = has_approximate_xcv_wi
|
|||
// Detect whether a geometry traits has all the necessary types and functions for approximation
|
||||
template <typename Gt>
|
||||
constexpr bool has_approximate_traits_v =
|
||||
has_approximate_2_object_v<Gt> && has_approximate_point_v<Gt, typename Gt::Approximate_2> &&
|
||||
(has_approximate_xcv_v<Gt, typename Gt::Approximate_2> ||
|
||||
has_approximate_xcv_with_bounds_v<Gt, typename Gt::Approximate_2>);
|
||||
has_approximate_2_object_v<Gt> && has_approximate_point_v<Gt, typename Gt::Approximate_2> &&
|
||||
(has_approximate_xcv_v<Gt, typename Gt::Approximate_2> ||
|
||||
has_approximate_xcv_with_bounds_v<Gt, typename Gt::Approximate_2>);
|
||||
|
||||
template <typename Gt, typename = std::void_t<>>
|
||||
struct has_is_in_x_range : std::false_type
|
||||
|
|
@ -112,8 +110,8 @@ struct has_is_in_x_range : std::false_type
|
|||
|
||||
template <typename Gt>
|
||||
struct has_is_in_x_range<Gt,
|
||||
std::void_t<decltype(std::declval<typename Gt::X_monotone_curve_2>().is_in_x_range(
|
||||
std::declval<const typename Gt::Point_2&>()))>> : std::true_type
|
||||
std::void_t<decltype(std::declval<typename Gt::X_monotone_curve_2>().is_in_x_range
|
||||
(std::declval<const typename Gt::Point_2&>()))>> : std::true_type
|
||||
{};
|
||||
|
||||
// Detect whether Gt::X_monotone_curve_2 has a member function bool is_in_x_range(const Gt::Point_2&)
|
||||
|
|
@ -122,8 +120,7 @@ inline constexpr bool has_is_in_x_range_v = has_is_in_x_range<Gt>::value;
|
|||
|
||||
// Detect whether Gt is or derives from Arr_geodesic_arc_on_sphere_traits_2<*, *, *>
|
||||
template <typename Gt>
|
||||
struct is_or_derived_from_agas
|
||||
{
|
||||
struct is_or_derived_from_agas {
|
||||
private:
|
||||
template <typename Kernel_, int AtanX, int AtanY>
|
||||
static std::true_type test(const Arr_geodesic_arc_on_sphere_traits_2<Kernel_, AtanX, AtanY>*);
|
||||
|
|
@ -143,30 +140,25 @@ inline constexpr bool is_or_derived_from_curved_surf_traits_v = is_or_derived_fr
|
|||
|
||||
// Static helpers to get template arguments from a geometry traits
|
||||
template <typename Gt>
|
||||
struct tmpl_args
|
||||
{};
|
||||
struct tmpl_args {};
|
||||
|
||||
template <typename Kernel_, int AtanX, int AtanY>
|
||||
struct tmpl_args<Arr_geodesic_arc_on_sphere_traits_2<Kernel_, AtanX, AtanY>>
|
||||
{
|
||||
struct tmpl_args<Arr_geodesic_arc_on_sphere_traits_2<Kernel_, AtanX, AtanY>> {
|
||||
using Kernel = Kernel_;
|
||||
static constexpr int atan_x = AtanX;
|
||||
static constexpr int atan_y = AtanY;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Approximation data types
|
||||
/*! \brief Approximation data types
|
||||
*
|
||||
* \tparam Gt Geometry traits
|
||||
*/
|
||||
template <typename Gt>
|
||||
class Arr_approximate_traits
|
||||
{
|
||||
class Arr_approximate_traits {
|
||||
using Geom_traits = Gt;
|
||||
|
||||
template <typename P, typename I>
|
||||
struct Triangle_soup_
|
||||
{
|
||||
struct Triangle_soup_ {
|
||||
using Index = I;
|
||||
using Triangle = std::array<Index, 3>;
|
||||
using Point = P;
|
||||
|
|
@ -198,8 +190,7 @@ public:
|
|||
* \tparam Gt Geometry traits
|
||||
*/
|
||||
template <typename Gt>
|
||||
class Construct_gt_point_2
|
||||
{
|
||||
class Construct_gt_point_2 {
|
||||
using Approx_traits = Arr_approximate_traits<Gt>;
|
||||
using Approx_point = typename Approx_traits::Approx_point;
|
||||
using Gt_point = typename Gt::Point_2;
|
||||
|
|
@ -210,8 +201,7 @@ public:
|
|||
|
||||
// Specialization for Arr_geodesic_arc_on_sphere_traits_2
|
||||
template <typename Kernel, int AtanX, int AtanY>
|
||||
class Construct_gt_point_2<Arr_geodesic_arc_on_sphere_traits_2<Kernel, AtanX, AtanY>>
|
||||
{
|
||||
class Construct_gt_point_2<Arr_geodesic_arc_on_sphere_traits_2<Kernel, AtanX, AtanY>> {
|
||||
using Geom_traits = Arr_geodesic_arc_on_sphere_traits_2<Kernel, AtanX, AtanY>;
|
||||
using Approx_traits = Arr_approximate_traits<Arr_geodesic_arc_on_sphere_traits_2<Kernel, AtanX, AtanY>>;
|
||||
using Approx_point = typename Approx_traits::Approx_point;
|
||||
|
|
@ -220,7 +210,8 @@ class Construct_gt_point_2<Arr_geodesic_arc_on_sphere_traits_2<Kernel, AtanX, At
|
|||
public:
|
||||
Gt_point operator()(const Approx_point& pt) const {
|
||||
using Direction_3 = typename Kernel::Direction_3;
|
||||
return Gt_point(Direction_3(pt.dx(), pt.dy(), pt.dz()), static_cast<typename Gt_point::Location_type>(pt.location()));
|
||||
return Gt_point(Direction_3(pt.dx(), pt.dy(), pt.dz()),
|
||||
static_cast<typename Gt_point::Location_type>(pt.location()));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include <CGAL/Arr_geodesic_arc_on_sphere_traits_2.h>
|
||||
#include <CGAL/Arrangement_2.h>
|
||||
#include <CGAL/Arrangement_on_surface_2.h>
|
||||
|
|
@ -132,29 +134,24 @@ public:
|
|||
|
||||
//!
|
||||
template <typename T, typename A, std::enable_if_t<!has_approximate_point_v<T, A>, int> = 0>
|
||||
void draw_region_impl2(const T& /* traits */, const A& /* approximate */, Halfedge_const_handle curr) {
|
||||
draw_exact_region(curr);
|
||||
}
|
||||
void draw_region_impl2(const T& /* traits */, const A& /* approximate */, Halfedge_const_handle curr)
|
||||
{ draw_exact_region(curr); }
|
||||
|
||||
//!
|
||||
template <typename T, typename A, std::enable_if_t<has_approximate_point_v<T, A>, int> = 0>
|
||||
auto draw_region_impl2(const T& /* traits */, const A& approx, Halfedge_const_handle curr) {
|
||||
draw_approximate_region(curr, approx);
|
||||
}
|
||||
auto draw_region_impl2(const T& /* traits */, const A& approx, Halfedge_const_handle curr)
|
||||
{ draw_approximate_region(curr, approx); }
|
||||
|
||||
/*! draws a region, where the traits does not has approximate_2_object.
|
||||
*/
|
||||
template <typename T, std::enable_if_t<!has_approximate_2_object_v<T> && !is_or_derived_from_agas_v<T>, int> = 0>
|
||||
void draw_region_impl1(const T& /* traits */, Halfedge_const_handle curr) {
|
||||
draw_exact_region(curr);
|
||||
}
|
||||
void draw_region_impl1(const T& /* traits */, Halfedge_const_handle curr)
|
||||
{ draw_exact_region(curr); }
|
||||
|
||||
///
|
||||
template <typename T, std::enable_if_t<has_approximate_2_object_v<T> && !is_or_derived_from_agas_v<T>, int> = 0>
|
||||
auto draw_region_impl1(const T& traits, Halfedge_const_handle curr) {
|
||||
using Approximate = typename Gt::Approximate_2;
|
||||
draw_region_impl2(traits, traits.approximate_2_object(), curr);
|
||||
}
|
||||
auto draw_region_impl1(const T& traits, Halfedge_const_handle curr)
|
||||
{ draw_region_impl2(traits, traits.approximate_2_object(), curr); }
|
||||
|
||||
/*! draws a geodesic region
|
||||
*/
|
||||
|
|
@ -191,10 +188,8 @@ public:
|
|||
auto ctr_min = traits->construct_min_vertex_2_object();
|
||||
auto ctr_max = traits->construct_max_vertex_2_object();
|
||||
m_gs.add_segment(ctr_min(curve), ctr_max(curve));
|
||||
if (colored)
|
||||
m_gs.add_segment(ctr_min(curve), ctr_max(curve), c);
|
||||
else
|
||||
m_gs.add_segment(ctr_min(curve), ctr_max(curve));
|
||||
if (colored) m_gs.add_segment(ctr_min(curve), ctr_max(curve), c);
|
||||
else m_gs.add_segment(ctr_min(curve), ctr_max(curve));
|
||||
}
|
||||
|
||||
/*! draws a region in an exact manner.
|
||||
|
|
@ -204,9 +199,8 @@ public:
|
|||
|
||||
//! Add all faces.
|
||||
template <typename Traits>
|
||||
void add_faces(const Traits&) {
|
||||
for (auto it = m_aos.unbounded_faces_begin(); it != m_aos.unbounded_faces_end(); ++it) add_face(it);
|
||||
}
|
||||
void add_faces(const Traits&)
|
||||
{ for (auto it = m_aos.unbounded_faces_begin(); it != m_aos.unbounded_faces_end(); ++it) add_face(it); }
|
||||
|
||||
//! Compile time dispatching
|
||||
|
||||
|
|
@ -214,47 +208,39 @@ public:
|
|||
*/
|
||||
template <typename Approximate>
|
||||
void draw_approximate_point(const Point& p, const Approximate& approx, bool colored, const CGAL::IO::Color& color) {
|
||||
if (colored)
|
||||
m_gs.add_point(approx(p), color);
|
||||
else
|
||||
m_gs.add_point(approx(p));
|
||||
if (colored) m_gs.add_point(approx(p), color);
|
||||
else m_gs.add_point(approx(p));
|
||||
}
|
||||
|
||||
//!
|
||||
void draw_exact_point(const Point& p, bool colored, const CGAL::IO::Color& color) {
|
||||
if (colored)
|
||||
m_gs.add_point(p, color);
|
||||
else
|
||||
m_gs.add_point(p);
|
||||
if (colored) m_gs.add_point(p, color);
|
||||
else m_gs.add_point(p);
|
||||
}
|
||||
|
||||
//!
|
||||
template <typename T, typename A, std::enable_if_t<!has_approximate_point_v<T, A>, int> = 0>
|
||||
void draw_point_impl2(
|
||||
const T& /* traits */, const A& /* approximate */, const Point& p, bool colored, const CGAL::IO::Color& c) {
|
||||
draw_exact_point(p, colored, c);
|
||||
}
|
||||
void draw_point_impl2(const T& /* traits */, const A& /* approximate */, const Point& p, bool colored,
|
||||
const CGAL::IO::Color& c)
|
||||
{ draw_exact_point(p, colored, c); }
|
||||
|
||||
//!
|
||||
template <typename T, typename A, std::enable_if_t<has_approximate_point_v<T, A>, int> = 0>
|
||||
auto
|
||||
draw_point_impl2(const T& /* traits */, const A& approx, const Point& p, bool colored, const CGAL::IO::Color& c) {
|
||||
draw_approximate_point(p, approx, colored, c);
|
||||
}
|
||||
draw_point_impl2(const T& /* traits */, const A& approx, const Point& p, bool colored, const CGAL::IO::Color& c)
|
||||
{ draw_approximate_point(p, approx, colored, c); }
|
||||
|
||||
/*! draws a point, where the traits does not has approximate_2_object.
|
||||
*/
|
||||
template <typename T, std::enable_if_t<!has_approximate_2_object_v<T> && !is_or_derived_from_agas_v<T>, int> = 0>
|
||||
void draw_point_impl1(const T& /* traits */, const Point& p, bool colored, const CGAL::IO::Color& c) {
|
||||
draw_exact_point(p, colored, c);
|
||||
}
|
||||
void draw_point_impl1(const T& /* traits */, const Point& p, bool colored, const CGAL::IO::Color& c)
|
||||
{ draw_exact_point(p, colored, c); }
|
||||
|
||||
/*! draws a point, where the traits does have approximate_2_object.
|
||||
*/
|
||||
template <typename T, std::enable_if_t<has_approximate_2_object_v<T> && !is_or_derived_from_agas_v<T>, int> = 0>
|
||||
auto draw_point_impl1(const T& traits, const Point& p, bool colored, const CGAL::IO::Color& c) {
|
||||
draw_point_impl2(traits, traits.approximate_2_object(), p, colored, c);
|
||||
}
|
||||
auto draw_point_impl1(const T& traits, const Point& p, bool colored, const CGAL::IO::Color& c)
|
||||
{ draw_point_impl2(traits, traits.approximate_2_object(), p, colored, c); }
|
||||
|
||||
/*! draws a geodesic point.
|
||||
*/
|
||||
|
|
@ -271,10 +257,8 @@ public:
|
|||
auto z = ap.dz();
|
||||
auto l = std::sqrt(x * x + y * y + z * z);
|
||||
Approx_point_3 p3(x / l, y / l, z / l);
|
||||
if (colored)
|
||||
m_gs.add_point(p3, color);
|
||||
else
|
||||
m_gs.add_point(p3);
|
||||
if (colored) m_gs.add_point(p3, color);
|
||||
else m_gs.add_point(p3);
|
||||
}
|
||||
|
||||
//! draws a point.
|
||||
|
|
@ -386,10 +370,8 @@ public:
|
|||
auto it = polyline.begin();
|
||||
auto prev = it++;
|
||||
for (; it != polyline.end(); prev = it++) {
|
||||
if (colored)
|
||||
m_gs.add_segment(*prev, *it, c);
|
||||
else
|
||||
m_gs.add_segment(*prev, *it);
|
||||
if (colored) m_gs.add_segment(*prev, *it, c);
|
||||
else m_gs.add_segment(*prev, *it);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -399,23 +381,20 @@ public:
|
|||
const A& /* approximate */,
|
||||
const X_monotone_curve& xcv,
|
||||
bool colored,
|
||||
const CGAL::IO::Color& c) {
|
||||
draw_exact_curve(xcv, colored, c);
|
||||
}
|
||||
const CGAL::IO::Color& c)
|
||||
{ draw_exact_curve(xcv, colored, c); }
|
||||
|
||||
///
|
||||
template <typename T, typename A, std::enable_if_t<has_approximate_point_v<T, A>, int> = 0>
|
||||
auto draw_curve_impl2(
|
||||
const T& /* traits */, const A& approx, const X_monotone_curve& xcv, bool colored, const CGAL::IO::Color& c) {
|
||||
draw_approximate_curve(xcv, approx, colored, c);
|
||||
}
|
||||
auto draw_curve_impl2(const T& /* traits */, const A& approx, const X_monotone_curve& xcv, bool colored,
|
||||
const CGAL::IO::Color& c)
|
||||
{ draw_approximate_curve(xcv, approx, colored, c); }
|
||||
|
||||
/*! draws a curve, where the traits does not has approximate_2_object.
|
||||
*/
|
||||
template <typename T, std::enable_if_t<!has_approximate_2_object_v<T> && !is_or_derived_from_agas_v<T>, int> = 0>
|
||||
void draw_curve_impl1(const T& /* traits */, const X_monotone_curve& xcv, bool colored, const CGAL::IO::Color& c) {
|
||||
draw_exact_curve(xcv, colored, c);
|
||||
}
|
||||
void draw_curve_impl1(const T& /* traits */, const X_monotone_curve& xcv, bool colored, const CGAL::IO::Color& c)
|
||||
{ draw_exact_curve(xcv, colored, c); }
|
||||
|
||||
/*! draws a curve, where the traits does have approximate_2_object.
|
||||
*/
|
||||
|
|
@ -431,7 +410,6 @@ public:
|
|||
void draw_curve_impl1(const T& traits, const X_monotone_curve& xcv, bool colored, const CGAL::IO::Color& c) {
|
||||
// std::cout << "draw_curve (geodesic)\n";
|
||||
using Traits = T;
|
||||
using Kernel = typename Traits::Kernel;
|
||||
using Ak = typename Traits::Approximate_kernel;
|
||||
using Ap = typename Traits::Approximate_point_2;
|
||||
using Approx_point_3 = typename Ak::Point_3;
|
||||
|
|
@ -452,10 +430,8 @@ public:
|
|||
auto z = it->dz();
|
||||
auto l = std::sqrt(x * x + y * y + z * z);
|
||||
Approx_point_3 next(x / l, y / l, z / l);
|
||||
if (colored)
|
||||
m_gs.add_segment(prev, next, c);
|
||||
else
|
||||
m_gs.add_segment(prev, next);
|
||||
if (colored) m_gs.add_segment(prev, next, c);
|
||||
else m_gs.add_segment(prev, next);
|
||||
prev = next;
|
||||
}
|
||||
}
|
||||
|
|
@ -535,11 +511,10 @@ protected:
|
|||
m_halfedge_map[e->twin()] = Halfedge_const_handle(); // twin is created as well
|
||||
}
|
||||
|
||||
virtual void before_split_edge(Halfedge_handle e, Vertex_handle v,
|
||||
const X_monotone_curve_2& c1,
|
||||
const X_monotone_curve_2& c2) override {
|
||||
if (m_vertex_map.find(v) == m_vertex_map.end()) m_vertex_map[v] = Vertex_const_handle(); // v is newly created
|
||||
}
|
||||
virtual void before_split_edge(Halfedge_handle /* e */, Vertex_handle v,
|
||||
const X_monotone_curve_2& /* c1 */,
|
||||
const X_monotone_curve_2& /* c2 */) override
|
||||
{ if (m_vertex_map.find(v) == m_vertex_map.end()) m_vertex_map[v] = Vertex_const_handle(); }
|
||||
|
||||
virtual void after_split_edge(Halfedge_handle e1, Halfedge_handle e2) override {
|
||||
if (auto it = m_halfedge_map.find(e1); it == m_halfedge_map.end())
|
||||
|
|
@ -597,8 +572,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
/*!
|
||||
* Maps tracking the changes between the original arrangement and modified arrangement.
|
||||
/*! maps tracking the changes between the original arrangement and modified arrangement.
|
||||
* The key is the current feature, and the value is the corresponding feature before modification.
|
||||
* If there is no entry about a feature, the corresponding feature is itself.
|
||||
* If the value is a invalid handle, it means that the feature is newly created and thus has no corresponding
|
||||
|
|
@ -774,15 +748,15 @@ void draw(const Arrangement& arr,
|
|||
gso.enable_vertices();
|
||||
gso.draw_vertex = [](const Arrangement&, const Vertex_const_handle&) { return true; };
|
||||
gso.colored_vertex = [](const Arrangement&, const Vertex_const_handle&) { return true; };
|
||||
gso.vertex_color = [](const Arrangement&, const Vertex_const_handle& vh) -> CGAL::IO::Color {
|
||||
return CGAL::IO::Color(255, 0, 0);
|
||||
};
|
||||
gso.vertex_color = [](const Arrangement&, const Vertex_const_handle& /* vh */) -> CGAL::IO::Color
|
||||
{ return CGAL::IO::Color(255, 0, 0); };
|
||||
|
||||
gso.enable_edges();
|
||||
gso.draw_edge = [](const Arrangement&, const Halfedge_const_handle&) { return true; };
|
||||
gso.colored_edge = [](const Arrangement&, const Halfedge_const_handle&) { return true; };
|
||||
gso.edge_color = [](const Arrangement&, const Halfedge_const_handle& heh) -> CGAL::IO::Color {
|
||||
return CGAL::IO::Color(0, 0, 0);
|
||||
};
|
||||
gso.edge_color = [](const Arrangement&, const Halfedge_const_handle& /* heh */) -> CGAL::IO::Color
|
||||
{ return CGAL::IO::Color(0, 0, 0); };
|
||||
|
||||
gso.enable_faces();
|
||||
gso.draw_face = [](const Arrangement&, const Face_const_handle&) { return true; };
|
||||
gso.colored_face = [](const Arrangement&, const Face_const_handle&) { return true; };
|
||||
|
|
@ -807,8 +781,8 @@ void add_to_graphics_scene(const CGAL_ARR_TYPE& aos, CGAL::Graphics_scene& graph
|
|||
template <typename GeometryTraits_2, typename TopologyTraits>
|
||||
void add_to_graphics_scene(const CGAL_ARR_TYPE& aos, CGAL::Graphics_scene& graphics_scene) {
|
||||
CGAL::Graphics_scene_options<CGAL_ARR_TYPE, typename CGAL_ARR_TYPE::Vertex_const_handle,
|
||||
typename CGAL_ARR_TYPE::Halfedge_const_handle, typename CGAL_ARR_TYPE::Face_const_handle>
|
||||
gso;
|
||||
typename CGAL_ARR_TYPE::Halfedge_const_handle,
|
||||
typename CGAL_ARR_TYPE::Face_const_handle> gso;
|
||||
// colored face?
|
||||
gso.colored_face = [](const CGAL_ARR_TYPE&, typename CGAL_ARR_TYPE::Face_const_handle) -> bool { return true; };
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue