/* $Id$
*
* Copyright (c) 2010-2011 Anders Wallin (anders.e.e.wallin "at" gmail.com).
*
* This file is part of OpenCAMlib
* (see https://github.com/aewallin/opencamlib).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#ifdef _OPENMP
#include
#endif
#include "millingcutter.hpp"
#include "point.hpp"
#include "triangle.hpp"
#include "line.hpp"
#include "path.hpp"
#include "adaptivewaterline.hpp"
#include "weave.hpp"
#include "fiberpushcutter.hpp"
namespace ocl
{
//******** ********************** */
AdaptiveWaterline::AdaptiveWaterline() {
subOp.clear();
subOp.push_back( new FiberPushCutter() );
subOp.push_back( new FiberPushCutter() );
subOp[0]->setXDirection();
subOp[1]->setYDirection();
nthreads = 1;
#ifdef _OPENMP
nthreads = omp_get_num_procs();
#endif
sampling = 1.0;
min_sampling = 0.1;
cosLimit = 0.999;
}
AdaptiveWaterline::~AdaptiveWaterline() {}
void AdaptiveWaterline::run() {
adaptive_sampling_run();
weave_process(); // in base-class Waterline
}
void AdaptiveWaterline::run2() {
adaptive_sampling_run();
weave_process2(); // in base-class Waterline
}
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;
}
void AdaptiveWaterline::xfiber_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 << "xfiber sample= ( " << start_t << " , " << stop_t << " ) \n";
double mid_y = span->getPoint( mid_t ).y;
Point mid_p1 = Point( minx, mid_y, zh );
Point mid_p2 = Point( maxx, mid_y, zh );
Fiber mid_f = Fiber( mid_p1, mid_p2 );
subOp[0]->run( mid_f );
double fw_step = fabs( start_f.p1.y - stop_f.p1.y ) ;
if ( fw_step > sampling ) { // above minimum step-forward, need to sample more
xfiber_adaptive_sample( span, start_t, mid_t , start_f, mid_f );
xfiber_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
xfiber_adaptive_sample( span, start_t, mid_t , start_f, mid_f );
xfiber_adaptive_sample( span, mid_t , stop_t, mid_f , stop_f );
}
} else {
xfibers.push_back(stop_f);
}
}
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";
double mid_x = span->getPoint( mid_t ).x;
Point mid_p1 = Point( mid_x, miny, zh );
Point mid_p2 = Point( mid_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);
}
}
// flat predicate to determine when we subdivide
bool AdaptiveWaterline::flat( Fiber& start, Fiber& mid, Fiber& stop ) const {
if ( start.size() != stop.size() ) // start, mid, and stop need to have same size()
return false;
else if ( start.size() != mid.size() )
return false;
else if ( mid.size() != stop.size() )
return false;
else {
if (!start.empty() ) { // all now have same size
assert( start.size() == stop.size() && start.size() == mid.size() );
for (unsigned int n=0;ncosLimit);
}
}// end namespace
// end file adaptivewaterline.cpp