int main(int argc, char** argv) { if(argc != 3) return usage(argv[0]); mark_tag vertex_index(1), vertex_x(2), vertex_y(3), vertex_z(4); sregex tface_re = bos >> *space >> "TFACE" >> *space >> eos; sregex vertex_re = bos >> *space >> "VRTX" >> +space >> (vertex_index=+_d) >> +space >> (vertex_x=+(digit|'-'|'+'|'.')) >> +space >> (vertex_y=+(digit|'-'|'+'|'.')) >> +space >> (vertex_z=+(digit|'-'|'+'|'.')) >> eos; sregex triangle_re = bos >> *space >> "TRGL" >> +space >> (s1=+digit) >> +space >> (s2=+digit) >> +space >> (s3=+digit) >> eos; sregex end_re = bos >> *space >> "END" >> *space >> eos; std::ifstream input(argv[1]); std::ofstream output(argv[2]); if(!input) { std::cerr << "Cannot read \"" << argv[1] << "\"!\n"; return EXIT_FAILURE; } if(!output) { std::cerr << "Cannot write to \"" << argv[2] << "\"!\n"; return EXIT_FAILURE; } std::string line; std::getline(input, line); smatch results; while(input && ! regex_match(line, tface_re)) // search line "TFACE" { std::getline(input, line); } std::getline(input, line); while(input && regex_match(line, results, vertex_re)) { vertices.push_back(boost::make_tuple(results[vertex_x], results[vertex_y], results[vertex_z])); std::getline(input, line); } while(input && regex_match(line, results, triangle_re)) { std::stringstream s; int i, j, k; s << results[1] << " " << results[2] << " " << results[3]; s >> i >> j >> k; faces.push_back(boost::make_tuple(i, j, k)); std::getline(input, line); } if(!input || !regex_match(line, end_re)) return incorrect_input("premature end of file!"); output << "OFF " << vertices.size() << " " << faces.size() << " " << "0\n"; for(Vertices::const_iterator vit = vertices.begin(), vend = vertices.end(); vit != vend; ++vit) output << boost::get<0>(*vit) << " " << boost::get<1>(*vit) << " " << boost::get<2>(*vit) << "\n"; for(Faces::const_iterator fit = faces.begin(), fend = faces.end(); fit != fend; ++fit) output << "3 " << boost::get<0>(*fit) << " " << boost::get<1>(*fit) << " " << boost::get<2>(*fit) << "\n"; if(output) return EXIT_SUCCESS; else return EXIT_FAILURE; };
void test(const int d, const string & type) { // we must write 'typename' below, because we are in a template-function, // so the parser has no way to know that TDS contains sub-types, before // instanciating the function. typedef typename TDS::Vertex_handle Vertex_handle; typedef typename TDS::Vertex_iterator Vertex_iterator; typedef typename TDS::Full_cell_handle Full_cell_handle; typedef typename TDS::Face Face; typedef typename TDS::Facet Facet; typedef typename TDS::Facet_iterator Facet_iterator; TDS tds(d); cout << "\nChecking Tds of (" << type << ") dimension " << tds.maximal_dimension(); assert(tds.empty()); vector<Vertex_handle> vhs; vhs.push_back(tds.insert_increase_dimension()); assert( tds.is_valid() ); size_t nb_verts = 1; for( int i = 0; i <= d; ++i ) { vhs.push_back(tds.insert_increase_dimension(vhs[0])); ++nb_verts; assert(i == tds.current_dimension()); assert(!tds.is_vertex(Vertex_handle())); assert(!tds.is_full_cell(Full_cell_handle())); assert(tds.is_vertex(vhs[i])); assert(tds.is_full_cell(vhs[i]->full_cell())); if( tds.current_dimension() > 0 ) { //int nbs = tds.number_of_full_cells(); tds.insert_in_full_cell(tds.full_cell(vhs[i+1])); ++nb_verts; //assert((size_t)(nbs+tds.current_dimension())==tds.number_of_full_cells()); } assert( tds.is_valid() ); } assert((nb_verts == tds.number_of_vertices())); if( d > 1 ) { // insert in hole std::vector<Full_cell_handle> simps; simps.push_back(tds.full_cells_begin()); simps.push_back(tds.neighbor(simps[0],0)); tds.insert_in_hole(simps.begin(), simps.end(), Facet(simps[0],1)); } // TEST Faces enumeration typedef std::vector<Face> Faces; Faces faces; for( Vertex_iterator vit = tds.vertices_begin(); vit != tds.vertices_end(); ++vit ) { for( int d = 1; d < tds.current_dimension() - 1; ++d ) { //cout << '\n' << d << "-dimensional faces adjacent to " << &(*vit) // << " ( current dimension is " << tds.current_dimension() << " )"; faces.clear(); std::back_insert_iterator<Faces> out(faces); tds.incident_faces(vit, d, out); typename Faces::iterator fit = faces.begin(); while( fit != faces.end() ) { //cout << '\n'; //for( int i = 0; i <= d; ++i ) // cout << ' ' << &(*fit->vertex(i)); ++fit; } } } // TEST Finite iterators if( tds.current_dimension() > 0 ) { Facet_iterator fit = tds.facets_begin(); size_t nbfft(0); while( fit != tds.facets_end() ) ++fit, ++nbfft; cout << '\n' << tds.number_of_full_cells() << " full cells, "; cout << ' ' << nbfft << " facets."; } // TEST File I/O std::ofstream fo((string("output-tds-")+type).c_str()); if( d % 2 ) CGAL::set_binary_mode(fo); fo << tds; fo.close(); std::ifstream fi((string("output-tds-")+type).c_str()); if( d % 2 ) CGAL::set_binary_mode(fi); TDS input_tds(d); fi >> input_tds; fi.close(); // TEST Copy Constructor TDS tds2(tds); assert( tds2.is_valid() ); assert( tds.current_dimension() == tds2.current_dimension() ); assert( tds.maximal_dimension() == tds2.maximal_dimension() ); assert( tds.number_of_vertices() == tds2.number_of_vertices() ); assert( tds.number_of_full_cells() == tds2.number_of_full_cells() ); // CLEAR tds.clear(); assert(-2==tds.current_dimension()); assert(tds.empty()); assert( tds.is_valid() ); }
// greebo: TODO: Make this a member method of the Brush class bool Brush_merge(Brush& brush, const BrushPtrVector& in, bool onlyshape) { // gather potential outer faces typedef std::vector<const Face*> Faces; Faces faces; for (BrushPtrVector::const_iterator i(in.begin()); i != in.end(); ++i) { (*i)->getBrush().evaluateBRep(); for (Brush::const_iterator j((*i)->getBrush().begin()); j != (*i)->getBrush().end(); ++j) { if (!(*j)->contributes()) { continue; } const Face& face1 = *(*j); bool skip = false; // test faces of all input brushes //!\todo SPEEDUP: Flag already-skip faces and only test brushes from i+1 upwards. for (BrushPtrVector::const_iterator k(in.begin()); !skip && k != in.end(); ++k) { if (k != i) { // don't test a brush against itself for (Brush::const_iterator l((*k)->getBrush().begin()); !skip && l != (*k)->getBrush().end(); ++l) { const Face& face2 = *(*l); // face opposes another face if (face1.plane3() == -face2.plane3()) { // skip opposing planes skip = true; break; } } } } // check faces already stored for (Faces::const_iterator m = faces.begin(); !skip && m != faces.end(); ++m) { const Face& face2 = *(*m); // face equals another face if (face1.plane3() == face2.plane3()) { // if the texture/shader references should be the same but are not if (!onlyshape && !shader_equal( face1.getFaceShader().getMaterialName(), face2.getFaceShader().getMaterialName() )) { return false; } // skip duplicate planes skip = true; break; } // face1 plane intersects face2 winding or vice versa if (Winding::planesConcave(face1.getWinding(), face2.getWinding(), face1.plane3(), face2.plane3())) { // result would not be convex return false; } } if (!skip) { faces.push_back(&face1); } } } for (Faces::const_iterator i = faces.begin(); i != faces.end(); ++i) { if (!brush.addFace(*(*i))) { // result would have too many sides return false; } } brush.removeEmptyFaces(); return true; }