gmchecknormals.cpp

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

CPP
356
字号
// ------------------------------------------------------------------// gmchecknormals.cpp//// This file contains a function for checking how smooth the normals// are across patch boundaries (departure from G^1).// ------------------------------------------------------------------// 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.// ------------------------------------------------------------------#include "qbrep.h"#include "qpatchtab.h"#include "qfrontend.h"#define GM_ROUTINE_NAME gmchecknormals#define GM_ROUTINE_NAME_Q "gmchecknormals"namespace {  using namespace QMG;  // Duplication of class defined in double.cpp.  Fix later.    struct PatchInBrepAddress {    Brep::Face_Spec fspec;    Brep::PatchIndex patchind;    PatchInBrepAddress(const Brep::Face_Spec& f, Brep::PatchIndex p) :     fspec(f), patchind(p) { }    PatchInBrepAddress(const PatchInBrepAddress& o) : fspec(o.fspec), patchind(o.patchind) { }    PatchInBrepAddress() { }    bool operator<(const PatchInBrepAddress& ip) const;    bool operator==(const PatchInBrepAddress& ip) const;  };      bool PatchInBrepAddress::operator<(const PatchInBrepAddress& ip) const {    if (fspec < ip.fspec) return true;    if (fspec > ip.fspec) return false;    return patchind < ip.patchind;  }    bool PatchInBrepAddress::operator==(const PatchInBrepAddress& ip) const {    return fspec == ip.fspec && patchind == ip.patchind;  }  // Duplicate of stuff from qseparation.cpp.  Fix later.  const int NUM_TEST_DIRECTIONS_2D = 4;  const int NUM_CURVATURE_TEST_DIRECTION = 13;  const Real test_direction_init[] = {0,1,0, 1,0,0, 1,1,0, 1,-1,0,                                      0,0,1,  0,1,1, 1,0,1, 1,1,1,                                      0,-1,1, -1,0,1, 1,-1,1, -1,1,1,                                      -1,-1,1};    struct CpnumFaceSpec {    Brep::ControlPointIndex cpnum;    Brep::FaceIndex faceind;    CpnumFaceSpec() { }    CpnumFaceSpec(Brep::ControlPointIndex cp1, Brep::FaceIndex f) :     cpnum(cp1), faceind(f) { }    CpnumFaceSpec(const CpnumFaceSpec& o) :     cpnum(o.cpnum), faceind(o.faceind) { }    bool operator<(const CpnumFaceSpec& o) const;  };  bool CpnumFaceSpec::operator<(const CpnumFaceSpec& o) const {    if (cpnum < o.cpnum) return true;    if (cpnum > o.cpnum) return false;    return faceind < o.faceind;  }      struct FacePatchInd {    Brep::PatchIndex patchind;    int whichvert;    FacePatchInd() { }    FacePatchInd(Brep::PatchIndex p, int w) :     patchind(p), whichvert(w) { }    FacePatchInd(const FacePatchInd& o) :     patchind(o.patchind), whichvert(o.whichvert) { }  };  typedef multimap<CpnumFaceSpec, FacePatchInd> Maptype;  struct Check_normals_return_val {    Real max_deviation_on_face;    Brep::Face_Spec face_with_max_deviation;    Brep::ControlPointIndex node_with_max_deviation_on_face;    /*    Real max_deviation_overall;    Brep::ControlPointIndex node_with_max_deviation_overall;    */  };  Check_normals_return_val check_normals(const Brep& b) {    Maptype cpmap;    map<PatchInBrepAddress, bool> patch_is_flipped;    int di = b.embedded_dim();    Point::InitStaticData(di);    int gdim = b.gdim();    if (gdim < di - 1)      throw_error("Brep must be full dimensional");    {        ostringstream nullstr;      QMG::MG::Logstream null_log(nullstr,0);      // Make a map to determine which patch is flipped.      QMG::MG::PatchTable patchtable(b, null_log, -1, -1);      for (QMG::MG::PatchTable::Index patchind = 0;       patchind < patchtable.numpatch();      ++patchind) {        if (patchtable.gdim(patchind) != di - 1) continue;        patch_is_flipped[PatchInBrepAddress(patchtable.owner(patchind),           patchtable.orig_index(patchind))] = patchtable.is_forward(patchind);      }    }    for (Brep::Face_Spec_Loop_Over_Faces_Of_Dim fspec(b, di - 1);    fspec.notdone();    ++fspec) {        Brep::FaceIndex faceind = fspec.faceind();      for (Brep::Loop_over_patches_of_face patchloop(b, fspec);      patchloop.notdone();      ++patchloop) {        Brep::PatchIndex patchind = patchloop.index();        if (di == 2) {          int deg = patchloop.degree1();          cpmap.insert(pair<CpnumFaceSpec, FacePatchInd>            (CpnumFaceSpec(patchloop.control_point(0), faceind),            FacePatchInd(patchind, 0)));          cpmap.insert(pair<CpnumFaceSpec, FacePatchInd>            (CpnumFaceSpec(patchloop.control_point(deg), faceind),            FacePatchInd(patchind, 1)));        }        else { // di == 3          if (patchloop.ptype() == BEZIER_TRIANGLE) {            int deg = patchloop.degree1();            cpmap.insert(pair<CpnumFaceSpec, FacePatchInd>              (CpnumFaceSpec(patchloop.control_point(0), faceind),              FacePatchInd(patchind, 0)));            cpmap.insert(pair<CpnumFaceSpec, FacePatchInd>              (CpnumFaceSpec(patchloop.control_point(deg * (deg + 1) / 2), faceind),               FacePatchInd(patchind, 1)));            cpmap.insert(pair<CpnumFaceSpec, FacePatchInd>              (CpnumFaceSpec(patchloop.control_point((deg + 1) * (deg + 2) / 2 - 1), faceind),               FacePatchInd(patchind, 2)));          }          else { // patchtype == BEZIER_QUAD            int deg1 = patchloop.degree1();            int deg2 = patchloop.degree2();            cpmap.insert(pair<CpnumFaceSpec, FacePatchInd>              (CpnumFaceSpec(patchloop.control_point(0), faceind),              FacePatchInd(patchind, 0)));            cpmap.insert(pair<CpnumFaceSpec, FacePatchInd>              (CpnumFaceSpec(patchloop.control_point(deg1), faceind),                FacePatchInd(patchind, 1)));            cpmap.insert(pair<CpnumFaceSpec, FacePatchInd>              (CpnumFaceSpec(patchloop.control_point(deg2 * (deg1 + 1)), faceind),              FacePatchInd(patchind, 2)));            cpmap.insert(pair<CpnumFaceSpec, FacePatchInd>              (CpnumFaceSpec(patchloop.control_point((deg2 + 1) * (deg1 + 1) - 1), faceind),              FacePatchInd(patchind, 3)));          }        }      }    }    // Now find maximum deviations.    Check_normals_return_val rval;    rval.max_deviation_on_face = -1.0;    //    rval.max_deviation_overall = -1.0;    Real maxip[NUM_CURVATURE_TEST_DIRECTION];    Real minip[NUM_CURVATURE_TEST_DIRECTION];    int num_test_directions = (di == 2)?          NUM_TEST_DIRECTIONS_2D : NUM_CURVATURE_TEST_DIRECTION;    vector<Point> test_directions(num_test_directions);    for (int j1 = 0; j1 < num_test_directions; ++j1) {      for (int k = 0; k < di; ++k)         test_directions[j1][k] = test_direction_init[j1 * 3 + k];      test_directions[j1].normalize();    }        Point paramcoord, normal_or_tan, direc;    direc[0] = 1.0;    // Pass 2 looks for maxdeviation per node/fspec pair.                // for (int passcount = 0;    // passcount < 2;    // ++passcount) {        Brep::ControlPointIndex lastv = -1;    Brep::FaceIndex lastface = -1;    Maptype::const_iterator start_search = cpmap.begin();    while (start_search != cpmap.end()) {      Brep::ControlPointIndex thisv = start_search -> first.cpnum;      Brep::FaceIndex thisf = start_search -> first.faceind;      Maptype::const_iterator end_search =                // (passcount == 0) ?        // cpmap.lower_bound(CpnumFaceSpec(thisv + 1, 0)) :                cpmap.upper_bound(CpnumFaceSpec(thisv, thisf));              for (int j = 0; j < num_test_directions; ++j) {        maxip[j] = -100;        minip[j] = 100;      }      for (Maptype::const_iterator it = start_search;       it != end_search;      ++it) {        Brep::FaceIndex thisf2 = it -> first.faceind;        Brep::Face_Spec owner(di - 1, thisf2);        Brep::PatchIndex patchind = it -> second.patchind;        int whichvert = it -> second.whichvert;        if (di == 2) {          paramcoord[0] = static_cast<double>(whichvert);          normal_or_tan = b.patchmath(owner, patchind).direc_deriv(paramcoord, direc);          if (normal_or_tan.l2norm() == 0)            throw_error("Tangential derivative vanishes at edge endpoint -- illegal Bezier curve");          normal_or_tan.normalize();        }        else { //di == 3          if (b.patch_type(owner, patchind) == BEZIER_TRIANGLE) {            if (whichvert == 0) {              paramcoord[0] = 0.0;              paramcoord[1] = 1.0;            }             else if (whichvert == 1) {              paramcoord[0] = 0.0;              paramcoord[1] = 0.0;            }            else { //whichvert == 2              paramcoord[0] = 1.0;              paramcoord[1] = 0.0;            }          }          else { // patchtype == BEZIER_QUAD            if (whichvert == 0) {              paramcoord[0] = 0.0;              paramcoord[1] = 0.0;            }            else if (whichvert == 1) {              paramcoord[0] = 1.0;              paramcoord[1] = 0.0;            }            else if (whichvert == 2) {              paramcoord[0] = 0.0;              paramcoord[1] = 1.0;            }            else { //whichvert == 3              paramcoord[0] = 1.0;              paramcoord[1] = 1.0;            }          }          normal_or_tan = b.patchmath(owner,patchind).normal(paramcoord);        }                if (patch_is_flipped[PatchInBrepAddress(owner, patchind)]) {          normal_or_tan[0] = -normal_or_tan[0];          normal_or_tan[1] = -normal_or_tan[1];          if (di == 3)            normal_or_tan[2] = -normal_or_tan[2];        }                // Update maxip and minip with normal_or_tan.                for (int j = 0; j < num_test_directions; ++j) {          Real ip = Point::inner_product(test_directions[j], normal_or_tan);          if (ip > maxip[j])            maxip[j] = ip;          if (ip < minip[j])            minip[j] = ip;        }      }            // Done with all relevant directions; now find the max gap in the      // inner products.            Real maxgap = 0.0;      for (int j2 = 0; j2 < num_test_directions; ++j2) {        Real gap = maxip[j2] - minip[j2];        if (gap > maxgap) {          maxgap = gap;        }      }            // if (passcount == 0) {      //  if (maxgap > rval.max_deviation_overall) {      //    rval.max_deviation_overall = maxgap;      //     rval.node_with_max_deviation_overall = thisv;      //  }      //  }      //  else { //passcount == 1      if (maxgap > rval.max_deviation_on_face) {        rval.max_deviation_on_face = maxgap;        rval.face_with_max_deviation = Brep::Face_Spec(di - 1, thisf);        rval.node_with_max_deviation_on_face = thisv;      }      //  }      start_search = end_search;      }      // }      return rval;  }  void worker(const QMG::FrontEnd::ArgValType& argvalhandle,    QMG::FrontEnd::ReturnValType& returnvalhandle,    QMG::FrontEnd::Interpreter& interp) {    argvalhandle.verify_nargin(1, 1, GM_ROUTINE_NAME_Q);    returnvalhandle.verify_nargout(3, 3, GM_ROUTINE_NAME_Q);    Brep_From_FrontEnd b = argvalhandle.get_brep(0);    Check_normals_return_val rval = check_normals(b);    returnvalhandle.put_double(0, rval.max_deviation_on_face);    returnvalhandle.put_string(1, b.face_name(rval.face_with_max_deviation));    returnvalhandle.put_int(2, rval.node_with_max_deviation_on_face);    // returnvalhandle.put_double(3, rval.max_deviation_overall);    // returnvalhandle.put_int(4, rval.node_with_max_deviation_overall);  }}#include "gm_entrypoint.cpp"

⌨️ 快捷键说明

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