library of assembled shared sources

http://lass.cocamware.com

mesh_interpolator.h

Go to the documentation of this file.
00001 /** @file
00002  *  @author Bram de Greve (bramz@users.sourceforge.net)
00003  *  @author Tom De Muer (tomdemuer@users.sourceforge.net)
00004  *
00005  *  *** BEGIN LICENSE INFORMATION ***
00006  *  
00007  *  The contents of this file are subject to the Common Public Attribution License 
00008  *  Version 1.0 (the "License"); you may not use this file except in compliance with 
00009  *  the License. You may obtain a copy of the License at 
00010  *  http://lass.sourceforge.net/cpal-license. The License is based on the 
00011  *  Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 
00012  *  use of software over a computer network and provide for limited attribution for 
00013  *  the Original Developer. In addition, Exhibit A has been modified to be consistent 
00014  *  with Exhibit B.
00015  *  
00016  *  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 
00017  *  WARRANTY OF ANY KIND, either express or implied. See the License for the specific 
00018  *  language governing rights and limitations under the License.
00019  *  
00020  *  The Original Code is LASS - Library of Assembled Shared Sources.
00021  *  
00022  *  The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
00023  *  The Original Developer is the Initial Developer.
00024  *  
00025  *  All portions of the code written by the Initial Developer are:
00026  *  Copyright (C) 2004-2007 the Initial Developer.
00027  *  All Rights Reserved.
00028  *  
00029  *  Contributor(s):
00030  *
00031  *  Alternatively, the contents of this file may be used under the terms of the 
00032  *  GNU General Public License Version 2 or later (the GPL), in which case the 
00033  *  provisions of GPL are applicable instead of those above.  If you wish to allow use
00034  *  of your version of this file only under the terms of the GPL and not to allow 
00035  *  others to use your version of this file under the CPAL, indicate your decision by 
00036  *  deleting the provisions above and replace them with the notice and other 
00037  *  provisions required by the GPL License. If you do not delete the provisions above,
00038  *  a recipient may use your version of this file under either the CPAL or the GPL.
00039  *  
00040  *  *** END LICENSE INFORMATION ***
00041  */
00042 
00043 
00044 
00045 /** @class lass::spat::MeshInterpolator
00046  *  Interface for interpolators on meshes.
00047  *  @brief a planar mesh
00048  *  @author Tom De Muer [TDM]
00049  *  @relates PlanarMesh
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;    /**< type must support stable iterators */
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     //e = mesh_.locate( iPoint );
00142     //LASS_ASSERT( TPlanarMesh::org(e) == iPoint );
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     for (size_t i = 0; i < iPoly.size(); ++i)
00172     {
00173         typename TPlanarMesh::TEdge* e = mesh_.locate(iPoly[i]);
00174         LASS_ASSERT(TPlanarMesh::org(e) == iPoly[i]);
00175         TPlanarMesh::setPointHandle(e, &info_.back());
00176     }
00177     */
00178 }
00179 
00180 
00181 /** @class lass::spat::LinearMeshInterpolator
00182  *  Interpolator working on triangulated mesh.  Interpolation is done linearly by finding a
00183  *  triangle containing the point of interest.  Via barycentric coordinates the linear weighted
00184  *  interpolation is performed and returned.
00185  *  Buildup of mesh is incremental so after querying for interpolation new points can be inserted.
00186  *  @brief a linear interpolator using planar meshes
00187  *  @author Tom De Muer [TDM]
00188  *  @relates PlanarMesh
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     /* This function can be optimized.  What is done now is compute all intersection points from a poly line with
00280        the mesh.  Subsequent for all these points the interpolated value is determined.  Each of these subsequent interpolations
00281        requires a locate (has now been partially optimized away) although it must be clear that that information has already been retrieved by the walkIntersections.  The
00282        points of intersection always lie on an edge (of course, or it wouldn't be intersections with edges) and computing the bary-
00283        centric coordinates is overkill.  So an optimization consists of:
00284             * keeping track of the edges passed together with the intersection point
00285             * compute the values on the org and dest of crossed edges and use this for interpolation
00286     */
00287 
00288     LASS_ENFORCE(iQuery.size()>1);
00289     typedef std::pair<TPoint2D, typename TPlanarMesh::TEdge*> TPointEdgePair;
00290     std::vector<TPointEdgePair> crossings;
00291     //TPolyLine2D crossings;
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

Generated on Mon Nov 10 14:20:31 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo