cgal/Stream_support/src/File_header_OFF.C

398 lines
12 KiB
C

// Copyright (c) 1997 Utrecht University (The Netherlands),
// ETH Zurich (Switzerland), Freie Universitaet Berlin (Germany),
// INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg
// (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria),
// and Tel-Aviv University (Israel). 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 Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with CGAL.
//
// 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) : Lutz Kettner <kettner@mpi-sb.mpg.de>
#ifndef CGAL_BASIC_H
#include <CGAL/basic.h>
#endif // CGAL_BASIC_H
#ifndef CGAL_KNOWN_BIT_SIZE_INTEGERS_H
#include <CGAL/known_bit_size_integers.h>
#endif
#ifndef CGAL_PROTECT_CSTDLIB
#include <cstdlib>
#define CGAL_PROTECT_CSTDLIB
#endif
#ifndef CGAL_PROTECT_CCTYPE
#include <cctype>
#define CGAL_PROTECT_CCTYPE
#endif
#ifndef CGAL_PROTECT_CSTRING
#include <cstring>
#define CGAL_PROTECT_CSTRING
#endif
#ifndef CGAL_PROTECT_IOSTREAM
#include <iostream>
#define CGAL_PROTECT_IOSTREAM
#endif
#ifndef CGAL_IO_BINARY_FILE_IO_H
#include <CGAL/IO/binary_file_io.h>
#endif // CGAL_IO_BINARY_FILE_IO_H
#ifndef CGAL_IO_FILE_HEADER_OFF_H
#include <CGAL/IO/File_header_OFF.h>
#endif // CGAL_IO_FILE_HEADER_OFF_H
#ifndef CGAL_PROTECT_ALGORITHM
#include <algorithm>
#define CGAL_PROTECT_ALGORITHM
#endif
CGAL_BEGIN_NAMESPACE
File_header_OFF::File_header_OFF( bool verbose)
: File_header_extended_OFF( verbose),
n_vertices(0),
n_facets(0),
m_skel(false),
m_binary(false),
m_no_comments(false),
m_offset(0),
m_colors(false),
m_normals(false),
m_tag4(false),
m_tagDim(false),
m_dim(3)
{}
File_header_OFF::File_header_OFF(
bool binary, bool noc, bool skel, bool verbose)
: File_header_extended_OFF( verbose),
n_vertices(0),
n_facets(0),
m_skel(skel),
m_binary(binary),
m_no_comments(noc),
m_offset(0),
m_colors(false),
m_normals(false),
m_tag4(false),
m_tagDim(false),
m_dim(3)
{}
//File_header_OFF::File_header_OFF( int v, int h, int f,
// bool verbose)
//: File_header_extended_OFF( verbose),
// n_vertices(v),
// n_facets(f),
// m_skel(false),
// m_binary(false),
// m_no_comments(false),
// m_offset(0),
// m_colors(false),
// m_normals(false),
// m_tag4(false),
// m_tagDim(false),
// m_dim(3)
//{
// set_halfedges(h);
//}
File_header_OFF::File_header_OFF( int v, int h, int f,
bool binary, bool noc, bool skel, bool verbose)
: File_header_extended_OFF( verbose),
n_vertices(v),
n_facets(f),
m_skel(skel),
m_binary(binary),
m_no_comments(noc),
m_offset(0),
m_colors(false),
m_normals(false),
m_tag4(false),
m_tagDim(false),
m_dim(3)
{
set_halfedges(h);
}
File_header_OFF::File_header_OFF(
const File_header_extended_OFF& ext_header)
: File_header_extended_OFF( ext_header),
n_vertices(0),
n_facets(0),
m_skel(false),
m_binary(false),
m_no_comments(false),
m_offset(0),
m_colors(false),
m_normals(false),
m_tag4(false),
m_tagDim(false),
m_dim(3)
{}
File_header_OFF::File_header_OFF(
const File_header_extended_OFF& ext_header,
bool binary, bool noc, bool skel)
: File_header_extended_OFF( ext_header),
n_vertices(0),
n_facets(0),
m_skel(skel),
m_binary(binary),
m_no_comments(noc),
m_offset(0),
m_colors(false),
m_normals(false),
m_tag4(false),
m_tagDim(false),
m_dim(3)
{}
File_header_OFF::File_header_OFF(
int v, int h, int f,
const File_header_extended_OFF& ext_header)
: File_header_extended_OFF( ext_header),
n_vertices(v),
n_facets(f),
m_skel(false),
m_binary(false),
m_no_comments(false),
m_offset(0),
m_colors(false),
m_normals(false),
m_tag4(false),
m_tagDim(false),
m_dim(3)
{
set_halfedges(h);
}
File_header_OFF::File_header_OFF(
int v, int h, int f,
const File_header_extended_OFF& ext_header,
bool binary, bool noc, bool skel)
: File_header_extended_OFF( ext_header),
n_vertices(v),
n_facets(f),
m_skel(skel),
m_binary(binary),
m_no_comments(noc),
m_offset(0),
m_colors(false),
m_normals(false),
m_tag4(false),
m_tagDim(false),
m_dim(3)
{
set_halfedges(h);
}
File_header_OFF& File_header_OFF::
operator+=( const File_header_OFF& header) {
(File_header_extended_OFF&)(*this) = header;
n_vertices += header.n_vertices;
n_facets += header.n_facets;
return *this;
}
// Write header.
std::ostream& operator<<( std::ostream& out, const File_header_OFF& h) {
if ( h.comments()) {
out << "# Output of a CGAL tool\n";
out << static_cast<const File_header_extended_OFF&>( h);
}
if ( h.has_normals())
out << 'N';
if ( h.skel())
out << "SKEL";
else
out << "OFF";
if ( h.binary()) {
out << " BINARY\n";
I_Binary_write_big_endian_integer32( out, h.size_of_vertices());
I_Binary_write_big_endian_integer32( out, h.size_of_facets());
if ( h.off())
I_Binary_write_big_endian_integer32( out, 0);
} else {
out << '\n';
out << h.size_of_vertices() << ' '<< h.size_of_facets();
if ( h.off())
out << " 0";
if ( h.comments()) {
out << "\n\n# " << h.size_of_vertices() << " vertices\n";
out << "# ------------------------------------------\n";
}
out << std::endl;
}
return out;
}
// Scan header. Marks streams badbit if not in SKEL format nor in OFF.
std::istream& operator>>( std::istream& in, File_header_OFF& h) {
// read in the first character and scan for comments, `OFF', or `NOFF',
// or `SKEL', or `4SKEL'.
h.set_off_header( false);
char c;
while ( (in >> c) && c == '#') {
if ( in.get(c) && c == 'C' &&
in.get(c) && c == 'B' &&
in.get(c) && c == 'P') {
in >> static_cast<File_header_extended_OFF&>( h);
} else if ( c != '\n')
in >> skip_until_EOL;
}
if ( ! in)
return in;
h.set_skel( false);
h.set_binary( false);
h.set_index_offset( 1);
h.set_colors( false);
h.set_normals( false);
h.set_homogeneous( false);
h.set_dimensional( false);
h.set_dimension( 3);
const int max_keyword = 42;
char keyword[max_keyword] = "";
int i = 0;
keyword[i++] = c;
while( i < max_keyword - 1 && in.get(c) && CGAL_CLIB_STD::isalnum(c))
keyword[i++] = c;
keyword[i] = '\0';
if ( i < 2 || (CGAL_CLIB_STD::isdigit(keyword[0]) && keyword[0] != '4')
|| CGAL_CLIB_STD::isdigit(keyword[1])) {
h.set_vertices( CGAL_CLIB_STD::atoi( keyword));
} else {
h.set_index_offset( 0);
int j = 0;
if ( j < i && keyword[j] == 'C') {
h.set_colors( true);
j++;
}
if ( j < i && keyword[j] == 'N') {
h.set_normals( true);
j++;
}
if ( j < i && keyword[j] == '4') {
h.set_homogeneous( true);
j++;
}
if ( j < i && keyword[j] == 'n') {
h.set_dimensional( true);
j++;
}
if ( i-j != 3 || keyword[j] != 'O'
|| keyword[j+1] != 'F'
|| keyword[j+2] != 'F') {
if ( i-j != 4 || keyword[j] != 'S'
|| keyword[j+1] != 'K'
|| keyword[j+2] != 'E'
|| keyword[j+3] != 'L') {
in.clear( std::ios::badbit);
if ( h.verbose()) {
std::cerr << " " << std::endl;
std::cerr << "error: File_header_OFF: "
"wrong format: neither OFF nor SKEL."
<< std::endl;
}
return in;
} else {
h.set_skel( true);
}
}
in >> skip_comment_OFF >> c;
if ( CGAL_CLIB_STD::isdigit(c)) {
in.putback(c);
int n;
in >> n;
h.set_vertices(n);
} else {
i = 0;
keyword[i++] = c;
while( i < max_keyword - 1 && in.get(c) &&
CGAL_CLIB_STD::isalnum(c))
keyword[i++] = c;
keyword[i] = '\0';
if ( CGAL_CLIB_STD::strcmp( keyword, "BINARY") == 0) {
h.set_binary( true);
if ( c != '\n')
in >> skip_until_EOL;
} else {
in.clear( std::ios::badbit);
if ( h.verbose()) {
std::cerr << " " << std::endl;
std::cerr << "error: File_header_OFF(): "
"wrong format: neither OFF nor SKEL."
<< std::endl;
}
return in;
}
}
}
// Read remaining size value(s).
int n_h;
if ( h.binary()) {
Integer32 a, b, c;
I_Binary_read_big_endian_integer32( in, a);
if ( h.n_dimensional()) {
h.set_dimension( a);
I_Binary_read_big_endian_integer32( in, a);
}
I_Binary_read_big_endian_integer32( in, b);
if ( h.off())
I_Binary_read_big_endian_integer32( in, c);
else
c = 0;
h.set_vertices( a);
h.set_facets( b);
n_h = c;
} else {
int n;
if ( h.n_dimensional()) {
h.set_dimension( h.size_of_vertices());
in >> n;
h.set_vertices(n);
}
in >> n;
h.set_facets(n);
if ( h.off())
in >> n_h;
else
n_h = 0;
}
if ( n_h == 0)
h.set_index_offset( 0);
if ( ! in || h.size_of_vertices() <= 0 || h.size_of_facets() < 0) {
in.clear( std::ios::badbit);
if ( h.verbose()) {
std::cerr << " " << std::endl;
std::cerr << "error: File_header_OFF(): "
"File contains <= 0 vertices or < 0 facets."
<< std::endl;
}
return in;
}
if ( h.size_of_halfedges() == 0) {
// be careful, because border edges count twice
h.set_halfedges( 2 * n_h);
// check against the Eulerian equation for connected planar graphs.
// We do not know the number of holes we must represent as dummy
// facets and we do not know the genus of the surface.
// So we add 12 and a factor of 5 percent.
if ( h.size_of_halfedges() == 0
|| h.size_of_halfedges() > (h.size_of_vertices()
+ h.size_of_facets() - 2 + 12) * 2.1
|| h.size_of_halfedges() < (h.size_of_vertices()
+ h.size_of_facets() - 2) * 2
)
h.set_halfedges( int((h.size_of_vertices() +
h.size_of_facets() - 2 + 12) * 2.1));
}
h.set_off_header( h.off());
return in;
}
CGAL_END_NAMESPACE
// EOF //