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

MeshedSurface.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 "MeshedSurface.H"
00027 #include <surfMesh/UnsortedMeshedSurface.H>
00028 #include <surfMesh/MeshedSurfaceProxy.H>
00029 #include <OpenFOAM/mergePoints.H>
00030 #include <OpenFOAM/Time.H>
00031 #include <OpenFOAM/ListOps.H>
00032 #include <OpenFOAM/polyBoundaryMesh.H>
00033 #include <OpenFOAM/polyMesh.H>
00034 #include <surfMesh/surfMesh.H>
00035 #include <OpenFOAM/primitivePatch.H>
00036 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00037 
00038 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00039 
00040 template<class Face>
00041 inline bool Foam::MeshedSurface<Face>::isTri()
00042 {
00043     return false;
00044 }
00045 
00046 
00047 template<class Face>
00048 Foam::wordHashSet Foam::MeshedSurface<Face>::readTypes()
00049 {
00050     return wordHashSet(*fileExtensionConstructorTablePtr_);
00051 }
00052 
00053 
00054 template<class Face>
00055 Foam::wordHashSet Foam::MeshedSurface<Face>::writeTypes()
00056 {
00057     return wordHashSet(*writefileExtensionMemberFunctionTablePtr_);
00058 }
00059 
00060 
00061 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
00062 
00063 template<class Face>
00064 bool Foam::MeshedSurface<Face>::canReadType
00065 (
00066     const word& ext,
00067     const bool verbose
00068 )
00069 {
00070     return checkSupport
00071     (
00072         readTypes() | FriendType::readTypes(),
00073         ext,
00074         verbose,
00075         "reading"
00076    );
00077 }
00078 
00079 
00080 template<class Face>
00081 bool Foam::MeshedSurface<Face>::canWriteType
00082 (
00083     const word& ext,
00084     const bool verbose
00085 )
00086 {
00087     return checkSupport
00088     (
00089         writeTypes() | ProxyType::writeTypes(),
00090         ext,
00091         verbose,
00092         "writing"
00093     );
00094 }
00095 
00096 
00097 template<class Face>
00098 bool Foam::MeshedSurface<Face>::canRead
00099 (
00100     const fileName& name,
00101     const bool verbose
00102 )
00103 {
00104     word ext = name.ext();
00105     if (ext == "gz")
00106     {
00107         ext = name.lessExt().ext();
00108     }
00109     return canReadType(ext, verbose);
00110 }
00111 
00112 
00113 template<class Face>
00114 void Foam::MeshedSurface<Face>::write
00115 (
00116     const fileName& name,
00117     const MeshedSurface<Face>& surf
00118 )
00119 {
00120     if (debug)
00121     {
00122         Info<< "MeshedSurface::write"
00123             "(const fileName&, const MeshedSurface&) : "
00124             "writing to " << name
00125             << endl;
00126     }
00127 
00128     const word ext = name.ext();
00129 
00130     typename writefileExtensionMemberFunctionTable::iterator mfIter =
00131         writefileExtensionMemberFunctionTablePtr_->find(ext);
00132 
00133     if (mfIter == writefileExtensionMemberFunctionTablePtr_->end())
00134     {
00135         // no direct writer, delegate to proxy if possible
00136         wordHashSet supported = ProxyType::writeTypes();
00137 
00138         if (supported.found(ext))
00139         {
00140             MeshedSurfaceProxy<Face>(surf).write(name);
00141         }
00142         else
00143         {
00144             FatalErrorIn
00145             (
00146                 "MeshedSurface::write"
00147                 "(const fileName&, const MeshedSurface&)"
00148             )   << "Unknown file extension " << ext << nl << nl
00149                 << "Valid types are :" << endl
00150                 << (supported | writeTypes())
00151                 << exit(FatalError);
00152         }
00153     }
00154     else
00155     {
00156         mfIter()(name, surf);
00157     }
00158 }
00159 
00160 
00161 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00162 
00163 template<class Face>
00164 Foam::MeshedSurface<Face>::MeshedSurface()
00165 :
00166     ParentType(List<Face>(), pointField())
00167 {}
00168 
00169 
00170 template<class Face>
00171 Foam::MeshedSurface<Face>::MeshedSurface
00172 (
00173     const Xfer< pointField >& pointLst,
00174     const Xfer< List<Face> >& faceLst,
00175     const Xfer< surfZoneList >& zoneLst
00176 )
00177 :
00178     ParentType(List<Face>(), pointField()),
00179     zones_()
00180 {
00181     reset(pointLst, faceLst, zoneLst);
00182 }
00183 
00184 
00185 template<class Face>
00186 Foam::MeshedSurface<Face>::MeshedSurface
00187 (
00188     const Xfer< pointField >& pointLst,
00189     const Xfer< List<Face> >& faceLst,
00190     const UList<label>& zoneSizes,
00191     const UList<word>& zoneNames
00192 )
00193 :
00194     ParentType(List<Face>(), pointField())
00195 {
00196     reset(pointLst, faceLst, Xfer<surfZoneList>());
00197 
00198     if (zoneSizes.size())
00199     {
00200         if (zoneNames.size())
00201         {
00202             addZones(zoneSizes, zoneNames);
00203         }
00204         else
00205         {
00206             addZones(zoneSizes);
00207         }
00208     }
00209 }
00210 
00211 
00212 template<class Face>
00213 Foam::MeshedSurface<Face>::MeshedSurface
00214 (
00215     const MeshedSurface<Face>& surf
00216 )
00217 :
00218     ParentType(surf.faces(), surf.points()),
00219     zones_(surf.surfZones())
00220 {}
00221 
00222 
00223 template<class Face>
00224 Foam::MeshedSurface<Face>::MeshedSurface
00225 (
00226     const UnsortedMeshedSurface<Face>& surf
00227 )
00228 :
00229     ParentType(List<Face>(), surf.points())
00230 {
00231     labelList faceMap;
00232     this->storedZones().transfer(surf.sortedZones(faceMap));
00233 
00234     const List<Face>& origFaces = surf.faces();
00235     List<Face> newFaces(origFaces.size());
00236 
00237     // this is somewhat like ListOps reorder and/or IndirectList
00238     forAll(newFaces, faceI)
00239     {
00240         newFaces[faceI] = origFaces[faceMap[faceI]];
00241     }
00242 
00243     this->storedFaces().transfer(newFaces);
00244 }
00245 
00246 
00247 template<class Face>
00248 Foam::MeshedSurface<Face>::MeshedSurface(const surfMesh& mesh)
00249 :
00250     ParentType(List<Face>(), pointField())
00251 {
00252     // same face type as surfMesh
00253     MeshedSurface<face> surf
00254     (
00255         xferCopy(mesh.points()),
00256         xferCopy(mesh.faces()),
00257         xferCopy(mesh.surfZones())
00258     );
00259 
00260     this->transcribe(surf);
00261 }
00262 
00263 
00264 template<class Face>
00265 Foam::MeshedSurface<Face>::MeshedSurface
00266 (
00267     const polyBoundaryMesh& bMesh,
00268     const bool useGlobalPoints
00269 )
00270 :
00271     ParentType(List<Face>(), pointField())
00272 {
00273     const polyMesh& mesh = bMesh.mesh();
00274     const polyPatchList& bPatches = bMesh;
00275 
00276     // Get a single patch for all boundaries
00277     primitivePatch allBoundary
00278     (
00279         SubList<face>
00280         (
00281             mesh.faces(),
00282             mesh.nFaces() - mesh.nInternalFaces(),
00283             mesh.nInternalFaces()
00284         ),
00285         mesh.points()
00286     );
00287 
00288     // use global/local points:
00289     const pointField& bPoints =
00290     (
00291         useGlobalPoints ? mesh.points() : allBoundary.localPoints()
00292     );
00293 
00294     // global/local face addressing:
00295     const List<Face>& bFaces =
00296     (
00297         useGlobalPoints ? allBoundary : allBoundary.localFaces()
00298     );
00299 
00300 
00301     // create zone list
00302     surfZoneList newZones(bPatches.size());
00303 
00304     label startFaceI = 0;
00305     label nZone = 0;
00306     forAll(bPatches, patchI)
00307     {
00308         const polyPatch& p = bPatches[patchI];
00309 
00310         if (p.size())
00311         {
00312             newZones[nZone] = surfZone
00313             (
00314                 p.name(),
00315                 p.size(),
00316                 startFaceI,
00317                 nZone
00318             );
00319 
00320             nZone++;
00321             startFaceI += p.size();
00322         }
00323     }
00324 
00325     newZones.setSize(nZone);
00326 
00327     // same face type as the polyBoundaryMesh
00328     MeshedSurface<face> surf
00329     (
00330         xferCopy(bPoints),
00331         xferCopy(bFaces),
00332         xferMove(newZones)
00333     );
00334 
00335     this->transcribe(surf);
00336 }
00337 
00338 
00339 template<class Face>
00340 Foam::MeshedSurface<Face>::MeshedSurface
00341 (
00342     const fileName& name,
00343     const word& ext
00344 )
00345 :
00346     ParentType(List<Face>(), pointField())
00347 {
00348     read(name, ext);
00349 }
00350 
00351 
00352 template<class Face>
00353 Foam::MeshedSurface<Face>::MeshedSurface(const fileName& name)
00354 :
00355     ParentType(List<Face>(), pointField())
00356 {
00357     read(name);
00358 }
00359 
00360 
00361 template<class Face>
00362 Foam::MeshedSurface<Face>::MeshedSurface
00363 (
00364     const Time& t,
00365     const word& surfName
00366 )
00367 :
00368     ParentType(List<Face>(), pointField())
00369 {
00370     surfMesh mesh
00371     (
00372         IOobject
00373         (
00374             "dummyName",
00375             t.timeName(),
00376             t,
00377             IOobject::MUST_READ,
00378             IOobject::NO_WRITE,
00379             false
00380         ),
00381         surfName
00382     );
00383 
00384     // same face type as surfMesh
00385     MeshedSurface<face> surf
00386     (
00387         xferMove(mesh.storedPoints()),
00388         xferMove(mesh.storedFaces()),
00389         xferMove(mesh.storedZones())
00390     );
00391 
00392     this->transcribe(surf);
00393 }
00394 
00395 
00396 template<class Face>
00397 Foam::MeshedSurface<Face>::MeshedSurface
00398 (
00399     const Xfer< UnsortedMeshedSurface<Face> >& surf
00400 )
00401 :
00402     ParentType(List<Face>(), pointField())
00403 {
00404     transfer(surf());
00405 }
00406 
00407 
00408 template<class Face>
00409 Foam::MeshedSurface<Face>::MeshedSurface
00410 (
00411     const Xfer< MeshedSurface<Face> >& surf
00412 )
00413 :
00414     ParentType(List<Face>(), pointField())
00415 {
00416     transfer(surf());
00417 }
00418 
00419 
00420 
00421 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00422 
00423 template<class Face>
00424 Foam::MeshedSurface<Face>::~MeshedSurface()
00425 {}
00426 
00427 
00428 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00429 
00430 
00431 // * * * * * * * * * * * * Protected Member Functions  * * * * * * * * * * * //
00432 
00433 template<class Face>
00434 void Foam::MeshedSurface<Face>::remapFaces
00435 (
00436     const UList<label>& faceMap
00437 )
00438 {
00439     // recalculate the zone start/size
00440     if (&faceMap && faceMap.size())
00441     {
00442         surfZoneList& zones = storedZones();
00443 
00444         if (zones.size() == 1)
00445         {
00446             // optimized for single zone case
00447             zones[0].size() = faceMap.size();
00448         }
00449         else if (zones.size())
00450         {
00451             label newFaceI = 0;
00452             label origEndI = 0;
00453             forAll(zones, zoneI)
00454             {
00455                 surfZone& zone = zones[zoneI];
00456 
00457                 // adjust zone start
00458                 zone.start() = newFaceI;
00459                 origEndI += zone.size();
00460 
00461                 for (label faceI = newFaceI; faceI < faceMap.size(); ++faceI)
00462                 {
00463                     if (faceMap[faceI] < origEndI)
00464                     {
00465                         ++newFaceI;
00466                     }
00467                     else
00468                     {
00469                         break;
00470                     }
00471                 }
00472 
00473                 // adjust zone size
00474                 zone.size() = newFaceI - zone.start();
00475             }
00476         }
00477     }
00478 }
00479 
00480 
00481 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00482 
00483 template<class Face>
00484 void Foam::MeshedSurface<Face>::clear()
00485 {
00486     ParentType::clearOut();
00487 
00488     storedPoints().clear();
00489     storedFaces().clear();
00490     storedZones().clear();
00491 }
00492 
00493 
00494 template<class Face>
00495 void Foam::MeshedSurface<Face>::movePoints(const pointField& newPoints)
00496 {
00497     // Remove all geometry dependent data
00498     ParentType::clearTopology();
00499 
00500     // Adapt for new point position
00501     ParentType::movePoints(newPoints);
00502 
00503     // Copy new points
00504     storedPoints() = newPoints;
00505 }
00506 
00507 
00508 template<class Face>
00509 void Foam::MeshedSurface<Face>::scalePoints(const scalar& scaleFactor)
00510 {
00511     // avoid bad scaling
00512     if (scaleFactor > 0 && scaleFactor != 1.0)
00513     {
00514         // Remove all geometry dependent data
00515         ParentType::clearTopology();
00516 
00517         // Adapt for new point position
00518         ParentType::movePoints(pointField());
00519 
00520         storedPoints() *= scaleFactor;
00521     }
00522 }
00523 
00524 
00525 template<class Face>
00526 void Foam::MeshedSurface<Face>::reset
00527 (
00528     const Xfer< pointField >& pointLst,
00529     const Xfer< List<Face> >& faceLst,
00530     const Xfer< surfZoneList >& zoneLst
00531 )
00532 {
00533     ParentType::clearOut();
00534 
00535     // Take over new primitive data.
00536     // Optimized to avoid overwriting data at all
00537     if (&pointLst)
00538     {
00539         storedPoints().transfer(pointLst());
00540     }
00541 
00542     if (&faceLst)
00543     {
00544         storedFaces().transfer(faceLst());
00545     }
00546 
00547     if (&zoneLst)
00548     {
00549         storedZones().transfer(zoneLst());
00550     }
00551 }
00552 
00553 
00554 template<class Face>
00555 void Foam::MeshedSurface<Face>::reset
00556 (
00557     const Xfer< List<point> >& pointLst,
00558     const Xfer< List<Face> >& faceLst,
00559     const Xfer< surfZoneList >& zoneLst
00560 )
00561 {
00562     ParentType::clearOut();
00563 
00564     // Take over new primitive data.
00565     // Optimized to avoid overwriting data at all
00566     if (&pointLst)
00567     {
00568         storedPoints().transfer(pointLst());
00569     }
00570 
00571     if (&faceLst)
00572     {
00573         storedFaces().transfer(faceLst());
00574     }
00575 
00576     if (&zoneLst)
00577     {
00578         storedZones().transfer(zoneLst());
00579     }
00580 }
00581 
00582 
00583 // Remove badly degenerate faces, double faces.
00584 template<class Face>
00585 void Foam::MeshedSurface<Face>::cleanup(const bool verbose)
00586 {
00587     // merge points (already done for STL, TRI)
00588     stitchFaces(SMALL, verbose);
00589 
00590     checkFaces(verbose);
00591     this->checkTopology(verbose);
00592 }
00593 
00594 
00595 template<class Face>
00596 bool Foam::MeshedSurface<Face>::stitchFaces
00597 (
00598     const scalar tol,
00599     const bool verbose
00600 )
00601 {
00602     pointField& pointLst = this->storedPoints();
00603 
00604     // Merge points
00605     labelList  pointMap(pointLst.size());
00606     pointField newPoints(pointLst.size());
00607 
00608     bool hasMerged = mergePoints(pointLst, tol, verbose, pointMap, newPoints);
00609 
00610     if (!hasMerged)
00611     {
00612         return false;
00613     }
00614 
00615     if (verbose)
00616     {
00617         Info<< "MeshedSurface::stitchFaces : Renumbering all faces"
00618             << endl;
00619     }
00620 
00621     // Set the coordinates to the merged ones
00622     pointLst.transfer(newPoints);
00623 
00624     List<Face>& faceLst = this->storedFaces();
00625 
00626     List<label> faceMap(faceLst.size());
00627 
00628     // Reset the point labels to the unique points array
00629     label newFaceI = 0;
00630     forAll(faceLst, faceI)
00631     {
00632         Face& f = faceLst[faceI];
00633         forAll(f, fp)
00634         {
00635             f[fp] = pointMap[f[fp]];
00636         }
00637 
00638         // for extra safety: collapse face as well
00639         if (f.collapse() >= 3)
00640         {
00641             if (newFaceI != faceI)
00642             {
00643                 faceLst[newFaceI] = f;
00644             }
00645             faceMap[newFaceI] = faceI;
00646             newFaceI++;
00647         }
00648         else if (verbose)
00649         {
00650             Pout<< "MeshedSurface::stitchFaces : "
00651                 << "Removing collapsed face " << faceI << endl
00652                 << "    vertices   :" << f << endl;
00653         }
00654     }
00655     pointMap.clear();
00656 
00657     if (newFaceI != faceLst.size())
00658     {
00659         if (verbose)
00660         {
00661             Pout<< "MeshedSurface::stitchFaces : "
00662                 << "Removed " << faceLst.size() - newFaceI
00663                 << " faces" << endl;
00664         }
00665         faceLst.setSize(newFaceI);
00666         remapFaces(faceMap);
00667     }
00668     faceMap.clear();
00669 
00670     // Merging points might have changed geometric factors
00671     ParentType::clearOut();
00672     return true;
00673 }
00674 
00675 
00676 // Remove badly degenerate faces and double faces.
00677 template<class Face>
00678 bool Foam::MeshedSurface<Face>::checkFaces
00679 (
00680     const bool verbose
00681 )
00682 {
00683     bool changed = false;
00684     List<Face>& faceLst = this->storedFaces();
00685 
00686     List<label> faceMap(faceLst.size());
00687 
00688     label newFaceI = 0;
00689     // Detect badly labelled faces and mark degenerate faces
00690     const label maxPointI = this->points().size() - 1;
00691     forAll(faceLst, faceI)
00692     {
00693         Face& f = faceLst[faceI];
00694 
00695         // avoid degenerate faces
00696         if (f.collapse() >= 3)
00697         {
00698             forAll(f, fp)
00699             {
00700                 if (f[fp] < 0 || f[fp] > maxPointI)
00701                 {
00702                     FatalErrorIn("MeshedSurface::checkFaces(bool)")
00703                         << "face " << f
00704                         << " uses point indices outside point range 0.."
00705                     << maxPointI
00706                         << exit(FatalError);
00707                 }
00708             }
00709 
00710             faceMap[faceI] = faceI;
00711             newFaceI++;
00712         }
00713         else
00714         {
00715             // mark as bad face
00716             faceMap[faceI] = -1;
00717 
00718             changed = true;
00719             if (verbose)
00720             {
00721                 WarningIn
00722                 (
00723                     "MeshedSurface::checkFaces(bool verbose)"
00724                 )   << "face[" << faceI << "] = " << f
00725                     << " does not have three unique vertices" << endl;
00726             }
00727         }
00728     }
00729 
00730     // Detect doubled faces
00731     // do not touch the faces
00732     const labelListList& fFaces = this->faceFaces();
00733     newFaceI = 0;
00734     forAll(faceLst, faceI)
00735     {
00736         // skip already collapsed faces:
00737         if (faceMap[faceI] < 0)
00738         {
00739             continue;
00740         }
00741 
00742         const Face& f = faceLst[faceI];
00743 
00744         // duplicate face check
00745         bool okay = true;
00746         const labelList& neighbours = fFaces[faceI];
00747 
00748         // Check if faceNeighbours use same points as this face.
00749         // Note: discards normal information - sides of baffle are merged.
00750         forAll(neighbours, neighI)
00751         {
00752             const label neiFaceI = neighbours[neighI];
00753 
00754             if (neiFaceI <= faceI || faceMap[neiFaceI] < 0)
00755             {
00756                 // lower numbered faces already checked
00757                 // skip neighbours that are themselves collapsed
00758                 continue;
00759             }
00760 
00761             const Face& nei = faceLst[neiFaceI];
00762 
00763             if (f == nei)
00764             {
00765                 okay = false;
00766 
00767                 if (verbose)
00768                 {
00769                     WarningIn
00770                     (
00771                         "MeshedSurface::checkFaces(bool verbose)"
00772                     )   << "faces share the same vertices:" << nl
00773                         << "    face[" << faceI << "] : " << f << nl
00774                         << "    face[" << neiFaceI << "] : " << nei << endl;
00775                     // printFace(Warning, "    ", f, points());
00776                     // printFace(Warning, "    ", nei, points());
00777                 }
00778 
00779                 break;
00780             }
00781         }
00782 
00783         if (okay)
00784         {
00785             faceMap[faceI] = faceI;
00786             newFaceI++;
00787         }
00788         else
00789         {
00790             faceMap[faceI] = -1;
00791         }
00792     }
00793 
00794     // Phase 1: pack
00795     // Done to keep numbering constant in phase 1
00796 
00797     if (changed || newFaceI < faceLst.size())
00798     {
00799         changed = true;
00800 
00801         if (verbose)
00802         {
00803             WarningIn
00804             (
00805                 "MeshedSurface::checkFaces(bool verbose)"
00806             )   << "Removed " << faceLst.size() - newFaceI
00807                 << " illegal faces." << endl;
00808         }
00809 
00810         // compress the face list
00811         newFaceI = 0;
00812         forAll(faceLst, faceI)
00813         {
00814             if (faceMap[faceI] >= 0)
00815             {
00816                 if (newFaceI != faceI)
00817                 {
00818                     faceLst[newFaceI] = faceLst[faceI];
00819                 }
00820                 faceMap[newFaceI] = faceI;
00821                 newFaceI++;
00822             }
00823         }
00824 
00825         faceLst.setSize(newFaceI);
00826         remapFaces(faceMap);
00827     }
00828     faceMap.clear();
00829 
00830     // Topology can change because of renumbering
00831     ParentType::clearOut();
00832     return changed;
00833 }
00834 
00835 
00836 template<class Face>
00837 Foam::label Foam::MeshedSurface<Face>::triangulate()
00838 {
00839     return triangulate
00840     (
00841         const_cast<List<label>&>(List<label>::null())
00842     );
00843 }
00844 
00845 
00846 template<class Face>
00847 Foam::label Foam::MeshedSurface<Face>::triangulate
00848 (
00849     List<label>& faceMapOut
00850 )
00851 {
00852     label nTri = 0;
00853     label maxTri = 0;  // the maximum number of triangles for any single face
00854     List<Face>& faceLst = this->storedFaces();
00855 
00856     // determine how many triangles will be needed
00857     forAll(faceLst, faceI)
00858     {
00859         const label n = faceLst[faceI].nTriangles();
00860         if (maxTri < n)
00861         {
00862             maxTri = n;
00863         }
00864         nTri += n;
00865     }
00866 
00867     // nothing to do
00868     if (nTri <= faceLst.size())
00869     {
00870         if (&faceMapOut)
00871         {
00872             faceMapOut.clear();
00873         }
00874         return 0;
00875     }
00876 
00877     List<Face>  newFaces(nTri);
00878     List<label> faceMap;
00879 
00880     // reuse storage from optional faceMap
00881     if (&faceMapOut)
00882     {
00883         faceMap.transfer(faceMapOut);
00884     }
00885     faceMap.setSize(nTri);
00886 
00887     // remember the number of *additional* faces
00888     nTri -= faceLst.size();
00889 
00890     if (this->points().empty())
00891     {
00892         // triangulate without points
00893         // simple face triangulation around f[0]
00894         label newFaceI = 0;
00895         forAll(faceLst, faceI)
00896         {
00897             const Face& f = faceLst[faceI];
00898 
00899             for (label fp = 1; fp < f.size() - 1; ++fp)
00900             {
00901                 label fp1 = f.fcIndex(fp);
00902 
00903                 newFaces[newFaceI] = triFace(f[0], f[fp], f[fp1]);
00904                 faceMap[newFaceI] = faceI;
00905                 newFaceI++;
00906             }
00907         }
00908     }
00909     else
00910     {
00911         // triangulate with points
00912         List<face> tmpTri(maxTri);
00913 
00914         label newFaceI = 0;
00915         forAll(faceLst, faceI)
00916         {
00917             // 'face' not '<Face>'
00918             const face& f = faceLst[faceI];
00919 
00920             label nTmp = 0;
00921             f.triangles(this->points(), nTmp, tmpTri);
00922             for (label triI = 0; triI < nTmp; triI++)
00923             {
00924                 newFaces[newFaceI] = Face
00925                 (
00926                     static_cast<UList<label>&>(tmpTri[triI])
00927                 );
00928                 faceMap[newFaceI] = faceI;
00929                 newFaceI++;
00930             }
00931         }
00932     }
00933 
00934     faceLst.transfer(newFaces);
00935     remapFaces(faceMap);
00936 
00937     // optionally return the faceMap
00938     if (&faceMapOut)
00939     {
00940         faceMapOut.transfer(faceMap);
00941     }
00942     faceMap.clear();
00943 
00944     // Topology can change because of renumbering
00945     ParentType::clearOut();
00946     return nTri;
00947 }
00948 
00949 
00950 
00951 
00952 template<class Face>
00953 Foam::MeshedSurface<Face> Foam::MeshedSurface<Face>::subsetMesh
00954 (
00955     const labelHashSet& include,
00956     labelList& pointMap,
00957     labelList& faceMap
00958 ) const
00959 {
00960     const pointField& locPoints = this->localPoints();
00961     const List<Face>& locFaces  = this->localFaces();
00962 
00963 
00964     // Fill pointMap, faceMap
00965     PatchTools::subsetMap(*this, include, pointMap, faceMap);
00966 
00967     // Create compact coordinate list and forward mapping array
00968     pointField newPoints(pointMap.size());
00969     labelList oldToNew(locPoints.size());
00970     forAll(pointMap, pointI)
00971     {
00972         newPoints[pointI] = locPoints[pointMap[pointI]];
00973         oldToNew[pointMap[pointI]] = pointI;
00974     }
00975 
00976     // create/copy a new zones list, each zone with zero size
00977     surfZoneList newZones(this->surfZones());
00978     forAll(newZones, zoneI)
00979     {
00980         newZones[zoneI].size() = 0;
00981     }
00982 
00983     // Renumber face node labels
00984     List<Face> newFaces(faceMap.size());
00985     forAll(faceMap, faceI)
00986     {
00987         const label origFaceI = faceMap[faceI];
00988         newFaces[faceI] = Face(locFaces[origFaceI]);
00989 
00990         // Renumber labels for face
00991         Face& f = newFaces[faceI];
00992         forAll(f, fp)
00993         {
00994             f[fp] = oldToNew[f[fp]];
00995         }
00996     }
00997     oldToNew.clear();
00998 
00999     // recalculate the zones start/size
01000     label newFaceI = 0;
01001     label origEndI = 0;
01002 
01003     // adjust zone sizes
01004     forAll(newZones, zoneI)
01005     {
01006         surfZone& zone = newZones[zoneI];
01007 
01008         // adjust zone start
01009         zone.start() = newFaceI;
01010         origEndI += zone.size();
01011 
01012         for (label faceI = newFaceI; faceI < faceMap.size(); ++faceI)
01013         {
01014             if (faceMap[faceI] < origEndI)
01015             {
01016                 ++newFaceI;
01017             }
01018             else
01019             {
01020                 break;
01021             }
01022         }
01023 
01024         // adjust zone size
01025         zone.size() = newFaceI - zone.start();
01026     }
01027 
01028 
01029     // construct a sub-surface
01030     return MeshedSurface
01031     (
01032         xferMove(newPoints),
01033         xferMove(newFaces),
01034         xferMove(newZones)
01035     );
01036 }
01037 
01038 
01039 template<class Face>
01040 Foam::MeshedSurface<Face>
01041 Foam::MeshedSurface<Face>::subsetMesh
01042 (
01043     const labelHashSet& include
01044 ) const
01045 {
01046     labelList pointMap, faceMap;
01047     return subsetMesh(include, pointMap, faceMap);
01048 }
01049 
01050 
01051 
01052 template<class Face>
01053 void Foam::MeshedSurface<Face>::transfer
01054 (
01055     MeshedSurface<Face>& surf
01056 )
01057 {
01058     reset
01059     (
01060         xferMove(surf.storedPoints()),
01061         xferMove(surf.storedFaces()),
01062         xferMove(surf.storedZones())
01063     );
01064 }
01065 
01066 
01067 template<class Face>
01068 void Foam::MeshedSurface<Face>::transfer
01069 (
01070     UnsortedMeshedSurface<Face>& surf
01071 )
01072 {
01073     clear();
01074 
01075     labelList faceMap;
01076     surfZoneList zoneLst = surf.sortedZones(faceMap);
01077 
01078     if (zoneLst.size() <= 1)
01079     {
01080         reset
01081         (
01082             xferMove(surf.storedPoints()),
01083             xferMove(surf.storedFaces()),
01084             Xfer<surfZoneList>()
01085         );
01086     }
01087     else
01088     {
01089         List<Face>& oldFaces = surf.storedFaces();
01090         List<Face> newFaces(faceMap.size());
01091 
01092         forAll(faceMap, faceI)
01093         {
01094             newFaces[faceI].transfer(oldFaces[faceMap[faceI]]);
01095         }
01096 
01097         reset
01098         (
01099             xferMove(surf.storedPoints()),
01100             xferMove(newFaces),
01101             xferMove(zoneLst)
01102         );
01103     }
01104 
01105     faceMap.clear();
01106     surf.clear();
01107 }
01108 
01109 
01110 template<class Face>
01111 Foam::Xfer< Foam::MeshedSurface<Face> >
01112 Foam::MeshedSurface<Face>::xfer()
01113 {
01114     return xferMove(*this);
01115 }
01116 
01117 
01118 // Read from file, determine format from extension
01119 template<class Face>
01120 bool Foam::MeshedSurface<Face>::read(const fileName& name)
01121 {
01122     word ext = name.ext();
01123     if (ext == "gz")
01124     {
01125         fileName unzipName = name.lessExt();
01126         return read(unzipName, unzipName.ext());
01127     }
01128     else
01129     {
01130         return read(name, ext);
01131     }
01132 }
01133 
01134 
01135 // Read from file in given format
01136 template<class Face>
01137 bool Foam::MeshedSurface<Face>::read
01138 (
01139     const fileName& name,
01140     const word& ext
01141 )
01142 {
01143     clear();
01144 
01145     // read via selector mechanism
01146     transfer(New(name, ext)());
01147     return true;
01148 }
01149 
01150 
01151 template<class Face>
01152 void Foam::MeshedSurface<Face>::write
01153 (
01154     const Time& t,
01155     const word& surfName
01156 ) const
01157 {
01158     MeshedSurfaceProxy<Face>(*this).write(t, surfName);
01159 }
01160 
01161 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
01162 
01163 template<class Face>
01164 void Foam::MeshedSurface<Face>::operator=(const MeshedSurface& surf)
01165 {
01166     clear();
01167 
01168     this->storedPoints() = surf.points();
01169     this->storedFaces()  = surf.faces();
01170     this->storedZones()  = surf.surfZones();
01171 }
01172 
01173 
01174 template<class Face>
01175 Foam::MeshedSurface<Face>::operator
01176 Foam::MeshedSurfaceProxy<Face>() const
01177 {
01178     return MeshedSurfaceProxy<Face>
01179     (
01180         this->points(),
01181         this->faces(),
01182         this->surfZones()
01183     );
01184 }
01185 
01186 // * * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * //
01187 
01188 // * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
01189 
01190 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
01191 
01192 #include "MeshedSurfaceZones.C"
01193 #include "MeshedSurfaceIO.C"
01194 #include "MeshedSurfaceNew.C"
01195 
01196 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines