objectstream.cpp
来自「算断裂的」· C++ 代码 · 共 944 行 · 第 1/2 页
CPP
944 行
// ------------------------------------------------------------------// objectstream.cpp//// This file contains functions for reading and writing a brep or// simplicial complex from/to a stream.// ------------------------------------------------------------------// Author: Stephen A. Vavasis// Copyright (c) 1999 by Cornell University. All rights reserved.// // See the accompanying file 'Copyright' for authorship information,// the terms of the license governing this software, and disclaimers// concerning this software.// ------------------------------------------------------------------// This file is part of the QMG software. // Version 2.0 of QMG, release date September 3, 1999.// ------------------------------------------------------------------#ifdef _MSC_VER#if _MSC_VER == 1200#pragma warning (disable: 4786)#pragma warning (disable: 4788)#endif#endif#include <iomanip>#include <cctype>#include "qerr.h"#include "qbrep_constr.h"#include "qsimpcomp.h"// exported functions:namespace QMG { Object_Type_Code read_header_from_istream(istream& istr, int& line_count); void init_faceselect_order(vector<unsigned int>& order, int gdim); string get_element_typename(int gdim, int order);}namespace { using namespace QMG; // ------------------------------------------------------------------ // class Ostream_with_wraparound // Nonglobal class Ostream_with_wraparound is like an ostream, // except it checks whether line length has exceeded 72 and if so // inserts a newline. class Ostream_with_wraparound { private: ostream& real_stream_; int linelength_; bool break_allowed_; public: ostream& real_stream() { return real_stream_;} void putstring(const ostringstream& ostr_tmp); explicit Ostream_with_wraparound(ostream& os) : real_stream_(os), linelength_(0), break_allowed_(true) { } void forbid_break() {break_allowed_ = false;} void enable_break() {break_allowed_ = true;} }; void Ostream_with_wraparound::putstring(const ostringstream& ostr_tmp) { const string& outstr = ostr_tmp.str(); int len = outstr.length(); int plen = 0; bool hasnewline = false; for (int j = 0; j < len; ++j) { if (outstr[j] == '\n') { plen = 0; hasnewline = true; } else if (outstr[j] == '\t') { ++plen; if (plen % 8) plen += (8 - (plen % 8)); } else { ++plen; } } if (hasnewline || !break_allowed_) { real_stream_ << outstr; linelength_ = plen; } else { if (linelength_ + plen > 72) { real_stream_ << "\n "; linelength_ = 4; } real_stream_ << outstr; linelength_ += plen; } } template<class T> Ostream_with_wraparound& operator<<(Ostream_with_wraparound& os, const T& t) { ostringstream ostr_tmp; ostr_tmp << t; os.putstring(ostr_tmp); return os; } Ostream_with_wraparound& nobreak_begin(Ostream_with_wraparound& os) { os.forbid_break(); return os; } Ostream_with_wraparound& nobreak_end(Ostream_with_wraparound& os) { os.enable_break(); return os; } Ostream_with_wraparound& operator<<(Ostream_with_wraparound& os, Ostream_with_wraparound& (*f)(Ostream_with_wraparound&)) { return f(os); } Ostream_with_wraparound& operator<<(Ostream_with_wraparound& os, Real d) { ostringstream ostr_tmp; ostr_tmp << std::setprecision(17) << d; os.putstring(ostr_tmp); return os; } // ------------------------------------------------------------------ // Nonglobal class Istream_skip_comments reads strings, ints and doubles // from an istream. It throws an exception if it doesn't like the input. // It also skips comments, which are delimited by a # sign. const char COMMENT_CHAR = '#'; const char LEFT_PAREN = '('; const char RIGHT_PAREN = ')'; class Istream_skip_comments { private: istream& real_stream_; int linecount_; Error_Message err_; void increment_line_(); void skip_space_(); void skip_comments_(); public: explicit Istream_skip_comments(istream& is, int init_linecount = -1) : real_stream_(is), linecount_(init_linecount) { err_.set_string(""); increment_line_(); } void get_left_paren(); bool get_left_paren2(); bool get_string(string& s); bool get_int(int& i); bool get_uint(unsigned int& i); bool get_double(double& d); int linecount() const {return linecount_;} void go_to_eof(); }; void Istream_skip_comments::increment_line_() { if (linecount_ >= 0) { ++linecount_; ostringstream os; os << "Error occurred while reading line " << linecount_; err_.set_string(os.str()); } } void Istream_skip_comments::skip_space_() { char c; for (;;) { if (!real_stream_.get(c)) return; if (c == '\n') increment_line_(); if (!isspace(c)) { real_stream_.putback(c); return; } } } void Istream_skip_comments::skip_comments_() { char c; for (;;) { skip_space_(); if (!real_stream_.get(c)) return; if (c != COMMENT_CHAR) { real_stream_.putback(c); return; } for (;;) { if (!real_stream_.get(c) || c == '\n') break; } increment_line_(); } } void Istream_skip_comments::get_left_paren() { skip_comments_(); char c; if (!real_stream_.get(c)) throw_error("Unexpected eof while scanning for open-paren"); if (c != LEFT_PAREN) throw_error("Expected open-paren"); } bool Istream_skip_comments::get_left_paren2() { skip_comments_(); char c; if (!real_stream_.get(c)) throw_error("Unexpected eof while scanning for open-paren"); if (c == LEFT_PAREN) return true; else if (c == RIGHT_PAREN) return false; else throw_error("Expected open or close paren"); return false; // never reached; needed for MSVC } // A string is terminate either by whitespace, provided there // is no pending open paren. // If there is an open paren, then wait for the close paren. bool Istream_skip_comments::get_string(string& s) { skip_comments_(); char c; if (!real_stream_.get(c)) throw_error("Unexpected eof while scanning for string"); if (c == RIGHT_PAREN) return false; real_stream_.putback(c); int nest_level = 0; for (;;) { if (!real_stream_.get(c)) throw_error("Unexpected eof in the middle of reading string"); if (c == COMMENT_CHAR) { real_stream_.putback(c); skip_comments_(); continue; } if (c == '\n') increment_line_(); if (isspace(c) && nest_level == 0) return true; if (c == LEFT_PAREN) ++nest_level; if (c == RIGHT_PAREN) { --nest_level; if (nest_level == -1) { real_stream_.putback(c); return true; } if (nest_level == 0) { s.append(1, c); return true; } } s.append(1, c); } } bool Istream_skip_comments::get_int(int& i) { skip_comments_(); char c; if (!real_stream_.get(c)) throw_error("Unexpected eof in the middle of reading an int"); if (c == RIGHT_PAREN) return false; real_stream_.putback(c); if (!(real_stream_ >> i)) throw_error("Error while reading integer"); return true; } bool Istream_skip_comments::get_uint(unsigned int& i) { skip_comments_(); char c; if (!real_stream_.get(c)) throw_error("Unexpected eof in the middle of reading an int"); if (c == RIGHT_PAREN) return false; real_stream_.putback(c); if (!(real_stream_ >> i)) throw_error("Error while reading unsigned integer"); return true; } bool Istream_skip_comments::get_double(double& d) { skip_comments_(); char c; if (!real_stream_.get(c)) throw_error("Unexpected eof in the middle of reading an int"); if (c == RIGHT_PAREN) return false; real_stream_.putback(c); if (!(real_stream_ >> d)) throw_error("Error while reading double"); return true; } void Istream_skip_comments::go_to_eof() { skip_comments_(); if (!real_stream_.eof()) throw_error("Symbols in the file beyond eof"); } // This is a function object used for a map whose key is a string. // We want to compare strings disregarding case. class Nocase { public: bool operator() (const string& x, const string& y) const { return compare_nocase(x,y) < 0; } }; // ------------------------------------------------------------------ // Class Face_lookup_map_type // This is a map from strings to fspecs. // It generates errors upon duplication, and so on. It is used // for keeping track of face names when a brep is read in. class Face_lookup_map_type { private: typedef map <string, Brep::Face_Spec, Nocase> Actual_Map_type; Actual_Map_type actual_map_; public: Face_lookup_map_type() { } ~Face_lookup_map_type() { } void insert(const string& facename, const Brep::Face_Spec& fspec) { const char* tmp = facename.c_str(); string tmp2 = string(tmp); Actual_Map_type::value_type new_rec(tmp2, fspec); pair<Actual_Map_type::iterator, bool> rval = actual_map_.insert(new_rec); if (!rval.second) { string errmsg = string("Duplicate face name ") + facename + " occurs in brep"; throw_error(errmsg); } return; } Brep::Face_Spec find(const string& facename) const { Actual_Map_type::const_iterator it = actual_map_.find(facename); if (it == actual_map_.end()) { string errmsg = string("Face ") + facename + " listed as a subface but is not found"; throw_error(errmsg); } return it -> second; } }; class Bkpt_obj { private: int j; public: Bkpt_obj(int i) : j(i) { } ~Bkpt_obj(); }; Bkpt_obj::~Bkpt_obj() { int k = j + 1; }}// ------------------------------------------------------------------// operator<< for breps.// This routine outputs a brep to a stream in Ascii form.QMG::ostream& operator<<(QMG::ostream& ostr, const QMG::Brep& g) { // output header info Ostream_with_wraparound os(ostr); os << g.io_header_code() << " " << g.gdim() << " " << g.embedded_dim() << "\n("; // output brep prop vals // Output prop-val pairs for (Brep::Loop_over_propvals_of_brep pvloop0(g); pvloop0.notdone(); ++pvloop0) { os << " "<< pvloop0.prop() << " " << pvloop0.val() << "\n"; } os << ")\n(\n"; { // Output control points for (Brep::ControlPointIndex j = 0; j < g.num_control_points(); ++j) { for (int d = 0; d < g.embedded_dim(); ++d) { os << g.control_point(j,d) << " "; } os << nobreak_begin << "# cp " << j << "\n" << nobreak_end; } } os << ") \n"; for (int dim = 0; dim <= g.gdim(); ++dim) { // Output topological faces os << nobreak_begin << "( # begin topological "; const char* facetype; if (dim == 0) facetype = "vertices"; else if (dim == 1) facetype = "edges"; else if (dim == 2 && g.embedded_dim() == 3) facetype = "surfaces"; else facetype = "regions"; os << facetype << "\n" << nobreak_end; for (Brep::Face_Spec_Loop_Over_Faces_Of_Dim fspec(g, dim); fspec.notdone(); ++fspec) { // Output prop-val pairs os << g.face_name(fspec) << " ("; for (Brep::Loop_over_propvals_of_face pvloop(g, fspec); pvloop.notdone(); ++pvloop) { os << " "<< pvloop.prop() << " " << pvloop.val() << "\n"; } os << ") ("; // Output bounding faces { for (Brep::Face_Spec_Loop_Over_Face_Subfaces subfspec(g, fspec); subfspec.notdone(); ++subfspec) { if (!subfspec.is_internal_boundary()) { os << nobreak_begin; if (subfspec.orientation() == 0) os << "+"; else if (subfspec.orientation() == 1) os << "-"; os << g.face_name(subfspec) << nobreak_end << " "; } } } // Output internal boundary faces os << ") ("; { for (Brep::Face_Spec_Loop_Over_Face_Subfaces subfspec(g, fspec); subfspec.notdone(); ++subfspec) { if (subfspec.is_internal_boundary()) { os << g.face_name(subfspec) << " "; } } } // Output patches os << ") ("; for (Brep::Loop_over_patches_of_face patch(g, fspec); patch.notdone(); ++patch) { if (patch.index() > 0) os << "\n "; os << " ("; if (fspec.fdim() == 0) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?