Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlGraphics/PolygonSimplifier.hpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.visualizationlibrary.org                                               */
00005 /*                                                                                    */
00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
00007 /*  All rights reserved.                                                              */
00008 /*                                                                                    */
00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
00010 /*  are permitted provided that the following conditions are met:                     */
00011 /*                                                                                    */
00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
00013 /*  list of conditions and the following disclaimer.                                  */
00014 /*                                                                                    */
00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
00017 /*  other materials provided with the distribution.                                   */
00018 /*                                                                                    */
00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
00029 /*                                                                                    */
00030 /**************************************************************************************/
00031 
00032 #ifndef PolygonSimplifier_INCLUDE_ONCE
00033 #define PolygonSimplifier_INCLUDE_ONCE
00034 
00035 #include <vlCore/Object.hpp>
00036 #include <vlCore/Vector3.hpp>
00037 #include <vlCore/glsl_math.hpp>
00038 #include <vlGraphics/link_config.hpp>
00039 #include <vector>
00040 #include <algorithm>
00041 
00042 namespace vl
00043 {
00044   class Geometry;
00045 //-----------------------------------------------------------------------------
00046 // PolygonSimplifier
00047 //-----------------------------------------------------------------------------
00052   class VLGRAPHICS_EXPORT PolygonSimplifier: public Object
00053   {
00054     VL_INSTRUMENT_CLASS(vl::PolygonSimplifier, Object)
00055 
00056   public:
00057     class Vertex;
00058     //-----------------------------------------------------------------------------
00059     // QErr
00060     //-----------------------------------------------------------------------------
00062     class QErr
00063     {
00064     public:
00065       QErr()
00066       {
00067         a2 = 0.0;
00068         ab = 0.0;
00069         ac = 0.0;
00070         ad = 0.0;
00071         b2 = 0.0;
00072         bc = 0.0;
00073         bd = 0.0;
00074         c2 = 0.0;
00075         cd = 0.0;
00076         d2 = 0.0;
00077       }
00078 
00079       QErr(const dvec3& n, double d, double w = 1.0)
00080       {
00081         a2 = w * n.x() * n.x();
00082         ab = w * n.x() * n.y();
00083         ac = w * n.x() * n.z();
00084         ad = w * n.x() * d;
00085         b2 = w * n.y() * n.y();
00086         bc = w * n.y() * n.z();
00087         bd = w * n.y() * d;
00088         c2 = w * n.z() * n.z();
00089         cd = w * n.z() * d;
00090         d2 = w * d*d;
00091 
00092         // indeterminate cases
00093         VL_CHECK( d2 == d2 )
00094       }
00095 
00096       dmat3 matrix() const
00097       {
00098         return dmat3(
00099           a2, ab, ac,
00100           ab, b2, bc,
00101           ac, bc, c2 );
00102       }
00103 
00104       dvec3 vector() const
00105       {
00106         return dvec3( ad, bd, cd );
00107       }
00108 
00109       double offset() const
00110       {
00111         return d2;
00112       }
00113 
00114       double evaluate(const dvec3& v) const
00115       {
00116         return v.x()*v.x()*a2 + 2*v.x()*v.y()*ab + 2*v.x()*v.z()*ac + 2*v.x()*ad
00117                               + v.y()*v.y()*b2   + 2*v.y()*v.z()*bc + 2*v.y()*bd
00118                                                  + v.z()*v.z()*c2   + 2*v.z()*cd
00119                                                                     + d2;
00120       }
00121 
00122       bool analyticSolution(dvec3& v) const
00123       {
00124 #if 0
00125         dmat3 Ainv;
00126         double det = matrix().getInverse(Ainv); 
00127         if (!det)
00128           return false;
00129         v = -(Ainv*vector());
00130         return true;
00131 #else
00132         double A = c2*b2-bc*bc;
00133         double B = bc*ac-c2*ab;
00134         double C = bc*ab-b2*ac;
00135         double det = a2*(A)+ab*(B)+ac*(C);
00136         if (fabs(det) < 0.0000001)
00137           return false;
00138         else
00139         {
00140           double inv_det = 1.0 / det;
00141           dmat3 Ainv( A*inv_det,             B*inv_det,             C*inv_det, 
00142                       (ac*bc-c2*ab)*inv_det, (c2*a2-ac*ac)*inv_det, (ab*ac-bc*a2)*inv_det,
00143                       (bc*ab-ac*b2)*inv_det, (ac*ab-bc*a2)*inv_det, (b2*a2-ab*ab)*inv_det );
00144           v = Ainv * dvec3( -ad, -bd, -cd );
00145           return true;
00146         }
00147 #endif
00148       }
00149 
00150       QErr operator+(const QErr& other)
00151       {
00152         QErr q = *this;
00153         q.a2 += other.a2;
00154         q.ab += other.ab;
00155         q.ac += other.ac;
00156         q.ad += other.ad;
00157         q.b2 += other.b2;
00158         q.bc += other.bc;
00159         q.bd += other.bd;
00160         q.c2 += other.c2;
00161         q.cd += other.cd;
00162         q.d2 += other.d2;
00163         return q;
00164       }
00165 
00166       const QErr& operator+=(const QErr& other)
00167       {
00168         a2 += other.a2;
00169         ab += other.ab;
00170         ac += other.ac;
00171         ad += other.ad;
00172         b2 += other.b2;
00173         bc += other.bc;
00174         bd += other.bd;
00175         c2 += other.c2;
00176         cd += other.cd;
00177         d2 += other.d2;
00178         return *this;
00179       }
00180 
00181     protected:
00182       // coefficients
00183       double a2, ab, ac, ad;
00184       double     b2, bc, bd;
00185       double         c2, cd;
00186       double             d2;
00187     };
00188     //-----------------------------------------------------------------------------
00189     // Triangle
00190     //-----------------------------------------------------------------------------
00192     class Triangle
00193     {
00194       friend class PolygonSimplifier;
00195       friend class Vertex;
00196     public:
00197       Triangle(): mRemoved(false)
00198       {
00199         mVertices[0] = NULL;
00200         mVertices[1] = NULL;
00201         mVertices[2] = NULL;
00202       }
00203 
00204       inline void replaceVertex( Vertex* oldv, Vertex* newv );
00205       inline void computeNormal();
00206       inline float computeArea() const;
00207       inline float computePotentialArea(const Vertex* oldv, const Vertex* newv) const;
00208       inline fvec3 computePotentialNormal(const Vertex* oldv, const Vertex* newv) const;
00209       inline bool hasVertex(const Vertex*v) const;
00210       inline bool checkTriangle() const;
00211       // inline float computeDistance(const fvec3&) const;
00212       inline QErr computeQErr() const;
00213 
00215       const Vertex* vertex(int index) const { return mVertices[index]; }
00216       Vertex* vertex(int index) { return mVertices[index]; }
00218       const fvec3& normal() const { return mNormal; }
00220       // float area() const { return mArea; }
00222       bool removed() const { return mRemoved; }
00224 
00225     protected:
00227       Vertex* mVertices[3];
00229       fvec3 mNormal;
00231       // float mArea;
00233       bool mRemoved;
00234     };
00235     //-----------------------------------------------------------------------------
00236     // Vertex
00237     //-----------------------------------------------------------------------------
00239     class Vertex
00240     {
00241       friend class Triangle;
00242       friend class PolygonSimplifier;
00243     public:
00244       Vertex(): mCollapseCost(0.0f), mOriginalIndex(-1) , mSimplifiedIndex(-1), mRemoveOrder(-1),
00245                 mRemoved(false), mProtected(false), mAlreadyProcessed(false)
00246       {
00247       }
00248 
00249       inline void addAdjacentVertex(Vertex* v);
00250       inline void removeAdjacentVertex(Vertex* v);
00251       inline void computeAdjacentVertices();
00252       inline bool checkConnectivity();
00253       inline bool isAdjacentVertex(Vertex*) const;
00254       inline bool isIncidentTriangle(Triangle*) const;
00255       inline void discardRemovedTriangles();
00256       inline void removeIncidentTriangle(const Triangle*);
00257       inline bool checkTriangles() const;
00258       inline void computeEdgePenalty();
00259 
00261       const fvec3& position() const { return mPosition; }
00263       int adjacentVerticesCount() const { return (int)mAdjacentVerts.size(); }
00264       Vertex* adjacentVertex(int index) const { return mAdjacentVerts[index]; }
00266       int incidentTrianglesCount() const { return (int)mIncidentTriangles.size(); }
00267       Triangle* incidentTriangle(int index) const { return mIncidentTriangles[index]; }
00269       Vertex* collapseVertex() const { return mCollapseVertex; }
00271       float collapseCost() const { return mCollapseCost; }
00273       const fvec3& collapsePosition() const { return mCollapsePosition; }
00274       void setCollapsePosition(const fvec3& pos) { mCollapsePosition = pos; }
00276       int removeOrder() const { return mRemoveOrder; }
00278       bool removed() const { return mRemoved; }
00280       bool isProtected() const { return mProtected; }
00282       int originalIndex() const { return mOriginalIndex; }
00284       int simplifiedIndex() const { return mSimplifiedIndex; }
00286       bool alreadyProcessed() const { return mAlreadyProcessed; }
00288       const QErr& qerr() const { return mQErr; }
00289       void setQErr(const QErr& qerr) { mQErr = qerr; }
00290       void addQErr(const QErr& qerr) { mQErr += qerr; }
00291 
00292     protected:
00293       QErr mQErr;
00295       fvec3 mPosition;
00297       std::vector< Vertex* > mAdjacentVerts;
00299       std::vector< Triangle* > mIncidentTriangles;
00301       Vertex* mCollapseVertex;
00303       float mCollapseCost;
00305       fvec3 mCollapsePosition;
00307       int mOriginalIndex;
00309       int mSimplifiedIndex;
00311       int mRemoveOrder;
00313       bool mRemoved;
00315       bool mProtected;
00317       bool mAlreadyProcessed;
00318     };
00319 
00320   public:
00321     PolygonSimplifier(): mRemoveDoubles(false), mVerbose(true), mQuick(true) {}
00322 
00323     void simplify();
00324     void simplify(const std::vector<fvec3>& in_verts, const std::vector<int>& in_tris);
00325 
00326     void setIntput(Geometry* geom) { mInput = geom; }
00327     Geometry* input() { return mInput.get(); }
00328     const Geometry* input() const { return mInput.get(); }
00329 
00330     std::vector< u32 >& targets() { return mTargets; }
00331     const std::vector< u32 >& targets() const { return mTargets; }
00332 
00333     std::vector< ref<Geometry> >& output() { return mOutput; }
00334     const std::vector< ref<Geometry> >& output() const { return mOutput; }
00335 
00336     void setProtectedVertices(const std::vector<int>& protected_verts) { mProtectedVerts = protected_verts; }
00337 
00338     int simplifiedVerticesCount() const { return (int)mSimplifiedVertices.size(); }
00339     Vertex* simplifiedVertices(int index) const { return mSimplifiedVertices[index]; }
00340 
00341     int simplifiedTrianglesCount() const { return (int)mSimplifiedTriangles.size(); }
00342     Triangle* simplifiedTriangles(int index) const { return mSimplifiedTriangles[index]; }
00343 
00344     void clearTrianglesAndVertices();
00345 
00346     bool removeDoubles() const { return mRemoveDoubles; }
00347     void setRemoveDoubles(bool remove_doubles) { mRemoveDoubles = remove_doubles; }
00348 
00349     bool verbose() const { return mVerbose; }
00350     void setVerbose(bool verbose) { mVerbose = verbose; }
00351 
00352     bool quick() const { return mQuick; }
00353     void setQuick(bool quick) { mQuick = quick; }
00354 
00355   protected:
00356     void outputSimplifiedGeometry();
00357     inline void collapse(Vertex* v);
00358     inline void computeCollapseInfo(Vertex* v);
00359 
00360   protected:
00361     ref<Geometry> mInput;
00362     std::vector< ref<Geometry> > mOutput;
00363     std::vector< u32 > mTargets;
00364     std::vector<Vertex*> mSimplifiedVertices;
00365     std::vector<Triangle*> mSimplifiedTriangles;
00366     std::vector<int> mProtectedVerts;
00367     bool mRemoveDoubles;
00368     bool mVerbose;
00369     bool mQuick;
00370 
00371   private:
00372     std::vector<Triangle> mTriangleLump;
00373     std::vector<Vertex> mVertexLump;
00374   };
00375   //-----------------------------------------------------------------------------
00376   // Vertex
00377   //-----------------------------------------------------------------------------
00378   inline void PolygonSimplifier::Vertex::addAdjacentVertex(Vertex* v)
00379   {
00380     if( v != this )
00381     {
00382       for(int i=0; i<adjacentVerticesCount(); ++i)
00383         if (mAdjacentVerts[i] == v)
00384           return;
00385       mAdjacentVerts.push_back(v);
00386     }
00387   }
00388   //-----------------------------------------------------------------------------
00389   inline void PolygonSimplifier::Vertex::removeAdjacentVertex(Vertex* v)
00390   {
00391     VL_CHECK( v != this )
00392     VL_CHECK( std::find(mAdjacentVerts.begin(), mAdjacentVerts.end(), v) != mAdjacentVerts.end() )
00393     for(int i=0; i<adjacentVerticesCount(); ++i)
00394       if (mAdjacentVerts[i] == v)
00395       {
00396         mAdjacentVerts.erase(mAdjacentVerts.begin() + i);
00397         return;
00398       }
00399   }
00400   //-----------------------------------------------------------------------------
00401   inline void PolygonSimplifier::Vertex::computeAdjacentVertices()
00402   {
00403     mAdjacentVerts.clear();
00404     for(int itri=0; itri<incidentTrianglesCount(); ++itri)
00405     {
00406       VL_CHECK(!mIncidentTriangles[itri]->mRemoved)
00407       addAdjacentVertex( mIncidentTriangles[itri]->mVertices[0] );
00408       addAdjacentVertex( mIncidentTriangles[itri]->mVertices[1] );
00409       addAdjacentVertex( mIncidentTriangles[itri]->mVertices[2] );
00410     }
00411     mRemoved = mAdjacentVerts.empty();
00412   }
00413   //-----------------------------------------------------------------------------
00414   inline bool PolygonSimplifier::Vertex::checkTriangles() const
00415   {
00416     for(int itri=incidentTrianglesCount(); itri--; )
00417       if ( !incidentTriangle(itri)->checkTriangle() )
00418         return false;
00419     return true;
00420   }
00421   //-----------------------------------------------------------------------------
00422   inline void PolygonSimplifier::Vertex::computeEdgePenalty()
00423   {
00424     for(int ivert=0; ivert<adjacentVerticesCount(); ++ivert)
00425     {
00426       int edge_count = 0;
00427       int border_tri = -1;
00428       for(int itri=0; itri<incidentTrianglesCount() && edge_count<=1; ++itri)
00429       {
00430         if ( incidentTriangle(itri)->hasVertex( adjacentVertex(ivert) ) )
00431         {
00432           border_tri = itri;
00433           ++edge_count;
00434         }
00435       }
00436       if ( edge_count == 1 )
00437       {
00438         fvec3 edge = position() - adjacentVertex(ivert)->position();
00439         dvec3 n = (dvec3)cross(incidentTriangle(border_tri)->normal(), edge );
00440         n.normalize();
00441         double d = -dot(n,(dvec3)position());
00442         mQErr += QErr( n, d, dot(edge, edge) * 1.0 );
00443       }
00444     }
00445   }
00446   inline void PolygonSimplifier::Vertex::removeIncidentTriangle(const Triangle* tri)
00447   {
00448     for(int itri=incidentTrianglesCount(); itri--; )
00449     {
00450       if (mIncidentTriangles[itri] == tri)
00451       {
00452         mIncidentTriangles.erase( mIncidentTriangles.begin() + itri );
00453         break;
00454       }
00455     }
00456   }
00457   //-----------------------------------------------------------------------------
00458   inline void PolygonSimplifier::Vertex::discardRemovedTriangles()
00459   {
00460     for(int itri=incidentTrianglesCount(); itri--; )
00461     {
00462       if (mIncidentTriangles[itri]->mRemoved)
00463         mIncidentTriangles.erase( mIncidentTriangles.begin() + itri );
00464     }
00465   }
00466   //-----------------------------------------------------------------------------
00467   inline bool PolygonSimplifier::Vertex::isAdjacentVertex(Vertex* v) const
00468   {
00469     for(int i=0; i<adjacentVerticesCount(); ++i)
00470       if ( adjacentVertex(i) == v )
00471         return true;
00472     return false;
00473   }
00474   //-----------------------------------------------------------------------------
00475   inline bool PolygonSimplifier::Vertex::isIncidentTriangle(Triangle* t) const
00476   {
00477     for(int i=0; i<incidentTrianglesCount(); ++i)
00478       if ( incidentTriangle(i) == t )
00479         return true;
00480     return false;
00481   }
00482   //-----------------------------------------------------------------------------
00483   inline bool PolygonSimplifier::Vertex::checkConnectivity()
00484   {
00485     VL_CHECK( mCollapseVertex )
00486     VL_CHECK( !mCollapseVertex->removed() )
00487     // check connectivity consistency
00488     for(int ivert=0; ivert<adjacentVerticesCount(); ++ivert)
00489     {
00490       Vertex* adj = mAdjacentVerts[ivert];
00491       if ( adj->removed() )
00492         return false;
00493       if( std::find(adj->mAdjacentVerts.begin(), adj->mAdjacentVerts.end(), this) == adj->mAdjacentVerts.end() )
00494         return false;
00495     }
00496     return true;
00497   }
00498   //-----------------------------------------------------------------------------
00499   // Triangle
00500   //-----------------------------------------------------------------------------
00501   inline PolygonSimplifier::QErr PolygonSimplifier::Triangle::computeQErr() const
00502   {
00503     dvec3 n = (dvec3)normal();
00504     double d = -dot((dvec3)vertex(0)->position(), n);
00505     QErr qerr(n, d, computeArea() * (1.0 / 3.0) );
00506     return qerr;
00507   }
00508   //-----------------------------------------------------------------------------
00509   inline fvec3 PolygonSimplifier::Triangle::computePotentialNormal(const Vertex* oldv, const Vertex* newv) const
00510   {
00511     fvec3 a = (mVertices[0]->mPosition == oldv->mPosition ? newv->mPosition : mVertices[0]->mPosition);
00512     fvec3 b = (mVertices[1]->mPosition == oldv->mPosition ? newv->mPosition : mVertices[1]->mPosition) - a;
00513     fvec3 c = (mVertices[2]->mPosition == oldv->mPosition ? newv->mPosition : mVertices[2]->mPosition) - a;
00514 
00515     fvec3 n = cross(b,c);
00516     n.normalize();
00517     return n;
00518   }
00519   //-----------------------------------------------------------------------------
00520   inline bool PolygonSimplifier::Triangle::checkTriangle() const
00521   {
00522     bool ok = true;
00523     ok &= !mVertices[0]->removed(); VL_CHECK(ok)
00524     ok &= !mVertices[1]->removed(); VL_CHECK(ok)
00525     ok &= !mVertices[2]->removed(); VL_CHECK(ok)
00526     ok &= mVertices[0] != mVertices[1]; VL_CHECK(ok)
00527     ok &= mVertices[0] != mVertices[2]; VL_CHECK(ok)
00528     ok &= mVertices[1] != mVertices[2]; VL_CHECK(ok)
00529     return ok;
00530   }
00531   //-----------------------------------------------------------------------------
00532   inline bool PolygonSimplifier::Triangle::hasVertex(const Vertex*v) const
00533   {
00534     return mVertices[0] == v || mVertices[1] == v || mVertices[2] == v;
00535   }
00536   //-----------------------------------------------------------------------------
00537   inline float PolygonSimplifier::Triangle::computePotentialArea(const Vertex* oldv, const Vertex* newv) const
00538   {
00539     fvec3 A = (mVertices[0]->mPosition == oldv->mPosition ? newv->mPosition : mVertices[0]->mPosition);
00540     fvec3 B = (mVertices[1]->mPosition == oldv->mPosition ? newv->mPosition : mVertices[1]->mPosition) - A;
00541     fvec3 C = (mVertices[2]->mPosition == oldv->mPosition ? newv->mPosition : mVertices[2]->mPosition) - A;
00542 
00543     float base   = 0.0f;
00544     float height = 0.0f;
00545     fvec3 AC = C-A;
00546     fvec3 AB = B-A;
00547     base = AB.length();
00548     AB = AB * (1.0f / base); // normalize
00549     fvec3 h = vl::dot(AC,AB) * AB + A;
00550     height = (C-h).length();
00551 
00552     return base * height * 0.5f;
00553   }
00554   //-----------------------------------------------------------------------------
00555   inline float PolygonSimplifier::Triangle::computeArea() const
00556   {
00557     const fvec3& A = mVertices[0]->mPosition;
00558     const fvec3& B = mVertices[1]->mPosition;
00559     const fvec3& C = mVertices[2]->mPosition;
00560 
00561     float base   = 0.0f;
00562     float height = 0.0f;
00563     fvec3 AC = C-A;
00564     fvec3 AB = B-A;
00565     base = AB.length();
00566     if (!base)
00567       return 0;
00568     AB = AB * (1.0f / base); // normalize
00569     fvec3 h = vl::dot(AC,AB) * AB + A;
00570     height = (C-h).length();
00571     // indeterminate cases
00572     VL_CHECK( base == base )
00573     VL_CHECK( height == height )
00574     return base * height * 0.5f;
00575   }
00576   //-----------------------------------------------------------------------------
00577   inline void PolygonSimplifier::Triangle::computeNormal()
00578   {
00579     const fvec3& a = mVertices[0]->mPosition;
00580     fvec3 b = mVertices[1]->mPosition - a;
00581     fvec3 c = mVertices[2]->mPosition - a;
00582     mNormal = cross(b,c);
00583     mNormal.normalize();
00584   }
00585   //-----------------------------------------------------------------------------
00586   inline void PolygonSimplifier::Triangle::replaceVertex( Vertex* oldv, Vertex* newv )
00587   {
00588     // becomes a degenerate triangle if "newv" is already here
00589     mRemoved = hasVertex(newv);
00590     if (mRemoved)
00591     {
00592       //mVertices[0]->removeIncidentTriangle(this);
00593       //mVertices[1]->removeIncidentTriangle(this);
00594       //mVertices[2]->removeIncidentTriangle(this);
00595     }
00596     else
00597     {
00598       if (mVertices[0] == oldv) mVertices[0] = newv;
00599       if (mVertices[1] == oldv) mVertices[1] = newv;
00600       if (mVertices[2] == oldv) mVertices[2] = newv;
00601       VL_CHECK( !mVertices[0]->mRemoved )
00602       VL_CHECK( !mVertices[1]->mRemoved )
00603       VL_CHECK( !mVertices[2]->mRemoved )
00604     }
00605   }
00606   //-----------------------------------------------------------------------------
00607   inline void PolygonSimplifier::collapse(Vertex* v)
00608   {
00609     VL_CHECK(!v->mRemoved)
00610     VL_CHECK(v->mCollapseVertex)
00611     VL_CHECK( !v->mCollapseVertex->mRemoved )
00612 #ifndef NDEBUG
00613     v->checkConnectivity();
00614     // check connectivity consistency
00615     for(int ivert=0; ivert<v->adjacentVerticesCount(); ++ivert)
00616     {
00617       VL_CHECK( v->mAdjacentVerts[ivert]->checkConnectivity() )
00618     }
00619 #endif
00620 
00621     v->mRemoved = true;
00622 
00623     v->mCollapseVertex->mPosition = v->mCollapsePosition;
00624     v->mCollapseVertex->mQErr += v->mQErr;
00625 
00626     for(int itri=0; itri<v->incidentTrianglesCount(); ++itri)
00627     {
00628       VL_CHECK(!v->mIncidentTriangles[itri]->mRemoved)
00629 
00630       // - point the triangle to use the new mCollapseVertex instead of "this"
00631       // - flags for removal
00632       v->mIncidentTriangles[itri]->replaceVertex( v, v->mCollapseVertex );
00633 
00634       // pass this's adjacent triangles to mCollapseVertex
00635       if (!v->mIncidentTriangles[itri]->mRemoved)
00636       {
00637         // check that it does not have it already, the ones in common have been marked as "removed"
00638         VL_CHECK( !v->mCollapseVertex->isIncidentTriangle( v->mIncidentTriangles[itri] ) )
00639         v->mCollapseVertex->mIncidentTriangles.push_back( v->mIncidentTriangles[itri] );
00640       }
00641     }
00642 
00643     // erase removed triangles from its adjacent vertices (including mCollapseVertex)
00644     for(int ivert=0; ivert<v->adjacentVerticesCount(); ++ivert)
00645       v->mAdjacentVerts[ivert]->discardRemovedTriangles();
00646 
00647     // update adjacent vertices of all the vertices adjacent to this (including mCollapseVertex)
00648     for(int ivert=0; ivert<v->adjacentVerticesCount(); ++ivert)
00649     {
00650 #if 1
00651       // this is correct and more robust since marks as removed the vertices with 0 triangles
00652       v->mAdjacentVerts[ivert]->computeAdjacentVertices();
00653 #else
00654       ... this is not correct since does not mark as removed the vertices that remain without triangles ...
00655       mAdjacentVerts[ivert]->removeAdjacentVertex(this);
00656       mAdjacentVerts[ivert]->addAdjacentVertex(mCollapseVertex);
00657       mCollapseVertex->addAdjacentVertex(mAdjacentVerts[ivert]);
00658 #endif
00659     }
00660 
00661 #ifndef NDEBUG
00662     for(int ivert=0; ivert<v->mCollapseVertex->adjacentVerticesCount(); ++ivert)
00663     {
00664       VL_CHECK( v->mCollapseVertex->adjacentVertex(ivert)->checkTriangles() )
00665     }
00666 
00667     // and outside even this vertex is removed.
00668     if ( v->mCollapseVertex->removed() )
00669     {
00670       VL_CHECK( v->mCollapseVertex->mIncidentTriangles.empty() )
00671       VL_CHECK( v->mCollapseVertex->mAdjacentVerts.empty() )
00672     }
00673 #endif
00674 
00675     // --- now we work on mCollapseVertex ---
00676 
00677     if ( !quick() )
00678     {
00679       // update the normals, used to compute anti-folding
00680       for(int itri=0; itri<v->mCollapseVertex->incidentTrianglesCount(); ++itri)
00681       {
00682         VL_CHECK( !v->mCollapseVertex->mIncidentTriangles[itri]->removed() )
00683         VL_CHECK( v->mCollapseVertex->mIncidentTriangles[itri]->checkTriangle() )
00684         v->mCollapseVertex->mIncidentTriangles[itri]->computeNormal();
00685       }
00686     }
00687 
00688     VL_CHECK( !v->mCollapseVertex->isAdjacentVertex(v) )
00689 
00690     // disconnect this vertex
00691     v->mIncidentTriangles.clear();
00692     v->mAdjacentVerts.clear();
00693   }
00694   //-----------------------------------------------------------------------------
00695   // compute collapse cost and vertex
00696   inline void PolygonSimplifier::computeCollapseInfo(Vertex* v)
00697   {
00698     VL_CHECK(!v->mRemoved)
00699     if(v->mRemoved)
00700       return;
00701 
00702     // choose the edge with minimum cost
00703 
00704     // intialize with a very high cost
00705     v->mCollapseCost = 1.0e+38f;
00706     v->mCollapseVertex = NULL;
00707     VL_CHECK( v->adjacentVerticesCount() )
00708     for(int ivert=0; ivert<v->adjacentVerticesCount(); ++ivert)
00709     {
00710       VL_CHECK(!v->mAdjacentVerts[ivert]->mRemoved)
00711 
00712       double cost = 0.0;
00713       dvec3 solution;
00714       if (quick())
00715       {
00716         QErr qe = v->qerr();
00717         qe += v->mAdjacentVerts[ivert]->qerr();
00718         // find the best solution
00719         solution = (dvec3)v->position();
00720         solution += (dvec3)v->mAdjacentVerts[ivert]->position();
00721         solution *= 0.5;
00722         cost = qe.evaluate( solution );
00723       }
00724       else
00725       {
00726         QErr qe = v->qerr();
00727         qe += v->mAdjacentVerts[ivert]->qerr();
00728         bool analytic_ok = qe.analyticSolution(solution);
00729         if ( analytic_ok )
00730         {
00731           cost = qe.evaluate(solution);
00732           VL_CHECK(cost < 1e+38)
00733         }
00734         else
00735         {
00736           dvec3 a = (dvec3)v->position();
00737           dvec3 b = (dvec3)v->mAdjacentVerts[ivert]->position();
00738           dvec3 c = (a+b) * 0.5;
00739           double ae = qe.evaluate(a);
00740           double be = qe.evaluate(b);
00741           double ce = qe.evaluate(c);
00742           if (ae < be && ae < ce)
00743           {
00744             solution = a;
00745             cost = ae;
00746           }
00747           else
00748           if (be < ae && be < ce)
00749           {
00750             solution = b;
00751             cost = be;
00752           }
00753           else
00754           {
00755             solution = c;
00756             cost = ce;
00757           }
00758           VL_CHECK(cost < 1e+38)
00759         }
00760 
00761         int degenerate_count = 0;
00762         for( int itri=0; itri<v->incidentTrianglesCount() && !degenerate_count; ++itri )
00763         {
00764           // triangle to be removed
00765           if ( v->incidentTriangle(itri)->hasVertex(v->mAdjacentVerts[ivert]) )
00766             continue;
00767 
00768           Vertex* edgev[] = { NULL, NULL };
00769           if ( v == v->incidentTriangle(itri)->vertex(0) )
00770           {
00771             edgev[0] = v->incidentTriangle(itri)->vertex(1);
00772             edgev[1] = v->incidentTriangle(itri)->vertex(2);
00773           }
00774           else
00775           if ( v == v->incidentTriangle(itri)->vertex(1) )
00776           {
00777             edgev[0] = v->incidentTriangle(itri)->vertex(0);
00778             edgev[1] = v->incidentTriangle(itri)->vertex(2);
00779           }
00780           else
00781           if ( v == v->incidentTriangle(itri)->vertex(2) )
00782           {
00783             edgev[0] = v->incidentTriangle(itri)->vertex(0);
00784             edgev[1] = v->incidentTriangle(itri)->vertex(1);
00785           }
00786 
00787           fvec3 edge = (edgev[1]->position() - edgev[0]->position());
00788           fvec3 n = cross( edge, v->incidentTriangle(itri)->normal() );
00789           n.normalize();
00790           float d1 = dot( v->position() - edgev[0]->position(), n );
00791           float d2 = dot( (fvec3)solution - edgev[0]->position(), n );
00792 
00793           if (d1 * d2 < 0)
00794             ++degenerate_count;
00795         }
00796 
00797         // controlla i triangoli intorno a v->mAdjacentVerts[ivert]
00798         Vertex* u = v->mAdjacentVerts[ivert];
00799         for( int itri=0; itri<u->incidentTrianglesCount() && !degenerate_count; ++itri )
00800         {
00801           // triangle to be removed
00802           if ( u->incidentTriangle(itri)->hasVertex(v) )
00803             continue;
00804 
00805           Vertex* edgev[] = { NULL, NULL };
00806           if ( u == u->incidentTriangle(itri)->vertex(0) )
00807           {
00808             edgev[0] = u->incidentTriangle(itri)->vertex(1);
00809             edgev[1] = u->incidentTriangle(itri)->vertex(2);
00810           }
00811           else
00812           if ( u == u->incidentTriangle(itri)->vertex(1) )
00813           {
00814             edgev[0] = u->incidentTriangle(itri)->vertex(0);
00815             edgev[1] = u->incidentTriangle(itri)->vertex(2);
00816           }
00817           else
00818           if ( u == u->incidentTriangle(itri)->vertex(2) )
00819           {
00820             edgev[0] = u->incidentTriangle(itri)->vertex(0);
00821             edgev[1] = u->incidentTriangle(itri)->vertex(1);
00822           }
00823 
00824           fvec3 edge = (edgev[1]->position() - edgev[0]->position());
00825           fvec3 n = cross( edge, u->incidentTriangle(itri)->normal() );
00826           n.normalize();
00827           float d1 = dot( u->position() - edgev[0]->position(), n );
00828           float d2 = dot( (fvec3)solution - edgev[0]->position(), n );
00829 
00830           if (d1 * d2 < 0)
00831             ++degenerate_count;
00832         }
00833 
00834         // non acceptable solution, assign very high cost
00835         if (degenerate_count)
00836           cost = 1.0e+37f;
00837       }
00838 
00839       // to correctly simplify planar and cylindrical regions
00840       cost += ((dvec3)v->position() - solution).length() * 1.0e-12;
00841 
00842       // check indeterminate case
00843       VL_CHECK( cost == cost )
00844       if ( cost < v->mCollapseCost )
00845       {
00846         v->mCollapseCost     = (float)cost;
00847         v->mCollapseVertex   = v->mAdjacentVerts[ivert];
00848         v->mCollapsePosition = (fvec3)solution;
00849       }
00850     }
00851 
00852     VL_CHECK( v->mCollapseVertex )
00853   }
00854   //-----------------------------------------------------------------------------
00855 }
00856 
00857 #endif

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:39.
Permission is granted to use this page to write and publish articles regarding Visualization Library.