1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 Extracts and writes surface features to file
31 \*---------------------------------------------------------------------------*/
34 #include "triSurface.H"
36 #include "surfaceFeatures.H"
37 #include "treeBoundBox.H"
38 #include "meshTools.H"
43 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
45 void dumpBox(const treeBoundBox& bb, const fileName& fName)
49 Pout<< "Dumping bounding box " << bb << " as lines to obj file "
50 << str.name() << endl;
53 pointField boxPoints(bb.points());
57 meshTools::writeOBJ(str, boxPoints[i]);
60 forAll(treeBoundBox::edges, i)
62 const edge& e = treeBoundBox::edges[i];
64 str<< "l " << e[0]+1 << ' ' << e[1]+1 << nl;
69 // Deletes all edges inside/outside bounding box from set.
72 const triSurface& surf,
73 const treeBoundBox& bb,
74 const bool removeInside,
75 List<surfaceFeatures::edgeStatus>& edgeStat
78 forAll(edgeStat, edgeI)
80 const point eMid = surf.edges()[edgeI].centre(surf.localPoints());
84 (removeInside && bb.contains(eMid))
85 || (!removeInside && !bb.contains(eMid))
88 edgeStat[edgeI] = surfaceFeatures::NONE;
96 int main(int argc, char *argv[])
98 argList::noParallel();
100 argList::validArgs.clear();
101 argList::validArgs.append("surface");
102 argList::validArgs.append("output set");
104 argList::validOptions.insert("includedAngle", "included angle [0..180]");
105 argList::validOptions.insert("set", "input feature set");
107 argList::validOptions.insert("minLen", "cumulative length of feature");
108 argList::validOptions.insert("minElem", "number of edges in feature");
109 argList::validOptions.insert("subsetBox", "((x0 y0 z0)(x1 y1 z1))");
110 argList::validOptions.insert("deleteBox", "((x0 y0 z0)(x1 y1 z1))");
111 argList args(argc, argv);
113 Pout<< "Feature line extraction is only valid on closed manifold surfaces."
117 fileName surfFileName(args.additionalArgs()[0]);
118 fileName outFileName(args.additionalArgs()[1]);
120 Pout<< "Surface : " << surfFileName << nl
121 << "Output feature set : " << outFileName << nl
128 triSurface surf(surfFileName);
130 Pout<< "Statistics:" << endl;
131 surf.writeStats(Pout);
137 // Either construct features from surface&featureangle or read set.
138 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
140 surfaceFeatures set(surf);
142 if (args.options().found("set"))
144 fileName setName(args.options()["set"]);
146 Pout<< "Reading existing feature set from file " << setName << endl;
148 set = surfaceFeatures(surf, setName);
150 else if (args.options().found("includedAngle"))
154 readScalar(IStringStream(args.options()["includedAngle"])())
157 Pout<< "Constructing feature set from included angle " << includedAngle
160 set = surfaceFeatures(surf, includedAngle);
162 Pout<< endl << "Writing initial features" << endl;
163 set.write("initial.fSet");
164 set.writeObj("initial");
168 FatalErrorIn(args.executable())
169 << "No initial feature set. Provide either one"
170 << " of -set (to read existing set)" << nl
171 << " or -includedAngle (to new set construct from angle)"
177 << "Initial feature set:" << nl
178 << " feature points : " << set.featurePoints().size() << nl
179 << " feature edges : " << set.featureEdges().size() << nl
181 << " region edges : " << set.nRegionEdges() << nl
182 << " external edges : " << set.nExternalEdges() << nl
183 << " internal edges : " << set.nInternalEdges() << nl
192 scalar minLen = -GREAT;
193 if (args.options().found("minLen"))
195 minLen = readScalar(IStringStream(args.options()["minLen"])());
196 Pout<< "Removing features of length < " << minLen << endl;
200 if (args.options().found("minElem"))
202 minElem = readLabel(IStringStream(args.options()["minElem"])());
203 Pout<< "Removing features with number of edges < " << minElem << endl;
206 // Trim away small groups of features
207 if (minLen > 0 || minLen > 0)
209 set.trimFeatures(minLen, minElem);
210 Pout<< endl << "Removed small features" << endl;
218 // Convert to marked edges, points
219 List<surfaceFeatures::edgeStatus> edgeStat(set.toStatus());
221 if (args.options().found("subsetBox"))
223 treeBoundBox bb(IStringStream(args.options()["subsetBox"])());
225 Pout<< "Removing all edges outside bb " << bb << endl;
226 dumpBox(bb, "subsetBox.obj");
236 else if (args.options().found("deleteBox"))
238 treeBoundBox bb(IStringStream(args.options()["deleteBox"])());
240 Pout<< "Removing all edges inside bb " << bb << endl;
241 dumpBox(bb, "deleteBox.obj");
252 surfaceFeatures newSet(surf);
253 newSet.setFromStatus(edgeStat);
255 Pout<< endl << "Writing trimmed features to " << outFileName << endl;
256 newSet.write(outFileName);
258 Pout<< endl << "Writing edge objs." << endl;
259 newSet.writeObj("final");
263 << "Final feature set:" << nl
264 << " feature points : " << newSet.featurePoints().size() << nl
265 << " feature edges : " << newSet.featureEdges().size() << nl
267 << " region edges : " << newSet.nRegionEdges() << nl
268 << " external edges : " << newSet.nExternalEdges() << nl
269 << " internal edges : " << newSet.nInternalEdges() << nl
272 Pout<< "End\n" << endl;
278 // ************************************************************************* //