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 + -
显示快捷键?