crtsubbox.cpp
来自「算断裂的」· C++ 代码 · 共 1,123 行 · 第 1/3 页
CPP
1,123 行
// ------------------------------------------------------------------// crtsubbox.cpp//// This file contains member functions from qboxstack.h for creating// subboxes. // ------------------------------------------------------------------// 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.// ------------------------------------------------------------------#ifdef _MSC_VER#if _MSC_VER == 1200#include "qmatvec.h"#endif#endif#include "qboxstack.h"#include "qunionfind.h"namespace QMG { namespace MG { using namespace QMG; //global function in this file void boxstack_init_static_data(int di); }}// File scope functions.#ifdef DEBUGGINGnamespace QMG { namespace Local_to_PatchMath_CPP { using namespace QMG; extern ostream* debug_str; extern bool dump_everything; }}#endifnamespace { using namespace QMG; using namespace QMG::MG; // ------------------------------------------------------------------ // Combinatorial merge: merge each patch with its child patches. This leaves // all bounding faces in the same connected component with the same label. // The return value is left in workspace variable wkspa.uf. void combinatorial_merge(const ActiveBox& b, ActiveBoxVec::Create_Subbox_Workspace& wkspa) { wkspa.map_to_relnum.reset(-1); for (int relnum = 0; relnum < b.num_patch(); relnum++) { PatchTable::Index p = b.patch(relnum).patchind(); wkspa.map_to_relnum[p] = relnum; // Loop over the children patches. for (PatchTable::Loop_over_children loop(wkspa.patchtable, p); loop.notdone(); ++loop) { PatchTable::Index c = loop.child_index(); int relnum2 = wkspa.map_to_relnum[c]; if (relnum2 >= 0) { wkspa.uf.merge(relnum, relnum2); } } } } // Merge patches that belong to the same brep face. Necessary else // alignment won't work correctly. Leave results in uf. void combinatorial_merge2(const ActiveBox& b, ActiveBoxVec::Create_Subbox_Workspace& wkspa) { { for (int relnum = 0; relnum < b.num_patch(); ++relnum) { PatchTable::Index p = b.patch(relnum).patchind(); wkspa.example_patchrelnum[wkspa.patchtable.owner(p)] = relnum; } } { for (int relnum = 0; relnum < b.num_patch(); ++relnum) { PatchTable::Index p = b.patch(relnum).patchind(); int relnum2 = wkspa.example_patchrelnum[wkspa.patchtable.owner(p)]; wkspa.uf.merge(relnum, relnum2); } } } // ------------------------------------------------------------------ // Draw a segment through a box; return the sorted list of hits on patches. // Used for geometric merging of connected components. Direct return // value is true if there is a degeneracy else false. The sorted list // is returned in workspace variable wkspa.hitlist. bool draw_segment_thru_box(const ActiveBox& b, IncidenceTable::Index startpoint_incind, int startpoint_relnum, const Point& endpoint, ActiveBoxVec::Create_Subbox_Workspace& wkspa) { wkspa.hitlist.resize(0, ActiveBoxVec::RayHitRecord()); PatchTable::Index startpoint_patchind = wkspa.inc_table.patchind(startpoint_incind); Point startpoint = wkspa.inc_table.real_coord(startpoint_incind); int di = wkspa.patchtable.embedded_dim(); Point normal; Point segment_tangent = Point::subtract(endpoint, startpoint); Real farthest_hit_dist = 0.0; pair<PatchTable::Index, PatchTable::ConeIntersectCode> rval1 = wkspa.patchtable.determine_ray_front_face(startpoint_patchind, wkspa.inc_table.param_coord(startpoint_incind), segment_tangent, wkspa.tol); if (rval1.second == PatchTable::DEGEN) { if (wkspa.logstr.verbosity() >= 8) { wkspa.logstr.str() << " Degeneracy in determine_ray_front_face\n"; } return true; } PatchTable::Index patchind_s = rval1.first; Brep::Face_Spec base_fspec = (rval1.second == PatchTable::HITS_PATCH_FRONT)? wkspa.patchtable.front_side(patchind_s) : wkspa.patchtable.back_side(patchind_s); if (wkspa.logstr.verbosity() >= 8) wkspa.logstr.str() << "reached shootray tangent = " << segment_tangent << " start point = " << startpoint << "= incd#" << wkspa.inc_table.seqno(startpoint_incind) << "#" << "\n basefspec = " << base_fspec << " startpoint_patchind = pat#" << startpoint_patchind << "#\n" << " endpoint = " << endpoint << '\n'; ActiveBoxVec::RayHitRecord rayhit; rayhit.relnum = startpoint_relnum; rayhit.front_hit = base_fspec; rayhit.dist = 0.0; rayhit.is_front = rval1.second == PatchTable::HITS_PATCH_FRONT; wkspa.hitlist.push_back(rayhit); for (int relnum = 0; relnum < b.num_patch(); ++relnum) { PatchTable::Index patchind = b.patch(relnum).patchind(); if (wkspa.patchtable.gdim(patchind) < di - 1) continue; if (wkspa.logstr.verbosity() >= 8) { wkspa.logstr.str() << "loop relnum = " << relnum << "pat#" << patchind << "#" << " orig = " << wkspa.patchtable.owner(patchind) << " # " << wkspa.patchtable.orig_index(patchind) << '\n'; } bool require_startpoint_degen = wkspa.patchtable.is_ancestor(startpoint_patchind, patchind); wkspa.output_stack.resize(0, PatchMath::IntersectRecord()); wkspa.patchtable.patchmath(patchind).intersect_seg(wkspa.output_stack, wkspa.rworkspace, startpoint, endpoint, wkspa.scfac, wkspa.tol, false); if (wkspa.logstr.verbosity() >= 8) wkspa.logstr.str() << "require startpoint degen = " << require_startpoint_degen << " size = " << wkspa.output_stack.size() << '\n'; int sz = wkspa.output_stack.size(); int degen_count = 0; for (int ii = 0; ii < sz; ++ii) { if (wkspa.logstr.verbosity() >= 8) { wkspa.logstr.str() << "hit " << ii << " at real point " << wkspa.output_stack[ii].realcoord << " param " << wkspa.output_stack[ii].paramcoord << "\n degen = " << wkspa.output_stack[ii].degen << " uncer = " << wkspa.output_stack[ii].param_uncertainty << " seguncer = " << wkspa.output_stack[ii].param_uncertainty_seg << " dist = " << wkspa.output_stack[ii].dist << '\n'; } if (wkspa.output_stack[ii].degen) { ++degen_count; continue; } normal = wkspa.patchtable.patchmath(patchind).normal(wkspa.output_stack[ii].paramcoord); Real ip = Point::inner_product(normal, segment_tangent); rayhit.relnum = relnum; rayhit.dist = wkspa.output_stack[ii].dist; if (ip > 0) { rayhit.front_hit = wkspa.patchtable.front_side(patchind); rayhit.back_hit = wkspa.patchtable.back_side(patchind); rayhit.is_front = true; } else { rayhit.front_hit = wkspa.patchtable.back_side(patchind); rayhit.back_hit = wkspa.patchtable.front_side(patchind); rayhit.is_front = false; } if (wkspa.logstr.verbosity() >= 8) { wkspa.logstr.str() << " front = " << rayhit.front_hit << " back = " << rayhit.back_hit << '\n'; } wkspa.hitlist.push_back(rayhit); } if (degen_count > 1 || (degen_count > 0 && !require_startpoint_degen)) return true; if (degen_count == 0 && require_startpoint_degen) { wkspa.logstr.str() << "Error! Output stack size = " << sz << '\n'; { for (int jj = 0; jj < sz; ++jj) { wkspa.logstr.str() << "output_stack[" << jj << "] dist = " << wkspa.output_stack[jj].dist << " degen = " << wkspa.output_stack[jj].degen << " paramcoord = " << wkspa.output_stack[jj].paramcoord << '\n'; } } QMG::Local_to_PatchMath_CPP::debug_str = &wkspa.logstr.str(); QMG::Local_to_PatchMath_CPP::dump_everything = true; wkspa.output_stack.resize(0, PatchMath::IntersectRecord()); wkspa.patchtable.patchmath(patchind).intersect_seg(wkspa.output_stack, wkspa.rworkspace, startpoint, endpoint, wkspa.scfac, wkspa.tol, false); int sz = wkspa.output_stack.size(); wkspa.logstr.str() << " Second time Output stack size = " << sz << '\n'; { for (int jj = 0; jj < sz; ++jj) { wkspa.logstr.str() << "wkspa.output_stack[" << jj << "] dist = " << wkspa.output_stack[jj].dist << " degen = " << wkspa.output_stack[jj].degen << " paramcoord = " << wkspa.output_stack[jj].paramcoord << '\n'; } } throw_error("Ray missed starting patch? This message may indicate a tolerance error"); } } sort(wkspa.hitlist.begin(), wkspa.hitlist.end());#ifdef DEBUGGING for (int hitlistind = 0; hitlistind < wkspa.hitlist.size() - 1; hitlistind++) { if (wkspa.hitlist[hitlistind].front_hit != wkspa.hitlist[hitlistind+1].back_hit) { ostringstream os; os << "Problem 2 in draw_segment.\n" << "This error may indicate a problem with illegally crossing faces\n" << "in the input brep. The two surfaces causing the error are\n" << wkspa.patchtable.owner(b.patch(wkspa.hitlist[hitlistind].relnum).patchind()) << " and " << wkspa.patchtable.owner(b.patch(wkspa.hitlist[hitlistind+1].relnum).patchind()); throw_error(os.str()); } }#endif return false; } // ------------------------------------------------------------------ // Merge connected components of the content of a box by shooting rays. // Return variable is wkspa.uf (union find). void segshoot_merge(const ActiveBox& b, ActiveBoxVec::Create_Subbox_Workspace& wkspa) { int di = wkspa.patchtable.embedded_dim(); int ufsize = wkspa.uf.size(); wkspa.ray_shot_from_label.resize(ufsize); for (int jj = 0; jj < ufsize; ++jj) wkspa.ray_shot_from_label[jj] = false; bool degenhit = true; int trycount = 0; if (wkspa.logstr.verbosity() >= 8) { wkspa.logstr.str() << " reached segshoot merge box = " << b << '\n'; } int oldverb = wkspa.logstr.verbosity(); while (degenhit && ++trycount < 400) { Point randpoint = b.select_rand_point(); if (trycount == 398) { wkspa.logstr.change_verbosity(8); wkspa.logstr.str() << "trycount at 398 b = "; b.full_dump(wkspa.logstr.str()); } if (wkspa.logstr.verbosity() >= 8) { wkspa.logstr.str() << "trycount = " << trycount << " randpoint = " << randpoint << "\n"; } degenhit = false; int root_component_patchrelnum = -1; for (int relnum1 = 0; relnum1 < b.num_patch(); ++relnum1) wkspa.ray_shot_from_label[relnum1] = false; for (int relnum = 0; relnum < b.num_patch(); ++relnum) { PatchTable::Index patchind = b.patch(relnum).patchind(); int c = wkspa.uf.get_label(relnum); if (wkspa.logstr.verbosity() >= 8) { wkspa.logstr.str() << " in loop relnum = " << relnum << " c = " << c << " rsfl = " << wkspa.ray_shot_from_label[c] << '\n'; } if (!wkspa.ray_shot_from_label[c]) { // Select starting point on patch relnum. Patch_in_ActiveBox ptc = b.patch(relnum); if (ptc.num_incidence() == 0) throw_error("No incidences on patch of component?"); IncidenceTable::Index incind = ptc.incidence(0); if (wkspa.logstr.verbosity() >= 8) { wkspa.logstr.str() << " calling draw seg from inc incd#" << wkspa.inc_table.seqno(incind) << "#\n"; } degenhit = draw_segment_thru_box(b, incind, relnum, randpoint, wkspa); // Last call puts return list in wkspa.hitlist. if (degenhit) { if (wkspa.logstr.verbosity() >= 8) { wkspa.logstr.str() << "degenhit = true\n"; } break; }#ifdef DEBUGGING // First hit should be on p. if (wkspa.hitlist.size() == 0 || wkspa.hitlist[0].relnum != relnum) { throw_error("Problem 1 in rayshoot_merge"); return; }#endif if (wkspa.logstr.verbosity() >= 8) { wkspa.logstr.str() << " hitlist size = " << wkspa.hitlist.size() << '\n'; for (int iii = 0; iii < wkspa.hitlist.size(); ++iii) { wkspa.logstr.str() << "hit list " << iii << " dist = " << wkspa.hitlist[iii].dist << " relnum = " << wkspa.hitlist[iii].relnum << " front = " << wkspa.hitlist[iii].front_hit << " back = " << wkspa.hitlist[iii].back_hit << '\n'; } } // Merge each item in the hit list with its successor. for (int hitlistind = 0; hitlistind < wkspa.hitlist.size() - 1; hitlistind++) { int relnum1 = wkspa.hitlist[hitlistind].relnum; int relnum2 = wkspa.hitlist[hitlistind + 1].relnum;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?