00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
00076
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;
00099 }
00100 else
00101 {
00102 TEUCHOS_TEST_FOR_EXCEPTION(cellDim<=0 || cellDim>3, std::runtime_error,
00103 "invalid point dimension " << cellDim);
00104 return false;
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;
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();
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 }