qseparation.cpp
来自「算断裂的」· C++ 代码 · 共 844 行 · 第 1/2 页
CPP
844 行
// ------------------------------------------------------------------// qseparation.cpp//// This file contains routines for separation on boxes in the// mesh generator.// ------------------------------------------------------------------// 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 "qseparation.h"namespace { using namespace QMG; using namespace QMG::MG; const int NUM_TEST_DIRECTIONS_2D = 4; 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};}// This routine tests if a box is crowded. Returns a bool (is it crowded?) and the face// of the apex if not. If it is crowded, returns two interfering faces.using QMG::Triple;Triple<QMG::Brep::Face_Spec, QMG::Brep::Face_Spec, bool> QMG::MG::Separation_Functor::is_crowded_(const ActiveBox& b, int phase) { Brep::Face_Spec apex1(-1, -1); Brep::Face_Spec apex2(-1, -1); { for (int relnum = 0; relnum < b.num_patch(); ++relnum) { PatchTable::Index patchind = b.patch(relnum).patchind(); Brep::Face_Spec owner = patchtable_.owner(patchind); // If there is a brep face of dimension lower than phase, then // the box is crowded. if (owner.fdim() < phase) return Triple<Brep::Face_Spec, Brep::Face_Spec, bool>(owner, owner, true); if (apex1.fdim() == -1 || apex1.fdim() > owner.fdim()) apex1 = owner; if (apex1.fdim() == owner.fdim() && apex1 != owner) apex2 = owner; } } // If there is no apex, or if the apex dimension is higher than the phase, // then the box is not crowded. if (apex1.fdim() == -1 || apex1.fdim() > phase) return Triple<Brep::Face_Spec, Brep::Face_Spec, bool>(apex1, apex1, false); // If two separate apexes, box is crowded. if (apex1.fdim() == apex2.fdim()) return Triple<Brep::Face_Spec, Brep::Face_Spec, bool>(apex1, apex2, true); { for (int relnum = 0; relnum < b.num_patch(); ++relnum) { PatchTable::Index patchind = b.patch(relnum).patchind(); Brep::Face_Spec owner = patchtable_.owner(patchind); bool owner_is_ancestor = false; for (Brep::Ancestor_Lookup::Loop_over_ancestors ancloop(lca_, apex1); ancloop.notdone(); ++ancloop) { if (ancloop.ancestor_fspec() == owner) { owner_is_ancestor = true; break; } } if (!owner_is_ancestor) return Triple<Brep::Face_Spec, Brep::Face_Spec, bool>(apex1, owner, true); } } return Triple<Brep::Face_Spec, Brep::Face_Spec, bool>(apex1, apex1, false);} // ------------------------------------------------------------------ // Tests if a completely interior box is OK for the size function. // Evaluates the size function at the box vertices.QMG::MG::Separation_Functor::Size_Return QMG::MG::Separation_Functor::ok_for_size_function_completely_interior_(const ActiveBox& b, const Brep::Face_Spec& apex) { Real boxwidth = b.real_width(); Size_Return ret; for (ActiveBox::Loop_over_vertices it(b); it.notdone(); ++it) { const Point& incpoint = it.realpoint(); pair<Real,bool> rval = size_control_.eval_interior(incpoint, apex); Real rqsize = rval.first; if (rqsize < boxwidth) { ret.val = rqsize; ret.fspec = apex; ret.ok = false; return ret; } if (rval.second) { ret.ok = true; return ret; } } ret.ok = true; return ret;} // ------------------------------------------------------------------ // Checks if a box is OK for the size function. Evaluates the size // function at all the incidences in the box.QMG::MG::Separation_Functor::Size_Return QMG::MG::Separation_Functor::ok_for_size_function_(const ActiveBox& b, const Brep::Face_Spec& apex) { Real boxwidth = b.real_width(); Point incpoint_real; Point incpoint_par; // *debug_str << "in ok boxwidth = " << boxwidth << '\n'; Size_Return ret; for (int relnum = 0; relnum < b.num_patch(); relnum++) { Patch_in_ActiveBox patch = b.patch(relnum); PatchTable::Index patchind = patch.patchind(); int numinc = patch.num_incidence(); for (int ii = 0; ii < numinc; ii++) { IncidenceTable::Index inc = patch.incidence(ii); incpoint_real = inc_table_.real_coord(inc); incpoint_par = inc_table_.param_coord(inc); pair<Real,bool> rval = size_control_.eval(incpoint_real, incpoint_par, patchind); Real rqsize = rval.first; // *debug_str << " rqsize = " << rqsize << '\n'; if (rqsize < boxwidth) { // *debug_str << " return false\n"; ret.val = rqsize; ret.fspec = apex; ret.ok = false; return ret; } if (rval.second) { // *debug_str << " return true 1\n"; ret.ok = true; return ret; } } } // *debug_str << "return true 2\n"; ret.ok = true; return ret;}// ------------------------------------------------------------------// helper function for ok_for_curvature. For a particular incidence,// updates the normal_variation and param_variation arrays to // keep track of how much the normal and parametric coordinates// vary over the box.// Results stored in track_min_max_.void QMG::MG::Separation_Functor::process_incidence0_(const Brep::Face_Spec& owner, const Point& normal_or_tan) { if (logstr_.verbosity() >= 9) logstr_.str() << " normal est owner = " << owner << " nrml = " << normal_or_tan << '\n'; for (int l = 0; l < num_test_directions_actual_; ++l) { Real ip = Point::inner_product(test_directions_[l], normal_or_tan); if (ip < track_max_min_(owner).lower_bound[l]) track_max_min_(owner).lower_bound[l] = ip; if (ip > track_max_min_(owner).upper_bound[l]) track_max_min_(owner).upper_bound[l] = ip; }}// Assuming track_max_min is already initialized (by the previous routine)// this routine checks whether a new vector is valid for track_max_min_.boolQMG::MG::Separation_Functor::recheck_normal_(const Brep::Face_Spec& owner, const Point& normal_or_tan) { Real rq1 = rqvariance_(owner); for (int l = 0; l < num_test_directions_actual_; ++l) { Real ip = Point::inner_product(test_directions_[l], normal_or_tan); Real mtp = (track_max_min_(owner).lower_bound[l] + track_max_min_(owner).upper_bound[l]) / 2.0; if (fabs(ip - mtp) > rq1) return false; } return true;}// For an incidence in a box, figure out the normal // and track it in track_min_max.void QMG::MG::Separation_Functor::process_incidence1_(PatchTable::Index patchind, const Point& paramcoord, const Point& realcoord) { if (logstr_.verbosity() >= 10) { logstr_.str() << " reached process incidence1 pat#" << patchind << "# paramcoord = " << paramcoord << " realcoord = " << realcoord << '\n'; } Brep::Face_Spec owner = patchtable_.owner(patchind); int pdim = patchtable_.gdim(patchind); if (owner.fdim() == 0 || pdim != owner.fdim()) return; Point normal_or_tan; if (pdim == 2) { normal_or_tan = patchtable_.patchmath(patchind).normal(paramcoord); } else { Point param_direc; param_direc[0] = 1.0; normal_or_tan = patchtable_.patchmath(patchind). direc_deriv(paramcoord, param_direc); normal_or_tan.normalize(); if (!patchtable_.is_forward(patchind)) { for (int j = 0; j < di_; ++j) normal_or_tan[j] = -normal_or_tan[j]; } } if (logstr_.verbosity() >= 10) { logstr_.str() << "owner = " << owner << " normal from direct eval = " << normal_or_tan << '\n'; } process_incidence0_(owner, normal_or_tan);}// In ok_for_curvature_ we do a search on patches to see// if the patches in a box are connected. This routine// determines whether a patch may be used for extending the search.bool QMG::MG::Separation_Functor::acceptable_for_search_(PatchTable::Index patchind, const Point& bmidpoint, Real bwidth) { if (logstr_.verbosity() >= 13) { logstr_.str() << "Reached acceptable_for_search_ pat#" << patchind << " bmidpoint = " << bmidpoint << " bwidth = " << bwidth << '\n'; } if (acceptable_for_search_cache_[patchind] >= 0) { if (logstr_.verbosity() >= 13) { logstr_.str() << " returning cached value " << acceptable_for_search_cache_[patchind] << '\n'; } return (acceptable_for_search_cache_[patchind] > 0); } // If the patch is in the box, it's OK. if (map_to_relnum_[patchind] >= 0) { acceptable_for_search_cache_[patchind] = 1; if (logstr_.verbosity() >= 13) { logstr_.str() << " is in box, return true\n"; } return true; } int gdim1 = patchtable_.gdim(patchind); // Can search only on 0 or 1-dim patches. if (gdim1 > 1) { if (logstr_.verbosity() >= 13) { logstr_.str() << " is hi dim, return false\n"; } acceptable_for_search_cache_[patchind] = 0; return false; } // 1-dml patches always OK. if (gdim1 == 1) { if (logstr_.verbosity() >= 13) { logstr_.str() << " is dim 1, return false\n"; } acceptable_for_search_cache_[patchind] = 1; return true; } // The only case left is the patch is a vertex and outside b itself. // Check if we can continue searching from a vertex // checking (1) whether it is in a larger box around b and (2) // whether its normals satisfy the rqvariance_ requirement. Point paramcoord; Point realcoord = patchtable_.patchmath(patchind).get_real_point(paramcoord); for (int j = 0; j < di_; ++j) { if (fabs(realcoord[j] - bmidpoint[j]) > 2 * bwidth) { if (logstr_.verbosity() >= 13) { logstr_.str() << " is outside box realcoord = " << realcoord << " return false\n"; } acceptable_for_search_cache_[patchind] = 0; return false; } } Point normal_or_tan, param_direc; param_direc[0] = 1; for (PatchTable::Loop_over_parents ploop1(patchtable_, patchind); ploop1.notdone(); ++ploop1) { PatchTable::Index ppatchind = ploop1.parent_index(); Point param1 = patchtable_.lift_parameters(paramcoord, patchind, ploop1.listind()); Brep::Face_Spec eowner = patchtable_.owner(ppatchind); if (eowner.fdim() == 1) { normal_or_tan = patchtable_.patchmath(ppatchind). direc_deriv(param1, param_direc); normal_or_tan.normalize(); if (!patchtable_.is_forward(patchind)) { for (int j = 0; j < di_; ++j) normal_or_tan[j] = -normal_or_tan[j]; } if (!recheck_normal_(eowner, normal_or_tan)) { if (logstr_.verbosity() >= 13) { logstr_.str() << " failed to confirm normal on parent pat#" << ppatchind << "# owner " << eowner << " return false\n"; } acceptable_for_search_cache_[patchind] = 0; return false; } } for (PatchTable::Loop_over_parents ploop2(patchtable_, ppatchind); ploop2.notdone(); ++ploop2) { PatchTable::Index gppatchind = ploop2.parent_index(); Point param2 = patchtable_.lift_parameters(param1, ppatchind, ploop2.listind()); Brep::Face_Spec fowner = patchtable_.owner(gppatchind); normal_or_tan = patchtable_.patchmath(gppatchind).normal(param2); if (!recheck_normal_(fowner, normal_or_tan)) { if (logstr_.verbosity() >= 13) { logstr_.str() << " failed to confirm normal on grandparent pat#" << gppatchind << "# owner " << fowner << " return false\n"; } acceptable_for_search_cache_[patchind] = 0; return false; } } } if (logstr_.verbosity() >= 13) { logstr_.str() << "Ran thru tests, all passed\n"; } acceptable_for_search_cache_[patchind] = 1; return true;} // ------------------------------------------------------------------// function determines whether the curvature of patches in a box// is excessive.QMG::MG::Separation_Functor::Size_Return QMG::MG::Separation_Functor::ok_for_curvature_(const ActiveBox& b) { Real boxwidth = b.real_width(); int oldverb = logstr_.verbosity(); /* IntCoord p1 = b.boxaddress().lowerleft(); if (p1[0] == 0x20000000U && p1[1] == 0x18000000U) { logstr_.str() << " reached special box"; b.full_dump2(logstr_.str(), patchtable_, inc_table_); logstr_.change_verbosity(15); } */ Point normal; if (logstr_.verbosity() >= 8) logstr_.str() << "In ok for curvature, b = " << b << '\n'; // Initialize the rqvariance field for each face. { for (int relnum = 0; relnum < b.num_patch(); ++relnum) { Patch_in_ActiveBox patch = b.patch(relnum); PatchTable::Index patchind = patch.patchind(); Brep::Face_Spec owner = patchtable_.owner(patchind); rqvariance_(owner) = BIG_REAL; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?