32 #include "DGtal/base/Common.h"
34 #include "DGtal/io/Display3D.h"
35 #include "DGtal/io/viewers/Viewer3D.h"
36 #include "DGtal/io/readers/MeshReader.h"
37 #include "DGtal/helpers/StdDefs.h"
38 #include "DGtal/io/readers/PointListReader.h"
40 #include <boost/program_options/options_description.hpp>
41 #include <boost/program_options/parsers.hpp>
42 #include <boost/program_options/variables_map.hpp>
46 using namespace DGtal;
119 class CustomViewer3D:
public Viewer3D<>
126 Viewer3D<>::setKeyDescription ( Qt::Key_I,
"Display mesh informations about #faces, #vertices" );
127 Viewer3D<>::setGLDoubleRenderingMode(
false);
129 QObject::connect(
this, SIGNAL(drawFinished(
bool)),
this, SLOT(saveSnapshot(
bool)));
132 virtual void keyPressEvent(QKeyEvent *e){
133 bool handled =
false;
134 if( e->key() == Qt::Key_I)
137 myIsDisplayingInfoMode = !myIsDisplayingInfoMode;
138 std::stringstream sstring;
139 Viewer3D<>::displayMessage(QString(myIsDisplayingInfoMode ?
140 myInfoDisplay.c_str() :
" "), 1000000);
141 Viewer3D<>::updateGL();
145 Viewer3D<>::keyPressEvent(e);
150 std::string myInfoDisplay =
"No information loaded...";
151 bool myIsDisplayingInfoMode =
false;
152 bool mySaveSnap =
false;
159 namespace po = boost::program_options;
161 int main(
int argc,
char** argv )
165 po::options_description general_opt(
"Allowed options are: ");
166 general_opt.add_options()
167 (
"help,h",
"display this message")
168 (
"input,i", po::value<std::vector<string> >()->multitoken(),
"off files (.off), or OFS file (.ofs) " )
169 (
"scaleX,x", po::value<float>()->default_value(1.0),
"set the scale value in the X direction (default 1.0)" )
170 (
"scaleY,y", po::value<float>()->default_value(1.0),
"set the scale value in the Y direction (default 1.0)" )
171 (
"scaleZ,z", po:: value<float>()->default_value(1.0),
"set the scale value in the Z direction (default 1.0)")
172 (
"minLineWidth,w", po:: value<float>()->default_value(1.5),
"set the min line width of the mesh faces (default 1.5)")
173 (
"customColorMesh",po::value<std::vector<unsigned int> >()->multitoken(),
"set the R, G, B, A components of the colors of the mesh faces and eventually the color R, G, B, A of the mesh edge lines (set by default to black). " )
174 (
"customColorSDP",po::value<std::vector<unsigned int> >()->multitoken(),
"set the R, G, B, A components of the colors of the sdp view" )
175 (
"displayVectorField,f",po::value<std::string>(),
"display a vector field from a simple sdp file (two points per line)" )
176 (
"vectorFieldIndex",po::value<std::vector<unsigned int> >()->multitoken(),
"specify special indices for the two point coordinates (instead usinf the default indices: 0 1, 2, 3, 4, 5)" )
177 (
"customLineColor",po::value<std::vector<unsigned int> >()->multitoken(),
"set the R, G, B components of the colors of the lines displayed from the --displayVectorField option (red by default). " )
178 (
"displaySDP,s", po::value<std::string>(),
"Add the display of a set of discrete points as ball of radius 0.5.")
179 (
"SDPradius", po::value<double>()->default_value(0.5),
"change the ball radius to display a set of discrete points (used with displaySDP option)")
180 (
"invertNormal,n",
"invert face normal vectors." )
181 (
"drawVertex,v",
"draw the vertex of the mesh" )
182 (
"doSnapShotAndExit,d", po::value<std::string>(),
"save display snapshot into file. Notes that the camera setting is set by default according the last saved configuration (use SHIFT+Key_M to save current camera setting in the Viewer3D). If the camera setting was not saved it will use the default camera setting." );
185 po::variables_map vm;
187 po::store(po::parse_command_line(argc, argv, general_opt), vm);
188 }
catch(
const std::exception& ex){
190 trace.info()<<
"Error checking program options: "<< ex.what()<< endl;
193 if( !parseOK || vm.count(
"help")||argc<=1)
195 std::cout <<
"Usage: " << argv[0] <<
" [input]\n"
196 <<
"Display OFF mesh file by using QGLviewer"
197 << general_opt <<
"\n";
201 if(! vm.count(
"input"))
203 trace.error() <<
" The file name was defined" << endl;
209 std::vector<std::string> inputFilenameVect = vm[
"input"].as<std::vector<std::string > >();
210 float sx = vm[
"scaleX"].as<
float>();
211 float sy = vm[
"scaleY"].as<
float>();
212 float sz = vm[
"scaleZ"].as<
float>();
214 unsigned int meshColorR = 240;
215 unsigned int meshColorG = 240;
216 unsigned int meshColorB = 240;
217 unsigned int meshColorA = 255;
219 unsigned int meshColorRLine = 0;
220 unsigned int meshColorGLine = 0;
221 unsigned int meshColorBLine = 0;
222 unsigned int meshColorALine = 255;
225 unsigned int sdpColorR = 240;
226 unsigned int sdpColorG = 240;
227 unsigned int sdpColorB = 240;
228 unsigned int sdpColorA = 255;
231 bool displayVectorField = vm.count(
"displayVectorField");
232 std::vector<unsigned int> vectFieldIndices = {0,1,2,3,4,5};
234 if (displayVectorField) {
235 if(vm.count(
"vectorFieldIndex")){
236 vectFieldIndices = vm[
"vectorFieldIndex"].as<std::vector<unsigned int> >();
237 if (vectFieldIndices.size() != 6) {
238 trace.warning() <<
"you should specify indices for each of the 6 fields of the two coordinates." << std::endl;
239 vectFieldIndices = {0,1,2,3,4,5};
244 float lineWidth = vm[
"minLineWidth"].as<
float>();
246 DGtal::Color vFieldLineColor = DGtal::Color::Red;
247 if(vm.count(
"customLineColor")){
248 std::vector<unsigned int > vectCol = vm[
"customLineColor"].as<std::vector<unsigned int> >();
249 if(vectCol.size()!=3 ){
250 trace.error() <<
"colors specification should contain R,G,B values (using default red)."<< std::endl;
252 vFieldLineColor.setRGBi(vectCol[0], vectCol[1], vectCol[2], 255);
255 if(vm.count(
"customColorMesh")){
256 std::vector<unsigned int > vectCol = vm[
"customColorMesh"].as<std::vector<unsigned int> >();
257 if(vectCol.size()!=4 && vectCol.size()!=8 ){
258 trace.error() <<
"colors specification should contain R,G,B and Alpha values"<< std::endl;
260 meshColorR = vectCol[0];
261 meshColorG = vectCol[1];
262 meshColorB = vectCol[2];
263 meshColorA = vectCol[3];
264 if(vectCol.size() == 8){
265 meshColorRLine = vectCol[4];
266 meshColorGLine = vectCol[5];
267 meshColorBLine = vectCol[6];
268 meshColorALine = vectCol[7];
273 if(vm.count(
"customColorSDP")){
274 std::vector<unsigned int > vectCol = vm[
"customColorSDP"].as<std::vector<unsigned int> >();
275 if(vectCol.size()!=4){
276 trace.error() <<
"colors specification should contain R,G,B and Alpha values"<< std::endl;
278 sdpColorR = vectCol[0];
279 sdpColorG = vectCol[1];
280 sdpColorB = vectCol[2];
281 sdpColorA = vectCol[3];
286 QApplication application(argc,argv);
287 CustomViewer3D viewer;
288 viewer.mySaveSnap = vm.count(
"doSnapShotAndExit");
289 if(vm.count(
"doSnapShotAndExit")){
290 viewer.setSnapshotFileName(QString(vm[
"doSnapShotAndExit"].as<std::string>().c_str()));
292 std::stringstream title;
293 title <<
"Simple Mesh Viewer: " << inputFilenameVect[0];
294 viewer.setWindowTitle(title.str().c_str());
296 viewer.myGLLineMinWidth = lineWidth;
297 viewer.setGLScale(sx, sy, sz);
298 bool invertNormal= vm.count(
"invertNormal");
301 double ballRadius = vm[
"SDPradius"].as<
double>();
303 trace.info() <<
"Importing mesh... ";
305 std::vector<Mesh<DGtal::Z3i::RealPoint> > vectMesh;
306 for(
unsigned int i = 0; i< inputFilenameVect.size(); i++){
307 Mesh<DGtal::Z3i::RealPoint> aMesh(!vm.count(
"customColorMesh"));
308 aMesh << inputFilenameVect[i];
309 vectMesh.push_back(aMesh);
313 bool import = vectMesh.size()==inputFilenameVect.size();
315 trace.info() <<
"File import failed. " << std::endl;
319 trace.info() <<
"[done]. "<< std::endl;
320 if(vm.count(
"displaySDP")){
321 std::string filenameSDP = vm[
"displaySDP"].as<std::string>();
322 vector<Z3i::RealPoint> vectPoints;
323 vectPoints = PointListReader<Z3i::RealPoint>::getPointsFromFile(filenameSDP);
324 viewer << CustomColors3D(Color(sdpColorR, sdpColorG, sdpColorB, sdpColorA),
325 Color(sdpColorR, sdpColorG, sdpColorB, sdpColorA));
326 for(
unsigned int i=0;i< vectPoints.size(); i++){
327 viewer.addBall(vectPoints.at(i), ballRadius);
331 for(
unsigned int i=0; i<vectMesh.size(); i++){
332 vectMesh[i].invertVertexFaceOrder();
336 viewer << CustomColors3D(Color(meshColorRLine, meshColorGLine, meshColorBLine, meshColorALine),
337 Color(meshColorR, meshColorG, meshColorB, meshColorA));
338 for(
unsigned int i=0; i<vectMesh.size(); i++){
339 viewer << vectMesh[i];
342 if(vm.count(
"drawVertex")){
343 for(
unsigned int i=0; i<vectMesh.size(); i++){
344 for( Mesh<DGtal::Z3i::RealPoint>::VertexStorage::const_iterator it = vectMesh[i].vertexBegin();
345 it!=vectMesh[i].vertexEnd(); ++it){
346 DGtal::Z3i::Point pt;
347 pt[0]=(*it)[0]; pt[1]=(*it)[1]; pt[2]=(*it)[2];
354 if (displayVectorField) {
355 std::vector<unsigned int > vectFieldIndices1 = {vectFieldIndices[0],vectFieldIndices[1], vectFieldIndices[2]};
356 std::vector<unsigned int > vectFieldIndices2 = {vectFieldIndices[3],vectFieldIndices[4], vectFieldIndices[5]};
358 std::vector<DGtal::Z3i::RealPoint> vectPt1 = PointListReader<DGtal::Z3i::RealPoint>::getPointsFromFile(vm[
"displayVectorField"].as<std::string>(), vectFieldIndices1);
359 std::vector<DGtal::Z3i::RealPoint> vectPt2 = PointListReader<DGtal::Z3i::RealPoint>::getPointsFromFile(vm[
"displayVectorField"].as<std::string>(), vectFieldIndices2);
360 viewer.createNewLineList();
361 for (
unsigned int i = 0; i < vectPt1.size(); i++) {
363 viewer.setLineColor(vFieldLineColor);
364 viewer.addLine(vectPt1[i], vectPt2[i]);
367 unsigned int nbVertex = 0;
368 unsigned int nbFaces = 0;
369 for(
auto const &m: vectMesh)
371 nbVertex += m.nbVertex();
372 nbFaces +=m.nbFaces();
375 ss <<
"# faces: " << std::fixed << nbFaces <<
" #vertex: " << nbVertex;
376 viewer.myInfoDisplay = ss.str();
377 viewer << CustomViewer3D::updateDisplay;
378 if(vm.count(
"doSnapShotAndExit")){
380 if(!viewer.restoreStateFromFile())
384 std::string name = vm[
"doSnapShotAndExit"].as<std::string>();
385 std::string extension = name.substr(name.find_last_of(
".") + 1);
386 std::string basename = name.substr(0, name.find_last_of(
"."));
387 for(
int i=0; i< viewer.snapshotCounter()-1; i++){
389 s << basename <<
"-"<< setfill(
'0') << setw(4)<< i <<
"." << extension;
390 trace.info() <<
"erase temp file: " << s.str() << std::endl;
391 remove(s.str().c_str());
394 s << basename <<
"-"<< setfill(
'0') << setw(4)<< viewer.snapshotCounter()-1 <<
"." << extension;
395 rename(s.str().c_str(), name.c_str());
399 return application.exec();