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

triSurface.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 \*---------------------------------------------------------------------------*/
00025 
00026 #include "triSurface.H"
00027 #include <OpenFOAM/demandDrivenData.H>
00028 #include <OpenFOAM/IFstream.H>
00029 #include <OpenFOAM/OFstream.H>
00030 #include <OpenFOAM/Time.H>
00031 #include <OpenFOAM/boundBox.H>
00032 #include <OpenFOAM/SortableList.H>
00033 #include <OpenFOAM/PackedBoolList.H>
00034 
00035 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00036 
00037 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00038 namespace Foam
00039 {
00040     defineTypeNameAndDebug(Foam::triSurface, 0);
00041 }
00042 
00043 
00044 Foam::fileName Foam::triSurface::triSurfInstance(const Time& d)
00045 {
00046     fileName foamName(d.caseName() + ".ftr");
00047 
00048     // Search back through the time directories list to find the time
00049     // closest to and lower than current time
00050 
00051     instantList ts = d.times();
00052     label i;
00053 
00054     for (i=ts.size()-1; i>=0; i--)
00055     {
00056         if (ts[i].value() <= d.timeOutputValue())
00057         {
00058             break;
00059         }
00060     }
00061 
00062     // Noting that the current directory has already been searched
00063     // for mesh data, start searching from the previously stored time directory
00064 
00065     if (i>=0)
00066     {
00067         for (label j=i; j>=0; j--)
00068         {
00069             if (isFile(d.path()/ts[j].name()/typeName/foamName))
00070             {
00071                 if (debug)
00072                 {
00073                     Pout<< " triSurface::triSurfInstance(const Time& d)"
00074                         << "reading " << foamName
00075                         << " from " << ts[j].name()/typeName
00076                         << endl;
00077                 }
00078 
00079                 return ts[j].name();
00080             }
00081         }
00082     }
00083 
00084     if (debug)
00085     {
00086         Pout<< " triSurface::triSurfInstance(const Time& d)"
00087             << "reading " << foamName
00088             << " from constant/" << endl;
00089     }
00090     return "constant";
00091 }
00092 
00093 
00094 Foam::List<Foam::labelledTri> Foam::triSurface::convertToTri
00095 (
00096     const faceList& faces,
00097     const label defaultRegion
00098 )
00099 {
00100     List<labelledTri> triFaces(faces.size());
00101 
00102     forAll(triFaces, faceI)
00103     {
00104         const face& f = faces[faceI];
00105 
00106         if (f.size() != 3)
00107         {
00108             FatalErrorIn
00109             (
00110                 "triSurface::convertToTri"
00111                 "(const faceList&, const label)"
00112             )   << "Face at position " << faceI
00113                 << " does not have three vertices:" << f
00114                 << abort(FatalError);
00115         }
00116 
00117         labelledTri& tri = triFaces[faceI];
00118 
00119         tri[0] = f[0];
00120         tri[1] = f[1];
00121         tri[2] = f[2];
00122         tri.region() = defaultRegion;
00123     }
00124 
00125     return triFaces;
00126 }
00127 
00128 
00129 Foam::List<Foam::labelledTri> Foam::triSurface::convertToTri
00130 (
00131     const triFaceList& faces,
00132     const label defaultRegion
00133 )
00134 {
00135     List<labelledTri> triFaces(faces.size());
00136 
00137     forAll(triFaces, faceI)
00138     {
00139         const triFace& f = faces[faceI];
00140 
00141         labelledTri& tri = triFaces[faceI];
00142 
00143         tri[0] = f[0];
00144         tri[1] = f[1];
00145         tri[2] = f[2];
00146         tri.region() = defaultRegion;
00147     }
00148 
00149     return triFaces;
00150 }
00151 
00152 
00153 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00154 
00155 void Foam::triSurface::printTriangle
00156 (
00157     Ostream& os,
00158     const string& pre,
00159     const labelledTri& f,
00160     const pointField& points
00161 )
00162 {
00163     os
00164         << pre.c_str() << "vertex numbers:"
00165         << f[0] << ' ' << f[1] << ' ' << f[2] << endl
00166         << pre.c_str() << "vertex coords :"
00167         << points[f[0]] << ' ' << points[f[1]] << ' ' << points[f[2]]
00168         << pre.c_str() << "region        :" << f.region() << endl
00169         << endl;
00170 }
00171 
00172 
00173 Foam::string Foam::triSurface::getLineNoComment(IFstream& is)
00174 {
00175     string line;
00176     do
00177     {
00178         is.getLine(line);
00179     }
00180     while ((line.empty() || line[0] == '#') && is.good());
00181 
00182     return line;
00183 }
00184 
00185 
00186 // Remove non-triangles, double triangles.
00187 void Foam::triSurface::checkTriangles(const bool verbose)
00188 {
00189     // Simple check on indices ok.
00190     const label maxPointI = points().size() - 1;
00191 
00192     forAll(*this, faceI)
00193     {
00194         const labelledTri& f = (*this)[faceI];
00195 
00196         if
00197         (
00198             (f[0] < 0) || (f[0] > maxPointI)
00199          || (f[1] < 0) || (f[1] > maxPointI)
00200          || (f[2] < 0) || (f[2] > maxPointI)
00201         )
00202         {
00203             FatalErrorIn("triSurface::checkTriangles(bool)")
00204                 << "triangle " << f
00205                 << " uses point indices outside point range 0.."
00206                 << maxPointI
00207                 << exit(FatalError);
00208         }
00209     }
00210 
00211     // Two phase process
00212     //   1. mark invalid faces
00213     //   2. pack
00214     // Done to keep numbering constant in phase 1
00215 
00216     // List of valid triangles
00217     boolList valid(size(), true);
00218     bool hasInvalid = false;
00219 
00220     const labelListList& fFaces = faceFaces();
00221 
00222     forAll(*this, faceI)
00223     {
00224         const labelledTri& f = (*this)[faceI];
00225 
00226         if ((f[0] == f[1]) || (f[0] == f[2]) || (f[1] == f[2]))
00227         {
00228             // 'degenerate' triangle check
00229             valid[faceI] = false;
00230             hasInvalid = true;
00231 
00232             if (verbose)
00233             {
00234                 WarningIn
00235                 (
00236                     "triSurface::checkTriangles(bool verbose)"
00237                 )   << "triangle " << faceI
00238                     << " does not have three unique vertices:\n";
00239                 printTriangle(Warning, "    ", f, points());
00240             }
00241         }
00242         else
00243         {
00244             // duplicate triangle check
00245             const labelList& neighbours = fFaces[faceI];
00246 
00247             // Check if faceNeighbours use same points as this face.
00248             // Note: discards normal information - sides of baffle are merged.
00249             forAll(neighbours, neighbourI)
00250             {
00251                 if (neighbours[neighbourI] <= faceI)
00252                 {
00253                     // lower numbered faces already checked
00254                     continue;
00255                 }
00256 
00257                 const labelledTri& n = (*this)[neighbours[neighbourI]];
00258 
00259                 if
00260                 (
00261                     ((f[0] == n[0]) || (f[0] == n[1]) || (f[0] == n[2]))
00262                  && ((f[1] == n[0]) || (f[1] == n[1]) || (f[1] == n[2]))
00263                  && ((f[2] == n[0]) || (f[2] == n[1]) || (f[2] == n[2]))
00264                 )
00265                 {
00266                     valid[faceI] = false;
00267                     hasInvalid = true;
00268 
00269                     if (verbose)
00270                     {
00271                         WarningIn
00272                         (
00273                             "triSurface::checkTriangles(bool verbose)"
00274                         )   << "triangles share the same vertices:\n"
00275                             << "    face 1 :" << faceI << endl;
00276                         printTriangle(Warning, "    ", f, points());
00277 
00278                         Warning
00279                             << endl
00280                             << "    face 2 :"
00281                             << neighbours[neighbourI] << endl;
00282                         printTriangle(Warning, "    ", n, points());
00283                     }
00284 
00285                     break;
00286                 }
00287             }
00288         }
00289     }
00290 
00291     if (hasInvalid)
00292     {
00293         // Pack
00294         label newFaceI = 0;
00295         forAll(*this, faceI)
00296         {
00297             if (valid[faceI])
00298             {
00299                 const labelledTri& f = (*this)[faceI];
00300                 (*this)[newFaceI++] = f;
00301             }
00302         }
00303 
00304         if (verbose)
00305         {
00306             WarningIn
00307             (
00308                 "triSurface::checkTriangles(bool verbose)"
00309             )   << "Removing " << size() - newFaceI
00310                 << " illegal faces." << endl;
00311         }
00312         (*this).setSize(newFaceI);
00313 
00314         // Topology can change because of renumbering
00315         clearOut();
00316     }
00317 }
00318 
00319 
00320 // Check/fix edges with more than two triangles
00321 void Foam::triSurface::checkEdges(const bool verbose)
00322 {
00323     const labelListList& eFaces = edgeFaces();
00324 
00325     forAll(eFaces, edgeI)
00326     {
00327         const labelList& myFaces = eFaces[edgeI];
00328 
00329         if (myFaces.empty())
00330         {
00331             FatalErrorIn("triSurface::checkEdges(bool verbose)")
00332                 << "Edge " << edgeI << " with vertices " << edges()[edgeI]
00333                 << " has no edgeFaces"
00334                 << exit(FatalError);
00335         }
00336         else if (myFaces.size() > 2)
00337         {
00338             WarningIn
00339             (
00340                 "triSurface::checkEdges(bool verbose)"
00341             )   << "Edge " << edgeI << " with vertices " << edges()[edgeI]
00342                 << " has more than 2 faces connected to it : " << myFaces
00343                 << endl;
00344         }
00345     }
00346 }
00347 
00348 
00349 // Read triangles, points from Istream
00350 bool Foam::triSurface::read(Istream& is)
00351 {
00352     is  >> patches_ >> storedPoints() >> storedFaces();
00353 
00354     return true;
00355 }
00356 
00357 
00358 // Read from file in given format
00359 bool Foam::triSurface::read
00360 (
00361     const fileName& name,
00362     const word& ext,
00363     const bool check
00364 )
00365 {
00366     if (check && !exists(name))
00367     {
00368         FatalErrorIn
00369         (
00370             "triSurface::read(const fileName&, const word&, const bool)"
00371         )   << "Cannnot read " << name << exit(FatalError);
00372     }
00373 
00374     if (ext == "gz")
00375     {
00376         fileName unzipName = name.lessExt();
00377 
00378         // Do not check for existence. Let IFstream do the unzipping.
00379         return read(unzipName, unzipName.ext(), false);
00380     }
00381     else if (ext == "ftr")
00382     {
00383         return read(IFstream(name)());
00384     }
00385     else if (ext == "stl")
00386     {
00387         return readSTL(name);
00388     }
00389     else if (ext == "stlb")
00390     {
00391         return readSTL(name);
00392     }
00393     else if (ext == "gts")
00394     {
00395         return readGTS(name);
00396     }
00397     else if (ext == "obj")
00398     {
00399         return readOBJ(name);
00400     }
00401     else if (ext == "off")
00402     {
00403         return readOFF(name);
00404     }
00405     else if (ext == "tri")
00406     {
00407         return readTRI(name);
00408     }
00409     else if (ext == "ac")
00410     {
00411         return readAC(name);
00412     }
00413     else if (ext == "nas")
00414     {
00415         return readNAS(name);
00416     }
00417     else
00418     {
00419         FatalErrorIn
00420         (
00421             "triSurface::read(const fileName&, const word&)"
00422         )   << "unknown file extension " << ext
00423             << ". Supported extensions are '.ftr', '.stl', '.stlb', '.gts'"
00424             << ", '.obj', '.ac', '.off', '.nas' and '.tri'"
00425             << exit(FatalError);
00426 
00427         return false;
00428     }
00429 }
00430 
00431 
00432 // Write to file in given format
00433 void Foam::triSurface::write
00434 (
00435     const fileName& name,
00436     const word& ext,
00437     const bool sort
00438 ) const
00439 {
00440     if (ext == "ftr")
00441     {
00442         return write(OFstream(name)());
00443     }
00444     else if (ext == "stl")
00445     {
00446         return writeSTLASCII(OFstream(name)());
00447     }
00448     else if (ext == "stlb")
00449     {
00450         ofstream outFile(name.c_str(), std::ios::binary);
00451 
00452         writeSTLBINARY(outFile);
00453     }
00454     else if (ext == "gts")
00455     {
00456         return writeGTS(sort, OFstream(name)());
00457     }
00458     else if (ext == "obj")
00459     {
00460         writeOBJ(sort, OFstream(name)());
00461     }
00462     else if (ext == "off")
00463     {
00464         writeOFF(sort, OFstream(name)());
00465     }
00466     else if (ext == "vtk")
00467     {
00468         writeVTK(sort, OFstream(name)());
00469     }
00470     else if (ext == "tri")
00471     {
00472         writeTRI(sort, OFstream(name)());
00473     }
00474     else if (ext == "dx")
00475     {
00476         writeDX(sort, OFstream(name)());
00477     }
00478     else if (ext == "ac")
00479     {
00480         writeAC(OFstream(name)());
00481     }
00482     else if (ext == "smesh")
00483     {
00484         writeSMESH(sort, OFstream(name)());
00485     }
00486     else
00487     {
00488         FatalErrorIn
00489         (
00490             "triSurface::write(const fileName&, const word&, const bool)"
00491         )   << "unknown file extension " << ext
00492             << ". Supported extensions are '.ftr', '.stl', '.stlb', "
00493             << "'.gts', '.obj', '.vtk'"
00494             << ", '.off', '.dx', '.smesh', '.ac' and '.tri'"
00495             << exit(FatalError);
00496     }
00497 }
00498 
00499 
00500 // Returns patch info. Sets faceMap to the indexing according to patch
00501 // numbers. Patch numbers start at 0.
00502 Foam::surfacePatchList Foam::triSurface::calcPatches(labelList& faceMap) const
00503 {
00504     // Sort according to region numbers of labelledTri
00505     SortableList<label> sortedRegion(size());
00506 
00507     forAll(sortedRegion, faceI)
00508     {
00509         sortedRegion[faceI] = operator[](faceI).region();
00510     }
00511     sortedRegion.sort();
00512 
00513     faceMap = sortedRegion.indices();
00514 
00515     // Extend regions
00516     label maxRegion = patches_.size()-1;    // for non-compacted regions
00517 
00518     if (faceMap.size())
00519     {
00520         maxRegion = max
00521         (
00522             maxRegion,
00523             operator[](faceMap[faceMap.size() - 1]).region()
00524         );
00525     }
00526 
00527     // Get new region list
00528     surfacePatchList newPatches(maxRegion + 1);
00529 
00530     // Fill patch sizes
00531     forAll(*this, faceI)
00532     {
00533         label region = operator[](faceI).region();
00534 
00535         newPatches[region].size()++;
00536     }
00537 
00538 
00539     // Fill rest of patch info
00540 
00541     label startFaceI = 0;
00542     forAll(newPatches, newPatchI)
00543     {
00544         surfacePatch& newPatch = newPatches[newPatchI];
00545 
00546         newPatch.index() = newPatchI;
00547 
00548         label oldPatchI = newPatchI;
00549 
00550         // start of patch
00551         newPatch.start() = startFaceI;
00552 
00553 
00554         // Take over any information from existing patches
00555         if ((oldPatchI < patches_.size()) && (patches_[oldPatchI].name() != ""))
00556         {
00557             newPatch.name() = patches_[oldPatchI].name();
00558         }
00559         else
00560         {
00561             newPatch.name() = word("patch") + name(newPatchI);
00562         }
00563 
00564         if
00565         (
00566             (oldPatchI < patches_.size())
00567          && (patches_[oldPatchI].geometricType() != "")
00568         )
00569         {
00570             newPatch.geometricType() = patches_[oldPatchI].geometricType();
00571         }
00572         else
00573         {
00574             newPatch.geometricType() = "empty";
00575         }
00576 
00577         startFaceI += newPatch.size();
00578     }
00579 
00580     return newPatches;
00581 }
00582 
00583 
00584 void Foam::triSurface::setDefaultPatches()
00585 {
00586     labelList faceMap;
00587 
00588     // Get names, types and sizes
00589     surfacePatchList newPatches(calcPatches(faceMap));
00590 
00591     // Take over names and types (but not size)
00592     patches_.setSize(newPatches.size());
00593 
00594     forAll(newPatches, patchI)
00595     {
00596         patches_[patchI].index() = patchI;
00597         patches_[patchI].name() = newPatches[patchI].name();
00598         patches_[patchI].geometricType() = newPatches[patchI].geometricType();
00599     }
00600 }
00601 
00602 
00603 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00604 
00605 Foam::triSurface::triSurface()
00606 :
00607     ParentType(List<Face>(), pointField()),
00608     patches_(0),
00609     sortedEdgeFacesPtr_(NULL),
00610     edgeOwnerPtr_(NULL)
00611 {}
00612 
00613 
00614 
00615 Foam::triSurface::triSurface
00616 (
00617     const List<labelledTri>& triangles,
00618     const geometricSurfacePatchList& patches,
00619     const pointField& points
00620 )
00621 :
00622     ParentType(triangles, points),
00623     patches_(patches),
00624     sortedEdgeFacesPtr_(NULL),
00625     edgeOwnerPtr_(NULL)
00626 {}
00627 
00628 
00629 Foam::triSurface::triSurface
00630 (
00631     List<labelledTri>& triangles,
00632     const geometricSurfacePatchList& patches,
00633     pointField& points,
00634     const bool reUse
00635 )
00636 :
00637     ParentType(triangles, points, reUse),
00638     patches_(patches),
00639     sortedEdgeFacesPtr_(NULL),
00640     edgeOwnerPtr_(NULL)
00641 {}
00642 
00643 
00644 Foam::triSurface::triSurface
00645 (
00646     const List<labelledTri>& triangles,
00647     const pointField& points
00648 )
00649 :
00650     ParentType(triangles, points),
00651     patches_(),
00652     sortedEdgeFacesPtr_(NULL),
00653     edgeOwnerPtr_(NULL)
00654 {
00655     setDefaultPatches();
00656 }
00657 
00658 
00659 Foam::triSurface::triSurface
00660 (
00661     const triFaceList& triangles,
00662     const pointField& points
00663 )
00664 :
00665     ParentType(convertToTri(triangles, 0), points),
00666     patches_(),
00667     sortedEdgeFacesPtr_(NULL),
00668     edgeOwnerPtr_(NULL)
00669 {
00670     setDefaultPatches();
00671 }
00672 
00673 
00674 Foam::triSurface::triSurface(const fileName& name)
00675 :
00676     ParentType(List<Face>(), pointField()),
00677     patches_(),
00678     sortedEdgeFacesPtr_(NULL),
00679     edgeOwnerPtr_(NULL)
00680 {
00681     word ext = name.ext();
00682 
00683     read(name, ext);
00684 
00685     setDefaultPatches();
00686 }
00687 
00688 
00689 Foam::triSurface::triSurface(Istream& is)
00690 :
00691     ParentType(List<Face>(), pointField()),
00692     patches_(),
00693     sortedEdgeFacesPtr_(NULL),
00694     edgeOwnerPtr_(NULL)
00695 {
00696     read(is);
00697 
00698     setDefaultPatches();
00699 }
00700 
00701 
00702 Foam::triSurface::triSurface(const Time& d)
00703 :
00704     ParentType(List<Face>(), pointField()),
00705     patches_(),
00706     sortedEdgeFacesPtr_(NULL),
00707     edgeOwnerPtr_(NULL)
00708 {
00709     fileName foamFile(d.caseName() + ".ftr");
00710 
00711     fileName foamPath(d.path()/triSurfInstance(d)/typeName/foamFile);
00712 
00713     IFstream foamStream(foamPath);
00714 
00715     read(foamStream);
00716 
00717     setDefaultPatches();
00718 }
00719 
00720 
00721 Foam::triSurface::triSurface(const triSurface& ts)
00722 :
00723     ParentType(ts, ts.points()),
00724     patches_(ts.patches()),
00725     sortedEdgeFacesPtr_(NULL),
00726     edgeOwnerPtr_(NULL)
00727 {}
00728 
00729 
00730 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00731 
00732 Foam::triSurface::~triSurface()
00733 {
00734     clearOut();
00735 }
00736 
00737 
00738 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00739 
00740 void Foam::triSurface::clearTopology()
00741 {
00742     ParentType::clearTopology();
00743     deleteDemandDrivenData(sortedEdgeFacesPtr_);
00744     deleteDemandDrivenData(edgeOwnerPtr_);
00745 }
00746 
00747 
00748 void Foam::triSurface::clearPatchMeshAddr()
00749 {
00750     ParentType::clearPatchMeshAddr();
00751 }
00752 
00753 
00754 void Foam::triSurface::clearOut()
00755 {
00756     ParentType::clearOut();
00757 
00758     clearTopology();
00759     clearPatchMeshAddr();
00760 }
00761 
00762 
00763 const Foam::labelListList& Foam::triSurface::sortedEdgeFaces() const
00764 {
00765     if (!sortedEdgeFacesPtr_)
00766     {
00767         calcSortedEdgeFaces();
00768     }
00769 
00770     return *sortedEdgeFacesPtr_;
00771 }
00772 
00773 
00774 const Foam::labelList& Foam::triSurface::edgeOwner() const
00775 {
00776     if (!edgeOwnerPtr_)
00777     {
00778         calcEdgeOwner();
00779     }
00780 
00781     return *edgeOwnerPtr_;
00782 }
00783 
00784 
00785 //- Move points
00786 void Foam::triSurface::movePoints(const pointField& newPoints)
00787 {
00788     // Remove all geometry dependent data
00789     deleteDemandDrivenData(sortedEdgeFacesPtr_);
00790 
00791     // Adapt for new point position
00792     ParentType::movePoints(newPoints);
00793 
00794     // Copy new points
00795     storedPoints() = newPoints;
00796 }
00797 
00798 
00799 // scale points
00800 void Foam::triSurface::scalePoints(const scalar& scaleFactor)
00801 {
00802     // avoid bad scaling
00803     if (scaleFactor > 0 && scaleFactor != 1.0)
00804     {
00805         // Remove all geometry dependent data
00806         clearTopology();
00807 
00808         // Adapt for new point position
00809         ParentType::movePoints(pointField());
00810 
00811         storedPoints() *= scaleFactor;
00812     }
00813 }
00814 
00815 
00816 // Remove non-triangles, double triangles.
00817 void Foam::triSurface::cleanup(const bool verbose)
00818 {
00819     // Merge points (already done for STL, TRI)
00820     stitchTriangles(points(), SMALL, verbose);
00821 
00822     // Merging points might have changed geometric factors
00823     clearOut();
00824 
00825     checkTriangles(verbose);
00826 
00827     checkEdges(verbose);
00828 }
00829 
00830 
00831 // Finds area, starting at faceI, delimited by borderEdge. Marks all visited
00832 // faces (from face-edge-face walk) with currentZone.
00833 void Foam::triSurface::markZone
00834 (
00835     const boolList& borderEdge,
00836     const label faceI,
00837     const label currentZone,
00838     labelList& faceZone
00839 ) const
00840 {
00841     // List of faces whose faceZone has been set.
00842     labelList changedFaces(1, faceI);
00843 
00844     while(true)
00845     {
00846         // Pick up neighbours of changedFaces
00847         DynamicList<label> newChangedFaces(2*changedFaces.size());
00848 
00849         forAll(changedFaces, i)
00850         {
00851             label faceI = changedFaces[i];
00852 
00853             const labelList& fEdges = faceEdges()[faceI];
00854 
00855             forAll(fEdges, i)
00856             {
00857                 label edgeI = fEdges[i];
00858 
00859                 if (!borderEdge[edgeI])
00860                 {
00861                     const labelList& eFaces = edgeFaces()[edgeI];
00862 
00863                     forAll(eFaces, j)
00864                     {
00865                         label nbrFaceI = eFaces[j];
00866 
00867                         if (faceZone[nbrFaceI] == -1)
00868                         {
00869                             faceZone[nbrFaceI] = currentZone;
00870                             newChangedFaces.append(nbrFaceI);
00871                         }
00872                         else if (faceZone[nbrFaceI] != currentZone)
00873                         {
00874                             FatalErrorIn
00875                             (
00876                                 "triSurface::markZone(const boolList&,"
00877                                 "const label, const label, labelList&) const"
00878                             )
00879                                 << "Zones " << faceZone[nbrFaceI]
00880                                 << " at face " << nbrFaceI
00881                                 << " connects to zone " << currentZone
00882                                 << " at face " << faceI
00883                                 << abort(FatalError);
00884                         }
00885                     }
00886                 }
00887             }
00888         }
00889 
00890         if (newChangedFaces.empty())
00891         {
00892             break;
00893         }
00894 
00895         changedFaces.transfer(newChangedFaces);
00896     }
00897 }
00898 
00899 
00900 // Finds areas delimited by borderEdge (or 'real' edges).
00901 // Fills faceZone accordingly
00902 Foam::label Foam::triSurface::markZones
00903 (
00904     const boolList& borderEdge,
00905     labelList& faceZone
00906 ) const
00907 {
00908     faceZone.setSize(size());
00909     faceZone = -1;
00910 
00911     if (borderEdge.size() != nEdges())
00912     {
00913         FatalErrorIn
00914         (
00915             "triSurface::markZones"
00916             "(const boolList&, labelList&)"
00917         )
00918             << "borderEdge boolList not same size as number of edges" << endl
00919             << "borderEdge:" << borderEdge.size() << endl
00920             << "nEdges    :" << nEdges()
00921             << exit(FatalError);
00922     }
00923 
00924     label zoneI = 0;
00925 
00926     for (label startFaceI = 0;; zoneI++)
00927     {
00928         // Find first non-coloured face
00929         for (; startFaceI < size(); startFaceI++)
00930         {
00931             if (faceZone[startFaceI] == -1)
00932             {
00933                 break;
00934             }
00935         }
00936 
00937         if (startFaceI >= size())
00938         {
00939             break;
00940         }
00941 
00942         faceZone[startFaceI] = zoneI;
00943 
00944         markZone(borderEdge, startFaceI, zoneI, faceZone);
00945     }
00946 
00947     return zoneI;
00948 }
00949 
00950 
00951 void Foam::triSurface::subsetMeshMap
00952 (
00953     const boolList& include,
00954     labelList& pointMap,
00955     labelList& faceMap
00956 ) const
00957 {
00958     const List<labelledTri>& locFaces = localFaces();
00959 
00960     label faceI = 0;
00961     label pointI = 0;
00962 
00963     faceMap.setSize(locFaces.size());
00964 
00965     pointMap.setSize(nPoints());
00966 
00967     boolList pointHad(nPoints(), false);
00968 
00969     forAll(include, oldFacei)
00970     {
00971         if (include[oldFacei])
00972         {
00973             // Store new faces compact
00974             faceMap[faceI++] = oldFacei;
00975 
00976             // Renumber labels for triangle
00977             const labelledTri& tri = locFaces[oldFacei];
00978 
00979             label a = tri[0];
00980             if (!pointHad[a])
00981             {
00982                 pointHad[a] = true;
00983                 pointMap[pointI++] = a;
00984             }
00985 
00986             label b = tri[1];
00987             if (!pointHad[b])
00988             {
00989                 pointHad[b] = true;
00990                 pointMap[pointI++] = b;
00991             }
00992 
00993             label c = tri[2];
00994             if (!pointHad[c])
00995             {
00996                 pointHad[c] = true;
00997                 pointMap[pointI++] = c;
00998             }
00999         }
01000     }
01001 
01002     // Trim
01003     faceMap.setSize(faceI);
01004 
01005     pointMap.setSize(pointI);
01006 }
01007 
01008 
01009 Foam::triSurface Foam::triSurface::subsetMesh
01010 (
01011     const boolList& include,
01012     labelList& pointMap,
01013     labelList& faceMap
01014 ) const
01015 {
01016     const pointField& locPoints = localPoints();
01017     const List<labelledTri>& locFaces = localFaces();
01018 
01019     // Fill pointMap, faceMap
01020     subsetMeshMap(include, pointMap, faceMap);
01021 
01022 
01023     // Create compact coordinate list and forward mapping array
01024     pointField newPoints(pointMap.size());
01025     labelList oldToNew(locPoints.size());
01026     forAll(pointMap, pointi)
01027     {
01028         newPoints[pointi] = locPoints[pointMap[pointi]];
01029         oldToNew[pointMap[pointi]] = pointi;
01030     }
01031 
01032     // Renumber triangle node labels and compact
01033     List<labelledTri> newTriangles(faceMap.size());
01034 
01035     forAll(faceMap, facei)
01036     {
01037         // Get old vertex labels
01038         const labelledTri& tri = locFaces[faceMap[facei]];
01039 
01040         newTriangles[facei][0] = oldToNew[tri[0]];
01041         newTriangles[facei][1] = oldToNew[tri[1]];
01042         newTriangles[facei][2] = oldToNew[tri[2]];
01043         newTriangles[facei].region() = tri.region();
01044     }
01045 
01046     // Construct subsurface
01047     return triSurface(newTriangles, patches(), newPoints, true);
01048 }
01049 
01050 
01051 void Foam::triSurface::write
01052 (
01053     const fileName& name,
01054     const bool sortByRegion
01055 ) const
01056 {
01057     write(name, name.ext(), sortByRegion);
01058 }
01059 
01060 
01061 void Foam::triSurface::write(Ostream& os) const
01062 {
01063     os  << patches() << endl;
01064 
01065     //Note: Write with global point numbering
01066     os  << points() << nl
01067         << static_cast<const List<labelledTri>&>(*this) << endl;
01068 
01069     // Check state of Ostream
01070     os.check("triSurface::write(Ostream&)");
01071 }
01072 
01073 
01074 void Foam::triSurface::write(const Time& d) const
01075 {
01076     fileName foamFile(d.caseName() + ".ftr");
01077 
01078     fileName foamPath(d.path()/triSurfInstance(d)/typeName/foamFile);
01079 
01080     OFstream foamStream(foamPath);
01081 
01082     write(foamStream);
01083 }
01084 
01085 
01086 void Foam::triSurface::writeStats(Ostream& os) const
01087 {
01088     // Unfortunately nPoints constructs meshPoints() so do compact version
01089     // ourselves.
01090     PackedBoolList pointIsUsed(points().size());
01091 
01092     label nPoints = 0;
01093     boundBox bb = boundBox::invertedBox;
01094 
01095     forAll(*this, triI)
01096     {
01097         const labelledTri& f = operator[](triI);
01098 
01099         forAll(f, fp)
01100         {
01101             label pointI = f[fp];
01102             if (pointIsUsed.set(pointI, 1))
01103             {
01104                 bb.min() = ::Foam::min(bb.min(), points()[pointI]);
01105                 bb.max() = ::Foam::max(bb.max(), points()[pointI]);
01106                 nPoints++;
01107             }
01108         }
01109     }
01110 
01111     os  << "Triangles    : " << size() << endl
01112         << "Vertices     : " << nPoints << endl
01113         << "Bounding Box : " << bb << endl;
01114 }
01115 
01116 
01117 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
01118 
01119 void Foam::triSurface::operator=(const triSurface& ts)
01120 {
01121     List<labelledTri>::operator=(ts);
01122     clearOut();
01123     storedPoints() = ts.points();
01124     patches_ = ts.patches();
01125 }
01126 
01127 
01128 // * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
01129 
01130 Foam::Ostream& Foam::operator<<(Ostream& os, const triSurface& sm)
01131 {
01132     sm.write(os);
01133     return os;
01134 }
01135 
01136 
01137 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines