double.cpp

来自「算断裂的」· C++ 代码 · 共 1,820 行 · 第 1/5 页

CPP
1,820
字号
  bool FspecCopyNum::operator<(const FspecCopyNum& o) const {    if (fspec < o.fspec) return true;    if (fspec > o.fspec) return false;    return copynum < o.copynum;  }  // Routine to determine which side of a surface has a certain  // simplex.  int determine_side(const Brep& b,                     const Brep::Face_Spec& owner,                     const SimpComplex& sc,                     Brep::Face_Spec regionspec,                     int seqno,                     int which_facet,                     const map<PatchInBrepAddress,bool>& patch_is_flipped,                     double scfac,                     double tol) {    int di = b.embedded_dim();    Point startpoint, basepoint, endpoint, tang, coef;    PatchMath::Workspace workspace;    vector<PatchMath::IntersectRecord> outputstack;    {      SimpComplex::VertexGlobalIndex vnum =         sc.node_of_meshface_on_face(regionspec, seqno, which_facet);      SimpComplex::VertexOrdinalIndex vnumo = sc.global_to_ordinal(vnum);      for (int j = 0; j < di; ++j)        startpoint[j] = sc.real_coord_o(vnumo, j);    }    int side;    bool degen = true;    int trycount = 0;    while (degen &&  ++trycount < 400) {      degen = false;      // Select a point in the base facet of the simplex      // via interpolation with randomized coeffs.      Real t = 1.0;      {        for (int j = 0; j < di - 1; ++j) {          coef[j] = 1.0/((double)(2*di)) + 1.0/((double)(2*di)) * random_real();          t -= coef[j];        }      }      coef[di - 1] = t;      {        for (int i = 0; i < di; ++i)          basepoint[i] = 0.0;      }      {        int k = 0;        for (int j = 0; j < di + 1; ++j) {          if (j == which_facet) continue;          SimpComplex::VertexGlobalIndex vnum =             sc.node_of_meshface_on_face(regionspec, seqno, j);          SimpComplex::VertexOrdinalIndex vnumo = sc.global_to_ordinal(vnum);          for (int i = 0; i < di; ++i)            basepoint[i] += coef[k] * sc.real_coord_o(vnumo,i);          ++k;        }      }      // endpoint extrapolates from startpoint to basepoint by      // a factor of 5.      {        for (int j = 0; j < di; ++j) {          tang[j] = startpoint[j] - basepoint[j];          endpoint[j] = startpoint[j] - 5.0 * tang[j];        }      }      // Loop over patches of the face; for each patch find      // the point where the segment from startpoint to      // endpoint crosses.  Save the first hit.      Real first_hit_dist = BIG_REAL;      for (Brep::Loop_over_patches_of_face ptloop(b, owner);           ptloop.notdone();           ++ptloop) {        outputstack.resize(0, PatchMath::IntersectRecord());        ptloop.patchmath().intersect_seg(outputstack, workspace,                                         startpoint, endpoint, scfac, tol, true);        for (int j = 0; j < outputstack.size(); ++j) {          if (outputstack[j].degen) {            degen = true;            break;          }          if (outputstack[j].dist < first_hit_dist) {            first_hit_dist = outputstack[j].dist;            Real ip = Point::inner_product(ptloop.patchmath()                                           .normal(outputstack[j].paramcoord), tang);            typedef map<PatchInBrepAddress,bool> MPIBB;            MPIBB::const_iterator it =               patch_is_flipped.find(PatchInBrepAddress(owner, ptloop.index()));            if (it == patch_is_flipped.end())               throw_error("record missing from patch_is_flipped");            if (it -> second)              ip = -ip;            if (ip < 0)              side = 0;            else              side = 1;          }        }        if (degen) break;      }      if (first_hit_dist > 10)        degen = true;    }    if (degen)      throw_error("Unrecoverable degeneracy in 'determine_side'");    return side;  }  }// This routine doubles the internal boundary faces of a brep.// The faces to double are given by the second argument.QMG::MG::Brep_Under_ConstructionQMG::MG::double_brep(const Brep& b,                     const vector<Brep::Face_Spec>& faces_to_double,                     double tol,                     // other return variables:                     Brep::Face_Labeling<Brep::FaceIndex>& oldfspec_to_new_map,                     Brep::Face_Labeling<int>& face_num_copies,                     map<PatchInBrepAddress, bool>& patch_is_flipped) {  double scfac = b.scale_factor();  AnglePatchIndPair::tol = tol;  SegHitRecord::tol = tol;  using std::ofstream;  using std::endl;  ostream logfile(0);  Logstream logstr(logfile, 1);  OnErrorFlushLog _unnamed_(logstr);    // initialize the random number generator.    random_real(1);  int di = b.embedded_dim();  small_initialize_static_data(di);  Point::InitStaticData(di);#ifdef DEBUGGING  Local_to_PatchMath_CPP::dump_everything = false;  Local_to_PatchMath_CPP::debug_str = &logstr.str();#endif    logstr.str() << "tol = " << tol << " scfac = " << scfac << '\n';  PatchTable patchtable(b, logstr, scfac, tol);    // Make a mapping from original brep's patchind index  // to patchtable's patch index.  map<PatchInBrepAddress, PatchTable::Index> lookup_patchind;   {    for (PatchTable::Index patchind = 0;          patchind < patchtable.numpatch();          ++patchind) {      Brep::Face_Spec owner = patchtable.owner(patchind);      if (patchtable.gdim(patchind) != owner.fdim()) continue;      Brep::PatchIndex patchind1 = patchtable.orig_index(patchind);      lookup_patchind[PatchInBrepAddress(owner,patchind1)] = patchind;    }  }    // Mark faces that must be doubled.  Brep::Face_Labeling<My_bool> must_be_doubled(b, My_bool(false));  Brep::Face_Labeling<Brep::Face_Spec>     parent_of_doubled_face(b, Brep::Face_Spec());  Brep::Ancestor_Lookup anc_lookup(b);  // used only in 3D  vector<bool> is_ib_ancestor_of_vtx(b.level_size(di - 1));  {    int ftds = faces_to_double.size();    for (int j = 0; j < ftds; ++j) {      Brep::Face_Spec fspec = faces_to_double[j];      if (fspec.fdim() != di - 1)        throw_error("Only faces of dimension di-1 may be doubled");      must_be_doubled(fspec) = true;      Brep::Face_Spec parent_fspec(-1,-1);      for (Brep::Ancestor_Lookup::Loop_over_ancestors ancloop(anc_lookup, fspec);           ancloop.notdone();           ++ancloop) {        Brep::Face_Spec afspec = ancloop.ancestor_fspec();        if (afspec.fdim() != fspec.fdim() + 1) continue;        if (ancloop.occurrence_count() % 2 != 0)        throw_error("Specified face is not an internal boundary of parent topological entity");        if (parent_fspec.fdim() >= 0)          throw_error("Specified face occurs as boundary of more than one parent topological entity");        parent_fspec = afspec;      }      if (parent_fspec.fdim() < 0)        throw_error("Specified face is not a boundary of any parent topological entity");      parent_of_doubled_face(fspec) = parent_fspec;    }  }  int patchtable_size = patchtable.numpatch();  vector<bool> patch_is_doubled(patchtable_size);  // Mark doubled patches.  {    for (PatchTable::Index patchind = 0; patchind < patchtable_size; ++patchind) {      patch_is_doubled[patchind] =  (patchtable.gdim(patchind) == di - 1) &&        must_be_doubled(patchtable.owner(patchind));    }  }  vector<AnglePatchIndPair> bigsortlist;  vector<int> pos_in_bigsortlist(patchtable_size);  vector<int> len_in_bigsortlist(patchtable_size, 0);            // Make a table that holds the patches around  // each bezier curve (3D) or point (2D) in order of angle.  {    vector<AnglePatchIndPair> sortlist;    for (PatchTable::Index patchind = 0; patchind < patchtable_size; ++patchind) {      if (patchtable.gdim(patchind) != di - 2) continue;      // For a patch of dimension di-2, find all its parents      // and properly list them in the big sort list  data structure.                  Point hhtransform;      Point paramcoord;      Real beta;            // Get the angle that the parent patch makes with respect      // to this patch.      if (di == 3) {        Point direc;        direc[0] = 1.0;        paramcoord[0] = 0.5;        Point tangent =           patchtable.patchmath(patchind).direc_deriv(paramcoord, direc);        beta = Matrix::compute_hh_transform(&hhtransform[0], &tangent[0], 1, 3);      }      sortlist.resize(0, AnglePatchIndPair());      for (PatchTable::Loop_over_parents parloop(patchtable, patchind);           parloop.notdone();           ++parloop) {        PatchTable::Index ppatchind = parloop.parent_index();        Point parent_tan =           patchtable.get_outward_tan_in_parent(paramcoord,                                               patchind,                                                parloop);        Point liftcoord = patchtable.lift_parameters(paramcoord,                                                     patchind,                                                     parloop.listind());        Point parent_normal = patchtable.patchmath(ppatchind).          normal(liftcoord);        if (di == 3) {          PatchTable::apply_3d_hh_and_shift(beta, hhtransform, parent_tan);          PatchTable::apply_3d_hh_and_shift(beta, hhtransform, parent_normal);        }        Real tanang = atan2(parent_tan[1], parent_tan[0]);        Real nrmang = atan2(parent_normal[1], parent_normal[0]);        if (nrmang < tanang)          nrmang += 2 * PI;        bool is_forward =  fabs(nrmang - tanang - PI_OVER_2) < PI_OVER_2;        Brep::Face_Spec front = patchtable.front_side(ppatchind);        Brep::Face_Spec back = patchtable.back_side(ppatchind);        if (!patch_is_doubled[ppatchind]) {                    sortlist.push_back(AnglePatchIndPair(tanang,                                               ppatchind,                                                0,                                                is_forward,                                               is_forward? front: back,                                               is_forward? back : front));        }        else {                    // if this is a doubled patch, put two copies          // of the patch in the sort list.  Assign epsilon so that          // the copy with the clockwise normal comes second.                    Brep::Face_Spec nullspec(di,-1);          sortlist.push_back(AnglePatchIndPair(tanang,                                                ppatchind,                                                0,                                               is_forward,                                               is_forward? front : nullspec,                                               is_forward? nullspec : front));          sortlist.push_back(AnglePatchIndPair(tanang,                                                ppatchind,                                                1,                                               is_forward,                                               is_forward? nullspec : back,                                               is_forward? back : nullspec));        }      }      // Sort the parent patches in order of angle.            sort(sortlist.begin(), sortlist.end());      int sortlistlen = sortlist.size();      // Find a starting point for the sweep.      // A starting point has the brep on its clockwise side.      int sweepstart = -1;      int both_covered_count = 0;      {        Brep::Face_Spec prev_region_above(-1,-1), first_region_below(-1,-1);        for (int ii = 0; ii < sortlistlen; ++ii) {          PatchTable::Index ppatchind = sortlist[ii].patchind;          int wc = sortlist[ii].which_copy;          bool isfor = sortlist[ii].is_forward;          Brep::Face_Spec region_above = sortlist[ii].region_above;          Brep::Face_Spec region_below = sortlist[ii].region_below;          if (ii > 0 && region_below != prev_region_above)            throw_error("Front/back inconsistency");          if (region_below.faceind() < 0 && region_above.faceind() >= 0)            sweepstart = ii;          if (region_below.faceind() >= 0 && region_above.faceind() >= 0)            ++both_covered_count;          prev_region_above = region_above;          if (ii == 0)            first_region_below = region_below;        }        if (first_region_below != prev_region_above)          throw_error("Front back inconsistency 2");      }      if (sweepstart < 0) {        if (both_covered_count == sortlistlen) {          sweepstart = 0;        }        else {          throw_error("ridge does not touch brep region");        }      }      int base = bigsortlist.size();      bigsortlist.resize(base + sortlistlen, AnglePatchIndPair());      pos_in_bigsortlist[patchind] = base;      len_in_bigsortlist[patchind] = sortlistlen;      {        for (int ii = 0; ii < sortlistlen; ++ii) {          int srcii = (ii + sweepstart) % sortlistlen;          bigsortlist[base + ii] = sortlist[srcii];        }      }    }  }

⌨️ 快捷键说明

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