gm_obj2list.cpp

来自「算断裂的」· C++ 代码 · 共 409 行

CPP
409
字号
// ------------------------------------------------------------------// gm_obj2list.cpp//// This file contains the driver function and work routines for// converting a brep or mesh to a Tcl/Tk list.// ------------------------------------------------------------------// 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.// ------------------------------------------------------------------extern "C" {#include "tcl.h"}#include "qbrep.h"#include "qsimpcomp.h"#include "qerr.h"namespace QMG {  // ------------------------------------------------------------------  // see brepstream.cpp  namespace FrontEnd {    extern Object_Type_Code get_obj_type(Tcl_Interp* interp, Tcl_Obj* obj);    extern Brep_From_FrontEnd get_brep_from_obj(Tcl_Interp* interp, Tcl_Obj* obj, int& returncode);    extern SimpComplex_From_FrontEnd       get_simpcomp_from_obj(Tcl_Interp* interp, Tcl_Obj* obj, int& returncode);  }}namespace {  using namespace QMG;  class AutoTclObjList {  private:    Tcl_Obj** data_;    int sz_;    AutoTclObjList(const AutoTclObjList&) { }    void operator=(const AutoTclObjList&) { }  public:    AutoTclObjList(int sz) : data_(new Tcl_Obj*[sz]), sz_(sz) { }    ~AutoTclObjList() {delete[] data_;}    Tcl_Obj* make_list() {      return Tcl_NewListObj(sz_, data_);    }    Tcl_Obj*& operator[](int i) {#ifdef RANGECHECK      if (i < 0 || i >= sz_)        throw_error("Range error");#endif      return data_[i];    }  };  // ------------------------------------------------------------------  // convert_brep2list  // convert a brep to a list.  Return a pointer to the new list.  Tcl_Obj* convert_brep2list(const Brep& g) {    int gdim = g.gdim();    if (gdim < -1 || gdim > 3)       throw_error("Gdim out of range in convert_brep2list");    int di = g.embedded_dim();    // A brep is a list with gdim+6 elements.    AutoTclObjList elems(gdim + 6);    // element 0: header code    elems[0] = Tcl_NewStringObj(const_cast<char*>(Brep::io_header_code()), -1);    // element 1: gdim    elems[1] = Tcl_NewIntObj(gdim);    // element 2: embedded_dim    elems[2] = Tcl_NewIntObj(di);        {      int bpvlength = 0;              for (Brep::Loop_over_propvals_of_brep bpvloop0(g);      bpvloop0.notdone();      ++bpvloop0) {        bpvlength += 2;      }            AutoTclObjList bpvlist(bpvlength);            int bpos = 0;      for (Brep::Loop_over_propvals_of_brep bpvloop(g);      bpvloop.notdone();      ++bpvloop) {        bpvlist[bpos++] = Tcl_NewStringObj(const_cast<char*>(bpvloop.prop().c_str()), -1);        bpvlist[bpos++] = Tcl_NewStringObj(const_cast<char*>(bpvloop.val().c_str()), -1);      }            // element 3: property-values of the entire brep.            elems[3] = bpvlist.make_list();    }    // element 4: control point coordinates.    {            int cplength = g.num_control_points() * di;      AutoTclObjList cplist(cplength);      for (int j1 = 0; j1 < g.num_control_points(); ++j1) {        for (int d = 0; d < di; ++d) {          cplist[j1 * di + d] = Tcl_NewDoubleObj(g.control_point(j1,d));        }      }      elems[4] = cplist.make_list();    }        // Output topological faces    // elements 5 to 5+gdim: the topological faces arranged by dimension.    for (int dim = 0; dim <= g.gdim(); ++dim) {      int levlth = g.level_size(dim) * 5;      AutoTclObjList flist(levlth);      int flistpos = 0;      for (Brep::Face_Spec_Loop_Over_Faces_Of_Dim fspec(g, dim);      fspec.notdone();      ++fspec) {        // Each face is composed of 5 elements.        // element 0: face name        flist[flistpos++] =           Tcl_NewStringObj(const_cast<char*>(g.face_name(fspec).c_str()), -1);        // element 1: prop-vals of the face        int pvlength = 0;                for (Brep::Loop_over_propvals_of_face pvloop0(g, fspec);        pvloop0.notdone();        ++pvloop0) {          pvlength += 2;        }        AutoTclObjList pvlist(pvlength);        int pos = 0;        for (Brep::Loop_over_propvals_of_face pvloop(g, fspec);        pvloop.notdone();        ++pvloop) {          pvlist[pos++] = Tcl_NewStringObj(const_cast<char*>(pvloop.prop().c_str()), -1);          pvlist[pos++] = Tcl_NewStringObj(const_cast<char*>(pvloop.val().c_str()), -1);        }        flist[flistpos++] = pvlist.make_list();        // elements 2 & 3 children and internal boundaries        int chlength = 0;        int iblength = 0;        for (Brep::Face_Spec_Loop_Over_Face_Subfaces subfspec0(g, fspec);        subfspec0.notdone();        ++subfspec0) {          if (subfspec0.is_internal_boundary())            ++iblength;          else            ++chlength;        }        AutoTclObjList chlist(chlength);        AutoTclObjList iblist(iblength);        int chpos = 0;        int ibpos = 0;        for (Brep::Face_Spec_Loop_Over_Face_Subfaces subfspec(g, fspec);        subfspec.notdone();        ++subfspec) {          if (subfspec.is_internal_boundary()) {            iblist[ibpos++] =               Tcl_NewStringObj(const_cast<char*>(g.face_name(subfspec).c_str()), -1);          }          else {            ostringstream ostr;            if (subfspec.orientation() == 0)              ostr << '+';            else if (subfspec.orientation() == 1)              ostr << '-';            ostr << g.face_name(subfspec);            chlist[chpos++] = Tcl_NewStringObj(const_cast<char*>(ostr.str().c_str()), -1);          }        }        flist[flistpos++] = chlist.make_list();        flist[flistpos++] = iblist.make_list();        // element 4: patches        int bzlength = 0;        for (Brep::Loop_over_patches_of_face patch0(g, fspec);        patch0.notdone();        ++patch0) {          ++bzlength;        }        AutoTclObjList bzlist(bzlength);        int bzpos = 0;        for (Brep::Loop_over_patches_of_face patch(g, fspec);        patch.notdone();        ++patch) {                    if (fspec.fdim() == 0) {            AutoTclObjList vtlist(2);            vtlist[0] = Tcl_NewStringObj("vertex", -1);            vtlist[1] = Tcl_NewIntObj(patch.control_point(0));            bzlist[bzpos++] = vtlist.make_list();          }          else if (fspec.fdim() == 1) {            int llength = patch.degree1() + 3;            AutoTclObjList vtlist(llength);            vtlist[0] = Tcl_NewStringObj("bezier_curve", -1);            vtlist[1] = Tcl_NewIntObj(patch.degree1());            for (int j = 0; j < patch.degree1() + 1; ++j) {              vtlist[j + 2] = Tcl_NewIntObj(patch.control_point(j));            }            bzlist[bzpos++] = vtlist.make_list();          }          else if (fspec.fdim() == 2) {            if (patch.ptype() == BEZIER_QUAD) {              int ncp = (patch.degree1() + 1) * (patch.degree2() + 1);              int llength =  ncp + 3;              AutoTclObjList vtlist(llength);              vtlist[0] = Tcl_NewStringObj("bezier_quad", -1);              vtlist[1] = Tcl_NewIntObj(patch.degree1());              vtlist[2] = Tcl_NewIntObj(patch.degree2());              for (int j = 0; j < ncp; ++j) {                vtlist[j + 3] = Tcl_NewIntObj(patch.control_point(j));              }              bzlist[bzpos++] = vtlist.make_list();            }            else {              int ncp = (patch.degree1() + 1) * (patch.degree1() + 2) / 2 ;              int llength =  ncp + 2;              AutoTclObjList vtlist(llength);               vtlist[0] = Tcl_NewStringObj("bezier_triangle", -1);              vtlist[1] = Tcl_NewIntObj(patch.degree1());              for (int j = 0; j < ncp; ++j) {                vtlist[j + 2] = Tcl_NewIntObj(patch.control_point(j));              }              bzlist[bzpos++] = vtlist.make_list();            }          }        }        flist[flistpos++] = bzlist.make_list();      }      elems[dim + 5] = flist.make_list();    }    Tcl_Obj* brepl = elems.make_list();    return brepl;  }  // ------------------------------------------------------------------  // convert_simpcomp2list  // Convert a simplicial complex to a Tcl list.  Tcl_Obj* convert_simpcomp2list(const SimpComplex& s) {    int gdim = s.gdim();    int di = s.embedded_dim();    AutoTclObjList elems(gdim + 6);    elems[0] = Tcl_NewStringObj(const_cast<char*>(SimpComplex::io_header_code()), -1);    elems[1] = Tcl_NewIntObj(gdim);    elems[2] = Tcl_NewIntObj(di);    {      int npv = s.num_prop_val();      AutoTclObjList pvlist(2 * npv);      for (int pvi = 0; pvi < npv; ++pvi) {        pvlist[pvi * 2] = Tcl_NewStringObj(const_cast<char*>(s.prop(pvi).c_str()), -1);        pvlist[pvi * 2 + 1] = Tcl_NewStringObj(const_cast<char*>(s.val(pvi).c_str()), -1);      }            elems[3] = pvlist.make_list();    }    // Convert node list.    {      int nnode = s.num_nodes();      AutoTclObjList cplist(nnode * (di + 1));      for (SimpComplex::VertexOrdinalIndex vnumo = 0; vnumo < nnode; ++vnumo) {        SimpComplex::VertexGlobalIndex vnum = s.ordinal_to_global(vnumo);        cplist[vnumo * (di + 1)] = Tcl_NewIntObj(vnum);        for (int j = 0; j < di; ++j) {          cplist[vnumo * (di + 1) + j + 1] =            Tcl_NewDoubleObj(s.real_coord_o(vnumo, j));        }      }      elems[4] = cplist.make_list();    }    // Convert simplices    for (int fdim = 0; fdim <= gdim; ++fdim) {      int levsize = s.brep_levelsize(fdim);      AutoTclObjList facelist(2 * levsize);      for (Brep::FaceIndex faceind = 0; faceind < levsize; ++faceind) {        Brep::Face_Spec fspec(fdim, faceind);        int nnf = s.num_node_on_face(fspec);        int nlsize = (fdim == 0)? 1 : 2 + fdim;        AutoTclObjList node_on_face(nnf * nlsize);        for (int seqno = 0; seqno < nnf; ++seqno) {          node_on_face[seqno * nlsize] = Tcl_NewIntObj(s.node_on_face(fspec, seqno));          if (fdim > 0)            node_on_face[seqno * nlsize + 1] = Tcl_NewIntObj(s.patchind_on_face(fspec, seqno));          for (int k = 0; k < fdim; ++k) {            node_on_face[seqno * nlsize + 2 + k] =               Tcl_NewDoubleObj(s.param_coord_on_face(fspec, seqno, k));          }        }        facelist[faceind * 2] = node_on_face.make_list();        int nmf = (fdim == 0)? 0 : s.num_meshface_on_face(fspec);        AutoTclObjList simp_on_face(nmf * (fdim + 1));        for (int seqno2 = 0; seqno2 < nmf; ++seqno2) {          for (int k = 0; k < fdim + 1; ++k) {            simp_on_face[seqno2 * (fdim + 1) + k] =               Tcl_NewIntObj(s.node_of_meshface_on_face(fspec, seqno2, k));          }        }        facelist[faceind * 2 + 1] = simp_on_face.make_list();      }      elems[5 + fdim] = facelist.make_list();    }      Tcl_Obj* newobj = elems.make_list();    return newobj;  }}extern "C" {  // Driver routine.  No need for the worker/driver split since  // this one is Tcl only.int gm_obj2list(ClientData clientdata,                    Tcl_Interp* interp,                    int objc,                    Tcl_Obj* const objv[]) {  using namespace QMG::FrontEnd;  QMG::Error_Message::init_error_message_list();  QMG::Error_Task::init_error_task_list();  if (objc != 2) {    Tcl_WrongNumArgs(interp, 1, objv, "object");    return TCL_ERROR;  }  Object_Type_Code code = get_obj_type(interp, objv[1]);  if (code == UNKNOWN) {    Tcl_AppendResult(interp, "Argument to gm_obj2list neither a brep nor simpcomplex", 0);    return TCL_ERROR;  }  Tcl_Obj* newobj;  int returncode;  if (code == BREP) {    Brep_From_FrontEnd b = get_brep_from_obj(interp, objv[1], returncode);    if (returncode != TCL_OK) {      Tcl_AppendResult(interp, "Conversion to brep of argument 0 in gm_obj2list failed",0);      return TCL_ERROR;    }    try {      newobj = convert_brep2list(b);    }    catch(QMG::Error e) {      Tcl_AppendResult(interp, e.get_error_messages(), 0);      Tcl_AppendResult(interp, "gm_obj2list terminated because of exception.", 0);      return TCL_ERROR;    }    catch(...) {      Tcl_AppendResult(interp, "gm_obj2list terminated because of unknown exception", 0);    return TCL_ERROR;    }  }  else  {    SimpComplex_From_FrontEnd s = get_simpcomp_from_obj(interp, objv[1], returncode);    if (returncode != TCL_OK) {      Tcl_AppendResult(interp, "Conversion to simpcomp of argument 0 in gm_obj2list failed",0);      return TCL_ERROR;    }    try {      newobj = convert_simpcomp2list(s);    }    catch(QMG::Error e) {      Tcl_AppendResult(interp, e.get_error_messages(), 0);      Tcl_AppendResult(interp, "gm_obj2list terminated because of exception.", 0);      return TCL_ERROR;    }    catch(...) {      Tcl_AppendResult(interp, "gm_obj2list terminated because of unknown exception", 0);    return TCL_ERROR;    }     }  Tcl_SetObjResult(interp, newobj);  return TCL_OK;}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?