Face.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 
00030 #ifndef FACE_HPP_
00031 #define FACE_HPP_
00032 
00033 #include "UblasCustomFunctions.hpp"
00034 #include <vector>
00035 #include "Exception.hpp"
00036 
00037 template <unsigned DIM>
00038 class Face
00039 {
00040 public:
00044     std::vector< c_vector<double, DIM>* > mVertices;
00045 
00046 private:
00047     void Increment(typename std::vector< c_vector<double, DIM>* >::iterator& rIterator,
00048                    Face<DIM>& rFace) const;
00049 
00050 public:
00051 
00052 
00053     class VertexAndAngle
00054     {
00055     public:
00056         c_vector< double ,DIM >* mpVertex;
00057         double mAngle;
00058         bool operator<(const VertexAndAngle& other) const
00059         {
00060             return mAngle < other.mAngle;
00061         }
00062     };
00063 
00064 
00069     bool operator==(Face<DIM>& otherFace);
00070 
00074     bool operator!=(Face<DIM>& otherFace);
00075 
00079     Face<DIM> operator-();
00080 
00086     double GetPerimeter() const;
00087 
00093     double GetArea() const;
00094 
00098     unsigned GetNumVertices() const;
00099 
00103     std::vector< c_vector<double, DIM>* > GetVertices() const;
00104 
00105 
00109      void OrderVerticesAntiClockwise();
00110 
00116      double ReturnPolarAngle(double x, double y) const;
00117 
00118 };
00119 
00120 
00121 
00122 template <unsigned DIM>
00123 void Face<DIM>::Increment(typename std::vector< c_vector<double, DIM>* >::iterator& rIterator,
00124                      Face<DIM>& rFace) const
00125 {
00126     rIterator++;
00127     if (rIterator==rFace.mVertices.end() )
00128     {
00129         rIterator=rFace.mVertices.begin();
00130     }
00131 };
00132 
00133 template <unsigned DIM>
00134 bool Face<DIM>::operator==(Face<DIM>& otherFace)
00135 {
00136     typename std::vector< c_vector<double, DIM>* >::iterator this_iterator=mVertices.begin();
00137     typename std::vector< c_vector<double, DIM>* >::iterator other_iterator=otherFace.mVertices.begin();
00138     // find first vertex
00139     while ( this_iterator!=mVertices.end() &&
00140             other_iterator!=otherFace.mVertices.end() &&
00141             norm_2(**this_iterator - **other_iterator) >1e-10 )
00142     {
00143         this_iterator++;
00144     }
00145     if (this_iterator==mVertices.end() || other_iterator==otherFace.mVertices.end())
00146     {
00147         // could not find first vertex
00148         // faces are distinct unless they are empty
00149         return this_iterator==mVertices.end() && other_iterator==otherFace.mVertices.end();
00150     }
00151 
00152     typename std::vector< c_vector<double, DIM>* >::iterator this_start=this_iterator;
00153     Increment(this_iterator, *this);
00154     Increment(other_iterator, otherFace);
00155 
00156     // check remanining vertices are equal
00157     while (this_iterator!=this_start)
00158     {
00159         if (norm_2(**this_iterator - **other_iterator) >1e-10)
00160         {
00161             return false;
00162         }
00163         else
00164         {
00165             Increment(this_iterator, *this);
00166             Increment(other_iterator, otherFace);
00167         }
00168     }
00169     return other_iterator==otherFace.mVertices.begin();
00170 };
00171 
00172 #define COVERAGE_IGNORE //Spuriously not covered
00173 template <unsigned DIM>
00174 bool Face<DIM>::operator!=(Face& otherFace)
00175 {
00176    return !(*this==otherFace);
00177 };
00178 #undef COVERAGE_IGNORE
00179 
00180 template <unsigned DIM>
00181 Face<DIM> Face<DIM>::operator-()
00182 {
00183    Face<DIM> reversed_face;
00184    typename std::vector< c_vector<double, DIM>* >::iterator this_iterator=mVertices.end();
00185    while (this_iterator !=mVertices.begin())
00186    {
00187        this_iterator--;
00188        reversed_face.mVertices.push_back(*this_iterator);
00189    }
00190    return reversed_face;
00191 };
00192 
00193 template <unsigned DIM>
00194 double Face<DIM>::GetPerimeter() const
00195 {
00196     double perimeter_return = 0;
00197     for(unsigned i=0; i<mVertices.size(); i++)
00198     {
00199         perimeter_return += norm_2(*mVertices[i]-*mVertices[(i+1)%mVertices.size()]);
00200     }
00201     return perimeter_return;
00202 };
00203 
00204 template <unsigned DIM>
00205 double Face<DIM>::GetArea() const
00206 {
00207     #define COVERAGE_IGNORE
00208     assert(DIM==2);
00209     #undef COVERAGE_IGNORE
00210 
00211     double area_return = 0;
00212     for(unsigned i=0; i<mVertices.size(); i++)
00213     {
00214         //  Area = sum ( x_i * y_i+1 - y_i * x_i+1 )/2.0 over all vertices,
00215         //      assuming vertices are ordered anti-clockwise
00216         area_return +=   ( (*mVertices[i])(0) * (*mVertices[(i+1)%mVertices.size()])(1)
00217                           -(*mVertices[i])(1) * (*mVertices[(i+1)%mVertices.size()])(0) ) / 2.0;
00218     }
00219     return area_return;
00220 };
00221 
00222 template <unsigned DIM>
00223 unsigned Face<DIM>::GetNumVertices() const
00224 {
00225     return mVertices.size();
00226 };
00227 
00228 template <unsigned DIM>
00229 std::vector< c_vector<double, DIM>* > Face<DIM>::GetVertices() const
00230 {
00231     return mVertices;
00232 };
00233 
00234 template<unsigned DIM>
00235 double Face<DIM>::ReturnPolarAngle(double x, double y) const
00236 {
00237     if (x==0)
00238     {
00239         if (y>0)
00240         {
00241             return M_PI/2.0;
00242         }
00243         else if (y<0)
00244         {
00245             return -M_PI/2.0;
00246         }
00247         else
00248         {
00249             EXCEPTION("Tried to compute polar angle of (0,0)");
00250         }
00251     }
00252 
00253     double angle = atan(y/x);
00254 
00255     if (y >= 0 && x < 0 )
00256     {
00257         angle += M_PI;
00258     }
00259     else if (y < 0 && x < 0 )
00260     {
00261         angle -= M_PI;
00262     }
00263     return angle;
00264 };
00265 
00266 
00267 
00268 template <unsigned DIM>
00269 void Face<DIM>::OrderVerticesAntiClockwise()
00270 {
00271      // Reorder mVertices Anticlockwise
00272     std::vector< VertexAndAngle > vertices_and_angles;
00273 
00274     c_vector<double,DIM> centre = zero_vector<double>(DIM);
00275 
00276     for(unsigned j=0; j<mVertices.size(); j++)
00277     {
00278         //std::cout<< "\n mVertices" << j << " " << (*(mVertices[j]))(0) << std::flush;
00279         centre += *(mVertices[j]);
00280     }
00281 
00282     centre /= mVertices.size();
00283     for(unsigned j=0; j<mVertices.size(); j++)
00284     {
00285 
00286         VertexAndAngle va;
00287         c_vector<double, DIM> centre_to_vertex;
00288         //assert(centre  *(mVertices[j]) );
00289         centre_to_vertex = *(mVertices[j]) - centre;
00290         va.mAngle = ReturnPolarAngle(centre_to_vertex(0), centre_to_vertex(1));
00291         va.mpVertex = mVertices[j];
00292         vertices_and_angles.push_back(va);
00293     }
00294 
00295     std::sort(vertices_and_angles.begin(), vertices_and_angles.end());
00296 
00297     // create face
00298     mVertices.clear();
00299     for ( typename std::vector< VertexAndAngle >::iterator vertex_iterator = vertices_and_angles.begin();
00300           vertex_iterator !=vertices_and_angles.end();
00301           vertex_iterator++)
00302     {
00303         mVertices.push_back(vertex_iterator->mpVertex);
00304     }
00305 };
00306 
00307 
00308 #endif /*FACE_HPP_*/

Generated on Wed Mar 18 12:51:56 2009 for Chaste by  doxygen 1.5.5