00001
00002
00003
00004
00005
00006
00007 #ifndef GEOMETRY_H_
00008 #define GEOMETRY_H_
00009
00010 #include <stdint.h>
00011 #include <vector>
00012 #include "types.h"
00013 #include "Log.h"
00014 #include "fv_config.h"
00015 #include "ElemId.hpp"
00016 #include "Enums.h"
00017 #include "MathHelper.h"
00018 #include "Matrix.h"
00019 #include "BBox3D.h"
00020 #include "Ray.h"
00021
00022 #include "Mesh.h"
00023 #include "Field.h"
00024
00025
00026
00027 namespace FemViewer {
00028 using namespace fvmath;
00029
00030 using std::fabs;
00031
00032
00033 extern uint64_t numRayTrianglesTests;
00034 extern uint64_t numRayTrianglesIsect;
00035
00036 template<typename TReal = CoordType>
00037 bool intersectTriangle(
00038 const Ray<TReal> &r,
00039 const Vec3<TReal>& v0, const Vec3<TReal>& v1, const Vec3<TReal>& v2,
00040 TReal tuv[]);
00041
00042 template<typename TReal = CoordType>
00043 bool intersectQuad(
00044 const Ray<TReal> &r,
00045 const Vec3<TReal>& v0, const Vec3<TReal>& v1, const Vec3<TReal>& v2, const Vec3<TReal>& v3,
00046 TReal tuv[]);
00047
00048 struct IsectData {
00049 float t;
00050 float u, v;
00051 uint32_t index;
00052 CVec3f N;
00053 IsectData() : t(0), u(0), v(0), index(0) {}
00054 };
00055
00056
00057 template<typename _Ty>
00058 struct prism_info {
00059
00060
00061 CVec3<_Ty> vts[6];
00062 Vec4<_Ty> pls[5];
00063 _Ty min_v;
00064 _Ty max_v;
00065
00066 };
00067
00068 template<typename _Ty>
00069 struct coeffs_info {
00070 short pdeg;
00071 short base;
00072 int nr_shap;
00073 _Ty coeffs[MAX_NUM_DOFS];
00074 };
00075
00076
00077
00078 typedef union {
00079 struct { float tmin, tmax; };
00080 float data[2];
00081 } coef_t;
00082
00083 typedef struct {
00084 coef_t coef;
00085 ElemId<id_t> id;
00086 } intersect_t ;
00087
00088 class mfvBaseObject
00089 {
00090 public:
00091 static const Mesh* parentMeshPtr;
00092 static const Field* parentFieldPtr;
00093 virtual ~mfvBaseObject() {}
00094 virtual const BBox3D& getBounds() const = 0;
00095 virtual bool intersect(const Ray<float>& ray,isect_info_t *isectData) const = 0;
00096 virtual void computeBounds(const Vec3f &planeNormal, float &dnear, float &dfar) const {};
00097 virtual CVec3f getCenter() const = 0;
00098 virtual void calculateNormals() = 0;
00099 };
00100
00101 template<class TReal = CoordType,
00102 class TIndex = id_t,
00103 unsigned NUM_VERTICES = 3>
00104 class mfvObject : public mfvBaseObject
00105 {
00106 public:
00107
00108 typedef TReal real_t;
00109 typedef ElemId<TIndex> index_type;
00110 typedef ScalarValueType value_type;
00111 typedef std::vector<value_type> vListType;
00112
00113 static const unsigned numVertices = NUM_VERTICES;
00114
00115 template<class U>
00116 static int convert(TReal in[],U out[]);
00117
00118 mfvObject(const index_type id =0,const Matrix<ScalarValueType>& po2w = Matrix<ScalarValueType>::Identity)
00119 : minValue(0.0)
00120 , maxValue(0.0)
00121 , solCoeffs()
00122 , pdeg(101)
00123 , index(id)
00124 , objectToWorld(po2w)
00125 , worldToObject() {
00126
00127 if (parentFieldPtr != NULL) this->getCoefficients();
00128 }
00129 virtual ~mfvObject() { }
00130
00131 index_type& getId() { return this->index; }
00132
00133 int degree() {return pdeg;}
00134
00135 double minV() { return minValue; }
00136
00137 double maxV() { return maxValue; }
00138
00139 const BBox3D& getBounds() const { return bbox; }
00140
00141 virtual void setBounds() {
00142 if (bbox.isInitialized()) return;
00143 for (unsigned i(0); i < NUM_VERTICES; ++i) bbox += this->vertices[i];
00144 }
00145
00146 CVec3f getCenter() const {
00147 const real_t f = real_t(1.0)/NUM_VERTICES;
00148 CVec3f center(this->vertices[0]);
00149 for (unsigned i(1); i < NUM_VERTICES; ++i) center += this->vertices[i];
00150 center *= f;
00151 return center;
00152 }
00153 virtual void getCoefficients();
00154
00155 protected:
00156
00157 mutable value_type minValue;
00158 mutable value_type maxValue;
00159 vListType solCoeffs;
00160 int pdeg;
00161 int base;
00162 int numShap;
00163 index_type index;
00164 Matrix<ScalarValueType> objectToWorld, worldToObject;
00165 Vec3<real_t> vertices[NUM_VERTICES];
00166 int idNodes[NUM_VERTICES+1];
00167 BBox3D bbox;
00168 };
00169
00170
00171
00172
00173 template<class TReal,class TIndex,unsigned NUM_VERTICES>
00174 template<class U>
00175 int mfvObject<TReal,TIndex,NUM_VERTICES>::convert(TReal InV[],U OutV[])
00176 {
00177 for (unsigned i(0); i < NUM_VERTICES; ++i) {
00178 OutV[i] = static_cast<U>(InV[i]);
00179 }
00180
00181 return numVertices;
00182 }
00183
00184 template<class TReal,class TIndex,unsigned NUM_VERTICES>
00185 void mfvObject<TReal,TIndex,NUM_VERTICES>::getCoefficients()
00186 {
00187
00188 assert(parentFieldPtr != NULL);
00189 int nel = static_cast<int>(index.eid);
00190
00191 int nshp =parentFieldPtr->GetNumberOfShapeFunc(nel,&pdeg);
00192
00193 solCoeffs.resize(nshp);
00194 parentFieldPtr->GetElementDofs<ScalarValueType>(nel,solCoeffs.data());
00195 assert(solCoeffs.size() == nshp);
00196
00197 }
00198
00199 #define NUM_TRIANGLE_VERTICES 3
00200 class Triangle : public mfvObject<CoordType,id_t,NUM_TRIANGLE_VERTICES>
00201 {
00202 public:
00203 Triangle(const id_t& id1,const id_t& id2,const id_t& id3);
00204 bool intersect(const Ray<CoordType> &r,isect_info_t* isectData) const
00205 {
00206 #ifdef MOLLER_TRUMBORE
00207 CVec3<TReal> edge1 = this->vertices[1] - this->vertices[0];
00208 CVec3<TReal> edge2 = this->vertices[2] - this->vertices[0];
00209 CVec3<TReal> pvec = r.dir * edge2;
00210 CoordType det = Dot(edge1, pvec);
00211 if (det == CoordType(0)) return false;
00212 CoordType invDet = CoordType(1) / det;
00213 CVec3<CoordType> tvec = r.orig - this->vertices[0];
00214 isectData.u = dot(tvec, pvec) * invDet;
00215 if (isectData.u < CoordType(0) || isectData.u > CoordType(1)) return false;
00216 CVec3<CoordType> qvec = cross(tvec, edge1);
00217 isectData.v = dot(r.dir, qvec) * invDet;
00218 if (isectData.v < CoordType(0) || isectData.u + isectData.v > CoordType(1)) return false;
00219 isectData.t = dot(edge2, qvec) * invDet;
00220 #else
00221 CVec3<CoordType> v0v1(this->vertices[1] - this->vertices[0]);
00222 CVec3<CoordType> v0v2(this->vertices[2] - this->vertices[0]);
00223 CVec3<CoordType> N = v0v1 * v0v2;
00224 CoordType nDotRay = Dot(N, r.dir);
00225 if (nDotRay == CoordType(0) || (nDotRay > CoordType(0) && isSingledSided)) return false;
00226 CoordType d = Dot(N, this->vertices[0]);
00227 CoordType t = -(Dot(N, r.orig) + d) / nDotRay;
00228 if (t < CoordType(0)) return false;
00229
00230
00231 CVec3<CoordType> Phit = r(t);
00232
00233
00234 CVec3<CoordType> v0p = Phit - this->vertices[0];
00235 CoordType v = Dot(N, v0v1 * v0p);
00236 if (v < CoordType(0)) return false;
00237
00238
00239 CVec3<CoordType> v1p = Phit - this->vertices[1];
00240 CVec3<CoordType> v1v2 = this->vertices[2] - this->vertices[1];
00241 CoordType w = Dot(N, v1v2 * v1p);
00242 if (w < CoordType(0)) return false;
00243
00244
00245 CVec3<CoordType> v2p = Phit - this->vertices[2];
00246 CVec3<CoordType> v2v0 = this->vertices[0] - this->vertices[2];
00247 CoordType u = Dot(N, v2v0 * v2p);
00248 if (u < CoordType(0)) return false;
00249
00250 CoordType nlen2 = Dot(N, N);
00251 isectData->t = t;
00252 isectData->u = u / nlen2;
00253 isectData->v = v / nlen2;
00254 #endif
00255 return true;
00256 }
00257 private:
00258 Vec4<CoordType> normal;
00259 void calculateNormals();
00260 bool isSingledSided;
00261 };
00262
00263 #define NUM_TETRA_FACES 4
00264 #define NUM_TETRA_VERTICES 4
00265 class Tetra : public mfvObject<CoordType,id_t,NUM_TETRA_VERTICES> {
00266 public:
00267 template<typename T>
00268 static BBox3D BoundingBox(const fvmath::Vec3<T>* elCoords);
00269 template<typename T>
00270 static fvmath::CVec3<T> Centrum(const fvmath::Vec3<T>* elCoords);
00271 Tetra(const id_t& id);
00272 bool intersect(const Ray<CoordType>& r,isect_info_t *isectData) const {
00273 isect_info_t tuv[4];
00274 unsigned sides = 0U;
00275 for (unsigned i(0); i < NUM_TETRA_FACES; ++i) {
00276 bool result(false);
00277 int i0 = Mesh::tetra[i][0];
00278 int i1 = Mesh::tetra[i][1];
00279 int i2 = Mesh::tetra[i][2];
00280 result = intersectTriangle(r,this->vertices[i0],this->vertices[i1],this->vertices[i2],(CoordType*)&tuv[i]);
00281 if (result && (r.tmin <= tuv[i].t && tuv[i].t <= r.tmax)) {
00282 tuv[i].side = i;
00283 } else tuv[i].side = -1;
00284 }
00285 unsigned mn_i(0U);
00286 do{
00287 if (tuv[mn_i].side != -1) break;
00288 }while(mn_i++ < 4);
00289 unsigned mx_i = mn_i;
00290 for (unsigned i = mn_i+1;i<4;++i) {
00291 if (tuv[mn_i].t > tuv[i].t) { mn_i = i; }
00292 if (tuv[mx_i].t < tuv[i].t) { mx_i = i; }
00293 }
00294 el_isect_info_t* pis = static_cast<el_isect_info_t *>(isectData);
00295 pis->t = tuv[mn_i].t;
00296 pis->u = tuv[mn_i].u;
00297 pis->v = tuv[mn_i].v;
00298 pis->out.t = tuv[mx_i].t;
00299 pis->out.u = tuv[mn_i].u;
00300 pis->out.v = tuv[mx_i].v;
00301 return (mn_i < mx_i);
00302 }
00303
00304 protected:
00305 Vec4<CoordType> normals[NUM_TETRA_FACES];
00306 void calculateNormals();
00307 int setCoordinates() {
00308 int lindex = static_cast<int>(index.eid);
00309 this->parentMeshPtr->GetElementCoordinates(lindex, this->idNodes, this->vertices[0].v);
00310 calculateNormals();
00311 return lindex;
00312 }
00313
00314 };
00315
00316 template<typename TCoord>
00317 BBox3D Tetra::BoundingBox(const fvmath::Vec3<TCoord>* v)
00318 {
00319 BBox3D bb;
00320 bb.mn.x = fv_min(fv_min(fv_min(fv_min(v[0].x,v[1].x),v[2].x),v[3].x),v[4].x);
00321 bb.mn.y = fv_min(fv_min(fv_min(fv_min(v[0].y,v[1].y),v[2].y),v[3].y),v[4].y);
00322 bb.mn.z = fv_min(fv_min(fv_min(fv_min(v[0].z,v[1].z),v[2].z),v[3].z),v[4].z);
00323 bb.mx.x = fv_max(fv_max(fv_max(fv_max(v[0].x,v[1].x),v[2].x),v[3].x),v[4].x);
00324 bb.mx.y = fv_max(fv_max(fv_max(fv_max(v[0].y,v[1].y),v[2].y),v[3].y),v[4].y);
00325 bb.mx.z = fv_max(fv_max(fv_max(fv_max(v[0].z,v[1].z),v[2].z),v[3].z),v[4].z);
00326 bb.setInitialized(true);
00327 return bb;
00328 }
00329
00330 template<typename T>
00331 fvmath::CVec3<T> Tetra::Centrum(const fvmath::Vec3<T>* elCoords)
00332 {
00333 CVec3<T> c;
00334 T inv_6 = 1. / NUM_TETRA_VERTICES;
00335 for (int i(0); i < NUM_TETRA_VERTICES; ++i) c += elCoords[i];
00336 c *= inv_6;
00337 return c;
00338 }
00339
00340 #define NUM_PRISM_VERTICES 6
00341 #define NUM_PRISM_FACES 5
00342
00343 class Prizm : public mfvObject<CoordType,id_t,NUM_PRISM_VERTICES>
00344 {
00345 public:
00346 template<typename TCoord>
00347 static CVec3<TCoord> TransformToReference(TCoord Coords[18],CVec3<TCoord> worldPt);
00348
00349 template<typename TCoord>
00350 static CVec3<TCoord> TransformToWorld(TCoord Coords[18],const CVec3<TCoord> *refPt);
00351
00352 template<typename TCoord>
00353 static void CalcInvJacobian(TCoord Coords[18],const CVec3<TCoord>& refPt, TCoord invJ[9]);
00354
00355 template<typename TCoord>
00356 static void ReferenceToWorldJacobian(TCoord Coords[18],const CVec3<TCoord>& refPt,TCoord J[9]);
00357
00358 template<typename TCoord>
00359 static BBox3D BoundingBox(fvmath::Vec3<TCoord> *v);
00360
00361 template<typename T>
00362 static fvmath::CVec3<T> Centrum(const fvmath::Vec3<T>* elCoords);
00363
00364 template<typename T>
00365 static int teselateReference(const int Pdeg[3],CVec3<T> RefPoints[]);
00366
00367 template<typename T>
00368 static int teselateWorld(const int base,const int Pdeg[3],const CVec3<T> ElCoords[],std::vector<CVec3<T> >* TesPoints);
00369
00370 static int getNumberOfShapeFunctions(const int Order[],int base);
00371
00372 Prizm(const index_type& id);
00373
00374 virtual ~Prizm() { }
00375 bool intersect(const Ray<CoordType>& r,isect_info_t *isectData) const {
00376 isect_info_t tuv[5];
00377 unsigned sides = 0U;
00378 for (unsigned i(0); i < NUM_PRISM_FACES; ++i) {
00379 bool result(false);
00380 int i0 = Mesh::prizm[i][0];
00381 int i1 = Mesh::prizm[i][1];
00382 int i2 = Mesh::prizm[i][2];
00383 int i3 = Mesh::prizm[i][3];
00384 if (i3 < 0)
00385 result = intersectTriangle(r,this->vertices[i0],this->vertices[i1],this->vertices[i2],(CoordType*)(&tuv[i]));
00386 else
00387 result = intersectQuad(r,this->vertices[i0],this->vertices[i1],this->vertices[i2],this->vertices[i3],(CoordType*)(&tuv[i]));
00388 if (result && (r.tmin <= tuv[i].t && tuv[i].t <= r.tmax)) {
00389 tuv[i].side = i;
00390 } else tuv[i].side = -1;
00391 }
00392 unsigned mn_i(0U);
00393 do{
00394 if (tuv[mn_i].side != -1) break;
00395 }while(mn_i++ < 5);
00396 unsigned mx_i = mn_i;
00397 for (unsigned i = mn_i+1;i<5;++i) {
00398 if (tuv[mn_i].t > tuv[i].t) { mn_i = i; }
00399 if (tuv[mx_i].t < tuv[i].t) { mx_i = i; }
00400 }
00401 el_isect_info_t* pis = static_cast<el_isect_info_t*>(isectData);
00402 pis->t = tuv[mn_i].t;
00403 pis->u = tuv[mn_i].u;
00404 pis->v = tuv[mn_i].v;
00405 pis->out.t = tuv[mx_i].t;
00406 pis->out.u = tuv[mn_i].u;
00407 pis->out.v = tuv[mx_i].v;
00408 return (mn_i < mx_i);
00409 }
00410
00411 private:
00412 Vec4<CoordType> normals[NUM_TETRA_FACES];
00413 bool isBaseParalled;
00414
00415 void calculateNormals();
00416 int setCoordinates() {
00417 int lindex = static_cast<int>(this->index.eid);
00418 lindex = this->parentMeshPtr->GetElementCoordinates(lindex, this->idNodes, this->vertices[0].v);
00419 this->calculateNormals();
00420 return lindex;
00421 }
00422 int setCoeffs();
00423 void calculateMinMaxRange();
00424 };
00425
00426 template<typename TCoord>
00427 BBox3D Prizm::BoundingBox(fvmath::Vec3<TCoord>* v)
00428 {
00429 BBox3D bb;
00430 bb.mn.x = fv_min(fv_min(fv_min(fv_min(fv_min(v[0].x,v[1].x),v[2].x),v[3].x),v[4].x),v[5].x);
00431 bb.mn.y = fv_min(fv_min(fv_min(fv_min(fv_min(v[0].y,v[1].y),v[2].y),v[3].y),v[4].y),v[5].y);
00432 bb.mn.z = fv_min(fv_min(fv_min(fv_min(fv_min(v[0].z,v[1].z),v[2].z),v[3].z),v[4].z),v[5].z);
00433 bb.mx.x = fv_max(fv_max(fv_max(fv_max(fv_max(v[0].x,v[1].x),v[2].x),v[3].x),v[4].x),v[5].x);
00434 bb.mx.y = fv_max(fv_max(fv_max(fv_max(fv_max(v[0].y,v[1].y),v[2].y),v[3].y),v[4].y),v[5].y);
00435 bb.mx.z = fv_max(fv_max(fv_max(fv_max(fv_max(v[0].z,v[1].z),v[2].z),v[3].z),v[4].z),v[5].z);
00436 bb.setInitialized(true);
00437 return bb;
00438 }
00439 template<typename T>
00440 fvmath::CVec3<T> Prizm::Centrum(const fvmath::Vec3<T>* elCoords)
00441 {
00442 CVec3<T> c;
00443 const T inv_6 = 1. / NUM_PRISM_VERTICES;
00444 for (int i(0); i < NUM_PRISM_VERTICES; ++i) c += elCoords[i];
00445 c *= inv_6;
00446 return c;
00447 }
00448
00449 template<typename TCoord>
00450 CVec3<TCoord> Prizm::TransformToReference(TCoord Coords[18],CVec3<TCoord> worldPt)
00451 {
00452 int runs = 0;
00453 TCoord tolerance(1e-5);
00454 ++runs;
00455
00456 typedef typename fvmath::CVec3<TCoord> WorldPoint;
00457 typedef typename fvmath::CVec3<TCoord> RefPoint;
00458
00459 RefPoint result(0.,0.,0.);
00460 TCoord inverse[9];
00461
00462 int numIterations = 0;
00463 const int MAX_ITERATIONS = 100;
00464
00465 do {
00466 WorldPoint f = TransformToWorld(Coords, &result) - worldPt;
00467
00468 CalcInvJacobian(Coords, result, inverse);
00469
00470 TCoord r_adjust = (inverse[0]*f.x + inverse[1]*f.y + inverse[2]*f.z);
00471 TCoord s_adjust = (inverse[3]*f.x + inverse[4]*f.y + inverse[5]*f.z);
00472 TCoord t_adjust = (inverse[6]*f.x + inverse[7]*f.y + inverse[8]*f.z);
00473
00474 if (fabs(r_adjust) < tolerance &&
00475 fabs(s_adjust) < tolerance &&
00476 fabs(t_adjust) < tolerance) {
00477 printf("Finished because transformation is within tolerance.\n");
00478 printf("World point: (%f, %f, %f)\n", worldPt.x, worldPt.y, worldPt.z);
00479
00480 return result;
00481 }
00482
00483 RefPoint pointAdjust(r_adjust, s_adjust, t_adjust);
00484 RefPoint tempResult = result - pointAdjust;
00485
00486
00487 if( result.x == tempResult.x && result.y == tempResult.y && result.z == tempResult.z )
00488 {
00489 printf("Finished because adjustment is too small.\n");
00490 printf("NumIter: %d\n",numIterations);
00491 return result;
00492 }
00493
00494 result = tempResult;
00495 WorldPoint inversePoint = TransformToWorld(Coords, &result);
00496
00497 if (worldPt.x == inversePoint.x &&
00498 worldPt.y == inversePoint.y &&
00499 worldPt.z == inversePoint.z )
00500 {
00501 printf("Finished because transformation is exact.\n");
00502 printf("NumIter: %d\n",numIterations);
00503 printf("World point: (%f, %f, %f)\n", worldPt.x, worldPt.y, worldPt.z);
00504 printf("Tensor point: (%f, %f, %f)\n", result.x, result.y, result.z);
00505
00506 return result;
00507 }
00508
00509 ++numIterations;
00510
00511 } while( numIterations < MAX_ITERATIONS);
00512
00513
00514 return result;
00515
00516 }
00517
00518 template<typename TCoord>
00519 CVec3<TCoord> Prizm::TransformToWorld(TCoord Coords[18],const CVec3<TCoord> *refPt)
00520 {
00521 TCoord r = refPt->x;
00522 TCoord s = refPt->y;
00523 TCoord t = refPt->z;
00524
00525 TCoord t1 = -(r+s)*(TCoord(1.0)-t);
00526 TCoord t2 = (TCoord(1.0)+r)*(TCoord(1.0)-t);
00527 TCoord t3 = (TCoord(1.0)+s)*(TCoord(1.0)-t);
00528 TCoord t4 = -(r+s)*(TCoord(1.0)+t);
00529 TCoord t5 = (TCoord(1.0)+r)*(TCoord(1.0)+t);
00530 TCoord t6 = (TCoord(1.0)+s)*(TCoord(1.0)+t);
00531
00532 TCoord x = TCoord(.25) * (t1*Coords[0] + t2*Coords[3] +
00533 t3*Coords[6] + t4*Coords[9] + t5*Coords[12] + t6*Coords[15]);
00534
00535 TCoord y = TCoord(.25) * (t1*Coords[1] + t2*Coords[4] +
00536 t3*Coords[7] + t4*Coords[10] + t5*Coords[13] + t6*Coords[16]);
00537
00538 TCoord z = TCoord(.25) * (t1*Coords[2] + t2*Coords[5] +
00539 t3*Coords[8] + t4*Coords[11] + t5*Coords[14] + t6*Coords[17]);
00540
00541 return CVec3<TCoord>(x, y, z);
00542 }
00543
00544 template<typename TCoord>
00545 void Prizm::CalcInvJacobian(TCoord Coords[18],const CVec3<TCoord>& refPt, TCoord invJ[9])
00546 {
00547 TCoord J[9];
00548 ReferenceToWorldJacobian(Coords, refPt, J);
00549
00550
00551 TCoord det = (-J[0]*J[4]*J[8]+J[0]*J[5]*J[7]+J[3]*J[1]*J[8]-J[3]*J[2]*J[7]-J[6]*J[1]*J[5]+J[6]*J[2]*J[4]);
00552 assert(det != 0);
00553 TCoord invdet = 1.0/det;
00554
00555 invJ[0] = (-J[4]*J[8]+J[5]*J[7])*invdet;
00556 invJ[1] = -(-J[1]*J[8]+J[2]*J[7])*invdet;
00557 invJ[2] = -(J[1]*J[5]-J[2]*J[4])*invdet;
00558 invJ[3] = -(-J[3]*J[8]+J[5]*J[6])*invdet;
00559 invJ[4] = (-J[0]*J[8]+J[2]*J[6])*invdet;
00560 invJ[5] = (J[0]*J[5]-J[2]*J[3])*invdet;
00561 invJ[6] = (-J[3]*J[7]+J[4]*J[6])*invdet;
00562 invJ[7] = (J[0]*J[7]-J[1]*J[6])*invdet;
00563 invJ[8] = -(J[0]*J[4]-J[1]*J[3])*invdet;
00564 }
00565
00566 template<typename TCoord>
00567 void Prizm::ReferenceToWorldJacobian(TCoord Coords[18],const fvmath::CVec3<TCoord>& refPt,TCoord J[9])
00568 {
00569 TCoord r = refPt.x;
00570 TCoord s = refPt.y;
00571 TCoord t = refPt.z;
00572
00573 TCoord t1 = TCoord(1.0)-t;
00574 TCoord t4 = TCoord(1.0)+t;
00575 TCoord t8 = r+s;
00576 TCoord t10 = TCoord(1.0)+r;
00577 TCoord t14 = TCoord(1.0)+s;
00578
00579 J[0] = 0.25*((Coords[3]-Coords[0])*t1 + (Coords[12]-Coords[9])*t4);
00580 J[3] = 0.25*((Coords[4]-Coords[1])*t1 + (Coords[13]-Coords[10])*t4);
00581 J[6] = 0.25*((Coords[5]-Coords[2])*t1 + (Coords[14]-Coords[11])*t4);;
00582 J[1] = 0.25*((Coords[6]-Coords[0])*t1 + (Coords[15]-Coords[9])*t4);
00583 J[4] = 0.25*((Coords[7]-Coords[1])*t1 + (Coords[16]-Coords[10])*t4);
00584 J[7] = 0.25*((Coords[8]-Coords[2])*t1 + (Coords[17]-Coords[11])*t4);
00585 J[2] = 0.25*((Coords[0]-Coords[9])*t8 + (Coords[12]-Coords[3])*t10 + (Coords[15]-Coords[6])*t14);
00586 J[5] = 0.25*((Coords[1]-Coords[10])*t8 + (Coords[13]-Coords[4])*t10 + (Coords[16]-Coords[7])*t14);
00587 J[8] = 0.25*((Coords[2]-Coords[11])*t8 + (Coords[14]-Coords[5])*t10 + (Coords[17]-Coords[8])*t14);
00588
00589 }
00590
00591
00592
00593 }
00594 #endif