cherish
Entity2DIntersector.h
1 #ifndef ENTITY2DINTERSECTOR_H
2 #define ENTITY2DINTERSECTOR_H
3 
4 #include <vector>
5 
6 #include <osg/ref_ptr>
7 #include <osgUtil/LineSegmentIntersector>
8 
9 #include "Utilities.h"
10 
11 // TODO: instead of using intersectors for each entity type, use this one with
12 // provided template, e.g. entity::Stroke, entity::Photo, etc.
13 
14 template <typename EntityType>
15 class Entity2DIntersector : public osgUtil::LineSegmentIntersector
16 {
17 public:
19  : osgUtil::LineSegmentIntersector(MODEL, 0.f, 0.f)
20  , m_offset(0.05f)
21  {
22  m_hitIndices.clear();
23  }
24 
25  Entity2DIntersector(const osg::Vec3& start, const osg::Vec3& end)
26  : osgUtil::LineSegmentIntersector(start, end)
27  , m_offset(0.05f)
28  {
29  m_hitIndices.clear();
30  }
31 
32  Entity2DIntersector(CoordinateFrame cf, double x, double y)
33  : osgUtil::LineSegmentIntersector(cf, x, y)
34  , m_offset(0.05f)
35  {
36  m_hitIndices.clear();
37  }
38 
39  Entity2DIntersector(CoordinateFrame cf, const osg::Vec3d& start, const osg::Vec3d& end)
40  : osgUtil::LineSegmentIntersector(cf, start, end)
41  , m_offset(0.05f)
42  {
43  m_hitIndices.clear();
44  }
45 
46  void setOffset(float offset)
47  {
48  m_offset = offset;
49  }
50 
51  float getOffset() const
52  {
53  return m_offset;
54  }
55 
56  void getHitIndices(int& first, int& last) const
57  {
58  if (m_hitIndices.empty()){
59  first = -1;
60  last = -1;
61  }
62  else {
63  first = m_hitIndices.front();
64  last = m_hitIndices.back();
65  }
66  }
67 
68  virtual Intersector* clone( osgUtil::IntersectionVisitor& iv )
69  {
70  if ( _coordinateFrame==MODEL && iv.getModelMatrix()==0 )
71  {
72  osg::ref_ptr<Entity2DIntersector> cloned = new Entity2DIntersector( _start, _end );
73  cloned->_parent = this;
74  cloned->m_offset = m_offset;
75  return cloned.release();
76  }
77 
78  osg::Matrix matrix;
79  switch ( _coordinateFrame )
80  {
81  case WINDOW:
82  if (iv.getWindowMatrix()) matrix.preMult( *iv.getWindowMatrix() );
83  if (iv.getProjectionMatrix()) matrix.preMult( *iv.getProjectionMatrix() );
84  if (iv.getViewMatrix()) matrix.preMult( *iv.getViewMatrix() );
85  if (iv.getModelMatrix()) matrix.preMult( *iv.getModelMatrix() );
86  break;
87  case PROJECTION:
88  if (iv.getProjectionMatrix()) matrix.preMult( *iv.getProjectionMatrix() );
89  if (iv.getViewMatrix()) matrix.preMult( *iv.getViewMatrix() );
90  if (iv.getModelMatrix()) matrix.preMult( *iv.getModelMatrix() );
91  break;
92  case VIEW:
93  if (iv.getViewMatrix()) matrix.preMult( *iv.getViewMatrix() );
94  if (iv.getModelMatrix()) matrix.preMult( *iv.getModelMatrix() );
95  break;
96  case MODEL:
97  if (iv.getModelMatrix()) matrix = *iv.getModelMatrix();
98  break;
99  }
100 
101  osg::Matrix inverse = osg::Matrix::inverse(matrix);
102  osg::ref_ptr<Entity2DIntersector> cloned = new Entity2DIntersector( _start*inverse, _end*inverse );
103  cloned->_parent = this;
104  cloned->m_offset = m_offset;
105  return cloned.release();
106  }
107 
108  virtual void intersect( osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable )
109  {
110  osg::BoundingBox bb = drawable->getBoundingBox();
111  bb.xMin() -= m_offset; bb.xMax() += m_offset;
112  bb.yMin() -= m_offset; bb.yMax() += m_offset;
113  bb.zMin() -= m_offset; bb.zMax() += m_offset;
114 
115  osg::Vec3d s(_start), e(_end);
116  if (!intersectAndClip(s, e, bb)) return;
117  if (iv.getDoDummyTraversal()) return;
118 
119  EntityType* geometry = dynamic_cast<EntityType*>(drawable->asGeometry());
120  if (geometry)
121  {
122  osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
123  if (!vertices) return;
124 
125  for (unsigned int i=1; i<vertices->size(); ++i)
126  {
127 
128  double distance = Utilities::getSkewLinesDistance(s,e,(*vertices)[i], (*vertices)[i-1]);
129 
130  if (m_offset<distance) continue;
131 
132  Intersection hit;
133  hit.ratio = distance;
134  hit.nodePath = iv.getNodePath();
135  hit.drawable = drawable;
136  hit.matrix = iv.getModelMatrix();
137  hit.localIntersectionPoint = (*vertices)[i];
138  m_hitIndices.push_back(i);
139  insertIntersection(hit);
140  }
141  }
142  }
143 
144 protected:
145  virtual ~Entity2DIntersector(){}
146 
147 private:
148  float m_offset;
149  std::vector<unsigned int> m_hitIndices;
150 };
151 
152 #endif // ENTITY2DINTERSECTOR_H
static double getSkewLinesDistance(const osg::Vec3d &r1, const osg::Vec3d &r2, const osg::Vec3d &v1, const osg::Vec3d &v2)
Definition: Utilities.cpp:271
Definition: Entity2DIntersector.h:15