00001
00002
00003
00004
00005
00006
00007 #ifndef _PHYSSIM_ADF_H_
00008 #define _PHYSSIM_ADF_H_
00009
00010 #include <boost/shared_ptr.hpp>
00011 #include <boost/enable_shared_from_this.hpp>
00012 #include <list>
00013 #include <vector>
00014 #include <Physsim/Types.h>
00015 #include <Physsim/TriangleMesh.h>
00016 #include <Physsim/Vector3.h>
00017
00018 namespace Physsim {
00019
00021 class ADF : public boost::enable_shared_from_this<ADF>
00022 {
00023 public:
00024 ADF();
00025 ADF(boost::shared_ptr<ADF> parent, unsigned recursion_level, const Vector3& lo_bounds, const Vector3& hi_bounds);
00026 ADF(boost::shared_ptr<ADF> parent, unsigned recursion_level, const std::vector<Vector3ConstPtr>& vertices);
00027 Real calc_signed_distance(const Vector3& point) const;
00028 const std::vector<Vector3ConstPtr>& get_vertices() const { return _vertices; }
00029 void set_distances(const std::vector<Real>& distances);
00030
00031 template <class ForwardIterator>
00032 void set_distances(ForwardIterator first, ForwardIterator last);
00033 void get_samples(std::vector<Vector3>& samples) const;
00034 void reset();
00035 void simplify(Real epsilon);
00036 void get_bounds(Vector3& lo, Vector3& hi) const;
00037 void set_bounds(const Vector3& lo_bound, const Vector3& hi_bound);
00038 static boost::shared_ptr<ADF> build_ADF_iso_inside_focus(const std::vector<TriangleConstPtr>& mesh, unsigned max_recursion, Real epsilon);
00039 const std::vector<Real>& get_distances() const { return _distances; }
00040 static boost::shared_ptr<ADF> intersect(boost::shared_ptr<ADF> adf1, boost::shared_ptr<ADF> adf2, Real epsilon, unsigned recursion_limit);
00041 bool contains(const Vector3& point) const;
00042 unsigned count_cells() const;
00043 bool generate_iso_sample(Vector3& sample, Real epsilon) const;
00044 void get_all_leaf_nodes(std::list<boost::shared_ptr<ADF> >& leafs) const;
00045 void get_all_cells(std::list<boost::shared_ptr<ADF> >& cells) const;
00046 void determine_normal(const Vector3& point, Vector3& normal) const;
00047 bool intersect_seg_iso_surface(const std::pair<Vector3, Vector3>& seg, Vector3& isect) const;
00048
00050 void set_parent(boost::shared_ptr<ADF> parent) { _parent = parent; }
00051
00053 boost::shared_ptr<ADF> get_parent() const { return (_parent.expired()) ? boost::shared_ptr<ADF>() : boost::shared_ptr<ADF>(_parent); }
00054
00056 bool is_leaf() const { return _children.empty(); }
00057
00059 unsigned get_recursion_level() const { return _recursion_level; }
00060
00062 void set_recursion_level(unsigned level) { _recursion_level = level; }
00063
00065 void subdivide();
00066
00068 const std::vector<boost::shared_ptr<ADF> >& get_children() const { return _children; }
00069
00070 private:
00071 static Real calc_max_distance(boost::shared_ptr<ADF> adf1, boost::shared_ptr<ADF> adf2, const Vector3& point);
00072 static Real tri_linear_interp(const std::vector<Vector3ConstPtr>& x, const std::vector<Real>& q, const Vector3& p);
00073 boost::shared_ptr<ADF> is_cell_occupied(const Vector3& point) const;
00074 unsigned get_sub_volume_idx(const Vector3& point) const;
00075
00076 static const unsigned OCT_CHILDREN = 8;
00077 static const unsigned BOX_VERTICES = 8;
00078 std::vector<boost::shared_ptr<ADF> > _children;
00079 boost::weak_ptr<ADF> _parent;
00080 std::vector<Vector3ConstPtr> _vertices;
00081 unsigned _recursion_level;
00082 std::vector<Real> _distances;
00083 Vector3 _lo_bounds, _hi_bounds;
00084 };
00085
00086 std::ostream& operator<<(std::ostream& out, const ADF& adf);
00087
00088
00089
00090
00091
00093
00097 template <class ForwardIterator>
00098 void ADF::set_distances(ForwardIterator first, ForwardIterator last)
00099 {
00100
00101 _distances = std::vector<Real>(BOX_VERTICES);
00102
00103
00104 for (unsigned i=0; i< BOX_VERTICES; i++)
00105 _distances[i] = TriangleMesh::calc_signed_distance(first, last, *_vertices[i]);
00106 }
00107
00108 }
00109
00110 #endif
00111