SundanceGeomUtils.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 #include "SundanceGeomUtils.hpp"
00043 #include "SundanceMesh.hpp"
00044 #include "SundancePoint.hpp"
00045 #include "SundanceSet.hpp"
00046 #include <queue>
00047 
00048 using namespace Sundance;
00049 using namespace Teuchos;
00050 using namespace Sundance;
00051 
00052 
00053 namespace Sundance
00054 {
00055   bool cellContainsPoint(const Mesh& mesh, int cellDim, int cellLID, 
00056                          const double* x, Array<int>& facetLID)
00057   {
00058     if (cellDim==1)
00059       {
00060         static Array<int> facetLID(2);
00061         static Array<int> tmp(2);
00062         mesh.getFacetArray(cellDim, cellLID, 0, facetLID, tmp);
00063         Point A = mesh.nodePosition(facetLID[0]);
00064         Point B = mesh.nodePosition(facetLID[1]);
00065         if (A[0] < B[0]) return (x[0] >= A[0] && x[0] <= B[0]);
00066         else return (x[0] <= A[0] && x[0] >= B[0]);
00067       }
00068     else if (cellDim==2)
00069       {
00070         static Array<int> tmp(3);
00071         mesh.getFacetArray(cellDim, cellLID, 0, facetLID, tmp);
00072         const double* A = mesh.nodePositionView(facetLID[0]);
00073         const double* B = mesh.nodePositionView(facetLID[1]);
00074         const double* C = mesh.nodePositionView(facetLID[2]);
00075         /* first determine whether the three points of the triangle
00076          * are in ccw or cw order. */
00077         double sign = orient2D(A, B, C);
00078         if (sign > 0.0)
00079           {
00080             double s1 = orient2D(A, B, x);
00081             double s2 = orient2D(B, C, x);
00082             double s3 = orient2D(C, A, x);
00083             if (s1 >= 0.0 && s2 >= 0.0 && s3 >= 0.0) return true;
00084             return false;
00085           }
00086         else
00087           {
00088             double s1 = orient2D(A, C, x);
00089             double s2 = orient2D(C, B, x);
00090             double s3 = orient2D(B, A, x);
00091             if (s1 >= 0.0 && s2 >= 0.0 && s3 >= 0.0) return true;
00092             return false;
00093           }
00094       }
00095     else if (cellDim==3)
00096       {
00097         TEUCHOS_TEST_FOR_EXCEPT(true);
00098         return false; // -Wall
00099       }
00100     else
00101       {
00102         TEUCHOS_TEST_FOR_EXCEPTION(cellDim<=0 || cellDim>3, std::runtime_error,
00103                            "invalid point dimension " << cellDim);
00104         return false; // -Wall
00105       }
00106   }
00107 
00108   double volume(const Mesh& mesh, int cellDim, int cellLID)
00109   {
00110     if (cellDim==1)
00111       {
00112         static Array<int> facetLID(2);
00113         static Array<int> tmp(2);
00114         mesh.getFacetArray(cellDim, cellLID, 0, facetLID, tmp);
00115         Point A = mesh.nodePosition(facetLID[0]);
00116         Point B = mesh.nodePosition(facetLID[1]);
00117         return fabs(A[0] - B[0]);
00118       }
00119     else if (cellDim==2)
00120       {
00121         static Array<int> facetLID(3);
00122         static Array<int> tmp(3);
00123         mesh.getFacetArray(cellDim, cellLID, 0, facetLID, tmp);
00124         const double* A = mesh.nodePositionView(facetLID[0]);
00125         const double* B = mesh.nodePositionView(facetLID[1]);
00126         const double* C = mesh.nodePositionView(facetLID[2]);
00127         return fabs(0.5*orient2D(A, B, C));
00128       }
00129     TEUCHOS_TEST_FOR_EXCEPT(true);
00130   }
00131 
00132 
00133   double orient2D(const double* A, const double* B, const double* x)
00134   {
00135     double acx, bcx, acy, bcy;
00136 
00137     acx = A[0] - x[0];
00138     bcx = B[0] - x[0];
00139     acy = A[1] - x[1];
00140     bcy = B[1] - x[1];
00141     return acx * bcy - acy * bcx;
00142   }
00143 
00144   int findEnclosingCell(const Mesh& mesh, int cellDim,
00145                         int initialGuessLID,
00146                         const double* x)
00147   {
00148     std::queue<int> Q;
00149     Set<int> repeats;
00150     static Array<int> facets;
00151 
00152     Q.push(initialGuessLID);
00153 
00154     
00155 
00156     while (!Q.empty())
00157       {
00158         int next = Q.front();
00159         Q.pop();
00160         if (repeats.contains(next)) continue;
00161 
00162         if (cellContainsPoint(mesh, cellDim, next, x, facets)) return next;
00163         repeats.put(next);
00164         
00165         std::list<int> neighbors;
00166         maximalNeighbors(mesh, cellDim, next, facets, neighbors);
00167         for (std::list<int>::const_iterator 
00168                i=neighbors.begin(); i!=neighbors.end(); i++)
00169           {
00170             Q.push(*i);
00171           }
00172       }
00173     return -1; // no containing cell found
00174   }
00175 
00176   Point pullback(const Mesh& mesh, int cellDim, int cellLID, const double* x)
00177   {
00178     int dim = cellDim;
00179     if (dim==2)
00180       {
00181         static Array<int> facetLID(3);
00182         static Array<int> tmp(3);
00183         mesh.getFacetArray(cellDim, cellLID, 0, facetLID, tmp);
00184         const double* A = mesh.nodePositionView(facetLID[0]);
00185         const double* B = mesh.nodePositionView(facetLID[1]);
00186         const double* C = mesh.nodePositionView(facetLID[2]);
00187 
00188         double bax = B[0] - A[0];
00189         double bay = B[1] - A[1];
00190         double cax = C[0] - A[0];
00191         double cay = C[1] - A[1];
00192         double delta = bax*cay - bay*cax;
00193 
00194         double xax = x[0] - A[0];
00195         double xay = x[1] - A[1];
00196 
00197         return Point( (cay*xax - cax*xay)/delta,
00198                       (-bay*xax + bax*xay)/delta );
00199           
00200       }
00201     else
00202       {
00203         TEUCHOS_TEST_FOR_EXCEPTION(cellDim != 2, std::runtime_error,
00204                            "invalid point dimension " << cellDim);
00205         return Point(); // -Wall
00206       }
00207   }
00208 
00209   void printCell(const Mesh& mesh, int cellLID)
00210   {
00211     if (mesh.spatialDim()==2)
00212       {
00213         static Array<int> facetLID(3);
00214         static Array<int> tmp(3);
00215         mesh.getFacetArray(mesh.spatialDim(), cellLID, 0, facetLID, tmp);
00216         Point A = mesh.nodePosition(facetLID[0]);
00217         Point B = mesh.nodePosition(facetLID[1]);
00218         Point C = mesh.nodePosition(facetLID[2]);
00219         std::cout << "{" << A << ", " << B << ", " << C << "}" << std::endl;
00220       }
00221   }
00222 
00223   void maximalNeighbors(const Mesh& mesh, int cellDim, int cellLID, 
00224                         const Array<int>& facetLID,
00225                         std::list<int>& rtn)
00226   {
00227     for (int f=0; f<facetLID.size(); f++)
00228       {
00229         Array<int> cofacets;
00230         mesh.getCofacets(0, facetLID[f], cellDim, cofacets);
00231         for (int c=0; c<cofacets.size(); c++)
00232           {
00233             if (cofacets[c] != cellLID) rtn.push_back(cofacets[c]);
00234           }
00235       }
00236   }
00237 
00238 
00239   int lookupEdgeLIDFromVerts(const Mesh& mesh, int v1, int v2)
00240   {
00241     Array<int> cofacetLIDs;
00242     mesh.getCofacets(0, v1, 1, cofacetLIDs);
00243     
00244     for (int c=0; c<cofacetLIDs.size(); c++)
00245       {
00246   int ori;
00247   for (int f=0; f<2; f++)
00248     {
00249       int v = mesh.facetLID(1, cofacetLIDs[c], 0, f, ori);
00250       if (v == v2) return cofacetLIDs[c];
00251     }
00252       }
00253     
00254     TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00255              "edge (" << v1 << ", " << v2 << ") not found in mesh");
00256     return -1;
00257   }
00258 
00259   
00260   
00261 }

Site Contact