checktri.cpp

来自「算断裂的」· C++ 代码 · 共 535 行 · 第 1/2 页

CPP
535
字号
// ------------------------------------------------------------------// checktri.cpp//// This file contains the routine for checking that a triangulation// of a brep is correct.// ------------------------------------------------------------------// 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#include "qmatvec.h"#endif#endif#include "qbrep.h"#include "qsimpcomp.h"#include "qmatvec.h"// Function exported by this file.namespace QMG {  Real checktri(const Brep& brep,    const SimpComplex& simpcomp,    ostream& os,    int checko,    double tol);}namespace {  using namespace QMG;  const int CHECKTRI_MAXDIM = 3;    // ------------------------------------------------------------------  // struct Facet_Rec  // A record of a facet of a simplex.  Used as a map data.  Keep track  // of how many times a facet occurs.  struct Facet_Rec {    int pos_occurrence_count;    int neg_occurrence_count;    int occurs_on_bdry;    int seqno_occ[2];    Facet_Rec() : pos_occurrence_count(0),      neg_occurrence_count(0),      occurs_on_bdry(0) { }  };    // ------------------------------------------------------------------  // struct Facet_Key  // A record of a facet of a simplex.  Used as a map key. The key is  // the list of vertices of the facet, sorted into increasing order.  struct Facet_Key {    static int facetdim;    SimpComplex::VertexGlobalIndex vert[CHECKTRI_MAXDIM];    bool operator<(const Facet_Key& other) const;    bool operator==(const Facet_Key& other) const;  };  bool Facet_Key::operator<(const Facet_Key& other) const {    for (int j = 0; j < facetdim + 1; ++j) {      if (vert[j] < other.vert[j])        return true;      if (vert[j] > other.vert[j])        return false;    }    return false;  }  int Facet_Key::facetdim;  bool Facet_Key::operator==(const Facet_Key& other) const {    for (int j = 0; j < facetdim + 1; ++j) {      if (vert[j] != other.vert[j])        return false;    }    return true;  }  class Dumpsimp {  private:    const SimpComplex& s;    const Brep& g;    Brep::Face_Spec fspec;    int seqno;  public:    Dumpsimp(const SimpComplex& s1,       const Brep& g1,             const Brep::Face_Spec& f1,      int seq1) :    s(s1), g(g1), fspec(f1), seqno(seq1) {}    friend QMG::ostream& operator<<(QMG::ostream& os, const Dumpsimp& ds);  };  QMG::ostream& operator<<(QMG::ostream& os, const Dumpsimp& ds) {    os << "simplex #" << ds.seqno << " of topological entity "      << ds.g.face_name(ds.fspec) << " (";    ::operator<<(os, ds.fspec);     os << ") which has vertices ";    for (int j = 0; j < ds.fspec.fdim() + 1; ++j)      os << ds.s.node_of_meshface_on_face(ds.fspec, ds.seqno, j) << " ";    os << '\n';    return os;  }}  // ------------------------------------------------------------------// checktri// Argument g is a brep and argument s is a putative triangulation// for g.  This routine checks whether the simplicial complex is// correct.  Problems detected are printed on outstream.  // The return value is the worst aspect ratio among all simplices.// It is negative if there is an error.// Set checko=1 if every elt should have forward orientation,// 2 if every elt should have backward orientation, 0 not to check orientation.// Note: orientation not checked for low-dimensional complexes.// ------------------------------------------------------------------QMG::Real QMG::checktri(const Brep& g,              const SimpComplex& s,              ostream& outstream,              int checko,              double tol) {    int di = g.embedded_dim();  if (di != s.embedded_dim()) {    throw_error("Brep and simpcomplex have different embedded dims");  }    // initialize the random number generator.  random_real(1);  Point::InitStaticData(di);  string brep_id1 = g.lookup_brep_propval(Brep::global_id_propname());  string brep_id2 = s.lookup_prop_val(Brep::global_id_propname());  bool match = compare_nocase(brep_id1, brep_id2) == 0;  if (!match)    throw_error("Brep and simpcomplex have different global id's");  int sdim = s.gdim();  if (sdim > CHECKTRI_MAXDIM) {    throw_error("Dimension out of range for checktri");  }  if (sdim > g.gdim()) {    throw_error("Intrinsic dimension of simp complex too high for brep");  }  double scfac = g.scale_factor();  double scaled_tol = scfac * tol;    Real minaltglobal = BIG_REAL;  Real maxsideglobal = 0.0;  Real maxaspglobal = 0.0;  int worsttriseq = -999;  Brep::Face_Spec worsttrifspec;  bool imperfectflag = false;    Matrix simplexmatrix(sdim, di);  Matrix simplexvertex(sdim + 1, di);  // hash table on facets; counts occurrences of facets on the  // positive and negative sides.  typedef map<Facet_Key, Facet_Rec> Facet_Map_Type;  Facet_Map_Type facet_occurrence_map;  map<SimpComplex::VertexGlobalIndex, int> checkoff;  map<SimpComplex::VertexGlobalIndex, int> onface;  int numvtx = s.num_nodes();  int numelt1 = 0;  vector<int> sortord(sdim + 1);  Real hhtrans[4];  for (int fdim = 0; fdim <= sdim; ++fdim) {    if (g.level_size(fdim) != s.brep_levelsize(fdim))      throw_error("Mismatch between brep and mesh (different level sizes)");    Facet_Key::facetdim = fdim - 1;    sortord.resize(fdim + 1);    for (Brep::FaceIndex faceind = 0; faceind < g.level_size(fdim); ++faceind) {      Brep::Face_Spec fspec(fdim, faceind);      if (fdim < di) {        int nnf = s.num_node_on_face(fspec);        if (nnf == 0) {          outstream << "?? Topological face " << g.face_name(fspec) << " (" << fspec             << ") does not have any mesh nodes\n";          imperfectflag = true;        }        onface.clear();              for (int seqno = 0; seqno < nnf; ++seqno) {          SimpComplex::VertexGlobalIndex vnum = s.node_on_face(fspec,seqno);          onface[vnum] = 1;          SimpComplex::VertexOrdinalIndex vnumo = s.global_to_ordinal_nothrow(vnum);          if (vnumo < 0) {            outstream << "?? Global node #" << vnum << " listed as lying on face "              << g.face_name(fspec) << "(" << fspec << ") but no node\n"              << "  with that number occurs in the coordinate list.\n";            imperfectflag = true;            continue;          }          Point real1, param1;          for (int j = 0; j < di; ++j)            real1[j] = s.real_coord_o(vnumo, j);          for (int j2 = 0; j2 < fdim; ++j2)            param1[j2] = s.param_coord_on_face(fspec, seqno,j2);          Brep::PatchIndex patchind = s.patchind_on_face(fspec, seqno);          Point real2 = g.patchmath(fspec, patchind).get_real_point(param1);          Real l2dist = Point::l2dist(real1,real2);          if (l2dist > scfac * tol) {            outstream << "?? Vertex " << vnum << " real coordinates too far away "              << " from actual point on " << g.face_name(fspec) << " ("               << fspec << ")\n"              << "  ( dist = " << l2dist << ")\n";            imperfectflag = true;          }        }      }      if (fdim == 0) continue;      int nmf = s.num_meshface_on_face(fspec);      facet_occurrence_map.clear();           {        Facet_Key key;          for (int seqno = 0; seqno < nmf; ++seqno) {          if (fdim < di) {            for (int jj = 0; jj < fdim + 1; ++jj) {              SimpComplex::VertexGlobalIndex vtx =                 s.node_of_meshface_on_face(fspec, seqno,jj);              if (!onface[vtx]) {                outstream << "?? Vertex " << vtx << " occurs in "                   << Dumpsimp(s,g,fspec,seqno) << " but is\n"                  << " not listed as a vertex on that topological entity.\n";                imperfectflag = true;              }            }          }          bool notfound = false;          for (int jj = 0; jj < fdim + 1; ++jj) {            SimpComplex::VertexGlobalIndex vtx =               s.node_of_meshface_on_face(fspec, seqno, jj);            SimpComplex::VertexOrdinalIndex vtxo =               s.global_to_ordinal_nothrow(vtx);            if (vtxo < 0) {              outstream << "?? Vertex " << vtx << " occurs in "                 << Dumpsimp(s,g,fspec,seqno) << " but has no coordinates in table.\n";              imperfectflag = true;              notfound = true;            }            else {              for (int j = 0; j < di; ++j)                simplexvertex(jj,j) = s.real_coord_o(vtxo,j);            }

⌨️ 快捷键说明

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