/* $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