[CC]Mesh文件保存

CC中有两个地方使用了文件保存,一个是MainWindow,另一个是ccCommandLineParser。

MainWindow的保存按钮关联的槽是doActionSaveFile()方法,实现了点云和Mesh的保存。

 void MainWindow::doActionSaveFile()
{
size_t selNum = m_selectedEntities.size();
if (selNum == )
return; ccHObject clouds("clouds");
ccHObject meshes("meshes");
ccHObject images("images");
ccHObject polylines("polylines");
ccHObject other("other");
ccHObject otherSerializable("serializable");
ccHObject::Container entitiesToDispatch;
entitiesToDispatch.insert(entitiesToDispatch.begin(),m_selectedEntities.begin(),m_selectedEntities.end());
ccHObject entitiesToSave;
while (!entitiesToDispatch.empty())
{
ccHObject* child = entitiesToDispatch.back();
entitiesToDispatch.pop_back(); if (child->isA(CC_TYPES::HIERARCHY_OBJECT))
{
for (unsigned j=; j<child->getChildrenNumber(); ++j)
entitiesToDispatch.push_back(child->getChild(j));
}
else
{
//we put the entity in the container corresponding to its type
ccHObject* dest = ;
if (child->isA(CC_TYPES::POINT_CLOUD))
dest = &clouds;
else if (child->isKindOf(CC_TYPES::MESH))
dest = &meshes;
else if (child->isKindOf(CC_TYPES::IMAGE))
dest = &images;
else if (child->isKindOf(CC_TYPES::POLY_LINE))
dest = &polylines;
else if (child->isSerializable())
dest = &otherSerializable;
else
dest = &other; assert(dest); //we don't want double insertions if the user has clicked both the father and child
if (!dest->find(child->getUniqueID()))
{
dest->addChild(child,ccHObject::DP_NONE);
entitiesToSave.addChild(child,ccHObject::DP_NONE);
}
}
} bool hasCloud = (clouds.getChildrenNumber() != );
bool hasMesh = (meshes.getChildrenNumber() != );
bool hasImages = (images.getChildrenNumber() != );
bool hasPolylines = (polylines.getChildrenNumber() != );
bool hasSerializable = (otherSerializable.getChildrenNumber() != );
bool hasOther = (other.getChildrenNumber() != ); int stdSaveTypes = static_cast<int>(hasCloud)
+ static_cast<int>(hasMesh)
+ static_cast<int>(hasImages)
+ static_cast<int>(hasPolylines)
+ static_cast<int>(hasSerializable);
if (stdSaveTypes == )
{
ccConsole::Error("Can't save selected entity(ies) this way!");
return;
} //we set up the right file filters, depending on the selected
//entities type (cloud, mesh, etc.).
QStringList fileFilters;
{
const FileIOFilter::FilterContainer& filters = FileIOFilter::GetFilters();
for (size_t i=; i<filters.size(); ++i)
{
bool atLeastOneExclusive = false; //current I/O filter
const FileIOFilter::Shared filter = filters[i]; //does this filter can export one or several clouds?
bool canExportClouds = true;
if (hasCloud)
{
bool isExclusive = true;
bool multiple = false;
canExportClouds = ( filter->canSave(CC_TYPES::POINT_CLOUD,multiple,isExclusive)
&& (multiple || clouds.getChildrenNumber() == ) );
atLeastOneExclusive |= isExclusive;
} //does this filter can export one or several meshes?
bool canExportMeshes = true;
if (hasMesh)
{
bool isExclusive = true;
bool multiple = false;
canExportMeshes = ( filter->canSave(CC_TYPES::MESH,multiple,isExclusive)
&& (multiple || meshes.getChildrenNumber() == ) );
atLeastOneExclusive |= isExclusive;
} //does this filter can export one or several polylines?
bool canExportPolylines = true;
if (hasPolylines)
{
bool isExclusive = true;
bool multiple = false;
canExportPolylines = ( filter->canSave(CC_TYPES::POLY_LINE,multiple,isExclusive)
&& (multiple || polylines.getChildrenNumber() == ) );
atLeastOneExclusive |= isExclusive;
} //does this filter can export one or several images?
bool canExportImages = true;
if (hasImages)
{
bool isExclusive = true;
bool multiple = false;
canExportImages = ( filter->canSave(CC_TYPES::IMAGE,multiple,isExclusive)
&& (multiple || images.getChildrenNumber() == ) );
atLeastOneExclusive |= isExclusive;
} //does this filter can export one or several other serializable entities?
bool canExportSerializables = true;
if (hasSerializable)
{
//check if all entities have the same type
{
CC_CLASS_ENUM firstClassID = otherSerializable.getChild()->getUniqueID();
for (unsigned j=; j<otherSerializable.getChildrenNumber(); ++j)
{
if (otherSerializable.getChild(j)->getUniqueID() != firstClassID)
{
//we add a virtual second 'stdSaveType' so as to properly handle exlusivity
++stdSaveTypes;
break;
}
}
} for (unsigned j=; j<otherSerializable.getChildrenNumber(); ++j)
{
ccHObject* child = otherSerializable.getChild(j);
bool isExclusive = true;
bool multiple = false;
canExportSerializables &= ( filter->canSave(child->getUniqueID(),multiple,isExclusive)
&& (multiple || otherSerializable.getChildrenNumber() == ) );
atLeastOneExclusive |= isExclusive;
}
} bool useThisFilter = canExportClouds
&& canExportMeshes
&& canExportImages
&& canExportPolylines
&& canExportSerializables
&& (!atLeastOneExclusive || stdSaveTypes == ); if (useThisFilter)
{
QStringList ff = filter->getFileFilters(false);
for (int j=; j<ff.size(); ++j)
fileFilters.append(ff[j]);
}
}
} //persistent settings
QSettings settings;
settings.beginGroup(ccPS::SaveFile()); //default filter
QString selectedFilter = fileFilters.first();
if (hasCloud)
selectedFilter = settings.value(ccPS::SelectedOutputFilterCloud(),selectedFilter).toString();
else if (hasMesh)
selectedFilter = settings.value(ccPS::SelectedOutputFilterMesh(), selectedFilter).toString();
else if (hasImages)
selectedFilter = settings.value(ccPS::SelectedOutputFilterImage(), selectedFilter).toString();
else if (hasPolylines)
selectedFilter = settings.value(ccPS::SelectedOutputFilterPoly(), selectedFilter).toString(); //default output path (+ filename)
QString currentPath = settings.value(ccPS::CurrentPath(),QApplication::applicationDirPath()).toString();
QString fullPathName = currentPath;
if (selNum == )
{
//hierarchy objects have generally as name: 'filename.ext (fullpath)'
//so we must only take the first part! (otherwise this type of name
//with a path inside perturbs the QFileDialog a lot ;))
QString defaultFileName(m_selectedEntities.front()->getName());
if (m_selectedEntities.front()->isA(CC_TYPES::HIERARCHY_OBJECT))
{
QStringList parts = defaultFileName.split(' ',QString::SkipEmptyParts);
if (parts.size() > )
defaultFileName = parts[];
} //we remove the extension
defaultFileName = QFileInfo(defaultFileName).baseName(); if (!IsValidFileName(defaultFileName))
{
ccLog::Warning("[I/O] First entity's name would make an invalid filename! Can't use it...");
defaultFileName = "project";
} fullPathName += QString("/") + defaultFileName;
} //ask the user for the output filename
QString selectedFilename = QFileDialog::getSaveFileName(this,
"Save file",
fullPathName,
fileFilters.join(s_fileFilterSeparator),
&selectedFilter); if (selectedFilename.isEmpty())
{
//process cancelled by the user
return;
} //ignored items
if (hasOther)
{
ccConsole::Warning("[I/O] The following selected entites won't be saved:");
for (unsigned i=; i<other.getChildrenNumber(); ++i)
ccConsole::Warning(QString("\t- %1s").arg(other.getChild(i)->getName()));
} CC_FILE_ERROR result = CC_FERR_NO_ERROR;
FileIOFilter::SaveParameters parameters;
{
parameters.alwaysDisplaySaveDialog = true;
parameters.parentWidget = this;
} //specific case: BIN format
if (selectedFilter == BinFilter::GetFileFilter())
{
if (selNum == )
{
result = FileIOFilter::SaveToFile(m_selectedEntities.front(),selectedFilename,parameters,selectedFilter);
}
else
{
//we'll regroup all selected entities in a temporary group
ccHObject tempContainer;
ConvertToGroup(m_selectedEntities,tempContainer,ccHObject::DP_NONE);
if (tempContainer.getChildrenNumber())
{
result = FileIOFilter::SaveToFile(&tempContainer,selectedFilename,parameters,selectedFilter);
}
else
{
ccLog::Warning("[I/O] None of the selected entities can be saved this way...");
result = CC_FERR_NO_SAVE;
}
}
}
else if (entitiesToSave.getChildrenNumber() != )
{
//ignored items
/*if (hasSerializable)
{
if (!hasOther)
ccConsole::Warning("[I/O] The following selected entites won't be saved:"); //display this warning only if not already done
for (unsigned i=0; i<otherSerializable.getChildrenNumber(); ++i)
ccConsole::Warning(QString("\t- %1").arg(otherSerializable.getChild(i)->getName()));
}
//*/ result = FileIOFilter::SaveToFile( entitiesToSave.getChildrenNumber() > ? &entitiesToSave : entitiesToSave.getChild(),
selectedFilename,
parameters,
selectedFilter);
} //update default filters
if (hasCloud)
settings.setValue(ccPS::SelectedOutputFilterCloud(),selectedFilter);
if (hasMesh)
settings.setValue(ccPS::SelectedOutputFilterMesh(), selectedFilter);
if (hasImages)
settings.setValue(ccPS::SelectedOutputFilterImage(),selectedFilter);
if (hasPolylines)
settings.setValue(ccPS::SelectedOutputFilterPoly(), selectedFilter); //we update current file path
currentPath = QFileInfo(selectedFilename).absolutePath();
settings.setValue(ccPS::CurrentPath(),currentPath);
settings.endGroup();
}

