1 /** @file triangulatedMeshToSolid_example.cpp
2
3 @brief Recover the features of a triangulated surface.
4
5 This file is part of the G+Smo library.
6
7 This Source Code Form is subject to the terms of the Mozilla Public
8 License, v. 2.0. If a copy of the MPL was not distributed with this
9 file, You can obtain one at http://mozilla.org/MPL/2.0/.
10
11 Author(s): M. Pauley
12 */
13
14
15 #include <gismo.h>
16 #include <iostream>
17 #include <fstream>
18
19 using namespace gismo;
20
main(int argc,char * argv[])21 int main(int argc, char *argv[])
22 {
23 bool plot = false; // If user gives --plot as argument, paraview file is generated and launched on exit
24 bool toxml = false;
25 bool noSmooth = false;
26 bool writePatchNumbers = false;
27 std::string filename = "off/mushroom_triangulated.off";
28 real_t cutoffAngle = 40.0;
29 real_t innerAngle = 15.0;
30 real_t patchAreaWeight = 0.2;
31 real_t mergeSmallPatches = 2;
32 index_t degree = 4;
33 index_t interiorPts = 5;
34 index_t wEdge = 10;
35 index_t wInterior = 1;
36
37 gsCmdLine cmd("Recover the features of a triangulated surface.");
38 cmd.addPlainString("filename", "File containing the input mesh", filename);
39 cmd.addSwitch("plot", "Output mesh in ParaView format", plot);
40 cmd.addSwitch("xml", "Output solid to xml file", toxml);
41 cmd.addSwitch("nosmooth", "Do not smooth corners of faces", noSmooth);
42 cmd.addSwitch("writenums", "Write patch numbers to patchnumbers.txt", writePatchNumbers);
43 cmd.addInt("f", "interiorweight","Surface fitting: weight for interior points.",
44 wInterior);
45 cmd.addInt("e", "edgeweight","Surface fitting: weight for edges.",
46 wEdge);
47 cmd.addInt("i", "interior","Interior knot points of each dimension of trimmed surface.",
48 interiorPts);
49 cmd.addInt("d", "degree","Degree of each dimension of trimmed surface.",
50 degree);
51 cmd.addReal("p", "paw","Patch area weight.", patchAreaWeight);
52 cmd.addReal("m", "msp","Merge small patches.", mergeSmallPatches);
53 cmd.addReal("y", "innerangle","Cutoff angle (degrees) for second pass.",
54 innerAngle);
55 cmd.addReal("c", "cutoff","Cutoff angle (degrees).", cutoffAngle);
56
57 try { cmd.getValues(argc,argv); } catch (int rv) { return rv; }
58
59 filename = gsFileManager::find(filename);
60 if ( filename.empty() )
61 {
62 gsInfo << "Could not find file.\n";
63 return EXIT_SUCCESS;
64 }
65
66 // decide on the base filename
67 size_t nameStartIdx = filename.rfind('/');
68 if ( nameStartIdx == std::string::npos)
69 nameStartIdx = 0;
70 else
71 nameStartIdx+= 1;
72 size_t nameEndIdx = filename.rfind('.');
73 std::string baseName = filename.substr(nameStartIdx, nameEndIdx - nameStartIdx);
74 gsInfo << "--- Settings ---\n";
75 gsInfo << "Processing " << baseName << "\n";
76 gsInfo << "Cutoff angle is " << cutoffAngle << "\n";
77 gsInfo << "Master surfaces have degree " << degree << " and " << interiorPts << " interior knot points.\n";
78 gsInfo << "Surface fit: edge weighting is " << wEdge << " and interior point weighting is " << wInterior << ".\n";
79 if(noSmooth) gsInfo << "Will NOT smooth corners of faces\n";
80 else gsInfo << "WILL smooth corners of faces\n";
81 if(plot) gsInfo << "WILL create paraview plot\n";
82 else gsInfo << "Will NOT create paraview plot\n";
83 gsInfo << "----------------\n";
84
85 gsMesh<>::uPtr m = gsReadFile<>(filename);
86 if (m)
87 gsInfo<< "Got "<< *m <<"\n";
88 else
89 {
90 gsInfo<< "Problem encountered in file "<<filename<<", quitting." <<"\n";
91 return EXIT_SUCCESS;
92 }
93 std::vector< gsMesh<> * > paraMeshes;// filled inside toSolid
94 std::vector< gsMesh<> * > fitMeshes; // filled inside toSolid
95 std::vector< gsMesh<> * > patchMeshes; // filled inside toSolid
96
97 std::vector< std::vector< gsVertex<>* > > iPoints;
98 std::vector< std::vector< gsVertex<>* > > oPoints;
99 std::vector< std::vector< std::vector<gsVertex<>* > > > innerBdrys;
100 std::vector< std::vector< gsVertex<> > > innerBdrysMassP;
101 std::vector< std::vector< bool > > oPointsConvexFlag;
102
103 // set up the gsTriMeshToSolid class to perform the feature detection
104 gsTriMeshToSolid<> tmts(m.get());
105 bool non_manifold, warning_borders;
106
107 // compute the features
108 tmts.getFeatures(cutoffAngle, non_manifold, warning_borders);
109 m->cleanMesh();
110
111 // give every face a patch number
112 tmts.calcPatchNumbers();
113
114 // improve quality by further dividing and merging patches according to more complex rules
115 tmts.storeNeighboringFaces();
116 tmts.divideAndMergePatches(innerAngle, patchAreaWeight, mergeSmallPatches);
117
118 // recompute patch numbers
119 tmts.calcPatchNumbers();
120
121 if(writePatchNumbers)
122 {
123 // write patch numbers
124 gsInfo << "Writing patch numbers...\n";
125 std::ofstream pn("patchnumbers.txt");
126
127 for(std::vector<gsMeshElement<>::gsFaceHandle >::const_iterator it(m->faces().begin());it!=m->faces().end();++it)
128 {
129 pn << (**it).faceIdentity << "\n";
130 }
131 }
132
133 // get the patches
134 tmts.getFaces(iPoints, oPoints, innerBdrys, innerBdrysMassP, oPointsConvexFlag);
135
136 gsSolid<> sl;
137 //if you need a higher number of interior points when fitting the surface increase the 8th input variable(now 5)
138 tmts.toSolid(sl,iPoints,oPoints,innerBdrys,innerBdrysMassP,oPointsConvexFlag,paraMeshes,fitMeshes,patchMeshes,degree,interiorPts,true,300,true,wEdge,wInterior,1,noSmooth);
139 gsInfo<<sl<<'\n';
140
141 if (toxml)
142 {
143 gsInfo << "Writing xml file..." << "\n";
144
145 gsFileData<> newdata;
146 newdata << sl;
147 newdata.dump(baseName);
148
149 //write sharpness information to a file:
150 // first line: #patches
151 // next #patches lines: #outer points of patch i, sharpness of first point ... sharpness of last point of patch i
152 // next #patches lines: #holes of patch i
153 // next #holes of patch i lines: #points of hole j of patch i, sharpness of first point ... sharpness of last point of hole j of patch i
154 std::string outputFilename;
155 outputFilename = "corner_data.txt";
156 std::ofstream myfile (outputFilename.c_str());
157 if (myfile.is_open())
158 {
159 myfile << oPoints.size()<<"\n";
160
161 for(size_t i=0;i<oPoints.size();i++)
162 {
163 myfile << oPoints[i].size()<<" ";
164 for(size_t j=0;j<oPoints[i].size();j++)
165 myfile<<(oPoints[i][j]->numEdges>2)<<" ";
166 myfile << "\n";
167
168 }
169 myfile << "\n";
170
171 for(size_t i=0;i<innerBdrys.size();i++)
172 {
173 myfile << innerBdrys[i].size()<<" ";
174 for(size_t j=0;j<innerBdrys[i].size();j++)
175 {
176 myfile << innerBdrys[i][j].size()<<" ";
177 for(size_t k=0;k<innerBdrys[i][j].size();k++)
178 myfile<<(innerBdrys[i][j][k]->numEdges>2)<<" ";
179 }
180 myfile << "\n";
181 }
182
183 myfile.close();
184 }
185
186 }
187
188 if (plot)
189 {
190 // Write a paraview file
191 gsInfo<<"Writing paraview file..." << "\n";
192
193 gsWriteParaview( *m, "output");
194 }
195 else
196 {
197 gsInfo << "Done. No output created, re-run with --plot to get a ParaView "
198 "file containing the solution.\n";
199 }
200
201 // free meshes
202 freeAll(fitMeshes);
203 freeAll(paraMeshes);
204 freeAll(patchMeshes);
205
206 return EXIT_SUCCESS;
207 }
208