/* $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 #ifdef _OPENMP #include #endif #include "millingcutter.hpp" #include "point.hpp" #include "triangle.hpp" #include "batchpushcutter.hpp" namespace ocl { //******** ********************** */ BatchPushCutter::BatchPushCutter() { fibers = new std::vector(); nCalls = 0; nthreads = 1; #ifdef _OPENMP nthreads = omp_get_num_procs(); // figure out how many cores we have #endif cutter = NULL; bucketSize = 1; root = new KDTree(); } BatchPushCutter::~BatchPushCutter() { delete fibers; delete root; } void BatchPushCutter::setSTL(const STLSurf &s) { surf = &s; // std::cout << "BPC::setSTL() Building kd-tree... bucketSize=" << bucketSize << ".."; root->setBucketSize( bucketSize ); if (x_direction) root->setYZDimensions(); // we search for triangles in the XY plane, don't care about Z-coordinate else if (y_direction) root->setXZDimensions(); else { std::cerr << "ERROR: setXDirection() or setYDirection() must be called before setSTL() \n"; assert(0); } // std::cout << "BPC::setSTL() root->build()..."; root->build(s.tris); // std::cout << "done.\n"; } void BatchPushCutter::appendFiber(Fiber& f) { fibers->push_back(f); } void BatchPushCutter::reset() { fibers->clear(); } /// very simple batch push-cutter /// each fiber is tested against all triangles of surface void BatchPushCutter::pushCutter1() { // std::cout << "BatchPushCutter1 with " << fibers->size() << // " fibers and " << surf->tris.size() << " triangles..." << std::endl; nCalls = 0; BOOST_FOREACH(Fiber& f, *fibers) { BOOST_FOREACH( const Triangle& t, surf->tris) {// test against all triangles in s Interval i; cutter->pushCutter(f,i,t); f.addInterval(i); ++nCalls; } } // std::cout << "BatchPushCutter done." << std::endl; return; } /// push-cutter which uses KDNode2 kd-tree search to find triangles /// overlapping with the cutter. void BatchPushCutter::pushCutter2() { // std::cout << "BatchPushCutter2 with " << fibers->size() << // " fibers and " << surf->tris.size() << " triangles..." << std::endl; nCalls = 0; std::list* overlap_triangles; BOOST_FOREACH(Fiber& f, *fibers) { CLPoint cl; if (x_direction) { cl.x = 0; cl.y = f.p1.y; cl.z = f.p1.z; } else if (y_direction) { cl.x = f.p1.x; cl.y = 0; cl.z = f.p1.z; } else { assert(0); } overlap_triangles = root->search_cutter_overlap(cutter, &cl); assert( overlap_triangles->size() <= surf->size() ); // can't possibly find more triangles than in the STLSurf BOOST_FOREACH( const Triangle& t, *overlap_triangles) { //if ( bb->overlaps( t.bb ) ) { Interval i; cutter->pushCutter(f,i,t); f.addInterval(i); ++nCalls; //} } delete( overlap_triangles ); } // std::cout << "BatchPushCutter2 done." << std::endl; return; } /// use kd-tree search to find overlapping triangles /// use OpenMP for multi-threading void BatchPushCutter::pushCutter3() { // std::cout << "BatchPushCutter3 with " << fibers->size() << // " fibers and " << surf->tris.size() << " triangles." << std::endl; // std::cout << " cutter = " << cutter->str() << "\n"; nCalls = 0; #ifdef _OPENMP omp_set_num_threads(nthreads); #endif std::list::iterator it,it_end; // for looping over found triabgles Interval* i; std::list* tris; std::vector& fiberr = *fibers; #ifdef _WIN32 // OpenMP version 2 of VS2013 OpenMP need signed loop variable int n; // loop variable int Nmax = static_cast(fibers->size()); // the number of fibers to process #else unsigned int n; // loop variable unsigned int Nmax = fibers->size(); // the number of fibers to process #endif unsigned int calls=0; #pragma omp parallel for schedule(dynamic) shared(calls, fiberr) private(n,i,tris,it,it_end) //#pragma omp parallel for shared( calls, fiberr) private(n,i,tris,it,it_end) for (n=0; nsearch_cutter_overlap(cutter, &cl); it_end = tris->end(); for ( it=tris->begin() ; it!=it_end ; ++it) { // loop through the found overlapping triangles //if ( bb->overlaps( it->bb ) ) { // todo: optimization where method-calls are skipped if triangle bbox already in the fiber i = new Interval(); cutter->pushCutter(fiberr[n],*i,*it); fiberr[n].addInterval(*i); ++calls; delete i; //} } delete( tris ); } // OpenMP parallel region ends here this->nCalls = calls; // std::cout << "\nBatchPushCutter3 done." << std::endl; return; } }// end namespace // end file batchpushcutter.cpp