void MainWindow::doActionSaveFile()

再看看ccCommandLineParser的Parse方法:

 int ccCommandLineParser::Parse(int nargs, char** args)
{
if (!args || nargs < )
{
assert(false);
return EXIT_SUCCESS;
} //reset default behavior(s)
s_loadParameters.autoComputeNormals = false;
s_MeshExportFormat = s_CloudExportFormat = BinFilter::GetFileFilter();
s_MeshExportExt = s_CloudExportExt = BinFilter::GetDefaultExtension();
s_precision = ;
s_addTimestamp = true;
s_silentMode = false;
s_autoSaveMode = true; //load arguments
QStringList arguments;
{
for (int i=; i<nargs; ++i) //'i=1' because first argument is always program executable file!
arguments.push_back(QString(args[i]));
}
assert(!arguments.empty()); //specific command: silent mode (will prevent the console dialog from appearing!
if (IsCommand(arguments.front(),COMMAND_SILENT_MODE))
{
arguments.pop_front();
s_silentMode = true;
} QDialog consoleDlg;
if (!s_silentMode)
{
//show console
Ui_commandLineDlg commandLineDlg;
commandLineDlg.setupUi(&consoleDlg);
consoleDlg.show();
ccConsole::Init(commandLineDlg.consoleWidget, &consoleDlg);
s_loadParameters.parentWidget = &consoleDlg;
} //parse input
int result = ccCommandLineParser().parse(arguments,&consoleDlg); if (!s_silentMode)
{
if (result == EXIT_SUCCESS)
QMessageBox::information(&consoleDlg,"Processed finished","Job done");
else
QMessageBox::warning(&consoleDlg,"Processed finished","An error occurred! Check console");
} ccConsole::ReleaseInstance(); return result;
}

