/* $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 "smart_weave.hpp"
namespace ocl
{
namespace weave
{
// given a VertexPair and an Interval, in the Interval find the Vertex above and below the given vertex
std::pair SmartWeave::find_neighbor_vertices( VertexPair v_pair, Interval& ival, bool above_equality ) {
Interval::VertexPairIterator itr = ival.intersections2.lower_bound( v_pair ); // returns first that is not less than argument (equal or greater)
assert( itr != ival.intersections2.end() ); // we must find a lower_bound
Interval::VertexPairIterator v_above;
if ( above_equality )
v_above = itr; // lower_bound returns one beyond the give key, i.e. what we want
else {
v_above = ++itr;
--itr;
}
Interval::VertexPairIterator v_below = --itr; // this is the vertex below the given vertex
std::pair out;
out.first = v_above->first; // vertex above v (xu)
out.second = v_below->first; // vertex below v (xl)
return out;
}
// this is the new smarter build() which uses less RAM
void SmartWeave::build() {
// std::cout << " SmartWeave::build()... \n";
// this adds all CL-vertices from x-intervals
// it also populates the xi.intersections_fibers set of intersecting y-fibers
// also add the first-crossing vertex and the last-crossing vertex
//std::cout << " build2() add_vertices_x() ... " << std::flush ;
add_vertices_x();
//std::cout << " done.\n" << std::flush ;
// the same for y-intervals, add all CL-points, and intersections to the set.
//std::cout << " build2() add_vertices_y() ... " << std::flush ;
add_vertices_y();
//std::cout << " done.\n" << std::flush ;
//std::cout << " build2() looping over xfibers ... " << std::flush ;
BOOST_FOREACH( Fiber& xf, xfibers ) {
std::vector::iterator xi;
for( xi = xf.ints.begin(); xi < xf.ints.end(); xi++ ) {
std::set::iterator>::const_iterator current, prev;
if( xi->intersections_fibers.size() > 1 ) {
current = xi->intersections_fibers.begin();
prev = current++;
for( ; current != xi->intersections_fibers.end(); current++ ) {
// for each x-interval, loop through the intersecting y-fibers
if( (*current - *prev) > 1 ) {
std::vector::iterator yi = find_interval_crossing_x( xf, *(*prev + 1) );
add_vertex( xf, *(*prev + 1), xi , yi, FULLINT );
if( (*current - *prev) > 2 ) {
yi = find_interval_crossing_x( xf, *(*current - 1) );
add_vertex( xf, *(*current - 1), xi, yi, FULLINT );
}
}
prev = current;
}
}
}
}
//std::cout << " done.\n" << std::flush ;
//std::cout << " build2() looping over yfibers ... " << std::flush ;
//std::cout << yfibers.size() << " fibers to loop over \n"<< std::flush ;
//int ny = 0;
BOOST_FOREACH( Fiber& yf, yfibers ) {
//std::cout << " fiber nr: " << ny++ << " has " << yf.ints.size() << " intervals\n" << std::flush ;
std::vector::iterator yi;
//int ny_int=0;
for( yi = yf.ints.begin(); yi < yf.ints.end(); yi++ ) {
//std::cout << " interval nr: " << ny_int++ << " has yi->intersections_fibers.size()= " << yi->intersections_fibers.size() << "\n" << std::flush;
std::set::iterator>::iterator current, prev;
if( yi->intersections_fibers.size() > 1 ) {
current = yi->intersections_fibers.begin();
prev = current++;
for( ; current != yi->intersections_fibers.end(); current++ ) {
if( (*current - *prev) > 1 ) {
std::vector::iterator xi = find_interval_crossing_y( *(*prev + 1), yf );
add_vertex( *(*prev + 1), yf, xi , yi, FULLINT );
if( (*current - *prev) > 2 ) {
xi = find_interval_crossing_y( *(*current - 1), yf );
add_vertex( *(*current - 1), yf, xi, yi, FULLINT );
}
}
prev = current;
}
}
}
}
//std::cout << " done.\n" << std::flush ;
// std::cout << " SmartWeave::build() add_all_edges()... " << std::flush ;
add_all_edges();
// std::cout << " done.\n" << std::flush ;
}
// add a new CL-vertex to Weave, also adding it to the interval intersection-set, and to clVertices
Vertex SmartWeave::add_cl_vertex( const Point& position, Interval& ival, double ipos) {
Vertex v = g.add_vertex();
g[v].position = position;
g[v].type = CL;
ival.intersections2.insert( VertexPair( v, ipos) ); // ?? this makes Interval depend on the WeaveGraph type
clVertexSet.insert(v);
return v;
}
void SmartWeave::add_vertices_x() {
std::vector::iterator xf;
for( xf = xfibers.begin(); xf < xfibers.end(); xf++ ) {
std::vector::iterator xi;
for( xi = xf->ints.begin(); xi < xf->ints.end(); xi++ ) {
// find first and last fiber crossing this interval
std::vector::iterator yf = yfibers.begin();
std::vector::iterator yi;
bool is_crossing = crossing_x( *yf, yi, *xi, *xf );
while( (yfpoint( xi->lower ) );
add_cl_vertex( lower, *xi, lower.x );
Point upper( xf->point( xi->upper ) );
add_cl_vertex( upper, *xi, upper.x );
add_vertex( *xf, *yf, xi, yi, INT ); // the first crossing vertex
xi->intersections_fibers.insert( yf );
yi->intersections_fibers.insert( xf );
is_crossing = crossing_x( *yf, yi, *xi, *xf );
while( (yfintersections_fibers.insert( yf );
yi->intersections_fibers.insert( xf );
}
}// end foreach x-interval
}// end foreach x-fiber
}
void SmartWeave::add_vertices_y() {
std::vector::iterator yf;
for( yf = yfibers.begin(); yf < yfibers.end(); yf++ ) {
std::vector::iterator yi;
for( yi = yf->ints.begin(); yi < yf->ints.end(); yi++ ) {
std::vector::iterator xf = xfibers.begin();
std::vector::iterator xi;
// find first and last fiber crossing this interval
bool is_crossing = crossing_y( *xf, xi, *yi, *yf );
while ( (xfpoint( yi->lower ) );
add_cl_vertex( lower, *yi, lower.y );
Point upper( yf->point( yi->upper ) );
add_cl_vertex( upper, *yi, upper.y );
if( add_vertex( *xf, *yf, xi, yi, INT ) ) { // add_vertex returns false if vertex already exists
xi->intersections_fibers.insert( yf );
yi->intersections_fibers.insert( xf );
}
bool is_crossing = crossing_y( *xf, xi, *yi, *yf );
while ( (xfintersections_fibers.insert( yf );
yi->intersections_fibers.insert( xf );
}
}
}// end foreach x-interval
}// end foreach x-fiber
}
//crossing_x fiber
bool SmartWeave::crossing_x( Fiber& yf, std::vector::iterator& yi, Interval& xi, Fiber& xf ) {
//if the FIBER crosses the xi interval
if( (yf.p1.x >= xf.point( xi.lower ).x) && (yf.p1.x <= xf.point( xi.upper ).x) ) {
//for all the intervals of this y-fiber...
std::vector::iterator it;
for( it = yf.ints.begin(); it < yf.ints.end(); it++ ) {
//find the first INTERVAL which crosses our xi interval
if( (yf.point( it->lower ).y <= xf.p1.y) && (yf.point( it->upper ).y >= xf.p1.y) ) {
//save the y-interval iterator
//and return true because we found an interval
yi = it;
return true;
}
}
//return false, there is no y-interval on this y-fiber crossing our xi interval
return false;
}
//this y-fiber doesn't cross our xi interval
else
return false;
}
//crossing_y fiber
bool SmartWeave::crossing_y( Fiber& xf, std::vector::iterator& xi, Interval& yi, Fiber& yf ) {
if( (xf.p1.y >= yf.point( yi.lower ).y) && (xf.p1.y <= yf.point( yi.upper ).y) ) {
std::vector::iterator it;
for( it = xf.ints.begin(); it < xf.ints.end(); it++ ) {
if( (xf.point( it->lower ).x <= yf.p1.x) && (xf.point( it->upper ).x >= yf.p1.x) ) {
xi = it;
return true;
}
}
return false;
}
else
return false;
}
//find_interval_crossing_x
std::vector::iterator SmartWeave::find_interval_crossing_x( Fiber& xf, Fiber& yf ) {
std::vector::iterator yi, xi;
yi = yf.ints.begin();
while( (yi::iterator SmartWeave::find_interval_crossing_y( Fiber& xf, Fiber& yf ) {
std::vector::iterator xi, yi;
xi = xf.ints.begin();
while( (xi::iterator xi,
std::vector::iterator yi,
enum VertexType type ) {
//test if vertex exists
BOOST_FOREACH( std::vector::iterator it_xf, yi->intersections_fibers ) {
if( *it_xf == xf )
return false;
}
Point v_position( yf.p1.x, xf.p1.y, xf.p1.z );
Vertex v =g.add_vertex();
g[v].position = v_position;
g[v].type = type;
g[v].xi= xi;
g[v].yi= yi;
xi->intersections2.insert( VertexPair( v, v_position.x ) );
yi->intersections2.insert( VertexPair( v, v_position.y ) );
return true;
}
//add_all_edges
void SmartWeave::add_all_edges()
{
std::vector vertices = g.vertices();
// std::cout << "There are " << vertices.size() << " vertices.\n";
BOOST_FOREACH( Vertex& vertex, vertices ) {
if( (g[vertex].type == INT) || (g[vertex].type == FULLINT) ) {
std::vector adjacent_vertices;
std::vector::iterator adj_itr;
std::vector in_edges, out_edges;
std::vector::iterator in_edge_itr, out_edge_itr;
Vertex x_u, x_l, y_u, y_l;
boost::tie( x_u, x_l ) = find_neighbor_vertices( VertexPair(vertex, g[vertex].position.x), *(g[vertex].xi), false );
boost::tie( y_u, y_l ) = find_neighbor_vertices( VertexPair(vertex, g[vertex].position.y), *(g[vertex].yi), false );
adjacent_vertices.push_back( x_l );
adjacent_vertices.push_back( y_u );
adjacent_vertices.push_back( x_u );
adjacent_vertices.push_back( y_l );
for( adj_itr=adjacent_vertices.begin(); adj_itr adjacent_vertices;
Vertex x_u, x_l, y_u, y_l;
boost::tie( x_u, x_l ) = find_neighbor_vertices( VertexPair(vertex, g[vertex].position.x), *(g[vertex].xi), false );
boost::tie( y_u, y_l ) = find_neighbor_vertices( VertexPair(vertex, g[vertex].position.y), *(g[vertex].yi), false );
if( g[x_l].type == INT ) adjacent_vertices.push_back( x_l );
if( g[y_u].type == INT ) adjacent_vertices.push_back( y_u );
if( g[x_u].type == INT ) adjacent_vertices.push_back( x_u );
if( g[y_l].type == INT ) adjacent_vertices.push_back( y_l );
if( adjacent_vertices.size() == 1 ) {
Edge in, out;
std::vector::iterator adj_itr = adjacent_vertices.begin();
if( hedi::has_edge( *adj_itr, vertex, g ) ) {
in = hedi::edge( *adj_itr, vertex, g );
out = hedi::edge( vertex, *adj_itr, g );
}
else {
in = hedi::add_edge( *adj_itr, vertex, g );
out = hedi::add_edge( vertex, *adj_itr, g );
}
g[in].next = out;
g[out].prev = in;
}
else {
std::vector::iterator adj_itr;
std::vector out_edges, in_edges;
std::vector::iterator edge_itr;
for( adj_itr=adjacent_vertices.begin(); adj_itr