1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
25 cfMesh utility to merge the supplied list of patches onto a single
29 Ivor Clifford <ivor.clifford@psi.ch>
31 \*---------------------------------------------------------------------------*/
34 #include "objectRegistry.H"
38 #include "triSurfModifier.H"
39 #include "demandDrivenData.H"
44 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 // Find the supplied list of patch names and return a list of patch Ids
49 const triSurf& origSurf,
50 const wordList& patchNames,
51 DynamicList<label>& patchIds
54 const geometricSurfacePatchList& origPatches = origSurf.patches();
56 // Create patch name map
57 HashSet<word> patchNameHash(patchNames);
59 // Find selected patches
61 forAll(origPatches, patchI)
63 if (patchNameHash.found(origPatches[patchI].name()))
65 patchIds.append(patchI);
70 if (nFound != patchNames.size())
72 WarningIn("getPatchIds")
73 << "Not all supplied patch names were found on the surface mesh" << endl;
78 // Copy all face subsets from one triSurf to another
81 const triSurf& origSurf,
85 DynList<label> subsetIds;
86 origSurf.facetSubsetIndices(subsetIds);
88 forAll(subsetIds, subsetI)
90 label newSubsetId = newSurf.addFacetSubset
92 origSurf.facetSubsetName(subsetI)
96 origSurf.facetsInSubset(subsetI, origFaces);
98 forAll(origFaces, faceI)
100 newSurf.addFacetToSubset
110 // Copy all edge subsets from one triSurf to another
113 const triSurf& origSurf,
117 DynList<label> subsetIds;
118 origSurf.edgeSubsetIndices(subsetIds);
120 forAll(subsetIds, subsetI)
122 label newSubsetId = newSurf.addEdgeSubset
124 origSurf.edgeSubsetName(subsetI)
128 origSurf.edgesInSubset(subsetI, origEdges);
130 forAll(origEdges, faceI)
132 newSurf.addEdgeToSubset
142 // Copy all point subsets from one triSurf to another
143 void copyPointSubsets
145 const triSurf& origSurf,
149 DynList<label> subsetIds;
150 origSurf.pointSubsetIndices(subsetIds);
152 forAll(subsetIds, subsetI)
154 label newSubsetId = newSurf.addPointSubset
156 origSurf.pointSubsetName(subsetI)
159 labelList origPoints;
160 origSurf.pointsInSubset(subsetI, origPoints);
162 forAll(origPoints, faceI)
164 newSurf.addPointToSubset
174 // Merge the supplied list of patchIds onto a new patch
175 autoPtr<triSurf> mergeSurfacePatches
177 const triSurf& origSurf, // Surface
178 const UList<label>& patchIds, // Ids of patches to merge
179 const word& newPatchName, // Name of new (merged) patch
180 bool keepPatches // Keep the original patches - they will be emptied
183 const geometricSurfacePatchList& origPatches = origSurf.patches();
184 const LongList<labelledTri>& origFacets = origSurf.facets();
186 label newPatchId = origPatches.size();
188 // Determine new patch type
189 word newPatchType = origPatches[patchIds[0]].geometricType();
191 // Create patch addressing
192 List<DynamicList<label> > patchAddr(origPatches.size()+1);
194 forAll(origFacets, faceI)
196 patchAddr[origFacets[faceI].region()].append(faceI);
199 // Move selected patches to new patch
200 forAll(patchIds, patchI)
202 patchAddr[newPatchId].append(patchAddr[patchIds[patchI]]);
203 patchAddr[patchIds[patchI]].clear();
206 // Create new facets list
207 LongList<labelledTri> newFacets(origFacets.size());
208 labelList newFaceAddr(origFacets.size(), -1);
210 label patchCount = 0;
212 forAll(patchAddr, patchI)
214 const unallocLabelList& addr = patchAddr[patchI];
220 newFacets[faceI] = origFacets[addr[i]];
221 newFacets[faceI].region() = patchCount;
223 newFaceAddr[addr[i]] = faceI;
229 if(addr.size() || keepPatches)
235 // Create new patch list
236 geometricSurfacePatchList newPatches(patchCount);
239 forAll(origPatches, patchI)
241 // Only add patches if they contain faces
242 if(patchAddr[patchI].size())
244 newPatches[patchCount] = origPatches[patchI];
245 newPatches[patchCount].index() = patchCount;
248 if(patchAddr[patchI].size() || keepPatches)
254 // Add new patch if it contains faces
255 if(patchAddr[patchAddr.size()-1].size())
257 newPatches[patchCount] = geometricSurfacePatch
264 if(patchAddr[patchAddr.size()-1].size() || keepPatches)
269 // Create new surface
270 autoPtr<triSurf> newSurf
276 origSurf.featureEdges(),
281 // Transfer face subsets
282 copyFaceSubsets(origSurf, newSurf());
283 newSurf->updateFacetsSubsets(newFaceAddr);
285 // Transfer feature edge subsets
286 copyEdgeSubsets(origSurf, newSurf());
288 // Transfer point subsets
289 copyPointSubsets(origSurf, newSurf());
295 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
297 int main(int argc, char *argv[])
299 argList::noParallel();
300 argList::validArgs.clear();
302 argList::validArgs.append("input surface file");
303 argList::validArgs.append("new patch");
304 argList::validOptions.insert("patchNames", "list of names");
305 argList::validOptions.insert("patchIds", "list of patchIds");
306 argList::validOptions.insert("patchIdRange", "( start end )");
307 argList::validOptions.insert("output", "file name (default overwrite)");
308 argList::validOptions.insert("keep", "");
309 argList args(argc, argv);
311 // Process commandline arguments
312 fileName inFileName(args.args()[1]);
314 word newPatchName(args.args()[2]);
316 fileName outFileName(inFileName);
318 if( args.options().found("output") )
320 outFileName = args.options()["output"];
323 bool keepPatches = false;
325 if( args.options().found("keep") )
330 // Read original surface
331 triSurf origSurf(inFileName);
334 DynamicList<label> patchIds;
336 if (args.options().found("patchNames"))
338 if (args.options().found("patchIds"))
340 FatalError() << "Cannot specify both patch names and ids"
341 << Foam::abort(FatalError);
344 IStringStream is(args.options()["patchNames"]);
345 wordList patchNames(is);
354 if (args.options().found("patchIds"))
356 IStringStream is(args.options()["patchIds"]);
358 patchIds = labelList(is);
360 if (args.options().found("patchIds"))
362 IStringStream is(args.options()["patchIds"]);
364 patchIds.append(labelList(is));
366 if (args.options().found("patchIdRange"))
368 IStringStream is(args.options()["patchIdRange"]);
370 Pair<label> idRange(is);
372 for(label id = idRange.first(); id <= idRange.second(); id++)
377 if (!patchIds.size())
379 FatalError() << "No patches specified"
380 << Foam::abort(FatalError);
384 autoPtr<triSurf> newSurf = mergeSurfacePatches
392 // Write new surface mesh
393 newSurf->writeSurface(outFileName);
395 Info << "Original surface patches: " << origSurf.patches().size() << endl;
396 Info << "Final surface patches: " << newSurf->patches().size() << endl;
397 Info << "Surface written to " << outFileName << endl;
399 Info << "End\n" << endl;
404 // ************************************************************************* //