int ccCommandLineParser::Parse(int nargs, char** args)

该方法被main函数调用。

 //主程序入口,十分重要
int main(int argc, char **argv)
{
//QT initialiation
qccApplication app(argc, argv); //Force 'english' local so as to get a consistent behavior everywhere
QLocale::setDefault(QLocale::English); #ifdef Q_OS_LINUX
// we reset the numeric locale. As suggested in documetation
// see http://qt-project.org/doc/qt-5/qcoreapplication.html#locale-settings
// Basically - from doc: - "On Unix/Linux Qt is configured to use the system locale settings by default.
// This can cause a conflict when using POSIX functions, for instance,
// when converting between data types such as floats and strings"
setlocale(LC_NUMERIC,"C");
#endif #ifdef USE_VLD
VLDEnable();
#endif //splash screen
QSplashScreen* splash = ;
QTime splashStartTime; //Command line mode?
bool commandLine = (argc > && argv[][] == '-'); //specific case: translation file selection
int lastArgumentIndex = ;
QTranslator translator;
if (commandLine && QString(argv[]).toUpper() == "-LANG")
{
QString langFilename = QString(argv[]); //Load translation file
if (translator.load(langFilename, QCoreApplication::applicationDirPath()))
{
qApp->installTranslator(&translator);
}
else
{
QMessageBox::warning(, QObject::tr("Translation"), QObject::tr("Failed to load language file '%1'").arg(langFilename));
}
commandLine = false;
lastArgumentIndex = ;
} //command line mode
if (!commandLine)
{
//OpenGL?
if (!QGLFormat::hasOpenGL())
{
QMessageBox::critical(, "Error", "This application needs OpenGL to run!");
return EXIT_FAILURE;
} //splash screen
splashStartTime.start();
QPixmap pixmap(QString::fromUtf8(":/CC/images/imLogoV2Qt.png"));
splash = new QSplashScreen(pixmap,Qt::WindowStaysOnTopHint);
splash->show();
QApplication::processEvents();
} //global structures initialization
ccTimer::Init();
FileIOFilter::InitInternalFilters(); //load all known I/O filters (plugins will come later!)
ccNormalVectors::GetUniqueInstance(); //force pre-computed normals array initialization
ccColorScalesManager::GetUniqueInstance(); //force pre-computed color tables initialization int result = ; if (commandLine)
{
//command line processing (no GUI)
result = ccCommandLineParser::Parse(argc,argv);
}
else
{
//main window init.
MainWindow* mainWindow = MainWindow::TheInstance();
if (!mainWindow)
{
QMessageBox::critical(, "Error", "Failed to initialize the main application window?!");
return EXIT_FAILURE;
}
mainWindow->show();
QApplication::processEvents(); if (argc > lastArgumentIndex)
{
if (splash)
splash->close(); //any additional argument is assumed to be a filename --> we try to load it/them
QStringList filenames;
for (int i = lastArgumentIndex; i<argc; ++i)
filenames << QString(argv[i]); mainWindow->addToDB(filenames);
} if (splash)
{
//we want the splash screen to be visible a minimum amount of time (1000 ms.)
while (splashStartTime.elapsed() < )
{
splash->raise();
QApplication::processEvents(); //to let the system breath!
} splash->close();
QApplication::processEvents(); delete splash;
splash = ;
} //let's rock!
try
{
result = app.exec();
}
catch(...)
{
QMessageBox::warning(, "CC crashed!","Hum, it seems that CC has crashed... Sorry about that :)");
}
} //release global structures
MainWindow::DestroyInstance();
FileIOFilter::UnregisterAll(); #ifdef CC_TRACK_ALIVE_SHARED_OBJECTS
//for debug purposes
unsigned alive = CCShareable::GetAliveCount();
if (alive > )
{
printf("Error: some shared objects (%u) have not been released on program end!",alive);
system("PAUSE");
}
#endif return result;
}

