SundanceGeomUtils.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                              Sundance
00005 //                 Copyright (2005) Sandia Corporation
00006 // 
00007 // Copyright (year first published) Sandia Corporation.  Under the terms 
00008 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 
00009 // retains certain rights in this software.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //                                                                                 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA                                                                                
00025 // Questions? Contact Kevin Long (krlong@sandia.gov), 
00026 // Sandia National Laboratories, Livermore, California, USA
00027 // 
00028 // ************************************************************************
00029 /* @HEADER@ */
00030 
00031 #include "SundanceGeomUtils.hpp"
00032 #include "SundanceMesh.hpp"
00033 #include "SundancePoint.hpp"
00034 #include "SundanceSet.hpp"
00035 #include <queue>
00036 
00037 using namespace Sundance;
00038 using namespace Teuchos;
00039 using namespace Sundance;
00040 
00041 
00042 namespace Sundance
00043 {
00044   bool cellContainsPoint(const Mesh& mesh, int cellDim, int cellLID, 
00045                          const double* x, Array<int>& facetLID)
00046   {
00047     if (cellDim==1)
00048       {
00049         static Array<int> facetLID(2);
00050         static Array<int> tmp(2);
00051         mesh.getFacetArray(cellDim, cellLID, 0, facetLID, tmp);
00052         Point A = mesh.nodePosition(facetLID[0]);
00053         Point B = mesh.nodePosition(facetLID[1]);
00054         if (A[0] < B[0]) return (x[0] >= A[0] && x[0] <= B[0]);
00055         else return (x[0] <= A[0] && x[0] >= B[0]);
00056       }
00057     else if (cellDim==2)
00058       {
00059         static Array<int> tmp(3);
00060         mesh.getFacetArray(cellDim, cellLID, 0, facetLID, tmp);
00061         const double* A = mesh.nodePositionView(facetLID[0]);
00062         const double* B = mesh.nodePositionView(facetLID[1]);
00063         const double* C = mesh.nodePositionView(facetLID[2]);
00064         /* first determine whether the three points of the triangle
00065          * are in ccw or cw order. */
00066         double sign = orient2D(A, B, C);
00067         if (sign > 0.0)
00068           {
00069             double s1 = orient2D(A, B, x);
00070             double s2 = orient2D(B, C, x);
00071             double s3 = orient2D(C, A, x);
00072             if (s1 >= 0.0 && s2 >= 0.0 && s3 >= 0.0) return true;
00073             return false;
00074           }
00075         else
00076           {
00077             double s1 = orient2D(A, C, x);
00078             double s2 = orient2D(C, B, x);
00079             double s3 = orient2D(B, A, x);
00080             if (s1 >= 0.0 && s2 >= 0.0 && s3 >= 0.0) return true;
00081             return false;
00082           }
00083       }
00084     else if (cellDim==3)
00085       {
00086         TEUCHOS_TEST_FOR_EXCEPT(true);
00087         return false; // -Wall
00088       }
00089     else
00090       {
00091         TEUCHOS_TEST_FOR_EXCEPTION(cellDim<=0 || cellDim>3, std::runtime_error,
00092                            "invalid point dimension " << cellDim);
00093         return false; // -Wall
00094       }
00095   }
00096 
00097   double volume(const Mesh& mesh, int cellDim, int cellLID)
00098   {
00099     if (cellDim==1)
00100       {
00101         static Array<int> facetLID(2);
00102         static Array<int> tmp(2);
00103         mesh.getFacetArray(cellDim, cellLID, 0, facetLID, tmp);
00104         Point A = mesh.nodePosition(facetLID[0]);
00105         Point B = mesh.nodePosition(facetLID[1]);
00106         return fabs(A[0] - B[0]);
00107       }
00108     else if (cellDim==2)
00109       {
00110         static Array<int> facetLID(3);
00111         static Array<int> tmp(3);
00112         mesh.getFacetArray(cellDim, cellLID, 0, facetLID, tmp);
00113         const double* A = mesh.nodePositionView(facetLID[0]);
00114         const double* B = mesh.nodePositionView(facetLID[1]);
00115         const double* C = mesh.nodePositionView(facetLID[2]);
00116         return fabs(0.5*orient2D(A, B, C));
00117       }
00118     TEUCHOS_TEST_FOR_EXCEPT(true);
00119   }
00120 
00121 
00122   double orient2D(const double* A, const double* B, const double* x)
00123   {
00124     double acx, bcx, acy, bcy;
00125 
00126     acx = A[0] - x[0];
00127     bcx = B[0] - x[0];
00128     acy = A[1] - x[1];
00129     bcy = B[1] - x[1];
00130     return acx * bcy - acy * bcx;
00131   }
00132 
00133   int findEnclosingCell(const Mesh& mesh, int cellDim,
00134                         int initialGuessLID,
00135                         const double* x)
00136   {
00137     std::queue<int> Q;
00138     Set<int> repeats;
00139     static Array<int> facets;
00140 
00141     Q.push(initialGuessLID);
00142 
00143     
00144 
00145     while (!Q.empty())
00146       {
00147         int next = Q.front();
00148         Q.pop();
00149         if (repeats.contains(next)) continue;
00150 
00151         if (cellContainsPoint(mesh, cellDim, next, x, facets)) return next;
00152         repeats.put(next);
00153         
00154         std::list<int> neighbors;
00155         maximalNeighbors(mesh, cellDim, next, facets, neighbors);
00156         for (std::list<int>::const_iterator 
00157                i=neighbors.begin(); i!=neighbors.end(); i++)
00158           {
00159             Q.push(*i);
00160           }
00161       }
00162     return -1; // no containing cell found
00163   }
00164 
00165   Point pullback(const Mesh& mesh, int cellDim, int cellLID, const double* x)
00166   {
00167     int dim = cellDim;
00168     if (dim==2)
00169       {
00170         static Array<int> facetLID(3);
00171         static Array<int> tmp(3);
00172         mesh.getFacetArray(cellDim, cellLID, 0, facetLID, tmp);
00173         const double* A = mesh.nodePositionView(facetLID[0]);
00174         const double* B = mesh.nodePositionView(facetLID[1]);
00175         const double* C = mesh.nodePositionView(facetLID[2]);
00176 
00177         double bax = B[0] - A[0];
00178         double bay = B[1] - A[1];
00179         double cax = C[0] - A[0];
00180         double cay = C[1] - A[1];
00181         double delta = bax*cay - bay*cax;
00182 
00183         double xax = x[0] - A[0];
00184         double xay = x[1] - A[1];
00185 
00186         return Point( (cay*xax - cax*xay)/delta,
00187                       (-bay*xax + bax*xay)/delta );
00188           
00189       }
00190     else
00191       {
00192         TEUCHOS_TEST_FOR_EXCEPTION(cellDim != 2, std::runtime_error,
00193                            "invalid point dimension " << cellDim);
00194         return Point(); // -Wall
00195       }
00196   }
00197 
00198   void printCell(const Mesh& mesh, int cellLID)
00199   {
00200     if (mesh.spatialDim()==2)
00201       {
00202         static Array<int> facetLID(3);
00203         static Array<int> tmp(3);
00204         mesh.getFacetArray(mesh.spatialDim(), cellLID, 0, facetLID, tmp);
00205         Point A = mesh.nodePosition(facetLID[0]);
00206         Point B = mesh.nodePosition(facetLID[1]);
00207         Point C = mesh.nodePosition(facetLID[2]);
00208         std::cout << "{" << A << ", " << B << ", " << C << "}" << std::endl;
00209       }
00210   }
00211 
00212   void maximalNeighbors(const Mesh& mesh, int cellDim, int cellLID, 
00213                         const Array<int>& facetLID,
00214                         std::list<int>& rtn)
00215   {
00216     for (int f=0; f<facetLID.size(); f++)
00217       {
00218         Array<int> cofacets;
00219         mesh.getCofacets(0, facetLID[f], cellDim, cofacets);
00220         for (int c=0; c<cofacets.size(); c++)
00221           {
00222             if (cofacets[c] != cellLID) rtn.push_back(cofacets[c]);
00223           }
00224       }
00225   }
00226 
00227   
00228 }

Site Contact