/* $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 "fiber.hpp"
namespace ocl
{
Fiber::Fiber(const Point &p1in, const Point &p2in) {
p1=p1in;
p2=p2in;
calcDir();
}
void Fiber::calcDir() {
dir = p2 - p1;
assert( dir.z == 0.0 );
dir.normalize();
}
bool Fiber::contains(Interval& i) const {
BOOST_FOREACH( Interval fi, ints) {
if ( i.inside( fi ) )
return true;
}
return false;
}
bool Fiber::missing(Interval& i) const {
bool result = true;
BOOST_FOREACH( Interval fi, ints) {
if ( !i.outside( fi ) ) // all existing ints must be non-overlapping
result = false;
}
return result;
}
void Fiber::addInterval(Interval& i) {
if (i.empty())
return; // do nothing.
if (ints.empty()) { // empty fiber case
ints.push_back(i);
return;
} else if ( this->contains(i) ) { // if fiber already contains i
return; // do nothing
} else if ( this->missing(i) ) { // if fiber doesn't contain i
ints.push_back(i);
return;
} else {
// this is the messier general case with partial overlap
std::vector::iterator itr;
itr = ints.begin();
std::vector overlaps;
while (itr!=ints.end()) { // loop through all intervals
if ( ! (itr->outside( i )) ) {
overlaps.push_back(*itr); // add overlaps here
itr = ints.erase(itr); // erase overlaps from ints
} else {
++itr;
}
}
overlaps.push_back(i);
// now build a new interval from i and the overlaps
Interval sumint;
BOOST_FOREACH(Interval intr, overlaps) {
sumint.updateLower( intr.lower, intr.lower_cc );
sumint.updateUpper( intr.upper, intr.upper_cc );
}
ints.push_back(sumint); // add the sum-interval to ints
return;
}
}
double Fiber::tval(Point& p) const {
// fiber is f = p1 + t * (p2-p1)
// t = (f-p1).dot(p2-p1) / (p2-p1).dot(p2-p1)
Point p2minp1 = p2 - p1;
return (p-p1).dot(p2minp1) / (p2minp1).dot(p2minp1);
}
Point Fiber::point(double t) const {
Point p = p1 + t*(p2-p1);
return p;
}
void Fiber::printInts() const {
int n=0;
BOOST_FOREACH( Interval i, ints) {
std::cout << n << ": [ " << i.lower << " , " << i.upper << " ]" << "\n";
++n;
}
}
std::ostream& operator<<(std::ostream &stream, const Fiber& f) {
stream << " fiber dir=" << f.dir << " and " << f.ints.size() << " intervals\n";
stream << " fiber.p1=" << f.p1 << " fiber.p2 " << f.p2 ;
return stream;
}
} // end namespace
// end file fiber.cpp