mirror of https://github.com/CGAL/cgal
Merge pull request #2574 from lrineau/Polyhedron_demo-update_SEP_reader-GF
Polyhedron demo: update the SEP reader
This commit is contained in:
commit
fd1045dcd3
|
|
@ -0,0 +1,313 @@
|
|||
// Copyright (c) 2016, 2017 GeometryFactory
|
||||
// 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; 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$
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
//
|
||||
// Author(s) : Laurent Rineau
|
||||
|
||||
#ifndef CGAL_SEP_HEADER_HPP
|
||||
#define CGAL_SEP_HEADER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/fusion/adapted/boost_tuple.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix_core.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
#include <boost/spirit/include/phoenix_object.hpp>
|
||||
#include <boost/spirit/include/phoenix_stl.hpp>
|
||||
#include <boost/spirit/include/phoenix_fusion.hpp>
|
||||
#include <boost/fusion/include/adapt_struct.hpp>
|
||||
|
||||
#ifdef CGAL_SEP_READER_DEBUG
|
||||
# include <boost/tuple/tuple_io.hpp>
|
||||
// The debug the Boost.Spirit.Qi parser, this is needed:
|
||||
namespace std {
|
||||
template <typename A, typename B>
|
||||
inline std::ostream& operator<<(std::ostream& out, const std::pair<A, B>& id) {
|
||||
return out << id.first << " " << id.second;
|
||||
}
|
||||
} //end namespace std
|
||||
#endif // CGAL_SEP_READER_DEBUG
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
struct SEP_header_aux
|
||||
{
|
||||
typedef std::map<std::string, int> Int_dict;
|
||||
typedef std::map<std::string, double> Double_dict;
|
||||
typedef std::map<std::string, std::string> String_dict;
|
||||
Int_dict int_dict;
|
||||
Double_dict double_dict;
|
||||
String_dict string_dict;
|
||||
|
||||
public:
|
||||
template <typename Tuple_string_variant>
|
||||
SEP_header_aux& operator<<(const Tuple_string_variant& tuple)
|
||||
{
|
||||
using boost::get;
|
||||
visitor vis(this, get<0>(tuple));
|
||||
boost::apply_visitor(vis, get<1>(tuple));
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
struct visitor : public boost::static_visitor<> {
|
||||
SEP_header_aux* self;
|
||||
std::string key;
|
||||
visitor(SEP_header_aux* header, std::string key)
|
||||
: self(header)
|
||||
, key(key)
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
void operator()(const T& t) {
|
||||
// std::cerr << "My assignement ("
|
||||
// << typeid(t).name() << "): "
|
||||
// << key << "=" << t << std::endl;
|
||||
self->add(key, t);
|
||||
}
|
||||
};
|
||||
|
||||
void add(const std::string& key, int v) {
|
||||
int_dict[key] = v;
|
||||
double_dict[key] = v;
|
||||
}
|
||||
|
||||
void add(const std::string& key, const double& v) {
|
||||
double_dict[key] = v;
|
||||
}
|
||||
|
||||
void add(const std::string& key, const std::string& v) {
|
||||
string_dict[key] = v;
|
||||
}
|
||||
}; // end struct SEP_header_aux
|
||||
|
||||
} // end namespace CGAL
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(
|
||||
CGAL::SEP_header_aux,
|
||||
( CGAL::SEP_header_aux::Int_dict, int_dict)
|
||||
( CGAL::SEP_header_aux::Double_dict, double_dict)
|
||||
( CGAL::SEP_header_aux::String_dict, string_dict)
|
||||
)
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
class SEP_header {
|
||||
|
||||
boost::array<std::size_t, 3> _n;
|
||||
boost::array<double, 3> _d;
|
||||
boost::array<double, 3> _o;
|
||||
|
||||
SEP_header_aux::String_dict _string_dict;
|
||||
|
||||
int _dim;
|
||||
|
||||
public:
|
||||
/// constructor
|
||||
SEP_header(std::string fileName) : _dim(-1) {
|
||||
std::ifstream input(fileName.c_str());
|
||||
if(!input) {
|
||||
std::cerr << "Error: cannot open the header file \""
|
||||
<< fileName << "\"!\n";
|
||||
return;
|
||||
}
|
||||
SEP_header_aux header;
|
||||
if(parseHeader(input, header))
|
||||
{
|
||||
get_n(1) = header.int_dict["n1"];
|
||||
get_n(2) = header.int_dict["n2"];
|
||||
get_n(3) = header.int_dict["n3"];
|
||||
_dim = 0;
|
||||
for(int i = 1; i <= 3; ++i) {
|
||||
if(get_n(i) == 0) get_n(i) = 1;
|
||||
if(get_n(i) != 1) ++_dim;
|
||||
}
|
||||
get_d(1) = header.double_dict["d1"];
|
||||
get_d(2) = header.double_dict["d2"];
|
||||
get_d(3) = header.double_dict["d3"];
|
||||
get_o(1) = header.double_dict["o1"];
|
||||
get_o(2) = header.double_dict["o2"];
|
||||
get_o(3) = header.double_dict["o3"];
|
||||
_string_dict = header.string_dict;
|
||||
}
|
||||
}
|
||||
|
||||
/// copy-constructor
|
||||
SEP_header(const SEP_header& other)
|
||||
: _n(other._n)
|
||||
, _d(other._d)
|
||||
, _o(other._o)
|
||||
, _dim(other._dim)
|
||||
{}
|
||||
|
||||
/// const getters
|
||||
/// @{
|
||||
double o(int i) const { return _o[i-1]; }
|
||||
double d(int i) const { return _d[i-1]; }
|
||||
std::size_t n(int i) const { return _n[i-1]; }
|
||||
int dimension() const { return _dim;}
|
||||
std::string string_field(std::string key) const {
|
||||
SEP_header_aux::String_dict::const_iterator it = _string_dict.find(key);
|
||||
if(it == _string_dict.end()) return std::string();
|
||||
else return it->second;
|
||||
}
|
||||
/// @}
|
||||
|
||||
/// non-const getters
|
||||
/// @{
|
||||
double& get_o(int i) { return _o[i-1]; }
|
||||
double& get_d(int i) { return _d[i-1]; }
|
||||
std::size_t& get_n(int i) { return _n[i-1]; }
|
||||
int& get_dim() { return _dim; }
|
||||
/// @}
|
||||
|
||||
std::ostream& display_information(std::string fileName,
|
||||
std::ostream& out) const {
|
||||
out << "Header file: " << fileName << std::endl;
|
||||
out << "Parameters:\n";
|
||||
out << "dimension = " << dimension() << "\n";
|
||||
for(int i = 1; i <= 3 ; ++i) {
|
||||
out << "d" << i << " = " << d(i) << "\n";
|
||||
out << "n" << i << " = " << n(i) << "\n";
|
||||
out << "o" << i << " = " << o(i) << "\n";
|
||||
}
|
||||
out << "in = " << string_field("in") << std::endl;
|
||||
return out;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Iterator>
|
||||
struct sep_header_grammar : boost::spirit::qi::grammar<Iterator, SEP_header_aux()>
|
||||
{
|
||||
sep_header_grammar()
|
||||
: sep_header_grammar::base_type(header,
|
||||
"sep_header_grammar")
|
||||
{
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace ascii = boost::spirit::ascii;
|
||||
using qi::lexeme;
|
||||
using ascii::char_;
|
||||
using qi::int_;
|
||||
using qi::real_parser;
|
||||
using boost::phoenix::at_c;
|
||||
using qi::_1;
|
||||
using qi::_2;
|
||||
using qi::_val;
|
||||
|
||||
qi::real_parser<double,
|
||||
qi::strict_real_policies<double> > double_with_dot;
|
||||
|
||||
skip_comment = ('#' >> *(qi::char_ - qi::eol) >> qi::eol);
|
||||
skip_comment.name("my skip comment");
|
||||
|
||||
skip = skip_comment | qi::space;
|
||||
skip.name("my skipper");
|
||||
|
||||
identifier = +((qi::alnum|char_('_'))[_val += _1]);
|
||||
identifier.name("my identifier");
|
||||
|
||||
string = +(char_ - qi::space)[_val += _1];
|
||||
string.name("my string");
|
||||
|
||||
quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
|
||||
quoted_string.name("my quoted string");
|
||||
|
||||
variant_of_value %= ( double_with_dot
|
||||
|
|
||||
int_
|
||||
|
|
||||
(quoted_string | string) );
|
||||
variant_of_value.name("my value");
|
||||
|
||||
assignment %= (identifier >> '=' >> variant_of_value);
|
||||
assignment.name("my assignment");
|
||||
|
||||
header = (*skip) >> +( assignment[_val << _1] >> (*skip));
|
||||
header.name("SEP header");
|
||||
|
||||
using boost::phoenix::construct;
|
||||
using boost::phoenix::val;
|
||||
qi::on_error<qi::fail>
|
||||
(
|
||||
header,
|
||||
std::cout
|
||||
<< val("Error! Expecting ")
|
||||
<< qi::_4 // what failed?
|
||||
<< val(" here: \"")
|
||||
<< construct<std::string>(qi::_3, qi::_2) // iterators to error-pos, end
|
||||
<< val("\"")
|
||||
<< std::endl
|
||||
);
|
||||
#ifdef CGAL_SEP_READER_DEBUG
|
||||
qi::debug(skip);
|
||||
qi::debug(skip_comment);
|
||||
qi::debug(identifier);
|
||||
qi::debug(header);
|
||||
qi::debug(variant_of_value);
|
||||
qi::debug(assignment);
|
||||
qi::debug(string);
|
||||
qi::debug(quoted_string);
|
||||
#endif // CGAL_SEP_READER_DEBUG
|
||||
} // end constructor of sep_header_grammar
|
||||
|
||||
typedef boost::variant<double,
|
||||
int,
|
||||
std::string> value;
|
||||
typedef boost::tuple<std::string, value> entry_type;
|
||||
|
||||
boost::spirit::qi::rule<Iterator> skip_comment;
|
||||
boost::spirit::qi::rule<Iterator> skip;
|
||||
boost::spirit::qi::rule<Iterator, std::string()> identifier;
|
||||
boost::spirit::qi::rule<Iterator, std::string()> quoted_string;
|
||||
boost::spirit::qi::rule<Iterator, std::string()> string;
|
||||
boost::spirit::qi::rule<Iterator, value()> variant_of_value;
|
||||
boost::spirit::qi::rule<Iterator, entry_type() > assignment;
|
||||
boost::spirit::qi::rule<Iterator, SEP_header_aux() > header;
|
||||
}; // end class template sep_header_grammar<Iterator>
|
||||
|
||||
bool parseHeader(std::ifstream& input, SEP_header_aux& header) {
|
||||
std::string file_content;
|
||||
|
||||
input.seekg(0, std::ios::end);
|
||||
file_content.reserve(input.tellg());
|
||||
input.seekg(0, std::ios::beg);
|
||||
|
||||
file_content.assign(std::istreambuf_iterator<char>(input),
|
||||
std::istreambuf_iterator<char>());
|
||||
if(!input) return false;
|
||||
|
||||
typedef std::string::const_iterator iterator;
|
||||
|
||||
iterator begin(file_content.begin()), end(file_content.end());
|
||||
|
||||
sep_header_grammar<iterator> grammar;
|
||||
|
||||
bool b = boost::spirit::qi::parse(begin, end, grammar, header);
|
||||
return b && (begin == end);
|
||||
}
|
||||
}; // end class SEP_header
|
||||
|
||||
} // end namespace CGAL
|
||||
|
||||
#endif // CGAL_SEP_HEADER_HPP
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
// Copyright (c) 2016, 2017 GeometryFactory
|
||||
// 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; 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$
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
//
|
||||
// Author(s) : Laurent Rineau
|
||||
|
||||
#ifndef CGAL_SEP_READER_IMAGEIO_HPP
|
||||
#define CGAL_SEP_READER_IMAGEIO_HPP
|
||||
|
||||
#include "SEP_header.h"
|
||||
#include <CGAL/ImageIO.h>
|
||||
#include <CGAL/Image_3.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
|
||||
#ifndef BOOST_FILESYSTEM_VERSION
|
||||
// That macro was not defined in previous releases of Boost.
|
||||
# define BOOST_FILESYSTEM_VERSION 2
|
||||
#endif
|
||||
|
||||
#include <CGAL/IO/binary_file_io.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename T>
|
||||
class SEP_to_ImageIO : public SEP_header
|
||||
{
|
||||
T* _data;
|
||||
_image* _im;
|
||||
CGAL::Image_3* _cgal_image;
|
||||
|
||||
bool valid;
|
||||
std::string err_msg;
|
||||
|
||||
public:
|
||||
bool is_valid() const { return valid; }
|
||||
std::string error_msg() const { return err_msg; }
|
||||
|
||||
SEP_to_ImageIO(std::string fileName)
|
||||
: SEP_header(fileName),
|
||||
_data(0),
|
||||
_im(0), _cgal_image(0),
|
||||
valid(false), err_msg()
|
||||
{
|
||||
if(dimension() < 0) {
|
||||
err_msg = "Invalid header file \"";
|
||||
err_msg += fileName;
|
||||
err_msg += "\"";
|
||||
return;
|
||||
}
|
||||
display_information(fileName, std::cout);
|
||||
|
||||
boost::filesystem::path headerFile(fileName);
|
||||
boost::filesystem::path dataFile(string_field("in"));
|
||||
#if BOOST_FILESYSTEM_VERSION == 2
|
||||
dataFile = boost::filesystem::complete(dataFile,
|
||||
boost::filesystem::complete(headerFile.parent_path()));
|
||||
#else
|
||||
dataFile = boost::filesystem::absolute(dataFile,
|
||||
boost::filesystem::absolute(headerFile.parent_path()));
|
||||
#endif
|
||||
if(!load_data(dataFile.string())) {
|
||||
return;
|
||||
err_msg = "Invalid data file \"";
|
||||
err_msg += dataFile.string();
|
||||
err_msg += "\"";
|
||||
}
|
||||
valid = true;
|
||||
}
|
||||
|
||||
~SEP_to_ImageIO()
|
||||
{
|
||||
if(_cgal_image != 0) delete _cgal_image;
|
||||
}
|
||||
|
||||
CGAL::Image_3* cgal_image() { return _cgal_image; }
|
||||
const CGAL::Image_3* cgal_image() const { return _cgal_image; }
|
||||
|
||||
protected :
|
||||
|
||||
bool load_data(std::string dataFilename)
|
||||
{
|
||||
if(_im) delete _im;
|
||||
_im = new _image;
|
||||
_im->xdim = static_cast<unsigned int>(n(1));
|
||||
_im->ydim = static_cast<unsigned int>(n(2));
|
||||
_im->zdim = static_cast<unsigned int>(n(3));
|
||||
_im->vdim = 1;
|
||||
|
||||
// spacing
|
||||
_im->vx = d(1);
|
||||
_im->vy = d(2);
|
||||
_im->vz = d(3);
|
||||
if(_im->vz == 0.f) _im->vz=1.f;
|
||||
|
||||
// image offset
|
||||
_im->tx = static_cast<float>(o(1));
|
||||
_im->ty = static_cast<float>(o(2));
|
||||
_im->tz = static_cast<float>(o(3));
|
||||
|
||||
// image center
|
||||
_im->cx = _im->cy = _im->cz = 0;
|
||||
// image rotation
|
||||
_im->rx = _im->ry = _im->rz = 0.0;
|
||||
|
||||
_im->fd = NULL;
|
||||
_im->openMode = OM_CLOSE;
|
||||
if(string_field("data_format") == "native_float" ||
|
||||
string_field("data_format") == "\"native_float\"")
|
||||
{
|
||||
_im->endianness = END_LITTLE;
|
||||
} else {
|
||||
_im->endianness = END_BIG;
|
||||
}
|
||||
|
||||
_im->dataMode = DM_BINARY;
|
||||
|
||||
// no user string
|
||||
_im->user = NULL;
|
||||
_im->nuser = 0;
|
||||
|
||||
// word type (unsigned byte)
|
||||
_im->wdim = sizeof(T);
|
||||
_im->wordKind = WK_FLOAT;
|
||||
_im->vectMode = VM_SCALAR;
|
||||
_im->sign = SGN_SIGNED;
|
||||
_im->imageFormat = NULL;
|
||||
|
||||
::_openReadImage(_im, dataFilename.c_str());
|
||||
if(!_im->fd) return false;
|
||||
|
||||
// Compute number of element
|
||||
const std::size_t size = n(1) * n(2) * n(3);
|
||||
|
||||
// Allocate array
|
||||
_data = new T[size];
|
||||
_im->data = (void*)_data;
|
||||
|
||||
// // Read file
|
||||
if(_readImageData(_im) < 0) return false;
|
||||
// char* buffer = reinterpret_cast<char*>(_data);
|
||||
// in.read (buffer, size * sizeof(T));
|
||||
|
||||
ImageIO_close(_im);
|
||||
_cgal_image = new CGAL::Image_3(_im);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace CGAL
|
||||
|
||||
#endif // CGAL_SEP_READER_IMAGEIO_HPP
|
||||
|
|
@ -1,420 +0,0 @@
|
|||
// Copyright (c) 2016 GeometryFactory
|
||||
// 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; 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$
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
//
|
||||
//
|
||||
// Author(s) : Laurent Rineau
|
||||
|
||||
#ifndef CGAL_READ_SEP_IMAGE_DATA_H
|
||||
#define CGAL_READ_SEP_IMAGE_DATA_H
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
|
||||
#ifndef BOOST_FILESYSTEM_VERSION
|
||||
// That macro was not defined in previous releases of Boost.
|
||||
# define BOOST_FILESYSTEM_VERSION 2
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix_core.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
#include <boost/spirit/include/phoenix_stl.hpp>
|
||||
|
||||
#include <CGAL/ImageIO.h>
|
||||
#include <CGAL/Image_3.h>
|
||||
|
||||
namespace read_file {
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace ascii = boost::spirit::ascii;
|
||||
|
||||
template <typename Iterator>
|
||||
bool parse_comment_or_empty(Iterator first, Iterator last) {
|
||||
using qi::phrase_parse;
|
||||
using ascii::space;
|
||||
using qi::char_;
|
||||
using qi::string;
|
||||
using qi::eoi;
|
||||
|
||||
bool r = phrase_parse(
|
||||
first, /*< start iterator >*/
|
||||
last, /*< end iterator >*/
|
||||
string("#") >> *(char_)|eoi, /*< the parser >*/
|
||||
space /*< the skip-parser >*/
|
||||
);
|
||||
if (first != last) // fail if we did not get a full match
|
||||
return false;
|
||||
return r;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Parser, typename Value>
|
||||
bool parse_assignement(Iterator first, Iterator last,
|
||||
Parser parser,
|
||||
std::string& parameter_name, Value& value)
|
||||
{
|
||||
using qi::phrase_parse;
|
||||
using ascii::space;
|
||||
using qi::char_;
|
||||
using boost::spirit::qi::_1;
|
||||
using boost::phoenix::ref;
|
||||
using boost::phoenix::push_back;
|
||||
|
||||
bool r = phrase_parse(first, /*< start iterator >*/
|
||||
last, /*< end iterator >*/
|
||||
*(char_ - '=')[push_back( boost::phoenix::ref(parameter_name), _1)]
|
||||
>> '='
|
||||
>> parser[ boost::phoenix::ref(value) = _1], /*< the parser >*/
|
||||
space /*< the skip-parser >*/
|
||||
);
|
||||
if (first != last) // fail if we did not get a full match
|
||||
return false;
|
||||
return r;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
bool parse_string_assignement(Iterator first, Iterator last,
|
||||
std::string& parameter_name,
|
||||
std::string& value)
|
||||
{
|
||||
using qi::phrase_parse;
|
||||
using ascii::space;
|
||||
using qi::char_;
|
||||
using boost::spirit::qi::_1;
|
||||
using boost::phoenix::ref;
|
||||
using boost::phoenix::push_back;
|
||||
|
||||
bool r = phrase_parse(first, /*< start iterator >*/
|
||||
last, /*< end iterator >*/
|
||||
*(char_ - '=')[push_back( boost::phoenix::ref(parameter_name), _1)]
|
||||
>> '='
|
||||
>> *char_[push_back( boost::phoenix::ref(value), _1)],
|
||||
/*< the parser >*/
|
||||
space /*< the skip-parser >*/
|
||||
);
|
||||
if (first != last) // fail if we did not get a full match
|
||||
return false;
|
||||
return r;
|
||||
}
|
||||
|
||||
} // end namespace read_file
|
||||
|
||||
template <typename T>
|
||||
class Sep_reader
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
std::string _fileName;
|
||||
|
||||
boost::array<std::size_t, 3> _n;
|
||||
boost::array<double, 3> _d;
|
||||
boost::array<double, 3> _o;
|
||||
|
||||
T* _data;
|
||||
_image* _im;
|
||||
CGAL::Image_3* _cgal_image;
|
||||
|
||||
bool valid;
|
||||
std::string err_msg;
|
||||
|
||||
std::map<std::string, int> int_dict;
|
||||
std::map<std::string, double> double_dict;
|
||||
std::map<std::string, std::string> string_dict;
|
||||
|
||||
int dimension;
|
||||
|
||||
const T special_value;
|
||||
|
||||
bool parseHeader(std::string fileName) {
|
||||
using boost::spirit::qi::int_;
|
||||
using boost::spirit::qi::double_;
|
||||
|
||||
std::ifstream input(fileName.c_str());
|
||||
if(!input) {
|
||||
std::cerr << "Error: cannot open the header file \""
|
||||
<< fileName << "\"!\n";
|
||||
return false;
|
||||
}
|
||||
std::string line;
|
||||
while(std::getline(input, line)) {
|
||||
if(read_file::parse_comment_or_empty(line.begin(), line.end())) continue;
|
||||
std::string parameter;
|
||||
int i;
|
||||
if(read_file::parse_assignement(line.begin(), line.end(),
|
||||
int_,
|
||||
parameter,
|
||||
i))
|
||||
{
|
||||
int_dict[parameter] = i;
|
||||
continue;
|
||||
}
|
||||
parameter.clear();
|
||||
double d;
|
||||
if(read_file::parse_assignement(line.begin(), line.end(),
|
||||
double_,
|
||||
parameter,
|
||||
d))
|
||||
{
|
||||
// std::cerr << parameter << "=" << d << std::endl;
|
||||
double_dict[parameter] = d;
|
||||
continue;
|
||||
}
|
||||
parameter.clear();
|
||||
std::string s;
|
||||
if(read_file::parse_string_assignement(line.begin(), line.end(),
|
||||
parameter,
|
||||
s))
|
||||
{
|
||||
// std::cerr << parameter << "=" << s << std::endl;
|
||||
string_dict[parameter] = s;
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
double& o(int i) { return _o[i-1]; }
|
||||
double& d(int i) { return _d[i-1]; }
|
||||
std::size_t& n(int i) { return _n[i-1]; }
|
||||
public:
|
||||
const double& o(int i) const { return _o[i-1]; }
|
||||
const double& d(int i) const { return _d[i-1]; }
|
||||
const std::size_t& n(int i) const { return _n[i-1]; }
|
||||
|
||||
bool is_valid() const { return valid; }
|
||||
std::string error_msg() const { return err_msg; }
|
||||
|
||||
Sep_reader(std::string fileName,
|
||||
const T special_value = std::numeric_limits<T>::infinity())
|
||||
: _fileName(fileName), _im(0), _cgal_image(0),
|
||||
valid(false), err_msg()
|
||||
, dimension(0), special_value(special_value)
|
||||
{
|
||||
if(!parseHeader(fileName)) {
|
||||
err_msg = "Invalid header file \"";
|
||||
err_msg += fileName;
|
||||
err_msg += "\"";
|
||||
return;
|
||||
}
|
||||
n(1) = int_dict["n1"];
|
||||
n(2) = int_dict["n2"];
|
||||
n(3) = int_dict["n3"];
|
||||
if(n(3)==0) {
|
||||
n(3) = 1;
|
||||
dimension = 2;
|
||||
}
|
||||
else {
|
||||
dimension = 3;
|
||||
}
|
||||
d(1) = double_dict["d1"];
|
||||
d(2) = double_dict["d2"];
|
||||
d(3) = double_dict["d3"];
|
||||
o(1) = double_dict["o1"];
|
||||
o(2) = double_dict["o2"];
|
||||
o(3) = double_dict["o3"];
|
||||
|
||||
std::cout << "Header file: " << fileName << std::endl;
|
||||
std::cout << "Parameters:\n";
|
||||
std::cout << "dimension = " << dimension << "\n";
|
||||
for(int i = 1; i <= 3 ; ++i) {
|
||||
std::cout << "d" << i << " = " << d(i) << "\n";
|
||||
std::cout << "n" << i << " = " << n(i) << "\n";
|
||||
std::cout << "o" << i << " = " << o(i) << "\n";
|
||||
}
|
||||
std::cout << "in = " << string_dict["in"] << std::endl;
|
||||
|
||||
boost::filesystem::path headerFile(fileName);
|
||||
boost::filesystem::path dataFile(string_dict["in"]);
|
||||
#if BOOST_FILESYSTEM_VERSION == 2
|
||||
dataFile = boost::filesystem::complete(dataFile,
|
||||
boost::filesystem::complete(headerFile.parent_path()));
|
||||
#else
|
||||
dataFile = boost::filesystem::absolute(dataFile,
|
||||
boost::filesystem::absolute(headerFile.parent_path()));
|
||||
#endif
|
||||
if(!load_data(dataFile.string())) {
|
||||
return;
|
||||
err_msg = "Invalid data file \"";
|
||||
err_msg += dataFile.string();
|
||||
err_msg += "\"";
|
||||
}
|
||||
std::cout << "min = " << (min)() << std::endl;
|
||||
std::cout << "special value = " << special_value << std::endl;
|
||||
valid = true;
|
||||
}
|
||||
|
||||
~Sep_reader()
|
||||
{
|
||||
if(_cgal_image != 0) delete _cgal_image;
|
||||
std::cerr << "Sep_reader destroyed\n";
|
||||
}
|
||||
|
||||
CGAL::Image_3* cgal_image() { return _cgal_image; }
|
||||
const CGAL::Image_3* cgal_image() const { return _cgal_image; }
|
||||
|
||||
const T& raw_value(std::size_t i, std::size_t j, std::size_t k = 0) const {
|
||||
const T* result = &_data[i + n(1) * ( j + n(2)*k )];
|
||||
// if(*result <= special_value) result = &raw_value(i, j, k + 1);
|
||||
return *result;
|
||||
}
|
||||
|
||||
T interpolation(const double& x, const double& y) const
|
||||
{
|
||||
const double lx = (x - o(1)) / d(1);
|
||||
const double ly = (y - o(2)) / d(2);
|
||||
|
||||
const std::size_t i1 = convert2index<1>(x);
|
||||
const std::size_t j1 = convert2index<2>(y);
|
||||
std::size_t i2 = i1 + 1;
|
||||
std::size_t j2 = j1 + 1;
|
||||
|
||||
if(i2 == n(1)) i2 = n(1) - 1;
|
||||
if(j2 == n(2)) j2 = n(2) - 1;
|
||||
|
||||
const double di2 = i2 - lx;
|
||||
const double di1 = lx - i1;
|
||||
const double dj2 = j2 - ly;
|
||||
const double dj1 = ly - j1;
|
||||
|
||||
const double v11 = raw_value(i1, j1);
|
||||
const double v12 = raw_value(i1, j2);
|
||||
|
||||
return
|
||||
(v11 * di2 + v12 * di1) * dj2 +
|
||||
(v11 * di2 + v12 * di1) * dj1;
|
||||
}
|
||||
|
||||
const T& operator()(const double& x, const double& y) const
|
||||
{
|
||||
const std::size_t i = convert2index<1>(x);
|
||||
const std::size_t j = convert2index<2>(y);
|
||||
return raw_value(i, j, 0);
|
||||
}
|
||||
|
||||
|
||||
const T& operator()(const double& x, const double& y, const double& z) const
|
||||
{
|
||||
const std::size_t i = convert2index<1>(x);
|
||||
const std::size_t j = convert2index<2>(y);
|
||||
const std::size_t k = convert2index<3>(z);
|
||||
return raw_value(i, j, k);
|
||||
}
|
||||
|
||||
template <int dim>
|
||||
std::size_t convert2index(const double& x) const {
|
||||
const double k = (x - o(dim)) / d(dim);
|
||||
if (k < 0) return 0;
|
||||
else if (k >= n(dim)) return n(dim) - 1;
|
||||
else return static_cast<std::size_t>(k);
|
||||
}
|
||||
|
||||
template <int dim>
|
||||
double index2coord(const std::size_t& i) const {
|
||||
return o(dim) + d(dim) * i;
|
||||
}
|
||||
|
||||
|
||||
T min BOOST_PREVENT_MACRO_SUBSTITUTION() const {
|
||||
return *std::min_element(_data, _data + n(1) * n(2) * n(3));
|
||||
}
|
||||
T max BOOST_PREVENT_MACRO_SUBSTITUTION() const {
|
||||
return *std::max_element(_data, _data + n(1) * n(2) * n(3));
|
||||
}
|
||||
|
||||
protected :
|
||||
|
||||
bool load_data(std::string dataFilename)
|
||||
{
|
||||
if(_im) delete _im;
|
||||
_im = new _image;
|
||||
_im->xdim = static_cast<unsigned int>(n(1));
|
||||
_im->ydim = static_cast<unsigned int>(n(2));
|
||||
_im->zdim = static_cast<unsigned int>(n(3));
|
||||
_im->vdim = 1;
|
||||
|
||||
// spacing
|
||||
_im->vx = d(1);
|
||||
_im->vy = d(2);
|
||||
_im->vz = d(3);
|
||||
if(_im->vz == 0.f) _im->vz=1.f;
|
||||
|
||||
// image offset
|
||||
_im->tx = static_cast<float>(o(1));
|
||||
_im->ty = static_cast<float>(o(2));
|
||||
_im->tz = static_cast<float>(o(3));
|
||||
|
||||
// image center
|
||||
_im->cx = _im->cy = _im->cz = 0;
|
||||
// image rotation
|
||||
_im->rx = _im->ry = _im->rz = 0.0;
|
||||
|
||||
_im->fd = NULL;
|
||||
_im->openMode = OM_CLOSE;
|
||||
if(string_dict["data_format"] == "native_float" ||
|
||||
string_dict["data_format"] == "\"native_float\"")
|
||||
{
|
||||
std::cerr << "little endian\n";
|
||||
_im->endianness = END_LITTLE;
|
||||
} else {
|
||||
std::cerr << "big endian\n";
|
||||
_im->endianness = END_BIG;
|
||||
}
|
||||
|
||||
_im->dataMode = DM_BINARY;
|
||||
|
||||
// no user string
|
||||
_im->user = NULL;
|
||||
_im->nuser = 0;
|
||||
|
||||
// word type (unsigned byte)
|
||||
_im->wdim = sizeof(T);
|
||||
_im->wordKind = WK_FLOAT;
|
||||
_im->vectMode = VM_SCALAR;
|
||||
_im->sign = SGN_SIGNED;
|
||||
_im->imageFormat = NULL;
|
||||
|
||||
::_openReadImage(_im, dataFilename.c_str());
|
||||
if(!_im->fd) return false;
|
||||
|
||||
// Compute number of element
|
||||
const std::size_t size = n(1) * n(2) * n(3);
|
||||
|
||||
// Allocate array
|
||||
_data = new T[size];
|
||||
_im->data = (void*)_data;
|
||||
|
||||
// // Read file
|
||||
if(_readImageData(_im) < 0) return false;
|
||||
// char* buffer = reinterpret_cast<char*>(_data);
|
||||
// in.read (buffer, size * sizeof(T));
|
||||
|
||||
ImageIO_close(_im);
|
||||
_cgal_image = new CGAL::Image_3(_im);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CGAL_READ_SEP_IMAGE_DATA_H
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include <CGAL/Image_3.h>
|
||||
#include <CGAL/ImageIO.h>
|
||||
#include <CGAL/read_sep_image_data.h>
|
||||
#include <CGAL/SEP_to_ImageIO.h>
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
||||
#include <CGAL/Three/Scene_interface.h>
|
||||
|
|
@ -1062,7 +1062,7 @@ Io_image_plugin::load(QFileInfo fileinfo) {
|
|||
//read a sep file
|
||||
else if(fileinfo.suffix() == "H" || fileinfo.suffix() == "HH")
|
||||
{
|
||||
Sep_reader<float> reader(fileinfo.filePath().toUtf8().data());
|
||||
CGAL::SEP_to_ImageIO<float> reader(fileinfo.filePath().toUtf8().data());
|
||||
*image = *reader.cgal_image();
|
||||
is_gray = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -534,10 +534,6 @@ void Volume_plane<T>::init(Viewer_interface* viewer) {
|
|||
|
||||
assert(vertices.size() == (3 * adim_ * bdim_));
|
||||
|
||||
int maxi, maxv;
|
||||
viewer->glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &maxi);
|
||||
viewer->glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &maxv);
|
||||
assert((vertices.size( ) / 3) < (unsigned int)maxi);
|
||||
vVBO.create();
|
||||
vVBO.bind();
|
||||
vVBO.allocate(vertices.data(),static_cast<int>(sizeof(float) * vertices.size()));
|
||||
|
|
|
|||
Loading…
Reference in New Issue