void AdaptiveWaterline::yfiber_adaptive_sample(const Span* span, double start_t, double stop_t, Fiber start_f, Fiber stop_f) {
    const double mid_t = start_t + (stop_t-start_t)/2.0; // mid point sample
    assert( mid_t > start_t );  assert( mid_t < stop_t );
    //std::cout << "yfiber sample= ( " << start_t << " , " << stop_t << " ) \n";
    Point mid_p1 = Point( span->getPoint( mid_t ).x, miny,  zh );
    Point mid_p2 = Point( span->getPoint( mid_t ).x, maxy, zh );
    Fiber mid_f = Fiber( mid_p1, mid_p2 );
    subOp[1]->run( mid_f );
    double fw_step = fabs( start_f.p1.x - stop_f.p1.x ) ;
    if ( fw_step > sampling ) { // above minimum step-forward, need to sample more
        yfiber_adaptive_sample( span, start_t, mid_t , start_f, mid_f  );
        yfiber_adaptive_sample( span, mid_t  , stop_t, mid_f  , stop_f );
    } else if ( !flat(start_f,mid_f,stop_f)   ) {
        if (fw_step > min_sampling) { // not a flat segment, and we have not reached maximum sampling
            yfiber_adaptive_sample( span, start_t, mid_t , start_f, mid_f  );
            yfiber_adaptive_sample( span, mid_t  , stop_t, mid_f  , stop_f );
        }
    } else {
        yfibers.push_back(stop_f); 
    }
}
void AdaptiveWaterline::adaptive_sampling_run() {
    minx = surf->bb.minpt.x - 2*cutter->getRadius();
    maxx = surf->bb.maxpt.x + 2*cutter->getRadius();
    miny = surf->bb.minpt.y - 2*cutter->getRadius();
    maxy = surf->bb.maxpt.y + 2*cutter->getRadius();
    Line* line = new Line( Point(minx,miny,zh) , Point(maxx,maxy,zh) );
    Span* linespan = new LineSpan(*line);
    
    xfibers.clear();
    Point xstart_p1 = Point( minx, linespan->getPoint(0.0).y,  zh );
    Point xstart_p2 = Point( maxx, linespan->getPoint(0.0).y,  zh );
    Point xstop_p1 = Point( minx, linespan->getPoint(1.0).y,  zh );
    Point xstop_p2 = Point( maxx, linespan->getPoint(1.0).y,  zh );
    Fiber xstart_f = Fiber( xstart_p1, xstart_p2 ) ;
    Fiber xstop_f = Fiber( xstop_p1, xstop_p2 ); 
    subOp[0]->run(xstart_f);
    subOp[0]->run(xstop_f);
    xfibers.push_back(xstart_f);
    std::cout << " XFiber adaptive sample \n";
    xfiber_adaptive_sample( linespan, 0.0, 1.0, xstart_f, xstop_f);
    
    yfibers.clear();
    Point ystart_p1 = Point( linespan->getPoint(0.0).x, miny,  zh );
    Point ystart_p2 = Point( linespan->getPoint(0.0).x, maxy,  zh );
    Point ystop_p1 = Point( linespan->getPoint(1.0).x, miny,  zh );
    Point ystop_p2 = Point( linespan->getPoint(1.0).x, maxy,  zh );
    Fiber ystart_f = Fiber( ystart_p1, ystart_p2 ) ;
    Fiber ystop_f = Fiber( ystop_p1, ystop_p2 ); 
    subOp[1]->run(ystart_f);
    subOp[1]->run(ystop_f);
    yfibers.push_back(ystart_f);
    std::cout << " YFiber adaptive sample \n";
    yfiber_adaptive_sample( linespan, 0.0, 1.0, ystart_f, ystop_f);
    
    delete line;
    delete linespan;
    
}
void AdaptiveWaterline::adaptive_sampling_run() {
    minx = surf->bb.minpt.x - 2*cutter->getRadius();
    maxx = surf->bb.maxpt.x + 2*cutter->getRadius();
    miny = surf->bb.minpt.y - 2*cutter->getRadius();
    maxy = surf->bb.maxpt.y + 2*cutter->getRadius();
    Line* line = new Line( Point(minx,miny,zh) , Point(maxx,maxy,zh) );
    Span* linespan = new LineSpan(*line);
    
#ifdef _WIN32 // OpenMP task not supported with the version 2 of VS2013 OpenMP
	#pragma omp parallel sections
	{
		#pragma omp section // Replace OMP Task by Parallel sections
		{ // first child
#else
#pragma omp parallel
	{
#pragma omp single nowait
		{ // initial root task
#pragma omp task
			{ // first child task
#endif // _WIN32
				xfibers.clear();
				Point xstart_p1 = Point(minx, linespan->getPoint(0.0).y, zh);
				Point xstart_p2 = Point(maxx, linespan->getPoint(0.0).y, zh);
				Point xstop_p1 = Point(minx, linespan->getPoint(1.0).y, zh);
				Point xstop_p2 = Point(maxx, linespan->getPoint(1.0).y, zh);
				Fiber xstart_f = Fiber(xstart_p1, xstart_p2);
				Fiber xstop_f = Fiber(xstop_p1, xstop_p2);
				subOp[0]->run(xstart_f);
				subOp[0]->run(xstop_f);
				xfibers.push_back(xstart_f);
				std::cout << " XFiber adaptive sample \n";
				xfiber_adaptive_sample(linespan, 0.0, 1.0, xstart_f, xstop_f);
#ifdef _WIN32 // OpenMP task not supported with the version 2 of VS2013 OpenMP
		}
		#pragma omp section
		{ // second child
#else
		}
# pragma omp task
			{ // second child task
#endif // _WIN32
				yfibers.clear();
				Point ystart_p1 = Point(linespan->getPoint(0.0).x, miny, zh);
				Point ystart_p2 = Point(linespan->getPoint(0.0).x, maxy, zh);
				Point ystop_p1 = Point(linespan->getPoint(1.0).x, miny, zh);
				Point ystop_p2 = Point(linespan->getPoint(1.0).x, maxy, zh);
				Fiber ystart_f = Fiber(ystart_p1, ystart_p2);
				Fiber ystop_f = Fiber(ystop_p1, ystop_p2);
				subOp[1]->run(ystart_f);
				subOp[1]->run(ystop_f);
				yfibers.push_back(ystart_f);
				std::cout << " YFiber adaptive sample \n";
				yfiber_adaptive_sample(linespan, 0.0, 1.0, ystart_f, ystop_f);
#ifdef _WIN32 // OpenMP task not supported with the version 2 of VS2013 OpenMP
		}
	} // end omp parallel
#else
            }
        }
    } // end omp parallel
#endif // _WIN32

    delete line;
    delete linespan;
    
}