1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
28 Extracts and writes surface features to file
30 \*---------------------------------------------------------------------------*/
33 #include "triSurface.H"
35 #include "surfaceFeatures.H"
36 #include "treeBoundBox.H"
37 #include "meshTools.H"
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44 void dumpBox(const treeBoundBox& bb, const fileName& fName)
48 Pout<< "Dumping bounding box " << bb << " as lines to obj file "
49 << str.name() << endl;
52 pointField boxPoints(bb.points());
56 meshTools::writeOBJ(str, boxPoints[i]);
59 forAll(treeBoundBox::edges, i)
61 const edge& e = treeBoundBox::edges[i];
63 str<< "l " << e[0]+1 << ' ' << e[1]+1 << nl;
68 // Deletes all edges inside/outside bounding box from set.
71 const triSurface& surf,
72 const treeBoundBox& bb,
73 const bool removeInside,
74 List<surfaceFeatures::edgeStatus>& edgeStat
77 forAll(edgeStat, edgeI)
79 const point eMid = surf.edges()[edgeI].centre(surf.localPoints());
83 (removeInside && bb.contains(eMid))
84 || (!removeInside && !bb.contains(eMid))
87 edgeStat[edgeI] = surfaceFeatures::NONE;
95 int main(int argc, char *argv[])
97 argList::noParallel();
99 argList::validArgs.clear();
100 argList::validArgs.append("surface");
101 argList::validArgs.append("output set");
103 argList::validOptions.insert("includedAngle", "included angle [0..180]");
104 argList::validOptions.insert("set", "input feature set");
106 argList::validOptions.insert("minLen", "cumulative length of feature");
107 argList::validOptions.insert("minElem", "number of edges in feature");
108 argList::validOptions.insert("subsetBox", "((x0 y0 z0)(x1 y1 z1))");
109 argList::validOptions.insert("deleteBox", "((x0 y0 z0)(x1 y1 z1))");
110 argList args(argc, argv);
112 Pout<< "Feature line extraction is only valid on closed manifold surfaces."
116 fileName surfFileName(args.additionalArgs()[0]);
117 fileName outFileName(args.additionalArgs()[1]);
119 Pout<< "Surface : " << surfFileName << nl
120 << "Output feature set : " << outFileName << nl
127 triSurface surf(surfFileName);
129 Pout<< "Statistics:" << endl;
130 surf.writeStats(Pout);
136 // Either construct features from surface&featureangle or read set.
137 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
139 surfaceFeatures set(surf);
141 if (args.optionFound("set"))
143 fileName setName(args.option("set"));
145 Pout<< "Reading existing feature set from file " << setName << endl;
147 set = surfaceFeatures(surf, setName);
149 else if (args.optionFound("includedAngle"))
151 scalar includedAngle = args.optionRead<scalar>("includedAngle");
153 Pout<< "Constructing feature set from included angle " << includedAngle
156 set = surfaceFeatures(surf, includedAngle);
158 Pout<< endl << "Writing initial features" << endl;
159 set.write("initial.fSet");
160 set.writeObj("initial");
164 FatalErrorIn(args.executable())
165 << "No initial feature set. Provide either one"
166 << " of -set (to read existing set)" << nl
167 << " or -includedAngle (to new set construct from angle)"
173 << "Initial feature set:" << nl
174 << " feature points : " << set.featurePoints().size() << nl
175 << " feature edges : " << set.featureEdges().size() << nl
177 << " region edges : " << set.nRegionEdges() << nl
178 << " external edges : " << set.nExternalEdges() << nl
179 << " internal edges : " << set.nInternalEdges() << nl
188 scalar minLen = -GREAT;
189 if (args.optionReadIfPresent("minLen", minLen))
191 Pout<< "Removing features of length < " << minLen << endl;
195 if (args.optionReadIfPresent("minElem", minElem))
197 Pout<< "Removing features with number of edges < " << minElem << endl;
200 // Trim away small groups of features
201 if (minLen > 0 || minLen > 0)
203 set.trimFeatures(minLen, minElem);
204 Pout<< endl << "Removed small features" << endl;
212 // Convert to marked edges, points
213 List<surfaceFeatures::edgeStatus> edgeStat(set.toStatus());
215 if (args.optionFound("subsetBox"))
217 treeBoundBox bb(args.optionLookup("subsetBox")());
219 Pout<< "Removing all edges outside bb " << bb << endl;
220 dumpBox(bb, "subsetBox.obj");
230 else if (args.optionFound("deleteBox"))
232 treeBoundBox bb(args.optionLookup("deleteBox")());
234 Pout<< "Removing all edges inside bb " << bb << endl;
235 dumpBox(bb, "deleteBox.obj");
246 surfaceFeatures newSet(surf);
247 newSet.setFromStatus(edgeStat);
249 Pout<< endl << "Writing trimmed features to " << outFileName << endl;
250 newSet.write(outFileName);
252 Pout<< endl << "Writing edge objs." << endl;
253 newSet.writeObj("final");
257 << "Final feature set:" << nl
258 << " feature points : " << newSet.featurePoints().size() << nl
259 << " feature edges : " << newSet.featureEdges().size() << nl
261 << " region edges : " << newSet.nRegionEdges() << nl
262 << " external edges : " << newSet.nExternalEdges() << nl
263 << " internal edges : " << newSet.nInternalEdges() << nl
266 Pout<< "End\n" << endl;
272 // ************************************************************************* //