/* $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