mirror of https://github.com/CGAL/cgal
218 lines
6.2 KiB
C++
218 lines
6.2 KiB
C++
// Copyright (c) 2007 INRIA Sophia-Antipolis (France).
|
|
// All rights reserved.
|
|
//
|
|
// This file is part of CGAL (www.cgal.org).
|
|
// You can redistribute it and/or modify it under the terms of the GNU
|
|
// General Public License as published by the Free Software Foundation,
|
|
// either version 3 of the License, or (at your option) any later version.
|
|
//
|
|
// Licensees holding a valid commercial license may use this file in
|
|
// accordance with the commercial license agreement provided with the software.
|
|
//
|
|
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
//
|
|
// $URL$
|
|
// $Id$
|
|
//
|
|
// Author(s) : Laurent Rineau
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <stack>
|
|
#include <boost/tuple/tuple.hpp>
|
|
#include <boost/tuple/tuple_comparison.hpp>
|
|
#include <boost/format.hpp>
|
|
|
|
using std::cout;
|
|
using std::cin;
|
|
using std::endl;
|
|
|
|
int main()
|
|
{
|
|
std::string header;
|
|
cin >> header;
|
|
|
|
if(header != "OFF")
|
|
{
|
|
std::cerr << "header is \"" << header << "\"\nshould be \"OFF\".\n";
|
|
return 1;
|
|
}
|
|
|
|
cout << header << endl;
|
|
unsigned int n_vertices;
|
|
unsigned int n_facets;
|
|
std::string dummy;
|
|
|
|
cin >> n_vertices;
|
|
cin >> n_facets;
|
|
getline(cin, dummy);
|
|
|
|
// Vector that maps from old vertex index to new vertex index,
|
|
// as some (old) vertices may have identical point coordinates.
|
|
std::vector<int> new_index(n_vertices);
|
|
|
|
typedef boost::tuple<double, double, double> Point;
|
|
// Vector that stores the points coordinates (in a Point).
|
|
std::vector<Point> points(n_vertices);
|
|
|
|
// Map that retains the mapping from the point coordinates (in a Point)
|
|
// to the nex index.
|
|
typedef std::map<Point, int> Renumber;
|
|
Renumber renumber;
|
|
|
|
unsigned int index = 0;
|
|
for(unsigned int i = 0; i < n_vertices; ++i)
|
|
{
|
|
cin >> boost::get<0>(points[index])
|
|
>> boost::get<1>(points[index]) >> boost::get<2>(points[index]);
|
|
Renumber::const_iterator it = renumber.find(points[index]);
|
|
if( it == renumber.end() )
|
|
{
|
|
renumber[points[index]] = index;
|
|
new_index[i] = index;
|
|
++index;
|
|
}
|
|
else
|
|
{
|
|
new_index[i] = it->second;
|
|
}
|
|
}
|
|
|
|
cout << index << " " << n_facets << dummy << endl;
|
|
for(unsigned int i = 0; i < index; ++i)
|
|
{
|
|
cout << boost::get<0>(points[i]) << " "
|
|
<< boost::get<1>(points[i]) << " "
|
|
<< boost::get<2>(points[i]) << "\n";
|
|
}
|
|
|
|
// Vector that stores each facet.
|
|
typedef std::vector<boost::tuple<int, int, int> > Facets;
|
|
Facets facets;
|
|
|
|
// For each (oriented) edge, that map stores a vector of adjacent facets,
|
|
// with a boolean that tells if the edge is in the opposite orientation,
|
|
// in the facet.
|
|
// Edges are stores in the direction from the smallest index to the
|
|
// greatest.
|
|
typedef std::pair<int, int> Edge;
|
|
typedef std::map<Edge, std::vector<std::pair<int, bool> > > Edges_map;
|
|
Edges_map edges;
|
|
|
|
// "nested function" opposite, that returns the edge, in the opposite
|
|
// direction.
|
|
struct {
|
|
Edge operator()(Edge e) const {
|
|
return std::make_pair(e.second, e.first);
|
|
};
|
|
} opposite;
|
|
|
|
for(unsigned int i_facet = 0; i_facet < n_facets; ++i_facet)
|
|
{
|
|
// Read a facet, then reindex its vertices.
|
|
int i, j, k;
|
|
cin >> dummy >> i >> j >> k;
|
|
if( dummy != "3" )
|
|
{
|
|
std::cerr << "In facet #" << i_facet << ", expected \"3\", found \""
|
|
<< dummy << "\"!\n";
|
|
return 1;
|
|
}
|
|
i = new_index[i];
|
|
j = new_index[j];
|
|
k = new_index[k];
|
|
facets.push_back(boost::make_tuple(i, j, k));
|
|
|
|
// Create the three edges of the facet.
|
|
Edge e[3];
|
|
e[0] = std::make_pair(i, j);
|
|
e[1] = std::make_pair(j, k);
|
|
e[2] = std::make_pair(k, i);
|
|
for(int i_edge = 0; i_edge < 3; ++i_edge)
|
|
{
|
|
if( e[i_edge].first < e[i_edge].second )
|
|
edges[e[i_edge]].push_back(std::make_pair(i_facet, false));
|
|
else
|
|
edges[opposite(e[i_edge])].push_back(std::make_pair(i_facet, true));
|
|
}
|
|
}
|
|
|
|
// Map that stores all already passed facet, and retains the orientation
|
|
// of the facet. "true" means that the facet needs to be reoriented.
|
|
std::map<int, bool> oriented_set;
|
|
|
|
// Stack of facets indices to be handled.
|
|
std::stack<int> stack;
|
|
int seed_facet_candidate = 0;
|
|
|
|
while (oriented_set.size() != n_facets) {
|
|
// find a facet index that is not yet in 'oriented_set'.
|
|
while( oriented_set.find(seed_facet_candidate) != oriented_set.end() )
|
|
++seed_facet_candidate;
|
|
std::cerr << "Need seed facet: " << seed_facet_candidate << "\n";
|
|
// push it in oriented set
|
|
oriented_set[seed_facet_candidate] = false;
|
|
stack.push(seed_facet_candidate);
|
|
|
|
while(! stack.empty() ) {
|
|
const int f = stack.top();
|
|
stack.pop();
|
|
const int i = boost::get<0>(facets[f]);
|
|
const int j = boost::get<1>(facets[f]);
|
|
const int k = boost::get<2>(facets[f]);
|
|
Edge e[3];
|
|
e[0] = std::make_pair(i, j);
|
|
e[1] = std::make_pair(j, k);
|
|
e[2] = std::make_pair(k, i);
|
|
for(int ih = 0 ; ih < 3 ; ++ih)
|
|
{
|
|
bool f_orient = false;
|
|
if(e[ih].first > e[ih].second) {
|
|
f_orient = true;
|
|
e[ih] = opposite(e[ih]);
|
|
}
|
|
|
|
Edges_map::iterator edge_it = edges.find(e[ih]);
|
|
if(edge_it->second.size() == 2) { // regular edge
|
|
int fn = edge_it->second[0].first;
|
|
bool fn_orient = edge_it->second[0].second;
|
|
if(fn == f)
|
|
{
|
|
fn = edge_it->second[1].first;
|
|
fn_orient = edge_it->second[1].second;
|
|
}
|
|
if (oriented_set.find(fn) == oriented_set.end())
|
|
{
|
|
if(f_orient == fn_orient)
|
|
oriented_set[fn] = ! oriented_set[f];
|
|
else
|
|
oriented_set[fn] = oriented_set[f];
|
|
stack.push(fn);
|
|
}
|
|
} // end "if the edge is regular"
|
|
else {
|
|
std::cerr << boost::format("Irregular edge: (%1%,%2%)"
|
|
", %3% facets.\n")
|
|
% e[ih].first % e[ih].second
|
|
% edge_it->second.size();
|
|
}
|
|
} // end "for each neighbor of f"
|
|
} // end "stack non empty"
|
|
} // end "oriented_set not full"
|
|
|
|
for(unsigned int i_facet = 0; i_facet < n_facets; ++i_facet)
|
|
{
|
|
const int i = boost::get<0>(facets[i_facet]);
|
|
const int j = boost::get<1>(facets[i_facet]);
|
|
const int k = boost::get<2>(facets[i_facet]);
|
|
if(oriented_set[i_facet])
|
|
cout << "3 " << j << " " << i << " " << k << "\n";
|
|
else
|
|
cout << "3 " << i << " " << j << " " << k << "\n";
|
|
}
|
|
}
|
|
|