/**************************************************************************** ** $Id: rs_math.cpp 1938 2004-12-09 23:09:53Z andrew $ ** ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved. ** ** This file is part of the qcadlib Library project. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** Licensees holding valid qcadlib Professional Edition licenses may use ** this file in accordance with the qcadlib Commercial License ** Agreement provided with the Software. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.ribbonsoft.com for further details. ** ** Contact info@ribbonsoft.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #include "rs_math.h" #include "rs_debug.h" /** * Rounds the given double to the next int. */ int RS_Math::round(double v) { return (v-floor(v)<0.5 ? (int)floor(v) : (int)ceil(v)); } /** * Save pow function */ double RS_Math::pow(double x, double y) { errno = 0; double ret = ::pow(x, y); if (errno==EDOM) { RS_DEBUG->print(RS_Debug::D_ERROR, "RS_Math::pow: EDOM in pow"); ret = 0.0; } else if (errno==ERANGE) { RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Math::pow: ERANGE in pow"); ret = 0.0; } return ret; } /** * Converts radians to degrees. */ double RS_Math::rad2deg(double a) { return (a/(2.0*M_PI)*360.0); } /** * Converts degrees to radians. */ double RS_Math::deg2rad(double a) { return ((a/360.0)*(2.0*M_PI)); } /** * Converts radians to gradians. */ double RS_Math::rad2gra(double a) { return (a/(2.0*M_PI)*400.0); } /** * Finds greatest common divider using Euclid's algorithm. */ int RS_Math::findGCD(int a, int b) { int rem; while (b!=0) { rem = a % b; a = b; b = rem; } return a; } /** * Tests if angle a is between a1 and a2. a, a1 and a2 must be in the * range between 0 and 2*PI. * All angles in rad. * * @param reversed true for clockwise testing. false for ccw testing. * @return true if the angle a is between a1 and a2. */ bool RS_Math::isAngleBetween(double a, double a1, double a2, bool reversed) { bool ret = false; if (reversed) { double tmp = a1; a1 = a2; a2 = tmp; } if(a1>=a2-1.0e-12) { if(a>=a1-1.0e-12 || a<=a2+1.0e-12) { ret = true; } } else { if(a>=a1-1.0e-12 && a<=a2+1.0e-12) { ret = true; } } //RS_DEBUG->print("angle %f is %sbetween %f and %f", // a, ret ? "" : "not ", a1, a2); return ret; } /** * Corrects the given angle to the range of 0-2*Pi. */ double RS_Math::correctAngle(double a) { while (a>2*M_PI) a-=2*M_PI; while (a<0) a+=2*M_PI; return a; } /** * @return The angle that needs to be added to a1 to reach a2. * Always positive and less than 2*pi. */ double RS_Math::getAngleDifference(double a1, double a2) { double ret; if (a1>=a2) { a2+=2*M_PI; } ret = a2-a1; if (ret>=2*M_PI) { ret=0.0; } return ret; } /** * Makes a text constructed with the given angle readable. Used * for dimension texts and for mirroring texts. * * @param readable true: make angle readable, false: unreadable * @param corrected Will point to true if the given angle was * corrected, false otherwise. * * @return The given angle or the given angle+PI, depending which on * is readable from the bottom or right. */ double RS_Math::makeAngleReadable(double angle, bool readable, bool* corrected) { double ret; bool cor = isAngleReadable(angle) ^ readable; // quadrant 1 & 4 if (!cor) { ret = angle; } // quadrant 2 & 3 else { ret = angle+M_PI; } if (corrected!=NULL) { *corrected = cor; } return ret; } /** * @return true: if the given angle is in a range that is readable * for texts created with that angle. */ bool RS_Math::isAngleReadable(double angle) { if (angle>M_PI/2.0*3.0+0.001 || angle2*M_PI-tol) { //std::cout << "RS_Math::isSameDirection: " << dir1 << " and " << dir2 // << " point in the same direction" << "\n"; return true; } else { //std::cout << "RS_Math::isSameDirection: " << dir1 << " and " << dir2 // << " don't point in the same direction" << "\n"; return false; } } /** * Compares two double values with a tolerance. */ bool RS_Math::cmpDouble(double v1, double v2, double tol) { return (fabs(v2-v1)