/* $Id$ * * Copyright (c) 2010 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 "arc.hpp" namespace ocl { Arc::Arc(const Point &p1in, const Point &p2in, const Point &cin, bool dirin) { p1=p1in; p2=p2in; c=cin; dir=dirin; setProperties(); } Arc::Arc(const Arc &a) { p1=a.p1; p2=a.p2; c=a.c; dir=a.dir; setProperties(); } void Arc::setProperties() { // arc properties Point vs = (p1 - c).xyPerp(); Point ve = (p2 - c).xyPerp(); radius = vs.xyNorm(); vs.normalize(); ve.normalize(); length = fabs(xyIncludedAngle(vs, ve, dir)) * radius; } std::ostream& operator<<(std::ostream &stream, const Arc& a) { stream << "(" << a.p1 << ", " << a.p2 << ", " << a.c << ", " << a.dir << ")"; return stream; } Point Arc::getPoint(double t)const { /// returns a point which is 0-1 along span if(fabs(t) < 0.00000000000001) return p1; if(fabs(t - 1.0) < 0.00000000000001) return p2; double d = t * length; if(!dir)d = -d; Point v = p1 - c; v.xyRotate(d / radius); return v + c; } double Arc::xyIncludedAngle(const Point& v1, const Point& v2, bool dir) { // returns the absolute included angle between 2 vectors in // the direction of dir ( true=acw false=cw ) int d = dir ? 1 : (-1); double inc_ang = v1.dot(v2); if(inc_ang > 1. - 1.0e-10) return 0; if(inc_ang < -1. + 1.0e-10) inc_ang = PI; else { // dot product, v1 . v2 = cos(alfa) if(inc_ang > 1.0) inc_ang = 1.0; inc_ang = acos(inc_ang); // 0 to pi radians double x = v1.x * v2.y - v1.y * v2.x; if(d * x < 0) inc_ang = 2 * PI - inc_ang ; // cp } return d * inc_ang; } } // end namespace // end file arc.cpp