int main(int argc, char **argv)

两处最终都落实到FileIOFilter::SaveToFile()方法的调用。

 //保存文件
CC_FILE_ERROR FileIOFilter::SaveToFile( ccHObject* entities,
const QString& filename,
SaveParameters& parameters,
QString fileFilter)
{
if (fileFilter.isEmpty())
return CC_FERR_BAD_ARGUMENT;
//获取对应的文件格式,存储器
Shared filter = GetFilter(fileFilter,false);
if (!filter)
{
ccLog::Error(QString("[Load] Internal error: no filter corresponds to filter '%1'").arg(fileFilter));
return CC_FERR_UNKNOWN_FILE;
} return SaveToFile(entities, filename, parameters, filter);
} CC_FILE_ERROR FileIOFilter::SaveToFile( ccHObject* entities,
const QString& filename,
SaveParameters& parameters,
Shared filter)
{
if (!entities || filename.isEmpty() || !filter)
return CC_FERR_BAD_ARGUMENT; //if the file name has no extension, we had a default one!
QString completeFileName(filename);
if (QFileInfo(filename).suffix().isEmpty())
completeFileName += QString(".%1").arg(filter->getDefaultExtension()); CC_FILE_ERROR result = CC_FERR_NO_ERROR;
try
{
result = filter->saveToFile(entities, completeFileName, parameters);
}
catch(...)
{
ccLog::Warning(QString("[I/O] CC has caught an unhandled exception while saving file '%1'").arg(filename));
result = CC_FERR_CONSOLE_ERROR;
} if (result == CC_FERR_NO_ERROR)
{
ccLog::Print(QString("[I/O] File '%1' saved successfully").arg(filename));
}
else
{
DisplayErrorMessage(result,"saving",filename);
} return result;
}

FileIOFilter::SaveToFile

获取需要的文件存储器。

 //获取存取器
FileIOFilter::Shared FileIOFilter::GetFilter(QString fileFilter, bool onImport)
{
if (!fileFilter.isEmpty())
{
for (FilterContainer::const_iterator it=s_ioFilters.begin(); it!=s_ioFilters.end(); ++it)
{
QStringList otherFilters = (*it)->getFileFilters(onImport);
if (otherFilters.contains(fileFilter))
return *it;
}
} return Shared();
}

FileIOFilter::Shared FileIOFilter::GetFilter

这里重点研究一下obj文件的保存。

上一篇:SQL 建表 插数据


下一篇:ERROR 000732:Output Geodatabase:Dataset Database Connections\Connection to localhost.sde\SDE.Dataset does not exist or is not supported