1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #ifndef __TRANSFORMEDTRIANGLEINLINE_HXX__
20 #define __TRANSFORMEDTRIANGLEINLINE_HXX__
22 // This file contains inline versions of some of the methods in the TransformedTriangle*.cxx files.
23 // It replaces those methods if OPTIMIZE is defined.
24 // NB : most of these methods have documentation in their corresponding .cxx - file.
26 // ----------------------------------------------------------------------------------
27 // Optimization methods. These are only defined and used if OPTIMIZE is defined.
28 // -----------------------------------------------------------------------------------
31 inline void TransformedTriangle::preCalculateTriangleSurroundsEdge()
33 for(TetraEdge edge = OX ; edge <= ZX ; edge = TetraEdge(edge + 1))
35 _triangleSurroundsEdgeCache[edge] = testTriangleSurroundsEdge(edge);
40 // ----------------------------------------------------------------------------------
41 // TransformedTriangle_math.cxx
42 // ----------------------------------------------------------------------------------
44 inline void TransformedTriangle::resetDoubleProducts(const TriSegment seg, const TetraCorner corner)
46 // set the three corresponding double products to 0.0
47 static const DoubleProduct DOUBLE_PRODUCTS[12] =
49 C_YZ, C_ZX, C_XY, // O
50 C_YZ, C_ZH, C_YH, // X
51 C_ZX, C_ZH, C_XH, // Y
55 for(int i = 0 ; i < 3 ; ++i) {
56 const DoubleProduct dp = DOUBLE_PRODUCTS[3*corner + i];
58 LOG(6, std::endl << "resetting inconsistent dp :" << dp << " for corner " << corner);
59 _doubleProducts[8*seg + dp] = 0.0;
63 inline double TransformedTriangle::calcStableC(const TriSegment seg, const DoubleProduct dp) const
65 return _doubleProducts[8*seg + dp];
68 inline double TransformedTriangle::calcStableT(const TetraCorner corner) const
70 // assert(_isTripleProductsCalculated);
71 // assert(_validTP[corner]);
72 return _tripleProducts[corner];
75 inline double TransformedTriangle::calcUnstableC(const TriSegment seg, const DoubleProduct dp) const
78 // find the points of the triangle
79 // 0 -> P, 1 -> Q, 2 -> R
81 const int pt2 = (seg + 1) % 3;
84 const int off1 = DP_OFFSET_1[dp];
85 const int off2 = DP_OFFSET_2[dp];
87 return _coords[5*pt1 + off1] * _coords[5*pt2 + off2] - _coords[5*pt1 + off2] * _coords[5*pt2 + off1];
90 // ----------------------------------------------------------------------------------
91 // TransformedTriangle_intersect.cxx
92 // ----------------------------------------------------------------------------------
93 inline bool TransformedTriangle::testSurfaceEdgeIntersection(const TetraEdge edge) const
95 return _triangleSurroundsEdgeCache[edge] && testEdgeIntersectsTriangle(edge);
98 inline bool TransformedTriangle::testSegmentFacetIntersection(const TriSegment seg, const TetraFacet facet) const
100 return testFacetSurroundsSegment(seg, facet) && testSegmentIntersectsFacet(seg, facet);
103 inline bool TransformedTriangle::testSurfaceRayIntersection(const TetraCorner corner) const
105 return testTriangleSurroundsRay( corner ) && testSurfaceAboveCorner( corner );
108 inline bool TransformedTriangle::testCornerInTetrahedron(const TriCorner corner) const
112 _coords[5*corner], // x
113 _coords[5*corner + 1], // y
114 _coords[5*corner + 2], // z
115 _coords[5*corner + 3] // z
118 for(int i = 0 ; i < 4 ; ++i)
120 if(pt[i] < 0.0 || pt[i] > 1.0)
128 inline bool TransformedTriangle::testCornerOnXYZFacet(const TriCorner corner) const
133 _coords[5*corner], // x
134 _coords[5*corner + 1], // y
135 _coords[5*corner + 2], // z
136 _coords[5*corner + 3] // h
139 const double* pt = &_coords[5*corner];
146 for(int i = 0 ; i < 3 ; ++i)
148 if(pt[i] < 0.0 || pt[i] > 1.0)
156 inline bool TransformedTriangle::testCornerAboveXYZFacet(const TriCorner corner) const
158 const double x = _coords[5*corner];
159 const double y = _coords[5*corner + 1];
160 const double h = _coords[5*corner + 3];
161 const double H = _coords[5*corner + 4];
163 return h < 0.0 && H >= 0.0 && x >= 0.0 && y >= 0.0;
167 inline bool TransformedTriangle::testEdgeIntersectsTriangle(const TetraEdge edge) const
170 // assert(edge < H01);
172 // correspondance edge - triple products
173 // for edges OX, ..., ZX (Grandy, table III)
174 static const TetraCorner TRIPLE_PRODUCTS[12] =
185 const double t1 = calcStableT(TRIPLE_PRODUCTS[2*edge]);
186 const double t2 = calcStableT(TRIPLE_PRODUCTS[2*edge + 1]);
188 //? should equality with zero use epsilon?
189 LOG(5, "testEdgeIntersectsTriangle : t1 = " << t1 << " t2 = " << t2 );
190 return (t1*t2 <= 0.0) && (t1 - t2 != 0.0);
193 inline bool TransformedTriangle::testFacetSurroundsSegment(const TriSegment seg, const TetraFacet facet) const
196 const double signs[3] =
198 SIGN_FOR_SEG_FACET_INTERSECTION[3*facet],
199 SIGN_FOR_SEG_FACET_INTERSECTION[3*facet + 1],
200 SIGN_FOR_SEG_FACET_INTERSECTION[3*facet + 2]
204 const double* signs = &SIGN_FOR_SEG_FACET_INTERSECTION[3*facet];
205 const double c1 = signs[0]*calcStableC(seg, DP_FOR_SEG_FACET_INTERSECTION[3*facet]);
206 const double c2 = signs[1]*calcStableC(seg, DP_FOR_SEG_FACET_INTERSECTION[3*facet + 1]);
207 const double c3 = signs[2]*calcStableC(seg, DP_FOR_SEG_FACET_INTERSECTION[3*facet + 2]);
209 return (c1*c3 > 0.0) && (c2*c3 > 0.0);
212 inline bool TransformedTriangle::testSegmentIntersectsFacet(const TriSegment seg, const TetraFacet facet) const
214 // use correspondance facet a = 0 <=> offset for coordinate a in _coords
215 // and also correspondance segment AB => corner A
216 const double coord1 = _coords[5*seg + facet];
217 const double coord2 = _coords[5*( (seg + 1) % 3) + facet];
219 //? should we use epsilon-equality here in second test?
220 LOG(5, "coord1 : " << coord1 << " coord2 : " << coord2 );
222 return (coord1*coord2 <= 0.0) && (coord1 != coord2);
225 inline bool TransformedTriangle::testSegmentIntersectsHPlane(const TriSegment seg) const
227 // get the H - coordinates
228 const double coord1 = _coords[5*seg + 4];
229 const double coord2 = _coords[5*( (seg + 1) % 3) + 4];
230 //? should we use epsilon-equality here in second test?
231 LOG(5, "coord1 : " << coord1 << " coord2 : " << coord2 );
233 return (coord1*coord2 <= 0.0) && (coord1 != coord2);
236 inline bool TransformedTriangle::testSurfaceAboveCorner(const TetraCorner corner) const
238 // ? There seems to be an error in Grandy -> it should be C_XY instead of C_YZ in [28].
239 // ? I haven't really figured out why, but it seems to work.
240 const double normal = calcStableC(PQ, C_XY) + calcStableC(QR, C_XY) + calcStableC(RP, C_XY);
242 LOG(6, "surface above corner " << corner << " : " << "n = " << normal << ", t = [" << calcTByDevelopingRow(corner, 1, false) << ", " << calcTByDevelopingRow(corner, 2, false) << ", " << calcTByDevelopingRow(corner, 3, false) );
243 LOG(6, "] - stable : " << calcStableT(corner) );
245 //? we don't care here if the triple product is "invalid", that is, the triangle does not surround one of the
246 // edges going out from the corner (Grandy [53])
247 if(!_validTP[corner])
249 return ( calcTByDevelopingRow(corner, 1, false) * normal ) >= 0.0;
253 return ( calcStableT(corner) * normal ) >= 0.0;
257 inline bool TransformedTriangle::testTriangleSurroundsRay(const TetraCorner corner) const
259 // assert(corner == X || corner == Y || corner == Z);
261 // double products to use for the possible corners
262 static const DoubleProduct DP_FOR_RAY_INTERSECTION[4] =
264 DoubleProduct(0), // O - only here to fill out and make indices match
270 const DoubleProduct dp = DP_FOR_RAY_INTERSECTION[corner];
272 const double cPQ = calcStableC(PQ, dp);
273 const double cQR = calcStableC(QR, dp);
274 const double cRP = calcStableC(RP, dp);
276 //? NB here we have no correction for precision - is this good?
277 // Our authority Grandy says nothing
278 LOG(5, "dp in triSurrRay for corner " << corner << " = [" << cPQ << ", " << cQR << ", " << cRP << "]" );
280 return ( cPQ*cQR > 0.0 ) && ( cPQ*cRP > 0.0 );