SCIRun  5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TriSurfMesh.h
Go to the documentation of this file.
1 /*
2  For more information, please see: http://software.sci.utah.edu
3 
4  The MIT License
5 
6  Copyright (c) 2009 Scientific Computing and Imaging Institute,
7  University of Utah.
8 
9 
10  Permission is hereby granted, free of charge, to any person obtaining a
11  copy of this software and associated documentation files (the "Software"),
12  to deal in the Software without restriction, including without limitation
13  the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  and/or sell copies of the Software, and to permit persons to whom the
15  Software is furnished to do so, subject to the following conditions:
16 
17  The above copyright notice and this permission notice shall be included
18  in all copies or substantial portions of the Software.
19 
20  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  DEALINGS IN THE SOFTWARE.
27 */
28 
29 #ifndef CORE_DATATYPES_TRISURFMESH_H
30 #define CORE_DATATYPES_TRISURFMESH_H 1
31 
32 /// Include what kind of support we want to have
33 /// Need to fix this and couple it sci-defs
35 
37 
46 
47 #include <Core/Basis/Locate.h>
50 #include <Core/Basis/TriCubicHmt.h>
51 
56 
57 #include <Core/Thread/Mutex.h>
59 #include <boost/thread.hpp>
60 
61 #include <set>
62 
64 
65 namespace SCIRun {
66 
67  using namespace SCIRun::Core::Basis;
68  using namespace SCIRun::Core::Geometry;
69 
70 /////////////////////////////////////////////////////
71 // Declarations for virtual interface
72 
73 /// Functions for creating the virtual interface
74 /// Declare the functions that instantiate the virtual interface
75 template<class MESH> class TriSurfMesh;
76 
77 /// make sure any other mesh other than the preinstantiate ones
78 /// returns no virtual interface. Altering this behavior will allow
79 /// for dynamically compiling the interface if needed.
80 template<class MESH>
81 VMesh* CreateVTriSurfMesh(MESH*) { return (0); }
82 
83 #if (SCIRUN_TRISURF_SUPPORT > 0)
84 /// Declare that these can be found in a library that is already
85 /// precompiled. So dynamic compilation will not instantiate them again.
87 #if (SCIRUN_QUADRATIC_SUPPORT > 0)
89 #endif
90 #if (SCIRUN_CUBIC_SUPPORT > 0)
92 #endif
93 
94 #endif
95 /////////////////////////////////////////////////////
96 
97 
98 /////////////////////////////////////////////////////
99 // Declarations for TriSurfMesh class
100 
101 template <class Basis>
102 class TriSurfMesh : public Mesh
103 {
104 
105 /// Make sure the virtual interface has access
106 template<class MESH> friend class VTriSurfMesh;
107 template<class MESH> friend class VMeshShared;
108 template<class MESH> friend class VUnstructuredMesh;
109 
110 public:
111  // Types that change depending on 32 or 64bits
116 
117  typedef boost::shared_ptr<TriSurfMesh<Basis> > handle_type;
118  typedef Basis basis_type;
119 
120  /// Index and Iterator types required for Mesh Concept.
121  struct Node {
126  };
127 
128  struct Edge {
132  typedef std::vector<index_type> array_type;
133  };
134 
135  struct Face {
139  typedef std::vector<index_type> array_type;
140  };
141 
142  struct Cell {
146  typedef std::vector<index_type> array_type;
147  };
148 
149  /// Elem refers to the most complex topological object
150  /// DElem refers to object just below Elem in the topological hierarchy
151  typedef Face Elem;
152  typedef Edge DElem;
153 
154  /// Somehow the information of how to interpolate inside an element
155  /// ended up in a separate class, as they need to share information
156  /// this construction was created to transfer data.
157  /// Hopefully in the future this class will disappear again.
158  friend class ElemData;
159 
160  class ElemData
161  {
162  public:
164 
165  ElemData(const TriSurfMesh<Basis>& msh, const index_type ind) :
166  mesh_(msh),
167  index_(ind)
168  {
169  /// Linear and Constant Basis never use edges_
170  if (basis_type::polynomial_order() > 1) {
171  mesh_.get_edges_from_face(edges_, index_);
172  }
173  }
174 
175  // the following designed to coordinate with ::get_nodes
176  inline
178  return mesh_.faces_[index_ * 3];
179  }
180  inline
182  return mesh_.faces_[index_ * 3 + 1];
183  }
184  inline
186  return mesh_.faces_[index_ * 3 + 2];
187  }
188 
189  // the following designed to coordinate with ::get_edges
190  inline
192  return edges_[0];
193  }
194  inline
196  return edges_[1];
197  }
198  inline
200  return edges_[2];
201  }
202 
203  inline
205  return index_;
206  }
207 
208  inline
209  const Core::Geometry::Point &node0() const {
210  return mesh_.points_[node0_index()];
211  }
212  inline
213  const Core::Geometry::Point &node1() const {
214  return mesh_.points_[node1_index()];
215  }
216  inline
217  const Core::Geometry::Point &node2() const {
218  return mesh_.points_[node2_index()];
219  }
220 
221  private:
222  /// reference to the mesh
223  const TriSurfMesh<Basis> &mesh_;
224  /// copy of element index
225  const index_type index_;
226  /// need edges for quadratic meshes
227  typename Edge::array_type edges_;
228  };
229 
230 
231  friend class Synchronize;
232 
233  class Synchronize /*: public Runnable*/
234  {
235  public:
237  mesh_(mesh), sync_(sync) {}
238 
239  void run()
240  {
241  this->operator()();
242  }
243  void operator()()
244  {
245  mesh_->synchronize_lock_.lock();
246  // block out all the tables that are already synchronized
247  sync_ &= ~(mesh_->synchronized_);
248  // block out all the tables that are already being computed
249  sync_ &= ~(mesh_->synchronizing_);
250  // Now sync_ contains what this thread will synchronize
251  // Denote what this thread will synchronize
252  mesh_->synchronizing_ |= sync_;
253  // Other threads now know what this tread will be doing
254  mesh_->synchronize_lock_.unlock();
255 
256  // Sync node neighbors
257  if (sync_ & Mesh::ELEM_NEIGHBORS_E) mesh_->compute_edge_neighbors();
258  if (sync_ & Mesh::NODE_NEIGHBORS_E) mesh_->compute_node_neighbors();
259  if (sync_ & Mesh::EDGES_E) mesh_->compute_edges_bugfix();
260  if (sync_ & Mesh::NORMALS_E) mesh_->compute_normals();
261  if (sync_ & Mesh::BOUNDING_BOX_E) mesh_->compute_bounding_box();
262 
263  // These depend on the bounding box being synchronized
265  {
266  {
267  Core::Thread::UniqueLock lock(mesh_->synchronize_lock_.get());
268  while(!(mesh_->synchronized_ & Mesh::BOUNDING_BOX_E))
269  mesh_->synchronize_cond_.wait(lock);
270  }
271  if (sync_ & Mesh::NODE_LOCATE_E)
272  {
273  mesh_->compute_node_grid();
274  }
275  if (sync_ & Mesh::ELEM_LOCATE_E)
276  {
277  mesh_->compute_elem_grid();
278  }
279  }
280 
281  mesh_->synchronize_lock_.lock();
282  // Mark the ones that were just synchronized
283  mesh_->synchronized_ |= sync_;
284  // Unmark the the ones that were done
285  mesh_->synchronizing_ &= ~(sync_);
286  /// Tell other threads we are done
287  mesh_->synchronize_cond_.conditionBroadcast();
288  mesh_->synchronize_lock_.unlock();
289  }
290 
291  private:
292  TriSurfMesh<Basis>* mesh_;
293  mask_type sync_;
294  };
295 
296 
297  //////////////////////////////////////////////////////////////////
298 
299  /// Construct a new mesh;
300  TriSurfMesh();
301 
302  /// Copy a mesh, needed for detaching the mesh from a field
303  TriSurfMesh(const TriSurfMesh &copy);
304 
305  /// Clone function for detaching the mesh and automatically generating
306  /// a new version if needed.
307  virtual TriSurfMesh *clone() const { return new TriSurfMesh(*this); }
308 
309  virtual MeshFacadeHandle getFacade() const { return boost::make_shared<Core::Datatypes::VirtualMeshFacade<VMesh>>(vmesh_); }
310 
311  /// Destructor
312  virtual ~TriSurfMesh();
313 
314  /// Access point to virtual interface
315  virtual VMesh* vmesh() { return (vmesh_.get()); }
316 
317  /// This one should go at some point, should be reroute through the
318  /// virtual interface
319  virtual int basis_order() { return (basis_.polynomial_order()); }
320 
321  /// Topological dimension
322  virtual int dimensionality() const { return 2; }
323 
324  /// What kind of mesh is this
325  /// structured = no connectivity data
326  /// regular = no node location data
327  virtual int topology_geometry() const
328  { return (Mesh::UNSTRUCTURED | Mesh::IRREGULAR); }
329 
330  /// Get the bounding box of the field
331  virtual Core::Geometry::BBox get_bounding_box() const;
332 
333  /// Return the transformation that takes a 0-1 space bounding box
334  /// to the current bounding box of this mesh.
335  virtual void get_canonical_transform(Core::Geometry::Transform &t) const;
336 
337  /// Core::Geometry::Transform a field (transform all nodes using this transformation matrix)
338  virtual void transform(const Core::Geometry::Transform &t);
339 
340  /// Check whether mesh can be altered by adding nodes or elements
341  virtual bool is_editable() const { return (true); }
342 
343  /// Has this mesh normals.
344  // Note: normals point outward.
345  /// @todo: this is inconsistent with QuadSurfMesh - should both surfaces
346  // have consistent normal direction?
347  virtual bool has_normals() const { return (true); }
348 
349  /// Compute tables for doing topology, these need to be synchronized
350  /// before doing a lot of operations.
351  virtual bool synchronize(mask_type mask);
352  virtual bool unsynchronize(mask_type mask);
353  bool clear_synchronization();
354 
355  /// Get the basis class.
356  Basis& get_basis() { return basis_; }
357 
358  /// begin/end iterators
359  void begin(typename Node::iterator &) const;
360  void begin(typename Edge::iterator &) const;
361  void begin(typename Face::iterator &) const;
362  void begin(typename Cell::iterator &) const;
363 
364  void end(typename Node::iterator &) const;
365  void end(typename Edge::iterator &) const;
366  void end(typename Face::iterator &) const;
367  void end(typename Cell::iterator &) const;
368 
369  void size(typename Node::size_type &) const;
370  void size(typename Edge::size_type &) const;
371  void size(typename Face::size_type &) const;
372  void size(typename Cell::size_type &) const;
373 
374  /// These are here to convert indices to unsigned int
375  /// counters. Some how the decision was made to use multi
376  /// dimensional indices in some fields, these functions
377  /// should deal with different pointer types.
378  /// Use the virtual interface to avoid all this non sense.
379  void to_index(typename Node::index_type &index, index_type i) const
380  { index = i; }
381  void to_index(typename Edge::index_type &index, index_type i) const
382  { index = i; }
383  void to_index(typename Face::index_type &index, index_type i) const
384  { index = i; }
385  void to_index(typename Cell::index_type &index, index_type i) const
386  { index = i; }
387 
388 
389  /// Get the child elements of the given index.
390  void get_nodes(typename Node::array_type &array, typename Node::index_type idx) const
391  { array.resize(1); array[0]= idx; }
392  void get_nodes(typename Node::array_type &array, typename Edge::index_type idx) const
393  { get_nodes_from_edge(array,idx); }
394  void get_nodes(typename Node::array_type &array, typename Face::index_type idx) const
395  { get_nodes_from_face(array,idx); }
396  void get_nodes(typename Node::array_type&, typename Cell::index_type) const
397  { ASSERTFAIL("TriSurfMesh: get_nodes has not been implemented for cells"); }
398 
399  void get_edges(typename Edge::array_type &array, typename Node::index_type idx) const
400  { get_edges_from_node(array,idx); }
401  void get_edges(typename Edge::array_type &array, typename Edge::index_type idx) const
402  { array.resize(1); array[0]= idx; }
403  void get_edges(typename Edge::array_type &array, typename Face::index_type idx) const
404  { get_edges_from_face(array,idx); }
405  void get_edges(typename Edge::array_type&, typename Cell::index_type) const
406  { ASSERTFAIL("TriSurfMesh: get_edges has not been implemented for cells"); }
407 
408  void get_faces(typename Face::array_type &array, typename Node::index_type idx) const
409  { get_faces_from_node(array,idx); }
410  void get_faces(typename Face::array_type &array, typename Edge::index_type idx) const
411  { get_faces_from_edge(array,idx); }
412  void get_faces(typename Face::array_type &array, typename Face::index_type idx) const
413  { array.resize(1); array[0]= idx; }
414  void get_faces(typename Face::array_type&, typename Cell::index_type) const
415  { ASSERTFAIL("TriSurfMesh: get_faces has not been implemented for cells"); }
416 
417  void get_cells(typename Cell::array_type&, typename Node::index_type) const
418  { ASSERTFAIL("TriSurfMesh: get_cells has not been implemented"); }
419  void get_cells(typename Cell::array_type&, typename Edge::index_type) const
420  { ASSERTFAIL("TriSurfMesh: get_cells has not been implemented"); }
421  void get_cells(typename Cell::array_type&, typename Face::index_type) const
422  { ASSERTFAIL("TriSurfMesh: get_cells has not been implemented"); }
423  void get_cells(typename Cell::array_type&, typename Cell::index_type) const
424  { ASSERTFAIL("TriSurfMesh: get_cells has not been implemented"); }
425 
426  void get_elems(typename Elem::array_type &array, typename Node::index_type idx) const
427  { get_faces_from_node(array,idx); }
428  void get_elems(typename Elem::array_type &array, typename Edge::index_type idx) const
429  { get_faces_from_edge(array,idx); }
430  void get_elems(typename Elem::array_type &array, typename Face::index_type idx) const
431  { array.resize(1); array[0]= idx; }
432  void get_elems(typename Face::array_type&, typename Cell::index_type) const
433  { ASSERTFAIL("TriSurfMesh: get_elems has not been implemented for cells"); }
434 
435  void get_delems(typename DElem::array_type &array, typename Node::index_type idx) const
436  { get_edges_from_node(array,idx); }
437  void get_delems(typename DElem::array_type &array, typename Edge::index_type idx) const
438  { array.resize(1); array[0]= idx; }
439  void get_delems(typename DElem::array_type &array, typename Face::index_type idx) const
440  { get_edges_from_face(array,idx); }
441  void get_delems(typename DElem::array_type&, typename Cell::index_type) const
442  { ASSERTFAIL("TriSurfMesh: get_delems has not been implemented for cells"); }
443 
444  /// Generate the list of points that make up a sufficiently accurate
445  /// piecewise linear approximation of an edge.
446  template<class VECTOR, class INDEX>
447  void pwl_approx_edge(std::vector<VECTOR > &coords,
448  INDEX ci,
449  unsigned int which_edge,
450  unsigned int div_per_unit) const
451  {
452  basis_.approx_edge(which_edge, div_per_unit, coords);
453  }
454 
455  /// Generate the list of points that make up a sufficiently accurate
456  /// piecewise linear approximation of an face.
457  template<class VECTOR, class INDEX>
458  void pwl_approx_face(std::vector<std::vector<VECTOR > > &coords,
459  INDEX ci,
460  unsigned int which_face,
461  unsigned int div_per_unit) const
462  {
463  basis_.approx_face(which_face, div_per_unit, coords);
464  }
465 
466  /// get the center point (in object space) of an element
467  void get_center(Core::Geometry::Point &result, typename Node::index_type idx) const
468  { get_node_center(result, idx); }
469  void get_center(Core::Geometry::Point &result, typename Edge::index_type idx) const
470  { get_edge_center(result, idx); }
471  void get_center(Core::Geometry::Point &result, typename Face::index_type idx) const
472  { get_face_center(result, idx); }
474  { ASSERTFAIL("TriSurfMesh: get_cneter has not been implemented for cells"); }
475 
476  /// Get the size of an elemnt (length, area, volume)
477  double get_size(typename Node::index_type /*idx*/) const
478  { return 0.0; }
479 
480  double get_size(typename Edge::index_type idx) const
481  {
482  typename Node::array_type arr;
483  get_nodes_from_edge(arr, idx);
484  return (points_[arr[0]] - points_[arr[1]]).length();
485  }
486 
487  double get_size(typename Face::index_type idx) const
488  {
489  typename Node::array_type ra;
490  get_nodes(ra,idx);
491  const Core::Geometry::Point &p0 = points_[ra[0]];
492  const Core::Geometry::Point &p1 = points_[ra[1]];
493  const Core::Geometry::Point &p2 = points_[ra[2]];
494  return (Cross(p0-p1,p2-p0)).length()*0.5;
495  }
496 
497  double get_size(typename Cell::index_type /*idx*/) const
498  { return 0.0; }
499 
500  /// More specific names for get_size
501  double get_length(typename Edge::index_type idx) const
502  { return get_size(idx); }
503  double get_area(typename Face::index_type idx) const
504  { return get_size(idx); }
505  double get_volume(typename Cell::index_type /*idx*/) const
506  { return 0.0; }
507 
508  /// Get neighbors of an element or a node
509 
510  /// THIS ONE IS FLAWED AS IN 3D SPACE MULTIPLE EDGES CAN CONNECTED THROUGH
511  /// ONE EDGE
512  bool get_neighbor(typename Elem::index_type &neighbor,
513  typename Elem::index_type elem,
514  typename DElem::index_type delem) const
515  { return(get_elem_neighbor(neighbor,elem,delem)); }
516 
517  /// These are more general implementations
518  void get_neighbors(std::vector<typename Node::index_type> &array,
519  typename Node::index_type node) const
520  { get_node_neighbors(array,node); }
521  bool get_neighbors(std::vector<typename Elem::index_type> &array,
522  typename Elem::index_type elem,
523  typename DElem::index_type delem) const
524  { return(get_elem_neighbors(array,elem,delem)); }
525  void get_neighbors(typename Elem::array_type &array,
526  typename Elem::index_type elem) const
527  { get_elem_neighbors(array,elem); }
528 
529  /// Locate a point in a mesh, find which is the closest node
530  bool locate(typename Node::index_type &loc, const Core::Geometry::Point &p) const
531  { return (locate_node(loc,p)); }
532  bool locate(typename Edge::index_type &loc, const Core::Geometry::Point &p) const
533  { return (locate_edge(loc,p)); }
534  bool locate(typename Face::index_type &loc, const Core::Geometry::Point &p) const
535  { return (locate_elem(loc,p)); }
536  bool locate(typename Cell::index_type&, const Core::Geometry::Point&) const
537  { return (false); }
538 
539  bool locate(typename Elem::index_type& elem,
540  std::vector<double>& coords,
541  const Core::Geometry::Point& p)
542  { return(locate_elem(elem,coords,p)); }
543 
544  /// These should become obsolete soon, they do not follow the concept
545  /// of the basis functions....
546  int get_weights(const Core::Geometry::Point &p, typename Node::array_type &l, double *w);
547  int get_weights(const Core::Geometry::Point&, typename Edge::array_type&, double*)
548  {ASSERTFAIL("TriSurfMesh::get_weights(Edges) not supported."); }
549  int get_weights(const Core::Geometry::Point &p, typename Face::array_type &l, double *w);
550  int get_weights(const Core::Geometry::Point&, typename Cell::array_type&, double*)
551  {ASSERTFAIL("TriSurfMesh::get_weights(Cells) not supported."); }
552 
553  /// Access the nodes of the mesh
554  void get_point(Core::Geometry::Point &result, typename Node::index_type index) const
555  { result = points_[index]; }
556  void set_point(const Core::Geometry::Point &point, typename Node::index_type index)
557  { points_[index] = point; }
558 
559  void get_random_point(Core::Geometry::Point &, typename Elem::index_type, FieldRNG &rng) const;
560 
561  /// Normals for visualizations
562  void get_normal(Core::Geometry::Vector &result, typename Node::index_type index) const
563  {
564  ASSERTMSG(synchronized_ & Mesh::NORMALS_E,
565  "Must call synchronize NORMALS_E on TriSurfMesh first");
566  result = normals_[index];
567  }
568 
569  /// Get the normals at the outside of the element
570  template<class VECTOR, class INDEX1, class INDEX2>
571  void get_normal(Core::Geometry::Vector &result, VECTOR &coords,
572  INDEX1 eidx, INDEX2 /*fidx*/)
573  {
574 
575  ElemData ed(*this, eidx);
576  std::vector<Core::Geometry::Point> Jv;
577  basis_.derivate(coords, ed, Jv);
578  result = Cross(Vector(Jv[0]), Vector(Jv[1]));
579  result.normalize();
580  }
581 
582  /// Add a new node to the mesh
583  typename Node::index_type add_point(const Core::Geometry::Point &p);
585  { return(add_point(p)); }
586 
587  /// Add a new element to the mesh
588  template <class ARRAY>
589  typename Elem::index_type add_elem(ARRAY a)
590  {
591  ASSERTMSG(a.size() == 3, "TriSurfMesh: Tried to add non-tri element.");
592 
593  faces_.push_back(static_cast<typename Node::index_type>(a[0]));
594  faces_.push_back(static_cast<typename Node::index_type>(a[1]));
595  faces_.push_back(static_cast<typename Node::index_type>(a[2]));
596  return static_cast<typename Elem::index_type>((faces_.size() - 1) / 3);
597  }
598 
599 
600  void node_reserve(size_type s) { points_.reserve(static_cast<size_t>(s)); }
601  void elem_reserve(size_type s) { faces_.reserve(static_cast<size_t>(s*3)); }
602  void resize_nodes(size_type s) { points_.resize(static_cast<size_t>(s)); }
603  void resize_elems(size_type s) { faces_.resize(static_cast<size_t>(s*3)); }
604 
605  /// Get the local coordinates for a certain point within an element
606  /// This function uses a couple of newton iterations to find the local
607  /// coordinate of a point
608  template<class VECTOR, class INDEX>
609  bool get_coords(VECTOR &coords, const Core::Geometry::Point &p, INDEX idx) const
610  {
611  ElemData ed(*this, idx);
612  return basis_.get_coords(coords, p, ed);
613  }
614 
615  /// Find the location in the global coordinate system for a local coordinate
616  /// This function is the opposite of get_coords.
617  template<class VECTOR, class INDEX>
618  void interpolate(Core::Geometry::Point &pt, VECTOR &coords, INDEX idx) const
619  {
620  ElemData ed(*this, idx);
621  pt = basis_.interpolate(coords, ed);
622  }
623 
624  /// Interpolate the derivate of the function, This infact will return the
625  /// jacobian of the local to global coordinate transformation. This function
626  /// is mainly intended for the non linear elements
627  template<class VECTOR1, class INDEX, class VECTOR2>
628  void derivate(const VECTOR1 &coords, INDEX idx, VECTOR2 &J) const
629  {
630  ElemData ed(*this, idx);
631  basis_.derivate(coords, ed, J);
632  }
633 
634  /// Get the determinant of the jacobian, which is the local volume of an element
635  /// and is intended to help with the integration of functions over an element.
636  template<class VECTOR, class INDEX>
637  double det_jacobian(const VECTOR& coords, INDEX idx) const
638  {
639  double J[9];
640  jacobian(coords,idx,J);
641  return (DetMatrix3x3(J));
642  }
643 
644  /// Get the jacobian of the transformation. In case one wants the non inverted
645  /// version of this matrix. This is currently here for completeness of the
646  /// interface
647  template<class VECTOR, class INDEX>
648  void jacobian(const VECTOR& coords, INDEX idx, double* J) const
649  {
651  ElemData ed(*this,idx);
652  basis_.derivate(coords,ed,Jv);
653  Core::Geometry::Vector Jv2 = Cross(Vector(Jv[0]), Vector(Jv[1]));
654  Jv2.normalize();
655  J[0] = Jv[0].x();
656  J[1] = Jv[0].y();
657  J[2] = Jv[0].z();
658  J[3] = Jv[1].x();
659  J[4] = Jv[1].y();
660  J[5] = Jv[1].z();
661  J[6] = Jv2.x();
662  J[7] = Jv2.y();
663  J[8] = Jv2.z();
664  }
665 
666  /// Get the inverse jacobian of the transformation. This one is needed to
667  /// translate local gradients into global gradients. Hence it is crucial for
668  /// calculating gradients of fields, or constructing finite elements.
669  template<class VECTOR, class INDEX>
670  double inverse_jacobian(const VECTOR& coords, INDEX idx, double* Ji) const
671  {
673  ElemData ed(*this,idx);
674  basis_.derivate(coords,ed,Jv);
675  Jv.resize(3);
676  Core::Geometry::Vector v = Cross(Vector(Jv[0]), Vector(Jv[1])); v.normalize();
677  Jv[2] = v.asPoint();
678 
679  return (InverseMatrix3P(Jv,Ji));
680  }
681 
682  template<class INDEX>
683  double scaled_jacobian_metric(INDEX idx) const
684  {
686  ElemData ed(*this,idx);
687 
688  double temp;
689 
690  Core::Geometry::Point p0, p1, p2;
691  typename Node::array_type nodes;
692  get_nodes(nodes,idx);
693  get_center(p0,nodes[0]);
694  get_center(p1,nodes[1]);
695  get_center(p2,nodes[2]);
696 
697  double l1 = (p0-p1).length();
698  double l2 = (p1-p2).length();
699  double l3 = (p2-p0).length();
700 
701  double max_scale = l1*l2;
702  if (l2*l3 > max_scale) max_scale = l2*l3;
703  if (l1*l3 > max_scale) max_scale = l1*l3;
704 
705  basis_.derivate(basis_.unit_center,ed,Jv);
706  Jv.resize(3);
707  Core::Geometry::Vector v = Cross(Vector(Jv[0]), Vector(Jv[1])); v.normalize();
708  Jv[2] = v.asPoint();
709  double min_jacobian = DetMatrix3P(Jv);
710  size_t num_vertices = basis_.number_of_vertices();
711  for (size_t j=0;j < num_vertices;j++)
712  {
713  basis_.derivate(basis_.unit_vertices[j],ed,Jv);
714  Jv.resize(3);
715  v = Cross(Vector(Jv[0]), Vector(Jv[1])); v.normalize();
716  Jv[2] = v.asPoint();
717  temp = DetMatrix3P(Jv);
718  if(temp < min_jacobian) min_jacobian = temp;
719  }
720 
721  return (min_jacobian/max_scale);
722  }
723 
724 
725  template<class INDEX>
726  double jacobian_metric(INDEX idx) const
727  {
729  ElemData ed(*this,idx);
730 
731  double temp;
732 
733  basis_.derivate(basis_.unit_center,ed,Jv);
734  Jv.resize(3);
735  Core::Geometry::Vector v = Cross(Vector(Jv[0]), Vector(Jv[1]));
736  v.normalize();
737  Jv[2] = v.asPoint();
738  double min_jacobian = DetMatrix3P(Jv);
739 
740  size_t num_vertices = basis_.number_of_vertices();
741  for (size_t j=0;j < num_vertices;j++)
742  {
743  basis_.derivate(basis_.unit_vertices[j],ed,Jv);
744  Jv.resize(3);
745  v = Cross(Vector(Jv[0]), Vector(Jv[1])); v.normalize();
746  Jv[2] = v.asPoint();
747  temp = DetMatrix3P(Jv);
748  if(temp < min_jacobian) min_jacobian = temp;
749  }
750 
751  return (min_jacobian);
752  }
753 
754 
755  template <class INDEX>
756  bool find_closest_node(double& pdist, Core::Geometry::Point &result,
757  INDEX &node, const Core::Geometry::Point &p) const
758  {
759  return(find_closest_node(pdist,result,node,p,-1.0));
760  }
761 
762  template <class INDEX>
763  bool find_closest_node(double& pdist, Core::Geometry::Point &result,
764  INDEX &node, const Core::Geometry::Point &p, double maxdist) const
765  {
766  if (maxdist < 0.0) maxdist = DBL_MAX; else maxdist = maxdist*maxdist;
767  typename Node::size_type sz; size(sz);
768 
769  /// If there are no nodes we cannot find the closest one
770  if (sz == 0) return (false);
771 
772  if (node >= 0 && node < sz)
773  {
774  Core::Geometry::Point point = points_[node];
775  double dist = (p-point).length2();
776 
777  if ( dist < epsilon2_ )
778  {
779  result = point;
780  pdist = sqrt(dist);
781  return (true);
782  }
783  }
784 
785  ASSERTMSG(synchronized_ & Mesh::NODE_LOCATE_E,
786  "TriSurfMesh::find_closest_node requires synchronize(NODE_LOCATE_E).")
787 
788  // get grid sizes
789  const size_type ni = node_grid_->get_ni()-1;
790  const size_type nj = node_grid_->get_nj()-1;
791  const size_type nk = node_grid_->get_nk()-1;
792 
793  // Convert to grid coordinates.
794  index_type bi, bj, bk, ei, ej, ek;
795  node_grid_->unsafe_locate(bi, bj, bk, p);
796 
797  // Clamp to closest point on the grid.
798  if (bi > ni) bi = ni; if (bi < 0) bi = 0;
799  if (bj > nj) bj = nj; if (bj < 0) bj = 0;
800  if (bk > nk) bk = nk; if (bk < 0) bk = 0;
801 
802  ei = bi; ej = bj; ek = bk;
803 
804  double dmin = maxdist;
805  bool found = true;
806  bool found_one = false;
807  do
808  {
809  found = true;
810  /// This looks incorrect - but it is correct
811  /// We need to do a full shell without any elements that are closer
812  /// to make sure there no closer elements in neighboring searchgrid cells
813 
814  for (index_type i = bi; i <= ei; i++)
815  {
816  if (i < 0 || i > ni) continue;
817  for (index_type j = bj; j <= ej; j++)
818  {
819  if (j < 0 || j > nj) continue;
820  for (index_type k = bk; k <= ek; k++)
821  {
822  if (k < 0 || k > nk) continue;
823  if (i == bi || i == ei || j == bj || j == ej || k == bk || k == ek)
824  {
825  if (node_grid_->min_distance_squared(p, i, j, k) < dmin)
826  {
827  found = false;
828  typename SearchGridT<index_type>::iterator it, eit;
829  node_grid_->lookup_ijk(it, eit, i, j, k);
830 
831  while (it != eit)
832  {
833  const Core::Geometry::Point point = points_[*it];
834  const double dist = (p-point).length2();
835 
836  if (dist < dmin)
837  {
838  found_one = true;
839  result = point;
840  node = INDEX(*it);
841  dmin = dist;
842 
843  /// If we are closer than eps^2 we found a node close enough
844  if (dmin < epsilon2_)
845  {
846  pdist = sqrt(dmin);
847  return (true);
848  }
849  }
850  ++it;
851  }
852  }
853  }
854  }
855  }
856  }
857  bi--;ei++;
858  bj--;ej++;
859  bk--;ek++;
860  }
861  while (!found) ;
862 
863  if (!found_one) return (false);
864 
865  pdist = sqrt(dmin);
866  return (true);
867  }
868 
869  template <class ARRAY>
870  bool find_closest_nodes(ARRAY &nodes, const Core::Geometry::Point &p, double maxdist) const
871  {
872  nodes.clear();
873 
874  ASSERTMSG(synchronized_ & Mesh::NODE_LOCATE_E,
875  "TriSurfMesh::find_closest_node requires synchronize(NODE_LOCATE_E).")
876 
877  // get grid sizes
878  const size_type ni = node_grid_->get_ni()-1;
879  const size_type nj = node_grid_->get_nj()-1;
880  const size_type nk = node_grid_->get_nk()-1;
881 
882  // Convert to grid coordinates.
883  index_type bi, bj, bk, ei, ej, ek;
884 
885  Core::Geometry::Point max = p+Core::Geometry::Vector(maxdist,maxdist,maxdist);
886  Core::Geometry::Point min = p+Core::Geometry::Vector(-maxdist,-maxdist,-maxdist);
887 
888  node_grid_->unsafe_locate(bi, bj, bk, min);
889  node_grid_->unsafe_locate(ei, ej, ek, max);
890 
891  // Clamp to closest point on the grid.
892  if (bi > ni) bi = ni; if (bi < 0) bi = 0;
893  if (bj > nj) bj = nj; if (bj < 0) bj = 0;
894  if (bk > nk) bk = nk; if (bk < 0) bk = 0;
895 
896  if (ei > ni) ei = ni; if (ei < 0) ei = 0;
897  if (ej > nj) ej = nj; if (ej < 0) ej = 0;
898  if (ek > nk) ek = nk; if (ek < 0) ek = 0;
899 
900  double maxdist2 = maxdist*maxdist;
901 
902  for (index_type i = bi; i <= ei; i++)
903  {
904  for (index_type j = bj; j <= ej; j++)
905  {
906  for (index_type k = bk; k <= ek; k++)
907  {
908  if (node_grid_->min_distance_squared(p, i, j, k) < maxdist2)
909  {
910  typename SearchGridT<index_type>::iterator it, eit;
911  node_grid_->lookup_ijk(it, eit, i, j, k);
912 
913  while (it != eit)
914  {
915  const Core::Geometry::Point point = points_[*it];
916  const double dist = (p-point).length2();
917 
918  if (dist < maxdist2)
919  {
920  nodes.push_back(*it);
921  }
922  ++it;
923  }
924  }
925  }
926  }
927  }
928 
929  return(nodes.size() > 0);
930  }
931 
932 
933  template <class ARRAY1, class ARRAY2>
934  bool find_closest_nodes(ARRAY1 &distances, ARRAY2 &nodes, const Core::Geometry::Point &p, double maxdist) const
935  {
936  nodes.clear();
937  distances.clear();
938 
939  ASSERTMSG(synchronized_ & Mesh::NODE_LOCATE_E,
940  "TriSurfMesh::find_closest_node requires synchronize(NODE_LOCATE_E).")
941 
942  // get grid sizes
943  const size_type ni = node_grid_->get_ni()-1;
944  const size_type nj = node_grid_->get_nj()-1;
945  const size_type nk = node_grid_->get_nk()-1;
946 
947  // Convert to grid coordinates.
948  index_type bi, bj, bk, ei, ej, ek;
949 
950  Core::Geometry::Point max = p+Core::Geometry::Vector(maxdist,maxdist,maxdist);
951  Core::Geometry::Point min = p+Core::Geometry::Vector(-maxdist,-maxdist,-maxdist);
952 
953  node_grid_->unsafe_locate(bi, bj, bk, min);
954  node_grid_->unsafe_locate(ei, ej, ek, max);
955 
956  // Clamp to closest point on the grid.
957  if (bi > ni) bi = ni; if (bi < 0) bi = 0;
958  if (bj > nj) bj = nj; if (bj < 0) bj = 0;
959  if (bk > nk) bk = nk; if (bk < 0) bk = 0;
960 
961  if (ei > ni) ei = ni; if (ei < 0) ei = 0;
962  if (ej > nj) ej = nj; if (ej < 0) ej = 0;
963  if (ek > nk) ek = nk; if (ek < 0) ek = 0;
964 
965  double maxdist2 = maxdist*maxdist;
966 
967  for (index_type i = bi; i <= ei; i++)
968  {
969  for (index_type j = bj; j <= ej; j++)
970  {
971  for (index_type k = bk; k <= ek; k++)
972  {
973  if (node_grid_->min_distance_squared(p, i, j, k) < maxdist2)
974  {
975  typename SearchGridT<index_type>::iterator it, eit;
976  node_grid_->lookup_ijk(it, eit, i, j, k);
977 
978  while (it != eit)
979  {
980  const Core::Geometry::Point point = points_[*it];
981  const double dist = (p-point).length2();
982 
983  if (dist < maxdist2)
984  {
985  nodes.push_back(*it);
986  distances.push_back(dist);
987  }
988  ++it;
989  }
990  }
991  }
992  }
993  }
994 
995  return(nodes.size() > 0);
996  }
997 
998 
999  /// This function will find the closest element and the location on that
1000  /// element that is the closest
1001  template <class INDEX, class ARRAY>
1002  bool find_closest_elem(double& pdist,
1003  Core::Geometry::Point &result,
1004  ARRAY &coords,
1005  INDEX &face,
1006  const Core::Geometry::Point &p) const
1007  {
1008  return (find_closest_elem(pdist,result,coords,face,p,-1.0));
1009  }
1010 
1011  /// This function will find the closest element and the location on that
1012  /// element that is the closest
1013  template <class INDEX, class ARRAY>
1014  bool find_closest_elem(double& pdist,
1015  Core::Geometry::Point &result,
1016  ARRAY &coords,
1017  INDEX &face,
1018  const Core::Geometry::Point &p,
1019  double maxdist) const
1020  {
1021  if (maxdist < 0.0) maxdist = DBL_MAX; else maxdist = maxdist*maxdist;
1022  typename Elem::size_type sz; size(sz);
1023 
1024  /// If there are no nodes we cannot find the closest one
1025  if (sz == 0) return (false);
1026 
1027  /// Test the one in face that is an initial guess
1028  if (face >= 0 && face < sz)
1029  {
1030  index_type idx = face*3;
1031  closest_point_on_tri(result, p, points_[faces_[idx]],
1032  points_[faces_[idx+1]], points_[faces_[idx+2]]);
1033  double dist = (p-result).length2();
1034  if ( dist < epsilon2_ )
1035  {
1036  pdist = sqrt(dist);
1037 
1038  ElemData ed(*this,face);
1039  basis_.get_coords(coords,result,ed);
1040  return (true);
1041  }
1042  }
1043 
1044  ASSERTMSG(synchronized_ & Mesh::ELEM_LOCATE_E,
1045  "TriSurfMesh::find_closest_elem requires synchronize(ELEM_LOCATE_E).")
1046 
1047  // get grid sizes
1048  const size_type ni = elem_grid_->get_ni()-1;
1049  const size_type nj = elem_grid_->get_nj()-1;
1050  const size_type nk = elem_grid_->get_nk()-1;
1051 
1052  // Convert to grid coordinates.
1053  index_type bi, ei, bj, ej, bk, ek;
1054  elem_grid_->unsafe_locate(bi, bj, bk, p);
1055 
1056  // Clamp to closest point on the grid.
1057  if (bi > ni) bi = ni; if (bi < 0) bi = 0;
1058  if (bj > nj) bj = nj; if (bj < 0) bj = 0;
1059  if (bk > nk) bk = nk; if (bk < 0) bk = 0;
1060 
1061  ei = bi; ej = bj; ek = bk;
1062 
1063  double dmin = maxdist;
1064  bool found = true;
1065  bool found_one = false;
1066 
1067  do
1068  {
1069  found = true;
1070  /// We need to do a full shell without any elements that are closer
1071  /// to make sure there no closer elements in neighboring searchgrid cells
1072  for (index_type i = bi; i <= ei; i++)
1073  {
1074  if (i < 0 || i > ni) continue;
1075  for (index_type j = bj; j <= ej; j++)
1076  {
1077  if (j < 0 || j > nj) continue;
1078  for (index_type k = bk; k <= ek; k++)
1079  {
1080  if (k < 0 || k > nk) continue;
1081  if (i == bi || i == ei || j == bj || j == ej || k == bk || k == ek)
1082  {
1083  if (elem_grid_->min_distance_squared(p, i, j, k) < dmin)
1084  {
1085  found = false;
1086  typename SearchGridT<index_type>::iterator it, eit;
1087  elem_grid_->lookup_ijk(it,eit, i, j, k);
1088 
1089  while (it != eit)
1090  {
1092  index_type idx = (*it) * 3;
1093  closest_point_on_tri(r, p,
1094  points_[faces_[idx ]],
1095  points_[faces_[idx+1]],
1096  points_[faces_[idx+2]]);
1097  const double dtmp = (p - r).length2();
1098  if (dtmp < dmin)
1099  {
1100  found_one = true;
1101  result = r;
1102  face = INDEX(*it);
1103  dmin = dtmp;
1104 
1105  if (dmin < epsilon2_)
1106  {
1107  pdist = sqrt(dmin);
1108 
1109  ElemData ed(*this,face);
1110  basis_.get_coords(coords,result,ed);
1111  return (true);
1112  }
1113  }
1114 
1115  ++it;
1116  }
1117  }
1118  }
1119  }
1120  }
1121  }
1122  bi--;ei++;
1123  bj--;ej++;
1124  bk--;ek++;
1125  }
1126  while (!found) ;
1127 
1128  ElemData ed(*this,face);
1129  basis_.get_coords(coords,result,ed);
1130 
1131  if (!found_one) return (false);
1132 
1133  pdist = sqrt(dmin);
1134  return (true);
1135  }
1136 
1137 
1138  template <class INDEX>
1139  bool find_closest_elem(double& pdist,
1140  Core::Geometry::Point &result,
1141  INDEX &elem,
1142  const Core::Geometry::Point &p) const
1143  {
1144  StackVector<double,2> coords;
1145  return(find_closest_elem(pdist,result,coords,elem,p,-1.0));
1146  }
1147 
1148 
1149 
1150  template <class INDEX>
1151  inline bool search_node(INDEX &loc, const Core::Geometry::Point &p) const
1152  {
1153  typename Node::iterator ni, nie;
1154  begin(ni);
1155  end(nie);
1156 
1157 
1158  if (ni == nie)
1159  {
1160  return false;
1161  }
1162 
1163  double min_dist = (p - points_[*ni]).length2();
1164  loc = static_cast<INDEX>(*ni);
1165  ++ni;
1166 
1167  while (ni != nie)
1168  {
1169  const double dist = (p - points_[*ni]).length2();
1170  if (dist < min_dist)
1171  {
1172  min_dist = dist;
1173  loc = static_cast<INDEX>(*ni);
1174  }
1175  ++ni;
1176  }
1177  return true;
1178  }
1179 
1180  /// This function will return multiple elements if the closest point is
1181  /// located on a node or edge. All bordering elements are returned in that
1182  /// case.
1183  template<class ARRAY>
1184  bool find_closest_elems(double& pdist, Core::Geometry::Point &result,
1185  ARRAY &elems, const Core::Geometry::Point &p) const
1186  {
1187  elems.clear();
1188 
1189  typename Elem::size_type sz; size(sz);
1190 
1191  /// If there are no nodes we cannot find the closest one
1192  if (sz == 0) return (false);
1193 
1194  ASSERTMSG(synchronized_ & Mesh::ELEM_LOCATE_E,
1195  "TriSurfMesh::find_closest_elems requires synchronize(ELEM_LOCATE_E).")
1196 
1197  // get grid sizes
1198  const size_type ni = elem_grid_->get_ni()-1;
1199  const size_type nj = elem_grid_->get_nj()-1;
1200  const size_type nk = elem_grid_->get_nk()-1;
1201 
1202  // Convert to grid coordinates.
1203  index_type bi, ei, bj, ej, bk, ek;
1204  elem_grid_->unsafe_locate(bi, bj, bk, p);
1205 
1206  // Clamp to closest point on the grid.
1207  if (bi > ni) bi = ni; if (bi < 0) bi = 0;
1208  if (bj > nj) bj = nj; if (bj < 0) bj = 0;
1209  if (bk > nk) bk = nk; if (bk < 0) bk = 0;
1210 
1211  ei = bi; ej = bj; ek = bk;
1212 
1213  double dmin = DBL_MAX;
1214 
1215  bool found;
1216  do
1217  {
1218  found = true;
1219  /// This looks incorrect - but it is correct
1220  /// We need to do a full shell without any elements that are closer
1221  /// to make sure there no closer elements
1222  for (index_type i = bi; i <= ei; i++)
1223  {
1224  if (i < 0|| i > ni) continue;
1225  for (index_type j = bj; j <= ej; j++)
1226  {
1227  if (j < 0 || j > nj) continue;
1228  for (index_type k = bk; k <= ek; k++)
1229  {
1230  if (k < 0 || k > nk) continue;
1231  if (i == bi || i == ei || j == bj || j == ej || k == bk || k == ek)
1232  {
1233  if (elem_grid_->min_distance_squared(p, i, j, k) < dmin)
1234  {
1235  found = false;
1236  typename SearchGridT<index_type>::iterator it, eit;
1237  elem_grid_->lookup_ijk(it,eit, i, j, k);
1238 
1239  while (it != eit)
1240  {
1241  Core::Geometry::Point rtmp;
1242  index_type idx = (*it) * 3;
1243  closest_point_on_tri(rtmp, p,
1244  points_[faces_[idx ]],
1245  points_[faces_[idx+1]],
1246  points_[faces_[idx+2]]);
1247  const double dtmp = (p - rtmp).length2();
1248 
1249  if (dtmp < dmin - epsilon2_)
1250  {
1251  elems.clear();
1252  result = rtmp;
1253  elems.push_back(typename ARRAY::value_type(*it));
1254  found = false;
1255  dmin = dtmp;
1256  }
1257  else if (dtmp < dmin + epsilon2_)
1258  {
1259  elems.push_back(typename ARRAY::value_type(*it));
1260  }
1261  ++it;
1262  }
1263  }
1264  }
1265  }
1266  }
1267  }
1268  bi--;ei++;
1269  bj--;ej++;
1270  bk--;ek++;
1271  }
1272  while ((!found)||(dmin == DBL_MAX)) ;
1273 
1274  pdist = sqrt(dmin);
1275  return (true);
1276  }
1277 
1278 
1279  double get_epsilon() const
1280  { return (epsilon_); }
1281 
1282  ///////////////////////////////////////////////////
1283  // STATIC VARIABLES AND FUNCTIONS
1284  /// Export this class using the old Pio system
1285  virtual void io(Piostream&);
1286 
1287  /// This ID is created as soon as this class will be instantiated
1289  /// Core functionality for getting the name of a templated mesh class
1290  static const std::string type_name(int n = -1);
1291  virtual std::string dynamic_type_name() const { return trisurf_typeid.type; }
1292  /// Type description, used for finding names of the mesh class for
1293  /// dynamic compilation purposes. Some of this should be obsolete
1294  virtual const TypeDescription *get_type_description() const;
1295  static const TypeDescription* node_type_description();
1296  static const TypeDescription* edge_type_description();
1297  static const TypeDescription* face_type_description();
1298  static const TypeDescription* cell_type_description();
1300  { return face_type_description(); }
1301 
1302  /// This function returns a maker for Pio.
1303  static Persistent *maker() { return new TriSurfMesh<Basis>(); }
1304  /// This function returns a handle for the virtual interface.
1305  static MeshHandle mesh_maker() { return boost::make_shared<TriSurfMesh<Basis>>(); }
1306 
1307 
1308  //////////////////////////////////////////////////////////////////
1309  // Mesh specific functions (these are not implemented in every mesh)
1310 
1311  // Extra functionality needed by this specific geometry.
1312  typename Node::index_type add_find_point(const Core::Geometry::Point &p,
1313  double err = 1.0e-3);
1314  typename Elem::index_type add_triangle(typename Node::index_type,
1315  typename Node::index_type,
1316  typename Node::index_type);
1317  typename Elem::index_type add_triangle(const Core::Geometry::Point& p0,
1318  const Core::Geometry::Point& p1,
1319  const Core::Geometry::Point& p2);
1320 
1321 
1322  /// swap the shared edge between 2 faces, if they share an edge.
1323  bool swap_shared_edge(typename Face::index_type, typename Face::index_type);
1324  bool remove_face(typename Face::index_type);
1325  bool remove_orphan_nodes();
1326  /// walk all the faces, enforcing consistent face orientations.
1327  void orient_faces();
1328  /// flip the orientaion of all the faces
1329  /// orient could make all faces face inward...
1330  void flip_faces();
1331  void flip_face(typename Face::index_type face);
1332 
1333 
1334  /// Subdivision Methods
1335  bool insert_node(const Core::Geometry::Point &p);
1336  void insert_node(typename Face::index_type face, const Core::Geometry::Point &p);
1337  void bisect_element(const typename Face::index_type);
1338 
1339  bool insert_node_in_edge_aux(typename Face::array_type &tris,
1340  typename Node::index_type &ni,
1341  index_type halfedge,
1342  const Core::Geometry::Point &p);
1343 
1344  bool insert_node_in_face_aux(typename Face::array_type &tris,
1345  typename Node::index_type &ni,
1346  typename Face::index_type face,
1347  const Core::Geometry::Point &p);
1348 
1349  bool insert_node_in_face(typename Face::array_type &tris,
1350  typename Node::index_type &ni,
1351  typename Face::index_type face,
1352  const Core::Geometry::Point &p);
1353 
1354 
1355 
1356  const Core::Geometry::Point &point(typename Node::index_type i) { return points_[i]; }
1357 
1358  // This one should be made obsolete
1359  bool get_neighbor(index_type &nbr_half_edge,
1360  index_type half_edge) const;
1361 
1362  void collapse_edges(const std::vector<index_type> &nodemap);
1363 
1364  // This function removes any triangles which happen to share one or
1365  // more exact nodes. It doesn't do an area test.
1366  void remove_obvious_degenerate_triangles();
1367 
1368 protected:
1369 
1370  //////////////////////////////////////////////////////////////
1371  // These functions are templates and are used to define the
1372  // dynamic compilation interface and the virtual interface
1373  // as they both use different datatypes as indices and arrays
1374  // the following functions have been templated and are inlined
1375  // at the places where they are needed.
1376  //
1377  // Secondly these templates allow for the use of the stack vector
1378  // as well as the STL vector. When an algorithm supports non linear
1379  // functions an STL vector is a better choice, in the other cases
1380  // often a StackVector is enough (The latter improves performance).
1381 
1382  template<class ARRAY, class INDEX>
1383  inline void get_nodes_from_edge(ARRAY& array, INDEX idx) const
1384  {
1385  ASSERTMSG(synchronized_ & Mesh::EDGES_E,
1386  "TriSurfMesh: Must call synchronize EDGES_E on TriSurfMesh first");
1387 
1388  index_type a = edges_[idx][0];
1389  index_type faceidx = a >> 2;
1390  index_type offset = a & 0x3;
1391  array.resize(2);
1392  if (offset == 0)
1393  {
1394  array[0] = static_cast<typename ARRAY::value_type>(faces_[faceidx*3]);
1395  array[1] = static_cast<typename ARRAY::value_type>(faces_[faceidx*3 + 1]);
1396  }
1397  else if (offset == 1)
1398  {
1399  array[0] = static_cast<typename ARRAY::value_type>(faces_[faceidx*3 + 1]);
1400  array[1] = static_cast<typename ARRAY::value_type>(faces_[faceidx*3 + 2]);
1401  }
1402  else
1403  {
1404  array[0] = static_cast<typename ARRAY::value_type>(faces_[faceidx*3 + 2]);
1405  array[1] = static_cast<typename ARRAY::value_type>(faces_[faceidx*3 ]);
1406  }
1407  }
1408 
1409 
1410  template<class ARRAY, class INDEX>
1411  inline void get_nodes_from_face(ARRAY& array, INDEX idx) const
1412  {
1413  array.resize(3);
1414  array[0] = static_cast<typename ARRAY::value_type>(faces_[idx * 3 + 0]);
1415  array[1] = static_cast<typename ARRAY::value_type>(faces_[idx * 3 + 1]);
1416  array[2] = static_cast<typename ARRAY::value_type>(faces_[idx * 3 + 2]);
1417  }
1418 
1419 
1420  template<class ARRAY, class INDEX>
1421  inline void get_nodes_from_elem(ARRAY& array, INDEX idx) const
1422  {
1423  get_nodes_from_face(array,idx);
1424  }
1425 
1426 
1427  template<class ARRAY, class INDEX>
1428  inline void get_edges_from_face(ARRAY& array, INDEX idx) const
1429  {
1430  ASSERTMSG(synchronized_ & Mesh::EDGES_E,
1431  "TriSurfMesh: Must call synchronize EDGES_E on TriSurfMesh first");
1432 
1433  array.resize(3);
1434 
1435  array[0] = static_cast<typename ARRAY::value_type>(halfedge_to_edge_[idx * 3 + 0]);
1436  array[1] = static_cast<typename ARRAY::value_type>(halfedge_to_edge_[idx * 3 + 1]);
1437  array[2] = static_cast<typename ARRAY::value_type>(halfedge_to_edge_[idx * 3 + 2]);
1438  }
1439 
1440  template<class ARRAY, class INDEX>
1441  inline void get_edges_from_elem(ARRAY& array, INDEX idx) const
1442  {
1443  get_edges_from_face(array,idx);
1444  }
1445 
1446 
1447  template<class ARRAY, class INDEX>
1448  inline void get_faces_from_node(ARRAY& array, INDEX idx) const
1449  {
1450  ASSERTMSG(synchronized_ & Mesh::NODE_NEIGHBORS_E,
1451  "TriSurfMesh: Must call synchronize NODE_NEIGHBORS_E on TriSurfMesh first");
1452 
1453  array.resize(node_neighbors_[idx].size());
1454  for (size_t i = 0; i < node_neighbors_[idx].size(); ++i)
1455  array[i] = static_cast<typename ARRAY::value_type>(node_neighbors_[idx][i]);
1456  }
1457 
1458 
1459  template<class ARRAY, class INDEX>
1460  inline void get_faces_from_edge(ARRAY& array, INDEX idx) const
1461  {
1462  ASSERTMSG(synchronized_ & Mesh::EDGES_E,
1463  "Must call synchronize EDGES_E on TriSurfMesh first");
1464 
1465  const std::vector<index_type>& faces = edges_[idx];
1466 
1467  // clear array
1468  array.clear();
1469  // conservative estimate
1470  array.reserve(faces.size());
1471 
1472  size_type fs = faces.size();
1473  for (index_type i=0; i<fs; i++)
1474  {
1475  array.push_back(faces[i]>>2);
1476  }
1477  }
1478 
1479 
1480  // Fixes bug #887 (gforge)
1481  template<class ARRAY, class INDEX>
1482  inline void get_edges_from_node(ARRAY& array, INDEX idx) const
1483  {
1484  ASSERTMSG(synchronized_ & Mesh::NODE_NEIGHBORS_E,
1485  "Must call synchronize NODE_NEIGHBORS_E on TriSurfMesh first");
1486 
1487  // Get the table of faces that are connected to the two nodes
1488  const std::vector<index_type>& faces = node_neighbors_[idx];
1489  array.clear();
1490 
1491  typename ARRAY::value_type edge;
1492  for (size_t i=0; i<faces.size(); i++)
1493  {
1494  for (index_type j=0; j<3; j++)
1495  {
1496  edge = halfedge_to_edge_[faces[i]*3+j];
1497  size_t k=0;
1498  for (; k<array.size(); k++)
1499  if (array[k] == edge) break;
1500  if (k == array.size()) array.push_back(edge);
1501  }
1502  }
1503  }
1504 
1505  template<class ARRAY, class INDEX>
1506  inline void get_edges_from_node_bugfix(ARRAY& array, INDEX idx) const
1507  {
1508  ASSERTMSG(synchronized_ & Mesh::NODE_NEIGHBORS_E,
1509  "Must call synchronize NODE_NEIGHBORS_E on TriSurfMesh first");
1510 
1511  array.clear();
1512  int n=edge_on_node_[idx].size();
1513  typename ARRAY::value_type edge;
1514  for(int i=0; i<n; i++)
1515  {
1516  edge = edge_on_node_[idx][i];
1517  size_t k=0;
1518  for (; k<array.size(); k++)
1519  if (array[k] == edge) break;
1520  if (k == array.size()) array.push_back(edge);
1521  }
1522  }
1523 
1524  template <class ARRAY, class INDEX>
1525  inline void set_nodes_by_elem(ARRAY &array, INDEX idx)
1526  {
1527  for (index_type n = 0; n < 3; ++n)
1528  faces_[idx * 3 + n] = static_cast<index_type>(array[n]);
1529  }
1530 
1531 
1532  /// This function has been rewritten to allow for non manifold surfaces to be
1533  /// handled ok.
1534  template <class INDEX1, class INDEX2>
1535  inline bool get_elem_neighbor(INDEX1 &neighbor, INDEX1 elem, INDEX2 delem) const
1536  {
1537  ASSERTMSG(synchronized_ & Mesh::EDGES_E,
1538  "Must call synchronize EDGES_E on TriSurfMesh first");
1539 
1540  const std::vector<index_type>& faces = edges_[delem];
1541 
1542  size_type fs = faces.size();
1543  for (index_type i=0; i<fs; i++)
1544  {
1545  index_type face = (faces[i]>>2);
1546  if (face != elem)
1547  {
1548  neighbor = face;
1549  return (true);
1550  }
1551  }
1552  return (false);
1553  }
1554 
1555  template <class ARRAY,class INDEX1, class INDEX2>
1556  inline bool get_elem_neighbors(ARRAY &array, INDEX1 elem, INDEX2 delem) const
1557  {
1558  ASSERTMSG(synchronized_ & Mesh::EDGES_E,
1559  "Must call synchronize EDGES_E on TriSurfMesh first");
1560 
1561  // Find the two nodes that make up the edge
1562  const std::vector<index_type>& faces = edges_[delem];
1563 
1564  // clear array
1565  array.clear();
1566 
1567  size_type fs = faces.size();
1568  for (index_type i=0; i<fs; i++)
1569  {
1570  index_type face = (faces[i]>>2);
1571  if (face != elem)
1572  {
1573  array.push_back(face);
1574  }
1575  }
1576 
1577  return (array.size() > 0);
1578  }
1579 
1580  template <class ARRAY, class INDEX>
1581  inline void get_elem_neighbors(ARRAY &array, INDEX idx) const
1582  {
1583  ASSERTMSG(synchronized_ & Mesh::EDGES_E,
1584  "Must call synchronize EDGES_E on TriSurfMesh first");
1585 
1586  typename Edge::array_type edges;
1587  get_edges_from_face(edges, idx);
1588 
1589  array.clear();
1590  array.reserve(edges.size());
1591 
1592  ARRAY nbor;
1593 
1594  size_type sz =static_cast<size_type>(edges.size());
1595  for (index_type i=0; i<sz; i++)
1596  {
1597  if (get_elem_neighbors(nbor, idx, edges[i]))
1598  {
1599  size_type nsz =static_cast<size_type>(nbor.size());
1600  for (index_type j=0; j<nsz; j++)
1601  array.push_back(nbor[j]);
1602  }
1603  }
1604  }
1605 
1606 
1607  template <class ARRAY, class INDEX>
1608  void get_node_neighbors(ARRAY &array, INDEX idx) const
1609  {
1610  ASSERTMSG(synchronized_ & Mesh::NODE_NEIGHBORS_E,
1611  "Must call synchronize NODE_NEIGHBORS_E on TriSurfMesh first");
1612  // clear old contents
1613  array.clear();
1614 
1615  // Get all the neighboring elements
1616  const std::vector<index_type>& faces = node_neighbors_[idx];
1617  // Make a conservative estimate of the number of node neighbors
1618  array.reserve(2*faces.size());
1619 
1620  for (size_t i=0;i<faces.size();i++)
1621  {
1622  index_type base = faces[i]*3;
1623  for (index_type j=0;j<3;j++)
1624  {
1625  if (faces_[base+j] == idx) continue;
1626  size_t k=0;
1627  for (;k<array.size();k++)
1628  if (static_cast<typename ARRAY::value_type>(faces_[base+j]) == array[k]) break;
1629  if (k==array.size())
1630  array.push_back(static_cast<typename ARRAY::value_type>(faces_[base+j]));
1631  }
1632  }
1633  }
1634 
1635  /// Locate a node inside the mesh using the lookup table
1636  template <class INDEX>
1637  inline bool locate_node(INDEX &node, const Core::Geometry::Point &p) const
1638  {
1639  typename Node::size_type sz; size(sz);
1640 
1641  /// If there are no nodes we cannot find a closest point
1642  if (sz == 0) return (false);
1643 
1644  /// Check first guess
1645  if (node >= 0 && node < sz)
1646  {
1647  if ((p - points_[node]).length2() < epsilon2_) return (true);
1648  }
1649 
1650 
1651  ASSERTMSG(synchronized_ & Mesh::NODE_LOCATE_E,
1652  "TriSurfMesh::locate_node requires synchronize(NODE_LOCATE_E).")
1653 
1654  // get grid sizes
1655  const size_type ni = node_grid_->get_ni()-1;
1656  const size_type nj = node_grid_->get_nj()-1;
1657  const size_type nk = node_grid_->get_nk()-1;
1658 
1659  // Convert to grid coordinates.
1660  index_type bi, bj, bk, ei, ej, ek;
1661  node_grid_->unsafe_locate(bi, bj, bk, p);
1662 
1663  // Clamp to closest point on the grid.
1664  if (bi > ni) bi =ni; if (bi < 0) bi = 0;
1665  if (bj > nj) bj =nj; if (bj < 0) bj = 0;
1666  if (bk > nk) bk =nk; if (bk < 0) bk = 0;
1667 
1668  ei = bi;
1669  ej = bj;
1670  ek = bk;
1671 
1672  double dmin = DBL_MAX;
1673  bool found = true;
1674  do
1675  {
1676  found = true;
1677  /// This looks incorrect - but it is correct
1678  /// We need to do a full shell without any elements that are closer
1679  /// to make sure there no closer elements in neighboring searchgrid cells
1680 
1681  for (index_type i = bi; i <= ei; i++)
1682  {
1683  if (i < 0 || i > ni) continue;
1684  for (index_type j = bj; j <= ej; j++)
1685  {
1686  if (j < 0 || j > nj) continue;
1687  for (index_type k = bk; k <= ek; k++)
1688  {
1689  if (k < 0 || k > nk) continue;
1690  if (i == bi || i == ei || j == bj || j == ej || k == bk || k == ek)
1691  {
1692  if (node_grid_->min_distance_squared(p, i, j, k) < dmin)
1693  {
1694  found = false;
1696  node_grid_->lookup_ijk(it, eit, i, j, k);
1697 
1698  while (it != eit)
1699  {
1700  const Core::Geometry::Point point = points_[*it];
1701  const double dist = (p-point).length2();
1702 
1703  if (dist < dmin)
1704  {
1705  node = INDEX(*it);
1706  dmin = dist;
1707 
1708  if (dist < epsilon2_) return (true);
1709  }
1710  ++it;
1711  }
1712  }
1713  }
1714  }
1715  }
1716  }
1717  bi--;ei++;
1718  bj--;ej++;
1719  bk--;ek++;
1720  }
1721  while ((!found)||(dmin == DBL_MAX)) ;
1722 
1723  return (true);
1724  }
1725 
1726 
1727  /// Locate an edge inside the mesh using the lookup table
1728  /// This currently an exhaustive search
1729  template <class INDEX>
1730  inline bool locate_edge(INDEX &loc, const Core::Geometry::Point &p) const
1731  {
1732  ASSERTMSG(synchronized_ & Mesh::EDGES_E,
1733  "Must call synchronize EDGES_E on TriSurfMesh first");
1734 
1735  typename Edge::iterator bi, ei;
1736  typename Node::array_type nodes;
1737  begin(bi);
1738  end(ei);
1739 
1740  bool found = false;
1741  double mindist = 0.0;
1742  while (bi != ei)
1743  {
1744  get_nodes(nodes,*bi);
1745  const double dist = distance_to_line2(p, points_[nodes[0]],
1746  points_[nodes[1]],epsilon_);
1747  if (!found || dist < mindist)
1748  {
1749  loc = static_cast<INDEX>(*bi);
1750  mindist = dist;
1751  found = true;
1752  }
1753  ++bi;
1754  }
1755  return (found);
1756  }
1757 
1758 
1759  /// Locate an element inside the mesh using the lookup table
1760  template <class INDEX>
1761  inline bool locate_elem(INDEX &elem, const Core::Geometry::Point &p) const
1762  {
1763  if (basis_.polynomial_order() > 1) return elem_locate(elem, *this, p);
1764 
1765  typename Elem::size_type sz; size(sz);
1766 
1767  /// If there are no nodes we cannot find a closest point
1768  if (sz == 0) return (false);
1769 
1770  /// Check whether the estimate given in idx is the point we are looking for
1771  if ((elem > 0)&&(elem < sz))
1772  {
1773  if (inside3_p(elem*3,p)) return (true);
1774  }
1775 
1776  ASSERTMSG(synchronized_ & Mesh::ELEM_LOCATE_E,
1777  "TriSurfMesh::locate_elem requires synchronize(ELEM_LOCATE_E).")
1778 
1779  typename SearchGridT<index_type>::iterator it, eit;
1780  if (elem_grid_->lookup(it, eit, p))
1781  {
1782  while (it != eit)
1783  {
1784  if (inside3_p((*it) * 3, p))
1785  {
1786  elem = static_cast<INDEX>(*it);
1787  return (true);
1788  }
1789  ++it;
1790  }
1791  }
1792  return (false);
1793  }
1794 
1795  template <class ARRAY>
1796  inline bool locate_elems(ARRAY &array, const Core::Geometry::BBox &b) const
1797  {
1798 
1799  ASSERTMSG(synchronized_ & Mesh::ELEM_LOCATE_E,
1800  "TriSurfMesh::locate_elems requires synchronize(ELEM_LOCATE_E).")
1801 
1802  array.clear();
1803  index_type is,js,ks;
1804  index_type ie,je,ke;
1805  elem_grid_->locate_clamp(is,js,ks,b.min());
1806  elem_grid_->locate_clamp(ie,je,ke,b.max());
1807  for (index_type i=is; i<=ie;i++)
1808  for (index_type j=js; j<je;j++)
1809  for (index_type k=ks; k<ke; k++)
1810  {
1811  typename SearchGridT<index_type>::iterator it, eit;
1812  elem_grid_->lookup_ijk(it, eit, i, j, k);
1813  while (it != eit)
1814  {
1815  size_t p=0;
1816  for (;p<array.size();p++) if (array[p] == typename ARRAY::value_type(*it)) break;
1817  if (p == array.size()) array.push_back(typename ARRAY::value_type(*it));
1818  ++it;
1819  }
1820  }
1821 
1822  return (array.size() > 0);
1823  }
1824 
1825  template <class INDEX, class ARRAY>
1826  inline bool locate_elem(INDEX &elem, ARRAY &coords, const Core::Geometry::Point &p) const
1827  {
1828  if (basis_.polynomial_order() > 1) return elem_locate(elem, *this, p);
1829 
1830  typename Elem::size_type sz; size(sz);
1831 
1832  /// If there are no nodes we cannot find a closest point
1833  if (sz == 0) return (false);
1834 
1835  /// Check whether the estimate given in idx is the point we are looking for
1836  if ((elem > 0)&&(elem < sz))
1837  {
1838  if (inside3_p(elem*3,p))
1839  {
1840  ElemData ed(*this, elem);
1841  basis_.get_coords(coords, p, ed);
1842  return (true);
1843  }
1844  }
1845 
1846  ASSERTMSG(synchronized_ & Mesh::ELEM_LOCATE_E,
1847  "TriSurfMesh::locate_node requires synchronize(ELEM_LOCATE_E).")
1848 
1849  typename SearchGridT<index_type>::iterator it, eit;
1850  if (elem_grid_->lookup(it, eit, p))
1851  {
1852  while (it != eit)
1853  {
1854  if (inside3_p((*it) * 3, p))
1855  {
1856  elem = static_cast<INDEX>(*it);
1857  ElemData ed(*this, elem);
1858  basis_.get_coords(coords, p, ed);
1859  return (true);
1860  }
1861  ++it;
1862  }
1863  }
1864  return (false);
1865  }
1866 
1867 
1868 
1869  template <class INDEX>
1870  void get_node_center(Core::Geometry::Point &p, INDEX idx) const
1871  {
1872  p = points_[idx];
1873  }
1874 
1875 
1876  template <class INDEX>
1877  void get_edge_center(Core::Geometry::Point &result, INDEX idx) const
1878  {
1879  typename Node::array_type arr;
1880  get_nodes_from_edge(arr, idx);
1881  result = points_[arr[0]];
1882  result += points_[arr[1]];
1883  result *= 0.5;
1884  }
1885 
1886 
1887  template <class INDEX>
1888  void get_face_center(Core::Geometry::Point &result, INDEX idx) const
1889  {
1890  // NEED TO OPTIMIZE THIS ONE
1891  typename Node::array_type arr;
1892  get_nodes_from_face(arr, idx);
1893  result = points_[arr[0]];
1894  result += points_[arr[1]];
1895  result += points_[arr[2]];
1896  result *= (1.0/3.0);
1897  }
1898 
1899 
1900  void walk_face_orient(typename Face::index_type face,
1901  std::vector<bool> &tested, std::vector<bool> &flip);
1902 
1903  // These require the synchronize_lock_ to be held before calling.
1904  void compute_normals();
1905  void compute_node_neighbors();
1906  void compute_edges();
1907  // Fixes bug #887 (gforge)
1908  void compute_edges_bugfix();
1909  void compute_edge_neighbors();
1910 
1911  void compute_node_grid();
1912  void compute_elem_grid();
1913  void compute_bounding_box();
1914 
1915  /// Used to recompute data for individual cells.
1916  void insert_elem_into_grid(typename Elem::index_type ci);
1917  void remove_elem_from_grid(typename Elem::index_type ci);
1918 
1919  void insert_node_into_grid(typename Node::index_type ci);
1920  void remove_node_from_grid(typename Node::index_type ci);
1921 
1922  void debug_test_edge_neighbors();
1923 
1924  bool inside3_p(index_type face_times_three, const Core::Geometry::Point &p) const;
1925 
1926  static index_type next(index_type i) { return ((i%3)==2) ? (i-2) : (i+1); }
1927  static index_type prev(index_type i) { return ((i%3)==0) ? (i+2) : (i-1); }
1928 
1929  /// Actual parameters
1930  std::vector<Core::Geometry::Point> points_; // Location of vertices
1931  std::vector<std::vector<index_type> > edges_; // edges->halfedge map
1932  std::vector<index_type> halfedge_to_edge_; // halfedge->edge map
1933  std::vector<index_type> faces_; // Connectivity of this mesh
1934  std::vector<index_type> edge_neighbors_; // Neighbor connectivity
1935  std::vector<Core::Geometry::Vector> normals_; // normalized per node normal.
1936  std::vector<std::vector<index_type> > node_neighbors_; // Node neighbor connectivity
1937  std::vector<std::vector<index_type> > edge_on_node_; // Edges emanating from a node
1938 
1939  boost::shared_ptr<SearchGridT<index_type> > node_grid_; // Lookup table for nodes
1940  boost::shared_ptr<SearchGridT<index_type> > elem_grid_; // Lookup table for elements
1941 
1942  // Lock and Condition Variable for hand shaking
1945 
1946  // Which tables have been computed
1948  // Which tables are currently being computed
1950 
1951  Basis basis_; // Interpolation basis
1952 
1954  double epsilon_; // Epsilon to use for computation 1e-8 of bbox diagonal
1955  double epsilon2_; // Square of epsilon
1956 
1957  boost::shared_ptr<VMesh> vmesh_; // Handle to virtual function table
1958 
1959 #ifdef HAVE_HASH_MAP
1960 
1961  struct edgehash
1962  {
1963  size_t operator()(const std::pair<index_type, index_type> &a) const
1964  {
1965 #if defined(__ECC) || defined(_MSC_VER)
1966  hash_compare<int> hasher;
1967 #else
1968  hash<int> hasher;
1969 #endif
1970  return hasher(static_cast<int>(hasher(a.first) + a.second));
1971  }
1972 #if defined(__ECC) || defined(_MSC_VER)
1973 
1974  static const size_t bucket_size = 4;
1975  static const size_t min_buckets = 8;
1976 
1977  bool operator()(const std::pair<index_type, index_type> &a, const std::pair<index_type, index_type> &b) const
1978  {
1979  return a.first < b.first || a.first == b.first && a.second < b.second;
1980  }
1981 #endif
1982  };
1983 
1984  struct edgecompare
1985  {
1986  bool operator()(const std::pair<index_type, index_type> &a, const std::pair<index_type, index_type> &b) const
1987  {
1988  return a.first == b.first && a.second == b.second;
1989  }
1990  };
1991 
1992 #else
1993 
1995  {
1996  bool operator()(const std::pair<index_type, index_type> &a, const std::pair<index_type, index_type> &b) const
1997  {
1998  return a.first < b.first || a.first == b.first && a.second < b.second;
1999  }
2000  };
2001 
2002 #endif
2003 
2004 #ifdef HAVE_HASH_MAP
2005 
2006 #if defined(__ECC) || defined(_MSC_VER)
2007  typedef hash_map<std::pair<index_type, index_type>, index_type, edgehash> EdgeMapType;
2008 #else
2009  typedef hash_map<std::pair<index_type, index_type>, index_type, edgehash, edgecompare> EdgeMapType;
2010 #endif
2011 
2012 #else
2013 
2014  typedef std::map<std::pair<index_type, index_type>, index_type, edgecompare> EdgeMapType;
2015 
2016 #endif
2017 
2018 #ifdef HAVE_HASH_MAP
2019 
2020 #if defined(__ECC) || defined(_MSC_VER)
2021  typedef hash_map<std::pair<index_type, index_type>, std::vector<index_type>, edgehash> EdgeMapType2;
2022 #else
2023  typedef hash_map<std::pair<index_type, index_type>, std::vector<index_type>, edgehash, edgecompare> EdgeMapType2;
2024 #endif
2025 
2026 #else
2027 
2028  typedef std::map<std::pair<index_type, index_type>, std::vector<index_type>, edgecompare> EdgeMapType2;
2029 
2030 #endif
2031 
2032 };
2033 
2034 
2035 struct less_int
2036 {
2037  bool operator()(const index_type s1, const index_type s2) const
2038  {
2039  return (s1 < s2);
2040  }
2041 };
2042 
2043 template <class Basis>
2044 PersistentTypeID
2046 
2047 template <class Basis>
2048 const std::string
2050 {
2051  ASSERT((n >= -1) && n <= 1);
2052  if (n == -1)
2053  {
2054  static const std::string name = TypeNameGenerator::make_template_id(type_name(0), type_name(1));
2055  return name;
2056  }
2057  else if (n == 0)
2058  {
2059  static const std::string nm("TriSurfMesh");
2060  return nm;
2061  }
2062  else
2063  {
2064  return find_type_name((Basis *)0);
2065  }
2066 }
2067 
2068 
2069 template <class Basis>
2071  : points_(0),
2072  faces_(0),
2073  edge_neighbors_(0),
2074  node_neighbors_(0),
2075  synchronize_lock_("TriSurfMesh lock"),
2076  synchronize_cond_("TriSurfMesh condition variable"),
2077  synchronized_(Mesh::NODES_E | Mesh::FACES_E | Mesh::CELLS_E),
2078  synchronizing_(0),
2079  epsilon_(0.0),
2080  epsilon2_(0.0)
2081 {
2082  DEBUG_CONSTRUCTOR("TriSurfMesh")
2083 
2084  /// Initialize the virtual interface when the mesh is created
2085  vmesh_.reset(CreateVTriSurfMesh(this));
2086 }
2087 
2088 
2089 template <class Basis>
2091  : Mesh(copy),
2092  points_(0),
2093  edges_(0),
2094  halfedge_to_edge_(0),
2095  faces_(0),
2096  edge_neighbors_(0),
2097  normals_(0),
2098  node_neighbors_(0),
2099  synchronize_lock_("TriSurfMesh lock"),
2100  synchronize_cond_("TriSurfMesh condition variable"),
2101  synchronized_(Mesh::NODES_E | Mesh::FACES_E | Mesh::CELLS_E),
2102  synchronizing_(0),
2103  epsilon_(0.0),
2104  epsilon2_(0.0)
2105 {
2106  DEBUG_CONSTRUCTOR("TriSurfMesh")
2107 
2108  /// We need to lock before we can copy these as these
2109  /// structures are generate dynamically when they are
2110  /// needed.
2111  copy.synchronize_lock_.lock();
2112 
2113  points_ = copy.points_;
2114 
2115  edges_ = copy.edges_;
2116  halfedge_to_edge_ = copy.halfedge_to_edge_;
2117  synchronized_ |= copy.synchronized_ & (Mesh::EDGES_E);
2118 
2119  faces_ = copy.faces_;
2120 
2121  edge_neighbors_ = copy.edge_neighbors_;
2122  synchronized_ |= copy.synchronized_ & Mesh::ELEM_NEIGHBORS_E;
2123 
2124  normals_ = copy.normals_;
2125  synchronized_ |= copy.synchronized_ & Mesh::NORMALS_E;
2126 
2127  node_neighbors_ = copy.node_neighbors_;
2128  synchronized_ |= copy.synchronized_ & Mesh::NODE_NEIGHBORS_E;
2129 
2130  copy.synchronize_lock_.unlock();
2131 
2132  /// Create a new virtual interface for this copy
2133  /// all pointers have changed hence create a new
2134  /// virtual interface class
2135  vmesh_.reset(CreateVTriSurfMesh(this));
2136 }
2137 
2138 
2139 template <class Basis>
2141 {
2142  DEBUG_DESTRUCTOR("TriSurfMesh")
2143 }
2144 
2145 
2146 
2147 template <class Basis>
2148 void
2150  typename Elem::index_type ei,
2151  FieldRNG &rng) const
2152 {
2153  // Fold the quad sample into a triangle.
2154  double u = rng();
2155  double v = rng();
2156  if (u + v > 1.0) { u = 1.0 - u; v = 1.0 - v; }
2157 
2158  // Compute the position of the random point.
2159  const Core::Geometry::Point& p0 = points_[faces_[ei*3+0]];
2160  const Core::Geometry::Point& p1 = points_[faces_[ei*3+1]];
2161  const Core::Geometry::Point& p2 = points_[faces_[ei*3+2]];
2162  p = p0+((p1-p0)*u)+((p2-p0)*v);
2163 
2164 }
2165 
2166 
2167 template <class Basis>
2170 {
2171  Core::Geometry::BBox result;
2172  typename Node::iterator ni, nie;
2173  begin(ni);
2174  end(nie);
2175  while (ni != nie)
2176  {
2177  result.extend(points_[*ni]);
2178  ++ni;
2179  }
2180  return (result);
2181 }
2182 
2183 template <class Basis>
2184 void
2186 {
2187  t.load_identity();
2188  Core::Geometry::BBox bbox = get_bounding_box();
2189  t.pre_scale(bbox.diagonal());
2191 }
2192 
2193 template <class Basis>
2194 void
2196 {
2197  synchronize_lock_.lock();
2198  std::vector<Core::Geometry::Point>::iterator itr = points_.begin();
2199  std::vector<Core::Geometry::Point>::iterator eitr = points_.end();
2200  while (itr != eitr)
2201  {
2202  *itr = t.project(*itr);
2203  ++itr;
2204  }
2205 
2206  if (bbox_.valid())
2207  {
2208  bbox_.reset();
2209 
2210  // Compute bounding box
2211  typename Node::iterator ni, nie;
2212  begin(ni);
2213  end(nie);
2214  while (ni != nie)
2215  {
2216  bbox_.extend(point(*ni));
2217  ++ni;
2218  }
2219 
2220  // Compute epsilons associated with the bounding box
2221  epsilon_ = bbox_.diagonal().length()*1e-8;
2222  epsilon2_ = epsilon_*epsilon_;
2223 
2224  synchronized_ |= Mesh::BOUNDING_BOX_E;
2225  }
2226 
2227  if (node_grid_) { node_grid_->transform(t); }
2228  if (elem_grid_) { elem_grid_->transform(t); }
2229 
2230  synchronize_lock_.unlock();
2231 }
2232 
2233 
2234 template <class Basis>
2235 void
2237 {
2238  ASSERTMSG(synchronized_ & Mesh::NODES_E,
2239  "Must call synchronize NODES_E on TriSurfMesh first");
2240  itr = 0;
2241 }
2242 
2243 
2244 template <class Basis>
2245 void
2247 {
2248  ASSERTMSG(synchronized_ & Mesh::NODES_E,
2249  "Must call synchronize NODES_E on TriSurfMesh first");
2250  itr = static_cast<index_type>(points_.size());
2251 }
2252 
2253 
2254 template <class Basis>
2255 void
2257 {
2258  ASSERTMSG(synchronized_ & Mesh::EDGES_E,
2259  "Must call synchronize EDGES_E on TriSurfMesh first");
2260  itr = 0;
2261 }
2262 
2263 
2264 template <class Basis>
2265 void
2267 {
2268  ASSERTMSG(synchronized_ & Mesh::EDGES_E,
2269  "Must call synchronize EDGES_E on TriSurfMesh first");
2270  itr = static_cast<index_type>(edges_.size());
2271 }
2272 
2273 
2274 template <class Basis>
2275 void
2277 {
2278  ASSERTMSG(synchronized_ & Mesh::FACES_E,
2279  "Must call synchronize FACES_E on TriSurfMesh first");
2280  itr = 0;
2281 }
2282 
2283 
2284 template <class Basis>
2285 void
2287 {
2288  ASSERTMSG(synchronized_ & Mesh::FACES_E,
2289  "Must call synchronize FACES_E on TriSurfMesh first");
2290  itr = static_cast<index_type>(faces_.size() / 3);
2291 }
2292 
2293 
2294 template <class Basis>
2295 void
2297 {
2298  ASSERTMSG(synchronized_ & Mesh::CELLS_E,
2299  "Must call synchronize CELLS_E on TriSurfMesh first");
2300  itr = 0;
2301 }
2302 
2303 
2304 template <class Basis>
2305 void
2307 {
2308  ASSERTMSG(synchronized_ & Mesh::CELLS_E,
2309  "Must call synchronize CELLS_E on TriSurfMesh first");
2310  itr = 0;
2311 }
2312 
2313 
2314 template <class Basis>
2315 int
2316 TriSurfMesh<Basis>::get_weights(const Core::Geometry::Point &p, typename Face::array_type &l,
2317  double *w)
2318 {
2319  typename Face::index_type idx;
2320  if (locate(idx, p))
2321  {
2322  l.resize(1);
2323  l[0] = idx;
2324  w[0] = 1.0;
2325  return 1;
2326  }
2327  return 0;
2328 }
2329 
2330 
2331 template <class Basis>
2332 int
2334  double *w)
2335 {
2336  typename Face::index_type idx;
2337  if (locate(idx, p))
2338  {
2339  get_nodes(l,idx);
2340  std::vector<double> coords(2);
2341  if (get_coords(coords, p, idx))
2342  {
2343  basis_.get_weights(coords, w);
2344  return basis_.dofs();
2345  }
2346  }
2347  return 0;
2348 }
2349 
2350 
2351 template <class Basis>
2352 bool
2354 {
2355  const Core::Geometry::Point &p0 = points_[faces_[i+0]];
2356  const Core::Geometry::Point &p1 = points_[faces_[i+1]];
2357  const Core::Geometry::Point &p2 = points_[faces_[i+2]];
2358  Core::Geometry::Vector v01(p0-p1);
2359  Core::Geometry::Vector v02(p0-p2);
2360  Core::Geometry::Vector v0(p0-p);
2361  Core::Geometry::Vector v1(p1-p);
2362  Core::Geometry::Vector v2(p2-p);
2363  const double a = Cross(v01, v02).length(); // area of the whole triangle (2x)
2364  const double a0 = Cross(v1, v2).length(); // area opposite p0
2365  const double a1 = Cross(v2, v0).length(); // area opposite p1
2366  const double a2 = Cross(v0, v1).length(); // area opposite p2
2367  const double s = a0+a1+a2;
2368 
2369  // For the point to be inside a triangle it must be inside one
2370  // of the four triangles that can be formed by using three of the
2371  // triangle vertices and the point in question.
2372  return fabs(s - a) < epsilon2_ && a > epsilon2_;
2373 }
2374 
2375 
2376 template <class Basis>
2377 bool
2379 {
2380  // Conversion table
2381  if (sync & (Mesh::DELEMS_E))
2382  { sync |= Mesh::EDGES_E; sync &= ~(Mesh::DELEMS_E); }
2383 
2384  if (sync & Mesh::FIND_CLOSEST_NODE_E)
2385  { sync |= NODE_LOCATE_E; sync &= ~(Mesh::FIND_CLOSEST_NODE_E); }
2386 
2387  if (sync & Mesh::FIND_CLOSEST_ELEM_E)
2388  { sync |= ELEM_LOCATE_E; sync &= ~(Mesh::FIND_CLOSEST_ELEM_E); }
2389 
2390  if (sync & (Mesh::NODE_LOCATE_E|Mesh::ELEM_LOCATE_E)) sync |= Mesh::BOUNDING_BOX_E;
2391  if (sync & Mesh::ELEM_NEIGHBORS_E) sync |= Mesh::EDGES_E;
2392 
2393  // Filter out the only tables available
2394  sync &= (Mesh::EDGES_E|Mesh::NORMALS_E|
2395  Mesh::NODE_NEIGHBORS_E|Mesh::BOUNDING_BOX_E|
2396  Mesh::ELEM_NEIGHBORS_E|
2397  Mesh::NODE_LOCATE_E|Mesh::ELEM_LOCATE_E);
2398 
2399  Core::Thread::UniqueLock lock(synchronize_lock_.get());
2400 
2401  // Only sync was hasn't been synched
2402  sync &= (~synchronized_);
2403 
2404  if (sync == Mesh::EDGES_E)
2405  {
2406  Synchronize Synchronize(this,sync);
2407  synchronize_lock_.unlock();
2408  Synchronize.run();
2409  synchronize_lock_.lock();
2410  }
2411  else if (sync & Mesh::EDGES_E)
2412  {
2413  mask_type tosync = Mesh::EDGES_E;
2414  Synchronize syncclass(this,tosync);
2415  boost::thread syncthread(syncclass);
2416  }
2417 
2418  if (sync == Mesh::NORMALS_E)
2419  {
2420  Synchronize Synchronize(this,sync);
2421  synchronize_lock_.unlock();
2422  Synchronize.run();
2423  synchronize_lock_.lock();
2424  }
2425  else if (sync & Mesh::NORMALS_E)
2426  {
2427  mask_type tosync = Mesh::NORMALS_E;
2428  Synchronize syncclass(this,tosync);
2429  boost::thread syncthread(syncclass);
2430  }
2431 
2432  if (sync == Mesh::NODE_NEIGHBORS_E)
2433  {
2434  Synchronize Synchronize(this,sync);
2435  synchronize_lock_.unlock();
2436  Synchronize.run();
2437  synchronize_lock_.lock();
2438  }
2439  else if (sync & Mesh::NODE_NEIGHBORS_E)
2440  {
2441  mask_type tosync = Mesh::NODE_NEIGHBORS_E;
2442  Synchronize syncclass(this,tosync);
2443  boost::thread syncthread(syncclass);
2444  }
2445 
2446  if (sync == Mesh::ELEM_NEIGHBORS_E)
2447  {
2448  Synchronize Synchronize(this,sync);
2449  synchronize_lock_.unlock();
2450  Synchronize.run();
2451  synchronize_lock_.lock();
2452  }
2453  else if (sync & Mesh::ELEM_NEIGHBORS_E)
2454  {
2455  mask_type tosync = Mesh::ELEM_NEIGHBORS_E;
2456  Synchronize syncclass(this,tosync);
2457  boost::thread syncthread(syncclass);
2458  }
2459 
2460  if (sync == Mesh::BOUNDING_BOX_E)
2461  {
2462  Synchronize Synchronize(this,sync);
2463  synchronize_lock_.unlock();
2464  Synchronize.run();
2465  synchronize_lock_.lock();
2466  }
2467  else if (sync & Mesh::BOUNDING_BOX_E)
2468  {
2469  mask_type tosync = Mesh::BOUNDING_BOX_E;
2470  Synchronize syncclass(this,tosync);
2471  boost::thread syncthread(syncclass);
2472  }
2473 
2474  if (sync == Mesh::NODE_LOCATE_E)
2475  {
2476  Synchronize Synchronize(this,sync);
2477  synchronize_lock_.unlock();
2478  Synchronize.run();
2479  synchronize_lock_.lock();
2480  }
2481  else if (sync & Mesh::NODE_LOCATE_E)
2482  {
2483  mask_type tosync = Mesh::NODE_LOCATE_E;
2484  Synchronize syncclass(this,tosync);
2485  boost::thread syncthread(syncclass);
2486  }
2487 
2488  if (sync == Mesh::ELEM_LOCATE_E)
2489  {
2490  Synchronize Synchronize(this,sync);
2491  synchronize_lock_.unlock();
2492  Synchronize.run();
2493  synchronize_lock_.lock();
2494  }
2495  else if (sync & Mesh::ELEM_LOCATE_E)
2496  {
2497  mask_type tosync = Mesh::ELEM_LOCATE_E;
2498  Synchronize syncclass(this,tosync);
2499  boost::thread syncthread(syncclass);
2500  }
2501 
2502  // Wait until threads are done
2503  while ((synchronized_ & sync) != sync)
2504  {
2505  synchronize_cond_.wait(lock);
2506  }
2507 
2508  return (true);
2509 }
2510 
2511 template <class Basis>
2512 bool
2514 {
2515  return (true);
2516 }
2517 
2518 template <class Basis>
2519 bool
2521 {
2522  synchronize_lock_.lock();
2523  // Undo marking the synchronization
2524  synchronized_ = Mesh::NODES_E | Mesh::ELEMS_E | Mesh::FACES_E | Mesh::CELLS_E;
2525 
2526  // Free memory where possible
2527 
2528  halfedge_to_edge_.clear();
2529  edge_neighbors_.clear();
2530  normals_.clear();
2531  edges_.clear();
2532  node_grid_.reset();
2533  elem_grid_.reset();
2534 
2535  synchronize_lock_.unlock();
2536  return (true);
2537 }
2538 
2539 
2540 
2541 template <class Basis>
2542 void
2544 {
2545  normals_.resize(points_.size()); // 1 per node
2546 
2547  // build table of faces that touch each node
2548  std::vector<std::vector<typename Face::index_type> > node_in_faces(points_.size());
2549  /// face normals (not normalized) so that magnitude is also the area.
2550  std::vector<Core::Geometry::Vector> face_normals(faces_.size());
2551  // Computing normal per face.
2552  typename Node::array_type nodes(3);
2553  typename Face::iterator iter, iter_end;
2554  begin(iter);
2555  end(iter_end);
2556  while (iter != iter_end)
2557  {
2558  get_nodes(nodes, *iter);
2559 
2560  Core::Geometry::Point p1, p2, p3;
2561  get_point(p1, nodes[0]);
2562  get_point(p2, nodes[1]);
2563  get_point(p3, nodes[2]);
2564  // build table of faces that touch each node
2565  node_in_faces[nodes[0]].push_back(*iter);
2566  node_in_faces[nodes[1]].push_back(*iter);
2567  node_in_faces[nodes[2]].push_back(*iter);
2568 
2569  Core::Geometry::Vector v0 = p2 - p1;
2570  Core::Geometry::Vector v1 = p3 - p2;
2571  Core::Geometry::Vector n = Cross(v0, v1);
2572  face_normals[*iter] = n;
2573  ++iter;
2574  }
2575 
2576  //Averaging the normals.
2577  typename std::vector<std::vector<typename Face::index_type> >::iterator nif_iter =
2578  node_in_faces.begin();
2579  index_type i = 0;
2580  while (nif_iter != node_in_faces.end())
2581  {
2582  const std::vector<typename Face::index_type> &v = *nif_iter;
2583  typename std::vector<typename Face::index_type>::const_iterator fiter =
2584  v.begin();
2585  Core::Geometry::Vector ave(0.L,0.L,0.L);
2586  while(fiter != v.end())
2587  {
2588  ave += face_normals[*fiter];
2589  ++fiter;
2590  }
2591  ave.safe_normalize();
2592  normals_[i] = ave; ++i;
2593  ++nif_iter;
2594  }
2595 
2596  synchronize_lock_.lock();
2597  synchronized_ |= Mesh::NORMALS_E;
2598  synchronize_lock_.unlock();
2599 }
2600 
2601 
2602 template <class Basis>
2603 void
2605 {
2606  const bool do_neighbors = synchronized_ & Mesh::ELEM_NEIGHBORS_E;
2607  const bool do_normals = false; // synchronized_ & NORMALS_E;
2608 
2609  typename Node::index_type pi = add_point(p);
2610  const index_type f0 = face*3;
2611  const index_type f1 = faces_.size();
2612  const index_type f2 = f1+3;
2613 
2614  synchronize_lock_.lock();
2615 
2616  faces_.push_back(faces_[f0+1]);
2617  faces_.push_back(faces_[f0+2]);
2618  faces_.push_back(pi);
2619 
2620  faces_.push_back(faces_[f0+2]);
2621  faces_.push_back(faces_[f0+0]);
2622  faces_.push_back(pi);
2623 
2624  // must do last
2625  faces_[f0+2] = pi;
2626 
2627  if (do_neighbors)
2628  {
2629  edge_neighbors_.push_back(edge_neighbors_[f0+1]);
2630  if (edge_neighbors_.back() != MESH_NO_NEIGHBOR)
2631  edge_neighbors_[edge_neighbors_.back()] = edge_neighbors_.size()-1;
2632  edge_neighbors_.push_back(f2+2);
2633  edge_neighbors_.push_back(f0+1);
2634 
2635  edge_neighbors_.push_back(edge_neighbors_[f0+2]);
2636  if (edge_neighbors_.back() != MESH_NO_NEIGHBOR)
2637  edge_neighbors_[edge_neighbors_.back()] = edge_neighbors_.size()-1;
2638  edge_neighbors_.push_back(f0+2);
2639  edge_neighbors_.push_back(f1+1);
2640 
2641  edge_neighbors_[f0+1] = f1+2;
2642  edge_neighbors_[f0+2] = f2+1;
2643  }
2644 
2645  if (do_normals)
2646  {
2648  normals_[faces_[f0]] +
2649  normals_[faces_[f1]] +
2650  normals_[faces_[f2]]);
2651  normal.safe_normalize();
2652  normals_.push_back(normals_[faces_[f1]]);
2653  normals_.push_back(normals_[faces_[f2]]);
2654  normals_.push_back(normal);
2655 
2656  normals_.push_back(normals_[faces_[f2]]);
2657  normals_.push_back(normals_[faces_[f0]]);
2658  normals_.push_back(normal);
2659 
2660  normals_[faces_[f0+2]] = normal;
2661 
2662  }
2663 
2664  if (!do_neighbors) synchronized_ &= ~Mesh::NODE_NEIGHBORS_E;
2665  synchronized_ &= ~(Mesh::EDGES_E);
2666  if (!do_normals) synchronized_ &= ~Mesh::NORMALS_E;
2667 
2668  synchronize_lock_.unlock();
2669 }
2670 
2671 
2672 template <class Basis>
2673 bool
2675 {
2676  typename Face::index_type face;
2677  if (!locate(face,p)) return false;
2678  insert_node(face,p);
2679  return true;
2680 }
2681 
2682 
2683 template <class Basis>
2684 void
2686 {
2687  for (index_type i = 0; i < static_cast<index_type>(edge_neighbors_.size()); i++)
2688  {
2689  if (edge_neighbors_[i] != MESH_NO_NEIGHBOR &&
2690  edge_neighbors_[edge_neighbors_[i]] != i)
2691  {
2692 // cout << "bad nbr[" << i << "] = " << edge_neighbors_[i] << ", nbr[" << edge_neighbors_[i] << "] = " << edge_neighbors_[edge_neighbors_[i]] << "\n";
2693  }
2694  }
2695 }
2696 
2697 template <class Basis>
2698 bool
2700  typename Node::index_type &ni,
2701  index_type halfedge,
2702  const Core::Geometry::Point &p)
2703 {
2704  ni = add_point(p);
2705 
2706  synchronize_lock_.lock();
2707 
2708  remove_elem_from_grid(halfedge/3);
2709 
2710  tris.clear();
2711 
2712  const index_type nbr = edge_neighbors_[halfedge];
2713 
2714  // f1
2715  const index_type f1 = static_cast<index_type>(faces_.size());
2716 
2717  tris.push_back(f1 / 3);
2718  faces_.push_back(ni);
2719  faces_.push_back(faces_[next(halfedge)]);
2720  faces_.push_back(faces_[prev(halfedge)]);
2721  edge_neighbors_.push_back(nbr);
2722  edge_neighbors_.push_back(edge_neighbors_[next(halfedge)]);
2723  edge_neighbors_.push_back(next(halfedge));
2724 
2725  if (edge_neighbors_[next(halfedge)] != MESH_NO_NEIGHBOR)
2726  {
2727  edge_neighbors_[edge_neighbors_[next(halfedge)]] = next(f1);
2728  }
2729 
2730  const index_type f3 = static_cast<index_type>(faces_.size()); // Only created if there's a neighbor.
2731 
2732  // f0
2733  tris.push_back(halfedge / 3);
2734  faces_[next(halfedge)] = ni;
2735  edge_neighbors_[halfedge] = (nbr!=MESH_NO_NEIGHBOR)?f3:MESH_NO_NEIGHBOR;
2736  edge_neighbors_[next(halfedge)] = prev(f1);
2737  edge_neighbors_[prev(halfedge)] = edge_neighbors_[prev(halfedge)];
2738 
2739  if (nbr != MESH_NO_NEIGHBOR)
2740  {
2741  remove_elem_from_grid(nbr / 3);
2742 
2743  // f3
2744  tris.push_back(f3 / 3);
2745  faces_.push_back(ni);
2746  faces_.push_back(faces_[next(nbr)]);
2747  faces_.push_back(faces_[prev(nbr)]);
2748  edge_neighbors_.push_back(halfedge);
2749  edge_neighbors_.push_back(edge_neighbors_[next(nbr)]);
2750  edge_neighbors_.push_back(next(nbr));
2751 
2752  if (edge_neighbors_[next(nbr)] != MESH_NO_NEIGHBOR)
2753  {
2754  edge_neighbors_[edge_neighbors_[next(nbr)]] = next(f3);
2755  }
2756 
2757  // f2
2758  tris.push_back(nbr / 3);
2759  faces_[next(nbr)] = ni;
2760  edge_neighbors_[nbr] = f1;
2761  edge_neighbors_[next(nbr)] = f3+2;
2762  }
2763 
2764  debug_test_edge_neighbors();
2765 
2766  synchronized_ &= ~Mesh::NODE_NEIGHBORS_E;
2767  synchronized_ &= ~(Mesh::EDGES_E);
2768  synchronized_ &= ~Mesh::NORMALS_E;
2769 
2770  for (size_t i = 0; i < tris.size(); i++)
2771  {
2772  insert_elem_into_grid(tris[i]);
2773  }
2774 
2775  synchronize_lock_.unlock();
2776 
2777  return true;
2778 }
2779 
2780 
2781 template <class Basis>
2782 bool
2784  typename Node::index_type &ni,
2785  typename Face::index_type face,
2786  const Core::Geometry::Point &p)
2787 {
2788  ni = add_point(p);
2789 
2790  synchronize_lock_.lock();
2791 
2792  remove_elem_from_grid(face);
2793 
2794  const index_type f0 = face*3;
2795  const index_type f1 = static_cast<index_type>(faces_.size());
2796  const index_type f2 = f1+3;
2797 
2798  tris.clear();
2799 
2800  if (edge_neighbors_[f0+1] != MESH_NO_NEIGHBOR)
2801  {
2802  edge_neighbors_[edge_neighbors_[f0+1]] = f1+0;
2803  }
2804  if (edge_neighbors_[f0+2] != MESH_NO_NEIGHBOR)
2805  {
2806  edge_neighbors_[edge_neighbors_[f0+2]] = f2+0;
2807  }
2808 
2809  tris.push_back(faces_.size() / 3);
2810  faces_.push_back(faces_[f0+1]);
2811  faces_.push_back(faces_[f0+2]);
2812  faces_.push_back(ni);
2813  edge_neighbors_.push_back(edge_neighbors_[f0+1]);
2814  edge_neighbors_.push_back(f2+2);
2815  edge_neighbors_.push_back(f0+1);
2816 
2817  tris.push_back(faces_.size() / 3);
2818  faces_.push_back(faces_[f0+2]);
2819  faces_.push_back(faces_[f0+0]);
2820  faces_.push_back(ni);
2821  edge_neighbors_.push_back(edge_neighbors_[f0+2]);
2822  edge_neighbors_.push_back(f0+2);
2823  edge_neighbors_.push_back(f1+1);
2824 
2825  // Must do last
2826  tris.push_back(face);
2827  faces_[f0+2] = ni;
2828  edge_neighbors_[f0+1] = f1+2;
2829  edge_neighbors_[f0+2] = f2+1;
2830 
2831  debug_test_edge_neighbors();
2832 
2833  synchronized_ &= ~Mesh::NODE_NEIGHBORS_E;
2834  synchronized_ &= ~(Mesh::EDGES_E);
2835  synchronized_ &= ~Mesh::NORMALS_E;
2836 
2837  for (size_t i = 0; i < tris.size(); i++)
2838  {
2839  insert_elem_into_grid(tris[i]);
2840  }
2841 
2842  synchronize_lock_.unlock();
2843 
2844  return true;
2845 }
2846 
2847 
2848 template <class Basis>
2849 bool
2851  typename Node::index_type &ni,
2852  typename Face::index_type face,
2853  const Core::Geometry::Point &p)
2854 {
2855  const Core::Geometry::Point &p0 = point(faces_[face * 3 + 0]);
2856  const Core::Geometry::Point &p1 = point(faces_[face * 3 + 1]);
2857  const Core::Geometry::Point &p2 = point(faces_[face * 3 + 2]);
2858 
2859  const double a0 = Cross(p - p1, p - p2).length2();
2860  const double a1 = Cross(p - p2, p - p0).length2();
2861  const double a2 = Cross(p - p0, p - p1).length2();
2862 
2863  mask_type mask = 0;
2864  if (a0 >= epsilon2_*epsilon2_) { mask |= 1; }
2865  if (a1 >= epsilon2_*epsilon2_) { mask |= 2; }
2866  if (a2 >= epsilon2_*epsilon2_) { mask |= 4; }
2867 
2868  if (mask == 7)
2869  {
2870  // Core::Geometry::Point is inside the face, do a three split.
2871  return insert_node_in_face_aux(tris, ni, face, p);
2872  }
2873  else if (mask == 0)
2874  {
2875  // Tri is degenerate, just return first point.
2876  tris.clear();
2877  tris.push_back(face);
2878  ni = faces_[face * 3 + 0];
2879  return true;
2880  }
2881  // The point is on a corner, return that corner.
2882  else if (mask == 1)
2883  {
2884  tris.clear();
2885  tris.push_back(face);
2886  ni = faces_[face * 3 + 0];
2887  return true;
2888  }
2889  else if (mask == 2)
2890  {
2891  tris.clear();
2892  tris.push_back(face);
2893  ni = faces_[face * 3 + 1];
2894  return true;
2895  }
2896  else if (mask == 4)
2897  {
2898  tris.clear();
2899  tris.push_back(face);
2900  ni = faces_[face * 3 + 2];
2901  return true;
2902  }
2903  // The point is on an edge, split that edge and neighboring triangle.
2904  else if (mask == 3)
2905  {
2906  return insert_node_in_edge_aux(tris, ni, face*3+0, p);
2907  }
2908  else if (mask == 5)
2909  {
2910  return insert_node_in_edge_aux(tris, ni, face*3+2, p);
2911  }
2912  else if (mask == 6)
2913  {
2914  return insert_node_in_edge_aux(tris, ni, face*3+1, p);
2915  }
2916  return false;
2917 }
2918 
2919 
2920 template <class Basis>
2921 void
2922 TriSurfMesh<Basis>::collapse_edges(const std::vector<index_type> &nodemap)
2923 {
2924  for (size_t i = 0; i < faces_.size(); i++)
2925  {
2926  faces_[i] = nodemap[faces_[i]];
2927  }
2928 }
2929 
2930 
2931 template <class Basis>
2932 void
2934 {
2935  std::vector<index_type> oldfaces = faces_;
2936  faces_.clear();
2937  for (size_t i = 0; i< oldfaces.size(); i+=3)
2938  {
2939  index_type a = oldfaces[i+0];
2940  index_type b = oldfaces[i+1];
2941  index_type c = oldfaces[i+2];
2942  if (a != b && a != c && b != c)
2943  {
2944  faces_.push_back(a);
2945  faces_.push_back(b);
2946  faces_.push_back(c);
2947  }
2948  }
2949  synchronized_ = NODES_E | FACES_E | CELLS_E;
2950 }
2951 
2952 
2953 /* 2
2954 // ^
2955 // / \
2956 // /f3 \
2957 // 5 /-----\ 4
2958 // / \fac/ \
2959 // /f1 \ /f2 \
2960 // / V \
2961 // <------------->
2962 // 0 3 1
2963 */
2964 
2965 #define DEBUGINFO(f) cerr << "Face #" << f/3 << " N1: " << faces_[f+0] << " N2: " << faces_[f+1] << " N3: " << faces_[f+2] << " B1: " << edge_neighbors_[f] << " B2: " << edge_neighbors_[f+1] << " B3: " << edge_neighbors_[f+2] << endl;
2966 template <class Basis>
2967 
2968 void
2970 {
2971  const bool do_neighbors = synchronized_ & Mesh::ELEM_NEIGHBORS_E;
2972  const bool do_normals = false; //synchronized_ & NORMALS_E;
2973 
2974  const index_type f0 = face*3;
2975  typename Node::array_type nodes;
2976  get_nodes(nodes,face);
2977  std::vector<Core::Geometry::Vector> normals(3);
2978  for (index_type edge = 0; edge < 3; ++edge)
2979  {
2980  Core::Geometry::Point p = ((points_[faces_[f0+edge]] +
2981  points_[faces_[next(f0+edge)]]) / 2.0).asPoint();
2982  nodes[edge] = add_point(p);
2983 
2984  if (do_normals)
2985  {
2986  normals[edge] = Core::Geometry::Vector(normals_[faces_[f0+edge]] +
2987  normals_[faces_[next(f0+edge)]]);
2988  normals[edge].safe_normalize();
2989  }
2990  }
2991 
2992  synchronize_lock_.lock();
2993 
2994  const index_type f1 = static_cast<index_type>(faces_.size());
2995  faces_.push_back(nodes[0]);
2996  faces_.push_back(nodes[3]);
2997  faces_.push_back(nodes[5]);
2998 
2999  const index_type f2 = static_cast<index_type>(faces_.size());
3000  faces_.push_back(nodes[1]);
3001  faces_.push_back(nodes[4]);
3002  faces_.push_back(nodes[3]);
3003 
3004  const index_type f3 = static_cast<index_type>(faces_.size());
3005  faces_.push_back(nodes[2]);
3006  faces_.push_back(nodes[5]);
3007  faces_.push_back(nodes[4]);
3008 
3009  faces_[f0+0] = nodes[3];
3010  faces_[f0+1] = nodes[4];
3011  faces_[f0+2] = nodes[5];
3012 
3013 
3014  if (do_neighbors)
3015  {
3016  edge_neighbors_.push_back(edge_neighbors_[f0+0]);
3017  edge_neighbors_.push_back(f0+2);
3018  edge_neighbors_.push_back(MESH_NO_NEIGHBOR);
3019 
3020  edge_neighbors_.push_back(edge_neighbors_[f0+1]);
3021  edge_neighbors_.push_back(f0+0);
3022  edge_neighbors_.push_back(MESH_NO_NEIGHBOR);
3023 
3024  edge_neighbors_.push_back(edge_neighbors_[f0+2]);
3025  edge_neighbors_.push_back(f0+1);
3026  edge_neighbors_.push_back(MESH_NO_NEIGHBOR);
3027 
3028  // must do last
3029  edge_neighbors_[f0+0] = f2+1;
3030  edge_neighbors_[f0+1] = f3+1;
3031  edge_neighbors_[f0+2] = f1+1;
3032  }
3033 
3034  if (do_normals)
3035  {
3036  normals_.push_back(normals_[f0+0]);
3037  normals_.push_back(normals[0]);
3038  normals_.push_back(normals[2]);
3039 
3040  normals_.push_back(normals_[f0+1]);
3041  normals_.push_back(normals[1]);
3042  normals_.push_back(normals[0]);
3043 
3044  normals_.push_back(normals_[f0+2]);
3045  normals_.push_back(normals[2]);
3046  normals_.push_back(normals[1]);
3047 
3048  normals_[f0+0] = normals[0];
3049  normals_[f0+1] = normals[1];
3050  normals_[f0+2] = normals[2];
3051  }
3052 
3053  if (do_neighbors && edge_neighbors_[f1] != MESH_NO_NEIGHBOR)
3054  {
3055  const index_type nbr = edge_neighbors_[f1];
3056  const index_type pnbr = prev(nbr);
3057  const index_type f4 = static_cast<index_type>(faces_.size());
3058  faces_.push_back(nodes[1]);
3059  faces_.push_back(nodes[3]);
3060  faces_.push_back(faces_[pnbr]);
3061  edge_neighbors_[f2+2] = f4;
3062  edge_neighbors_.push_back(f2+2);
3063  edge_neighbors_.push_back(pnbr);
3064  edge_neighbors_.push_back(edge_neighbors_[pnbr]);
3065  edge_neighbors_[edge_neighbors_.back()] = f4+2;
3066  faces_[nbr] = nodes[3];
3067  edge_neighbors_[pnbr] = f4+1;
3068  if (do_normals)
3069  {
3070  normals_[nbr] = normals[0];
3071  normals_.push_back(normals_[f0+1]);
3072  normals_.push_back(normals[0]);
3073  normals_.push_back(normals_[pnbr]);
3074  }
3075  }
3076 
3077  if (do_neighbors && edge_neighbors_[f2] != MESH_NO_NEIGHBOR)
3078  {
3079  const index_type nbr = edge_neighbors_[f2];
3080  const index_type pnbr = prev(nbr);
3081  const index_type f5 = static_cast<index_type>(faces_.size());
3082  faces_.push_back(nodes[2]);
3083  faces_.push_back(nodes[4]);
3084  faces_.push_back(faces_[pnbr]);
3085  edge_neighbors_[f3+2] = f5;
3086  edge_neighbors_.push_back(f3+2);
3087  edge_neighbors_.push_back(pnbr);
3088  edge_neighbors_.push_back(edge_neighbors_[pnbr]);
3089  edge_neighbors_[edge_neighbors_.back()] = f5+2;
3090  faces_[nbr] = nodes[4];
3091  edge_neighbors_[pnbr] = f5+1;
3092  if (do_normals)
3093  {
3094  normals_[nbr] = normals[1];
3095  normals_.push_back(normals_[f0+2]);
3096  normals_.push_back(normals[1]);
3097  normals_.push_back(normals_[pnbr]);
3098  }
3099  }
3100 
3101  if (do_neighbors && edge_neighbors_[f3] != MESH_NO_NEIGHBOR)
3102  {
3103  const index_type nbr = edge_neighbors_[f3];
3104  const index_type pnbr = prev(nbr);
3105  const index_type f6 = static_cast<index_type>(faces_.size());
3106  faces_.push_back(nodes[0]);
3107  faces_.push_back(nodes[5]);
3108  faces_.push_back(faces_[pnbr]);
3109  edge_neighbors_[f1+2] = f6;
3110  edge_neighbors_.push_back(f1+2);
3111  edge_neighbors_.push_back(pnbr);
3112  edge_neighbors_.push_back(edge_neighbors_[pnbr]);
3113  edge_neighbors_[edge_neighbors_.back()] = f6+2;
3114  faces_[nbr] = nodes[5];
3115  edge_neighbors_[pnbr] = f6+1;
3116  if (do_normals)
3117  {
3118  normals_[nbr] = normals[2];
3119  normals_.push_back(normals_[f0+0]);
3120  normals_.push_back(normals[2]);
3121  normals_.push_back(normals_[pnbr]);
3122  }
3123  }
3124 
3125  if (!do_neighbors) synchronized_ &= ~Mesh::NODE_NEIGHBORS_E;
3126  synchronized_ &= ~(Mesh::EDGES_E);
3127  if (!do_normals) synchronized_ &= ~Mesh::NORMALS_E;
3128 
3129  synchronize_lock_.unlock();
3130 }
3131 
3132 
3133 template <class Basis>
3134 void
3136 {
3137  node_neighbors_.clear();
3138  node_neighbors_.resize(points_.size());
3139  size_type nfaces = static_cast<size_type>(faces_.size());
3140  for (index_type f = 0; f < nfaces; ++f)
3141  {
3142  node_neighbors_[faces_[f]].push_back(f/3);
3143  }
3144  synchronize_lock_.lock();
3145  synchronized_ |= Mesh::NODE_NEIGHBORS_E;
3146  synchronize_lock_.unlock();
3147 }
3148 
3149 
3150 template <class Basis>
3151 void
3153 {
3154  EdgeMapType2 edge_map;
3155 
3156  size_type num_faces = static_cast<index_type>(faces_.size())/3;
3157  for (index_type i=0; i < num_faces; i++)
3158  {
3159  index_type n0 = faces_[3*i];
3160  index_type n1 = faces_[3*i+1];
3161  index_type n2 = faces_[3*i+2];
3162 
3163  if (n0 > n1) edge_map[std::pair<index_type, index_type>(n1,n0)].push_back(i<<2);
3164  else edge_map[std::pair<index_type, index_type>(n0,n1)].push_back(i<<2);
3165 
3166  if (n1 > n2) edge_map[std::pair<index_type, index_type>(n2,n1)].push_back((i<<2)+1);
3167  else edge_map[std::pair<index_type, index_type>(n1,n2)].push_back((i<<2)+1);
3168 
3169  if (n2 > n0) edge_map[std::pair<index_type, index_type>(n0,n2)].push_back((i<<2)+2);
3170  else edge_map[std::pair<index_type, index_type>(n2,n0)].push_back((i<<2)+2);
3171  }
3172 
3173  typename EdgeMapType2::iterator itr;
3174  edges_.clear();
3175  edges_.resize(edge_map.size());
3176  halfedge_to_edge_.resize(faces_.size());
3177 
3178  size_t k=0;
3179  for (itr = edge_map.begin(); itr != edge_map.end(); ++itr)
3180  {
3181  const std::vector<index_type >& hedges = (*itr).second;
3182  for (size_t j=0; j<hedges.size(); j++)
3183  {
3184  index_type h = hedges[j];
3185  edges_[k].push_back(h);
3186  halfedge_to_edge_[(h>>2)*3 + (h&0x3)] = k;
3187 
3188  }
3189  k++;
3190  }
3191 
3192  synchronize_lock_.lock();
3193  synchronized_ |= (Mesh::EDGES_E);
3194  synchronize_lock_.unlock();
3195 }
3196 
3197 // Fixes bug #887 (gforge)
3198 template <class Basis>
3199 void
3201 {
3202  EdgeMapType2 edge_map;
3203 
3204  size_type num_faces = static_cast<index_type>(faces_.size())/3;
3205  for (index_type i=0; i < num_faces; i++)
3206  {
3207  index_type n0 = faces_[3*i];
3208  index_type n1 = faces_[3*i+1];
3209  index_type n2 = faces_[3*i+2];
3210 
3211  if (n0 > n1) edge_map[std::pair<index_type, index_type>(n1,n0)].push_back(i<<2);
3212  else edge_map[std::pair<index_type, index_type>(n0,n1)].push_back(i<<2);
3213 
3214  if (n1 > n2) edge_map[std::pair<index_type, index_type>(n2,n1)].push_back((i<<2)+1);
3215  else edge_map[std::pair<index_type, index_type>(n1,n2)].push_back((i<<2)+1);
3216 
3217  if (n2 > n0) edge_map[std::pair<index_type, index_type>(n0,n2)].push_back((i<<2)+2);
3218  else edge_map[std::pair<index_type, index_type>(n2,n0)].push_back((i<<2)+2);
3219  }
3220 
3221  typename EdgeMapType2::iterator itr;
3222  edges_.clear();
3223  edges_.resize(edge_map.size());
3224  halfedge_to_edge_.resize(faces_.size());
3225  edge_on_node_.clear();
3226  edge_on_node_.resize(points_.size());
3227 
3228  size_t k=0;
3229  for (itr = edge_map.begin(); itr != edge_map.end(); ++itr)
3230  {
3231  const std::vector<index_type >& hedges = (*itr).second;
3232  for (size_t j=0; j<hedges.size(); j++)
3233  {
3234  index_type h = hedges[j];
3235  edges_[k].push_back(h);
3236  halfedge_to_edge_[(h>>2)*3 + (h&0x3)] = k;
3237  }
3238  edge_on_node_[(*itr).first.first].push_back(k);
3239  edge_on_node_[(*itr).first.second].push_back(k);
3240  k++;
3241  }
3242 
3243  synchronize_lock_.lock();
3244  synchronized_ |= (Mesh::EDGES_E);
3245  synchronize_lock_.unlock();
3246 }
3247 
3248 template <class Basis>
3251 {
3252  typename Node::index_type i;
3253  if (search_node(i, p) && (p - points_[i]).length2() < err)
3254  {
3255  return i;
3256  }
3257  else
3258  {
3259  synchronize_lock_.lock();
3260  points_.push_back(p);
3261  node_neighbors_.push_back(std::vector<under_type>());
3262  synchronize_lock_.unlock();
3263  return static_cast<typename Node::index_type>(points_.size() - 1);
3264  }
3265 }
3266 
3267 
3268 // swap the shared edge between 2 faces. If faces don't share an edge,
3269 // do nothing.
3270 template <class Basis>
3271 bool
3273  typename Face::index_type f2)
3274 {
3275  const index_type face1 = f1 * 3;
3276  std::set<index_type, less_int> shared;
3277  shared.insert(faces_[face1]);
3278  shared.insert(faces_[face1 + 1]);
3279  shared.insert(faces_[face1 + 2]);
3280 
3281  index_type not_shar[2];
3282  index_type *ns = not_shar;
3283  const index_type face2 = f2 * 3;
3284  std::pair<std::set<index_type, less_int>::iterator, bool> p = shared.insert(faces_[face2]);
3285  if (!p.second) { *ns = faces_[face2]; ++ns;}
3286  p = shared.insert(faces_[face2 + 1]);
3287  if (!p.second) { *ns = faces_[face2 + 1]; ++ns;}
3288  p = shared.insert(faces_[face2 + 2]);
3289  if (!p.second) { *ns = faces_[face2 + 2]; }
3290 
3291  // no shared nodes means no shared edge.
3292  if (shared.size() > 4) return false;
3293 
3294  std::set<index_type, less_int>::iterator iter = shared.find(not_shar[0]);
3295  shared.erase(iter);
3296 
3297  iter = shared.find(not_shar[1]);
3298  shared.erase(iter);
3299 
3300  iter = shared.begin();
3301  index_type s1 = *iter++;
3302  index_type s2 = *iter;
3303 
3304  synchronize_lock_.lock();
3305  faces_[face1] = s1;
3306  faces_[face1 + 1] = not_shar[0];
3307  faces_[face1 + 2] = s2;
3308 
3309  faces_[face2] = s2;
3310  faces_[face2 + 1] = not_shar[1];
3311  faces_[face2 + 2] = s1;
3312 
3313  synchronized_ &= ~Mesh::ELEM_NEIGHBORS_E;
3314  synchronized_ &= ~Mesh::NODE_NEIGHBORS_E;
3315  synchronized_ &= ~Mesh::NORMALS_E;
3316  synchronize_lock_.unlock();
3317 
3318  return true;
3319 }
3320 
3321 template <class Basis>
3322 bool
3324 {
3325  bool rval = false;
3326 
3327  /// find the orphan nodes.
3328  std::vector<index_type> onodes;
3329  /// check each point against the face list.
3330  for (index_type i = 0; i < static_cast<index_type>(points_.size()); i++) {
3331  if (find(faces_.begin(), faces_.end(), i) == faces_.end()) {
3332  /// node does not belong to a face
3333  onodes.push_back(i);
3334  }
3335  }
3336 
3337  if (onodes.size()) rval = true;
3338 
3339  /// check each point against the face list.
3340  std::vector<index_type>::reverse_iterator orph_iter = onodes.rbegin();
3341  while (orph_iter != onodes.rend())
3342  {
3343  index_type i = *orph_iter++;
3344  std::vector<index_type>::iterator iter = faces_.begin();
3345  while (iter != faces_.end())
3346  {
3347  index_type &node = *iter++;
3348  if (node > i)
3349  {
3350  node--;
3351  }
3352  }
3353  std::vector<Core::Geometry::Point>::iterator niter = points_.begin();
3354  niter += i;
3355  points_.erase(niter);
3356  }
3357 
3358  synchronized_ &= ~Mesh::ELEM_NEIGHBORS_E;
3359  synchronized_ &= ~Mesh::NODE_NEIGHBORS_E;
3360  synchronized_ &= ~Mesh::NORMALS_E;
3361  return rval;
3362 }
3363 
3364 template <class Basis>
3365 bool
3367 {
3368  bool rval = true;
3369 
3370  synchronize_lock_.lock();
3371  std::vector<under_type>::iterator fb = faces_.begin() + f*3;
3372  std::vector<under_type>::iterator fe = fb + 3;
3373 
3374  if (fe <= faces_.end())
3375  faces_.erase(fb, fe);
3376  else {
3377  rval = false;
3378  }
3379  synchronized_ &= ~Mesh::ELEM_NEIGHBORS_E;
3380  synchronized_ &= ~Mesh::NODE_NEIGHBORS_E;
3381  synchronized_ &= ~Mesh::NORMALS_E;
3382  synchronize_lock_.unlock();
3383 
3384  return rval;
3385 }
3386 
3387 
3388 template <class Basis>
3391  typename Node::index_type b,
3392  typename Node::index_type c)
3393 {
3394  synchronize_lock_.lock();
3395  faces_.push_back(a);
3396  faces_.push_back(b);
3397  faces_.push_back(c);
3398  synchronized_ &= ~Mesh::ELEM_NEIGHBORS_E;
3399  synchronized_ &= ~Mesh::NODE_NEIGHBORS_E;
3400  synchronized_ &= ~Mesh::NORMALS_E;
3401  synchronize_lock_.unlock();
3402  return static_cast<typename Elem::index_type>((static_cast<index_type>(faces_.size()) / 3) - 1);
3403 }
3404 
3405 
3406 template <class Basis>
3407 void
3409 {
3410  synchronize_lock_.lock();
3411  typename Face::iterator fiter, fend;
3412  begin(fiter);
3413  end(fend);
3414  while (fiter != fend)
3415  {
3416  flip_face(*fiter);
3417  ++fiter;
3418  }
3419  synchronized_ &= ~(Mesh::EDGES_E);
3420  synchronized_ &= ~Mesh::ELEM_NEIGHBORS_E;
3421  synchronized_ &= ~Mesh::NODE_NEIGHBORS_E;
3422  synchronized_ &= ~Mesh::NORMALS_E;
3423  synchronize_lock_.unlock();
3424 }
3425 
3426 
3427 template <class Basis>
3428 void
3430 {
3431  const index_type base = face * 3;
3432  index_type tmp = faces_[base + 1];
3433  faces_[base + 1] = faces_[base + 2];
3434  faces_[base + 2] = tmp;
3435 
3436  synchronized_ &= ~(Mesh::EDGES_E);
3437  synchronized_ &= ~Mesh::ELEM_NEIGHBORS_E;
3438  synchronized_ &= ~Mesh::NODE_NEIGHBORS_E;
3439  synchronized_ &= ~Mesh::NORMALS_E;
3440 }
3441 
3442 
3443 template <class Basis>
3444 void
3446  std::vector<bool> &tested,
3447  std::vector<bool> &flip)
3448 {
3449  tested[face] = true;
3450  for (index_type i = 0; i < 3; i++)
3451  {
3452  const index_type edge = face * 3 + i;
3453  const index_type nbr = edge_neighbors_[edge];
3454  if (nbr != MESH_NO_NEIGHBOR && !tested[nbr/3])
3455  {
3456  if (!flip[face] && faces_[edge] == faces_[nbr] ||
3457  flip[face] && faces_[next(edge)] == faces_[nbr])
3458  {
3459  flip[nbr/3] = true;
3460  }
3461  walk_face_orient(nbr/3, tested, flip);
3462  }
3463  }
3464 }
3465 
3466 template <class Basis>
3467 void
3469 {
3470  synchronize(Mesh::EDGES_E | Mesh::ELEM_NEIGHBORS_E);
3471  synchronize_lock_.lock();
3472 
3473  index_type nfaces = (int)faces_.size() / 3;
3474  std::vector<bool> tested(nfaces, false);
3475  std::vector<bool> flip(nfaces, false);
3476 
3477  typename Face::iterator fiter, fend;
3478  begin(fiter);
3479  end(fend);
3480  while (fiter != fend)
3481  {
3482  if (! tested[*fiter])
3483  {
3484  walk_face_orient(*fiter, tested, flip);
3485  }
3486  ++fiter;
3487  }
3488 
3489  begin(fiter);
3490  while (fiter != fend)
3491  {
3492  if (flip[*fiter])
3493  {
3494  flip_face(*fiter);
3495  }
3496  ++fiter;
3497  }
3498 
3499  synchronized_ &= ~(Mesh::EDGES_E);
3500  synchronized_ &= ~Mesh::ELEM_NEIGHBORS_E;
3501  synchronized_ &= ~Mesh::NORMALS_E;
3502  synchronize_lock_.unlock();
3503 }
3504 
3505 
3506 template <class Basis>
3507 void
3509 {
3510  EdgeMapType edge_map;
3511 
3512  edge_neighbors_.resize(faces_.size());
3513  for (size_t j = 0; j < edge_neighbors_.size(); j++)
3514  {
3515  edge_neighbors_[j] = MESH_NO_NEIGHBOR;
3516  }
3517 
3518  index_type i;
3519  for (i=static_cast<index_type>(faces_.size()-1); i >= 0; i--)
3520  {
3521  const index_type a = i;
3522  const index_type b = a - a % 3 + (a+1) % 3;
3523 
3524  index_type n0 = faces_[a];
3525  index_type n1 = faces_[b];
3526  index_type tmp;
3527  if (n0 > n1) { tmp = n0; n0 = n1; n1 = tmp; }
3528 
3529  std::pair<index_type, index_type> nodes(n0, n1);
3530 
3531  typename EdgeMapType::iterator maploc;
3532 
3533  maploc = edge_map.find(nodes);
3534  if (maploc != edge_map.end())
3535  {
3536  edge_neighbors_[(*maploc).second] = i;
3537  edge_neighbors_[i] = (*maploc).second;
3538  }
3539  edge_map[nodes] = i;
3540  }
3541 
3542  debug_test_edge_neighbors();
3543 
3544  synchronize_lock_.lock();
3545  synchronized_ |= Mesh::ELEM_NEIGHBORS_E;
3546  synchronize_lock_.unlock();
3547 }
3548 
3549 
3550 template <class Basis>
3551 void
3553 {
3554  /// @todo: This can crash if you insert a new cell outside of the grid.
3555  // Need to recompute grid at that point.
3556  const index_type idx = ci*3;
3558  box.extend(points_[faces_[idx]]);
3559  box.extend(points_[faces_[idx+1]]);
3560  box.extend(points_[faces_[idx+2]]);
3561  box.extend(epsilon_);
3562  elem_grid_->insert(ci, box);
3563 }
3564 
3565 
3566 template <class Basis>
3567 void
3569 {
3570  const index_type idx = ci*3;
3572  box.extend(points_[faces_[idx]]);
3573  box.extend(points_[faces_[idx+1]]);
3574  box.extend(points_[faces_[idx+2]]);
3575  box.extend(epsilon_);
3576  elem_grid_->remove(ci, box);
3577 }
3578 
3579 
3580 template <class Basis>
3581 void
3583 {
3584  /// @todo: This can crash if you insert a new cell outside of the grid.
3585  // Need to recompute grid at that point.
3586  node_grid_->insert(ni,points_[ni]);
3587 }
3588 
3589 
3590 template <class Basis>
3591 void
3593 {
3594  node_grid_->remove(ni,points_[ni]);
3595 }
3596 
3597 
3598 template <class Basis>
3599 void
3601 {
3602  if (bbox_.valid())
3603  {
3604  // Cubed root of number of cells to get a subdivision ballpark.
3605 
3606  typename Elem::size_type esz; size(esz);
3607 
3608  const size_type s =
3609  3*static_cast<size_type>((ceil(pow(static_cast<double>(esz) , (1.0/3.0))))/2.0 + 1.0);
3610 
3611  Core::Geometry::Vector diag = bbox_.diagonal();
3612  double trace = (diag.x()+diag.y()+diag.z());
3613  size_type sx = static_cast<size_type>(ceil(0.5+diag.x()/trace*s));
3614  size_type sy = static_cast<size_type>(ceil(0.5+diag.y()/trace*s));
3615  size_type sz = static_cast<size_type>(ceil(0.5+diag.z()/trace*s));
3616 
3617  Core::Geometry::BBox b = bbox_; b.extend(10*epsilon_);
3618  elem_grid_.reset(new SearchGridT<index_type>(sx, sy, sz, b.min(), b.max()));
3619 
3620  typename Elem::iterator ci, cie;
3621  begin(ci); end(cie);
3622  while(ci != cie)
3623  {
3624  insert_elem_into_grid(*ci);
3625  ++ci;
3626  }
3627  }
3628 
3629  synchronize_lock_.lock();
3630  synchronized_ |= Mesh::ELEM_LOCATE_E;
3631  synchronize_lock_.unlock();
3632 }
3633 
3634 
3635 template <class Basis>
3636 void
3638 {
3639  if (bbox_.valid())
3640  {
3641  // Cubed root of number of cells to get a subdivision ballpark.
3642 
3643  typename Elem::size_type esz; size(esz);
3644 
3645  const size_type s = 3*static_cast<size_type>
3646  ((ceil(pow(static_cast<double>(esz) , (1.0/3.0))))/2.0 + 1.0);
3647 
3648  Core::Geometry::Vector diag = bbox_.diagonal();
3649  double trace = (diag.x()+diag.y()+diag.z());
3650  size_type sx = static_cast<size_type>(ceil(0.5+diag.x()/trace*s));
3651  size_type sy = static_cast<size_type>(ceil(0.5+diag.y()/trace*s));
3652  size_type sz = static_cast<size_type>(ceil(0.5+diag.z()/trace*s));
3653 
3654  Core::Geometry::BBox b = bbox_; b.extend(10*epsilon_);
3655  node_grid_.reset(new SearchGridT<index_type>(sx, sy, sz, b.min(), b.max()));
3656 
3657  typename Node::iterator ni, nie;
3658  begin(ni); end(nie);
3659 
3660  while(ni != nie)
3661  {
3662  insert_node_into_grid(*ni);
3663  ++ni;
3664  }
3665  }
3666 
3667  synchronize_lock_.lock();
3668  synchronized_ |= Mesh::NODE_LOCATE_E;
3669  synchronize_lock_.unlock();
3670 }
3671 
3672 
3673 template <class Basis>
3674 void
3676 {
3677  bbox_.reset();
3678 
3679  // Compute bounding box
3680  typename Node::iterator ni, nie;
3681  begin(ni);
3682  end(nie);
3683  while (ni != nie)
3684  {
3685  bbox_.extend(point(*ni));
3686  ++ni;
3687  }
3688 
3689  // Compute epsilons associated with the bounding box
3690  epsilon_ = bbox_.diagonal().length()*1e-8;
3691  epsilon2_ = epsilon_*epsilon_;
3692 
3693  synchronize_lock_.lock();
3694  synchronized_ |= Mesh::BOUNDING_BOX_E;
3695  synchronize_lock_.unlock();
3696 }
3697 
3698 
3699 template <class Basis>
3702 {
3703  points_.push_back(p);
3704  return static_cast<typename Node::index_type>(points_.size() - 1);
3705 }
3706 
3707 
3708 
3709 template <class Basis>
3712  const Core::Geometry::Point &p1,
3713  const Core::Geometry::Point &p2)
3714 {
3715  return add_triangle(add_find_point(p0), add_find_point(p1), add_find_point(p2));
3716 }
3717 
3718 #define TRISURFMESH_VERSION 4
3719 
3720 template <class Basis>
3721 void
3723 {
3724  int version = stream.begin_class(type_name(-1), TRISURFMESH_VERSION);
3725 
3726  Mesh::io(stream);
3727 
3728  Pio(stream, points_);
3729  Pio_index(stream, faces_);
3730 
3731  if (version < 4)
3732  {
3733 // Reading data we do not use anymore
3734  std::vector<unsigned int> old;
3735  Pio(stream, old);
3736  }
3737 
3738  if (version >= 2)
3739  {
3740  basis_.io(stream);
3741  }
3742 
3743  stream.end_class();
3744 
3745  if (stream.reading() && edge_neighbors_.size())
3746  {
3747  synchronized_ |= Mesh::ELEM_NEIGHBORS_E;
3748  }
3749 
3750  if (stream.reading())
3751  vmesh_.reset(CreateVTriSurfMesh(this));
3752 }
3753 
3754 template <class Basis>
3755 void
3757 {
3758  typename Node::iterator itr; end(itr);
3759  s = *itr;
3760 }
3761 
3762 
3763 template <class Basis>
3764 void
3766 {
3767  ASSERTMSG(synchronized_ & Mesh::EDGES_E,
3768  "Must call synchronize EDGES_E on TriSurfMesh first");
3769 
3770  typename Edge::iterator itr; end(itr);
3771  s = *itr;
3772 }
3773 
3774 
3775 template <class Basis>
3776 void
3778 {
3779  typename Face::iterator itr; end(itr);
3780  s = *itr;
3781 }
3782 
3783 
3784 template <class Basis>
3785 void
3787 {
3788  typename Cell::iterator itr; end(itr);
3789  s = *itr;
3790 }
3791 
3792 
3793 template <class Basis>
3794 const TypeDescription*
3796 {
3797  static TypeDescription *td = 0;
3798  if (!td)
3799  {
3800  const TypeDescription *sub = get_type_description((Basis*)0);
3802  (*subs)[0] = sub;
3803  td = new TypeDescription("TriSurfMesh", subs,
3804  std::string(__FILE__),
3805  "SCIRun",
3806  TypeDescription::MESH_E);
3807  }
3808  return td;
3809 }
3810 
3811 
3812 template <class Basis>
3813 const TypeDescription*
3815 {
3817 }
3818 
3819 
3820 template <class Basis>
3821 const TypeDescription*
3823 {
3824  static TypeDescription *td = 0;
3825  if (!td)
3826  {
3827  const TypeDescription *me =
3829  td = new TypeDescription(me->get_name() + "::Node",
3830  std::string(__FILE__),
3831  "SCIRun",
3832  TypeDescription::MESH_E);
3833  }
3834  return td;
3835 }
3836 
3837 
3838 template <class Basis>
3839 const TypeDescription*
3841 {
3842  static TypeDescription *td = 0;
3843  if (!td)
3844  {
3845  const TypeDescription *me =
3847  td = new TypeDescription(me->get_name() + "::Edge",
3848  std::string(__FILE__),
3849  "SCIRun",
3850  TypeDescription::MESH_E);
3851  }
3852  return td;
3853 }
3854 
3855 
3856 template <class Basis>
3857 const TypeDescription*
3859 {
3860  static TypeDescription *td = 0;
3861  if (!td)
3862  {
3863  const TypeDescription *me =
3865  td = new TypeDescription(me->get_name() + "::Face",
3866  std::string(__FILE__),
3867  "SCIRun",
3868  TypeDescription::MESH_E);
3869  }
3870  return td;
3871 }
3872 
3873 
3874 template <class Basis>
3875 const TypeDescription*
3877 {
3878  static TypeDescription *td = 0;
3879  if (!td)
3880  {
3881  const TypeDescription *me =
3883  td = new TypeDescription(me->get_name() + "::Cell",
3884  std::string(__FILE__),
3885  "SCIRun",
3886  TypeDescription::MESH_E);
3887  }
3888  return td;
3889 }
3890 
3891 template <class Basis>
3892 bool
3894  index_type half_edge) const
3895 {
3896  ASSERTMSG(synchronized_ & ELEM_NEIGHBORS_E,
3897  "Must call synchronize ELEM_NEIGHBORS_E on TriSurfMesh first");
3898  nbr_half_edge = edge_neighbors_[half_edge];
3899  return nbr_half_edge != MESH_NO_NEIGHBOR;
3900 }
3901 
3902 } // namespace SCIRun
3903 
3904 
3905 #endif
boost::shared_ptr< TriSurfMesh< Basis > > handle_type
Definition: TriSurfMesh.h:117
virtual TriSurfMesh * clone() const
Definition: TriSurfMesh.h:307
void get_normal(Core::Geometry::Vector &result, VECTOR &coords, INDEX1 eidx, INDEX2)
Get the normals at the outside of the element.
Definition: TriSurfMesh.h:571
SCIRun::index_type under_type
Definition: TriSurfMesh.h:112
boost::shared_ptr< VMesh > vmesh_
Definition: TriSurfMesh.h:1957
Interface to statically allocated std::vector class.
Definition: VUnstructuredMesh.h:41
static PersistentTypeID trisurf_typeid
This ID is created as soon as this class will be instantiated.
Definition: TriSurfMesh.h:1288
std::vector< Core::Geometry::Point > points_
Actual parameters.
Definition: TriSurfMesh.h:1930
bool reading() const
Definition: Persistent.h:164
Distinct type for node FieldIterator.
Definition: FieldIterator.h:89
void get_edges_from_node_bugfix(ARRAY &array, INDEX idx) const
Definition: TriSurfMesh.h:1506
bool get_neighbor(typename Elem::index_type &neighbor, typename Elem::index_type elem, typename DElem::index_type delem) const
Get neighbors of an element or a node.
Definition: TriSurfMesh.h:512
Node::index_type add_node(const Core::Geometry::Point &p)
Definition: TriSurfMesh.h:584
bool operator()(const index_type s1, const index_type s2) const
Definition: TriSurfMesh.h:2037
Definition: FieldRNG.h:37
void get_edge_center(Core::Geometry::Point &result, INDEX idx) const
Definition: TriSurfMesh.h:1877
std::string get_name(const std::string &type_sep_start="<", const std::string &type_sep_end="> ") const
Definition: TypeDescription.cc:135
Distinct type for face Iterator.
Definition: FieldIterator.h:121
Basis basis_
Definition: TriSurfMesh.h:1951
CellIndex< under_type > size_type
Definition: TriSurfMesh.h:145
void resize_nodes(size_type s)
Definition: TriSurfMesh.h:602
Definition: ConditionVariable.h:45
Vector project(const Vector &p) const
Definition: Transform.cc:425
SCIRun::index_type index_type
Definition: TriSurfMesh.h:113
Definition: Mesh.h:64
bool locate_elem(INDEX &elem, const Core::Geometry::Point &p) const
Locate an element inside the mesh using the lookup table.
Definition: TriSurfMesh.h:1761
std::vector< index_type > array_type
Definition: TriSurfMesh.h:146
Point max() const
Definition: BBox.h:195
#define ASSERTMSG(condition, message)
Definition: Exception.h:113
void get_elems(typename Elem::array_type &array, typename Face::index_type idx) const
Definition: TriSurfMesh.h:430
void get_center(Core::Geometry::Point &, typename Cell::index_type) const
Definition: TriSurfMesh.h:473
double get_size(typename Edge::index_type idx) const
Definition: TriSurfMesh.h:480
static const TypeDescription * elem_type_description()
Definition: TriSurfMesh.h:1299
const Core::Geometry::Point & node2() const
Definition: TriSurfMesh.h:217
bool find_closest_elem(double &pdist, Core::Geometry::Point &result, INDEX &elem, const Core::Geometry::Point &p) const
Definition: TriSurfMesh.h:1139
void interpolate(Core::Geometry::Point &pt, VECTOR &coords, INDEX idx) const
Definition: TriSurfMesh.h:618
Definition: Persistent.h:89
Basis basis_type
Definition: TriSurfMesh.h:118
void pre_scale(const Vector &)
Definition: Transform.cc:193
double inverse_jacobian(const VECTOR &coords, INDEX idx, double *Ji) const
Definition: TriSurfMesh.h:670
bool locate(typename Elem::index_type &elem, std::vector< double > &coords, const Core::Geometry::Point &p)
Definition: TriSurfMesh.h:539
void get_neighbors(std::vector< typename Node::index_type > &array, typename Node::index_type node) const
These are more general implementations.
Definition: TriSurfMesh.h:518
bool locate_node(INDEX &node, const Core::Geometry::Point &p) const
Locate a node inside the mesh using the lookup table.
Definition: TriSurfMesh.h:1637
index_type edge2_index() const
Definition: TriSurfMesh.h:199
#define TRISURFMESH_VERSION
Definition: TriSurfMesh.h:3718
Definition: TriCubicHmt.h:58
std::vector< std::vector< index_type > > node_neighbors_
Definition: TriSurfMesh.h:1936
void resize_elems(size_type s)
Definition: TriSurfMesh.h:603
bool get_neighbors(std::vector< typename Elem::index_type > &array, typename Elem::index_type elem, typename DElem::index_type delem) const
Definition: TriSurfMesh.h:521
index_type edge0_index() const
Definition: TriSurfMesh.h:191
void get_cells(typename Cell::array_type &, typename Face::index_type) const
Definition: TriSurfMesh.h:421
double InverseMatrix3P(const PointVector &p, double *q)
Inline templated inverse matrix.
Definition: Locate.h:72
void get_cells(typename Cell::array_type &, typename Edge::index_type) const
Definition: TriSurfMesh.h:419
void to_index(typename Edge::index_type &index, index_type i) const
Definition: TriSurfMesh.h:381
void get_faces(typename Face::array_type &array, typename Edge::index_type idx) const
Definition: TriSurfMesh.h:410
void derivate(const VECTOR1 &coords, INDEX idx, VECTOR2 &J) const
Definition: TriSurfMesh.h:628
Definition: Persistent.h:187
bool index_(ArrayMathProgramCode &pc)
Definition: ArrayMathFunctionSourceSink.cc:636
Elem::index_type add_elem(ARRAY a)
Add a new element to the mesh.
Definition: TriSurfMesh.h:589
index_type edge1_index() const
Definition: TriSurfMesh.h:195
BBox & extend(const Point &p)
Expand the bounding box to include point p.
Definition: BBox.h:98
void to_index(typename Face::index_type &index, index_type i) const
Definition: TriSurfMesh.h:383
double get_area(typename Face::index_type idx) const
Definition: TriSurfMesh.h:503
void get_nodes(typename Node::array_type &, typename Cell::index_type) const
Definition: TriSurfMesh.h:396
void get_face_center(Core::Geometry::Point &result, INDEX idx) const
Definition: TriSurfMesh.h:1888
FieldHandle mesh()
Definition: BuildTDCSMatrixTests.cc:56
Definition: Mesh.h:84
Definition: Point.h:49
Definition: TypeDescription.h:45
#define SCISHARE
Definition: share.h:39
std::vector< const TypeDescription * > td_vec
Definition: TypeDescription.h:56
void get_edges_from_node(ARRAY &array, INDEX idx) const
Definition: TriSurfMesh.h:1482
std::map< std::pair< index_type, index_type >, index_type, edgecompare > EdgeMapType
Definition: QuadSurfMesh.h:2930
ElemData(const TriSurfMesh< Basis > &msh, const index_type ind)
Definition: TriSurfMesh.h:165
VMesh * CreateVTriSurfMesh(MESH *)
Definition: TriSurfMesh.h:81
void run()
Definition: TriSurfMesh.h:239
Definition: Mesh.h:45
FaceIterator< under_type > iterator
Definition: TriSurfMesh.h:137
Definition: BBox.h:46
boost::shared_ptr< Mesh > MeshHandle
Definition: DatatypeFwd.h:67
Definition: Mutex.h:43
index_type elem_index() const
Definition: TriSurfMesh.h:204
#define MESH_NO_NEIGHBOR
Definition: MeshTraits.h:67
Distinct type for cell Iterator.
Definition: FieldIterator.h:134
void get_faces(typename Face::array_type &array, typename Node::index_type idx) const
Definition: TriSurfMesh.h:408
int get_weights(const Core::Geometry::Point &, typename Edge::array_type &, double *)
Definition: TriSurfMesh.h:547
unsigned int mask_type
Definition: Types.h:45
bool locate(typename Cell::index_type &, const Core::Geometry::Point &) const
Definition: TriSurfMesh.h:536
void get_node_neighbors(ARRAY &array, INDEX idx) const
Definition: TriSurfMesh.h:1608
std::map< std::pair< index_type, index_type >, std::vector< index_type >, edgecompare > EdgeMapType2
Definition: QuadSurfMesh.h:2944
bool find_closest_node(double &pdist, Core::Geometry::Point &result, INDEX &node, const Core::Geometry::Point &p) const
Definition: TriSurfMesh.h:756
Point & asPoint() const
Definition: Vector.h:457
Definition: TriSurfMesh.h:2035
NodeIndex< under_type > index_type
Definition: TriSurfMesh.h:122
#define ASSERT(condition)
Definition: Assert.h:110
virtual bool has_normals() const
Has this mesh normals.
Definition: TriSurfMesh.h:347
Definition: TriSurfMesh.h:75
bool get_elem_neighbor(INDEX1 &neighbor, INDEX1 elem, INDEX2 delem) const
Definition: TriSurfMesh.h:1535
Index and Iterator types required for Mesh Concept.
Definition: TriSurfMesh.h:121
virtual ~TriSurfMesh()
Destructor.
Definition: TriSurfMesh.h:2140
SCIRun::size_type size_type
Definition: TriSurfMesh.h:114
virtual int begin_class(const std::string &name, int current_version)
Definition: Persistent.cc:143
bool locate(typename Edge::index_type &loc, const Core::Geometry::Point &p) const
Definition: TriSurfMesh.h:532
boost::shared_ptr< SearchGridT< index_type > > node_grid_
Definition: TriSurfMesh.h:1939
bool search_node(INDEX &loc, const Core::Geometry::Point &p) const
Definition: TriSurfMesh.h:1151
Core::Geometry::BBox bbox_
Definition: TriSurfMesh.h:1953
void get_nodes(typename Node::array_type &array, typename Face::index_type idx) const
Definition: TriSurfMesh.h:394
bool find_closest_elem(double &pdist, Core::Geometry::Point &result, ARRAY &coords, INDEX &face, const Core::Geometry::Point &p, double maxdist) const
Definition: TriSurfMesh.h:1014
Definition: Vector.h:63
static MeshHandle mesh_maker()
This function returns a handle for the virtual interface.
Definition: TriSurfMesh.h:1305
void get_delems(typename DElem::array_type &array, typename Edge::index_type idx) const
Definition: TriSurfMesh.h:437
bool find_closest_nodes(ARRAY1 &distances, ARRAY2 &nodes, const Core::Geometry::Point &p, double maxdist) const
Definition: TriSurfMesh.h:934
std::vector< index_type > array_type
Definition: TriSurfMesh.h:132
double epsilon2_
Definition: TriSurfMesh.h:1955
boost::unique_lock< boost::mutex > UniqueLock
Definition: ConditionVariable.h:43
double DetMatrix3P(const VectorOfPoints &p)
Inline templated determinant of matrix.
Definition: Locate.h:120
std::vector< std::vector< index_type > > edges_
Definition: TriSurfMesh.h:1931
const string find_type_name(float *)
Definition: TypeName.cc:63
Definition: Mesh.h:72
void node_reserve(size_type s)
Definition: TriSurfMesh.h:600
std::vector< index_type > halfedge_to_edge_
Definition: TriSurfMesh.h:1932
double length2() const
Definition: Vector.h:248
T DetMatrix3x3(const T *p)
Definition: Locate.h:95
FaceIndex< under_type > index_type
Definition: TriSurfMesh.h:136
bool operator()(const std::pair< index_type, index_type > &a, const std::pair< index_type, index_type > &b) const
Definition: TriSurfMesh.h:1996
Definition: Mesh.h:87
static index_type prev(index_type i)
Definition: TriSurfMesh.h:1927
Definition: VMeshShared.h:40
virtual VMesh * vmesh()
Access point to virtual interface.
Definition: TriSurfMesh.h:315
void get_center(Core::Geometry::Point &result, typename Face::index_type idx) const
Definition: TriSurfMesh.h:471
Definition: ParallelLinearAlgebraTests.cc:358
double jacobian_metric(INDEX idx) const
Definition: TriSurfMesh.h:726
double get_size(typename Cell::index_type) const
Definition: TriSurfMesh.h:497
bool locate_edge(INDEX &loc, const Core::Geometry::Point &p) const
Definition: TriSurfMesh.h:1730
Definition: SearchGridT.h:47
TriSurfMesh< Basis >::index_type index_type
Definition: TriSurfMesh.h:163
const char * name[]
Definition: BoostGraphExampleTests.cc:87
double get_length(typename Edge::index_type idx) const
More specific names for get_size.
Definition: TriSurfMesh.h:501
void get_edges(typename Edge::array_type &array, typename Face::index_type idx) const
Definition: TriSurfMesh.h:403
void Pio_index(Piostream &stream, index_type *data, size_type size)
Definition: Persistent.cc:606
long long size_type
Definition: Types.h:40
TriSurfMesh()
Construct a new mesh;.
Definition: TriSurfMesh.h:2070
Definition: MTextFileToTriSurf_Plugin.cc:51
std::vector< index_type > faces_
Definition: TriSurfMesh.h:1933
Definition: StackVector.h:50
bool find_closest_elems(double &pdist, Core::Geometry::Point &result, ARRAY &elems, const Core::Geometry::Point &p) const
Definition: TriSurfMesh.h:1184
Vector Cross(const Vector &v1, const Vector &v2)
Definition: Vector.h:378
double det_jacobian(const VECTOR &coords, INDEX idx) const
Definition: TriSurfMesh.h:637
Definition: TriSurfMesh.h:233
bool find_closest_node(double &pdist, Core::Geometry::Point &result, INDEX &node, const Core::Geometry::Point &p, double maxdist) const
Definition: TriSurfMesh.h:763
Vector diagonal() const
Definition: BBox.h:198
Definition: Mesh.h:81
void begin(typename Node::iterator &) const
begin/end iterators
Definition: TriSurfMesh.h:2236
static index_type next(index_type i)
Definition: TriSurfMesh.h:1926
Definition: Mesh.h:79
std::vector< index_type > array_type
Definition: TriSurfMesh.h:139
Definition: TriQuadraticLgn.h:58
void get_elems(typename Elem::array_type &array, typename Edge::index_type idx) const
Definition: TriSurfMesh.h:428
std::vector< INDEX >::iterator iterator
Definition: SearchGridT.h:53
const Core::Geometry::Point & node0() const
Definition: TriSurfMesh.h:209
mask_type synchronized_
Definition: TriSurfMesh.h:1947
virtual int topology_geometry() const
Definition: TriSurfMesh.h:327
bool get_coords(VECTOR &coords, const Core::Geometry::Point &p, INDEX idx) const
Definition: TriSurfMesh.h:609
Point min() const
Definition: BBox.h:192
Distinct type for face index.
Definition: FieldIndex.h:90
Definition: Mesh.h:62
Definition: QuadSurfMesh.h:2910
int get_weights(const Core::Geometry::Point &, typename Cell::array_type &, double *)
Definition: TriSurfMesh.h:550
Definition: Transform.h:53
void get_cells(typename Cell::array_type &, typename Node::index_type) const
Definition: TriSurfMesh.h:417
void x(double)
Definition: Vector.h:175
void set_nodes_by_elem(ARRAY &array, INDEX idx)
Definition: TriSurfMesh.h:1525
index_type node1_index() const
Definition: TriSurfMesh.h:181
void closest_point_on_tri(Point &result, const Point &orig, const Point &p0, const Point &p1, const Point &p2, const double epsilon)
Definition: CompGeom.cc:136
void to_index(typename Cell::index_type &index, index_type i) const
Definition: TriSurfMesh.h:385
void get_nodes_from_elem(ARRAY &array, INDEX idx) const
Definition: TriSurfMesh.h:1421
void get_faces(typename Face::array_type &array, typename Face::index_type idx) const
Definition: TriSurfMesh.h:412
void pwl_approx_edge(std::vector< VECTOR > &coords, INDEX ci, unsigned int which_edge, unsigned int div_per_unit) const
Definition: TriSurfMesh.h:447
std::vector< index_type > edge_neighbors_
Definition: TriSurfMesh.h:1934
void get_edges_from_elem(ARRAY &array, INDEX idx) const
Definition: TriSurfMesh.h:1441
void get_elem_neighbors(ARRAY &array, INDEX idx) const
Definition: TriSurfMesh.h:1581
virtual MeshFacadeHandle getFacade() const
Definition: TriSurfMesh.h:309
static const std::string make_template_id(const std::string &templateName, const std::string &templateParam)
Definition: TypeName.h:62
void get_delems(typename DElem::array_type &, typename Cell::index_type) const
Definition: TriSurfMesh.h:441
index_type node2_index() const
Definition: TriSurfMesh.h:185
boost::shared_ptr< SearchGridT< index_type > > elem_grid_
Definition: TriSurfMesh.h:1940
v
Definition: readAllFields.py:42
void pre_translate(const Vector &)
Definition: Transform.cc:278
double normalize()
Definition: Vector.h:437
void get_center(Core::Geometry::Point &result, typename Edge::index_type idx) const
Definition: TriSurfMesh.h:469
FaceIndex< under_type > size_type
Definition: TriSurfMesh.h:138
Basis & get_basis()
Get the basis class.
Definition: TriSurfMesh.h:356
double get_epsilon() const
Definition: TriSurfMesh.h:1279
EdgeIterator< under_type > iterator
Definition: TriSurfMesh.h:130
void get_cells(typename Cell::array_type &, typename Cell::index_type) const
Definition: TriSurfMesh.h:423
void get_point(Core::Geometry::Point &result, typename Node::index_type index) const
Access the nodes of the mesh.
Definition: TriSurfMesh.h:554
void y(double)
Definition: Vector.h:185
double safe_normalize()
Definition: Vector.h:236
double distance_to_line2(const Point &p, const Point &a, const Point &b, const double epsilon)
Definition: CompGeom.cc:53
double get_volume(typename Cell::index_type) const
Definition: TriSurfMesh.h:505
Distinct type for edge Iterator.
Definition: FieldIterator.h:105
StackVector< index_type, 4 > array_type
Definition: TriSurfMesh.h:125
Definition: TriLinearLgn.h:324
#define ASSERTFAIL(string)
Definition: Assert.h:52
index_type node0_index() const
Definition: TriSurfMesh.h:177
Definition: TriSurfMesh.h:160
virtual bool is_editable() const
Check whether mesh can be altered by adding nodes or elements.
Definition: TriSurfMesh.h:341
virtual std::string dynamic_type_name() const
Definition: TriSurfMesh.h:1291
Some convenient simple iterators for fields.
Definition: TriSurfMesh.h:128
NodeIndex< under_type > size_type
Definition: TriSurfMesh.h:124
double get_size(typename Node::index_type) const
Get the size of an elemnt (length, area, volume)
Definition: TriSurfMesh.h:477
void get_nodes_from_face(ARRAY &array, INDEX idx) const
Definition: TriSurfMesh.h:1411
void get_delems(typename DElem::array_type &array, typename Face::index_type idx) const
Definition: TriSurfMesh.h:439
Definition: TriSurfMesh.h:142
virtual int basis_order()
Definition: TriSurfMesh.h:319
void operator()()
Definition: TriSurfMesh.h:243
void get_edges_from_face(ARRAY &array, INDEX idx) const
Definition: TriSurfMesh.h:1428
double length() const
Definition: Vector.h:365
Definition: Mesh.h:80
virtual void end_class()
Definition: Persistent.cc:178
Face Elem
Definition: TriSurfMesh.h:151
Core::Thread::Mutex synchronize_lock_
Definition: TriSurfMesh.h:1943
void get_delems(typename DElem::array_type &array, typename Node::index_type idx) const
Definition: TriSurfMesh.h:435
long long index_type
Definition: Types.h:39
bool locate_elem(INDEX &elem, ARRAY &coords, const Core::Geometry::Point &p) const
Definition: TriSurfMesh.h:1826
std::vector< Core::Geometry::Vector > normals_
Definition: TriSurfMesh.h:1935
Definition: Mesh.h:83
Definition: TriSurfMesh.h:135
void get_edges(typename Edge::array_type &, typename Cell::index_type) const
Definition: TriSurfMesh.h:405
double epsilon_
Definition: TriSurfMesh.h:1954
void resize(size_t size, const value_type &val=value_type())
Definition: StackVector.h:61
void get_nodes_from_edge(ARRAY &array, INDEX idx) const
Definition: TriSurfMesh.h:1383
mask_type synchronizing_
Definition: TriSurfMesh.h:1949
static Persistent * maker()
This function returns a maker for Pio.
Definition: TriSurfMesh.h:1303
static const std::string type_name(int n=-1)
Core functionality for getting the name of a templated mesh class.
const Core::Geometry::Point & node1() const
Definition: TriSurfMesh.h:213
void get_nodes(typename Node::array_type &array, typename Edge::index_type idx) const
Definition: TriSurfMesh.h:392
void reset()
Definition: BBox.h:95
Definition: TriSurfMesh.h:1994
Definition: Persistent.h:64
CellIndex< under_type > index_type
Definition: TriSurfMesh.h:143
std::vector< std::vector< index_type > > edge_on_node_
Definition: TriSurfMesh.h:1937
void get_center(Core::Geometry::Point &result, typename Node::index_type idx) const
get the center point (in object space) of an element
Definition: TriSurfMesh.h:467
Edge DElem
Definition: TriSurfMesh.h:152
void pwl_approx_face(std::vector< std::vector< VECTOR > > &coords, INDEX ci, unsigned int which_face, unsigned int div_per_unit) const
Definition: TriSurfMesh.h:458
void get_faces(typename Face::array_type &, typename Cell::index_type) const
Definition: TriSurfMesh.h:414
double get_size(typename Face::index_type idx) const
Definition: TriSurfMesh.h:487
Distinct type for edge index.
Definition: FieldIndex.h:81
virtual int dimensionality() const
Topological dimension.
Definition: TriSurfMesh.h:322
void get_elems(typename Elem::array_type &array, typename Node::index_type idx) const
Definition: TriSurfMesh.h:426
int n
Definition: eab.py:9
bool find_closest_elem(double &pdist, Core::Geometry::Point &result, ARRAY &coords, INDEX &face, const Core::Geometry::Point &p) const
Definition: TriSurfMesh.h:1002
double scaled_jacobian_metric(INDEX idx) const
Definition: TriSurfMesh.h:683
void get_edges(typename Edge::array_type &array, typename Node::index_type idx) const
Definition: TriSurfMesh.h:399
void jacobian(const VECTOR &coords, INDEX idx, double *J) const
Definition: TriSurfMesh.h:648
bool get_elem_neighbors(ARRAY &array, INDEX1 elem, INDEX2 delem) const
Definition: TriSurfMesh.h:1556
void get_edges(typename Edge::array_type &array, typename Edge::index_type idx) const
Definition: TriSurfMesh.h:401
SCIRun::mask_type mask_type
Definition: TriSurfMesh.h:115
std::map< std::pair< index_type, index_type >, std::vector< index_type >, edgecompare > EdgeMapType2
Definition: TriSurfMesh.h:2028
EdgeIndex< under_type > index_type
Definition: TriSurfMesh.h:129
void Pio(Piostream &stream, BBox &box)
Definition: BBox.cc:134
EdgeIndex< under_type > size_type
Definition: TriSurfMesh.h:131
#define DEBUG_CONSTRUCTOR(type)
Definition: Debug.h:64
void set_point(const Core::Geometry::Point &point, typename Node::index_type index)
Definition: TriSurfMesh.h:556
void get_elems(typename Face::array_type &, typename Cell::index_type) const
Definition: TriSurfMesh.h:432
std::map< std::pair< index_type, index_type >, index_type, edgecompare > EdgeMapType
Definition: TriSurfMesh.h:2014
Synchronize(TriSurfMesh< Basis > *mesh, mask_type sync)
Definition: TriSurfMesh.h:236
void z(double)
Definition: Vector.h:195
boost::shared_ptr< MeshFacade< VMesh > > MeshFacadeHandle
Definition: MeshTraits.h:61
void elem_reserve(size_type s)
Definition: TriSurfMesh.h:601
const Core::Geometry::Point & point(typename Node::index_type i)
Definition: TriSurfMesh.h:1356
Definition: VMesh.h:53
void get_faces_from_node(ARRAY &array, INDEX idx) const
Definition: TriSurfMesh.h:1448
CellIterator< under_type > iterator
Definition: TriSurfMesh.h:144
bool find_closest_nodes(ARRAY &nodes, const Core::Geometry::Point &p, double maxdist) const
Definition: TriSurfMesh.h:870
bool locate(typename Face::index_type &loc, const Core::Geometry::Point &p) const
Definition: TriSurfMesh.h:534
NodeIterator< under_type > iterator
Definition: TriSurfMesh.h:123
void get_neighbors(typename Elem::array_type &array, typename Elem::index_type elem) const
Definition: TriSurfMesh.h:525
int size
Definition: eabLatVolData.py:2
bool locate_elems(ARRAY &array, const Core::Geometry::BBox &b) const
Definition: TriSurfMesh.h:1796
void get_node_center(Core::Geometry::Point &p, INDEX idx) const
Definition: TriSurfMesh.h:1870
void get_normal(Core::Geometry::Vector &result, typename Node::index_type index) const
Normals for visualizations.
Definition: TriSurfMesh.h:562
Core::Thread::ConditionVariable synchronize_cond_
Definition: TriSurfMesh.h:1944
#define DEBUG_DESTRUCTOR(type)
Definition: Debug.h:65
const TypeDescription * get_type_description(Core::Basis::ConstantBasis< T > *)
Definition: Constant.h:209
bool locate(typename Node::index_type &loc, const Core::Geometry::Point &p) const
Locate a point in a mesh, find which is the closest node.
Definition: TriSurfMesh.h:530
void get_nodes(typename Node::array_type &array, typename Node::index_type idx) const
Get the child elements of the given index.
Definition: TriSurfMesh.h:390
bool elem_locate(INDEX &elem, MESH &msh, const Core::Geometry::Point &p)
General case locate, search each elem.
Definition: Mesh.h:188
void get_faces_from_edge(ARRAY &array, INDEX idx) const
Definition: TriSurfMesh.h:1460
void to_index(typename Node::index_type &index, index_type i) const
Definition: TriSurfMesh.h:379