# Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics

[Home] [Tutorials] [All Classes] [Grouped Classes]

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/src/vlGraphics/PolygonSimplifier.hpp

Go to the documentation of this file.

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

Visualization Library v2011.05.1142 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 26 2011 22:51:24.
Permission is granted to use this page to write and publish articles regarding Visualization Library.