FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

surfaceIntersection.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 Description
00025 
00026 \*---------------------------------------------------------------------------*/
00027 
00028 #include "surfaceIntersection.H"
00029 #include <meshTools/triSurfaceSearch.H>
00030 #include <triSurface/labelPairLookup.H>
00031 #include <OpenFOAM/OFstream.H>
00032 #include <OpenFOAM/HashSet.H>
00033 #include <triSurface/triSurface.H>
00034 #include <meshTools/pointIndexHit.H>
00035 #include <meshTools/octreeDataTriSurface.H>
00036 #include <meshTools/octree.H>
00037 #include <OpenFOAM/mergePoints.H>
00038 #include <OpenFOAM/plane.H>
00039 #include "edgeIntersections.H"
00040 
00041 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00042 
00043 defineTypeNameAndDebug(Foam::surfaceIntersection, 0);
00044 
00045 
00046 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00047 
00048 // Checks if there exists a special topological situation that causes
00049 // edge and the face it hit not to be recognized.
00050 //
00051 // For now if the face shares a point with the edge
00052 bool Foam::surfaceIntersection::excludeEdgeHit
00053 (
00054     const triSurface& surf,
00055     const label edgeI,
00056     const label faceI,
00057     const scalar
00058 )
00059 {
00060     const labelledTri& f = surf.localFaces()[faceI];
00061 
00062     const edge& e = surf.edges()[edgeI];
00063 
00064     if
00065     (
00066         (f[0] == e.start())
00067      || (f[0] == e.end())
00068      || (f[1] == e.start())
00069      || (f[1] == e.end())
00070      || (f[2] == e.start())
00071      || (f[2] == e.end())
00072     )
00073     {
00074         return true;
00075 
00076 //        // Get edge vector
00077 //        vector eVec = e.vec(surf.localPoints());
00078 //        eVec /= mag(eVec) + VSMALL;
00079 //
00080 //        const labelList& eLabels = surf.faceEdges()[faceI];
00081 //
00082 //        // Get edge vector of 0th edge of face
00083 //        vector e0Vec = surf.edges()[eLabels[0]].vec(surf.localPoints());
00084 //        e0Vec /= mag(e0Vec) + VSMALL;
00085 //
00086 //        vector n = e0Vec ^ eVec;
00087 //
00088 //        if (mag(n) < SMALL)
00089 //        {
00090 //            // e0 is aligned with e. Choose next edge of face.
00091 //            vector e1Vec = surf.edges()[eLabels[1]].vec(surf.localPoints());
00092 //            e1Vec /= mag(e1Vec) + VSMALL;
00093 //
00094 //            n = e1Vec ^ eVec;
00095 //
00096 //            if (mag(n) < SMALL)
00097 //            {
00098 //                // Problematic triangle. Two edges aligned with edgeI. Give
00099 //                // up.
00100 //                return true;
00101 //            }
00102 //        }
00103 //
00104 //        // Check if same as faceNormal
00105 //        if (mag(n & surf.faceNormals()[faceI]) > 1-tol)
00106 //        {
00107 //
00108 //            Pout<< "edge:" << e << "  face:" << faceI
00109 //                << "  e0Vec:" << e0Vec << "  n:" << n
00110 //                << "  normalComponent:" << (n & surf.faceNormals()[faceI])
00111 //                << "  tol:" << tol << endl;
00112 //
00113 //            return true;
00114 //        }
00115 //        else
00116 //        {
00117 //            return false;
00118 //        }
00119     }
00120     else
00121     {
00122         return false;
00123     }
00124 }
00125 
00126 
00130 //Foam::pointIndexHit Foam::surfaceIntersection::faceEdgeIntersection
00131 //(
00132 //    const triSurface& surf,
00133 //    const label hitFaceI,
00134 //
00135 //    const vector& n,
00136 //    const point& eStart,
00137 //    const point& eEnd
00138 //)
00139 //{
00140 //    pointIndexHit pInter;
00141 //
00142 //    const pointField& points = surf.points();
00143 //
00144 //    const labelledTri& f = surf.localFaces()[hitFaceI];
00145 //
00146 //    // Plane for intersect test.
00147 //    plane pl(eStart, n);
00148 //
00149 //    forAll(f, fp)
00150 //    {
00151 //        label fp1 = (fp + 1) % 3;
00152 //
00153 //        const point& start = points[f[fp]];
00154 //        const point& end = points[f[fp1]];
00155 //
00156 //        vector eVec(end - start);
00157 //
00158 //        scalar s = pl.normalIntersect(start, eVec);
00159 //
00160 //        if (s < 0 || s > 1)
00161 //        {
00162 //            pInter.setPoint(start + s*eVec);
00163 //
00164 //            // Check if is correct one: orientation walking
00165 //            //  eStart - eEnd - hitPoint should be opposite n
00166 //            vector n2(triPointRef(start, end, pInter.hitPoint()).normal());
00167 //
00168 //            Pout<< "plane normal:" << n
00169 //                << "  start:" << start << "  end:" << end
00170 //                << "  hit at:" << pInter.hitPoint()
00171 //                << "  resulting normal:" << n2 << endl;
00172 //
00173 //            if ((n2 & n) < 0)
00174 //            {
00175 //                pInter.setHit();
00176 //
00177 //                // Find corresponding edge between f[fp] f[fp1]
00178 //                label edgeI =
00179 //                    meshTools::findEdge
00180 //                    (
00181 //                        surf.edges(),
00182 //                        surf.faceEdges()[hitFaceI],
00183 //                        f[fp],
00184 //                        f[fp1]
00185 //                    );
00186 //
00187 //                pInter.setIndex(edgeI);
00188 //
00189 //                return pInter;
00190 //            }
00191 //        }
00192 //    }
00193 //
00194 //    FatalErrorIn("surfaceIntersection::borderEdgeIntersection")
00195 //        << "Did not find intersection of plane " << pl
00196 //        << " with edges of face " << hitFaceI << " verts:" << f
00197 //        << abort(FatalError);
00198 //
00199 //    return pInter;
00200 //}
00201 
00202 
00203 
00204 void Foam::surfaceIntersection::storeIntersection
00205 (
00206     const bool isFirstSurf,
00207     const labelList& facesA,
00208     const label faceB,
00209     DynamicList<edge>& allCutEdges,
00210     DynamicList<point>& allCutPoints
00211 )
00212 {
00213 
00214     forAll(facesA, facesAI)
00215     {
00216         label faceA = facesA[facesAI];
00217 
00218         // Combine two faces. Always make sure the face from the first surface
00219         // is element 0.
00220         FixedList<label, 2> twoFaces;
00221         if (isFirstSurf)
00222         {
00223             twoFaces[0] = faceA;
00224             twoFaces[1] = faceB;
00225         }
00226         else
00227         {
00228             twoFaces[0] = faceB;
00229             twoFaces[1] = faceA;
00230         }
00231 
00232         labelPairLookup::const_iterator iter = facePairToVertex_.find(twoFaces);
00233 
00234         if (iter == facePairToVertex_.end())
00235         {
00236             // New intersection. Store face-face intersection.
00237             facePairToVertex_.insert(twoFaces, allCutPoints.size()-1);
00238         }
00239         else
00240         {
00241             // Second occurrence of surf1-surf2 intersection.
00242             // Or rather the face on surf1 intersects a face on
00243             // surface2 twice -> we found edge.
00244 
00245             // Check whether perhaps degenerate
00246             const point& prevHit = allCutPoints[*iter];
00247 
00248             const point& thisHit = allCutPoints[allCutPoints.size()-1];
00249 
00250             if (mag(prevHit - thisHit) < SMALL)
00251             {
00252                 WarningIn
00253                 (
00254                     "Foam::surfaceIntersection::storeIntersection"
00255                     "(const bool isFirstSurf, const labelList& facesA,"
00256                     "const label faceB, DynamicList<edge>& allCutEdges,"
00257                     "DynamicList<point>& allCutPoints)"
00258                 )   << "Encountered degenerate edge between face "
00259                     << twoFaces[0] << " on first surface"
00260                     << " and face " << twoFaces[1] << " on second surface"
00261                     << endl
00262                     << "Point on first surface:" << prevHit << endl
00263                     << "Point on second surface:" << thisHit << endl
00264                     << endl;
00265             }
00266             else
00267             {
00268                 allCutEdges.append(edge(*iter, allCutPoints.size()-1));
00269 
00270                 // Remember face on surf
00271                 facePairToEdge_.insert(twoFaces, allCutEdges.size()-1);
00272             }
00273         }
00274     }
00275 }
00276 
00277 
00278 // Classify cut of edge of surface1 with surface2:
00279 // 1- point of edge hits point on surface2
00280 // 2- edge pierces point on surface2
00281 // 3- point of edge hits edge on surface2
00282 // 4- edge pierces edge on surface2
00283 // 5- point of edge hits face on surface2
00284 // 6- edge pierces face on surface2
00285 //
00286 // Note that handling of 2 and 4 should be the same but with surface1 and
00287 // surface2 reversed.
00288 void Foam::surfaceIntersection::classifyHit
00289 (
00290     const triSurface& surf1,
00291     const scalarField& surf1PointTol,
00292     const triSurface& surf2,
00293     const bool isFirstSurf,
00294     const label edgeI,
00295     const scalar tolDim,
00296     const pointIndexHit& pHit,
00297 
00298     DynamicList<edge>& allCutEdges,
00299     DynamicList<point>& allCutPoints,
00300     List<DynamicList<label> >& surfEdgeCuts
00301 )
00302 {
00303     const edge& e = surf1.edges()[edgeI];
00304 
00305     const labelList& facesA = surf1.edgeFaces()[edgeI];
00306 
00307     // Label of face on surface2 edgeI intersected
00308     label surf2FaceI = pHit.index();
00309 
00310     // Classify point on surface2
00311 
00312     const labelledTri& f2 = surf2.localFaces()[surf2FaceI];
00313 
00314     const pointField& surf2Pts = surf2.localPoints();
00315 
00316     label nearType;
00317     label nearLabel;
00318 
00319     (void)triPointRef
00320     (
00321         surf2Pts[f2[0]],
00322         surf2Pts[f2[1]],
00323         surf2Pts[f2[2]]
00324     ).classify(pHit.hitPoint(), tolDim, nearType, nearLabel);
00325 
00326     // Classify points on edge of surface1
00327     label edgeEnd =
00328         classify
00329         (
00330             surf1PointTol[e.start()],
00331             surf1PointTol[e.end()],
00332             pHit.hitPoint(),
00333             e,
00334             surf1.localPoints()
00335         );
00336 
00337     if (nearType == triPointRef::POINT)
00338     {
00339         if (edgeEnd >= 0)
00340         {
00341             // 1. Point hits point. Do nothing.
00342             if (debug&2)
00343             {
00344                 Pout<< pHit.hitPoint() << " is surf1:"
00345                     << " end point of edge " << e
00346                     << " surf2: vertex " << f2[nearLabel]
00347                     << " coord:" << surf2Pts[f2[nearLabel]] << endl;
00348             }
00349         }
00350         else
00351         {
00352             // 2. Edge hits point. Cut edge with new point.
00353             if (debug&2)
00354             {
00355                 Pout<< pHit.hitPoint() << " is surf1:"
00356                     << " somewhere on edge " << e
00357                     << " surf2: vertex " << f2[nearLabel]
00358                     << " coord:" << surf2Pts[f2[nearLabel]] << endl;
00359             }
00360 
00361             allCutPoints.append(pHit.hitPoint());
00362             surfEdgeCuts[edgeI].append(allCutPoints.size()-1);
00363 
00364             const labelList& facesB = surf2.pointFaces()[f2[nearLabel]];
00365 
00366             forAll(facesB, faceBI)
00367             {
00368                 storeIntersection
00369                 (
00370                     isFirstSurf,
00371                     facesA,
00372                     facesB[faceBI],
00373                     allCutEdges,
00374                     allCutPoints
00375                 );
00376             }
00377         }
00378     }
00379     else if (nearType == triPointRef::EDGE)
00380     {
00381         if (edgeEnd >= 0)
00382         {
00383             // 3. Point hits edge. Do nothing on this side. Reverse
00384             // is handled by 2 (edge hits point)
00385             label edge2I = getEdge(surf2, surf2FaceI, nearLabel);
00386             const edge& e2 = surf2.edges()[edge2I];
00387 
00388             if (debug&2)
00389             {
00390                 Pout<< pHit.hitPoint() << " is surf1:"
00391                     << " end point of edge " << e
00392                     << " surf2: edge " << e2
00393                     << " coords:" << surf2Pts[e2.start()]
00394                     << surf2Pts[e2.end()] << endl;
00395             }
00396         }
00397         else
00398         {
00399             // 4. Edge hits edge.
00400 
00401             // Cut edge with new point (creates duplicates when
00402             // doing the surf2 with surf1 intersection but these
00403             // are merged later on)
00404 
00405             label edge2I = getEdge(surf2, surf2FaceI, nearLabel);
00406             const edge& e2 = surf2.edges()[edge2I];
00407 
00408             if (debug&2)
00409             {
00410                 Pout<< pHit.hitPoint() << " is surf1:"
00411                     << " somewhere on edge " << e
00412                     << " surf2: edge " << e2
00413                     << " coords:" << surf2Pts[e2.start()]
00414                     << surf2Pts[e2.end()] << endl;
00415             }
00416 
00417             allCutPoints.append(pHit.hitPoint());
00418             surfEdgeCuts[edgeI].append(allCutPoints.size()-1);
00419 
00420             // edge hits all faces on surf2 connected to the edge
00421 
00422             if (isFirstSurf)
00423             {
00424                 // edge-edge intersection is symmetric, store only
00425                 // once.
00426                 // edge hits all faces on surf2 connected to the
00427                 // edge
00428 
00429                 const labelList& facesB = surf2.edgeFaces()[edge2I];
00430 
00431                 forAll(facesB, faceBI)
00432                 {
00433                     storeIntersection
00434                     (
00435                         isFirstSurf,
00436                         facesA,
00437                         facesB[faceBI],
00438                         allCutEdges,
00439                         allCutPoints
00440                     );
00441                 }
00442             }
00443         }
00444     }
00445     else
00446     {
00447         if (edgeEnd >= 0)
00448         {
00449             // 5. Point hits face. Do what? Introduce
00450             // point & triangulation in face?
00451             if (debug&2)
00452             {
00453                 Pout<< pHit.hitPoint() << " is surf1:"
00454                     << " end point of edge " << e
00455                     << " surf2: face " << surf2FaceI
00456                     << endl;
00457             }
00458 
00459             //
00460             // Look exactly at what side (of surf2) edge is. Leave out ones on
00461             // inside of surf2 (i.e. on opposite side of normal)
00462             //
00463 
00464             // Vertex on/near surf2
00465             label nearVert = -1;
00466 
00467             if (edgeEnd == 0)
00468             {
00469                 nearVert = e.start();
00470             }
00471             else
00472             {
00473                 nearVert = e.end();
00474             }
00475 
00476             const point& nearPt = surf1.localPoints()[nearVert];
00477 
00478             // Vertex away from surf2
00479             label otherVert = e.otherVertex(nearVert);
00480 
00481             const point& otherPt = surf1.localPoints()[otherVert];
00482 
00483 
00484             if (debug)
00485             {
00486                 Pout
00487                     << pHit.hitPoint() << " is surf1:"
00488                     << " end point of edge " << e << " coord:"
00489                     << surf1.localPoints()[nearVert]
00490                     << " surf2: face " << surf2FaceI << endl;
00491             }
00492 
00493             vector eVec = otherPt - nearPt;
00494 
00495             if ((surf2.faceNormals()[surf2FaceI] & eVec) > 0)
00496             {
00497                 // otherVert on outside of surf2
00498 
00499                 // Shift hitPoint a bit along edge.
00500                 //point hitPt = nearPt + 0.1*eVec;
00501                 point hitPt = nearPt;
00502 
00503                 if (debug&2)
00504                 {
00505                     Pout<< "Shifted " << pHit.hitPoint()
00506                         << " to " << hitPt
00507                         << " along edge:" << e
00508                         << " coords:" << surf1.localPoints()[e.start()]
00509                         << surf1.localPoints()[e.end()] << endl;
00510                 }
00511 
00512                 // Reclassify as normal edge-face pierce (see below)
00513 
00514                 allCutPoints.append(hitPt);
00515                 surfEdgeCuts[edgeI].append(allCutPoints.size()-1);
00516 
00517                 // edge hits single face only
00518                 storeIntersection
00519                 (
00520                     isFirstSurf,
00521                     facesA,
00522                     surf2FaceI,
00523                     allCutEdges,
00524                     allCutPoints
00525                 );
00526             }
00527             else
00528             {
00529                 if (debug&2)
00530                 {
00531                     Pout<< "Discarding " << pHit.hitPoint()
00532                         << " since edge " << e << " on inside of surf2."
00533                         << " surf2 normal:" << surf2.faceNormals()[surf2FaceI]
00534                         << endl;
00535                 }
00536             }
00537         }
00538         else
00539         {
00540             // 6. Edge pierces face. 'Normal' situation.
00541             if (debug&2)
00542             {
00543                 Pout<< pHit.hitPoint() << " is surf1:"
00544                     << " somewhere on edge " << e
00545                     << " surf2: face " << surf2FaceI
00546                     << endl;
00547             }
00548 
00549             // edgeI intersects surf2. Store point.
00550             allCutPoints.append(pHit.hitPoint());
00551             surfEdgeCuts[edgeI].append(allCutPoints.size()-1);
00552 
00553             // edge hits single face only
00554             storeIntersection
00555             (
00556                 isFirstSurf,
00557                 facesA,
00558                 surf2FaceI,
00559                 allCutEdges,
00560                 allCutPoints
00561             );
00562         }
00563     }
00564     if (debug&2)
00565     {
00566         Pout<< endl;
00567     }
00568 }
00569 
00570 
00571 // Cut all edges of surf1 with surf2. Sets
00572 // - cutPoints          : coordinates of cutPoints
00573 // - cutEdges           : newly created edges between cutPoints
00574 // - facePairToVertex   : hash from face1I and face2I to cutPoint
00575 // - facePairToEdge     : hash from face1I and face2I to cutEdge
00576 // - surfEdgeCuts       : gives for each edge the cutPoints
00577 //                        (in order from start to end)
00578 //
00579 void Foam::surfaceIntersection::doCutEdges
00580 (
00581     const triSurface& surf1,
00582     const triSurfaceSearch& querySurf2,
00583     const bool isFirstSurf,
00584     const bool isSelfIntersection,
00585 
00586     DynamicList<edge>& allCutEdges,
00587     DynamicList<point>& allCutPoints,
00588     List<DynamicList<label> >& surfEdgeCuts
00589 )
00590 {
00591     scalar oldTol = intersection::setPlanarTol(1E-3);
00592 
00593     const pointField& surf1Pts = surf1.localPoints();
00594 
00595     // Calculate local (to point) tolerance based on min edge length.
00596     scalarField surf1PointTol(surf1Pts.size());
00597 
00598     forAll(surf1PointTol, pointI)
00599     {
00600         surf1PointTol[pointI] =
00601             intersection::planarTol()
00602           * minEdgeLen(surf1, pointI);
00603     }
00604 
00605     const triSurface& surf2 = querySurf2.surface();
00606 
00607     forAll(surf1.edges(), edgeI)
00608     {
00609         const edge& e = surf1.edges()[edgeI];
00610 
00611         point pStart = surf1Pts[e.start()];
00612         const point& pEnd = surf1Pts[e.end()];
00613 
00614         const point tolVec = intersection::planarTol()*(pEnd-pStart);
00615         const scalar tolDim = mag(tolVec);
00616 
00617         bool doTrack = false;
00618         do
00619         {
00620             pointIndexHit pHit = querySurf2.tree().findLine(pStart, pEnd);
00621 
00622             if (pHit.hit())
00623             {
00624                 if (isSelfIntersection)
00625                 {
00626                     // Skip all intersections which are hit at endpoints of
00627                     // edge.
00628                     // Problem is that if faces are almost coincident the
00629                     // intersection point will be calculated quite incorrectly
00630                     // The error might easily be larger than 1% of the edge
00631                     // length.
00632                     // So what we do here is to exclude hit faces if our edge
00633                     // is in their plane and they share a point with the edge.
00634 
00635                     // Label of face on surface2 edgeI intersected
00636                     label hitFaceI = pHit.index();
00637 
00638                     if
00639                     (
00640                         !excludeEdgeHit
00641                         (
00642                             surf1,
00643                             edgeI,
00644                             hitFaceI,
00645                             0.1         // 1-cos of angle between normals
00646                         )
00647                     )
00648                     {
00649                         // Classify point on surface1
00650                         label edgeEnd = classify
00651                         (
00652                             surf1PointTol[e.start()],
00653                             surf1PointTol[e.end()],
00654                             pHit.hitPoint(),
00655                             e,
00656                             surf1Pts
00657                         );
00658 
00659                         if (edgeEnd < 0)
00660                         {
00661                             if (debug)
00662                             {
00663                                 Pout<< "edge:" << edgeI << " vertices:" << e
00664                                     << "  start:" << surf1Pts[e.start()]
00665                                     << "  end:" << surf1Pts[e.end()]
00666                                     << "  hit:" << pHit.hitPoint()
00667                                     << "  tolDim:" << tolDim
00668                                     << "  planarTol:"
00669                                     << intersection::planarTol()
00670                                     << endl;
00671                             }
00672                             allCutPoints.append(pHit.hitPoint());
00673                             surfEdgeCuts[edgeI].append(allCutPoints.size()-1);
00674                         }
00675                     }
00676                 }
00677                 else
00678                 {
00679                     classifyHit
00680                     (
00681                         surf1,
00682                         surf1PointTol,
00683                         surf2,
00684                         isFirstSurf,
00685                         edgeI,
00686                         tolDim,
00687                         pHit,
00688 
00689                         allCutEdges,
00690                         allCutPoints,
00691                         surfEdgeCuts
00692                     );
00693                 }
00694 
00695                 if (mag(pHit.hitPoint() - pEnd) < tolDim)
00696                 {
00697                     doTrack = false;
00698                 }
00699                 else
00700                 {
00701                     pStart = pHit.hitPoint() + tolVec;
00702 
00703                     doTrack = true;
00704                 }
00705             }
00706             else
00707             {
00708                 doTrack = false;
00709             }
00710         }
00711         while(doTrack);
00712     }
00713     intersection::setPlanarTol(oldTol);
00714 }
00715 
00716 
00717 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00718 
00719 // Null constructor
00720 Foam::surfaceIntersection::surfaceIntersection()
00721 :
00722     cutPoints_(0),
00723     cutEdges_(0),
00724     facePairToVertex_(0),
00725     facePairToEdge_(0),
00726     surf1EdgeCuts_(0),
00727     surf2EdgeCuts_(0)
00728 {}
00729 
00730 
00731 // Construct from two surfaces
00732 Foam::surfaceIntersection::surfaceIntersection
00733 (
00734     const triSurfaceSearch& query1,
00735     const triSurfaceSearch& query2
00736 )
00737 :
00738     cutPoints_(0),
00739     cutEdges_(0),
00740     facePairToVertex_(2*max(query1.surface().size(), query2.surface().size())),
00741     facePairToEdge_(2*max(query1.surface().size(), query2.surface().size())),
00742     surf1EdgeCuts_(0),
00743     surf2EdgeCuts_(0)
00744 {
00745     const triSurface& surf1 = query1.surface();
00746     const triSurface& surf2 = query2.surface();
00747 
00748     //
00749     // Cut all edges of surf1 with surf2.
00750     //
00751     if (debug)
00752     {
00753         Pout<< "Cutting surf1 edges" << endl;
00754     }
00755 
00756 
00757     DynamicList<edge> allCutEdges(surf1.nEdges()/20);
00758     DynamicList<point> allCutPoints(surf1.nPoints()/20);
00759 
00760 
00761     // From edge to cut index on surface1
00762     List<DynamicList<label> > edgeCuts1(query1.surface().nEdges());
00763 
00764     doCutEdges
00765     (
00766         surf1,
00767         query2,
00768         true,               // is first surface; construct labelPair in correct
00769                             // order
00770         false,              // not self intersection
00771 
00772         allCutEdges,
00773         allCutPoints,
00774         edgeCuts1
00775     );
00776     // Transfer to straight labelListList
00777     transfer(edgeCuts1, surf1EdgeCuts_);
00778 
00779 
00780     //
00781     // Cut all edges of surf2 with surf1.
00782     //
00783     if (debug)
00784     {
00785         Pout<< "Cutting surf2 edges" << endl;
00786     }
00787 
00788     // From edge to cut index
00789     List<DynamicList<label> > edgeCuts2(query2.surface().nEdges());
00790 
00791     doCutEdges
00792     (
00793         surf2,
00794         query1,
00795         false,              // is second surface
00796         false,              // not self intersection
00797 
00798         allCutEdges,
00799         allCutPoints,
00800         edgeCuts2
00801     );
00802 
00803     // Transfer to straight label(List)List
00804     transfer(edgeCuts2, surf2EdgeCuts_);
00805     cutEdges_.transfer(allCutEdges);
00806     cutPoints_.transfer(allCutPoints);
00807 
00808 
00809     if (debug)
00810     {
00811         Pout<< "surfaceIntersection : Intersection generated:"
00812             << endl
00813             << "    points:" << cutPoints_.size() << endl
00814             << "    edges :" << cutEdges_.size() << endl;
00815 
00816         Pout<< "surfaceIntersection : Writing intersection to intEdges.obj"
00817             << endl;
00818 
00819         OFstream intStream("intEdges.obj");
00820         writeOBJ(cutPoints_, cutEdges_, intStream);
00821 
00822         // Dump all cut edges to files
00823         Pout<< "Dumping cut edges of surface1 to surf1EdgeCuts.obj" << endl;
00824         OFstream edge1Stream("surf1EdgeCuts.obj");
00825         writeIntersectedEdges(surf1, surf1EdgeCuts_, edge1Stream);
00826 
00827         Pout<< "Dumping cut edges of surface2 to surf2EdgeCuts.obj" << endl;
00828         OFstream edge2Stream("surf2EdgeCuts.obj");
00829         writeIntersectedEdges(surf2, surf2EdgeCuts_, edge2Stream);
00830     }
00831 }
00832 
00833 
00834 // Construct from full intersection Poutrmation
00835 Foam::surfaceIntersection::surfaceIntersection
00836 (
00837     const triSurface& surf1,
00838     const edgeIntersections& intersections1,
00839     const triSurface& surf2,
00840     const edgeIntersections& intersections2
00841 )
00842 :
00843     cutPoints_(0),
00844     cutEdges_(0),
00845     facePairToVertex_(2*max(surf1.size(), surf2.size())),
00846     facePairToEdge_(2*max(surf1.size(), surf2.size())),
00847     surf1EdgeCuts_(0),
00848     surf2EdgeCuts_(0)
00849 {
00850 
00851     // All intersection Pout (so for both surfaces)
00852     DynamicList<edge> allCutEdges((surf1.nEdges() + surf2.nEdges())/20);
00853     DynamicList<point> allCutPoints((surf1.nPoints() + surf2.nPoints())/20);
00854 
00855 
00856     // Cut all edges of surf1 with surf2
00857     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00858 
00859     if (debug)
00860     {
00861         Pout<< "Storing surf1 intersections" << endl;
00862     }
00863 
00864     {
00865         // From edge to cut index on surface1
00866         List<DynamicList<label> > edgeCuts1(surf1.nEdges());
00867 
00868         forAll(intersections1, edgeI)
00869         {
00870             const List<pointIndexHit>& intersections = intersections1[edgeI];
00871 
00872             forAll(intersections, i)
00873             {
00874                 const pointIndexHit& pHit = intersections[i];
00875 
00876                 // edgeI intersects surf2. Store point.
00877                 allCutPoints.append(pHit.hitPoint());
00878                 edgeCuts1[edgeI].append(allCutPoints.size()-1);
00879 
00880                 storeIntersection
00881                 (
00882                     true,                       // is first surface
00883                     surf1.edgeFaces()[edgeI],
00884                     pHit.index(),               // surf2FaceI
00885                     allCutEdges,
00886                     allCutPoints
00887                 );
00888             }
00889         }
00890 
00891         // Transfer to straight labelListList
00892         transfer(edgeCuts1, surf1EdgeCuts_);
00893     }
00894 
00895 
00896 
00897     // Cut all edges of surf2 with surf1
00898     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00899 
00900     if (debug)
00901     {
00902         Pout<< "Storing surf2 intersections" << endl;
00903     }
00904 
00905     {
00906         // From edge to cut index on surface2
00907         List<DynamicList<label> > edgeCuts2(surf2.nEdges());
00908 
00909         forAll(intersections2, edgeI)
00910         {
00911             const List<pointIndexHit>& intersections = intersections2[edgeI];
00912 
00913             forAll(intersections, i)
00914             {
00915                 const pointIndexHit& pHit = intersections[i];
00916 
00917                 // edgeI intersects surf1. Store point.
00918                 allCutPoints.append(pHit.hitPoint());
00919                 edgeCuts2[edgeI].append(allCutPoints.size()-1);
00920 
00921                 storeIntersection
00922                 (
00923                     false,                      // is second surface
00924                     surf2.edgeFaces()[edgeI],
00925                     pHit.index(),               // surf2FaceI
00926                     allCutEdges,
00927                     allCutPoints
00928                 );
00929             }
00930         }
00931 
00932         // Transfer to surf2EdgeCuts_ (straight labelListList)
00933         transfer(edgeCuts2, surf2EdgeCuts_);
00934     }
00935 
00936 
00937     // Transfer to straight label(List)List
00938     cutEdges_.transfer(allCutEdges);
00939     cutPoints_.transfer(allCutPoints);
00940 
00941 
00942     if (debug)
00943     {
00944         Pout<< "surfaceIntersection : Intersection generated:"
00945             << endl
00946             << "    points:" << cutPoints_.size() << endl
00947             << "    edges :" << cutEdges_.size() << endl;
00948 
00949         Pout<< "surfaceIntersection : Writing intersection to intEdges.obj"
00950             << endl;
00951 
00952         OFstream intStream("intEdges.obj");
00953         writeOBJ(cutPoints_, cutEdges_, intStream);
00954 
00955         // Dump all cut edges to files
00956         Pout<< "Dumping cut edges of surface1 to surf1EdgeCuts.obj" << endl;
00957         OFstream edge1Stream("surf1EdgeCuts.obj");
00958         writeIntersectedEdges(surf1, surf1EdgeCuts_, edge1Stream);
00959 
00960         Pout<< "Dumping cut edges of surface2 to surf2EdgeCuts.obj" << endl;
00961         OFstream edge2Stream("surf2EdgeCuts.obj");
00962         writeIntersectedEdges(surf2, surf2EdgeCuts_, edge2Stream);
00963     }
00964 
00965 
00966     // Debugging stuff
00967     {
00968         // Check all facePairToVertex is used.
00969         labelHashSet usedPoints;
00970 
00971         forAllConstIter(labelPairLookup, facePairToEdge_, iter)
00972         {
00973             label edgeI = iter();
00974 
00975             const edge& e = cutEdges_[edgeI];
00976 
00977             usedPoints.insert(e[0]);
00978             usedPoints.insert(e[1]);
00979         }
00980 
00981         forAllConstIter(labelPairLookup, facePairToVertex_, iter)
00982         {
00983             label pointI = iter();
00984 
00985             if (!usedPoints.found(pointI))
00986             {
00987                 FatalErrorIn("surfaceIntersection::surfaceIntersection")
00988                     << "Problem: cut point:" << pointI
00989                     << " coord:" << cutPoints_[pointI]
00990                     << " not used by any edge" << abort(FatalError);
00991             }
00992         }
00993     }
00994 }
00995 
00996 
00997 // Construct from single surface. Used to test for self-intersection.
00998 Foam::surfaceIntersection::surfaceIntersection
00999 (
01000     const triSurfaceSearch& query1
01001 )
01002 :
01003     cutPoints_(0),
01004     cutEdges_(0),
01005     facePairToVertex_(2*query1.surface().size()),
01006     facePairToEdge_(2*query1.surface().size()),
01007     surf1EdgeCuts_(0),
01008     surf2EdgeCuts_(0)
01009 {
01010     const triSurface& surf1 = query1.surface();
01011 
01012     //
01013     // Cut all edges of surf1 with surf1 itself.
01014     //
01015     if (debug)
01016     {
01017         Pout<< "Cutting surf1 edges" << endl;
01018     }
01019 
01020     DynamicList<edge> allCutEdges;
01021     DynamicList<point> allCutPoints;
01022 
01023     // From edge to cut index on surface1
01024     List<DynamicList<label> > edgeCuts1(query1.surface().nEdges());
01025 
01026     doCutEdges
01027     (
01028         surf1,
01029         query1,
01030         true,               // is first surface; construct labelPair in correct
01031                             // order
01032         true,               // self intersection
01033 
01034 
01035         allCutEdges,
01036         allCutPoints,
01037         edgeCuts1
01038     );
01039 
01040     // Transfer to straight label(List)List
01041     transfer(edgeCuts1, surf1EdgeCuts_);
01042     cutEdges_.transfer(allCutEdges);
01043     cutPoints_.transfer(allCutPoints);
01044 
01045     // Shortcut.
01046     if (cutPoints_.empty() && cutEdges_.empty())
01047     {
01048         if (debug)
01049         {
01050             Pout<< "Empty intersection" << endl;
01051         }
01052         return;
01053     }
01054 
01055     //
01056     // Remove duplicate points (from edge-point or edge-edge cutting)
01057     //
01058 
01059     // Get typical dimension.
01060     scalar minEdgeLen = GREAT;
01061     forAll(surf1.edges(), edgeI)
01062     {
01063         minEdgeLen = min
01064         (
01065             minEdgeLen,
01066             surf1.edges()[edgeI].mag(surf1.localPoints())
01067         );
01068     }
01069 
01070     // Merge points
01071     labelList pointMap;
01072     pointField newPoints;
01073 
01074     bool hasMerged = mergePoints
01075     (
01076         cutPoints_,
01077         minEdgeLen*intersection::planarTol(),
01078         false,
01079         pointMap,
01080         newPoints
01081     );
01082 
01083     if (hasMerged)
01084     {
01085         if (debug)
01086         {
01087             Pout<< "Merged:" << hasMerged
01088                 << "  mergeDist:" << minEdgeLen*intersection::planarTol()
01089                 << "  cutPoints:" << cutPoints_.size()
01090                 << "  newPoints:" << newPoints.size()
01091                 << endl;
01092         }
01093 
01094         // Copy points
01095         cutPoints_.transfer(newPoints);
01096 
01097         // Renumber vertices referenced by edges
01098         forAll(cutEdges_, edgeI)
01099         {
01100             edge& e = cutEdges_[edgeI];
01101 
01102             e.start() = pointMap[e.start()];
01103             e.end() = pointMap[e.end()];
01104 
01105             if (e.mag(cutPoints_) < minEdgeLen*intersection::planarTol())
01106             {
01107                 if (debug)
01108                 {
01109                     Pout<< "Degenerate cut:" << edgeI << " vertices:" << e
01110                         << " coords:" << cutPoints_[e.start()] << ' '
01111                         << cutPoints_[e.end()] << endl;
01112                 }
01113             }
01114         }
01115 
01116         // Renumber vertices referenced by edgeCut lists. Remove duplicates.
01117         forAll(surf1EdgeCuts_, edgeI)
01118         {
01119             // Get indices of cutPoints this edge is cut by
01120             labelList& cutVerts = surf1EdgeCuts_[edgeI];
01121 
01122             removeDuplicates(pointMap, cutVerts);
01123         }
01124     }
01125 
01126     if (debug)
01127     {
01128         Pout<< "surfaceIntersection : Intersection generated and compressed:"
01129             << endl
01130             << "    points:" << cutPoints_.size() << endl
01131             << "    edges :" << cutEdges_.size() << endl;
01132 
01133 
01134         Pout<< "surfaceIntersection : Writing intersection to intEdges.obj"
01135             << endl;
01136 
01137         OFstream intStream("intEdges.obj");
01138         writeOBJ(cutPoints_, cutEdges_, intStream);
01139     }
01140 
01141     if (debug)
01142     {
01143         // Dump all cut edges to files
01144         Pout<< "Dumping cut edges of surface1 to surf1EdgeCuts.obj" << endl;
01145         OFstream edge1Stream("surf1EdgeCuts.obj");
01146         writeIntersectedEdges(surf1, surf1EdgeCuts_, edge1Stream);
01147     }
01148 }
01149 
01150 
01151 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
01152 
01153 const Foam::pointField& Foam::surfaceIntersection::cutPoints() const
01154 {
01155     return cutPoints_;
01156 }
01157 
01158 
01159 const Foam::edgeList& Foam::surfaceIntersection::cutEdges() const
01160 {
01161     return cutEdges_;
01162 }
01163 
01164 
01165 const Foam::labelPairLookup& Foam::surfaceIntersection::facePairToEdge() const
01166 {
01167     return facePairToEdge_;
01168 }
01169 
01170 
01171 const Foam::labelListList& Foam::surfaceIntersection::edgeCuts
01172 (
01173     const bool isFirstSurf
01174 ) const
01175 {
01176     if (isFirstSurf)
01177     {
01178         return surf1EdgeCuts_;
01179     }
01180     else
01181     {
01182         return surf2EdgeCuts_;
01183     }
01184 }
01185 
01186 
01187 const Foam::labelListList& Foam::surfaceIntersection::surf1EdgeCuts() const
01188 {
01189     return surf1EdgeCuts_;
01190 }
01191 
01192 
01193 const Foam::labelListList& Foam::surfaceIntersection::surf2EdgeCuts() const
01194 {
01195     return surf2EdgeCuts_;
01196 }
01197 
01198 
01199 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines