Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

bsimplex.C

Go to the documentation of this file.
00001 /**********************************************************************
00002  * bsimplex.C
00003  **********************************************************************/
00004 #include "mesh/bsimplex.H"
00005 #include "mesh/simplex_filter.H"
00006 #include "mesh/simplex_array.H"
00007 
00008 Bsimplex::IDtable Bsimplex::_table(1<<14);
00009 
00010 Bsimplex::~Bsimplex()
00011 {
00012    if (_data_list) {
00013       _data_list->notify_simplex_deleted();
00014       delete _data_list;
00015       _data_list = 0;
00016    }
00017 }
00018 
00019 uint 
00020 Bsimplex::generate_key() 
00021 {
00022    // called once to generate the "key" for this simplex 
00023    // (first time _key is accessed)
00024 
00025    // XXX - change back to 1<<24 after verifying highest bit is no
00026    // longer being used in some hacky code somewhere like it was at
00027    // one point
00028    if (_table.num() >= ((1<<23) - 1)) {
00029       // can't allocate > 8 million IDs
00030       err_msg("Bsimplex::generate_key: error: key table is full");
00031    } else {
00032       _key = _table.num();
00033       _table += this;
00034    }
00035    return _key;
00036 }
00037 
00038 void 
00039 Bsimplex::notify_split(Bsimplex *new_simp)
00040 {
00041    // the simplex has split, introducing one or more new
00042    // simplices. this method, called once for each newly created
00043    // simplex, notifies simplex data of the original simplex
00044    // (i.e. this one) about the new simplex. that way the data or its
00045    // owner can decide to put some relevant data onto the new simplex
00046    // if that's appropriate.
00047    if (_data_list)
00048       _data_list->notify_split(new_simp);
00049 }
00050 
00051 void
00052 Bsimplex::notify_xform(CWtransf& xf)
00053 {
00054    // a transform was applied to the vertices ... pass it on.
00055    if (_data_list)
00056       _data_list->notify_simplex_xformed(xf);
00057 }
00058 
00059 void
00060 Bsimplex::geometry_changed()
00061 {
00062    // This is called for the following reasons.
00063    //
00064    //   For a vertex: It moved.
00065    //
00066    //   For an edge or face:
00067    //      Its shape changed. I.e. one of its vertices moved.
00068 
00069    // Notify associated data in case any of them care:
00070    if (_data_list)
00071       _data_list->notify_simplex_changed();
00072 }
00073 
00074 void
00075 Bsimplex::normal_changed()
00076 {
00077    // This is called for the following reasons.
00078    //
00079    //   For a face: One of its vertices moved.
00080    //
00081    //   For an edge or vertex:
00082    //      An adjacent face changed shape, or was added or removed.
00083 
00084    // Notify associated data in case any of them care:
00085    if (_data_list)
00086       _data_list->notify_normal_changed();
00087 }
00088 
00089 void 
00090 Bsimplex::add_simplex_data(SimplexData* sd) 
00091 {
00092    // Quietly ignore NULL pointers:
00093    if (!sd)
00094       return;
00095 
00096    // React badly if an item with the same key already exists.
00097    // But cut a little slack if it's actually the same item:
00098    SimplexData* cur = find_data(sd->id());
00099    if (cur) {
00100       if (cur == sd) {
00101          cerr << "Bsimplex::add_simplex_data: Warning: "
00102               << "attempt to add data twice -- ignored"
00103               << endl;
00104          return;
00105       } else assert(0);
00106    }
00107 
00108    // Create the data list if needed:
00109    if (!_data_list) _data_list = new SimplexDataList(); assert(_data_list);
00110 
00111    // Now go ahead:
00112    _data_list->add(sd);
00113 }
00114 
00115 Bsimplex* 
00116 Bsimplex::walk_to_target(CWpt& target, const SimplexFilter& f) const
00117 {
00118    assert(f.accept(this));
00119 
00120    // overview: do a local search over the mesh to get as
00121    // close as possible to the given target point. return
00122    // the simplex that is locally closest to the target.
00123    // however the mesh walk is restricted to traversing
00124    // simplices accepted by the given filter.
00125 
00126    // first find the closest point on this simplex, and find the
00127    // corresponding "closest" simplex contained in this one.
00128    // e.g. if this is a face and the closest point is on the
00129    // boundary of the face, then it is on an edge or vertex; if
00130    // this is an edge, "closest" could be one of the vertices at
00131    // its endpoints. or it could be this simplex itself if the
00132    // closest point is not on the boundary.
00133    Wvec bc;
00134    double    min_dist = dist(target,bc);
00135    Bsimplex*  closest = bc2sim(bc);
00136 
00137    // note: we can switch to a lower-dimension simplex
00138    // without getting closer to the target, but if we go to
00139    // a higher dimesion (e.g. edge to face) we require that
00140    // the distance to target decreases by some nonzero amount.
00141 
00142    if (closest != this && f.accept(closest))
00143       return closest->walk_to_target(target, f); // switch to lower-dim simplex
00144    closest = (Bsimplex*)this;
00145 
00146    // can any neighbors get closer?
00147    Bsimplex_list nbrs = neighbors().filter(f);
00148    for (int i=0; i<nbrs.num(); i++) {
00149       double d = nbrs[i]->dist(target);
00150       if (d < min_dist - epsAbsMath()) {         // get closer by nonzero amount
00151          min_dist = d;
00152          closest = nbrs[i];
00153       }
00154    }
00155 
00156    // return this if it is closest;
00157    // otherwise recurse to the neighbor that was closest:
00158    return (closest == this) ? closest : closest->walk_to_target(target, f);
00159 }
00160 
00161 // end of file bsimplex.C

Generated on Mon Sep 18 11:39:28 2006 for jot by  doxygen 1.4.4