/* $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 #include "compositecutter.hpp" #include "numeric.hpp" #include "cylcutter.hpp" #include "ballcutter.hpp" #include "bullcutter.hpp" #include "conecutter.hpp" namespace ocl { CompositeCutter::CompositeCutter() { radiusvec = std::vector(); cutter = std::vector(); radius=0; diameter=0; } // add cutter c which is valid until radius=r and height=z with z-offset zoff void CompositeCutter::addCutter(MillingCutter& c, double r, double h, double zoff) { radiusvec.push_back(r); heightvec.push_back(h); cutter.push_back(&c); zoffset.push_back(zoff); if (r>radius) { radius = r; diameter = 2*r; } // update length also? } // this allows vertexDrop in the base-class to work as for other cutters double CompositeCutter::height(double r) const { unsigned int idx = radius_to_index(r); return cutter[idx]->height(r) + zoffset[idx]; } // return the width of the cutter at height h. double CompositeCutter::width(double h) const { unsigned int idx = height_to_index(h); // std::cout << "CompositeCutter::width( " << h << " ) idx=" << idx << " zoffset= " << zoffset[idx] << "\n"; // std::cout << " width = " << cutter[idx]->width( h - zoffset[idx] ) << "\n"; return cutter[idx]->width( h - zoffset[idx] ); } unsigned int CompositeCutter::height_to_index(double h) const { for (unsigned int n=0; n(cutter.size()) - 1; std::cout << " Error, height= " << h << " has no index \n"; assert(0); return 0; } unsigned int CompositeCutter::radius_to_index(double r) const { for (unsigned int n=0; ntype == NONE) return false; double d = cl.xyDistance(*cl.cc); double lolimit; double hilimit; if (n==0) lolimit = - 1E-6; else lolimit = radiusvec[n-1] - 1E-6; hilimit = radiusvec[n]+1e-6; // FIXME: really ugly solution this one... if (dhilimit) return false; else return true; } bool CompositeCutter::ccValidHeight(unsigned int n, CCPoint& cc, const Fiber& f) const { //if ( ((cc.z-f.p1.z) >= 0.0) && (n == height_to_index(cc.z-f.p1.z)) ) if ( n == height_to_index(cc.z-f.p1.z) ) return true; else return false; } // return true if height h belongs to cutter n bool CompositeCutter::validHeight(unsigned int n, double h) const { double lolimit, hilimit; if (n==0) lolimit = -1E-6; else lolimit = heightvec[n-1] - 1E-6; hilimit = heightvec[n]+1e-6; // FIXME: really ugly solution this one... if ( (lolimit<=h) ) if (h<=hilimit) return true; return false; } bool CompositeCutter::validRadius(unsigned int n, double r) const { assert( r >= 0.0 ); double lolimit, hilimit; if (n==0) lolimit = -1E-6; else lolimit = radiusvec[n-1] - 1E-6; hilimit = radiusvec[n]+1e-6; // FIXME: really ugly solution this one... if ( (lolimit<=r) ) if (r<=hilimit) return true; return false; } //******** facetDrop ********************** */ // call facetDrop on each cutter and pick a valid cc-point bool CompositeCutter::facetDrop(CLPoint &cl, const Triangle &t) const { bool result = false; for (unsigned int n=0; nfacetDrop(cl_tmp, t) ) { assert( cl_tmp.cc != 0); if ( ccValidRadius(n,cl_tmp) ) { // cc-point is valid cc_tmp = new CCPoint(*cl_tmp.cc); if (cl.liftZ( cl_tmp.z - zoffset[n] )) { // we need to lift the cutter cc_tmp->type = FACET; cl.cc = cc_tmp; result = true; } else { delete cc_tmp; } } } } return result; } //******** edge **************************************************** */ bool CompositeCutter::edgeDrop(CLPoint &cl, const Triangle &t) const { bool result = false; for (unsigned int n=0; nedgeDrop(cl_tmp,t) ) { // drop sub-cutter against edge if ( ccValidRadius(n,cl_tmp) ) { // check if cc-point is valid cc_tmp = new CCPoint(*cl_tmp.cc); if (cl.liftZ( cl_tmp.z - zoffset[n] ) ) { // we need to lift the cutter cc_tmp->type = EDGE; cl.cc = cc_tmp; result = true; } else { delete cc_tmp; } } } } return result; } bool CompositeCutter::vertexPush(const Fiber& f, Interval& i, const Triangle& t) const { bool result = false; std::vector< std::pair > contacts; for (unsigned int n=0; nvertexPush(cf,ci,t) ) { if ( ccValidHeight( n, ci.upper_cc, f ) ) contacts.push_back( std::pair(ci.upper, ci.upper_cc) ); if ( ccValidHeight( n, ci.lower_cc, f ) ) contacts.push_back( std::pair(ci.lower, ci.lower_cc) ); } } for( unsigned int n=0; n > contacts; for (unsigned int n=0; nfacetPush(cf,ci,t) ) { if ( ccValidHeight( n, ci.upper_cc, f ) ) contacts.push_back( std::pair(ci.upper, ci.upper_cc) ); if ( ccValidHeight( n, ci.lower_cc, f ) ) contacts.push_back( std::pair(ci.lower, ci.lower_cc) ); } } for( unsigned int n=0; n > contacts; for (unsigned int n=0; nedgePush(cf,ci,t) ) { if ( ccValidHeight( n, ci.upper_cc, f ) ) contacts.push_back( std::pair(ci.upper, ci.upper_cc) ); if ( ccValidHeight( n, ci.lower_cc, f ) ) contacts.push_back( std::pair(ci.lower, ci.lower_cc) ); } } for( unsigned int n=0; nstr() << "\n"; o << " radius["<< n << "]="<< radiusvec[n] << "\n"; o << " height["<< n << "]="<< heightvec[n] << "\n"; o << " zoffset["<< n << "]="<< zoffset[n] << "\n"; } return o.str(); } //******** actual Composite-cutters ******************************* */ // only constructors required, drop-cutter and push-cutter calls handled by base-class // TESTING CompCylCutter::CompCylCutter(double diam2, double clength) { MillingCutter* shaft = new CylCutter(diam2, clength ); addCutter( *shaft, diam2/2.0, clength , 0.0 ); length = clength; } // TESTING CompBallCutter::CompBallCutter(double diam2, double clength) { MillingCutter* shaft = new BallCutter(diam2, clength ); addCutter( *shaft, diam2/2.0, clength , 0.0 ); length = clength; } CylConeCutter::CylConeCutter(double diam1, double diam2, double angle) { MillingCutter* cyl = new CylCutter(diam1, 1 ); MillingCutter* cone = new ConeCutter(diam2, angle); MillingCutter* shaft = new CylCutter(diam2, 20 ); // FIXME: dummy height double cone_offset= - (diam1/2)/tan(angle); double cyl_height = 0.0; double cone_height = (diam2/2.0)/tan(angle) + cone_offset; addCutter( *cyl, diam1/2.0, cyl_height, 0.0 ); addCutter( *cone, diam2/2.0, cone_height, cone_offset ); addCutter( *shaft, diam2/2.0, (diam2/2.0)/tan(angle) + 20 , cone_height ); length = cyl_height + cone_height + 10; // Arbitrary 10 here! } BallConeCutter::BallConeCutter(double diam1, double diam2, double angle) { MillingCutter* c1 = new BallCutter(diam1, 1); // at offset zero MillingCutter* c2 = new ConeCutter(diam2, angle); MillingCutter* shaft = new CylCutter(diam2, 20); // FIXME: length double radius1 = diam1/2.0; double radius2 = diam2/2.0; double rcontact = radius1*cos(angle); double height1 = radius1 - sqrt( square(radius1)-square(rcontact) ); double cone_offset = - ( (rcontact)/tan(angle) - height1 ); double height2 = radius2/tan(angle) + cone_offset; double shaft_offset = height2; // cutter, radivec, heightvec, zoffset addCutter( *c1, rcontact, height1, 0.0 ); addCutter( *c2, diam2/2.0, height2, cone_offset ); addCutter( *shaft, diam2/2.0, height2+20, shaft_offset ); length = 30; } BullConeCutter::BullConeCutter(double diam1, double radius1, double diam2, double angle) { MillingCutter* c1 = new BullCutter(diam1, radius1, 1.0); // at offset zero MillingCutter* c2 = new ConeCutter(diam2, angle); MillingCutter* shaft = new CylCutter(diam2, 20); double h1 = radius1*sin(angle); // the contact point is this much down from the toroid-ring double rad = sqrt( square(radius1) - square(h1) ); double rcontact = (diam1/2.0) - radius1 + rad; // radius of the contact-ring double cone_offset= - ( rcontact/tan(angle) - (radius1-h1)); double height1 = radius1 - h1; double height2 = (diam2/2.0)/tan(angle) + cone_offset; double shaft_offset = height2; addCutter( *c1, rcontact, height1, 0.0 ); addCutter( *c2, diam2/2.0, height2, cone_offset ); addCutter( *shaft, diam2/2.0, height2+20, shaft_offset ); length=30; } ConeConeCutter::ConeConeCutter(double diam1, double angle1, double diam2, double angle2) { MillingCutter* c1 = new ConeCutter(diam1, angle1); // at offset zero MillingCutter* c2 = new ConeCutter(diam2, angle2); MillingCutter* shaft = new CylCutter(diam2, 20); double height1 = (diam1/2.0)/tan(angle1); double tmp = (diam1/2.0)/tan(angle2); double cone_offset= - ( tmp-height1); double height2 = (diam2/2.0)/tan(angle2) + cone_offset; double shaft_offset = height2; addCutter( *c1, diam1/2.0, height1, 0.0 ); addCutter( *c2, diam2/2.0, height2, cone_offset ); addCutter( *shaft, diam2/2.0, height2+20, shaft_offset ); length=30; } } // end namespace // end file compositecutter.cpp