00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #ifndef LASS_GUARDIAN_OF_INCLUSION_SPAT_MESH_INTERPOLATOR_H
00053 #define LASS_GUARDIAN_OF_INCLUSION_SPAT_MESH_INTERPOLATOR_H
00054
00055 #include "spat_common.h"
00056 #include "planar_mesh.h"
00057 #include "../meta/null_type.h"
00058
00059 namespace lass
00060 {
00061 namespace spat
00062 {
00063
00064
00065 template<typename T>
00066 void barycenters( const prim::Point2D<T>& q, const prim::Point2D<T>& a, const prim::Point2D<T>& b, const prim::Point2D<T>& c,
00067 T& bA, T& bB, T& bC )
00068 {
00069 typedef prim::Vector2D<T> TVector2D;
00070
00071 TVector2D v02 = a-c;
00072 TVector2D v12 = b-c;
00073 TVector2D vq2 = q-c;
00074
00075 T m00 = dot(v02,v02);
00076 T m01 = dot(v02,v12);
00077 T m11 = dot(v12,v12);
00078 T r0 = dot(v02,vq2);
00079 T r1 = dot(v12,vq2);
00080 T det = m00*m11-m01*m01;
00081
00082 LASS_ASSERT( det != 0 );
00083
00084 T invDet = static_cast<T>(1)/det;
00085
00086 bA = (m11*r0-m01*r1)*invDet;
00087 bB = (m00*r1-m01*r0)*invDet;
00088 bC = static_cast<T>(1) - bA - bB;
00089 }
00090
00091
00092 template<typename T, typename TPI>
00093 class MeshInterpolator
00094 {
00095 public:
00096 typedef prim::Aabb2D<T> TAabb2D;
00097 public:
00098 typedef PlanarMesh<T, TPI*, meta::EmptyType , meta::EmptyType > TPlanarMesh;
00099 typedef typename TPlanarMesh::TPoint2D TPoint2D;
00100 typedef std::vector<TPoint2D> TPolyLine2D;
00101
00102 MeshInterpolator( const TAabb2D& iAabb );
00103 virtual ~MeshInterpolator() {}
00104
00105 const TPlanarMesh& mesh() const { return mesh_; }
00106 const TAabb2D& aabb() const { return aabb_; }
00107
00108 virtual void insertSite( const TPoint2D& iPoint, const TPI& iPointInfo );
00109 virtual void insertPolyLine( const TPolyLine2D& iPoly, const TPI& iPointInfo );
00110 virtual TPI interpolate( const TPoint2D& iQuery ) const = 0;
00111 template <typename OutputIterator> OutputIterator interpolate( const TPolyLine2D& iQuery, OutputIterator oOutput ) const;
00112 protected:
00113 MeshInterpolator() {}
00114
00115 typedef std::deque<TPI> TInfoList;
00116 TInfoList& info() { return info_; }
00117
00118 private:
00119 TPlanarMesh mesh_;
00120 TAabb2D aabb_;
00121
00122 TInfoList info_;
00123 };
00124
00125
00126 template<typename T, typename TPI>
00127 MeshInterpolator<T,TPI>::MeshInterpolator( const TAabb2D& iAabb ) : mesh_( iAabb )
00128 {
00129 aabb_ = iAabb;
00130 }
00131
00132 template<typename T, typename TPI>
00133 void MeshInterpolator<T,TPI>::insertSite( const TPoint2D& iPoint, const TPI& iPointInfo )
00134 {
00135 if (!aabb_.contains( iPoint ))
00136 {
00137 LASS_THROW("MeshInterpolator: cannot insert point outside bounding box");
00138 }
00139
00140 typename TPlanarMesh::TEdge* e = mesh_.insertSite( iPoint );
00141
00142
00143
00144 info_.push_back( iPointInfo );
00145 TPlanarMesh::setPointHandle( e, &info_.back() );
00146 }
00147
00148 template<typename T, typename TPI>
00149 void MeshInterpolator<T,TPI>::insertPolyLine( const TPolyLine2D& iPoly, const TPI& iPointInfo )
00150 {
00151 if (iPoly.size() < 2)
00152 {
00153 LASS_THROW("MeshInterpolator: A poly line needs at least two vertices ... poly, remember?");
00154 }
00155
00156 for (size_t i = 0; i < iPoly.size(); ++i)
00157 {
00158 if (!aabb_.contains( iPoly[i] ))
00159 {
00160 LASS_THROW("MeshInterpolator: cannot insert point outside bounding box");
00161 }
00162 }
00163
00164 info_.push_back( iPointInfo );
00165 for (size_t i = 1; i < iPoly.size(); ++i)
00166 {
00167 mesh_.insertEdge(typename TPlanarMesh::TLineSegment2D(iPoly[i - 1], iPoly[i]), meta::EmptyType(),meta::EmptyType(),&info_.back(), true);
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 template<typename T, typename TPI>
00193 class LinearMeshInterpolator : public MeshInterpolator<T,TPI>
00194 {
00195 public:
00196 typedef typename MeshInterpolator<T,TPI>::TPoint2D TPoint2D;
00197 typedef typename MeshInterpolator<T,TPI>::TAabb2D TAabb2D;
00198 typedef typename MeshInterpolator<T,TPI>::TPolyLine2D TPolyLine2D;
00199 typedef typename MeshInterpolator<T,TPI>::TPlanarMesh TPlanarMesh;
00200
00201 LinearMeshInterpolator( const TAabb2D& iAabb, const TPI& iValueOutside );
00202 virtual ~LinearMeshInterpolator() {}
00203 virtual TPI interpolate( const TPoint2D& iQuery ) const;
00204 template <typename OutputIterator> OutputIterator interpolate( const TPolyLine2D& iQuery, OutputIterator oOutput ) const;
00205
00206 private:
00207 LinearMeshInterpolator() {}
00208 virtual TPI interpolate( const TPoint2D& iQuery, typename TPlanarMesh::TEdge* iEdge ) const;
00209 TPI valueOutside_;
00210 };
00211
00212
00213 template<typename T, typename TPI>
00214 LinearMeshInterpolator<T,TPI>::LinearMeshInterpolator( const TAabb2D& iAabb, const TPI& iValueOutside ) : MeshInterpolator<T,TPI>( iAabb )
00215 {
00216 valueOutside_ = iValueOutside;
00217 TPoint2D topleft( iAabb.min().x, iAabb.max().y );
00218 TPoint2D topright( iAabb.max().x, iAabb.max().y );
00219 TPoint2D bottomleft( iAabb.min().x, iAabb.min().y );
00220 TPoint2D bottomright( iAabb.max().x, iAabb.min().y );
00221
00222 typename TPlanarMesh::TEdge* e;
00223
00224 this->info().push_back(iValueOutside);
00225
00226 e = this->mesh().locate(topleft);
00227 LASS_ASSERT(TPlanarMesh::org(e) == topleft);
00228 TPlanarMesh::setPointHandle(e, &this->info().back());
00229
00230 e = this->mesh().locate(topright);
00231 LASS_ASSERT(TPlanarMesh::org(e) == topright);
00232 TPlanarMesh::setPointHandle( e, &this->info().back() );
00233
00234 e = this->mesh().locate(bottomleft);
00235 LASS_ASSERT(TPlanarMesh::org(e) == bottomleft);
00236 TPlanarMesh::setPointHandle(e, &this->info().back());
00237
00238 e = this->mesh().locate(bottomright);
00239 LASS_ASSERT(TPlanarMesh::org(e) == bottomright);
00240 TPlanarMesh::setPointHandle( e, &this->info().back() );
00241
00242 }
00243
00244 template<typename T, typename TPI>
00245 TPI LinearMeshInterpolator<T,TPI>::interpolate( const TPoint2D& iQuery, typename TPlanarMesh::TEdge* e ) const
00246 {
00247 if (!this->aabb().contains(iQuery))
00248 return valueOutside_;
00249
00250 TPoint2D a = TPlanarMesh::fastOrg(e);
00251 TPoint2D b = TPlanarMesh::fastDest(e);
00252 TPoint2D c = TPlanarMesh::fastDest(e->lNext());
00253
00254 TPI* ia = TPlanarMesh::pointHandle(e);
00255 TPI* ib = TPlanarMesh::pointHandle(e->lNext());
00256 TPI* ic = TPlanarMesh::pointHandle(e->lNext()->lNext());
00257
00258 T ba,bb,bc;
00259
00260 barycenters(iQuery, a, b, c, ba, bb, bc);
00261
00262 return (*ia)*ba+(*ib)*bb+(*ic)*bc;
00263 }
00264
00265
00266 template<typename T, typename TPI>
00267 TPI LinearMeshInterpolator<T,TPI>::interpolate( const TPoint2D& iQuery ) const
00268 {
00269 typename TPlanarMesh::TEdge* e = this->mesh().locate(iQuery);
00270 if (this->mesh().isBoundingPoint(TPlanarMesh::fastOrg(e)) && !TPlanarMesh::hasLeftFace(e))
00271 e = e->sym();
00272 return interpolate(iQuery,e);
00273 }
00274
00275 template<typename T, typename TPI>
00276 template <typename OutputIterator>
00277 OutputIterator LinearMeshInterpolator<T,TPI>::interpolate( const TPolyLine2D& iQuery, OutputIterator oOutput ) const
00278 {
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 LASS_ENFORCE(iQuery.size()>1);
00289 typedef std::pair<TPoint2D, typename TPlanarMesh::TEdge*> TPointEdgePair;
00290 std::vector<TPointEdgePair> crossings;
00291
00292 for (size_t i=0;i<iQuery.size()-1;++i)
00293 {
00294 crossings.push_back(TPointEdgePair(iQuery[i],this->mesh().locate(iQuery[i])));
00295 this->mesh().walkIntersections(typename TPlanarMesh::TLineSegment2D(iQuery[i],iQuery[i+1]),
00296 std::back_inserter(crossings));
00297 }
00298 crossings.push_back(TPointEdgePair(iQuery.back(),this->mesh().locate(iQuery.back())));
00299
00300 TPoint2D lastInterpolate = crossings[0].first;
00301 typename TPlanarMesh::TEdge* interpEdge = crossings[0].second;
00302 if (this->mesh().isBoundingPoint(TPlanarMesh::fastOrg(interpEdge)) && !TPlanarMesh::hasLeftFace(interpEdge))
00303 interpEdge = interpEdge->sym();
00304 (*oOutput++) = std::pair<TPoint2D, TPI>(crossings[0].first,interpolate(crossings[0].first,interpEdge));
00305 for (size_t i=1;i<crossings.size();++i)
00306 {
00307 if (crossings[i].first!=lastInterpolate)
00308 {
00309 interpEdge = crossings[i].second;
00310 if (this->mesh().isBoundingPoint(TPlanarMesh::fastOrg(interpEdge)) && !TPlanarMesh::hasLeftFace(interpEdge))
00311 interpEdge = interpEdge->sym();
00312 (*oOutput++) = std::pair<TPoint2D, TPI>(crossings[i].first,interpolate(crossings[i].first,crossings[i].second ));
00313 lastInterpolate = crossings[i].first;
00314 }
00315 }
00316 return oOutput;
00317 }
00318
00319
00320 }
00321 }
00322 #endif