diff --git a/Curved_kernel_via_analysis_2/include/CGAL/Curved_kernel_via_analysis_2/Curve_renderer_facade.h b/Curved_kernel_via_analysis_2/include/CGAL/Curved_kernel_via_analysis_2/Curve_renderer_facade.h index 2cfb8feeeca..f9aa8728154 100644 --- a/Curved_kernel_via_analysis_2/include/CGAL/Curved_kernel_via_analysis_2/Curve_renderer_facade.h +++ b/Curved_kernel_via_analysis_2/include/CGAL/Curved_kernel_via_analysis_2/Curve_renderer_facade.h @@ -212,7 +212,9 @@ public: //! the drawing window inline void get_setup_parameters(CGAL::Bbox_2 *pbox, int& res_w, int& res_h) { +#ifndef CGAL_CKVA_DUMMY_RENDERER return renderer().get_setup_parameters(pbox, res_w, res_h); +#endif } /*!\brief @@ -226,30 +228,32 @@ public: { #ifndef CGAL_CKVA_DUMMY_RENDERER renderer().setup(bbox, res_w, res_h); -#endif // !CGAL_CKVA_DUMMY_RENDERER +#endif } /*!\brief * rasterizes an x-monotone curve \c arc * - * outputs the list of sequences of pixel coordinates as objects of type - * \c Coord_2 to the output iterator \c pts , end-point coordinates are - * returned as a two-tuple \c end_pts - * - * \c Container must support \c push_back and \c clear operations + * inserts the list of sequences of pixel coordinates as objects of type + * \c Coord_2 to \c pts , \c Container must support \c push_back and \c + * clear operations * * \c Coord_2 must be constructible from a pair of integers / doubles - * depending on the renderer type + * depending on the renderer type + * + * computes optionaly end-point coordinates (even if they lie outside the + * window) */ template < class Coord_2, template < class > class Container > inline void draw(const Arc_2& arc, Container< std::vector >& pts, - boost::array< Coord_2, 2 >& end_pts) { + boost::optional< Coord_2 > *end_pt1 = NULL, + boost::optional< Coord_2 > *end_pt2 = NULL) { #ifndef CGAL_CKVA_DUMMY_RENDERER Bbox_2 bbox; int res_w, res_h; try { - renderer().draw(arc, pts, end_pts); + renderer().draw(arc, pts, end_pt1, end_pt2); } catch(CGALi::Insufficient_rasterize_precision_exception) { std::cerr << "Switching to multi-precision arithmetic" << @@ -263,7 +267,7 @@ public: bigfloat_renderer().setup(bbox, res_w, res_h); try { pts.clear(); - bigfloat_renderer().draw(arc, pts, end_pts); + bigfloat_renderer().draw(arc, pts, end_pt1, end_pt2); return; } catch(CGALi::Insufficient_rasterize_precision_exception) { @@ -280,7 +284,7 @@ public: exact_renderer().setup(bbox, res_w, res_h); try { pts.clear(); - exact_renderer().draw(arc, pts, end_pts); + exact_renderer().draw(arc, pts, end_pt1, end_pt2); return; } catch(CGALi::Insufficient_rasterize_precision_exception) { diff --git a/Curved_kernel_via_analysis_2/include/CGAL/Curved_kernel_via_analysis_2/gfx/Curve_renderer_2.h b/Curved_kernel_via_analysis_2/include/CGAL/Curved_kernel_via_analysis_2/gfx/Curve_renderer_2.h index c83eca435ae..d7f7465c0fa 100644 --- a/Curved_kernel_via_analysis_2/include/CGAL/Curved_kernel_via_analysis_2/gfx/Curve_renderer_2.h +++ b/Curved_kernel_via_analysis_2/include/CGAL/Curved_kernel_via_analysis_2/gfx/Curve_renderer_2.h @@ -395,11 +395,14 @@ public: * thrown whenever the precision of currently used NT is not enough * to correctly render a curve arc. The exception has to be caught * outside the renderer to switch to a higher-precision arithmetic + * + * \c end_pt1/2 computes end-points (optionally) */ template < class Coord_2, template < class > class Container > void draw(const Arc_2& arc, Container< std::vector < Coord_2 > >& points, - boost::array< Coord_2, 2 >& end_points) -{ + boost::optional< Coord_2 > *end_pt1 = NULL, + boost::optional< Coord_2 > *end_pt2 = NULL) { + if(!initialized) return; select_cache_entry(arc); // lookup for appropriate cache instance @@ -410,20 +413,22 @@ void draw(const Arc_2& arc, Container< std::vector < Coord_2 > >& points, engine.x_max << "; " << engine.y_max << "]" << std::endl); Rational lower, upper, y_lower = 0, y_upper = 0; - bool infty_src = true, infty_tgt = true, clip_src=false, clip_tgt=false; + bool clip_src = false, clip_tgt = false; CGAL::Arr_parameter_space loc_p1 = arc.location(CGAL::ARR_MIN_END), loc_p2 = arc.location(CGAL::ARR_MAX_END); -//!@todo: should be adapted for other boundary types + Rational ref_bound = engine.pixel_w_r/CGAL_REFINE_X; if(loc_p1 != CGAL::ARR_LEFT_BOUNDARY) { const X_coordinate_1& x0 = arc.curve_end_x(CGAL::ARR_MIN_END); - while(ubound_x(x0) - lbound_x(x0) > engine.pixel_w_r/CGAL_REFINE_X) + while(ubound_x(x0) - lbound_x(x0) > ref_bound) refine_x(x0); lower = ubound_x(x0); - } else - lower = engine.x_min_r; - + } else { + lower = engine.x_min_r; + clip_src = true; + } + // since end-points are sorted lexicographically, no need to check for // lower boundary if(loc_p2 == CGAL::ARR_TOP_BOUNDARY && arc.is_vertical()) @@ -431,59 +436,95 @@ void draw(const Arc_2& arc, Container< std::vector < Coord_2 > >& points, if(loc_p2 != CGAL::ARR_RIGHT_BOUNDARY) { const X_coordinate_1& x0 = arc.curve_end_x(CGAL::ARR_MAX_END); - while(ubound_x(x0) - lbound_x(x0) > engine.pixel_w_r/CGAL_REFINE_X) + while(ubound_x(x0) - lbound_x(x0) > ref_bound) refine_x(x0); upper = lbound_x(x0); - } else + } else { upper = engine.x_max_r; - - if(upper <= engine.x_min_r||lower >= engine.x_max_r) + clip_tgt = true; + } + + bool x_outside_window = false; +#ifdef CGAL_CKVA_RENDER_WITH_REFINEMENT + Rational lower0 = lower, upper0 = upper, y_lower0(-1), y_upper0(-1); +#endif + + if(upper <= engine.x_min_r||lower >= engine.x_max_r) { +#ifdef CGAL_CKVA_RENDER_WITH_REFINEMENT + x_outside_window = true; + clip_src = clip_tgt = true; +#else return; +#endif + } if(lower < engine.x_min_r) { lower = engine.x_min_r; clip_src = true; - loc_p1 = CGAL::ARR_INTERIOR; } if(upper > engine.x_max_r) { upper = engine.x_max_r; clip_tgt = true; - loc_p2 = CGAL::ARR_INTERIOR; } - Rational height_r = (engine.y_max_r-engine.y_min_r)*2; - switch(loc_p1) { - case CGAL::ARR_BOTTOM_BOUNDARY: - y_lower = (arc.is_vertical() ? engine.y_min_r : - engine.y_min_r - height_r); - break; - - case CGAL::ARR_TOP_BOUNDARY: - // endpoints must be sorted lexicographical - CGAL_precondition(!arc.is_vertical()); - y_lower = engine.y_max_r + height_r; - break; - - default: - infty_src = false; - y_lower = get_endpoint_y(arc, lower, CGAL::ARR_MIN_END, clip_src); - } + if(!x_outside_window) { + Rational height_r = (engine.y_max_r-engine.y_min_r)*2; + ref_bound = engine.pixel_h_r/CGAL_REFINE_X; + +#ifdef CGAL_CKVA_RENDER_WITH_REFINEMENT + ref_bound = std::min(ref_bound, Rational(CGAL_REFINE_DOUBLE_APPROX)); +#endif + if(loc_p1 == CGAL::ARR_INTERIOR || clip_src) + y_lower = get_endpoint_y(arc, lower, CGAL::ARR_MIN_END, clip_src, + ref_bound); - switch(loc_p2) { - case CGAL::ARR_BOTTOM_BOUNDARY: - // endpoints must be sorted lexicographical - CGAL_precondition(!arc.is_vertical()); - y_upper = engine.y_min_r - height_r; - break; + else if(loc_p1 == CGAL::ARR_BOTTOM_BOUNDARY) + y_lower = (arc.is_vertical() ? engine.y_min_r : + engine.y_min_r - height_r); + + else { // endpoints must be sorted lexicographical + CGAL_precondition(!arc.is_vertical()); + y_lower = engine.y_max_r + height_r; + } + + if(loc_p2 == CGAL::ARR_INTERIOR || clip_tgt) + y_upper = get_endpoint_y(arc, upper, CGAL::ARR_MAX_END, clip_tgt, + ref_bound); - case CGAL::ARR_TOP_BOUNDARY: - y_upper = (arc.is_vertical() ? engine.y_max_r : + else if(loc_p2 == CGAL::ARR_BOTTOM_BOUNDARY) { + CGAL_precondition(!arc.is_vertical()); + y_upper = engine.y_min_r - height_r; + + } else + y_upper = (arc.is_vertical() ? engine.y_max_r : engine.y_max_r + height_r); - break; - default: - infty_tgt = false; - y_upper = get_endpoint_y(arc, upper, CGAL::ARR_MAX_END, clip_tgt); + } + +#ifdef CGAL_CKVA_RENDER_WITH_REFINEMENT + if(end_pt1 != NULL && loc_p1 == CGAL::ARR_INTERIOR && + (clip_src || y_lower < engine.y_min_r || y_lower > engine.y_max_r)) { + y_lower0 = (clip_src ? + get_endpoint_y(arc, lower0, CGAL::ARR_MIN_END, false, + CGAL_REFINE_DOUBLE_APPROX) : y_lower); + Gfx_OUT("lower end-point: [" << CGAL::to_double(lower0) << "; " << + CGAL::to_double(y_lower0) << "]\n"); + *end_pt1 = Coord_2(CGAL::to_double(lower0), + CGAL::to_double(y_lower0)); } + if(end_pt2 != NULL && loc_p2 == CGAL::ARR_INTERIOR && + (clip_tgt || y_upper < engine.y_min_r || y_upper > engine.y_max_r)) { + y_upper0 = (clip_tgt ? + get_endpoint_y(arc, upper0, CGAL::ARR_MAX_END, false, + CGAL_REFINE_DOUBLE_APPROX) : y_upper); + Gfx_OUT("upper end-point: [" << CGAL::to_double(upper0) << "; " << + CGAL::to_double(y_upper0) << "]\n"); + *end_pt2 = Coord_2(CGAL::to_double(upper0), + CGAL::to_double(y_upper0)); + } + if(x_outside_window) + return; +#endif + Pixel_2 pix_1, pix_2; Gfx_OUT("lower: " << CGAL::to_double(lower) << "; upper: " << @@ -493,14 +534,11 @@ void draw(const Arc_2& arc, Container< std::vector < Coord_2 > >& points, get_pixel_coords(lower, y_lower, pix_1); get_pixel_coords(upper, y_upper, pix_2); - //(clip_src ? engine.res_w+4 : pix_1.x); - //(clip_tgt ? engine.res_w+4 : pix_2.x); -#ifdef CGAL_CKVA_RENDER_WITH_REFINEMENT - end_points[0] = Coord_2(pix_1.xv, pix_1.yv); - end_points[1] = Coord_2(pix_2.xv, pix_2.yv); -#else - end_points[0] = Coord_2(pix_1.x, pix_1.y); - end_points[1] = Coord_2(pix_2.x, pix_2.y); +#ifndef CGAL_CKVA_RENDER_WITH_REFINEMENT + if(end_pt1 != NULL) + *end_pt1 = Coord_2(pix_1.x, pix_1.y); + if(end_pt2 != NULL) + *end_pt2 = Coord_2(pix_2.x, pix_2.y); #endif Gfx_OUT("lower pix: (" << pix_1.x << "; " << pix_1.y << @@ -753,11 +791,6 @@ void draw(const Arc_2& arc, Container< std::vector < Coord_2 > >& points, break; it++; } - - /*if(!get_isolating_box(lower, y_lower, isolated_l)) - isolated_l.level = -1u; - if(!get_isolating_box(upper, y_upper, isolated_h)) - isolated_h.level = -1u;*/ } /*!\brief @@ -772,33 +805,42 @@ bool draw(const Point_2& pt, Coord_2& coord) { Gfx_OUT("rasterizing point: " << CGAL::to_double(pt.x()) << std::endl); const X_coordinate_1& x0 = pt.x(); - while(ubound_x(x0) - lbound_x(x0) > engine.pixel_w_r/2) + Rational ref_bound = +#ifdef CGAL_CKVA_RENDER_WITH_REFINEMENT + engine.pixel_w_r / CGAL_REFINE_X; +#else + engine.pixel_w_r / 2; +#endif + + while(ubound_x(x0) - lbound_x(x0) > ref_bound) refine_x(x0); Rational x_s = lbound_x(x0), y_s; -//#ifndef CGAL_CKVA_RENDER_WITH_REFINEMENT +#ifndef CGAL_CKVA_RENDER_WITH_REFINEMENT if(x_s < engine.x_min_r || x_s > engine.x_max_r) return false; -//#endif +#endif + ref_bound = engine.pixel_h_r / CGAL_REFINE_X; + +#ifdef CGAL_REFINE_DOUBLE_APPROX + ref_bound = std::min(ref_bound, Rational(CGAL_REFINE_DOUBLE_APPROX)); +#endif Xy_coordinate_2 xy(x0, pt.curve(), pt.arcno()); - refine_xy(xy, engine.pixel_h_r / CGAL_REFINE_X); + refine_xy(xy, ref_bound); y_s = ubound_y(xy); Pixel_2 pix; get_pixel_coords(x_s, y_s, pix); -//#ifndef CGAL_CKVA_RENDER_WITH_REFINEMENT +#ifndef CGAL_CKVA_RENDER_WITH_REFINEMENT if(pix.x < 0 || pix.x >= engine.res_w || pix.y < 0 || pix.y >= engine.res_h) return false; -//#endif -#ifdef CGAL_CKVA_RENDER_WITH_REFINEMENT - coord = Coord_2(pix.xv, pix.yv); -#else coord = Coord_2(pix.x, pix.y); +#else + coord = Coord_2(pix.xv, pix.yv); #endif - return true; } @@ -833,6 +875,8 @@ void draw_lump(std::vector< Coord_2 >& rev_points, int& last_x, return; } + Gfx_OUT("draw_lump: pix_1 = " << pix_1 << "; pix_2 = " << pix_2 << "\n"); + std::vector< Coord_2 > points; // reserve a list of point coordinates points.reserve(CGAL_ABS(pix_2.x - pix_1.x)); @@ -1236,27 +1280,12 @@ bool get_seed_point(const Rational& seed, Pixel_2& start, int *dir, typename CGAL::Coercion_traits::Cast cast; -// Gfx_OUT("poly: " << *(engine.rational_fy) << -// "\n\nat: " << xcs << "; and " << ycs << "\n"); -// -// Gfx_OUT("vx before: " << cast(vx) << " " << (vy > 0) << -// "\nvvx before: " << vvx << " " << (vvy > 0) << "\n"); - -// vvx = -vvx; -// vx = -vx; - -// Gfx_OUT("vx after: " << cast(vx) << " " << (vy > 0) << "\nvy = " << -// (vy) << "\n"); -// Gfx_OUT("vvx after: " << vvx << " " << (vvy > 0) << "; vvy = " << vvy << "\n"); - NT vvx = rat2float(vx), vvy = rat2float(vy); //Coeff vvx = cast(vx), vvy = cast(vy); if(vvy < 0) { vvx = -vvx; } - Gfx_OUT("final vvx = " << vvx << " " << (vvx > 0) << "\n"); - // vx > 0: 2 - right(1), 6 - left(0) // vx < 0: 2 - left(0), 6 - right(1) bool flag = (vvx > 0); @@ -2124,7 +2153,7 @@ inline bool get_range_1(int var, const NT& lower, const NT& upper, //! \brief copmutes an isolating interval for y-coordinate of an end-point, //! uses caching if possible Rational get_endpoint_y(const Arc_2& arc, const Rational& x, - CGAL::Arr_curve_end end, bool is_clipped) { + CGAL::Arr_curve_end end, bool is_clipped, Rational refine_bound) { int arcno; Xy_coordinate_2 xy; @@ -2141,7 +2170,7 @@ Rational get_endpoint_y(const Arc_2& arc, const Rational& x, // refine the y-interval until its size is smaller than the pixel size ////////////////////////// CHANGED REFINE_Y by REFINE_X - refine_xy(xy, engine.pixel_h_r/CGAL_REFINE_X); + refine_xy(xy, refine_bound); ////////////////////////// CHANGED REFINE_Y by REFINE_X return ubound_y(xy);//event.upper_boundary(arcno); } diff --git a/Curved_kernel_via_analysis_2/include/CGAL/IO/Qt_widget_Curve_renderer_2.h b/Curved_kernel_via_analysis_2/include/CGAL/IO/Qt_widget_Curve_renderer_2.h index cb66f2ce54b..1b173da3ee2 100644 --- a/Curved_kernel_via_analysis_2/include/CGAL/IO/Qt_widget_Curve_renderer_2.h +++ b/Curved_kernel_via_analysis_2/include/CGAL/IO/Qt_widget_Curve_renderer_2.h @@ -36,13 +36,13 @@ Qt_widget& operator << (Qt_widget& ws, const CGALi::Arc_2< CKvA_2 >& arc) { typedef std::pair< int, int > Coord_2; typedef std::vector< Coord_2 > Coord_vec_2; - boost::array< Coord_2, 2 > end_points; + boost::optional < Coord_2 > p1, p2; std::list points; Facade::setup(CGAL::Bbox_2(ws.x_min(), ws.y_min(), ws.x_max(), ws.y_max()), ws.width(), ws.height()); - - Facade::instance().draw(arc, points, end_points); + + Facade::instance().draw(arc, points, &p1, &p2); if(points.empty()) return ws; @@ -50,38 +50,35 @@ Qt_widget& operator << (Qt_widget& ws, const CGALi::Arc_2< CKvA_2 >& arc) { int height = ws.height(); // std::cerr << ws.width() << " and " << ws.height() << "\n"; - typename std::list::const_iterator lit = points.begin(); + //ppnt->moveTo((*p1).first, height - (*p1).second); while(lit != points.end()) { const Coord_vec_2& vec = *lit; typename Coord_vec_2::const_iterator vit = vec.begin(); - - if(vec.size() == 2) { - ppnt->moveTo(vit->first, height - vit->second); - vit++; + //std::cerr << "(" << vit->first << "; " << vit->second << ")\n"; + if(/*lit != points.begin() &&*/ vit != vec.end()) { ppnt->lineTo(vit->first, height - vit->second); - - } else { - ppnt->moveTo(vit->first, height - vit->second); + vit++; + } + while(vit != vec.end()) { + ppnt->lineTo(vit->first, height - vit->second); + vit++; //std::cerr << "(" << vit->e0 << "; " << vit->e1 << "\n"; - while(vit != vec.end()) { - ppnt->lineTo(vit->first, height - vit->second); - vit++; - //if(vit != vec.end()) - //std::cerr << "(" << vit->e0 << "; " << vit->e1 << "\n"; - } } lit++; } + //ppnt->lineTo((*p2).first, height - (*p2).second); QPen old_pen = ppnt->pen(); ppnt->setPen(QPen(Qt::NoPen)); // avoid drawing outlines // draw with the current brush attributes - ppnt->drawEllipse(end_points[0].first-3, height-end_points[0].second-3, - 6, 6); - ppnt->drawEllipse(end_points[1].first-3, height-end_points[1].second-3, - 6, 6); + + //std::cerr << "endpts1: (" << (*p1).first << "; " << (*p1).second << "\n"; + //std::cerr << "endpts2: (" << (*p2).first << "; " << (*p2).second << "\n"; + + ppnt->drawEllipse((*p1).first-3, height-(*p1).second-3, 6, 6); + ppnt->drawEllipse((*p2).first-3, height-(*p2).second-3, 6, 6); ppnt->setPen(old_pen); return ws;