52#ifndef LASS_GUARDIAN_OF_INCLUSION_SPAT_MESH_INTERPOLATOR_H
53#define LASS_GUARDIAN_OF_INCLUSION_SPAT_MESH_INTERPOLATOR_H
66void barycenters(
const prim::Point2D<T>& q,
const prim::Point2D<T>& a,
const prim::Point2D<T>& b,
const prim::Point2D<T>& c,
69 typedef prim::Vector2D<T> TVector2D;
80 T det = m00*m11-m01*m01;
82 LASS_ASSERT( det != 0 );
84 T invDet =
static_cast<T
>(1)/det;
86 bA = (m11*r0-m01*r1)*invDet;
87 bB = (m00*r1-m01*r0)*invDet;
88 bC =
static_cast<T
>(1) - bA - bB;
92template<
typename T,
typename TPI>
99 typedef typename TPlanarMesh::TPoint2D TPoint2D;
100 typedef std::vector<TPoint2D> TPolyLine2D;
102 MeshInterpolator(
const TAabb2D& iAabb );
103 virtual ~MeshInterpolator() {}
105 const TPlanarMesh& mesh()
const {
return mesh_; }
106 const TAabb2D& aabb()
const {
return aabb_; }
108 virtual void insertSite(
const TPoint2D& iPoint,
const TPI& iPointInfo );
109 virtual void insertPolyLine(
const TPolyLine2D& iPoly,
const TPI& iPointInfo );
110 virtual TPI interpolate(
const TPoint2D& iQuery )
const = 0;
111 template <
typename OutputIterator> OutputIterator interpolate(
const TPolyLine2D& iQuery, OutputIterator oOutput )
const;
113 MeshInterpolator() {}
126template<
typename T,
typename TPI>
127MeshInterpolator<T,TPI>::MeshInterpolator(
const TAabb2D& iAabb ) : mesh_( iAabb )
132template<
typename T,
typename TPI>
133void MeshInterpolator<T,TPI>::insertSite(
const TPoint2D& iPoint,
const TPI& iPointInfo )
135 if (!aabb_.contains( iPoint ))
137 LASS_THROW(
"MeshInterpolator: cannot insert point outside bounding box");
140 typename TPlanarMesh::TEdge* e = mesh_.insertSite( iPoint );
144 info_.push_back( iPointInfo );
145 TPlanarMesh::setPointHandle( e, &info_.back() );
148template<
typename T,
typename TPI>
149void MeshInterpolator<T,TPI>::insertPolyLine(
const TPolyLine2D& iPoly,
const TPI& iPointInfo )
151 if (iPoly.size() < 2)
153 LASS_THROW(
"MeshInterpolator: A poly line needs at least two vertices ... poly, remember?");
156 for (
size_t i = 0; i < iPoly.size(); ++i)
158 if (!aabb_.contains( iPoly[i] ))
160 LASS_THROW(
"MeshInterpolator: cannot insert point outside bounding box");
164 info_.push_back( iPointInfo );
165 for (
size_t i = 1; i < iPoly.size(); ++i)
167 mesh_.insertEdge(
typename TPlanarMesh::TLineSegment2D(iPoly[i - 1], iPoly[i]), meta::EmptyType(),meta::EmptyType(),&info_.back(),
true);
192template<
typename T,
typename TPI>
193class LinearMeshInterpolator :
public MeshInterpolator<T,TPI>
196 typedef typename MeshInterpolator<T,TPI>::TPoint2D TPoint2D;
197 typedef typename MeshInterpolator<T,TPI>::TAabb2D TAabb2D;
198 typedef typename MeshInterpolator<T,TPI>::TPolyLine2D TPolyLine2D;
199 typedef typename MeshInterpolator<T,TPI>::TPlanarMesh TPlanarMesh;
201 LinearMeshInterpolator(
const TAabb2D& iAabb,
const TPI& iValueOutside );
202 virtual ~LinearMeshInterpolator() {}
203 TPI interpolate(
const TPoint2D& iQuery )
const override;
204 template <
typename OutputIterator> OutputIterator interpolate(
const TPolyLine2D& iQuery, OutputIterator oOutput )
const;
207 LinearMeshInterpolator() {}
208 virtual TPI interpolate(
const TPoint2D& iQuery,
typename TPlanarMesh::TEdge* iEdge )
const;
213template<
typename T,
typename TPI>
214LinearMeshInterpolator<T,TPI>::LinearMeshInterpolator(
const TAabb2D& iAabb,
const TPI& iValueOutside ) :
MeshInterpolator<T,TPI>( iAabb )
216 valueOutside_ = iValueOutside;
217 TPoint2D topleft( iAabb.min().x, iAabb.max().y );
218 TPoint2D topright( iAabb.max().x, iAabb.max().y );
219 TPoint2D bottomleft( iAabb.min().x, iAabb.min().y );
220 TPoint2D bottomright( iAabb.max().x, iAabb.min().y );
222 typename TPlanarMesh::TEdge* e;
224 this->info().push_back(iValueOutside);
226 e = this->mesh().
locate(topleft);
227 LASS_ASSERT(TPlanarMesh::org(e) == topleft);
228 TPlanarMesh::setPointHandle(e, &this->info().back());
230 e = this->mesh().
locate(topright);
231 LASS_ASSERT(TPlanarMesh::org(e) == topright);
232 TPlanarMesh::setPointHandle( e, &this->info().back() );
234 e = this->mesh().
locate(bottomleft);
235 LASS_ASSERT(TPlanarMesh::org(e) == bottomleft);
236 TPlanarMesh::setPointHandle(e, &this->info().back());
238 e = this->mesh().
locate(bottomright);
239 LASS_ASSERT(TPlanarMesh::org(e) == bottomright);
240 TPlanarMesh::setPointHandle( e, &this->info().back() );
244template<
typename T,
typename TPI>
245TPI LinearMeshInterpolator<T,TPI>::interpolate(
const TPoint2D& iQuery,
typename TPlanarMesh::TEdge* e )
const
247 if (!this->aabb().contains(iQuery))
248 return valueOutside_;
250 TPoint2D a = TPlanarMesh::fastOrg(e);
251 TPoint2D b = TPlanarMesh::fastDest(e);
252 TPoint2D c = TPlanarMesh::fastDest(e->lNext());
254 TPI* ia = TPlanarMesh::pointHandle(e);
255 TPI* ib = TPlanarMesh::pointHandle(e->lNext());
256 TPI* ic = TPlanarMesh::pointHandle(e->lNext()->lNext());
260 barycenters(iQuery, a, b, c, ba, bb, bc);
262 return (*ia)*ba+(*ib)*bb+(*ic)*bc;
266template<
typename T,
typename TPI>
267TPI LinearMeshInterpolator<T,TPI>::interpolate(
const TPoint2D& iQuery )
const
269 typename TPlanarMesh::TEdge* e = this->mesh().locate(iQuery);
270 if (this->mesh().isBoundingPoint(TPlanarMesh::fastOrg(e)) && !TPlanarMesh::hasLeftFace(e))
272 return interpolate(iQuery,e);
275template<
typename T,
typename TPI>
276template <
typename OutputIterator>
277OutputIterator LinearMeshInterpolator<T,TPI>::interpolate(
const TPolyLine2D& iQuery, OutputIterator oOutput )
const
288 LASS_ENFORCE(iQuery.size()>1);
289 typedef std::pair<TPoint2D, typename TPlanarMesh::TEdge*> TPointEdgePair;
290 std::vector<TPointEdgePair> crossings;
292 for (
size_t i=0;i<iQuery.size()-1;++i)
294 crossings.push_back(TPointEdgePair(iQuery[i],this->mesh().locate(iQuery[i])));
295 this->mesh().walkIntersections(
typename TPlanarMesh::TLineSegment2D(iQuery[i],iQuery[i+1]),
296 std::back_inserter(crossings));
298 crossings.push_back(TPointEdgePair(iQuery.back(),this->mesh().locate(iQuery.back())));
300 TPoint2D lastInterpolate = crossings[0].first;
301 typename TPlanarMesh::TEdge* interpEdge = crossings[0].second;
302 if (this->mesh().isBoundingPoint(TPlanarMesh::fastOrg(interpEdge)) && !TPlanarMesh::hasLeftFace(interpEdge))
303 interpEdge = interpEdge->sym();
304 (*oOutput++) = std::pair<TPoint2D, TPI>(crossings[0].first,interpolate(crossings[0].first,interpEdge));
305 for (
size_t i=1;i<crossings.size();++i)
307 if (crossings[i].first!=lastInterpolate)
309 interpEdge = crossings[i].second;
310 if (this->mesh().isBoundingPoint(TPlanarMesh::fastOrg(interpEdge)) && !TPlanarMesh::hasLeftFace(interpEdge))
311 interpEdge = interpEdge->sym();
312 (*oOutput++) = std::pair<TPoint2D, TPI>(crossings[i].first,interpolate(crossings[i].first,crossings[i].second ));
313 lastInterpolate = crossings[i].first;
your momma's axis aligned bounding box.
std::deque< TPI > TInfoList
type must support stable iterators
TEdge * locate(const TPoint2D &iPoint, TEdge *iHint=0) const
locate an edge of the triangle containing iPoint
spatial subdivisions, quadtrees, octrees, meshes in 2D and 3D, triangulators, ...
Library for Assembled Shared Sources.