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