Back to index

salome-med  6.5.0
TransformedTriangleInline.hxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 #ifndef __TRANSFORMEDTRIANGLEINLINE_HXX__
00021 #define __TRANSFORMEDTRIANGLEINLINE_HXX__
00022 
00023 // This file contains inline versions of some of the methods in the TransformedTriangle*.cxx files.
00024 // It replaces those methods if OPTIMIZE is defined.
00025 // NB : most of these methods have documentation in their corresponding .cxx - file.
00026 
00027 // ----------------------------------------------------------------------------------
00028 //  Optimization methods. These are only defined and used if OPTIMIZE is defined.
00029 // -----------------------------------------------------------------------------------
00030 
00031 
00032 inline void TransformedTriangle::preCalculateTriangleSurroundsEdge() 
00033 {
00034   for(TetraEdge edge = OX ; edge <= ZX ; edge = TetraEdge(edge + 1))
00035     {
00036       _triangleSurroundsEdgeCache[edge] = testTriangleSurroundsEdge(edge);
00037     }
00038 }
00039 
00040 
00041 // ----------------------------------------------------------------------------------
00042 //   TransformedTriangle_math.cxx                                                 
00043 // ----------------------------------------------------------------------------------
00044 
00045 inline void TransformedTriangle::resetDoubleProducts(const TriSegment seg, const TetraCorner corner)
00046 {
00047   // set the three corresponding double products to 0.0
00048   static const DoubleProduct DOUBLE_PRODUCTS[12] =
00049     {
00050       C_YZ, C_ZX, C_XY, // O
00051       C_YZ, C_ZH, C_YH, // X
00052       C_ZX, C_ZH, C_XH, // Y
00053       C_XY, C_YH, C_XH  // Z
00054     };
00055   
00056   for(int i = 0 ; i < 3 ; ++i) {
00057     const DoubleProduct dp = DOUBLE_PRODUCTS[3*corner + i];
00058     
00059     LOG(6, std::endl << "resetting inconsistent dp :" << dp << " for corner " << corner);
00060     _doubleProducts[8*seg + dp] = 0.0;
00061   };
00062 }
00063 
00064 inline double TransformedTriangle::calcStableC(const TriSegment seg, const DoubleProduct dp) const
00065 {
00066   return _doubleProducts[8*seg + dp];
00067 }
00068 
00069 inline double TransformedTriangle::calcStableT(const TetraCorner corner) const
00070 {
00071   //   assert(_isTripleProductsCalculated);
00072   //   assert(_validTP[corner]);
00073   return _tripleProducts[corner];
00074 }
00075 
00076 inline double TransformedTriangle::calcUnstableC(const TriSegment seg, const DoubleProduct dp) const
00077 {
00078   
00079   // find the points of the triangle
00080   // 0 -> P, 1 -> Q, 2 -> R 
00081   const int pt1 = seg;
00082   const int pt2 = (seg + 1) % 3;
00083   
00084   // find offsets
00085   const int off1 = DP_OFFSET_1[dp];
00086   const int off2 = DP_OFFSET_2[dp];
00087   
00088   return _coords[5*pt1 + off1] * _coords[5*pt2 + off2] - _coords[5*pt1 + off2] * _coords[5*pt2 + off1];
00089 }
00090 
00091 // ----------------------------------------------------------------------------------
00092 //  TransformedTriangle_intersect.cxx                                            
00093 // ----------------------------------------------------------------------------------
00094 inline bool TransformedTriangle::testSurfaceEdgeIntersection(const TetraEdge edge) const 
00095 { 
00096   return _triangleSurroundsEdgeCache[edge] && testEdgeIntersectsTriangle(edge);
00097 }
00098 
00099 inline bool TransformedTriangle::testSegmentFacetIntersection(const TriSegment seg, const TetraFacet facet) const 
00100 { 
00101   return testFacetSurroundsSegment(seg, facet) && testSegmentIntersectsFacet(seg, facet); 
00102 }
00103 
00104 inline bool TransformedTriangle::testSurfaceRayIntersection(const TetraCorner corner) const
00105 { 
00106   return testTriangleSurroundsRay( corner ) && testSurfaceAboveCorner( corner ); 
00107 }
00108 
00109 inline bool TransformedTriangle::testCornerInTetrahedron(const TriCorner corner) const
00110 {
00111   const double pt[4] = 
00112     {
00113       _coords[5*corner],     // x
00114       _coords[5*corner + 1], // y
00115       _coords[5*corner + 2], // z
00116       _coords[5*corner + 3]  // z
00117     };
00118   
00119   for(int i = 0 ; i < 4 ; ++i) 
00120     {
00121       if(pt[i] < 0.0 || pt[i] > 1.0)
00122         {
00123           return false;
00124         }
00125     }
00126   return true;
00127 }
00128 
00129 inline  bool TransformedTriangle::testCornerOnXYZFacet(const TriCorner corner) const
00130 {
00131 #if 0
00132   const double pt[4] = 
00133     {
00134       _coords[5*corner],     // x
00135       _coords[5*corner + 1], // y 
00136       _coords[5*corner + 2], // z
00137       _coords[5*corner + 3]  // h
00138     };
00139 #endif
00140   const double* pt = &_coords[5*corner];
00141     
00142   if(pt[3] != 0.0) 
00143     {
00144       return false;
00145     }
00146 
00147   for(int i = 0 ; i < 3 ; ++i) 
00148     {
00149       if(pt[i] < 0.0 || pt[i] > 1.0)
00150         {
00151           return false;
00152         }
00153     }
00154   return true;
00155 }
00156 
00157 inline  bool TransformedTriangle::testCornerAboveXYZFacet(const TriCorner corner) const
00158 {
00159   const double x = _coords[5*corner];
00160   const double y = _coords[5*corner + 1];
00161   const double h = _coords[5*corner + 3];
00162   const double H = _coords[5*corner + 4];
00163         
00164   return h < 0.0 && H >= 0.0 && x >= 0.0 && y >= 0.0;
00165         
00166 }
00167 
00168 inline bool TransformedTriangle::testEdgeIntersectsTriangle(const TetraEdge edge) const
00169 {
00170   
00171   //  assert(edge < H01);
00172   
00173   // correspondance edge - triple products
00174   // for edges OX, ..., ZX (Grandy, table III)
00175   static const TetraCorner TRIPLE_PRODUCTS[12] = 
00176     {
00177       X, O, // OX
00178       Y, O, // OY
00179       Z, O, // OZ 
00180       X, Y, // XY
00181       Y, Z, // YZ
00182       Z, X, // ZX
00183     };
00184 
00185   // Grandy, [16]
00186   const double t1 = calcStableT(TRIPLE_PRODUCTS[2*edge]);
00187   const double t2 = calcStableT(TRIPLE_PRODUCTS[2*edge + 1]);
00188 
00189   //? should equality with zero use epsilon?
00190   LOG(5, "testEdgeIntersectsTriangle : t1 = " << t1 << " t2 = " << t2 );
00191   return (t1*t2 <= 0.0) && (t1 - t2 != 0.0);
00192 }
00193 
00194 inline bool TransformedTriangle::testFacetSurroundsSegment(const TriSegment seg, const TetraFacet facet) const
00195 {
00196 #if 0
00197   const double signs[3] = 
00198     {
00199       SIGN_FOR_SEG_FACET_INTERSECTION[3*facet],
00200       SIGN_FOR_SEG_FACET_INTERSECTION[3*facet + 1],
00201       SIGN_FOR_SEG_FACET_INTERSECTION[3*facet + 2]
00202     };
00203 #endif
00204 
00205   const double* signs = &SIGN_FOR_SEG_FACET_INTERSECTION[3*facet];
00206   const double c1 = signs[0]*calcStableC(seg, DP_FOR_SEG_FACET_INTERSECTION[3*facet]);
00207   const double c2 = signs[1]*calcStableC(seg, DP_FOR_SEG_FACET_INTERSECTION[3*facet + 1]);
00208   const double c3 = signs[2]*calcStableC(seg, DP_FOR_SEG_FACET_INTERSECTION[3*facet + 2]);
00209 
00210   return (c1*c3 > 0.0) && (c2*c3 > 0.0);
00211 }
00212 
00213 inline bool TransformedTriangle::testSegmentIntersectsFacet(const TriSegment seg, const TetraFacet facet) const
00214 {
00215   // use correspondance facet a = 0 <=> offset for coordinate a in _coords
00216   // and also correspondance segment AB => corner A
00217   const double coord1 = _coords[5*seg + facet];
00218   const double coord2 = _coords[5*( (seg + 1) % 3) + facet];
00219   
00220   //? should we use epsilon-equality here in second test?
00221   LOG(5, "coord1 : " << coord1 << " coord2 : " << coord2 );
00222   
00223   return (coord1*coord2 <= 0.0) && (coord1 != coord2);
00224 }
00225 
00226 inline bool TransformedTriangle::testSegmentIntersectsHPlane(const TriSegment seg) const
00227 {
00228   // get the H - coordinates
00229   const double coord1 = _coords[5*seg + 4];
00230   const double coord2 = _coords[5*( (seg + 1) % 3) + 4];
00231   //? should we use epsilon-equality here in second test?
00232   LOG(5, "coord1 : " << coord1 << " coord2 : " << coord2 );
00233   
00234   return (coord1*coord2 <= 0.0) && (coord1 != coord2);
00235 }
00236 
00237 inline bool TransformedTriangle::testSurfaceAboveCorner(const TetraCorner corner) const
00238 {
00239   // ? There seems to be an error in Grandy -> it should be C_XY instead of C_YZ in [28].
00240   // ? I haven't really figured out why, but it seems to work.
00241   const double normal = calcStableC(PQ, C_XY) + calcStableC(QR, C_XY) + calcStableC(RP, C_XY);
00242 
00243   LOG(6, "surface above corner " << corner << " : " << "n = " << normal << ", t = [" <<  calcTByDevelopingRow(corner, 1, false) << ", "  << calcTByDevelopingRow(corner, 2, false) << ", " << calcTByDevelopingRow(corner, 3, false) );
00244   LOG(6, "] - stable : " << calcStableT(corner)  );
00245 
00246   //? we don't care here if the triple product is "invalid", that is, the triangle does not surround one of the
00247   // edges going out from the corner (Grandy [53])
00248   if(!_validTP[corner])
00249     {
00250       return ( calcTByDevelopingRow(corner, 1, false) * normal ) >= 0.0;
00251     }
00252   else
00253     {
00254       return ( calcStableT(corner) * normal ) >= 0.0;
00255     }
00256 }
00257 
00258 inline bool TransformedTriangle::testTriangleSurroundsRay(const TetraCorner corner) const
00259 {
00260   //  assert(corner == X || corner == Y || corner == Z);
00261 
00262   // double products to use for the possible corners
00263   static const DoubleProduct DP_FOR_RAY_INTERSECTION[4] = 
00264     {
00265       DoubleProduct(0),        // O - only here to fill out and make indices match
00266       C_10,     // X
00267       C_01,     // Y
00268       C_XY      // Z
00269     };
00270 
00271   const DoubleProduct dp = DP_FOR_RAY_INTERSECTION[corner];
00272 
00273   const double cPQ = calcStableC(PQ, dp);
00274   const double cQR = calcStableC(QR, dp);
00275   const double cRP = calcStableC(RP, dp);
00276 
00277   //? NB here we have no correction for precision - is this good?
00278   // Our authority Grandy says nothing
00279   LOG(5, "dp in triSurrRay for corner " << corner << " = [" << cPQ << ", " << cQR << ", " << cRP << "]" );
00280 
00281   return ( cPQ*cQR > 0.0 ) && ( cPQ*cRP > 0.0 );
00282 
00283 }
00284 #endif