From 4b20052932bde9921223b4cf7d54078454366112 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Mon, 16 Dec 2019 12:01:53 -0500 Subject: [PATCH 001/121] Added tag stable-2019-12 for changeset 14518462105b --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 1e71dab5f..5df26c98f 100644 --- a/.hgtags +++ b/.hgtags @@ -20,3 +20,4 @@ b638b3820fea390f8e15a87756e0ca51bf8ec678 simdissdk-1.10 b905137c5b97d337b93919770ebbb4f533780220 simdissdk-1.10 4174e5d213265d708442b7444a82e2e679ef5061 simdis10.0_SR6 4174e5d213265d708442b7444a82e2e679ef5061 simdissdk-1.11 +14518462105ba7e265e3e6bb970c127656302861 stable-2019-12 From 2d266ead1df16770ad368ad0a0d5f6aa90925d54 Mon Sep 17 00:00:00 2001 From: SIMDIS Build Machine Date: Tue, 17 Dec 2019 06:19:03 -0500 Subject: [PATCH 002/121] DEV: Fixed false positive on non-compiled files in Unity build by skipping those items in unity build. --- SDK/simCore/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SDK/simCore/CMakeLists.txt b/SDK/simCore/CMakeLists.txt index a8966fcbe..44d9bedfa 100644 --- a/SDK/simCore/CMakeLists.txt +++ b/SDK/simCore/CMakeLists.txt @@ -168,6 +168,11 @@ source_group("" FILES ${CORE_ALL_HEADER}) # ---------------------------------------------------------------------- +# Avoid false MSVC 2017/2019 MSB8027 warning from Unity build on Utils.cpp and Angle.cpp +set_source_files_properties(${CORE_STRING_SRC}Angle.cpp ${CORE_STRING_SRC}Utils.cpp + ${CORE_CALC_SRC}Angle.cpp ${CORE_TIME_SRC}Utils.cpp + PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON) + set(CORE_PROJECT_FILES ${CORE_COMMON_HEADERS} ${CORE_COMMON_SOURCES} ${CORE_CALC_HEADERS} ${CORE_CALC_SOURCES} From 44e2a33b197890c25f99d14703dca4f54b2259c1 Mon Sep 17 00:00:00 2001 From: SIMDIS Build Machine Date: Tue, 17 Dec 2019 07:37:08 -0500 Subject: [PATCH 003/121] DEV: Fixed another false positive for Unity build. No review. --- SDK/simVis/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SDK/simVis/CMakeLists.txt b/SDK/simVis/CMakeLists.txt index a66118f21..c8c9be815 100644 --- a/SDK/simVis/CMakeLists.txt +++ b/SDK/simVis/CMakeLists.txt @@ -365,6 +365,10 @@ set(VIS_SOURCES ${VIS_SOURCES_CORE} ${VIS_SOURCES_RFPROP} ${VIS_SOURCES_GOG} ${V # ---------------------------------------------------------------------- +# Avoid false MSVC 2017/2019 MSB8027 warning from Unity build on Utils.cpp and Angle.cpp +set_source_files_properties(${VIS_SRC}Utils.cpp ${VIS_SRC}GOG/Utils.cpp + PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON) + set(VIS_PROJECT_FILES ${VIS_HEADERS} ${VIS_SOURCES} ${VIS_ALL_HEADER} ) From f47d7b026e3d4e828267dfbadb96cb0b069c7ece Mon Sep 17 00:00:00 2001 From: Colin McNulty Date: Tue, 17 Dec 2019 14:41:29 -0500 Subject: [PATCH 004/121] DEV: Rename CategoryTreeModel2 and CategoryFilterWidget2 to remove the number. Addresses SIM-10800. Review 20153 --- .../CategoryFilterTest.cpp | 10 +- Plugins/QtDesignerWidgets/CMakeLists.txt | 2 - .../CategoryFilterWidget2Plugin.cpp | 40 +- .../CategoryFilterWidget2Plugin.h | 10 +- .../CategoryFilterWidgetPlugin.cpp | 123 ---- .../CategoryFilterWidgetPlugin.h | 61 -- .../simQtDesignerPlugins.cpp | 4 - SDK/simQt/CMakeLists.txt | 4 - SDK/simQt/CategoryFilterWidget.cpp | 212 ------ SDK/simQt/CategoryFilterWidget.h | 121 ---- SDK/simQt/CategoryTreeModel.cpp | 671 ------------------ SDK/simQt/CategoryTreeModel.h | 170 ----- SDK/simQt/CategoryTreeModel2.cpp | 249 +++---- SDK/simQt/CategoryTreeModel2.h | 41 +- SDK/simQt/EntityCategoryFilter.cpp | 26 +- SDK/simQt/EntityCategoryFilter.h | 18 +- 16 files changed, 164 insertions(+), 1598 deletions(-) delete mode 100644 Plugins/QtDesignerWidgets/CategoryFilterWidgetPlugin.cpp delete mode 100644 Plugins/QtDesignerWidgets/CategoryFilterWidgetPlugin.h delete mode 100644 SDK/simQt/CategoryFilterWidget.cpp delete mode 100644 SDK/simQt/CategoryFilterWidget.h delete mode 100644 SDK/simQt/CategoryTreeModel.cpp delete mode 100644 SDK/simQt/CategoryTreeModel.h diff --git a/Examples/QtCategoryFilterTest/CategoryFilterTest.cpp b/Examples/QtCategoryFilterTest/CategoryFilterTest.cpp index 1bfbea565..0c8d960de 100644 --- a/Examples/QtCategoryFilterTest/CategoryFilterTest.cpp +++ b/Examples/QtCategoryFilterTest/CategoryFilterTest.cpp @@ -47,12 +47,12 @@ MainWindow::MainWindow(simData::DataStore* dataStore, QWidget *parent) connect(ui_->togglePushButton, SIGNAL(clicked()), this, SLOT(toggleState_())); // Configure the new Category Filter Widget - ui_->categoryFilterWidget2->setDataStore(dataStore); - connect(ui_->categoryFilterWidget2, SIGNAL(filterChanged(simData::CategoryFilter)), + ui_->categoryFilterWidget->setDataStore(dataStore); + connect(ui_->categoryFilterWidget, SIGNAL(filterChanged(simData::CategoryFilter)), ui_->breadcrumbs, SLOT(setFilter(simData::CategoryFilter))); connect(ui_->breadcrumbs, SIGNAL(filterEdited(simData::CategoryFilter)), - ui_->categoryFilterWidget2, SLOT(setFilter(simData::CategoryFilter))); - connect(ui_->categoryFilterWidget2, SIGNAL(filterChanged(simData::CategoryFilter)), + ui_->categoryFilterWidget, SLOT(setFilter(simData::CategoryFilter))); + connect(ui_->categoryFilterWidget, SIGNAL(filterChanged(simData::CategoryFilter)), this, SLOT(categoryFilterChanged_(simData::CategoryFilter))); connect(ui_->breadcrumbs, SIGNAL(filterEdited(simData::CategoryFilter)), this, SLOT(categoryFilterChanged_(simData::CategoryFilter))); @@ -110,7 +110,7 @@ void MainWindow::toggleState_() { simData::CategoryFilter* filter = new simData::CategoryFilter(dataStore_, true); filter->updateAll(state_); - ui_->categoryFilterWidget2->setFilter(*filter); + ui_->categoryFilterWidget->setFilter(*filter); delete filter; state_ = !state_; } diff --git a/Plugins/QtDesignerWidgets/CMakeLists.txt b/Plugins/QtDesignerWidgets/CMakeLists.txt index 538d67a9c..35f6f3e69 100644 --- a/Plugins/QtDesignerWidgets/CMakeLists.txt +++ b/Plugins/QtDesignerWidgets/CMakeLists.txt @@ -8,7 +8,6 @@ project(PLUGIN_SIMQT_DESIGNER_PLUGINS) set(PROJ_HEADERS simQtDesignerPlugins.h CategoryDataBreadcrumbsPlugin.h - CategoryFilterWidgetPlugin.h CategoryFilterWidget2Plugin.h ColorButtonPlugin.h ColorWidgetPlugin.h @@ -31,7 +30,6 @@ set(PROJ_HEADERS # .cpp files set(PROJ_SOURCES CategoryDataBreadcrumbsPlugin.cpp - CategoryFilterWidgetPlugin.cpp CategoryFilterWidget2Plugin.cpp ColorButtonPlugin.cpp ColorWidgetPlugin.cpp diff --git a/Plugins/QtDesignerWidgets/CategoryFilterWidget2Plugin.cpp b/Plugins/QtDesignerWidgets/CategoryFilterWidget2Plugin.cpp index d1b1d02eb..f37e86955 100644 --- a/Plugins/QtDesignerWidgets/CategoryFilterWidget2Plugin.cpp +++ b/Plugins/QtDesignerWidgets/CategoryFilterWidget2Plugin.cpp @@ -26,33 +26,33 @@ #include "simQt/CategoryTreeModel2.h" #include "CategoryFilterWidget2Plugin.h" -CategoryFilterWidget2Plugin::CategoryFilterWidget2Plugin(QObject *parent) +CategoryFilterWidgetPlugin::CategoryFilterWidgetPlugin(QObject *parent) : QObject(parent), dataStore_(NULL) { } -CategoryFilterWidget2Plugin::~CategoryFilterWidget2Plugin() +CategoryFilterWidgetPlugin::~CategoryFilterWidgetPlugin() { delete dataStore_; } -void CategoryFilterWidget2Plugin::initialize(QDesignerFormEditorInterface *) +void CategoryFilterWidgetPlugin::initialize(QDesignerFormEditorInterface *) { if (dataStore_) return; dataStore_ = new simData::MemoryDataStore; - CategoryFilterWidget2Plugin::createDefaultCategories(*dataStore_); + CategoryFilterWidgetPlugin::createDefaultCategories(*dataStore_); } -bool CategoryFilterWidget2Plugin::isInitialized() const +bool CategoryFilterWidgetPlugin::isInitialized() const { return dataStore_ != NULL; } -QWidget *CategoryFilterWidget2Plugin::createWidget(QWidget *parent) +QWidget *CategoryFilterWidgetPlugin::createWidget(QWidget *parent) { - simQt::CategoryFilterWidget2* rv = new simQt::CategoryFilterWidget2(parent); + simQt::CategoryFilterWidget* rv = new simQt::CategoryFilterWidget(parent); // Create the data store, adding default categories initialize(NULL); rv->setDataStore(dataStore_); @@ -74,51 +74,51 @@ QWidget *CategoryFilterWidget2Plugin::createWidget(QWidget *parent) return rv; } -QString CategoryFilterWidget2Plugin::name() const +QString CategoryFilterWidgetPlugin::name() const { - return "simQt::CategoryFilterWidget2"; + return "simQt::CategoryFilterWidget"; } -QString CategoryFilterWidget2Plugin::group() const +QString CategoryFilterWidgetPlugin::group() const { return "simQt"; } -QIcon CategoryFilterWidget2Plugin::icon() const +QIcon CategoryFilterWidgetPlugin::icon() const { return QIcon(":/SDKPlugins/images/Categorize.png"); } -QString CategoryFilterWidget2Plugin::toolTip() const +QString CategoryFilterWidgetPlugin::toolTip() const { return "Filter entities by category"; } -QString CategoryFilterWidget2Plugin::whatsThis() const +QString CategoryFilterWidgetPlugin::whatsThis() const { return toolTip(); } -bool CategoryFilterWidget2Plugin::isContainer() const +bool CategoryFilterWidgetPlugin::isContainer() const { return false; } -QString CategoryFilterWidget2Plugin::domXml() const +QString CategoryFilterWidgetPlugin::domXml() const { return - "" - "\n" + "" + "\n" "\n" ""; } -QString CategoryFilterWidget2Plugin::includeFile() const +QString CategoryFilterWidgetPlugin::includeFile() const { - return "simQt/CategoryTreeModel2.h"; + return "simQt/CategoryTreeModel.h"; } -void CategoryFilterWidget2Plugin::createDefaultCategories(simData::DataStore& dataStore) +void CategoryFilterWidgetPlugin::createDefaultCategories(simData::DataStore& dataStore) { // Add some useful category names for display purposes simData::CategoryNameManager& nameManager = dataStore.categoryNameManager(); diff --git a/Plugins/QtDesignerWidgets/CategoryFilterWidget2Plugin.h b/Plugins/QtDesignerWidgets/CategoryFilterWidget2Plugin.h index b017f7a20..e8c79d617 100644 --- a/Plugins/QtDesignerWidgets/CategoryFilterWidget2Plugin.h +++ b/Plugins/QtDesignerWidgets/CategoryFilterWidget2Plugin.h @@ -19,22 +19,22 @@ * disclose, or release this software. * */ -#ifndef CATEGORY_FILTER_WIDGET2_PLUGIN_H -#define CATEGORY_FILTER_WIDGET2_PLUGIN_H +#ifndef CATEGORY_FILTER_WIDGET_PLUGIN_H +#define CATEGORY_FILTER_WIDGET_PLUGIN_H #include namespace simData { class DataStore; } // Wrapper class for the CategoryFilterWidget2 to provide QDesignerCustomWidgetInterface -class CategoryFilterWidget2Plugin : public QObject, public QDesignerCustomWidgetInterface +class CategoryFilterWidgetPlugin : public QObject, public QDesignerCustomWidgetInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) public: - explicit CategoryFilterWidget2Plugin(QObject *parent = 0); - virtual ~CategoryFilterWidget2Plugin(); + explicit CategoryFilterWidgetPlugin(QObject *parent = 0); + virtual ~CategoryFilterWidgetPlugin(); bool isContainer() const; bool isInitialized() const; diff --git a/Plugins/QtDesignerWidgets/CategoryFilterWidgetPlugin.cpp b/Plugins/QtDesignerWidgets/CategoryFilterWidgetPlugin.cpp deleted file mode 100644 index 2aad88b5e..000000000 --- a/Plugins/QtDesignerWidgets/CategoryFilterWidgetPlugin.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ -#ifdef USE_DEPRECATED_SIMDISSDK_API - -#include -#include "simData/CategoryData/CategoryFilter.h" -#include "simData/MemoryDataStore.h" -#include "simQt/CategoryFilterWidget.h" -#include "CategoryFilterWidget2Plugin.h" -#include "CategoryFilterWidgetPlugin.h" - -CategoryFilterWidgetPlugin::CategoryFilterWidgetPlugin(QObject *parent) - : QObject(parent), - dataStore_(NULL) -{ -} - -CategoryFilterWidgetPlugin::~CategoryFilterWidgetPlugin() -{ - delete dataStore_; -} - -void CategoryFilterWidgetPlugin::initialize(QDesignerFormEditorInterface *) -{ - if (dataStore_) - return; - dataStore_ = new simData::MemoryDataStore; - CategoryFilterWidget2Plugin::createDefaultCategories(*dataStore_); -} - -bool CategoryFilterWidgetPlugin::isInitialized() const -{ - return dataStore_ != NULL; -} - -QWidget *CategoryFilterWidgetPlugin::createWidget(QWidget *parent) -{ - simQt::CategoryFilterWidget* rv = new simQt::CategoryFilterWidget(parent); - - // Create the data store, adding default categories - initialize(NULL); - rv->setProviders(dataStore_); - - // Create a filter for user to see - simData::CategoryNameManager& nameManager = dataStore_->categoryNameManager(); - simData::CategoryFilter filter(dataStore_); - - // Affinity: Friendly entities only - const int affinityName = nameManager.addCategoryName("Affinity"); - filter.setValue(affinityName, nameManager.addCategoryValue(affinityName, "Friendly"), true); - // Platform Type: Unlisted values on; ignore Ship and Submarine - const int platformTypeName = nameManager.addCategoryName("Platform Type"); - filter.setValue(platformTypeName, nameManager.addCategoryValue(platformTypeName, "Submarine"), false); - filter.setValue(platformTypeName, nameManager.addCategoryValue(platformTypeName, "Surface Ship"), false); - filter.setValue(platformTypeName, simData::CategoryNameManager::UNLISTED_CATEGORY_VALUE, true); - rv->setFilter(filter); - - return rv; -} - -QString CategoryFilterWidgetPlugin::name() const -{ - return "simQt::CategoryFilterWidget"; -} - -QString CategoryFilterWidgetPlugin::group() const -{ - return "simQt"; -} - -QIcon CategoryFilterWidgetPlugin::icon() const -{ - return QIcon(":/SDKPlugins/images/Categorize.png"); -} - -QString CategoryFilterWidgetPlugin::toolTip() const -{ - return "Filter entities by category"; -} - -QString CategoryFilterWidgetPlugin::whatsThis() const -{ - return toolTip(); -} - -bool CategoryFilterWidgetPlugin::isContainer() const -{ - return false; -} - -QString CategoryFilterWidgetPlugin::domXml() const -{ - return - "" - "\n" - "\n" - ""; -} - -QString CategoryFilterWidgetPlugin::includeFile() const -{ - return "simQt/CategoryFilterWidget.h"; -} -#endif // USE_DEPRECATED_SIMDISSDK_API diff --git a/Plugins/QtDesignerWidgets/CategoryFilterWidgetPlugin.h b/Plugins/QtDesignerWidgets/CategoryFilterWidgetPlugin.h deleted file mode 100644 index 060fec3bd..000000000 --- a/Plugins/QtDesignerWidgets/CategoryFilterWidgetPlugin.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ -#ifdef USE_DEPRECATED_SIMDISSDK_API - -#ifndef CATEGORY_FILTER_WIDGET_PLUGIN_H -#define CATEGORY_FILTER_WIDGET_PLUGIN_H - -#include - -namespace simData { class DataStore; } - -// Wrapper class for the FileSelectorWidget to provide QDesignerCustomWidgetInterface -class CategoryFilterWidgetPlugin : public QObject, public QDesignerCustomWidgetInterface -{ - Q_OBJECT - Q_INTERFACES(QDesignerCustomWidgetInterface) - -public: - explicit CategoryFilterWidgetPlugin(QObject *parent = 0); - virtual ~CategoryFilterWidgetPlugin(); - - bool isContainer() const; - bool isInitialized() const; - QIcon icon() const; - QString domXml() const; - QString group() const; - QString includeFile() const; - QString name() const; - QString toolTip() const; - QString whatsThis() const; - QWidget *createWidget(QWidget *parent); - void initialize(QDesignerFormEditorInterface *core); - - /** Creates a set of category names and values for testing/display purposes */ - static void createDefaultCategories(simData::DataStore& dataStore); - -private: - simData::DataStore* dataStore_; -}; - -#endif // CATEGORY_FILTER_WIDGET_PLUGIN_H -#endif // USE_DEPRECATED_SIMDISSDK_API diff --git a/Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp b/Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp index c6738aa18..9aee3fb1c 100644 --- a/Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp +++ b/Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp @@ -26,7 +26,6 @@ #endif #include "ColorWidgetPlugin.h" #include "CategoryDataBreadcrumbsPlugin.h" -#include "CategoryFilterWidgetPlugin.h" #include "CategoryFilterWidget2Plugin.h" #include "DataTableComboBoxPlugin.h" #include "DirectorySelectorWidgetPlugin.h" @@ -48,10 +47,7 @@ simQtDesignerPlugins::simQtDesignerPlugins(QObject* parent) : QObject(parent) { // Add all plug-in widgets here widgetFactories_.append(new CategoryDataBreadcrumbsPlugin(this)); -#ifdef USE_DEPRECATED_SIMDISSDK_API widgetFactories_.append(new CategoryFilterWidgetPlugin(this)); -#endif - widgetFactories_.append(new CategoryFilterWidget2Plugin(this)); widgetFactories_.append(new ColorButtonPlugin(this)); #ifdef HAVE_OSG widgetFactories_.append(new ColorGradientWidgetPlugin(this)); diff --git a/SDK/simQt/CMakeLists.txt b/SDK/simQt/CMakeLists.txt index f6c461ef0..39cf1b7ae 100644 --- a/SDK/simQt/CMakeLists.txt +++ b/SDK/simQt/CMakeLists.txt @@ -65,8 +65,6 @@ if(TARGET simData) list(APPEND SIMQT_HEADERS_TO_MOC ${SIMQT_INC}CategoryDataBreadcrumbs.h ${SIMQT_INC}CategoryFilterCounter.h - ${SIMQT_INC}CategoryFilterWidget.h - ${SIMQT_INC}CategoryTreeModel.h ${SIMQT_INC}CategoryTreeModel2.h ${SIMQT_INC}DataTableComboBox.h ${SIMQT_INC}DataTableModel.h @@ -187,8 +185,6 @@ if(TARGET simData) list(APPEND SIMQT_SOURCES ${SIMQT_SRC}CategoryDataBreadcrumbs.cpp ${SIMQT_SRC}CategoryFilterCounter.cpp - ${SIMQT_SRC}CategoryFilterWidget.cpp - ${SIMQT_SRC}CategoryTreeModel.cpp ${SIMQT_SRC}CategoryTreeModel2.cpp ${SIMQT_SRC}DataTableComboBox.cpp ${SIMQT_SRC}DataTableModel.cpp diff --git a/SDK/simQt/CategoryFilterWidget.cpp b/SDK/simQt/CategoryFilterWidget.cpp deleted file mode 100644 index a4669d998..000000000 --- a/SDK/simQt/CategoryFilterWidget.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ -#ifdef USE_DEPRECATED_SIMDISSDK_API - // this is deprecated; use simQt::CategoryFilterWidget2 found in CategoryTreeModel2.h - -#include -#include -#include -#include -#include -#include -#include "simData/CategoryData/CategoryNameManager.h" -#include "simData/CategoryData/CategoryFilter.h" -#include "simQt/SearchLineEdit.h" -#include "simQt/CategoryTreeModel.h" -#include "simQt/CategoryTreeModel2.h" -#include "simQt/CategoryFilterWidget.h" - -namespace simQt { - -/** Keep the indexes in the tree so it is not necessary to compare strings */ -static const int CategoryNameRole = Qt::UserRole + 0; -static const int CategoryValueRole = Qt::UserRole + 1; - -CategoryFilterWidget::CategoryFilterWidget(QWidget * parent) - : QWidget(parent), - categoryFilter_(NULL), - dataStore_(NULL), - collapseAction_(NULL), - expandAction_(NULL), - activeFiltering_(false) -{ - setWindowTitle("Category Data Filter:"); - setObjectName("CategoryFilterWidget"); - - treeModel_ = new simQt::CategoryTreeModel(this); - proxy_ = new CategoryProxyModel(); - proxy_->setSortRole(simQt::CategoryTreeModel::SortRole); - proxy_->setSourceModel(treeModel_); - - treeView_ = new QTreeView(); - treeView_->setObjectName("CategoryFilterTree"); - treeView_->setHeaderHidden(true); - treeView_->setRootIsDecorated(false); - treeView_->setSortingEnabled(true); - treeView_->sortByColumn(0, Qt::AscendingOrder); - treeView_->setModel(proxy_); - - collapseAction_ = new QAction(tr("Collapse Values"), this); - connect(collapseAction_, SIGNAL(triggered()), this, SLOT(collapseLeaves_())); - collapseAction_->setIcon(QIcon(":/simQt/images/Collapse.png")); - expandAction_ = new QAction(tr("Expand Values"), this); - connect(expandAction_, SIGNAL(triggered()), treeView_, SLOT(expandAll())); - expandAction_->setIcon(QIcon(":/simQt/images/Expand.png")); - treeView_->setContextMenuPolicy(Qt::ActionsContextMenu); - treeView_->addAction(collapseAction_); - treeView_->addAction(expandAction_); - - search_ = new SearchLineEdit(); - search_->setPlaceholderText(tr("Search Category Data")); - QHBoxLayout* searchLayout = new QHBoxLayout(); - searchLayout->addWidget(search_); - - QVBoxLayout *layout = new QVBoxLayout; - layout->setObjectName("CategoryFilterWidgetVBox"); - layout->setMargin(0); - layout->addItem(searchLayout); - layout->addWidget(treeView_); - setLayout(layout); - - connect(treeModel_, SIGNAL(categoryFilterChanged(simData::CategoryFilter)), this, SIGNAL(categoryFilterChanged(simData::CategoryFilter))); - connect(treeModel_, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(expandDueToModel_(QModelIndex, int, int))); - connect(proxy_, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(expandDueToProxy_(QModelIndex, int, int))); - connect(search_, SIGNAL(textChanged(QString)), this, SLOT(newFilterText_(QString))); - connect(search_, SIGNAL(textChanged(QString)), proxy_, SLOT(setFilterText(QString))); -} - -CategoryFilterWidget::~CategoryFilterWidget() -{ - delete treeView_; - treeView_ = NULL; - delete collapseAction_; - collapseAction_ = NULL; - delete expandAction_; - expandAction_ = NULL; - - delete proxy_; - proxy_ = NULL; - - delete treeModel_; - treeModel_ = NULL; - - delete categoryFilter_; - categoryFilter_ = NULL; -} - -void CategoryFilterWidget::setProviders(simData::DataStore* dataStore) -{ - treeModel_->setProviders(NULL, NULL); - delete categoryFilter_; - categoryFilter_ = NULL; - dataStore_ = dataStore; - if (dataStore_ == NULL) - return; - - categoryFilter_ = new simData::CategoryFilter(dataStore_, true); - - treeModel_->setProviders(dataStore_, categoryFilter_); - treeView_->expandAll(); -} - -void CategoryFilterWidget::setFilter(const simData::CategoryFilter& categoryFilter) -{ - treeModel_->setFilter(categoryFilter); -} - -void CategoryFilterWidget::collapseLeaves_() -{ - treeView_->clearSelection(); - treeView_->collapseAll(); - QModelIndex index = treeModel_->index(0, 0, QModelIndex()); - treeView_->expand(proxy_->mapFromSource(index)); -} - -void CategoryFilterWidget::newFilterText_(const QString& text) -{ - if (text.isEmpty()) - { - // Just remove the last character of a search so expand all to make everything visible - if (activeFiltering_) - treeView_->expandAll(); - - activeFiltering_ = false; - } - else - { - // Just started a search so expand all to make everything visible - if (!activeFiltering_) - treeView_->expandAll(); - - activeFiltering_ = true; - } -} - -void CategoryFilterWidget::expandDueToModel_(const QModelIndex& parentIndex, int to, int from) -{ - if (!activeFiltering_) - return; - - if (!parentIndex.isValid()) - return; - - bool isCategory = !parentIndex.parent().isValid(); - if (isCategory) - return; - - if (!treeView_->isExpanded(parentIndex)) - proxy_->resetFilter(); -} - -void CategoryFilterWidget::expandDueToProxy_(const QModelIndex& parentIndex, int to, int from) -{ - if (!parentIndex.isValid()) - return; - - bool isCategory = !parentIndex.parent().isValid(); - if (isCategory) - { - // check that category name parent (the 'All Categories' node) is expanded - QModelIndex index = treeModel_->index(0, 0, QModelIndex()); - if (!treeView_->isExpanded(index)) - treeView_->expand(proxy_->mapFromSource(index)); - - // The category names are the "to" to "from" and they just showed up, so expand them - for (int ii = to; ii <= from; ++ii) - { - QModelIndex catIndex = parentIndex.model()->index(ii, 0, parentIndex); - treeView_->expand(catIndex); - } - } - else - { - if (activeFiltering_) - { - // Adding a category value; make sure it is visible by expanding its parent - if (!treeView_->isExpanded(parentIndex)) - treeView_->expand(parentIndex); - } - } -} - -} -#endif diff --git a/SDK/simQt/CategoryFilterWidget.h b/SDK/simQt/CategoryFilterWidget.h deleted file mode 100644 index 65d1caecf..000000000 --- a/SDK/simQt/CategoryFilterWidget.h +++ /dev/null @@ -1,121 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ -#ifdef USE_DEPRECATED_SIMDISSDK_API - // this is deprecated; use simQt::CategoryFilterWidget2 found in CategoryTreeModel2.h - -#ifndef SIMQT_CATEGORY_FILTER_WIDGET_H -#define SIMQT_CATEGORY_FILTER_WIDGET_H - -#include -#include "simCore/Common/Common.h" -#include "simData/CategoryData/CategoryNameManager.h" - -class QLineEdit; -class QString; -class QTreeView; -class QTreeWidgetItem; -class QModelIndex; - -namespace simData { class CategoryFilter; class DataStore; } - -namespace simQt { - -class SearchLineEdit; -class CategoryTreeModel; -class CategoryProxyModel; - -/** -* Widget for displaying the Category Filter in a tree view with check boxes next to the names and values -* call setProviders with a reference to the DataStore, which allows the widget to query the DataStore for -* all possible categories to fill its tree, as well as to listen to the DataStore updates, which will -* adjust the tree. -*/ -class SDKQT_EXPORT CategoryFilterWidget : public QWidget -{ - Q_OBJECT; - -public: - /** Constructor */ - CategoryFilterWidget(QWidget * parent = 0); - - /** Destructor */ - virtual ~CategoryFilterWidget(); - - /** - * Set the reference to the data store, which will update the category tree based on changes to the data store - * @param dataStore - */ - void setProviders(simData::DataStore* dataStore); - - /** - * Returns the current state of all the check boxes in a CategoryFilter object - * @return CategoryFilter - */ - const simData::CategoryFilter& categoryFilter() const { return *categoryFilter_; } - -public slots: - /** - * Updates local categoryFilter and the check boxes on the tree from the categoryFilter supplied - * @param categoryFilter - */ - void setFilter(const simData::CategoryFilter& categoryFilter); - -signals: - /** Emitted whenever the underlying category filter changes */ - void categoryFilterChanged(const simData::CategoryFilter& categoryFilter); - -private slots: - /** Collapse the leaves of the tree */ - void collapseLeaves_(); - /** Expand the given index from the model if filtering */ - void expandDueToModel_(const QModelIndex& parentIndex, int to, int from); - /** Expand the given index from the proxy if filtering */ - void expandDueToProxy_(const QModelIndex& parentIndex, int to, int from); - /** Text for filtering */ - void newFilterText_(const QString& text); - -private: - /** Helper class for managing all the category information */ - simData::CategoryFilter* categoryFilter_; - /** The tree */ - QTreeView* treeView_; - /** Hold the category data */ - CategoryTreeModel* treeModel_; - /** Provides sorting and filtering */ - CategoryProxyModel* proxy_; - /** Category search text */ - SearchLineEdit* search_; - /** The data store */ - simData::DataStore* dataStore_; - /** Action to collapse the leaves in the tree widget */ - QAction* collapseAction_; - /** Action to expand all elements of the tree widget */ - QAction* expandAction_; - /** If true the category values are filtered */ - bool activeFiltering_; -}; - -} - - -#endif -#endif diff --git a/SDK/simQt/CategoryTreeModel.cpp b/SDK/simQt/CategoryTreeModel.cpp deleted file mode 100644 index c185f5e65..000000000 --- a/SDK/simQt/CategoryTreeModel.cpp +++ /dev/null @@ -1,671 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ -#ifdef USE_DEPRECATED_SIMDISSDK_API - // this is deprecated; use simQt::CategoryTreeModel2 -#include -#include "simData/DataStore.h" -#include "simData/DataStoreHelpers.h" -#include "simQt/CategoryTreeModel.h" - -namespace simQt { - -static const QString ALL_CATEGORIES = "All Categories"; - -/// Monitors for category data changes -class CategoryTreeModel::CategoryFilterListener : public simData::CategoryNameManager::Listener -{ -public: - /// Constructor - explicit CategoryFilterListener(CategoryTreeModel* parent) : parent_(parent) - { - } - - virtual ~CategoryFilterListener() - { - } - - /// Invoked when a new category is added - virtual void onAddCategory(int categoryIndex) - { - parent_->addCategoryName_(categoryIndex); - } - - /// Invoked when a new value is added to a category - virtual void onAddValue(int categoryIndex, int valueIndex) - { - parent_->addCategoryValue_(categoryIndex, valueIndex, true); - } - - /// Invoked when all data is cleared - virtual void onClear() - { - parent_->clear_(); - } - - /// Invoked when all listeners have received onClear() - virtual void doneClearing() - { - // noop - } - -private: - CategoryTreeModel* parent_; -}; - -//---------------------------------------------------------------------------- -CategoryTreeItem::CategoryTreeItem(const QString& text, const QString& sortText, int categoryIndex, CategoryTreeItem *parent) - : text_(text), - sortText_(sortText), - categoryIndex_(categoryIndex), - parentItem_(parent), - state_(Qt::Unchecked), - numCheckedChildren_(0) -{ -} - -CategoryTreeItem::~CategoryTreeItem() -{ - qDeleteAll(childItems_); -} - -QString CategoryTreeItem::text() const -{ - return text_; -} - -QString CategoryTreeItem::sortText() const -{ - return sortText_; -} - -int CategoryTreeItem::categoryIndex() const -{ - return categoryIndex_; -} - -Qt::CheckState CategoryTreeItem::state() const -{ - return state_; -} - -void CategoryTreeItem::setState(Qt::CheckState value) -{ - // don't bother to update if no change - if (state_ == value) - return; - state_ = value; - // let the parent know about our updated state - if (parentItem_ != NULL) - parentItem_->updateNumCheckedChildren_(value); -} - -Qt::CheckState CategoryTreeItem::childrenState() const -{ - // This isn't really a good state and there's no good answer if we have no children. Assert - // and the developer can determine if this IS a good state or not, and update appropriately. - assert(!childItems_.empty()); - if (childItems_.empty()) - return Qt::PartiallyChecked; - Qt::CheckState state = childItems_[0]->state(); - for (int k = 1; k < childItems_.count(); ++k) - { - if (state != childItems_[k]->state()) - return Qt::PartiallyChecked; - } - return state; -} - -void CategoryTreeItem::updateNumCheckedChildren_(Qt::CheckState value) -{ - // increment if a child has been checked - if (value == Qt::Checked) - { - // moving from unchecked to checked state, since one of our children is now checked - if (numCheckedChildren_ == 0) - setState(Qt::Checked); - ++numCheckedChildren_; - } - // decrement down to 0 if a child has been unchecked - else if (numCheckedChildren_ > 0) - { - --numCheckedChildren_; - // moving from checked to unchecked, since none of our children are now checked - if (numCheckedChildren_ == 0) - setState(Qt::Unchecked); - } -} - -void CategoryTreeItem::appendChild(CategoryTreeItem *item) -{ - childItems_.append(item); - // Only should updateNumCheckedChildren_() when we're checked. Unchecked does nothing - if (item->state() == Qt::Checked) - updateNumCheckedChildren_(Qt::Checked); -} - -void CategoryTreeItem::removeChild(CategoryTreeItem *item) -{ - const bool wasChecked = (item->state() == Qt::Checked); - childItems_.removeOne(item); - delete item; - // Only decrement if this one was previously checked - if (wasChecked) - updateNumCheckedChildren_(Qt::Unchecked); -} - -CategoryTreeItem* CategoryTreeItem::child(int row) -{ - return childItems_.value(row); -} - -int CategoryTreeItem::childCount() const -{ - return childItems_.count(); -} - -CategoryTreeItem* CategoryTreeItem::parent() -{ - return parentItem_; -} - -int CategoryTreeItem::row() const -{ - if (parentItem_) - return parentItem_->childItems_.indexOf(const_cast(this)); - - return 0; -} - -//----------------------------------------------------------------------------------------- - -CategoryTreeModel::CategoryTreeModel(QObject *parent, simData::DataStore* dataStore, simData::CategoryFilter* categoryFilter) - : QAbstractItemModel(parent), - rootItem_(NULL), - dataStore_(NULL), - categoryFilter_(NULL) -{ - // create observers/listeners - listenerPtr_ = simData::CategoryNameManager::ListenerPtr(new CategoryFilterListener(this)); - - // setting the data store will register our observer and listener - setProviders(dataStore, categoryFilter); -} - -CategoryTreeModel::~CategoryTreeModel() -{ - setProviders(NULL, NULL); - delete rootItem_; -} - -void CategoryTreeModel::setProviders(simData::DataStore* dataStore, simData::CategoryFilter* categoryFilter) -{ - if (dataStore == dataStore_) - return; - - // Remove the prefs observers on the data store - if (dataStore_) - dataStore_->categoryNameManager().removeListener(listenerPtr_); - - // Update the pointers - dataStore_ = dataStore; - categoryFilter_ = categoryFilter; - - // re-add the prefs observers - if (dataStore_) - dataStore->categoryNameManager().addListener(listenerPtr_); - - // fill the tree model - forceRefresh(); -} - -//nameIndex is a unique index representing the name, managed by the Category Name Manager. -CategoryTreeItem* CategoryTreeModel::findCategoryName_(int nameIndex) -{ - for (int ii = 0; ii < allCategoriesItem_->childCount(); ii++) - { - CategoryTreeItem* child = allCategoriesItem_->child(ii); - if (child->categoryIndex() == nameIndex) - return child; - } - - return NULL; -} - -//valueIndex is a unique index representing the value, managed by the Category Name Manager. -CategoryTreeItem* CategoryTreeModel::findCategoryValue_(CategoryTreeItem* parent, int valueIndex) -{ - if (parent == NULL) - return NULL; - - for (int ii = 0; ii < parent->childCount(); ii++) - { - CategoryTreeItem* child = parent->child(ii); - if (child->categoryIndex() == valueIndex) - return child; - } - - return NULL; -} - -void CategoryTreeModel::addCategoryName_(int nameIndex) -{ - // must call setProviders first - assert(categoryFilter_ != NULL); - - // Prevent duplication - if (findCategoryName_(nameIndex) != NULL) - return; - - // New category was added to the category name manager. Check to see if the category is present - // in the current filter (it probably isn't) and make sure we have each of those value checked - const simData::CategoryFilter::CategoryCheck& categoryCheck = categoryFilter_->getCategoryFilter(); - simData::CategoryFilter::CategoryCheck::const_iterator iter = categoryCheck.find(nameIndex); - assert(iter != categoryCheck.end()); - if (iter != categoryCheck.end()) - { - QString name = QString::fromStdString(dataStore_->categoryNameManager().nameIntToString(iter->first)); - CategoryTreeItem* catNameItem = new CategoryTreeItem(name, name, iter->first, allCategoriesItem_); - beginInsertRows(createIndex(allCategoriesItem_->row(), 0, allCategoriesItem_), allCategoriesItem_->childCount(), allCategoriesItem_->childCount()); - allCategoriesItem_->appendChild(catNameItem); - endInsertRows(); - for (simData::CategoryFilter::ValuesCheck::const_iterator valIter = iter->second.second.begin(); valIter != iter->second.second.end(); ++valIter) - addCategoryValue_(iter->first, valIter->first, false); - } -} - -void CategoryTreeModel::addCategoryValue_(int nameIndex, int valueIndex, bool rebuild) -{ - // Find Category Name in GUI tree - CategoryTreeItem* categoryName = findCategoryName_(nameIndex); - if (categoryName == NULL) - { - // Add Category name to GUI tree - addCategoryName_(nameIndex); - categoryName = findCategoryName_(nameIndex); - } - - // Prevent duplicates - if (findCategoryValue_(categoryName, valueIndex)) - { - // The CategoryTreeModel is out of sync - assert(false); - return; - } - - // A new value was added. Give it a valid checked or not checked state as appropriate based on - // the content of the category filter. - const simData::CategoryFilter::CategoryCheck& categoryCheck = categoryFilter_->getCategoryFilter(); - simData::CategoryFilter::CategoryCheck::const_iterator iter = categoryCheck.find(nameIndex); - assert(iter != categoryCheck.end()); - if (iter != categoryCheck.end()) - { - // Found category so look for value - simData::CategoryFilter::ValuesCheck::const_iterator valIter = iter->second.second.find(valueIndex); - assert(valIter != iter->second.second.end()); - if (valIter != iter->second.second.end()) - { - QString value = QString::fromStdString(dataStore_->categoryNameManager().valueIntToString(valIter->first)); - - CategoryTreeItem* catValItem = new CategoryTreeItem(value, valueSortName_(value), valIter->first, categoryName); - catValItem->setState(valIter->second ? Qt::Checked : Qt::Unchecked); - beginInsertRows(createIndex(categoryName->row(), 0, categoryName), categoryName->childCount(), categoryName->childCount()); - categoryName->appendChild(catValItem); - endInsertRows(); - } - } -} - -void CategoryTreeModel::clear_() -{ - // must call setProviders first - assert(categoryFilter_ != NULL); - buildTree_(); -} - -void CategoryTreeModel::forceRefresh() -{ - if (dataStore_ != NULL) - buildTree_(); -} - -int CategoryTreeModel::columnCount(const QModelIndex &parent) const -{ - return 1; -} - -QVariant CategoryTreeModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - if ((role == Qt::DisplayRole) && (index.column() == 0)) - { - CategoryTreeItem *item = static_cast(index.internalPointer()); - return item->text(); - } - - if ((role == CategoryTreeModel::SortRole) && (index.column() == 0)) - { - CategoryTreeItem *item = static_cast(index.internalPointer()); - return item->sortText(); - } - - if ((role == Qt::CheckStateRole) && (index.column() == 0)) - { - CategoryTreeItem *item = static_cast(index.internalPointer()); - return item->state(); - } - - if ((role == Qt::ToolTipRole) && (index.column() == 0)) - { - CategoryTreeItem *item = static_cast(index.internalPointer()); - if (item->childCount() > 0) - { - return QString(tr("# of Values: %1")).arg(item->childCount()); - } - } - - return QVariant(); -} - -int CategoryTreeModel::setState_(CategoryTreeItem* item, Qt::CheckState state) -{ - int rv = (item->state() == state) ? 0 : 1; - item->setState(state); - for (int ii = 0; ii < item->childCount(); ++ii) - rv += setState_(item->child(ii), state); - return rv; -} - -bool CategoryTreeModel::setData(const QModelIndex& index, const QVariant& value, int role) -{ - if ((index.column() == 0) && (role == Qt::CheckStateRole)) - { - CategoryTreeItem *item = static_cast(index.internalPointer()); - Qt::CheckState state = value.toBool() ? Qt::Checked : Qt::Unchecked; - if (setState_(item, state) > 0) - { - emit dataChanged(index, index); - // need to update the category filter - if (item->parent() == rootItem_) - categoryFilter_->updateAll(value.toBool()); - else if (item->parent() == allCategoriesItem_) - categoryFilter_->updateCategoryFilterName(item->categoryIndex(), value.toBool()); - else - categoryFilter_->updateCategoryFilterValue(item->parent()->categoryIndex(), item->categoryIndex(), value.toBool()); - emit(categoryFilterChanged(*categoryFilter_)); - } - return true; - } - return QAbstractItemModel::setData(index, value, role); -} - -Qt::ItemFlags CategoryTreeModel::flags(const QModelIndex& index) const -{ - if (!index.isValid()) - return Qt::NoItemFlags; - - if (index.column() == 0) - return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable; - - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; -} - -QModelIndex CategoryTreeModel::index(int row, int column, const QModelIndex &parent) const -{ - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - CategoryTreeItem *parentItem; - - if (!parent.isValid()) - parentItem = rootItem_; - else - parentItem = static_cast(parent.internalPointer()); - - CategoryTreeItem *childItem = parentItem->child(row); - if (childItem) - return createIndex(row, column, childItem); - - return QModelIndex(); -} - -QString CategoryTreeModel::text(const QModelIndex &index) const -{ - if (!index.isValid()) - return 0; - - CategoryTreeItem *childItem = static_cast(index.internalPointer()); - if (childItem == NULL) - return ""; - - return childItem->text(); -} - -QModelIndex CategoryTreeModel::parent(const QModelIndex &index) const -{ - if (!index.isValid()) - return QModelIndex(); - - CategoryTreeItem *childItem = static_cast(index.internalPointer()); - if (childItem == NULL) - return QModelIndex(); - - CategoryTreeItem *parentItem = childItem->parent(); - - if (parentItem == NULL) - return QModelIndex(); - - if (parentItem == rootItem_) - return QModelIndex(); - - return createIndex(parentItem->row(), 0, parentItem); -} - -int CategoryTreeModel::rowCount(const QModelIndex &parent) const -{ - if (rootItem_ == NULL) - return 0; - - CategoryTreeItem *parentItem; - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) - parentItem = rootItem_; - else - parentItem = static_cast(parent.internalPointer()); - - return parentItem->childCount(); -} - -void CategoryTreeModel::buildTree_() -{ - beginResetModel(); - delete rootItem_; - rootItem_ = new CategoryTreeItem("Root", "Root", 0, NULL); - allCategoriesItem_ = new CategoryTreeItem(ALL_CATEGORIES, ALL_CATEGORIES, -1, rootItem_); - rootItem_->appendChild(allCategoriesItem_); - - if (categoryFilter_ != NULL) - { - const simData::CategoryFilter::CategoryCheck& categoryCheck = categoryFilter_->getCategoryFilter(); - for (simData::CategoryFilter::CategoryCheck::const_iterator iter = categoryCheck.begin(); iter != categoryCheck.end(); ++iter) - { - QString name = QString::fromStdString(dataStore_->categoryNameManager().nameIntToString(iter->first)); - CategoryTreeItem* catNameItem = new CategoryTreeItem(name, name, iter->first, allCategoriesItem_); - allCategoriesItem_->appendChild(catNameItem); - addAllValues_(iter->second.second, catNameItem, dataStore_->categoryNameManager()); - } - } - - endResetModel(); -} - -void CategoryTreeModel::addAllValues_(const simData::CategoryFilter::ValuesCheck& iter, CategoryTreeItem* nameItem, const simData::CategoryNameManager& categoryNameManager) -{ - for (simData::CategoryFilter::ValuesCheck::const_iterator valIter = iter.begin(); valIter != iter.end(); ++valIter) - { - QString value = QString::fromStdString(categoryNameManager.valueIntToString(valIter->first)); - CategoryTreeItem* catValItem = new CategoryTreeItem(value, valueSortName_(value), valIter->first, nameItem); - nameItem->appendChild(catValItem); - } -} - -QString CategoryTreeModel::valueSortName_(const QString& value) const -{ - if (value == "Unlisted Value") - return " "; - - if (value == "No Value") - return " "; - - return value; -} - -/** - * The passed in categoryFilter may have a subset of the category information. - * If categoryFilter is missing a category name the GUI should show checked for everything - * If categoryFilter is missing a category value the GUI should show the "Unlisted" state - */ -void CategoryTreeModel::setFilter(const simData::CategoryFilter& categoryFilter) -{ - // Only update with a different filter - if (&categoryFilter == categoryFilter_ || categoryFilter_ == NULL) - return; - - // Simplify the filter. This will reduce the total number of operations here. - simData::CategoryFilter simplified = categoryFilter; - simplified.simplify(); - - // Do a quick check on the current filter and make sure it doesn't match incoming filter. - // Do it in an artificial scope to prevent temporary filter from lasting long. - { - simData::CategoryFilter localSimplified = *categoryFilter_; - localSimplified.simplify(); - if (localSimplified == simplified) - return; - } - - - // If the name is in the simplified filter, that means it's got an influence on the filter state. - // If it's absent, then it has no influence; GUI should be checked and all values set true, - // which is the state we're starting with here. Therefore, we only need to update the filter - // state for items that exist in the category filter. - std::vector allNamesVec; - simplified.getNames(allNamesVec); - // Convert this into a set for faster find() - std::set allNamesSet(allNamesVec.begin(), allNamesVec.end()); - - // First, update the GUI - const int numCategories = allCategoriesItem_->childCount(); - for (int categoryIndex = 0; categoryIndex < numCategories; ++categoryIndex) - { - CategoryTreeItem* categoryItem = allCategoriesItem_->child(categoryIndex); - // Assertion fail means failure in CategoryTreeItem::child() or childCount() - assert(categoryItem); - if (!categoryItem) - continue; - - // Determine if the name is in the simplified filter. If it is, then the item needs - // to be checked. If it's not, then the GUI can be fully checked or fully unchecked, - // since both states are equivalent; don't change anything in that case. - const bool categoryIsInSimplified = (allNamesSet.find(categoryItem->categoryIndex()) != allNamesSet.end()); - if (!categoryIsInSimplified) - { - const Qt::CheckState currentState = categoryItem->childrenState(); - if (currentState == Qt::PartiallyChecked) - setState_(categoryItem, Qt::Checked); - continue; - } - - // Item is in the filter. It applies in some way. - categoryItem->setState(Qt::Checked); - - // Get all the checks for this category. This is a simplified listing and we need to - // rely on "Unlisted Value" to tell us entries. - simData::CategoryFilter::ValuesCheck checks; - simplified.getValues(categoryItem->categoryIndex(), checks); - // Determine whether Unlisted Values are checked or unchecked - auto unlistedIter = checks.find(simData::CategoryNameManager::UNLISTED_CATEGORY_VALUE); - // Assertion validates that if "Unlisted Value" is present, that it's set to true (a non-default value) - assert(unlistedIter == checks.end() || unlistedIter->second); - const bool unlistedValues = (unlistedIter != checks.end()); - - // Loop through all children, setting the values correctly - const int numValues = categoryItem->childCount(); - for (int valueIndex = 0; valueIndex < numValues; ++valueIndex) - { - CategoryTreeItem* valueItem = categoryItem->child(valueIndex); - assert(valueItem); // Implies failure in child() or childCount() - - // Find it in the filter - const int valueInt = valueItem->categoryIndex(); - auto simpleIter = checks.find(valueInt); - // Is it present? If so use that value - if (simpleIter != checks.end()) - valueItem->setState(simpleIter->second ? Qt::Checked : Qt::Unchecked); - else - { - // Else, use the unlisted value that we detected, unless it's the NO VALUE special case (always off by default) - if (valueInt == simData::CategoryNameManager::NO_CATEGORY_VALUE_AT_TIME) - valueItem->setState(Qt::Unchecked); - else - valueItem->setState(unlistedValues ? Qt::Checked : Qt::Unchecked); - } - } - } - - // Next, update the state of the internal filter to match what the GUI shows - bool globalCheck = false; - for (int categoryIndex = 0; categoryIndex < numCategories; ++categoryIndex) - { - CategoryTreeItem* categoryItem = allCategoriesItem_->child(categoryIndex); - if (!categoryItem) - continue; - const int nameInt = categoryItem->categoryIndex(); - categoryFilter_->updateCategoryFilterName(nameInt, categoryItem->state() == Qt::Checked); - - // Keep track of the global flag for check/uncheck on top level - if (categoryItem->state() == Qt::Checked) - globalCheck = true; - - // Set each child value appropriately - const int numValues = categoryItem->childCount(); - for (int valueIndex = 0; valueIndex < numValues; ++valueIndex) - { - // Check the item in the filter if the GUI item is checked - CategoryTreeItem* valueItem = categoryItem->child(valueIndex); - if (valueItem) - categoryFilter_->setValue(nameInt, valueItem->categoryIndex(), valueItem->state() == Qt::Checked); - } - } - - // Synchronize the state on the All Items check - allCategoriesItem_->setState(globalCheck ? Qt::Checked : Qt::Unchecked); - - // Emit dataChanged() to update the GUI - emit dataChanged(createIndex(0, 0), createIndex(allCategoriesItem_->childCount(), 0)); -} - -} -#endif /* USE_DEPRECATED_SIMDISSDK_API */ diff --git a/SDK/simQt/CategoryTreeModel.h b/SDK/simQt/CategoryTreeModel.h deleted file mode 100644 index 687de7c33..000000000 --- a/SDK/simQt/CategoryTreeModel.h +++ /dev/null @@ -1,170 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ -#ifdef USE_DEPRECATED_SIMDISSDK_API - // this is deprecated; use simQt::CategoryTreeModel2 - -#ifndef SIMQT_CATEGORY_TREE_MODEL_H -#define SIMQT_CATEGORY_TREE_MODEL_H - -#include -#include - -#include "simCore/Common/Common.h" -#include "simData/CategoryData/CategoryFilter.h" -#include "simData/CategoryData/CategoryNameManager.h" - -namespace simData { class DataStore; } - -namespace simQt { - -/// represent either one category name or on category value -class SDKQT_EXPORT CategoryTreeItem -{ -public: - /// constructor - CategoryTreeItem(const QString& text, const QString& sortText, int categoryIndex, CategoryTreeItem *parent = NULL); - virtual ~CategoryTreeItem(); - - /// Returns the category name or category value - QString text() const; - /// For sorting force "Unlisted Value" and "No Value" to the top - QString sortText() const; - /// Returns the index for the category name or category value - int categoryIndex() const; - /// Returns the check box state - Qt::CheckState state() const; - /// Sets the check box state - void setState(Qt::CheckState value); - /// Returns Checked, Unchecked, or PartiallyChecked to indicate whether children are uniformly checked - Qt::CheckState childrenState() const; - - /**@name Tree management routines - *@{ - */ - void appendChild(CategoryTreeItem *item); - void removeChild(CategoryTreeItem *item); - CategoryTreeItem *child(int row); - int childCount() const; - CategoryTreeItem *parent(); - int columnCount() const; - int row() const; - ///@} - -protected: - /// Update the numCheckedChildren_ value based on the provided value, which will increment or decrement the total - void updateNumCheckedChildren_(Qt::CheckState value); - - QString text_; ///< the category name or category value - QString sortText_; ///< If category value is "Unlisted Value" or "No Value" change to " " and " " to force them to the top of the sort - int categoryIndex_; ///< the index for the category name or category value - CategoryTreeItem *parentItem_; ///< parent of the item. Null if top item - Qt::CheckState state_; ///< the check box state - int numCheckedChildren_; ///< keep track of the number of checked children, to manage current check state - QList childItems_; ///< Children of item, if any. If no children, than item is a category value -}; - - -/// model (data representation) for a tree of Entities (Platforms, Beams, Gates, etc.) -class SDKQT_EXPORT CategoryTreeModel : public QAbstractItemModel -{ - Q_OBJECT - -public: - /// constructor - explicit CategoryTreeModel(QObject *parent = NULL, simData::DataStore* dataStore = NULL, simData::CategoryFilter* categoryFilter = NULL); - virtual ~CategoryTreeModel(); - - /** - * Set providers - * @param dataStore The datastore - * @param categoryFilter The category filter - **/ - void setProviders(simData::DataStore* dataStore, simData::CategoryFilter* categoryFilter); - /** - * Returns the text for the given index - * @param index The index - * @return The text for the given index, will be "" if index is invalid - **/ - QString text(const QModelIndex &index) const; - - /** @copydoc QAbstractItemModel::columnCount() */ - virtual int columnCount(const QModelIndex &parent) const; - /** @copydoc QAbstractItemModel::data() */ - virtual QVariant data(const QModelIndex &index, int role) const; - /** @copydoc QAbstractItemModel::setData() */ - virtual bool setData(const QModelIndex& index, const QVariant& value, int role); - /** @copydoc QAbstractItemModel::flags() */ - virtual Qt::ItemFlags flags(const QModelIndex& index) const; - /** @copydoc QAbstractItemModel::index() */ - virtual QModelIndex index(int row, int column, const QModelIndex &parent) const; - /** @copydoc QAbstractItemModel::parent() */ - virtual QModelIndex parent(const QModelIndex &index) const; - /** @copydoc QAbstractItemModel::rowCount() */ - virtual int rowCount(const QModelIndex &parent) const; - - /// data role for obtaining names that are remapped to force "Unlisted Value" and "No Value" to the top - static const int SortRole = Qt::UserRole + 1; - -public slots: - /** Updates the contents of the frame */ - virtual void forceRefresh(); - /// Update the filter to the passed in filter - void setFilter(const simData::CategoryFilter& categoryFilter); - -signals: - /** Emitted whenever the underlying category filter changes */ - void categoryFilterChanged(const simData::CategoryFilter& categoryFilter); - -private: - class CategoryFilterListener; - - /** Helper function to create and add all the category value QTreeWidgetItems to the parent QTreeWidgetItem */ - void addAllValues_(const simData::CategoryFilter::ValuesCheck& iter, CategoryTreeItem* nameItem, const simData::CategoryNameManager& categoryNameManager); - /** Sets the stat for the given item and all its children */ - int setState_(CategoryTreeItem* item, Qt::CheckState state); - /** Updates user interface tree based on passed in value */ - void addCategoryName_(int nameIndex); - /** Updates user interface tree based on passed in value; if rebuild is true then rebuild the category filter */ - void addCategoryValue_(int nameIndex, int valueIndex, bool rebuild); - /** Clear all data */ - void clear_(); - /** Returns the item for the given index; may return NULL */ - CategoryTreeItem* findCategoryName_(int nameIndex); - /** Returns the item for the given parent index; may return NULL */ - CategoryTreeItem* findCategoryValue_(CategoryTreeItem* parent, int valueIndex); - /** Setup the tree */ - void buildTree_(); - /** Convert value into a sortable name */ - QString valueSortName_(const QString& value) const; - - CategoryTreeItem *rootItem_; - CategoryTreeItem *allCategoriesItem_; - simData::DataStore* dataStore_; - simData::CategoryFilter* categoryFilter_; - simData::CategoryNameManager::ListenerPtr listenerPtr_; -}; - -} - -#endif -#endif /* USE_DEPRECATED_SIMDISSDK_API */ - diff --git a/SDK/simQt/CategoryTreeModel2.cpp b/SDK/simQt/CategoryTreeModel2.cpp index fe16dc661..eab70e03f 100644 --- a/SDK/simQt/CategoryTreeModel2.cpp +++ b/SDK/simQt/CategoryTreeModel2.cpp @@ -46,10 +46,6 @@ #include "simQt/Settings.h" #include "simQt/CategoryTreeModel2.h" -#ifdef USE_DEPRECATED_SIMDISSDK_API -#include "simQt/CategoryTreeModel.h" -#endif - namespace simQt { /** Lighter than lightGray, matches QPalette::Midlight */ @@ -61,11 +57,6 @@ static const QString LOCKED_SETTING = "LockedCategories"; /** Locked settings meta data to define it as private */ static const simQt::Settings::MetaData LOCKED_SETTING_METADATA(Settings::STRING_LIST, "", "", Settings::PRIVATE); -#ifdef USE_DEPRECATED_SIMDISSDK_API -// Used to differentiate between the old and new CategoryTreeModel in CategoryProxyModel TODO Will be removed with the old model after December 2019 -static const QString ALL_CATEGORIES = "All Categories"; -#endif - ///////////////////////////////////////////////////////////////////////// @@ -164,7 +155,7 @@ class TreeItem ///////////////////////////////////////////////////////////////////////// /** Represents a group node in tree, showing a category name and containing children values. */ -class CategoryTreeModel2::CategoryItem : public TreeItem +class CategoryTreeModel::CategoryItem : public TreeItem { public: CategoryItem(const simData::CategoryNameManager& nameManager, int nameInt); @@ -222,7 +213,7 @@ class CategoryTreeModel2::CategoryItem : public TreeItem ///////////////////////////////////////////////////////////////////////// /** Represents a leaf node in tree, showing a category value. */ -class CategoryTreeModel2::ValueItem : public TreeItem +class CategoryTreeModel::ValueItem : public TreeItem { public: ValueItem(const simData::CategoryNameManager& nameManager, int nameInt, int valueInt); @@ -322,7 +313,7 @@ void TreeItem::addChild(TreeItem* item) ///////////////////////////////////////////////////////////////////////// -CategoryTreeModel2::CategoryItem::CategoryItem(const simData::CategoryNameManager& nameManager, int nameInt) +CategoryTreeModel::CategoryItem::CategoryItem(const simData::CategoryNameManager& nameManager, int nameInt) : categoryName_(QString::fromStdString(nameManager.nameIntToString(nameInt))), nameInt_(nameInt), unlistedValue_(false), @@ -332,32 +323,32 @@ CategoryTreeModel2::CategoryItem::CategoryItem(const simData::CategoryNameManage { } -bool CategoryTreeModel2::CategoryItem::isUnlistedValueChecked() const +bool CategoryTreeModel::CategoryItem::isUnlistedValueChecked() const { return unlistedValue_; } -bool CategoryTreeModel2::CategoryItem::isRegExpApplied() const +bool CategoryTreeModel::CategoryItem::isRegExpApplied() const { return !regExpString_.isEmpty(); } -int CategoryTreeModel2::CategoryItem::nameInt() const +int CategoryTreeModel::CategoryItem::nameInt() const { return nameInt_; } -QString CategoryTreeModel2::CategoryItem::categoryName() const +QString CategoryTreeModel::CategoryItem::categoryName() const { return categoryName_; } -Qt::ItemFlags CategoryTreeModel2::CategoryItem::flags() const +Qt::ItemFlags CategoryTreeModel::CategoryItem::flags() const { return Qt::ItemIsEnabled; } -QVariant CategoryTreeModel2::CategoryItem::data(int role) const +QVariant CategoryTreeModel::CategoryItem::data(int role) const { switch (role) { @@ -386,7 +377,7 @@ QVariant CategoryTreeModel2::CategoryItem::data(int role) const return QVariant(); } -bool CategoryTreeModel2::CategoryItem::setData(const QVariant& value, int role, simData::CategoryFilter& filter, bool& filterChanged) +bool CategoryTreeModel::CategoryItem::setData(const QVariant& value, int role, simData::CategoryFilter& filter, bool& filterChanged) { if (role == ROLE_EXCLUDE) return setExcludeData_(value, filter, filterChanged); @@ -402,7 +393,7 @@ bool CategoryTreeModel2::CategoryItem::setData(const QVariant& value, int role, return false; } -bool CategoryTreeModel2::CategoryItem::setExcludeData_(const QVariant& value, simData::CategoryFilter& filter, bool& filterChanged) +bool CategoryTreeModel::CategoryItem::setExcludeData_(const QVariant& value, simData::CategoryFilter& filter, bool& filterChanged) { filterChanged = false; // If value does not change, or if disabled, then return early @@ -431,7 +422,7 @@ bool CategoryTreeModel2::CategoryItem::setExcludeData_(const QVariant& value, si return true; } -bool CategoryTreeModel2::CategoryItem::setRegExpStringData_(const QVariant& value, simData::CategoryFilter& filter, bool& filterChanged) +bool CategoryTreeModel::CategoryItem::setRegExpStringData_(const QVariant& value, simData::CategoryFilter& filter, bool& filterChanged) { // Check for easy no-op filterChanged = false; @@ -459,7 +450,7 @@ bool CategoryTreeModel2::CategoryItem::setRegExpStringData_(const QVariant& valu return true; } -bool CategoryTreeModel2::CategoryItem::recalcContributionTo(const simData::CategoryFilter& filter) +bool CategoryTreeModel::CategoryItem::recalcContributionTo(const simData::CategoryFilter& filter) { // First check the regular expression. If there's a regexp, then this category definitely contributes const bool newValue = filter.nameContributesToFilter(nameInt_); @@ -469,12 +460,12 @@ bool CategoryTreeModel2::CategoryItem::recalcContributionTo(const simData::Categ return true; } -void CategoryTreeModel2::CategoryItem::setFont(QFont* font) +void CategoryTreeModel::CategoryItem::setFont(QFont* font) { font_ = font; } -bool CategoryTreeModel2::CategoryItem::setChildChecks_(const simData::RegExpFilter* reFilter) +bool CategoryTreeModel::CategoryItem::setChildChecks_(const simData::RegExpFilter* reFilter) { bool hasChange = false; const int count = childCount(); @@ -492,7 +483,7 @@ bool CategoryTreeModel2::CategoryItem::setChildChecks_(const simData::RegExpFilt return hasChange; } -int CategoryTreeModel2::CategoryItem::updateTo(const simData::CategoryFilter& filter) +int CategoryTreeModel::CategoryItem::updateTo(const simData::CategoryFilter& filter) { // Update the category if it has a RegExp const QString oldRegExp = regExpString_; @@ -563,7 +554,7 @@ int CategoryTreeModel2::CategoryItem::updateTo(const simData::CategoryFilter& fi return hasChange ? 1 : 0; } -void CategoryTreeModel2::CategoryItem::updateFilter_(const ValueItem& valueItem, simData::CategoryFilter& filter) const +void CategoryTreeModel::CategoryItem::updateFilter_(const ValueItem& valueItem, simData::CategoryFilter& filter) const { const bool filterValue = (valueItem.isChecked() != unlistedValue_); // NO_VALUE is a special case @@ -579,7 +570,7 @@ void CategoryTreeModel2::CategoryItem::updateFilter_(const ValueItem& valueItem, } } -int CategoryTreeModel2::CategoryItem::updateValueItem_(ValueItem& valueItem, const simData::CategoryFilter::ValuesCheck& checks) const +int CategoryTreeModel::CategoryItem::updateValueItem_(ValueItem& valueItem, const simData::CategoryFilter::ValuesCheck& checks) const { // NO VALUE is a special case unfortunately const auto i = checks.find(valueItem.valueInt()); @@ -617,7 +608,7 @@ int CategoryTreeModel2::CategoryItem::updateValueItem_(ValueItem& valueItem, con return 1; } -bool CategoryTreeModel2::CategoryItem::updateCounts(const std::map& valueToCountMap) const +bool CategoryTreeModel::CategoryItem::updateCounts(const std::map& valueToCountMap) const { const int numValues = childCount(); bool haveChange = false; @@ -650,7 +641,7 @@ bool CategoryTreeModel2::CategoryItem::updateCounts(const std::map& ///////////////////////////////////////////////////////////////////////// -CategoryTreeModel2::ValueItem::ValueItem(const simData::CategoryNameManager& nameManager, int nameInt, int valueInt) +CategoryTreeModel::ValueItem::ValueItem(const simData::CategoryNameManager& nameManager, int nameInt, int valueInt) : nameInt_(nameInt), valueInt_(valueInt), numMatches_(-1), @@ -659,7 +650,7 @@ CategoryTreeModel2::ValueItem::ValueItem(const simData::CategoryNameManager& nam { } -bool CategoryTreeModel2::ValueItem::isUnlistedValueChecked() const +bool CategoryTreeModel::ValueItem::isUnlistedValueChecked() const { // Assertion failure means we have orphan value items assert(parent()); @@ -668,7 +659,7 @@ bool CategoryTreeModel2::ValueItem::isUnlistedValueChecked() const return parent()->isUnlistedValueChecked(); } -bool CategoryTreeModel2::ValueItem::isRegExpApplied() const +bool CategoryTreeModel::ValueItem::isRegExpApplied() const { // Assertion failure means we have orphan value items assert(parent()); @@ -677,12 +668,12 @@ bool CategoryTreeModel2::ValueItem::isRegExpApplied() const return parent()->isRegExpApplied(); } -int CategoryTreeModel2::ValueItem::nameInt() const +int CategoryTreeModel::ValueItem::nameInt() const { return nameInt_; } -QString CategoryTreeModel2::ValueItem::categoryName() const +QString CategoryTreeModel::ValueItem::categoryName() const { // Assertion failure means we have orphan value items assert(parent()); @@ -691,12 +682,12 @@ QString CategoryTreeModel2::ValueItem::categoryName() const return parent()->data(ROLE_CATEGORY_NAME).toString(); } -int CategoryTreeModel2::ValueItem::valueInt() const +int CategoryTreeModel::ValueItem::valueInt() const { return valueInt_; } -QString CategoryTreeModel2::ValueItem::valueString() const +QString CategoryTreeModel::ValueItem::valueString() const { // "No Value" should return empty string here, not user-facing string if (valueInt_ == simData::CategoryNameManager::NO_CATEGORY_VALUE_AT_TIME) @@ -704,14 +695,14 @@ QString CategoryTreeModel2::ValueItem::valueString() const return valueString_; } -Qt::ItemFlags CategoryTreeModel2::ValueItem::flags() const +Qt::ItemFlags CategoryTreeModel::ValueItem::flags() const { if (isRegExpApplied()) return Qt::NoItemFlags; return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable; } -QVariant CategoryTreeModel2::ValueItem::data(int role) const +QVariant CategoryTreeModel::ValueItem::data(int role) const { switch (role) { @@ -763,7 +754,7 @@ QVariant CategoryTreeModel2::ValueItem::data(int role) const return QVariant(); } -bool CategoryTreeModel2::ValueItem::setData(const QVariant& value, int role, simData::CategoryFilter& filter, bool& filterChanged) +bool CategoryTreeModel::ValueItem::setData(const QVariant& value, int role, simData::CategoryFilter& filter, bool& filterChanged) { // Internally handle check/uncheck value. For ROLE_REGEXP and ROLE_LOCKED_STATE, rely on category parent if (role == Qt::CheckStateRole) @@ -776,7 +767,7 @@ bool CategoryTreeModel2::ValueItem::setData(const QVariant& value, int role, sim return false; } -bool CategoryTreeModel2::ValueItem::setCheckStateData_(const QVariant& value, simData::CategoryFilter& filter, bool& filterChanged) +bool CategoryTreeModel::ValueItem::setCheckStateData_(const QVariant& value, simData::CategoryFilter& filter, bool& filterChanged) { filterChanged = false; @@ -837,34 +828,34 @@ bool CategoryTreeModel2::ValueItem::setCheckStateData_(const QVariant& value, si return true; } -void CategoryTreeModel2::ValueItem::setChecked(bool value) +void CategoryTreeModel::ValueItem::setChecked(bool value) { checked_ = (value ? Qt::Checked : Qt::Unchecked); } -bool CategoryTreeModel2::ValueItem::isChecked() const +bool CategoryTreeModel::ValueItem::isChecked() const { return checked_ == Qt::Checked; } -void CategoryTreeModel2::ValueItem::setNumMatches(int matches) +void CategoryTreeModel::ValueItem::setNumMatches(int matches) { numMatches_ = matches; } -int CategoryTreeModel2::ValueItem::numMatches() const +int CategoryTreeModel::ValueItem::numMatches() const { return numMatches_; } ///////////////////////////////////////////////////////////////////////// -/// Monitors for category data changes, calling methods in CategoryTreeModel2. -class CategoryTreeModel2::CategoryFilterListener : public simData::CategoryNameManager::Listener +/// Monitors for category data changes, calling methods in CategoryTreeModel. +class CategoryTreeModel::CategoryFilterListener : public simData::CategoryNameManager::Listener { public: /// Constructor - explicit CategoryFilterListener(CategoryTreeModel2& parent) + explicit CategoryFilterListener(CategoryTreeModel& parent) : parent_(parent) { } @@ -898,14 +889,13 @@ class CategoryTreeModel2::CategoryFilterListener : public simData::CategoryNameM } private: - CategoryTreeModel2& parent_; + CategoryTreeModel& parent_; }; ///////////////////////////////////////////////////////////////////////// CategoryProxyModel::CategoryProxyModel(QObject *parent) - : QSortFilterProxyModel(parent), - hasAllCategories_(true) + : QSortFilterProxyModel(parent) { } @@ -913,20 +903,6 @@ CategoryProxyModel::~CategoryProxyModel() { } -void CategoryProxyModel::setSourceModel(QAbstractItemModel* sourceModel) -{ -#ifdef USE_DEPRECATED_SIMDISSDK_API - // simQt::CategoryTreeModel has a top level "All Categories" item. This item affects - // some of the way filtering works. Detect whether we're using a CategoryTreeModel - // and change our internal flag appropriately. Note that another possible choice - // is simQt::CategoryTreeModel2, which does not have an All Categories item. - hasAllCategories_ = (dynamic_cast(sourceModel) != NULL); -#else - hasAllCategories_ = false; -#endif - QSortFilterProxyModel::setSourceModel(sourceModel); -} - void CategoryProxyModel::resetFilter() { invalidateFilter(); @@ -946,10 +922,6 @@ bool CategoryProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sour if (filter_.isEmpty()) return true; - // Always accept top level "All Categories" item - if (hasAllCategories_ && !sourceParent.isValid()) - return true; - const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); const QString itemText = index.data(Qt::DisplayRole).toString(); @@ -962,19 +934,8 @@ bool CategoryProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sour { const QString parentText = sourceParent.data(Qt::DisplayRole).toString(); -#ifdef USE_DEPRECATED_SIMDISSDK_API - // We only care about matching "All Categories" for the old model type. TODO Will be removed with the old model after December 2019 - if (hasAllCategories_) - { - if (parentText != ALL_CATEGORIES && parentText.contains(filter_, Qt::CaseInsensitive)) - return true; - } - else -#endif - { - if (parentText.contains(filter_, Qt::CaseInsensitive)) + if (parentText.contains(filter_, Qt::CaseInsensitive)) return true; - } } // include items with any children that pass the filter @@ -993,7 +954,7 @@ bool CategoryProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sour ///////////////////////////////////////////////////////////////////////// -CategoryTreeModel2::CategoryTreeModel2(QObject* parent) +CategoryTreeModel::CategoryTreeModel(QObject* parent) : QAbstractItemModel(parent), dataStore_(NULL), filter_(new simData::CategoryFilter(NULL)), @@ -1007,7 +968,7 @@ CategoryTreeModel2::CategoryTreeModel2(QObject* parent) categoryFont_->setBold(true); } -CategoryTreeModel2::~CategoryTreeModel2() +CategoryTreeModel::~CategoryTreeModel() { categories_.deleteAll(); categoryIntToItem_.clear(); @@ -1019,7 +980,7 @@ CategoryTreeModel2::~CategoryTreeModel2() dataStore_->categoryNameManager().removeListener(listener_); } -QModelIndex CategoryTreeModel2::index(int row, int column, const QModelIndex &parent) const +QModelIndex CategoryTreeModel::index(int row, int column, const QModelIndex &parent) const { if (!hasIndex(row, column, parent)) return QModelIndex(); @@ -1033,7 +994,7 @@ QModelIndex CategoryTreeModel2::index(int row, int column, const QModelIndex &pa return createIndex(row, column, parentItem->child(row)); } -QModelIndex CategoryTreeModel2::parent(const QModelIndex &child) const +QModelIndex CategoryTreeModel::parent(const QModelIndex &child) const { if (!child.isValid() || !child.internalPointer()) return QModelIndex(); @@ -1046,7 +1007,7 @@ QModelIndex CategoryTreeModel2::parent(const QModelIndex &child) const return createIndex(categories_.indexOf(static_cast(parentItem)), 0, parentItem); } -int CategoryTreeModel2::rowCount(const QModelIndex &parent) const +int CategoryTreeModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { @@ -1058,12 +1019,12 @@ int CategoryTreeModel2::rowCount(const QModelIndex &parent) const return categories_.size(); } -int CategoryTreeModel2::columnCount(const QModelIndex &parent) const +int CategoryTreeModel::columnCount(const QModelIndex &parent) const { return 1; } -QVariant CategoryTreeModel2::data(const QModelIndex &index, int role) const +QVariant CategoryTreeModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || !index.internalPointer()) return QVariant(); @@ -1071,7 +1032,7 @@ QVariant CategoryTreeModel2::data(const QModelIndex &index, int role) const return treeItem->data(role); } -QVariant CategoryTreeModel2::headerData(int section, Qt::Orientation orientation, int role) const +QVariant CategoryTreeModel::headerData(int section, Qt::Orientation orientation, int role) const { if ((orientation == Qt::Horizontal) && (role == Qt::DisplayRole)) { @@ -1087,7 +1048,7 @@ QVariant CategoryTreeModel2::headerData(int section, Qt::Orientation orientation return QAbstractItemModel::headerData(section, orientation, role); } -Qt::ItemFlags CategoryTreeModel2::flags(const QModelIndex& index) const +Qt::ItemFlags CategoryTreeModel::flags(const QModelIndex& index) const { if (!index.isValid() || !index.internalPointer()) return Qt::NoItemFlags; @@ -1095,7 +1056,7 @@ Qt::ItemFlags CategoryTreeModel2::flags(const QModelIndex& index) const return item->flags(); } -bool CategoryTreeModel2::setData(const QModelIndex& index, const QVariant& value, int role) +bool CategoryTreeModel::setData(const QModelIndex& index, const QVariant& value, int role) { // Ensure we have a valid index with a valid TreeItem pointer if (!index.isValid() || !index.internalPointer()) @@ -1146,7 +1107,7 @@ bool CategoryTreeModel2::setData(const QModelIndex& index, const QVariant& value return rv; } -void CategoryTreeModel2::setFilter(const simData::CategoryFilter& filter) +void CategoryTreeModel::setFilter(const simData::CategoryFilter& filter) { // Check the data store; if it's set in filter and different from ours, update if (filter.getDataStore() && filter.getDataStore() != dataStore_) @@ -1199,14 +1160,14 @@ void CategoryTreeModel2::setFilter(const simData::CategoryFilter& filter) emit filterChanged(*filter_); } -const simData::CategoryFilter& CategoryTreeModel2::categoryFilter() const +const simData::CategoryFilter& CategoryTreeModel::categoryFilter() const { // Precondition of this method is that data store was set; filter must be non-NULL assert(filter_); return *filter_; } -void CategoryTreeModel2::setDataStore(simData::DataStore* dataStore) +void CategoryTreeModel::setDataStore(simData::DataStore* dataStore) { if (dataStore_ == dataStore) return; @@ -1277,7 +1238,7 @@ void CategoryTreeModel2::setDataStore(simData::DataStore* dataStore) emit filterChanged(*filter_); } -void CategoryTreeModel2::setSettings(Settings* settings, const QString& settingsKeyPrefix) +void CategoryTreeModel::setSettings(Settings* settings, const QString& settingsKeyPrefix) { settings_ = settings; settingsKey_ = settingsKeyPrefix + "/" + LOCKED_SETTING; @@ -1293,7 +1254,7 @@ void CategoryTreeModel2::setSettings(Settings* settings, const QString& settings } } -void CategoryTreeModel2::clearTree_() +void CategoryTreeModel::clearTree_() { beginResetModel(); categories_.deleteAll(); @@ -1303,7 +1264,7 @@ void CategoryTreeModel2::clearTree_() endResetModel(); } -void CategoryTreeModel2::addName_(int nameInt) +void CategoryTreeModel::addName_(int nameInt) { assert(dataStore_ != NULL); @@ -1338,21 +1299,21 @@ void CategoryTreeModel2::addName_(int nameInt) endInsertRows(); } -CategoryTreeModel2::CategoryItem* CategoryTreeModel2::findNameTree_(int nameInt) const +CategoryTreeModel::CategoryItem* CategoryTreeModel::findNameTree_(int nameInt) const { auto i = categoryIntToItem_.find(nameInt); return (i == categoryIntToItem_.end()) ? NULL : i->second; } -void CategoryTreeModel2::updateLockedState_(const QStringList& lockedCategories, CategoryItem& category) +void CategoryTreeModel::updateLockedState_(const QStringList& lockedCategories, CategoryItem& category) { if (!lockedCategories.contains(category.categoryName())) return; bool wasChanged = false; - category.setData(true, CategoryTreeModel2::ROLE_LOCKED_STATE, *filter_, wasChanged); + category.setData(true, CategoryTreeModel::ROLE_LOCKED_STATE, *filter_, wasChanged); } -void CategoryTreeModel2::addValue_(int nameInt, int valueInt) +void CategoryTreeModel::addValue_(int nameInt, int valueInt) { // Find the parent item TreeItem* nameItem = findNameTree_(nameInt); @@ -1378,7 +1339,7 @@ void CategoryTreeModel2::addValue_(int nameInt, int valueInt) endInsertRows(); } -void CategoryTreeModel2::processCategoryCounts(const simQt::CategoryCountResults& results) +void CategoryTreeModel::processCategoryCounts(const simQt::CategoryCountResults& results) { const int numCategories = categories_.size(); int firstRowChanged = -1; @@ -1651,8 +1612,8 @@ void CategoryTreeItemDelegate::paintCategory_(QPainter* painter, QStyleOptionVie StyleOptionToggleSwitch switchOpt; ToggleSwitchPainter switchPainter; switchOpt.rect = r.excludeToggle; - switchOpt.locked = index.data(CategoryTreeModel2::ROLE_LOCKED_STATE).toBool(); - switchOpt.value = (switchOpt.locked ? false : index.data(CategoryTreeModel2::ROLE_EXCLUDE).toBool()); + switchOpt.locked = index.data(CategoryTreeModel::ROLE_LOCKED_STATE).toBool(); + switchOpt.value = (switchOpt.locked ? false : index.data(CategoryTreeModel::ROLE_EXCLUDE).toBool()); switchPainter.paint(switchOpt, painter); } @@ -1728,7 +1689,7 @@ bool CategoryTreeItemDelegate::categoryEvent_(QEvent* evt, QAbstractItemModel* m return false; } // Ignore event if category is locked - if (index.data(CategoryTreeModel2::ROLE_LOCKED_STATE).toBool()) + if (index.data(CategoryTreeModel::ROLE_LOCKED_STATE).toBool()) { clickedIndex_ = QModelIndex(); return true; @@ -1750,7 +1711,7 @@ bool CategoryTreeItemDelegate::categoryEvent_(QEvent* evt, QAbstractItemModel* m case QEvent::MouseButtonRelease: { // Ignore event if category is locked - if (index.data(CategoryTreeModel2::ROLE_LOCKED_STATE).toBool()) + if (index.data(CategoryTreeModel::ROLE_LOCKED_STATE).toBool()) { clickedIndex_ = QModelIndex(); return true; @@ -1763,9 +1724,9 @@ bool CategoryTreeItemDelegate::categoryEvent_(QEvent* evt, QAbstractItemModel* m // Toggle button should, well, toggle if (clickedElement_ == SE_EXCLUDE_TOGGLE) { - QVariant oldState = index.data(CategoryTreeModel2::ROLE_EXCLUDE); + QVariant oldState = index.data(CategoryTreeModel::ROLE_EXCLUDE); if (index.flags().testFlag(Qt::ItemIsEnabled)) - model->setData(index, !oldState.toBool(), CategoryTreeModel2::ROLE_EXCLUDE); + model->setData(index, !oldState.toBool(), CategoryTreeModel::ROLE_EXCLUDE); clickedIndex_ = QModelIndex(); return true; } @@ -1783,7 +1744,7 @@ bool CategoryTreeItemDelegate::categoryEvent_(QEvent* evt, QAbstractItemModel* m case QEvent::MouseButtonDblClick: // Ignore event if category is locked - if (index.data(CategoryTreeModel2::ROLE_LOCKED_STATE).toBool()) + if (index.data(CategoryTreeModel::ROLE_LOCKED_STATE).toBool()) { clickedIndex_ = QModelIndex(); return true; @@ -1867,7 +1828,7 @@ void CategoryTreeItemDelegate::calculateRects_(const QStyleOptionViewItem& optio rects.branch.setRight(rects.branch.left() + rects.branch.height()); // Calculate the width given the rectangle of height, for the toggle switch - const bool haveRegExp = !index.data(CategoryTreeModel2::ROLE_REGEXP_STRING).toString().isEmpty(); + const bool haveRegExp = !index.data(CategoryTreeModel::ROLE_REGEXP_STRING).toString().isEmpty(); if (haveRegExp) { rects.excludeToggle = QRect(); @@ -1946,10 +1907,10 @@ bool CategoryTreeItemDelegate::helpEvent(QHelpEvent* evt, QAbstractItemView* vie * Class that listens for entity events in the DataStore, and * informs the parent when they happen. */ -class CategoryFilterWidget2::DataStoreListener : public simData::DataStore::Listener +class CategoryFilterWidget::DataStoreListener : public simData::DataStore::Listener { public: - explicit DataStoreListener(CategoryFilterWidget2& parent) + explicit DataStoreListener(CategoryFilterWidget& parent) : parent_(parent) {}; @@ -1974,12 +1935,12 @@ class CategoryFilterWidget2::DataStoreListener : public simData::DataStore::List virtual void onFlush(simData::DataStore* source, simData::ObjectId id) {} private: - CategoryFilterWidget2& parent_; + CategoryFilterWidget& parent_; }; ///////////////////////////////////////////////////////////////////////// -CategoryFilterWidget2::CategoryFilterWidget2(QWidget* parent) +CategoryFilterWidget::CategoryFilterWidget(QWidget* parent) : QWidget(parent), activeFiltering_(false), showEntityCount_(false), @@ -1988,12 +1949,12 @@ CategoryFilterWidget2::CategoryFilterWidget2(QWidget* parent) countDirty_(true) { setWindowTitle("Category Data Filter"); - setObjectName("CategoryFilterWidget2"); + setObjectName("CategoryFilterWidget"); - treeModel_ = new simQt::CategoryTreeModel2(this); + treeModel_ = new simQt::CategoryTreeModel(this); proxy_ = new simQt::CategoryProxyModel(this); proxy_->setSourceModel(treeModel_); - proxy_->setSortRole(simQt::CategoryTreeModel2::ROLE_SORT_STRING); + proxy_->setSortRole(simQt::CategoryTreeModel::ROLE_SORT_STRING); proxy_->sort(0); treeView_ = new QTreeView(this); @@ -2075,16 +2036,16 @@ CategoryFilterWidget2::CategoryFilterWidget2(QWidget* parent) // Entity filtering is on by default setShowEntityCount(true); - dsListener_.reset(new CategoryFilterWidget2::DataStoreListener(*this)); + dsListener_.reset(new CategoryFilterWidget::DataStoreListener(*this)); } -CategoryFilterWidget2::~CategoryFilterWidget2() +CategoryFilterWidget::~CategoryFilterWidget() { if (categoryFilter().getDataStore()) categoryFilter().getDataStore()->removeListener(dsListener_); } -void CategoryFilterWidget2::setDataStore(simData::DataStore* dataStore) +void CategoryFilterWidget::setDataStore(simData::DataStore* dataStore) { simData::DataStore* prevDataStore = categoryFilter().getDataStore(); if (prevDataStore == dataStore) @@ -2100,32 +2061,32 @@ void CategoryFilterWidget2::setDataStore(simData::DataStore* dataStore) dataStore->addListener(dsListener_); } -void CategoryFilterWidget2::setSettings(Settings* settings, const QString& settingsKeyPrefix) +void CategoryFilterWidget::setSettings(Settings* settings, const QString& settingsKeyPrefix) { treeModel_->setSettings(settings, settingsKeyPrefix); } -const simData::CategoryFilter& CategoryFilterWidget2::categoryFilter() const +const simData::CategoryFilter& CategoryFilterWidget::categoryFilter() const { return treeModel_->categoryFilter(); } -void CategoryFilterWidget2::setFilter(const simData::CategoryFilter& categoryFilter) +void CategoryFilterWidget::setFilter(const simData::CategoryFilter& categoryFilter) { treeModel_->setFilter(categoryFilter); } -void CategoryFilterWidget2::processCategoryCounts(const simQt::CategoryCountResults& results) +void CategoryFilterWidget::processCategoryCounts(const simQt::CategoryCountResults& results) { treeModel_->processCategoryCounts(results); } -bool CategoryFilterWidget2::showEntityCount() const +bool CategoryFilterWidget::showEntityCount() const { return showEntityCount_; } -void CategoryFilterWidget2::setShowEntityCount(bool fl) +void CategoryFilterWidget::setShowEntityCount(bool fl) { if (fl == showEntityCount_) return; @@ -2150,7 +2111,7 @@ void CategoryFilterWidget2::setShowEntityCount(bool fl) } } -void CategoryFilterWidget2::expandAfterFilterEdited_(const QString& filterText) +void CategoryFilterWidget::expandAfterFilterEdited_(const QString& filterText) { if (filterText.isEmpty()) { @@ -2170,7 +2131,7 @@ void CategoryFilterWidget2::expandAfterFilterEdited_(const QString& filterText) } } -void CategoryFilterWidget2::expandDueToProxy_(const QModelIndex& parentIndex, int to, int from) +void CategoryFilterWidget::expandDueToProxy_(const QModelIndex& parentIndex, int to, int from) { // Only expand when we're actively filtering, because we want // to see rows that match the active filter as they show up @@ -2198,12 +2159,12 @@ void CategoryFilterWidget2::expandDueToProxy_(const QModelIndex& parentIndex, in } } -void CategoryFilterWidget2::toggleExpanded_(const QModelIndex& proxyIndex) +void CategoryFilterWidget::toggleExpanded_(const QModelIndex& proxyIndex) { treeView_->setExpanded(proxyIndex, !treeView_->isExpanded(proxyIndex)); } -void CategoryFilterWidget2::resetFilter_() +void CategoryFilterWidget::resetFilter_() { // Create a new empty filter using same data store const simData::CategoryFilter newFilter(treeModel_->categoryFilter().getDataStore()); @@ -2214,15 +2175,15 @@ void CategoryFilterWidget2::resetFilter_() emit filterEdited(treeModel_->categoryFilter()); } -void CategoryFilterWidget2::showContextMenu_(const QPoint& point) +void CategoryFilterWidget::showContextMenu_(const QPoint& point) { QMenu contextMenu(this); contextMenu.addActions(treeView_->actions()); // Mark the RegExp and Lock actions enabled or disabled based on current state const QModelIndex idx = treeView_->indexAt(point); - const bool emptyRegExp = idx.data(CategoryTreeModel2::ROLE_REGEXP_STRING).toString().isEmpty(); - const bool locked = idx.data(CategoryTreeModel2::ROLE_LOCKED_STATE).toBool(); + const bool emptyRegExp = idx.data(CategoryTreeModel::ROLE_REGEXP_STRING).toString().isEmpty(); + const bool locked = idx.data(CategoryTreeModel::ROLE_LOCKED_STATE).toBool(); if (locked && !emptyRegExp) assert(0); // Should not be possible to have a RegExp set on a locked category setRegExpAction_->setProperty("index", idx); @@ -2248,7 +2209,7 @@ void CategoryFilterWidget2::showContextMenu_(const QPoint& point) toggleLockCategoryAction_->setProperty("index", QVariant()); } -void CategoryFilterWidget2::setRegularExpression_() +void CategoryFilterWidget::setRegularExpression_() { // Make sure we have a sender and can pull out the index. If not, return QObject* senderObject = sender(); @@ -2259,11 +2220,11 @@ void CategoryFilterWidget2::setRegularExpression_() showRegExpEditGui_(index); } -void CategoryFilterWidget2::showRegExpEditGui_(const QModelIndex& index) +void CategoryFilterWidget::showRegExpEditGui_(const QModelIndex& index) { // Grab category name and old regexp, then ask user for new value - const QString oldRegExp = index.data(CategoryTreeModel2::ROLE_REGEXP_STRING).toString(); - const QString categoryName = index.data(CategoryTreeModel2::ROLE_CATEGORY_NAME).toString(); + const QString oldRegExp = index.data(CategoryTreeModel::ROLE_REGEXP_STRING).toString(); + const QString categoryName = index.data(CategoryTreeModel::ROLE_CATEGORY_NAME).toString(); // pop up dialog with a entity filter line edit that supports formatting regexp QDialog optionsDialog(this); @@ -2292,11 +2253,11 @@ void CategoryFilterWidget2::showRegExpEditGui_(const QModelIndex& index) // index.model() is const because changes to the model might invalidate indices. Since we know this // and no longer use the index after this call, it is safe to use const_cast here to use setData(). QAbstractItemModel* model = const_cast(index.model()); - model->setData(index, lineEdit->text(), CategoryTreeModel2::ROLE_REGEXP_STRING); + model->setData(index, lineEdit->text(), CategoryTreeModel::ROLE_REGEXP_STRING); } } -void CategoryFilterWidget2::clearRegularExpression_() +void CategoryFilterWidget::clearRegularExpression_() { // Make sure we have a sender and can pull out the index. If not, return QObject* senderObject = sender(); @@ -2308,10 +2269,10 @@ void CategoryFilterWidget2::clearRegularExpression_() // index.model() is const because changes to the model might invalidate indices. Since we know this // and no longer use the index after this call, it is safe to use const_cast here to use setData(). QAbstractItemModel* model = const_cast(index.model()); - model->setData(index, QString(""), CategoryTreeModel2::ROLE_REGEXP_STRING); + model->setData(index, QString(""), CategoryTreeModel::ROLE_REGEXP_STRING); } -void CategoryFilterWidget2::toggleLockCategory_() +void CategoryFilterWidget::toggleLockCategory_() { // Make sure we have a sender and can pull out the index. If not, return QObject* senderObject = sender(); @@ -2321,7 +2282,7 @@ void CategoryFilterWidget2::toggleLockCategory_() if (!index.isValid()) return; - const bool locked = index.data(CategoryTreeModel2::ROLE_LOCKED_STATE).toBool(); + const bool locked = index.data(CategoryTreeModel::ROLE_LOCKED_STATE).toBool(); if (!locked) { @@ -2342,21 +2303,21 @@ void CategoryFilterWidget2::toggleLockCategory_() // and no longer use the index after this call, it is safe to use const_cast here to use setData(). QAbstractItemModel* model = const_cast(index.model()); // Unlock the category - model->setData(index, !locked, CategoryTreeModel2::ROLE_LOCKED_STATE); + model->setData(index, !locked, CategoryTreeModel::ROLE_LOCKED_STATE); } -void CategoryFilterWidget2::expandUnlockedCategories_() +void CategoryFilterWidget::expandUnlockedCategories_() { // Expand each category if it isn't locked for (int i = 0; i < proxy_->rowCount(); ++i) { const QModelIndex& idx = proxy_->index(i, 0); - if (!idx.data(CategoryTreeModel2::ROLE_LOCKED_STATE).toBool()) + if (!idx.data(CategoryTreeModel::ROLE_LOCKED_STATE).toBool()) treeView_->setExpanded(idx, true); } } -void CategoryFilterWidget2::recountCategories_() +void CategoryFilterWidget::recountCategories_() { if (countDirty_) { diff --git a/SDK/simQt/CategoryTreeModel2.h b/SDK/simQt/CategoryTreeModel2.h index 19adac1d9..bd8ed9e70 100644 --- a/SDK/simQt/CategoryTreeModel2.h +++ b/SDK/simQt/CategoryTreeModel2.h @@ -19,8 +19,8 @@ * disclose, or release this software. * */ -#ifndef SIMQT_CATEGORYTREEMODEL2_H -#define SIMQT_CATEGORYTREEMODEL2_H +#ifndef SIMQT_CATEGORYTREEMODEL_H +#define SIMQT_CATEGORYTREEMODEL_H #include #include @@ -91,9 +91,6 @@ class SDKQT_EXPORT CategoryProxyModel : public QSortFilterProxyModel explicit CategoryProxyModel(QObject *parent = 0); virtual ~CategoryProxyModel(); - /** Override setSourceModel() to detect the "All Items" model type */ - virtual void setSourceModel(QAbstractItemModel* sourceModel); - public slots: /// string to filter against void setFilterText(const QString& filter); @@ -107,17 +104,15 @@ public slots: private: /// string to filter against QString filter_; - /// Set true when "All Categories" is the root item (i.e. using CategoryTreeModel, not CategoryTreeModel2) - bool hasAllCategories_; }; /** Single tier tree model that maintains and allows users to edit a simData::CategoryFilter. */ -class SDKQT_EXPORT CategoryTreeModel2 : public QAbstractItemModel +class SDKQT_EXPORT CategoryTreeModel : public QAbstractItemModel { Q_OBJECT; public: - explicit CategoryTreeModel2(QObject* parent = NULL); - virtual ~CategoryTreeModel2(); + explicit CategoryTreeModel(QObject* parent = NULL); + virtual ~CategoryTreeModel(); /** Changes the data store, updating what categories and values are shown. */ void setDataStore(simData::DataStore* dataStore); @@ -203,10 +198,15 @@ public slots: QString settingsKey_; }; +// Typedef to CategoryTreeModel2 for backwards compatibility +#ifdef USE_DEPRECATED_SIMDISSDK_API +typedef CategoryTreeModel CategoryTreeModel2; +#endif + /** - * Item delegate that provides custom styling for a QTreeView with a CategoryTreeModel2. This + * Item delegate that provides custom styling for a QTreeView with a CategoryTreeModel. This * delegate is required in order to get "Unlisted Value" editing working properly with - * CategoryTreeModel2. The Unlisted Value editing is shown as an EXCLUDE flag on the category + * CategoryTreeModel. The Unlisted Value editing is shown as an EXCLUDE flag on the category * itself, using a toggle switch to draw the on/off state. Clicking on the toggle will change * the value in the tree model and therefore in the filter. * @@ -273,16 +273,16 @@ class SDKQT_EXPORT CategoryTreeItemDelegate : public QStyledItemDelegate /** * Widget that includes a QTreeView with a Category Tree Model and a Search Filter * widget that will display a given category filter. This is an easy-to-use wrapper - * around the CategoryTreeModel2 class that provides a view widget and search field. + * around the CategoryTreeModel class that provides a view widget and search field. */ -class SDKQT_EXPORT CategoryFilterWidget2 : public QWidget +class SDKQT_EXPORT CategoryFilterWidget : public QWidget { Q_OBJECT; Q_PROPERTY(bool showEntityCount READ showEntityCount WRITE setShowEntityCount); public: - explicit CategoryFilterWidget2(QWidget* parent = 0); - virtual ~CategoryFilterWidget2(); + explicit CategoryFilterWidget(QWidget* parent = 0); + virtual ~CategoryFilterWidget(); /** Sets the data store, updating the category tree based on changes to that data store. */ void setDataStore(simData::DataStore* dataStore); @@ -340,7 +340,7 @@ private slots: /** The tree */ QTreeView* treeView_; /** Hold the category data */ - simQt::CategoryTreeModel2* treeModel_; + simQt::CategoryTreeModel* treeModel_; /** Provides sorting and filtering */ simQt::CategoryProxyModel* proxy_; /** If true the category values are filtered; used to conditionally expand tree. */ @@ -361,6 +361,11 @@ private slots: bool countDirty_; }; +// Typedef to CategoryFilterWidget2 for backwards compatibility +#ifdef USE_DEPRECATED_SIMDISSDK_API +typedef CategoryFilterWidget CategoryFilterWidget2; +#endif + } -#endif /* SIMQT_CATEGORYTREEMODEL2_H */ +#endif /* SIMQT_CATEGORYTREEMODEL_H */ diff --git a/SDK/simQt/EntityCategoryFilter.cpp b/SDK/simQt/EntityCategoryFilter.cpp index bdbc00006..ea6389603 100644 --- a/SDK/simQt/EntityCategoryFilter.cpp +++ b/SDK/simQt/EntityCategoryFilter.cpp @@ -20,7 +20,6 @@ * */ #include "simData/CategoryData/CategoryFilter.h" -#include "simQt/CategoryFilterWidget.h" #include "simQt/CategoryTreeModel2.h" #include "simQt/RegExpImpl.h" #include "simQt/EntityCategoryFilter.h" @@ -55,25 +54,13 @@ QWidget* EntityCategoryFilter::widget(QWidget* newWidgetParent) const break; case SHOW_WIDGET: { - CategoryFilterWidget2* rv = new CategoryFilterWidget2(newWidgetParent); + CategoryFilterWidget* rv = new CategoryFilterWidget(newWidgetParent); rv->setDataStore(categoryFilter_->getDataStore()); rv->setFilter(*categoryFilter_); rv->setSettings(settings_, settingsKeyPrefix_); bindToWidget(rv); return rv; } - case SHOW_LEGACY_WIDGET: - { -#ifdef USE_DEPRECATED_SIMDISSDK_API - CategoryFilterWidget* rv = new CategoryFilterWidget(newWidgetParent); - rv->setProviders(categoryFilter_->getDataStore()); - rv->setFilter(*categoryFilter_); - bindToWidget(rv); - return rv; -#else - return NULL; -#endif - } } return NULL; @@ -104,7 +91,7 @@ void EntityCategoryFilter::setFilterSettings(const QMap& sett } } -void EntityCategoryFilter::bindToWidget(CategoryFilterWidget2* widget) const +void EntityCategoryFilter::bindToWidget(CategoryFilterWidget* widget) const { // Whenever the filter updates in the GUI, update our internal filter, // which then in turn emits filterUpdated(). @@ -114,15 +101,6 @@ void EntityCategoryFilter::bindToWidget(CategoryFilterWidget2* widget) const connect(this, SIGNAL(categoryFilterChanged(simData::CategoryFilter)), widget, SLOT(setFilter(simData::CategoryFilter))); } -#ifdef USE_DEPRECATED_SIMDISSDK_API -void EntityCategoryFilter::bindToWidget(CategoryFilterWidget* widget) const -{ - // connect to the signals/slots between the gui and the filter so changes to one will update the other - connect(widget, SIGNAL(categoryFilterChanged(const simData::CategoryFilter&)), this, SLOT(setCategoryFilterFromGui_(const simData::CategoryFilter&))); - connect(this, SIGNAL(categoryFilterChanged(simData::CategoryFilter)), widget, SLOT(setFilter(simData::CategoryFilter))); -} -#endif - void EntityCategoryFilter::setCategoryFilter(const simData::CategoryFilter& categoryFilter) { if ((*categoryFilter_) == categoryFilter) diff --git a/SDK/simQt/EntityCategoryFilter.h b/SDK/simQt/EntityCategoryFilter.h index 59980ef98..66bef59c4 100644 --- a/SDK/simQt/EntityCategoryFilter.h +++ b/SDK/simQt/EntityCategoryFilter.h @@ -32,11 +32,7 @@ namespace simData { namespace simQt { - -#ifdef USE_DEPRECATED_SIMDISSDK_API class CategoryFilterWidget; -#endif -class CategoryFilterWidget2; class Settings; /** @@ -52,10 +48,8 @@ class SDKQT_EXPORT EntityCategoryFilter : public EntityFilter { /** widget() will return NULL, creating nothing when integrated into Qt. */ NO_WIDGET, - /** widget() will return a CategoryFilterWidget2, the new style of category filtering. */ - SHOW_WIDGET, - /** widget() will return a CategoryFilterWidget, the old legacy style of category filtering. */ - SHOW_LEGACY_WIDGET + /** widget() will return a CategoryFilterWidget, the new style of category filtering. */ + SHOW_WIDGET }; /** @@ -90,19 +84,15 @@ class SDKQT_EXPORT EntityCategoryFilter : public EntityFilter virtual void setFilterSettings(const QMap& settings); /** - * Bind this filter to a CategoryFilterWidget2 so that changes to either widget updates the other widget. + * Bind this filter to a CategoryFilterWidget so that changes to either widget updates the other widget. * @param widget to be bound */ - void bindToWidget(CategoryFilterWidget2* widget) const; -#ifdef USE_DEPRECATED_SIMDISSDK_API - /** Category Filter Widget (legacy style) variant of bindToWidget() */ void bindToWidget(CategoryFilterWidget* widget) const; -#endif /** Retrieves the current category filter. */ const simData::CategoryFilter& categoryFilter() const; - /** Set the settings object and key prefix that gets used by the CategoryFilterWidget2 */ + /** Set the settings object and key prefix that gets used by the CategoryFilterWidget */ void setSettings(Settings* settings, const QString& settingsKeyPrefix); public slots: From 05588dbc205945f3c1603488ad94799afa6ddfa4 Mon Sep 17 00:00:00 2001 From: Colin McNulty Date: Tue, 17 Dec 2019 15:14:12 -0500 Subject: [PATCH 005/121] DEV: CategoryTreeModel2 file rename. Addresses SIM-10800. Review 20155 --- Plugins/QtDesignerWidgets/CMakeLists.txt | 4 ++-- ...FilterWidget2Plugin.cpp => CategoryFilterWidgetPlugin.cpp} | 4 ++-- ...goryFilterWidget2Plugin.h => CategoryFilterWidgetPlugin.h} | 0 Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp | 2 +- SDK/simQt/CMakeLists.txt | 4 ++-- SDK/simQt/{CategoryTreeModel2.cpp => CategoryTreeModel.cpp} | 2 +- SDK/simQt/{CategoryTreeModel2.h => CategoryTreeModel.h} | 0 SDK/simQt/EntityCategoryFilter.cpp | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) rename Plugins/QtDesignerWidgets/{CategoryFilterWidget2Plugin.cpp => CategoryFilterWidgetPlugin.cpp} (98%) rename Plugins/QtDesignerWidgets/{CategoryFilterWidget2Plugin.h => CategoryFilterWidgetPlugin.h} (100%) rename SDK/simQt/{CategoryTreeModel2.cpp => CategoryTreeModel.cpp} (99%) rename SDK/simQt/{CategoryTreeModel2.h => CategoryTreeModel.h} (100%) diff --git a/Plugins/QtDesignerWidgets/CMakeLists.txt b/Plugins/QtDesignerWidgets/CMakeLists.txt index 35f6f3e69..dfc363099 100644 --- a/Plugins/QtDesignerWidgets/CMakeLists.txt +++ b/Plugins/QtDesignerWidgets/CMakeLists.txt @@ -8,7 +8,7 @@ project(PLUGIN_SIMQT_DESIGNER_PLUGINS) set(PROJ_HEADERS simQtDesignerPlugins.h CategoryDataBreadcrumbsPlugin.h - CategoryFilterWidget2Plugin.h + CategoryFilterWidgetPlugin.h ColorButtonPlugin.h ColorWidgetPlugin.h DataTableComboBoxPlugin.h @@ -30,7 +30,7 @@ set(PROJ_HEADERS # .cpp files set(PROJ_SOURCES CategoryDataBreadcrumbsPlugin.cpp - CategoryFilterWidget2Plugin.cpp + CategoryFilterWidgetPlugin.cpp ColorButtonPlugin.cpp ColorWidgetPlugin.cpp DataTableComboBoxPlugin.cpp diff --git a/Plugins/QtDesignerWidgets/CategoryFilterWidget2Plugin.cpp b/Plugins/QtDesignerWidgets/CategoryFilterWidgetPlugin.cpp similarity index 98% rename from Plugins/QtDesignerWidgets/CategoryFilterWidget2Plugin.cpp rename to Plugins/QtDesignerWidgets/CategoryFilterWidgetPlugin.cpp index f37e86955..d2ca14957 100644 --- a/Plugins/QtDesignerWidgets/CategoryFilterWidget2Plugin.cpp +++ b/Plugins/QtDesignerWidgets/CategoryFilterWidgetPlugin.cpp @@ -23,8 +23,8 @@ #include "simData/CategoryData/CategoryFilter.h" #include "simData/CategoryData/CategoryNameManager.h" #include "simData/MemoryDataStore.h" -#include "simQt/CategoryTreeModel2.h" -#include "CategoryFilterWidget2Plugin.h" +#include "simQt/CategoryTreeModel.h" +#include "CategoryFilterWidgetPlugin.h" CategoryFilterWidgetPlugin::CategoryFilterWidgetPlugin(QObject *parent) : QObject(parent), diff --git a/Plugins/QtDesignerWidgets/CategoryFilterWidget2Plugin.h b/Plugins/QtDesignerWidgets/CategoryFilterWidgetPlugin.h similarity index 100% rename from Plugins/QtDesignerWidgets/CategoryFilterWidget2Plugin.h rename to Plugins/QtDesignerWidgets/CategoryFilterWidgetPlugin.h diff --git a/Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp b/Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp index 9aee3fb1c..7fd640c40 100644 --- a/Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp +++ b/Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp @@ -26,7 +26,7 @@ #endif #include "ColorWidgetPlugin.h" #include "CategoryDataBreadcrumbsPlugin.h" -#include "CategoryFilterWidget2Plugin.h" +#include "CategoryFilterWidgetPlugin.h" #include "DataTableComboBoxPlugin.h" #include "DirectorySelectorWidgetPlugin.h" #include "DockWidgetPlugin.h" diff --git a/SDK/simQt/CMakeLists.txt b/SDK/simQt/CMakeLists.txt index 39cf1b7ae..3a68bea63 100644 --- a/SDK/simQt/CMakeLists.txt +++ b/SDK/simQt/CMakeLists.txt @@ -65,7 +65,7 @@ if(TARGET simData) list(APPEND SIMQT_HEADERS_TO_MOC ${SIMQT_INC}CategoryDataBreadcrumbs.h ${SIMQT_INC}CategoryFilterCounter.h - ${SIMQT_INC}CategoryTreeModel2.h + ${SIMQT_INC}CategoryTreeModel.h ${SIMQT_INC}DataTableComboBox.h ${SIMQT_INC}DataTableModel.h ${SIMQT_INC}EntityCategoryFilter.h @@ -185,7 +185,7 @@ if(TARGET simData) list(APPEND SIMQT_SOURCES ${SIMQT_SRC}CategoryDataBreadcrumbs.cpp ${SIMQT_SRC}CategoryFilterCounter.cpp - ${SIMQT_SRC}CategoryTreeModel2.cpp + ${SIMQT_SRC}CategoryTreeModel.cpp ${SIMQT_SRC}DataTableComboBox.cpp ${SIMQT_SRC}DataTableModel.cpp ${SIMQT_SRC}EntityCategoryFilter.cpp diff --git a/SDK/simQt/CategoryTreeModel2.cpp b/SDK/simQt/CategoryTreeModel.cpp similarity index 99% rename from SDK/simQt/CategoryTreeModel2.cpp rename to SDK/simQt/CategoryTreeModel.cpp index eab70e03f..0db844928 100644 --- a/SDK/simQt/CategoryTreeModel2.cpp +++ b/SDK/simQt/CategoryTreeModel.cpp @@ -44,7 +44,7 @@ #include "simQt/RegExpImpl.h" #include "simQt/SearchLineEdit.h" #include "simQt/Settings.h" -#include "simQt/CategoryTreeModel2.h" +#include "simQt/CategoryTreeModel.h" namespace simQt { diff --git a/SDK/simQt/CategoryTreeModel2.h b/SDK/simQt/CategoryTreeModel.h similarity index 100% rename from SDK/simQt/CategoryTreeModel2.h rename to SDK/simQt/CategoryTreeModel.h diff --git a/SDK/simQt/EntityCategoryFilter.cpp b/SDK/simQt/EntityCategoryFilter.cpp index ea6389603..6dc46216d 100644 --- a/SDK/simQt/EntityCategoryFilter.cpp +++ b/SDK/simQt/EntityCategoryFilter.cpp @@ -20,7 +20,7 @@ * */ #include "simData/CategoryData/CategoryFilter.h" -#include "simQt/CategoryTreeModel2.h" +#include "simQt/CategoryTreeModel.h" #include "simQt/RegExpImpl.h" #include "simQt/EntityCategoryFilter.h" From 4828a1b703514d5f6093173915c4f5645d47b49a Mon Sep 17 00:00:00 2001 From: Andrew LaFrance Date: Tue, 17 Dec 2019 17:06:50 -0500 Subject: [PATCH 006/121] Addendum to Review 20155, fixing SDK_Examples build. Full build also succeeds now. Approved by Dan. --- Examples/QtCategoryFilterTest/MainWindow.ui | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Examples/QtCategoryFilterTest/MainWindow.ui b/Examples/QtCategoryFilterTest/MainWindow.ui index 1b75ad1b5..ebbcd51b8 100644 --- a/Examples/QtCategoryFilterTest/MainWindow.ui +++ b/Examples/QtCategoryFilterTest/MainWindow.ui @@ -20,7 +20,7 @@ - + @@ -65,9 +65,9 @@
simQt/CategoryDataBreadcrumbs.h
- simQt::CategoryFilterWidget2 + simQt::CategoryFilterWidget QWidget -
simQt/CategoryTreeModel2.h
+
simQt/CategoryTreeModel.h
From ef0f0f9c0f3877d768ab8bb97f7b83ecf0d90efd Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Wed, 18 Dec 2019 12:53:55 -0500 Subject: [PATCH 007/121] DEV: Declutter property is now properly set for the TextSymbol, based on the value of priority preference. This allows Callout technique to omit a single label, just like can be done for the Labels technique. Fixes SIM-10816 request. Review: 20178 --- SDK/simVis/EntityLabel.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SDK/simVis/EntityLabel.cpp b/SDK/simVis/EntityLabel.cpp index 066b3b9aa..0625acbcb 100644 --- a/SDK/simVis/EntityLabel.cpp +++ b/SDK/simVis/EntityLabel.cpp @@ -140,6 +140,7 @@ void EntityLabelNode::update(const simData::CommonPrefs& commonPrefs, const std: PB_FIELD_CHANGED(&lastLabelPrefs, &labelPrefs, textoutline) || PB_FIELD_CHANGED(&lastLabelPrefs, &labelPrefs, backdroptype) || PB_FIELD_CHANGED(&lastLabelPrefs, &labelPrefs, alignment) || + PB_FIELD_CHANGED(&lastLabelPrefs, &labelPrefs, priority) || PB_FIELD_CHANGED(&lastLabelPrefs, &labelPrefs, backdropimplementation); // update the style: @@ -151,6 +152,9 @@ void EntityLabelNode::update(const simData::CommonPrefs& commonPrefs, const std: ts->pixelOffset() = osg::Vec2s(labelPrefs.offsetx(), labelPrefs.offsety()); ts->encoding() = osgEarth::TextSymbol::ENCODING_UTF8; + // Declutter is off if priority is negative + ts->declutter() = (labelPrefs.priority() >= 0); + // text color: osg::Vec4 color = ColorUtils::RgbaToVec4(labelPrefs.color()); ts->fill() = osgEarth::Fill(color.r(), color.g(), color.b(), color.a()); From 2adc08bbf61a4423612371e7f814e0fcd63ba666 Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Fri, 3 Jan 2020 15:36:59 -0500 Subject: [PATCH 008/121] DEV: SDK: TimeTicks added to simVis Platform fist pass, SIM-4428, review 20218 --- SDK/simVis/CMakeLists.txt | 4 + SDK/simVis/Platform.cpp | 71 +++- SDK/simVis/Platform.h | 3 + SDK/simVis/TimeTicks.cpp | 702 ++++++++++++++++++++++++++++++++++ SDK/simVis/TimeTicks.h | 222 +++++++++++ SDK/simVis/TimeTicksChunk.cpp | 259 +++++++++++++ SDK/simVis/TimeTicksChunk.h | 120 ++++++ SDK/simVis/TrackChunkNode.cpp | 195 +++++----- SDK/simVis/TrackChunkNode.h | 295 +++++++------- 9 files changed, 1627 insertions(+), 244 deletions(-) create mode 100644 SDK/simVis/TimeTicks.cpp create mode 100644 SDK/simVis/TimeTicks.h create mode 100644 SDK/simVis/TimeTicksChunk.cpp create mode 100644 SDK/simVis/TimeTicksChunk.h diff --git a/SDK/simVis/CMakeLists.txt b/SDK/simVis/CMakeLists.txt index c8c9be815..4cb56237f 100644 --- a/SDK/simVis/CMakeLists.txt +++ b/SDK/simVis/CMakeLists.txt @@ -122,6 +122,8 @@ set(VIS_HEADERS_CORE ${VIS_INC}SphericalVolume.h ${VIS_INC}TargetDelegation.h ${VIS_INC}Text.h + ${VIS_INC}TimeTicks.h + ${VIS_INC}TimeTicksChunk.h ${VIS_INC}Tool.h ${VIS_INC}TrackChunkNode.h ${VIS_INC}TrackHistory.h @@ -263,6 +265,8 @@ set(VIS_SOURCES_CORE ${VIS_SRC}SphericalVolume.cpp ${VIS_SRC}TargetDelegation.cpp ${VIS_SRC}Text.cpp + ${VIS_SRC}TimeTicks.cpp + ${VIS_SRC}TimeTicksChunk.cpp ${VIS_SRC}TrackChunkNode.cpp ${VIS_SRC}TrackHistory.cpp ${VIS_SRC}Utils.cpp diff --git a/SDK/simVis/Platform.cpp b/SDK/simVis/Platform.cpp index 3cd553ae4..38fc728f6 100644 --- a/SDK/simVis/Platform.cpp +++ b/SDK/simVis/Platform.cpp @@ -37,6 +37,7 @@ #include "simVis/PlatformModel.h" #include "simVis/RadialLOSNode.h" #include "simVis/Registry.h" +#include "simVis/TimeTicks.h" #include "simVis/TrackHistory.h" #include "simVis/Utils.h" #include "simVis/VelocityVector.h" @@ -160,6 +161,7 @@ lastUpdateTime_(-std::numeric_limits::max()), firstHistoryTime_(std::numeric_limits::max()), expireModeGroupAttach_(expireModeGroupAttach), track_(NULL), +timeTicks_(NULL), localGrid_(NULL), bodyAxisVector_(NULL), inertialAxisVector_(NULL), @@ -205,6 +207,9 @@ PlatformNode::~PlatformNode() if (track_.valid()) expireModeGroup_->removeChild(track_); track_ = NULL; + if (timeTicks_.valid()) + expireModeGroup_->removeChild(timeTicks_); + timeTicks_ = NULL; if (expireModeGroupAttach_.valid()) expireModeGroupAttach_->removeChild(expireModeGroup_); @@ -285,6 +290,8 @@ void PlatformNode::setPrefs(const simData::PlatformPrefs& prefs) { // normal processing: update the track history data track_->setPrefs(prefs, lastProps_); + if (timeTicks_.valid()) + timeTicks_->setPrefs(prefs, lastProps_); // track_ cannot be valid without having had platform prefs set at least once; // if assert fails, check whether prefs are initialized correctly when platform is created @@ -296,15 +303,25 @@ void PlatformNode::setPrefs(const simData::PlatformPrefs& prefs) // track history is constrained by platform data limiting track_->reset(); track_->update(); + // time ticks follows data limiting same as track history + if (timeTicks_.valid()) + { + timeTicks_->reset(); + timeTicks_->update(); + } } - if (track_.valid()) - track_->setNodeMask(prefsDraw ? simVis::DISPLAY_MASK_TRACK_HISTORY : simVis::DISPLAY_MASK_NONE); + track_->setNodeMask(prefsDraw ? simVis::DISPLAY_MASK_TRACK_HISTORY : simVis::DISPLAY_MASK_NONE); + if (timeTicks_.valid()) + timeTicks_->setNodeMask(prefsDraw ? simVis::DISPLAY_MASK_TRACK_HISTORY : simVis::DISPLAY_MASK_NONE); } } else { expireModeGroup_->removeChild(track_); track_ = NULL; + // time ticks is always hidden if track history is hidden + expireModeGroup_->removeChild(timeTicks_); + timeTicks_ = NULL; } // validate localgrid prefs changes that might provide user notifications @@ -481,6 +498,8 @@ bool PlatformNode::updateFromDataStore(const simData::DataSliceBase* updateSlice if (!updateSlice->hasChanged() && !force && !forceUpdateFromDataStore_) { + if (timeTicks_.valid()) + timeTicks_->update(); // Even if the platform has not changed, the label can still change - entity name could change as a result of category data, for example. updateLabel_(lastPrefs_); return false; @@ -534,15 +553,28 @@ bool PlatformNode::updateFromDataStore(const simData::DataSliceBase* updateSlice { if (!track_.valid()) createTrackHistoryNode_(lastPrefs_); - else if (timeChanged || updateSlice->hasChanged()) - track_->update(); + else + { + if (timeChanged || updateSlice->hasChanged()) + track_->update(); + // always update time ticks + if (timeTicks_.valid()) + timeTicks_->update(); + } } - else if (track_.valid()) + else { - expireModeGroup_->removeChild(track_); - track_ = NULL; + if (track_.valid()) + { + expireModeGroup_->removeChild(track_); + track_ = NULL; + } + if (timeTicks_.valid()) + { + expireModeGroup_->removeChild(timeTicks_); + timeTicks_ = NULL; + } } - // avoid applying a null update over and over if (!updateSlice->current() && getNodeMask() == DISPLAY_MASK_NONE && !valid_) return false; @@ -605,8 +637,29 @@ bool PlatformNode::createTrackHistoryNode_(const simData::PlatformPrefs& prefs) track_->setPrefs(prefs, lastProps_, true); updateHostBounds_(prefs.scale()); track_->update(); + const bool prefsDraw = lastPrefs_.commonprefs().datadraw() && prefs.commonprefs().draw(); track_->setNodeMask(prefsDraw ? simVis::DISPLAY_MASK_TRACK_HISTORY : simVis::DISPLAY_MASK_NONE); + + // TODO: SIM-4428 draw time ticks will be controlled by a separate pref + //createTimeTicks_(prefs); + + return true; +} + +bool PlatformNode::createTimeTicks_(const simData::PlatformPrefs& prefs) +{ + // if assert fails, check that callers only call on !valid() condition + assert(!timeTicks_.valid()); + + timeTicks_ = new TimeTicks(ds_, getLocator()->getSRS(), platformTspiFilterManager_, getId()); + expireModeGroup_->addChild(timeTicks_); + timeTicks_->setPrefs(prefs, lastProps_, true); + timeTicks_->update(); + + const bool prefsDraw = lastPrefs_.commonprefs().datadraw() && prefs.commonprefs().draw(); + timeTicks_->setNodeMask(prefsDraw ? simVis::DISPLAY_MASK_TRACK_HISTORY : simVis::DISPLAY_MASK_NONE); + return true; } @@ -615,6 +668,8 @@ void PlatformNode::updateClockMode(const simCore::Clock* clock) // notify the track history of a change in time direction if (track_.valid()) track_->updateClockMode(clock); + if (timeTicks_.valid()) + timeTicks_->updateClockMode(clock); } void PlatformNode::flush() diff --git a/SDK/simVis/Platform.h b/SDK/simVis/Platform.h index 9b37e5608..3db313d49 100644 --- a/SDK/simVis/Platform.h +++ b/SDK/simVis/Platform.h @@ -43,6 +43,7 @@ class PlatformModelNode; class PlatformTspiFilterManager; class ProjectorNode; class RadialLOSNode; +class TimeTicks; class TrackHistoryNode; class VelocityVector; @@ -295,6 +296,7 @@ class SDKVIS_EXPORT PlatformNode : public EntityNode void updateHostBounds_(double scale); void updateLabel_(const simData::PlatformPrefs& prefs); bool createTrackHistoryNode_(const simData::PlatformPrefs& prefs); + bool createTimeTicks_(const simData::PlatformPrefs& prefs); void updateOrRemoveBodyAxis_(bool prefsDraw, const simData::PlatformPrefs& prefs); void updateOrRemoveInertialAxis_(bool prefsDraw, const simData::PlatformPrefs& prefs); void updateOrRemoveVelocityVector_(bool prefsDraw, const simData::PlatformPrefs& prefs); @@ -323,6 +325,7 @@ class SDKVIS_EXPORT PlatformNode : public EntityNode osg::observer_ptr expireModeGroupAttach_; /// track history points osg::ref_ptr track_; + osg::ref_ptr timeTicks_; osg::ref_ptr localGrid_; osg::ref_ptr highlight_; osg::ref_ptr bodyAxisVector_; diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp new file mode 100644 index 000000000..f0d8f4718 --- /dev/null +++ b/SDK/simVis/TimeTicks.cpp @@ -0,0 +1,702 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ +#include + +#include "osg/Depth" +#include "osgText/Text" +#include "osgEarth/Capabilities" +#include "osgEarth/Horizon" +#include "osgEarth/LabelNode" +#include "osgEarth/LineDrawable" +#include "osgEarth/Registry" +#include "osgEarth/VirtualProgram" + +#include "simCore/Calc/Angle.h" +#include "simCore/Calc/Calculations.h" +#include "simCore/Time/TimeClass.h" +#include "simCore/Time/String.h" +#include "simData/DataTable.h" +#include "simVis/AlphaTest.h" +#include "simVis/Constants.h" +#include "simVis/Locator.h" +#include "simVis/OverheadMode.h" +#include "simVis/PlatformFilter.h" +#include "simVis/PointSize.h" +#include "simVis/Shaders.h" +#include "simVis/TimeTicksChunk.h" +#include "simVis/Types.h" +#include "simVis/Utils.h" +#include "simVis/TimeTicks.h" + +namespace simVis +{ + +namespace +{ + // TODO: these will be prefs, SIM-4428 + static const double TIME_INTERVAL_SMALL_SECS = 10; + static const double TIME_INTERVAL_LARGE_SECS = 6 * TIME_INTERVAL_SMALL_SECS; + static const int TICK_TYPE = 1; // 0 = point, 1 = line + static const double TICK_WIDTH = 40; + static const double TICK_LINE_WIDTH = 2; + static const int LABEL_FONT_SIZE = 30; + + // follow track history flat mode + static const std::string SIMVIS_TRACK_FLATMODE = "simvis_track_flatmode"; +} + + +/// constructor. +TimeTicks::TimeTicks(const simData::DataStore& ds, const osgEarth::SpatialReference* srs, PlatformTspiFilterManager& platformTspiFilterManager, simData::ObjectId entityId) + : ds_(ds), + supportsShaders_(osgEarth::Registry::capabilities().supportsGLSL(3.3f)), + chunkSize_(64), // keep this lowish or your app won't scale. + color_(osg::Vec4f(1.0, 1.0, 1.0, 0.5)), + totalPoints_(0), + hasLastDrawTime_(false), + lastDrawTime_(0.0), + lastCurrentTime_(-1.0), + lastLargeTickTime_(-1.0), + timeDirection_(simCore::FORWARD), + chunkGroup_(NULL), + labelGroup_(NULL), + platformTspiFilterManager_(platformTspiFilterManager), + entityId_(entityId), + currentPointChunk_(NULL) +{ + updateSliceBase_ = ds_.platformUpdateSlice(entityId); + assert(updateSliceBase_); // should be a valid update slice before time tick is created + + locator_ = new simVis::Locator(srs); + + setNodeMask(simVis::DISPLAY_MASK_TRACK_HISTORY); + + reset(); + + // configure the local state set + simVis::setLighting(getOrCreateStateSet(), 0); + + // flatten in overhead mode. + simVis::OverheadMode::enableGeometryFlattening(true, this); +} + +TimeTicks::~TimeTicks() +{ + chunkGroup_ = NULL; + labelGroup_ = NULL; + currentPointChunk_ = NULL; + locator_ = NULL; +} + +void TimeTicks::reset() +{ + // blow everything away + removeChildren(0, getNumChildren()); + labels_.clear(); + + hasLastDrawTime_ = false; + lastCurrentTime_ = -1.0; + totalPoints_ = 0; + chunkGroup_ = new osg::Group(); + labelGroup_ = new osg::Group(); + addChild(labelGroup_); + addChild(chunkGroup_); + currentPointChunk_ = NULL; + lastLargeTickTime_ = -1.0; +} + +TimeTicksChunk* TimeTicks::getCurrentChunk_() +{ + // see if there's already a chunk we can use. + unsigned int num = chunkGroup_->getNumChildren(); + if (num > 0) + { + TimeTicksChunk* chunk = static_cast(chunkGroup_->getChild(num - 1)); + if (!chunk->isFull()) + { + // yes. + return chunk; + } + } + return NULL; +} + +TimeTicksChunk* TimeTicks::getLastChunk_() +{ + unsigned int num = chunkGroup_->getNumChildren(); + if (num > 0) + { + TimeTicksChunk* chunk = static_cast(chunkGroup_->getChild(num - 1)); + return chunk; + } + return NULL; +} + +TimeTicksChunk* TimeTicks::getFirstChunk_() +{ + unsigned int num = chunkGroup_->getNumChildren(); + if (num > 0) + { + TimeTicksChunk* chunk = static_cast(chunkGroup_->getChild(0)); + return chunk; + } + return NULL; +} + +double TimeTicks::toDrawTime_(double updateTime) const +{ + return updateTime * ((timeDirection_ == simCore::REVERSE) ? -1.0 : 1.0); +} + +void TimeTicks::addUpdate_(double tickTime) +{ + const simData::PlatformUpdateSlice* updateSlice = static_cast(updateSliceBase_); + if (updateSlice == NULL) + { + // a valid/active platform must have an updateSlice - if assert fails, ensure that time ticks is not being updated for a non valid platform + assert(0); + return; + } + auto iter = updateSlice->lower_bound(tickTime); + if (!iter.hasNext()) + return; + + bool hasPrevious = iter.hasPrevious(); + auto prevIter = iter; + const simData::PlatformUpdate* prev = prevIter.previous(); + const simData::PlatformUpdate* update = iter.next(); + osg::Matrix hostMatrix; + + bool largeTick = false; + // if first tick, get the current platform position + if (chunkGroup_->getNumChildren() == 0) + { + if (!getMatrix_(*update, hostMatrix)) + return; + // first tick is always large + if (lastLargeTickTime_ == -1) + { + largeTick = true; + lastLargeTickTime_ = tickTime; + } + } + // not first tick, get the next position, possibly interpolated + else if (hasPrevious) + { + if (!getMatrix_(*prev, *update, tickTime, hostMatrix)) + return; + // check to see if it is time for the next large tick + if (lastLargeTickTime_ == -1.0 || abs(tickTime - lastLargeTickTime_) >= TIME_INTERVAL_LARGE_SECS) + { + lastLargeTickTime_ = tickTime; + largeTick = true; + } + } + else + return; + + // add label for large tick TODO: SIM-4428 this might be a separate pref to define label interval + if (largeTick) + { + int refYear = 1970; + simData::DataStore::Transaction t; + const simData::ScenarioProperties* sp = ds_.scenarioProperties(&t); + if (sp) + refYear = sp->referenceyear(); + + simCore::TimeStamp textTime(refYear, tickTime); + simCore::HoursTimeFormatter fmt; + std::string labelText = fmt.toString(textTime, refYear, 0); + + osg::MatrixTransform* xform = new osg::MatrixTransform(); + osgText::Text* text = new osgText::Text(); + text->setPosition(osg::Vec3(0, 0, 0)); + text->setText(labelText); + text->setFont(osgEarth::Registry::instance()->getDefaultFont()); + text->setAutoRotateToScreen(true); + text->setCharacterSizeMode(osgText::TextBase::OBJECT_COORDS); + text->setAlignment(osgText::TextBase::LEFT_BOTTOM); + text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT); + text->setCharacterSize(LABEL_FONT_SIZE); + text->getOrCreateStateSet()->setRenderBinToInherit(); + osg::Depth* noDepthTest = new osg::Depth(osg::Depth::ALWAYS, 0, 1, false); + text->getOrCreateStateSet()->setAttributeAndModes(noDepthTest, 1); + xform->addChild(text); + xform->setMatrix(hostMatrix); + labelGroup_->addChild(xform); + labels_[toDrawTime_(tickTime)] = xform; + } + + // get a chunk to which to add the new point, creating a new one if necessary + TimeTicksChunk* chunk = getCurrentChunk_(); + if (!chunk) + { + // allocate a new chunk + TimeTicksChunk::Type type = ((TICK_TYPE == 0) ? TimeTicksChunk::POINT_TICKS : TimeTicksChunk::LINE_TICKS); + chunk = new TimeTicksChunk(chunkSize_, type, TICK_WIDTH, TICK_WIDTH * 2); + + // if there is a preceding chunk, duplicate its last point so there is no + // discontinuity from previous chunk to this new chunk - this matters for line drawing mode + int numc = chunkGroup_->getNumChildren(); + if (numc > 0) + { + osg::Matrix last; + if (getLastChunk_()->getEndMatrix(last) == 0) + { + double last_t = getLastChunk_()->getEndTime(); + chunk->addPoint(last, last_t, color_, largeTick); + } + } + + // add the new chunk and update its appearance + chunkGroup_->addChild(chunk); + chunk->addCullCallback(new osgEarth::HorizonCullCallback()); + } + + const double drawTime = toDrawTime_(tickTime); + + // add the point (along with its timestamp) + bool addSuccess = chunk->addPoint(hostMatrix, drawTime, color_, largeTick); + if (!addSuccess) + { + // if assert fails, check that getCurrentChunk_ and previous code ensure that either chunk is not full, or new chunk created + assert(0); + } + else + totalPoints_++; + + // record time of last draw update - must be an actual point time that can be found in the chunk + // in forward mode, lastDrawTime_ represents the newest time tick + // in reverse mode, lastDrawTime_ represents the earliest time tick + lastDrawTime_ = drawTime; + hasLastDrawTime_ = true; + +} + +void TimeTicks::updateClockMode(const simCore::Clock* clock) +{ + // STOP does not require any change in time ticks + if (clock->timeDirection() == simCore::STOP) + return; + + // we only care about fwd-rev, rev-fwd, including fwd-stop-rev and rev-stop-fwd + if (timeDirection_ != clock->timeDirection()) + { + // clear time ticks + reset(); + timeDirection_ = clock->timeDirection(); + update(); + } +} + +void TimeTicks::removePointsOlderThan_(double oldestDrawTime) +{ + if (!labels_.empty()) + { + auto iter = labels_.begin(); + while (!labels_.empty() && iter->first < oldestDrawTime) + { + labelGroup_->removeChild(iter->second); + labels_.erase(iter); + iter = labels_.begin(); + } + } + while (chunkGroup_->getNumChildren() > 0) + { + TimeTicksChunk* oldest = static_cast(chunkGroup_->getChild(0)); + unsigned int numRemoved = oldest->removePointsBefore(oldestDrawTime); + totalPoints_ -= numRemoved; + if (oldest->size() == 0) + { + chunkGroup_->removeChild(0, 1); + if (chunkGroup_->getNumChildren() > 0) + { + // Last point was duplicated to prevent discontinuity, remove it + static_cast(chunkGroup_->getChild(0))->removeOldestPoint(); + } + else // removal logic is faulty in chunk + assert(totalPoints_ == 0); + } + else + break; + } +} + +void TimeTicks::updateVisibility_(const simData::TrackPrefs& prefs) +{ + const bool invisible = (prefs.trackdrawmode() == simData::TrackPrefs::OFF); + setNodeMask(invisible ? simVis::DISPLAY_MASK_NONE : simVis::DISPLAY_MASK_TRACK_HISTORY); +} + +void TimeTicks::updateFlatMode_(bool flatMode) +{ + if (!supportsShaders_) + return; + + if (!flatModeUniform_.valid()) + { + if (flatMode == false) + return; // Does not exist and not needed so return; + + osg::StateSet* stateset = this->getOrCreateStateSet(); + flatModeUniform_ = stateset->getOrCreateUniform(SIMVIS_TRACK_FLATMODE, osg::Uniform::BOOL); + } + + flatModeUniform_->set(flatMode); +} + +void TimeTicks::setPrefs(const simData::PlatformPrefs& platformPrefs, const simData::PlatformProperties& platformProps, bool force) +{ + const simData::TrackPrefs& prefs = platformPrefs.trackprefs(); + // lastPlatformPrefs_ will not have data that represents current state on initial call + // force should be true in this case; + // in any case, if force is set, we should not test on lastPlatformPrefs_ + const simData::TrackPrefs& lastPrefs = lastPlatformPrefs_.trackprefs(); + + // platform should be deleting track when trackdrawmode turned off, this should never be called with trackdrawmode off + // if assert fails, check platform setPrefs logic that processes prefs.trackprefs().trackdrawmode() + assert(prefs.trackdrawmode() != simData::TrackPrefs_Mode_OFF); + bool resetRequested = false; + + if (force || PB_FIELD_CHANGED(&lastPrefs, &prefs, tracklength)) + { + // clear the time ticks and recreate + resetRequested = true; + } + + if (force || PB_FIELD_CHANGED(&lastPrefs, &prefs, flatmode)) + { + updateFlatMode_(prefs.flatmode()); + } + + if (force || PB_FIELD_CHANGED(&lastPlatformPrefs_, &platformPrefs, useclampalt) || + PB_FIELD_CHANGED(&lastPlatformPrefs_, &platformPrefs, clampvalaltmin) || + PB_FIELD_CHANGED(&lastPlatformPrefs_, &platformPrefs, clampvalaltmax) || + PB_FIELD_CHANGED(&lastPlatformPrefs_, &platformPrefs, surfaceclamping)) + { + // Did not test for the clamped angles since they are intended for stationary platforms + resetRequested = true; + } + + // TODO: SIM-4428 update linewidth and other time tick specific prefs + osg::StateSet* stateSet = this->getOrCreateStateSet(); + osgEarth::LineDrawable::setLineWidth(stateSet, TICK_LINE_WIDTH); + + lastPlatformPrefs_ = platformPrefs; + lastPlatformProps_ = platformProps; + + if (resetRequested) + { + reset(); + update(); + } + updateVisibility_(prefs); +} + +void TimeTicks::update() +{ + // tracklength 0 means no time ticks are shown + if (lastPlatformPrefs_.trackprefs().tracklength() == 0) + return; + + const simData::PlatformUpdateSlice* updateSlice = static_cast(updateSliceBase_); + if (updateSlice == NULL) + { + // a valid/active platform must have an updateSlice - if assert fails, ensure that time ticks is not being updated for a non valid platform + assert(0); + return; + } + + // if the current is not valid, and scenario is prior to first update time, nothing to do + if (updateSlice->current() == NULL && ds_.updateTime() < updateSlice->firstTime()) + { + // platform is not valid, this should only occur during platform creation + return; + } + + // ignore static platforms + if (updateSlice->current() && updateSlice->current()->time() == -1) + { + // time ticks should never be created for a static platform. - see PlatformNode::createTimeTicks_ + assert(0); + return; + } + + // update time ticks to match current time window + updateTrackData_(ds_.updateTime(), *updateSlice); +} + +void TimeTicks::updateTrackData_(double currentTime, const simData::PlatformUpdateSlice& updateSlice) +{ + // determine the time window that time ticks should display + double endTime = currentTime; + double beginTime = updateSlice.firstTime(); + int trackLength = lastPlatformPrefs_.trackprefs().tracklength(); + if (trackLength > 0 && (endTime - trackLength) > beginTime) + beginTime = endTime - trackLength; + + // if there is an existing time ticks, determine if we can add only new points; this should be the case for normal time movement + if (hasLastDrawTime_) + { + if (timeDirection_ == simCore::FORWARD) + { + // backward jump (e.g. time slider move) while in forward mode in time requires reset() + if (currentTime < lastCurrentTime_) + { + reset(); + // assume now going in reverse, so switch direction + timeDirection_ = simCore::REVERSE; + } + else + { + // enforce tracklength/data limiting prefs - remove all points older than new begin time + removePointsOlderThan_(beginTime); + // if new window overlaps previous window, then reuse existing points, only add the new points + if (lastDrawTime_ >= beginTime) + { + // adjust beginTime so that we add only new points, avoid re-adding points that are still in the history + beginTime = FLT_EPSILON + lastDrawTime_; + } + } + } + else if (timeDirection_ == simCore::REVERSE) + { + // forward jump in time (e.g. time slider move) while in reverse mode requires reset + if (currentTime > lastCurrentTime_) + { + reset(); + // assume now going forward, so switch direction + timeDirection_ = simCore::FORWARD; + } + else + { + // remove all points with drawtime "older" than reverse mode end drawtime; i.e., remove all points with time newer than current time + removePointsOlderThan_(toDrawTime_(endTime)); + // if new window overlaps previous window, then reuse existing points, only add the new points + if (toDrawTime_(lastDrawTime_) <= endTime) + { + // adjust endTime so that we add only new points, and avoid re-adding points that are still in the history + endTime = -FLT_EPSILON + toDrawTime_(lastDrawTime_); + } + } + } + } + + // store currentTime to enable time jump detection + lastCurrentTime_ = currentTime; + + // update time ticks with points in the requested window + backfillHistory_(endTime, beginTime); + + // when the current point is interpolated, line mode requires special processing + updateCurrentPoint_(updateSlice, beginTime); +} + +void TimeTicks::backfillHistory_(double endTime, double beginTime) +{ + if (timeDirection_ == simCore::FORWARD) + { + double tickTime = beginTime; + // if there is already a chunk, start counting from its end time + simVis::TimeTicksChunk* lastChunk = getLastChunk_(); + if (lastChunk) + tickTime = lastChunk->getEndTime() + TIME_INTERVAL_SMALL_SECS; + + while (tickTime <= endTime) + { + addUpdate_(tickTime); + tickTime += TIME_INTERVAL_SMALL_SECS; + } + } + else + { + double tickTime = endTime; + // if there is already a chunk, start counting from its end time + simVis::TimeTicksChunk* lastChunk = getLastChunk_(); + if (lastChunk) + tickTime = toDrawTime_(lastChunk->getEndTime()) - TIME_INTERVAL_SMALL_SECS; + + while (tickTime >= beginTime) + { + addUpdate_(tickTime); + tickTime -= TIME_INTERVAL_SMALL_SECS; + } + } +} + +void TimeTicks::updateCurrentPoint_(const simData::PlatformUpdateSlice& updateSlice, double beginTime) +{ + // remove previous, will recreate if needed + if (currentPointChunk_ != NULL) + currentPointChunk_->reset(); + + // no current point if not line ticks + if (TICK_TYPE == 0) + return; + + // only line, ribbon, and bridge draw modes require this processing, + // but if there is not a previous point, there is nothing to do + if (chunkGroup_->getNumChildren() == 0) + return; + + // create the special chunk for rendering the interpolated point, has two points to connect to rest of history for line mode + if (currentPointChunk_ == NULL) + { + currentPointChunk_ = new TimeTicksChunk(2, TimeTicksChunk::LINE, TICK_WIDTH, TICK_WIDTH * 2); + if (currentPointChunk_ == NULL) + return; + addChild(currentPointChunk_); + } + // find the most current update, either whatever is current, or the last available update + const simData::PlatformUpdate* current = updateSlice.current(); + if (current == NULL) + { + simData::PlatformUpdateSlice::Iterator iter = updateSlice.lower_bound(updateSlice.lastTime()); + current = iter.next(); + } + osg::Matrix curMatrix; + + // if this fails, this platform node got created with no platform data + assert(current); + + if (!getMatrix_(*current, curMatrix)) + { + // failed to get the current position, check locator + assert(0); + return; + } + + if (timeDirection_ == simCore::FORWARD) + { + TimeTicksChunk* curChunk = getLastChunk_(); + // should have a last chunk if chunk group is not empty + assert(curChunk != NULL); + osg::Matrix end; + if (curChunk->getEndMatrix(end) == 0) + currentPointChunk_->addPoint(end, curChunk->getEndTime(), color_, false); + else + assert(0); // chunk is out of sync + } + + // points must be added in order of increasing drawTime + currentPointChunk_->addPoint(curMatrix, toDrawTime_(beginTime), color_, false); + + // duplicate the most recent (non-current) datapoint so that this chunk connects to the previous chunk + if (timeDirection_ == simCore::REVERSE) + { + TimeTicksChunk* curChunk = getLastChunk_(); + curChunk = getFirstChunk_(); + // should have a first chunk if chunk group is not empty + assert(curChunk != NULL); + osg::Matrix begin; + if (curChunk->getBeginMatrix(begin) == 0) + currentPointChunk_->addPoint(begin, curChunk->getBeginTime(), color_, false); + else + assert(0); // chunk is out of sync + } +} + +bool TimeTicks::getMatrix_(const simData::PlatformUpdate& u, osg::Matrix& hostMatrix) +{ + simData::PlatformUpdate update = u; + if (platformTspiFilterManager_.filter(update, lastPlatformPrefs_, lastPlatformProps_) == PlatformTspiFilterManager::POINT_DROPPED) + return false; + + // update our locator for the current update + simCore::Coordinate ecefCoord( + simCore::COORD_SYS_ECEF, + simCore::Vec3(update.x(), update.y(), update.z()), + simCore::Vec3(update.psi(), update.theta(), update.phi())); + + locator_->setCoordinate(ecefCoord, u.time()); + + // fetch the positioning matrix from the locator we are tracking + if (!locator_->getLocatorMatrix(hostMatrix)) + { + // if assert fails, check that invalid platform updates are not being sent to track + assert(0); + return false; + } + + return true; +} + +bool TimeTicks::getMatrix_(const simData::PlatformUpdate& prevPoint, const simData::PlatformUpdate& curPoint, double time, osg::Matrix& hostMatrix) +{ + simData::PlatformUpdate prevUpdate = prevPoint; + simData::PlatformUpdate curUpdate = curPoint; + // apply filters, which may change position values + if (platformTspiFilterManager_.filter(curUpdate, lastPlatformPrefs_, lastPlatformProps_) == PlatformTspiFilterManager::POINT_DROPPED + || platformTspiFilterManager_.filter(prevUpdate, lastPlatformPrefs_, lastPlatformProps_) == PlatformTspiFilterManager::POINT_DROPPED) + return false; + + simData::Interpolator* li = ds_.interpolator(); + simData::PlatformUpdate platformUpdate = curUpdate; + if (curUpdate.time() != time) + li->interpolate(time, prevUpdate, curUpdate, &platformUpdate); + + simCore::Coordinate ecefCoordCur(simCore::COORD_SYS_ECEF, simCore::Vec3(platformUpdate.x(), platformUpdate.y(), platformUpdate.z())); + + // for point ticks, only need the position + if (TICK_TYPE == 0) + { + locator_->setCoordinate(ecefCoordCur, time); + + // fetch the positioning matrix from the locator we are tracking + if (locator_->getLocatorMatrix(hostMatrix)) + return true; + else + { + // if assert fails, check that invalid platform updates are not being sent to track + assert(0); + return false; + } + } + + // for line ticks, need to calculate the orientation as well as the position + + simCore::Coordinate ecefCoordPrev(simCore::COORD_SYS_ECEF, simCore::Vec3(prevUpdate.x(), prevUpdate.y(), prevUpdate.z())); + simCore::Coordinate llaCoordPrev; + simCore::CoordinateConverter::convertEcefToGeodetic(ecefCoordPrev, llaCoordPrev); + simCore::Coordinate llaCoordCur; + simCore::CoordinateConverter::convertEcefToGeodetic(ecefCoordCur, llaCoordCur); + + double az = 0; + simCore::sodanoInverse(llaCoordPrev.lat(), llaCoordPrev.lon(), 0, llaCoordCur.lat(), llaCoordCur.lon(), &az); + simCore::Vec3 ecefOri; + simCore::CoordinateConverter::convertGeodeticOriToEcef(llaCoordCur.position(), simCore::Vec3(az, 0, 0), ecefOri); + // update our locator for the current update + simCore::Coordinate finalCoord(simCore::COORD_SYS_ECEF, simCore::Vec3(platformUpdate.x(), platformUpdate.y(), platformUpdate.z()), ecefOri); + + locator_->setCoordinate(finalCoord, time); + + // fetch the positioning matrix from the locator we are tracking + if (!locator_->getLocatorMatrix(hostMatrix)) + { + // if assert fails, check that invalid platform updates are not being sent to track + assert(0); + return false; + } + return true; +} + +} diff --git a/SDK/simVis/TimeTicks.h b/SDK/simVis/TimeTicks.h new file mode 100644 index 000000000..d3994526c --- /dev/null +++ b/SDK/simVis/TimeTicks.h @@ -0,0 +1,222 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ +#ifndef SIMVIS_TIME_TICKS_H +#define SIMVIS_TIME_TICKS_H + +#include "simCore/Time/Clock.h" +#include "simData/DataSlice.h" +#include "simData/DataTable.h" +#include "osg/Geode" +#include "osg/MatrixTransform" +#include "simVis/Types.h" + +//---------------------------------------------------------------------------- +namespace osgEarth +{ + class LineDrawable; + class SpatialReference; +} +namespace simData +{ + class DataStore; + class PlatformPrefs; + class TrackPrefs; + class DataSliceBase; +} + +namespace simVis +{ +class Locator; +class TimeTicksChunk; +class PlatformTspiFilterManager; + +/** + * Scene graph node that depicts a time ticks trail for a platform + */ +class SDKVIS_EXPORT TimeTicks : public osg::Group +{ +public: + TimeTicks(const simData::DataStore& ds, const osgEarth::SpatialReference* srs, PlatformTspiFilterManager& manager, simData::ObjectId entityId); + + /** + * Reset the time ticks visualization, erasing everything that exists + * so it can start building again from scratch. + */ + void reset(); + + /** + * Accesses the updates for the associated platform and adds points, using current prefs settings + * This method is intended to update the time ticks in normal operation, as well as to recreate the time ticks in response to user action + * This may be slow if track history preferences are set to display many points, since time ticks match track history for data limiting. + * Time ticks will be created from the first available update time, factoring in data limiting and track length, up to the current scenario time + * or up to the last update time if the scenario time is past the end of the data history, interpolating at a specified interval. + */ + void update(); + + /** + * Update the time ticks based on the change in the Clock mode, e.g. to + * change the time direction. + * @param clock Clock that might have changed. + */ + void updateClockMode(const simCore::Clock* clock); + + /** + * Sets new preferences for this object. + * @param[in ] platformPrefs Preferences to apply + * @param[in ] platformProps Properties for the platform + * @param[in ] force Apply them even if the current settings already match + */ + void setPrefs(const simData::PlatformPrefs& platformPrefs, const simData::PlatformProperties& platformProps, bool force = false); + + /** Return the proper library name */ + virtual const char* libraryName() const { return "simVis"; } + + /** Return the class name */ + virtual const char* className() const { return "TimeTicks"; } + +protected: // methods + /// osg::Referenced-derived + virtual ~TimeTicks(); + +private: // methods + + /** Copy constructor, not implemented or available. */ + TimeTicks(const TimeTicks&); + + /** + * Return a chunk to which you can add a new point + * @return chunk that can accept a new point, or NULL if a new one needs to be created + */ + TimeTicksChunk* getCurrentChunk_(); + + /** + * Return the last chunk in the group, + * @return last chunk, or NULL if group is empty + */ + TimeTicksChunk* getLastChunk_(); + + /** + * Return the first chunk in the group + * @return first chunk, or NULL if group is empty + */ + TimeTicksChunk* getFirstChunk_(); + + /// Update the "flat mode" setting that zeros out the time ticks altitude; initialize shader programs if necessary + void updateFlatMode_(bool enabled); + + /// Update the draw flag + void updateVisibility_(const simData::TrackPrefs& prefs); + + /** + * Remove all points with draw times older than specified time + * @param oldestDrawTime oldest draw time that will remain in time ticks + */ + void removePointsOlderThan_(double oldestDrawTime); + + /** + * Determines the time window that time ticks should display, then + * determines what needs to be done to display that window, then + * adds required datapoints. + * @param currentTime latest time to display + * @param updateSlice platform update slice for associated platform to get current time + */ + void updateTrackData_(double currentTime, const simData::PlatformUpdateSlice& updateSlice); + + /** + * Accesses the updates for the associated platform and adds points for the interval [beginTime, endTime] + * This may be slow depending on how may points must be backfilled + * @param endTime last time to be added + * @param beginTime starting time for points to be added + */ + void backfillHistory_(double endTime, double beginTime); + + /** + * Update the time ticks visuals for the current point when drawing line ticks + * @param updateSlice platform update slice for associated platform + * @param beginTime earliest platform update time to use when going in reverse + */ + void updateCurrentPoint_(const simData::PlatformUpdateSlice& updateSlice, double beginTime); + + /** + * Update the time ticks visuals with a point to correspond to the specified time + * @param tickTime time to draw a tick + */ + void addUpdate_(double tickTime); + + /** + * Convert update time to draw time + * To support REVERSE playback mode, we play a little trick and simply negate + * the time so that time always appears to be increasing from the perspective + * of the rendering code. We do this to avoid adding complex logic in the rendering + * code for handling bi-directional track drawing. + * Throughout this class, we use the term "draw time" to represent the adjusted + * unidirectional time, versus "update time" which is the actual time in the + * data store. + * @param updateTime platform update time + * @return draw time that corresponds to the update time + */ + double toDrawTime_(double updateTime) const; + + /// utility function to get an OSG ENU matrix that corresponds to platform update's position and orientation + bool getMatrix_(const simData::PlatformUpdate& u, osg::Matrix& hostMatrix); + /// utility function to get an OSG ENU matrix that corresponds to the platform position at time, interpolated between the prevPoint and curPoint + bool getMatrix_(const simData::PlatformUpdate& prevPoint, const simData::PlatformUpdate& curPoint, double time, osg::Matrix& hostMatrix); + +private: // data + /// data store for initializing data slice + const simData::DataStore& ds_; + /// flag indicates if current system supports using shaders + bool supportsShaders_; + + simData::PlatformPrefs lastPlatformPrefs_; + simData::PlatformProperties lastPlatformProps_; + unsigned int chunkSize_; + osg::Vec4f color_; + unsigned int totalPoints_; + + // "draw time" is the same as the clock's update time, but adjusted + // for time direction. i.e. it will be negated in the case of simCore::REVERSE. + bool hasLastDrawTime_; + double lastDrawTime_; + double lastCurrentTime_; + double lastLargeTickTime_; + + // Playback direction (follows a datastore-bound Clock). + simCore::TimeDirection timeDirection_; + + osg::ref_ptr flatModeUniform_; + osg::ref_ptr chunkGroup_; + osg::ref_ptr labelGroup_; + std::map labels_; + + const simData::DataSliceBase* updateSliceBase_; + PlatformTspiFilterManager& platformTspiFilterManager_; + /// entity id for the platform + simData::ObjectId entityId_; + + osg::ref_ptr currentPointChunk_; + osg::ref_ptr locator_; +}; + +} // namespace simVis + +#endif // SIMVIS_TIME_TICKS_H diff --git a/SDK/simVis/TimeTicksChunk.cpp b/SDK/simVis/TimeTicksChunk.cpp new file mode 100644 index 000000000..1917cfc53 --- /dev/null +++ b/SDK/simVis/TimeTicksChunk.cpp @@ -0,0 +1,259 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ +#include +#include "osg/Geode" +#include "osg/Geometry" +#include "osgText/Text" +#include "osgEarth/GeoData" +#include "osgEarth/LineDrawable" +#include "simVis/PointSize.h" +#include "simVis/Types.h" +#include "simVis/TimeTicksChunk.h" + +namespace simVis +{ +// TODO: SIM-4428 these will likely be prefs, possibly derived from tick linewidth +static const int POINT_SIZE = 4; +static const int LARGE_POINT_SIZE = 8; + +TimeTicksChunk::TimeTicksChunk(unsigned int maxSize, Type type, double lineTickWidth, double largeLineTickWidth) + : TrackPointsChunk(maxSize), + type_(type), + lineTickWidth_(lineTickWidth), + largeLineTickWidth_(largeLineTickWidth) +{ + allocate_(); +} + +TimeTicksChunk::~TimeTicksChunk() +{ + geode_ = NULL; + line_ = NULL; + point_ = NULL; + largePoint_ = NULL; + line_ = NULL; +} + +bool TimeTicksChunk::addPoint(const osg::Matrix& matrix, double time, const osg::Vec4& color, bool large) +{ + // first make sure there's room. + if (isFull()) + return false; + + // if this is the first point added, set up the localization matrix. + if (offset_ == 0 && count_ == 0) + { + world2local_.invert(matrix); + setMatrix(matrix); + } + + // record the timestamp and world coords + times_[offset_ + count_] = time; + worldCoords_[offset_ + count_] = matrix; + + // resolve the localized point and append it to the various geometries. + append_(matrix, color, large); + + // advance the counter and update the psets. + count_++; + updatePrimitiveSets_(); + + return true; +} + +int TimeTicksChunk::getBeginMatrix(osg::Matrix& begin) const +{ + if (count_ < 1) + return 1; + begin = worldCoords_[offset_]; + return 0; +} + +int TimeTicksChunk::getEndMatrix(osg::Matrix& end) const +{ + if (count_ < 1) + return 1; + end = worldCoords_[offset_ + count_-1]; + return 0; +} + +void TimeTicksChunk::allocate_() +{ + // clear existing: + removeChildren(0, getNumChildren()); + + // timestamp vector. + times_.resize(maxSize_); + times_[0] = 0.0; + worldCoords_.resize(maxSize_); + + // pointers into the points list. + offset_ = 0; + count_ = 0; + + if (type_ == POINT_TICKS) + { + // large points + largePoint_ = new osg::Geometry(); + largePoint_->setUseVertexBufferObjects(true); + largePoint_->setUseDisplayList(false); + largePoint_->setDataVariance(osg::Object::DYNAMIC); + osg::Vec3Array* largeVerts = new osg::Vec3Array(); + largeVerts->assign(maxSize_, osg::Vec3()); + largePoint_->setVertexArray(largeVerts); + osg::Vec4Array* largeColors = new osg::Vec4Array(); + largeColors->setBinding(osg::Array::BIND_PER_VERTEX); + largeColors->assign(maxSize_, osg::Vec4(0, 0, 0, 0)); + largePoint_->setColorArray(largeColors); + largePoint_->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, offset_, count_)); + addChild(largePoint_.get()); + PointSize::setValues(largePoint_->getOrCreateStateSet(), LARGE_POINT_SIZE, osg::StateAttribute::ON); + + // points + point_ = new osg::Geometry(); + point_->setUseVertexBufferObjects(true); + point_->setUseDisplayList(false); + point_->setDataVariance(osg::Object::DYNAMIC); + osg::Vec3Array* verts = new osg::Vec3Array(); + verts->assign(maxSize_, osg::Vec3()); + point_->setVertexArray(verts); + osg::Vec4Array* colors = new osg::Vec4Array(); + colors->setBinding(osg::Array::BIND_PER_VERTEX); + colors->assign(maxSize_, simVis::Color::White); + point_->setColorArray(colors); + point_->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, offset_, count_)); + addChild(point_.get()); + PointSize::setValues(point_->getOrCreateStateSet(), POINT_SIZE, osg::StateAttribute::ON); + } + else if (type_ == LINE_TICKS) + { + // geode to hold all line geometry: + geode_ = new osgEarth::LineGroup(); + addChild(geode_.get()); + + // center line (line mode) + line_ = new osgEarth::LineDrawable(GL_LINE_STRIP); + line_->setDataVariance(osg::Object::DYNAMIC); + line_->allocate(4 * maxSize_); + geode_->addChild(line_.get()); + } + else if (type_ == LINE) + { + // geode to hold all line geometry: + geode_ = new osgEarth::LineGroup(); + addChild(geode_.get()); + + // center line (line mode) + line_ = new osgEarth::LineDrawable(GL_LINE_STRIP); + line_->setDataVariance(osg::Object::DYNAMIC); + line_->allocate(maxSize_); + geode_->addChild(line_.get()); + } + + // reset to identity matrices + world2local_ = osg::Matrixd::identity(); +} + +void TimeTicksChunk::append_(const osg::Matrix& matrix, const osg::Vec4& color, bool large) +{ + // calculate the local point. + const osg::Vec3d& world = matrix.getTrans(); + const osg::Vec3f local = world * world2local_; + + // insertion index: + const unsigned int i = offset_ + count_; + + if (type_ == POINT_TICKS) + { + if (large) + { + osg::Vec3Array* largeVerts = static_cast(largePoint_->getVertexArray()); + (*largeVerts)[i] = local; + largeVerts->dirty(); + osg::Vec4Array* largeColors = static_cast(largePoint_->getColorArray()); + (*largeColors)[i] = color; + largeColors->dirty(); + largePoint_->dirtyBound(); + } + osg::Vec3Array* pointVerts = static_cast(point_->getVertexArray()); + (*pointVerts)[i] = local; + pointVerts->dirty(); + osg::Vec4Array* colors = static_cast(point_->getColorArray()); + (*colors)[i] = color; + colors->dirty(); + point_->dirtyBound(); + } + else if (type_ == LINE_TICKS) + { + // add a new tick. The x value and y value for + // hostBounds represents the xMin and xMax values of a bounding box respectively. + const osg::Matrix posMatrix = matrix * world2local_; + + double width = (large ? largeLineTickWidth_ : lineTickWidth_); + + const osg::Vec3f left = osg::Vec3d(-width, 0.0, 0.0) * posMatrix; + const osg::Vec3f right = osg::Vec3d(width, 0.0, 0.0) * posMatrix; + + line_->setVertex(4 * i, local); + line_->setVertex(4 * i + 1, left); + line_->setVertex(4 * i + 2, right); + line_->setVertex(4 * i + 3, local); + + for (unsigned int c = 0; c < 4; ++c) + line_->setColor(4 * i + c, color); + } + else if (type_ == LINE) + { + line_->setVertex(i, local); + line_->setColor(i, color); + } +} + +void TimeTicksChunk::fixGraphicsAfterRemoval_() +{ + // no-op +} + +void TimeTicksChunk::updatePrimitiveSets_() +{ + if (type_ == POINT_TICKS) + { + osg::DrawArrays* pointSet = static_cast(point_->getPrimitiveSet(0)); + pointSet->setFirst(offset_); + pointSet->setCount(count_); + osg::DrawArrays* largeSet = static_cast(largePoint_->getPrimitiveSet(0)); + largeSet->setFirst(offset_); + largeSet->setCount(count_); + } + else if (type_ == LINE_TICKS) + { + line_->setFirst(4 * offset_); + line_->setCount(4 * count_); + } + else if (type_ == LINE) + { + line_->setFirst(offset_); + line_->setCount(count_); + } +} + +} diff --git a/SDK/simVis/TimeTicksChunk.h b/SDK/simVis/TimeTicksChunk.h new file mode 100644 index 000000000..e254b93b4 --- /dev/null +++ b/SDK/simVis/TimeTicksChunk.h @@ -0,0 +1,120 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ +#ifndef SIMVIS_TIME_TICKS_CHUNK_H +#define SIMVIS_TIME_TICKS_CHUNK_H + +#include +#include +#include "osg/ref_ptr" +#include "osg/MatrixTransform" +#include "simData/DataTypes.h" +#include "simVis/TrackChunkNode.h" + +namespace simVis +{ +/** Implementation of the TrackPointsChunk to draw track history time ticks */ +class SDKVIS_EXPORT TimeTicksChunk : public TrackPointsChunk +{ +public: + /// Draw mode for the time ticks + enum Type + { + POINT_TICKS, + LINE_TICKS, + LINE + }; + + /** + * Create a new chunk with a maximum size + * @param maxSize maximum chunk size, in points + * @param drawPoints if true draw point ticks, otherwise draw line ticks + */ + TimeTicksChunk(unsigned int maxSize, Type type, double lineTickWidth, double largeLineTickWidth); + + /** + * Add a new point to the chunk + * @param matrix the position matrix that corresponds to the platform position (may be interpolated) + * @param t time that corresponds to the platform update, seconds since scenario ref year + * @param color color to render this chunk + * @param large indicates if this is a large tick + * @return true if point was added + */ + bool addPoint(const osg::Matrix& matrix, double t, const osg::Vec4& color, bool large); + + /** + * Get the earliest position matrix added to the chunk, accounting for data limiting + * @param position matrix that corresponds to a platform position (may be interpolated) + * @return 0 on success, non-zero if chunk is empty + */ + int getBeginMatrix(osg::Matrix& first) const; + + /** + * Get the latest position matrix added to the chunk, accounting for data limiting + * @param position matrix that corresponds to a platform position (may be interpolated) + * @return 0 on success, non-zero if chunk is empty + */ + int getEndMatrix(osg::Matrix& last) const; + + /** Return the proper library name */ + virtual const char* libraryName() const { return "simVis"; } + + /** Return the class name */ + virtual const char* className() const { return "TimeTicksChunk"; } + +protected: + virtual ~TimeTicksChunk(); + +private: + /// Allocate the graphical elements for this chunk. + void allocate_(); + + /// Appends a new local point to each geometry set. + void append_(const osg::Matrix& matrix, const osg::Vec4& color, bool large); + + virtual void fixGraphicsAfterRemoval_(); + /// Update the offset and count on each primitive set to draw the proper data. + virtual void updatePrimitiveSets_(); + +private: + /// draw type + Type type_; + /// line tick width + double lineTickWidth_; + /// large line tick width + double largeLineTickWidth_; + ///container for drawables + osg::ref_ptr geode_; + /// point graphic + osg::ref_ptr point_; + /// point graphic for large points + osg::ref_ptr largePoint_; + /// line graphic + osg::ref_ptr line_; + /// matrix to convert from world to local coords + osg::Matrixd world2local_; + /// cache the world coordinates for quick access + std::vector worldCoords_; +}; + +} // namespace simVis + +#endif // SIMVIS_TIME_TICKS_CHUNK_H diff --git a/SDK/simVis/TrackChunkNode.cpp b/SDK/simVis/TrackChunkNode.cpp index 929e9e48a..d8cffb848 100644 --- a/SDK/simVis/TrackChunkNode.cpp +++ b/SDK/simVis/TrackChunkNode.cpp @@ -29,11 +29,92 @@ namespace simVis { +//---------------------------------------------------------------------------- +TrackPointsChunk::TrackPointsChunk(unsigned int maxSize) + : maxSize_(maxSize) +{ +} + +/// is this chunk full? i.e. no room for more points? +bool TrackPointsChunk::isFull() const +{ + return (offset_ + count_) >= maxSize_; +} + +/// how many points are rendered by this chunk? +unsigned int TrackPointsChunk::size() const +{ + return count_; +} + + +/// remove the oldest point in this chunk. +bool TrackPointsChunk::removeOldestPoint() +{ + if (count_ == 0) + return false; + + offset_++; + count_--; + updatePrimitiveSets_(); + // don't bother updating the bound. + + fixGraphicsAfterRemoval_(); + return true; +} + +/// remove points from the tail; return the number of points removed. +unsigned int TrackPointsChunk::removePointsBefore(double t) +{ + const unsigned int origOffset = offset_; + while (count_ > 0 && times_[offset_] < t) + { + offset_++; + count_--; + } + + if (origOffset != offset_) + { + updatePrimitiveSets_(); + // would normally dirtyBound(), but don't bother. + + // this does dirtyBound if ribbon mode + fixGraphicsAfterRemoval_(); + } + + return offset_ - origOffset; +} + +void TrackPointsChunk::reset() +{ + times_[0] = 0.0; + offset_ = 0; + count_ = 0; +} + +/// time of the first point in this chunk +double TrackPointsChunk::getBeginTime() const +{ + return count_ >= 1 ? times_[offset_] : -1.0; +} + +/// time of the last point in this chunk +double TrackPointsChunk::getEndTime() const +{ + return count_ >= 1 ? times_[offset_ + count_ - 1] : -1.0; +} + +/// is this chunk empty? +bool TrackPointsChunk::isEmpty_() const +{ + return count_ == 0; +} + //---------------------------------------------------------------------------- /** Creates a new chunk with a maximum size. */ TrackChunkNode::TrackChunkNode(unsigned int maxSize, const osgEarth::SpatialReference* srs, simData::TrackPrefs_Mode mode) - : maxSize_(maxSize), + : TrackPointsChunk(maxSize), srs_(srs), mode_(mode) { @@ -50,18 +131,6 @@ TrackChunkNode::~TrackChunkNode() srs_ = NULL; } -/// is this chunk full? i.e. no room for more points? -bool TrackChunkNode::isFull() const -{ - return (offset_ + count_) >= maxSize_; -} - -/// how many points are rendered by this chunk? -unsigned int TrackChunkNode::size() const -{ - return count_; -} - /// add a new point to the chunk. bool TrackChunkNode::addPoint(const osg::Matrix& matrix, double t, const osg::Vec4& color, const osg::Vec2& hostBounds) { @@ -99,51 +168,6 @@ bool TrackChunkNode::getNewestData(osg::Matrix& out_matrix, double& out_time) co return true; } -/// remove the oldest point in this chunk. -bool TrackChunkNode::removeOldestPoint() -{ - if (count_ == 0) - return false; - - offset_++; - count_--; - updatePrimitiveSets_(); - // don't bother updating the bound. - - // this does dirtyBound if ribbon mode - fixRibbon_(); - return true; -} - -/// remove points from the tail; return the number of points removed. -unsigned int TrackChunkNode::removePointsBefore(double t) -{ - const unsigned int origOffset = offset_; - while (count_ > 0 && times_[offset_] < t) - { - offset_++; - count_--; - } - - if (origOffset != offset_) - { - updatePrimitiveSets_(); - // would normally dirtyBound(), but don't bother. - - // this does dirtyBound if ribbon mode - fixRibbon_(); - } - - return offset_ - origOffset; -} - -void TrackChunkNode::reset() -{ - times_[0] = 0.0; - offset_ = 0; - count_ = 0; -} - /// allocate the graphical elements for this chunk. void TrackChunkNode::allocate_() { @@ -207,41 +231,6 @@ void TrackChunkNode::allocate_() world2local_ = osg::Matrixd::identity(); } -/// time of the first point in this chunk -double TrackChunkNode::getStartTime_() const -{ - return count_ >= 1 ? times_[offset_] : -1.0; -} - -/// time of the last point in this chunk -double TrackChunkNode::getEndTime_() const -{ - return count_ >= 1 ? times_[offset_+count_-1] : -1.0; -} - -/// is this chunk empty? -bool TrackChunkNode::isEmpty_() const -{ - return count_ == 0; -} - -/// remove all the points in this chunk that occur after the timestamp -unsigned int TrackChunkNode::removePointsAtAndBeyond_(double t) -{ - const unsigned int origCount = count_; - while (count_ > 0 && times_[offset_+count_-1] >= t) - { - count_--; - } - - if (origCount != count_) - { - updatePrimitiveSets_(); - } - - return origCount - count_; -} - /// appends a new local point to each geometry set. void TrackChunkNode::append_(const osg::Matrix& matrix, const osg::Vec4& color, const osg::Vec2& hostBounds) { @@ -255,12 +244,12 @@ void TrackChunkNode::append_(const osg::Matrix& matrix, const osg::Vec4& color, if (mode_ == simData::TrackPrefs_Mode_POINT) { // and update the center points track as well: - osg::Vec3Array& centerPointsVerts = static_cast(*centerPoints_->getVertexArray()); - centerPointsVerts[i] = local; - centerPointsVerts.dirty(); - osg::Vec4Array& centerPointsColors = static_cast(*centerPoints_->getColorArray()); - centerPointsColors[i] = color; - centerPointsColors.dirty(); + osg::Vec3Array* centerPointsVerts = static_cast(centerPoints_->getVertexArray()); + (*centerPointsVerts)[i] = local; + centerPointsVerts->dirty(); + osg::Vec4Array* centerPointsColors = static_cast(centerPoints_->getColorArray()); + (*centerPointsColors)[i] = color; + centerPointsColors->dirty(); centerPoints_->dirtyBound(); return; } @@ -314,9 +303,9 @@ void TrackChunkNode::updatePrimitiveSets_() { if (mode_ == simData::TrackPrefs_Mode_POINT) { - osg::DrawArrays& centerPointsPrimSet = static_cast(*centerPoints_->getPrimitiveSet(0)); - centerPointsPrimSet.setFirst(offset_); - centerPointsPrimSet.setCount(count_); + osg::DrawArrays* centerPointsPrimSet = static_cast(centerPoints_->getPrimitiveSet(0)); + centerPointsPrimSet->setFirst(offset_); + centerPointsPrimSet->setCount(count_); return; } @@ -338,7 +327,7 @@ void TrackChunkNode::updatePrimitiveSets_() } // only to be called when points are deleted, so that ribbon visual can be fixed to not show links to deleted point -void TrackChunkNode::fixRibbon_() +void TrackChunkNode::fixGraphicsAfterRemoval_() { if (mode_ == simData::TrackPrefs_Mode_RIBBON && !isEmpty_() && offset_ > 0) { diff --git a/SDK/simVis/TrackChunkNode.h b/SDK/simVis/TrackChunkNode.h index 5497feac1..dbc25aedd 100644 --- a/SDK/simVis/TrackChunkNode.h +++ b/SDK/simVis/TrackChunkNode.h @@ -24,147 +24,176 @@ #include "osg/ref_ptr" #include "osg/MatrixTransform" +#include "osgEarth/LineDrawable" #include "simData/DataTypes.h" -namespace osgEarth -{ - class LineDrawable; - class SpatialReference; +namespace osg { + class Geode; + class Geometry; } +namespace osgEarth { class SpatialReference; } + namespace simVis { +/** + * Node that renders a "chunk" of the track history trail points + * A full track history trail is segmented into chunks. This allows a + * number of things: + * + * - efficiently add points to the track (only need to update the last chunk) + * - efficiently maintain a limited track size (restricting the total number of points) + * - dealing with long tracks (eliminate jitter and improve culling) + * - manage memory effectively (always allocate buffer objects of exactly the same size, which OSG likes) + * + * Each chunk will hold a limited (and specific) number of points. Once + * the capacity of a chunk is exceeded, a new chunk gets appended to the + * graph. Similarly, when point-limiting is in effect, we can adjust the + * oldest chunk to "drop" points from the end of the track. + * + * Each chunk lives under its own MT to prevent single-precision jitter + * effects in a geocentric map. + * + * Note: Choose the Chunk Size carefully. Each chunk pre-allocates all the memory + * it will possibly need, so if you have a large number of entities with track + * histories, you can quickly run out of memory. +*/ +class SDKVIS_EXPORT TrackPointsChunk : public osg::MatrixTransform +{ +public: + /** + * Create a new chunk with a maximum size + * @param maxSize maximum chunk size, in points + */ + TrackPointsChunk(unsigned int maxSize); + + /** + * Is this chunk full? i.e. no room for more points? + * @return true if this chunk is full + */ + bool isFull() const; + + /** + * How many points are rendered by this chunk? + * @return number of active points in this chunk + */ + unsigned int size() const; + + /** + * Return time of the first point in this chunk in seconds since ref year, accounting for data limiting + * @return begin time in seconds + */ + double getBeginTime() const; + + /** + * Return time of the last point in this chunk in seconds since ref year, accounting for data limiting + * @return end time in seconds + */ + double getEndTime() const; + + /** + * Remove the oldest point in this chunk + * @return true if point was removed + */ + bool removeOldestPoint(); + + /** + * Remove points from the tail + * @param t earliest time that will remain in this chunk + * @return number of points removed + */ + unsigned int removePointsBefore(double t); + + /** Allows the node to be re-used */ + void reset(); + +protected: + virtual ~TrackPointsChunk() {} + + /// Is this chunk empty? + bool isEmpty_() const; + + /// Fix graphics after points are removed + virtual void fixGraphicsAfterRemoval_() = 0; + + /// Update the offset and count on each primitive set to draw the proper data. + virtual void updatePrimitiveSets_() = 0; + + // data + /// timestamp of each point + std::vector times_; + /// offset into the point list to the start of points to render + unsigned int offset_; + /// number of points to render + unsigned int count_; + /// maximum allowable number of points in chunk + unsigned int maxSize_; +}; + +/** Implementation of the TrackPointsChunk for drawing track history update points */ +class SDKVIS_EXPORT TrackChunkNode : public TrackPointsChunk +{ +public: + /** + * Create a new chunk with a maximum size + * @param maxSize maximum chunk size, in points + * @param srs spatial reference that is being used for track data + * @param mode track draw mode that this chunk will display + */ + TrackChunkNode(unsigned int maxSize, const osgEarth::SpatialReference* srs, simData::TrackPrefs_Mode mode = simData::TrackPrefs_Mode_POINT); + /** - * Node that renders a "chunk" of the track history - * A full track history trail is segmented into chunks. This allows a - * number of things: - * - * - efficiently add points to the track (only need to update the last chunk) - * - efficiently maintain a limited track size (restricting the total number of points) - * - dealing with long tracks (eliminate jitter and improve culling) - * - manage memory effectively (always allocate buffer objects of exactly the same size, which OSG likes) - * - * Each chunk will hold a limited (and specific) number of points. Once - * the capacity of a chunk is exceeded, a new chunk gets appended to the - * graph. Similarly, when point-limiting is in effect, we can adjust the - * oldest chunk to "drop" points from the end of the track. - * - * Each chunk lives under its own MT to prevent single-precision jitter - * effects in a geocentric map. - * - * Note: Choose the Chunk Size carefully. Each chunk pre-allocates all the memory - * it will possibly need, so if you have a large number of entities with track - * histories, you can quickly run out of memory. + * Add a new point to the chunk + * @param matrix the position matrix that corresponds to the platform update position + * @param t time that corresponds to the platform update + * @param color color to render this chunk + * @param hostBounds left and right boundaries of the host model + * @return true if point was added */ - class TrackChunkNode : public osg::MatrixTransform - { - public: - /** - * Create a new chunk with a maximum size - * @param maxSize maximum chunk size, in points - * @param srs spatial reference that is being used for track data - * @param mode track draw mode that this chunk will display - */ - TrackChunkNode(unsigned int maxSize, const osgEarth::SpatialReference* srs, simData::TrackPrefs_Mode mode = simData::TrackPrefs_Mode_POINT); - - /** - * Is this chunk full? i.e. no room for more points? - * @return true if this chunk is full - */ - bool isFull() const; - - /** - * How many points are rendered by this chunk? - * @return number of active points in this chunk - */ - unsigned int size() const; - - /** - * Add a new point to the chunk - * @param matrix the position matrix that corresponds to the platform update position - * @param t time that corresponds to the platform update - * @param color color to render this chunk - * @param hostBounds left and right boundaries of the host model - * @return true if point was added - */ - bool addPoint(const osg::Matrix& matrix, double t, const osg::Vec4& color, const osg::Vec2& hostBounds); - - /** - * Get the matrix and time associated with the newest point in this chunk - * @param out_matrix position matrix for the newest point in the chunk - * @param out_time update time of the newest point in the chunk - * @return true if matrix and time are valid - */ - bool getNewestData(osg::Matrix& out_matrix, double& out_time) const; - - /** - * Remove the oldest point in this chunk - * @return true if point was removed - */ - bool removeOldestPoint(); - - /** - * Remove points from the tail - * @param t earliest time that will remain in this chunk - * @return number of points removed - */ - unsigned int removePointsBefore(double t); - - /** Allows the node to be re-used */ - void reset(); - - /** Return the proper library name */ - virtual const char* libraryName() const { return "simVis"; } - - /** Return the class name */ - virtual const char* className() const { return "TrackChunkNode"; } - - protected: - virtual ~TrackChunkNode(); - - private: - /// Allocate the graphical elements for this chunk. - void allocate_(); - - /// Return time of the first point in this chunk - double getStartTime_() const; - - /// Return time of the last point in this chunk - double getEndTime_() const; - - /// Is this chunk empty? - bool isEmpty_() const; - - /// Remove all the points in this chunk that occur after the timestamp - unsigned int removePointsAtAndBeyond_(double t); - - /// Appends a new local point to each geometry set. - void append_(const osg::Matrix& matrix, const osg::Vec4& color, const osg::Vec2& hostBounds); - - /// Update the offset and count on each primitive set to draw the proper data. - void updatePrimitiveSets_(); - - /// Fix the ribbon visual after points deletion to not show links to deleted point - void fixRibbon_(); - - private: - std::vector times_; /// timestamp of each point - unsigned int offset_; /// offset into the point list to the start of points to render - unsigned int count_; /// number of points to render - unsigned int maxSize_; /// maximum allowable number of points in chunk - osg::ref_ptr geode_; - - osg::ref_ptr centerLine_; - osg::ref_ptr centerPoints_; - - osg::ref_ptr ribbon_; - - osg::ref_ptr drop_; - - osg::ref_ptr srs_; - osg::Matrixd world2local_; - simData::TrackPrefs_Mode mode_; /// track draw mode that this chunk will display - }; + bool addPoint(const osg::Matrix& matrix, double t, const osg::Vec4& color, const osg::Vec2& hostBounds); + + /** + * Get the matrix and time associated with the newest point in this chunk + * @param out_matrix position matrix for the newest point in the chunk + * @param out_time update time of the newest point in the chunk + * @return true if matrix and time are valid + */ + bool getNewestData(osg::Matrix& out_matrix, double& out_time) const; + + /** Return the proper library name */ + virtual const char* libraryName() const { return "simVis"; } + + /** Return the class name */ + virtual const char* className() const { return "TrackChunkNode"; } + +protected: + virtual ~TrackChunkNode(); + + /// Update the offset and count on each primitive set to draw the proper data. + virtual void updatePrimitiveSets_(); + + /// Fix the ribbon visual after points deletion to not show links to deleted point + virtual void fixGraphicsAfterRemoval_(); + +private: + /// Allocate the graphical elements for this chunk. + void allocate_(); + /// Appends a new local point to each geometry set. + void append_(const osg::Matrix& matrix, const osg::Vec4& color, const osg::Vec2& hostBounds); + +private: + osg::ref_ptr geode_; + osg::ref_ptr centerLine_; + osg::ref_ptr centerPoints_; + osg::ref_ptr ribbon_; + osg::ref_ptr drop_; + + osg::ref_ptr srs_; + osg::Matrixd world2local_; + + /// track draw mode that this chunk will display + simData::TrackPrefs_Mode mode_; +}; } // namespace simVis From 8cc4dafacfab61a7b555a9365a5215883a500aa4 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Mon, 6 Jan 2020 05:42:20 -0500 Subject: [PATCH 009/121] DEV: Made constant unique to satisfy one-definition-rule for unity build. No review, build fix. --- SDK/simVis/TimeTicks.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index f0d8f4718..ca41bd017 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -61,7 +61,7 @@ namespace static const int LABEL_FONT_SIZE = 30; // follow track history flat mode - static const std::string SIMVIS_TRACK_FLATMODE = "simvis_track_flatmode"; + static const std::string SIMVIS_TIMETICKS_TRACK_FLATMODE = "simvis_track_flatmode"; } @@ -358,7 +358,7 @@ void TimeTicks::updateFlatMode_(bool flatMode) return; // Does not exist and not needed so return; osg::StateSet* stateset = this->getOrCreateStateSet(); - flatModeUniform_ = stateset->getOrCreateUniform(SIMVIS_TRACK_FLATMODE, osg::Uniform::BOOL); + flatModeUniform_ = stateset->getOrCreateUniform(SIMVIS_TIMETICKS_TRACK_FLATMODE, osg::Uniform::BOOL); } flatModeUniform_->set(flatMode); From bfda5ea0c631ac5403f4cf007fd64969390e1f07 Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Mon, 6 Jan 2020 11:47:41 -0500 Subject: [PATCH 010/121] DEV: SDK:simVis TimeTicks handles case of drawing first tick when time goes from forward to reverse, review 20278 --- SDK/simVis/TimeTicks.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index ca41bd017..b6bcf2328 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -185,13 +185,25 @@ void TimeTicks::addUpdate_(double tickTime) const simData::PlatformUpdate* prev = prevIter.previous(); const simData::PlatformUpdate* update = iter.next(); osg::Matrix hostMatrix; - bool largeTick = false; + // if first tick, get the current platform position if (chunkGroup_->getNumChildren() == 0) { - if (!getMatrix_(*update, hostMatrix)) - return; + // special case for first point when going backwards + // need to get the possibly interpolated point to start since there may not be a point at the current location + if (timeDirection_ == simCore::REVERSE) + { + if (!hasPrevious) + return; + if (!getMatrix_(*prev, *update, tickTime, hostMatrix)) + return; + } + else + { + if (!getMatrix_(*update, hostMatrix)) + return; + } // first tick is always large if (lastLargeTickTime_ == -1) { From 91172d91d89b8eee904932ac7dda537e3f68340f Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Wed, 8 Jan 2020 14:15:09 -0500 Subject: [PATCH 011/121] SDK API NEW FEATURE: simData TimeTickPrefs added to control simVis TimeTicks for drawing a time ticks trail on a platform DEV: SDK: simData TimeTickPrefs added to PlatformPrefs, used by TimeTicks, SIM-4428, review 20318 --- SDK/simData/GeneratedCode/simData.proto | 29 +++++++++ SDK/simVis/Platform.cpp | 15 ++++- SDK/simVis/TimeTicks.cpp | 85 ++++++++++++++++++------- SDK/simVis/TimeTicks.h | 3 + SDK/simVis/TimeTicksChunk.cpp | 17 ++--- SDK/simVis/TimeTicksChunk.h | 17 +++-- 6 files changed, 125 insertions(+), 41 deletions(-) diff --git a/SDK/simData/GeneratedCode/simData.proto b/SDK/simData/GeneratedCode/simData.proto index c67538aa1..0832ef6f6 100644 --- a/SDK/simData/GeneratedCode/simData.proto +++ b/SDK/simData/GeneratedCode/simData.proto @@ -251,6 +251,34 @@ message CoordinateFrame { optional TangentPlaneOffsets tangentPlaneOffset = 8; }; +// preferences for the display of platform time ticks +message TimeTickPrefs { + enum DrawStyle { + NONE = 0; + POINT = 1; ///< draw ticks as points + LINE = 2; ///< draw ticks as lines + }; + optional DrawStyle drawStyle = 1 [default = POINT]; + /// default color is translucent white + optional fixed32 color = 2 [default = 0xFFFFFF99]; + /// time tick interval in seconds + optional double interval = 3 [default = 10.0]; + /// defines interval to draw the tick larger, draws at multiple of the tick interval; 0 means no large ticks + optional uint32 largeIntervalFactor = 4 [default = 6]; + /// defines interval to draw a label on the tick, draws at a multiple of the tick interval; 0 means no labels + optional uint32 labelIntervalFactor = 5 [default = 6]; + optional string labelFontName = 6 [default = "arial.ttf"]; + optional fixed32 labelFontPointSize = 7 [default = 12]; + /// tick line length in meters + optional double lineLength = 8 [default = 40]; + /// defines how big to draw the large line tick or the point tick, draws large tick as a multiple of lineLength and large point tick as a multiple of lineWidth + optional uint32 largeSizeFactor = 9 [default = 2]; + /// format for the time shown in the label text + optional ElapsedTimeFormat labelTimeFormat = 10 [default = ELAPSED_HOURS]; + /// line and point width for drawing the time ticks + optional double lineWidth = 11 [default = 2]; +}; + /// preferences for the display of platform tracks message TrackPrefs { /// off-white, the default color to use for track history. Track color history at time is defined in a data table, simData::INTERNAL_TRACK_HISTORY_TABLE, in column simData::INTERNAL_TRACK_HISTORY_COLOR_COLUMN @@ -277,6 +305,7 @@ message TrackPrefs { }; optional Mode trackDrawMode = 11 [default = POINT]; + optional TimeTickPrefs timeTicks = 12; }; /// define the text outline style diff --git a/SDK/simVis/Platform.cpp b/SDK/simVis/Platform.cpp index 38fc728f6..72279c062 100644 --- a/SDK/simVis/Platform.cpp +++ b/SDK/simVis/Platform.cpp @@ -284,6 +284,18 @@ void PlatformNode::setPrefs(const simData::PlatformPrefs& prefs) // remove or create track history if (showTrack_(prefs)) { + // first check time ticks + if (prefs.trackprefs().timeticks().drawstyle() != simData::TimeTickPrefs::NONE) + { + if (!timeTicks_.valid()) + createTimeTicks_(prefs); + } + else if (timeTicks_.valid()) + { + expireModeGroup_->removeChild(timeTicks_); + timeTicks_ = NULL; + } + if (!track_.valid()) createTrackHistoryNode_(prefs); else @@ -641,9 +653,6 @@ bool PlatformNode::createTrackHistoryNode_(const simData::PlatformPrefs& prefs) const bool prefsDraw = lastPrefs_.commonprefs().datadraw() && prefs.commonprefs().draw(); track_->setNodeMask(prefsDraw ? simVis::DISPLAY_MASK_TRACK_HISTORY : simVis::DISPLAY_MASK_NONE); - // TODO: SIM-4428 draw time ticks will be controlled by a separate pref - //createTimeTicks_(prefs); - return true; } diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index b6bcf2328..a64e1b80f 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -41,6 +41,7 @@ #include "simVis/OverheadMode.h" #include "simVis/PlatformFilter.h" #include "simVis/PointSize.h" +#include "simVis/Registry.h" #include "simVis/Shaders.h" #include "simVis/TimeTicksChunk.h" #include "simVis/Types.h" @@ -53,11 +54,7 @@ namespace simVis namespace { // TODO: these will be prefs, SIM-4428 - static const double TIME_INTERVAL_SMALL_SECS = 10; - static const double TIME_INTERVAL_LARGE_SECS = 6 * TIME_INTERVAL_SMALL_SECS; - static const int TICK_TYPE = 1; // 0 = point, 1 = line static const double TICK_WIDTH = 40; - static const double TICK_LINE_WIDTH = 2; static const int LABEL_FONT_SIZE = 30; // follow track history flat mode @@ -76,6 +73,9 @@ TimeTicks::TimeTicks(const simData::DataStore& ds, const osgEarth::SpatialRefere lastDrawTime_(0.0), lastCurrentTime_(-1.0), lastLargeTickTime_(-1.0), + lastLabelTime_(-1.0), + largeTickInterval_(0.0), + labelInterval_(0.0), timeDirection_(simCore::FORWARD), chunkGroup_(NULL), labelGroup_(NULL), @@ -122,6 +122,7 @@ void TimeTicks::reset() addChild(chunkGroup_); currentPointChunk_ = NULL; lastLargeTickTime_ = -1.0; + lastLabelTime_ = -1.0; } TimeTicksChunk* TimeTicks::getCurrentChunk_() @@ -205,7 +206,7 @@ void TimeTicks::addUpdate_(double tickTime) return; } // first tick is always large - if (lastLargeTickTime_ == -1) + if (largeTickInterval_ > 0 && lastLargeTickTime_ == -1) { largeTick = true; lastLargeTickTime_ = tickTime; @@ -217,7 +218,7 @@ void TimeTicks::addUpdate_(double tickTime) if (!getMatrix_(*prev, *update, tickTime, hostMatrix)) return; // check to see if it is time for the next large tick - if (lastLargeTickTime_ == -1.0 || abs(tickTime - lastLargeTickTime_) >= TIME_INTERVAL_LARGE_SECS) + if (largeTickInterval_ > 0 && (lastLargeTickTime_ == -1.0 || abs(tickTime - lastLargeTickTime_) >= largeTickInterval_)) { lastLargeTickTime_ = tickTime; largeTick = true; @@ -226,15 +227,18 @@ void TimeTicks::addUpdate_(double tickTime) else return; - // add label for large tick TODO: SIM-4428 this might be a separate pref to define label interval - if (largeTick) + // add label for large tick + if (labelInterval_ > 0 && (lastLabelTime_ == -1.0 || abs(tickTime - lastLabelTime_) >= labelInterval_)) { + lastLabelTime_ = tickTime; + int refYear = 1970; simData::DataStore::Transaction t; const simData::ScenarioProperties* sp = ds_.scenarioProperties(&t); if (sp) refYear = sp->referenceyear(); + // TODO: SIM-4428 format label text based on pref simCore::TimeStamp textTime(refYear, tickTime); simCore::HoursTimeFormatter fmt; std::string labelText = fmt.toString(textTime, refYear, 0); @@ -243,12 +247,17 @@ void TimeTicks::addUpdate_(double tickTime) osgText::Text* text = new osgText::Text(); text->setPosition(osg::Vec3(0, 0, 0)); text->setText(labelText); - text->setFont(osgEarth::Registry::instance()->getDefaultFont()); + const simData::TimeTickPrefs& timeTicks = lastPlatformPrefs_.trackprefs().timeticks(); + std::string fileFullPath = simVis::Registry::instance()->findFontFile(timeTicks.labelfontname()); + if (!fileFullPath.empty()) // only set if font file found, use default font otherwise + text->setFont(fileFullPath); + else + text->setFont(osgEarth::Registry::instance()->getDefaultFont()); text->setAutoRotateToScreen(true); text->setCharacterSizeMode(osgText::TextBase::OBJECT_COORDS); text->setAlignment(osgText::TextBase::LEFT_BOTTOM); text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT); - text->setCharacterSize(LABEL_FONT_SIZE); + text->setCharacterSize(timeTicks.labelfontpointsize()); text->getOrCreateStateSet()->setRenderBinToInherit(); osg::Depth* noDepthTest = new osg::Depth(osg::Depth::ALWAYS, 0, 1, false); text->getOrCreateStateSet()->setAttributeAndModes(noDepthTest, 1); @@ -263,8 +272,9 @@ void TimeTicks::addUpdate_(double tickTime) if (!chunk) { // allocate a new chunk - TimeTicksChunk::Type type = ((TICK_TYPE == 0) ? TimeTicksChunk::POINT_TICKS : TimeTicksChunk::LINE_TICKS); - chunk = new TimeTicksChunk(chunkSize_, type, TICK_WIDTH, TICK_WIDTH * 2); + const simData::TimeTickPrefs& timeTicks = lastPlatformPrefs_.trackprefs().timeticks(); + TimeTicksChunk::Type type = ((timeTicks.drawstyle() == simData::TimeTickPrefs::POINT) ? TimeTicksChunk::POINT_TICKS : TimeTicksChunk::LINE_TICKS); + chunk = new TimeTicksChunk(chunkSize_, type, timeTicks.linelength() / 2, timeTicks.linewidth(), timeTicks.largesizefactor()); // if there is a preceding chunk, duplicate its last point so there is no // discontinuity from previous chunk to this new chunk - this matters for line drawing mode @@ -383,6 +393,8 @@ void TimeTicks::setPrefs(const simData::PlatformPrefs& platformPrefs, const simD // force should be true in this case; // in any case, if force is set, we should not test on lastPlatformPrefs_ const simData::TrackPrefs& lastPrefs = lastPlatformPrefs_.trackprefs(); + const simData::TimeTickPrefs& timeTicks = prefs.timeticks(); + const simData::TimeTickPrefs& lastTimeTicks = lastPrefs.timeticks(); // platform should be deleting track when trackdrawmode turned off, this should never be called with trackdrawmode off // if assert fails, check platform setPrefs logic that processes prefs.trackprefs().trackdrawmode() @@ -409,9 +421,36 @@ void TimeTicks::setPrefs(const simData::PlatformPrefs& platformPrefs, const simD resetRequested = true; } - // TODO: SIM-4428 update linewidth and other time tick specific prefs - osg::StateSet* stateSet = this->getOrCreateStateSet(); - osgEarth::LineDrawable::setLineWidth(stateSet, TICK_LINE_WIDTH); + if (force || PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, linewidth)) + { + osg::StateSet* stateSet = this->getOrCreateStateSet(); + osgEarth::LineDrawable::setLineWidth(stateSet, timeTicks.linewidth()); + } + + if (force || PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, color)) + { + color_ = simVis::Color(simVis::Color(timeTicks.color(), simVis::Color::RGBA)); + resetRequested = true; + } + + if (force || PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, interval) || + PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, largeintervalfactor) || + PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, labelintervalfactor)) + { + double interval = timeTicks.interval(); + largeTickInterval_ = interval * timeTicks.largeintervalfactor(); + labelInterval_ = interval * timeTicks.labelintervalfactor(); + resetRequested = true; + } + // check on other changes that could force a redraw + if (force || PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, drawstyle) || + PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, linelength) || + PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, largesizefactor) || + PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, labelfontname) || + PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, labelfontpointsize)) + { + resetRequested = true; + } lastPlatformPrefs_ = platformPrefs; lastPlatformProps_ = platformProps; @@ -525,18 +564,19 @@ void TimeTicks::updateTrackData_(double currentTime, const simData::PlatformUpda void TimeTicks::backfillHistory_(double endTime, double beginTime) { + double interval = lastPlatformPrefs_.trackprefs().timeticks().interval(); if (timeDirection_ == simCore::FORWARD) { double tickTime = beginTime; // if there is already a chunk, start counting from its end time simVis::TimeTicksChunk* lastChunk = getLastChunk_(); if (lastChunk) - tickTime = lastChunk->getEndTime() + TIME_INTERVAL_SMALL_SECS; + tickTime = lastChunk->getEndTime() + interval; while (tickTime <= endTime) { addUpdate_(tickTime); - tickTime += TIME_INTERVAL_SMALL_SECS; + tickTime += interval; } } else @@ -545,12 +585,12 @@ void TimeTicks::backfillHistory_(double endTime, double beginTime) // if there is already a chunk, start counting from its end time simVis::TimeTicksChunk* lastChunk = getLastChunk_(); if (lastChunk) - tickTime = toDrawTime_(lastChunk->getEndTime()) - TIME_INTERVAL_SMALL_SECS; + tickTime = toDrawTime_(lastChunk->getEndTime()) - interval; while (tickTime >= beginTime) { addUpdate_(tickTime); - tickTime -= TIME_INTERVAL_SMALL_SECS; + tickTime -= interval; } } } @@ -562,7 +602,7 @@ void TimeTicks::updateCurrentPoint_(const simData::PlatformUpdateSlice& updateSl currentPointChunk_->reset(); // no current point if not line ticks - if (TICK_TYPE == 0) + if (lastPlatformPrefs_.trackprefs().timeticks().drawstyle() == simData::TimeTickPrefs::POINT) return; // only line, ribbon, and bridge draw modes require this processing, @@ -573,7 +613,8 @@ void TimeTicks::updateCurrentPoint_(const simData::PlatformUpdateSlice& updateSl // create the special chunk for rendering the interpolated point, has two points to connect to rest of history for line mode if (currentPointChunk_ == NULL) { - currentPointChunk_ = new TimeTicksChunk(2, TimeTicksChunk::LINE, TICK_WIDTH, TICK_WIDTH * 2); + const simData::TimeTickPrefs& timeTicks = lastPlatformPrefs_.trackprefs().timeticks(); + currentPointChunk_ = new TimeTicksChunk(2, TimeTicksChunk::LINE, timeTicks.linelength() / 2, timeTicks.linewidth(), timeTicks.largesizefactor()); if (currentPointChunk_ == NULL) return; addChild(currentPointChunk_); @@ -669,7 +710,7 @@ bool TimeTicks::getMatrix_(const simData::PlatformUpdate& prevPoint, const simDa simCore::Coordinate ecefCoordCur(simCore::COORD_SYS_ECEF, simCore::Vec3(platformUpdate.x(), platformUpdate.y(), platformUpdate.z())); // for point ticks, only need the position - if (TICK_TYPE == 0) + if (lastPlatformPrefs_.trackprefs().timeticks().drawstyle() == simData::TimeTickPrefs::POINT) { locator_->setCoordinate(ecefCoordCur, time); diff --git a/SDK/simVis/TimeTicks.h b/SDK/simVis/TimeTicks.h index d3994526c..11a6cd90c 100644 --- a/SDK/simVis/TimeTicks.h +++ b/SDK/simVis/TimeTicks.h @@ -199,6 +199,9 @@ class SDKVIS_EXPORT TimeTicks : public osg::Group double lastDrawTime_; double lastCurrentTime_; double lastLargeTickTime_; + double largeTickInterval_; + double lastLabelTime_; + double labelInterval_; // Playback direction (follows a datastore-bound Clock). simCore::TimeDirection timeDirection_; diff --git a/SDK/simVis/TimeTicksChunk.cpp b/SDK/simVis/TimeTicksChunk.cpp index 1917cfc53..c95a0c63a 100644 --- a/SDK/simVis/TimeTicksChunk.cpp +++ b/SDK/simVis/TimeTicksChunk.cpp @@ -31,15 +31,12 @@ namespace simVis { -// TODO: SIM-4428 these will likely be prefs, possibly derived from tick linewidth -static const int POINT_SIZE = 4; -static const int LARGE_POINT_SIZE = 8; - -TimeTicksChunk::TimeTicksChunk(unsigned int maxSize, Type type, double lineTickWidth, double largeLineTickWidth) +TimeTicksChunk::TimeTicksChunk(unsigned int maxSize, Type type, double lineLength, double pointSize, unsigned int largeFactor) : TrackPointsChunk(maxSize), type_(type), - lineTickWidth_(lineTickWidth), - largeLineTickWidth_(largeLineTickWidth) + lineLength_(lineLength), + pointSize_(pointSize), + largeSizeFactor_(largeFactor) { allocate_(); } @@ -126,7 +123,7 @@ void TimeTicksChunk::allocate_() largePoint_->setColorArray(largeColors); largePoint_->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, offset_, count_)); addChild(largePoint_.get()); - PointSize::setValues(largePoint_->getOrCreateStateSet(), LARGE_POINT_SIZE, osg::StateAttribute::ON); + PointSize::setValues(largePoint_->getOrCreateStateSet(), pointSize_ * largeSizeFactor_, osg::StateAttribute::ON); // points point_ = new osg::Geometry(); @@ -142,7 +139,7 @@ void TimeTicksChunk::allocate_() point_->setColorArray(colors); point_->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, offset_, count_)); addChild(point_.get()); - PointSize::setValues(point_->getOrCreateStateSet(), POINT_SIZE, osg::StateAttribute::ON); + PointSize::setValues(point_->getOrCreateStateSet(), pointSize_, osg::StateAttribute::ON); } else if (type_ == LINE_TICKS) { @@ -208,7 +205,7 @@ void TimeTicksChunk::append_(const osg::Matrix& matrix, const osg::Vec4& color, // hostBounds represents the xMin and xMax values of a bounding box respectively. const osg::Matrix posMatrix = matrix * world2local_; - double width = (large ? largeLineTickWidth_ : lineTickWidth_); + double width = lineLength_ * (large ? largeSizeFactor_ : 1); const osg::Vec3f left = osg::Vec3d(-width, 0.0, 0.0) * posMatrix; const osg::Vec3f right = osg::Vec3d(width, 0.0, 0.0) * posMatrix; diff --git a/SDK/simVis/TimeTicksChunk.h b/SDK/simVis/TimeTicksChunk.h index e254b93b4..738c5f76b 100644 --- a/SDK/simVis/TimeTicksChunk.h +++ b/SDK/simVis/TimeTicksChunk.h @@ -46,9 +46,12 @@ class SDKVIS_EXPORT TimeTicksChunk : public TrackPointsChunk /** * Create a new chunk with a maximum size * @param maxSize maximum chunk size, in points - * @param drawPoints if true draw point ticks, otherwise draw line ticks + * @param type draw style for rendering ticks + * @param lineLength width in meters of line tick to draw + * @param pointSize pixel size of points tick to draw + * @param largeFactor large tick factor for line and point, multiple of lineLength for line, multiple of pointSize for point */ - TimeTicksChunk(unsigned int maxSize, Type type, double lineTickWidth, double largeLineTickWidth); + TimeTicksChunk(unsigned int maxSize, Type type, double lineLength, double pointSize, unsigned int largeFactor); /** * Add a new point to the chunk @@ -97,10 +100,12 @@ class SDKVIS_EXPORT TimeTicksChunk : public TrackPointsChunk private: /// draw type Type type_; - /// line tick width - double lineTickWidth_; - /// large line tick width - double largeLineTickWidth_; + /// line tick length + double lineLength_; + /// point tick size + double pointSize_; + /// large tick size factor + double largeSizeFactor_; ///container for drawables osg::ref_ptr geode_; /// point graphic From a6baa236d528b92e62e9f0a48366c2e6f12a6093 Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Wed, 8 Jan 2020 14:59:20 -0500 Subject: [PATCH 012/121] SDK: TimeTicks fixes initialization list order, no review --- SDK/simVis/TimeTicks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index a64e1b80f..725dcd460 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -73,8 +73,8 @@ TimeTicks::TimeTicks(const simData::DataStore& ds, const osgEarth::SpatialRefere lastDrawTime_(0.0), lastCurrentTime_(-1.0), lastLargeTickTime_(-1.0), - lastLabelTime_(-1.0), largeTickInterval_(0.0), + lastLabelTime_(-1.0), labelInterval_(0.0), timeDirection_(simCore::FORWARD), chunkGroup_(NULL), From 9e2d67304cf2df3fc81235388b4b78bb1ab71d43 Mon Sep 17 00:00:00 2001 From: Ferzam Mohammad Date: Wed, 8 Jan 2020 15:02:19 -0500 Subject: [PATCH 013/121] DEV: Projects in this folder had redundant names, so changed CMakeLists file to generate more appropriate project labels. SIM-10675, Review: 20325 --- Examples/ASIViewer/CMakeLists.txt | 2 +- Examples/AngleTest/CMakeLists.txt | 2 +- Examples/AnimatedLine/CMakeLists.txt | 2 +- Examples/AntennaPattern/CMakeLists.txt | 2 +- Examples/ArticulatedModel/CMakeLists.txt | 2 +- Examples/AsyncModelLoading/CMakeLists.txt | 2 +- Examples/BasicViewer/CMakeLists.txt | 2 +- Examples/BasicViewerText/CMakeLists.txt | 2 +- Examples/BeamTest/CMakeLists.txt | 2 +- Examples/CentroidEyePosition/CMakeLists.txt | 2 +- Examples/CustomRenderingTest/CMakeLists.txt | 2 +- Examples/DBReader/CMakeLists.txt | 2 +- Examples/GOGAttachments/CMakeLists.txt | 2 +- Examples/GOGReader/CMakeLists.txt | 2 +- Examples/GateTest/CMakeLists.txt | 2 +- Examples/GeoFencing/CMakeLists.txt | 2 +- Examples/HudPositionManager/CMakeLists.txt | 2 +- Examples/ImageIcons/CMakeLists.txt | 2 +- Examples/LOBTest/CMakeLists.txt | 2 +- Examples/LoadEarthFile/CMakeLists.txt | 2 +- Examples/LocalGrid/CMakeLists.txt | 2 +- Examples/LocatorTest/CMakeLists.txt | 2 +- Examples/MapScale/CMakeLists.txt | 2 +- Examples/MassiveData/CMakeLists.txt | 2 +- Examples/ObserverMaker/CMakeLists.txt | 2 +- Examples/Ocean/CMakeLists.txt | 2 +- Examples/Overhead/CMakeLists.txt | 2 +- Examples/Periscope/CMakeLists.txt | 2 +- Examples/Picking/CMakeLists.txt | 2 +- Examples/PlanetariumViewTest/CMakeLists.txt | 2 +- Examples/PlatformAzimElevViewTest/CMakeLists.txt | 2 +- Examples/PlatformSymbology/CMakeLists.txt | 2 +- Examples/Projectors/CMakeLists.txt | 2 +- Examples/Qt/CMakeLists.txt | 2 +- Examples/QtActionItemModelTest/CMakeLists.txt | 2 +- Examples/QtCategoryFilterTest/CMakeLists.txt | 2 +- Examples/QtColorWidgetTest/CMakeLists.txt | 2 +- Examples/QtConsoleDataModel/CMakeLists.txt | 2 +- Examples/QtDataTableViewTest/CMakeLists.txt | 2 +- Examples/QtDockableViews/CMakeLists.txt | 2 +- Examples/QtEntityLineEditTest/CMakeLists.txt | 2 +- Examples/QtEntityViewTest/CMakeLists.txt | 2 +- Examples/QtFileSelectorTest/CMakeLists.txt | 2 +- Examples/QtThreadExample/CMakeLists.txt | 2 +- Examples/QtTimeButtons/CMakeLists.txt | 2 +- Examples/QtTimeWidgetTest/CMakeLists.txt | 2 +- Examples/QtUnitsWidgetTest/CMakeLists.txt | 2 +- Examples/QtViewManagerDataModel/CMakeLists.txt | 2 +- Examples/QtViewManagerTest/CMakeLists.txt | 2 +- Examples/RCS/CMakeLists.txt | 2 +- Examples/RFProp/CMakeLists.txt | 2 +- Examples/RadialLOS/CMakeLists.txt | 2 +- Examples/RangeTool/CMakeLists.txt | 2 +- Examples/RocketBurn/CMakeLists.txt | 2 +- Examples/SimpleServer/CMakeLists.txt | 2 +- Examples/SkyModel/CMakeLists.txt | 2 +- Examples/TimestampedLayer/CMakeLists.txt | 2 +- Examples/TrackHistoryTest/CMakeLists.txt | 2 +- Examples/ViewManagerTest/CMakeLists.txt | 2 +- Plugins/OSGEarthDBDriver/CMakeLists.txt | 2 +- Plugins/QtDesignerWidgets/CMakeLists.txt | 2 +- SDK/simCore/CMakeLists.txt | 2 +- SDK/simData/CMakeLists.txt | 4 ++-- SDK/simNotify/CMakeLists.txt | 2 +- SDK/simQt/CMakeLists.txt | 2 +- SDK/simUtil/CMakeLists.txt | 2 +- SDK/simVis/CMakeLists.txt | 2 +- Testing/SimCore/CMakeLists.txt | 2 +- Testing/SimData/CMakeLists.txt | 2 +- Testing/SimData/DataStorePerformanceTest/CMakeLists.txt | 2 +- Testing/SimNotify/CMakeLists.txt | 2 +- Testing/SimQt/CMakeLists.txt | 2 +- Testing/SimUtil/CMakeLists.txt | 2 +- Testing/SimVis/CMakeLists.txt | 2 +- 74 files changed, 75 insertions(+), 75 deletions(-) diff --git a/Examples/ASIViewer/CMakeLists.txt b/Examples/ASIViewer/CMakeLists.txt index dacfc084c..0f777b9cd 100644 --- a/Examples/ASIViewer/CMakeLists.txt +++ b/Examples/ASIViewer/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_asiviewer ${PROJECT_FILES}) target_link_libraries(example_asiviewer PRIVATE simVis simUtil) set_target_properties(example_asiviewer PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - ASI Simple Viewer" + PROJECT_LABEL "ASI Simple Viewer" ) vsi_install_target(example_asiviewer SDK_Examples) diff --git a/Examples/AngleTest/CMakeLists.txt b/Examples/AngleTest/CMakeLists.txt index 38af1de93..4a0feb87d 100644 --- a/Examples/AngleTest/CMakeLists.txt +++ b/Examples/AngleTest/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_angletest ${PROJECT_FILES}) target_link_libraries(example_angletest PRIVATE simVis simUtil) set_target_properties(example_angletest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Angle Test" + PROJECT_LABEL "Angle Test" ) vsi_install_target(example_angletest SDK_Examples) diff --git a/Examples/AnimatedLine/CMakeLists.txt b/Examples/AnimatedLine/CMakeLists.txt index aa10502be..54bb547b8 100644 --- a/Examples/AnimatedLine/CMakeLists.txt +++ b/Examples/AnimatedLine/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_animatedline ${PROJECT_FILES}) target_link_libraries(example_animatedline PRIVATE simVis simUtil) set_target_properties(example_animatedline PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Animated Line" + PROJECT_LABEL "Animated Line" ) vsi_install_target(example_animatedline SDK_Examples) diff --git a/Examples/AntennaPattern/CMakeLists.txt b/Examples/AntennaPattern/CMakeLists.txt index cb226b4a7..2ae577f23 100644 --- a/Examples/AntennaPattern/CMakeLists.txt +++ b/Examples/AntennaPattern/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_antennapattern ${PROJECT_FILES}) target_link_libraries(example_antennapattern PRIVATE simVis simUtil) set_target_properties(example_antennapattern PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Antenna Pattern" + PROJECT_LABEL "Antenna Pattern" ) vsi_install_target(example_antennapattern SDK_Examples) diff --git a/Examples/ArticulatedModel/CMakeLists.txt b/Examples/ArticulatedModel/CMakeLists.txt index 63b0e6cee..81b6bcdd7 100644 --- a/Examples/ArticulatedModel/CMakeLists.txt +++ b/Examples/ArticulatedModel/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_articulatedmodel ${PROJECT_FILES}) target_link_libraries(example_articulatedmodel PRIVATE simVis simUtil) set_target_properties(example_articulatedmodel PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Articulated Model" + PROJECT_LABEL "Articulated Model" ) vsi_install_target(example_articulatedmodel SDK_Examples) diff --git a/Examples/AsyncModelLoading/CMakeLists.txt b/Examples/AsyncModelLoading/CMakeLists.txt index 92dcfd545..9fafdcf59 100644 --- a/Examples/AsyncModelLoading/CMakeLists.txt +++ b/Examples/AsyncModelLoading/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_asyncmodelloading ${PROJECT_FILES}) target_link_libraries(example_asyncmodelloading PRIVATE simVis simUtil) set_target_properties(example_asyncmodelloading PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Asynchronous Model Loading" + PROJECT_LABEL "Asynchronous Model Loading" ) vsi_install_target(example_asyncmodelloading SDK_Examples) diff --git a/Examples/BasicViewer/CMakeLists.txt b/Examples/BasicViewer/CMakeLists.txt index dac7a52eb..a581703de 100644 --- a/Examples/BasicViewer/CMakeLists.txt +++ b/Examples/BasicViewer/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_basicviewer ${PROJECT_FILES}) target_link_libraries(example_basicviewer PRIVATE simVis simUtil) set_target_properties(example_basicviewer PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Basic Viewer" + PROJECT_LABEL "Basic Viewer" ) vsi_install_target(example_basicviewer SDK_Examples) diff --git a/Examples/BasicViewerText/CMakeLists.txt b/Examples/BasicViewerText/CMakeLists.txt index c437e7021..c3b1ea216 100644 --- a/Examples/BasicViewerText/CMakeLists.txt +++ b/Examples/BasicViewerText/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_basicviewertext ${PROJECT_FILES}) target_link_libraries(example_basicviewertext PRIVATE simVis simUtil) set_target_properties(example_basicviewertext PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Basic Viewer Text" + PROJECT_LABEL "Basic Viewer Text" ) vsi_install_target(example_basicviewertext SDK_Examples) diff --git a/Examples/BeamTest/CMakeLists.txt b/Examples/BeamTest/CMakeLists.txt index a1d2b9ad4..7662cbcce 100644 --- a/Examples/BeamTest/CMakeLists.txt +++ b/Examples/BeamTest/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_beamtest ${PROJECT_FILES}) target_link_libraries(example_beamtest PRIVATE simVis simUtil) set_target_properties(example_beamtest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Beams Test" + PROJECT_LABEL "Beams Test" ) vsi_install_target(example_beamtest SDK_Examples) diff --git a/Examples/CentroidEyePosition/CMakeLists.txt b/Examples/CentroidEyePosition/CMakeLists.txt index dde31be94..1b11dfa67 100644 --- a/Examples/CentroidEyePosition/CMakeLists.txt +++ b/Examples/CentroidEyePosition/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_centroideyeposition ${PROJECT_FILES}) target_link_libraries(example_centroideyeposition PRIVATE simVis simUtil) set_target_properties(example_centroideyeposition PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Centroid Eye Position" + PROJECT_LABEL "Centroid Eye Position" ) vsi_install_target(example_centroideyeposition SDK_Examples) diff --git a/Examples/CustomRenderingTest/CMakeLists.txt b/Examples/CustomRenderingTest/CMakeLists.txt index 3289edb62..f001a8682 100644 --- a/Examples/CustomRenderingTest/CMakeLists.txt +++ b/Examples/CustomRenderingTest/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_customrenderingtest ${PROJECT_FILES}) target_link_libraries(example_customrenderingtest PRIVATE simVis simUtil) set_target_properties(example_customrenderingtest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Custom Rendering" + PROJECT_LABEL "Custom Rendering" ) vsi_install_target(example_customrenderingtest SDK_Examples) diff --git a/Examples/DBReader/CMakeLists.txt b/Examples/DBReader/CMakeLists.txt index 66b216a66..efb359bbe 100644 --- a/Examples/DBReader/CMakeLists.txt +++ b/Examples/DBReader/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_dbreader ${PROJECT_FILES}) target_link_libraries(example_dbreader PRIVATE simVis simUtil) set_target_properties(example_dbreader PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - DB Reader" + PROJECT_LABEL "DB Reader Test" ) vsi_install_target(example_dbreader SDK_Examples) diff --git a/Examples/GOGAttachments/CMakeLists.txt b/Examples/GOGAttachments/CMakeLists.txt index 74e006e16..d0b05cddb 100644 --- a/Examples/GOGAttachments/CMakeLists.txt +++ b/Examples/GOGAttachments/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_gogattachments ${PROJECT_FILES}) target_link_libraries(example_gogattachments PRIVATE simVis simUtil) set_target_properties(example_gogattachments PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - GOG Attachments" + PROJECT_LABEL "GOG Attachments" ) vsi_install_target(example_gogattachments SDK_Examples) diff --git a/Examples/GOGReader/CMakeLists.txt b/Examples/GOGReader/CMakeLists.txt index d76591e95..7681e9131 100644 --- a/Examples/GOGReader/CMakeLists.txt +++ b/Examples/GOGReader/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_gogreader ${PROJECT_FILES}) target_link_libraries(example_gogreader PRIVATE simVis simUtil) set_target_properties(example_gogreader PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - GOG Reader" + PROJECT_LABEL "GOG Reader" ) vsi_install_target(example_gogreader SDK_Examples) diff --git a/Examples/GateTest/CMakeLists.txt b/Examples/GateTest/CMakeLists.txt index af7637f4f..b02f023a2 100644 --- a/Examples/GateTest/CMakeLists.txt +++ b/Examples/GateTest/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_gatetest ${PROJECT_FILES}) target_link_libraries(example_gatetest PRIVATE simVis simUtil) set_target_properties(example_gatetest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Gates Test" + PROJECT_LABEL "Gates Test" ) vsi_install_target(example_gatetest SDK_Examples) diff --git a/Examples/GeoFencing/CMakeLists.txt b/Examples/GeoFencing/CMakeLists.txt index 9616c38d6..890771e49 100644 --- a/Examples/GeoFencing/CMakeLists.txt +++ b/Examples/GeoFencing/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_geofencing ${PROJECT_FILES}) target_link_libraries(example_geofencing PRIVATE simVis simUtil) set_target_properties(example_geofencing PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - GeoFencing" + PROJECT_LABEL "GeoFencing" ) vsi_install_target(example_geofencing SDK_Examples) diff --git a/Examples/HudPositionManager/CMakeLists.txt b/Examples/HudPositionManager/CMakeLists.txt index f8ce3d310..303e5c4fe 100644 --- a/Examples/HudPositionManager/CMakeLists.txt +++ b/Examples/HudPositionManager/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_hudpositionmanager ${PROJECT_FILES}) target_link_libraries(example_hudpositionmanager PRIVATE simVis simUtil) set_target_properties(example_hudpositionmanager PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - HUD Position Manager" + PROJECT_LABEL "HUD Position Manager" ) vsi_install_target(example_hudpositionmanager SDK_Examples) diff --git a/Examples/ImageIcons/CMakeLists.txt b/Examples/ImageIcons/CMakeLists.txt index 6589ec7c8..14098d02c 100644 --- a/Examples/ImageIcons/CMakeLists.txt +++ b/Examples/ImageIcons/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_imageicons ${PROJECT_FILES}) target_link_libraries(example_imageicons PRIVATE simVis simUtil) set_target_properties(example_imageicons PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Image Icons" + PROJECT_LABEL "Image Icons" ) vsi_install_target(example_imageicons SDK_Examples) diff --git a/Examples/LOBTest/CMakeLists.txt b/Examples/LOBTest/CMakeLists.txt index 3844a2048..3400aa27e 100644 --- a/Examples/LOBTest/CMakeLists.txt +++ b/Examples/LOBTest/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_lobtest ${PROJECT_FILES}) target_link_libraries(example_lobtest PRIVATE simVis simUtil) set_target_properties(example_lobtest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Line of Bearing Test" + PROJECT_LABEL "Line of Bearing Test" ) vsi_install_target(example_lobtest SDK_Examples) diff --git a/Examples/LoadEarthFile/CMakeLists.txt b/Examples/LoadEarthFile/CMakeLists.txt index 9ac312ea2..706773676 100644 --- a/Examples/LoadEarthFile/CMakeLists.txt +++ b/Examples/LoadEarthFile/CMakeLists.txt @@ -8,6 +8,6 @@ add_executable(example_loadearthfile LoadEarthFile.cpp) target_link_libraries(example_loadearthfile PRIVATE simVis simUtil OSGDB OSGEARTH) set_target_properties(example_loadearthfile PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Load Earth File" + PROJECT_LABEL "Load Earth File" ) vsi_install_target(example_loadearthfile SDK_Examples) diff --git a/Examples/LocalGrid/CMakeLists.txt b/Examples/LocalGrid/CMakeLists.txt index ec199e762..4b9ebbb9f 100644 --- a/Examples/LocalGrid/CMakeLists.txt +++ b/Examples/LocalGrid/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_localgrid ${PROJECT_FILES}) target_link_libraries(example_localgrid PRIVATE simVis simUtil simData) set_target_properties(example_localgrid PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Local Grid" + PROJECT_LABEL "Local Grid" ) vsi_install_target(example_localgrid SDK_Examples) diff --git a/Examples/LocatorTest/CMakeLists.txt b/Examples/LocatorTest/CMakeLists.txt index 033dd4009..4a21b6580 100644 --- a/Examples/LocatorTest/CMakeLists.txt +++ b/Examples/LocatorTest/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_locatortest ${PROJECT_FILES}) target_link_libraries(example_locatortest PRIVATE simVis simUtil) set_target_properties(example_locatortest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Locator Test" + PROJECT_LABEL "Locator Test" ) vsi_install_target(example_locatortest SDK_Examples) diff --git a/Examples/MapScale/CMakeLists.txt b/Examples/MapScale/CMakeLists.txt index a41c52707..513aed128 100644 --- a/Examples/MapScale/CMakeLists.txt +++ b/Examples/MapScale/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_mapscale ${PROJECT_FILES}) target_link_libraries(example_mapscale PRIVATE simVis simUtil) set_target_properties(example_mapscale PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Map Scale" + PROJECT_LABEL "Map Scale" ) vsi_install_target(example_mapscale SDK_Examples) diff --git a/Examples/MassiveData/CMakeLists.txt b/Examples/MassiveData/CMakeLists.txt index bf9c0ddbf..f5843ad70 100644 --- a/Examples/MassiveData/CMakeLists.txt +++ b/Examples/MassiveData/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_massivedata ${PROJECT_FILES}) target_link_libraries(example_massivedata PRIVATE simVis simUtil) set_target_properties(example_massivedata PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Massive Data" + PROJECT_LABEL "Massive Data" ) vsi_install_target(example_massivedata SDK_Examples) diff --git a/Examples/ObserverMaker/CMakeLists.txt b/Examples/ObserverMaker/CMakeLists.txt index e751b1b9b..1392fc9c0 100644 --- a/Examples/ObserverMaker/CMakeLists.txt +++ b/Examples/ObserverMaker/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_observermaker ${PROJECT_FILES}) target_link_libraries(example_observermaker PRIVATE simVis) set_target_properties(example_observermaker PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Observer Maker" + PROJECT_LABEL "Observer Maker" ) vsi_install_target(example_observermaker SDK_Examples) diff --git a/Examples/Ocean/CMakeLists.txt b/Examples/Ocean/CMakeLists.txt index b92ea00eb..52b8be7a7 100644 --- a/Examples/Ocean/CMakeLists.txt +++ b/Examples/Ocean/CMakeLists.txt @@ -12,7 +12,7 @@ add_executable(example_ocean ${PROJECT_FILES}) target_link_libraries(example_ocean PRIVATE simVis simUtil) set_target_properties(example_ocean PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Ocean" + PROJECT_LABEL "Ocean" ) vsi_install_target(example_ocean SDK_Examples) diff --git a/Examples/Overhead/CMakeLists.txt b/Examples/Overhead/CMakeLists.txt index 476af69ea..91eb3c6fe 100644 --- a/Examples/Overhead/CMakeLists.txt +++ b/Examples/Overhead/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_overhead ${PROJECT_FILES}) target_link_libraries(example_overhead PRIVATE simVis simUtil) set_target_properties(example_overhead PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Overhead" + PROJECT_LABEL "Overhead" ) vsi_install_target(example_overhead SDK_Examples) diff --git a/Examples/Periscope/CMakeLists.txt b/Examples/Periscope/CMakeLists.txt index 79a5f4f1a..1529204b4 100644 --- a/Examples/Periscope/CMakeLists.txt +++ b/Examples/Periscope/CMakeLists.txt @@ -12,7 +12,7 @@ add_executable(example_periscope ${PROJECT_FILES}) target_link_libraries(example_periscope PRIVATE simVis simUtil) set_target_properties(example_periscope PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Periscope" + PROJECT_LABEL "Periscope" ) vsi_install_target(example_periscope SDK_Examples) diff --git a/Examples/Picking/CMakeLists.txt b/Examples/Picking/CMakeLists.txt index f5ba987e7..f423ee8ef 100644 --- a/Examples/Picking/CMakeLists.txt +++ b/Examples/Picking/CMakeLists.txt @@ -13,6 +13,6 @@ add_executable(example_picking ${PROJECT_FILES}) target_link_libraries(example_picking PRIVATE simVis simUtil) set_target_properties(example_picking PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Picking" + PROJECT_LABEL "Picking" ) vsi_install_target(example_picking SDK_Examples) diff --git a/Examples/PlanetariumViewTest/CMakeLists.txt b/Examples/PlanetariumViewTest/CMakeLists.txt index 6958ba3e4..8a9f69cd6 100644 --- a/Examples/PlanetariumViewTest/CMakeLists.txt +++ b/Examples/PlanetariumViewTest/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_planetariumviewtest ${PROJECT_FILES}) target_link_libraries(example_planetariumviewtest PRIVATE simVis simUtil) set_target_properties(example_planetariumviewtest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Planetarium View Test" + PROJECT_LABEL "Planetarium View Test" ) vsi_install_target(example_planetariumviewtest SDK_Examples) diff --git a/Examples/PlatformAzimElevViewTest/CMakeLists.txt b/Examples/PlatformAzimElevViewTest/CMakeLists.txt index f346ca0a4..234418f5a 100644 --- a/Examples/PlatformAzimElevViewTest/CMakeLists.txt +++ b/Examples/PlatformAzimElevViewTest/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_platformazimelevviewtest ${PROJECT_FILES}) target_link_libraries(example_platformazimelevviewtest PRIVATE simVis simUtil) set_target_properties(example_platformazimelevviewtest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Platform AzimElev View Test" + PROJECT_LABEL "Platform AzimElev View Test" ) vsi_install_target(example_platformazimelevviewtest SDK_Examples) diff --git a/Examples/PlatformSymbology/CMakeLists.txt b/Examples/PlatformSymbology/CMakeLists.txt index 7b90eeba4..1729bae2b 100644 --- a/Examples/PlatformSymbology/CMakeLists.txt +++ b/Examples/PlatformSymbology/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_platformsymbology ${PROJECT_FILES}) target_link_libraries(example_platformsymbology PRIVATE simVis simUtil) set_target_properties(example_platformsymbology PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Platform Symbology" + PROJECT_LABEL "Platform Symbology" ) vsi_install_target(example_platformsymbology SDK_Examples) diff --git a/Examples/Projectors/CMakeLists.txt b/Examples/Projectors/CMakeLists.txt index f36e83069..f7770632e 100644 --- a/Examples/Projectors/CMakeLists.txt +++ b/Examples/Projectors/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_projectors ${PROJECT_FILES}) target_link_libraries(example_projectors PRIVATE simVis simUtil) set_target_properties(example_projectors PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Projectors" + PROJECT_LABEL "Projectors" ) vsi_install_target(example_projectors SDK_Examples) diff --git a/Examples/Qt/CMakeLists.txt b/Examples/Qt/CMakeLists.txt index 1094afc9f..081c3f7d1 100644 --- a/Examples/Qt/CMakeLists.txt +++ b/Examples/Qt/CMakeLists.txt @@ -20,7 +20,7 @@ target_link_libraries(example_qt PRIVATE simVis simUtil simQt) target_include_directories(example_qt PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qt PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt Integration" + PROJECT_LABEL "Qt Integration" ) vsi_install_target(example_qt SDK_Examples) diff --git a/Examples/QtActionItemModelTest/CMakeLists.txt b/Examples/QtActionItemModelTest/CMakeLists.txt index ce7d89a9c..fc065f563 100644 --- a/Examples/QtActionItemModelTest/CMakeLists.txt +++ b/Examples/QtActionItemModelTest/CMakeLists.txt @@ -20,7 +20,7 @@ target_link_libraries(example_qtactionitemmodeltest PRIVATE simQt) target_include_directories(example_qtactionitemmodeltest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qtactionitemmodeltest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt Action Item Model Test" + PROJECT_LABEL "Qt Action Item Model Test" ) vsi_install_target(example_qtactionitemmodeltest SDK_Examples) diff --git a/Examples/QtCategoryFilterTest/CMakeLists.txt b/Examples/QtCategoryFilterTest/CMakeLists.txt index 9fa4b3178..8754f5dc1 100644 --- a/Examples/QtCategoryFilterTest/CMakeLists.txt +++ b/Examples/QtCategoryFilterTest/CMakeLists.txt @@ -23,7 +23,7 @@ target_link_libraries(example_qtcategoryfiltertest PRIVATE simQt simData) target_include_directories(example_qtcategoryfiltertest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qtcategoryfiltertest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt Category Filter Test" + PROJECT_LABEL "Qt Category Filter Test" ) vsi_install_target(example_qtcategoryfiltertest SDK_Examples) diff --git a/Examples/QtColorWidgetTest/CMakeLists.txt b/Examples/QtColorWidgetTest/CMakeLists.txt index 39e5da51d..81d6607b1 100644 --- a/Examples/QtColorWidgetTest/CMakeLists.txt +++ b/Examples/QtColorWidgetTest/CMakeLists.txt @@ -26,7 +26,7 @@ target_link_libraries(example_qtcolorwidgettest PRIVATE simQt) target_include_directories(example_qtcolorwidgettest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qtcolorwidgettest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt Color Widget Test" + PROJECT_LABEL "Qt Color Widget Test" ) vsi_install_target(example_qtcolorwidgettest SDK_Examples) diff --git a/Examples/QtConsoleDataModel/CMakeLists.txt b/Examples/QtConsoleDataModel/CMakeLists.txt index 5408c0903..290040607 100644 --- a/Examples/QtConsoleDataModel/CMakeLists.txt +++ b/Examples/QtConsoleDataModel/CMakeLists.txt @@ -23,7 +23,7 @@ target_link_libraries(example_qtconsoledatamodel PRIVATE simQt simCore) target_include_directories(example_qtconsoledatamodel PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qtconsoledatamodel PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt Console Data Model" + PROJECT_LABEL "Qt Console Data Model" ) vsi_install_target(example_qtconsoledatamodel SDK_Examples) diff --git a/Examples/QtDataTableViewTest/CMakeLists.txt b/Examples/QtDataTableViewTest/CMakeLists.txt index 3a25acf61..85036ca2f 100644 --- a/Examples/QtDataTableViewTest/CMakeLists.txt +++ b/Examples/QtDataTableViewTest/CMakeLists.txt @@ -23,7 +23,7 @@ target_link_libraries(example_qtdatatableviewtest PRIVATE simQt simData simUtil) target_include_directories(example_qtdatatableviewtest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qtdatatableviewtest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt Data Table View Test" + PROJECT_LABEL "Qt Data Table View Test" ) vsi_install_target(example_qtdatatableviewtest SDK_Examples) diff --git a/Examples/QtDockableViews/CMakeLists.txt b/Examples/QtDockableViews/CMakeLists.txt index 1ee9bfb45..30901e6c3 100644 --- a/Examples/QtDockableViews/CMakeLists.txt +++ b/Examples/QtDockableViews/CMakeLists.txt @@ -21,7 +21,7 @@ target_link_libraries(example_qtdockableviews PRIVATE simVis simUtil simQt) target_include_directories(example_qtdockableviews PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qtdockableviews PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt Dockable Views" + PROJECT_LABEL "Qt Dockable Views" ) vsi_install_target(example_qtdockableviews SDK_Examples) diff --git a/Examples/QtEntityLineEditTest/CMakeLists.txt b/Examples/QtEntityLineEditTest/CMakeLists.txt index f25e12746..04d3566f1 100644 --- a/Examples/QtEntityLineEditTest/CMakeLists.txt +++ b/Examples/QtEntityLineEditTest/CMakeLists.txt @@ -23,7 +23,7 @@ target_link_libraries(example_qtentitylineedittest PRIVATE simQt simData simVis) target_include_directories(example_qtentitylineedittest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qtentitylineedittest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt Entity Line Edit Test" + PROJECT_LABEL "Qt Entity Line Edit Test" ) vsi_install_target(example_qtentitylineedittest SDK_Examples) diff --git a/Examples/QtEntityViewTest/CMakeLists.txt b/Examples/QtEntityViewTest/CMakeLists.txt index 61acb445f..41e634b45 100644 --- a/Examples/QtEntityViewTest/CMakeLists.txt +++ b/Examples/QtEntityViewTest/CMakeLists.txt @@ -26,7 +26,7 @@ endif() target_include_directories(example_qtentityviewtest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qtentityviewtest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt Entity View Test" + PROJECT_LABEL "Qt Entity View Test" ) vsi_install_target(example_qtentityviewtest SDK_Examples) diff --git a/Examples/QtFileSelectorTest/CMakeLists.txt b/Examples/QtFileSelectorTest/CMakeLists.txt index 2c26aa3a8..1908a6c80 100644 --- a/Examples/QtFileSelectorTest/CMakeLists.txt +++ b/Examples/QtFileSelectorTest/CMakeLists.txt @@ -26,7 +26,7 @@ target_link_libraries(example_qtfileselectortest PRIVATE simQt simCore) target_include_directories(example_qtfileselectortest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qtfileselectortest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt File Selector Test" + PROJECT_LABEL "Qt File Selector Test" ) vsi_install_target(example_qtfileselectortest SDK_Examples) diff --git a/Examples/QtThreadExample/CMakeLists.txt b/Examples/QtThreadExample/CMakeLists.txt index 02cb33115..9b9f2a360 100644 --- a/Examples/QtThreadExample/CMakeLists.txt +++ b/Examples/QtThreadExample/CMakeLists.txt @@ -35,7 +35,7 @@ target_link_libraries(example_qtthreadexample PRIVATE simCore simData simVis target_include_directories(example_qtthreadexample PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qtthreadexample PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt Thread Example" + PROJECT_LABEL "Qt Thread Example" ) vsi_install_target(example_qtthreadexample SDK_Examples) diff --git a/Examples/QtTimeButtons/CMakeLists.txt b/Examples/QtTimeButtons/CMakeLists.txt index e7bb35066..50e75ed3a 100644 --- a/Examples/QtTimeButtons/CMakeLists.txt +++ b/Examples/QtTimeButtons/CMakeLists.txt @@ -21,7 +21,7 @@ target_link_libraries(example_qttimebuttons PRIVATE simQt simCore target_include_directories(example_qttimebuttons PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qttimebuttons PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt Time Buttons" + PROJECT_LABEL "Qt Time Buttons" ) vsi_install_target(example_qttimebuttons SDK_Examples) diff --git a/Examples/QtTimeWidgetTest/CMakeLists.txt b/Examples/QtTimeWidgetTest/CMakeLists.txt index 99a3290e2..bf78263e4 100644 --- a/Examples/QtTimeWidgetTest/CMakeLists.txt +++ b/Examples/QtTimeWidgetTest/CMakeLists.txt @@ -24,7 +24,7 @@ target_link_libraries(example_qttimewidgettest PRIVATE simQt simCore) target_include_directories(example_qttimewidgettest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qttimewidgettest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt Time Widget Test" + PROJECT_LABEL "Qt Time Widget Test" ) vsi_install_target(example_qttimewidgettest SDK_Examples) diff --git a/Examples/QtUnitsWidgetTest/CMakeLists.txt b/Examples/QtUnitsWidgetTest/CMakeLists.txt index acca63bec..2a9c09a8f 100644 --- a/Examples/QtUnitsWidgetTest/CMakeLists.txt +++ b/Examples/QtUnitsWidgetTest/CMakeLists.txt @@ -24,7 +24,7 @@ target_link_libraries(example_qtunitswidgettest PRIVATE simQt) target_include_directories(example_qtunitswidgettest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(example_qtunitswidgettest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt Units Widget Test" + PROJECT_LABEL "Qt Units Widget Test" ) vsi_install_target(example_qtunitswidgettest SDK_Examples) diff --git a/Examples/QtViewManagerDataModel/CMakeLists.txt b/Examples/QtViewManagerDataModel/CMakeLists.txt index b27b59b9c..debe855b5 100644 --- a/Examples/QtViewManagerDataModel/CMakeLists.txt +++ b/Examples/QtViewManagerDataModel/CMakeLists.txt @@ -17,7 +17,7 @@ add_executable(example_qtviewmanagerdatamodel ${PROJECT_FILES} ${PROJECT_MOC_FIL target_link_libraries(example_qtviewmanagerdatamodel PRIVATE simVis simUtil simQt) set_target_properties(example_qtviewmanagerdatamodel PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt View Manager Data Model" + PROJECT_LABEL "Qt View Manager Data Model" ) vsi_install_target(example_qtviewmanagerdatamodel SDK_Examples) diff --git a/Examples/QtViewManagerTest/CMakeLists.txt b/Examples/QtViewManagerTest/CMakeLists.txt index 37d0e9cde..23a68d42d 100644 --- a/Examples/QtViewManagerTest/CMakeLists.txt +++ b/Examples/QtViewManagerTest/CMakeLists.txt @@ -15,7 +15,7 @@ add_executable(example_qtviewmanagertest ${PROJECT_FILES}) target_link_libraries(example_qtviewmanagertest PRIVATE simVis simUtil simQt) set_target_properties(example_qtviewmanagertest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Qt View Manager Test" + PROJECT_LABEL "Qt View Manager Test" ) vsi_install_target(example_qtviewmanagertest SDK_Examples) diff --git a/Examples/RCS/CMakeLists.txt b/Examples/RCS/CMakeLists.txt index d8ba8760c..17aa23378 100644 --- a/Examples/RCS/CMakeLists.txt +++ b/Examples/RCS/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_rcs ${PROJECT_FILES}) target_link_libraries(example_rcs PRIVATE simVis simUtil) set_target_properties(example_rcs PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - RCS" + PROJECT_LABEL "RCS" ) vsi_install_target(example_rcs SDK_Examples) diff --git a/Examples/RFProp/CMakeLists.txt b/Examples/RFProp/CMakeLists.txt index f167cc339..0432f597e 100644 --- a/Examples/RFProp/CMakeLists.txt +++ b/Examples/RFProp/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_rfprop ${PROJECT_FILES}) target_link_libraries(example_rfprop PRIVATE simVis simUtil) set_target_properties(example_rfprop PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - RF Propagation" + PROJECT_LABEL "RF Propagation" ) vsi_install_target(example_rfprop SDK_Examples) diff --git a/Examples/RadialLOS/CMakeLists.txt b/Examples/RadialLOS/CMakeLists.txt index 65fc0c21a..038da3933 100644 --- a/Examples/RadialLOS/CMakeLists.txt +++ b/Examples/RadialLOS/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_radiallos ${PROJECT_FILES}) target_link_libraries(example_radiallos PRIVATE simVis simUtil) set_target_properties(example_radiallos PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Radial LOS" + PROJECT_LABEL "Radial LOS" ) vsi_install_target(example_radiallos SDK_Examples) diff --git a/Examples/RangeTool/CMakeLists.txt b/Examples/RangeTool/CMakeLists.txt index c7c9c32af..29664df2e 100644 --- a/Examples/RangeTool/CMakeLists.txt +++ b/Examples/RangeTool/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_rangetool ${PROJECT_FILES}) target_link_libraries(example_rangetool PRIVATE simVis simUtil) set_target_properties(example_rangetool PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Range Tool" + PROJECT_LABEL "Range Tool" ) vsi_install_target(example_rangetool SDK_Examples) diff --git a/Examples/RocketBurn/CMakeLists.txt b/Examples/RocketBurn/CMakeLists.txt index da0203025..d34c49d05 100644 --- a/Examples/RocketBurn/CMakeLists.txt +++ b/Examples/RocketBurn/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_rocketburn ${PROJECT_FILES}) target_link_libraries(example_rocketburn PRIVATE simVis simUtil) set_target_properties(example_rocketburn PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Rocket Burn" + PROJECT_LABEL "Rocket Burn" ) vsi_install_target(example_rocketburn SDK_Examples) diff --git a/Examples/SimpleServer/CMakeLists.txt b/Examples/SimpleServer/CMakeLists.txt index 1ae360f59..ffddbd5c9 100644 --- a/Examples/SimpleServer/CMakeLists.txt +++ b/Examples/SimpleServer/CMakeLists.txt @@ -20,7 +20,7 @@ add_executable(example_simpleserver ${PROJECT_FILES}) target_link_libraries(example_simpleserver PRIVATE simVis simUtil) set_target_properties(example_simpleserver PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Simple Server" + PROJECT_LABEL "Simple Server" ) vsi_install_target(example_simpleserver SDK_Examples) diff --git a/Examples/SkyModel/CMakeLists.txt b/Examples/SkyModel/CMakeLists.txt index cace9e069..2ef0432c5 100644 --- a/Examples/SkyModel/CMakeLists.txt +++ b/Examples/SkyModel/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_skymodel ${PROJECT_FILES}) target_link_libraries(example_skymodel PRIVATE simVis simUtil) set_target_properties(example_skymodel PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Sky Model" + PROJECT_LABEL "Sky Model" ) vsi_install_target(example_skymodel SDK_Examples) diff --git a/Examples/TimestampedLayer/CMakeLists.txt b/Examples/TimestampedLayer/CMakeLists.txt index 1c97a5fc7..c466165a8 100644 --- a/Examples/TimestampedLayer/CMakeLists.txt +++ b/Examples/TimestampedLayer/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_timestampedlayer ${PROJECT_FILES}) target_link_libraries(example_timestampedlayer PRIVATE simVis simUtil) set_target_properties(example_timestampedlayer PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Timestamped Layer" + PROJECT_LABEL "Timestamped Layer" ) vsi_install_target(example_timestampedlayer SDK_Examples) diff --git a/Examples/TrackHistoryTest/CMakeLists.txt b/Examples/TrackHistoryTest/CMakeLists.txt index eb6b1e197..d30560d69 100644 --- a/Examples/TrackHistoryTest/CMakeLists.txt +++ b/Examples/TrackHistoryTest/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_trackhistorytest ${PROJECT_FILES}) target_link_libraries(example_trackhistorytest PRIVATE simVis simUtil) set_target_properties(example_trackhistorytest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - Track History Test" + PROJECT_LABEL "Track History Test" ) vsi_install_target(example_trackhistorytest SDK_Examples) diff --git a/Examples/ViewManagerTest/CMakeLists.txt b/Examples/ViewManagerTest/CMakeLists.txt index 89605cd1d..cc6f3a58d 100644 --- a/Examples/ViewManagerTest/CMakeLists.txt +++ b/Examples/ViewManagerTest/CMakeLists.txt @@ -12,6 +12,6 @@ add_executable(example_viewmanagertest ${PROJECT_FILES}) target_link_libraries(example_viewmanagertest PRIVATE simVis simUtil) set_target_properties(example_viewmanagertest PROPERTIES FOLDER "Examples" - PROJECT_LABEL "Example - View Manager Test" + PROJECT_LABEL "View Manager Test" ) vsi_install_target(example_viewmanagertest SDK_Examples) diff --git a/Plugins/OSGEarthDBDriver/CMakeLists.txt b/Plugins/OSGEarthDBDriver/CMakeLists.txt index 9d276a300..49fbafed2 100644 --- a/Plugins/OSGEarthDBDriver/CMakeLists.txt +++ b/Plugins/OSGEarthDBDriver/CMakeLists.txt @@ -45,6 +45,6 @@ endif() set_target_properties(osgdb_osgearth_db PROPERTIES PREFIX "" FOLDER "OSG Plugins" - PROJECT_LABEL "Plugin - OSGEarth .db Driver" + PROJECT_LABEL "osgEarth .db Driver" ) vsi_install_shared_library(osgdb_osgearth_db SDK_OSG_Plugins "${INSTALLSETTINGS_OSGPLUGIN_DIR}") diff --git a/Plugins/QtDesignerWidgets/CMakeLists.txt b/Plugins/QtDesignerWidgets/CMakeLists.txt index dfc363099..0a615f74d 100644 --- a/Plugins/QtDesignerWidgets/CMakeLists.txt +++ b/Plugins/QtDesignerWidgets/CMakeLists.txt @@ -94,7 +94,7 @@ target_include_directories(simQtDesignerWidgets PRIVATE ${CMAKE_CURRENT_BINARY_D target_compile_definitions(simQtDesignerWidgets PRIVATE QDESIGNER_EXPORT_WIDGETS) set_target_properties(simQtDesignerWidgets PROPERTIES FOLDER "Qt Designer Plugins" - PROJECT_LABEL "Plugin - simQt Designer Widgets") + PROJECT_LABEL "simQt Designer Widgets") if(OSG_FOUND) target_compile_definitions(simQtDesignerWidgets PRIVATE HAVE_OSG) diff --git a/SDK/simCore/CMakeLists.txt b/SDK/simCore/CMakeLists.txt index 44d9bedfa..2a8514275 100644 --- a/SDK/simCore/CMakeLists.txt +++ b/SDK/simCore/CMakeLists.txt @@ -195,7 +195,7 @@ endif() add_library(simCore ${STATIC_OR_SHARED} ${CORE_PROJECT_FILES}) set_target_properties(simCore PROPERTIES FOLDER "SIMDIS SDK" - PROJECT_LABEL "SIMDIS SDK - Core" + PROJECT_LABEL "simCore" ) ApplySDKVersion(simCore) target_include_directories(simCore PUBLIC diff --git a/SDK/simData/CMakeLists.txt b/SDK/simData/CMakeLists.txt index c80af4971..fa42463a5 100644 --- a/SDK/simData/CMakeLists.txt +++ b/SDK/simData/CMakeLists.txt @@ -141,7 +141,7 @@ vsi_protobuf_generate(simData_protobuf_generation "${CMAKE_CURRENT_SOURCE_DIR}/G SIMDATA_PROTO_H SIMDATA_PROTO_CC =dllexport_decl=SDKDATA_EXPORT:.) set_target_properties(simData_protobuf_generation PROPERTIES FOLDER "SIMDIS SDK" - PROJECT_LABEL "SIMDIS SDK - Data Protobuf Generation") + PROJECT_LABEL "simData Protobuf Generation") # ---------------------------------------------------------------------- @@ -159,7 +159,7 @@ endif() add_library(simData ${STATIC_OR_SHARED} ${DATA_PROJECT_FILES}) set_target_properties(simData PROPERTIES FOLDER "SIMDIS SDK" - PROJECT_LABEL "SIMDIS SDK - Data" + PROJECT_LABEL "simData" ) ApplySDKVersion(simData) # Need binary path for generated CMake files diff --git a/SDK/simNotify/CMakeLists.txt b/SDK/simNotify/CMakeLists.txt index 3361ffb57..218ac6551 100644 --- a/SDK/simNotify/CMakeLists.txt +++ b/SDK/simNotify/CMakeLists.txt @@ -36,7 +36,7 @@ endif() add_library(simNotify ${STATIC_OR_SHARED} ${NOTIFY_PROJECT_FILES}) set_target_properties(simNotify PROPERTIES FOLDER "SIMDIS SDK" - PROJECT_LABEL "SIMDIS SDK - Notify" + PROJECT_LABEL "simNotify" ) ApplySDKVersion(simNotify) target_include_directories(simNotify PUBLIC diff --git a/SDK/simQt/CMakeLists.txt b/SDK/simQt/CMakeLists.txt index 3a68bea63..0eea03ac8 100644 --- a/SDK/simQt/CMakeLists.txt +++ b/SDK/simQt/CMakeLists.txt @@ -287,7 +287,7 @@ endif() add_library(simQt ${STATIC_OR_SHARED} ${SIMQT_PROJECT_FILES}) set_target_properties(simQt PROPERTIES FOLDER "SIMDIS SDK" - PROJECT_LABEL "SIMDIS SDK - Qt" + PROJECT_LABEL "simQt" ) ApplySDKVersion(simQt) target_include_directories(simQt diff --git a/SDK/simUtil/CMakeLists.txt b/SDK/simUtil/CMakeLists.txt index 4383f7f33..3c550fe2d 100644 --- a/SDK/simUtil/CMakeLists.txt +++ b/SDK/simUtil/CMakeLists.txt @@ -132,7 +132,7 @@ endif() add_library(simUtil ${STATIC_OR_SHARED} ${UTIL_PROJECT_FILES}) set_target_properties(simUtil PROPERTIES FOLDER "SIMDIS SDK" - PROJECT_LABEL "SIMDIS SDK - Util" + PROJECT_LABEL "simUtil" ) ApplySDKVersion(simUtil) target_include_directories(simUtil PUBLIC diff --git a/SDK/simVis/CMakeLists.txt b/SDK/simVis/CMakeLists.txt index 4cb56237f..4256d3309 100644 --- a/SDK/simVis/CMakeLists.txt +++ b/SDK/simVis/CMakeLists.txt @@ -386,7 +386,7 @@ endif() add_library(simVis ${STATIC_OR_SHARED} ${VIS_PROJECT_FILES}) set_target_properties(simVis PROPERTIES FOLDER "SIMDIS SDK" - PROJECT_LABEL "SIMDIS SDK - Vis" + PROJECT_LABEL "simVis" ) ApplySDKVersion(simVis) target_include_directories(simVis PUBLIC diff --git a/Testing/SimCore/CMakeLists.txt b/Testing/SimCore/CMakeLists.txt index 1ce764438..6dc10f5f6 100644 --- a/Testing/SimCore/CMakeLists.txt +++ b/Testing/SimCore/CMakeLists.txt @@ -45,7 +45,7 @@ if(TARGET simUtil) endif() set_target_properties(SimCoreTests PROPERTIES FOLDER "Unit Tests" - PROJECT_LABEL "Unit Tests - SimCore" + PROJECT_LABEL "simCore Test" ) add_test(NAME VersionTest COMMAND SimCoreTests VersionTest) diff --git a/Testing/SimData/CMakeLists.txt b/Testing/SimData/CMakeLists.txt index a8e3dbc3f..cdac06bf2 100644 --- a/Testing/SimData/CMakeLists.txt +++ b/Testing/SimData/CMakeLists.txt @@ -33,7 +33,7 @@ add_executable(SimDataTests ${SimDataTestFiles}) target_link_libraries(SimDataTests PRIVATE simData simUtil) set_target_properties(SimDataTests PROPERTIES FOLDER "Unit Tests" - PROJECT_LABEL "Unit Tests - SimData" + PROJECT_LABEL "simData Test" ) # simQt is used in CategoryDataTest for its Regular Expression implementation diff --git a/Testing/SimData/DataStorePerformanceTest/CMakeLists.txt b/Testing/SimData/DataStorePerformanceTest/CMakeLists.txt index 22376be51..94d201d58 100644 --- a/Testing/SimData/DataStorePerformanceTest/CMakeLists.txt +++ b/Testing/SimData/DataStorePerformanceTest/CMakeLists.txt @@ -11,5 +11,5 @@ add_executable(DataStorePerformanceTest DataStorePerformanceTest.cpp) target_link_libraries(DataStorePerformanceTest PRIVATE simData simUtil) set_target_properties(DataStorePerformanceTest PROPERTIES FOLDER "Performance Tests" - PROJECT_LABEL "Performance Tests - DataStore" + PROJECT_LABEL "DataStore Test" ) diff --git a/Testing/SimNotify/CMakeLists.txt b/Testing/SimNotify/CMakeLists.txt index f913f49b6..9f5ff1fbe 100644 --- a/Testing/SimNotify/CMakeLists.txt +++ b/Testing/SimNotify/CMakeLists.txt @@ -16,7 +16,7 @@ add_executable(SimNotifyTests ${SimNotifyTestFiles} NotifySupport.h NotifySuppor target_link_libraries(SimNotifyTests PRIVATE simNotify simCore) set_target_properties(SimNotifyTests PROPERTIES FOLDER "Unit Tests" - PROJECT_LABEL "Unit Tests - SimNotify" + PROJECT_LABEL "simNotify Test" ) add_test(NAME TestNotify1 COMMAND SimNotifyTests TestNotify) add_test(NAME TestNotify2 COMMAND SimNotifyTests NotifyTest) diff --git a/Testing/SimQt/CMakeLists.txt b/Testing/SimQt/CMakeLists.txt index 2743e7bd3..20117f8a5 100644 --- a/Testing/SimQt/CMakeLists.txt +++ b/Testing/SimQt/CMakeLists.txt @@ -38,7 +38,7 @@ target_link_libraries(SimQtTests PRIVATE simQt simCore) target_include_directories(SimQtTests PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(SimQtTests PROPERTIES FOLDER "Unit Tests" - PROJECT_LABEL "Unit Tests - SimQt" + PROJECT_LABEL "simQt Test" ) VSI_QT_USE_MODULES(SimQtTests LINK_PRIVATE Widgets) diff --git a/Testing/SimUtil/CMakeLists.txt b/Testing/SimUtil/CMakeLists.txt index f294f80fd..e30b15aa1 100644 --- a/Testing/SimUtil/CMakeLists.txt +++ b/Testing/SimUtil/CMakeLists.txt @@ -13,7 +13,7 @@ add_executable(SimUtilTests ${SimUtilTestFiles}) target_link_libraries(SimUtilTests PRIVATE simUtil) set_target_properties(SimUtilTests PROPERTIES FOLDER "Unit Tests" - PROJECT_LABEL "Unit Tests - SimUtil" + PROJECT_LABEL "simUtil Test" ) add_test(NAME IdMapperTest COMMAND SimUtilTests IdMapperTest) diff --git a/Testing/SimVis/CMakeLists.txt b/Testing/SimVis/CMakeLists.txt index 2cdd29ee5..ee3ac9a99 100644 --- a/Testing/SimVis/CMakeLists.txt +++ b/Testing/SimVis/CMakeLists.txt @@ -14,7 +14,7 @@ add_executable(SimVisTests ${SimVisTestFiles}) target_link_libraries(SimVisTests PRIVATE simCore simVis) set_target_properties(SimVisTests PROPERTIES FOLDER "Unit Tests" - PROJECT_LABEL "Unit Tests - SimVis" + PROJECT_LABEL "simVis Test" ) add_test(NAME LocatorTest COMMAND SimVisTests LocatorTest) From 874d10c0a3ed390e1dbad9f6616bd17aa306c448 Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Thu, 9 Jan 2020 12:54:56 -0500 Subject: [PATCH 014/121] DEV: SDK: TimeTicks finishes up label drawing, SIM-4428, review 20345 --- SDK/simData/GeneratedCode/simData.proto | 4 +-- SDK/simVis/TimeTicks.cpp | 40 ++++++++++++++++++++----- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/SDK/simData/GeneratedCode/simData.proto b/SDK/simData/GeneratedCode/simData.proto index 0832ef6f6..8c1e48954 100644 --- a/SDK/simData/GeneratedCode/simData.proto +++ b/SDK/simData/GeneratedCode/simData.proto @@ -254,11 +254,11 @@ message CoordinateFrame { // preferences for the display of platform time ticks message TimeTickPrefs { enum DrawStyle { - NONE = 0; + NONE = 0; POINT = 1; ///< draw ticks as points LINE = 2; ///< draw ticks as lines }; - optional DrawStyle drawStyle = 1 [default = POINT]; + optional DrawStyle drawStyle = 1 [default = NONE]; /// default color is translucent white optional fixed32 color = 2 [default = 0xFFFFFF99]; /// time tick interval in seconds diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index 725dcd460..0e5cab247 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -232,35 +232,55 @@ void TimeTicks::addUpdate_(double tickTime) { lastLabelTime_ = tickTime; + // get formatted time string int refYear = 1970; simData::DataStore::Transaction t; const simData::ScenarioProperties* sp = ds_.scenarioProperties(&t); if (sp) refYear = sp->referenceyear(); - - // TODO: SIM-4428 format label text based on pref simCore::TimeStamp textTime(refYear, tickTime); - simCore::HoursTimeFormatter fmt; - std::string labelText = fmt.toString(textTime, refYear, 0); + std::string labelText; + const simData::TimeTickPrefs& timeTicks = lastPlatformPrefs_.trackprefs().timeticks(); + const simData::ElapsedTimeFormat timeFormat = timeTicks.labeltimeformat(); + // show HH:MM:SS + if (timeFormat == simData::ELAPSED_HOURS) + { + simCore::HoursWrappedTimeFormatter formatter; + labelText = formatter.toString(textTime, refYear, 0); + } + + // show MM:SS + else if (timeFormat == simData::ELAPSED_MINUTES) + { + simCore::MinutesWrappedTimeFormatter formatter; + labelText = formatter.toString(textTime, refYear, 0); + } + + // show SS + else + { + simCore::SecondsTimeFormatter formatter; + labelText = formatter.toString(textTime, refYear, 0); + } osg::MatrixTransform* xform = new osg::MatrixTransform(); osgText::Text* text = new osgText::Text(); text->setPosition(osg::Vec3(0, 0, 0)); text->setText(labelText); - const simData::TimeTickPrefs& timeTicks = lastPlatformPrefs_.trackprefs().timeticks(); std::string fileFullPath = simVis::Registry::instance()->findFontFile(timeTicks.labelfontname()); if (!fileFullPath.empty()) // only set if font file found, use default font otherwise text->setFont(fileFullPath); else text->setFont(osgEarth::Registry::instance()->getDefaultFont()); text->setAutoRotateToScreen(true); - text->setCharacterSizeMode(osgText::TextBase::OBJECT_COORDS); - text->setAlignment(osgText::TextBase::LEFT_BOTTOM); + text->setCharacterSizeMode(osgText::TextBase::SCREEN_COORDS); + text->setAlignment(osgText::TextBase::RIGHT_BOTTOM); text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT); text->setCharacterSize(timeTicks.labelfontpointsize()); text->getOrCreateStateSet()->setRenderBinToInherit(); osg::Depth* noDepthTest = new osg::Depth(osg::Depth::ALWAYS, 0, 1, false); text->getOrCreateStateSet()->setAttributeAndModes(noDepthTest, 1); + text->setColor(ColorUtils::RgbaToVec4(timeTicks.color())); xform->addChild(text); xform->setMatrix(hostMatrix); labelGroup_->addChild(xform); @@ -425,6 +445,9 @@ void TimeTicks::setPrefs(const simData::PlatformPrefs& platformPrefs, const simD { osg::StateSet* stateSet = this->getOrCreateStateSet(); osgEarth::LineDrawable::setLineWidth(stateSet, timeTicks.linewidth()); + // need to redraw points if line width changed + if (timeTicks.drawstyle() == simData::TimeTickPrefs::POINT) + resetRequested = true; } if (force || PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, color)) @@ -447,7 +470,8 @@ void TimeTicks::setPrefs(const simData::PlatformPrefs& platformPrefs, const simD PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, linelength) || PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, largesizefactor) || PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, labelfontname) || - PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, labelfontpointsize)) + PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, labelfontpointsize) || + PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, labeltimeformat)) { resetRequested = true; } From cd618e08a8fe8a6427e80171b70d5a052c516d92 Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Fri, 10 Jan 2020 09:24:13 -0500 Subject: [PATCH 015/121] DEV: SDK: TimeTicks label sets render bin to draw over top of the tick, SIM-4428, review 20355 --- SDK/simVis/TimeTicks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index 0e5cab247..e45536650 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -277,7 +277,7 @@ void TimeTicks::addUpdate_(double tickTime) text->setAlignment(osgText::TextBase::RIGHT_BOTTOM); text->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT); text->setCharacterSize(timeTicks.labelfontpointsize()); - text->getOrCreateStateSet()->setRenderBinToInherit(); + text->getOrCreateStateSet()->setRenderBinDetails(simVis::BIN_LABEL, simVis::BIN_TRAVERSAL_ORDER_SIMSDK); osg::Depth* noDepthTest = new osg::Depth(osg::Depth::ALWAYS, 0, 1, false); text->getOrCreateStateSet()->setAttributeAndModes(noDepthTest, 1); text->setColor(ColorUtils::RgbaToVec4(timeTicks.color())); From 5282b9cfb922f46a5906752789cbf21ff580b71f Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Fri, 10 Jan 2020 10:04:13 -0500 Subject: [PATCH 016/121] DEV: SDK: TimeTicks respect track override color, SIM-4428, review 20365 --- SDK/simVis/TimeTicks.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index e45536650..817ecee57 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -280,7 +280,7 @@ void TimeTicks::addUpdate_(double tickTime) text->getOrCreateStateSet()->setRenderBinDetails(simVis::BIN_LABEL, simVis::BIN_TRAVERSAL_ORDER_SIMSDK); osg::Depth* noDepthTest = new osg::Depth(osg::Depth::ALWAYS, 0, 1, false); text->getOrCreateStateSet()->setAttributeAndModes(noDepthTest, 1); - text->setColor(ColorUtils::RgbaToVec4(timeTicks.color())); + text->setColor(color_); xform->addChild(text); xform->setMatrix(hostMatrix); labelGroup_->addChild(xform); @@ -427,11 +427,22 @@ void TimeTicks::setPrefs(const simData::PlatformPrefs& platformPrefs, const simD resetRequested = true; } + // check for override color + if (force || PB_FIELD_CHANGED(&lastPrefs, &prefs, usetrackoverridecolor)) + { + resetRequested = true; + if (prefs.usetrackoverridecolor()) + color_ = simVis::Color(prefs.trackoverridecolor(), simVis::Color::RGBA); + else + color_ = simVis::Color(timeTicks.color(), simVis::Color::RGBA); + } + if (force || PB_FIELD_CHANGED(&lastPrefs, &prefs, flatmode)) { updateFlatMode_(prefs.flatmode()); } + // check for any clamping changes, which will redraw ticks if (force || PB_FIELD_CHANGED(&lastPlatformPrefs_, &platformPrefs, useclampalt) || PB_FIELD_CHANGED(&lastPlatformPrefs_, &platformPrefs, clampvalaltmin) || PB_FIELD_CHANGED(&lastPlatformPrefs_, &platformPrefs, clampvalaltmax) || @@ -450,9 +461,10 @@ void TimeTicks::setPrefs(const simData::PlatformPrefs& platformPrefs, const simD resetRequested = true; } - if (force || PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, color)) + // use tick color if not overridden by track color + if ((force || PB_FIELD_CHANGED(&lastTimeTicks, &timeTicks, color)) && !prefs.usetrackoverridecolor()) { - color_ = simVis::Color(simVis::Color(timeTicks.color(), simVis::Color::RGBA)); + color_ = simVis::Color(timeTicks.color(), simVis::Color::RGBA); resetRequested = true; } From e847241b1140896a2cfc759dde8dcdde0248e773 Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Fri, 10 Jan 2020 10:27:50 -0500 Subject: [PATCH 017/121] SDK: TimeTicks redraw when track override color changes, no review --- SDK/simVis/TimeTicks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index 817ecee57..aeab51213 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -428,7 +428,7 @@ void TimeTicks::setPrefs(const simData::PlatformPrefs& platformPrefs, const simD } // check for override color - if (force || PB_FIELD_CHANGED(&lastPrefs, &prefs, usetrackoverridecolor)) + if (force || PB_FIELD_CHANGED(&lastPrefs, &prefs, usetrackoverridecolor) || PB_FIELD_CHANGED(&lastPrefs, &prefs, trackoverridecolor)) { resetRequested = true; if (prefs.usetrackoverridecolor()) From 54f7d1ede48e0b58ab20de92d6264399c76fc48d Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Fri, 10 Jan 2020 15:12:37 -0500 Subject: [PATCH 018/121] DEV: SDK: TimeTicks now always display consistently forward or backward or if reset while data limiting, SIM-10890, review 20377 --- SDK/simVis/TimeTicks.cpp | 66 ++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index aeab51213..b600795b0 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -32,6 +32,7 @@ #include "simCore/Calc/Angle.h" #include "simCore/Calc/Calculations.h" +#include "simCore/Calc/Math.h" #include "simCore/Time/TimeClass.h" #include "simCore/Time/String.h" #include "simData/DataTable.h" @@ -188,23 +189,13 @@ void TimeTicks::addUpdate_(double tickTime) osg::Matrix hostMatrix; bool largeTick = false; - // if first tick, get the current platform position - if (chunkGroup_->getNumChildren() == 0) + // if tick is at first platform point, get the platform position at that time + if (!hasPrevious) { // special case for first point when going backwards - // need to get the possibly interpolated point to start since there may not be a point at the current location - if (timeDirection_ == simCore::REVERSE) - { - if (!hasPrevious) - return; - if (!getMatrix_(*prev, *update, tickTime, hostMatrix)) - return; - } - else - { - if (!getMatrix_(*update, hostMatrix)) - return; - } + if (!getMatrix_(*update, hostMatrix)) + return; + // first tick is always large if (largeTickInterval_ > 0 && lastLargeTickTime_ == -1) { @@ -212,8 +203,8 @@ void TimeTicks::addUpdate_(double tickTime) lastLargeTickTime_ = tickTime; } } - // not first tick, get the next position, possibly interpolated - else if (hasPrevious) + // not first tick, or not at fist platform position, get the next position, possibly interpolated + else { if (!getMatrix_(*prev, *update, tickTime, hostMatrix)) return; @@ -224,8 +215,6 @@ void TimeTicks::addUpdate_(double tickTime) largeTick = true; } } - else - return; // add label for large tick if (labelInterval_ > 0 && (lastLabelTime_ == -1.0 || abs(tickTime - lastLabelTime_) >= labelInterval_)) @@ -587,6 +576,45 @@ void TimeTicks::updateTrackData_(double currentTime, const simData::PlatformUpda } } } + // check last draw time again, since it may have been updated in the block above + if (!hasLastDrawTime_) + { + // time ticks should reference from scenario start time + double firstTime = ds_.timeBounds(0).first; + // update begin time to always count up to a valid draw time from first time in case data limiting is occurring + const double interval = lastPlatformPrefs_.trackprefs().timeticks().interval(); + if (beginTime != firstTime) + { + const double beginSpan = beginTime - firstTime; + double numIntervals = floor(beginSpan / interval); + beginTime = firstTime + (numIntervals * interval); + beginTime += interval; + + if (timeDirection_ == simCore::FORWARD) + { + // update last large tick time and labels to ensure they are always drawn consistently + numIntervals = floor(beginSpan / largeTickInterval_); + lastLargeTickTime_ = firstTime + (numIntervals * largeTickInterval_); + numIntervals = floor(beginSpan / labelInterval_); + lastLabelTime_ = firstTime + (numIntervals * labelInterval_); + } + } + if (timeDirection_ == simCore::REVERSE) + { + // set the end tick time to ensure it is at a valid interval from the first time + const double endSpan = endTime - firstTime; + double numIntervals = floor(endSpan / interval); + endTime = firstTime + (numIntervals * interval); + + // update last large tick time and labels to ensure they are always drawn consistently, make sure they are one interval past the current valid end time + numIntervals = floor(endSpan / largeTickInterval_); + lastLargeTickTime_ = firstTime + (numIntervals * largeTickInterval_); + lastLargeTickTime_ += largeTickInterval_; + numIntervals = floor(endSpan / labelInterval_); + lastLabelTime_ = firstTime + (numIntervals * labelInterval_); + lastLabelTime_ += labelInterval_; + } + } // store currentTime to enable time jump detection lastCurrentTime_ = currentTime; From 686a472e34ed1bf9c9eeff0d13b7887a4ddd6a40 Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Mon, 13 Jan 2020 10:04:32 -0500 Subject: [PATCH 019/121] DEV: SDK: TimeTicksChunk no longer draws center line for line ticks, SIM-10901, review 20383 --- SDK/simVis/TimeTicks.cpp | 76 ----------------------------------- SDK/simVis/TimeTicks.h | 7 ---- SDK/simVis/TimeTicksChunk.cpp | 46 +++++---------------- SDK/simVis/TimeTicksChunk.h | 3 +- 4 files changed, 11 insertions(+), 121 deletions(-) diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index b600795b0..199638d8b 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -621,9 +621,6 @@ void TimeTicks::updateTrackData_(double currentTime, const simData::PlatformUpda // update time ticks with points in the requested window backfillHistory_(endTime, beginTime); - - // when the current point is interpolated, line mode requires special processing - updateCurrentPoint_(updateSlice, beginTime); } void TimeTicks::backfillHistory_(double endTime, double beginTime) @@ -659,79 +656,6 @@ void TimeTicks::backfillHistory_(double endTime, double beginTime) } } -void TimeTicks::updateCurrentPoint_(const simData::PlatformUpdateSlice& updateSlice, double beginTime) -{ - // remove previous, will recreate if needed - if (currentPointChunk_ != NULL) - currentPointChunk_->reset(); - - // no current point if not line ticks - if (lastPlatformPrefs_.trackprefs().timeticks().drawstyle() == simData::TimeTickPrefs::POINT) - return; - - // only line, ribbon, and bridge draw modes require this processing, - // but if there is not a previous point, there is nothing to do - if (chunkGroup_->getNumChildren() == 0) - return; - - // create the special chunk for rendering the interpolated point, has two points to connect to rest of history for line mode - if (currentPointChunk_ == NULL) - { - const simData::TimeTickPrefs& timeTicks = lastPlatformPrefs_.trackprefs().timeticks(); - currentPointChunk_ = new TimeTicksChunk(2, TimeTicksChunk::LINE, timeTicks.linelength() / 2, timeTicks.linewidth(), timeTicks.largesizefactor()); - if (currentPointChunk_ == NULL) - return; - addChild(currentPointChunk_); - } - // find the most current update, either whatever is current, or the last available update - const simData::PlatformUpdate* current = updateSlice.current(); - if (current == NULL) - { - simData::PlatformUpdateSlice::Iterator iter = updateSlice.lower_bound(updateSlice.lastTime()); - current = iter.next(); - } - osg::Matrix curMatrix; - - // if this fails, this platform node got created with no platform data - assert(current); - - if (!getMatrix_(*current, curMatrix)) - { - // failed to get the current position, check locator - assert(0); - return; - } - - if (timeDirection_ == simCore::FORWARD) - { - TimeTicksChunk* curChunk = getLastChunk_(); - // should have a last chunk if chunk group is not empty - assert(curChunk != NULL); - osg::Matrix end; - if (curChunk->getEndMatrix(end) == 0) - currentPointChunk_->addPoint(end, curChunk->getEndTime(), color_, false); - else - assert(0); // chunk is out of sync - } - - // points must be added in order of increasing drawTime - currentPointChunk_->addPoint(curMatrix, toDrawTime_(beginTime), color_, false); - - // duplicate the most recent (non-current) datapoint so that this chunk connects to the previous chunk - if (timeDirection_ == simCore::REVERSE) - { - TimeTicksChunk* curChunk = getLastChunk_(); - curChunk = getFirstChunk_(); - // should have a first chunk if chunk group is not empty - assert(curChunk != NULL); - osg::Matrix begin; - if (curChunk->getBeginMatrix(begin) == 0) - currentPointChunk_->addPoint(begin, curChunk->getBeginTime(), color_, false); - else - assert(0); // chunk is out of sync - } -} - bool TimeTicks::getMatrix_(const simData::PlatformUpdate& u, osg::Matrix& hostMatrix) { simData::PlatformUpdate update = u; diff --git a/SDK/simVis/TimeTicks.h b/SDK/simVis/TimeTicks.h index 11a6cd90c..b06cdecf8 100644 --- a/SDK/simVis/TimeTicks.h +++ b/SDK/simVis/TimeTicks.h @@ -149,13 +149,6 @@ class SDKVIS_EXPORT TimeTicks : public osg::Group */ void backfillHistory_(double endTime, double beginTime); - /** - * Update the time ticks visuals for the current point when drawing line ticks - * @param updateSlice platform update slice for associated platform - * @param beginTime earliest platform update time to use when going in reverse - */ - void updateCurrentPoint_(const simData::PlatformUpdateSlice& updateSlice, double beginTime); - /** * Update the time ticks visuals with a point to correspond to the specified time * @param tickTime time to draw a tick diff --git a/SDK/simVis/TimeTicksChunk.cpp b/SDK/simVis/TimeTicksChunk.cpp index c95a0c63a..1c3b13b59 100644 --- a/SDK/simVis/TimeTicksChunk.cpp +++ b/SDK/simVis/TimeTicksChunk.cpp @@ -147,22 +147,10 @@ void TimeTicksChunk::allocate_() geode_ = new osgEarth::LineGroup(); addChild(geode_.get()); - // center line (line mode) - line_ = new osgEarth::LineDrawable(GL_LINE_STRIP); + // cross hatch line ticks + line_ = new osgEarth::LineDrawable(GL_LINES); line_->setDataVariance(osg::Object::DYNAMIC); - line_->allocate(4 * maxSize_); - geode_->addChild(line_.get()); - } - else if (type_ == LINE) - { - // geode to hold all line geometry: - geode_ = new osgEarth::LineGroup(); - addChild(geode_.get()); - - // center line (line mode) - line_ = new osgEarth::LineDrawable(GL_LINE_STRIP); - line_->setDataVariance(osg::Object::DYNAMIC); - line_->allocate(maxSize_); + line_->allocate(2 * maxSize_); geode_->addChild(line_.get()); } @@ -201,27 +189,18 @@ void TimeTicksChunk::append_(const osg::Matrix& matrix, const osg::Vec4& color, } else if (type_ == LINE_TICKS) { - // add a new tick. The x value and y value for - // hostBounds represents the xMin and xMax values of a bounding box respectively. + // add a new cross hatch tick const osg::Matrix posMatrix = matrix * world2local_; - double width = lineLength_ * (large ? largeSizeFactor_ : 1); const osg::Vec3f left = osg::Vec3d(-width, 0.0, 0.0) * posMatrix; const osg::Vec3f right = osg::Vec3d(width, 0.0, 0.0) * posMatrix; - line_->setVertex(4 * i, local); - line_->setVertex(4 * i + 1, left); - line_->setVertex(4 * i + 2, right); - line_->setVertex(4 * i + 3, local); + line_->setVertex(2 * i, left); + line_->setVertex(2 * i + 1, right); - for (unsigned int c = 0; c < 4; ++c) - line_->setColor(4 * i + c, color); - } - else if (type_ == LINE) - { - line_->setVertex(i, local); - line_->setColor(i, color); + for (unsigned int c = 0; c < 2; ++c) + line_->setColor(2 * i + c, color); } } @@ -243,13 +222,8 @@ void TimeTicksChunk::updatePrimitiveSets_() } else if (type_ == LINE_TICKS) { - line_->setFirst(4 * offset_); - line_->setCount(4 * count_); - } - else if (type_ == LINE) - { - line_->setFirst(offset_); - line_->setCount(count_); + line_->setFirst(2 * offset_); + line_->setCount(2 * count_); } } diff --git a/SDK/simVis/TimeTicksChunk.h b/SDK/simVis/TimeTicksChunk.h index 738c5f76b..4a970d01f 100644 --- a/SDK/simVis/TimeTicksChunk.h +++ b/SDK/simVis/TimeTicksChunk.h @@ -39,8 +39,7 @@ class SDKVIS_EXPORT TimeTicksChunk : public TrackPointsChunk enum Type { POINT_TICKS, - LINE_TICKS, - LINE + LINE_TICKS }; /** From 279b086a822085839bbd8496991e3e953adc1cf9 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Tue, 14 Jan 2020 08:38:21 -0500 Subject: [PATCH 020/121] DEV: Added missing ReadFile header, since osgEarth headers updated to not extraneously include it. Prep for SIM-10915. Review: 20397 --- Examples/ASIViewer/ASIViewer.cpp | 7 ++++--- Examples/BasicViewerText/BasicViewerText.cpp | 2 +- Examples/Periscope/PeriscopeExample.cpp | 1 + Examples/PlatformSymbology/PlatformSymbology.cpp | 1 + Examples/RocketBurn/RocketBurn.cpp | 1 + Examples/TimestampedLayer/ExampleTimestampedLayer.cpp | 1 + SDK/simQt/MapDataModel.h | 1 - SDK/simVis/Compass.cpp | 3 ++- SDK/simVis/ModelCache.cpp | 1 + 9 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Examples/ASIViewer/ASIViewer.cpp b/Examples/ASIViewer/ASIViewer.cpp index 9803116e6..89dfa97ff 100644 --- a/Examples/ASIViewer/ASIViewer.cpp +++ b/Examples/ASIViewer/ASIViewer.cpp @@ -43,9 +43,10 @@ #include "simVis/Types.h" #include "simUtil/ExampleResources.h" -#include -#include -#include +#include "osg/ImageStream" +#include "osgDB/ReadFile" +#include "osgEarth/Controls" +#include "osgEarth/StringUtils" namespace ui = osgEarth::Util::Controls; diff --git a/Examples/BasicViewerText/BasicViewerText.cpp b/Examples/BasicViewerText/BasicViewerText.cpp index f6763e4d0..3c635b451 100644 --- a/Examples/BasicViewerText/BasicViewerText.cpp +++ b/Examples/BasicViewerText/BasicViewerText.cpp @@ -24,7 +24,7 @@ * BasicViewerText is the BasicViewer example with Help overlay removed and various HudManager HudText elements added. * It demonstrates HudText layout behaviors. */ - +#include "osgDB/ReadFile" #include "simNotify/Notify.h" #include "simCore/Common/Version.h" #include "simCore/Common/HighPerformanceGraphics.h" diff --git a/Examples/Periscope/PeriscopeExample.cpp b/Examples/Periscope/PeriscopeExample.cpp index 412187f96..f301cef07 100644 --- a/Examples/Periscope/PeriscopeExample.cpp +++ b/Examples/Periscope/PeriscopeExample.cpp @@ -42,6 +42,7 @@ #include "simUtil/ExampleResources.h" #include "simUtil/HudManager.h" +#include "osgDB/ReadFile" #include "osgEarth/Controls" #include "osgEarth/SimpleOceanLayer" #include "osgEarth/Version" diff --git a/Examples/PlatformSymbology/PlatformSymbology.cpp b/Examples/PlatformSymbology/PlatformSymbology.cpp index 4608d84e9..77a99ac10 100644 --- a/Examples/PlatformSymbology/PlatformSymbology.cpp +++ b/Examples/PlatformSymbology/PlatformSymbology.cpp @@ -59,6 +59,7 @@ /// paths to models #include "simUtil/ExampleResources.h" +#include "osgDB/ReadFile" #include "osgEarth/LatLongFormatter" #include "osgEarth/MGRSFormatter" #include "osgEarth/StringUtils" diff --git a/Examples/RocketBurn/RocketBurn.cpp b/Examples/RocketBurn/RocketBurn.cpp index b8abdbd31..0df9ef242 100644 --- a/Examples/RocketBurn/RocketBurn.cpp +++ b/Examples/RocketBurn/RocketBurn.cpp @@ -19,6 +19,7 @@ * disclose, or release this software. * */ +#include "osgDB/ReadFile" #include "simCore/Common/Version.h" #include "simCore/Common/HighPerformanceGraphics.h" #include "simData/MemoryDataStore.h" diff --git a/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp b/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp index 9c4d7a84a..287973474 100644 --- a/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp +++ b/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp @@ -20,6 +20,7 @@ * */ +#include "osgDB/ReadFile" #include "osgEarth/Map" #include "osgEarth/MapNode" #include "osgEarth/VisibleLayer" diff --git a/SDK/simQt/MapDataModel.h b/SDK/simQt/MapDataModel.h index 335aae4a6..a42f13a69 100644 --- a/SDK/simQt/MapDataModel.h +++ b/SDK/simQt/MapDataModel.h @@ -35,7 +35,6 @@ namespace osgEarth { class Layer; class Map; - class TerrainLayer; } typedef std::vector > FeatureModelLayerVector; diff --git a/SDK/simVis/Compass.cpp b/SDK/simVis/Compass.cpp index c7039538c..dc140a09f 100644 --- a/SDK/simVis/Compass.cpp +++ b/SDK/simVis/Compass.cpp @@ -19,6 +19,7 @@ * disclose, or release this software. * */ +#include "osgDB/ReadFile" #include "osgEarth/NodeUtils" #include "osgEarth/AnnotationUtils" #include "simCore/Calc/Angle.h" @@ -163,7 +164,7 @@ void CompassNode::initCompass_(const std::string& compassFilename) 0, // texture image unit 0.0, // heading image->s() / COMPASS_SIZE); // scale, down to 128x128 - + // Texture is likely GL_LUMINANCE or GL_LUMINANCE_ALPHA; fix it if so if (compass && compass->getStateSet()) { diff --git a/SDK/simVis/ModelCache.cpp b/SDK/simVis/ModelCache.cpp index 18c91efcd..282f70ac0 100644 --- a/SDK/simVis/ModelCache.cpp +++ b/SDK/simVis/ModelCache.cpp @@ -32,6 +32,7 @@ #include "osg/TexEnv" #include "osg/TexEnvCombine" #include "osg/ValueObject" +#include "osgDB/ReadFile" #include "osgSim/DOFTransform" #include "osgSim/LightPointNode" #include "osgSim/MultiSwitch" From e2cdc1c16c185026de7018df834e0b48afe20a4a Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Tue, 14 Jan 2020 09:20:40 -0500 Subject: [PATCH 021/121] DEV: SDK: TimeTicks draw first point properly when playing time backwards, SIM-10913, review 20394 --- SDK/simVis/Platform.cpp | 4 ++++ SDK/simVis/TimeTicks.cpp | 26 ++++++++------------------ 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/SDK/simVis/Platform.cpp b/SDK/simVis/Platform.cpp index 72279c062..d8597d13f 100644 --- a/SDK/simVis/Platform.cpp +++ b/SDK/simVis/Platform.cpp @@ -653,6 +653,10 @@ bool PlatformNode::createTrackHistoryNode_(const simData::PlatformPrefs& prefs) const bool prefsDraw = lastPrefs_.commonprefs().datadraw() && prefs.commonprefs().draw(); track_->setNodeMask(prefsDraw ? simVis::DISPLAY_MASK_TRACK_HISTORY : simVis::DISPLAY_MASK_NONE); + // check to see if we need to create time ticks, since time ticks, like track history, can be turned on before platform is actually valid + if ((prefs.trackprefs().timeticks().drawstyle() != simData::TimeTickPrefs::NONE) && !timeTicks_.valid()) + createTimeTicks_(prefs); + return true; } diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index 199638d8b..f836db971 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -192,28 +192,18 @@ void TimeTicks::addUpdate_(double tickTime) // if tick is at first platform point, get the platform position at that time if (!hasPrevious) { - // special case for first point when going backwards if (!getMatrix_(*update, hostMatrix)) return; - - // first tick is always large - if (largeTickInterval_ > 0 && lastLargeTickTime_ == -1) - { - largeTick = true; - lastLargeTickTime_ = tickTime; - } } - // not first tick, or not at fist platform position, get the next position, possibly interpolated - else + // not first tick, or not at first platform position, get the next position, possibly interpolated + else if (!getMatrix_(*prev, *update, tickTime, hostMatrix)) + return; + + // check to see if it is time for the next large tick + if (largeTickInterval_ > 0 && (lastLargeTickTime_ == -1 || abs(tickTime - lastLargeTickTime_) >= largeTickInterval_)) { - if (!getMatrix_(*prev, *update, tickTime, hostMatrix)) - return; - // check to see if it is time for the next large tick - if (largeTickInterval_ > 0 && (lastLargeTickTime_ == -1.0 || abs(tickTime - lastLargeTickTime_) >= largeTickInterval_)) - { - lastLargeTickTime_ = tickTime; - largeTick = true; - } + lastLargeTickTime_ = tickTime; + largeTick = true; } // add label for large tick From 446bd6f2b4ca9ed6cd557b51a30b8d57bba3cde8 Mon Sep 17 00:00:00 2001 From: gwaldron Date: Tue, 14 Jan 2020 12:30:49 -0500 Subject: [PATCH 022/121] Apply TileLayer/TileSource refactor --- Examples/ASIViewer/ASIViewer.cpp | 1 + Examples/BasicViewer/BasicViewer.cpp | 1 - Examples/BasicViewerText/BasicViewerText.cpp | 1 + Examples/Periscope/PeriscopeExample.cpp | 2 + .../PlatformSymbology/PlatformSymbology.cpp | 2 + Examples/RocketBurn/RocketBurn.cpp | 2 + .../ExampleTimestampedLayer.cpp | 1 + .../OSGEarthDBDriver/include/DBTileSource.h | 4 +- Plugins/OSGEarthDBDriver/src/DBTileSource.cpp | 4 +- Plugins/OSGEarthDBDriver/src/Plugin.cpp | 2 +- SDK/simVis/Compass.cpp | 1 + SDK/simVis/DBFormat.cpp | 343 +----------------- SDK/simVis/DBFormat.h | 34 +- SDK/simVis/DBOptions.h | 6 +- SDK/simVis/LayerRefreshCallback.cpp | 14 +- SDK/simVis/LayerRefreshCallback.h | 6 +- SDK/simVis/ModelCache.cpp | 1 + SDK/simVis/SceneManager.cpp | 4 +- SDK/simVis/SceneManager.h | 4 +- 19 files changed, 67 insertions(+), 366 deletions(-) diff --git a/Examples/ASIViewer/ASIViewer.cpp b/Examples/ASIViewer/ASIViewer.cpp index 9803116e6..df2a4ae89 100644 --- a/Examples/ASIViewer/ASIViewer.cpp +++ b/Examples/ASIViewer/ASIViewer.cpp @@ -46,6 +46,7 @@ #include #include #include +#include "osgDB/ReadFile" namespace ui = osgEarth::Util::Controls; diff --git a/Examples/BasicViewer/BasicViewer.cpp b/Examples/BasicViewer/BasicViewer.cpp index a58d53f34..1b0b316f1 100644 --- a/Examples/BasicViewer/BasicViewer.cpp +++ b/Examples/BasicViewer/BasicViewer.cpp @@ -25,7 +25,6 @@ * map control. It shows how to adjust window appearance, how to add or remove * inset views, and how to change the motion model. */ - #include "simNotify/Notify.h" #include "simCore/Common/Version.h" #include "simCore/Common/HighPerformanceGraphics.h" diff --git a/Examples/BasicViewerText/BasicViewerText.cpp b/Examples/BasicViewerText/BasicViewerText.cpp index f6763e4d0..2f1b4a5c0 100644 --- a/Examples/BasicViewerText/BasicViewerText.cpp +++ b/Examples/BasicViewerText/BasicViewerText.cpp @@ -39,6 +39,7 @@ #include "simUtil/HudManager.h" #include "simUtil/Replaceables.h" #include "simUtil/StatusText.h" +#include "osgDB/ReadFile" #define LC "[BasicViewerText demo] " diff --git a/Examples/Periscope/PeriscopeExample.cpp b/Examples/Periscope/PeriscopeExample.cpp index 412187f96..535afdd2d 100644 --- a/Examples/Periscope/PeriscopeExample.cpp +++ b/Examples/Periscope/PeriscopeExample.cpp @@ -46,6 +46,8 @@ #include "osgEarth/SimpleOceanLayer" #include "osgEarth/Version" +#include "osgDB/ReadFile" + #ifdef HAVE_TRITON_NODEKIT #include "osgEarthTriton/TritonLayer" #endif diff --git a/Examples/PlatformSymbology/PlatformSymbology.cpp b/Examples/PlatformSymbology/PlatformSymbology.cpp index 4608d84e9..756398b88 100644 --- a/Examples/PlatformSymbology/PlatformSymbology.cpp +++ b/Examples/PlatformSymbology/PlatformSymbology.cpp @@ -64,6 +64,8 @@ #include "osgEarth/StringUtils" #include "osgEarth/Style" +#include "osgDB/ReadFile" + #include "google/protobuf/stubs/common.h" using namespace osgEarth; diff --git a/Examples/RocketBurn/RocketBurn.cpp b/Examples/RocketBurn/RocketBurn.cpp index b8abdbd31..a32040321 100644 --- a/Examples/RocketBurn/RocketBurn.cpp +++ b/Examples/RocketBurn/RocketBurn.cpp @@ -34,6 +34,8 @@ #include "simUtil/ExampleResources.h" #include "simUtil/PlatformSimulator.h" +#include "osgDB/ReadFile" + namespace { /// get time and platform removal notifications diff --git a/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp b/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp index 9c4d7a84a..12e1f5ec5 100644 --- a/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp +++ b/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp @@ -30,6 +30,7 @@ #include "simVis/SceneManager.h" #include "simVis/Viewer.h" #include "simUtil/ExampleResources.h" +#include "osgDB/ReadFile" namespace ui = osgEarth::Util::Controls; diff --git a/Plugins/OSGEarthDBDriver/include/DBTileSource.h b/Plugins/OSGEarthDBDriver/include/DBTileSource.h index d8230b54d..f2dfc4c5a 100644 --- a/Plugins/OSGEarthDBDriver/include/DBTileSource.h +++ b/Plugins/OSGEarthDBDriver/include/DBTileSource.h @@ -32,11 +32,11 @@ namespace simVis_db { - class DBTileSource : public osgEarth::TileSource + class DBTileSource : public osgEarth::Contrib::TileSource { public: /** Constructs a new driver for reading .DB raster files */ - DBTileSource(const osgEarth::TileSourceOptions& options); + DBTileSource(const osgEarth::Contrib::TileSourceOptions& options); /// TileSource interface virtual osgEarth::Status initialize(const osgDB::Options* dbOptions); diff --git a/Plugins/OSGEarthDBDriver/src/DBTileSource.cpp b/Plugins/OSGEarthDBDriver/src/DBTileSource.cpp index 7766d3059..93e67f921 100644 --- a/Plugins/OSGEarthDBDriver/src/DBTileSource.cpp +++ b/Plugins/OSGEarthDBDriver/src/DBTileSource.cpp @@ -120,8 +120,8 @@ namespace // -------------------------------------------------------------------------- -DBTileSource::DBTileSource(const osgEarth::TileSourceOptions& options) - : osgEarth::TileSource(options), +DBTileSource::DBTileSource(const osgEarth::Contrib::TileSourceOptions& options) + : osgEarth::Contrib::TileSource(options), options_(options), db_(NULL), rasterFormat_(SPLIT_UNKNOWN), diff --git a/Plugins/OSGEarthDBDriver/src/Plugin.cpp b/Plugins/OSGEarthDBDriver/src/Plugin.cpp index b97c685b0..43635c2b5 100644 --- a/Plugins/OSGEarthDBDriver/src/Plugin.cpp +++ b/Plugins/OSGEarthDBDriver/src/Plugin.cpp @@ -25,7 +25,7 @@ #include #include "DBTileSource.h" -class SimSdkOSGEarthDBDriverPlugin : public osgEarth::TileSourceDriver +class SimSdkOSGEarthDBDriverPlugin : public osgEarth::Contrib::TileSourceDriver { public: SimSdkOSGEarthDBDriverPlugin() { } diff --git a/SDK/simVis/Compass.cpp b/SDK/simVis/Compass.cpp index c7039538c..c3d636158 100644 --- a/SDK/simVis/Compass.cpp +++ b/SDK/simVis/Compass.cpp @@ -28,6 +28,7 @@ #include "simVis/Utils.h" #include "simVis/View.h" #include "simVis/Compass.h" +#include "osgDB/ReadFile" namespace simVis { diff --git a/SDK/simVis/DBFormat.cpp b/SDK/simVis/DBFormat.cpp index 0f6398436..04c2fd7e5 100644 --- a/SDK/simVis/DBFormat.cpp +++ b/SDK/simVis/DBFormat.cpp @@ -24,308 +24,9 @@ using namespace simVis; -//........................................................... -#if 0 -#include "simCore/Common/Common.h" -#include "simCore/Calc/MathConstants.h" - -namespace simVis { namespace DB -{ - typedef int16_t LevelInt; - static const LevelInt QT_MIN_LEVEL = 0; - static const LevelInt QT_MAX_LEVEL = 32; - - typedef uint8_t ChildIndexInt; - static const ChildIndexInt QT_CHILD_NE = 0; - static const ChildIndexInt QT_CHILD_NW = 1; - static const ChildIndexInt QT_CHILD_SW = 2; - static const ChildIndexInt QT_CHILD_SE = 3; - - typedef uint8_t FaceIndexType; - static const FaceIndexType QsFaceIndexWW = 0; - static const FaceIndexType QsFaceIndexW = 1; - static const FaceIndexType QsFaceIndexE = 2; - static const FaceIndexType QsFaceIndexEE = 3; - static const FaceIndexType QsFaceIndexN = 4; - static const FaceIndexType QsFaceIndexS = 5; - - typedef float AltitudeDataType; - - static const int16_t MAX_NUM_READ_THREADS = 128; - - typedef uint64_t QsPosType; - -#if defined Linux || defined Solaris - static const QsPosType gQsMaxLength = 4294967296LL; - static const QsPosType gQsHalfMaxLength = 2147483648LL; -#else - static const QsPosType gQsMaxLength = 4294967296; - static const QsPosType gQsHalfMaxLength = 2147483648; -#endif - static const double gQsDMaxLength = 4294967296.0; - static const double gQsDHalfMaxLength = 2147483648.0; - static const double gQsLatLonDelta = M_PI_2 / gQsDMaxLength; - - /** A bounding rectangle of x/y extents */ - struct PosXPosYExtents - { - QsPosType minX; - QsPosType maxX; - QsPosType minY; - QsPosType maxY; - - PosXPosYExtents(QsPosType minX = gQsMaxLength, QsPosType maxX = 0, QsPosType minY = gQsMaxLength, QsPosType maxY = 0); - - /** Sets up invalid extents */ - void Initialize(); - - /** Confirms validity of extents */ - bool Valid() const; - - /** Sets the extents */ - void SetAll(const PosXPosYExtents& given); - void SetAll(const QsPosType& minX, const QsPosType& maxX, const QsPosType& minY, const QsPosType& maxY); - - /** Packs/unpacks the extents into or from a buffer */ - void Pack(uint8_t*) const; - void UnPack(const uint8_t*); - void UnPackHexChars(const char*); - - /** Prints the extents to the console */ - void Print(); - }; - - // --- SQLiteDataBaseReadUtil - - static const char* QS_TO_ID = "id"; - static const char* QS_DEFAULT_SET_TABLE_NAME = "default"; - static const char* SPLITTER_STRING_OUTPUTDB = "dbFile"; - static const char* SIMQS_CONFIG_TABLENAME_KEYWORD = "tableName"; - static const char* QS_LIST_OF_TEXTURE_SETS_TABLE_NAME = "ListOfTextureSets"; - static const char* QS_TSO_NAME_OF_TEXTURE_SET_TABLE = "nt"; - static const char* QS_TSO_OUTPUT_TYPE = "ot"; - static const char* QS_TSO_PIXEL_LENGTH = "pl"; - static const char* QS_TSO_SHALLOWEST_LEVEL = "sl"; - static const char* QS_TSO_DEEPEST_LEVEL = "dl"; - static const char* QS_TSO_EXTENTS = "ex"; - static const char* QS_TSO_SOURCE = "s"; - static const char* QS_TSO_CLASSIFICATION = "c"; - static const char* QS_TSO_DESCRIPTION = "ds"; - static const char* QS_TSO_TIME_SPECIFIED = "ts"; - - class SQLiteDataBaseReadUtil - { - public: - SQLiteDataBaseReadUtil(); - virtual ~SQLiteDataBaseReadUtil(); - - /** Opens a database file */ - QsErrorType OpenDataBaseFile(const std::string& dbFileName, - sqlite3** sqlite3Db, - const int& flags) const; - - /** - * Gets TextureSet information about a data table - * @param[in] sqlite3Db Pointer to a SQLite database object - * @param[in] tableName Name of the table to access within the given database - * The following are TextureSet creation options - * @param[out] rasterFormat Flag that determines how the texture image is drawn - * @param[out] pixelLength Tile size of the TextureSet - * @param[out] shallowLevel Minimum depth of the TextureSet - * @param[out] deepLevel Maximum depth of the TextureSet - * @param[out] tmpExtents Stores the TextureSet's X/Y extent values - * @param[out] source Name of the TextureSet's source file - * @param[out] classification Classification information of the loaded TextureSet - * @param[out] description Description of the loaded TextureSet - * @param[out] timeSpecified Whether or not a valid timeStamp was specified for the source file - * @param[out] timeStamp Loads a time value, if there is a valid timeStamp on the file - * @return Returns 0 on success, otherwise returns an error value mapped to QsErrorType. - */ - QsErrorType TsGetSetFromListOfSetsTable(sqlite3* sqlite3Db, - const std::string& tableName, - int& rasterFormat, - int& pixelLength, - int& shallowLevel, - int& deepLevel, - PosXPosYExtents tmpExtents[6], - std::string& source, - std::string& classification, - std::string& description, - bool& timeSpecified, - simCore::TimeStamp& timeStamp) const; - - /** - * Reads a node's data buffer from a sets table; caller is responsible for deleting buffer - * @param[in] sqlite3Db Pointer to a SQLite database object - * @param[in] dbFileName Name of a SQLite database file, used to fetch a database if sqlite3Db == NULL - * @param[in] dataTableName Name of the table to access within the given database - * @param[in] faceIndex Mapping to a face index/orientation, used to create a SQLite idBlob - * @param[in] nodeID Used to fill the idBlob - * @param[out] buffer Destination for data from the SQLite database - * @param[in, out] bufferSize Current max size of the buffer, will be changed if data to be copied is greater than max - * @param[out] currentRasterSize Size (bytes) of the data from the SQLite database - * @param[in] allowLocalDB Determines whether to fall back to a local database pointed to by dbFileName - * @param[in] displayErrorMessage Determines whether to display error messages to console when failing - * @return An error value, mapped to QsErrorType - */ - QsErrorType TsReadDataBuffer(sqlite3* sqlite3Db, - const std::string& dbFileName, - const std::string& dataTableName, - const FaceIndexType& faceIndex, - const QSNodeId& nodeID, - TextureDataType** buffer, - uint32_t* bufferSize, - uint32_t* currentRasterSize, - bool allowLocalDB, - bool displayErrorMessage = false) const; - protected: - int sizeOfIdBlob_; - - std::string textureSetSelectCommand_; - std::string textureSetSelectFileCommand1_; - std::string textureSetSelectFileCommand2_; - - // ids for inserting a "texture set" into a "list of texture sets" table - int tsInsertFileIdData_; - int tsInsertSetTextureSetName_; - int tsInsertSetIdRasterFormat_; - int tsInsertSetIdPixelLength_; - int tsInsertSetIdShallowestLevel_; - int tsInsertSetIdDeepestLevel_; - int tsInsertSetIdExtents_; - int tsInsertSetIdSource_; - int tsInsertSetIdClassification_; - int tsInsertSetIdDescription_; - int tsInsertSetIdTimeSpecified_; - int tsInsertSetIdTimeValue_; - }; -} } -#endif - -#if 0 -//........................................................... - -void DB::Options::readFrom(const osgEarth::Config& conf) -{ -} - -void DB::Options::writeTo(osgEarth::Config& conf) const -{ -} -//........................................................... - -osgEarth::Status DB::Driver::open( - const osgEarth::URI& uri, - osg::ref_ptr& profile, - osgEarth::DataExtentList& dataExtents, - const osgDB::Options* readOptions) -{ - pathname_ = osgDB::findDataFile(uri, readOptions); - - if (DB::OpenDataBaseFile(pathname_, &db_, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) != QS_IS_OK) - { - db_ = NULL; - return Status::Error(Stringify() << "Failed to open DB file at " << options_.url()->full()); - } - else - { - QsErrorType err = DBUtil::TsGetSetFromListOfSetsTable( - db_, - "default", - rasterFormat_, - pixelLength_, - shallowLevel_, - deepLevel_, - extents_, - source_, - classification_, - description_, - timeSpecified_, - timeStamp_); - - // Limit the deepLevel_ by the passed-in option - if (options_.deepestLevel().isSet()) - { - deepLevel_ = simCore::sdkMin(deepLevel_, static_cast(options_.deepestLevel().get())); - } - - if (err != QS_IS_OK) - { - sqlite3_close(db_); - db_ = NULL; - return Status::Error(Stringify() << "Failed to read metadata for " << pathname_); - } - - // Set up as a unified cube: - profile = new osgEarth::UnifiedCubeProfile(); - - // Lat/long extents (for debugging) - GeoExtent llex[6]; - - // Tell the engine how deep the data actually goes: - for (unsigned int f = 0; f < 6; ++f) - { - if (extents_[f].minX < extents_[f].maxX && extents_[f].minY < extents_[f].maxY) - { - const double x0 = extents_[f].minX / gQsDMaxLength; - const double x1 = extents_[f].maxX / gQsDMaxLength; - const double y0 = extents_[f].minY / gQsDMaxLength; - const double y1 = extents_[f].maxY / gQsDMaxLength; - - GeoExtent cubeEx(profile->getSRS(), f + x0, y0, f + x1, y1); - - // Transform to lat/long for the debugging msgs - cubeEx.transform(profile->getSRS()->getGeodeticSRS(), llex[f]); - - dataExtents.push_back(DataExtent(cubeEx, shallowLevel_, deepLevel_)); - } - } - - // Set time value of image if a time was found in the db - if (timeStamp_ != simCore::INFINITE_TIME_STAMP) - { - DateTime osgTime(timeStamp_.secondsSinceRefYear(1970)); - // Set time as a user value since config is not editable from here - setUserValue("time", osgTime.asISO8601()); - } - - OE_INFO << LC - << "Table: " << uri.full() << std::endl - << " Raster format = " << rasterFormat_ << std::endl - << " Tile size = " << pixelLength_ << std::endl - << " Shallow level = " << shallowLevel_ << std::endl - << " Deep level = " << deepLevel_ << std::endl - << " QS Extents = " << std::endl - << " 0: " << extents_[0].minX << "," << extents_[0].minY << "," << extents_[0].maxX << "," << extents_[0].maxY << "(" << (llex[0].isValid() ? llex[0].toString() : "empty") << ")\n" - << " 1: " << extents_[1].minX << "," << extents_[1].minY << "," << extents_[1].maxX << "," << extents_[1].maxY << "(" << (llex[1].isValid() ? llex[1].toString() : "empty") << ")\n" - << " 2: " << extents_[2].minX << "," << extents_[2].minY << "," << extents_[2].maxX << "," << extents_[2].maxY << "(" << (llex[2].isValid() ? llex[2].toString() : "empty") << ")\n" - << " 3: " << extents_[3].minX << "," << extents_[3].minY << "," << extents_[3].maxX << "," << extents_[3].maxY << "(" << (llex[3].isValid() ? llex[3].toString() : "empty") << ")\n" - << " 4: " << extents_[4].minX << "," << extents_[4].minY << "," << extents_[4].maxX << "," << extents_[4].maxY << "(" << (llex[4].isValid() ? llex[4].toString() : "empty") << ")\n" - << " 5: " << extents_[5].minX << "," << extents_[5].minY << "," << extents_[5].maxX << "," << extents_[5].maxY << "(" << (llex[5].isValid() ? llex[5].toString() : "empty") << ")\n"; - - // Line up the native format readers: - pngReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/png"); - jpgReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/jpeg"); - tifReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/tiff"); - rgbReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/x-rgb"); - } - return STATUS_OK; -} - -osgEarth::ReadResult DB::Driver::read( - const osgEarth::TileKey& key, - osgEarth::ProgressCallback* progress, - const osgDB::Options* readOptions) const -{ - //todo -} -#endif - -//........................................................... - osgEarth::Config DBImageLayer::Options::getConfig() const { - osgEarth::Config conf = osgEarth::ImageLayer::Options::getConfig(); + osgEarth::Config conf = osgEarth::Contrib::TileSourceImageLayer::Options::getConfig(); conf.merge(driver()->getConfig()); return conf; } @@ -337,44 +38,41 @@ void DBImageLayer::Options::fromConfig(const osgEarth::Config& conf) void DBImageLayer::setURL(const osgEarth::URI& value) { - options().driver()->url() = value; + localCopyOfOptions_.url() = value; + options().driver() = localCopyOfOptions_; } const osgEarth::URI& DBImageLayer::getURL() const { - return options().driver()->url().get(); + return localCopyOfOptions_.url().get(); } void DBImageLayer::setDeepestLevel(const unsigned int& value) { - options().driver()->deepestLevel() = value; + localCopyOfOptions_.deepestLevel() = value; + options().driver() = localCopyOfOptions_; } const unsigned int& DBImageLayer::getDeepestLevel() const { - return options().driver()->deepestLevel().get(); -} - -osgEarth::TileSource* DBImageLayer::createTileSource() -{ - return osgEarth::TileSourceFactory::create(options().driver().get()); + return localCopyOfOptions_.deepestLevel().get(); } void DBImageLayer::init() { - osgEarth::ImageLayer::init(); - setTileSourceExpected(true); + osgEarth::Contrib::TileSourceImageLayer::init(); + localCopyOfOptions_ = simVis::DBOptions(options().driver().get()); } osgEarth::Status DBImageLayer::openImplementation() { - return osgEarth::ImageLayer::openImplementation(); + return osgEarth::Contrib::TileSourceImageLayer::openImplementation(); } osgEarth::GeoImage DBImageLayer::createImageImplementation(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress) const { //todo - return osgEarth::ImageLayer::createImageImplementation(key, progress); + return osgEarth::Contrib::TileSourceImageLayer::createImageImplementation(key, progress); } //........................................................... @@ -393,33 +91,30 @@ void DBElevationLayer::Options::fromConfig(const osgEarth::Config& conf) void DBElevationLayer::setURL(const osgEarth::URI& value) { - options().driver()->url() = value; + localCopyOfOptions_.url() = value; + options().driver() = localCopyOfOptions_; } const osgEarth::URI& DBElevationLayer::getURL() const { - return options().driver()->url().get(); + return localCopyOfOptions_.url().get(); } void DBElevationLayer::setDeepestLevel(const unsigned int& value) { - options().driver()->deepestLevel() = value; + localCopyOfOptions_.deepestLevel() = value; + options().driver() = localCopyOfOptions_; } const unsigned int& DBElevationLayer::getDeepestLevel() const { - return options().driver()->deepestLevel().get(); -} - -osgEarth::TileSource* DBElevationLayer::createTileSource() -{ - return osgEarth::TileSourceFactory::create(options().driver().get()); + return localCopyOfOptions_.deepestLevel().get(); } void DBElevationLayer::init() { - osgEarth::ElevationLayer::init(); - setTileSourceExpected(true); + osgEarth::Contrib::ElevationLayer::init(); + localCopyOfOptions_ = simVis::DBOptions(options().driver().get()); } osgEarth::Status DBElevationLayer::openImplementation() diff --git a/SDK/simVis/DBFormat.h b/SDK/simVis/DBFormat.h index a35b85019..646498d23 100644 --- a/SDK/simVis/DBFormat.h +++ b/SDK/simVis/DBFormat.h @@ -23,8 +23,8 @@ #define SIMVIS_DBFORMAT_H #include -#include "osgEarth/ImageLayer" -#include "osgEarth/ElevationLayer" +#include "osgEarth/TileSourceImageLayer" +#include "osgEarth/TileSourceElevationLayer" #include "osgEarth/URI" #include "simCore/Common/Common.h" #include "simCore/Common/Export.h" @@ -37,20 +37,19 @@ namespace simVis // OE_OPTION uses unqualified optional<> type using osgEarth::optional; -class SDKVIS_EXPORT DBImageLayer : public osgEarth::ImageLayer +class SDKVIS_EXPORT DBImageLayer : public osgEarth::Contrib::TileSourceImageLayer { public: // serialization - class SDKVIS_EXPORT Options : public osgEarth::ImageLayer::Options { + class SDKVIS_EXPORT Options : public osgEarth::Contrib::TileSourceImageLayer::Options { public: - META_LayerOptions(simVis, Options, osgEarth::ImageLayer::Options); - OE_OPTION(simVis::DBOptions, driver); + META_LayerOptions(simVis, Options, osgEarth::Contrib::TileSourceImageLayer::Options); virtual osgEarth::Config getConfig() const; private: void fromConfig(const osgEarth::Config&); }; public: - META_Layer(simVis, DBImageLayer, Options, osgEarth::ImageLayer, DBImage); + META_Layer(simVis, DBImageLayer, Options, osgEarth::Contrib::TileSourceImageLayer, DBImage); public: /// Base URL of TileCache endpoint @@ -74,30 +73,28 @@ class SDKVIS_EXPORT DBImageLayer : public osgEarth::ImageLayer /// Called by constructors virtual void init(); - /// Create and return the underlying TileSource - virtual osgEarth::TileSource* createTileSource(); - /// Destructor virtual ~DBImageLayer() { } + + simVis::DBOptions localCopyOfOptions_; }; /** * Elevation layer connected to a DB file */ -class SDKVIS_EXPORT DBElevationLayer : public osgEarth::ElevationLayer +class SDKVIS_EXPORT DBElevationLayer : public osgEarth::Contrib::TileSourceElevationLayer { public: // serialization - class SDKVIS_EXPORT Options : public osgEarth::ElevationLayer::Options { + class SDKVIS_EXPORT Options : public osgEarth::Contrib::TileSourceElevationLayer::Options { public: - META_LayerOptions(simVis, Options, osgEarth::ElevationLayer::Options); - OE_OPTION(simVis::DBOptions, driver); + META_LayerOptions(simVis, Options, osgEarth::Contrib::TileSourceElevationLayer::Options); virtual osgEarth::Config getConfig() const; private: void fromConfig(const osgEarth::Config&); }; public: - META_Layer(simVis, DBElevationLayer, Options, osgEarth::ElevationLayer, DBElevation); + META_Layer(simVis, DBElevationLayer, Options, osgEarth::Contrib::TileSourceElevationLayer, DBElevation); /// URL of the database file void setURL(const osgEarth::URI& value); @@ -117,14 +114,13 @@ class SDKVIS_EXPORT DBElevationLayer : public osgEarth::ElevationLayer protected: // Layer - /// Called by constructors + /// Called by constructors virtual void init(); - /// Create and return the underlying TileSource - virtual osgEarth::TileSource* createTileSource(); - /// Destructor virtual ~DBElevationLayer() { } + + simVis::DBOptions localCopyOfOptions_; }; } diff --git a/SDK/simVis/DBOptions.h b/SDK/simVis/DBOptions.h index d7d8279ee..4f47c02f7 100644 --- a/SDK/simVis/DBOptions.h +++ b/SDK/simVis/DBOptions.h @@ -33,7 +33,7 @@ namespace simVis /** * Configuration options for the "DB" tile source driver. */ -class DBOptions : public osgEarth::TileSourceOptions // header-only (no export) +class DBOptions : public osgEarth::Contrib::TileSourceOptions // header-only (no export) { public: /** Location of the DB file to load (mutable) */ @@ -65,7 +65,7 @@ class DBOptions : public osgEarth::TileSourceOptions // header-only (no export) // (override from osgEarth::TileSourceOptions) virtual osgEarth::Config getConfig() const { - osgEarth::Config conf = osgEarth::TileSourceOptions::getConfig(); + osgEarth::Config conf = osgEarth::Contrib::TileSourceOptions::getConfig(); conf.set("url", _url); conf.set("deepest_level", _deepestLevel); return conf; @@ -76,7 +76,7 @@ class DBOptions : public osgEarth::TileSourceOptions // header-only (no export) // (override from osgEarth::TileSourceOptions) virtual void mergeConfig(const osgEarth::Config& conf) { - osgEarth::TileSourceOptions::mergeConfig(conf); + osgEarth::Contrib::TileSourceOptions::mergeConfig(conf); fromConfig_(conf); } diff --git a/SDK/simVis/LayerRefreshCallback.cpp b/SDK/simVis/LayerRefreshCallback.cpp index c9e097e7c..736d232ed 100644 --- a/SDK/simVis/LayerRefreshCallback.cpp +++ b/SDK/simVis/LayerRefreshCallback.cpp @@ -42,7 +42,7 @@ class LayerRefreshCallback::MapUpdatedCallback : public osgEarth::MapCallback /** Watch a TerrainLayer when it's added */ virtual void onLayerAdded(osgEarth::Layer* layer, unsigned index) { - const osgEarth::TerrainLayer* terrainLayer = dynamic_cast(layer); + const osgEarth::TileLayer* terrainLayer = dynamic_cast(layer); if (terrainLayer != NULL) parent_.watchLayer_(terrainLayer); } @@ -50,7 +50,7 @@ class LayerRefreshCallback::MapUpdatedCallback : public osgEarth::MapCallback /** Forget a TerrainLayer when it's removed */ virtual void onLayerRemoved(osgEarth::Layer* layer, unsigned index) { - const osgEarth::TerrainLayer* terrainLayer = dynamic_cast(layer); + const osgEarth::TileLayer* terrainLayer = dynamic_cast(layer); if (terrainLayer != NULL) parent_.forgetLayer_(terrainLayer); } @@ -58,7 +58,7 @@ class LayerRefreshCallback::MapUpdatedCallback : public osgEarth::MapCallback /** Watch a TerrainLayer when it's enabled */ virtual void onLayerEnabled(osgEarth::Layer* layer) { - const osgEarth::TerrainLayer* terrainLayer = dynamic_cast(layer); + const osgEarth::TileLayer* terrainLayer = dynamic_cast(layer); if (terrainLayer != NULL) parent_.watchLayer_(terrainLayer); } @@ -66,7 +66,7 @@ class LayerRefreshCallback::MapUpdatedCallback : public osgEarth::MapCallback /** Forget a TerrainLayer when it's disabled */ virtual void onLayerDisabled(osgEarth::Layer* layer) { - const osgEarth::TerrainLayer* terrainLayer = dynamic_cast(layer); + const osgEarth::TileLayer* terrainLayer = dynamic_cast(layer); if (terrainLayer != NULL) parent_.forgetLayer_(terrainLayer); } @@ -136,7 +136,7 @@ void LayerRefreshCallback::runImpl_() // Loop through all watched layers for (auto it = watchedLayers_.begin(); it != watchedLayers_.end(); ++it) { - osg::observer_ptr layer = (*it).layer; + osg::observer_ptr layer = (*it).layer; if (!layer.valid() || !layer->getEnabled()) { assert(0); // Should not be watching a NULL or disabled layer @@ -167,7 +167,7 @@ void LayerRefreshCallback::runImpl_() // NOTE: A call to terrainEngine->dirtyTerrain() is NOT required here } -void LayerRefreshCallback::watchLayer_(const osgEarth::TerrainLayer* layer) +void LayerRefreshCallback::watchLayer_(const osgEarth::TileLayer* layer) { if (layer == NULL) return; @@ -178,7 +178,7 @@ void LayerRefreshCallback::watchLayer_(const osgEarth::TerrainLayer* layer) watchedLayers_.push_back(info); } -void LayerRefreshCallback::forgetLayer_(const osgEarth::TerrainLayer* layer) +void LayerRefreshCallback::forgetLayer_(const osgEarth::TileLayer* layer) { if (layer == NULL) return; diff --git a/SDK/simVis/LayerRefreshCallback.h b/SDK/simVis/LayerRefreshCallback.h index dcb3bde71..a27bd0c0e 100644 --- a/SDK/simVis/LayerRefreshCallback.h +++ b/SDK/simVis/LayerRefreshCallback.h @@ -69,7 +69,7 @@ class LayerRefreshCallback : public osg::Callback /** Groups a TerrainLayer pointer and the elapsed time since last its refresh */ struct LayerInfo { - osg::observer_ptr layer; + osg::observer_ptr layer; osg::ElapsedTime elapsedTime; }; @@ -77,9 +77,9 @@ class LayerRefreshCallback : public osg::Callback void runImpl_(); /** Watch the given layer and refresh it when required a refresh is due */ - void watchLayer_(const osgEarth::TerrainLayer* layer); + void watchLayer_(const osgEarth::TileLayer* layer); /** Stop watching the given layer */ - void forgetLayer_(const osgEarth::TerrainLayer* layer); + void forgetLayer_(const osgEarth::TileLayer* layer); /** Get the interval for the given layer in seconds */ double getIntervalForLayer_(const osgEarth::Layer* layer) const; diff --git a/SDK/simVis/ModelCache.cpp b/SDK/simVis/ModelCache.cpp index 18c91efcd..282f70ac0 100644 --- a/SDK/simVis/ModelCache.cpp +++ b/SDK/simVis/ModelCache.cpp @@ -32,6 +32,7 @@ #include "osg/TexEnv" #include "osg/TexEnvCombine" #include "osg/ValueObject" +#include "osgDB/ReadFile" #include "osgSim/DOFTransform" #include "osgSim/LightPointNode" #include "osgSim/MultiSwitch" diff --git a/SDK/simVis/SceneManager.cpp b/SDK/simVis/SceneManager.cpp index c6a9c1c08..4effc5c4c 100644 --- a/SDK/simVis/SceneManager.cpp +++ b/SDK/simVis/SceneManager.cpp @@ -462,9 +462,9 @@ void SceneManager::applyImageLayerDisplaySettings_(const osgEarth::ImageLayer& s destLayer->setEnabled(sourceLayer.getEnabled()); } -std::string SceneManager::getLayerHash_(osgEarth::TerrainLayer* layer) const +std::string SceneManager::getLayerHash_(osgEarth::TileLayer* layer) const { - // This method mimics the logic in osgEarth::TerrainLayer::setCache for generating a unique id for the layer + // This method mimics the logic in osgEarth::TileLayer::setCache for generating a unique id for the layer // system will generate a cacheId. technically, this is not quite right, we need to remove everything that's // an image layer property and just use the tilesource properties. diff --git a/SDK/simVis/SceneManager.h b/SDK/simVis/SceneManager.h index 45f2b3ffe..dd5e1f112 100644 --- a/SDK/simVis/SceneManager.h +++ b/SDK/simVis/SceneManager.h @@ -195,8 +195,8 @@ namespace simVis void init_(); /** Detects engine driver problems and sets internal state appropriately */ void detectTerrainEngineDriverProblems_(); - /** Returns the unique hash identifying the layer. Taken from osgEarth::TerrainLayer::setCache method */ - std::string getLayerHash_(osgEarth::TerrainLayer* layer) const; + /** Returns the unique hash identifying the layer. Taken from osgEarth::TileLayer::setCache method */ + std::string getLayerHash_(osgEarth::TileLayer* layer) const; /** Replace image layers in currentMap with image layers in newMap, unless the layer already exists in currentMap. Removes old layers not in newMap */ void updateImageLayers_(const osgEarth::Map& newMap, osgEarth::Map* currentMap); /** Replace elevation layers in currentMap with image layers in newMap, unless the layer already exists in currentMap. Removes old layers not in newMap */ From edbe9dd28fb106fac61ce46f64c909f733071cf5 Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Tue, 14 Jan 2020 15:36:25 -0500 Subject: [PATCH 023/121] DEV: SDK: First tick at first platform point orientation looks nicer, SIM-10914, review 20403 --- SDK/simVis/TimeTicks.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index f836db971..5a7b991ab 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -189,10 +189,18 @@ void TimeTicks::addUpdate_(double tickTime) osg::Matrix hostMatrix; bool largeTick = false; - // if tick is at first platform point, get the platform position at that time + // if tick is at first platform point, use that for position if (!hasPrevious) { - if (!getMatrix_(*update, hostMatrix)) + // if only a single point, use it + const simData::PlatformUpdate* next = iter.next(); + if (!next) + { + if (!getMatrix_(*update, hostMatrix)) + return; + } + // use the next point to calculate the correct orientation for the first tick + else if (!getMatrix_(*next, *update, tickTime, hostMatrix)) return; } // not first tick, or not at first platform position, get the next position, possibly interpolated From 60c046a3b412ac71cc830590725b4bbca63324af Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Wed, 15 Jan 2020 10:50:45 -0500 Subject: [PATCH 024/121] DEV: SDK: TimeTicks reset first tick properly in live mode, SIM-10914, review 20415 --- SDK/simVis/TimeTicks.cpp | 26 ++++++++++++++++++++++---- SDK/simVis/TimeTicks.h | 2 ++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index 5a7b991ab..407180392 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -70,6 +70,7 @@ TimeTicks::TimeTicks(const simData::DataStore& ds, const osgEarth::SpatialRefere chunkSize_(64), // keep this lowish or your app won't scale. color_(osg::Vec4f(1.0, 1.0, 1.0, 0.5)), totalPoints_(0), + singlePoint_(false), hasLastDrawTime_(false), lastDrawTime_(0.0), lastCurrentTime_(-1.0), @@ -124,6 +125,7 @@ void TimeTicks::reset() currentPointChunk_ = NULL; lastLargeTickTime_ = -1.0; lastLabelTime_ = -1.0; + singlePoint_ = false; } TimeTicksChunk* TimeTicks::getCurrentChunk_() @@ -198,14 +200,26 @@ void TimeTicks::addUpdate_(double tickTime) { if (!getMatrix_(*update, hostMatrix)) return; + // if drawing line ticks, set singlePoint_ flag since orientation may not be correct and will need to update once next point comes in + // this may occur in live mode + if (lastPlatformPrefs_.trackprefs().timeticks().drawstyle() == simData::TimeTickPrefs::LINE) + singlePoint_ = true; } // use the next point to calculate the correct orientation for the first tick - else if (!getMatrix_(*next, *update, tickTime, hostMatrix)) - return; + else + { + if (!getMatrix_(*next, *update, tickTime, hostMatrix)) + return; + singlePoint_ = false; + } } // not first tick, or not at first platform position, get the next position, possibly interpolated - else if (!getMatrix_(*prev, *update, tickTime, hostMatrix)) - return; + else + { + singlePoint_ = false; + if (!getMatrix_(*prev, *update, tickTime, hostMatrix)) + return; + } // check to see if it is time for the next large tick if (largeTickInterval_ > 0 && (lastLargeTickTime_ == -1 || abs(tickTime - lastLargeTickTime_) >= largeTickInterval_)) @@ -528,6 +542,10 @@ void TimeTicks::updateTrackData_(double currentTime, const simData::PlatformUpda if (trackLength > 0 && (endTime - trackLength) > beginTime) beginTime = endTime - trackLength; + // first tick was built from a single point, so orientation may have been off, reset to ensure first tick is drawn with correct orientation + if (singlePoint_ && updateSlice.numItems() > 1) + reset(); + // if there is an existing time ticks, determine if we can add only new points; this should be the case for normal time movement if (hasLastDrawTime_) { diff --git a/SDK/simVis/TimeTicks.h b/SDK/simVis/TimeTicks.h index b06cdecf8..b9106c508 100644 --- a/SDK/simVis/TimeTicks.h +++ b/SDK/simVis/TimeTicks.h @@ -186,6 +186,8 @@ class SDKVIS_EXPORT TimeTicks : public osg::Group osg::Vec4f color_; unsigned int totalPoints_; + /// keep track of the single point state which may initiate a reset + bool singlePoint_; // "draw time" is the same as the clock's update time, but adjusted // for time direction. i.e. it will be negated in the case of simCore::REVERSE. bool hasLastDrawTime_; From f5b5468056f3b85c0f33a4761797c5f280f80219 Mon Sep 17 00:00:00 2001 From: gwaldron Date: Tue, 14 Jan 2020 12:30:49 -0500 Subject: [PATCH 025/121] From Glenn: Apply TileLayer/TileSource refactor --- Examples/BasicViewer/BasicViewer.cpp | 1 - Examples/BasicViewerText/BasicViewerText.cpp | 1 + Examples/Periscope/PeriscopeExample.cpp | 2 + .../PlatformSymbology/PlatformSymbology.cpp | 2 + Examples/RocketBurn/RocketBurn.cpp | 2 + .../ExampleTimestampedLayer.cpp | 1 + .../OSGEarthDBDriver/include/DBTileSource.h | 4 +- Plugins/OSGEarthDBDriver/src/DBTileSource.cpp | 4 +- Plugins/OSGEarthDBDriver/src/Plugin.cpp | 2 +- SDK/simVis/Compass.cpp | 1 + SDK/simVis/DBFormat.cpp | 343 +----------------- SDK/simVis/DBFormat.h | 34 +- SDK/simVis/DBOptions.h | 6 +- SDK/simVis/LayerRefreshCallback.cpp | 14 +- SDK/simVis/LayerRefreshCallback.h | 6 +- SDK/simVis/SceneManager.cpp | 4 +- SDK/simVis/SceneManager.h | 4 +- 17 files changed, 65 insertions(+), 366 deletions(-) diff --git a/Examples/BasicViewer/BasicViewer.cpp b/Examples/BasicViewer/BasicViewer.cpp index a58d53f34..1b0b316f1 100644 --- a/Examples/BasicViewer/BasicViewer.cpp +++ b/Examples/BasicViewer/BasicViewer.cpp @@ -25,7 +25,6 @@ * map control. It shows how to adjust window appearance, how to add or remove * inset views, and how to change the motion model. */ - #include "simNotify/Notify.h" #include "simCore/Common/Version.h" #include "simCore/Common/HighPerformanceGraphics.h" diff --git a/Examples/BasicViewerText/BasicViewerText.cpp b/Examples/BasicViewerText/BasicViewerText.cpp index 3c635b451..f7cf2d984 100644 --- a/Examples/BasicViewerText/BasicViewerText.cpp +++ b/Examples/BasicViewerText/BasicViewerText.cpp @@ -39,6 +39,7 @@ #include "simUtil/HudManager.h" #include "simUtil/Replaceables.h" #include "simUtil/StatusText.h" +#include "osgDB/ReadFile" #define LC "[BasicViewerText demo] " diff --git a/Examples/Periscope/PeriscopeExample.cpp b/Examples/Periscope/PeriscopeExample.cpp index f301cef07..0a2248f52 100644 --- a/Examples/Periscope/PeriscopeExample.cpp +++ b/Examples/Periscope/PeriscopeExample.cpp @@ -47,6 +47,8 @@ #include "osgEarth/SimpleOceanLayer" #include "osgEarth/Version" +#include "osgDB/ReadFile" + #ifdef HAVE_TRITON_NODEKIT #include "osgEarthTriton/TritonLayer" #endif diff --git a/Examples/PlatformSymbology/PlatformSymbology.cpp b/Examples/PlatformSymbology/PlatformSymbology.cpp index 77a99ac10..1cf1aa20a 100644 --- a/Examples/PlatformSymbology/PlatformSymbology.cpp +++ b/Examples/PlatformSymbology/PlatformSymbology.cpp @@ -65,6 +65,8 @@ #include "osgEarth/StringUtils" #include "osgEarth/Style" +#include "osgDB/ReadFile" + #include "google/protobuf/stubs/common.h" using namespace osgEarth; diff --git a/Examples/RocketBurn/RocketBurn.cpp b/Examples/RocketBurn/RocketBurn.cpp index 0df9ef242..e32041074 100644 --- a/Examples/RocketBurn/RocketBurn.cpp +++ b/Examples/RocketBurn/RocketBurn.cpp @@ -35,6 +35,8 @@ #include "simUtil/ExampleResources.h" #include "simUtil/PlatformSimulator.h" +#include "osgDB/ReadFile" + namespace { /// get time and platform removal notifications diff --git a/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp b/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp index 287973474..af3168628 100644 --- a/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp +++ b/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp @@ -31,6 +31,7 @@ #include "simVis/SceneManager.h" #include "simVis/Viewer.h" #include "simUtil/ExampleResources.h" +#include "osgDB/ReadFile" namespace ui = osgEarth::Util::Controls; diff --git a/Plugins/OSGEarthDBDriver/include/DBTileSource.h b/Plugins/OSGEarthDBDriver/include/DBTileSource.h index d8230b54d..f2dfc4c5a 100644 --- a/Plugins/OSGEarthDBDriver/include/DBTileSource.h +++ b/Plugins/OSGEarthDBDriver/include/DBTileSource.h @@ -32,11 +32,11 @@ namespace simVis_db { - class DBTileSource : public osgEarth::TileSource + class DBTileSource : public osgEarth::Contrib::TileSource { public: /** Constructs a new driver for reading .DB raster files */ - DBTileSource(const osgEarth::TileSourceOptions& options); + DBTileSource(const osgEarth::Contrib::TileSourceOptions& options); /// TileSource interface virtual osgEarth::Status initialize(const osgDB::Options* dbOptions); diff --git a/Plugins/OSGEarthDBDriver/src/DBTileSource.cpp b/Plugins/OSGEarthDBDriver/src/DBTileSource.cpp index 7766d3059..93e67f921 100644 --- a/Plugins/OSGEarthDBDriver/src/DBTileSource.cpp +++ b/Plugins/OSGEarthDBDriver/src/DBTileSource.cpp @@ -120,8 +120,8 @@ namespace // -------------------------------------------------------------------------- -DBTileSource::DBTileSource(const osgEarth::TileSourceOptions& options) - : osgEarth::TileSource(options), +DBTileSource::DBTileSource(const osgEarth::Contrib::TileSourceOptions& options) + : osgEarth::Contrib::TileSource(options), options_(options), db_(NULL), rasterFormat_(SPLIT_UNKNOWN), diff --git a/Plugins/OSGEarthDBDriver/src/Plugin.cpp b/Plugins/OSGEarthDBDriver/src/Plugin.cpp index b97c685b0..43635c2b5 100644 --- a/Plugins/OSGEarthDBDriver/src/Plugin.cpp +++ b/Plugins/OSGEarthDBDriver/src/Plugin.cpp @@ -25,7 +25,7 @@ #include #include "DBTileSource.h" -class SimSdkOSGEarthDBDriverPlugin : public osgEarth::TileSourceDriver +class SimSdkOSGEarthDBDriverPlugin : public osgEarth::Contrib::TileSourceDriver { public: SimSdkOSGEarthDBDriverPlugin() { } diff --git a/SDK/simVis/Compass.cpp b/SDK/simVis/Compass.cpp index dc140a09f..59f2e4723 100644 --- a/SDK/simVis/Compass.cpp +++ b/SDK/simVis/Compass.cpp @@ -29,6 +29,7 @@ #include "simVis/Utils.h" #include "simVis/View.h" #include "simVis/Compass.h" +#include "osgDB/ReadFile" namespace simVis { diff --git a/SDK/simVis/DBFormat.cpp b/SDK/simVis/DBFormat.cpp index 0f6398436..04c2fd7e5 100644 --- a/SDK/simVis/DBFormat.cpp +++ b/SDK/simVis/DBFormat.cpp @@ -24,308 +24,9 @@ using namespace simVis; -//........................................................... -#if 0 -#include "simCore/Common/Common.h" -#include "simCore/Calc/MathConstants.h" - -namespace simVis { namespace DB -{ - typedef int16_t LevelInt; - static const LevelInt QT_MIN_LEVEL = 0; - static const LevelInt QT_MAX_LEVEL = 32; - - typedef uint8_t ChildIndexInt; - static const ChildIndexInt QT_CHILD_NE = 0; - static const ChildIndexInt QT_CHILD_NW = 1; - static const ChildIndexInt QT_CHILD_SW = 2; - static const ChildIndexInt QT_CHILD_SE = 3; - - typedef uint8_t FaceIndexType; - static const FaceIndexType QsFaceIndexWW = 0; - static const FaceIndexType QsFaceIndexW = 1; - static const FaceIndexType QsFaceIndexE = 2; - static const FaceIndexType QsFaceIndexEE = 3; - static const FaceIndexType QsFaceIndexN = 4; - static const FaceIndexType QsFaceIndexS = 5; - - typedef float AltitudeDataType; - - static const int16_t MAX_NUM_READ_THREADS = 128; - - typedef uint64_t QsPosType; - -#if defined Linux || defined Solaris - static const QsPosType gQsMaxLength = 4294967296LL; - static const QsPosType gQsHalfMaxLength = 2147483648LL; -#else - static const QsPosType gQsMaxLength = 4294967296; - static const QsPosType gQsHalfMaxLength = 2147483648; -#endif - static const double gQsDMaxLength = 4294967296.0; - static const double gQsDHalfMaxLength = 2147483648.0; - static const double gQsLatLonDelta = M_PI_2 / gQsDMaxLength; - - /** A bounding rectangle of x/y extents */ - struct PosXPosYExtents - { - QsPosType minX; - QsPosType maxX; - QsPosType minY; - QsPosType maxY; - - PosXPosYExtents(QsPosType minX = gQsMaxLength, QsPosType maxX = 0, QsPosType minY = gQsMaxLength, QsPosType maxY = 0); - - /** Sets up invalid extents */ - void Initialize(); - - /** Confirms validity of extents */ - bool Valid() const; - - /** Sets the extents */ - void SetAll(const PosXPosYExtents& given); - void SetAll(const QsPosType& minX, const QsPosType& maxX, const QsPosType& minY, const QsPosType& maxY); - - /** Packs/unpacks the extents into or from a buffer */ - void Pack(uint8_t*) const; - void UnPack(const uint8_t*); - void UnPackHexChars(const char*); - - /** Prints the extents to the console */ - void Print(); - }; - - // --- SQLiteDataBaseReadUtil - - static const char* QS_TO_ID = "id"; - static const char* QS_DEFAULT_SET_TABLE_NAME = "default"; - static const char* SPLITTER_STRING_OUTPUTDB = "dbFile"; - static const char* SIMQS_CONFIG_TABLENAME_KEYWORD = "tableName"; - static const char* QS_LIST_OF_TEXTURE_SETS_TABLE_NAME = "ListOfTextureSets"; - static const char* QS_TSO_NAME_OF_TEXTURE_SET_TABLE = "nt"; - static const char* QS_TSO_OUTPUT_TYPE = "ot"; - static const char* QS_TSO_PIXEL_LENGTH = "pl"; - static const char* QS_TSO_SHALLOWEST_LEVEL = "sl"; - static const char* QS_TSO_DEEPEST_LEVEL = "dl"; - static const char* QS_TSO_EXTENTS = "ex"; - static const char* QS_TSO_SOURCE = "s"; - static const char* QS_TSO_CLASSIFICATION = "c"; - static const char* QS_TSO_DESCRIPTION = "ds"; - static const char* QS_TSO_TIME_SPECIFIED = "ts"; - - class SQLiteDataBaseReadUtil - { - public: - SQLiteDataBaseReadUtil(); - virtual ~SQLiteDataBaseReadUtil(); - - /** Opens a database file */ - QsErrorType OpenDataBaseFile(const std::string& dbFileName, - sqlite3** sqlite3Db, - const int& flags) const; - - /** - * Gets TextureSet information about a data table - * @param[in] sqlite3Db Pointer to a SQLite database object - * @param[in] tableName Name of the table to access within the given database - * The following are TextureSet creation options - * @param[out] rasterFormat Flag that determines how the texture image is drawn - * @param[out] pixelLength Tile size of the TextureSet - * @param[out] shallowLevel Minimum depth of the TextureSet - * @param[out] deepLevel Maximum depth of the TextureSet - * @param[out] tmpExtents Stores the TextureSet's X/Y extent values - * @param[out] source Name of the TextureSet's source file - * @param[out] classification Classification information of the loaded TextureSet - * @param[out] description Description of the loaded TextureSet - * @param[out] timeSpecified Whether or not a valid timeStamp was specified for the source file - * @param[out] timeStamp Loads a time value, if there is a valid timeStamp on the file - * @return Returns 0 on success, otherwise returns an error value mapped to QsErrorType. - */ - QsErrorType TsGetSetFromListOfSetsTable(sqlite3* sqlite3Db, - const std::string& tableName, - int& rasterFormat, - int& pixelLength, - int& shallowLevel, - int& deepLevel, - PosXPosYExtents tmpExtents[6], - std::string& source, - std::string& classification, - std::string& description, - bool& timeSpecified, - simCore::TimeStamp& timeStamp) const; - - /** - * Reads a node's data buffer from a sets table; caller is responsible for deleting buffer - * @param[in] sqlite3Db Pointer to a SQLite database object - * @param[in] dbFileName Name of a SQLite database file, used to fetch a database if sqlite3Db == NULL - * @param[in] dataTableName Name of the table to access within the given database - * @param[in] faceIndex Mapping to a face index/orientation, used to create a SQLite idBlob - * @param[in] nodeID Used to fill the idBlob - * @param[out] buffer Destination for data from the SQLite database - * @param[in, out] bufferSize Current max size of the buffer, will be changed if data to be copied is greater than max - * @param[out] currentRasterSize Size (bytes) of the data from the SQLite database - * @param[in] allowLocalDB Determines whether to fall back to a local database pointed to by dbFileName - * @param[in] displayErrorMessage Determines whether to display error messages to console when failing - * @return An error value, mapped to QsErrorType - */ - QsErrorType TsReadDataBuffer(sqlite3* sqlite3Db, - const std::string& dbFileName, - const std::string& dataTableName, - const FaceIndexType& faceIndex, - const QSNodeId& nodeID, - TextureDataType** buffer, - uint32_t* bufferSize, - uint32_t* currentRasterSize, - bool allowLocalDB, - bool displayErrorMessage = false) const; - protected: - int sizeOfIdBlob_; - - std::string textureSetSelectCommand_; - std::string textureSetSelectFileCommand1_; - std::string textureSetSelectFileCommand2_; - - // ids for inserting a "texture set" into a "list of texture sets" table - int tsInsertFileIdData_; - int tsInsertSetTextureSetName_; - int tsInsertSetIdRasterFormat_; - int tsInsertSetIdPixelLength_; - int tsInsertSetIdShallowestLevel_; - int tsInsertSetIdDeepestLevel_; - int tsInsertSetIdExtents_; - int tsInsertSetIdSource_; - int tsInsertSetIdClassification_; - int tsInsertSetIdDescription_; - int tsInsertSetIdTimeSpecified_; - int tsInsertSetIdTimeValue_; - }; -} } -#endif - -#if 0 -//........................................................... - -void DB::Options::readFrom(const osgEarth::Config& conf) -{ -} - -void DB::Options::writeTo(osgEarth::Config& conf) const -{ -} -//........................................................... - -osgEarth::Status DB::Driver::open( - const osgEarth::URI& uri, - osg::ref_ptr& profile, - osgEarth::DataExtentList& dataExtents, - const osgDB::Options* readOptions) -{ - pathname_ = osgDB::findDataFile(uri, readOptions); - - if (DB::OpenDataBaseFile(pathname_, &db_, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) != QS_IS_OK) - { - db_ = NULL; - return Status::Error(Stringify() << "Failed to open DB file at " << options_.url()->full()); - } - else - { - QsErrorType err = DBUtil::TsGetSetFromListOfSetsTable( - db_, - "default", - rasterFormat_, - pixelLength_, - shallowLevel_, - deepLevel_, - extents_, - source_, - classification_, - description_, - timeSpecified_, - timeStamp_); - - // Limit the deepLevel_ by the passed-in option - if (options_.deepestLevel().isSet()) - { - deepLevel_ = simCore::sdkMin(deepLevel_, static_cast(options_.deepestLevel().get())); - } - - if (err != QS_IS_OK) - { - sqlite3_close(db_); - db_ = NULL; - return Status::Error(Stringify() << "Failed to read metadata for " << pathname_); - } - - // Set up as a unified cube: - profile = new osgEarth::UnifiedCubeProfile(); - - // Lat/long extents (for debugging) - GeoExtent llex[6]; - - // Tell the engine how deep the data actually goes: - for (unsigned int f = 0; f < 6; ++f) - { - if (extents_[f].minX < extents_[f].maxX && extents_[f].minY < extents_[f].maxY) - { - const double x0 = extents_[f].minX / gQsDMaxLength; - const double x1 = extents_[f].maxX / gQsDMaxLength; - const double y0 = extents_[f].minY / gQsDMaxLength; - const double y1 = extents_[f].maxY / gQsDMaxLength; - - GeoExtent cubeEx(profile->getSRS(), f + x0, y0, f + x1, y1); - - // Transform to lat/long for the debugging msgs - cubeEx.transform(profile->getSRS()->getGeodeticSRS(), llex[f]); - - dataExtents.push_back(DataExtent(cubeEx, shallowLevel_, deepLevel_)); - } - } - - // Set time value of image if a time was found in the db - if (timeStamp_ != simCore::INFINITE_TIME_STAMP) - { - DateTime osgTime(timeStamp_.secondsSinceRefYear(1970)); - // Set time as a user value since config is not editable from here - setUserValue("time", osgTime.asISO8601()); - } - - OE_INFO << LC - << "Table: " << uri.full() << std::endl - << " Raster format = " << rasterFormat_ << std::endl - << " Tile size = " << pixelLength_ << std::endl - << " Shallow level = " << shallowLevel_ << std::endl - << " Deep level = " << deepLevel_ << std::endl - << " QS Extents = " << std::endl - << " 0: " << extents_[0].minX << "," << extents_[0].minY << "," << extents_[0].maxX << "," << extents_[0].maxY << "(" << (llex[0].isValid() ? llex[0].toString() : "empty") << ")\n" - << " 1: " << extents_[1].minX << "," << extents_[1].minY << "," << extents_[1].maxX << "," << extents_[1].maxY << "(" << (llex[1].isValid() ? llex[1].toString() : "empty") << ")\n" - << " 2: " << extents_[2].minX << "," << extents_[2].minY << "," << extents_[2].maxX << "," << extents_[2].maxY << "(" << (llex[2].isValid() ? llex[2].toString() : "empty") << ")\n" - << " 3: " << extents_[3].minX << "," << extents_[3].minY << "," << extents_[3].maxX << "," << extents_[3].maxY << "(" << (llex[3].isValid() ? llex[3].toString() : "empty") << ")\n" - << " 4: " << extents_[4].minX << "," << extents_[4].minY << "," << extents_[4].maxX << "," << extents_[4].maxY << "(" << (llex[4].isValid() ? llex[4].toString() : "empty") << ")\n" - << " 5: " << extents_[5].minX << "," << extents_[5].minY << "," << extents_[5].maxX << "," << extents_[5].maxY << "(" << (llex[5].isValid() ? llex[5].toString() : "empty") << ")\n"; - - // Line up the native format readers: - pngReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/png"); - jpgReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/jpeg"); - tifReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/tiff"); - rgbReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/x-rgb"); - } - return STATUS_OK; -} - -osgEarth::ReadResult DB::Driver::read( - const osgEarth::TileKey& key, - osgEarth::ProgressCallback* progress, - const osgDB::Options* readOptions) const -{ - //todo -} -#endif - -//........................................................... - osgEarth::Config DBImageLayer::Options::getConfig() const { - osgEarth::Config conf = osgEarth::ImageLayer::Options::getConfig(); + osgEarth::Config conf = osgEarth::Contrib::TileSourceImageLayer::Options::getConfig(); conf.merge(driver()->getConfig()); return conf; } @@ -337,44 +38,41 @@ void DBImageLayer::Options::fromConfig(const osgEarth::Config& conf) void DBImageLayer::setURL(const osgEarth::URI& value) { - options().driver()->url() = value; + localCopyOfOptions_.url() = value; + options().driver() = localCopyOfOptions_; } const osgEarth::URI& DBImageLayer::getURL() const { - return options().driver()->url().get(); + return localCopyOfOptions_.url().get(); } void DBImageLayer::setDeepestLevel(const unsigned int& value) { - options().driver()->deepestLevel() = value; + localCopyOfOptions_.deepestLevel() = value; + options().driver() = localCopyOfOptions_; } const unsigned int& DBImageLayer::getDeepestLevel() const { - return options().driver()->deepestLevel().get(); -} - -osgEarth::TileSource* DBImageLayer::createTileSource() -{ - return osgEarth::TileSourceFactory::create(options().driver().get()); + return localCopyOfOptions_.deepestLevel().get(); } void DBImageLayer::init() { - osgEarth::ImageLayer::init(); - setTileSourceExpected(true); + osgEarth::Contrib::TileSourceImageLayer::init(); + localCopyOfOptions_ = simVis::DBOptions(options().driver().get()); } osgEarth::Status DBImageLayer::openImplementation() { - return osgEarth::ImageLayer::openImplementation(); + return osgEarth::Contrib::TileSourceImageLayer::openImplementation(); } osgEarth::GeoImage DBImageLayer::createImageImplementation(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress) const { //todo - return osgEarth::ImageLayer::createImageImplementation(key, progress); + return osgEarth::Contrib::TileSourceImageLayer::createImageImplementation(key, progress); } //........................................................... @@ -393,33 +91,30 @@ void DBElevationLayer::Options::fromConfig(const osgEarth::Config& conf) void DBElevationLayer::setURL(const osgEarth::URI& value) { - options().driver()->url() = value; + localCopyOfOptions_.url() = value; + options().driver() = localCopyOfOptions_; } const osgEarth::URI& DBElevationLayer::getURL() const { - return options().driver()->url().get(); + return localCopyOfOptions_.url().get(); } void DBElevationLayer::setDeepestLevel(const unsigned int& value) { - options().driver()->deepestLevel() = value; + localCopyOfOptions_.deepestLevel() = value; + options().driver() = localCopyOfOptions_; } const unsigned int& DBElevationLayer::getDeepestLevel() const { - return options().driver()->deepestLevel().get(); -} - -osgEarth::TileSource* DBElevationLayer::createTileSource() -{ - return osgEarth::TileSourceFactory::create(options().driver().get()); + return localCopyOfOptions_.deepestLevel().get(); } void DBElevationLayer::init() { - osgEarth::ElevationLayer::init(); - setTileSourceExpected(true); + osgEarth::Contrib::ElevationLayer::init(); + localCopyOfOptions_ = simVis::DBOptions(options().driver().get()); } osgEarth::Status DBElevationLayer::openImplementation() diff --git a/SDK/simVis/DBFormat.h b/SDK/simVis/DBFormat.h index a35b85019..646498d23 100644 --- a/SDK/simVis/DBFormat.h +++ b/SDK/simVis/DBFormat.h @@ -23,8 +23,8 @@ #define SIMVIS_DBFORMAT_H #include -#include "osgEarth/ImageLayer" -#include "osgEarth/ElevationLayer" +#include "osgEarth/TileSourceImageLayer" +#include "osgEarth/TileSourceElevationLayer" #include "osgEarth/URI" #include "simCore/Common/Common.h" #include "simCore/Common/Export.h" @@ -37,20 +37,19 @@ namespace simVis // OE_OPTION uses unqualified optional<> type using osgEarth::optional; -class SDKVIS_EXPORT DBImageLayer : public osgEarth::ImageLayer +class SDKVIS_EXPORT DBImageLayer : public osgEarth::Contrib::TileSourceImageLayer { public: // serialization - class SDKVIS_EXPORT Options : public osgEarth::ImageLayer::Options { + class SDKVIS_EXPORT Options : public osgEarth::Contrib::TileSourceImageLayer::Options { public: - META_LayerOptions(simVis, Options, osgEarth::ImageLayer::Options); - OE_OPTION(simVis::DBOptions, driver); + META_LayerOptions(simVis, Options, osgEarth::Contrib::TileSourceImageLayer::Options); virtual osgEarth::Config getConfig() const; private: void fromConfig(const osgEarth::Config&); }; public: - META_Layer(simVis, DBImageLayer, Options, osgEarth::ImageLayer, DBImage); + META_Layer(simVis, DBImageLayer, Options, osgEarth::Contrib::TileSourceImageLayer, DBImage); public: /// Base URL of TileCache endpoint @@ -74,30 +73,28 @@ class SDKVIS_EXPORT DBImageLayer : public osgEarth::ImageLayer /// Called by constructors virtual void init(); - /// Create and return the underlying TileSource - virtual osgEarth::TileSource* createTileSource(); - /// Destructor virtual ~DBImageLayer() { } + + simVis::DBOptions localCopyOfOptions_; }; /** * Elevation layer connected to a DB file */ -class SDKVIS_EXPORT DBElevationLayer : public osgEarth::ElevationLayer +class SDKVIS_EXPORT DBElevationLayer : public osgEarth::Contrib::TileSourceElevationLayer { public: // serialization - class SDKVIS_EXPORT Options : public osgEarth::ElevationLayer::Options { + class SDKVIS_EXPORT Options : public osgEarth::Contrib::TileSourceElevationLayer::Options { public: - META_LayerOptions(simVis, Options, osgEarth::ElevationLayer::Options); - OE_OPTION(simVis::DBOptions, driver); + META_LayerOptions(simVis, Options, osgEarth::Contrib::TileSourceElevationLayer::Options); virtual osgEarth::Config getConfig() const; private: void fromConfig(const osgEarth::Config&); }; public: - META_Layer(simVis, DBElevationLayer, Options, osgEarth::ElevationLayer, DBElevation); + META_Layer(simVis, DBElevationLayer, Options, osgEarth::Contrib::TileSourceElevationLayer, DBElevation); /// URL of the database file void setURL(const osgEarth::URI& value); @@ -117,14 +114,13 @@ class SDKVIS_EXPORT DBElevationLayer : public osgEarth::ElevationLayer protected: // Layer - /// Called by constructors + /// Called by constructors virtual void init(); - /// Create and return the underlying TileSource - virtual osgEarth::TileSource* createTileSource(); - /// Destructor virtual ~DBElevationLayer() { } + + simVis::DBOptions localCopyOfOptions_; }; } diff --git a/SDK/simVis/DBOptions.h b/SDK/simVis/DBOptions.h index d7d8279ee..4f47c02f7 100644 --- a/SDK/simVis/DBOptions.h +++ b/SDK/simVis/DBOptions.h @@ -33,7 +33,7 @@ namespace simVis /** * Configuration options for the "DB" tile source driver. */ -class DBOptions : public osgEarth::TileSourceOptions // header-only (no export) +class DBOptions : public osgEarth::Contrib::TileSourceOptions // header-only (no export) { public: /** Location of the DB file to load (mutable) */ @@ -65,7 +65,7 @@ class DBOptions : public osgEarth::TileSourceOptions // header-only (no export) // (override from osgEarth::TileSourceOptions) virtual osgEarth::Config getConfig() const { - osgEarth::Config conf = osgEarth::TileSourceOptions::getConfig(); + osgEarth::Config conf = osgEarth::Contrib::TileSourceOptions::getConfig(); conf.set("url", _url); conf.set("deepest_level", _deepestLevel); return conf; @@ -76,7 +76,7 @@ class DBOptions : public osgEarth::TileSourceOptions // header-only (no export) // (override from osgEarth::TileSourceOptions) virtual void mergeConfig(const osgEarth::Config& conf) { - osgEarth::TileSourceOptions::mergeConfig(conf); + osgEarth::Contrib::TileSourceOptions::mergeConfig(conf); fromConfig_(conf); } diff --git a/SDK/simVis/LayerRefreshCallback.cpp b/SDK/simVis/LayerRefreshCallback.cpp index c9e097e7c..736d232ed 100644 --- a/SDK/simVis/LayerRefreshCallback.cpp +++ b/SDK/simVis/LayerRefreshCallback.cpp @@ -42,7 +42,7 @@ class LayerRefreshCallback::MapUpdatedCallback : public osgEarth::MapCallback /** Watch a TerrainLayer when it's added */ virtual void onLayerAdded(osgEarth::Layer* layer, unsigned index) { - const osgEarth::TerrainLayer* terrainLayer = dynamic_cast(layer); + const osgEarth::TileLayer* terrainLayer = dynamic_cast(layer); if (terrainLayer != NULL) parent_.watchLayer_(terrainLayer); } @@ -50,7 +50,7 @@ class LayerRefreshCallback::MapUpdatedCallback : public osgEarth::MapCallback /** Forget a TerrainLayer when it's removed */ virtual void onLayerRemoved(osgEarth::Layer* layer, unsigned index) { - const osgEarth::TerrainLayer* terrainLayer = dynamic_cast(layer); + const osgEarth::TileLayer* terrainLayer = dynamic_cast(layer); if (terrainLayer != NULL) parent_.forgetLayer_(terrainLayer); } @@ -58,7 +58,7 @@ class LayerRefreshCallback::MapUpdatedCallback : public osgEarth::MapCallback /** Watch a TerrainLayer when it's enabled */ virtual void onLayerEnabled(osgEarth::Layer* layer) { - const osgEarth::TerrainLayer* terrainLayer = dynamic_cast(layer); + const osgEarth::TileLayer* terrainLayer = dynamic_cast(layer); if (terrainLayer != NULL) parent_.watchLayer_(terrainLayer); } @@ -66,7 +66,7 @@ class LayerRefreshCallback::MapUpdatedCallback : public osgEarth::MapCallback /** Forget a TerrainLayer when it's disabled */ virtual void onLayerDisabled(osgEarth::Layer* layer) { - const osgEarth::TerrainLayer* terrainLayer = dynamic_cast(layer); + const osgEarth::TileLayer* terrainLayer = dynamic_cast(layer); if (terrainLayer != NULL) parent_.forgetLayer_(terrainLayer); } @@ -136,7 +136,7 @@ void LayerRefreshCallback::runImpl_() // Loop through all watched layers for (auto it = watchedLayers_.begin(); it != watchedLayers_.end(); ++it) { - osg::observer_ptr layer = (*it).layer; + osg::observer_ptr layer = (*it).layer; if (!layer.valid() || !layer->getEnabled()) { assert(0); // Should not be watching a NULL or disabled layer @@ -167,7 +167,7 @@ void LayerRefreshCallback::runImpl_() // NOTE: A call to terrainEngine->dirtyTerrain() is NOT required here } -void LayerRefreshCallback::watchLayer_(const osgEarth::TerrainLayer* layer) +void LayerRefreshCallback::watchLayer_(const osgEarth::TileLayer* layer) { if (layer == NULL) return; @@ -178,7 +178,7 @@ void LayerRefreshCallback::watchLayer_(const osgEarth::TerrainLayer* layer) watchedLayers_.push_back(info); } -void LayerRefreshCallback::forgetLayer_(const osgEarth::TerrainLayer* layer) +void LayerRefreshCallback::forgetLayer_(const osgEarth::TileLayer* layer) { if (layer == NULL) return; diff --git a/SDK/simVis/LayerRefreshCallback.h b/SDK/simVis/LayerRefreshCallback.h index dcb3bde71..a27bd0c0e 100644 --- a/SDK/simVis/LayerRefreshCallback.h +++ b/SDK/simVis/LayerRefreshCallback.h @@ -69,7 +69,7 @@ class LayerRefreshCallback : public osg::Callback /** Groups a TerrainLayer pointer and the elapsed time since last its refresh */ struct LayerInfo { - osg::observer_ptr layer; + osg::observer_ptr layer; osg::ElapsedTime elapsedTime; }; @@ -77,9 +77,9 @@ class LayerRefreshCallback : public osg::Callback void runImpl_(); /** Watch the given layer and refresh it when required a refresh is due */ - void watchLayer_(const osgEarth::TerrainLayer* layer); + void watchLayer_(const osgEarth::TileLayer* layer); /** Stop watching the given layer */ - void forgetLayer_(const osgEarth::TerrainLayer* layer); + void forgetLayer_(const osgEarth::TileLayer* layer); /** Get the interval for the given layer in seconds */ double getIntervalForLayer_(const osgEarth::Layer* layer) const; diff --git a/SDK/simVis/SceneManager.cpp b/SDK/simVis/SceneManager.cpp index c6a9c1c08..4effc5c4c 100644 --- a/SDK/simVis/SceneManager.cpp +++ b/SDK/simVis/SceneManager.cpp @@ -462,9 +462,9 @@ void SceneManager::applyImageLayerDisplaySettings_(const osgEarth::ImageLayer& s destLayer->setEnabled(sourceLayer.getEnabled()); } -std::string SceneManager::getLayerHash_(osgEarth::TerrainLayer* layer) const +std::string SceneManager::getLayerHash_(osgEarth::TileLayer* layer) const { - // This method mimics the logic in osgEarth::TerrainLayer::setCache for generating a unique id for the layer + // This method mimics the logic in osgEarth::TileLayer::setCache for generating a unique id for the layer // system will generate a cacheId. technically, this is not quite right, we need to remove everything that's // an image layer property and just use the tilesource properties. diff --git a/SDK/simVis/SceneManager.h b/SDK/simVis/SceneManager.h index 45f2b3ffe..dd5e1f112 100644 --- a/SDK/simVis/SceneManager.h +++ b/SDK/simVis/SceneManager.h @@ -195,8 +195,8 @@ namespace simVis void init_(); /** Detects engine driver problems and sets internal state appropriately */ void detectTerrainEngineDriverProblems_(); - /** Returns the unique hash identifying the layer. Taken from osgEarth::TerrainLayer::setCache method */ - std::string getLayerHash_(osgEarth::TerrainLayer* layer) const; + /** Returns the unique hash identifying the layer. Taken from osgEarth::TileLayer::setCache method */ + std::string getLayerHash_(osgEarth::TileLayer* layer) const; /** Replace image layers in currentMap with image layers in newMap, unless the layer already exists in currentMap. Removes old layers not in newMap */ void updateImageLayers_(const osgEarth::Map& newMap, osgEarth::Map* currentMap); /** Replace elevation layers in currentMap with image layers in newMap, unless the layer already exists in currentMap. Removes old layers not in newMap */ From 29a1792d7641e7ae16f693537a0011e3dc397c82 Mon Sep 17 00:00:00 2001 From: gwaldron Date: Tue, 14 Jan 2020 15:24:27 -0500 Subject: [PATCH 026/121] From c70c32458572f845eaf0ee8f658e6dbe1cf89c17 Mon Sep 17 00:00:00 2001 From Glenn: Refactor DB out of plugin and into layers; support is optional and depends on sqlite3 --- CMakeLists.txt | 4 + Examples/CMakeLists.txt | 9 +- Examples/DBReader/DBReader.cpp | 1 - Examples/Ocean/Ocean.cpp | 1 - Plugins/CMakeLists.txt | 10 +- SDK/simUtil.h | 2 +- SDK/simUtil/CMakeLists.txt | 8 +- SDK/simUtil/DbConfigurationFile.cpp | 1 - SDK/simUtil/ExampleResources.cpp | 1 - SDK/simUtil/LayerFactory.cpp | 8 + SDK/simUtil/LayerFactory.h | 6 + SDK/simVis.h | 1 - SDK/simVis/CMakeLists.txt | 34 +- SDK/simVis/DB/Plugin.cpp | 56 ++ SDK/simVis/DB/QSCommon.h | 50 ++ SDK/simVis/DB/QSError.cpp | 171 +++++ SDK/simVis/DB/QSError.h | 81 +++ SDK/simVis/DB/QSNodeID96.cpp | 302 +++++++++ SDK/simVis/DB/QSNodeID96.h | 64 ++ SDK/simVis/DB/QSPosXYExtents.cpp | 170 +++++ SDK/simVis/DB/QSPosXYExtents.h | 85 +++ SDK/simVis/DB/RasterCommon.h | 0 SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp | 364 +++++++++++ SDK/simVis/DB/SQLiteDataBaseReadUtil.h | 162 +++++ SDK/simVis/DB/swapbytes.h | 780 +++++++++++++++++++++++ SDK/simVis/DBFormat.cpp | 773 +++++++++++++++++++++- SDK/simVis/DBFormat.h | 28 +- 27 files changed, 3114 insertions(+), 58 deletions(-) create mode 100644 SDK/simVis/DB/Plugin.cpp create mode 100644 SDK/simVis/DB/QSCommon.h create mode 100644 SDK/simVis/DB/QSError.cpp create mode 100644 SDK/simVis/DB/QSError.h create mode 100644 SDK/simVis/DB/QSNodeID96.cpp create mode 100644 SDK/simVis/DB/QSNodeID96.h create mode 100644 SDK/simVis/DB/QSPosXYExtents.cpp create mode 100644 SDK/simVis/DB/QSPosXYExtents.h create mode 100644 SDK/simVis/DB/RasterCommon.h create mode 100644 SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp create mode 100644 SDK/simVis/DB/SQLiteDataBaseReadUtil.h create mode 100644 SDK/simVis/DB/swapbytes.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e2849ff6..eca0c0e46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -206,6 +206,10 @@ include(ImportProtobuf) # --- SQLITE3 ----------------------------- set(SQLITE3_DIR "" CACHE PATH "Sqlite3 root directory") include(ImportSQLite) +if (SQLITE3_FOUND) + set(SIM_HAVE_DB_SUPPORT 1) + add_definitions(-DSIM_HAVE_DB_SUPPORT) +endif() # subprojects add_subdirectory(SDK) diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index 7e71e2ba8..64e51cbed 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -10,7 +10,6 @@ add_subdirectory(BasicViewer) add_subdirectory(BasicViewerText) add_subdirectory(CentroidEyePosition) add_subdirectory(CustomRenderingTest) -add_subdirectory(DBReader) add_subdirectory(GeoFencing) add_subdirectory(GOGAttachments) add_subdirectory(GOGReader) @@ -20,7 +19,6 @@ add_subdirectory(MapScale) add_subdirectory(MassiveData) add_subdirectory(ObserverMaker) add_subdirectory(Ocean) -add_subdirectory(Overhead) add_subdirectory(Periscope) add_subdirectory(Picking) add_subdirectory(PlatformSymbology) @@ -30,11 +28,16 @@ add_subdirectory(RangeTool) add_subdirectory(RCS) add_subdirectory(RFProp) add_subdirectory(RocketBurn) -add_subdirectory(LoadEarthFile) add_subdirectory(SkyModel) add_subdirectory(SimpleServer) add_subdirectory(TimestampedLayer) +if(SIM_HAVE_DB_SUPPORT) + add_subdirectory(DBReader) + add_subdirectory(LoadEarthFile) + add_subdirectory(Overhead) +endif() + if(QT_FOUND) add_subdirectory(Qt) add_subdirectory(QtActionItemModelTest) diff --git a/Examples/DBReader/DBReader.cpp b/Examples/DBReader/DBReader.cpp index 9dcf6c356..71b77cfcf 100644 --- a/Examples/DBReader/DBReader.cpp +++ b/Examples/DBReader/DBReader.cpp @@ -33,7 +33,6 @@ #include "simCore/Common/HighPerformanceGraphics.h" #include "simUtil/ExampleResources.h" #include "simVis/Viewer.h" -#include "simVis/DBOptions.h" #include "simVis/osgEarthVersion.h" #include "simUtil/ExampleResources.h" #include "simVis/DBFormat.h" diff --git a/Examples/Ocean/Ocean.cpp b/Examples/Ocean/Ocean.cpp index 7b450aff2..cc7d7e7f9 100644 --- a/Examples/Ocean/Ocean.cpp +++ b/Examples/Ocean/Ocean.cpp @@ -42,7 +42,6 @@ #include "simData/MemoryDataStore.h" #include "simVis/BathymetryGenerator.h" -#include "simVis/DBOptions.h" #include "simVis/osgEarthVersion.h" #include "simVis/Platform.h" #include "simVis/PlatformModel.h" diff --git a/Plugins/CMakeLists.txt b/Plugins/CMakeLists.txt index ca300b023..49208ea63 100644 --- a/Plugins/CMakeLists.txt +++ b/Plugins/CMakeLists.txt @@ -1,9 +1,9 @@ # DB plugin no longer needed with osgEarth 3.x -if(SQLITE3_LIBRARY_RELEASE_NAME) - add_subdirectory(OSGEarthDBDriver) -else() - message(STATUS "Skipping osgEarth .db Driver plug-in because of missing dependencies.") -endif() +#if(SQLITE3_LIBRARY_RELEASE_NAME) +# add_subdirectory(OSGEarthDBDriver) +#else() +# message(STATUS "Skipping osgEarth .db Driver plug-in because of missing dependencies.") +#endif() if(QT_FOUND) option(ENABLE_QTDESIGNER_WIDGETS "Build Qt Designer Plugins for simQt widgets" ON) diff --git a/SDK/simUtil.h b/SDK/simUtil.h index 91c5b8fa2..698cb4387 100644 --- a/SDK/simUtil.h +++ b/SDK/simUtil.h @@ -25,7 +25,7 @@ #include "simUtil/Capabilities.h" #include "simUtil/DataStoreTestHelper.h" #include "simUtil/DatumConvert.h" -#include "simUtil/DbConfigurationFile.h" +//#include "simUtil/DbConfigurationFile.h" #include "simUtil/DefaultDataStoreValues.h" #include "simUtil/DynamicSelectionPicker.h" #include "simUtil/ExampleControls.h" diff --git a/SDK/simUtil/CMakeLists.txt b/SDK/simUtil/CMakeLists.txt index 3c550fe2d..f364093dc 100644 --- a/SDK/simUtil/CMakeLists.txt +++ b/SDK/simUtil/CMakeLists.txt @@ -18,7 +18,6 @@ set(UTIL_HEADERS ${UTIL_INC}Capabilities.h ${UTIL_INC}DataStoreTestHelper.h ${UTIL_INC}DatumConvert.h - ${UTIL_INC}DbConfigurationFile.h ${UTIL_INC}DefaultDataStoreValues.h ${UTIL_INC}ExampleControls.h ${UTIL_INC}ExampleResources.h @@ -54,7 +53,6 @@ set(UTIL_SOURCES ${UTIL_SRC}Capabilities.cpp ${UTIL_SRC}DataStoreTestHelper.cpp ${UTIL_SRC}DatumConvert.cpp - ${UTIL_SRC}DbConfigurationFile.cpp ${UTIL_SRC}DefaultDataStoreValues.cpp ${UTIL_SRC}ExampleControls.cpp ${UTIL_SRC}ExampleResources.cpp @@ -83,6 +81,12 @@ set(UTIL_SOURCES ${UTIL_SRC}ViewpointMonitor.cpp ${UTIL_SRC}ViewpointPositions.cpp ) + +if(SIM_HAVE_DB_SUPPORT) + set(UTIL_HEADERS ${UTIL_HEADERS} ${UTIL_INC}DbConfigurationFile.h) + set(UTIL_SOURCES ${UTIL_SOURCES} ${UTIL_SRC}DbConfigurationFile.cpp) +endif() + set(UTIL_GENERATED_HEADERS) set(UTIL_GENERATED_SOURCES) diff --git a/SDK/simUtil/DbConfigurationFile.cpp b/SDK/simUtil/DbConfigurationFile.cpp index 4ae7f057b..697ca79bf 100644 --- a/SDK/simUtil/DbConfigurationFile.cpp +++ b/SDK/simUtil/DbConfigurationFile.cpp @@ -34,7 +34,6 @@ #include "simCore/String/Utils.h" #include "simCore/String/ValidNumber.h" #include "simVis/AlphaColorFilter.h" -#include "simVis/DBOptions.h" #include "simVis/DBFormat.h" #include "simVis/SceneManager.h" #include "simVis/Utils.h" diff --git a/SDK/simUtil/ExampleResources.cpp b/SDK/simUtil/ExampleResources.cpp index cc30723e7..e4e89225b 100644 --- a/SDK/simUtil/ExampleResources.cpp +++ b/SDK/simUtil/ExampleResources.cpp @@ -34,7 +34,6 @@ #include "simCore/String/Utils.h" #include "simCore/Time/ClockImpl.h" #include "simData/DataStore.h" -#include "simVis/DBOptions.h" #include "simVis/Gl3Utils.h" #include "simVis/Registry.h" #include "simVis/SceneManager.h" diff --git a/SDK/simUtil/LayerFactory.cpp b/SDK/simUtil/LayerFactory.cpp index d6eef5877..f9fa0fe06 100644 --- a/SDK/simUtil/LayerFactory.cpp +++ b/SDK/simUtil/LayerFactory.cpp @@ -29,7 +29,11 @@ #include "simCore/String/Format.h" #include "simCore/String/Utils.h" #include "simVis/Constants.h" + +#ifdef SIM_HAVE_DB_SUPPORT #include "simVis/DBFormat.h" +#endif + #include "simVis/Types.h" #include "simUtil/LayerFactory.h" @@ -38,6 +42,7 @@ namespace simUtil { /** Default cache time of one year */ static const osgEarth::TimeSpan ONE_YEAR(365 * 86400); +#ifdef SIM_HAVE_DB_SUPPORT simVis::DBImageLayer* LayerFactory::newDbImageLayer(const std::string& fullPath) const { osgEarth::Config config; @@ -55,6 +60,7 @@ simVis::DBImageLayer* LayerFactory::newDbImageLayer(const std::string& fullPath) return layer.release(); } +#endif osgEarth::MBTilesImageLayer* LayerFactory::newMbTilesImageLayer(const std::string& fullPath) const { @@ -95,6 +101,7 @@ osgEarth::GDALImageLayer* LayerFactory::newGdalImageLayer(const std::string& ful return layer.release(); } +#ifdef SIM_HAVE_DB_SUPPORT simVis::DBElevationLayer* LayerFactory::newDbElevationLayer(const std::string& fullPath) const { osgEarth::Config config; @@ -112,6 +119,7 @@ simVis::DBElevationLayer* LayerFactory::newDbElevationLayer(const std::string& f return layer.release(); } +#endif osgEarth::MBTilesElevationLayer* LayerFactory::newMbTilesElevationLayer(const std::string& fullPath) const { diff --git a/SDK/simUtil/LayerFactory.h b/SDK/simUtil/LayerFactory.h index 320e7620e..6d943ecad 100644 --- a/SDK/simUtil/LayerFactory.h +++ b/SDK/simUtil/LayerFactory.h @@ -58,15 +58,21 @@ namespace simUtil { class SDKUTIL_EXPORT LayerFactory { public: +#ifdef SIM_HAVE_DB_SUPPORT /** Returns an image layer properly configured for DB layer. */ simVis::DBImageLayer* newDbImageLayer(const std::string& fullPath) const; +#endif + /** Returns an image layer properly configured for MBTiles layer. */ osgEarth::MBTilesImageLayer* newMbTilesImageLayer(const std::string& fullPath) const; /** Returns an image layer properly configured for GDAL layer. */ osgEarth::GDALImageLayer* newGdalImageLayer(const std::string& fullPath) const; +#ifdef SIM_HAVE_DB_SUPPORT /** Returns an elevation layer properly configured for DB layer. */ simVis::DBElevationLayer* newDbElevationLayer(const std::string& fullPath) const; +#endif + /** Returns an elevation layer properly configured for MBTiles layer. */ osgEarth::MBTilesElevationLayer* newMbTilesElevationLayer(const std::string& fullPath) const; /** Returns an elevation layer properly configured for GDAL layer. */ diff --git a/SDK/simVis.h b/SDK/simVis.h index 29949f19d..91e040310 100644 --- a/SDK/simVis.h +++ b/SDK/simVis.h @@ -43,7 +43,6 @@ #include "simVis/CustomRendering.h" #include "simVis/CylinderGeode.h" #include "simVis/CylinderStorage.h" -#include "simVis/DBOptions.h" #include "simVis/DisableDepthOnAlpha.h" #include "simVis/DynamicScaleTransform.h" #include "simVis/EarthManipulator.h" diff --git a/SDK/simVis/CMakeLists.txt b/SDK/simVis/CMakeLists.txt index 4256d3309..25feb39ab 100644 --- a/SDK/simVis/CMakeLists.txt +++ b/SDK/simVis/CMakeLists.txt @@ -64,8 +64,6 @@ set(VIS_HEADERS_CORE ${VIS_INC}CustomRendering.h ${VIS_INC}CylinderGeode.h ${VIS_INC}CylinderStorage.h - ${VIS_INC}DBFormat.h - ${VIS_INC}DBOptions.h ${VIS_INC}DisableDepthOnAlpha.h ${VIS_INC}DynamicScaleTransform.h ${VIS_INC}EarthManipulator.h @@ -139,6 +137,17 @@ set(VIS_HEADERS_CORE ${CMAKE_CURRENT_BINARY_DIR}/include/simVis/osgEarthVersion.h ) +set(VIS_HEADERS_DB + ${VIS_INC}DBFormat.h + ${VIS_INC}DB/QSCommon.h + ${VIS_INC}DB/QSError.h + ${VIS_INC}DB/QSNodeID96.h + ${VIS_INC}DB/QSPosXYExtents.h + ${VIS_INC}DB/RasterCommon.h + ${VIS_INC}DB/SQLiteDataBaseReadUtil.h + ${VIS_INC}DB/swapbytes.h +) + set(VIS_HEADERS_RFPROP ${VIS_INC}RFProp/ArepsLoader.h ${VIS_INC}RFProp/BearingProfileMap.h @@ -211,7 +220,6 @@ set(VIS_SOURCES_CORE ${VIS_SRC}CustomRendering.cpp ${VIS_SRC}CylinderGeode.cpp ${VIS_SRC}CylinderStorage.cpp - ${VIS_SRC}DBFormat.cpp ${VIS_SRC}DisableDepthOnAlpha.cpp ${VIS_SRC}DynamicScaleTransform.cpp ${VIS_SRC}EarthManipulator.cpp @@ -279,6 +287,14 @@ set(VIS_SOURCES_CORE ${VIS_SRC}ViewManagerLogDbAdapter.cpp ) +set(VIS_SOURCES_DB + ${VIS_INC}DBFormat.cpp + ${VIS_INC}DB/QSError.cpp + ${VIS_INC}DB/QSNodeID96.cpp + ${VIS_INC}DB/QSPosXYExtents.cpp + ${VIS_INC}DB/SQLiteDataBaseReadUtil.cpp +) + set(VIS_SOURCES_RFPROP ${VIS_SRC}RFProp/ArepsLoader.cpp ${VIS_SRC}RFProp/BearingProfileMap.cpp @@ -367,6 +383,14 @@ source_group("" FILES ${VIS_ALL_HEADER}) set(VIS_HEADERS ${VIS_HEADERS_CORE} ${VIS_HEADERS_RFPROP} ${VIS_HEADERS_GOG}) set(VIS_SOURCES ${VIS_SOURCES_CORE} ${VIS_SOURCES_RFPROP} ${VIS_SOURCES_GOG} ${VIS_SHADER_FILES}) +if(SIM_HAVE_DB_SUPPORT) + source_group(Headers\\DB FILES ${VIS_HEADERS_DB}) + source_group(Sources\\DB FILES ${VIS_SOURCES_DB}) + + set(VIS_HEADERS ${VIS_HEADERS} ${VIS_HEADERS_DB}) + set(VIS_SOURCES ${VIS_SOURCES} ${VIS_SOURCES_DB}) +endif() + # ---------------------------------------------------------------------- # Avoid false MSVC 2017/2019 MSB8027 warning from Unity build on Utils.cpp and Angle.cpp @@ -398,6 +422,10 @@ target_link_libraries(simVis PUBLIC simData simCore simNotify ${OSG_ALL_LIBDEPENDENCIES} OSGEARTH) target_link_libraries(simVis PRIVATE VSI::GL) +if(SQLITE3_FOUND) + target_link_libraries(simVis PUBLIC SQLITE3) +endif() + if(SIMVIS_SHARED) target_compile_definitions(simVis PRIVATE simVis_LIB_EXPORT_SHARED) else() diff --git a/SDK/simVis/DB/Plugin.cpp b/SDK/simVis/DB/Plugin.cpp new file mode 100644 index 000000000..43635c2b5 --- /dev/null +++ b/SDK/simVis/DB/Plugin.cpp @@ -0,0 +1,56 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** +***** ***** +***** Classification: UNCLASSIFIED ***** +***** Classified By: ***** +***** Declassify On: ***** +***** ***** +**************************************************************************** +* +* +* Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. +* EW Modeling & Simulation, Code 5773 +* 4555 Overlook Ave. +* Washington, D.C. 20375-5339 +* +* License for source code at https://simdis.nrl.navy.mil/License.aspx +* +* The U.S. Government retains all rights to use, duplicate, distribute, +* disclose, or release this software. +* +*/ +#include "osgEarth/TileSource" +#include "osgDB/FileNameUtils" +#include "osgDB/Registry" +#include +#include "DBTileSource.h" + +class SimSdkOSGEarthDBDriverPlugin : public osgEarth::Contrib::TileSourceDriver +{ +public: + SimSdkOSGEarthDBDriverPlugin() { } + + const char* className() + { + return "OSGEarth DB Driver"; + } + + bool acceptsExtension(const std::string& extension) const + { + return osgDB::equalCaseInsensitive("osgearth_db", extension); + } + + osgDB::ReaderWriter::ReadResult readObject(const std::string& uri, const osgDB::Options* options) const + { + std::string ext = osgDB::getFileExtension(uri); + if (!acceptsExtension(ext)) + { + return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED; + } + + return osgDB::ReaderWriter::ReadResult( + new simVis_db::DBTileSource(getTileSourceOptions(options))); + } +}; + +REGISTER_OSGPLUGIN(osgearth_db, SimSdkOSGEarthDBDriverPlugin) diff --git a/SDK/simVis/DB/QSCommon.h b/SDK/simVis/DB/QSCommon.h new file mode 100644 index 000000000..6e1f6d744 --- /dev/null +++ b/SDK/simVis/DB/QSCommon.h @@ -0,0 +1,50 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ +#ifndef QS_COMMON_H +#define QS_COMMON_H + +#include "simCore/Common/Common.h" + +namespace simVis_db +{ + typedef uint8_t FaceIndexType; + typedef uint8_t TextureDataType; + typedef uint8_t RasterFormat; + + /// Raster formats + static const RasterFormat SPLIT_UNKNOWN = 0; + static const RasterFormat SPLIT_SGI_RGB = 1; + static const RasterFormat SPLIT_SGI_RGBA = 2; + static const RasterFormat SPLIT_5551_GZ = 3; + static const RasterFormat SPLIT_5551_ZLIB_COMPRESS = 4; + static const RasterFormat SPLIT_RGBA_ZLIB_COMPRESS = 5; + static const RasterFormat SPLIT_INTA_ZLIB_COMPRESS = 6; + static const RasterFormat SPLIT_JPEG_2000 = 8; + static const RasterFormat SPLIT_8BIT_GZ = 9; // GL_LUMINANCE + static const RasterFormat SPLIT_8BIT_ZLIB_COMPRESS = 10; + static const RasterFormat SPLIT_FLOAT32_ZLIB_COMPRESS = 11; + static const RasterFormat SPLIT_JPEG = 12; + static const RasterFormat SPLIT_PNG = 13; + static const RasterFormat SPLIT_TIFF = 14; +} // namespace simVis_db + +#endif /* QS_COMMON_H */ diff --git a/SDK/simVis/DB/QSError.cpp b/SDK/simVis/DB/QSError.cpp new file mode 100644 index 000000000..ddff49188 --- /dev/null +++ b/SDK/simVis/DB/QSError.cpp @@ -0,0 +1,171 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#include +#include +#include "QSError.h" + +namespace simVis_db { + +static const char* QS_IS_UNRECOGNIZED_ERROR_VALUE_STR = "Unrecognized Error Value"; +static const char* QS_IS_OK_STR = "\0"; +static const char* QS_IS_COMMAND_LINE_STR = "Command line error"; +static const char* QS_IS_UNEXPECTED_NULL_STR = "Unexpected NULL"; +static const char* QS_IS_NO_TMPDIR_STR = "TMPDIR environment variable not set"; +static const char* QS_IS_UNABLE_TO_OPEN_DB_STR = "Unable to open database"; +static const char* QS_IS_UNABLE_TO_OPEN_SRC_DS_STR = "Unable to open src dataset"; +static const char* QS_IS_UNABLE_TO_GET_SRC_DRIVER_STR = "Unable to get src driver"; +static const char* QS_IS_UNABLE_TO_GET_SRC_DRIVER_NAME_STR = "Unable to get src driver name"; +static const char* QS_IS_UNABLE_TO_CONVERT_TO_GEOGRAPHIC_STR = "Unable to convert to geographic dataset"; +static const char* QS_IS_UNABLE_TO_CREATE_INFO_FILE_STR = "Unable to create info file"; +static const char* QS_IS_UNABLE_TO_OPEN_INFO_FILE_STR = "Unable to open info file"; +static const char* QS_IS_TIME_STRING_ERROR_STR = "Time string error"; +static const char* QS_IS_UNABLE_TO_GET_FACE_STRING_STR = "Unable to get face string"; +static const char* QS_IS_DB_NOT_INITIALIZED_STR = "Database not initialized"; +static const char* QS_IS_UNABLE_TO_CREATE_TN_INDEX_STR = "Unable to create texture name index"; +static const char* QS_IS_UNABLE_TO_INSERT_TS_INTO_LIST_STR = "Unable to insert texture set into list"; +static const char* QS_IS_EMPTY_TABLE_NAME_STR = "Empty table name"; +static const char* QS_IS_UNABLE_TO_CREATE_TABLE_STR = "Unable to create table"; +static const char* QS_IS_UNABLE_TO_CREATE_ID_INDEX_STR = "Unable to create id index"; +static const char* QS_IS_UNABLE_TO_CREATE_P_IMAGE_STR = "Unable to create polar image"; +static const char* QS_IS_UNABLE_TO_READ_FROM_RASTER_STR = "Unable to read from raster"; +static const char* QS_IS_FORMAT_NOT_IMPLEMENTED_STR = "Format not implemented"; +static const char* QS_IS_UNABLE_TO_WRITE_TO_BLOB_STR = "Unable to write to blob"; +static const char* QS_IS_UNABLE_SCALE_IMAGE_STR = "Unable to scale image"; +static const char* QS_IS_PREPARE_ERROR_STR = "Unable to prepare statement"; +static const char* QS_IS_TS_NOT_FOUND_STR = "Texture set not found"; +static const char* QS_IS_UNABLE_TO_UPDATE_EXTENTS_STR = "Unable to update extents"; +static const char* QS_IS_UNABLE_TO_WRITE_DATA_BUFFER_STR = "Unable to write data buffer"; +static const char* QS_IS_UNABLE_TO_READ_DATA_BUFFER_STR = "Unable to read data buffer"; +static const char* QS_IS_BUSY_STR = "Database is busy"; +static const char* QS_IS_UNABLE_TO_UPDATE_TIME_STR = "Unable to update time"; +static const char* QS_IS_UNABLE_TO_SET_NUM_BYTES_STR = "Unable to set num bytes"; +static const char* QS_IS_UNABLE_TO_GET_AVERAGE_REQUEST_TIME_STR = "Unable to get average request time"; +static const char* QS_IS_UNABLE_TO_REMOVE_OLDER_THAN_AVG_STR = "Unable to remove older than average"; +static const char* QS_IS_UNABLE_TO_SUM_NUMBER_OF_BYTES_STR = "Unable to sum number of bytes"; +static const char* QS_IS_UNABLE_TO_WRITE_TO_OUTPUT_DIR_STR = "Unable to write to output directory"; +static const char* QS_IS_COULD_NOT_CREATE_FUNCTION_STR = "Unable to create function"; +static const char* QS_IS_EMPTY_FUNCTION_NAME_STR = "Empty function name"; +static const char* QS_IS_UNABLE_TO_EXECUTE_FUNCTION_STR = "Unable to execture function"; +static const char* QS_IS_UNABLE_TO_WRITE_TO_RASTER_STR = "Unable to write to raster"; +static const char* QS_IS_EMPTY_FILENAME_STR = "Empty filename"; +static const char* QS_IS_SET_CREATION_FAILED_STR = "Attempted raster set creation failed"; +static const char* QS_IS_NO_TIME_STAMP_STR = "Unable to obtain timestamp"; + +const char* GetErrorString(const QsErrorType& errorValue) +{ + switch (errorValue) + { + case QS_IS_OK: + return QS_IS_OK_STR; + case QS_IS_COMMAND_LINE: + return QS_IS_COMMAND_LINE_STR; + case QS_IS_UNEXPECTED_NULL: + return QS_IS_UNEXPECTED_NULL_STR; + case QS_IS_NO_TMPDIR: + return QS_IS_NO_TMPDIR_STR; + case QS_IS_UNABLE_TO_OPEN_DB: + return QS_IS_UNABLE_TO_OPEN_DB_STR; + case QS_IS_UNABLE_TO_OPEN_SRC_DS: + return QS_IS_UNABLE_TO_OPEN_SRC_DS_STR; + case QS_IS_UNABLE_TO_GET_SRC_DRIVER: + return QS_IS_UNABLE_TO_GET_SRC_DRIVER_STR; + case QS_IS_UNABLE_TO_GET_SRC_DRIVER_NAME: + return QS_IS_UNABLE_TO_GET_SRC_DRIVER_NAME_STR; + case QS_IS_UNABLE_TO_CONVERT_TO_GEOGRAPHIC: + return QS_IS_UNABLE_TO_CONVERT_TO_GEOGRAPHIC_STR; + case QS_IS_UNABLE_TO_CREATE_INFO_FILE: + return QS_IS_UNABLE_TO_CREATE_INFO_FILE_STR; + case QS_IS_UNABLE_TO_OPEN_INFO_FILE: + return QS_IS_UNABLE_TO_OPEN_INFO_FILE_STR; + case QS_IS_TIME_STRING_ERROR: + return QS_IS_TIME_STRING_ERROR_STR; + case QS_IS_UNABLE_TO_GET_FACE_STRING: + return QS_IS_UNABLE_TO_GET_FACE_STRING_STR; + case QS_IS_DB_NOT_INITIALIZED: + return QS_IS_DB_NOT_INITIALIZED_STR; + case QS_IS_UNABLE_TO_CREATE_TN_INDEX: + return QS_IS_UNABLE_TO_CREATE_TN_INDEX_STR; + case QS_IS_UNABLE_TO_INSERT_TS_INTO_LIST: + return QS_IS_UNABLE_TO_INSERT_TS_INTO_LIST_STR; + case QS_IS_EMPTY_TABLE_NAME: + return QS_IS_EMPTY_TABLE_NAME_STR; + case QS_IS_UNABLE_TO_CREATE_TABLE: + return QS_IS_UNABLE_TO_CREATE_TABLE_STR; + case QS_IS_UNABLE_TO_CREATE_ID_INDEX: + return QS_IS_UNABLE_TO_CREATE_ID_INDEX_STR; + case QS_IS_UNABLE_TO_CREATE_P_IMAGE: + return QS_IS_UNABLE_TO_CREATE_P_IMAGE_STR; + case QS_IS_UNABLE_TO_READ_FROM_RASTER: + return QS_IS_UNABLE_TO_READ_FROM_RASTER_STR; + case QS_IS_FORMAT_NOT_IMPLEMENTED: + return QS_IS_FORMAT_NOT_IMPLEMENTED_STR; + case QS_IS_UNABLE_TO_WRITE_TO_BLOB: + return QS_IS_UNABLE_TO_WRITE_TO_BLOB_STR; + case QS_IS_UNABLE_SCALE_IMAGE: + return QS_IS_UNABLE_SCALE_IMAGE_STR; + case QS_IS_PREPARE_ERROR: + return QS_IS_PREPARE_ERROR_STR; + case QS_IS_TS_NOT_FOUND: + return QS_IS_TS_NOT_FOUND_STR; + case QS_IS_UNABLE_TO_UPDATE_EXTENTS: + return QS_IS_UNABLE_TO_UPDATE_EXTENTS_STR; + case QS_IS_UNABLE_TO_WRITE_DATA_BUFFER: + return QS_IS_UNABLE_TO_WRITE_DATA_BUFFER_STR; + case QS_IS_UNABLE_TO_READ_DATA_BUFFER: + return QS_IS_UNABLE_TO_READ_DATA_BUFFER_STR; + case QS_IS_BUSY: + return QS_IS_BUSY_STR; + case QS_IS_UNABLE_TO_UPDATE_TIME: + return QS_IS_UNABLE_TO_UPDATE_TIME_STR; + case QS_IS_UNABLE_TO_SET_NUM_BYTES: + return QS_IS_UNABLE_TO_SET_NUM_BYTES_STR; + case QS_IS_UNABLE_TO_GET_AVERAGE_REQUEST_TIME: + return QS_IS_UNABLE_TO_GET_AVERAGE_REQUEST_TIME_STR; + case QS_IS_UNABLE_TO_REMOVE_OLDER_THAN_AVG: + return QS_IS_UNABLE_TO_REMOVE_OLDER_THAN_AVG_STR; + case QS_IS_UNABLE_TO_SUM_NUMBER_OF_BYTES: + return QS_IS_UNABLE_TO_SUM_NUMBER_OF_BYTES_STR; + case QS_IS_UNABLE_TO_WRITE_TO_OUTPUT_DIR: + return QS_IS_UNABLE_TO_WRITE_TO_OUTPUT_DIR_STR; + case QS_IS_COULD_NOT_CREATE_FUNCTION: + return QS_IS_COULD_NOT_CREATE_FUNCTION_STR; + case QS_IS_EMPTY_FUNCTION_NAME: + return QS_IS_EMPTY_FUNCTION_NAME_STR; + case QS_IS_UNABLE_TO_EXECUTE_FUNCTION: + return QS_IS_UNABLE_TO_EXECUTE_FUNCTION_STR; + case QS_IS_UNABLE_TO_WRITE_TO_RASTER: + return QS_IS_UNABLE_TO_WRITE_TO_RASTER_STR; + case QS_IS_EMPTY_FILENAME: + return QS_IS_EMPTY_FILENAME_STR; + case QS_IS_SET_CREATION_FAILED: + return QS_IS_SET_CREATION_FAILED_STR; + case QS_IS_NO_TIME_STAMP: + return QS_IS_NO_TIME_STAMP_STR; + default: + std::cerr << "ERROR: Unrecognized error value (" << errorValue << ").\n"; + assert(0); + return QS_IS_UNRECOGNIZED_ERROR_VALUE_STR; + } +} + +} diff --git a/SDK/simVis/DB/QSError.h b/SDK/simVis/DB/QSError.h new file mode 100644 index 000000000..e4d3c42d1 --- /dev/null +++ b/SDK/simVis/DB/QSError.h @@ -0,0 +1,81 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#ifndef QS_ERROR_H +#define QS_ERROR_H + +#include + +namespace simVis_db +{ + //=========================================================================== + typedef int QsErrorType; + static const QsErrorType QS_IS_OK = 0; + static const QsErrorType QS_IS_COMMAND_LINE = 1; + static const QsErrorType QS_IS_UNEXPECTED_NULL = 2; + static const QsErrorType QS_IS_NO_TMPDIR = 3; + static const QsErrorType QS_IS_UNABLE_TO_OPEN_DB = 4; + static const QsErrorType QS_IS_UNABLE_TO_OPEN_SRC_DS = 5; + static const QsErrorType QS_IS_UNABLE_TO_GET_SRC_DRIVER = 6; + static const QsErrorType QS_IS_UNABLE_TO_GET_SRC_DRIVER_NAME = 7; + static const QsErrorType QS_IS_UNABLE_TO_CONVERT_TO_GEOGRAPHIC = 8; + static const QsErrorType QS_IS_UNABLE_TO_CREATE_INFO_FILE = 9; + static const QsErrorType QS_IS_UNABLE_TO_OPEN_INFO_FILE = 10; + static const QsErrorType QS_IS_TIME_STRING_ERROR = 11; + static const QsErrorType QS_IS_UNABLE_TO_GET_FACE_STRING = 12; + static const QsErrorType QS_IS_DB_NOT_INITIALIZED = 13; + static const QsErrorType QS_IS_UNABLE_TO_CREATE_TN_INDEX = 14; + static const QsErrorType QS_IS_UNABLE_TO_INSERT_TS_INTO_LIST = 15; + static const QsErrorType QS_IS_EMPTY_TABLE_NAME = 16; + static const QsErrorType QS_IS_UNABLE_TO_CREATE_TABLE = 17; + static const QsErrorType QS_IS_UNABLE_TO_CREATE_ID_INDEX = 18; + static const QsErrorType QS_IS_UNABLE_TO_CREATE_P_IMAGE = 19; + static const QsErrorType QS_IS_UNABLE_TO_READ_FROM_RASTER = 20; + static const QsErrorType QS_IS_FORMAT_NOT_IMPLEMENTED = 21; + static const QsErrorType QS_IS_UNABLE_TO_WRITE_TO_BLOB = 22; + static const QsErrorType QS_IS_UNABLE_SCALE_IMAGE = 23; + static const QsErrorType QS_IS_PREPARE_ERROR = 24; + static const QsErrorType QS_IS_TS_NOT_FOUND = 25; + static const QsErrorType QS_IS_UNABLE_TO_UPDATE_EXTENTS = 26; + static const QsErrorType QS_IS_UNABLE_TO_WRITE_DATA_BUFFER = 27; + static const QsErrorType QS_IS_UNABLE_TO_READ_DATA_BUFFER = 28; + static const QsErrorType QS_IS_BUSY = 29; + static const QsErrorType QS_IS_UNABLE_TO_UPDATE_TIME = 30; + static const QsErrorType QS_IS_UNABLE_TO_SET_NUM_BYTES = 31; + static const QsErrorType QS_IS_UNABLE_TO_GET_AVERAGE_REQUEST_TIME = 32; + static const QsErrorType QS_IS_UNABLE_TO_REMOVE_OLDER_THAN_AVG = 33; + static const QsErrorType QS_IS_UNABLE_TO_SUM_NUMBER_OF_BYTES = 34; + static const QsErrorType QS_IS_UNABLE_TO_WRITE_TO_OUTPUT_DIR = 35; + static const QsErrorType QS_IS_COULD_NOT_CREATE_FUNCTION = 36; + static const QsErrorType QS_IS_EMPTY_FUNCTION_NAME = 37; + static const QsErrorType QS_IS_UNABLE_TO_EXECUTE_FUNCTION = 38; + static const QsErrorType QS_IS_UNABLE_TO_WRITE_TO_RASTER = 39; + static const QsErrorType QS_IS_EMPTY_FILENAME = 40; + static const QsErrorType QS_IS_SET_CREATION_FAILED = 41; + static const QsErrorType QS_IS_NO_TIME_STAMP = 42; + + //=========================================================================== + const char* GetErrorString(const QsErrorType&); + +} // namespace simVis_db + +#endif /* QS_ERROR_H */ diff --git a/SDK/simVis/DB/QSNodeID96.cpp b/SDK/simVis/DB/QSNodeID96.cpp new file mode 100644 index 000000000..ccaa33a02 --- /dev/null +++ b/SDK/simVis/DB/QSNodeID96.cpp @@ -0,0 +1,302 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ +#include "swapbytes.h" +#include "QSNodeID96.h" + +namespace simVis_db { + +//=========================================================================== +QSNodeID96::QSNodeID96() + : one_(0), + two_(0), + three_(0) +{ +} + +//--------------------------------------------------------------------------- +QSNodeID96::QSNodeID96(const uint32_t& value) + : one_(value), + two_(0), + three_(0) +{ +} + +//--------------------------------------------------------------------------- +QSNodeID96::~QSNodeID96() +{ +} + +//--------------------------------------------------------------------------- +bool QSNodeID96::operator==(const QSNodeID96& value) const +{ + return ((one_ == value.one_) && (two_ == value.two_) && (three_ == value.three_)); +} + +//--------------------------------------------------------------------------- +bool QSNodeID96::operator<(const QSNodeID96& value) const +{ + if (one_ != value.one_) + return one_ < value.one_; + if (two_ != value.two_) + return two_ < value.two_; + return three_ < value.three_; +} + +//--------------------------------------------------------------------------- +QSNodeID96& QSNodeID96::operator=(const QSNodeID96& value) +{ + one_ = value.one_; + two_ = value.two_; + three_ = value.three_; + return *this; +} + +//--------------------------------------------------------------------------- +QSNodeID96 QSNodeID96::operator~() const +{ + QSNodeID96 returnValue = (*this); + returnValue.one_ = ~one_; + returnValue.two_ = ~two_; + returnValue.three_ = ~three_; + return returnValue; +} + +//--------------------------------------------------------------------------- +QSNodeID96& QSNodeID96::operator|=(const QSNodeID96& value) +{ + one_ |= value.one_; + two_ |= value.two_; + three_ |= value.three_; + return *this; +} + +//--------------------------------------------------------------------------- +QSNodeID96& QSNodeID96::operator&=(const QSNodeID96& value) +{ + one_ &= value.one_; + two_ &= value.two_; + three_ &= value.three_; + return *this; +} + +//--------------------------------------------------------------------------- +QSNodeID96 QSNodeID96::operator>>(int numBitsToShift) const +{ + QSNodeID96 returnValue; + if (numBitsToShift >= 0) + { + if (numBitsToShift == 32) + { + returnValue.one_ = two_; + returnValue.two_ = three_; + returnValue.three_ = 0; + } + else if (numBitsToShift == 0) + { + returnValue.one_ = one_; + returnValue.two_ = two_; + returnValue.three_ = three_; + } + else if (numBitsToShift == 64) + { + returnValue.one_ = three_; + returnValue.two_ = 0; + returnValue.three_ = 0; + } + else if (numBitsToShift < 32) + { + returnValue.three_ = (three_ >> numBitsToShift); + returnValue.two_ = (two_ >> numBitsToShift) | (three_ << (32 - numBitsToShift)); + returnValue.one_ = (one_ >> numBitsToShift) | (two_ << (32 - numBitsToShift)); + } + else if (numBitsToShift < 64) + { + returnValue.three_ = 0; + returnValue.two_ = three_ >> (numBitsToShift-32); + returnValue.one_ = (two_ >> (numBitsToShift-32)) | (three_ << (64 - numBitsToShift)); + } + else if (numBitsToShift < 96) + { + returnValue.three_ = 0; + returnValue.two_ = 0; + returnValue.one_ = three_ >> (numBitsToShift-64); + } + else + { + returnValue.one_ = 0; + returnValue.two_ = 0; + returnValue.three_ = 0; + } + } + else + returnValue.operator<<(-numBitsToShift); + + return returnValue; +} + +//--------------------------------------------------------------------------- +QSNodeID96 QSNodeID96::operator<<(int numBitsToShift) const +{ + QSNodeID96 returnValue; + if (numBitsToShift >= 0) + { + if (numBitsToShift == 32) + { + returnValue.one_ = 0; + returnValue.two_ = one_; + returnValue.three_ = two_; + } + else if (numBitsToShift == 0) + { + returnValue.one_ = one_; + returnValue.two_ = two_; + returnValue.three_ = three_; + } + else if (numBitsToShift == 64) + { + returnValue.one_ = 0; + returnValue.two_ = 0; + returnValue.three_ = one_; + } + else if (numBitsToShift < 32) + { + returnValue.one_ = one_ << numBitsToShift; + returnValue.two_ = (two_ << numBitsToShift) | (one_ >> (32 - numBitsToShift)); + returnValue.three_ = (three_ << numBitsToShift) | (two_ >> (32 - numBitsToShift)); + } + else if (numBitsToShift < 64) + { + returnValue.one_ = 0; + returnValue.two_ = one_ << (numBitsToShift-32); + returnValue.three_ = (two_ << (numBitsToShift-32)) | (one_ >> (64 - numBitsToShift)); + } + else if (numBitsToShift < 96) + { + returnValue.one_ = 0; + returnValue.two_ = 0; + returnValue.three_ = one_ << (numBitsToShift-64); + } + else + { + returnValue.three_ = 0; + returnValue.two_ = 0; + returnValue.one_ = 0; + } + } + else + returnValue.operator>>(-numBitsToShift); + + return returnValue; +} + +//--------------------------------------------------------------------------- +QSNodeID96 QSNodeID96::operator&(const QSNodeID96& value) const +{ + QSNodeID96 returnValue; + returnValue.one_ = one_ & value.one_; + returnValue.two_ = two_ & value.two_; + returnValue.three_ = three_ & value.three_; + return returnValue; +} + +//--------------------------------------------------------------------------- +void QSNodeID96::Pack(uint8_t* buffer) const +{ + if (buffer == NULL) + return; + bewrite(buffer, &three_); + bewrite(buffer + sizeof(three_), &two_); + bewrite(buffer + sizeof(three_) + sizeof(two_), &one_); +} + +//--------------------------------------------------------------------------- +void QSNodeID96::UnPack(const uint8_t* buffer) +{ + if (buffer == NULL) + return; + beread(buffer, &three_); + beread(buffer + sizeof(three_), &two_); + beread(buffer + sizeof(three_) + sizeof(two_), &one_); +} + +//--------------------------------------------------------------------------- +std::string QSNodeID96::FormatAsHex(bool bLeadingZeros) const +{ + std::string returnValue; + + char sTemp[64]; + + if (bLeadingZeros) + { + sprintf(sTemp, "%08x", three_); + returnValue += sTemp; + } + else + { + if (three_) + { + sprintf(sTemp, "%x", three_); + returnValue += sTemp; + } + } + + if (bLeadingZeros) + { + sprintf(sTemp, "%08x", two_); + returnValue += sTemp; + } + else + { + if (two_) + { + if (three_) + sprintf(sTemp, "%08x", two_); + else + sprintf(sTemp, "%x", two_); + returnValue += sTemp; + } + } + + if (bLeadingZeros) + { + sprintf(sTemp, "%08x", one_); + returnValue += sTemp; + } + else + { + if (one_) + { + if (three_ || two_) + sprintf(sTemp, "%08x", one_); + else + sprintf(sTemp, "%x", one_); + returnValue += sTemp; + } + } + + if (returnValue.empty()) + returnValue = "0"; + + return returnValue; +} + +} diff --git a/SDK/simVis/DB/QSNodeID96.h b/SDK/simVis/DB/QSNodeID96.h new file mode 100644 index 000000000..54d9cb6bc --- /dev/null +++ b/SDK/simVis/DB/QSNodeID96.h @@ -0,0 +1,64 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#ifndef QSNODEID96_H +#define QSNODEID96_H + +#include +#include "simCore/Common/Common.h" + +namespace simVis_db +{ + class QSNodeID96 + { + public: + QSNodeID96(); + QSNodeID96(const uint32_t& value); + ~QSNodeID96(); + + bool operator==(const QSNodeID96& value) const; + bool operator<(const QSNodeID96& value) const; + QSNodeID96& operator=(const QSNodeID96& value); + QSNodeID96 operator~() const; + QSNodeID96& operator|=(const QSNodeID96& value); + QSNodeID96& operator&=(const QSNodeID96& value); + QSNodeID96 operator>>(int numBitsToShift) const; + QSNodeID96 operator<<(int numBitsToShift) const; + QSNodeID96 operator&(const QSNodeID96& value) const; + + int SizeOf() const {return 12;} + void Pack(uint8_t*) const; + void UnPack(const uint8_t*); + std::string FormatAsHex(bool bLeadingZeros=true) const; + + protected: + uint32_t one_; + uint32_t two_; + uint32_t three_; + }; + + //=========================================================================== + typedef QSNodeID96 QSNodeId; + +} // namespace simVis_db + +#endif /* QSNODEID96_H */ diff --git a/SDK/simVis/DB/QSPosXYExtents.cpp b/SDK/simVis/DB/QSPosXYExtents.cpp new file mode 100644 index 000000000..6f49b8be3 --- /dev/null +++ b/SDK/simVis/DB/QSPosXYExtents.cpp @@ -0,0 +1,170 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#include +#include "simCore/Calc/Math.h" +#include "swapbytes.h" +#include "QSCommon.h" +#include "QSPosXYExtents.h" + +namespace simVis_db { + +//===================================================================================== +PosXPosYExtents::PosXPosYExtents(QsPosType minXIn, QsPosType maxXIn, QsPosType minYIn, QsPosType maxYIn) + : minX(minXIn), + maxX(maxXIn), + minY(minYIn), + maxY(maxYIn) +{ +} + +void PosXPosYExtents::Initialize() +{ + minX = gQsMaxLength; + maxX = 0; + minY = gQsMaxLength; + maxY = 0; +} + +bool PosXPosYExtents::Valid() const +{ + return ((minX >= maxX) || (minY >= maxY)) ? false : true; +} + +void PosXPosYExtents::SetAll(const PosXPosYExtents& given) +{ + minX = given.minX; + maxX = given.maxX; + minY = given.minY; + maxY = given.maxY; +} + +void PosXPosYExtents::SetAll(const QsPosType& minXIn, const QsPosType& maxXIn, const QsPosType& minYIn, const QsPosType& maxYIn) +{ + minX = minXIn; + maxX = maxXIn; + minY = minYIn; + maxY = maxYIn; +} + +void PosXPosYExtents::Pack(uint8_t* buffer) const +{ + if (buffer == NULL) + return; + bewrite(buffer, &minX); + bewrite(buffer + sizeof(minX), &maxX); + bewrite(buffer + sizeof(minX) + sizeof(maxX), &minY); + bewrite(buffer + sizeof(minX) + sizeof(maxX) + sizeof(minY), &maxY); +} + +void PosXPosYExtents::UnPack(const uint8_t* buffer) +{ + if (buffer == NULL) + return; + beread(buffer, &minX); + beread(buffer + sizeof(minX), &maxX); + beread(buffer + sizeof(minX) + sizeof(maxX), &minY); + beread(buffer + sizeof(minX) + sizeof(maxX) + sizeof(minY), &maxY); +} + +void PosXPosYExtents::Print() +{ + std::cerr << "minX = " << minX << "\n"; + std::cerr << "maxX = " << maxX << "\n"; + std::cerr << "minY = " << minY << "\n"; + std::cerr << "maxY = " << maxY << "\n"; +} + +//===================================================================================== +bool equalTo(const PosXPosYExtents& a, const PosXPosYExtents& b) +{ + if (a.minX != b.minX) return false; + if (a.maxX != b.maxX) return false; + if (a.minY != b.minY) return false; + if (a.maxY != b.maxY) return false; + return true; +} + +bool operator==(const PosXPosYExtents& a, const PosXPosYExtents& b) +{ + return equalTo(a, b); +} + +bool operator!=(const PosXPosYExtents& a, const PosXPosYExtents& b) +{ + return !simVis_db::equalTo(a, b); +} + +//===================================================================================== +void UpdateExtents(const QsPosType& posX, const QsPosType& posY, PosXPosYExtents* extents) +{ + if (extents == NULL) + return; + + extents->minX = simCore::sdkMin(extents->minX, posX); + extents->minY = simCore::sdkMin(extents->minY, posY); + extents->maxX = simCore::sdkMax(extents->maxX, posX); + extents->maxY = simCore::sdkMax(extents->maxY, posY); +} + +bool Copy6Extents(const PosXPosYExtents* copyFrom, PosXPosYExtents* copyTo) +{ + if ((copyFrom == NULL) || (copyTo == NULL)) + return false; + + FaceIndexType faceIndex; + for (faceIndex = 0; faceIndex < 6; ++faceIndex) + copyTo[faceIndex].SetAll(copyFrom[faceIndex]); + + return true; +} + +bool AnyOverlap(const PosXPosYExtents& extA, const PosXPosYExtents& extB) +{ + if ((extA.Valid() == false) || (extB.Valid() == false)) + return false; + + // checks for no x overlap + if ((extA.minX > extB.maxX) || + (extA.maxX < extB.minX)) + return false; + + // checks for no y overlap + if ((extA.minY > extB.maxY) || + (extA.maxY < extB.minY)) + return false; + + return true; +} + +bool AnyOverlap(const QsPosType& posX, const QsPosType& posY, const PosXPosYExtents& extents) +{ + if (extents.Valid() == false) + return false; + + return ((posX < extents.minX) || + (posX > extents.maxX) || + (posY < extents.minY) || + (posY > extents.maxY)) ? false : true; +} + +} diff --git a/SDK/simVis/DB/QSPosXYExtents.h b/SDK/simVis/DB/QSPosXYExtents.h new file mode 100644 index 000000000..e00f32be3 --- /dev/null +++ b/SDK/simVis/DB/QSPosXYExtents.h @@ -0,0 +1,85 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#ifndef QS_POSXY_EXTENTS_H +#define QS_POSXY_EXTENTS_H + +namespace simVis_db +{ + typedef uint64_t QsPosType; + +#if defined Linux || defined Solaris + static const QsPosType gQsMaxLength = 4294967296LL; +#else + static const QsPosType gQsMaxLength = 4294967296; +#endif + static const double gQsDMaxLength = 4294967296.0; + + /** A bounding rectangle of x/y extents */ + struct PosXPosYExtents + { + QsPosType minX; + QsPosType maxX; + QsPosType minY; + QsPosType maxY; + + PosXPosYExtents(QsPosType minX=gQsMaxLength, QsPosType maxX=0, QsPosType minY=gQsMaxLength, QsPosType maxY=0); + + /** Sets up invalid extents */ + void Initialize(); + + /** Confirms validity of extents */ + bool Valid() const; + + /** Sets the extents */ + void SetAll(const PosXPosYExtents& given); + void SetAll(const QsPosType& minX, const QsPosType& maxX, const QsPosType& minY, const QsPosType& maxY); + + /** Packs/unpacks the extents into or from a buffer */ + void Pack(uint8_t*) const; + void UnPack(const uint8_t*); + + /** Prints the extents to the console */ + void Print(); + }; + + //===================================================================================== + bool equalTo(const PosXPosYExtents& a, const PosXPosYExtents& b); + bool operator==(const PosXPosYExtents& a, const PosXPosYExtents& b); + bool operator!=(const PosXPosYExtents& a, const PosXPosYExtents& b); + + //===================================================================================== + /** Updates extents such that the given x/y is within the extents */ + void UpdateExtents(const QsPosType& posX, const QsPosType& posY, PosXPosYExtents* extents); + + /** Copies an array of 6 extents */ + bool Copy6Extents(const PosXPosYExtents*, PosXPosYExtents*); + + /** Checks for any overlap between two rectangles */ + bool AnyOverlap(const PosXPosYExtents&, const PosXPosYExtents&); + + /** Checks if the given x/y is within the given extents */ + bool AnyOverlap(const QsPosType& posX, const QsPosType& posY, const PosXPosYExtents&); + +} // Namespace simVis_db + +#endif /* QS_POSXY_EXTENTS_H */ diff --git a/SDK/simVis/DB/RasterCommon.h b/SDK/simVis/DB/RasterCommon.h new file mode 100644 index 000000000..e69de29bb diff --git a/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp b/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp new file mode 100644 index 000000000..b6a26cc5b --- /dev/null +++ b/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp @@ -0,0 +1,364 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#include +#include +#include "simCore/Time/Utils.h" +#include "swapbytes.h" +#include "QSCommon.h" +#include "SQLiteDataBaseReadUtil.h" + +namespace simVis_db { + +namespace +{ + //===================================================================================== + template + void UnPackArray(SomeClass* givenArray, const uint8_t* givenBuffer, const uint32_t& numElements) + { + if ((givenArray == NULL) || (givenBuffer == NULL)) + return; + + size_t i; + uint8_t tmpBuffer[sizeof(SomeClass)]; + for (i = 0; i < numElements; ++i) + { + memcpy(tmpBuffer, givenBuffer + (sizeof(SomeClass) * i), sizeof(SomeClass)); + givenArray[i].UnPack(tmpBuffer); + } + } + + static const int gMaxBufferSize = 20000000; + + std::string printExtendedErrorMessage(sqlite3* sqlite3Db) + { + std::stringstream errStr; + int extendedErrorCode = sqlite3_extended_errcode(sqlite3Db); + errStr << " Ext Err Code(" << extendedErrorCode << ") "; + // Extended Result Codes: http://www.sqlite.org/c3ref/c_abort_rollback.html + switch (extendedErrorCode) + { + case SQLITE_IOERR_READ: errStr << "SQLITE_IOERR_READ"; break; + case SQLITE_IOERR_SHORT_READ: errStr << "SQLITE_SHORT_READ"; break; + case SQLITE_IOERR_WRITE: errStr << "SQLITE_IOERR_WRITE"; break; + case SQLITE_IOERR_FSYNC: errStr << "SQLITE_IOERR_FSYNC"; break; + case SQLITE_IOERR_DIR_FSYNC: errStr << "SQLITE_IOERR_DIR_FSYNC"; break; + case SQLITE_IOERR_TRUNCATE: errStr << "SQLITE_IOERR_TRUNCATE"; break; + case SQLITE_IOERR_FSTAT: errStr << "SQLITE_IOERR_FSTAT"; break; + case SQLITE_IOERR_UNLOCK: errStr << "SQLITE_IOERR_UNLOCK"; break; + case SQLITE_IOERR_RDLOCK: errStr << "SQLITE_IOERR_RDLOCK"; break; + case SQLITE_IOERR_DELETE: errStr << "SQLITE_IOERR_DELETE"; break; + case SQLITE_IOERR_BLOCKED: errStr << "SQLITE_IOERR_BLOCKED"; break; + case SQLITE_IOERR_NOMEM: errStr << "SQLITE_IOERR_NOMEM"; break; + case SQLITE_IOERR_ACCESS: errStr << "SQLITE_IOERR_ACCESS"; break; + case SQLITE_IOERR_CHECKRESERVEDLOCK: errStr << "SQLITE_IOERR_CHECKRESERVEDLOCK"; break; + case SQLITE_IOERR_LOCK: errStr << "SQLITE_IOERR_LOCK"; break; + case SQLITE_IOERR_CLOSE: errStr << "SQLITE_IOERR_CLOSE"; break; + case SQLITE_IOERR_DIR_CLOSE: errStr << "SQLITE_IOERR_DIR_CLOSE"; break; + case SQLITE_IOERR_SHMOPEN: errStr << "SQLITE_IOERR_SHMOPEN"; break; + case SQLITE_IOERR_SHMSIZE: errStr << "SQLITE_IOERR_SHMSIZE"; break; + case SQLITE_IOERR_SHMLOCK: errStr << "SQLITE_IOERR_SHMLOCK"; break; + case SQLITE_IOERR_SHMMAP: errStr << "SQLITE_IOERR_SHMMAP"; break; + case SQLITE_IOERR_SEEK: errStr << "SQLITE_IOERR_SEEK"; break; + case SQLITE_LOCKED_SHAREDCACHE: errStr << "SQLITE_LOCKED_SHAREDCACHE"; break; + case SQLITE_BUSY_RECOVERY: errStr << "SQLITE_BUSY_RECOVERY"; break; + case SQLITE_CANTOPEN_NOTEMPDIR: errStr << "SQLITE_CANTOPEN_NOTEMPDIR"; break; + case SQLITE_CANTOPEN_ISDIR: errStr << "SQLITE_CANTOPEN_ISDIR"; break; + case SQLITE_CORRUPT_VTAB: errStr << "SQLITE_CORRUPT_VTAB"; break; + case SQLITE_READONLY_RECOVERY: errStr << "SQLITE_READONLY_RECOVERY"; break; + case SQLITE_READONLY_CANTLOCK: errStr << "SQLITE_READONLY_CANTLOCK"; break; + case SQLITE_ABORT_ROLLBACK: errStr << "SQLITE_ABORT_ROLLBACK"; break; + default: errStr << "UNK"; break; + } + errStr << ", Desc: " << sqlite3_errmsg(sqlite3Db) << "\n"; + return errStr.str(); + } +} + +//===================================================================================== +SQLiteDataBaseReadUtil::SQLiteDataBaseReadUtil() + : textureSetSelectCommand_(""), + tsInsertFileIdData_(2), + tsInsertSetTextureSetName_(1), + tsInsertSetIdRasterFormat_(2), + tsInsertSetIdPixelLength_(3), + tsInsertSetIdShallowestLevel_(4), + tsInsertSetIdDeepestLevel_(5), + tsInsertSetIdExtents_(6), + tsInsertSetIdSource_(7), + tsInsertSetIdClassification_(8), + tsInsertSetIdDescription_(9), + tsInsertSetIdTimeSpecified_(10), + tsInsertSetIdTimeValue_(11) +{ + QSNodeId nodeID; + sizeOfIdBlob_ = sizeof(FaceIndexType) + nodeID.SizeOf(); + + // Creates the command for reading an image from a "texture set" table + textureSetSelectFileCommand1_ = "SELECT * From \""; + textureSetSelectFileCommand2_ = "\" WHERE "; + textureSetSelectFileCommand2_.append(QS_TO_ID); + textureSetSelectFileCommand2_.append("=?"); + + // Creates the command for select a texture set row from a "list of texture sets" table + textureSetSelectCommand_ = "SELECT * From "; + textureSetSelectCommand_.append(QS_LIST_OF_TEXTURE_SETS_TABLE_NAME); + textureSetSelectCommand_.append(" WHERE "); + textureSetSelectCommand_.append(QS_TSO_NAME_OF_TEXTURE_SET_TABLE); + textureSetSelectCommand_.append("=?"); +} + +//------------------------------------------------------------------------------------- +SQLiteDataBaseReadUtil::~SQLiteDataBaseReadUtil() +{ +} + +//------------------------------------------------------------------------------------- +QsErrorType SQLiteDataBaseReadUtil::OpenDataBaseFile(const std::string& dbFileName, + sqlite3** sqlite3Db, + const int& flags) const +{ + if (dbFileName.empty() || (sqlite3Db == NULL)) + return QS_IS_UNABLE_TO_OPEN_DB; + + // Attempts to open the database file + int errorCode = sqlite3_open_v2(dbFileName.c_str(), sqlite3Db, flags, NULL); + if ((*sqlite3Db == 0) || (errorCode != SQLITE_OK)) + { + if ((errorCode == SQLITE_BUSY) || + (errorCode == SQLITE_LOCKED)) + return QS_IS_BUSY; + std::cerr << "OpenDataBaseFile sqlite3_open_v2 Error: " << dbFileName << "\n" << printExtendedErrorMessage(*sqlite3Db); + return QS_IS_UNABLE_TO_OPEN_DB; + } + if (sqlite3_exec(*sqlite3Db, "PRAGMA CACHE_SIZE=100;", NULL, NULL, NULL) != SQLITE_OK) + { + std::cerr << "Unable to set SQLite cache size " << dbFileName << "\n"; + std::cerr << printExtendedErrorMessage(*sqlite3Db); + } + + return QS_IS_OK; +} + +//------------------------------------------------------------------------------------- +QsErrorType SQLiteDataBaseReadUtil::TsReadDataBuffer(sqlite3* sqlite3Db, + const std::string& dbFileName, + const std::string& dataTableName, + const FaceIndexType& faceIndex, + const QSNodeId& nodeID, + TextureDataType** buffer, + uint32_t* bufferSize, + uint32_t* currentRasterSize, + bool allowLocalDB, + bool displayErrorMessage) const +{ + int returnValue; + + if ((buffer == NULL) || (bufferSize == NULL) || (currentRasterSize == NULL)) + return QS_IS_UNEXPECTED_NULL; + + *currentRasterSize = 0; + + if (dataTableName.empty() || dbFileName.empty()) + return QS_IS_EMPTY_TABLE_NAME; + + // opens the database + bool localDb = false; + QsErrorType tmpReturnValue; + if (sqlite3Db == NULL) + { + if (allowLocalDB == false) + return QS_IS_DB_NOT_INITIALIZED; + localDb = true; + tmpReturnValue = OpenDataBaseFile(dbFileName, &sqlite3Db, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX); + if (tmpReturnValue != QS_IS_OK) + return tmpReturnValue; + } + + std::string sqlCommand; + sqlCommand = textureSetSelectFileCommand1_; + sqlCommand.append(dataTableName); + sqlCommand.append(textureSetSelectFileCommand2_); + + // prepares the statement + sqlite3_stmt* stmt = 0; + returnValue = sqlite3_prepare_v2(sqlite3Db, sqlCommand.c_str(), static_cast(sqlCommand.length()), &stmt, NULL); + if (returnValue != SQLITE_OK) + { + if (displayErrorMessage && (returnValue != SQLITE_BUSY && returnValue != SQLITE_LOCKED)) + { + std::cerr << "TsReadDataBuffer sqlite3_prepare_v2 Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); + } + if (stmt != NULL) sqlite3_finalize(stmt); + if (localDb) sqlite3_close(sqlite3Db); + if ((returnValue == SQLITE_BUSY) || + (returnValue == SQLITE_LOCKED)) + return QS_IS_BUSY; + return QS_IS_PREPARE_ERROR; + } + + // binds id + uint8_t* idBlob = new uint8_t[sizeOfIdBlob_]; + bewrite(idBlob, &faceIndex); + nodeID.Pack(idBlob + sizeof(FaceIndexType)); + returnValue = sqlite3_bind_blob(stmt, 1, idBlob, sizeOfIdBlob_, SQLITE_TRANSIENT); + if (returnValue != SQLITE_OK && displayErrorMessage) + { + std::cerr << "TsReadDataBuffer sqlite3_bind_blob Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); + } + delete[] idBlob; + + // executes the statement + returnValue = sqlite3_step(stmt); + QsErrorType otherReturnValue = QS_IS_UNABLE_TO_READ_DATA_BUFFER; + if ((returnValue == SQLITE_ROW) || (returnValue == SQLITE_DONE)) + { + // gets the data + *currentRasterSize = sqlite3_column_bytes(stmt, tsInsertFileIdData_ - 1); + if ((*currentRasterSize > 0) && (*currentRasterSize <= static_cast(gMaxBufferSize))) + { + if (*currentRasterSize > (*bufferSize)) + { + if ((*buffer) != NULL) + delete[] * buffer; + *buffer = new uint8_t[*currentRasterSize]; + *bufferSize = (*currentRasterSize); + } + memcpy(*buffer, (const uint8_t*)sqlite3_column_blob(stmt, tsInsertFileIdData_ - 1), *currentRasterSize); + } + otherReturnValue = QS_IS_OK; + } + else if ((returnValue == SQLITE_BUSY) || (returnValue == SQLITE_LOCKED)) + { + otherReturnValue = QS_IS_BUSY; + } + else + { + if (displayErrorMessage) + { + std::cerr << "TsReadDataBuffer sqlite3_step Error(" << returnValue << "): " << dbFileName << "\n"; + std::cerr << "not done (" << nodeID.FormatAsHex().c_str() << ") " << printExtendedErrorMessage(sqlite3Db); + } + otherReturnValue = QS_IS_UNABLE_TO_READ_DATA_BUFFER; + } + + if (stmt != NULL) sqlite3_finalize(stmt); + if (localDb) + { + returnValue = sqlite3_close(sqlite3Db); + if (returnValue != SQLITE_OK && displayErrorMessage) + { + std::cerr << "TsReadDataBuffer localDb sqlite3_close Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); + } + } + return otherReturnValue; +} + +//------------------------------------------------------------------------------------- +QsErrorType SQLiteDataBaseReadUtil::TsGetSetFromListOfSetsTable(sqlite3* sqlite3Db, + const std::string& tableName, + int& rasterFormat, + int& pixelLength, + int& shallowLevel, + int& deepLevel, + PosXPosYExtents tmpExtents[6], + std::string& source, + std::string& classification, + std::string& description, + bool& timeSpecified, + simCore::TimeStamp& timeStamp) const +{ + if (sqlite3Db == NULL) + return QS_IS_DB_NOT_INITIALIZED; + if (tableName.empty()) + return QS_IS_EMPTY_TABLE_NAME; + + int returnValue; + QsErrorType otherReturnValue; + + // prepares the statement + sqlite3_stmt* stmt = 0; + returnValue = sqlite3_prepare_v2(sqlite3Db, textureSetSelectCommand_.c_str(), static_cast(textureSetSelectCommand_.length()), &stmt, NULL); + if (returnValue != SQLITE_OK) + { + std::cerr << "TsGetSetFromListOfSetsTable sqlite3_prepare_v2 Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); + if (stmt != NULL) sqlite3_finalize(stmt); + return QS_IS_PREPARE_ERROR; + } + + // binds the texture set name + returnValue = sqlite3_bind_text(stmt, 1, tableName.c_str(), int(tableName.length()), SQLITE_TRANSIENT); + if (returnValue != SQLITE_OK) + { + std::cerr << "TsGetSetFromListOfSetsTable sqlite3_bind_text Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); + } + + // executes the statement + returnValue = sqlite3_step(stmt); + if (returnValue > SQLITE_OK&& returnValue < SQLITE_ROW) + { + std::cerr << "TsGetSetFromListOfSetsTable sqlite3_step Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); + } + + if (returnValue == SQLITE_ROW) + { + // sets some texture set creation options + rasterFormat = sqlite3_column_int(stmt, tsInsertSetIdRasterFormat_ - 1); + pixelLength = sqlite3_column_int(stmt, tsInsertSetIdPixelLength_ - 1); + shallowLevel = sqlite3_column_int(stmt, tsInsertSetIdShallowestLevel_ - 1); + deepLevel = sqlite3_column_int(stmt, tsInsertSetIdDeepestLevel_ - 1); + UnPackArray(tmpExtents, (const uint8_t*)sqlite3_column_blob(stmt, tsInsertSetIdExtents_ - 1), 6); + source = (const char*)sqlite3_column_text(stmt, tsInsertSetIdSource_ - 1); + classification = (const char*)sqlite3_column_text(stmt, tsInsertSetIdClassification_ - 1); + description = (const char*)sqlite3_column_text(stmt, tsInsertSetIdDescription_ - 1); + timeSpecified = (sqlite3_column_int(stmt, tsInsertSetIdTimeSpecified_ - 1) != 0); + + if (timeSpecified) + { + const uint8_t* buffer = (const uint8_t*)sqlite3_column_blob(stmt, tsInsertSetIdTimeValue_ - 1); + int refYear = 0; + int secs = 0; + int frac = 0; + + // read TimeStamp data members from buffer + beread(buffer, &refYear); + beread(buffer + sizeof(refYear), &(secs)); + beread(buffer + sizeof(refYear) + sizeof(secs), &(frac)); + simCore::Seconds secsSinceRefYear(secs, frac); + timeStamp.setTime(refYear, secsSinceRefYear); + } + otherReturnValue = QS_IS_OK; + } + else if (returnValue == SQLITE_BUSY) + { + otherReturnValue = QS_IS_BUSY; + } + else + { + otherReturnValue = QS_IS_TS_NOT_FOUND; + } + + if (stmt != NULL) sqlite3_finalize(stmt); + return otherReturnValue; +} + +} diff --git a/SDK/simVis/DB/SQLiteDataBaseReadUtil.h b/SDK/simVis/DB/SQLiteDataBaseReadUtil.h new file mode 100644 index 000000000..db708e850 --- /dev/null +++ b/SDK/simVis/DB/SQLiteDataBaseReadUtil.h @@ -0,0 +1,162 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#ifndef SQLITE_DATABASE_READ_UTIL_H +#define SQLITE_DATABASE_READ_UTIL_H + +#include +#include "sqlite3.h" +#include "simCore/Time/TimeClass.h" +#include "QSCommon.h" +#include "QSError.h" +#include "QSNodeID96.h" +#include "QSPosXYExtents.h" + +// Temporary defines until we update sqlite +#ifndef SQLITE_OPEN_READONLY +#define SQLITE_OPEN_READONLY 0x00000001 +#define SQLITE_OPEN_READWRITE 0x00000002 +#define SQLITE_OPEN_CREATE 0x00000004 +#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 +#define SQLITE_OPEN_EXCLUSIVE 0x00000010 +#define SQLITE_OPEN_MAIN_DB 0x00000100 +#define SQLITE_OPEN_TEMP_DB 0x00000200 +#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 +#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 +#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 +#define SQLITE_OPEN_SUBJOURNAL 0x00002000 +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 +#define SQLITE_OPEN_NOMUTEX 0x00008000 +#define SQLITE_OPEN_FULLMUTEX 0x00010000 +#endif /* SQLITE_OPEN_READONLY */ + +namespace simVis_db +{ + static const char* QS_TO_ID = "id"; + + //===================================================================================== + static const char* QS_DEFAULT_SET_TABLE_NAME = "default"; + static const char* SPLITTER_STRING_OUTPUTDB = "dbFile"; + static const char* SIMQS_CONFIG_TABLENAME_KEYWORD = "tableName"; + static const char* QS_LIST_OF_TEXTURE_SETS_TABLE_NAME = "ListOfTextureSets"; + static const char* QS_TSO_NAME_OF_TEXTURE_SET_TABLE = "nt"; + static const char* QS_TSO_OUTPUT_TYPE = "ot"; + static const char* QS_TSO_PIXEL_LENGTH = "pl"; + static const char* QS_TSO_SHALLOWEST_LEVEL = "sl"; + static const char* QS_TSO_DEEPEST_LEVEL = "dl"; + static const char* QS_TSO_EXTENTS = "ex"; + static const char* QS_TSO_SOURCE = "s"; + static const char* QS_TSO_CLASSIFICATION = "c"; + static const char* QS_TSO_DESCRIPTION = "ds"; + static const char* QS_TSO_TIME_SPECIFIED = "ts"; + + //===================================================================================== + class SQLiteDataBaseReadUtil + { + public: + SQLiteDataBaseReadUtil(); + virtual ~SQLiteDataBaseReadUtil(); + + /** Opens a database file */ + QsErrorType OpenDataBaseFile(const std::string& dbFileName, + sqlite3** sqlite3Db, + const int& flags) const; + + /** + * Gets TextureSet information about a data table + * @param[in] sqlite3Db Pointer to a SQLite database object + * @param[in] tableName Name of the table to access within the given database + * The following are TextureSet creation options + * @param[out] rasterFormat Flag that determines how the texture image is drawn + * @param[out] pixelLength Tile size of the TextureSet + * @param[out] shallowLevel Minimum depth of the TextureSet + * @param[out] deepLevel Maximum depth of the TextureSet + * @param[out] tmpExtents Stores the TextureSet's X/Y extent values + * @param[out] source Name of the TextureSet's source file + * @param[out] classification Classification information of the loaded TextureSet + * @param[out] description Description of the loaded TextureSet + * @param[out] timeSpecified Whether or not a valid timeStamp was specified for the source file + * @param[out] timeStamp Loads a time value, if there is a valid timeStamp on the file + * @return Returns 0 on success, otherwise returns an error value mapped to QsErrorType. + */ + QsErrorType TsGetSetFromListOfSetsTable(sqlite3* sqlite3Db, + const std::string& tableName, + int& rasterFormat, + int& pixelLength, + int& shallowLevel, + int& deepLevel, + PosXPosYExtents tmpExtents[6], + std::string& source, + std::string& classification, + std::string& description, + bool& timeSpecified, + simCore::TimeStamp& timeStamp) const; + + /** + * Reads a node's data buffer from a sets table; caller is responsible for deleting buffer + * @param[in] sqlite3Db Pointer to a SQLite database object + * @param[in] dbFileName Name of a SQLite database file, used to fetch a database if sqlite3Db == NULL + * @param[in] dataTableName Name of the table to access within the given database + * @param[in] faceIndex Mapping to a face index/orientation, used to create a SQLite idBlob + * @param[in] nodeID Used to fill the idBlob + * @param[out] buffer Destination for data from the SQLite database + * @param[in, out] bufferSize Current max size of the buffer, will be changed if data to be copied is greater than max + * @param[out] currentRasterSize Size (bytes) of the data from the SQLite database + * @param[in] allowLocalDB Determines whether to fall back to a local database pointed to by dbFileName + * @param[in] displayErrorMessage Determines whether to display error messages to console when failing + * @return An error value, mapped to QsErrorType + */ + QsErrorType TsReadDataBuffer(sqlite3* sqlite3Db, + const std::string& dbFileName, + const std::string& dataTableName, + const FaceIndexType& faceIndex, + const QSNodeId& nodeID, + TextureDataType** buffer, + uint32_t* bufferSize, + uint32_t* currentRasterSize, + bool allowLocalDB, + bool displayErrorMessage=false) const; + protected: + int sizeOfIdBlob_; + + std::string textureSetSelectCommand_; + std::string textureSetSelectFileCommand1_; + std::string textureSetSelectFileCommand2_; + + // ids for inserting a "texture set" into a "list of texture sets" table + int tsInsertFileIdData_; + int tsInsertSetTextureSetName_; + int tsInsertSetIdRasterFormat_; + int tsInsertSetIdPixelLength_; + int tsInsertSetIdShallowestLevel_; + int tsInsertSetIdDeepestLevel_; + int tsInsertSetIdExtents_; + int tsInsertSetIdSource_; + int tsInsertSetIdClassification_; + int tsInsertSetIdDescription_; + int tsInsertSetIdTimeSpecified_; + int tsInsertSetIdTimeValue_; + }; + +} // namespace simVis_db + +#endif /* SQLITE_DATABASE_READ_UTIL_H */ diff --git a/SDK/simVis/DB/swapbytes.h b/SDK/simVis/DB/swapbytes.h new file mode 100644 index 000000000..e80d007f4 --- /dev/null +++ b/SDK/simVis/DB/swapbytes.h @@ -0,0 +1,780 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#ifndef SIMUTIL_SWAPBYTES_H +#define SIMUTIL_SWAPBYTES_H + +#include +#include +#include +#include +#include "simCore/Common/Common.h" + +#if !defined(SIM_LITTLE_ENDIAN) && !defined(SIM_BIG_ENDIAN) +#if defined(X86) || defined(ALPHA) || defined(__x86_64__) || defined(_WIN64) || defined(WIN32) +#define SIM_LITTLE_ENDIAN +#endif +#endif + +#ifndef BYTESWAPSHIFT + +namespace simVis_db +{ + template + inline + void swap_bytes(T *const value, const size_t nItems = 1) + { + // using namespace std; + for (size_t i = 0; i < nItems; ++i) + { + char *ptr = (char*)&value[i]; // Treat value as an array of bytes + size_t size = sizeof(T); + size_t halfSize = size >> 1; + size_t end = size - 1; + for (size_t i = 0; i < halfSize; ++i) + std::swap(ptr[end - i], ptr[i]); + } + } + + template + inline + T swap_bytes_return(const T &value, const size_t nItems = 1) + { + T temp = value; + swap_bytes(&temp); + return temp; + } + +#ifdef SIM_LITTLE_ENDIAN + + template + inline + void make_little_endian_(T *const value) + { + } + + template + inline + void make_big_endian_(T *const value) + { + swap_bytes(value); + } + +#else + + template + inline + void make_little_endian_(T *const value) + { + swap_bytes(value); + } + + template + inline + void make_big_endian_(T *const value) + { + } + +#endif + + inline + void make_big_endian(char *const val) { make_big_endian_(val); } + inline + void make_big_endian(int8_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(uint8_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(int16_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(uint16_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(int32_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(uint32_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(int64_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(uint64_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(float *const val) { make_big_endian_(val); } + inline + void make_big_endian(double *const val) { make_big_endian_(val); } + + inline + void make_little_endian(char *const val) { make_little_endian_(val); } + inline + void make_little_endian(int8_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(uint8_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(int16_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(uint16_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(int32_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(uint32_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(int64_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(uint64_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(float *const val) { make_little_endian_(val); } + inline + void make_little_endian(double *const val) { make_little_endian_(val); } + + template + inline + void make_big_endian(T *const value, const size_t nItems) + { + for (size_t i = 0; i < nItems; ++i) + { + make_big_endian(&value[i]); + } + } + + template + inline + void make_little_endian(T *const value, const size_t nItems) + { + for (size_t i = 0; i < nItems; ++i) + { + make_little_endian(&value[i]); + } + } + + template + inline + size_t beread(FILE *stream, T *const val, const size_t nItems = 1) + { + size_t nItemsRead = fread(val, sizeof(T), nItems, stream); + make_big_endian(val, nItemsRead); + return nItemsRead; + } + + template + inline + size_t bewrite(FILE *stream, const T *const val, const size_t nItems = 1) + { + size_t nItemsWrote = 0; + for (size_t i = 0; i < nItems; ++i) + { + T temp = val[i]; + make_big_endian(&temp); + if (fwrite(&temp, sizeof(T), 1, stream) != 1) + break; + ++nItemsWrote; + } + return nItemsWrote; + } + + template + inline + size_t leread(FILE *stream, T *const val, const size_t nItems = 1) + { + size_t nItemsRead = fread(val, sizeof(T), nItems, stream); + make_little_endian(val, nItemsRead); + return nItemsRead; + } + + template + inline + size_t lewrite(FILE *stream, const T *const val, const size_t nItems = 1) + { + size_t nItemsWrote = 0; + for (size_t i = 0; i < nItems; ++i) + { + T temp = val[i]; + make_little_endian(&temp); + if (fwrite(&temp, sizeof(T), 1, stream) != 1) + break; + ++nItemsWrote; + } + return nItemsWrote; + } + + template + inline + size_t beread(std::istream &stream, T *const val, const std::streamsize nItems = 1) + { + stream.read((char *)val, nItems * sizeof(T)); + size_t nItemsRead = stream.gcount() / sizeof(T); + make_big_endian(val, nItemsRead); + return nItemsRead; + } + + template + inline + size_t bewrite(std::ostream &stream, const T *const val, const size_t nItems = 1) + { + size_t nItemsWrote = 0; + for (size_t i = 0; i < nItems; ++i) + { + T temp = val[i]; + make_big_endian(&temp); + stream.write((const char *)&temp, sizeof(T)); + if (stream.bad()) + break; + ++nItemsWrote; + } + return nItemsWrote; + } + + template + inline + size_t leread(std::istream &stream, T *const val, const size_t nItems = 1) + { + stream.read((char *)val, nItems * sizeof(T)); + size_t nItemsRead = stream.gcount() / sizeof(T); + make_little_endian(val, nItemsRead); + return nItemsRead; + } + + template + inline + size_t lewrite(std::ostream &stream, const T *const val, const size_t nItems = 1) + { + size_t nItemsWrote = 0; + for (size_t i = 0; i < nItems; ++i) + { + T temp = val[i]; + make_little_endian(&temp); + stream.write((const char *)&temp, sizeof(T)); + if (stream.bad()) + break; + ++nItemsWrote; + } + return nItemsWrote; + } + + template + inline + size_t beread(const void *const stream, T *const val, const size_t nItems = 1) + { + memcpy(val, stream, nItems * sizeof(T)); + make_big_endian(val, nItems); + return nItems; + } + + template + inline + size_t bewrite(void *const stream, const T *const val, const size_t nItems = 1) + { + memcpy(stream, val, nItems * sizeof(T)); + make_big_endian((T *)stream, nItems); + return nItems; + } + + template + inline + size_t leread(const void *const stream, T *const val, const size_t nItems = 1) + { + memcpy(val, stream, nItems * sizeof(T)); + make_little_endian(val, nItems); + return nItems; + } + + template + inline + size_t lewrite(void *const stream, const T *const val, const size_t nItems = 1) + { + memcpy(stream, val, nItems * sizeof(T)); + make_little_endian((T *)stream, nItems); + return nItems; + } + +#else + +// Swap macros. +#define SWAP16(val)((((val)>>8)&0xff)|(((val)<<8)&0xff00)) +#define SWAP32(val)((((val)>>24)&0xff)|(((val)>>8)&0xff00)|(((val)<<8)&0xff0000)|(((val)<<24)&0xff000000)) +#ifdef __GNUC__ +#define SWAP64(val)((((val)>>56)&0xffLL)|(((val)>>40)&0xff00LL)|(((val)>>24)&0xff0000LL)|(((val)>>8)&0xff000000LL)| \ + (((val)<<8)&0xff00000000LL)|(((val)<<24)&0xff0000000000LL)|(((val)<<40)&0xff000000000000LL)|(((val)<<56)&0xff00000000000000LL)) +#else +#define SWAP64(val)((((val)>>56)&0xffL)|(((val)>>40)&0xff00L)|(((val)>>24)&0xff0000L)|(((val)>>8)&0xff000000L)| \ + (((val)<<8)&0xff00000000L)|(((val)<<24)&0xff0000000000L)|(((val)<<40)&0xff000000000000L)|(((val)<<56)&0xff00000000000000L)) +#endif + + // Generic byte swapping routines. + template inline void swap_bytes(T *const value) + { + char *ptr=(char*)(void*)value; // Treat value as an array of bytes + size_t size = sizeof(T); + register size_t halfSize = size >> 1; + register size_t end = size - 1; + for (register size_t i = 0; i < halfSize; ++i) + std::swap(ptr[end - i], ptr[i]); + } + + template inline void swap_bytes(T *const value, register const size_t nItems) + { + for (register size_t i=0;i> 1; + register size_t end = size - 1; + for (register size_t i = 0; i < halfSize; ++i) + std::swap(ptr[end - i], ptr[i]); + } + } + + + // Specialized routines. + + // NULL routines. + template<> inline void swap_bytes(char *const value) {} + template<> inline void swap_bytes(char *const value, register const size_t nItems) {} + template<> inline void swap_bytes(int8_t *const value) {} + template<> inline void swap_bytes(uint8_t *const value) {} + template<> inline void swap_bytes(int8_t *const value, register const size_t nItems) {} + template<> inline void swap_bytes(uint8_t *const value, register const size_t nItems) {} + + // Single item routines. + template<> inline void swap_bytes(int16_t *const value) { *value=SWAP16(*value); } + template<> inline void swap_bytes(uint16_t *const value) { *value=SWAP16(*value); } + template<> inline void swap_bytes(int32_t *const value) { *value=SWAP32(*value); } + template<> inline void swap_bytes(uint32_t *const value) { *value=SWAP32(*value); } + template<> inline void swap_bytes(int64_t *const value) { *value=SWAP64(*value); } + template<> inline void swap_bytes(uint64_t *const value) { *value=SWAP64(*value); } + + template<> inline void swap_bytes(float *const value) + { + int32_t *const pseudo=(int32_t*)(void*)value; + *pseudo=SWAP32(*pseudo); + } + + template<> inline void swap_bytes(double *const value) + { + int64_t *const pseudo=(int64_t*)(void*)value; + *pseudo=SWAP64(*pseudo); + } + + #ifdef SIM_LITTLE_ENDIAN + template inline void make_little_endian(T *const value) {} + + // Generic swap. Has a '_' prefix to prevent it from accidently being used with structs, etc. + template inline void make_little_endian_(T *const value) {} + template inline void make_big_endian_(T *const value) { swap_bytes(value); } + + inline void make_big_endian(char *const value) {} + inline void make_big_endian(int8_t *const value) {} + inline void make_big_endian(uint8_t *const value) {} + inline void make_big_endian(int16_t *const value) { *value=SWAP16(*value); } + inline void make_big_endian(uint16_t *const value) { *value=SWAP16(*value); } + inline void make_big_endian(int32_t *const value) { *value=SWAP32(*value); } + inline void make_big_endian(uint32_t *const value) { *value=SWAP32(*value); } + inline void make_big_endian(int64_t *const value) { *value=SWAP64(*value); } + inline void make_big_endian(uint64_t *const value) { *value=SWAP64(*value); } + + inline void make_big_endian(float *const value) + { + int32_t *const pseudo=(int32_t*)(void*)value; + *pseudo=SWAP32(*pseudo); + } + + inline void make_big_endian(double *const value) + { + int64_t *const pseudo=(int64_t*)(void*)value; + *pseudo=SWAP64(*pseudo); + } +#else + template inline void make_big_endian(T *const value) {} + template inline void make_big_endian_(T *const value) {} + template inline void make_little_endian_(T *const value) { swap_bytes(value); } + + inline void make_little_endian(char *const value) {} + inline void make_little_endian(int8_t *const value) {} + inline void make_little_endian(uint8_t *const value) {} + inline void make_little_endian(int16_t *const value) { *value=SWAP16(*value); } + inline void make_little_endian(uint16_t *const value) { *value=SWAP16(*value); } + inline void make_little_endian(int32_t *const value) { *value=SWAP32(*value); } + inline void make_little_endian(uint32_t *const value) { *value=SWAP32(*value); } + inline void make_little_endian(int64_t *const value) { *value=SWAP64(*value); } + inline void make_little_endian(uint64_t *const value) { *value=SWAP64(*value); } + + inline void make_little_endian(float *const value) + { + int32_t *const pseudo=(int32_t*)(void*)value; + *pseudo=SWAP32(*pseudo); + } + + inline void make_little_endian(double *const value) + { + int64_t *const pseudo=(int64_t*)(void*)value; + *pseudo=SWAP64(*pseudo); + } +#endif + + // Multi item routines. + template<> inline void swap_bytes(int16_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); + } + + template<> inline void swap_bytes(uint16_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); + } + + template<> inline void swap_bytes(int32_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); + } + + template<> inline void swap_bytes(uint32_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); + } + + template<> inline void swap_bytes(int64_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); + } + + template<> inline void swap_bytes(uint64_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); + } + + template<> inline void swap_bytes(float *const value, register const size_t nItems) + { + int32_t *const pseudo=(int32_t*)(void*)value; + for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP32(pseudo[i]); + } + + template<> inline void swap_bytes(double *const value, register const size_t nItems) + { + int64_t *const pseudo=(int64_t*)(void*)value; + for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP64(pseudo[i]); + } + +#ifdef SIM_LITTLE_ENDIAN + template inline void make_little_endian(T *const value, register const size_t nItems) {} + template inline void make_little_endian_(T *const value, register const size_t nItems) {} + template inline void make_big_endian_(T *const value, register const size_t nItems) { swap_bytes(value, nItems); } + + inline void make_big_endian(char *const value, register const size_t nItems) {} + inline void make_big_endian(int8_t *const value, register const size_t nItems) {} + inline void make_big_endian(uint8_t *const value, register const size_t nItems) {} + + inline void make_big_endian(int16_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); + } + + inline void make_big_endian(uint16_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); + } + + inline void make_big_endian(int32_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); + } + + inline void make_big_endian(uint32_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); + } + + inline void make_big_endian(int64_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); + } + + inline void make_big_endian(uint64_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); + } + + inline void make_big_endian(float *const value, register const size_t nItems) + { + int32_t *const pseudo = (int32_t*)(void*)value; + for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP32(pseudo[i]); + } + + inline void make_big_endian(double *const value, register const size_t nItems) + { + int64_t *const pseudo = (int64_t*)(void*)value; + for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP64(pseudo[i]); + } +#else + template inline void make_big_endian(T *const value, register const size_t nItems) {} + template inline void make_big_endian_(T *const value, register const size_t nItems) {} + template inline void make_little_endian_(T *const value, register const size_t nItems) { swap_bytes(value, nItems); } + + inline void make_little_endian(char *const value, register const size_t nItems) {} + inline void make_little_endian(int8_t *const value, register const size_t nItems) {} + inline void make_little_endian(uint8_t *const value, register const size_t nItems) {} + + inline void make_little_endian(int16_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); + } + + inline void make_little_endian(uint16_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); + } + + inline void make_little_endian(int32_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); + } + + inline void make_little_endian(uint32_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); + } + + inline void make_little_endian(int64_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); + } + + inline void make_little_endian(uint64_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); + } + + inline void make_little_endian(float *const value, register const size_t nItems) + { + int32_t *const pseudo = (int32_t*)(void*)value; + for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP32(pseudo[i]); + } + + inline void make_little_endian(double *const value, register const size_t nItems) + { + int64_t *const pseudo = (int64_t*)(void*)value; + for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP64(pseudo[i]); + } + #endif + + + // Swapped I\O + template inline size_t beread(FILE *stream, T *const val) + { + size_t nItemsRead = fread(val, sizeof(T), 1, stream); + make_big_endian(val); + return nItemsRead; + } + + template inline size_t beread(FILE *stream, T *const val, register const size_t nItems) + { + size_t nItemsRead = fread(val, sizeof(T), nItems, stream); + make_big_endian(val, nItemsRead); + return nItemsRead; + } + + template inline size_t bewrite(FILE *stream, const T *const val) + { + T temp = *val; + make_big_endian(&temp); + return fwrite(&temp, sizeof(T), 1, stream); + } + + template inline size_t bewrite(FILE *stream, const T *const val, register const size_t nItems) + { + register size_t nItemsWrit = 0; + while (nItemsWrit < nItems) + { + T temp = val[nItemsWrit++]; + make_big_endian(&temp); + if (fwrite(&temp, sizeof(T), 1, stream)!=1) + break; + } + return nItemsWrit; + } + + template inline size_t leread(FILE *stream, T *const val) + { + size_t nItemsRead = fread(val, sizeof(T), 1, stream); + make_little_endian(val); + return nItemsRead; + } + + template inline size_t leread(FILE *stream, T *const val, register const size_t nItems) + { + size_t nItemsRead = fread(val, sizeof(T), nItems, stream); + make_little_endian(val, nItemsRead); + return nItemsRead; + } + + template inline size_t lewrite(FILE *stream, const T *const val) + { + T temp = *val; + make_little_endian(&temp); + return fwrite(&temp, sizeof(T), 1, stream); + } + + template inline size_t lewrite(FILE *stream, const T *const val, register const size_t nItems) + { + register size_t nItemsWrit = 0; + while (nItemsWrit < nItems) + { + T temp = val[nItemsWrit++]; + make_little_endian(&temp); + if (fwrite(&temp, sizeof(T), 1, stream) != 1) + break; + } + return nItemsWrit; + } + + template inline size_t beread(std::istream &stream, T *const val) + { + stream.read((char *)val, sizeof(T)); + size_t nItemsRead = stream.gcount() / sizeof(T); + make_big_endian(val); + return nItemsRead; + } + + template inline size_t beread(std::istream &stream, T *const val, register const size_t nItems) + { + stream.read((char *)val, nItems * sizeof(T)); + size_t nItemsRead = stream.gcount() / sizeof(T); + make_big_endian(val, nItemsRead); + return nItemsRead; + } + + template inline size_t bewrite(std::ostream &stream, const T *const val) + { + T temp = *val; + make_big_endian(&temp); + stream.write((const char *)&temp, sizeof(T)); + return (stream.bad()) ? 0 : 1; + } + + template inline size_t bewrite(std::ostream &stream, const T *const val, register const size_t nItems) + { + register size_t nItemsWrit = 0; + while (nItemsWrit < nItems) + { + T temp = val[nItemsWrit++]; + make_big_endian(&temp); + stream.write((const char *)&temp, sizeof(T)); + if (stream.bad()) + break; + } + return nItemsWrit; + } + + template inline size_t leread(std::istream &stream, T *const val) + { + stream.read((char *)val, sizeof(T)); + size_t nItemsRead = stream.gcount()/sizeof(T); + make_little_endian(val); + return nItemsRead; + } + + template inline size_t leread(std::istream &stream, T *const val, register const size_t nItems) + { + stream.read((char *)val, nItems * sizeof(T)); + size_t nItemsRead = stream.gcount() / sizeof(T); + make_little_endian(val, nItemsRead); + return nItemsRead; + } + + template inline size_t lewrite(std::ostream &stream, const T *const val) + { + T temp = *val; + make_little_endian(&temp); + stream.write((const char *)&temp, sizeof(T)); + return (stream.bad()) ? 0 : 1; + } + + template inline size_t lewrite(std::ostream &stream, const T *const val, register const size_t nItems) + { + size_t nItemsWrit = 0; + while (nItemsWrit < nItems) + { + T temp = val[nItemsWrit++]; + make_little_endian(&temp); + stream.write((const char *)&temp, sizeof(T)); + if (stream.bad()) + break; + } + return nItemsWrit; + } + + template inline size_t beread(const void *const stream, T *const val) + { + memcpy(val, stream, sizeof(T)); + make_big_endian(val); + return 1; + } + + template inline size_t beread(const void *const stream, T *const val, register const size_t nItems) + { + memcpy(val, stream, nItems * sizeof(T)); + make_big_endian(val, nItems); + return nItems; + } + + template inline size_t bewrite(void *const stream, const T *const val) + { + memcpy(stream, val, sizeof(T)); + make_big_endian((T *)stream); + return 1; + } + + template inline size_t bewrite(void *const stream, const T *const val, register const size_t nItems) + { + memcpy(stream, val, nItems * sizeof(T)); + make_big_endian((T *)stream, nItems); + return nItems; + } + + template inline size_t leread(const void *const stream, T *const val) + { + memcpy(val, stream, sizeof(T)); + make_little_endian(val); + return 1; + } + + template inline size_t leread(const void *const stream, T *const val, register const size_t nItems) + { + memcpy(val, stream, nItems * sizeof(T)); + make_little_endian(val, nItems); + return nItems; + } + + template inline size_t lewrite(void *const stream, const T *const val) + { + memcpy(stream, val, sizeof(T)); + make_little_endian((T *)stream); + return 1; + } + + template inline size_t lewrite(void *const stream, const T *const val, register const size_t nItems) + { + memcpy(stream, val, nItems * sizeof(T)); + make_little_endian((T *)stream, nItems); + return nItems; + } + +#endif + +} // namespace simVis_db + +#endif /* SIMUTIL_SWAPBYTES_H */ diff --git a/SDK/simVis/DBFormat.cpp b/SDK/simVis/DBFormat.cpp index 04c2fd7e5..001c0f39c 100644 --- a/SDK/simVis/DBFormat.cpp +++ b/SDK/simVis/DBFormat.cpp @@ -21,109 +21,828 @@ */ #include "osgDB/FileUtils" #include "simVis/DBFormat.h" +#include "simVis/DB/QSCommon.h" +#include "simVis/DB/swapbytes.h" +#include "simVis/DB/SQLiteDataBaseReadUtil.h" +#include "simCore/Calc/Math.h" +#include "osgEarth/Cube" +#include "osgEarth/ImageToHeightFieldConverter" using namespace simVis; +using namespace simVis_db; + +//........................................................... + +namespace +{ + bool convertTileKeyToQsKey(const osgEarth::TileKey& key, FaceIndexType& out_faceIndex, QSNodeId& out_nodeId, + osg::Vec2d& out_fmin, osg::Vec2d& out_fmax) + { + QSNodeId zero(0); + QSNodeId one(1); + + const unsigned int maxLevel = key.getLevelOfDetail(); + + QSNodeId nodeId; + + osgEarth::TileKey pkey = key; + + for (unsigned int i = 0; i < maxLevel; ++i) + { + const unsigned int plevel = pkey.getLevelOfDetail(); + const unsigned int level = plevel * 3; + const QSNodeId bit0 = one << level; + const QSNodeId bit1 = one << (level + 1); + const QSNodeId bit2 = one << (level + 2); + + unsigned int tx, ty; + pkey.getTileXY(tx, ty); + + const int xoff = ((tx % 2) == 0) ? 0 : 1; + const int yoff = ((ty % 2) == 0) ? 0 : 1; + + if (xoff == 0 && yoff == 0) + { + nodeId |= bit1; + } + else if (xoff == 1 && yoff == 0) + { + nodeId |= bit0; + } + else if (xoff == 0 && yoff == 1) + { + nodeId |= bit0; + nodeId |= bit1; + } + else if (xoff == 1 && yoff == 1) + { + nodeId |= bit2; + } + + pkey = pkey.createParentKey(); + } + + out_faceIndex = osgEarth::Contrib::UnifiedCubeProfile::getFace(key); + out_nodeId = nodeId; + + double xMin = key.getExtent().xMin(); + double yMin = key.getExtent().yMin(); + double xMax = key.getExtent().xMax(); + double yMax = key.getExtent().yMax(); + int face; + + osgEarth::Contrib::CubeUtils::cubeToFace(xMin, yMin, xMax, yMax, face); + + out_fmin.set(xMin * gQsDMaxLength, yMin * gQsDMaxLength); + out_fmax.set(xMax * gQsDMaxLength, yMax * gQsDMaxLength); + + return true; + } + + bool decompressZLIB(const char* input, int inputLen, std::string& output) + { + osgDB::BaseCompressor* comp = osgDB::Registry::instance()->getObjectWrapperManager()->findCompressor("zlib"); + std::string inString(input, inputLen); + std::istringstream inStream(inString); + return comp->decompress(inStream, output); + } + + // Uses one of OSG's native ReaderWriter's to read image data from a buffer. + bool readNativeImage(osgDB::ReaderWriter* reader, const char* inBuf, int inBufLen, osg::ref_ptr& outImage) + { + std::string inString(inBuf, inBufLen); + std::istringstream inStream(inString); + osgDB::ReaderWriter::ReadResult result = reader->readImage(inStream); + outImage = result.getImage(); + if (result.error() || !outImage.valid()) + { + return false; + } + else + return true; + } + + struct DBContext + { + DBContext() + { + rasterFormat_ = SPLIT_UNKNOWN; + pixelLength_ = 128; + shallowLevel_ = 0; + deepLevel_ = 32; + timeSpecified_ = false; + timeStamp_ = simCore::INFINITE_TIME_STAMP; + } + + int rasterFormat_; + int pixelLength_; + int shallowLevel_; + int deepLevel_; + bool timeSpecified_; + simCore::TimeStamp timeStamp_; + + std::string pathname_; + sqlite3* db_; + SQLiteDataBaseReadUtil dbUtil_; + PosXPosYExtents extents_[6]; + std::string source_; + std::string classification_; + std::string description_; + + osg::ref_ptr pngReader_; + osg::ref_ptr jpgReader_; + osg::ref_ptr tifReader_; + osg::ref_ptr rgbReader_; + + template + void makeImage(int size, GLenum internalFormat, GLenum pixelFormat, GLenum type, + std::string& buf, osg::ref_ptr& outImage) + { + unsigned char* data = new unsigned char[buf.length()]; + std::copy(buf.begin(), buf.end(), data); + + // Be sure to cast here to get the right swap function: + make_big_endian((T*)data, size * size); + + outImage = new osg::Image(); + outImage->setImage(size, size, 1, internalFormat, pixelFormat, type, data, osg::Image::USE_NEW_DELETE); + } + + bool decodeRaster_(int rasterFormat, const char* inputBuffer, int inputBufferLen, osg::ref_ptr& outImage) + { + switch (rasterFormat) + { + case SPLIT_5551_ZLIB_COMPRESS: // TESTED OK + case SPLIT_5551_GZ: // UNTESTED + { + std::string buf; + if (decompressZLIB(inputBuffer, inputBufferLen, buf)) + { + // Three component image (red, green, and blue channels) + makeImage( + pixelLength_, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, buf, outImage); + return true; + } + } + break; + + case SPLIT_8BIT_ZLIB_COMPRESS: // TESTED OK + case SPLIT_8BIT_GZ: // UNTESTED + { + std::string buf; + if (decompressZLIB(inputBuffer, inputBufferLen, buf)) + { + // Single component image (grayscale channel) + makeImage( + pixelLength_, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, buf, outImage); + return true; + } + } + break; + case SPLIT_INTA_ZLIB_COMPRESS: // TESTED OK + { + std::string buf; + if (decompressZLIB(inputBuffer, inputBufferLen, buf)) + { + // Two component image (grayscale w/alpha channel) + makeImage( + pixelLength_, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, buf, outImage); + return true; + } + break; + } + case SPLIT_RGBA_ZLIB_COMPRESS: // TESTED OK + { + std::string buf; + if (decompressZLIB(inputBuffer, inputBufferLen, buf)) + { + // Four component image (red, green, blue and alpha channels) + makeImage( + pixelLength_, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, buf, outImage); + return true; + } + break; + } + case SPLIT_SGI_RGBA: // TESTED - OK (earthColorSGI.db) + { + if (rgbReader_.valid()) + return readNativeImage(rgbReader_.get(), inputBuffer, inputBufferLen, outImage); + else + OE_WARN << "SGI RGBA reader not available" << std::endl; + } + break; + + case SPLIT_SGI_RGB: // UNTESTED + { + if (rgbReader_.valid()) + return readNativeImage(rgbReader_.get(), inputBuffer, inputBufferLen, outImage); + else + OE_WARN << "SGI RGB reader not available" << std::endl; + } + break; + + case SPLIT_FLOAT32_ZLIB_COMPRESS: // TESTED OK; + { + // Single-channel 32-bit float elevation data + std::string buf; + if (decompressZLIB(inputBuffer, inputBufferLen, buf)) + { + makeImage(pixelLength_, GL_LUMINANCE32F_ARB, GL_LUMINANCE, GL_FLOAT, buf, outImage); + return true; + } + } + break; + + case SPLIT_JPEG: // TESTED OK + { + if (jpgReader_.valid()) + return readNativeImage(jpgReader_.get(), inputBuffer, inputBufferLen, outImage); + else + OE_WARN << "JPEG reader not available" << std::endl; + } + break; + + case SPLIT_PNG: // UNTESTED + { + if (pngReader_.valid()) + return readNativeImage(pngReader_.get(), inputBuffer, inputBufferLen, outImage); + else + OE_WARN << "PNG reader not available" << std::endl; + } + break; + + case SPLIT_TIFF: // UNTESTED + { + if (tifReader_.valid()) + return readNativeImage(tifReader_.get(), inputBuffer, inputBufferLen, outImage); + else + OE_WARN << "TIFF reader not available" << std::endl; + } + break; + + default: + { + OE_WARN << "Support for raster format " << rasterFormat << " not implemented" << std::endl; + } + break; + } + return false; + } + }; +} + +//........................................................... + +#undef LC +#define LC "[DBImageLayer] " + +REGISTER_OSGEARTH_LAYER(dbimage, simVis::DBImageLayer); osgEarth::Config DBImageLayer::Options::getConfig() const { - osgEarth::Config conf = osgEarth::Contrib::TileSourceImageLayer::Options::getConfig(); - conf.merge(driver()->getConfig()); + osgEarth::Config conf = osgEarth::ImageLayer::Options::getConfig(); + conf.set("url", url()); + conf.set("deepest_level", deepestLevel()); return conf; } void DBImageLayer::Options::fromConfig(const osgEarth::Config& conf) { - driver() = simVis::DBOptions(conf); + conf.get("url", url()); + conf.get("deepest_level", deepestLevel()); } void DBImageLayer::setURL(const osgEarth::URI& value) { - localCopyOfOptions_.url() = value; - options().driver() = localCopyOfOptions_; + options().url() = value; } const osgEarth::URI& DBImageLayer::getURL() const { - return localCopyOfOptions_.url().get(); + return options().url().get(); } void DBImageLayer::setDeepestLevel(const unsigned int& value) { - localCopyOfOptions_.deepestLevel() = value; - options().driver() = localCopyOfOptions_; + options().deepestLevel() = value; } const unsigned int& DBImageLayer::getDeepestLevel() const { - return localCopyOfOptions_.deepestLevel().get(); + return options().deepestLevel().get(); } void DBImageLayer::init() { - osgEarth::Contrib::TileSourceImageLayer::init(); - localCopyOfOptions_ = simVis::DBOptions(options().driver().get()); + osgEarth::ImageLayer::init(); + context_ = new DBContext(); +} + +DBImageLayer::~DBImageLayer() +{ + delete ((DBContext*)context_); } osgEarth::Status DBImageLayer::openImplementation() { - return osgEarth::Contrib::TileSourceImageLayer::openImplementation(); + osgEarth::Status parent = osgEarth::ImageLayer::openImplementation(); + if (parent.isError()) + return parent; + + DBContext& cx = *(DBContext*)context_; + + if (!options().url().isSet()) + return osgEarth::Status(osgEarth::Status::ConfigurationError, "Missing required URL"); + + cx.pathname_ = osgDB::findDataFile(options().url()->full(), getReadOptions()); + + if (cx.dbUtil_.OpenDataBaseFile(cx.pathname_, &cx.db_, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) != QS_IS_OK) + { + cx.db_ = NULL; + return osgEarth::Status( + osgEarth::Status::ResourceUnavailable, + osgEarth::Stringify() << "Failed to open DB file at " << options().url()->full()); + } + else + { + QsErrorType err = cx.dbUtil_.TsGetSetFromListOfSetsTable( + cx.db_, + "default", + cx.rasterFormat_, + cx.pixelLength_, + cx.shallowLevel_, + cx.deepLevel_, + cx.extents_, + cx.source_, + cx.classification_, + cx.description_, + cx.timeSpecified_, + cx.timeStamp_); + + // Limit the deepLevel_ by the passed-in option + if (options().deepestLevel().isSet()) + { + cx.deepLevel_ = simCore::sdkMin(cx.deepLevel_, static_cast(options().deepestLevel().get())); + } + + if (err != QS_IS_OK) + { + sqlite3_close(cx.db_); + cx.db_ = NULL; + return osgEarth::Status( + osgEarth::Status::ResourceUnavailable, + osgEarth::Stringify() << "Failed to read metadata for " << cx.pathname_); + } + + // Set up as a unified cube: + osgEarth::Profile* profile = new osgEarth::Contrib::UnifiedCubeProfile(); + // DB are expected to be wgs84, which Cube defaults to + setProfile(profile); + + // Lat/long extents (for debugging) + osgEarth::GeoExtent llex[6]; + + // Tell the engine how deep the data actually goes: + for (unsigned int f = 0; f < 6; ++f) + { + if (cx.extents_[f].minX < cx.extents_[f].maxX && cx.extents_[f].minY < cx.extents_[f].maxY) + { + const double x0 = cx.extents_[f].minX / gQsDMaxLength; + const double x1 = cx.extents_[f].maxX / gQsDMaxLength; + const double y0 = cx.extents_[f].minY / gQsDMaxLength; + const double y1 = cx.extents_[f].maxY / gQsDMaxLength; + + osgEarth::GeoExtent cubeEx(profile->getSRS(), f + x0, y0, f + x1, y1); + + // Transform to lat/long for the debugging msgs + cubeEx.transform(profile->getSRS()->getGeodeticSRS(), llex[f]); + + dataExtents().push_back(osgEarth::DataExtent(cubeEx, cx.shallowLevel_, cx.deepLevel_)); + } + } + + // Set time value of image if a time was found in the db + if (cx.timeStamp_ != simCore::INFINITE_TIME_STAMP) + { + const osgEarth::DateTime osgTime(cx.timeStamp_.secondsSinceRefYear(1970).getSeconds()); + // Set time as a user value since config is not editable from here + setUserValue("time", osgTime.asISO8601()); + } + + OE_INFO << LC + << "Table: " << options().url()->full() << std::endl + << " Raster format = " << cx.rasterFormat_ << std::endl + << " Tile size = " << cx.pixelLength_ << std::endl + << " Shallow level = " << cx.shallowLevel_ << std::endl + << " Deep level = " << cx.deepLevel_ << std::endl + << " QS Extents = " << std::endl + << " 0: " << cx.extents_[0].minX << "," << cx.extents_[0].minY << "," << cx.extents_[0].maxX << "," << cx.extents_[0].maxY << "(" << (llex[0].isValid() ? llex[0].toString() : "empty") << ")\n" + << " 1: " << cx.extents_[1].minX << "," << cx.extents_[1].minY << "," << cx.extents_[1].maxX << "," << cx.extents_[1].maxY << "(" << (llex[1].isValid() ? llex[1].toString() : "empty") << ")\n" + << " 2: " << cx.extents_[2].minX << "," << cx.extents_[2].minY << "," << cx.extents_[2].maxX << "," << cx.extents_[2].maxY << "(" << (llex[2].isValid() ? llex[2].toString() : "empty") << ")\n" + << " 3: " << cx.extents_[3].minX << "," << cx.extents_[3].minY << "," << cx.extents_[3].maxX << "," << cx.extents_[3].maxY << "(" << (llex[3].isValid() ? llex[3].toString() : "empty") << ")\n" + << " 4: " << cx.extents_[4].minX << "," << cx.extents_[4].minY << "," << cx.extents_[4].maxX << "," << cx.extents_[4].maxY << "(" << (llex[4].isValid() ? llex[4].toString() : "empty") << ")\n" + << " 5: " << cx.extents_[5].minX << "," << cx.extents_[5].minY << "," << cx.extents_[5].maxX << "," << cx.extents_[5].maxY << "(" << (llex[5].isValid() ? llex[5].toString() : "empty") << ")\n"; + + // Line up the native format readers: + cx.pngReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/png"); + cx.jpgReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/jpeg"); + cx.tifReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/tiff"); + cx.rgbReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/x-rgb"); + } + return osgEarth::Status::OK(); } osgEarth::GeoImage DBImageLayer::createImageImplementation(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress) const { - //todo - return osgEarth::Contrib::TileSourceImageLayer::createImageImplementation(key, progress); + DBContext& cx = *(DBContext*)context_; + + if (!cx.db_) + return osgEarth::GeoImage::INVALID; + + osg::ref_ptr result; + + // Convert osgEarth::TileKey into a QuadKeyID + FaceIndexType faceId; + QSNodeId nodeId; + osg::Vec2d tileMin; + osg::Vec2d tileMax; // Tile extents in QS units + convertTileKeyToQsKey(key, faceId, nodeId, tileMin, tileMax); + + if (!cx.extents_[faceId].Valid()) + { + // no data on this face? return nothing + return osgEarth::GeoImage::INVALID; + } + + if (key.getLevelOfDetail() > static_cast(cx.deepLevel_)) + { + // Hopefully this doesn't happen since we called setMaxDataLevel, but you never know + return osgEarth::GeoImage::INVALID; + } + + // Query the database + TextureDataType* buf = NULL; + uint32_t bufSize = 0; + uint32_t currentRasterSize = 0; + + QsErrorType err = cx.dbUtil_.TsReadDataBuffer( + cx.db_, + cx.pathname_, + "default", + faceId, + nodeId, + &buf, + &bufSize, + ¤tRasterSize, + false, true); // AllowLocalDB: no, we created it ourselves + + if (err == QS_IS_OK) + { + if (currentRasterSize > 0) + { + if (cx.decodeRaster_(cx.rasterFormat_, (const char*)buf, currentRasterSize, result)) + { + // If result is 1x1, skip border processing + if (result->s() >= 1 && result->t() >= 1) + { + const unsigned int resultS = static_cast(result->s()); + const unsigned int resultT = static_cast(result->t()); + + // Tile width and height in QS units: + const double tileWidth = tileMax.x() - tileMin.x(); + const double tileHeight = tileMax.y() - tileMin.y(); + + const double qppx = 0.0; + const double qppy = 0.0; + const double xMin = cx.extents_[faceId].minX + qppx; + const double xMax = cx.extents_[faceId].maxX - qppx; + const double yMin = cx.extents_[faceId].minY + qppy; + const double yMax = cx.extents_[faceId].maxY - qppy; + + osgEarth::ImageUtils::PixelReader read(result.get()); + osgEarth::ImageUtils::PixelWriter write(result.get()); + + // Write "no data" to all pixels outside the reported extent. + const double colw = tileWidth / (resultS - 1); + const double rowh = tileHeight / (resultT - 1); + + for (unsigned int row = 0; row < resultS; ++row) + { + const double y = tileMin.y() + row * rowh; + + for (unsigned int col = 0; col < resultT; ++col) + { + const double x = tileMin.x() + col * colw; + + if (x < xMin || x > xMax || y < yMin || y > yMax) + { + osg::Vec4f pixel = read(col, row); + pixel.a() = 0.0f; + write(pixel, col, row); + } + } + } + } + } + else + { + OE_WARN << "Image decode failed for key " << key.str() << std::endl; + } + } + else + { + // Raster size of 0 means no tile in the db + //OE_DEBUG << "No image in the database for key " << key->str() << std::endl; + result = NULL; + } + } + else + { + std::cerr << GetErrorString(err) << std::endl; + OE_WARN << "Failed to read image from " << key.str() << std::endl; + } + + delete[] buf; + + return osgEarth::GeoImage(result.release(), key.getExtent()); } //........................................................... +#undef LC +#define LC "[DBElevationLayer] " + +REGISTER_OSGEARTH_LAYER(dbelevation, simVis::DBElevationLayer); + osgEarth::Config DBElevationLayer::Options::getConfig() const { osgEarth::Config conf = osgEarth::ElevationLayer::Options::getConfig(); - conf.merge(driver()->getConfig()); + conf.set("url", url()); + conf.set("deepest_level", deepestLevel()); return conf; } void DBElevationLayer::Options::fromConfig(const osgEarth::Config& conf) { - driver() = simVis::DBOptions(conf); + conf.get("url", url()); + conf.get("deepest_level", deepestLevel()); } void DBElevationLayer::setURL(const osgEarth::URI& value) { - localCopyOfOptions_.url() = value; - options().driver() = localCopyOfOptions_; + options().url() = value; } const osgEarth::URI& DBElevationLayer::getURL() const { - return localCopyOfOptions_.url().get(); + return options().url().get(); } void DBElevationLayer::setDeepestLevel(const unsigned int& value) { - localCopyOfOptions_.deepestLevel() = value; - options().driver() = localCopyOfOptions_; + options().deepestLevel() = value; } const unsigned int& DBElevationLayer::getDeepestLevel() const { - return localCopyOfOptions_.deepestLevel().get(); + return options().deepestLevel().get(); } void DBElevationLayer::init() { - osgEarth::Contrib::ElevationLayer::init(); - localCopyOfOptions_ = simVis::DBOptions(options().driver().get()); + osgEarth::ElevationLayer::init(); + context_ = new DBContext(); +} + +DBElevationLayer::~DBElevationLayer() +{ + delete ((DBContext*)context_); } osgEarth::Status DBElevationLayer::openImplementation() { - return osgEarth::ElevationLayer::openImplementation(); + osgEarth::Status parent = osgEarth::ElevationLayer::openImplementation(); + if (parent.isError()) + return parent; + + + DBContext& cx = *(DBContext*)context_; + + if (!options().url().isSet()) + return osgEarth::Status(osgEarth::Status::ConfigurationError, "Missing required URL"); + + cx.pathname_ = osgDB::findDataFile(options().url()->full(), getReadOptions()); + + if (cx.dbUtil_.OpenDataBaseFile(cx.pathname_, &cx.db_, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) != QS_IS_OK) + { + cx.db_ = NULL; + return osgEarth::Status( + osgEarth::Status::ResourceUnavailable, + osgEarth::Stringify() << "Failed to open DB file at " << options().url()->full()); + } + else + { + QsErrorType err = cx.dbUtil_.TsGetSetFromListOfSetsTable( + cx.db_, + "default", + cx.rasterFormat_, + cx.pixelLength_, + cx.shallowLevel_, + cx.deepLevel_, + cx.extents_, + cx.source_, + cx.classification_, + cx.description_, + cx.timeSpecified_, + cx.timeStamp_); + + // Limit the deepLevel_ by the passed-in option + if (options().deepestLevel().isSet()) + { + cx.deepLevel_ = simCore::sdkMin(cx.deepLevel_, static_cast(options().deepestLevel().get())); + } + + if (err != QS_IS_OK) + { + sqlite3_close(cx.db_); + cx.db_ = NULL; + return osgEarth::Status( + osgEarth::Status::ResourceUnavailable, + osgEarth::Stringify() << "Failed to read metadata for " << cx.pathname_); + } + + // Set up as a unified cube: + osgEarth::Profile* profile = new osgEarth::Contrib::UnifiedCubeProfile(); + // DB are expected to be wgs84, which Cube defaults to + setProfile(profile); + + // Lat/long extents (for debugging) + osgEarth::GeoExtent llex[6]; + + // Tell the engine how deep the data actually goes: + for (unsigned int f = 0; f < 6; ++f) + { + if (cx.extents_[f].minX < cx.extents_[f].maxX && cx.extents_[f].minY < cx.extents_[f].maxY) + { + const double x0 = cx.extents_[f].minX / gQsDMaxLength; + const double x1 = cx.extents_[f].maxX / gQsDMaxLength; + const double y0 = cx.extents_[f].minY / gQsDMaxLength; + const double y1 = cx.extents_[f].maxY / gQsDMaxLength; + + osgEarth::GeoExtent cubeEx(profile->getSRS(), f + x0, y0, f + x1, y1); + + // Transform to lat/long for the debugging msgs + cubeEx.transform(profile->getSRS()->getGeodeticSRS(), llex[f]); + + dataExtents().push_back(osgEarth::DataExtent(cubeEx, cx.shallowLevel_, cx.deepLevel_)); + } + } + + // Set time value of image if a time was found in the db + if (cx.timeStamp_ != simCore::INFINITE_TIME_STAMP) + { + const osgEarth::DateTime osgTime(cx.timeStamp_.secondsSinceRefYear(1970).getSeconds()); + // Set time as a user value since config is not editable from here + setUserValue("time", osgTime.asISO8601()); + } + + OE_INFO << LC + << "Table: " << options().url()->full() << std::endl + << " Raster format = " << cx.rasterFormat_ << std::endl + << " Tile size = " << cx.pixelLength_ << std::endl + << " Shallow level = " << cx.shallowLevel_ << std::endl + << " Deep level = " << cx.deepLevel_ << std::endl + << " QS Extents = " << std::endl + << " 0: " << cx.extents_[0].minX << "," << cx.extents_[0].minY << "," << cx.extents_[0].maxX << "," << cx.extents_[0].maxY << "(" << (llex[0].isValid() ? llex[0].toString() : "empty") << ")\n" + << " 1: " << cx.extents_[1].minX << "," << cx.extents_[1].minY << "," << cx.extents_[1].maxX << "," << cx.extents_[1].maxY << "(" << (llex[1].isValid() ? llex[1].toString() : "empty") << ")\n" + << " 2: " << cx.extents_[2].minX << "," << cx.extents_[2].minY << "," << cx.extents_[2].maxX << "," << cx.extents_[2].maxY << "(" << (llex[2].isValid() ? llex[2].toString() : "empty") << ")\n" + << " 3: " << cx.extents_[3].minX << "," << cx.extents_[3].minY << "," << cx.extents_[3].maxX << "," << cx.extents_[3].maxY << "(" << (llex[3].isValid() ? llex[3].toString() : "empty") << ")\n" + << " 4: " << cx.extents_[4].minX << "," << cx.extents_[4].minY << "," << cx.extents_[4].maxX << "," << cx.extents_[4].maxY << "(" << (llex[4].isValid() ? llex[4].toString() : "empty") << ")\n" + << " 5: " << cx.extents_[5].minX << "," << cx.extents_[5].minY << "," << cx.extents_[5].maxX << "," << cx.extents_[5].maxY << "(" << (llex[5].isValid() ? llex[5].toString() : "empty") << ")\n"; + + // Line up the native format readers: + cx.pngReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/png"); + cx.jpgReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/jpeg"); + cx.tifReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/tiff"); + cx.rgbReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/x-rgb"); + } + return osgEarth::Status::OK(); } osgEarth::GeoHeightField DBElevationLayer::createHeightFieldImplementation(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress) const { - //todo - return osgEarth::ElevationLayer::createHeightFieldImplementation(key, progress); + DBContext& cx = *(DBContext*)context_; + + if (!cx.db_) + return osgEarth::GeoHeightField::INVALID; + + osg::ref_ptr result; + + // Convert osgEarth::TileKey into a QuadKeyID + FaceIndexType faceId; + QSNodeId nodeId; + osg::Vec2d tileMin; + osg::Vec2d tileMax; // Tile extents in QS units + convertTileKeyToQsKey(key, faceId, nodeId, tileMin, tileMax); + + if (!cx.extents_[faceId].Valid()) + { + // If there is no data on that face, return nothing. + return osgEarth::GeoHeightField::INVALID; + } + + // Query the database + TextureDataType* buf = NULL; + uint32_t bufSize = 0; + uint32_t currentRasterSize = 0; + + QsErrorType err = cx.dbUtil_.TsReadDataBuffer( + cx.db_, + cx.pathname_, + "default", + faceId, + nodeId, + &buf, + &bufSize, + ¤tRasterSize, + false); // AllowLocalDB: no, we created it ourselves + + if (err == QS_IS_OK) + { + if (currentRasterSize > 0) + { + osg::ref_ptr image; + if (cx.decodeRaster_(cx.rasterFormat_, (const char*)buf, currentRasterSize, image)) + { + + // SIMDIS .db elevation data is y-inverted: + image->flipVertical(); + + osgEarth::ImageToHeightFieldConverter i2h; + result = i2h.convert(image.get()); + + // If result is 1x1, skip border processing + if (result->getNumColumns() >= 1 && result->getNumRows() >= 1) + { + // Tile width and height in QS units: + const double tileWidth = tileMax.x() - tileMin.x(); + const double tileHeight = tileMax.y() - tileMin.y(); + + /** + * DB data contains a one-pixel border with undefined data. That border falls + * within the reported extents. We have to fill that with "NO DATA". + * First, calculate the size of a pixel in QS units for this tile: + */ + const double qppx = tileWidth / cx.pixelLength_; + const double qppy = tileHeight / cx.pixelLength_; + + /** + * Adjust the reported extents to remove the border. + * NOTE: This will fail in the (rare?) edge case in which a data extent falls + * exactly on a cube-face boundary. Ignore that for now. + */ + const double xMin = cx.extents_[faceId].minX + qppx; + const double xMax = cx.extents_[faceId].maxX - qppx; + const double yMin = cx.extents_[faceId].minY + qppy; + const double yMax = cx.extents_[faceId].maxY - qppy; + + // Write "no data" to all pixels outside the reported extent. + const double colWidth = tileWidth / (result->getNumColumns() - 1); + const double rowHeight = tileHeight / (result->getNumRows() - 1); + + for (unsigned int row = 0; row < result->getNumRows(); ++row) + { + const double y = tileMin.y() + row * rowHeight; + + for (unsigned int col = 0; col < result->getNumColumns(); ++col) + { + const double x = tileMin.x() + col * colWidth; + + if (x < xMin || x > xMax || y < yMin || y > yMax) + { + result->setHeight(col, row, NO_DATA_VALUE); + } + } + } + } + } + else + { + OE_WARN << "Heightfield decode failed for key " << key.str() << std::endl; + } + } + else + { + // Raster size of 0 means no tile in the db + result = NULL; + } + } + else + { + OE_WARN << "Failed to read heightfield from " << key.str() << std::endl; + } + + delete[] buf; + + return osgEarth::GeoHeightField(result.release(), key.getExtent()); } diff --git a/SDK/simVis/DBFormat.h b/SDK/simVis/DBFormat.h index 646498d23..a9e710f60 100644 --- a/SDK/simVis/DBFormat.h +++ b/SDK/simVis/DBFormat.h @@ -37,19 +37,21 @@ namespace simVis // OE_OPTION uses unqualified optional<> type using osgEarth::optional; -class SDKVIS_EXPORT DBImageLayer : public osgEarth::Contrib::TileSourceImageLayer +class SDKVIS_EXPORT DBImageLayer : public osgEarth::ImageLayer { public: // serialization - class SDKVIS_EXPORT Options : public osgEarth::Contrib::TileSourceImageLayer::Options { + class SDKVIS_EXPORT Options : public osgEarth::ImageLayer::Options { public: - META_LayerOptions(simVis, Options, osgEarth::Contrib::TileSourceImageLayer::Options); + META_LayerOptions(simVis, Options, osgEarth::ImageLayer::Options); + OE_OPTION(osgEarth::URI, url); + OE_OPTION(unsigned, deepestLevel); virtual osgEarth::Config getConfig() const; private: void fromConfig(const osgEarth::Config&); }; public: - META_Layer(simVis, DBImageLayer, Options, osgEarth::Contrib::TileSourceImageLayer, DBImage); + META_Layer(simVis, DBImageLayer, Options, osgEarth::ImageLayer, DBImage); public: /// Base URL of TileCache endpoint @@ -74,27 +76,29 @@ class SDKVIS_EXPORT DBImageLayer : public osgEarth::Contrib::TileSourceImageLaye virtual void init(); /// Destructor - virtual ~DBImageLayer() { } + virtual ~DBImageLayer(); - simVis::DBOptions localCopyOfOptions_; + void* context_; }; /** * Elevation layer connected to a DB file */ -class SDKVIS_EXPORT DBElevationLayer : public osgEarth::Contrib::TileSourceElevationLayer +class SDKVIS_EXPORT DBElevationLayer : public osgEarth::ElevationLayer { public: // serialization - class SDKVIS_EXPORT Options : public osgEarth::Contrib::TileSourceElevationLayer::Options { + class SDKVIS_EXPORT Options : public osgEarth::ElevationLayer::Options { public: - META_LayerOptions(simVis, Options, osgEarth::Contrib::TileSourceElevationLayer::Options); + META_LayerOptions(simVis, Options, osgEarth::ElevationLayer::Options); + OE_OPTION(osgEarth::URI, url); + OE_OPTION(unsigned, deepestLevel); virtual osgEarth::Config getConfig() const; private: void fromConfig(const osgEarth::Config&); }; public: - META_Layer(simVis, DBElevationLayer, Options, osgEarth::Contrib::TileSourceElevationLayer, DBElevation); + META_Layer(simVis, DBElevationLayer, Options, osgEarth::ElevationLayer, DBElevation); /// URL of the database file void setURL(const osgEarth::URI& value); @@ -118,9 +122,9 @@ class SDKVIS_EXPORT DBElevationLayer : public osgEarth::Contrib::TileSourceEleva virtual void init(); /// Destructor - virtual ~DBElevationLayer() { } + virtual ~DBElevationLayer(); - simVis::DBOptions localCopyOfOptions_; + void* context_; }; } From c70c32458572f845eaf0ee8f658e6dbe1cf89c17 Mon Sep 17 00:00:00 2001 From: gwaldron Date: Tue, 14 Jan 2020 15:24:27 -0500 Subject: [PATCH 027/121] Refactor DB out of plugin and into layers; support is optional and depends on sqlite3 --- CMakeLists.txt | 4 + Examples/CMakeLists.txt | 9 +- Examples/DBReader/DBReader.cpp | 1 - Examples/Ocean/Ocean.cpp | 1 - Plugins/CMakeLists.txt | 10 +- SDK/simUtil.h | 2 +- SDK/simUtil/CMakeLists.txt | 8 +- SDK/simUtil/DbConfigurationFile.cpp | 1 - SDK/simUtil/ExampleResources.cpp | 1 - SDK/simUtil/LayerFactory.cpp | 8 + SDK/simUtil/LayerFactory.h | 6 + SDK/simVis.h | 1 - SDK/simVis/CMakeLists.txt | 34 +- SDK/simVis/DB/Plugin.cpp | 56 ++ SDK/simVis/DB/QSCommon.h | 50 ++ SDK/simVis/DB/QSError.cpp | 171 +++++ SDK/simVis/DB/QSError.h | 81 +++ SDK/simVis/DB/QSNodeID96.cpp | 302 +++++++++ SDK/simVis/DB/QSNodeID96.h | 64 ++ SDK/simVis/DB/QSPosXYExtents.cpp | 170 +++++ SDK/simVis/DB/QSPosXYExtents.h | 85 +++ SDK/simVis/DB/RasterCommon.h | 0 SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp | 364 +++++++++++ SDK/simVis/DB/SQLiteDataBaseReadUtil.h | 162 +++++ SDK/simVis/DB/swapbytes.h | 780 +++++++++++++++++++++++ SDK/simVis/DBFormat.cpp | 773 +++++++++++++++++++++- SDK/simVis/DBFormat.h | 28 +- 27 files changed, 3114 insertions(+), 58 deletions(-) create mode 100644 SDK/simVis/DB/Plugin.cpp create mode 100644 SDK/simVis/DB/QSCommon.h create mode 100644 SDK/simVis/DB/QSError.cpp create mode 100644 SDK/simVis/DB/QSError.h create mode 100644 SDK/simVis/DB/QSNodeID96.cpp create mode 100644 SDK/simVis/DB/QSNodeID96.h create mode 100644 SDK/simVis/DB/QSPosXYExtents.cpp create mode 100644 SDK/simVis/DB/QSPosXYExtents.h create mode 100644 SDK/simVis/DB/RasterCommon.h create mode 100644 SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp create mode 100644 SDK/simVis/DB/SQLiteDataBaseReadUtil.h create mode 100644 SDK/simVis/DB/swapbytes.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e2849ff6..eca0c0e46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -206,6 +206,10 @@ include(ImportProtobuf) # --- SQLITE3 ----------------------------- set(SQLITE3_DIR "" CACHE PATH "Sqlite3 root directory") include(ImportSQLite) +if (SQLITE3_FOUND) + set(SIM_HAVE_DB_SUPPORT 1) + add_definitions(-DSIM_HAVE_DB_SUPPORT) +endif() # subprojects add_subdirectory(SDK) diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index 7e71e2ba8..64e51cbed 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -10,7 +10,6 @@ add_subdirectory(BasicViewer) add_subdirectory(BasicViewerText) add_subdirectory(CentroidEyePosition) add_subdirectory(CustomRenderingTest) -add_subdirectory(DBReader) add_subdirectory(GeoFencing) add_subdirectory(GOGAttachments) add_subdirectory(GOGReader) @@ -20,7 +19,6 @@ add_subdirectory(MapScale) add_subdirectory(MassiveData) add_subdirectory(ObserverMaker) add_subdirectory(Ocean) -add_subdirectory(Overhead) add_subdirectory(Periscope) add_subdirectory(Picking) add_subdirectory(PlatformSymbology) @@ -30,11 +28,16 @@ add_subdirectory(RangeTool) add_subdirectory(RCS) add_subdirectory(RFProp) add_subdirectory(RocketBurn) -add_subdirectory(LoadEarthFile) add_subdirectory(SkyModel) add_subdirectory(SimpleServer) add_subdirectory(TimestampedLayer) +if(SIM_HAVE_DB_SUPPORT) + add_subdirectory(DBReader) + add_subdirectory(LoadEarthFile) + add_subdirectory(Overhead) +endif() + if(QT_FOUND) add_subdirectory(Qt) add_subdirectory(QtActionItemModelTest) diff --git a/Examples/DBReader/DBReader.cpp b/Examples/DBReader/DBReader.cpp index 9dcf6c356..71b77cfcf 100644 --- a/Examples/DBReader/DBReader.cpp +++ b/Examples/DBReader/DBReader.cpp @@ -33,7 +33,6 @@ #include "simCore/Common/HighPerformanceGraphics.h" #include "simUtil/ExampleResources.h" #include "simVis/Viewer.h" -#include "simVis/DBOptions.h" #include "simVis/osgEarthVersion.h" #include "simUtil/ExampleResources.h" #include "simVis/DBFormat.h" diff --git a/Examples/Ocean/Ocean.cpp b/Examples/Ocean/Ocean.cpp index 7b450aff2..cc7d7e7f9 100644 --- a/Examples/Ocean/Ocean.cpp +++ b/Examples/Ocean/Ocean.cpp @@ -42,7 +42,6 @@ #include "simData/MemoryDataStore.h" #include "simVis/BathymetryGenerator.h" -#include "simVis/DBOptions.h" #include "simVis/osgEarthVersion.h" #include "simVis/Platform.h" #include "simVis/PlatformModel.h" diff --git a/Plugins/CMakeLists.txt b/Plugins/CMakeLists.txt index ca300b023..49208ea63 100644 --- a/Plugins/CMakeLists.txt +++ b/Plugins/CMakeLists.txt @@ -1,9 +1,9 @@ # DB plugin no longer needed with osgEarth 3.x -if(SQLITE3_LIBRARY_RELEASE_NAME) - add_subdirectory(OSGEarthDBDriver) -else() - message(STATUS "Skipping osgEarth .db Driver plug-in because of missing dependencies.") -endif() +#if(SQLITE3_LIBRARY_RELEASE_NAME) +# add_subdirectory(OSGEarthDBDriver) +#else() +# message(STATUS "Skipping osgEarth .db Driver plug-in because of missing dependencies.") +#endif() if(QT_FOUND) option(ENABLE_QTDESIGNER_WIDGETS "Build Qt Designer Plugins for simQt widgets" ON) diff --git a/SDK/simUtil.h b/SDK/simUtil.h index 91c5b8fa2..698cb4387 100644 --- a/SDK/simUtil.h +++ b/SDK/simUtil.h @@ -25,7 +25,7 @@ #include "simUtil/Capabilities.h" #include "simUtil/DataStoreTestHelper.h" #include "simUtil/DatumConvert.h" -#include "simUtil/DbConfigurationFile.h" +//#include "simUtil/DbConfigurationFile.h" #include "simUtil/DefaultDataStoreValues.h" #include "simUtil/DynamicSelectionPicker.h" #include "simUtil/ExampleControls.h" diff --git a/SDK/simUtil/CMakeLists.txt b/SDK/simUtil/CMakeLists.txt index 3c550fe2d..f364093dc 100644 --- a/SDK/simUtil/CMakeLists.txt +++ b/SDK/simUtil/CMakeLists.txt @@ -18,7 +18,6 @@ set(UTIL_HEADERS ${UTIL_INC}Capabilities.h ${UTIL_INC}DataStoreTestHelper.h ${UTIL_INC}DatumConvert.h - ${UTIL_INC}DbConfigurationFile.h ${UTIL_INC}DefaultDataStoreValues.h ${UTIL_INC}ExampleControls.h ${UTIL_INC}ExampleResources.h @@ -54,7 +53,6 @@ set(UTIL_SOURCES ${UTIL_SRC}Capabilities.cpp ${UTIL_SRC}DataStoreTestHelper.cpp ${UTIL_SRC}DatumConvert.cpp - ${UTIL_SRC}DbConfigurationFile.cpp ${UTIL_SRC}DefaultDataStoreValues.cpp ${UTIL_SRC}ExampleControls.cpp ${UTIL_SRC}ExampleResources.cpp @@ -83,6 +81,12 @@ set(UTIL_SOURCES ${UTIL_SRC}ViewpointMonitor.cpp ${UTIL_SRC}ViewpointPositions.cpp ) + +if(SIM_HAVE_DB_SUPPORT) + set(UTIL_HEADERS ${UTIL_HEADERS} ${UTIL_INC}DbConfigurationFile.h) + set(UTIL_SOURCES ${UTIL_SOURCES} ${UTIL_SRC}DbConfigurationFile.cpp) +endif() + set(UTIL_GENERATED_HEADERS) set(UTIL_GENERATED_SOURCES) diff --git a/SDK/simUtil/DbConfigurationFile.cpp b/SDK/simUtil/DbConfigurationFile.cpp index 4ae7f057b..697ca79bf 100644 --- a/SDK/simUtil/DbConfigurationFile.cpp +++ b/SDK/simUtil/DbConfigurationFile.cpp @@ -34,7 +34,6 @@ #include "simCore/String/Utils.h" #include "simCore/String/ValidNumber.h" #include "simVis/AlphaColorFilter.h" -#include "simVis/DBOptions.h" #include "simVis/DBFormat.h" #include "simVis/SceneManager.h" #include "simVis/Utils.h" diff --git a/SDK/simUtil/ExampleResources.cpp b/SDK/simUtil/ExampleResources.cpp index cc30723e7..e4e89225b 100644 --- a/SDK/simUtil/ExampleResources.cpp +++ b/SDK/simUtil/ExampleResources.cpp @@ -34,7 +34,6 @@ #include "simCore/String/Utils.h" #include "simCore/Time/ClockImpl.h" #include "simData/DataStore.h" -#include "simVis/DBOptions.h" #include "simVis/Gl3Utils.h" #include "simVis/Registry.h" #include "simVis/SceneManager.h" diff --git a/SDK/simUtil/LayerFactory.cpp b/SDK/simUtil/LayerFactory.cpp index d6eef5877..f9fa0fe06 100644 --- a/SDK/simUtil/LayerFactory.cpp +++ b/SDK/simUtil/LayerFactory.cpp @@ -29,7 +29,11 @@ #include "simCore/String/Format.h" #include "simCore/String/Utils.h" #include "simVis/Constants.h" + +#ifdef SIM_HAVE_DB_SUPPORT #include "simVis/DBFormat.h" +#endif + #include "simVis/Types.h" #include "simUtil/LayerFactory.h" @@ -38,6 +42,7 @@ namespace simUtil { /** Default cache time of one year */ static const osgEarth::TimeSpan ONE_YEAR(365 * 86400); +#ifdef SIM_HAVE_DB_SUPPORT simVis::DBImageLayer* LayerFactory::newDbImageLayer(const std::string& fullPath) const { osgEarth::Config config; @@ -55,6 +60,7 @@ simVis::DBImageLayer* LayerFactory::newDbImageLayer(const std::string& fullPath) return layer.release(); } +#endif osgEarth::MBTilesImageLayer* LayerFactory::newMbTilesImageLayer(const std::string& fullPath) const { @@ -95,6 +101,7 @@ osgEarth::GDALImageLayer* LayerFactory::newGdalImageLayer(const std::string& ful return layer.release(); } +#ifdef SIM_HAVE_DB_SUPPORT simVis::DBElevationLayer* LayerFactory::newDbElevationLayer(const std::string& fullPath) const { osgEarth::Config config; @@ -112,6 +119,7 @@ simVis::DBElevationLayer* LayerFactory::newDbElevationLayer(const std::string& f return layer.release(); } +#endif osgEarth::MBTilesElevationLayer* LayerFactory::newMbTilesElevationLayer(const std::string& fullPath) const { diff --git a/SDK/simUtil/LayerFactory.h b/SDK/simUtil/LayerFactory.h index 320e7620e..6d943ecad 100644 --- a/SDK/simUtil/LayerFactory.h +++ b/SDK/simUtil/LayerFactory.h @@ -58,15 +58,21 @@ namespace simUtil { class SDKUTIL_EXPORT LayerFactory { public: +#ifdef SIM_HAVE_DB_SUPPORT /** Returns an image layer properly configured for DB layer. */ simVis::DBImageLayer* newDbImageLayer(const std::string& fullPath) const; +#endif + /** Returns an image layer properly configured for MBTiles layer. */ osgEarth::MBTilesImageLayer* newMbTilesImageLayer(const std::string& fullPath) const; /** Returns an image layer properly configured for GDAL layer. */ osgEarth::GDALImageLayer* newGdalImageLayer(const std::string& fullPath) const; +#ifdef SIM_HAVE_DB_SUPPORT /** Returns an elevation layer properly configured for DB layer. */ simVis::DBElevationLayer* newDbElevationLayer(const std::string& fullPath) const; +#endif + /** Returns an elevation layer properly configured for MBTiles layer. */ osgEarth::MBTilesElevationLayer* newMbTilesElevationLayer(const std::string& fullPath) const; /** Returns an elevation layer properly configured for GDAL layer. */ diff --git a/SDK/simVis.h b/SDK/simVis.h index 29949f19d..91e040310 100644 --- a/SDK/simVis.h +++ b/SDK/simVis.h @@ -43,7 +43,6 @@ #include "simVis/CustomRendering.h" #include "simVis/CylinderGeode.h" #include "simVis/CylinderStorage.h" -#include "simVis/DBOptions.h" #include "simVis/DisableDepthOnAlpha.h" #include "simVis/DynamicScaleTransform.h" #include "simVis/EarthManipulator.h" diff --git a/SDK/simVis/CMakeLists.txt b/SDK/simVis/CMakeLists.txt index 4256d3309..25feb39ab 100644 --- a/SDK/simVis/CMakeLists.txt +++ b/SDK/simVis/CMakeLists.txt @@ -64,8 +64,6 @@ set(VIS_HEADERS_CORE ${VIS_INC}CustomRendering.h ${VIS_INC}CylinderGeode.h ${VIS_INC}CylinderStorage.h - ${VIS_INC}DBFormat.h - ${VIS_INC}DBOptions.h ${VIS_INC}DisableDepthOnAlpha.h ${VIS_INC}DynamicScaleTransform.h ${VIS_INC}EarthManipulator.h @@ -139,6 +137,17 @@ set(VIS_HEADERS_CORE ${CMAKE_CURRENT_BINARY_DIR}/include/simVis/osgEarthVersion.h ) +set(VIS_HEADERS_DB + ${VIS_INC}DBFormat.h + ${VIS_INC}DB/QSCommon.h + ${VIS_INC}DB/QSError.h + ${VIS_INC}DB/QSNodeID96.h + ${VIS_INC}DB/QSPosXYExtents.h + ${VIS_INC}DB/RasterCommon.h + ${VIS_INC}DB/SQLiteDataBaseReadUtil.h + ${VIS_INC}DB/swapbytes.h +) + set(VIS_HEADERS_RFPROP ${VIS_INC}RFProp/ArepsLoader.h ${VIS_INC}RFProp/BearingProfileMap.h @@ -211,7 +220,6 @@ set(VIS_SOURCES_CORE ${VIS_SRC}CustomRendering.cpp ${VIS_SRC}CylinderGeode.cpp ${VIS_SRC}CylinderStorage.cpp - ${VIS_SRC}DBFormat.cpp ${VIS_SRC}DisableDepthOnAlpha.cpp ${VIS_SRC}DynamicScaleTransform.cpp ${VIS_SRC}EarthManipulator.cpp @@ -279,6 +287,14 @@ set(VIS_SOURCES_CORE ${VIS_SRC}ViewManagerLogDbAdapter.cpp ) +set(VIS_SOURCES_DB + ${VIS_INC}DBFormat.cpp + ${VIS_INC}DB/QSError.cpp + ${VIS_INC}DB/QSNodeID96.cpp + ${VIS_INC}DB/QSPosXYExtents.cpp + ${VIS_INC}DB/SQLiteDataBaseReadUtil.cpp +) + set(VIS_SOURCES_RFPROP ${VIS_SRC}RFProp/ArepsLoader.cpp ${VIS_SRC}RFProp/BearingProfileMap.cpp @@ -367,6 +383,14 @@ source_group("" FILES ${VIS_ALL_HEADER}) set(VIS_HEADERS ${VIS_HEADERS_CORE} ${VIS_HEADERS_RFPROP} ${VIS_HEADERS_GOG}) set(VIS_SOURCES ${VIS_SOURCES_CORE} ${VIS_SOURCES_RFPROP} ${VIS_SOURCES_GOG} ${VIS_SHADER_FILES}) +if(SIM_HAVE_DB_SUPPORT) + source_group(Headers\\DB FILES ${VIS_HEADERS_DB}) + source_group(Sources\\DB FILES ${VIS_SOURCES_DB}) + + set(VIS_HEADERS ${VIS_HEADERS} ${VIS_HEADERS_DB}) + set(VIS_SOURCES ${VIS_SOURCES} ${VIS_SOURCES_DB}) +endif() + # ---------------------------------------------------------------------- # Avoid false MSVC 2017/2019 MSB8027 warning from Unity build on Utils.cpp and Angle.cpp @@ -398,6 +422,10 @@ target_link_libraries(simVis PUBLIC simData simCore simNotify ${OSG_ALL_LIBDEPENDENCIES} OSGEARTH) target_link_libraries(simVis PRIVATE VSI::GL) +if(SQLITE3_FOUND) + target_link_libraries(simVis PUBLIC SQLITE3) +endif() + if(SIMVIS_SHARED) target_compile_definitions(simVis PRIVATE simVis_LIB_EXPORT_SHARED) else() diff --git a/SDK/simVis/DB/Plugin.cpp b/SDK/simVis/DB/Plugin.cpp new file mode 100644 index 000000000..43635c2b5 --- /dev/null +++ b/SDK/simVis/DB/Plugin.cpp @@ -0,0 +1,56 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** +***** ***** +***** Classification: UNCLASSIFIED ***** +***** Classified By: ***** +***** Declassify On: ***** +***** ***** +**************************************************************************** +* +* +* Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. +* EW Modeling & Simulation, Code 5773 +* 4555 Overlook Ave. +* Washington, D.C. 20375-5339 +* +* License for source code at https://simdis.nrl.navy.mil/License.aspx +* +* The U.S. Government retains all rights to use, duplicate, distribute, +* disclose, or release this software. +* +*/ +#include "osgEarth/TileSource" +#include "osgDB/FileNameUtils" +#include "osgDB/Registry" +#include +#include "DBTileSource.h" + +class SimSdkOSGEarthDBDriverPlugin : public osgEarth::Contrib::TileSourceDriver +{ +public: + SimSdkOSGEarthDBDriverPlugin() { } + + const char* className() + { + return "OSGEarth DB Driver"; + } + + bool acceptsExtension(const std::string& extension) const + { + return osgDB::equalCaseInsensitive("osgearth_db", extension); + } + + osgDB::ReaderWriter::ReadResult readObject(const std::string& uri, const osgDB::Options* options) const + { + std::string ext = osgDB::getFileExtension(uri); + if (!acceptsExtension(ext)) + { + return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED; + } + + return osgDB::ReaderWriter::ReadResult( + new simVis_db::DBTileSource(getTileSourceOptions(options))); + } +}; + +REGISTER_OSGPLUGIN(osgearth_db, SimSdkOSGEarthDBDriverPlugin) diff --git a/SDK/simVis/DB/QSCommon.h b/SDK/simVis/DB/QSCommon.h new file mode 100644 index 000000000..6e1f6d744 --- /dev/null +++ b/SDK/simVis/DB/QSCommon.h @@ -0,0 +1,50 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ +#ifndef QS_COMMON_H +#define QS_COMMON_H + +#include "simCore/Common/Common.h" + +namespace simVis_db +{ + typedef uint8_t FaceIndexType; + typedef uint8_t TextureDataType; + typedef uint8_t RasterFormat; + + /// Raster formats + static const RasterFormat SPLIT_UNKNOWN = 0; + static const RasterFormat SPLIT_SGI_RGB = 1; + static const RasterFormat SPLIT_SGI_RGBA = 2; + static const RasterFormat SPLIT_5551_GZ = 3; + static const RasterFormat SPLIT_5551_ZLIB_COMPRESS = 4; + static const RasterFormat SPLIT_RGBA_ZLIB_COMPRESS = 5; + static const RasterFormat SPLIT_INTA_ZLIB_COMPRESS = 6; + static const RasterFormat SPLIT_JPEG_2000 = 8; + static const RasterFormat SPLIT_8BIT_GZ = 9; // GL_LUMINANCE + static const RasterFormat SPLIT_8BIT_ZLIB_COMPRESS = 10; + static const RasterFormat SPLIT_FLOAT32_ZLIB_COMPRESS = 11; + static const RasterFormat SPLIT_JPEG = 12; + static const RasterFormat SPLIT_PNG = 13; + static const RasterFormat SPLIT_TIFF = 14; +} // namespace simVis_db + +#endif /* QS_COMMON_H */ diff --git a/SDK/simVis/DB/QSError.cpp b/SDK/simVis/DB/QSError.cpp new file mode 100644 index 000000000..ddff49188 --- /dev/null +++ b/SDK/simVis/DB/QSError.cpp @@ -0,0 +1,171 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#include +#include +#include "QSError.h" + +namespace simVis_db { + +static const char* QS_IS_UNRECOGNIZED_ERROR_VALUE_STR = "Unrecognized Error Value"; +static const char* QS_IS_OK_STR = "\0"; +static const char* QS_IS_COMMAND_LINE_STR = "Command line error"; +static const char* QS_IS_UNEXPECTED_NULL_STR = "Unexpected NULL"; +static const char* QS_IS_NO_TMPDIR_STR = "TMPDIR environment variable not set"; +static const char* QS_IS_UNABLE_TO_OPEN_DB_STR = "Unable to open database"; +static const char* QS_IS_UNABLE_TO_OPEN_SRC_DS_STR = "Unable to open src dataset"; +static const char* QS_IS_UNABLE_TO_GET_SRC_DRIVER_STR = "Unable to get src driver"; +static const char* QS_IS_UNABLE_TO_GET_SRC_DRIVER_NAME_STR = "Unable to get src driver name"; +static const char* QS_IS_UNABLE_TO_CONVERT_TO_GEOGRAPHIC_STR = "Unable to convert to geographic dataset"; +static const char* QS_IS_UNABLE_TO_CREATE_INFO_FILE_STR = "Unable to create info file"; +static const char* QS_IS_UNABLE_TO_OPEN_INFO_FILE_STR = "Unable to open info file"; +static const char* QS_IS_TIME_STRING_ERROR_STR = "Time string error"; +static const char* QS_IS_UNABLE_TO_GET_FACE_STRING_STR = "Unable to get face string"; +static const char* QS_IS_DB_NOT_INITIALIZED_STR = "Database not initialized"; +static const char* QS_IS_UNABLE_TO_CREATE_TN_INDEX_STR = "Unable to create texture name index"; +static const char* QS_IS_UNABLE_TO_INSERT_TS_INTO_LIST_STR = "Unable to insert texture set into list"; +static const char* QS_IS_EMPTY_TABLE_NAME_STR = "Empty table name"; +static const char* QS_IS_UNABLE_TO_CREATE_TABLE_STR = "Unable to create table"; +static const char* QS_IS_UNABLE_TO_CREATE_ID_INDEX_STR = "Unable to create id index"; +static const char* QS_IS_UNABLE_TO_CREATE_P_IMAGE_STR = "Unable to create polar image"; +static const char* QS_IS_UNABLE_TO_READ_FROM_RASTER_STR = "Unable to read from raster"; +static const char* QS_IS_FORMAT_NOT_IMPLEMENTED_STR = "Format not implemented"; +static const char* QS_IS_UNABLE_TO_WRITE_TO_BLOB_STR = "Unable to write to blob"; +static const char* QS_IS_UNABLE_SCALE_IMAGE_STR = "Unable to scale image"; +static const char* QS_IS_PREPARE_ERROR_STR = "Unable to prepare statement"; +static const char* QS_IS_TS_NOT_FOUND_STR = "Texture set not found"; +static const char* QS_IS_UNABLE_TO_UPDATE_EXTENTS_STR = "Unable to update extents"; +static const char* QS_IS_UNABLE_TO_WRITE_DATA_BUFFER_STR = "Unable to write data buffer"; +static const char* QS_IS_UNABLE_TO_READ_DATA_BUFFER_STR = "Unable to read data buffer"; +static const char* QS_IS_BUSY_STR = "Database is busy"; +static const char* QS_IS_UNABLE_TO_UPDATE_TIME_STR = "Unable to update time"; +static const char* QS_IS_UNABLE_TO_SET_NUM_BYTES_STR = "Unable to set num bytes"; +static const char* QS_IS_UNABLE_TO_GET_AVERAGE_REQUEST_TIME_STR = "Unable to get average request time"; +static const char* QS_IS_UNABLE_TO_REMOVE_OLDER_THAN_AVG_STR = "Unable to remove older than average"; +static const char* QS_IS_UNABLE_TO_SUM_NUMBER_OF_BYTES_STR = "Unable to sum number of bytes"; +static const char* QS_IS_UNABLE_TO_WRITE_TO_OUTPUT_DIR_STR = "Unable to write to output directory"; +static const char* QS_IS_COULD_NOT_CREATE_FUNCTION_STR = "Unable to create function"; +static const char* QS_IS_EMPTY_FUNCTION_NAME_STR = "Empty function name"; +static const char* QS_IS_UNABLE_TO_EXECUTE_FUNCTION_STR = "Unable to execture function"; +static const char* QS_IS_UNABLE_TO_WRITE_TO_RASTER_STR = "Unable to write to raster"; +static const char* QS_IS_EMPTY_FILENAME_STR = "Empty filename"; +static const char* QS_IS_SET_CREATION_FAILED_STR = "Attempted raster set creation failed"; +static const char* QS_IS_NO_TIME_STAMP_STR = "Unable to obtain timestamp"; + +const char* GetErrorString(const QsErrorType& errorValue) +{ + switch (errorValue) + { + case QS_IS_OK: + return QS_IS_OK_STR; + case QS_IS_COMMAND_LINE: + return QS_IS_COMMAND_LINE_STR; + case QS_IS_UNEXPECTED_NULL: + return QS_IS_UNEXPECTED_NULL_STR; + case QS_IS_NO_TMPDIR: + return QS_IS_NO_TMPDIR_STR; + case QS_IS_UNABLE_TO_OPEN_DB: + return QS_IS_UNABLE_TO_OPEN_DB_STR; + case QS_IS_UNABLE_TO_OPEN_SRC_DS: + return QS_IS_UNABLE_TO_OPEN_SRC_DS_STR; + case QS_IS_UNABLE_TO_GET_SRC_DRIVER: + return QS_IS_UNABLE_TO_GET_SRC_DRIVER_STR; + case QS_IS_UNABLE_TO_GET_SRC_DRIVER_NAME: + return QS_IS_UNABLE_TO_GET_SRC_DRIVER_NAME_STR; + case QS_IS_UNABLE_TO_CONVERT_TO_GEOGRAPHIC: + return QS_IS_UNABLE_TO_CONVERT_TO_GEOGRAPHIC_STR; + case QS_IS_UNABLE_TO_CREATE_INFO_FILE: + return QS_IS_UNABLE_TO_CREATE_INFO_FILE_STR; + case QS_IS_UNABLE_TO_OPEN_INFO_FILE: + return QS_IS_UNABLE_TO_OPEN_INFO_FILE_STR; + case QS_IS_TIME_STRING_ERROR: + return QS_IS_TIME_STRING_ERROR_STR; + case QS_IS_UNABLE_TO_GET_FACE_STRING: + return QS_IS_UNABLE_TO_GET_FACE_STRING_STR; + case QS_IS_DB_NOT_INITIALIZED: + return QS_IS_DB_NOT_INITIALIZED_STR; + case QS_IS_UNABLE_TO_CREATE_TN_INDEX: + return QS_IS_UNABLE_TO_CREATE_TN_INDEX_STR; + case QS_IS_UNABLE_TO_INSERT_TS_INTO_LIST: + return QS_IS_UNABLE_TO_INSERT_TS_INTO_LIST_STR; + case QS_IS_EMPTY_TABLE_NAME: + return QS_IS_EMPTY_TABLE_NAME_STR; + case QS_IS_UNABLE_TO_CREATE_TABLE: + return QS_IS_UNABLE_TO_CREATE_TABLE_STR; + case QS_IS_UNABLE_TO_CREATE_ID_INDEX: + return QS_IS_UNABLE_TO_CREATE_ID_INDEX_STR; + case QS_IS_UNABLE_TO_CREATE_P_IMAGE: + return QS_IS_UNABLE_TO_CREATE_P_IMAGE_STR; + case QS_IS_UNABLE_TO_READ_FROM_RASTER: + return QS_IS_UNABLE_TO_READ_FROM_RASTER_STR; + case QS_IS_FORMAT_NOT_IMPLEMENTED: + return QS_IS_FORMAT_NOT_IMPLEMENTED_STR; + case QS_IS_UNABLE_TO_WRITE_TO_BLOB: + return QS_IS_UNABLE_TO_WRITE_TO_BLOB_STR; + case QS_IS_UNABLE_SCALE_IMAGE: + return QS_IS_UNABLE_SCALE_IMAGE_STR; + case QS_IS_PREPARE_ERROR: + return QS_IS_PREPARE_ERROR_STR; + case QS_IS_TS_NOT_FOUND: + return QS_IS_TS_NOT_FOUND_STR; + case QS_IS_UNABLE_TO_UPDATE_EXTENTS: + return QS_IS_UNABLE_TO_UPDATE_EXTENTS_STR; + case QS_IS_UNABLE_TO_WRITE_DATA_BUFFER: + return QS_IS_UNABLE_TO_WRITE_DATA_BUFFER_STR; + case QS_IS_UNABLE_TO_READ_DATA_BUFFER: + return QS_IS_UNABLE_TO_READ_DATA_BUFFER_STR; + case QS_IS_BUSY: + return QS_IS_BUSY_STR; + case QS_IS_UNABLE_TO_UPDATE_TIME: + return QS_IS_UNABLE_TO_UPDATE_TIME_STR; + case QS_IS_UNABLE_TO_SET_NUM_BYTES: + return QS_IS_UNABLE_TO_SET_NUM_BYTES_STR; + case QS_IS_UNABLE_TO_GET_AVERAGE_REQUEST_TIME: + return QS_IS_UNABLE_TO_GET_AVERAGE_REQUEST_TIME_STR; + case QS_IS_UNABLE_TO_REMOVE_OLDER_THAN_AVG: + return QS_IS_UNABLE_TO_REMOVE_OLDER_THAN_AVG_STR; + case QS_IS_UNABLE_TO_SUM_NUMBER_OF_BYTES: + return QS_IS_UNABLE_TO_SUM_NUMBER_OF_BYTES_STR; + case QS_IS_UNABLE_TO_WRITE_TO_OUTPUT_DIR: + return QS_IS_UNABLE_TO_WRITE_TO_OUTPUT_DIR_STR; + case QS_IS_COULD_NOT_CREATE_FUNCTION: + return QS_IS_COULD_NOT_CREATE_FUNCTION_STR; + case QS_IS_EMPTY_FUNCTION_NAME: + return QS_IS_EMPTY_FUNCTION_NAME_STR; + case QS_IS_UNABLE_TO_EXECUTE_FUNCTION: + return QS_IS_UNABLE_TO_EXECUTE_FUNCTION_STR; + case QS_IS_UNABLE_TO_WRITE_TO_RASTER: + return QS_IS_UNABLE_TO_WRITE_TO_RASTER_STR; + case QS_IS_EMPTY_FILENAME: + return QS_IS_EMPTY_FILENAME_STR; + case QS_IS_SET_CREATION_FAILED: + return QS_IS_SET_CREATION_FAILED_STR; + case QS_IS_NO_TIME_STAMP: + return QS_IS_NO_TIME_STAMP_STR; + default: + std::cerr << "ERROR: Unrecognized error value (" << errorValue << ").\n"; + assert(0); + return QS_IS_UNRECOGNIZED_ERROR_VALUE_STR; + } +} + +} diff --git a/SDK/simVis/DB/QSError.h b/SDK/simVis/DB/QSError.h new file mode 100644 index 000000000..e4d3c42d1 --- /dev/null +++ b/SDK/simVis/DB/QSError.h @@ -0,0 +1,81 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#ifndef QS_ERROR_H +#define QS_ERROR_H + +#include + +namespace simVis_db +{ + //=========================================================================== + typedef int QsErrorType; + static const QsErrorType QS_IS_OK = 0; + static const QsErrorType QS_IS_COMMAND_LINE = 1; + static const QsErrorType QS_IS_UNEXPECTED_NULL = 2; + static const QsErrorType QS_IS_NO_TMPDIR = 3; + static const QsErrorType QS_IS_UNABLE_TO_OPEN_DB = 4; + static const QsErrorType QS_IS_UNABLE_TO_OPEN_SRC_DS = 5; + static const QsErrorType QS_IS_UNABLE_TO_GET_SRC_DRIVER = 6; + static const QsErrorType QS_IS_UNABLE_TO_GET_SRC_DRIVER_NAME = 7; + static const QsErrorType QS_IS_UNABLE_TO_CONVERT_TO_GEOGRAPHIC = 8; + static const QsErrorType QS_IS_UNABLE_TO_CREATE_INFO_FILE = 9; + static const QsErrorType QS_IS_UNABLE_TO_OPEN_INFO_FILE = 10; + static const QsErrorType QS_IS_TIME_STRING_ERROR = 11; + static const QsErrorType QS_IS_UNABLE_TO_GET_FACE_STRING = 12; + static const QsErrorType QS_IS_DB_NOT_INITIALIZED = 13; + static const QsErrorType QS_IS_UNABLE_TO_CREATE_TN_INDEX = 14; + static const QsErrorType QS_IS_UNABLE_TO_INSERT_TS_INTO_LIST = 15; + static const QsErrorType QS_IS_EMPTY_TABLE_NAME = 16; + static const QsErrorType QS_IS_UNABLE_TO_CREATE_TABLE = 17; + static const QsErrorType QS_IS_UNABLE_TO_CREATE_ID_INDEX = 18; + static const QsErrorType QS_IS_UNABLE_TO_CREATE_P_IMAGE = 19; + static const QsErrorType QS_IS_UNABLE_TO_READ_FROM_RASTER = 20; + static const QsErrorType QS_IS_FORMAT_NOT_IMPLEMENTED = 21; + static const QsErrorType QS_IS_UNABLE_TO_WRITE_TO_BLOB = 22; + static const QsErrorType QS_IS_UNABLE_SCALE_IMAGE = 23; + static const QsErrorType QS_IS_PREPARE_ERROR = 24; + static const QsErrorType QS_IS_TS_NOT_FOUND = 25; + static const QsErrorType QS_IS_UNABLE_TO_UPDATE_EXTENTS = 26; + static const QsErrorType QS_IS_UNABLE_TO_WRITE_DATA_BUFFER = 27; + static const QsErrorType QS_IS_UNABLE_TO_READ_DATA_BUFFER = 28; + static const QsErrorType QS_IS_BUSY = 29; + static const QsErrorType QS_IS_UNABLE_TO_UPDATE_TIME = 30; + static const QsErrorType QS_IS_UNABLE_TO_SET_NUM_BYTES = 31; + static const QsErrorType QS_IS_UNABLE_TO_GET_AVERAGE_REQUEST_TIME = 32; + static const QsErrorType QS_IS_UNABLE_TO_REMOVE_OLDER_THAN_AVG = 33; + static const QsErrorType QS_IS_UNABLE_TO_SUM_NUMBER_OF_BYTES = 34; + static const QsErrorType QS_IS_UNABLE_TO_WRITE_TO_OUTPUT_DIR = 35; + static const QsErrorType QS_IS_COULD_NOT_CREATE_FUNCTION = 36; + static const QsErrorType QS_IS_EMPTY_FUNCTION_NAME = 37; + static const QsErrorType QS_IS_UNABLE_TO_EXECUTE_FUNCTION = 38; + static const QsErrorType QS_IS_UNABLE_TO_WRITE_TO_RASTER = 39; + static const QsErrorType QS_IS_EMPTY_FILENAME = 40; + static const QsErrorType QS_IS_SET_CREATION_FAILED = 41; + static const QsErrorType QS_IS_NO_TIME_STAMP = 42; + + //=========================================================================== + const char* GetErrorString(const QsErrorType&); + +} // namespace simVis_db + +#endif /* QS_ERROR_H */ diff --git a/SDK/simVis/DB/QSNodeID96.cpp b/SDK/simVis/DB/QSNodeID96.cpp new file mode 100644 index 000000000..ccaa33a02 --- /dev/null +++ b/SDK/simVis/DB/QSNodeID96.cpp @@ -0,0 +1,302 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ +#include "swapbytes.h" +#include "QSNodeID96.h" + +namespace simVis_db { + +//=========================================================================== +QSNodeID96::QSNodeID96() + : one_(0), + two_(0), + three_(0) +{ +} + +//--------------------------------------------------------------------------- +QSNodeID96::QSNodeID96(const uint32_t& value) + : one_(value), + two_(0), + three_(0) +{ +} + +//--------------------------------------------------------------------------- +QSNodeID96::~QSNodeID96() +{ +} + +//--------------------------------------------------------------------------- +bool QSNodeID96::operator==(const QSNodeID96& value) const +{ + return ((one_ == value.one_) && (two_ == value.two_) && (three_ == value.three_)); +} + +//--------------------------------------------------------------------------- +bool QSNodeID96::operator<(const QSNodeID96& value) const +{ + if (one_ != value.one_) + return one_ < value.one_; + if (two_ != value.two_) + return two_ < value.two_; + return three_ < value.three_; +} + +//--------------------------------------------------------------------------- +QSNodeID96& QSNodeID96::operator=(const QSNodeID96& value) +{ + one_ = value.one_; + two_ = value.two_; + three_ = value.three_; + return *this; +} + +//--------------------------------------------------------------------------- +QSNodeID96 QSNodeID96::operator~() const +{ + QSNodeID96 returnValue = (*this); + returnValue.one_ = ~one_; + returnValue.two_ = ~two_; + returnValue.three_ = ~three_; + return returnValue; +} + +//--------------------------------------------------------------------------- +QSNodeID96& QSNodeID96::operator|=(const QSNodeID96& value) +{ + one_ |= value.one_; + two_ |= value.two_; + three_ |= value.three_; + return *this; +} + +//--------------------------------------------------------------------------- +QSNodeID96& QSNodeID96::operator&=(const QSNodeID96& value) +{ + one_ &= value.one_; + two_ &= value.two_; + three_ &= value.three_; + return *this; +} + +//--------------------------------------------------------------------------- +QSNodeID96 QSNodeID96::operator>>(int numBitsToShift) const +{ + QSNodeID96 returnValue; + if (numBitsToShift >= 0) + { + if (numBitsToShift == 32) + { + returnValue.one_ = two_; + returnValue.two_ = three_; + returnValue.three_ = 0; + } + else if (numBitsToShift == 0) + { + returnValue.one_ = one_; + returnValue.two_ = two_; + returnValue.three_ = three_; + } + else if (numBitsToShift == 64) + { + returnValue.one_ = three_; + returnValue.two_ = 0; + returnValue.three_ = 0; + } + else if (numBitsToShift < 32) + { + returnValue.three_ = (three_ >> numBitsToShift); + returnValue.two_ = (two_ >> numBitsToShift) | (three_ << (32 - numBitsToShift)); + returnValue.one_ = (one_ >> numBitsToShift) | (two_ << (32 - numBitsToShift)); + } + else if (numBitsToShift < 64) + { + returnValue.three_ = 0; + returnValue.two_ = three_ >> (numBitsToShift-32); + returnValue.one_ = (two_ >> (numBitsToShift-32)) | (three_ << (64 - numBitsToShift)); + } + else if (numBitsToShift < 96) + { + returnValue.three_ = 0; + returnValue.two_ = 0; + returnValue.one_ = three_ >> (numBitsToShift-64); + } + else + { + returnValue.one_ = 0; + returnValue.two_ = 0; + returnValue.three_ = 0; + } + } + else + returnValue.operator<<(-numBitsToShift); + + return returnValue; +} + +//--------------------------------------------------------------------------- +QSNodeID96 QSNodeID96::operator<<(int numBitsToShift) const +{ + QSNodeID96 returnValue; + if (numBitsToShift >= 0) + { + if (numBitsToShift == 32) + { + returnValue.one_ = 0; + returnValue.two_ = one_; + returnValue.three_ = two_; + } + else if (numBitsToShift == 0) + { + returnValue.one_ = one_; + returnValue.two_ = two_; + returnValue.three_ = three_; + } + else if (numBitsToShift == 64) + { + returnValue.one_ = 0; + returnValue.two_ = 0; + returnValue.three_ = one_; + } + else if (numBitsToShift < 32) + { + returnValue.one_ = one_ << numBitsToShift; + returnValue.two_ = (two_ << numBitsToShift) | (one_ >> (32 - numBitsToShift)); + returnValue.three_ = (three_ << numBitsToShift) | (two_ >> (32 - numBitsToShift)); + } + else if (numBitsToShift < 64) + { + returnValue.one_ = 0; + returnValue.two_ = one_ << (numBitsToShift-32); + returnValue.three_ = (two_ << (numBitsToShift-32)) | (one_ >> (64 - numBitsToShift)); + } + else if (numBitsToShift < 96) + { + returnValue.one_ = 0; + returnValue.two_ = 0; + returnValue.three_ = one_ << (numBitsToShift-64); + } + else + { + returnValue.three_ = 0; + returnValue.two_ = 0; + returnValue.one_ = 0; + } + } + else + returnValue.operator>>(-numBitsToShift); + + return returnValue; +} + +//--------------------------------------------------------------------------- +QSNodeID96 QSNodeID96::operator&(const QSNodeID96& value) const +{ + QSNodeID96 returnValue; + returnValue.one_ = one_ & value.one_; + returnValue.two_ = two_ & value.two_; + returnValue.three_ = three_ & value.three_; + return returnValue; +} + +//--------------------------------------------------------------------------- +void QSNodeID96::Pack(uint8_t* buffer) const +{ + if (buffer == NULL) + return; + bewrite(buffer, &three_); + bewrite(buffer + sizeof(three_), &two_); + bewrite(buffer + sizeof(three_) + sizeof(two_), &one_); +} + +//--------------------------------------------------------------------------- +void QSNodeID96::UnPack(const uint8_t* buffer) +{ + if (buffer == NULL) + return; + beread(buffer, &three_); + beread(buffer + sizeof(three_), &two_); + beread(buffer + sizeof(three_) + sizeof(two_), &one_); +} + +//--------------------------------------------------------------------------- +std::string QSNodeID96::FormatAsHex(bool bLeadingZeros) const +{ + std::string returnValue; + + char sTemp[64]; + + if (bLeadingZeros) + { + sprintf(sTemp, "%08x", three_); + returnValue += sTemp; + } + else + { + if (three_) + { + sprintf(sTemp, "%x", three_); + returnValue += sTemp; + } + } + + if (bLeadingZeros) + { + sprintf(sTemp, "%08x", two_); + returnValue += sTemp; + } + else + { + if (two_) + { + if (three_) + sprintf(sTemp, "%08x", two_); + else + sprintf(sTemp, "%x", two_); + returnValue += sTemp; + } + } + + if (bLeadingZeros) + { + sprintf(sTemp, "%08x", one_); + returnValue += sTemp; + } + else + { + if (one_) + { + if (three_ || two_) + sprintf(sTemp, "%08x", one_); + else + sprintf(sTemp, "%x", one_); + returnValue += sTemp; + } + } + + if (returnValue.empty()) + returnValue = "0"; + + return returnValue; +} + +} diff --git a/SDK/simVis/DB/QSNodeID96.h b/SDK/simVis/DB/QSNodeID96.h new file mode 100644 index 000000000..54d9cb6bc --- /dev/null +++ b/SDK/simVis/DB/QSNodeID96.h @@ -0,0 +1,64 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#ifndef QSNODEID96_H +#define QSNODEID96_H + +#include +#include "simCore/Common/Common.h" + +namespace simVis_db +{ + class QSNodeID96 + { + public: + QSNodeID96(); + QSNodeID96(const uint32_t& value); + ~QSNodeID96(); + + bool operator==(const QSNodeID96& value) const; + bool operator<(const QSNodeID96& value) const; + QSNodeID96& operator=(const QSNodeID96& value); + QSNodeID96 operator~() const; + QSNodeID96& operator|=(const QSNodeID96& value); + QSNodeID96& operator&=(const QSNodeID96& value); + QSNodeID96 operator>>(int numBitsToShift) const; + QSNodeID96 operator<<(int numBitsToShift) const; + QSNodeID96 operator&(const QSNodeID96& value) const; + + int SizeOf() const {return 12;} + void Pack(uint8_t*) const; + void UnPack(const uint8_t*); + std::string FormatAsHex(bool bLeadingZeros=true) const; + + protected: + uint32_t one_; + uint32_t two_; + uint32_t three_; + }; + + //=========================================================================== + typedef QSNodeID96 QSNodeId; + +} // namespace simVis_db + +#endif /* QSNODEID96_H */ diff --git a/SDK/simVis/DB/QSPosXYExtents.cpp b/SDK/simVis/DB/QSPosXYExtents.cpp new file mode 100644 index 000000000..6f49b8be3 --- /dev/null +++ b/SDK/simVis/DB/QSPosXYExtents.cpp @@ -0,0 +1,170 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#include +#include "simCore/Calc/Math.h" +#include "swapbytes.h" +#include "QSCommon.h" +#include "QSPosXYExtents.h" + +namespace simVis_db { + +//===================================================================================== +PosXPosYExtents::PosXPosYExtents(QsPosType minXIn, QsPosType maxXIn, QsPosType minYIn, QsPosType maxYIn) + : minX(minXIn), + maxX(maxXIn), + minY(minYIn), + maxY(maxYIn) +{ +} + +void PosXPosYExtents::Initialize() +{ + minX = gQsMaxLength; + maxX = 0; + minY = gQsMaxLength; + maxY = 0; +} + +bool PosXPosYExtents::Valid() const +{ + return ((minX >= maxX) || (minY >= maxY)) ? false : true; +} + +void PosXPosYExtents::SetAll(const PosXPosYExtents& given) +{ + minX = given.minX; + maxX = given.maxX; + minY = given.minY; + maxY = given.maxY; +} + +void PosXPosYExtents::SetAll(const QsPosType& minXIn, const QsPosType& maxXIn, const QsPosType& minYIn, const QsPosType& maxYIn) +{ + minX = minXIn; + maxX = maxXIn; + minY = minYIn; + maxY = maxYIn; +} + +void PosXPosYExtents::Pack(uint8_t* buffer) const +{ + if (buffer == NULL) + return; + bewrite(buffer, &minX); + bewrite(buffer + sizeof(minX), &maxX); + bewrite(buffer + sizeof(minX) + sizeof(maxX), &minY); + bewrite(buffer + sizeof(minX) + sizeof(maxX) + sizeof(minY), &maxY); +} + +void PosXPosYExtents::UnPack(const uint8_t* buffer) +{ + if (buffer == NULL) + return; + beread(buffer, &minX); + beread(buffer + sizeof(minX), &maxX); + beread(buffer + sizeof(minX) + sizeof(maxX), &minY); + beread(buffer + sizeof(minX) + sizeof(maxX) + sizeof(minY), &maxY); +} + +void PosXPosYExtents::Print() +{ + std::cerr << "minX = " << minX << "\n"; + std::cerr << "maxX = " << maxX << "\n"; + std::cerr << "minY = " << minY << "\n"; + std::cerr << "maxY = " << maxY << "\n"; +} + +//===================================================================================== +bool equalTo(const PosXPosYExtents& a, const PosXPosYExtents& b) +{ + if (a.minX != b.minX) return false; + if (a.maxX != b.maxX) return false; + if (a.minY != b.minY) return false; + if (a.maxY != b.maxY) return false; + return true; +} + +bool operator==(const PosXPosYExtents& a, const PosXPosYExtents& b) +{ + return equalTo(a, b); +} + +bool operator!=(const PosXPosYExtents& a, const PosXPosYExtents& b) +{ + return !simVis_db::equalTo(a, b); +} + +//===================================================================================== +void UpdateExtents(const QsPosType& posX, const QsPosType& posY, PosXPosYExtents* extents) +{ + if (extents == NULL) + return; + + extents->minX = simCore::sdkMin(extents->minX, posX); + extents->minY = simCore::sdkMin(extents->minY, posY); + extents->maxX = simCore::sdkMax(extents->maxX, posX); + extents->maxY = simCore::sdkMax(extents->maxY, posY); +} + +bool Copy6Extents(const PosXPosYExtents* copyFrom, PosXPosYExtents* copyTo) +{ + if ((copyFrom == NULL) || (copyTo == NULL)) + return false; + + FaceIndexType faceIndex; + for (faceIndex = 0; faceIndex < 6; ++faceIndex) + copyTo[faceIndex].SetAll(copyFrom[faceIndex]); + + return true; +} + +bool AnyOverlap(const PosXPosYExtents& extA, const PosXPosYExtents& extB) +{ + if ((extA.Valid() == false) || (extB.Valid() == false)) + return false; + + // checks for no x overlap + if ((extA.minX > extB.maxX) || + (extA.maxX < extB.minX)) + return false; + + // checks for no y overlap + if ((extA.minY > extB.maxY) || + (extA.maxY < extB.minY)) + return false; + + return true; +} + +bool AnyOverlap(const QsPosType& posX, const QsPosType& posY, const PosXPosYExtents& extents) +{ + if (extents.Valid() == false) + return false; + + return ((posX < extents.minX) || + (posX > extents.maxX) || + (posY < extents.minY) || + (posY > extents.maxY)) ? false : true; +} + +} diff --git a/SDK/simVis/DB/QSPosXYExtents.h b/SDK/simVis/DB/QSPosXYExtents.h new file mode 100644 index 000000000..e00f32be3 --- /dev/null +++ b/SDK/simVis/DB/QSPosXYExtents.h @@ -0,0 +1,85 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#ifndef QS_POSXY_EXTENTS_H +#define QS_POSXY_EXTENTS_H + +namespace simVis_db +{ + typedef uint64_t QsPosType; + +#if defined Linux || defined Solaris + static const QsPosType gQsMaxLength = 4294967296LL; +#else + static const QsPosType gQsMaxLength = 4294967296; +#endif + static const double gQsDMaxLength = 4294967296.0; + + /** A bounding rectangle of x/y extents */ + struct PosXPosYExtents + { + QsPosType minX; + QsPosType maxX; + QsPosType minY; + QsPosType maxY; + + PosXPosYExtents(QsPosType minX=gQsMaxLength, QsPosType maxX=0, QsPosType minY=gQsMaxLength, QsPosType maxY=0); + + /** Sets up invalid extents */ + void Initialize(); + + /** Confirms validity of extents */ + bool Valid() const; + + /** Sets the extents */ + void SetAll(const PosXPosYExtents& given); + void SetAll(const QsPosType& minX, const QsPosType& maxX, const QsPosType& minY, const QsPosType& maxY); + + /** Packs/unpacks the extents into or from a buffer */ + void Pack(uint8_t*) const; + void UnPack(const uint8_t*); + + /** Prints the extents to the console */ + void Print(); + }; + + //===================================================================================== + bool equalTo(const PosXPosYExtents& a, const PosXPosYExtents& b); + bool operator==(const PosXPosYExtents& a, const PosXPosYExtents& b); + bool operator!=(const PosXPosYExtents& a, const PosXPosYExtents& b); + + //===================================================================================== + /** Updates extents such that the given x/y is within the extents */ + void UpdateExtents(const QsPosType& posX, const QsPosType& posY, PosXPosYExtents* extents); + + /** Copies an array of 6 extents */ + bool Copy6Extents(const PosXPosYExtents*, PosXPosYExtents*); + + /** Checks for any overlap between two rectangles */ + bool AnyOverlap(const PosXPosYExtents&, const PosXPosYExtents&); + + /** Checks if the given x/y is within the given extents */ + bool AnyOverlap(const QsPosType& posX, const QsPosType& posY, const PosXPosYExtents&); + +} // Namespace simVis_db + +#endif /* QS_POSXY_EXTENTS_H */ diff --git a/SDK/simVis/DB/RasterCommon.h b/SDK/simVis/DB/RasterCommon.h new file mode 100644 index 000000000..e69de29bb diff --git a/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp b/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp new file mode 100644 index 000000000..b6a26cc5b --- /dev/null +++ b/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp @@ -0,0 +1,364 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#include +#include +#include "simCore/Time/Utils.h" +#include "swapbytes.h" +#include "QSCommon.h" +#include "SQLiteDataBaseReadUtil.h" + +namespace simVis_db { + +namespace +{ + //===================================================================================== + template + void UnPackArray(SomeClass* givenArray, const uint8_t* givenBuffer, const uint32_t& numElements) + { + if ((givenArray == NULL) || (givenBuffer == NULL)) + return; + + size_t i; + uint8_t tmpBuffer[sizeof(SomeClass)]; + for (i = 0; i < numElements; ++i) + { + memcpy(tmpBuffer, givenBuffer + (sizeof(SomeClass) * i), sizeof(SomeClass)); + givenArray[i].UnPack(tmpBuffer); + } + } + + static const int gMaxBufferSize = 20000000; + + std::string printExtendedErrorMessage(sqlite3* sqlite3Db) + { + std::stringstream errStr; + int extendedErrorCode = sqlite3_extended_errcode(sqlite3Db); + errStr << " Ext Err Code(" << extendedErrorCode << ") "; + // Extended Result Codes: http://www.sqlite.org/c3ref/c_abort_rollback.html + switch (extendedErrorCode) + { + case SQLITE_IOERR_READ: errStr << "SQLITE_IOERR_READ"; break; + case SQLITE_IOERR_SHORT_READ: errStr << "SQLITE_SHORT_READ"; break; + case SQLITE_IOERR_WRITE: errStr << "SQLITE_IOERR_WRITE"; break; + case SQLITE_IOERR_FSYNC: errStr << "SQLITE_IOERR_FSYNC"; break; + case SQLITE_IOERR_DIR_FSYNC: errStr << "SQLITE_IOERR_DIR_FSYNC"; break; + case SQLITE_IOERR_TRUNCATE: errStr << "SQLITE_IOERR_TRUNCATE"; break; + case SQLITE_IOERR_FSTAT: errStr << "SQLITE_IOERR_FSTAT"; break; + case SQLITE_IOERR_UNLOCK: errStr << "SQLITE_IOERR_UNLOCK"; break; + case SQLITE_IOERR_RDLOCK: errStr << "SQLITE_IOERR_RDLOCK"; break; + case SQLITE_IOERR_DELETE: errStr << "SQLITE_IOERR_DELETE"; break; + case SQLITE_IOERR_BLOCKED: errStr << "SQLITE_IOERR_BLOCKED"; break; + case SQLITE_IOERR_NOMEM: errStr << "SQLITE_IOERR_NOMEM"; break; + case SQLITE_IOERR_ACCESS: errStr << "SQLITE_IOERR_ACCESS"; break; + case SQLITE_IOERR_CHECKRESERVEDLOCK: errStr << "SQLITE_IOERR_CHECKRESERVEDLOCK"; break; + case SQLITE_IOERR_LOCK: errStr << "SQLITE_IOERR_LOCK"; break; + case SQLITE_IOERR_CLOSE: errStr << "SQLITE_IOERR_CLOSE"; break; + case SQLITE_IOERR_DIR_CLOSE: errStr << "SQLITE_IOERR_DIR_CLOSE"; break; + case SQLITE_IOERR_SHMOPEN: errStr << "SQLITE_IOERR_SHMOPEN"; break; + case SQLITE_IOERR_SHMSIZE: errStr << "SQLITE_IOERR_SHMSIZE"; break; + case SQLITE_IOERR_SHMLOCK: errStr << "SQLITE_IOERR_SHMLOCK"; break; + case SQLITE_IOERR_SHMMAP: errStr << "SQLITE_IOERR_SHMMAP"; break; + case SQLITE_IOERR_SEEK: errStr << "SQLITE_IOERR_SEEK"; break; + case SQLITE_LOCKED_SHAREDCACHE: errStr << "SQLITE_LOCKED_SHAREDCACHE"; break; + case SQLITE_BUSY_RECOVERY: errStr << "SQLITE_BUSY_RECOVERY"; break; + case SQLITE_CANTOPEN_NOTEMPDIR: errStr << "SQLITE_CANTOPEN_NOTEMPDIR"; break; + case SQLITE_CANTOPEN_ISDIR: errStr << "SQLITE_CANTOPEN_ISDIR"; break; + case SQLITE_CORRUPT_VTAB: errStr << "SQLITE_CORRUPT_VTAB"; break; + case SQLITE_READONLY_RECOVERY: errStr << "SQLITE_READONLY_RECOVERY"; break; + case SQLITE_READONLY_CANTLOCK: errStr << "SQLITE_READONLY_CANTLOCK"; break; + case SQLITE_ABORT_ROLLBACK: errStr << "SQLITE_ABORT_ROLLBACK"; break; + default: errStr << "UNK"; break; + } + errStr << ", Desc: " << sqlite3_errmsg(sqlite3Db) << "\n"; + return errStr.str(); + } +} + +//===================================================================================== +SQLiteDataBaseReadUtil::SQLiteDataBaseReadUtil() + : textureSetSelectCommand_(""), + tsInsertFileIdData_(2), + tsInsertSetTextureSetName_(1), + tsInsertSetIdRasterFormat_(2), + tsInsertSetIdPixelLength_(3), + tsInsertSetIdShallowestLevel_(4), + tsInsertSetIdDeepestLevel_(5), + tsInsertSetIdExtents_(6), + tsInsertSetIdSource_(7), + tsInsertSetIdClassification_(8), + tsInsertSetIdDescription_(9), + tsInsertSetIdTimeSpecified_(10), + tsInsertSetIdTimeValue_(11) +{ + QSNodeId nodeID; + sizeOfIdBlob_ = sizeof(FaceIndexType) + nodeID.SizeOf(); + + // Creates the command for reading an image from a "texture set" table + textureSetSelectFileCommand1_ = "SELECT * From \""; + textureSetSelectFileCommand2_ = "\" WHERE "; + textureSetSelectFileCommand2_.append(QS_TO_ID); + textureSetSelectFileCommand2_.append("=?"); + + // Creates the command for select a texture set row from a "list of texture sets" table + textureSetSelectCommand_ = "SELECT * From "; + textureSetSelectCommand_.append(QS_LIST_OF_TEXTURE_SETS_TABLE_NAME); + textureSetSelectCommand_.append(" WHERE "); + textureSetSelectCommand_.append(QS_TSO_NAME_OF_TEXTURE_SET_TABLE); + textureSetSelectCommand_.append("=?"); +} + +//------------------------------------------------------------------------------------- +SQLiteDataBaseReadUtil::~SQLiteDataBaseReadUtil() +{ +} + +//------------------------------------------------------------------------------------- +QsErrorType SQLiteDataBaseReadUtil::OpenDataBaseFile(const std::string& dbFileName, + sqlite3** sqlite3Db, + const int& flags) const +{ + if (dbFileName.empty() || (sqlite3Db == NULL)) + return QS_IS_UNABLE_TO_OPEN_DB; + + // Attempts to open the database file + int errorCode = sqlite3_open_v2(dbFileName.c_str(), sqlite3Db, flags, NULL); + if ((*sqlite3Db == 0) || (errorCode != SQLITE_OK)) + { + if ((errorCode == SQLITE_BUSY) || + (errorCode == SQLITE_LOCKED)) + return QS_IS_BUSY; + std::cerr << "OpenDataBaseFile sqlite3_open_v2 Error: " << dbFileName << "\n" << printExtendedErrorMessage(*sqlite3Db); + return QS_IS_UNABLE_TO_OPEN_DB; + } + if (sqlite3_exec(*sqlite3Db, "PRAGMA CACHE_SIZE=100;", NULL, NULL, NULL) != SQLITE_OK) + { + std::cerr << "Unable to set SQLite cache size " << dbFileName << "\n"; + std::cerr << printExtendedErrorMessage(*sqlite3Db); + } + + return QS_IS_OK; +} + +//------------------------------------------------------------------------------------- +QsErrorType SQLiteDataBaseReadUtil::TsReadDataBuffer(sqlite3* sqlite3Db, + const std::string& dbFileName, + const std::string& dataTableName, + const FaceIndexType& faceIndex, + const QSNodeId& nodeID, + TextureDataType** buffer, + uint32_t* bufferSize, + uint32_t* currentRasterSize, + bool allowLocalDB, + bool displayErrorMessage) const +{ + int returnValue; + + if ((buffer == NULL) || (bufferSize == NULL) || (currentRasterSize == NULL)) + return QS_IS_UNEXPECTED_NULL; + + *currentRasterSize = 0; + + if (dataTableName.empty() || dbFileName.empty()) + return QS_IS_EMPTY_TABLE_NAME; + + // opens the database + bool localDb = false; + QsErrorType tmpReturnValue; + if (sqlite3Db == NULL) + { + if (allowLocalDB == false) + return QS_IS_DB_NOT_INITIALIZED; + localDb = true; + tmpReturnValue = OpenDataBaseFile(dbFileName, &sqlite3Db, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX); + if (tmpReturnValue != QS_IS_OK) + return tmpReturnValue; + } + + std::string sqlCommand; + sqlCommand = textureSetSelectFileCommand1_; + sqlCommand.append(dataTableName); + sqlCommand.append(textureSetSelectFileCommand2_); + + // prepares the statement + sqlite3_stmt* stmt = 0; + returnValue = sqlite3_prepare_v2(sqlite3Db, sqlCommand.c_str(), static_cast(sqlCommand.length()), &stmt, NULL); + if (returnValue != SQLITE_OK) + { + if (displayErrorMessage && (returnValue != SQLITE_BUSY && returnValue != SQLITE_LOCKED)) + { + std::cerr << "TsReadDataBuffer sqlite3_prepare_v2 Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); + } + if (stmt != NULL) sqlite3_finalize(stmt); + if (localDb) sqlite3_close(sqlite3Db); + if ((returnValue == SQLITE_BUSY) || + (returnValue == SQLITE_LOCKED)) + return QS_IS_BUSY; + return QS_IS_PREPARE_ERROR; + } + + // binds id + uint8_t* idBlob = new uint8_t[sizeOfIdBlob_]; + bewrite(idBlob, &faceIndex); + nodeID.Pack(idBlob + sizeof(FaceIndexType)); + returnValue = sqlite3_bind_blob(stmt, 1, idBlob, sizeOfIdBlob_, SQLITE_TRANSIENT); + if (returnValue != SQLITE_OK && displayErrorMessage) + { + std::cerr << "TsReadDataBuffer sqlite3_bind_blob Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); + } + delete[] idBlob; + + // executes the statement + returnValue = sqlite3_step(stmt); + QsErrorType otherReturnValue = QS_IS_UNABLE_TO_READ_DATA_BUFFER; + if ((returnValue == SQLITE_ROW) || (returnValue == SQLITE_DONE)) + { + // gets the data + *currentRasterSize = sqlite3_column_bytes(stmt, tsInsertFileIdData_ - 1); + if ((*currentRasterSize > 0) && (*currentRasterSize <= static_cast(gMaxBufferSize))) + { + if (*currentRasterSize > (*bufferSize)) + { + if ((*buffer) != NULL) + delete[] * buffer; + *buffer = new uint8_t[*currentRasterSize]; + *bufferSize = (*currentRasterSize); + } + memcpy(*buffer, (const uint8_t*)sqlite3_column_blob(stmt, tsInsertFileIdData_ - 1), *currentRasterSize); + } + otherReturnValue = QS_IS_OK; + } + else if ((returnValue == SQLITE_BUSY) || (returnValue == SQLITE_LOCKED)) + { + otherReturnValue = QS_IS_BUSY; + } + else + { + if (displayErrorMessage) + { + std::cerr << "TsReadDataBuffer sqlite3_step Error(" << returnValue << "): " << dbFileName << "\n"; + std::cerr << "not done (" << nodeID.FormatAsHex().c_str() << ") " << printExtendedErrorMessage(sqlite3Db); + } + otherReturnValue = QS_IS_UNABLE_TO_READ_DATA_BUFFER; + } + + if (stmt != NULL) sqlite3_finalize(stmt); + if (localDb) + { + returnValue = sqlite3_close(sqlite3Db); + if (returnValue != SQLITE_OK && displayErrorMessage) + { + std::cerr << "TsReadDataBuffer localDb sqlite3_close Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); + } + } + return otherReturnValue; +} + +//------------------------------------------------------------------------------------- +QsErrorType SQLiteDataBaseReadUtil::TsGetSetFromListOfSetsTable(sqlite3* sqlite3Db, + const std::string& tableName, + int& rasterFormat, + int& pixelLength, + int& shallowLevel, + int& deepLevel, + PosXPosYExtents tmpExtents[6], + std::string& source, + std::string& classification, + std::string& description, + bool& timeSpecified, + simCore::TimeStamp& timeStamp) const +{ + if (sqlite3Db == NULL) + return QS_IS_DB_NOT_INITIALIZED; + if (tableName.empty()) + return QS_IS_EMPTY_TABLE_NAME; + + int returnValue; + QsErrorType otherReturnValue; + + // prepares the statement + sqlite3_stmt* stmt = 0; + returnValue = sqlite3_prepare_v2(sqlite3Db, textureSetSelectCommand_.c_str(), static_cast(textureSetSelectCommand_.length()), &stmt, NULL); + if (returnValue != SQLITE_OK) + { + std::cerr << "TsGetSetFromListOfSetsTable sqlite3_prepare_v2 Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); + if (stmt != NULL) sqlite3_finalize(stmt); + return QS_IS_PREPARE_ERROR; + } + + // binds the texture set name + returnValue = sqlite3_bind_text(stmt, 1, tableName.c_str(), int(tableName.length()), SQLITE_TRANSIENT); + if (returnValue != SQLITE_OK) + { + std::cerr << "TsGetSetFromListOfSetsTable sqlite3_bind_text Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); + } + + // executes the statement + returnValue = sqlite3_step(stmt); + if (returnValue > SQLITE_OK&& returnValue < SQLITE_ROW) + { + std::cerr << "TsGetSetFromListOfSetsTable sqlite3_step Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); + } + + if (returnValue == SQLITE_ROW) + { + // sets some texture set creation options + rasterFormat = sqlite3_column_int(stmt, tsInsertSetIdRasterFormat_ - 1); + pixelLength = sqlite3_column_int(stmt, tsInsertSetIdPixelLength_ - 1); + shallowLevel = sqlite3_column_int(stmt, tsInsertSetIdShallowestLevel_ - 1); + deepLevel = sqlite3_column_int(stmt, tsInsertSetIdDeepestLevel_ - 1); + UnPackArray(tmpExtents, (const uint8_t*)sqlite3_column_blob(stmt, tsInsertSetIdExtents_ - 1), 6); + source = (const char*)sqlite3_column_text(stmt, tsInsertSetIdSource_ - 1); + classification = (const char*)sqlite3_column_text(stmt, tsInsertSetIdClassification_ - 1); + description = (const char*)sqlite3_column_text(stmt, tsInsertSetIdDescription_ - 1); + timeSpecified = (sqlite3_column_int(stmt, tsInsertSetIdTimeSpecified_ - 1) != 0); + + if (timeSpecified) + { + const uint8_t* buffer = (const uint8_t*)sqlite3_column_blob(stmt, tsInsertSetIdTimeValue_ - 1); + int refYear = 0; + int secs = 0; + int frac = 0; + + // read TimeStamp data members from buffer + beread(buffer, &refYear); + beread(buffer + sizeof(refYear), &(secs)); + beread(buffer + sizeof(refYear) + sizeof(secs), &(frac)); + simCore::Seconds secsSinceRefYear(secs, frac); + timeStamp.setTime(refYear, secsSinceRefYear); + } + otherReturnValue = QS_IS_OK; + } + else if (returnValue == SQLITE_BUSY) + { + otherReturnValue = QS_IS_BUSY; + } + else + { + otherReturnValue = QS_IS_TS_NOT_FOUND; + } + + if (stmt != NULL) sqlite3_finalize(stmt); + return otherReturnValue; +} + +} diff --git a/SDK/simVis/DB/SQLiteDataBaseReadUtil.h b/SDK/simVis/DB/SQLiteDataBaseReadUtil.h new file mode 100644 index 000000000..db708e850 --- /dev/null +++ b/SDK/simVis/DB/SQLiteDataBaseReadUtil.h @@ -0,0 +1,162 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#ifndef SQLITE_DATABASE_READ_UTIL_H +#define SQLITE_DATABASE_READ_UTIL_H + +#include +#include "sqlite3.h" +#include "simCore/Time/TimeClass.h" +#include "QSCommon.h" +#include "QSError.h" +#include "QSNodeID96.h" +#include "QSPosXYExtents.h" + +// Temporary defines until we update sqlite +#ifndef SQLITE_OPEN_READONLY +#define SQLITE_OPEN_READONLY 0x00000001 +#define SQLITE_OPEN_READWRITE 0x00000002 +#define SQLITE_OPEN_CREATE 0x00000004 +#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 +#define SQLITE_OPEN_EXCLUSIVE 0x00000010 +#define SQLITE_OPEN_MAIN_DB 0x00000100 +#define SQLITE_OPEN_TEMP_DB 0x00000200 +#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 +#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 +#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 +#define SQLITE_OPEN_SUBJOURNAL 0x00002000 +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 +#define SQLITE_OPEN_NOMUTEX 0x00008000 +#define SQLITE_OPEN_FULLMUTEX 0x00010000 +#endif /* SQLITE_OPEN_READONLY */ + +namespace simVis_db +{ + static const char* QS_TO_ID = "id"; + + //===================================================================================== + static const char* QS_DEFAULT_SET_TABLE_NAME = "default"; + static const char* SPLITTER_STRING_OUTPUTDB = "dbFile"; + static const char* SIMQS_CONFIG_TABLENAME_KEYWORD = "tableName"; + static const char* QS_LIST_OF_TEXTURE_SETS_TABLE_NAME = "ListOfTextureSets"; + static const char* QS_TSO_NAME_OF_TEXTURE_SET_TABLE = "nt"; + static const char* QS_TSO_OUTPUT_TYPE = "ot"; + static const char* QS_TSO_PIXEL_LENGTH = "pl"; + static const char* QS_TSO_SHALLOWEST_LEVEL = "sl"; + static const char* QS_TSO_DEEPEST_LEVEL = "dl"; + static const char* QS_TSO_EXTENTS = "ex"; + static const char* QS_TSO_SOURCE = "s"; + static const char* QS_TSO_CLASSIFICATION = "c"; + static const char* QS_TSO_DESCRIPTION = "ds"; + static const char* QS_TSO_TIME_SPECIFIED = "ts"; + + //===================================================================================== + class SQLiteDataBaseReadUtil + { + public: + SQLiteDataBaseReadUtil(); + virtual ~SQLiteDataBaseReadUtil(); + + /** Opens a database file */ + QsErrorType OpenDataBaseFile(const std::string& dbFileName, + sqlite3** sqlite3Db, + const int& flags) const; + + /** + * Gets TextureSet information about a data table + * @param[in] sqlite3Db Pointer to a SQLite database object + * @param[in] tableName Name of the table to access within the given database + * The following are TextureSet creation options + * @param[out] rasterFormat Flag that determines how the texture image is drawn + * @param[out] pixelLength Tile size of the TextureSet + * @param[out] shallowLevel Minimum depth of the TextureSet + * @param[out] deepLevel Maximum depth of the TextureSet + * @param[out] tmpExtents Stores the TextureSet's X/Y extent values + * @param[out] source Name of the TextureSet's source file + * @param[out] classification Classification information of the loaded TextureSet + * @param[out] description Description of the loaded TextureSet + * @param[out] timeSpecified Whether or not a valid timeStamp was specified for the source file + * @param[out] timeStamp Loads a time value, if there is a valid timeStamp on the file + * @return Returns 0 on success, otherwise returns an error value mapped to QsErrorType. + */ + QsErrorType TsGetSetFromListOfSetsTable(sqlite3* sqlite3Db, + const std::string& tableName, + int& rasterFormat, + int& pixelLength, + int& shallowLevel, + int& deepLevel, + PosXPosYExtents tmpExtents[6], + std::string& source, + std::string& classification, + std::string& description, + bool& timeSpecified, + simCore::TimeStamp& timeStamp) const; + + /** + * Reads a node's data buffer from a sets table; caller is responsible for deleting buffer + * @param[in] sqlite3Db Pointer to a SQLite database object + * @param[in] dbFileName Name of a SQLite database file, used to fetch a database if sqlite3Db == NULL + * @param[in] dataTableName Name of the table to access within the given database + * @param[in] faceIndex Mapping to a face index/orientation, used to create a SQLite idBlob + * @param[in] nodeID Used to fill the idBlob + * @param[out] buffer Destination for data from the SQLite database + * @param[in, out] bufferSize Current max size of the buffer, will be changed if data to be copied is greater than max + * @param[out] currentRasterSize Size (bytes) of the data from the SQLite database + * @param[in] allowLocalDB Determines whether to fall back to a local database pointed to by dbFileName + * @param[in] displayErrorMessage Determines whether to display error messages to console when failing + * @return An error value, mapped to QsErrorType + */ + QsErrorType TsReadDataBuffer(sqlite3* sqlite3Db, + const std::string& dbFileName, + const std::string& dataTableName, + const FaceIndexType& faceIndex, + const QSNodeId& nodeID, + TextureDataType** buffer, + uint32_t* bufferSize, + uint32_t* currentRasterSize, + bool allowLocalDB, + bool displayErrorMessage=false) const; + protected: + int sizeOfIdBlob_; + + std::string textureSetSelectCommand_; + std::string textureSetSelectFileCommand1_; + std::string textureSetSelectFileCommand2_; + + // ids for inserting a "texture set" into a "list of texture sets" table + int tsInsertFileIdData_; + int tsInsertSetTextureSetName_; + int tsInsertSetIdRasterFormat_; + int tsInsertSetIdPixelLength_; + int tsInsertSetIdShallowestLevel_; + int tsInsertSetIdDeepestLevel_; + int tsInsertSetIdExtents_; + int tsInsertSetIdSource_; + int tsInsertSetIdClassification_; + int tsInsertSetIdDescription_; + int tsInsertSetIdTimeSpecified_; + int tsInsertSetIdTimeValue_; + }; + +} // namespace simVis_db + +#endif /* SQLITE_DATABASE_READ_UTIL_H */ diff --git a/SDK/simVis/DB/swapbytes.h b/SDK/simVis/DB/swapbytes.h new file mode 100644 index 000000000..e80d007f4 --- /dev/null +++ b/SDK/simVis/DB/swapbytes.h @@ -0,0 +1,780 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#ifndef SIMUTIL_SWAPBYTES_H +#define SIMUTIL_SWAPBYTES_H + +#include +#include +#include +#include +#include "simCore/Common/Common.h" + +#if !defined(SIM_LITTLE_ENDIAN) && !defined(SIM_BIG_ENDIAN) +#if defined(X86) || defined(ALPHA) || defined(__x86_64__) || defined(_WIN64) || defined(WIN32) +#define SIM_LITTLE_ENDIAN +#endif +#endif + +#ifndef BYTESWAPSHIFT + +namespace simVis_db +{ + template + inline + void swap_bytes(T *const value, const size_t nItems = 1) + { + // using namespace std; + for (size_t i = 0; i < nItems; ++i) + { + char *ptr = (char*)&value[i]; // Treat value as an array of bytes + size_t size = sizeof(T); + size_t halfSize = size >> 1; + size_t end = size - 1; + for (size_t i = 0; i < halfSize; ++i) + std::swap(ptr[end - i], ptr[i]); + } + } + + template + inline + T swap_bytes_return(const T &value, const size_t nItems = 1) + { + T temp = value; + swap_bytes(&temp); + return temp; + } + +#ifdef SIM_LITTLE_ENDIAN + + template + inline + void make_little_endian_(T *const value) + { + } + + template + inline + void make_big_endian_(T *const value) + { + swap_bytes(value); + } + +#else + + template + inline + void make_little_endian_(T *const value) + { + swap_bytes(value); + } + + template + inline + void make_big_endian_(T *const value) + { + } + +#endif + + inline + void make_big_endian(char *const val) { make_big_endian_(val); } + inline + void make_big_endian(int8_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(uint8_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(int16_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(uint16_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(int32_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(uint32_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(int64_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(uint64_t *const val) { make_big_endian_(val); } + inline + void make_big_endian(float *const val) { make_big_endian_(val); } + inline + void make_big_endian(double *const val) { make_big_endian_(val); } + + inline + void make_little_endian(char *const val) { make_little_endian_(val); } + inline + void make_little_endian(int8_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(uint8_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(int16_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(uint16_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(int32_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(uint32_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(int64_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(uint64_t *const val) { make_little_endian_(val); } + inline + void make_little_endian(float *const val) { make_little_endian_(val); } + inline + void make_little_endian(double *const val) { make_little_endian_(val); } + + template + inline + void make_big_endian(T *const value, const size_t nItems) + { + for (size_t i = 0; i < nItems; ++i) + { + make_big_endian(&value[i]); + } + } + + template + inline + void make_little_endian(T *const value, const size_t nItems) + { + for (size_t i = 0; i < nItems; ++i) + { + make_little_endian(&value[i]); + } + } + + template + inline + size_t beread(FILE *stream, T *const val, const size_t nItems = 1) + { + size_t nItemsRead = fread(val, sizeof(T), nItems, stream); + make_big_endian(val, nItemsRead); + return nItemsRead; + } + + template + inline + size_t bewrite(FILE *stream, const T *const val, const size_t nItems = 1) + { + size_t nItemsWrote = 0; + for (size_t i = 0; i < nItems; ++i) + { + T temp = val[i]; + make_big_endian(&temp); + if (fwrite(&temp, sizeof(T), 1, stream) != 1) + break; + ++nItemsWrote; + } + return nItemsWrote; + } + + template + inline + size_t leread(FILE *stream, T *const val, const size_t nItems = 1) + { + size_t nItemsRead = fread(val, sizeof(T), nItems, stream); + make_little_endian(val, nItemsRead); + return nItemsRead; + } + + template + inline + size_t lewrite(FILE *stream, const T *const val, const size_t nItems = 1) + { + size_t nItemsWrote = 0; + for (size_t i = 0; i < nItems; ++i) + { + T temp = val[i]; + make_little_endian(&temp); + if (fwrite(&temp, sizeof(T), 1, stream) != 1) + break; + ++nItemsWrote; + } + return nItemsWrote; + } + + template + inline + size_t beread(std::istream &stream, T *const val, const std::streamsize nItems = 1) + { + stream.read((char *)val, nItems * sizeof(T)); + size_t nItemsRead = stream.gcount() / sizeof(T); + make_big_endian(val, nItemsRead); + return nItemsRead; + } + + template + inline + size_t bewrite(std::ostream &stream, const T *const val, const size_t nItems = 1) + { + size_t nItemsWrote = 0; + for (size_t i = 0; i < nItems; ++i) + { + T temp = val[i]; + make_big_endian(&temp); + stream.write((const char *)&temp, sizeof(T)); + if (stream.bad()) + break; + ++nItemsWrote; + } + return nItemsWrote; + } + + template + inline + size_t leread(std::istream &stream, T *const val, const size_t nItems = 1) + { + stream.read((char *)val, nItems * sizeof(T)); + size_t nItemsRead = stream.gcount() / sizeof(T); + make_little_endian(val, nItemsRead); + return nItemsRead; + } + + template + inline + size_t lewrite(std::ostream &stream, const T *const val, const size_t nItems = 1) + { + size_t nItemsWrote = 0; + for (size_t i = 0; i < nItems; ++i) + { + T temp = val[i]; + make_little_endian(&temp); + stream.write((const char *)&temp, sizeof(T)); + if (stream.bad()) + break; + ++nItemsWrote; + } + return nItemsWrote; + } + + template + inline + size_t beread(const void *const stream, T *const val, const size_t nItems = 1) + { + memcpy(val, stream, nItems * sizeof(T)); + make_big_endian(val, nItems); + return nItems; + } + + template + inline + size_t bewrite(void *const stream, const T *const val, const size_t nItems = 1) + { + memcpy(stream, val, nItems * sizeof(T)); + make_big_endian((T *)stream, nItems); + return nItems; + } + + template + inline + size_t leread(const void *const stream, T *const val, const size_t nItems = 1) + { + memcpy(val, stream, nItems * sizeof(T)); + make_little_endian(val, nItems); + return nItems; + } + + template + inline + size_t lewrite(void *const stream, const T *const val, const size_t nItems = 1) + { + memcpy(stream, val, nItems * sizeof(T)); + make_little_endian((T *)stream, nItems); + return nItems; + } + +#else + +// Swap macros. +#define SWAP16(val)((((val)>>8)&0xff)|(((val)<<8)&0xff00)) +#define SWAP32(val)((((val)>>24)&0xff)|(((val)>>8)&0xff00)|(((val)<<8)&0xff0000)|(((val)<<24)&0xff000000)) +#ifdef __GNUC__ +#define SWAP64(val)((((val)>>56)&0xffLL)|(((val)>>40)&0xff00LL)|(((val)>>24)&0xff0000LL)|(((val)>>8)&0xff000000LL)| \ + (((val)<<8)&0xff00000000LL)|(((val)<<24)&0xff0000000000LL)|(((val)<<40)&0xff000000000000LL)|(((val)<<56)&0xff00000000000000LL)) +#else +#define SWAP64(val)((((val)>>56)&0xffL)|(((val)>>40)&0xff00L)|(((val)>>24)&0xff0000L)|(((val)>>8)&0xff000000L)| \ + (((val)<<8)&0xff00000000L)|(((val)<<24)&0xff0000000000L)|(((val)<<40)&0xff000000000000L)|(((val)<<56)&0xff00000000000000L)) +#endif + + // Generic byte swapping routines. + template inline void swap_bytes(T *const value) + { + char *ptr=(char*)(void*)value; // Treat value as an array of bytes + size_t size = sizeof(T); + register size_t halfSize = size >> 1; + register size_t end = size - 1; + for (register size_t i = 0; i < halfSize; ++i) + std::swap(ptr[end - i], ptr[i]); + } + + template inline void swap_bytes(T *const value, register const size_t nItems) + { + for (register size_t i=0;i> 1; + register size_t end = size - 1; + for (register size_t i = 0; i < halfSize; ++i) + std::swap(ptr[end - i], ptr[i]); + } + } + + + // Specialized routines. + + // NULL routines. + template<> inline void swap_bytes(char *const value) {} + template<> inline void swap_bytes(char *const value, register const size_t nItems) {} + template<> inline void swap_bytes(int8_t *const value) {} + template<> inline void swap_bytes(uint8_t *const value) {} + template<> inline void swap_bytes(int8_t *const value, register const size_t nItems) {} + template<> inline void swap_bytes(uint8_t *const value, register const size_t nItems) {} + + // Single item routines. + template<> inline void swap_bytes(int16_t *const value) { *value=SWAP16(*value); } + template<> inline void swap_bytes(uint16_t *const value) { *value=SWAP16(*value); } + template<> inline void swap_bytes(int32_t *const value) { *value=SWAP32(*value); } + template<> inline void swap_bytes(uint32_t *const value) { *value=SWAP32(*value); } + template<> inline void swap_bytes(int64_t *const value) { *value=SWAP64(*value); } + template<> inline void swap_bytes(uint64_t *const value) { *value=SWAP64(*value); } + + template<> inline void swap_bytes(float *const value) + { + int32_t *const pseudo=(int32_t*)(void*)value; + *pseudo=SWAP32(*pseudo); + } + + template<> inline void swap_bytes(double *const value) + { + int64_t *const pseudo=(int64_t*)(void*)value; + *pseudo=SWAP64(*pseudo); + } + + #ifdef SIM_LITTLE_ENDIAN + template inline void make_little_endian(T *const value) {} + + // Generic swap. Has a '_' prefix to prevent it from accidently being used with structs, etc. + template inline void make_little_endian_(T *const value) {} + template inline void make_big_endian_(T *const value) { swap_bytes(value); } + + inline void make_big_endian(char *const value) {} + inline void make_big_endian(int8_t *const value) {} + inline void make_big_endian(uint8_t *const value) {} + inline void make_big_endian(int16_t *const value) { *value=SWAP16(*value); } + inline void make_big_endian(uint16_t *const value) { *value=SWAP16(*value); } + inline void make_big_endian(int32_t *const value) { *value=SWAP32(*value); } + inline void make_big_endian(uint32_t *const value) { *value=SWAP32(*value); } + inline void make_big_endian(int64_t *const value) { *value=SWAP64(*value); } + inline void make_big_endian(uint64_t *const value) { *value=SWAP64(*value); } + + inline void make_big_endian(float *const value) + { + int32_t *const pseudo=(int32_t*)(void*)value; + *pseudo=SWAP32(*pseudo); + } + + inline void make_big_endian(double *const value) + { + int64_t *const pseudo=(int64_t*)(void*)value; + *pseudo=SWAP64(*pseudo); + } +#else + template inline void make_big_endian(T *const value) {} + template inline void make_big_endian_(T *const value) {} + template inline void make_little_endian_(T *const value) { swap_bytes(value); } + + inline void make_little_endian(char *const value) {} + inline void make_little_endian(int8_t *const value) {} + inline void make_little_endian(uint8_t *const value) {} + inline void make_little_endian(int16_t *const value) { *value=SWAP16(*value); } + inline void make_little_endian(uint16_t *const value) { *value=SWAP16(*value); } + inline void make_little_endian(int32_t *const value) { *value=SWAP32(*value); } + inline void make_little_endian(uint32_t *const value) { *value=SWAP32(*value); } + inline void make_little_endian(int64_t *const value) { *value=SWAP64(*value); } + inline void make_little_endian(uint64_t *const value) { *value=SWAP64(*value); } + + inline void make_little_endian(float *const value) + { + int32_t *const pseudo=(int32_t*)(void*)value; + *pseudo=SWAP32(*pseudo); + } + + inline void make_little_endian(double *const value) + { + int64_t *const pseudo=(int64_t*)(void*)value; + *pseudo=SWAP64(*pseudo); + } +#endif + + // Multi item routines. + template<> inline void swap_bytes(int16_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); + } + + template<> inline void swap_bytes(uint16_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); + } + + template<> inline void swap_bytes(int32_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); + } + + template<> inline void swap_bytes(uint32_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); + } + + template<> inline void swap_bytes(int64_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); + } + + template<> inline void swap_bytes(uint64_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); + } + + template<> inline void swap_bytes(float *const value, register const size_t nItems) + { + int32_t *const pseudo=(int32_t*)(void*)value; + for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP32(pseudo[i]); + } + + template<> inline void swap_bytes(double *const value, register const size_t nItems) + { + int64_t *const pseudo=(int64_t*)(void*)value; + for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP64(pseudo[i]); + } + +#ifdef SIM_LITTLE_ENDIAN + template inline void make_little_endian(T *const value, register const size_t nItems) {} + template inline void make_little_endian_(T *const value, register const size_t nItems) {} + template inline void make_big_endian_(T *const value, register const size_t nItems) { swap_bytes(value, nItems); } + + inline void make_big_endian(char *const value, register const size_t nItems) {} + inline void make_big_endian(int8_t *const value, register const size_t nItems) {} + inline void make_big_endian(uint8_t *const value, register const size_t nItems) {} + + inline void make_big_endian(int16_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); + } + + inline void make_big_endian(uint16_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); + } + + inline void make_big_endian(int32_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); + } + + inline void make_big_endian(uint32_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); + } + + inline void make_big_endian(int64_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); + } + + inline void make_big_endian(uint64_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); + } + + inline void make_big_endian(float *const value, register const size_t nItems) + { + int32_t *const pseudo = (int32_t*)(void*)value; + for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP32(pseudo[i]); + } + + inline void make_big_endian(double *const value, register const size_t nItems) + { + int64_t *const pseudo = (int64_t*)(void*)value; + for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP64(pseudo[i]); + } +#else + template inline void make_big_endian(T *const value, register const size_t nItems) {} + template inline void make_big_endian_(T *const value, register const size_t nItems) {} + template inline void make_little_endian_(T *const value, register const size_t nItems) { swap_bytes(value, nItems); } + + inline void make_little_endian(char *const value, register const size_t nItems) {} + inline void make_little_endian(int8_t *const value, register const size_t nItems) {} + inline void make_little_endian(uint8_t *const value, register const size_t nItems) {} + + inline void make_little_endian(int16_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); + } + + inline void make_little_endian(uint16_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); + } + + inline void make_little_endian(int32_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); + } + + inline void make_little_endian(uint32_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); + } + + inline void make_little_endian(int64_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); + } + + inline void make_little_endian(uint64_t *const value, register const size_t nItems) + { + for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); + } + + inline void make_little_endian(float *const value, register const size_t nItems) + { + int32_t *const pseudo = (int32_t*)(void*)value; + for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP32(pseudo[i]); + } + + inline void make_little_endian(double *const value, register const size_t nItems) + { + int64_t *const pseudo = (int64_t*)(void*)value; + for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP64(pseudo[i]); + } + #endif + + + // Swapped I\O + template inline size_t beread(FILE *stream, T *const val) + { + size_t nItemsRead = fread(val, sizeof(T), 1, stream); + make_big_endian(val); + return nItemsRead; + } + + template inline size_t beread(FILE *stream, T *const val, register const size_t nItems) + { + size_t nItemsRead = fread(val, sizeof(T), nItems, stream); + make_big_endian(val, nItemsRead); + return nItemsRead; + } + + template inline size_t bewrite(FILE *stream, const T *const val) + { + T temp = *val; + make_big_endian(&temp); + return fwrite(&temp, sizeof(T), 1, stream); + } + + template inline size_t bewrite(FILE *stream, const T *const val, register const size_t nItems) + { + register size_t nItemsWrit = 0; + while (nItemsWrit < nItems) + { + T temp = val[nItemsWrit++]; + make_big_endian(&temp); + if (fwrite(&temp, sizeof(T), 1, stream)!=1) + break; + } + return nItemsWrit; + } + + template inline size_t leread(FILE *stream, T *const val) + { + size_t nItemsRead = fread(val, sizeof(T), 1, stream); + make_little_endian(val); + return nItemsRead; + } + + template inline size_t leread(FILE *stream, T *const val, register const size_t nItems) + { + size_t nItemsRead = fread(val, sizeof(T), nItems, stream); + make_little_endian(val, nItemsRead); + return nItemsRead; + } + + template inline size_t lewrite(FILE *stream, const T *const val) + { + T temp = *val; + make_little_endian(&temp); + return fwrite(&temp, sizeof(T), 1, stream); + } + + template inline size_t lewrite(FILE *stream, const T *const val, register const size_t nItems) + { + register size_t nItemsWrit = 0; + while (nItemsWrit < nItems) + { + T temp = val[nItemsWrit++]; + make_little_endian(&temp); + if (fwrite(&temp, sizeof(T), 1, stream) != 1) + break; + } + return nItemsWrit; + } + + template inline size_t beread(std::istream &stream, T *const val) + { + stream.read((char *)val, sizeof(T)); + size_t nItemsRead = stream.gcount() / sizeof(T); + make_big_endian(val); + return nItemsRead; + } + + template inline size_t beread(std::istream &stream, T *const val, register const size_t nItems) + { + stream.read((char *)val, nItems * sizeof(T)); + size_t nItemsRead = stream.gcount() / sizeof(T); + make_big_endian(val, nItemsRead); + return nItemsRead; + } + + template inline size_t bewrite(std::ostream &stream, const T *const val) + { + T temp = *val; + make_big_endian(&temp); + stream.write((const char *)&temp, sizeof(T)); + return (stream.bad()) ? 0 : 1; + } + + template inline size_t bewrite(std::ostream &stream, const T *const val, register const size_t nItems) + { + register size_t nItemsWrit = 0; + while (nItemsWrit < nItems) + { + T temp = val[nItemsWrit++]; + make_big_endian(&temp); + stream.write((const char *)&temp, sizeof(T)); + if (stream.bad()) + break; + } + return nItemsWrit; + } + + template inline size_t leread(std::istream &stream, T *const val) + { + stream.read((char *)val, sizeof(T)); + size_t nItemsRead = stream.gcount()/sizeof(T); + make_little_endian(val); + return nItemsRead; + } + + template inline size_t leread(std::istream &stream, T *const val, register const size_t nItems) + { + stream.read((char *)val, nItems * sizeof(T)); + size_t nItemsRead = stream.gcount() / sizeof(T); + make_little_endian(val, nItemsRead); + return nItemsRead; + } + + template inline size_t lewrite(std::ostream &stream, const T *const val) + { + T temp = *val; + make_little_endian(&temp); + stream.write((const char *)&temp, sizeof(T)); + return (stream.bad()) ? 0 : 1; + } + + template inline size_t lewrite(std::ostream &stream, const T *const val, register const size_t nItems) + { + size_t nItemsWrit = 0; + while (nItemsWrit < nItems) + { + T temp = val[nItemsWrit++]; + make_little_endian(&temp); + stream.write((const char *)&temp, sizeof(T)); + if (stream.bad()) + break; + } + return nItemsWrit; + } + + template inline size_t beread(const void *const stream, T *const val) + { + memcpy(val, stream, sizeof(T)); + make_big_endian(val); + return 1; + } + + template inline size_t beread(const void *const stream, T *const val, register const size_t nItems) + { + memcpy(val, stream, nItems * sizeof(T)); + make_big_endian(val, nItems); + return nItems; + } + + template inline size_t bewrite(void *const stream, const T *const val) + { + memcpy(stream, val, sizeof(T)); + make_big_endian((T *)stream); + return 1; + } + + template inline size_t bewrite(void *const stream, const T *const val, register const size_t nItems) + { + memcpy(stream, val, nItems * sizeof(T)); + make_big_endian((T *)stream, nItems); + return nItems; + } + + template inline size_t leread(const void *const stream, T *const val) + { + memcpy(val, stream, sizeof(T)); + make_little_endian(val); + return 1; + } + + template inline size_t leread(const void *const stream, T *const val, register const size_t nItems) + { + memcpy(val, stream, nItems * sizeof(T)); + make_little_endian(val, nItems); + return nItems; + } + + template inline size_t lewrite(void *const stream, const T *const val) + { + memcpy(stream, val, sizeof(T)); + make_little_endian((T *)stream); + return 1; + } + + template inline size_t lewrite(void *const stream, const T *const val, register const size_t nItems) + { + memcpy(stream, val, nItems * sizeof(T)); + make_little_endian((T *)stream, nItems); + return nItems; + } + +#endif + +} // namespace simVis_db + +#endif /* SIMUTIL_SWAPBYTES_H */ diff --git a/SDK/simVis/DBFormat.cpp b/SDK/simVis/DBFormat.cpp index 04c2fd7e5..001c0f39c 100644 --- a/SDK/simVis/DBFormat.cpp +++ b/SDK/simVis/DBFormat.cpp @@ -21,109 +21,828 @@ */ #include "osgDB/FileUtils" #include "simVis/DBFormat.h" +#include "simVis/DB/QSCommon.h" +#include "simVis/DB/swapbytes.h" +#include "simVis/DB/SQLiteDataBaseReadUtil.h" +#include "simCore/Calc/Math.h" +#include "osgEarth/Cube" +#include "osgEarth/ImageToHeightFieldConverter" using namespace simVis; +using namespace simVis_db; + +//........................................................... + +namespace +{ + bool convertTileKeyToQsKey(const osgEarth::TileKey& key, FaceIndexType& out_faceIndex, QSNodeId& out_nodeId, + osg::Vec2d& out_fmin, osg::Vec2d& out_fmax) + { + QSNodeId zero(0); + QSNodeId one(1); + + const unsigned int maxLevel = key.getLevelOfDetail(); + + QSNodeId nodeId; + + osgEarth::TileKey pkey = key; + + for (unsigned int i = 0; i < maxLevel; ++i) + { + const unsigned int plevel = pkey.getLevelOfDetail(); + const unsigned int level = plevel * 3; + const QSNodeId bit0 = one << level; + const QSNodeId bit1 = one << (level + 1); + const QSNodeId bit2 = one << (level + 2); + + unsigned int tx, ty; + pkey.getTileXY(tx, ty); + + const int xoff = ((tx % 2) == 0) ? 0 : 1; + const int yoff = ((ty % 2) == 0) ? 0 : 1; + + if (xoff == 0 && yoff == 0) + { + nodeId |= bit1; + } + else if (xoff == 1 && yoff == 0) + { + nodeId |= bit0; + } + else if (xoff == 0 && yoff == 1) + { + nodeId |= bit0; + nodeId |= bit1; + } + else if (xoff == 1 && yoff == 1) + { + nodeId |= bit2; + } + + pkey = pkey.createParentKey(); + } + + out_faceIndex = osgEarth::Contrib::UnifiedCubeProfile::getFace(key); + out_nodeId = nodeId; + + double xMin = key.getExtent().xMin(); + double yMin = key.getExtent().yMin(); + double xMax = key.getExtent().xMax(); + double yMax = key.getExtent().yMax(); + int face; + + osgEarth::Contrib::CubeUtils::cubeToFace(xMin, yMin, xMax, yMax, face); + + out_fmin.set(xMin * gQsDMaxLength, yMin * gQsDMaxLength); + out_fmax.set(xMax * gQsDMaxLength, yMax * gQsDMaxLength); + + return true; + } + + bool decompressZLIB(const char* input, int inputLen, std::string& output) + { + osgDB::BaseCompressor* comp = osgDB::Registry::instance()->getObjectWrapperManager()->findCompressor("zlib"); + std::string inString(input, inputLen); + std::istringstream inStream(inString); + return comp->decompress(inStream, output); + } + + // Uses one of OSG's native ReaderWriter's to read image data from a buffer. + bool readNativeImage(osgDB::ReaderWriter* reader, const char* inBuf, int inBufLen, osg::ref_ptr& outImage) + { + std::string inString(inBuf, inBufLen); + std::istringstream inStream(inString); + osgDB::ReaderWriter::ReadResult result = reader->readImage(inStream); + outImage = result.getImage(); + if (result.error() || !outImage.valid()) + { + return false; + } + else + return true; + } + + struct DBContext + { + DBContext() + { + rasterFormat_ = SPLIT_UNKNOWN; + pixelLength_ = 128; + shallowLevel_ = 0; + deepLevel_ = 32; + timeSpecified_ = false; + timeStamp_ = simCore::INFINITE_TIME_STAMP; + } + + int rasterFormat_; + int pixelLength_; + int shallowLevel_; + int deepLevel_; + bool timeSpecified_; + simCore::TimeStamp timeStamp_; + + std::string pathname_; + sqlite3* db_; + SQLiteDataBaseReadUtil dbUtil_; + PosXPosYExtents extents_[6]; + std::string source_; + std::string classification_; + std::string description_; + + osg::ref_ptr pngReader_; + osg::ref_ptr jpgReader_; + osg::ref_ptr tifReader_; + osg::ref_ptr rgbReader_; + + template + void makeImage(int size, GLenum internalFormat, GLenum pixelFormat, GLenum type, + std::string& buf, osg::ref_ptr& outImage) + { + unsigned char* data = new unsigned char[buf.length()]; + std::copy(buf.begin(), buf.end(), data); + + // Be sure to cast here to get the right swap function: + make_big_endian((T*)data, size * size); + + outImage = new osg::Image(); + outImage->setImage(size, size, 1, internalFormat, pixelFormat, type, data, osg::Image::USE_NEW_DELETE); + } + + bool decodeRaster_(int rasterFormat, const char* inputBuffer, int inputBufferLen, osg::ref_ptr& outImage) + { + switch (rasterFormat) + { + case SPLIT_5551_ZLIB_COMPRESS: // TESTED OK + case SPLIT_5551_GZ: // UNTESTED + { + std::string buf; + if (decompressZLIB(inputBuffer, inputBufferLen, buf)) + { + // Three component image (red, green, and blue channels) + makeImage( + pixelLength_, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, buf, outImage); + return true; + } + } + break; + + case SPLIT_8BIT_ZLIB_COMPRESS: // TESTED OK + case SPLIT_8BIT_GZ: // UNTESTED + { + std::string buf; + if (decompressZLIB(inputBuffer, inputBufferLen, buf)) + { + // Single component image (grayscale channel) + makeImage( + pixelLength_, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, buf, outImage); + return true; + } + } + break; + case SPLIT_INTA_ZLIB_COMPRESS: // TESTED OK + { + std::string buf; + if (decompressZLIB(inputBuffer, inputBufferLen, buf)) + { + // Two component image (grayscale w/alpha channel) + makeImage( + pixelLength_, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, buf, outImage); + return true; + } + break; + } + case SPLIT_RGBA_ZLIB_COMPRESS: // TESTED OK + { + std::string buf; + if (decompressZLIB(inputBuffer, inputBufferLen, buf)) + { + // Four component image (red, green, blue and alpha channels) + makeImage( + pixelLength_, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, buf, outImage); + return true; + } + break; + } + case SPLIT_SGI_RGBA: // TESTED - OK (earthColorSGI.db) + { + if (rgbReader_.valid()) + return readNativeImage(rgbReader_.get(), inputBuffer, inputBufferLen, outImage); + else + OE_WARN << "SGI RGBA reader not available" << std::endl; + } + break; + + case SPLIT_SGI_RGB: // UNTESTED + { + if (rgbReader_.valid()) + return readNativeImage(rgbReader_.get(), inputBuffer, inputBufferLen, outImage); + else + OE_WARN << "SGI RGB reader not available" << std::endl; + } + break; + + case SPLIT_FLOAT32_ZLIB_COMPRESS: // TESTED OK; + { + // Single-channel 32-bit float elevation data + std::string buf; + if (decompressZLIB(inputBuffer, inputBufferLen, buf)) + { + makeImage(pixelLength_, GL_LUMINANCE32F_ARB, GL_LUMINANCE, GL_FLOAT, buf, outImage); + return true; + } + } + break; + + case SPLIT_JPEG: // TESTED OK + { + if (jpgReader_.valid()) + return readNativeImage(jpgReader_.get(), inputBuffer, inputBufferLen, outImage); + else + OE_WARN << "JPEG reader not available" << std::endl; + } + break; + + case SPLIT_PNG: // UNTESTED + { + if (pngReader_.valid()) + return readNativeImage(pngReader_.get(), inputBuffer, inputBufferLen, outImage); + else + OE_WARN << "PNG reader not available" << std::endl; + } + break; + + case SPLIT_TIFF: // UNTESTED + { + if (tifReader_.valid()) + return readNativeImage(tifReader_.get(), inputBuffer, inputBufferLen, outImage); + else + OE_WARN << "TIFF reader not available" << std::endl; + } + break; + + default: + { + OE_WARN << "Support for raster format " << rasterFormat << " not implemented" << std::endl; + } + break; + } + return false; + } + }; +} + +//........................................................... + +#undef LC +#define LC "[DBImageLayer] " + +REGISTER_OSGEARTH_LAYER(dbimage, simVis::DBImageLayer); osgEarth::Config DBImageLayer::Options::getConfig() const { - osgEarth::Config conf = osgEarth::Contrib::TileSourceImageLayer::Options::getConfig(); - conf.merge(driver()->getConfig()); + osgEarth::Config conf = osgEarth::ImageLayer::Options::getConfig(); + conf.set("url", url()); + conf.set("deepest_level", deepestLevel()); return conf; } void DBImageLayer::Options::fromConfig(const osgEarth::Config& conf) { - driver() = simVis::DBOptions(conf); + conf.get("url", url()); + conf.get("deepest_level", deepestLevel()); } void DBImageLayer::setURL(const osgEarth::URI& value) { - localCopyOfOptions_.url() = value; - options().driver() = localCopyOfOptions_; + options().url() = value; } const osgEarth::URI& DBImageLayer::getURL() const { - return localCopyOfOptions_.url().get(); + return options().url().get(); } void DBImageLayer::setDeepestLevel(const unsigned int& value) { - localCopyOfOptions_.deepestLevel() = value; - options().driver() = localCopyOfOptions_; + options().deepestLevel() = value; } const unsigned int& DBImageLayer::getDeepestLevel() const { - return localCopyOfOptions_.deepestLevel().get(); + return options().deepestLevel().get(); } void DBImageLayer::init() { - osgEarth::Contrib::TileSourceImageLayer::init(); - localCopyOfOptions_ = simVis::DBOptions(options().driver().get()); + osgEarth::ImageLayer::init(); + context_ = new DBContext(); +} + +DBImageLayer::~DBImageLayer() +{ + delete ((DBContext*)context_); } osgEarth::Status DBImageLayer::openImplementation() { - return osgEarth::Contrib::TileSourceImageLayer::openImplementation(); + osgEarth::Status parent = osgEarth::ImageLayer::openImplementation(); + if (parent.isError()) + return parent; + + DBContext& cx = *(DBContext*)context_; + + if (!options().url().isSet()) + return osgEarth::Status(osgEarth::Status::ConfigurationError, "Missing required URL"); + + cx.pathname_ = osgDB::findDataFile(options().url()->full(), getReadOptions()); + + if (cx.dbUtil_.OpenDataBaseFile(cx.pathname_, &cx.db_, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) != QS_IS_OK) + { + cx.db_ = NULL; + return osgEarth::Status( + osgEarth::Status::ResourceUnavailable, + osgEarth::Stringify() << "Failed to open DB file at " << options().url()->full()); + } + else + { + QsErrorType err = cx.dbUtil_.TsGetSetFromListOfSetsTable( + cx.db_, + "default", + cx.rasterFormat_, + cx.pixelLength_, + cx.shallowLevel_, + cx.deepLevel_, + cx.extents_, + cx.source_, + cx.classification_, + cx.description_, + cx.timeSpecified_, + cx.timeStamp_); + + // Limit the deepLevel_ by the passed-in option + if (options().deepestLevel().isSet()) + { + cx.deepLevel_ = simCore::sdkMin(cx.deepLevel_, static_cast(options().deepestLevel().get())); + } + + if (err != QS_IS_OK) + { + sqlite3_close(cx.db_); + cx.db_ = NULL; + return osgEarth::Status( + osgEarth::Status::ResourceUnavailable, + osgEarth::Stringify() << "Failed to read metadata for " << cx.pathname_); + } + + // Set up as a unified cube: + osgEarth::Profile* profile = new osgEarth::Contrib::UnifiedCubeProfile(); + // DB are expected to be wgs84, which Cube defaults to + setProfile(profile); + + // Lat/long extents (for debugging) + osgEarth::GeoExtent llex[6]; + + // Tell the engine how deep the data actually goes: + for (unsigned int f = 0; f < 6; ++f) + { + if (cx.extents_[f].minX < cx.extents_[f].maxX && cx.extents_[f].minY < cx.extents_[f].maxY) + { + const double x0 = cx.extents_[f].minX / gQsDMaxLength; + const double x1 = cx.extents_[f].maxX / gQsDMaxLength; + const double y0 = cx.extents_[f].minY / gQsDMaxLength; + const double y1 = cx.extents_[f].maxY / gQsDMaxLength; + + osgEarth::GeoExtent cubeEx(profile->getSRS(), f + x0, y0, f + x1, y1); + + // Transform to lat/long for the debugging msgs + cubeEx.transform(profile->getSRS()->getGeodeticSRS(), llex[f]); + + dataExtents().push_back(osgEarth::DataExtent(cubeEx, cx.shallowLevel_, cx.deepLevel_)); + } + } + + // Set time value of image if a time was found in the db + if (cx.timeStamp_ != simCore::INFINITE_TIME_STAMP) + { + const osgEarth::DateTime osgTime(cx.timeStamp_.secondsSinceRefYear(1970).getSeconds()); + // Set time as a user value since config is not editable from here + setUserValue("time", osgTime.asISO8601()); + } + + OE_INFO << LC + << "Table: " << options().url()->full() << std::endl + << " Raster format = " << cx.rasterFormat_ << std::endl + << " Tile size = " << cx.pixelLength_ << std::endl + << " Shallow level = " << cx.shallowLevel_ << std::endl + << " Deep level = " << cx.deepLevel_ << std::endl + << " QS Extents = " << std::endl + << " 0: " << cx.extents_[0].minX << "," << cx.extents_[0].minY << "," << cx.extents_[0].maxX << "," << cx.extents_[0].maxY << "(" << (llex[0].isValid() ? llex[0].toString() : "empty") << ")\n" + << " 1: " << cx.extents_[1].minX << "," << cx.extents_[1].minY << "," << cx.extents_[1].maxX << "," << cx.extents_[1].maxY << "(" << (llex[1].isValid() ? llex[1].toString() : "empty") << ")\n" + << " 2: " << cx.extents_[2].minX << "," << cx.extents_[2].minY << "," << cx.extents_[2].maxX << "," << cx.extents_[2].maxY << "(" << (llex[2].isValid() ? llex[2].toString() : "empty") << ")\n" + << " 3: " << cx.extents_[3].minX << "," << cx.extents_[3].minY << "," << cx.extents_[3].maxX << "," << cx.extents_[3].maxY << "(" << (llex[3].isValid() ? llex[3].toString() : "empty") << ")\n" + << " 4: " << cx.extents_[4].minX << "," << cx.extents_[4].minY << "," << cx.extents_[4].maxX << "," << cx.extents_[4].maxY << "(" << (llex[4].isValid() ? llex[4].toString() : "empty") << ")\n" + << " 5: " << cx.extents_[5].minX << "," << cx.extents_[5].minY << "," << cx.extents_[5].maxX << "," << cx.extents_[5].maxY << "(" << (llex[5].isValid() ? llex[5].toString() : "empty") << ")\n"; + + // Line up the native format readers: + cx.pngReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/png"); + cx.jpgReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/jpeg"); + cx.tifReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/tiff"); + cx.rgbReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/x-rgb"); + } + return osgEarth::Status::OK(); } osgEarth::GeoImage DBImageLayer::createImageImplementation(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress) const { - //todo - return osgEarth::Contrib::TileSourceImageLayer::createImageImplementation(key, progress); + DBContext& cx = *(DBContext*)context_; + + if (!cx.db_) + return osgEarth::GeoImage::INVALID; + + osg::ref_ptr result; + + // Convert osgEarth::TileKey into a QuadKeyID + FaceIndexType faceId; + QSNodeId nodeId; + osg::Vec2d tileMin; + osg::Vec2d tileMax; // Tile extents in QS units + convertTileKeyToQsKey(key, faceId, nodeId, tileMin, tileMax); + + if (!cx.extents_[faceId].Valid()) + { + // no data on this face? return nothing + return osgEarth::GeoImage::INVALID; + } + + if (key.getLevelOfDetail() > static_cast(cx.deepLevel_)) + { + // Hopefully this doesn't happen since we called setMaxDataLevel, but you never know + return osgEarth::GeoImage::INVALID; + } + + // Query the database + TextureDataType* buf = NULL; + uint32_t bufSize = 0; + uint32_t currentRasterSize = 0; + + QsErrorType err = cx.dbUtil_.TsReadDataBuffer( + cx.db_, + cx.pathname_, + "default", + faceId, + nodeId, + &buf, + &bufSize, + ¤tRasterSize, + false, true); // AllowLocalDB: no, we created it ourselves + + if (err == QS_IS_OK) + { + if (currentRasterSize > 0) + { + if (cx.decodeRaster_(cx.rasterFormat_, (const char*)buf, currentRasterSize, result)) + { + // If result is 1x1, skip border processing + if (result->s() >= 1 && result->t() >= 1) + { + const unsigned int resultS = static_cast(result->s()); + const unsigned int resultT = static_cast(result->t()); + + // Tile width and height in QS units: + const double tileWidth = tileMax.x() - tileMin.x(); + const double tileHeight = tileMax.y() - tileMin.y(); + + const double qppx = 0.0; + const double qppy = 0.0; + const double xMin = cx.extents_[faceId].minX + qppx; + const double xMax = cx.extents_[faceId].maxX - qppx; + const double yMin = cx.extents_[faceId].minY + qppy; + const double yMax = cx.extents_[faceId].maxY - qppy; + + osgEarth::ImageUtils::PixelReader read(result.get()); + osgEarth::ImageUtils::PixelWriter write(result.get()); + + // Write "no data" to all pixels outside the reported extent. + const double colw = tileWidth / (resultS - 1); + const double rowh = tileHeight / (resultT - 1); + + for (unsigned int row = 0; row < resultS; ++row) + { + const double y = tileMin.y() + row * rowh; + + for (unsigned int col = 0; col < resultT; ++col) + { + const double x = tileMin.x() + col * colw; + + if (x < xMin || x > xMax || y < yMin || y > yMax) + { + osg::Vec4f pixel = read(col, row); + pixel.a() = 0.0f; + write(pixel, col, row); + } + } + } + } + } + else + { + OE_WARN << "Image decode failed for key " << key.str() << std::endl; + } + } + else + { + // Raster size of 0 means no tile in the db + //OE_DEBUG << "No image in the database for key " << key->str() << std::endl; + result = NULL; + } + } + else + { + std::cerr << GetErrorString(err) << std::endl; + OE_WARN << "Failed to read image from " << key.str() << std::endl; + } + + delete[] buf; + + return osgEarth::GeoImage(result.release(), key.getExtent()); } //........................................................... +#undef LC +#define LC "[DBElevationLayer] " + +REGISTER_OSGEARTH_LAYER(dbelevation, simVis::DBElevationLayer); + osgEarth::Config DBElevationLayer::Options::getConfig() const { osgEarth::Config conf = osgEarth::ElevationLayer::Options::getConfig(); - conf.merge(driver()->getConfig()); + conf.set("url", url()); + conf.set("deepest_level", deepestLevel()); return conf; } void DBElevationLayer::Options::fromConfig(const osgEarth::Config& conf) { - driver() = simVis::DBOptions(conf); + conf.get("url", url()); + conf.get("deepest_level", deepestLevel()); } void DBElevationLayer::setURL(const osgEarth::URI& value) { - localCopyOfOptions_.url() = value; - options().driver() = localCopyOfOptions_; + options().url() = value; } const osgEarth::URI& DBElevationLayer::getURL() const { - return localCopyOfOptions_.url().get(); + return options().url().get(); } void DBElevationLayer::setDeepestLevel(const unsigned int& value) { - localCopyOfOptions_.deepestLevel() = value; - options().driver() = localCopyOfOptions_; + options().deepestLevel() = value; } const unsigned int& DBElevationLayer::getDeepestLevel() const { - return localCopyOfOptions_.deepestLevel().get(); + return options().deepestLevel().get(); } void DBElevationLayer::init() { - osgEarth::Contrib::ElevationLayer::init(); - localCopyOfOptions_ = simVis::DBOptions(options().driver().get()); + osgEarth::ElevationLayer::init(); + context_ = new DBContext(); +} + +DBElevationLayer::~DBElevationLayer() +{ + delete ((DBContext*)context_); } osgEarth::Status DBElevationLayer::openImplementation() { - return osgEarth::ElevationLayer::openImplementation(); + osgEarth::Status parent = osgEarth::ElevationLayer::openImplementation(); + if (parent.isError()) + return parent; + + + DBContext& cx = *(DBContext*)context_; + + if (!options().url().isSet()) + return osgEarth::Status(osgEarth::Status::ConfigurationError, "Missing required URL"); + + cx.pathname_ = osgDB::findDataFile(options().url()->full(), getReadOptions()); + + if (cx.dbUtil_.OpenDataBaseFile(cx.pathname_, &cx.db_, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) != QS_IS_OK) + { + cx.db_ = NULL; + return osgEarth::Status( + osgEarth::Status::ResourceUnavailable, + osgEarth::Stringify() << "Failed to open DB file at " << options().url()->full()); + } + else + { + QsErrorType err = cx.dbUtil_.TsGetSetFromListOfSetsTable( + cx.db_, + "default", + cx.rasterFormat_, + cx.pixelLength_, + cx.shallowLevel_, + cx.deepLevel_, + cx.extents_, + cx.source_, + cx.classification_, + cx.description_, + cx.timeSpecified_, + cx.timeStamp_); + + // Limit the deepLevel_ by the passed-in option + if (options().deepestLevel().isSet()) + { + cx.deepLevel_ = simCore::sdkMin(cx.deepLevel_, static_cast(options().deepestLevel().get())); + } + + if (err != QS_IS_OK) + { + sqlite3_close(cx.db_); + cx.db_ = NULL; + return osgEarth::Status( + osgEarth::Status::ResourceUnavailable, + osgEarth::Stringify() << "Failed to read metadata for " << cx.pathname_); + } + + // Set up as a unified cube: + osgEarth::Profile* profile = new osgEarth::Contrib::UnifiedCubeProfile(); + // DB are expected to be wgs84, which Cube defaults to + setProfile(profile); + + // Lat/long extents (for debugging) + osgEarth::GeoExtent llex[6]; + + // Tell the engine how deep the data actually goes: + for (unsigned int f = 0; f < 6; ++f) + { + if (cx.extents_[f].minX < cx.extents_[f].maxX && cx.extents_[f].minY < cx.extents_[f].maxY) + { + const double x0 = cx.extents_[f].minX / gQsDMaxLength; + const double x1 = cx.extents_[f].maxX / gQsDMaxLength; + const double y0 = cx.extents_[f].minY / gQsDMaxLength; + const double y1 = cx.extents_[f].maxY / gQsDMaxLength; + + osgEarth::GeoExtent cubeEx(profile->getSRS(), f + x0, y0, f + x1, y1); + + // Transform to lat/long for the debugging msgs + cubeEx.transform(profile->getSRS()->getGeodeticSRS(), llex[f]); + + dataExtents().push_back(osgEarth::DataExtent(cubeEx, cx.shallowLevel_, cx.deepLevel_)); + } + } + + // Set time value of image if a time was found in the db + if (cx.timeStamp_ != simCore::INFINITE_TIME_STAMP) + { + const osgEarth::DateTime osgTime(cx.timeStamp_.secondsSinceRefYear(1970).getSeconds()); + // Set time as a user value since config is not editable from here + setUserValue("time", osgTime.asISO8601()); + } + + OE_INFO << LC + << "Table: " << options().url()->full() << std::endl + << " Raster format = " << cx.rasterFormat_ << std::endl + << " Tile size = " << cx.pixelLength_ << std::endl + << " Shallow level = " << cx.shallowLevel_ << std::endl + << " Deep level = " << cx.deepLevel_ << std::endl + << " QS Extents = " << std::endl + << " 0: " << cx.extents_[0].minX << "," << cx.extents_[0].minY << "," << cx.extents_[0].maxX << "," << cx.extents_[0].maxY << "(" << (llex[0].isValid() ? llex[0].toString() : "empty") << ")\n" + << " 1: " << cx.extents_[1].minX << "," << cx.extents_[1].minY << "," << cx.extents_[1].maxX << "," << cx.extents_[1].maxY << "(" << (llex[1].isValid() ? llex[1].toString() : "empty") << ")\n" + << " 2: " << cx.extents_[2].minX << "," << cx.extents_[2].minY << "," << cx.extents_[2].maxX << "," << cx.extents_[2].maxY << "(" << (llex[2].isValid() ? llex[2].toString() : "empty") << ")\n" + << " 3: " << cx.extents_[3].minX << "," << cx.extents_[3].minY << "," << cx.extents_[3].maxX << "," << cx.extents_[3].maxY << "(" << (llex[3].isValid() ? llex[3].toString() : "empty") << ")\n" + << " 4: " << cx.extents_[4].minX << "," << cx.extents_[4].minY << "," << cx.extents_[4].maxX << "," << cx.extents_[4].maxY << "(" << (llex[4].isValid() ? llex[4].toString() : "empty") << ")\n" + << " 5: " << cx.extents_[5].minX << "," << cx.extents_[5].minY << "," << cx.extents_[5].maxX << "," << cx.extents_[5].maxY << "(" << (llex[5].isValid() ? llex[5].toString() : "empty") << ")\n"; + + // Line up the native format readers: + cx.pngReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/png"); + cx.jpgReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/jpeg"); + cx.tifReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/tiff"); + cx.rgbReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/x-rgb"); + } + return osgEarth::Status::OK(); } osgEarth::GeoHeightField DBElevationLayer::createHeightFieldImplementation(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress) const { - //todo - return osgEarth::ElevationLayer::createHeightFieldImplementation(key, progress); + DBContext& cx = *(DBContext*)context_; + + if (!cx.db_) + return osgEarth::GeoHeightField::INVALID; + + osg::ref_ptr result; + + // Convert osgEarth::TileKey into a QuadKeyID + FaceIndexType faceId; + QSNodeId nodeId; + osg::Vec2d tileMin; + osg::Vec2d tileMax; // Tile extents in QS units + convertTileKeyToQsKey(key, faceId, nodeId, tileMin, tileMax); + + if (!cx.extents_[faceId].Valid()) + { + // If there is no data on that face, return nothing. + return osgEarth::GeoHeightField::INVALID; + } + + // Query the database + TextureDataType* buf = NULL; + uint32_t bufSize = 0; + uint32_t currentRasterSize = 0; + + QsErrorType err = cx.dbUtil_.TsReadDataBuffer( + cx.db_, + cx.pathname_, + "default", + faceId, + nodeId, + &buf, + &bufSize, + ¤tRasterSize, + false); // AllowLocalDB: no, we created it ourselves + + if (err == QS_IS_OK) + { + if (currentRasterSize > 0) + { + osg::ref_ptr image; + if (cx.decodeRaster_(cx.rasterFormat_, (const char*)buf, currentRasterSize, image)) + { + + // SIMDIS .db elevation data is y-inverted: + image->flipVertical(); + + osgEarth::ImageToHeightFieldConverter i2h; + result = i2h.convert(image.get()); + + // If result is 1x1, skip border processing + if (result->getNumColumns() >= 1 && result->getNumRows() >= 1) + { + // Tile width and height in QS units: + const double tileWidth = tileMax.x() - tileMin.x(); + const double tileHeight = tileMax.y() - tileMin.y(); + + /** + * DB data contains a one-pixel border with undefined data. That border falls + * within the reported extents. We have to fill that with "NO DATA". + * First, calculate the size of a pixel in QS units for this tile: + */ + const double qppx = tileWidth / cx.pixelLength_; + const double qppy = tileHeight / cx.pixelLength_; + + /** + * Adjust the reported extents to remove the border. + * NOTE: This will fail in the (rare?) edge case in which a data extent falls + * exactly on a cube-face boundary. Ignore that for now. + */ + const double xMin = cx.extents_[faceId].minX + qppx; + const double xMax = cx.extents_[faceId].maxX - qppx; + const double yMin = cx.extents_[faceId].minY + qppy; + const double yMax = cx.extents_[faceId].maxY - qppy; + + // Write "no data" to all pixels outside the reported extent. + const double colWidth = tileWidth / (result->getNumColumns() - 1); + const double rowHeight = tileHeight / (result->getNumRows() - 1); + + for (unsigned int row = 0; row < result->getNumRows(); ++row) + { + const double y = tileMin.y() + row * rowHeight; + + for (unsigned int col = 0; col < result->getNumColumns(); ++col) + { + const double x = tileMin.x() + col * colWidth; + + if (x < xMin || x > xMax || y < yMin || y > yMax) + { + result->setHeight(col, row, NO_DATA_VALUE); + } + } + } + } + } + else + { + OE_WARN << "Heightfield decode failed for key " << key.str() << std::endl; + } + } + else + { + // Raster size of 0 means no tile in the db + result = NULL; + } + } + else + { + OE_WARN << "Failed to read heightfield from " << key.str() << std::endl; + } + + delete[] buf; + + return osgEarth::GeoHeightField(result.release(), key.getExtent()); } diff --git a/SDK/simVis/DBFormat.h b/SDK/simVis/DBFormat.h index 646498d23..a9e710f60 100644 --- a/SDK/simVis/DBFormat.h +++ b/SDK/simVis/DBFormat.h @@ -37,19 +37,21 @@ namespace simVis // OE_OPTION uses unqualified optional<> type using osgEarth::optional; -class SDKVIS_EXPORT DBImageLayer : public osgEarth::Contrib::TileSourceImageLayer +class SDKVIS_EXPORT DBImageLayer : public osgEarth::ImageLayer { public: // serialization - class SDKVIS_EXPORT Options : public osgEarth::Contrib::TileSourceImageLayer::Options { + class SDKVIS_EXPORT Options : public osgEarth::ImageLayer::Options { public: - META_LayerOptions(simVis, Options, osgEarth::Contrib::TileSourceImageLayer::Options); + META_LayerOptions(simVis, Options, osgEarth::ImageLayer::Options); + OE_OPTION(osgEarth::URI, url); + OE_OPTION(unsigned, deepestLevel); virtual osgEarth::Config getConfig() const; private: void fromConfig(const osgEarth::Config&); }; public: - META_Layer(simVis, DBImageLayer, Options, osgEarth::Contrib::TileSourceImageLayer, DBImage); + META_Layer(simVis, DBImageLayer, Options, osgEarth::ImageLayer, DBImage); public: /// Base URL of TileCache endpoint @@ -74,27 +76,29 @@ class SDKVIS_EXPORT DBImageLayer : public osgEarth::Contrib::TileSourceImageLaye virtual void init(); /// Destructor - virtual ~DBImageLayer() { } + virtual ~DBImageLayer(); - simVis::DBOptions localCopyOfOptions_; + void* context_; }; /** * Elevation layer connected to a DB file */ -class SDKVIS_EXPORT DBElevationLayer : public osgEarth::Contrib::TileSourceElevationLayer +class SDKVIS_EXPORT DBElevationLayer : public osgEarth::ElevationLayer { public: // serialization - class SDKVIS_EXPORT Options : public osgEarth::Contrib::TileSourceElevationLayer::Options { + class SDKVIS_EXPORT Options : public osgEarth::ElevationLayer::Options { public: - META_LayerOptions(simVis, Options, osgEarth::Contrib::TileSourceElevationLayer::Options); + META_LayerOptions(simVis, Options, osgEarth::ElevationLayer::Options); + OE_OPTION(osgEarth::URI, url); + OE_OPTION(unsigned, deepestLevel); virtual osgEarth::Config getConfig() const; private: void fromConfig(const osgEarth::Config&); }; public: - META_Layer(simVis, DBElevationLayer, Options, osgEarth::Contrib::TileSourceElevationLayer, DBElevation); + META_Layer(simVis, DBElevationLayer, Options, osgEarth::ElevationLayer, DBElevation); /// URL of the database file void setURL(const osgEarth::URI& value); @@ -118,9 +122,9 @@ class SDKVIS_EXPORT DBElevationLayer : public osgEarth::Contrib::TileSourceEleva virtual void init(); /// Destructor - virtual ~DBElevationLayer() { } + virtual ~DBElevationLayer(); - simVis::DBOptions localCopyOfOptions_; + void* context_; }; } From 4adee505c00c8a31113d1da2cad6b620e3baddcb Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 16 Jan 2020 06:27:12 -0500 Subject: [PATCH 028/121] DEV: Updates to recent TileSource refactor: * Fixed CMake for public/private definitions and third party SQLITE * Code style updates * simQt now respects layer time value * Removed extra includes * Unity build fix * simUtil::LayerFactory can now return NULL if simVis not configured with DB loader Review: 20407 --- CMakeLists.txt | 1 - Examples/BasicViewerText/BasicViewerText.cpp | 1 - Examples/Periscope/PeriscopeExample.cpp | 2 -- .../PlatformSymbology/PlatformSymbology.cpp | 2 -- Examples/RocketBurn/RocketBurn.cpp | 2 -- .../ExampleTimestampedLayer.cpp | 1 - SDK/simQt/TimestampedLayerManager.cpp | 6 ++-- SDK/simUtil.h | 1 - SDK/simUtil/CMakeLists.txt | 9 +++-- SDK/simUtil/LayerFactory.cpp | 22 ++++++++---- SDK/simUtil/LayerFactory.h | 10 ++---- SDK/simVis/CMakeLists.txt | 20 ++++++++--- SDK/simVis/Compass.cpp | 1 - SDK/simVis/DB/Plugin.cpp | 4 +-- SDK/simVis/DB/swapbytes.h | 7 ++-- SDK/simVis/DBFormat.cpp | 34 +++++++++---------- SDK/simVis/DBFormat.h | 16 +++++---- SDK/simVis/GeoFence.cpp | 3 +- 18 files changed, 75 insertions(+), 67 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eca0c0e46..67b8cf178 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -208,7 +208,6 @@ set(SQLITE3_DIR "" CACHE PATH "Sqlite3 root directory") include(ImportSQLite) if (SQLITE3_FOUND) set(SIM_HAVE_DB_SUPPORT 1) - add_definitions(-DSIM_HAVE_DB_SUPPORT) endif() # subprojects diff --git a/Examples/BasicViewerText/BasicViewerText.cpp b/Examples/BasicViewerText/BasicViewerText.cpp index f7cf2d984..3c635b451 100644 --- a/Examples/BasicViewerText/BasicViewerText.cpp +++ b/Examples/BasicViewerText/BasicViewerText.cpp @@ -39,7 +39,6 @@ #include "simUtil/HudManager.h" #include "simUtil/Replaceables.h" #include "simUtil/StatusText.h" -#include "osgDB/ReadFile" #define LC "[BasicViewerText demo] " diff --git a/Examples/Periscope/PeriscopeExample.cpp b/Examples/Periscope/PeriscopeExample.cpp index 0a2248f52..f301cef07 100644 --- a/Examples/Periscope/PeriscopeExample.cpp +++ b/Examples/Periscope/PeriscopeExample.cpp @@ -47,8 +47,6 @@ #include "osgEarth/SimpleOceanLayer" #include "osgEarth/Version" -#include "osgDB/ReadFile" - #ifdef HAVE_TRITON_NODEKIT #include "osgEarthTriton/TritonLayer" #endif diff --git a/Examples/PlatformSymbology/PlatformSymbology.cpp b/Examples/PlatformSymbology/PlatformSymbology.cpp index 1cf1aa20a..77a99ac10 100644 --- a/Examples/PlatformSymbology/PlatformSymbology.cpp +++ b/Examples/PlatformSymbology/PlatformSymbology.cpp @@ -65,8 +65,6 @@ #include "osgEarth/StringUtils" #include "osgEarth/Style" -#include "osgDB/ReadFile" - #include "google/protobuf/stubs/common.h" using namespace osgEarth; diff --git a/Examples/RocketBurn/RocketBurn.cpp b/Examples/RocketBurn/RocketBurn.cpp index e32041074..0df9ef242 100644 --- a/Examples/RocketBurn/RocketBurn.cpp +++ b/Examples/RocketBurn/RocketBurn.cpp @@ -35,8 +35,6 @@ #include "simUtil/ExampleResources.h" #include "simUtil/PlatformSimulator.h" -#include "osgDB/ReadFile" - namespace { /// get time and platform removal notifications diff --git a/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp b/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp index af3168628..287973474 100644 --- a/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp +++ b/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp @@ -31,7 +31,6 @@ #include "simVis/SceneManager.h" #include "simVis/Viewer.h" #include "simUtil/ExampleResources.h" -#include "osgDB/ReadFile" namespace ui = osgEarth::Util::Controls; diff --git a/SDK/simQt/TimestampedLayerManager.cpp b/SDK/simQt/TimestampedLayerManager.cpp index 1e1b2f08f..dbcc65b7c 100644 --- a/SDK/simQt/TimestampedLayerManager.cpp +++ b/SDK/simQt/TimestampedLayerManager.cpp @@ -302,11 +302,11 @@ void TimestampedLayerManager::addLayerWithTime_(osgEarth::ImageLayer* newLayer) iso8601 = conf.value("times"); /* * Some image layer file types can have time values (e.g. db files). Config values can't be - * changed at time of file read, so time is set as a user value of the tile source in these cases. + * changed at time of file read, so time is set as a user value of the layer in these cases. * Config values take precedence of user values. */ - if (iso8601.empty() && newLayer->getTileSource()) - newLayer->getTileSource()->getUserValue("time", iso8601); + if (iso8601.empty()) + newLayer->getUserValue("time", iso8601); // If layer has no time, nothing to do with it if (iso8601.empty()) return; diff --git a/SDK/simUtil.h b/SDK/simUtil.h index 698cb4387..415d3cb4d 100644 --- a/SDK/simUtil.h +++ b/SDK/simUtil.h @@ -25,7 +25,6 @@ #include "simUtil/Capabilities.h" #include "simUtil/DataStoreTestHelper.h" #include "simUtil/DatumConvert.h" -//#include "simUtil/DbConfigurationFile.h" #include "simUtil/DefaultDataStoreValues.h" #include "simUtil/DynamicSelectionPicker.h" #include "simUtil/ExampleControls.h" diff --git a/SDK/simUtil/CMakeLists.txt b/SDK/simUtil/CMakeLists.txt index f364093dc..e44a693ba 100644 --- a/SDK/simUtil/CMakeLists.txt +++ b/SDK/simUtil/CMakeLists.txt @@ -83,9 +83,9 @@ set(UTIL_SOURCES ) if(SIM_HAVE_DB_SUPPORT) - set(UTIL_HEADERS ${UTIL_HEADERS} ${UTIL_INC}DbConfigurationFile.h) - set(UTIL_SOURCES ${UTIL_SOURCES} ${UTIL_SRC}DbConfigurationFile.cpp) -endif() + list(APPEND UTIL_HEADERS ${UTIL_INC}DbConfigurationFile.h) + list(APPEND UTIL_SOURCES ${UTIL_SRC}DbConfigurationFile.cpp) +endif() set(UTIL_GENERATED_HEADERS) set(UTIL_GENERATED_SOURCES) @@ -162,6 +162,9 @@ endif() if(OSGEARTH_SILVERLINING_SUPPORT STREQUAL "NODEKIT" AND TARGET OSGEARTH_SILVERLINING) target_link_libraries(simUtil PRIVATE OSGEARTH_SILVERLINING) endif() +if(SIM_HAVE_DB_SUPPORT) + target_compile_definitions(simUtil PRIVATE SIM_HAVE_DB_SUPPORT) +endif() if(INSTALL_SIMDIS_SDK_SHADERS) if(NOT SIMDIS_SDK_SHADERS_INSTALL_DIR) diff --git a/SDK/simUtil/LayerFactory.cpp b/SDK/simUtil/LayerFactory.cpp index f9fa0fe06..6d05035cb 100644 --- a/SDK/simUtil/LayerFactory.cpp +++ b/SDK/simUtil/LayerFactory.cpp @@ -19,6 +19,7 @@ * disclose, or release this software. * */ +#include #include "osgEarth/ElevationLayer" #include "osgEarth/FeatureModelLayer" #include "osgEarth/GDAL" @@ -29,22 +30,25 @@ #include "simCore/String/Format.h" #include "simCore/String/Utils.h" #include "simVis/Constants.h" +#include "simVis/Types.h" +#include "simUtil/LayerFactory.h" #ifdef SIM_HAVE_DB_SUPPORT #include "simVis/DBFormat.h" #endif -#include "simVis/Types.h" -#include "simUtil/LayerFactory.h" - namespace simUtil { /** Default cache time of one year */ static const osgEarth::TimeSpan ONE_YEAR(365 * 86400); -#ifdef SIM_HAVE_DB_SUPPORT simVis::DBImageLayer* LayerFactory::newDbImageLayer(const std::string& fullPath) const { +#ifndef SIM_HAVE_DB_SUPPORT + // Likely developer error unintended + assert(0); + return NULL; +#else osgEarth::Config config; config.setReferrer(fullPath); @@ -59,8 +63,8 @@ simVis::DBImageLayer* LayerFactory::newDbImageLayer(const std::string& fullPath) layer->setCachePolicy(cachePolicy); return layer.release(); -} #endif +} osgEarth::MBTilesImageLayer* LayerFactory::newMbTilesImageLayer(const std::string& fullPath) const { @@ -101,9 +105,13 @@ osgEarth::GDALImageLayer* LayerFactory::newGdalImageLayer(const std::string& ful return layer.release(); } -#ifdef SIM_HAVE_DB_SUPPORT simVis::DBElevationLayer* LayerFactory::newDbElevationLayer(const std::string& fullPath) const { +#ifndef SIM_HAVE_DB_SUPPORT + // Likely developer error unintended + assert(0); + return NULL; +#else osgEarth::Config config; config.setReferrer(fullPath); @@ -118,8 +126,8 @@ simVis::DBElevationLayer* LayerFactory::newDbElevationLayer(const std::string& f layer->setCachePolicy(cachePolicy); return layer.release(); -} #endif +} osgEarth::MBTilesElevationLayer* LayerFactory::newMbTilesElevationLayer(const std::string& fullPath) const { diff --git a/SDK/simUtil/LayerFactory.h b/SDK/simUtil/LayerFactory.h index 6d943ecad..90b9d6a7a 100644 --- a/SDK/simUtil/LayerFactory.h +++ b/SDK/simUtil/LayerFactory.h @@ -58,21 +58,15 @@ namespace simUtil { class SDKUTIL_EXPORT LayerFactory { public: -#ifdef SIM_HAVE_DB_SUPPORT - /** Returns an image layer properly configured for DB layer. */ + /** Returns an image layer properly configured for DB layer. May return NULL if not configured with DB support. */ simVis::DBImageLayer* newDbImageLayer(const std::string& fullPath) const; -#endif - /** Returns an image layer properly configured for MBTiles layer. */ osgEarth::MBTilesImageLayer* newMbTilesImageLayer(const std::string& fullPath) const; /** Returns an image layer properly configured for GDAL layer. */ osgEarth::GDALImageLayer* newGdalImageLayer(const std::string& fullPath) const; -#ifdef SIM_HAVE_DB_SUPPORT - /** Returns an elevation layer properly configured for DB layer. */ + /** Returns an elevation layer properly configured for DB layer. May return NULL if not configured with DB support. */ simVis::DBElevationLayer* newDbElevationLayer(const std::string& fullPath) const; -#endif - /** Returns an elevation layer properly configured for MBTiles layer. */ osgEarth::MBTilesElevationLayer* newMbTilesElevationLayer(const std::string& fullPath) const; /** Returns an elevation layer properly configured for GDAL layer. */ diff --git a/SDK/simVis/CMakeLists.txt b/SDK/simVis/CMakeLists.txt index 25feb39ab..07610ba35 100644 --- a/SDK/simVis/CMakeLists.txt +++ b/SDK/simVis/CMakeLists.txt @@ -139,6 +139,10 @@ set(VIS_HEADERS_CORE set(VIS_HEADERS_DB ${VIS_INC}DBFormat.h + ${VIS_INC}DBOptions.h +) + +set(VIS_HEADERS_DB_PRIVATE ${VIS_INC}DB/QSCommon.h ${VIS_INC}DB/QSError.h ${VIS_INC}DB/QSNodeID96.h @@ -383,12 +387,15 @@ source_group("" FILES ${VIS_ALL_HEADER}) set(VIS_HEADERS ${VIS_HEADERS_CORE} ${VIS_HEADERS_RFPROP} ${VIS_HEADERS_GOG}) set(VIS_SOURCES ${VIS_SOURCES_CORE} ${VIS_SOURCES_RFPROP} ${VIS_SOURCES_GOG} ${VIS_SHADER_FILES}) +# Add DB Format support to right MSVC folders and headers for installation if(SIM_HAVE_DB_SUPPORT) - source_group(Headers\\DB FILES ${VIS_HEADERS_DB}) + source_group(Headers FILES ${VIS_HEADERS_DB}) + source_group(Headers\\DB FILES ${VIS_HEADERS_DB_PRIVATE}) source_group(Sources\\DB FILES ${VIS_SOURCES_DB}) - - set(VIS_HEADERS ${VIS_HEADERS} ${VIS_HEADERS_DB}) - set(VIS_SOURCES ${VIS_SOURCES} ${VIS_SOURCES_DB}) + + list(APPEND VIS_HEADERS_CORE ${VIS_HEADERS_DB}) + list(APPEND VIS_HEADERS ${VIS_HEADERS_DB} ${VIS_HEADERS_DB_PRIVATE}) + list(APPEND VIS_SOURCES ${VIS_SOURCES_DB}) endif() # ---------------------------------------------------------------------- @@ -423,7 +430,7 @@ target_link_libraries(simVis PUBLIC simData simCore simNotify target_link_libraries(simVis PRIVATE VSI::GL) if(SQLITE3_FOUND) - target_link_libraries(simVis PUBLIC SQLITE3) + target_link_libraries(simVis PRIVATE SQLITE3) endif() if(SIMVIS_SHARED) @@ -431,6 +438,9 @@ if(SIMVIS_SHARED) else() target_compile_definitions(simVis PUBLIC simVis_LIB_EXPORT_STATIC) endif() +if(SIM_HAVE_DB_SUPPORT) + target_compile_definitions(simVis PRIVATE SIM_HAVE_DB_SUPPORT) +endif() if(INSTALL_SIMDIS_SDK_LIBRARIES) vsi_install_export(simVis ${SIMDIS_SDK_VERSION_STRING} AnyNewerVersion) diff --git a/SDK/simVis/Compass.cpp b/SDK/simVis/Compass.cpp index 59f2e4723..dc140a09f 100644 --- a/SDK/simVis/Compass.cpp +++ b/SDK/simVis/Compass.cpp @@ -29,7 +29,6 @@ #include "simVis/Utils.h" #include "simVis/View.h" #include "simVis/Compass.h" -#include "osgDB/ReadFile" namespace simVis { diff --git a/SDK/simVis/DB/Plugin.cpp b/SDK/simVis/DB/Plugin.cpp index 43635c2b5..4f95218cb 100644 --- a/SDK/simVis/DB/Plugin.cpp +++ b/SDK/simVis/DB/Plugin.cpp @@ -19,10 +19,10 @@ * disclose, or release this software. * */ -#include "osgEarth/TileSource" +#include #include "osgDB/FileNameUtils" #include "osgDB/Registry" -#include +#include "osgEarth/TileSource" #include "DBTileSource.h" class SimSdkOSGEarthDBDriverPlugin : public osgEarth::Contrib::TileSourceDriver diff --git a/SDK/simVis/DB/swapbytes.h b/SDK/simVis/DB/swapbytes.h index e80d007f4..af6fe9b74 100644 --- a/SDK/simVis/DB/swapbytes.h +++ b/SDK/simVis/DB/swapbytes.h @@ -19,9 +19,8 @@ * disclose, or release this software. * */ - -#ifndef SIMUTIL_SWAPBYTES_H -#define SIMUTIL_SWAPBYTES_H +#ifndef SIMVIS_DB_SWAPBYTES_H +#define SIMVIS_DB_SWAPBYTES_H #include #include @@ -777,4 +776,4 @@ namespace simVis_db } // namespace simVis_db -#endif /* SIMUTIL_SWAPBYTES_H */ +#endif /* SIMVIS_DB_SWAPBYTES_H */ diff --git a/SDK/simVis/DBFormat.cpp b/SDK/simVis/DBFormat.cpp index 001c0f39c..77fd7237b 100644 --- a/SDK/simVis/DBFormat.cpp +++ b/SDK/simVis/DBFormat.cpp @@ -20,13 +20,13 @@ * */ #include "osgDB/FileUtils" +#include "osgEarth/Cube" +#include "osgEarth/ImageToHeightFieldConverter" +#include "simCore/Calc/Math.h" #include "simVis/DBFormat.h" #include "simVis/DB/QSCommon.h" #include "simVis/DB/swapbytes.h" #include "simVis/DB/SQLiteDataBaseReadUtil.h" -#include "simCore/Calc/Math.h" -#include "osgEarth/Cube" -#include "osgEarth/ImageToHeightFieldConverter" using namespace simVis; using namespace simVis_db; @@ -167,7 +167,7 @@ namespace outImage = new osg::Image(); outImage->setImage(size, size, 1, internalFormat, pixelFormat, type, data, osg::Image::USE_NEW_DELETE); } - + bool decodeRaster_(int rasterFormat, const char* inputBuffer, int inputBufferLen, osg::ref_ptr& outImage) { switch (rasterFormat) @@ -322,12 +322,12 @@ const osgEarth::URI& DBImageLayer::getURL() const return options().url().get(); } -void DBImageLayer::setDeepestLevel(const unsigned int& value) +void DBImageLayer::setDeepestLevel(unsigned int value) { options().deepestLevel() = value; } -const unsigned int& DBImageLayer::getDeepestLevel() const +unsigned int DBImageLayer::getDeepestLevel() const { return options().deepestLevel().get(); } @@ -340,7 +340,7 @@ void DBImageLayer::init() DBImageLayer::~DBImageLayer() { - delete ((DBContext*)context_); + delete static_cast(context_); } osgEarth::Status DBImageLayer::openImplementation() @@ -349,7 +349,7 @@ osgEarth::Status DBImageLayer::openImplementation() if (parent.isError()) return parent; - DBContext& cx = *(DBContext*)context_; + DBContext& cx = *static_cast(context_); if (!options().url().isSet()) return osgEarth::Status(osgEarth::Status::ConfigurationError, "Missing required URL"); @@ -390,7 +390,7 @@ osgEarth::Status DBImageLayer::openImplementation() sqlite3_close(cx.db_); cx.db_ = NULL; return osgEarth::Status( - osgEarth::Status::ResourceUnavailable, + osgEarth::Status::ResourceUnavailable, osgEarth::Stringify() << "Failed to read metadata for " << cx.pathname_); } @@ -454,7 +454,7 @@ osgEarth::Status DBImageLayer::openImplementation() osgEarth::GeoImage DBImageLayer::createImageImplementation(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress) const { - DBContext& cx = *(DBContext*)context_; + DBContext& cx = *static_cast(context_); if (!cx.db_) return osgEarth::GeoImage::INVALID; @@ -598,12 +598,12 @@ const osgEarth::URI& DBElevationLayer::getURL() const return options().url().get(); } -void DBElevationLayer::setDeepestLevel(const unsigned int& value) +void DBElevationLayer::setDeepestLevel(unsigned int value) { options().deepestLevel() = value; } -const unsigned int& DBElevationLayer::getDeepestLevel() const +unsigned int DBElevationLayer::getDeepestLevel() const { return options().deepestLevel().get(); } @@ -616,7 +616,7 @@ void DBElevationLayer::init() DBElevationLayer::~DBElevationLayer() { - delete ((DBContext*)context_); + delete static_cast(context_); } osgEarth::Status DBElevationLayer::openImplementation() @@ -626,7 +626,7 @@ osgEarth::Status DBElevationLayer::openImplementation() return parent; - DBContext& cx = *(DBContext*)context_; + DBContext& cx = *static_cast(context_); if (!options().url().isSet()) return osgEarth::Status(osgEarth::Status::ConfigurationError, "Missing required URL"); @@ -667,7 +667,7 @@ osgEarth::Status DBElevationLayer::openImplementation() sqlite3_close(cx.db_); cx.db_ = NULL; return osgEarth::Status( - osgEarth::Status::ResourceUnavailable, + osgEarth::Status::ResourceUnavailable, osgEarth::Stringify() << "Failed to read metadata for " << cx.pathname_); } @@ -731,8 +731,8 @@ osgEarth::Status DBElevationLayer::openImplementation() osgEarth::GeoHeightField DBElevationLayer::createHeightFieldImplementation(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress) const { - DBContext& cx = *(DBContext*)context_; - + DBContext& cx = *static_cast(context_); + if (!cx.db_) return osgEarth::GeoHeightField::INVALID; diff --git a/SDK/simVis/DBFormat.h b/SDK/simVis/DBFormat.h index a9e710f60..4549518d9 100644 --- a/SDK/simVis/DBFormat.h +++ b/SDK/simVis/DBFormat.h @@ -44,7 +44,7 @@ class SDKVIS_EXPORT DBImageLayer : public osgEarth::ImageLayer public: META_LayerOptions(simVis, Options, osgEarth::ImageLayer::Options); OE_OPTION(osgEarth::URI, url); - OE_OPTION(unsigned, deepestLevel); + OE_OPTION(unsigned int, deepestLevel); virtual osgEarth::Config getConfig() const; private: void fromConfig(const osgEarth::Config&); @@ -59,8 +59,8 @@ class SDKVIS_EXPORT DBImageLayer : public osgEarth::ImageLayer const osgEarth::URI& getURL() const; /// Maximum level to use in DB file - void setDeepestLevel(const unsigned int& value); - const unsigned int& getDeepestLevel() const; + void setDeepestLevel(unsigned int value); + unsigned int getDeepestLevel() const; public: // Layer @@ -78,6 +78,8 @@ class SDKVIS_EXPORT DBImageLayer : public osgEarth::ImageLayer /// Destructor virtual ~DBImageLayer(); +private: + /// DBContext instance, a struct that maintains per-DB parameters and persistent data void* context_; }; @@ -91,7 +93,7 @@ class SDKVIS_EXPORT DBElevationLayer : public osgEarth::ElevationLayer public: META_LayerOptions(simVis, Options, osgEarth::ElevationLayer::Options); OE_OPTION(osgEarth::URI, url); - OE_OPTION(unsigned, deepestLevel); + OE_OPTION(unsigned int, deepestLevel); virtual osgEarth::Config getConfig() const; private: void fromConfig(const osgEarth::Config&); @@ -105,8 +107,8 @@ class SDKVIS_EXPORT DBElevationLayer : public osgEarth::ElevationLayer const osgEarth::URI& getURL() const; /// Maximum level to use in DB file - void setDeepestLevel(const unsigned int& value); - const unsigned int& getDeepestLevel() const; + void setDeepestLevel(unsigned int value); + unsigned int getDeepestLevel() const; public: // Layer @@ -124,6 +126,8 @@ class SDKVIS_EXPORT DBElevationLayer : public osgEarth::ElevationLayer /// Destructor virtual ~DBElevationLayer(); +private: + /// DBContext instance, a struct that maintains per-DB parameters and persistent data void* context_; }; diff --git a/SDK/simVis/GeoFence.cpp b/SDK/simVis/GeoFence.cpp index 8a9c7e7ec..c2178685c 100644 --- a/SDK/simVis/GeoFence.cpp +++ b/SDK/simVis/GeoFence.cpp @@ -21,6 +21,7 @@ */ #include "simVis/GeoFence.h" +#undef LC #define LC "[GeoFence] " namespace simVis { @@ -55,4 +56,4 @@ bool HorizonGeoFence::contains(const osg::Vec3d& p) const return dev >= minDeviation_; } -} \ No newline at end of file +} From 996f66f44bdbe6de32fb516071d6f538ee3cda8d Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 16 Jan 2020 06:27:21 -0500 Subject: [PATCH 029/121] DEV: Removed dead CMake function, now that osgEarth db loader is no longer a plug-in. Updated vsi_require_target command. Review: 20412 --- CMakeModules/CreateInstallProperties.cmake | 34 ---------------------- CMakeModules/HelperFunctions.cmake | 5 +++- 2 files changed, 4 insertions(+), 35 deletions(-) diff --git a/CMakeModules/CreateInstallProperties.cmake b/CMakeModules/CreateInstallProperties.cmake index d5bece91d..e12a6ee26 100644 --- a/CMakeModules/CreateInstallProperties.cmake +++ b/CMakeModules/CreateInstallProperties.cmake @@ -109,40 +109,6 @@ function(create_plugin_install_properties TARGET) endfunction() -# Used for SIMDIS SDK osg/osgEarth plug-ins (osgdb_osgearth_db) -function(create_osg_plugin_install_properties TARGET) - # Separate ARGN into specific lists so that the INSTALLATION_COMPONENT can be removed from create_library arg list and iterated over - set(arglists "INSTALLATION_COMPONENT") - # Option names - set(options "RPATH") - - # Get the argument lists - parse_arguments(ARG "${arglists}" "${options}" ${ARGN}) - - if(ARG_RPATH) - # Compute RPATH for lib directory containing dependencies relative to bin installation directory - set(LIBRARY_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/${INSTALLSETTINGS_LIBRARY_DIR}) - set(RUNTIME_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/${INSTALLSETTINGS_OSGPLUGIN_DIR}) - file(RELATIVE_PATH REL_INSTALL_PATH ${RUNTIME_INSTALL_PATH} ${LIBRARY_INSTALL_PATH}) - - # If the lib and bin paths were the same, an empty value will be returned - if(NOT REL_INSTALL_PATH) - set(REL_INSTALL_PATH ".") - endif() - - # Set install RPATH variable - set_target_properties(${TARGET} PROPERTIES INSTALL_RPATH "\$ORIGIN/${REL_INSTALL_PATH}") - endif() - - # Setup installation - foreach(COMPONENT ${ARG_INSTALLATION_COMPONENT}) - install(TARGETS ${TARGET} - COMPONENT ${COMPONENT} - RUNTIME DESTINATION ${INSTALLSETTINGS_OSGPLUGIN_DIR} # Windows DLL destination - LIBRARY DESTINATION ${INSTALLSETTINGS_OSGPLUGIN_DIR}) # UNIX shared object destination - endforeach() -endfunction() - # Include the code for post_build_install() command include(PostBuildInstall) diff --git a/CMakeModules/HelperFunctions.cmake b/CMakeModules/HelperFunctions.cmake index a2d98db48..523fe1464 100644 --- a/CMakeModules/HelperFunctions.cmake +++ b/CMakeModules/HelperFunctions.cmake @@ -503,7 +503,10 @@ endfunction() macro(vsi_require_target) foreach(target ${ARGN}) if(NOT TARGET ${target}) - if(VERBOSE) + if(WARN_SKIPPED_TARGETS) + get_filename_component(_DIR "${CMAKE_CURRENT_LIST_DIR}" NAME) + message(WARNING "Skipping ${_DIR}, missing target ${target}") + elseif(VERBOSE) get_filename_component(_DIR "${CMAKE_CURRENT_LIST_DIR}" NAME) message(STATUS "Skipping ${_DIR}, missing target ${target}") endif() From b4467f15021e6268d371dd7b277f9df33081139c Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 16 Jan 2020 06:28:45 -0500 Subject: [PATCH 030/121] DEV: Track Chunk now uses PointDrawable instead of geometry with GL_POINTS. Track history is now rounded properly. Fixes SIM-10906. Review: 20390 --- SDK/simVis/TrackChunkNode.cpp | 35 +++++++++++++---------------------- SDK/simVis/TrackChunkNode.h | 9 +++------ SDK/simVis/TrackHistory.cpp | 4 ++-- 3 files changed, 18 insertions(+), 30 deletions(-) diff --git a/SDK/simVis/TrackChunkNode.cpp b/SDK/simVis/TrackChunkNode.cpp index d8cffb848..1606b7b40 100644 --- a/SDK/simVis/TrackChunkNode.cpp +++ b/SDK/simVis/TrackChunkNode.cpp @@ -21,14 +21,15 @@ */ #include #include "osg/Geode" -#include "osg/Geometry" #include "osgEarth/GeoData" #include "osgEarth/LineDrawable" +#include "osgEarth/PointDrawable" #include "simVis/Types.h" #include "simVis/TrackChunkNode.h" namespace simVis { + //---------------------------------------------------------------------------- TrackPointsChunk::TrackPointsChunk(unsigned int maxSize) : maxSize_(maxSize) @@ -185,18 +186,14 @@ void TrackChunkNode::allocate_() if (mode_ == simData::TrackPrefs_Mode_POINT) { // center line (point mode) - centerPoints_ = new osg::Geometry(); - centerPoints_->setUseVertexBufferObjects(true); - centerPoints_->setUseDisplayList(false); + centerPoints_ = new osgEarth::PointDrawable(); centerPoints_->setDataVariance(osg::Object::DYNAMIC); - osg::Vec3Array* verts = new osg::Vec3Array(); - verts->assign(maxSize_, osg::Vec3()); - centerPoints_->setVertexArray(verts); - osg::Vec4Array* colors = new osg::Vec4Array(); - colors->setBinding(osg::Array::BIND_PER_VERTEX); - colors->assign(maxSize_, simVis::Color::White); - centerPoints_->setColorArray(colors); - centerPoints_->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, offset_, count_)); + centerPoints_->allocate(maxSize_); + centerPoints_->setColor(simVis::Color::White); + // finish() will create the primitive set, allowing us to micromanage first/count + centerPoints_->finish(); + centerPoints_->setFirst(offset_); + centerPoints_->setCount(count_); this->addChild(centerPoints_.get()); } else @@ -244,13 +241,8 @@ void TrackChunkNode::append_(const osg::Matrix& matrix, const osg::Vec4& color, if (mode_ == simData::TrackPrefs_Mode_POINT) { // and update the center points track as well: - osg::Vec3Array* centerPointsVerts = static_cast(centerPoints_->getVertexArray()); - (*centerPointsVerts)[i] = local; - centerPointsVerts->dirty(); - osg::Vec4Array* centerPointsColors = static_cast(centerPoints_->getColorArray()); - (*centerPointsColors)[i] = color; - centerPointsColors->dirty(); - centerPoints_->dirtyBound(); + centerPoints_->setVertex(i, local); + centerPoints_->setColor(i, color); return; } @@ -303,9 +295,8 @@ void TrackChunkNode::updatePrimitiveSets_() { if (mode_ == simData::TrackPrefs_Mode_POINT) { - osg::DrawArrays* centerPointsPrimSet = static_cast(centerPoints_->getPrimitiveSet(0)); - centerPointsPrimSet->setFirst(offset_); - centerPointsPrimSet->setCount(count_); + centerPoints_->setFirst(offset_); + centerPoints_->setCount(count_); return; } diff --git a/SDK/simVis/TrackChunkNode.h b/SDK/simVis/TrackChunkNode.h index dbc25aedd..328398923 100644 --- a/SDK/simVis/TrackChunkNode.h +++ b/SDK/simVis/TrackChunkNode.h @@ -25,13 +25,10 @@ #include "osg/ref_ptr" #include "osg/MatrixTransform" #include "osgEarth/LineDrawable" +#include "osgEarth/PointDrawable" #include "simData/DataTypes.h" -namespace osg { - class Geode; - class Geometry; -} - +namespace osg { class Geode; } namespace osgEarth { class SpatialReference; } namespace simVis @@ -184,7 +181,7 @@ class SDKVIS_EXPORT TrackChunkNode : public TrackPointsChunk private: osg::ref_ptr geode_; osg::ref_ptr centerLine_; - osg::ref_ptr centerPoints_; + osg::ref_ptr centerPoints_; osg::ref_ptr ribbon_; osg::ref_ptr drop_; diff --git a/SDK/simVis/TrackHistory.cpp b/SDK/simVis/TrackHistory.cpp index 01dd9faed..c5a7b64a6 100644 --- a/SDK/simVis/TrackHistory.cpp +++ b/SDK/simVis/TrackHistory.cpp @@ -22,6 +22,7 @@ #include #include "osgEarth/Capabilities" +#include "osgEarth/GLUtils" #include "osgEarth/Horizon" #include "osgEarth/LineDrawable" #include "osgEarth/Registry" @@ -33,7 +34,6 @@ #include "simVis/Locator.h" #include "simVis/OverheadMode.h" #include "simVis/PlatformFilter.h" -#include "simVis/PointSize.h" #include "simVis/Shaders.h" #include "simVis/Types.h" #include "simVis/Utils.h" @@ -576,7 +576,7 @@ void TrackHistoryNode::setPrefs(const simData::PlatformPrefs& platformPrefs, con const double lineWidth = osg::clampAbove(prefs.linewidth(), 1.0); osg::StateSet* stateSet = this->getOrCreateStateSet(); osgEarth::LineDrawable::setLineWidth(stateSet, lineWidth); - PointSize::setValues(stateSet, lineWidth, osg::StateAttribute::ON); + osgEarth::GLUtils::setPointSize(stateSet, lineWidth, osg::StateAttribute::ON); } if (force || PB_FIELD_CHANGED(&lastPrefs, &prefs, tracklength)) From b0094d889e50532937d35d7736343e2bed5eb8a0 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 16 Jan 2020 06:29:01 -0500 Subject: [PATCH 031/121] DEV: Removed SphericalVolume's DRAW_MODE_POINTS, as it was unused. Fixes SIM-10904 by making it OBE. Review: 20389 --- SDK/simVis/SphericalVolume.cpp | 7 ------- SDK/simVis/SphericalVolume.h | 3 +-- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/SDK/simVis/SphericalVolume.cpp b/SDK/simVis/SphericalVolume.cpp index 2c8d17822..5123eca66 100644 --- a/SDK/simVis/SphericalVolume.cpp +++ b/SDK/simVis/SphericalVolume.cpp @@ -1059,13 +1059,6 @@ void SVFactory::createCone_(osg::Geode* geode, const SVData& d, const osg::Vec3& // asserting that we used all the vertices we expected to // if assert fails, check numVerts calculation assert(numVerts == vptr); - - // highlights the face points for a visual effect: - if (SVData::DRAW_MODE_POINTS & d.drawMode_) - { - geom->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, wallOffset)); - PointSize::setValues(geom->getOrCreateStateSet(), 3.f, osg::StateAttribute::ON); - } } } diff --git a/SDK/simVis/SphericalVolume.h b/SDK/simVis/SphericalVolume.h index 2c0d5036f..415f882b3 100644 --- a/SDK/simVis/SphericalVolume.h +++ b/SDK/simVis/SphericalVolume.h @@ -49,8 +49,7 @@ struct SVData DRAW_MODE_SOLID = 1 << 0, ///< solid (probably translucent) DRAW_MODE_STIPPLE = 1 << 1, ///< stippled (many small dots) DRAW_MODE_WIRE = 1 << 2, ///< wireframe - DRAW_MODE_OUTLINE = 1 << 3, ///< outlines only - DRAW_MODE_POINTS = 1 << 4 ///< points at the key locations + DRAW_MODE_OUTLINE = 1 << 3 ///< outlines only }; /** Draw as a pyramid or cone */ From 2e186598cbb6cf755002cde83dec2114ef7ecf89 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 16 Jan 2020 06:29:08 -0500 Subject: [PATCH 032/121] DEV: LocalGrid now uses PointDrawable for the inter-cardinal lines. Slightly increased point size to account for roundness. Review: 20387 --- SDK/simVis/LocalGrid.cpp | 73 +++++++++++++++++----------------------- SDK/simVis/LocalGrid.h | 6 ++-- 2 files changed, 34 insertions(+), 45 deletions(-) diff --git a/SDK/simVis/LocalGrid.cpp b/SDK/simVis/LocalGrid.cpp index a5618ccf3..19b05cb93 100644 --- a/SDK/simVis/LocalGrid.cpp +++ b/SDK/simVis/LocalGrid.cpp @@ -26,9 +26,11 @@ #include "osg/Geometry" #include "osgText/Text" +#include "osgEarth/Color" +#include "osgEarth/GLUtils" +#include "osgEarth/PointDrawable" #include "osgEarth/Registry" #include "osgEarth/ShaderGenerator" -#include "osgEarth/Color" #include "simCore/Calc/Math.h" #include "simNotify/Notify.h" @@ -38,7 +40,6 @@ #include "simVis/Constants.h" #include "simVis/Locator.h" #include "simVis/Platform.h" -#include "simVis/PointSize.h" #include "simVis/Registry.h" #include "simVis/Types.h" #include "simVis/Utils.h" @@ -287,16 +288,15 @@ class Axis : public LineStrip }; /// Geometry for off-axis sectors in Polar and SpeedRing grid types. -class RadialPoints : public osg::Geometry +class RadialPoints : public osg::Group { public: RadialPoints(const osg::Vec4f& color, float sectorAngleDeg, unsigned int numRings) : sectorAngleDeg_(sectorAngleDeg), - numRings_(numRings) + numRings_(numRings), + points_(new osgEarth::PointDrawable) { setName("simVis::LocalGridNode::RadialPoints"); - setUseVertexBufferObjects(true); - setUseDisplayList(false); // determine how many vertices we'll actually use unsigned int vertexCount = 0; @@ -310,26 +310,15 @@ class RadialPoints : public osg::Geometry { if (osg::equivalent(static_cast(fmod(static_cast(i), RADIAL_VERTEX_FACTOR)), 0.f)) // don't overdraw the rings continue; - vertexCount++; + ++vertexCount; } } - osg::ref_ptr vertexArray = new osg::Vec3Array(osg::Array::BIND_PER_VERTEX, vertexCount); - setVertexArray(vertexArray.get()); - - osg::ref_ptr colorArray = new osg::Vec4Array(osg::Array::BIND_OVERALL, 1); - (*colorArray)[0] = color; - setColorArray(colorArray.get()); - - addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, vertexArray->size())); + points_->allocate(vertexCount); + points_->setColor(color); + addChild(points_); } void update(double sizeM) { - osg::ref_ptr vertexArray = dynamic_cast(getVertexArray()); - if (!vertexArray) - { - assert(0); - return; - } const float spacingM = sizeM / osg::maximum(1u, numRings_); const float radialVertexSpacing = spacingM / RADIAL_VERTEX_FACTOR; size_t index = 0; @@ -348,15 +337,16 @@ class RadialPoints : public osg::Geometry continue; // if assert fails, re-check algorithm for determining vertexCount in constructor assert(index < vertexArray->getNumElements()); - (*vertexArray)[index] = osg::Vec3(x * radialVertexSpacing * i, y * radialVertexSpacing * i, 0.f); - index++; + points_->setVertex(index, osg::Vec3f(x * radialVertexSpacing * i, y * radialVertexSpacing * i, 0.f)); + ++index; } } - vertexArray->dirty(); + points_->dirty(); } private: float sectorAngleDeg_; unsigned int numRings_; + osgEarth::PointDrawable* points_; }; /// Geometry for range rings in Polar, RangeRing and SpeedRing grid types. @@ -461,8 +451,7 @@ void LocalGridNode::rebuild_(const simData::LocalGridPrefs& prefs) { graphicsGroup_ = new osg::Geode(); graphicsGroup_->setName("simVis::LocalGridNode::GraphicsGeode"); - osg::StateSet* ss = graphicsGroup_->getOrCreateStateSet(); - PointSize::setValues(ss, 1.5f, osg::StateAttribute::ON); + osgEarth::GLUtils::setPointSize(graphicsGroup_->getOrCreateStateSet(), 2.f, osg::StateAttribute::ON); addChild(graphicsGroup_.get()); } @@ -673,7 +662,7 @@ void LocalGridNode::syncWithLocator() } // creates a Cartesian grid. -void LocalGridNode::createCartesian_(const simData::LocalGridPrefs& prefs, osg::Geode* geomGroup, osg::Geode* labelGroup) const +void LocalGridNode::createCartesian_(const simData::LocalGridPrefs& prefs, osg::Group* geomGroup, osg::Geode* labelGroup) const { const osgEarth::Units& sizeUnits = simVis::convertUnitsToOsgEarth(prefs.sizeunits()); // Note that size is halved; it's provided in diameter, and we need it as radius @@ -705,7 +694,7 @@ void LocalGridNode::createCartesian_(const simData::LocalGridPrefs& prefs, osg:: sub1->update(osg::Vec3(x, y0, 0.f), osg::Vec3(x, y0 + span, 0.f)); sub1->setName("simVis::LocalGridNode::GridSubDivision1"); sub1->setColor(subColor); - geomGroup->addDrawable(sub1); + geomGroup->addChild(sub1); } { const float y = y0 + subSpacing * s; @@ -713,7 +702,7 @@ void LocalGridNode::createCartesian_(const simData::LocalGridPrefs& prefs, osg:: sub2->update(osg::Vec3(x0, y, 0.f), osg::Vec3(x0 + span, y, 0.f)); sub2->setName("simVis::LocalGridNode::GridSubDivision2"); sub2->setColor(subColor); - geomGroup->addDrawable(sub2); + geomGroup->addChild(sub2); } } @@ -726,7 +715,7 @@ void LocalGridNode::createCartesian_(const simData::LocalGridPrefs& prefs, osg:: div1->update(osg::Vec3(x, y0, 0.f), osg::Vec3(x, y0 + span, 0.f)); div1->setName("simVis::LocalGridNode::GridDivision1"); div1->setColor(color); - geomGroup->addDrawable(div1); + geomGroup->addChild(div1); } // x-label: if (x < 0 && prefs.gridlabeldraw()) @@ -742,7 +731,7 @@ void LocalGridNode::createCartesian_(const simData::LocalGridPrefs& prefs, osg:: div2->update(osg::Vec3(x0, y, 0.f), osg::Vec3(x0 + span, y, 0.f)); div2->setName("simVis::LocalGridNode::GridDivision2"); div2->setColor(color); - geomGroup->addDrawable(div2); + geomGroup->addChild(div2); } // y-label if (y > 0 && prefs.gridlabeldraw()) @@ -755,7 +744,7 @@ void LocalGridNode::createCartesian_(const simData::LocalGridPrefs& prefs, osg:: } // creates a range-rings local grid with optional polar radials. -void LocalGridNode::createRangeRings_(const simData::LocalGridPrefs& prefs, osg::Geode* geomGroup, osg::Geode* labelGroup, bool includePolarRadials) const +void LocalGridNode::createRangeRings_(const simData::LocalGridPrefs& prefs, osg::Group* geomGroup, osg::Geode* labelGroup, bool includePolarRadials) const { const osgEarth::Units& sizeUnits = simVis::convertUnitsToOsgEarth(prefs.sizeunits()); // Note that size is halved; it's provided in diameter, and we need it as radius @@ -785,7 +774,7 @@ void LocalGridNode::createRangeRings_(const simData::LocalGridPrefs& prefs, osg: RangeRing* rangeRing = new RangeRing(i); rangeRing->setColor(isMajorRing ? color : subColor); - geomGroup->addDrawable(rangeRing); + geomGroup->addChild(rangeRing); rangeRing->update(prefs, sizeM); // label: @@ -807,26 +796,26 @@ void LocalGridNode::createRangeRings_(const simData::LocalGridPrefs& prefs, osg: { Axis* majorAxis = new Axis(true); majorAxis->setColor(color); - geomGroup->addDrawable(majorAxis); + geomGroup->addChild(majorAxis); majorAxis->update(sizeM); Axis* minorAxis = new Axis(false); minorAxis->setColor(color); - geomGroup->addDrawable(minorAxis); + geomGroup->addChild(minorAxis); minorAxis->update(sizeM); const float sectorAngle = prefs.gridsettings().sectorangle(); if (sectorAngle > 0.0f) { RadialPoints* points = new RadialPoints(subColor, sectorAngle, numRings); - geomGroup->addDrawable(points); + geomGroup->addChild(points); points->update(sizeM); } } } // creates a speed-rings local grid with optional polar radials. -void LocalGridNode::createSpeedRings_(const simData::LocalGridPrefs& prefs, osg::Geode* graphicsGroup, osg::Geode* labelGroup, bool drawSpeedLine) const +void LocalGridNode::createSpeedRings_(const simData::LocalGridPrefs& prefs, osg::Group* graphicsGroup, osg::Geode* labelGroup, bool drawSpeedLine) const { const osg::Vec4f& color = simVis::Color(prefs.gridcolor(), simVis::Color::RGBA); const osg::Vec4f& subColor = simVis::Color(color * 0.5f, 1.0f); @@ -839,7 +828,7 @@ void LocalGridNode::createSpeedRings_(const simData::LocalGridPrefs& prefs, osg: SpeedLine* speedLine = new SpeedLine(); speedLine->setDataVariance(osg::Object::DYNAMIC); speedLine->setColor(color); - graphicsGroup->addDrawable(speedLine); + graphicsGroup->addChild(speedLine); if (!prefs.gridlabeldraw()) return; @@ -849,11 +838,11 @@ void LocalGridNode::createSpeedRings_(const simData::LocalGridPrefs& prefs, osg: Axis* majorAxis = new Axis(true); majorAxis->setDataVariance(osg::Object::DYNAMIC); majorAxis->setColor(color); - graphicsGroup->addDrawable(majorAxis); + graphicsGroup->addChild(majorAxis); Axis* minorAxis = new Axis(false); minorAxis->setDataVariance(osg::Object::DYNAMIC); minorAxis->setColor(color); - graphicsGroup->addDrawable(minorAxis); + graphicsGroup->addChild(minorAxis); const float sectorAngle = prefs.gridsettings().sectorangle(); // draw polar radials for speed rings @@ -861,7 +850,7 @@ void LocalGridNode::createSpeedRings_(const simData::LocalGridPrefs& prefs, osg: { RadialPoints* points = new RadialPoints(subColor, sectorAngle, numRings); points->setDataVariance(osg::Object::DYNAMIC); - graphicsGroup->addDrawable(points); + graphicsGroup->addChild(points); } } @@ -873,7 +862,7 @@ void LocalGridNode::createSpeedRings_(const simData::LocalGridPrefs& prefs, osg: RangeRing* speedRing = new RangeRing(i); speedRing->setDataVariance(osg::Object::DYNAMIC); speedRing->setColor(isMajorRing ? color : subColor); - graphicsGroup->addDrawable(speedRing); + graphicsGroup->addChild(speedRing); } // labels are only added to major rings if (isMajorRing && prefs.gridlabeldraw()) diff --git a/SDK/simVis/LocalGrid.h b/SDK/simVis/LocalGrid.h index 2354fd457..e4d2d9d17 100644 --- a/SDK/simVis/LocalGrid.h +++ b/SDK/simVis/LocalGrid.h @@ -89,13 +89,13 @@ namespace simVis void configureLocator_(const simData::LocalGridPrefs& prefs); /// create Cartesian grid display - void createCartesian_(const simData::LocalGridPrefs& prefs, osg::Geode* geomGroup, osg::Geode* labelGroup) const; + void createCartesian_(const simData::LocalGridPrefs& prefs, osg::Group* geomGroup, osg::Geode* labelGroup) const; /// create polar ring or range ring display - void createRangeRings_(const simData::LocalGridPrefs& prefs, osg::Geode* geomGroup, osg::Geode* labelGroup, bool includePolarRadials) const; + void createRangeRings_(const simData::LocalGridPrefs& prefs, osg::Group* geomGroup, osg::Geode* labelGroup, bool includePolarRadials) const; /// create speed ring or speed line display - void createSpeedRings_(const simData::LocalGridPrefs& prefs, osg::Geode* geomGroup, osg::Geode* labelGroup, bool drawSpeedLine) const; + void createSpeedRings_(const simData::LocalGridPrefs& prefs, osg::Group* geomGroup, osg::Geode* labelGroup, bool drawSpeedLine) const; /// update the speed ring/line display for current data void updateSpeedRings_(const simData::LocalGridPrefs& prefs, double sizeM, double timeRadiusSeconds); From db26d5058a6ab4b5ca707791438a236f5d88d1a4 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 16 Jan 2020 06:31:30 -0500 Subject: [PATCH 033/121] SDK NEW FEATURE: DB Driver osgEarth Plug-in is no longer built. Instead, DB support is built directly into simVis, matching new osgEarth 3.0 style. Review: 20422 --- Plugins/CMakeLists.txt | 7 - Plugins/OSGEarthDBDriver/CMakeLists.txt | 50 -- .../OSGEarthDBDriver/include/DBTileSource.h | 89 -- Plugins/OSGEarthDBDriver/include/QSCommon.h | 50 -- Plugins/OSGEarthDBDriver/include/QSError.h | 81 -- Plugins/OSGEarthDBDriver/include/QSNodeID96.h | 64 -- .../OSGEarthDBDriver/include/QSPosXYExtents.h | 85 -- .../OSGEarthDBDriver/include/RasterCommon.h | 0 .../include/SQLiteDataBaseReadUtil.h | 162 ---- Plugins/OSGEarthDBDriver/include/swapbytes.h | 780 ------------------ Plugins/OSGEarthDBDriver/src/DBTileSource.cpp | 667 --------------- Plugins/OSGEarthDBDriver/src/Plugin.cpp | 56 -- Plugins/OSGEarthDBDriver/src/QSError.cpp | 171 ---- Plugins/OSGEarthDBDriver/src/QSNodeID96.cpp | 302 ------- .../OSGEarthDBDriver/src/QSPosXYExtents.cpp | 170 ---- .../src/SQLiteDataBaseReadUtil.cpp | 364 -------- 16 files changed, 3098 deletions(-) delete mode 100644 Plugins/OSGEarthDBDriver/CMakeLists.txt delete mode 100644 Plugins/OSGEarthDBDriver/include/DBTileSource.h delete mode 100644 Plugins/OSGEarthDBDriver/include/QSCommon.h delete mode 100644 Plugins/OSGEarthDBDriver/include/QSError.h delete mode 100644 Plugins/OSGEarthDBDriver/include/QSNodeID96.h delete mode 100644 Plugins/OSGEarthDBDriver/include/QSPosXYExtents.h delete mode 100644 Plugins/OSGEarthDBDriver/include/RasterCommon.h delete mode 100644 Plugins/OSGEarthDBDriver/include/SQLiteDataBaseReadUtil.h delete mode 100644 Plugins/OSGEarthDBDriver/include/swapbytes.h delete mode 100644 Plugins/OSGEarthDBDriver/src/DBTileSource.cpp delete mode 100644 Plugins/OSGEarthDBDriver/src/Plugin.cpp delete mode 100644 Plugins/OSGEarthDBDriver/src/QSError.cpp delete mode 100644 Plugins/OSGEarthDBDriver/src/QSNodeID96.cpp delete mode 100644 Plugins/OSGEarthDBDriver/src/QSPosXYExtents.cpp delete mode 100644 Plugins/OSGEarthDBDriver/src/SQLiteDataBaseReadUtil.cpp diff --git a/Plugins/CMakeLists.txt b/Plugins/CMakeLists.txt index 49208ea63..cee1e9df0 100644 --- a/Plugins/CMakeLists.txt +++ b/Plugins/CMakeLists.txt @@ -1,10 +1,3 @@ -# DB plugin no longer needed with osgEarth 3.x -#if(SQLITE3_LIBRARY_RELEASE_NAME) -# add_subdirectory(OSGEarthDBDriver) -#else() -# message(STATUS "Skipping osgEarth .db Driver plug-in because of missing dependencies.") -#endif() - if(QT_FOUND) option(ENABLE_QTDESIGNER_WIDGETS "Build Qt Designer Plugins for simQt widgets" ON) if(ENABLE_QTDESIGNER_WIDGETS) diff --git a/Plugins/OSGEarthDBDriver/CMakeLists.txt b/Plugins/OSGEarthDBDriver/CMakeLists.txt deleted file mode 100644 index 49fbafed2..000000000 --- a/Plugins/OSGEarthDBDriver/CMakeLists.txt +++ /dev/null @@ -1,50 +0,0 @@ -if(NOT SQLITE3_FOUND OR NOT OSG_FOUND OR NOT OPENTHREADS_FOUND OR NOT OSGEARTH_FOUND) - return() -endif() - -project(PLUGIN_OSGEARTH_DB_DRIVER) - -set(PROJECT_SRC - src/Plugin.cpp - src/DBTileSource.cpp - src/QSError.cpp - src/QSNodeID96.cpp - src/QSPosXYExtents.cpp - src/SQLiteDataBaseReadUtil.cpp -) - -set(PROJECT_HEADERS - include/DBTileSource.h - include/QSCommon.h - include/QSError.h - include/QSNodeID96.h - include/QSPosXYExtents.h - include/SQLiteDataBaseReadUtil.h - include/swapbytes.h -) - -add_library(osgdb_osgearth_db SHARED ${PROJECT_HEADERS} ${PROJECT_SRC}) -target_include_directories(osgdb_osgearth_db PRIVATE include ${SIMDIS_SDK_BINARY_DIR}/simVis/include) -target_link_libraries(osgdb_osgearth_db - PRIVATE - SQLITE3 - OSG OSGDB OPENTHREADS - OSGEARTH - simCore -) -target_compile_definitions(osgdb_osgearth_db PRIVATE USE_SIMDIS_SDK) -if(SDK_BIG_ENDIAN) - target_compile_definitions(osgdb_osgearth_db PRIVATE SIM_BIG_ENDIAN) -else() - target_compile_definitions(osgdb_osgearth_db PRIVATE SIM_LITTLE_ENDIAN) -endif() -if(NOT WIN32) - target_compile_definitions(osgdb_osgearth_db PRIVATE Linux) -endif() - -set_target_properties(osgdb_osgearth_db PROPERTIES - PREFIX "" - FOLDER "OSG Plugins" - PROJECT_LABEL "osgEarth .db Driver" -) -vsi_install_shared_library(osgdb_osgearth_db SDK_OSG_Plugins "${INSTALLSETTINGS_OSGPLUGIN_DIR}") diff --git a/Plugins/OSGEarthDBDriver/include/DBTileSource.h b/Plugins/OSGEarthDBDriver/include/DBTileSource.h deleted file mode 100644 index f2dfc4c5a..000000000 --- a/Plugins/OSGEarthDBDriver/include/DBTileSource.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ - -#ifndef SIMDIS_PLUGIN_OSGEARTH_DB_DRIVER_H -#define SIMDIS_PLUGIN_OSGEARTH_DB_DRIVER_H 1 - -#include "sqlite3.h" -#include "osgEarth/TileSource" -#include "simCore/Time/Utils.h" -#include "simVis/DBOptions.h" -#include "QSPosXYExtents.h" -#include "SQLiteDataBaseReadUtil.h" - -namespace simVis_db -{ - class DBTileSource : public osgEarth::Contrib::TileSource - { - public: - /** Constructs a new driver for reading .DB raster files */ - DBTileSource(const osgEarth::Contrib::TileSourceOptions& options); - - /// TileSource interface - virtual osgEarth::Status initialize(const osgDB::Options* dbOptions); - virtual osg::Image* createImage(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress); - virtual osg::HeightField* createHeightField(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress); - virtual std::string getExtension() const; - virtual int getPixelsPerTile() const; - - protected: - virtual ~DBTileSource(); - - private: - bool decodeRaster_( - int rasterFormat, - const char* inputBuffer, - int inputBufferLen, - osg::ref_ptr& out_image); - - osg::Image* createImage_(const osgEarth::TileKey& key, bool isHeightField); - - const simVis::DBOptions options_; - std::string pathname_; - sqlite3* db_; - SQLiteDataBaseReadUtil dbUtil_; - - // layer metadata - /** Defined in RasterCommon.h */ - int rasterFormat_; - /** AKA tile size */ - int pixelLength_; - int shallowLevel_; - int deepLevel_; - PosXPosYExtents extents_[6]; - std::string source_; - std::string classification_; - std::string description_; - bool timeSpecified_; - simCore::TimeStamp timeStamp_; - - osg::ref_ptr pngReader_; - osg::ref_ptr jpgReader_; - osg::ref_ptr tifReader_; - osg::ref_ptr rgbReader_; - }; - -} // namespace simVis_db - - -#endif // SIMDIS_PLUGIN_OSGEARTH_DB_DRIVER_H - diff --git a/Plugins/OSGEarthDBDriver/include/QSCommon.h b/Plugins/OSGEarthDBDriver/include/QSCommon.h deleted file mode 100644 index 6e1f6d744..000000000 --- a/Plugins/OSGEarthDBDriver/include/QSCommon.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ -#ifndef QS_COMMON_H -#define QS_COMMON_H - -#include "simCore/Common/Common.h" - -namespace simVis_db -{ - typedef uint8_t FaceIndexType; - typedef uint8_t TextureDataType; - typedef uint8_t RasterFormat; - - /// Raster formats - static const RasterFormat SPLIT_UNKNOWN = 0; - static const RasterFormat SPLIT_SGI_RGB = 1; - static const RasterFormat SPLIT_SGI_RGBA = 2; - static const RasterFormat SPLIT_5551_GZ = 3; - static const RasterFormat SPLIT_5551_ZLIB_COMPRESS = 4; - static const RasterFormat SPLIT_RGBA_ZLIB_COMPRESS = 5; - static const RasterFormat SPLIT_INTA_ZLIB_COMPRESS = 6; - static const RasterFormat SPLIT_JPEG_2000 = 8; - static const RasterFormat SPLIT_8BIT_GZ = 9; // GL_LUMINANCE - static const RasterFormat SPLIT_8BIT_ZLIB_COMPRESS = 10; - static const RasterFormat SPLIT_FLOAT32_ZLIB_COMPRESS = 11; - static const RasterFormat SPLIT_JPEG = 12; - static const RasterFormat SPLIT_PNG = 13; - static const RasterFormat SPLIT_TIFF = 14; -} // namespace simVis_db - -#endif /* QS_COMMON_H */ diff --git a/Plugins/OSGEarthDBDriver/include/QSError.h b/Plugins/OSGEarthDBDriver/include/QSError.h deleted file mode 100644 index e4d3c42d1..000000000 --- a/Plugins/OSGEarthDBDriver/include/QSError.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ - -#ifndef QS_ERROR_H -#define QS_ERROR_H - -#include - -namespace simVis_db -{ - //=========================================================================== - typedef int QsErrorType; - static const QsErrorType QS_IS_OK = 0; - static const QsErrorType QS_IS_COMMAND_LINE = 1; - static const QsErrorType QS_IS_UNEXPECTED_NULL = 2; - static const QsErrorType QS_IS_NO_TMPDIR = 3; - static const QsErrorType QS_IS_UNABLE_TO_OPEN_DB = 4; - static const QsErrorType QS_IS_UNABLE_TO_OPEN_SRC_DS = 5; - static const QsErrorType QS_IS_UNABLE_TO_GET_SRC_DRIVER = 6; - static const QsErrorType QS_IS_UNABLE_TO_GET_SRC_DRIVER_NAME = 7; - static const QsErrorType QS_IS_UNABLE_TO_CONVERT_TO_GEOGRAPHIC = 8; - static const QsErrorType QS_IS_UNABLE_TO_CREATE_INFO_FILE = 9; - static const QsErrorType QS_IS_UNABLE_TO_OPEN_INFO_FILE = 10; - static const QsErrorType QS_IS_TIME_STRING_ERROR = 11; - static const QsErrorType QS_IS_UNABLE_TO_GET_FACE_STRING = 12; - static const QsErrorType QS_IS_DB_NOT_INITIALIZED = 13; - static const QsErrorType QS_IS_UNABLE_TO_CREATE_TN_INDEX = 14; - static const QsErrorType QS_IS_UNABLE_TO_INSERT_TS_INTO_LIST = 15; - static const QsErrorType QS_IS_EMPTY_TABLE_NAME = 16; - static const QsErrorType QS_IS_UNABLE_TO_CREATE_TABLE = 17; - static const QsErrorType QS_IS_UNABLE_TO_CREATE_ID_INDEX = 18; - static const QsErrorType QS_IS_UNABLE_TO_CREATE_P_IMAGE = 19; - static const QsErrorType QS_IS_UNABLE_TO_READ_FROM_RASTER = 20; - static const QsErrorType QS_IS_FORMAT_NOT_IMPLEMENTED = 21; - static const QsErrorType QS_IS_UNABLE_TO_WRITE_TO_BLOB = 22; - static const QsErrorType QS_IS_UNABLE_SCALE_IMAGE = 23; - static const QsErrorType QS_IS_PREPARE_ERROR = 24; - static const QsErrorType QS_IS_TS_NOT_FOUND = 25; - static const QsErrorType QS_IS_UNABLE_TO_UPDATE_EXTENTS = 26; - static const QsErrorType QS_IS_UNABLE_TO_WRITE_DATA_BUFFER = 27; - static const QsErrorType QS_IS_UNABLE_TO_READ_DATA_BUFFER = 28; - static const QsErrorType QS_IS_BUSY = 29; - static const QsErrorType QS_IS_UNABLE_TO_UPDATE_TIME = 30; - static const QsErrorType QS_IS_UNABLE_TO_SET_NUM_BYTES = 31; - static const QsErrorType QS_IS_UNABLE_TO_GET_AVERAGE_REQUEST_TIME = 32; - static const QsErrorType QS_IS_UNABLE_TO_REMOVE_OLDER_THAN_AVG = 33; - static const QsErrorType QS_IS_UNABLE_TO_SUM_NUMBER_OF_BYTES = 34; - static const QsErrorType QS_IS_UNABLE_TO_WRITE_TO_OUTPUT_DIR = 35; - static const QsErrorType QS_IS_COULD_NOT_CREATE_FUNCTION = 36; - static const QsErrorType QS_IS_EMPTY_FUNCTION_NAME = 37; - static const QsErrorType QS_IS_UNABLE_TO_EXECUTE_FUNCTION = 38; - static const QsErrorType QS_IS_UNABLE_TO_WRITE_TO_RASTER = 39; - static const QsErrorType QS_IS_EMPTY_FILENAME = 40; - static const QsErrorType QS_IS_SET_CREATION_FAILED = 41; - static const QsErrorType QS_IS_NO_TIME_STAMP = 42; - - //=========================================================================== - const char* GetErrorString(const QsErrorType&); - -} // namespace simVis_db - -#endif /* QS_ERROR_H */ diff --git a/Plugins/OSGEarthDBDriver/include/QSNodeID96.h b/Plugins/OSGEarthDBDriver/include/QSNodeID96.h deleted file mode 100644 index 54d9cb6bc..000000000 --- a/Plugins/OSGEarthDBDriver/include/QSNodeID96.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ - -#ifndef QSNODEID96_H -#define QSNODEID96_H - -#include -#include "simCore/Common/Common.h" - -namespace simVis_db -{ - class QSNodeID96 - { - public: - QSNodeID96(); - QSNodeID96(const uint32_t& value); - ~QSNodeID96(); - - bool operator==(const QSNodeID96& value) const; - bool operator<(const QSNodeID96& value) const; - QSNodeID96& operator=(const QSNodeID96& value); - QSNodeID96 operator~() const; - QSNodeID96& operator|=(const QSNodeID96& value); - QSNodeID96& operator&=(const QSNodeID96& value); - QSNodeID96 operator>>(int numBitsToShift) const; - QSNodeID96 operator<<(int numBitsToShift) const; - QSNodeID96 operator&(const QSNodeID96& value) const; - - int SizeOf() const {return 12;} - void Pack(uint8_t*) const; - void UnPack(const uint8_t*); - std::string FormatAsHex(bool bLeadingZeros=true) const; - - protected: - uint32_t one_; - uint32_t two_; - uint32_t three_; - }; - - //=========================================================================== - typedef QSNodeID96 QSNodeId; - -} // namespace simVis_db - -#endif /* QSNODEID96_H */ diff --git a/Plugins/OSGEarthDBDriver/include/QSPosXYExtents.h b/Plugins/OSGEarthDBDriver/include/QSPosXYExtents.h deleted file mode 100644 index e00f32be3..000000000 --- a/Plugins/OSGEarthDBDriver/include/QSPosXYExtents.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ - -#ifndef QS_POSXY_EXTENTS_H -#define QS_POSXY_EXTENTS_H - -namespace simVis_db -{ - typedef uint64_t QsPosType; - -#if defined Linux || defined Solaris - static const QsPosType gQsMaxLength = 4294967296LL; -#else - static const QsPosType gQsMaxLength = 4294967296; -#endif - static const double gQsDMaxLength = 4294967296.0; - - /** A bounding rectangle of x/y extents */ - struct PosXPosYExtents - { - QsPosType minX; - QsPosType maxX; - QsPosType minY; - QsPosType maxY; - - PosXPosYExtents(QsPosType minX=gQsMaxLength, QsPosType maxX=0, QsPosType minY=gQsMaxLength, QsPosType maxY=0); - - /** Sets up invalid extents */ - void Initialize(); - - /** Confirms validity of extents */ - bool Valid() const; - - /** Sets the extents */ - void SetAll(const PosXPosYExtents& given); - void SetAll(const QsPosType& minX, const QsPosType& maxX, const QsPosType& minY, const QsPosType& maxY); - - /** Packs/unpacks the extents into or from a buffer */ - void Pack(uint8_t*) const; - void UnPack(const uint8_t*); - - /** Prints the extents to the console */ - void Print(); - }; - - //===================================================================================== - bool equalTo(const PosXPosYExtents& a, const PosXPosYExtents& b); - bool operator==(const PosXPosYExtents& a, const PosXPosYExtents& b); - bool operator!=(const PosXPosYExtents& a, const PosXPosYExtents& b); - - //===================================================================================== - /** Updates extents such that the given x/y is within the extents */ - void UpdateExtents(const QsPosType& posX, const QsPosType& posY, PosXPosYExtents* extents); - - /** Copies an array of 6 extents */ - bool Copy6Extents(const PosXPosYExtents*, PosXPosYExtents*); - - /** Checks for any overlap between two rectangles */ - bool AnyOverlap(const PosXPosYExtents&, const PosXPosYExtents&); - - /** Checks if the given x/y is within the given extents */ - bool AnyOverlap(const QsPosType& posX, const QsPosType& posY, const PosXPosYExtents&); - -} // Namespace simVis_db - -#endif /* QS_POSXY_EXTENTS_H */ diff --git a/Plugins/OSGEarthDBDriver/include/RasterCommon.h b/Plugins/OSGEarthDBDriver/include/RasterCommon.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/Plugins/OSGEarthDBDriver/include/SQLiteDataBaseReadUtil.h b/Plugins/OSGEarthDBDriver/include/SQLiteDataBaseReadUtil.h deleted file mode 100644 index db708e850..000000000 --- a/Plugins/OSGEarthDBDriver/include/SQLiteDataBaseReadUtil.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ - -#ifndef SQLITE_DATABASE_READ_UTIL_H -#define SQLITE_DATABASE_READ_UTIL_H - -#include -#include "sqlite3.h" -#include "simCore/Time/TimeClass.h" -#include "QSCommon.h" -#include "QSError.h" -#include "QSNodeID96.h" -#include "QSPosXYExtents.h" - -// Temporary defines until we update sqlite -#ifndef SQLITE_OPEN_READONLY -#define SQLITE_OPEN_READONLY 0x00000001 -#define SQLITE_OPEN_READWRITE 0x00000002 -#define SQLITE_OPEN_CREATE 0x00000004 -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 -#define SQLITE_OPEN_MAIN_DB 0x00000100 -#define SQLITE_OPEN_TEMP_DB 0x00000200 -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 -#define SQLITE_OPEN_NOMUTEX 0x00008000 -#define SQLITE_OPEN_FULLMUTEX 0x00010000 -#endif /* SQLITE_OPEN_READONLY */ - -namespace simVis_db -{ - static const char* QS_TO_ID = "id"; - - //===================================================================================== - static const char* QS_DEFAULT_SET_TABLE_NAME = "default"; - static const char* SPLITTER_STRING_OUTPUTDB = "dbFile"; - static const char* SIMQS_CONFIG_TABLENAME_KEYWORD = "tableName"; - static const char* QS_LIST_OF_TEXTURE_SETS_TABLE_NAME = "ListOfTextureSets"; - static const char* QS_TSO_NAME_OF_TEXTURE_SET_TABLE = "nt"; - static const char* QS_TSO_OUTPUT_TYPE = "ot"; - static const char* QS_TSO_PIXEL_LENGTH = "pl"; - static const char* QS_TSO_SHALLOWEST_LEVEL = "sl"; - static const char* QS_TSO_DEEPEST_LEVEL = "dl"; - static const char* QS_TSO_EXTENTS = "ex"; - static const char* QS_TSO_SOURCE = "s"; - static const char* QS_TSO_CLASSIFICATION = "c"; - static const char* QS_TSO_DESCRIPTION = "ds"; - static const char* QS_TSO_TIME_SPECIFIED = "ts"; - - //===================================================================================== - class SQLiteDataBaseReadUtil - { - public: - SQLiteDataBaseReadUtil(); - virtual ~SQLiteDataBaseReadUtil(); - - /** Opens a database file */ - QsErrorType OpenDataBaseFile(const std::string& dbFileName, - sqlite3** sqlite3Db, - const int& flags) const; - - /** - * Gets TextureSet information about a data table - * @param[in] sqlite3Db Pointer to a SQLite database object - * @param[in] tableName Name of the table to access within the given database - * The following are TextureSet creation options - * @param[out] rasterFormat Flag that determines how the texture image is drawn - * @param[out] pixelLength Tile size of the TextureSet - * @param[out] shallowLevel Minimum depth of the TextureSet - * @param[out] deepLevel Maximum depth of the TextureSet - * @param[out] tmpExtents Stores the TextureSet's X/Y extent values - * @param[out] source Name of the TextureSet's source file - * @param[out] classification Classification information of the loaded TextureSet - * @param[out] description Description of the loaded TextureSet - * @param[out] timeSpecified Whether or not a valid timeStamp was specified for the source file - * @param[out] timeStamp Loads a time value, if there is a valid timeStamp on the file - * @return Returns 0 on success, otherwise returns an error value mapped to QsErrorType. - */ - QsErrorType TsGetSetFromListOfSetsTable(sqlite3* sqlite3Db, - const std::string& tableName, - int& rasterFormat, - int& pixelLength, - int& shallowLevel, - int& deepLevel, - PosXPosYExtents tmpExtents[6], - std::string& source, - std::string& classification, - std::string& description, - bool& timeSpecified, - simCore::TimeStamp& timeStamp) const; - - /** - * Reads a node's data buffer from a sets table; caller is responsible for deleting buffer - * @param[in] sqlite3Db Pointer to a SQLite database object - * @param[in] dbFileName Name of a SQLite database file, used to fetch a database if sqlite3Db == NULL - * @param[in] dataTableName Name of the table to access within the given database - * @param[in] faceIndex Mapping to a face index/orientation, used to create a SQLite idBlob - * @param[in] nodeID Used to fill the idBlob - * @param[out] buffer Destination for data from the SQLite database - * @param[in, out] bufferSize Current max size of the buffer, will be changed if data to be copied is greater than max - * @param[out] currentRasterSize Size (bytes) of the data from the SQLite database - * @param[in] allowLocalDB Determines whether to fall back to a local database pointed to by dbFileName - * @param[in] displayErrorMessage Determines whether to display error messages to console when failing - * @return An error value, mapped to QsErrorType - */ - QsErrorType TsReadDataBuffer(sqlite3* sqlite3Db, - const std::string& dbFileName, - const std::string& dataTableName, - const FaceIndexType& faceIndex, - const QSNodeId& nodeID, - TextureDataType** buffer, - uint32_t* bufferSize, - uint32_t* currentRasterSize, - bool allowLocalDB, - bool displayErrorMessage=false) const; - protected: - int sizeOfIdBlob_; - - std::string textureSetSelectCommand_; - std::string textureSetSelectFileCommand1_; - std::string textureSetSelectFileCommand2_; - - // ids for inserting a "texture set" into a "list of texture sets" table - int tsInsertFileIdData_; - int tsInsertSetTextureSetName_; - int tsInsertSetIdRasterFormat_; - int tsInsertSetIdPixelLength_; - int tsInsertSetIdShallowestLevel_; - int tsInsertSetIdDeepestLevel_; - int tsInsertSetIdExtents_; - int tsInsertSetIdSource_; - int tsInsertSetIdClassification_; - int tsInsertSetIdDescription_; - int tsInsertSetIdTimeSpecified_; - int tsInsertSetIdTimeValue_; - }; - -} // namespace simVis_db - -#endif /* SQLITE_DATABASE_READ_UTIL_H */ diff --git a/Plugins/OSGEarthDBDriver/include/swapbytes.h b/Plugins/OSGEarthDBDriver/include/swapbytes.h deleted file mode 100644 index e80d007f4..000000000 --- a/Plugins/OSGEarthDBDriver/include/swapbytes.h +++ /dev/null @@ -1,780 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ - -#ifndef SIMUTIL_SWAPBYTES_H -#define SIMUTIL_SWAPBYTES_H - -#include -#include -#include -#include -#include "simCore/Common/Common.h" - -#if !defined(SIM_LITTLE_ENDIAN) && !defined(SIM_BIG_ENDIAN) -#if defined(X86) || defined(ALPHA) || defined(__x86_64__) || defined(_WIN64) || defined(WIN32) -#define SIM_LITTLE_ENDIAN -#endif -#endif - -#ifndef BYTESWAPSHIFT - -namespace simVis_db -{ - template - inline - void swap_bytes(T *const value, const size_t nItems = 1) - { - // using namespace std; - for (size_t i = 0; i < nItems; ++i) - { - char *ptr = (char*)&value[i]; // Treat value as an array of bytes - size_t size = sizeof(T); - size_t halfSize = size >> 1; - size_t end = size - 1; - for (size_t i = 0; i < halfSize; ++i) - std::swap(ptr[end - i], ptr[i]); - } - } - - template - inline - T swap_bytes_return(const T &value, const size_t nItems = 1) - { - T temp = value; - swap_bytes(&temp); - return temp; - } - -#ifdef SIM_LITTLE_ENDIAN - - template - inline - void make_little_endian_(T *const value) - { - } - - template - inline - void make_big_endian_(T *const value) - { - swap_bytes(value); - } - -#else - - template - inline - void make_little_endian_(T *const value) - { - swap_bytes(value); - } - - template - inline - void make_big_endian_(T *const value) - { - } - -#endif - - inline - void make_big_endian(char *const val) { make_big_endian_(val); } - inline - void make_big_endian(int8_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(uint8_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(int16_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(uint16_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(int32_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(uint32_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(int64_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(uint64_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(float *const val) { make_big_endian_(val); } - inline - void make_big_endian(double *const val) { make_big_endian_(val); } - - inline - void make_little_endian(char *const val) { make_little_endian_(val); } - inline - void make_little_endian(int8_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(uint8_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(int16_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(uint16_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(int32_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(uint32_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(int64_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(uint64_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(float *const val) { make_little_endian_(val); } - inline - void make_little_endian(double *const val) { make_little_endian_(val); } - - template - inline - void make_big_endian(T *const value, const size_t nItems) - { - for (size_t i = 0; i < nItems; ++i) - { - make_big_endian(&value[i]); - } - } - - template - inline - void make_little_endian(T *const value, const size_t nItems) - { - for (size_t i = 0; i < nItems; ++i) - { - make_little_endian(&value[i]); - } - } - - template - inline - size_t beread(FILE *stream, T *const val, const size_t nItems = 1) - { - size_t nItemsRead = fread(val, sizeof(T), nItems, stream); - make_big_endian(val, nItemsRead); - return nItemsRead; - } - - template - inline - size_t bewrite(FILE *stream, const T *const val, const size_t nItems = 1) - { - size_t nItemsWrote = 0; - for (size_t i = 0; i < nItems; ++i) - { - T temp = val[i]; - make_big_endian(&temp); - if (fwrite(&temp, sizeof(T), 1, stream) != 1) - break; - ++nItemsWrote; - } - return nItemsWrote; - } - - template - inline - size_t leread(FILE *stream, T *const val, const size_t nItems = 1) - { - size_t nItemsRead = fread(val, sizeof(T), nItems, stream); - make_little_endian(val, nItemsRead); - return nItemsRead; - } - - template - inline - size_t lewrite(FILE *stream, const T *const val, const size_t nItems = 1) - { - size_t nItemsWrote = 0; - for (size_t i = 0; i < nItems; ++i) - { - T temp = val[i]; - make_little_endian(&temp); - if (fwrite(&temp, sizeof(T), 1, stream) != 1) - break; - ++nItemsWrote; - } - return nItemsWrote; - } - - template - inline - size_t beread(std::istream &stream, T *const val, const std::streamsize nItems = 1) - { - stream.read((char *)val, nItems * sizeof(T)); - size_t nItemsRead = stream.gcount() / sizeof(T); - make_big_endian(val, nItemsRead); - return nItemsRead; - } - - template - inline - size_t bewrite(std::ostream &stream, const T *const val, const size_t nItems = 1) - { - size_t nItemsWrote = 0; - for (size_t i = 0; i < nItems; ++i) - { - T temp = val[i]; - make_big_endian(&temp); - stream.write((const char *)&temp, sizeof(T)); - if (stream.bad()) - break; - ++nItemsWrote; - } - return nItemsWrote; - } - - template - inline - size_t leread(std::istream &stream, T *const val, const size_t nItems = 1) - { - stream.read((char *)val, nItems * sizeof(T)); - size_t nItemsRead = stream.gcount() / sizeof(T); - make_little_endian(val, nItemsRead); - return nItemsRead; - } - - template - inline - size_t lewrite(std::ostream &stream, const T *const val, const size_t nItems = 1) - { - size_t nItemsWrote = 0; - for (size_t i = 0; i < nItems; ++i) - { - T temp = val[i]; - make_little_endian(&temp); - stream.write((const char *)&temp, sizeof(T)); - if (stream.bad()) - break; - ++nItemsWrote; - } - return nItemsWrote; - } - - template - inline - size_t beread(const void *const stream, T *const val, const size_t nItems = 1) - { - memcpy(val, stream, nItems * sizeof(T)); - make_big_endian(val, nItems); - return nItems; - } - - template - inline - size_t bewrite(void *const stream, const T *const val, const size_t nItems = 1) - { - memcpy(stream, val, nItems * sizeof(T)); - make_big_endian((T *)stream, nItems); - return nItems; - } - - template - inline - size_t leread(const void *const stream, T *const val, const size_t nItems = 1) - { - memcpy(val, stream, nItems * sizeof(T)); - make_little_endian(val, nItems); - return nItems; - } - - template - inline - size_t lewrite(void *const stream, const T *const val, const size_t nItems = 1) - { - memcpy(stream, val, nItems * sizeof(T)); - make_little_endian((T *)stream, nItems); - return nItems; - } - -#else - -// Swap macros. -#define SWAP16(val)((((val)>>8)&0xff)|(((val)<<8)&0xff00)) -#define SWAP32(val)((((val)>>24)&0xff)|(((val)>>8)&0xff00)|(((val)<<8)&0xff0000)|(((val)<<24)&0xff000000)) -#ifdef __GNUC__ -#define SWAP64(val)((((val)>>56)&0xffLL)|(((val)>>40)&0xff00LL)|(((val)>>24)&0xff0000LL)|(((val)>>8)&0xff000000LL)| \ - (((val)<<8)&0xff00000000LL)|(((val)<<24)&0xff0000000000LL)|(((val)<<40)&0xff000000000000LL)|(((val)<<56)&0xff00000000000000LL)) -#else -#define SWAP64(val)((((val)>>56)&0xffL)|(((val)>>40)&0xff00L)|(((val)>>24)&0xff0000L)|(((val)>>8)&0xff000000L)| \ - (((val)<<8)&0xff00000000L)|(((val)<<24)&0xff0000000000L)|(((val)<<40)&0xff000000000000L)|(((val)<<56)&0xff00000000000000L)) -#endif - - // Generic byte swapping routines. - template inline void swap_bytes(T *const value) - { - char *ptr=(char*)(void*)value; // Treat value as an array of bytes - size_t size = sizeof(T); - register size_t halfSize = size >> 1; - register size_t end = size - 1; - for (register size_t i = 0; i < halfSize; ++i) - std::swap(ptr[end - i], ptr[i]); - } - - template inline void swap_bytes(T *const value, register const size_t nItems) - { - for (register size_t i=0;i> 1; - register size_t end = size - 1; - for (register size_t i = 0; i < halfSize; ++i) - std::swap(ptr[end - i], ptr[i]); - } - } - - - // Specialized routines. - - // NULL routines. - template<> inline void swap_bytes(char *const value) {} - template<> inline void swap_bytes(char *const value, register const size_t nItems) {} - template<> inline void swap_bytes(int8_t *const value) {} - template<> inline void swap_bytes(uint8_t *const value) {} - template<> inline void swap_bytes(int8_t *const value, register const size_t nItems) {} - template<> inline void swap_bytes(uint8_t *const value, register const size_t nItems) {} - - // Single item routines. - template<> inline void swap_bytes(int16_t *const value) { *value=SWAP16(*value); } - template<> inline void swap_bytes(uint16_t *const value) { *value=SWAP16(*value); } - template<> inline void swap_bytes(int32_t *const value) { *value=SWAP32(*value); } - template<> inline void swap_bytes(uint32_t *const value) { *value=SWAP32(*value); } - template<> inline void swap_bytes(int64_t *const value) { *value=SWAP64(*value); } - template<> inline void swap_bytes(uint64_t *const value) { *value=SWAP64(*value); } - - template<> inline void swap_bytes(float *const value) - { - int32_t *const pseudo=(int32_t*)(void*)value; - *pseudo=SWAP32(*pseudo); - } - - template<> inline void swap_bytes(double *const value) - { - int64_t *const pseudo=(int64_t*)(void*)value; - *pseudo=SWAP64(*pseudo); - } - - #ifdef SIM_LITTLE_ENDIAN - template inline void make_little_endian(T *const value) {} - - // Generic swap. Has a '_' prefix to prevent it from accidently being used with structs, etc. - template inline void make_little_endian_(T *const value) {} - template inline void make_big_endian_(T *const value) { swap_bytes(value); } - - inline void make_big_endian(char *const value) {} - inline void make_big_endian(int8_t *const value) {} - inline void make_big_endian(uint8_t *const value) {} - inline void make_big_endian(int16_t *const value) { *value=SWAP16(*value); } - inline void make_big_endian(uint16_t *const value) { *value=SWAP16(*value); } - inline void make_big_endian(int32_t *const value) { *value=SWAP32(*value); } - inline void make_big_endian(uint32_t *const value) { *value=SWAP32(*value); } - inline void make_big_endian(int64_t *const value) { *value=SWAP64(*value); } - inline void make_big_endian(uint64_t *const value) { *value=SWAP64(*value); } - - inline void make_big_endian(float *const value) - { - int32_t *const pseudo=(int32_t*)(void*)value; - *pseudo=SWAP32(*pseudo); - } - - inline void make_big_endian(double *const value) - { - int64_t *const pseudo=(int64_t*)(void*)value; - *pseudo=SWAP64(*pseudo); - } -#else - template inline void make_big_endian(T *const value) {} - template inline void make_big_endian_(T *const value) {} - template inline void make_little_endian_(T *const value) { swap_bytes(value); } - - inline void make_little_endian(char *const value) {} - inline void make_little_endian(int8_t *const value) {} - inline void make_little_endian(uint8_t *const value) {} - inline void make_little_endian(int16_t *const value) { *value=SWAP16(*value); } - inline void make_little_endian(uint16_t *const value) { *value=SWAP16(*value); } - inline void make_little_endian(int32_t *const value) { *value=SWAP32(*value); } - inline void make_little_endian(uint32_t *const value) { *value=SWAP32(*value); } - inline void make_little_endian(int64_t *const value) { *value=SWAP64(*value); } - inline void make_little_endian(uint64_t *const value) { *value=SWAP64(*value); } - - inline void make_little_endian(float *const value) - { - int32_t *const pseudo=(int32_t*)(void*)value; - *pseudo=SWAP32(*pseudo); - } - - inline void make_little_endian(double *const value) - { - int64_t *const pseudo=(int64_t*)(void*)value; - *pseudo=SWAP64(*pseudo); - } -#endif - - // Multi item routines. - template<> inline void swap_bytes(int16_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); - } - - template<> inline void swap_bytes(uint16_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); - } - - template<> inline void swap_bytes(int32_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); - } - - template<> inline void swap_bytes(uint32_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); - } - - template<> inline void swap_bytes(int64_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); - } - - template<> inline void swap_bytes(uint64_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); - } - - template<> inline void swap_bytes(float *const value, register const size_t nItems) - { - int32_t *const pseudo=(int32_t*)(void*)value; - for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP32(pseudo[i]); - } - - template<> inline void swap_bytes(double *const value, register const size_t nItems) - { - int64_t *const pseudo=(int64_t*)(void*)value; - for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP64(pseudo[i]); - } - -#ifdef SIM_LITTLE_ENDIAN - template inline void make_little_endian(T *const value, register const size_t nItems) {} - template inline void make_little_endian_(T *const value, register const size_t nItems) {} - template inline void make_big_endian_(T *const value, register const size_t nItems) { swap_bytes(value, nItems); } - - inline void make_big_endian(char *const value, register const size_t nItems) {} - inline void make_big_endian(int8_t *const value, register const size_t nItems) {} - inline void make_big_endian(uint8_t *const value, register const size_t nItems) {} - - inline void make_big_endian(int16_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); - } - - inline void make_big_endian(uint16_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); - } - - inline void make_big_endian(int32_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); - } - - inline void make_big_endian(uint32_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); - } - - inline void make_big_endian(int64_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); - } - - inline void make_big_endian(uint64_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); - } - - inline void make_big_endian(float *const value, register const size_t nItems) - { - int32_t *const pseudo = (int32_t*)(void*)value; - for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP32(pseudo[i]); - } - - inline void make_big_endian(double *const value, register const size_t nItems) - { - int64_t *const pseudo = (int64_t*)(void*)value; - for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP64(pseudo[i]); - } -#else - template inline void make_big_endian(T *const value, register const size_t nItems) {} - template inline void make_big_endian_(T *const value, register const size_t nItems) {} - template inline void make_little_endian_(T *const value, register const size_t nItems) { swap_bytes(value, nItems); } - - inline void make_little_endian(char *const value, register const size_t nItems) {} - inline void make_little_endian(int8_t *const value, register const size_t nItems) {} - inline void make_little_endian(uint8_t *const value, register const size_t nItems) {} - - inline void make_little_endian(int16_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); - } - - inline void make_little_endian(uint16_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); - } - - inline void make_little_endian(int32_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); - } - - inline void make_little_endian(uint32_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); - } - - inline void make_little_endian(int64_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); - } - - inline void make_little_endian(uint64_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); - } - - inline void make_little_endian(float *const value, register const size_t nItems) - { - int32_t *const pseudo = (int32_t*)(void*)value; - for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP32(pseudo[i]); - } - - inline void make_little_endian(double *const value, register const size_t nItems) - { - int64_t *const pseudo = (int64_t*)(void*)value; - for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP64(pseudo[i]); - } - #endif - - - // Swapped I\O - template inline size_t beread(FILE *stream, T *const val) - { - size_t nItemsRead = fread(val, sizeof(T), 1, stream); - make_big_endian(val); - return nItemsRead; - } - - template inline size_t beread(FILE *stream, T *const val, register const size_t nItems) - { - size_t nItemsRead = fread(val, sizeof(T), nItems, stream); - make_big_endian(val, nItemsRead); - return nItemsRead; - } - - template inline size_t bewrite(FILE *stream, const T *const val) - { - T temp = *val; - make_big_endian(&temp); - return fwrite(&temp, sizeof(T), 1, stream); - } - - template inline size_t bewrite(FILE *stream, const T *const val, register const size_t nItems) - { - register size_t nItemsWrit = 0; - while (nItemsWrit < nItems) - { - T temp = val[nItemsWrit++]; - make_big_endian(&temp); - if (fwrite(&temp, sizeof(T), 1, stream)!=1) - break; - } - return nItemsWrit; - } - - template inline size_t leread(FILE *stream, T *const val) - { - size_t nItemsRead = fread(val, sizeof(T), 1, stream); - make_little_endian(val); - return nItemsRead; - } - - template inline size_t leread(FILE *stream, T *const val, register const size_t nItems) - { - size_t nItemsRead = fread(val, sizeof(T), nItems, stream); - make_little_endian(val, nItemsRead); - return nItemsRead; - } - - template inline size_t lewrite(FILE *stream, const T *const val) - { - T temp = *val; - make_little_endian(&temp); - return fwrite(&temp, sizeof(T), 1, stream); - } - - template inline size_t lewrite(FILE *stream, const T *const val, register const size_t nItems) - { - register size_t nItemsWrit = 0; - while (nItemsWrit < nItems) - { - T temp = val[nItemsWrit++]; - make_little_endian(&temp); - if (fwrite(&temp, sizeof(T), 1, stream) != 1) - break; - } - return nItemsWrit; - } - - template inline size_t beread(std::istream &stream, T *const val) - { - stream.read((char *)val, sizeof(T)); - size_t nItemsRead = stream.gcount() / sizeof(T); - make_big_endian(val); - return nItemsRead; - } - - template inline size_t beread(std::istream &stream, T *const val, register const size_t nItems) - { - stream.read((char *)val, nItems * sizeof(T)); - size_t nItemsRead = stream.gcount() / sizeof(T); - make_big_endian(val, nItemsRead); - return nItemsRead; - } - - template inline size_t bewrite(std::ostream &stream, const T *const val) - { - T temp = *val; - make_big_endian(&temp); - stream.write((const char *)&temp, sizeof(T)); - return (stream.bad()) ? 0 : 1; - } - - template inline size_t bewrite(std::ostream &stream, const T *const val, register const size_t nItems) - { - register size_t nItemsWrit = 0; - while (nItemsWrit < nItems) - { - T temp = val[nItemsWrit++]; - make_big_endian(&temp); - stream.write((const char *)&temp, sizeof(T)); - if (stream.bad()) - break; - } - return nItemsWrit; - } - - template inline size_t leread(std::istream &stream, T *const val) - { - stream.read((char *)val, sizeof(T)); - size_t nItemsRead = stream.gcount()/sizeof(T); - make_little_endian(val); - return nItemsRead; - } - - template inline size_t leread(std::istream &stream, T *const val, register const size_t nItems) - { - stream.read((char *)val, nItems * sizeof(T)); - size_t nItemsRead = stream.gcount() / sizeof(T); - make_little_endian(val, nItemsRead); - return nItemsRead; - } - - template inline size_t lewrite(std::ostream &stream, const T *const val) - { - T temp = *val; - make_little_endian(&temp); - stream.write((const char *)&temp, sizeof(T)); - return (stream.bad()) ? 0 : 1; - } - - template inline size_t lewrite(std::ostream &stream, const T *const val, register const size_t nItems) - { - size_t nItemsWrit = 0; - while (nItemsWrit < nItems) - { - T temp = val[nItemsWrit++]; - make_little_endian(&temp); - stream.write((const char *)&temp, sizeof(T)); - if (stream.bad()) - break; - } - return nItemsWrit; - } - - template inline size_t beread(const void *const stream, T *const val) - { - memcpy(val, stream, sizeof(T)); - make_big_endian(val); - return 1; - } - - template inline size_t beread(const void *const stream, T *const val, register const size_t nItems) - { - memcpy(val, stream, nItems * sizeof(T)); - make_big_endian(val, nItems); - return nItems; - } - - template inline size_t bewrite(void *const stream, const T *const val) - { - memcpy(stream, val, sizeof(T)); - make_big_endian((T *)stream); - return 1; - } - - template inline size_t bewrite(void *const stream, const T *const val, register const size_t nItems) - { - memcpy(stream, val, nItems * sizeof(T)); - make_big_endian((T *)stream, nItems); - return nItems; - } - - template inline size_t leread(const void *const stream, T *const val) - { - memcpy(val, stream, sizeof(T)); - make_little_endian(val); - return 1; - } - - template inline size_t leread(const void *const stream, T *const val, register const size_t nItems) - { - memcpy(val, stream, nItems * sizeof(T)); - make_little_endian(val, nItems); - return nItems; - } - - template inline size_t lewrite(void *const stream, const T *const val) - { - memcpy(stream, val, sizeof(T)); - make_little_endian((T *)stream); - return 1; - } - - template inline size_t lewrite(void *const stream, const T *const val, register const size_t nItems) - { - memcpy(stream, val, nItems * sizeof(T)); - make_little_endian((T *)stream, nItems); - return nItems; - } - -#endif - -} // namespace simVis_db - -#endif /* SIMUTIL_SWAPBYTES_H */ diff --git a/Plugins/OSGEarthDBDriver/src/DBTileSource.cpp b/Plugins/OSGEarthDBDriver/src/DBTileSource.cpp deleted file mode 100644 index 93e67f921..000000000 --- a/Plugins/OSGEarthDBDriver/src/DBTileSource.cpp +++ /dev/null @@ -1,667 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ - -#include "simCore/Calc/Math.h" -#include "osg/ValueObject" -#include "osgEarth/Registry" -#include "osgEarth/FileUtils" -#include "osgEarth/Cube" -#include "osgEarth/HeightFieldUtils" -#include "osgEarth/ImageUtils" -#include "osgEarth/ImageToHeightFieldConverter" -#include "osgEarth/DateTime" -#include "osgDB/FileNameUtils" -#include "osgDB/ObjectWrapper" -#include "osgDB/WriteFile" -#include "osgDB/FileUtils" -#include "simVis/osgEarthVersion.h" -#include "QSCommon.h" -#include "swapbytes.h" -#include "SQLiteDataBaseReadUtil.h" -#include "DBTileSource.h" - -#define LC "[simVis::DBTileSource] " - -namespace simVis_db { - -namespace -{ - bool convertTileKeyToQsKey(const osgEarth::TileKey& key, FaceIndexType& out_faceIndex, QSNodeId& out_nodeId, - osg::Vec2d& out_fmin, osg::Vec2d& out_fmax) - { - QSNodeId zero(0); - QSNodeId one(1); - - const unsigned int maxLevel = key.getLevelOfDetail(); - - QSNodeId nodeId; - - osgEarth::TileKey pkey = key; - - for (unsigned int i = 0; i < maxLevel; ++i) - { - const unsigned int plevel = pkey.getLevelOfDetail(); - const unsigned int level = plevel * 3; - const QSNodeId bit0 = one << level; - const QSNodeId bit1 = one << (level + 1); - const QSNodeId bit2 = one << (level + 2); - - unsigned int tx, ty; - pkey.getTileXY(tx, ty); - - const int xoff = ((tx % 2) == 0) ? 0 : 1; - const int yoff = ((ty % 2) == 0) ? 0 : 1; - - if (xoff == 0 && yoff == 0) - { - nodeId |= bit1; - } - else if (xoff == 1 && yoff == 0) - { - nodeId |= bit0; - } - else if (xoff == 0 && yoff == 1) - { - nodeId |= bit0; - nodeId |= bit1; - } - else if (xoff == 1 && yoff == 1) - { - nodeId |= bit2; - } - - pkey = pkey.createParentKey(); - } - - out_faceIndex = osgEarth::Contrib::UnifiedCubeProfile::getFace(key); - out_nodeId = nodeId; - - double xMin = key.getExtent().xMin(); - double yMin = key.getExtent().yMin(); - double xMax = key.getExtent().xMax(); - double yMax = key.getExtent().yMax(); - int face; - - osgEarth::Contrib::CubeUtils::cubeToFace(xMin, yMin, xMax, yMax, face); - - out_fmin.set(xMin * gQsDMaxLength, yMin * gQsDMaxLength); - out_fmax.set(xMax * gQsDMaxLength, yMax * gQsDMaxLength); - - return true; - } - - bool decompressZLIB(const char* input, int inputLen, std::string& output) - { - osgDB::BaseCompressor* comp = osgDB::Registry::instance()->getObjectWrapperManager()->findCompressor("zlib"); - std::string inString(input, inputLen); - std::istringstream inStream(inString); - return comp->decompress(inStream, output); - } -} - -// -------------------------------------------------------------------------- - -DBTileSource::DBTileSource(const osgEarth::Contrib::TileSourceOptions& options) - : osgEarth::Contrib::TileSource(options), - options_(options), - db_(NULL), - rasterFormat_(SPLIT_UNKNOWN), - pixelLength_(128), - shallowLevel_(0), - deepLevel_(32), - timeSpecified_(false), - timeStamp_(simCore::INFINITE_TIME_STAMP) -{ - if (!options_.url().isSet() || options_.url()->empty()) - { - OE_WARN << LC << "No pathname given" << std::endl; - } -} - -DBTileSource::~DBTileSource() -{ - if (db_) - { - sqlite3_close(db_); - } -} - -osgEarth::Status DBTileSource::initialize(const osgDB::Options* dbOptions) -{ - if (options_.url().isSet()) - { - pathname_ = osgDB::findDataFile(options_.url()->full(), dbOptions); - - if (dbUtil_.OpenDataBaseFile(pathname_, &db_, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) != QS_IS_OK) - { - db_ = NULL; - return osgEarth::Status::Error(osgEarth::Stringify() << "Failed to open DB file at " << options_.url()->full()); - } - else - { - QsErrorType err = dbUtil_.TsGetSetFromListOfSetsTable( - db_, - "default", - rasterFormat_, - pixelLength_, - shallowLevel_, - deepLevel_, - extents_, - source_, - classification_, - description_, - timeSpecified_, - timeStamp_); - - // Limit the deepLevel_ by the passed-in option - if (options_.deepestLevel().isSet()) - { - deepLevel_ = simCore::sdkMin(deepLevel_, static_cast(options_.deepestLevel().get())); - } - - if (err != QS_IS_OK) - { - sqlite3_close(db_); - db_ = NULL; - return osgEarth::Status::Error(osgEarth::Stringify() << "Failed to read metadata for " << pathname_); - } - // Set up as a unified cube: - osgEarth::Profile* profile = new osgEarth::Contrib::UnifiedCubeProfile(); - // DB are expected to be wgs84, which Cube defaults to - setProfile(profile); - - // Lat/long extents (for debugging) - osgEarth::GeoExtent llex[6]; - - // Tell the engine how deep the data actually goes: - for (unsigned int f = 0; f < 6; ++f) - { - if (extents_[f].minX < extents_[f].maxX && extents_[f].minY < extents_[f].maxY) - { - const double x0 = extents_[f].minX / gQsDMaxLength; - const double x1 = extents_[f].maxX / gQsDMaxLength; - const double y0 = extents_[f].minY / gQsDMaxLength; - const double y1 = extents_[f].maxY / gQsDMaxLength; - - osgEarth::GeoExtent cubeEx(profile->getSRS(), f + x0, y0, f + x1, y1); - - // Transform to lat/long for the debugging msgs - cubeEx.transform(profile->getSRS()->getGeodeticSRS(), llex[f]); - - getDataExtents().push_back(osgEarth::DataExtent(cubeEx, shallowLevel_, deepLevel_)); - } - } - - // Set time value of image if a time was found in the db - if (timeStamp_ != simCore::INFINITE_TIME_STAMP) - { - const osgEarth::DateTime osgTime(timeStamp_.secondsSinceRefYear(1970).getSeconds()); - // Set time as a user value since config is not editable from here - setUserValue("time", osgTime.asISO8601()); - } - - OE_INFO << LC - << "Table: " << options_.url()->full() << std::endl - << " Raster format = " << rasterFormat_ << std::endl - << " Tile size = " << pixelLength_ << std::endl - << " Shallow level = " << shallowLevel_ << std::endl - << " Deep level = " << deepLevel_ << std::endl - << " QS Extents = " << std::endl - << " 0: " << extents_[0].minX << "," << extents_[0].minY << "," << extents_[0].maxX << "," << extents_[0].maxY << "(" << (llex[0].isValid() ? llex[0].toString() : "empty") << ")\n" - << " 1: " << extents_[1].minX << "," << extents_[1].minY << "," << extents_[1].maxX << "," << extents_[1].maxY << "(" << (llex[1].isValid() ? llex[1].toString() : "empty") << ")\n" - << " 2: " << extents_[2].minX << "," << extents_[2].minY << "," << extents_[2].maxX << "," << extents_[2].maxY << "(" << (llex[2].isValid() ? llex[2].toString() : "empty") << ")\n" - << " 3: " << extents_[3].minX << "," << extents_[3].minY << "," << extents_[3].maxX << "," << extents_[3].maxY << "(" << (llex[3].isValid() ? llex[3].toString() : "empty") << ")\n" - << " 4: " << extents_[4].minX << "," << extents_[4].minY << "," << extents_[4].maxX << "," << extents_[4].maxY << "(" << (llex[4].isValid() ? llex[4].toString() : "empty") << ")\n" - << " 5: " << extents_[5].minX << "," << extents_[5].minY << "," << extents_[5].maxX << "," << extents_[5].maxY << "(" << (llex[5].isValid() ? llex[5].toString() : "empty") << ")\n"; - - // Line up the native format readers: - pngReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/png"); - jpgReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/jpeg"); - tifReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/tiff"); - rgbReader_ = osgDB::Registry::instance()->getReaderWriterForMimeType("image/x-rgb"); - } - } - - return osgEarth::STATUS_OK; -} - -int DBTileSource::getPixelsPerTile() const -{ - return pixelLength_; -} - -osg::Image* DBTileSource::createImage(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress) -{ - return createImage_(key, false); -} - -osg::HeightField* DBTileSource::createHeightField(const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress) -{ - if (!db_) return NULL; - - osg::ref_ptr result; - - // Convert osgEarth::TileKey into a QuadKeyID - FaceIndexType faceId; - QSNodeId nodeId; - osg::Vec2d tileMin; - osg::Vec2d tileMax; // Tile extents in QS units - convertTileKeyToQsKey(key, faceId, nodeId, tileMin, tileMax); - - if (!extents_[faceId].Valid()) - { - // If there is no data on that face, return nothing. - OE_DEBUG << LC << "Face " << (int)faceId << " is invalid; returning empty heightfield" << std::endl; - return NULL; - } - - // Query the database - TextureDataType* buf = NULL; - uint32_t bufSize = 0; - uint32_t currentRasterSize = 0; - - QsErrorType err = dbUtil_.TsReadDataBuffer( - db_, - pathname_, - "default", - faceId, - nodeId, - &buf, - &bufSize, - ¤tRasterSize, - false); // AllowLocalDB: no, we created it ourselves - - if (err == QS_IS_OK) - { - if (currentRasterSize > 0) - { - osg::ref_ptr image; - if (decodeRaster_(rasterFormat_, (const char*)buf, currentRasterSize, image)) - { - - // SIMDIS .db elevation data is y-inverted: - image->flipVertical(); - - osgEarth::ImageToHeightFieldConverter i2h; - result = i2h.convert(image.get()); - - // If result is 1x1, skip border processing - if (result->getNumColumns() >= 1 && result->getNumRows() >= 1) - { - // Tile width and height in QS units: - const double tileWidth = tileMax.x() - tileMin.x(); - const double tileHeight = tileMax.y() - tileMin.y(); - - /** - * DB data contains a one-pixel border with undefined data. That border falls - * within the reported extents. We have to fill that with "NO DATA". - * First, calculate the size of a pixel in QS units for this tile: - */ - const double qppx = tileWidth / pixelLength_; - const double qppy = tileHeight / pixelLength_; - - /** - * Adjust the reported extents to remove the border. - * NOTE: This will fail in the (rare?) edge case in which a data extent falls - * exactly on a cube-face boundary. Ignore that for now. - */ - const double xMin = extents_[faceId].minX + qppx; - const double xMax = extents_[faceId].maxX - qppx; - const double yMin = extents_[faceId].minY + qppy; - const double yMax = extents_[faceId].maxY - qppy; - - // Write "no data" to all pixels outside the reported extent. - const double colWidth = tileWidth / (result->getNumColumns() - 1); - const double rowHeight = tileHeight / (result->getNumRows() - 1); - - for (unsigned int row = 0; row < result->getNumRows(); ++row) - { - const double y = tileMin.y() + row * rowHeight; - - for (unsigned int col = 0; col < result->getNumColumns(); ++col) - { - const double x = tileMin.x() + col * colWidth; - - if (x < xMin || x > xMax || y < yMin || y > yMax) - { - result->setHeight(col, row, NO_DATA_VALUE); - } - } - } - } - } - else - { - OE_WARN << "Heightfield decode failed for key " << key.str() << std::endl; - } - } - else - { - // Raster size of 0 means no tile in the db - result = NULL; - } - } - else - { - OE_WARN << "Failed to read heightfield from " << key.str() << std::endl; - } - - delete[] buf; - return result.release(); -} - -osg::Image* DBTileSource::createImage_(const osgEarth::TileKey& key, bool isHeightField) -{ - if (!db_) - return NULL; - - osg::ref_ptr result; - - // Convert osgEarth::TileKey into a QuadKeyID - FaceIndexType faceId; - QSNodeId nodeId; - osg::Vec2d tileMin; - osg::Vec2d tileMax; // Tile extents in QS units - convertTileKeyToQsKey(key, faceId, nodeId, tileMin, tileMax); - - if (!extents_[faceId].Valid()) - { - // If there is no data on that face, return nothing. - OE_DEBUG << LC << "Face " << static_cast(faceId) << " is invalid; returning empty image" << std::endl; - return NULL; - } - - if (key.getLevelOfDetail() > static_cast(deepLevel_)) - { - // Hopefully this doesn't happen since we called setMaxDataLevel, but you never know - return NULL; - } - - // Query the database - TextureDataType* buf = NULL; - uint32_t bufSize = 0; - uint32_t currentRasterSize = 0; - - QsErrorType err = dbUtil_.TsReadDataBuffer( - db_, - pathname_, - "default", - faceId, - nodeId, - &buf, - &bufSize, - ¤tRasterSize, - false, true); // AllowLocalDB: no, we created it ourselves - - if (err == QS_IS_OK) - { - if (currentRasterSize > 0) - { - if (decodeRaster_(rasterFormat_, (const char*)buf, currentRasterSize, result)) - { - // If result is 1x1, skip border processing - if (result->s() >= 1 && result->t() >= 1) - { - const unsigned int resultS = static_cast(result->s()); - const unsigned int resultT = static_cast(result->t()); - - // Tile width and height in QS units: - const double tileWidth = tileMax.x() - tileMin.x(); - const double tileHeight = tileMax.y() - tileMin.y(); - - const double qppx = 0.0; - const double qppy = 0.0; - const double xMin = extents_[faceId].minX + qppx; - const double xMax = extents_[faceId].maxX - qppx; - const double yMin = extents_[faceId].minY + qppy; - const double yMax = extents_[faceId].maxY - qppy; - - osgEarth::ImageUtils::PixelReader read(result.get()); - osgEarth::ImageUtils::PixelWriter write(result.get()); - - // Write "no data" to all pixels outside the reported extent. - const double colw = tileWidth / (resultS - 1); - const double rowh = tileHeight / (resultT - 1); - - for (unsigned int row = 0; row < resultS; ++row) - { - const double y = tileMin.y() + row * rowh; - - for (unsigned int col = 0; col < resultT; ++col) - { - const double x = tileMin.x() + col * colw; - - if (x < xMin || x > xMax || y < yMin || y > yMax) - { - osg::Vec4f pixel = read(col, row); - pixel.a() = 0.0f; - write(pixel, col, row); - } - } - } - } - } - else - { - OE_WARN << "Image decode failed for key " << key.str() << std::endl; - } - } - else - { - // Raster size of 0 means no tile in the db - //OE_DEBUG << "No image in the database for key " << key->str() << std::endl; - result = NULL; - } - } - else - { - std::cerr << GetErrorString(err) << std::endl; - OE_WARN << "Failed to read image from " << key.str() << std::endl; - } - - delete[] buf; - return result.release(); -} - -std::string DBTileSource::getExtension() const -{ - // Image formats with an alpha channel: - if ( - rasterFormat_ == SPLIT_5551_ZLIB_COMPRESS || - rasterFormat_ == SPLIT_5551_GZ || - rasterFormat_ == SPLIT_RGBA_ZLIB_COMPRESS || - rasterFormat_ == SPLIT_INTA_ZLIB_COMPRESS || - rasterFormat_ == SPLIT_SGI_RGBA || - rasterFormat_ == SPLIT_PNG || - rasterFormat_ == SPLIT_TIFF) - { - return "png"; - } - - // Image formats with no alpha channel: - else if ( - rasterFormat_ == SPLIT_SGI_RGB || - rasterFormat_ == SPLIT_JPEG) - { - return "jpg"; - } - - // Elevation formats: - else - { - return "tif"; - } -} - -template -void makeImage(int size, GLenum internalFormat, GLenum pixelFormat, GLenum type, - std::string& buf, osg::ref_ptr& outImage) -{ - unsigned char* data = new unsigned char[buf.length()]; - std::copy(buf.begin(), buf.end(), data); - - // Be sure to cast here to get the right swap function: - make_big_endian((T*)data, size * size); - - outImage = new osg::Image(); - outImage->setImage(size, size, 1, internalFormat, pixelFormat, type, data, osg::Image::USE_NEW_DELETE); -} - -// Uses one of OSG's native ReaderWriter's to read image data from a buffer. -static bool readNativeImage(osgDB::ReaderWriter* reader, const char* inBuf, int inBufLen, osg::ref_ptr& outImage) -{ - std::string inString(inBuf, inBufLen); - std::istringstream inStream(inString); - osgDB::ReaderWriter::ReadResult result = reader->readImage(inStream); - outImage = result.getImage(); - if (result.error() || !outImage.valid()) - { - OE_WARN << LC << "Failed to read JPEG image" << std::endl; - return false; - } - else - return true; -} - -// Decode a raster from an input buffer in one of SIMDIS's .db raster formats. -bool DBTileSource::decodeRaster_(int rasterFormat, const char* inputBuffer, int inputBufferLen, osg::ref_ptr& outImage) -{ - switch (rasterFormat) - { - case SPLIT_5551_ZLIB_COMPRESS: // TESTED OK - case SPLIT_5551_GZ: // UNTESTED - { - std::string buf; - if (decompressZLIB(inputBuffer, inputBufferLen, buf)) - { - // Three component image (red, green, and blue channels) - makeImage( - pixelLength_, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, buf, outImage); - return true; - } - } - break; - - case SPLIT_8BIT_ZLIB_COMPRESS: // TESTED OK - case SPLIT_8BIT_GZ: // UNTESTED - { - std::string buf; - if (decompressZLIB(inputBuffer, inputBufferLen, buf)) - { - // Single component image (grayscale channel) - makeImage( - pixelLength_, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, buf, outImage); - return true; - } - } - break; - case SPLIT_INTA_ZLIB_COMPRESS: // TESTED OK - { - std::string buf; - if (decompressZLIB(inputBuffer, inputBufferLen, buf)) - { - // Two component image (grayscale w/alpha channel) - makeImage( - pixelLength_, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, buf, outImage); - return true; - } - break; - } - case SPLIT_RGBA_ZLIB_COMPRESS: // TESTED OK - { - std::string buf; - if (decompressZLIB(inputBuffer, inputBufferLen, buf)) - { - // Four component image (red, green, blue and alpha channels) - makeImage( - pixelLength_, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, buf, outImage); - return true; - } - break; - } - case SPLIT_SGI_RGBA: // TESTED - OK (earthColorSGI.db) - { - if (rgbReader_.valid()) - return readNativeImage(rgbReader_.get(), inputBuffer, inputBufferLen, outImage); - else - OE_WARN << LC << "SGI RGBA reader not available" << std::endl; - } - break; - - case SPLIT_SGI_RGB: // UNTESTED - { - if (rgbReader_.valid()) - return readNativeImage(rgbReader_.get(), inputBuffer, inputBufferLen, outImage); - else - OE_WARN << LC << "SGI RGB reader not available" << std::endl; - } - break; - - case SPLIT_FLOAT32_ZLIB_COMPRESS: // TESTED OK; - { - // Single-channel 32-bit float elevation data - std::string buf; - if (decompressZLIB(inputBuffer, inputBufferLen, buf)) - { - makeImage(pixelLength_, GL_LUMINANCE32F_ARB, GL_LUMINANCE, GL_FLOAT, buf, outImage); - return true; - } - } - break; - - case SPLIT_JPEG: // TESTED OK - { - if (jpgReader_.valid()) - return readNativeImage(jpgReader_.get(), inputBuffer, inputBufferLen, outImage); - else - OE_WARN << LC << "JPEG reader not available" << std::endl; - } - break; - - case SPLIT_PNG: // UNTESTED - { - if (pngReader_.valid()) - return readNativeImage(pngReader_.get(), inputBuffer, inputBufferLen, outImage); - else - OE_WARN << LC << "PNG reader not available" << std::endl; - } - break; - - case SPLIT_TIFF: // UNTESTED - { - if (tifReader_.valid()) - return readNativeImage(tifReader_.get(), inputBuffer, inputBufferLen, outImage); - else - OE_WARN << LC << "TIFF reader not available" << std::endl; - } - break; - - default: - { - OE_WARN << "Support for raster format " << rasterFormat << " not implemented" << std::endl; - } - break; - } - return false; -} - -} diff --git a/Plugins/OSGEarthDBDriver/src/Plugin.cpp b/Plugins/OSGEarthDBDriver/src/Plugin.cpp deleted file mode 100644 index 43635c2b5..000000000 --- a/Plugins/OSGEarthDBDriver/src/Plugin.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** -***** ***** -***** Classification: UNCLASSIFIED ***** -***** Classified By: ***** -***** Declassify On: ***** -***** ***** -**************************************************************************** -* -* -* Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. -* EW Modeling & Simulation, Code 5773 -* 4555 Overlook Ave. -* Washington, D.C. 20375-5339 -* -* License for source code at https://simdis.nrl.navy.mil/License.aspx -* -* The U.S. Government retains all rights to use, duplicate, distribute, -* disclose, or release this software. -* -*/ -#include "osgEarth/TileSource" -#include "osgDB/FileNameUtils" -#include "osgDB/Registry" -#include -#include "DBTileSource.h" - -class SimSdkOSGEarthDBDriverPlugin : public osgEarth::Contrib::TileSourceDriver -{ -public: - SimSdkOSGEarthDBDriverPlugin() { } - - const char* className() - { - return "OSGEarth DB Driver"; - } - - bool acceptsExtension(const std::string& extension) const - { - return osgDB::equalCaseInsensitive("osgearth_db", extension); - } - - osgDB::ReaderWriter::ReadResult readObject(const std::string& uri, const osgDB::Options* options) const - { - std::string ext = osgDB::getFileExtension(uri); - if (!acceptsExtension(ext)) - { - return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED; - } - - return osgDB::ReaderWriter::ReadResult( - new simVis_db::DBTileSource(getTileSourceOptions(options))); - } -}; - -REGISTER_OSGPLUGIN(osgearth_db, SimSdkOSGEarthDBDriverPlugin) diff --git a/Plugins/OSGEarthDBDriver/src/QSError.cpp b/Plugins/OSGEarthDBDriver/src/QSError.cpp deleted file mode 100644 index ddff49188..000000000 --- a/Plugins/OSGEarthDBDriver/src/QSError.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ - -#include -#include -#include "QSError.h" - -namespace simVis_db { - -static const char* QS_IS_UNRECOGNIZED_ERROR_VALUE_STR = "Unrecognized Error Value"; -static const char* QS_IS_OK_STR = "\0"; -static const char* QS_IS_COMMAND_LINE_STR = "Command line error"; -static const char* QS_IS_UNEXPECTED_NULL_STR = "Unexpected NULL"; -static const char* QS_IS_NO_TMPDIR_STR = "TMPDIR environment variable not set"; -static const char* QS_IS_UNABLE_TO_OPEN_DB_STR = "Unable to open database"; -static const char* QS_IS_UNABLE_TO_OPEN_SRC_DS_STR = "Unable to open src dataset"; -static const char* QS_IS_UNABLE_TO_GET_SRC_DRIVER_STR = "Unable to get src driver"; -static const char* QS_IS_UNABLE_TO_GET_SRC_DRIVER_NAME_STR = "Unable to get src driver name"; -static const char* QS_IS_UNABLE_TO_CONVERT_TO_GEOGRAPHIC_STR = "Unable to convert to geographic dataset"; -static const char* QS_IS_UNABLE_TO_CREATE_INFO_FILE_STR = "Unable to create info file"; -static const char* QS_IS_UNABLE_TO_OPEN_INFO_FILE_STR = "Unable to open info file"; -static const char* QS_IS_TIME_STRING_ERROR_STR = "Time string error"; -static const char* QS_IS_UNABLE_TO_GET_FACE_STRING_STR = "Unable to get face string"; -static const char* QS_IS_DB_NOT_INITIALIZED_STR = "Database not initialized"; -static const char* QS_IS_UNABLE_TO_CREATE_TN_INDEX_STR = "Unable to create texture name index"; -static const char* QS_IS_UNABLE_TO_INSERT_TS_INTO_LIST_STR = "Unable to insert texture set into list"; -static const char* QS_IS_EMPTY_TABLE_NAME_STR = "Empty table name"; -static const char* QS_IS_UNABLE_TO_CREATE_TABLE_STR = "Unable to create table"; -static const char* QS_IS_UNABLE_TO_CREATE_ID_INDEX_STR = "Unable to create id index"; -static const char* QS_IS_UNABLE_TO_CREATE_P_IMAGE_STR = "Unable to create polar image"; -static const char* QS_IS_UNABLE_TO_READ_FROM_RASTER_STR = "Unable to read from raster"; -static const char* QS_IS_FORMAT_NOT_IMPLEMENTED_STR = "Format not implemented"; -static const char* QS_IS_UNABLE_TO_WRITE_TO_BLOB_STR = "Unable to write to blob"; -static const char* QS_IS_UNABLE_SCALE_IMAGE_STR = "Unable to scale image"; -static const char* QS_IS_PREPARE_ERROR_STR = "Unable to prepare statement"; -static const char* QS_IS_TS_NOT_FOUND_STR = "Texture set not found"; -static const char* QS_IS_UNABLE_TO_UPDATE_EXTENTS_STR = "Unable to update extents"; -static const char* QS_IS_UNABLE_TO_WRITE_DATA_BUFFER_STR = "Unable to write data buffer"; -static const char* QS_IS_UNABLE_TO_READ_DATA_BUFFER_STR = "Unable to read data buffer"; -static const char* QS_IS_BUSY_STR = "Database is busy"; -static const char* QS_IS_UNABLE_TO_UPDATE_TIME_STR = "Unable to update time"; -static const char* QS_IS_UNABLE_TO_SET_NUM_BYTES_STR = "Unable to set num bytes"; -static const char* QS_IS_UNABLE_TO_GET_AVERAGE_REQUEST_TIME_STR = "Unable to get average request time"; -static const char* QS_IS_UNABLE_TO_REMOVE_OLDER_THAN_AVG_STR = "Unable to remove older than average"; -static const char* QS_IS_UNABLE_TO_SUM_NUMBER_OF_BYTES_STR = "Unable to sum number of bytes"; -static const char* QS_IS_UNABLE_TO_WRITE_TO_OUTPUT_DIR_STR = "Unable to write to output directory"; -static const char* QS_IS_COULD_NOT_CREATE_FUNCTION_STR = "Unable to create function"; -static const char* QS_IS_EMPTY_FUNCTION_NAME_STR = "Empty function name"; -static const char* QS_IS_UNABLE_TO_EXECUTE_FUNCTION_STR = "Unable to execture function"; -static const char* QS_IS_UNABLE_TO_WRITE_TO_RASTER_STR = "Unable to write to raster"; -static const char* QS_IS_EMPTY_FILENAME_STR = "Empty filename"; -static const char* QS_IS_SET_CREATION_FAILED_STR = "Attempted raster set creation failed"; -static const char* QS_IS_NO_TIME_STAMP_STR = "Unable to obtain timestamp"; - -const char* GetErrorString(const QsErrorType& errorValue) -{ - switch (errorValue) - { - case QS_IS_OK: - return QS_IS_OK_STR; - case QS_IS_COMMAND_LINE: - return QS_IS_COMMAND_LINE_STR; - case QS_IS_UNEXPECTED_NULL: - return QS_IS_UNEXPECTED_NULL_STR; - case QS_IS_NO_TMPDIR: - return QS_IS_NO_TMPDIR_STR; - case QS_IS_UNABLE_TO_OPEN_DB: - return QS_IS_UNABLE_TO_OPEN_DB_STR; - case QS_IS_UNABLE_TO_OPEN_SRC_DS: - return QS_IS_UNABLE_TO_OPEN_SRC_DS_STR; - case QS_IS_UNABLE_TO_GET_SRC_DRIVER: - return QS_IS_UNABLE_TO_GET_SRC_DRIVER_STR; - case QS_IS_UNABLE_TO_GET_SRC_DRIVER_NAME: - return QS_IS_UNABLE_TO_GET_SRC_DRIVER_NAME_STR; - case QS_IS_UNABLE_TO_CONVERT_TO_GEOGRAPHIC: - return QS_IS_UNABLE_TO_CONVERT_TO_GEOGRAPHIC_STR; - case QS_IS_UNABLE_TO_CREATE_INFO_FILE: - return QS_IS_UNABLE_TO_CREATE_INFO_FILE_STR; - case QS_IS_UNABLE_TO_OPEN_INFO_FILE: - return QS_IS_UNABLE_TO_OPEN_INFO_FILE_STR; - case QS_IS_TIME_STRING_ERROR: - return QS_IS_TIME_STRING_ERROR_STR; - case QS_IS_UNABLE_TO_GET_FACE_STRING: - return QS_IS_UNABLE_TO_GET_FACE_STRING_STR; - case QS_IS_DB_NOT_INITIALIZED: - return QS_IS_DB_NOT_INITIALIZED_STR; - case QS_IS_UNABLE_TO_CREATE_TN_INDEX: - return QS_IS_UNABLE_TO_CREATE_TN_INDEX_STR; - case QS_IS_UNABLE_TO_INSERT_TS_INTO_LIST: - return QS_IS_UNABLE_TO_INSERT_TS_INTO_LIST_STR; - case QS_IS_EMPTY_TABLE_NAME: - return QS_IS_EMPTY_TABLE_NAME_STR; - case QS_IS_UNABLE_TO_CREATE_TABLE: - return QS_IS_UNABLE_TO_CREATE_TABLE_STR; - case QS_IS_UNABLE_TO_CREATE_ID_INDEX: - return QS_IS_UNABLE_TO_CREATE_ID_INDEX_STR; - case QS_IS_UNABLE_TO_CREATE_P_IMAGE: - return QS_IS_UNABLE_TO_CREATE_P_IMAGE_STR; - case QS_IS_UNABLE_TO_READ_FROM_RASTER: - return QS_IS_UNABLE_TO_READ_FROM_RASTER_STR; - case QS_IS_FORMAT_NOT_IMPLEMENTED: - return QS_IS_FORMAT_NOT_IMPLEMENTED_STR; - case QS_IS_UNABLE_TO_WRITE_TO_BLOB: - return QS_IS_UNABLE_TO_WRITE_TO_BLOB_STR; - case QS_IS_UNABLE_SCALE_IMAGE: - return QS_IS_UNABLE_SCALE_IMAGE_STR; - case QS_IS_PREPARE_ERROR: - return QS_IS_PREPARE_ERROR_STR; - case QS_IS_TS_NOT_FOUND: - return QS_IS_TS_NOT_FOUND_STR; - case QS_IS_UNABLE_TO_UPDATE_EXTENTS: - return QS_IS_UNABLE_TO_UPDATE_EXTENTS_STR; - case QS_IS_UNABLE_TO_WRITE_DATA_BUFFER: - return QS_IS_UNABLE_TO_WRITE_DATA_BUFFER_STR; - case QS_IS_UNABLE_TO_READ_DATA_BUFFER: - return QS_IS_UNABLE_TO_READ_DATA_BUFFER_STR; - case QS_IS_BUSY: - return QS_IS_BUSY_STR; - case QS_IS_UNABLE_TO_UPDATE_TIME: - return QS_IS_UNABLE_TO_UPDATE_TIME_STR; - case QS_IS_UNABLE_TO_SET_NUM_BYTES: - return QS_IS_UNABLE_TO_SET_NUM_BYTES_STR; - case QS_IS_UNABLE_TO_GET_AVERAGE_REQUEST_TIME: - return QS_IS_UNABLE_TO_GET_AVERAGE_REQUEST_TIME_STR; - case QS_IS_UNABLE_TO_REMOVE_OLDER_THAN_AVG: - return QS_IS_UNABLE_TO_REMOVE_OLDER_THAN_AVG_STR; - case QS_IS_UNABLE_TO_SUM_NUMBER_OF_BYTES: - return QS_IS_UNABLE_TO_SUM_NUMBER_OF_BYTES_STR; - case QS_IS_UNABLE_TO_WRITE_TO_OUTPUT_DIR: - return QS_IS_UNABLE_TO_WRITE_TO_OUTPUT_DIR_STR; - case QS_IS_COULD_NOT_CREATE_FUNCTION: - return QS_IS_COULD_NOT_CREATE_FUNCTION_STR; - case QS_IS_EMPTY_FUNCTION_NAME: - return QS_IS_EMPTY_FUNCTION_NAME_STR; - case QS_IS_UNABLE_TO_EXECUTE_FUNCTION: - return QS_IS_UNABLE_TO_EXECUTE_FUNCTION_STR; - case QS_IS_UNABLE_TO_WRITE_TO_RASTER: - return QS_IS_UNABLE_TO_WRITE_TO_RASTER_STR; - case QS_IS_EMPTY_FILENAME: - return QS_IS_EMPTY_FILENAME_STR; - case QS_IS_SET_CREATION_FAILED: - return QS_IS_SET_CREATION_FAILED_STR; - case QS_IS_NO_TIME_STAMP: - return QS_IS_NO_TIME_STAMP_STR; - default: - std::cerr << "ERROR: Unrecognized error value (" << errorValue << ").\n"; - assert(0); - return QS_IS_UNRECOGNIZED_ERROR_VALUE_STR; - } -} - -} diff --git a/Plugins/OSGEarthDBDriver/src/QSNodeID96.cpp b/Plugins/OSGEarthDBDriver/src/QSNodeID96.cpp deleted file mode 100644 index ccaa33a02..000000000 --- a/Plugins/OSGEarthDBDriver/src/QSNodeID96.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ -#include "swapbytes.h" -#include "QSNodeID96.h" - -namespace simVis_db { - -//=========================================================================== -QSNodeID96::QSNodeID96() - : one_(0), - two_(0), - three_(0) -{ -} - -//--------------------------------------------------------------------------- -QSNodeID96::QSNodeID96(const uint32_t& value) - : one_(value), - two_(0), - three_(0) -{ -} - -//--------------------------------------------------------------------------- -QSNodeID96::~QSNodeID96() -{ -} - -//--------------------------------------------------------------------------- -bool QSNodeID96::operator==(const QSNodeID96& value) const -{ - return ((one_ == value.one_) && (two_ == value.two_) && (three_ == value.three_)); -} - -//--------------------------------------------------------------------------- -bool QSNodeID96::operator<(const QSNodeID96& value) const -{ - if (one_ != value.one_) - return one_ < value.one_; - if (two_ != value.two_) - return two_ < value.two_; - return three_ < value.three_; -} - -//--------------------------------------------------------------------------- -QSNodeID96& QSNodeID96::operator=(const QSNodeID96& value) -{ - one_ = value.one_; - two_ = value.two_; - three_ = value.three_; - return *this; -} - -//--------------------------------------------------------------------------- -QSNodeID96 QSNodeID96::operator~() const -{ - QSNodeID96 returnValue = (*this); - returnValue.one_ = ~one_; - returnValue.two_ = ~two_; - returnValue.three_ = ~three_; - return returnValue; -} - -//--------------------------------------------------------------------------- -QSNodeID96& QSNodeID96::operator|=(const QSNodeID96& value) -{ - one_ |= value.one_; - two_ |= value.two_; - three_ |= value.three_; - return *this; -} - -//--------------------------------------------------------------------------- -QSNodeID96& QSNodeID96::operator&=(const QSNodeID96& value) -{ - one_ &= value.one_; - two_ &= value.two_; - three_ &= value.three_; - return *this; -} - -//--------------------------------------------------------------------------- -QSNodeID96 QSNodeID96::operator>>(int numBitsToShift) const -{ - QSNodeID96 returnValue; - if (numBitsToShift >= 0) - { - if (numBitsToShift == 32) - { - returnValue.one_ = two_; - returnValue.two_ = three_; - returnValue.three_ = 0; - } - else if (numBitsToShift == 0) - { - returnValue.one_ = one_; - returnValue.two_ = two_; - returnValue.three_ = three_; - } - else if (numBitsToShift == 64) - { - returnValue.one_ = three_; - returnValue.two_ = 0; - returnValue.three_ = 0; - } - else if (numBitsToShift < 32) - { - returnValue.three_ = (three_ >> numBitsToShift); - returnValue.two_ = (two_ >> numBitsToShift) | (three_ << (32 - numBitsToShift)); - returnValue.one_ = (one_ >> numBitsToShift) | (two_ << (32 - numBitsToShift)); - } - else if (numBitsToShift < 64) - { - returnValue.three_ = 0; - returnValue.two_ = three_ >> (numBitsToShift-32); - returnValue.one_ = (two_ >> (numBitsToShift-32)) | (three_ << (64 - numBitsToShift)); - } - else if (numBitsToShift < 96) - { - returnValue.three_ = 0; - returnValue.two_ = 0; - returnValue.one_ = three_ >> (numBitsToShift-64); - } - else - { - returnValue.one_ = 0; - returnValue.two_ = 0; - returnValue.three_ = 0; - } - } - else - returnValue.operator<<(-numBitsToShift); - - return returnValue; -} - -//--------------------------------------------------------------------------- -QSNodeID96 QSNodeID96::operator<<(int numBitsToShift) const -{ - QSNodeID96 returnValue; - if (numBitsToShift >= 0) - { - if (numBitsToShift == 32) - { - returnValue.one_ = 0; - returnValue.two_ = one_; - returnValue.three_ = two_; - } - else if (numBitsToShift == 0) - { - returnValue.one_ = one_; - returnValue.two_ = two_; - returnValue.three_ = three_; - } - else if (numBitsToShift == 64) - { - returnValue.one_ = 0; - returnValue.two_ = 0; - returnValue.three_ = one_; - } - else if (numBitsToShift < 32) - { - returnValue.one_ = one_ << numBitsToShift; - returnValue.two_ = (two_ << numBitsToShift) | (one_ >> (32 - numBitsToShift)); - returnValue.three_ = (three_ << numBitsToShift) | (two_ >> (32 - numBitsToShift)); - } - else if (numBitsToShift < 64) - { - returnValue.one_ = 0; - returnValue.two_ = one_ << (numBitsToShift-32); - returnValue.three_ = (two_ << (numBitsToShift-32)) | (one_ >> (64 - numBitsToShift)); - } - else if (numBitsToShift < 96) - { - returnValue.one_ = 0; - returnValue.two_ = 0; - returnValue.three_ = one_ << (numBitsToShift-64); - } - else - { - returnValue.three_ = 0; - returnValue.two_ = 0; - returnValue.one_ = 0; - } - } - else - returnValue.operator>>(-numBitsToShift); - - return returnValue; -} - -//--------------------------------------------------------------------------- -QSNodeID96 QSNodeID96::operator&(const QSNodeID96& value) const -{ - QSNodeID96 returnValue; - returnValue.one_ = one_ & value.one_; - returnValue.two_ = two_ & value.two_; - returnValue.three_ = three_ & value.three_; - return returnValue; -} - -//--------------------------------------------------------------------------- -void QSNodeID96::Pack(uint8_t* buffer) const -{ - if (buffer == NULL) - return; - bewrite(buffer, &three_); - bewrite(buffer + sizeof(three_), &two_); - bewrite(buffer + sizeof(three_) + sizeof(two_), &one_); -} - -//--------------------------------------------------------------------------- -void QSNodeID96::UnPack(const uint8_t* buffer) -{ - if (buffer == NULL) - return; - beread(buffer, &three_); - beread(buffer + sizeof(three_), &two_); - beread(buffer + sizeof(three_) + sizeof(two_), &one_); -} - -//--------------------------------------------------------------------------- -std::string QSNodeID96::FormatAsHex(bool bLeadingZeros) const -{ - std::string returnValue; - - char sTemp[64]; - - if (bLeadingZeros) - { - sprintf(sTemp, "%08x", three_); - returnValue += sTemp; - } - else - { - if (three_) - { - sprintf(sTemp, "%x", three_); - returnValue += sTemp; - } - } - - if (bLeadingZeros) - { - sprintf(sTemp, "%08x", two_); - returnValue += sTemp; - } - else - { - if (two_) - { - if (three_) - sprintf(sTemp, "%08x", two_); - else - sprintf(sTemp, "%x", two_); - returnValue += sTemp; - } - } - - if (bLeadingZeros) - { - sprintf(sTemp, "%08x", one_); - returnValue += sTemp; - } - else - { - if (one_) - { - if (three_ || two_) - sprintf(sTemp, "%08x", one_); - else - sprintf(sTemp, "%x", one_); - returnValue += sTemp; - } - } - - if (returnValue.empty()) - returnValue = "0"; - - return returnValue; -} - -} diff --git a/Plugins/OSGEarthDBDriver/src/QSPosXYExtents.cpp b/Plugins/OSGEarthDBDriver/src/QSPosXYExtents.cpp deleted file mode 100644 index 6f49b8be3..000000000 --- a/Plugins/OSGEarthDBDriver/src/QSPosXYExtents.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ - -#include -#include "simCore/Calc/Math.h" -#include "swapbytes.h" -#include "QSCommon.h" -#include "QSPosXYExtents.h" - -namespace simVis_db { - -//===================================================================================== -PosXPosYExtents::PosXPosYExtents(QsPosType minXIn, QsPosType maxXIn, QsPosType minYIn, QsPosType maxYIn) - : minX(minXIn), - maxX(maxXIn), - minY(minYIn), - maxY(maxYIn) -{ -} - -void PosXPosYExtents::Initialize() -{ - minX = gQsMaxLength; - maxX = 0; - minY = gQsMaxLength; - maxY = 0; -} - -bool PosXPosYExtents::Valid() const -{ - return ((minX >= maxX) || (minY >= maxY)) ? false : true; -} - -void PosXPosYExtents::SetAll(const PosXPosYExtents& given) -{ - minX = given.minX; - maxX = given.maxX; - minY = given.minY; - maxY = given.maxY; -} - -void PosXPosYExtents::SetAll(const QsPosType& minXIn, const QsPosType& maxXIn, const QsPosType& minYIn, const QsPosType& maxYIn) -{ - minX = minXIn; - maxX = maxXIn; - minY = minYIn; - maxY = maxYIn; -} - -void PosXPosYExtents::Pack(uint8_t* buffer) const -{ - if (buffer == NULL) - return; - bewrite(buffer, &minX); - bewrite(buffer + sizeof(minX), &maxX); - bewrite(buffer + sizeof(minX) + sizeof(maxX), &minY); - bewrite(buffer + sizeof(minX) + sizeof(maxX) + sizeof(minY), &maxY); -} - -void PosXPosYExtents::UnPack(const uint8_t* buffer) -{ - if (buffer == NULL) - return; - beread(buffer, &minX); - beread(buffer + sizeof(minX), &maxX); - beread(buffer + sizeof(minX) + sizeof(maxX), &minY); - beread(buffer + sizeof(minX) + sizeof(maxX) + sizeof(minY), &maxY); -} - -void PosXPosYExtents::Print() -{ - std::cerr << "minX = " << minX << "\n"; - std::cerr << "maxX = " << maxX << "\n"; - std::cerr << "minY = " << minY << "\n"; - std::cerr << "maxY = " << maxY << "\n"; -} - -//===================================================================================== -bool equalTo(const PosXPosYExtents& a, const PosXPosYExtents& b) -{ - if (a.minX != b.minX) return false; - if (a.maxX != b.maxX) return false; - if (a.minY != b.minY) return false; - if (a.maxY != b.maxY) return false; - return true; -} - -bool operator==(const PosXPosYExtents& a, const PosXPosYExtents& b) -{ - return equalTo(a, b); -} - -bool operator!=(const PosXPosYExtents& a, const PosXPosYExtents& b) -{ - return !simVis_db::equalTo(a, b); -} - -//===================================================================================== -void UpdateExtents(const QsPosType& posX, const QsPosType& posY, PosXPosYExtents* extents) -{ - if (extents == NULL) - return; - - extents->minX = simCore::sdkMin(extents->minX, posX); - extents->minY = simCore::sdkMin(extents->minY, posY); - extents->maxX = simCore::sdkMax(extents->maxX, posX); - extents->maxY = simCore::sdkMax(extents->maxY, posY); -} - -bool Copy6Extents(const PosXPosYExtents* copyFrom, PosXPosYExtents* copyTo) -{ - if ((copyFrom == NULL) || (copyTo == NULL)) - return false; - - FaceIndexType faceIndex; - for (faceIndex = 0; faceIndex < 6; ++faceIndex) - copyTo[faceIndex].SetAll(copyFrom[faceIndex]); - - return true; -} - -bool AnyOverlap(const PosXPosYExtents& extA, const PosXPosYExtents& extB) -{ - if ((extA.Valid() == false) || (extB.Valid() == false)) - return false; - - // checks for no x overlap - if ((extA.minX > extB.maxX) || - (extA.maxX < extB.minX)) - return false; - - // checks for no y overlap - if ((extA.minY > extB.maxY) || - (extA.maxY < extB.minY)) - return false; - - return true; -} - -bool AnyOverlap(const QsPosType& posX, const QsPosType& posY, const PosXPosYExtents& extents) -{ - if (extents.Valid() == false) - return false; - - return ((posX < extents.minX) || - (posX > extents.maxX) || - (posY < extents.minY) || - (posY > extents.maxY)) ? false : true; -} - -} diff --git a/Plugins/OSGEarthDBDriver/src/SQLiteDataBaseReadUtil.cpp b/Plugins/OSGEarthDBDriver/src/SQLiteDataBaseReadUtil.cpp deleted file mode 100644 index b6a26cc5b..000000000 --- a/Plugins/OSGEarthDBDriver/src/SQLiteDataBaseReadUtil.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** - ***** ***** - ***** Classification: UNCLASSIFIED ***** - ***** Classified By: ***** - ***** Declassify On: ***** - ***** ***** - **************************************************************************** - * - * - * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. - * EW Modeling & Simulation, Code 5773 - * 4555 Overlook Ave. - * Washington, D.C. 20375-5339 - * - * License for source code at https://simdis.nrl.navy.mil/License.aspx - * - * The U.S. Government retains all rights to use, duplicate, distribute, - * disclose, or release this software. - * - */ - -#include -#include -#include "simCore/Time/Utils.h" -#include "swapbytes.h" -#include "QSCommon.h" -#include "SQLiteDataBaseReadUtil.h" - -namespace simVis_db { - -namespace -{ - //===================================================================================== - template - void UnPackArray(SomeClass* givenArray, const uint8_t* givenBuffer, const uint32_t& numElements) - { - if ((givenArray == NULL) || (givenBuffer == NULL)) - return; - - size_t i; - uint8_t tmpBuffer[sizeof(SomeClass)]; - for (i = 0; i < numElements; ++i) - { - memcpy(tmpBuffer, givenBuffer + (sizeof(SomeClass) * i), sizeof(SomeClass)); - givenArray[i].UnPack(tmpBuffer); - } - } - - static const int gMaxBufferSize = 20000000; - - std::string printExtendedErrorMessage(sqlite3* sqlite3Db) - { - std::stringstream errStr; - int extendedErrorCode = sqlite3_extended_errcode(sqlite3Db); - errStr << " Ext Err Code(" << extendedErrorCode << ") "; - // Extended Result Codes: http://www.sqlite.org/c3ref/c_abort_rollback.html - switch (extendedErrorCode) - { - case SQLITE_IOERR_READ: errStr << "SQLITE_IOERR_READ"; break; - case SQLITE_IOERR_SHORT_READ: errStr << "SQLITE_SHORT_READ"; break; - case SQLITE_IOERR_WRITE: errStr << "SQLITE_IOERR_WRITE"; break; - case SQLITE_IOERR_FSYNC: errStr << "SQLITE_IOERR_FSYNC"; break; - case SQLITE_IOERR_DIR_FSYNC: errStr << "SQLITE_IOERR_DIR_FSYNC"; break; - case SQLITE_IOERR_TRUNCATE: errStr << "SQLITE_IOERR_TRUNCATE"; break; - case SQLITE_IOERR_FSTAT: errStr << "SQLITE_IOERR_FSTAT"; break; - case SQLITE_IOERR_UNLOCK: errStr << "SQLITE_IOERR_UNLOCK"; break; - case SQLITE_IOERR_RDLOCK: errStr << "SQLITE_IOERR_RDLOCK"; break; - case SQLITE_IOERR_DELETE: errStr << "SQLITE_IOERR_DELETE"; break; - case SQLITE_IOERR_BLOCKED: errStr << "SQLITE_IOERR_BLOCKED"; break; - case SQLITE_IOERR_NOMEM: errStr << "SQLITE_IOERR_NOMEM"; break; - case SQLITE_IOERR_ACCESS: errStr << "SQLITE_IOERR_ACCESS"; break; - case SQLITE_IOERR_CHECKRESERVEDLOCK: errStr << "SQLITE_IOERR_CHECKRESERVEDLOCK"; break; - case SQLITE_IOERR_LOCK: errStr << "SQLITE_IOERR_LOCK"; break; - case SQLITE_IOERR_CLOSE: errStr << "SQLITE_IOERR_CLOSE"; break; - case SQLITE_IOERR_DIR_CLOSE: errStr << "SQLITE_IOERR_DIR_CLOSE"; break; - case SQLITE_IOERR_SHMOPEN: errStr << "SQLITE_IOERR_SHMOPEN"; break; - case SQLITE_IOERR_SHMSIZE: errStr << "SQLITE_IOERR_SHMSIZE"; break; - case SQLITE_IOERR_SHMLOCK: errStr << "SQLITE_IOERR_SHMLOCK"; break; - case SQLITE_IOERR_SHMMAP: errStr << "SQLITE_IOERR_SHMMAP"; break; - case SQLITE_IOERR_SEEK: errStr << "SQLITE_IOERR_SEEK"; break; - case SQLITE_LOCKED_SHAREDCACHE: errStr << "SQLITE_LOCKED_SHAREDCACHE"; break; - case SQLITE_BUSY_RECOVERY: errStr << "SQLITE_BUSY_RECOVERY"; break; - case SQLITE_CANTOPEN_NOTEMPDIR: errStr << "SQLITE_CANTOPEN_NOTEMPDIR"; break; - case SQLITE_CANTOPEN_ISDIR: errStr << "SQLITE_CANTOPEN_ISDIR"; break; - case SQLITE_CORRUPT_VTAB: errStr << "SQLITE_CORRUPT_VTAB"; break; - case SQLITE_READONLY_RECOVERY: errStr << "SQLITE_READONLY_RECOVERY"; break; - case SQLITE_READONLY_CANTLOCK: errStr << "SQLITE_READONLY_CANTLOCK"; break; - case SQLITE_ABORT_ROLLBACK: errStr << "SQLITE_ABORT_ROLLBACK"; break; - default: errStr << "UNK"; break; - } - errStr << ", Desc: " << sqlite3_errmsg(sqlite3Db) << "\n"; - return errStr.str(); - } -} - -//===================================================================================== -SQLiteDataBaseReadUtil::SQLiteDataBaseReadUtil() - : textureSetSelectCommand_(""), - tsInsertFileIdData_(2), - tsInsertSetTextureSetName_(1), - tsInsertSetIdRasterFormat_(2), - tsInsertSetIdPixelLength_(3), - tsInsertSetIdShallowestLevel_(4), - tsInsertSetIdDeepestLevel_(5), - tsInsertSetIdExtents_(6), - tsInsertSetIdSource_(7), - tsInsertSetIdClassification_(8), - tsInsertSetIdDescription_(9), - tsInsertSetIdTimeSpecified_(10), - tsInsertSetIdTimeValue_(11) -{ - QSNodeId nodeID; - sizeOfIdBlob_ = sizeof(FaceIndexType) + nodeID.SizeOf(); - - // Creates the command for reading an image from a "texture set" table - textureSetSelectFileCommand1_ = "SELECT * From \""; - textureSetSelectFileCommand2_ = "\" WHERE "; - textureSetSelectFileCommand2_.append(QS_TO_ID); - textureSetSelectFileCommand2_.append("=?"); - - // Creates the command for select a texture set row from a "list of texture sets" table - textureSetSelectCommand_ = "SELECT * From "; - textureSetSelectCommand_.append(QS_LIST_OF_TEXTURE_SETS_TABLE_NAME); - textureSetSelectCommand_.append(" WHERE "); - textureSetSelectCommand_.append(QS_TSO_NAME_OF_TEXTURE_SET_TABLE); - textureSetSelectCommand_.append("=?"); -} - -//------------------------------------------------------------------------------------- -SQLiteDataBaseReadUtil::~SQLiteDataBaseReadUtil() -{ -} - -//------------------------------------------------------------------------------------- -QsErrorType SQLiteDataBaseReadUtil::OpenDataBaseFile(const std::string& dbFileName, - sqlite3** sqlite3Db, - const int& flags) const -{ - if (dbFileName.empty() || (sqlite3Db == NULL)) - return QS_IS_UNABLE_TO_OPEN_DB; - - // Attempts to open the database file - int errorCode = sqlite3_open_v2(dbFileName.c_str(), sqlite3Db, flags, NULL); - if ((*sqlite3Db == 0) || (errorCode != SQLITE_OK)) - { - if ((errorCode == SQLITE_BUSY) || - (errorCode == SQLITE_LOCKED)) - return QS_IS_BUSY; - std::cerr << "OpenDataBaseFile sqlite3_open_v2 Error: " << dbFileName << "\n" << printExtendedErrorMessage(*sqlite3Db); - return QS_IS_UNABLE_TO_OPEN_DB; - } - if (sqlite3_exec(*sqlite3Db, "PRAGMA CACHE_SIZE=100;", NULL, NULL, NULL) != SQLITE_OK) - { - std::cerr << "Unable to set SQLite cache size " << dbFileName << "\n"; - std::cerr << printExtendedErrorMessage(*sqlite3Db); - } - - return QS_IS_OK; -} - -//------------------------------------------------------------------------------------- -QsErrorType SQLiteDataBaseReadUtil::TsReadDataBuffer(sqlite3* sqlite3Db, - const std::string& dbFileName, - const std::string& dataTableName, - const FaceIndexType& faceIndex, - const QSNodeId& nodeID, - TextureDataType** buffer, - uint32_t* bufferSize, - uint32_t* currentRasterSize, - bool allowLocalDB, - bool displayErrorMessage) const -{ - int returnValue; - - if ((buffer == NULL) || (bufferSize == NULL) || (currentRasterSize == NULL)) - return QS_IS_UNEXPECTED_NULL; - - *currentRasterSize = 0; - - if (dataTableName.empty() || dbFileName.empty()) - return QS_IS_EMPTY_TABLE_NAME; - - // opens the database - bool localDb = false; - QsErrorType tmpReturnValue; - if (sqlite3Db == NULL) - { - if (allowLocalDB == false) - return QS_IS_DB_NOT_INITIALIZED; - localDb = true; - tmpReturnValue = OpenDataBaseFile(dbFileName, &sqlite3Db, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX); - if (tmpReturnValue != QS_IS_OK) - return tmpReturnValue; - } - - std::string sqlCommand; - sqlCommand = textureSetSelectFileCommand1_; - sqlCommand.append(dataTableName); - sqlCommand.append(textureSetSelectFileCommand2_); - - // prepares the statement - sqlite3_stmt* stmt = 0; - returnValue = sqlite3_prepare_v2(sqlite3Db, sqlCommand.c_str(), static_cast(sqlCommand.length()), &stmt, NULL); - if (returnValue != SQLITE_OK) - { - if (displayErrorMessage && (returnValue != SQLITE_BUSY && returnValue != SQLITE_LOCKED)) - { - std::cerr << "TsReadDataBuffer sqlite3_prepare_v2 Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); - } - if (stmt != NULL) sqlite3_finalize(stmt); - if (localDb) sqlite3_close(sqlite3Db); - if ((returnValue == SQLITE_BUSY) || - (returnValue == SQLITE_LOCKED)) - return QS_IS_BUSY; - return QS_IS_PREPARE_ERROR; - } - - // binds id - uint8_t* idBlob = new uint8_t[sizeOfIdBlob_]; - bewrite(idBlob, &faceIndex); - nodeID.Pack(idBlob + sizeof(FaceIndexType)); - returnValue = sqlite3_bind_blob(stmt, 1, idBlob, sizeOfIdBlob_, SQLITE_TRANSIENT); - if (returnValue != SQLITE_OK && displayErrorMessage) - { - std::cerr << "TsReadDataBuffer sqlite3_bind_blob Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); - } - delete[] idBlob; - - // executes the statement - returnValue = sqlite3_step(stmt); - QsErrorType otherReturnValue = QS_IS_UNABLE_TO_READ_DATA_BUFFER; - if ((returnValue == SQLITE_ROW) || (returnValue == SQLITE_DONE)) - { - // gets the data - *currentRasterSize = sqlite3_column_bytes(stmt, tsInsertFileIdData_ - 1); - if ((*currentRasterSize > 0) && (*currentRasterSize <= static_cast(gMaxBufferSize))) - { - if (*currentRasterSize > (*bufferSize)) - { - if ((*buffer) != NULL) - delete[] * buffer; - *buffer = new uint8_t[*currentRasterSize]; - *bufferSize = (*currentRasterSize); - } - memcpy(*buffer, (const uint8_t*)sqlite3_column_blob(stmt, tsInsertFileIdData_ - 1), *currentRasterSize); - } - otherReturnValue = QS_IS_OK; - } - else if ((returnValue == SQLITE_BUSY) || (returnValue == SQLITE_LOCKED)) - { - otherReturnValue = QS_IS_BUSY; - } - else - { - if (displayErrorMessage) - { - std::cerr << "TsReadDataBuffer sqlite3_step Error(" << returnValue << "): " << dbFileName << "\n"; - std::cerr << "not done (" << nodeID.FormatAsHex().c_str() << ") " << printExtendedErrorMessage(sqlite3Db); - } - otherReturnValue = QS_IS_UNABLE_TO_READ_DATA_BUFFER; - } - - if (stmt != NULL) sqlite3_finalize(stmt); - if (localDb) - { - returnValue = sqlite3_close(sqlite3Db); - if (returnValue != SQLITE_OK && displayErrorMessage) - { - std::cerr << "TsReadDataBuffer localDb sqlite3_close Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); - } - } - return otherReturnValue; -} - -//------------------------------------------------------------------------------------- -QsErrorType SQLiteDataBaseReadUtil::TsGetSetFromListOfSetsTable(sqlite3* sqlite3Db, - const std::string& tableName, - int& rasterFormat, - int& pixelLength, - int& shallowLevel, - int& deepLevel, - PosXPosYExtents tmpExtents[6], - std::string& source, - std::string& classification, - std::string& description, - bool& timeSpecified, - simCore::TimeStamp& timeStamp) const -{ - if (sqlite3Db == NULL) - return QS_IS_DB_NOT_INITIALIZED; - if (tableName.empty()) - return QS_IS_EMPTY_TABLE_NAME; - - int returnValue; - QsErrorType otherReturnValue; - - // prepares the statement - sqlite3_stmt* stmt = 0; - returnValue = sqlite3_prepare_v2(sqlite3Db, textureSetSelectCommand_.c_str(), static_cast(textureSetSelectCommand_.length()), &stmt, NULL); - if (returnValue != SQLITE_OK) - { - std::cerr << "TsGetSetFromListOfSetsTable sqlite3_prepare_v2 Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); - if (stmt != NULL) sqlite3_finalize(stmt); - return QS_IS_PREPARE_ERROR; - } - - // binds the texture set name - returnValue = sqlite3_bind_text(stmt, 1, tableName.c_str(), int(tableName.length()), SQLITE_TRANSIENT); - if (returnValue != SQLITE_OK) - { - std::cerr << "TsGetSetFromListOfSetsTable sqlite3_bind_text Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); - } - - // executes the statement - returnValue = sqlite3_step(stmt); - if (returnValue > SQLITE_OK&& returnValue < SQLITE_ROW) - { - std::cerr << "TsGetSetFromListOfSetsTable sqlite3_step Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); - } - - if (returnValue == SQLITE_ROW) - { - // sets some texture set creation options - rasterFormat = sqlite3_column_int(stmt, tsInsertSetIdRasterFormat_ - 1); - pixelLength = sqlite3_column_int(stmt, tsInsertSetIdPixelLength_ - 1); - shallowLevel = sqlite3_column_int(stmt, tsInsertSetIdShallowestLevel_ - 1); - deepLevel = sqlite3_column_int(stmt, tsInsertSetIdDeepestLevel_ - 1); - UnPackArray(tmpExtents, (const uint8_t*)sqlite3_column_blob(stmt, tsInsertSetIdExtents_ - 1), 6); - source = (const char*)sqlite3_column_text(stmt, tsInsertSetIdSource_ - 1); - classification = (const char*)sqlite3_column_text(stmt, tsInsertSetIdClassification_ - 1); - description = (const char*)sqlite3_column_text(stmt, tsInsertSetIdDescription_ - 1); - timeSpecified = (sqlite3_column_int(stmt, tsInsertSetIdTimeSpecified_ - 1) != 0); - - if (timeSpecified) - { - const uint8_t* buffer = (const uint8_t*)sqlite3_column_blob(stmt, tsInsertSetIdTimeValue_ - 1); - int refYear = 0; - int secs = 0; - int frac = 0; - - // read TimeStamp data members from buffer - beread(buffer, &refYear); - beread(buffer + sizeof(refYear), &(secs)); - beread(buffer + sizeof(refYear) + sizeof(secs), &(frac)); - simCore::Seconds secsSinceRefYear(secs, frac); - timeStamp.setTime(refYear, secsSinceRefYear); - } - otherReturnValue = QS_IS_OK; - } - else if (returnValue == SQLITE_BUSY) - { - otherReturnValue = QS_IS_BUSY; - } - else - { - otherReturnValue = QS_IS_TS_NOT_FOUND; - } - - if (stmt != NULL) sqlite3_finalize(stmt); - return otherReturnValue; -} - -} From cc3c021f7a9055bb4435e8d33478d210d83eb2ae Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 16 Jan 2020 07:03:01 -0500 Subject: [PATCH 034/121] DEV: Fixed assert error, no review. --- SDK/simVis/LocalGrid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/simVis/LocalGrid.cpp b/SDK/simVis/LocalGrid.cpp index 19b05cb93..93137e64a 100644 --- a/SDK/simVis/LocalGrid.cpp +++ b/SDK/simVis/LocalGrid.cpp @@ -336,7 +336,7 @@ class RadialPoints : public osg::Group if (osg::equivalent(static_cast(fmod(static_cast(i), RADIAL_VERTEX_FACTOR)), 0.f)) // don't overdraw the rings continue; // if assert fails, re-check algorithm for determining vertexCount in constructor - assert(index < vertexArray->getNumElements()); + assert(index < points_->size()); points_->setVertex(index, osg::Vec3f(x * radialVertexSpacing * i, y * radialVertexSpacing * i, 0.f)); ++index; } From f0e89af2f3b396225fe9e9c90be158bc788ee85c Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 16 Jan 2020 07:03:23 -0500 Subject: [PATCH 035/121] DEV: Significant refactor on the DB driver code: * Removes unused/dead code * RasterFormat.h and Plugin.cpp, not used, were removed * Fixes rarely useful little endian flag on simVis that did not copy from DB plug-in transition * Style updates to headers, function names, variables, constants, ifndef include guards * Refactored unused defines (Linux, Solaris) * Removed SQLite legacy constant stub * Removed little endian conversion code, unused in SDK * Header updates Fixes SIM-10563. Review: 20423 --- SDK/simVis/CMakeLists.txt | 6 +- SDK/simVis/DB/Plugin.cpp | 56 -- SDK/simVis/DB/QSCommon.h | 6 +- SDK/simVis/DB/QSError.cpp | 2 +- SDK/simVis/DB/QSError.h | 8 +- SDK/simVis/DB/QSNodeID96.cpp | 18 +- SDK/simVis/DB/QSNodeID96.h | 15 +- SDK/simVis/DB/QSPosXYExtents.cpp | 96 +-- SDK/simVis/DB/QSPosXYExtents.h | 46 +- SDK/simVis/DB/RasterCommon.h | 0 SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp | 47 +- SDK/simVis/DB/SQLiteDataBaseReadUtil.h | 42 +- SDK/simVis/DB/swapbytes.h | 706 +---------------------- SDK/simVis/DBFormat.cpp | 50 +- SDK/simVis/DBFormat.h | 3 - 15 files changed, 144 insertions(+), 957 deletions(-) delete mode 100644 SDK/simVis/DB/Plugin.cpp delete mode 100644 SDK/simVis/DB/RasterCommon.h diff --git a/SDK/simVis/CMakeLists.txt b/SDK/simVis/CMakeLists.txt index 07610ba35..4bd925f8f 100644 --- a/SDK/simVis/CMakeLists.txt +++ b/SDK/simVis/CMakeLists.txt @@ -147,7 +147,6 @@ set(VIS_HEADERS_DB_PRIVATE ${VIS_INC}DB/QSError.h ${VIS_INC}DB/QSNodeID96.h ${VIS_INC}DB/QSPosXYExtents.h - ${VIS_INC}DB/RasterCommon.h ${VIS_INC}DB/SQLiteDataBaseReadUtil.h ${VIS_INC}DB/swapbytes.h ) @@ -440,6 +439,11 @@ else() endif() if(SIM_HAVE_DB_SUPPORT) target_compile_definitions(simVis PRIVATE SIM_HAVE_DB_SUPPORT) + if(SDK_BIG_ENDIAN) + target_compile_definitions(simVis PRIVATE SIM_BIG_ENDIAN) + else() + target_compile_definitions(simVis PRIVATE SIM_LITTLE_ENDIAN) + endif() endif() if(INSTALL_SIMDIS_SDK_LIBRARIES) diff --git a/SDK/simVis/DB/Plugin.cpp b/SDK/simVis/DB/Plugin.cpp deleted file mode 100644 index 4f95218cb..000000000 --- a/SDK/simVis/DB/Plugin.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** -***** ***** -***** Classification: UNCLASSIFIED ***** -***** Classified By: ***** -***** Declassify On: ***** -***** ***** -**************************************************************************** -* -* -* Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. -* EW Modeling & Simulation, Code 5773 -* 4555 Overlook Ave. -* Washington, D.C. 20375-5339 -* -* License for source code at https://simdis.nrl.navy.mil/License.aspx -* -* The U.S. Government retains all rights to use, duplicate, distribute, -* disclose, or release this software. -* -*/ -#include -#include "osgDB/FileNameUtils" -#include "osgDB/Registry" -#include "osgEarth/TileSource" -#include "DBTileSource.h" - -class SimSdkOSGEarthDBDriverPlugin : public osgEarth::Contrib::TileSourceDriver -{ -public: - SimSdkOSGEarthDBDriverPlugin() { } - - const char* className() - { - return "OSGEarth DB Driver"; - } - - bool acceptsExtension(const std::string& extension) const - { - return osgDB::equalCaseInsensitive("osgearth_db", extension); - } - - osgDB::ReaderWriter::ReadResult readObject(const std::string& uri, const osgDB::Options* options) const - { - std::string ext = osgDB::getFileExtension(uri); - if (!acceptsExtension(ext)) - { - return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED; - } - - return osgDB::ReaderWriter::ReadResult( - new simVis_db::DBTileSource(getTileSourceOptions(options))); - } -}; - -REGISTER_OSGPLUGIN(osgearth_db, SimSdkOSGEarthDBDriverPlugin) diff --git a/SDK/simVis/DB/QSCommon.h b/SDK/simVis/DB/QSCommon.h index 6e1f6d744..a5c7d076b 100644 --- a/SDK/simVis/DB/QSCommon.h +++ b/SDK/simVis/DB/QSCommon.h @@ -19,8 +19,8 @@ * disclose, or release this software. * */ -#ifndef QS_COMMON_H -#define QS_COMMON_H +#ifndef SIMVIS_DB_QSCOMMON_H +#define SIMVIS_DB_QSCOMMON_H #include "simCore/Common/Common.h" @@ -47,4 +47,4 @@ namespace simVis_db static const RasterFormat SPLIT_TIFF = 14; } // namespace simVis_db -#endif /* QS_COMMON_H */ +#endif /* SIMVIS_DB_QSCOMMON_H */ diff --git a/SDK/simVis/DB/QSError.cpp b/SDK/simVis/DB/QSError.cpp index ddff49188..77bc6ff69 100644 --- a/SDK/simVis/DB/QSError.cpp +++ b/SDK/simVis/DB/QSError.cpp @@ -71,7 +71,7 @@ static const char* QS_IS_EMPTY_FILENAME_STR = "Empty file static const char* QS_IS_SET_CREATION_FAILED_STR = "Attempted raster set creation failed"; static const char* QS_IS_NO_TIME_STAMP_STR = "Unable to obtain timestamp"; -const char* GetErrorString(const QsErrorType& errorValue) +const char* getErrorString(const QsErrorType& errorValue) { switch (errorValue) { diff --git a/SDK/simVis/DB/QSError.h b/SDK/simVis/DB/QSError.h index e4d3c42d1..2461f8659 100644 --- a/SDK/simVis/DB/QSError.h +++ b/SDK/simVis/DB/QSError.h @@ -20,8 +20,8 @@ * */ -#ifndef QS_ERROR_H -#define QS_ERROR_H +#ifndef SIMVIS_DB_QSERROR_H +#define SIMVIS_DB_QSERROR_H #include @@ -74,8 +74,8 @@ namespace simVis_db static const QsErrorType QS_IS_NO_TIME_STAMP = 42; //=========================================================================== - const char* GetErrorString(const QsErrorType&); + const char* getErrorString(const QsErrorType&); } // namespace simVis_db -#endif /* QS_ERROR_H */ +#endif /* SIMVIS_DB_QSERROR_H */ diff --git a/SDK/simVis/DB/QSNodeID96.cpp b/SDK/simVis/DB/QSNodeID96.cpp index ccaa33a02..88a8a98c3 100644 --- a/SDK/simVis/DB/QSNodeID96.cpp +++ b/SDK/simVis/DB/QSNodeID96.cpp @@ -219,27 +219,27 @@ QSNodeID96 QSNodeID96::operator&(const QSNodeID96& value) const } //--------------------------------------------------------------------------- -void QSNodeID96::Pack(uint8_t* buffer) const +void QSNodeID96::pack(uint8_t* buffer) const { if (buffer == NULL) return; - bewrite(buffer, &three_); - bewrite(buffer + sizeof(three_), &two_); - bewrite(buffer + sizeof(three_) + sizeof(two_), &one_); + beWrite(buffer, &three_); + beWrite(buffer + sizeof(three_), &two_); + beWrite(buffer + sizeof(three_) + sizeof(two_), &one_); } //--------------------------------------------------------------------------- -void QSNodeID96::UnPack(const uint8_t* buffer) +void QSNodeID96::unpack(const uint8_t* buffer) { if (buffer == NULL) return; - beread(buffer, &three_); - beread(buffer + sizeof(three_), &two_); - beread(buffer + sizeof(three_) + sizeof(two_), &one_); + beRead(buffer, &three_); + beRead(buffer + sizeof(three_), &two_); + beRead(buffer + sizeof(three_) + sizeof(two_), &one_); } //--------------------------------------------------------------------------- -std::string QSNodeID96::FormatAsHex(bool bLeadingZeros) const +std::string QSNodeID96::formatAsHex(bool bLeadingZeros) const { std::string returnValue; diff --git a/SDK/simVis/DB/QSNodeID96.h b/SDK/simVis/DB/QSNodeID96.h index 54d9cb6bc..e738e2e95 100644 --- a/SDK/simVis/DB/QSNodeID96.h +++ b/SDK/simVis/DB/QSNodeID96.h @@ -19,9 +19,8 @@ * disclose, or release this software. * */ - -#ifndef QSNODEID96_H -#define QSNODEID96_H +#ifndef SIMVIS_DB_QSNODEID96_H +#define SIMVIS_DB_QSNODEID96_H #include #include "simCore/Common/Common.h" @@ -45,10 +44,10 @@ namespace simVis_db QSNodeID96 operator<<(int numBitsToShift) const; QSNodeID96 operator&(const QSNodeID96& value) const; - int SizeOf() const {return 12;} - void Pack(uint8_t*) const; - void UnPack(const uint8_t*); - std::string FormatAsHex(bool bLeadingZeros=true) const; + int sizeOf() const {return 12;} + void pack(uint8_t*) const; + void unpack(const uint8_t*); + std::string formatAsHex(bool bLeadingZeros=true) const; protected: uint32_t one_; @@ -61,4 +60,4 @@ namespace simVis_db } // namespace simVis_db -#endif /* QSNODEID96_H */ +#endif /* SIMVIS_DB_QSNODEID96_H */ diff --git a/SDK/simVis/DB/QSPosXYExtents.cpp b/SDK/simVis/DB/QSPosXYExtents.cpp index 6f49b8be3..2372d828c 100644 --- a/SDK/simVis/DB/QSPosXYExtents.cpp +++ b/SDK/simVis/DB/QSPosXYExtents.cpp @@ -19,7 +19,6 @@ * disclose, or release this software. * */ - #include #include "simCore/Calc/Math.h" #include "swapbytes.h" @@ -37,20 +36,20 @@ PosXPosYExtents::PosXPosYExtents(QsPosType minXIn, QsPosType maxXIn, QsPosType m { } -void PosXPosYExtents::Initialize() +void PosXPosYExtents::initialize() { - minX = gQsMaxLength; + minX = QS_MAX_LENGTH_UINT64; maxX = 0; - minY = gQsMaxLength; + minY = QS_MAX_LENGTH_UINT64; maxY = 0; } -bool PosXPosYExtents::Valid() const +bool PosXPosYExtents::isValid() const { return ((minX >= maxX) || (minY >= maxY)) ? false : true; } -void PosXPosYExtents::SetAll(const PosXPosYExtents& given) +void PosXPosYExtents::setAll(const PosXPosYExtents& given) { minX = given.minX; maxX = given.maxX; @@ -58,7 +57,7 @@ void PosXPosYExtents::SetAll(const PosXPosYExtents& given) maxY = given.maxY; } -void PosXPosYExtents::SetAll(const QsPosType& minXIn, const QsPosType& maxXIn, const QsPosType& minYIn, const QsPosType& maxYIn) +void PosXPosYExtents::setAll(const QsPosType& minXIn, const QsPosType& maxXIn, const QsPosType& minYIn, const QsPosType& maxYIn) { minX = minXIn; maxX = maxXIn; @@ -66,32 +65,24 @@ void PosXPosYExtents::SetAll(const QsPosType& minXIn, const QsPosType& maxXIn, c maxY = maxYIn; } -void PosXPosYExtents::Pack(uint8_t* buffer) const +void PosXPosYExtents::pack(uint8_t* buffer) const { if (buffer == NULL) return; - bewrite(buffer, &minX); - bewrite(buffer + sizeof(minX), &maxX); - bewrite(buffer + sizeof(minX) + sizeof(maxX), &minY); - bewrite(buffer + sizeof(minX) + sizeof(maxX) + sizeof(minY), &maxY); + beWrite(buffer, &minX); + beWrite(buffer + sizeof(minX), &maxX); + beWrite(buffer + sizeof(minX) + sizeof(maxX), &minY); + beWrite(buffer + sizeof(minX) + sizeof(maxX) + sizeof(minY), &maxY); } -void PosXPosYExtents::UnPack(const uint8_t* buffer) +void PosXPosYExtents::unpack(const uint8_t* buffer) { if (buffer == NULL) return; - beread(buffer, &minX); - beread(buffer + sizeof(minX), &maxX); - beread(buffer + sizeof(minX) + sizeof(maxX), &minY); - beread(buffer + sizeof(minX) + sizeof(maxX) + sizeof(minY), &maxY); -} - -void PosXPosYExtents::Print() -{ - std::cerr << "minX = " << minX << "\n"; - std::cerr << "maxX = " << maxX << "\n"; - std::cerr << "minY = " << minY << "\n"; - std::cerr << "maxY = " << maxY << "\n"; + beRead(buffer, &minX); + beRead(buffer + sizeof(minX), &maxX); + beRead(buffer + sizeof(minX) + sizeof(maxX), &minY); + beRead(buffer + sizeof(minX) + sizeof(maxX) + sizeof(minY), &maxY); } //===================================================================================== @@ -106,7 +97,7 @@ bool equalTo(const PosXPosYExtents& a, const PosXPosYExtents& b) bool operator==(const PosXPosYExtents& a, const PosXPosYExtents& b) { - return equalTo(a, b); + return simVis_db::equalTo(a, b); } bool operator!=(const PosXPosYExtents& a, const PosXPosYExtents& b) @@ -114,57 +105,4 @@ bool operator!=(const PosXPosYExtents& a, const PosXPosYExtents& b) return !simVis_db::equalTo(a, b); } -//===================================================================================== -void UpdateExtents(const QsPosType& posX, const QsPosType& posY, PosXPosYExtents* extents) -{ - if (extents == NULL) - return; - - extents->minX = simCore::sdkMin(extents->minX, posX); - extents->minY = simCore::sdkMin(extents->minY, posY); - extents->maxX = simCore::sdkMax(extents->maxX, posX); - extents->maxY = simCore::sdkMax(extents->maxY, posY); -} - -bool Copy6Extents(const PosXPosYExtents* copyFrom, PosXPosYExtents* copyTo) -{ - if ((copyFrom == NULL) || (copyTo == NULL)) - return false; - - FaceIndexType faceIndex; - for (faceIndex = 0; faceIndex < 6; ++faceIndex) - copyTo[faceIndex].SetAll(copyFrom[faceIndex]); - - return true; -} - -bool AnyOverlap(const PosXPosYExtents& extA, const PosXPosYExtents& extB) -{ - if ((extA.Valid() == false) || (extB.Valid() == false)) - return false; - - // checks for no x overlap - if ((extA.minX > extB.maxX) || - (extA.maxX < extB.minX)) - return false; - - // checks for no y overlap - if ((extA.minY > extB.maxY) || - (extA.maxY < extB.minY)) - return false; - - return true; -} - -bool AnyOverlap(const QsPosType& posX, const QsPosType& posY, const PosXPosYExtents& extents) -{ - if (extents.Valid() == false) - return false; - - return ((posX < extents.minX) || - (posX > extents.maxX) || - (posY < extents.minY) || - (posY > extents.maxY)) ? false : true; -} - } diff --git a/SDK/simVis/DB/QSPosXYExtents.h b/SDK/simVis/DB/QSPosXYExtents.h index e00f32be3..4e56faab0 100644 --- a/SDK/simVis/DB/QSPosXYExtents.h +++ b/SDK/simVis/DB/QSPosXYExtents.h @@ -20,19 +20,21 @@ * */ -#ifndef QS_POSXY_EXTENTS_H -#define QS_POSXY_EXTENTS_H +#ifndef SIMVIS_DB_POSXYEXTENTS_H +#define SIMVIS_DB_POSXYEXTENTS_H + +#include "simCore/Common/Common.h" namespace simVis_db { typedef uint64_t QsPosType; -#if defined Linux || defined Solaris - static const QsPosType gQsMaxLength = 4294967296LL; +#ifndef WIN32 + static const QsPosType QS_MAX_LENGTH_UINT64 = 4294967296LL; #else - static const QsPosType gQsMaxLength = 4294967296; + static const QsPosType QS_MAX_LENGTH_UINT64 = 4294967296; #endif - static const double gQsDMaxLength = 4294967296.0; + static const double QS_MAX_LENGTH_DOUBLE = 4294967296.0; /** A bounding rectangle of x/y extents */ struct PosXPosYExtents @@ -42,24 +44,21 @@ namespace simVis_db QsPosType minY; QsPosType maxY; - PosXPosYExtents(QsPosType minX=gQsMaxLength, QsPosType maxX=0, QsPosType minY=gQsMaxLength, QsPosType maxY=0); + PosXPosYExtents(QsPosType minX=QS_MAX_LENGTH_UINT64, QsPosType maxX=0, QsPosType minY=QS_MAX_LENGTH_UINT64, QsPosType maxY=0); /** Sets up invalid extents */ - void Initialize(); + void initialize(); /** Confirms validity of extents */ - bool Valid() const; + bool isValid() const; /** Sets the extents */ - void SetAll(const PosXPosYExtents& given); - void SetAll(const QsPosType& minX, const QsPosType& maxX, const QsPosType& minY, const QsPosType& maxY); + void setAll(const PosXPosYExtents& given); + void setAll(const QsPosType& minX, const QsPosType& maxX, const QsPosType& minY, const QsPosType& maxY); /** Packs/unpacks the extents into or from a buffer */ - void Pack(uint8_t*) const; - void UnPack(const uint8_t*); - - /** Prints the extents to the console */ - void Print(); + void pack(uint8_t*) const; + void unpack(const uint8_t*); }; //===================================================================================== @@ -67,19 +66,6 @@ namespace simVis_db bool operator==(const PosXPosYExtents& a, const PosXPosYExtents& b); bool operator!=(const PosXPosYExtents& a, const PosXPosYExtents& b); - //===================================================================================== - /** Updates extents such that the given x/y is within the extents */ - void UpdateExtents(const QsPosType& posX, const QsPosType& posY, PosXPosYExtents* extents); - - /** Copies an array of 6 extents */ - bool Copy6Extents(const PosXPosYExtents*, PosXPosYExtents*); - - /** Checks for any overlap between two rectangles */ - bool AnyOverlap(const PosXPosYExtents&, const PosXPosYExtents&); - - /** Checks if the given x/y is within the given extents */ - bool AnyOverlap(const QsPosType& posX, const QsPosType& posY, const PosXPosYExtents&); - } // Namespace simVis_db -#endif /* QS_POSXY_EXTENTS_H */ +#endif /* SIMVIS_DB_POSXYEXTENTS_H */ diff --git a/SDK/simVis/DB/RasterCommon.h b/SDK/simVis/DB/RasterCommon.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp b/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp index b6a26cc5b..3fd642dd3 100644 --- a/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp +++ b/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp @@ -19,10 +19,9 @@ * disclose, or release this software. * */ - #include #include -#include "simCore/Time/Utils.h" +#include "simCore/Time/TimeClass.h" #include "swapbytes.h" #include "QSCommon.h" #include "SQLiteDataBaseReadUtil.h" @@ -33,7 +32,7 @@ namespace { //===================================================================================== template - void UnPackArray(SomeClass* givenArray, const uint8_t* givenBuffer, const uint32_t& numElements) + void unpackArray(SomeClass* givenArray, const uint8_t* givenBuffer, const uint32_t& numElements) { if ((givenArray == NULL) || (givenBuffer == NULL)) return; @@ -43,7 +42,7 @@ namespace for (i = 0; i < numElements; ++i) { memcpy(tmpBuffer, givenBuffer + (sizeof(SomeClass) * i), sizeof(SomeClass)); - givenArray[i].UnPack(tmpBuffer); + givenArray[i].unpack(tmpBuffer); } } @@ -111,7 +110,7 @@ SQLiteDataBaseReadUtil::SQLiteDataBaseReadUtil() tsInsertSetIdTimeValue_(11) { QSNodeId nodeID; - sizeOfIdBlob_ = sizeof(FaceIndexType) + nodeID.SizeOf(); + sizeOfIdBlob_ = sizeof(FaceIndexType) + nodeID.sizeOf(); // Creates the command for reading an image from a "texture set" table textureSetSelectFileCommand1_ = "SELECT * From \""; @@ -133,7 +132,7 @@ SQLiteDataBaseReadUtil::~SQLiteDataBaseReadUtil() } //------------------------------------------------------------------------------------- -QsErrorType SQLiteDataBaseReadUtil::OpenDataBaseFile(const std::string& dbFileName, +QsErrorType SQLiteDataBaseReadUtil::openDatabaseFile(const std::string& dbFileName, sqlite3** sqlite3Db, const int& flags) const { @@ -147,7 +146,7 @@ QsErrorType SQLiteDataBaseReadUtil::OpenDataBaseFile(const std::string& dbFileNa if ((errorCode == SQLITE_BUSY) || (errorCode == SQLITE_LOCKED)) return QS_IS_BUSY; - std::cerr << "OpenDataBaseFile sqlite3_open_v2 Error: " << dbFileName << "\n" << printExtendedErrorMessage(*sqlite3Db); + std::cerr << "openDatabaseFile sqlite3_open_v2 Error: " << dbFileName << "\n" << printExtendedErrorMessage(*sqlite3Db); return QS_IS_UNABLE_TO_OPEN_DB; } if (sqlite3_exec(*sqlite3Db, "PRAGMA CACHE_SIZE=100;", NULL, NULL, NULL) != SQLITE_OK) @@ -160,7 +159,7 @@ QsErrorType SQLiteDataBaseReadUtil::OpenDataBaseFile(const std::string& dbFileNa } //------------------------------------------------------------------------------------- -QsErrorType SQLiteDataBaseReadUtil::TsReadDataBuffer(sqlite3* sqlite3Db, +QsErrorType SQLiteDataBaseReadUtil::readDataBuffer(sqlite3* sqlite3Db, const std::string& dbFileName, const std::string& dataTableName, const FaceIndexType& faceIndex, @@ -189,7 +188,7 @@ QsErrorType SQLiteDataBaseReadUtil::TsReadDataBuffer(sqlite3* sqlite3Db, if (allowLocalDB == false) return QS_IS_DB_NOT_INITIALIZED; localDb = true; - tmpReturnValue = OpenDataBaseFile(dbFileName, &sqlite3Db, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX); + tmpReturnValue = openDatabaseFile(dbFileName, &sqlite3Db, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX); if (tmpReturnValue != QS_IS_OK) return tmpReturnValue; } @@ -206,7 +205,7 @@ QsErrorType SQLiteDataBaseReadUtil::TsReadDataBuffer(sqlite3* sqlite3Db, { if (displayErrorMessage && (returnValue != SQLITE_BUSY && returnValue != SQLITE_LOCKED)) { - std::cerr << "TsReadDataBuffer sqlite3_prepare_v2 Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); + std::cerr << "readDataBuffer sqlite3_prepare_v2 Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); } if (stmt != NULL) sqlite3_finalize(stmt); if (localDb) sqlite3_close(sqlite3Db); @@ -218,12 +217,12 @@ QsErrorType SQLiteDataBaseReadUtil::TsReadDataBuffer(sqlite3* sqlite3Db, // binds id uint8_t* idBlob = new uint8_t[sizeOfIdBlob_]; - bewrite(idBlob, &faceIndex); - nodeID.Pack(idBlob + sizeof(FaceIndexType)); + beWrite(idBlob, &faceIndex); + nodeID.pack(idBlob + sizeof(FaceIndexType)); returnValue = sqlite3_bind_blob(stmt, 1, idBlob, sizeOfIdBlob_, SQLITE_TRANSIENT); if (returnValue != SQLITE_OK && displayErrorMessage) { - std::cerr << "TsReadDataBuffer sqlite3_bind_blob Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); + std::cerr << "readDataBuffer sqlite3_bind_blob Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); } delete[] idBlob; @@ -255,8 +254,8 @@ QsErrorType SQLiteDataBaseReadUtil::TsReadDataBuffer(sqlite3* sqlite3Db, { if (displayErrorMessage) { - std::cerr << "TsReadDataBuffer sqlite3_step Error(" << returnValue << "): " << dbFileName << "\n"; - std::cerr << "not done (" << nodeID.FormatAsHex().c_str() << ") " << printExtendedErrorMessage(sqlite3Db); + std::cerr << "readDataBuffer sqlite3_step Error(" << returnValue << "): " << dbFileName << "\n"; + std::cerr << "not done (" << nodeID.formatAsHex().c_str() << ") " << printExtendedErrorMessage(sqlite3Db); } otherReturnValue = QS_IS_UNABLE_TO_READ_DATA_BUFFER; } @@ -267,14 +266,14 @@ QsErrorType SQLiteDataBaseReadUtil::TsReadDataBuffer(sqlite3* sqlite3Db, returnValue = sqlite3_close(sqlite3Db); if (returnValue != SQLITE_OK && displayErrorMessage) { - std::cerr << "TsReadDataBuffer localDb sqlite3_close Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); + std::cerr << "readDataBuffer localDb sqlite3_close Error(" << returnValue << "): " << dbFileName << "\n" << printExtendedErrorMessage(sqlite3Db); } } return otherReturnValue; } //------------------------------------------------------------------------------------- -QsErrorType SQLiteDataBaseReadUtil::TsGetSetFromListOfSetsTable(sqlite3* sqlite3Db, +QsErrorType SQLiteDataBaseReadUtil::getSetFromListOfSetsTable(sqlite3* sqlite3Db, const std::string& tableName, int& rasterFormat, int& pixelLength, @@ -300,7 +299,7 @@ QsErrorType SQLiteDataBaseReadUtil::TsGetSetFromListOfSetsTable(sqlite3* sqlite3 returnValue = sqlite3_prepare_v2(sqlite3Db, textureSetSelectCommand_.c_str(), static_cast(textureSetSelectCommand_.length()), &stmt, NULL); if (returnValue != SQLITE_OK) { - std::cerr << "TsGetSetFromListOfSetsTable sqlite3_prepare_v2 Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); + std::cerr << "getSetFromListOfSetsTable sqlite3_prepare_v2 Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); if (stmt != NULL) sqlite3_finalize(stmt); return QS_IS_PREPARE_ERROR; } @@ -309,14 +308,14 @@ QsErrorType SQLiteDataBaseReadUtil::TsGetSetFromListOfSetsTable(sqlite3* sqlite3 returnValue = sqlite3_bind_text(stmt, 1, tableName.c_str(), int(tableName.length()), SQLITE_TRANSIENT); if (returnValue != SQLITE_OK) { - std::cerr << "TsGetSetFromListOfSetsTable sqlite3_bind_text Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); + std::cerr << "getSetFromListOfSetsTable sqlite3_bind_text Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); } // executes the statement returnValue = sqlite3_step(stmt); if (returnValue > SQLITE_OK&& returnValue < SQLITE_ROW) { - std::cerr << "TsGetSetFromListOfSetsTable sqlite3_step Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); + std::cerr << "getSetFromListOfSetsTable sqlite3_step Error(" << returnValue << ")\n" << printExtendedErrorMessage(sqlite3Db); } if (returnValue == SQLITE_ROW) @@ -326,7 +325,7 @@ QsErrorType SQLiteDataBaseReadUtil::TsGetSetFromListOfSetsTable(sqlite3* sqlite3 pixelLength = sqlite3_column_int(stmt, tsInsertSetIdPixelLength_ - 1); shallowLevel = sqlite3_column_int(stmt, tsInsertSetIdShallowestLevel_ - 1); deepLevel = sqlite3_column_int(stmt, tsInsertSetIdDeepestLevel_ - 1); - UnPackArray(tmpExtents, (const uint8_t*)sqlite3_column_blob(stmt, tsInsertSetIdExtents_ - 1), 6); + unpackArray(tmpExtents, (const uint8_t*)sqlite3_column_blob(stmt, tsInsertSetIdExtents_ - 1), 6); source = (const char*)sqlite3_column_text(stmt, tsInsertSetIdSource_ - 1); classification = (const char*)sqlite3_column_text(stmt, tsInsertSetIdClassification_ - 1); description = (const char*)sqlite3_column_text(stmt, tsInsertSetIdDescription_ - 1); @@ -340,9 +339,9 @@ QsErrorType SQLiteDataBaseReadUtil::TsGetSetFromListOfSetsTable(sqlite3* sqlite3 int frac = 0; // read TimeStamp data members from buffer - beread(buffer, &refYear); - beread(buffer + sizeof(refYear), &(secs)); - beread(buffer + sizeof(refYear) + sizeof(secs), &(frac)); + beRead(buffer, &refYear); + beRead(buffer + sizeof(refYear), &(secs)); + beRead(buffer + sizeof(refYear) + sizeof(secs), &(frac)); simCore::Seconds secsSinceRefYear(secs, frac); timeStamp.setTime(refYear, secsSinceRefYear); } diff --git a/SDK/simVis/DB/SQLiteDataBaseReadUtil.h b/SDK/simVis/DB/SQLiteDataBaseReadUtil.h index db708e850..90a05ef92 100644 --- a/SDK/simVis/DB/SQLiteDataBaseReadUtil.h +++ b/SDK/simVis/DB/SQLiteDataBaseReadUtil.h @@ -20,34 +20,17 @@ * */ -#ifndef SQLITE_DATABASE_READ_UTIL_H -#define SQLITE_DATABASE_READ_UTIL_H +#ifndef SIMVIS_DB_SQLITEDATABASEREADUTIL_H +#define SIMVIS_DB_SQLITEDATABASEREADUTIL_H #include #include "sqlite3.h" -#include "simCore/Time/TimeClass.h" #include "QSCommon.h" #include "QSError.h" #include "QSNodeID96.h" #include "QSPosXYExtents.h" -// Temporary defines until we update sqlite -#ifndef SQLITE_OPEN_READONLY -#define SQLITE_OPEN_READONLY 0x00000001 -#define SQLITE_OPEN_READWRITE 0x00000002 -#define SQLITE_OPEN_CREATE 0x00000004 -#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 -#define SQLITE_OPEN_EXCLUSIVE 0x00000010 -#define SQLITE_OPEN_MAIN_DB 0x00000100 -#define SQLITE_OPEN_TEMP_DB 0x00000200 -#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 -#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 -#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 -#define SQLITE_OPEN_SUBJOURNAL 0x00002000 -#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 -#define SQLITE_OPEN_NOMUTEX 0x00008000 -#define SQLITE_OPEN_FULLMUTEX 0x00010000 -#endif /* SQLITE_OPEN_READONLY */ +namespace simCore { class TimeStamp; } namespace simVis_db { @@ -55,19 +38,8 @@ namespace simVis_db //===================================================================================== static const char* QS_DEFAULT_SET_TABLE_NAME = "default"; - static const char* SPLITTER_STRING_OUTPUTDB = "dbFile"; - static const char* SIMQS_CONFIG_TABLENAME_KEYWORD = "tableName"; static const char* QS_LIST_OF_TEXTURE_SETS_TABLE_NAME = "ListOfTextureSets"; static const char* QS_TSO_NAME_OF_TEXTURE_SET_TABLE = "nt"; - static const char* QS_TSO_OUTPUT_TYPE = "ot"; - static const char* QS_TSO_PIXEL_LENGTH = "pl"; - static const char* QS_TSO_SHALLOWEST_LEVEL = "sl"; - static const char* QS_TSO_DEEPEST_LEVEL = "dl"; - static const char* QS_TSO_EXTENTS = "ex"; - static const char* QS_TSO_SOURCE = "s"; - static const char* QS_TSO_CLASSIFICATION = "c"; - static const char* QS_TSO_DESCRIPTION = "ds"; - static const char* QS_TSO_TIME_SPECIFIED = "ts"; //===================================================================================== class SQLiteDataBaseReadUtil @@ -77,7 +49,7 @@ namespace simVis_db virtual ~SQLiteDataBaseReadUtil(); /** Opens a database file */ - QsErrorType OpenDataBaseFile(const std::string& dbFileName, + QsErrorType openDatabaseFile(const std::string& dbFileName, sqlite3** sqlite3Db, const int& flags) const; @@ -98,7 +70,7 @@ namespace simVis_db * @param[out] timeStamp Loads a time value, if there is a valid timeStamp on the file * @return Returns 0 on success, otherwise returns an error value mapped to QsErrorType. */ - QsErrorType TsGetSetFromListOfSetsTable(sqlite3* sqlite3Db, + QsErrorType getSetFromListOfSetsTable(sqlite3* sqlite3Db, const std::string& tableName, int& rasterFormat, int& pixelLength, @@ -125,7 +97,7 @@ namespace simVis_db * @param[in] displayErrorMessage Determines whether to display error messages to console when failing * @return An error value, mapped to QsErrorType */ - QsErrorType TsReadDataBuffer(sqlite3* sqlite3Db, + QsErrorType readDataBuffer(sqlite3* sqlite3Db, const std::string& dbFileName, const std::string& dataTableName, const FaceIndexType& faceIndex, @@ -159,4 +131,4 @@ namespace simVis_db } // namespace simVis_db -#endif /* SQLITE_DATABASE_READ_UTIL_H */ +#endif /* SIMVIS_DB_SQLITEDATABASEREADUTIL_H */ diff --git a/SDK/simVis/DB/swapbytes.h b/SDK/simVis/DB/swapbytes.h index af6fe9b74..8992437d5 100644 --- a/SDK/simVis/DB/swapbytes.h +++ b/SDK/simVis/DB/swapbytes.h @@ -23,757 +23,103 @@ #define SIMVIS_DB_SWAPBYTES_H #include -#include -#include -#include +#include #include "simCore/Common/Common.h" +// Try to guess endianness #if !defined(SIM_LITTLE_ENDIAN) && !defined(SIM_BIG_ENDIAN) #if defined(X86) || defined(ALPHA) || defined(__x86_64__) || defined(_WIN64) || defined(WIN32) #define SIM_LITTLE_ENDIAN #endif #endif -#ifndef BYTESWAPSHIFT - namespace simVis_db { template inline - void swap_bytes(T *const value, const size_t nItems = 1) + void swapBytes(T *const value, const size_t nItems = 1) { - // using namespace std; for (size_t i = 0; i < nItems; ++i) { char *ptr = (char*)&value[i]; // Treat value as an array of bytes - size_t size = sizeof(T); - size_t halfSize = size >> 1; - size_t end = size - 1; + const size_t size = sizeof(T); + const size_t halfSize = size >> 1; + const size_t end = size - 1; for (size_t i = 0; i < halfSize; ++i) std::swap(ptr[end - i], ptr[i]); } } - template - inline - T swap_bytes_return(const T &value, const size_t nItems = 1) - { - T temp = value; - swap_bytes(&temp); - return temp; - } - #ifdef SIM_LITTLE_ENDIAN template inline - void make_little_endian_(T *const value) - { - } - - template - inline - void make_big_endian_(T *const value) + void makeBigEndianImpl(T *const value) { - swap_bytes(value); + swapBytes(value); } #else template inline - void make_little_endian_(T *const value) - { - swap_bytes(value); - } - - template - inline - void make_big_endian_(T *const value) + void makeBigEndianImpl(T *const value) { } #endif inline - void make_big_endian(char *const val) { make_big_endian_(val); } - inline - void make_big_endian(int8_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(uint8_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(int16_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(uint16_t *const val) { make_big_endian_(val); } + void makeBigEndian(char *const val) { makeBigEndianImpl(val); } inline - void make_big_endian(int32_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(uint32_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(int64_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(uint64_t *const val) { make_big_endian_(val); } - inline - void make_big_endian(float *const val) { make_big_endian_(val); } - inline - void make_big_endian(double *const val) { make_big_endian_(val); } - - inline - void make_little_endian(char *const val) { make_little_endian_(val); } - inline - void make_little_endian(int8_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(uint8_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(int16_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(uint16_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(int32_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(uint32_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(int64_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(uint64_t *const val) { make_little_endian_(val); } - inline - void make_little_endian(float *const val) { make_little_endian_(val); } - inline - void make_little_endian(double *const val) { make_little_endian_(val); } - - template + void makeBigEndian(int8_t *const val) { makeBigEndianImpl(val); } inline - void make_big_endian(T *const value, const size_t nItems) - { - for (size_t i = 0; i < nItems; ++i) - { - make_big_endian(&value[i]); - } - } - - template + void makeBigEndian(uint8_t *const val) { makeBigEndianImpl(val); } inline - void make_little_endian(T *const value, const size_t nItems) - { - for (size_t i = 0; i < nItems; ++i) - { - make_little_endian(&value[i]); - } - } - - template + void makeBigEndian(int16_t *const val) { makeBigEndianImpl(val); } inline - size_t beread(FILE *stream, T *const val, const size_t nItems = 1) - { - size_t nItemsRead = fread(val, sizeof(T), nItems, stream); - make_big_endian(val, nItemsRead); - return nItemsRead; - } - - template + void makeBigEndian(uint16_t *const val) { makeBigEndianImpl(val); } inline - size_t bewrite(FILE *stream, const T *const val, const size_t nItems = 1) - { - size_t nItemsWrote = 0; - for (size_t i = 0; i < nItems; ++i) - { - T temp = val[i]; - make_big_endian(&temp); - if (fwrite(&temp, sizeof(T), 1, stream) != 1) - break; - ++nItemsWrote; - } - return nItemsWrote; - } - - template + void makeBigEndian(int32_t *const val) { makeBigEndianImpl(val); } inline - size_t leread(FILE *stream, T *const val, const size_t nItems = 1) - { - size_t nItemsRead = fread(val, sizeof(T), nItems, stream); - make_little_endian(val, nItemsRead); - return nItemsRead; - } - - template + void makeBigEndian(uint32_t *const val) { makeBigEndianImpl(val); } inline - size_t lewrite(FILE *stream, const T *const val, const size_t nItems = 1) - { - size_t nItemsWrote = 0; - for (size_t i = 0; i < nItems; ++i) - { - T temp = val[i]; - make_little_endian(&temp); - if (fwrite(&temp, sizeof(T), 1, stream) != 1) - break; - ++nItemsWrote; - } - return nItemsWrote; - } - - template + void makeBigEndian(int64_t *const val) { makeBigEndianImpl(val); } inline - size_t beread(std::istream &stream, T *const val, const std::streamsize nItems = 1) - { - stream.read((char *)val, nItems * sizeof(T)); - size_t nItemsRead = stream.gcount() / sizeof(T); - make_big_endian(val, nItemsRead); - return nItemsRead; - } - - template + void makeBigEndian(uint64_t *const val) { makeBigEndianImpl(val); } inline - size_t bewrite(std::ostream &stream, const T *const val, const size_t nItems = 1) - { - size_t nItemsWrote = 0; - for (size_t i = 0; i < nItems; ++i) - { - T temp = val[i]; - make_big_endian(&temp); - stream.write((const char *)&temp, sizeof(T)); - if (stream.bad()) - break; - ++nItemsWrote; - } - return nItemsWrote; - } - - template + void makeBigEndian(float *const val) { makeBigEndianImpl(val); } inline - size_t leread(std::istream &stream, T *const val, const size_t nItems = 1) - { - stream.read((char *)val, nItems * sizeof(T)); - size_t nItemsRead = stream.gcount() / sizeof(T); - make_little_endian(val, nItemsRead); - return nItemsRead; - } + void makeBigEndian(double *const val) { makeBigEndianImpl(val); } template inline - size_t lewrite(std::ostream &stream, const T *const val, const size_t nItems = 1) + void makeBigEndian(T *const value, const size_t nItems) { - size_t nItemsWrote = 0; for (size_t i = 0; i < nItems; ++i) { - T temp = val[i]; - make_little_endian(&temp); - stream.write((const char *)&temp, sizeof(T)); - if (stream.bad()) - break; - ++nItemsWrote; + makeBigEndian(&value[i]); } - return nItemsWrote; } template inline - size_t beread(const void *const stream, T *const val, const size_t nItems = 1) + size_t beRead(const void *const stream, T *const val, const size_t nItems = 1) { memcpy(val, stream, nItems * sizeof(T)); - make_big_endian(val, nItems); + makeBigEndian(val, nItems); return nItems; } template inline - size_t bewrite(void *const stream, const T *const val, const size_t nItems = 1) - { - memcpy(stream, val, nItems * sizeof(T)); - make_big_endian((T *)stream, nItems); - return nItems; - } - - template - inline - size_t leread(const void *const stream, T *const val, const size_t nItems = 1) - { - memcpy(val, stream, nItems * sizeof(T)); - make_little_endian(val, nItems); - return nItems; - } - - template - inline - size_t lewrite(void *const stream, const T *const val, const size_t nItems = 1) - { - memcpy(stream, val, nItems * sizeof(T)); - make_little_endian((T *)stream, nItems); - return nItems; - } - -#else - -// Swap macros. -#define SWAP16(val)((((val)>>8)&0xff)|(((val)<<8)&0xff00)) -#define SWAP32(val)((((val)>>24)&0xff)|(((val)>>8)&0xff00)|(((val)<<8)&0xff0000)|(((val)<<24)&0xff000000)) -#ifdef __GNUC__ -#define SWAP64(val)((((val)>>56)&0xffLL)|(((val)>>40)&0xff00LL)|(((val)>>24)&0xff0000LL)|(((val)>>8)&0xff000000LL)| \ - (((val)<<8)&0xff00000000LL)|(((val)<<24)&0xff0000000000LL)|(((val)<<40)&0xff000000000000LL)|(((val)<<56)&0xff00000000000000LL)) -#else -#define SWAP64(val)((((val)>>56)&0xffL)|(((val)>>40)&0xff00L)|(((val)>>24)&0xff0000L)|(((val)>>8)&0xff000000L)| \ - (((val)<<8)&0xff00000000L)|(((val)<<24)&0xff0000000000L)|(((val)<<40)&0xff000000000000L)|(((val)<<56)&0xff00000000000000L)) -#endif - - // Generic byte swapping routines. - template inline void swap_bytes(T *const value) - { - char *ptr=(char*)(void*)value; // Treat value as an array of bytes - size_t size = sizeof(T); - register size_t halfSize = size >> 1; - register size_t end = size - 1; - for (register size_t i = 0; i < halfSize; ++i) - std::swap(ptr[end - i], ptr[i]); - } - - template inline void swap_bytes(T *const value, register const size_t nItems) - { - for (register size_t i=0;i> 1; - register size_t end = size - 1; - for (register size_t i = 0; i < halfSize; ++i) - std::swap(ptr[end - i], ptr[i]); - } - } - - - // Specialized routines. - - // NULL routines. - template<> inline void swap_bytes(char *const value) {} - template<> inline void swap_bytes(char *const value, register const size_t nItems) {} - template<> inline void swap_bytes(int8_t *const value) {} - template<> inline void swap_bytes(uint8_t *const value) {} - template<> inline void swap_bytes(int8_t *const value, register const size_t nItems) {} - template<> inline void swap_bytes(uint8_t *const value, register const size_t nItems) {} - - // Single item routines. - template<> inline void swap_bytes(int16_t *const value) { *value=SWAP16(*value); } - template<> inline void swap_bytes(uint16_t *const value) { *value=SWAP16(*value); } - template<> inline void swap_bytes(int32_t *const value) { *value=SWAP32(*value); } - template<> inline void swap_bytes(uint32_t *const value) { *value=SWAP32(*value); } - template<> inline void swap_bytes(int64_t *const value) { *value=SWAP64(*value); } - template<> inline void swap_bytes(uint64_t *const value) { *value=SWAP64(*value); } - - template<> inline void swap_bytes(float *const value) - { - int32_t *const pseudo=(int32_t*)(void*)value; - *pseudo=SWAP32(*pseudo); - } - - template<> inline void swap_bytes(double *const value) - { - int64_t *const pseudo=(int64_t*)(void*)value; - *pseudo=SWAP64(*pseudo); - } - - #ifdef SIM_LITTLE_ENDIAN - template inline void make_little_endian(T *const value) {} - - // Generic swap. Has a '_' prefix to prevent it from accidently being used with structs, etc. - template inline void make_little_endian_(T *const value) {} - template inline void make_big_endian_(T *const value) { swap_bytes(value); } - - inline void make_big_endian(char *const value) {} - inline void make_big_endian(int8_t *const value) {} - inline void make_big_endian(uint8_t *const value) {} - inline void make_big_endian(int16_t *const value) { *value=SWAP16(*value); } - inline void make_big_endian(uint16_t *const value) { *value=SWAP16(*value); } - inline void make_big_endian(int32_t *const value) { *value=SWAP32(*value); } - inline void make_big_endian(uint32_t *const value) { *value=SWAP32(*value); } - inline void make_big_endian(int64_t *const value) { *value=SWAP64(*value); } - inline void make_big_endian(uint64_t *const value) { *value=SWAP64(*value); } - - inline void make_big_endian(float *const value) - { - int32_t *const pseudo=(int32_t*)(void*)value; - *pseudo=SWAP32(*pseudo); - } - - inline void make_big_endian(double *const value) - { - int64_t *const pseudo=(int64_t*)(void*)value; - *pseudo=SWAP64(*pseudo); - } -#else - template inline void make_big_endian(T *const value) {} - template inline void make_big_endian_(T *const value) {} - template inline void make_little_endian_(T *const value) { swap_bytes(value); } - - inline void make_little_endian(char *const value) {} - inline void make_little_endian(int8_t *const value) {} - inline void make_little_endian(uint8_t *const value) {} - inline void make_little_endian(int16_t *const value) { *value=SWAP16(*value); } - inline void make_little_endian(uint16_t *const value) { *value=SWAP16(*value); } - inline void make_little_endian(int32_t *const value) { *value=SWAP32(*value); } - inline void make_little_endian(uint32_t *const value) { *value=SWAP32(*value); } - inline void make_little_endian(int64_t *const value) { *value=SWAP64(*value); } - inline void make_little_endian(uint64_t *const value) { *value=SWAP64(*value); } - - inline void make_little_endian(float *const value) - { - int32_t *const pseudo=(int32_t*)(void*)value; - *pseudo=SWAP32(*pseudo); - } - - inline void make_little_endian(double *const value) - { - int64_t *const pseudo=(int64_t*)(void*)value; - *pseudo=SWAP64(*pseudo); - } -#endif - - // Multi item routines. - template<> inline void swap_bytes(int16_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); - } - - template<> inline void swap_bytes(uint16_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); - } - - template<> inline void swap_bytes(int32_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); - } - - template<> inline void swap_bytes(uint32_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); - } - - template<> inline void swap_bytes(int64_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); - } - - template<> inline void swap_bytes(uint64_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); - } - - template<> inline void swap_bytes(float *const value, register const size_t nItems) - { - int32_t *const pseudo=(int32_t*)(void*)value; - for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP32(pseudo[i]); - } - - template<> inline void swap_bytes(double *const value, register const size_t nItems) - { - int64_t *const pseudo=(int64_t*)(void*)value; - for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP64(pseudo[i]); - } - -#ifdef SIM_LITTLE_ENDIAN - template inline void make_little_endian(T *const value, register const size_t nItems) {} - template inline void make_little_endian_(T *const value, register const size_t nItems) {} - template inline void make_big_endian_(T *const value, register const size_t nItems) { swap_bytes(value, nItems); } - - inline void make_big_endian(char *const value, register const size_t nItems) {} - inline void make_big_endian(int8_t *const value, register const size_t nItems) {} - inline void make_big_endian(uint8_t *const value, register const size_t nItems) {} - - inline void make_big_endian(int16_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); - } - - inline void make_big_endian(uint16_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); - } - - inline void make_big_endian(int32_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); - } - - inline void make_big_endian(uint32_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); - } - - inline void make_big_endian(int64_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); - } - - inline void make_big_endian(uint64_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); - } - - inline void make_big_endian(float *const value, register const size_t nItems) - { - int32_t *const pseudo = (int32_t*)(void*)value; - for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP32(pseudo[i]); - } - - inline void make_big_endian(double *const value, register const size_t nItems) - { - int64_t *const pseudo = (int64_t*)(void*)value; - for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP64(pseudo[i]); - } -#else - template inline void make_big_endian(T *const value, register const size_t nItems) {} - template inline void make_big_endian_(T *const value, register const size_t nItems) {} - template inline void make_little_endian_(T *const value, register const size_t nItems) { swap_bytes(value, nItems); } - - inline void make_little_endian(char *const value, register const size_t nItems) {} - inline void make_little_endian(int8_t *const value, register const size_t nItems) {} - inline void make_little_endian(uint8_t *const value, register const size_t nItems) {} - - inline void make_little_endian(int16_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); - } - - inline void make_little_endian(uint16_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP16(value[i]); - } - - inline void make_little_endian(int32_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); - } - - inline void make_little_endian(uint32_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP32(value[i]); - } - - inline void make_little_endian(int64_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); - } - - inline void make_little_endian(uint64_t *const value, register const size_t nItems) - { - for (register size_t i = 0; i < nItems; ++i) value[i] = SWAP64(value[i]); - } - - inline void make_little_endian(float *const value, register const size_t nItems) - { - int32_t *const pseudo = (int32_t*)(void*)value; - for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP32(pseudo[i]); - } - - inline void make_little_endian(double *const value, register const size_t nItems) - { - int64_t *const pseudo = (int64_t*)(void*)value; - for (register size_t i = 0; i < nItems; ++i) pseudo[i] = SWAP64(pseudo[i]); - } - #endif - - - // Swapped I\O - template inline size_t beread(FILE *stream, T *const val) - { - size_t nItemsRead = fread(val, sizeof(T), 1, stream); - make_big_endian(val); - return nItemsRead; - } - - template inline size_t beread(FILE *stream, T *const val, register const size_t nItems) - { - size_t nItemsRead = fread(val, sizeof(T), nItems, stream); - make_big_endian(val, nItemsRead); - return nItemsRead; - } - - template inline size_t bewrite(FILE *stream, const T *const val) - { - T temp = *val; - make_big_endian(&temp); - return fwrite(&temp, sizeof(T), 1, stream); - } - - template inline size_t bewrite(FILE *stream, const T *const val, register const size_t nItems) - { - register size_t nItemsWrit = 0; - while (nItemsWrit < nItems) - { - T temp = val[nItemsWrit++]; - make_big_endian(&temp); - if (fwrite(&temp, sizeof(T), 1, stream)!=1) - break; - } - return nItemsWrit; - } - - template inline size_t leread(FILE *stream, T *const val) - { - size_t nItemsRead = fread(val, sizeof(T), 1, stream); - make_little_endian(val); - return nItemsRead; - } - - template inline size_t leread(FILE *stream, T *const val, register const size_t nItems) - { - size_t nItemsRead = fread(val, sizeof(T), nItems, stream); - make_little_endian(val, nItemsRead); - return nItemsRead; - } - - template inline size_t lewrite(FILE *stream, const T *const val) - { - T temp = *val; - make_little_endian(&temp); - return fwrite(&temp, sizeof(T), 1, stream); - } - - template inline size_t lewrite(FILE *stream, const T *const val, register const size_t nItems) - { - register size_t nItemsWrit = 0; - while (nItemsWrit < nItems) - { - T temp = val[nItemsWrit++]; - make_little_endian(&temp); - if (fwrite(&temp, sizeof(T), 1, stream) != 1) - break; - } - return nItemsWrit; - } - - template inline size_t beread(std::istream &stream, T *const val) - { - stream.read((char *)val, sizeof(T)); - size_t nItemsRead = stream.gcount() / sizeof(T); - make_big_endian(val); - return nItemsRead; - } - - template inline size_t beread(std::istream &stream, T *const val, register const size_t nItems) - { - stream.read((char *)val, nItems * sizeof(T)); - size_t nItemsRead = stream.gcount() / sizeof(T); - make_big_endian(val, nItemsRead); - return nItemsRead; - } - - template inline size_t bewrite(std::ostream &stream, const T *const val) - { - T temp = *val; - make_big_endian(&temp); - stream.write((const char *)&temp, sizeof(T)); - return (stream.bad()) ? 0 : 1; - } - - template inline size_t bewrite(std::ostream &stream, const T *const val, register const size_t nItems) - { - register size_t nItemsWrit = 0; - while (nItemsWrit < nItems) - { - T temp = val[nItemsWrit++]; - make_big_endian(&temp); - stream.write((const char *)&temp, sizeof(T)); - if (stream.bad()) - break; - } - return nItemsWrit; - } - - template inline size_t leread(std::istream &stream, T *const val) - { - stream.read((char *)val, sizeof(T)); - size_t nItemsRead = stream.gcount()/sizeof(T); - make_little_endian(val); - return nItemsRead; - } - - template inline size_t leread(std::istream &stream, T *const val, register const size_t nItems) - { - stream.read((char *)val, nItems * sizeof(T)); - size_t nItemsRead = stream.gcount() / sizeof(T); - make_little_endian(val, nItemsRead); - return nItemsRead; - } - - template inline size_t lewrite(std::ostream &stream, const T *const val) - { - T temp = *val; - make_little_endian(&temp); - stream.write((const char *)&temp, sizeof(T)); - return (stream.bad()) ? 0 : 1; - } - - template inline size_t lewrite(std::ostream &stream, const T *const val, register const size_t nItems) - { - size_t nItemsWrit = 0; - while (nItemsWrit < nItems) - { - T temp = val[nItemsWrit++]; - make_little_endian(&temp); - stream.write((const char *)&temp, sizeof(T)); - if (stream.bad()) - break; - } - return nItemsWrit; - } - - template inline size_t beread(const void *const stream, T *const val) - { - memcpy(val, stream, sizeof(T)); - make_big_endian(val); - return 1; - } - - template inline size_t beread(const void *const stream, T *const val, register const size_t nItems) - { - memcpy(val, stream, nItems * sizeof(T)); - make_big_endian(val, nItems); - return nItems; - } - - template inline size_t bewrite(void *const stream, const T *const val) - { - memcpy(stream, val, sizeof(T)); - make_big_endian((T *)stream); - return 1; - } - - template inline size_t bewrite(void *const stream, const T *const val, register const size_t nItems) + size_t beWrite(void *const stream, const T *const val, const size_t nItems = 1) { memcpy(stream, val, nItems * sizeof(T)); - make_big_endian((T *)stream, nItems); - return nItems; - } - - template inline size_t leread(const void *const stream, T *const val) - { - memcpy(val, stream, sizeof(T)); - make_little_endian(val); - return 1; - } - - template inline size_t leread(const void *const stream, T *const val, register const size_t nItems) - { - memcpy(val, stream, nItems * sizeof(T)); - make_little_endian(val, nItems); + makeBigEndian((T *)stream, nItems); return nItems; } - template inline size_t lewrite(void *const stream, const T *const val) - { - memcpy(stream, val, sizeof(T)); - make_little_endian((T *)stream); - return 1; - } - - template inline size_t lewrite(void *const stream, const T *const val, register const size_t nItems) - { - memcpy(stream, val, nItems * sizeof(T)); - make_little_endian((T *)stream, nItems); - return nItems; - } - -#endif - } // namespace simVis_db #endif /* SIMVIS_DB_SWAPBYTES_H */ diff --git a/SDK/simVis/DBFormat.cpp b/SDK/simVis/DBFormat.cpp index 77fd7237b..79ff5feb2 100644 --- a/SDK/simVis/DBFormat.cpp +++ b/SDK/simVis/DBFormat.cpp @@ -23,6 +23,8 @@ #include "osgEarth/Cube" #include "osgEarth/ImageToHeightFieldConverter" #include "simCore/Calc/Math.h" +#include "simCore/Time/TimeClass.h" +#include "simVis/DBOptions.h" #include "simVis/DBFormat.h" #include "simVis/DB/QSCommon.h" #include "simVis/DB/swapbytes.h" @@ -93,8 +95,8 @@ namespace osgEarth::Contrib::CubeUtils::cubeToFace(xMin, yMin, xMax, yMax, face); - out_fmin.set(xMin * gQsDMaxLength, yMin * gQsDMaxLength); - out_fmax.set(xMax * gQsDMaxLength, yMax * gQsDMaxLength); + out_fmin.set(xMin * QS_MAX_LENGTH_DOUBLE, yMin * QS_MAX_LENGTH_DOUBLE); + out_fmax.set(xMax * QS_MAX_LENGTH_DOUBLE, yMax * QS_MAX_LENGTH_DOUBLE); return true; } @@ -162,7 +164,7 @@ namespace std::copy(buf.begin(), buf.end(), data); // Be sure to cast here to get the right swap function: - make_big_endian((T*)data, size * size); + makeBigEndian((T*)data, size * size); outImage = new osg::Image(); outImage->setImage(size, size, 1, internalFormat, pixelFormat, type, data, osg::Image::USE_NEW_DELETE); @@ -356,7 +358,7 @@ osgEarth::Status DBImageLayer::openImplementation() cx.pathname_ = osgDB::findDataFile(options().url()->full(), getReadOptions()); - if (cx.dbUtil_.OpenDataBaseFile(cx.pathname_, &cx.db_, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) != QS_IS_OK) + if (cx.dbUtil_.openDatabaseFile(cx.pathname_, &cx.db_, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) != simVis_db::QS_IS_OK) { cx.db_ = NULL; return osgEarth::Status( @@ -365,7 +367,7 @@ osgEarth::Status DBImageLayer::openImplementation() } else { - QsErrorType err = cx.dbUtil_.TsGetSetFromListOfSetsTable( + QsErrorType err = cx.dbUtil_.getSetFromListOfSetsTable( cx.db_, "default", cx.rasterFormat_, @@ -385,7 +387,7 @@ osgEarth::Status DBImageLayer::openImplementation() cx.deepLevel_ = simCore::sdkMin(cx.deepLevel_, static_cast(options().deepestLevel().get())); } - if (err != QS_IS_OK) + if (err != simVis_db::QS_IS_OK) { sqlite3_close(cx.db_); cx.db_ = NULL; @@ -407,10 +409,10 @@ osgEarth::Status DBImageLayer::openImplementation() { if (cx.extents_[f].minX < cx.extents_[f].maxX && cx.extents_[f].minY < cx.extents_[f].maxY) { - const double x0 = cx.extents_[f].minX / gQsDMaxLength; - const double x1 = cx.extents_[f].maxX / gQsDMaxLength; - const double y0 = cx.extents_[f].minY / gQsDMaxLength; - const double y1 = cx.extents_[f].maxY / gQsDMaxLength; + const double x0 = cx.extents_[f].minX / QS_MAX_LENGTH_DOUBLE; + const double x1 = cx.extents_[f].maxX / QS_MAX_LENGTH_DOUBLE; + const double y0 = cx.extents_[f].minY / QS_MAX_LENGTH_DOUBLE; + const double y1 = cx.extents_[f].maxY / QS_MAX_LENGTH_DOUBLE; osgEarth::GeoExtent cubeEx(profile->getSRS(), f + x0, y0, f + x1, y1); @@ -468,7 +470,7 @@ osgEarth::GeoImage DBImageLayer::createImageImplementation(const osgEarth::TileK osg::Vec2d tileMax; // Tile extents in QS units convertTileKeyToQsKey(key, faceId, nodeId, tileMin, tileMax); - if (!cx.extents_[faceId].Valid()) + if (!cx.extents_[faceId].isValid()) { // no data on this face? return nothing return osgEarth::GeoImage::INVALID; @@ -485,7 +487,7 @@ osgEarth::GeoImage DBImageLayer::createImageImplementation(const osgEarth::TileK uint32_t bufSize = 0; uint32_t currentRasterSize = 0; - QsErrorType err = cx.dbUtil_.TsReadDataBuffer( + QsErrorType err = cx.dbUtil_.readDataBuffer( cx.db_, cx.pathname_, "default", @@ -496,7 +498,7 @@ osgEarth::GeoImage DBImageLayer::createImageImplementation(const osgEarth::TileK ¤tRasterSize, false, true); // AllowLocalDB: no, we created it ourselves - if (err == QS_IS_OK) + if (err == simVis_db::QS_IS_OK) { if (currentRasterSize > 0) { @@ -558,7 +560,7 @@ osgEarth::GeoImage DBImageLayer::createImageImplementation(const osgEarth::TileK } else { - std::cerr << GetErrorString(err) << std::endl; + std::cerr << simVis_db::getErrorString(err) << std::endl; OE_WARN << "Failed to read image from " << key.str() << std::endl; } @@ -633,7 +635,7 @@ osgEarth::Status DBElevationLayer::openImplementation() cx.pathname_ = osgDB::findDataFile(options().url()->full(), getReadOptions()); - if (cx.dbUtil_.OpenDataBaseFile(cx.pathname_, &cx.db_, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) != QS_IS_OK) + if (cx.dbUtil_.openDatabaseFile(cx.pathname_, &cx.db_, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) != simVis_db::QS_IS_OK) { cx.db_ = NULL; return osgEarth::Status( @@ -642,7 +644,7 @@ osgEarth::Status DBElevationLayer::openImplementation() } else { - QsErrorType err = cx.dbUtil_.TsGetSetFromListOfSetsTable( + QsErrorType err = cx.dbUtil_.getSetFromListOfSetsTable( cx.db_, "default", cx.rasterFormat_, @@ -662,7 +664,7 @@ osgEarth::Status DBElevationLayer::openImplementation() cx.deepLevel_ = simCore::sdkMin(cx.deepLevel_, static_cast(options().deepestLevel().get())); } - if (err != QS_IS_OK) + if (err != simVis_db::QS_IS_OK) { sqlite3_close(cx.db_); cx.db_ = NULL; @@ -684,10 +686,10 @@ osgEarth::Status DBElevationLayer::openImplementation() { if (cx.extents_[f].minX < cx.extents_[f].maxX && cx.extents_[f].minY < cx.extents_[f].maxY) { - const double x0 = cx.extents_[f].minX / gQsDMaxLength; - const double x1 = cx.extents_[f].maxX / gQsDMaxLength; - const double y0 = cx.extents_[f].minY / gQsDMaxLength; - const double y1 = cx.extents_[f].maxY / gQsDMaxLength; + const double x0 = cx.extents_[f].minX / QS_MAX_LENGTH_DOUBLE; + const double x1 = cx.extents_[f].maxX / QS_MAX_LENGTH_DOUBLE; + const double y0 = cx.extents_[f].minY / QS_MAX_LENGTH_DOUBLE; + const double y1 = cx.extents_[f].maxY / QS_MAX_LENGTH_DOUBLE; osgEarth::GeoExtent cubeEx(profile->getSRS(), f + x0, y0, f + x1, y1); @@ -745,7 +747,7 @@ osgEarth::GeoHeightField DBElevationLayer::createHeightFieldImplementation(const osg::Vec2d tileMax; // Tile extents in QS units convertTileKeyToQsKey(key, faceId, nodeId, tileMin, tileMax); - if (!cx.extents_[faceId].Valid()) + if (!cx.extents_[faceId].isValid()) { // If there is no data on that face, return nothing. return osgEarth::GeoHeightField::INVALID; @@ -756,7 +758,7 @@ osgEarth::GeoHeightField DBElevationLayer::createHeightFieldImplementation(const uint32_t bufSize = 0; uint32_t currentRasterSize = 0; - QsErrorType err = cx.dbUtil_.TsReadDataBuffer( + QsErrorType err = cx.dbUtil_.readDataBuffer( cx.db_, cx.pathname_, "default", @@ -767,7 +769,7 @@ osgEarth::GeoHeightField DBElevationLayer::createHeightFieldImplementation(const ¤tRasterSize, false); // AllowLocalDB: no, we created it ourselves - if (err == QS_IS_OK) + if (err == simVis_db::QS_IS_OK) { if (currentRasterSize > 0) { diff --git a/SDK/simVis/DBFormat.h b/SDK/simVis/DBFormat.h index 4549518d9..bcde4bee9 100644 --- a/SDK/simVis/DBFormat.h +++ b/SDK/simVis/DBFormat.h @@ -27,9 +27,6 @@ #include "osgEarth/TileSourceElevationLayer" #include "osgEarth/URI" #include "simCore/Common/Common.h" -#include "simCore/Common/Export.h" -#include "simCore/Time/TimeClass.h" -#include "simVis/DBOptions.h" namespace simVis { From c991eda5e72efa71d791a4d5ee966409032e35dc Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 16 Jan 2020 13:33:20 -0500 Subject: [PATCH 036/121] DEV: Time Ticks now use PointDrawable instead of native geometry, making large points appear as circles instead of squares. Fixes SIM-10905. Review: 20431 --- SDK/simVis/TimeTicksChunk.cpp | 70 +++++++++++++---------------------- SDK/simVis/TimeTicksChunk.h | 5 ++- 2 files changed, 28 insertions(+), 47 deletions(-) diff --git a/SDK/simVis/TimeTicksChunk.cpp b/SDK/simVis/TimeTicksChunk.cpp index 1c3b13b59..3eef8ae28 100644 --- a/SDK/simVis/TimeTicksChunk.cpp +++ b/SDK/simVis/TimeTicksChunk.cpp @@ -24,13 +24,15 @@ #include "osg/Geometry" #include "osgText/Text" #include "osgEarth/GeoData" +#include "osgEarth/GLUtils" #include "osgEarth/LineDrawable" -#include "simVis/PointSize.h" +#include "osgEarth/PointDrawable" #include "simVis/Types.h" #include "simVis/TimeTicksChunk.h" namespace simVis { + TimeTicksChunk::TimeTicksChunk(unsigned int maxSize, Type type, double lineLength, double pointSize, unsigned int largeFactor) : TrackPointsChunk(maxSize), type_(type), @@ -110,36 +112,26 @@ void TimeTicksChunk::allocate_() if (type_ == POINT_TICKS) { // large points - largePoint_ = new osg::Geometry(); - largePoint_->setUseVertexBufferObjects(true); - largePoint_->setUseDisplayList(false); + largePoint_ = new osgEarth::PointDrawable(); largePoint_->setDataVariance(osg::Object::DYNAMIC); - osg::Vec3Array* largeVerts = new osg::Vec3Array(); - largeVerts->assign(maxSize_, osg::Vec3()); - largePoint_->setVertexArray(largeVerts); - osg::Vec4Array* largeColors = new osg::Vec4Array(); - largeColors->setBinding(osg::Array::BIND_PER_VERTEX); - largeColors->assign(maxSize_, osg::Vec4(0, 0, 0, 0)); - largePoint_->setColorArray(largeColors); - largePoint_->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, offset_, count_)); + largePoint_->allocate(maxSize_); + largePoint_->setColor(osg::Vec4f(0.f, 0.f, 0.f, 0.f)); + largePoint_->finish(); + largePoint_->setFirst(offset_); + largePoint_->setCount(count_); addChild(largePoint_.get()); - PointSize::setValues(largePoint_->getOrCreateStateSet(), pointSize_ * largeSizeFactor_, osg::StateAttribute::ON); + osgEarth::GLUtils::setPointSize(largePoint_->getOrCreateStateSet(), pointSize_ * largeSizeFactor_, osg::StateAttribute::ON); // points - point_ = new osg::Geometry(); - point_->setUseVertexBufferObjects(true); - point_->setUseDisplayList(false); + point_ = new osgEarth::PointDrawable(); point_->setDataVariance(osg::Object::DYNAMIC); - osg::Vec3Array* verts = new osg::Vec3Array(); - verts->assign(maxSize_, osg::Vec3()); - point_->setVertexArray(verts); - osg::Vec4Array* colors = new osg::Vec4Array(); - colors->setBinding(osg::Array::BIND_PER_VERTEX); - colors->assign(maxSize_, simVis::Color::White); - point_->setColorArray(colors); - point_->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, offset_, count_)); + point_->allocate(maxSize_); + point_->setColor(simVis::Color::White); + point_->finish(); + point_->setFirst(offset_); + point_->setCount(count_); addChild(point_.get()); - PointSize::setValues(point_->getOrCreateStateSet(), pointSize_, osg::StateAttribute::ON); + osgEarth::GLUtils::setPointSize(point_->getOrCreateStateSet(), pointSize_, osg::StateAttribute::ON); } else if (type_ == LINE_TICKS) { @@ -171,21 +163,11 @@ void TimeTicksChunk::append_(const osg::Matrix& matrix, const osg::Vec4& color, { if (large) { - osg::Vec3Array* largeVerts = static_cast(largePoint_->getVertexArray()); - (*largeVerts)[i] = local; - largeVerts->dirty(); - osg::Vec4Array* largeColors = static_cast(largePoint_->getColorArray()); - (*largeColors)[i] = color; - largeColors->dirty(); - largePoint_->dirtyBound(); + largePoint_->setVertex(i, local); + largePoint_->setColor(i, color); } - osg::Vec3Array* pointVerts = static_cast(point_->getVertexArray()); - (*pointVerts)[i] = local; - pointVerts->dirty(); - osg::Vec4Array* colors = static_cast(point_->getColorArray()); - (*colors)[i] = color; - colors->dirty(); - point_->dirtyBound(); + point_->setVertex(i, local); + point_->setColor(i, color); } else if (type_ == LINE_TICKS) { @@ -213,12 +195,10 @@ void TimeTicksChunk::updatePrimitiveSets_() { if (type_ == POINT_TICKS) { - osg::DrawArrays* pointSet = static_cast(point_->getPrimitiveSet(0)); - pointSet->setFirst(offset_); - pointSet->setCount(count_); - osg::DrawArrays* largeSet = static_cast(largePoint_->getPrimitiveSet(0)); - largeSet->setFirst(offset_); - largeSet->setCount(count_); + point_->setFirst(offset_); + point_->setCount(count_); + largePoint_->setFirst(offset_); + largePoint_->setCount(count_); } else if (type_ == LINE_TICKS) { diff --git a/SDK/simVis/TimeTicksChunk.h b/SDK/simVis/TimeTicksChunk.h index 4a970d01f..9b6e8c5d5 100644 --- a/SDK/simVis/TimeTicksChunk.h +++ b/SDK/simVis/TimeTicksChunk.h @@ -31,6 +31,7 @@ namespace simVis { + /** Implementation of the TrackPointsChunk to draw track history time ticks */ class SDKVIS_EXPORT TimeTicksChunk : public TrackPointsChunk { @@ -108,9 +109,9 @@ class SDKVIS_EXPORT TimeTicksChunk : public TrackPointsChunk ///container for drawables osg::ref_ptr geode_; /// point graphic - osg::ref_ptr point_; + osg::ref_ptr point_; /// point graphic for large points - osg::ref_ptr largePoint_; + osg::ref_ptr largePoint_; /// line graphic osg::ref_ptr line_; /// matrix to convert from world to local coords From c25ef763829cfc40e914e6b9ced596276b5a1fe7 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 16 Jan 2020 15:13:35 -0500 Subject: [PATCH 037/121] DEV: Script that generates the top level headers is now fixed to avoid SQLite-specific headers in simVis and simUtil. Review: 20430 --- SDK/genTopLevelHeaders.sh | 5 ++--- SDK/simQt.h | 2 -- SDK/simVis.h | 6 +++++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/SDK/genTopLevelHeaders.sh b/SDK/genTopLevelHeaders.sh index 06de575ba..509e39f9e 100755 --- a/SDK/genTopLevelHeaders.sh +++ b/SDK/genTopLevelHeaders.sh @@ -44,14 +44,13 @@ writeFooter() writeHeader simVis.h SIMVIS echo "#include \"simVis/Shaders.h\"" >> simVis.h.inc echo "#include \"simVis/osgEarthVersion.h\"" >> simVis.h.inc -find simVis -name '*.h' | grep -v "simVis/Shaders.h" | sed 's/^/#include "/' | sed 's/$/"/' >> simVis.h.inc +find simVis -name '*.h' | sort -f | grep -v "simVis/Shaders.h" | grep -v "simVis/DBFormat.h" | grep -v "simVis/DBOptions.h" | grep -v "simVis/DB/" | sed 's/^/#include "/' | sed 's/$/"/' >> simVis.h.inc addIncludes simVis.h writeFooter simVis.h SIMVIS - # simUtil writeHeader simUtil.h SIMUTIL -find simUtil -name '*.h' | sort -f | sed 's/^/#include "/' | sed 's/$/"/' >> simUtil.h.inc +find simUtil -name '*.h' | sort -f | grep -v "simUtil/DbConfigurationFile" | sed 's/^/#include "/' | sed 's/$/"/' >> simUtil.h.inc addIncludes simUtil.h writeFooter simUtil.h SIMUTIL diff --git a/SDK/simQt.h b/SDK/simQt.h index 16d95201a..ab8d65128 100644 --- a/SDK/simQt.h +++ b/SDK/simQt.h @@ -28,9 +28,7 @@ #include "simQt/BoundSettings.h" #include "simQt/CategoryDataBreadcrumbs.h" #include "simQt/CategoryFilterCounter.h" -#include "simQt/CategoryFilterWidget.h" #include "simQt/CategoryTreeModel.h" -#include "simQt/CategoryTreeModel2.h" #include "simQt/CenterEntity.h" #include "simQt/ColorButton.h" #include "simQt/ColorGradient.h" diff --git a/SDK/simVis.h b/SDK/simVis.h index 91e040310..d6d950d21 100644 --- a/SDK/simVis.h +++ b/SDK/simVis.h @@ -35,7 +35,9 @@ #include "simVis/BillboardAutoTransform.h" #include "simVis/BoxGraphic.h" #include "simVis/BoxZoomMouseHandler.h" +#include "simVis/BrightnessContrastColorFilter.h" #include "simVis/CentroidManager.h" +#include "simVis/ChromaKeyColorFilter.h" #include "simVis/ClassificationBanner.h" #include "simVis/ClockOptions.h" #include "simVis/Compass.h" @@ -84,6 +86,7 @@ #include "simVis/InsetViewEventHandler.h" #include "simVis/LabelContentManager.h" #include "simVis/Laser.h" +#include "simVis/LayerRefreshCallback.h" #include "simVis/LobGroup.h" #include "simVis/LocalGrid.h" #include "simVis/Locator.h" @@ -96,7 +99,6 @@ #include "simVis/osgEarthVersion.h" #include "simVis/OverheadMode.h" #include "simVis/OverrideColor.h" -#include "simVis/LayerRefreshCallback.h" #include "simVis/Picker.h" #include "simVis/PlanetariumViewTool.h" #include "simVis/Platform.h" @@ -146,6 +148,8 @@ #include "simVis/SphericalVolume.h" #include "simVis/TargetDelegation.h" #include "simVis/Text.h" +#include "simVis/TimeTicks.h" +#include "simVis/TimeTicksChunk.h" #include "simVis/Tool.h" #include "simVis/TrackChunkNode.h" #include "simVis/TrackHistory.h" From 6c5edef54c5a9637617d20bf9f3fd378d46b0cf5 Mon Sep 17 00:00:00 2001 From: Andrew LaFrance Date: Fri, 17 Jan 2020 10:14:49 -0500 Subject: [PATCH 038/121] SDK BUGFIX: WorldMagneticModel::GeoMag::calculateVariance() now clamps input date to (latest WMM year + 5) before calculating variance, rather than returning a variance of 0.0 when date was past that limit. Dev: GeoMag::calculateVariance clamps date when past the latest WMM rather than defaulting to True. SIM-10936, Review #20435. --- SDK/simCore/Calc/MagneticVariance.cpp | 33 +++++++++++++++++++-------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/SDK/simCore/Calc/MagneticVariance.cpp b/SDK/simCore/Calc/MagneticVariance.cpp index c61eab486..ca5a8890d 100644 --- a/SDK/simCore/Calc/MagneticVariance.cpp +++ b/SDK/simCore/Calc/MagneticVariance.cpp @@ -20,6 +20,7 @@ * */ #include +#include "simNotify/Notify.h" #include "simCore/Calc/Vec3.h" #include "simCore/Calc/Angle.h" #include "simCore/Time/TimeClass.h" @@ -428,8 +429,13 @@ class WorldMagneticModel::GeoMag double aor_, ar_, br_, bt_, bp_, bpp_; double otime_, oalt_, olat_, olon_; int oyear_; + + /** Track if we've issued a warning about the WMM bounds */ + static bool tooLateWarned_; }; +bool WorldMagneticModel::GeoMag::tooLateWarned_ = false; + // // // // // // // // // // // // // // // // // // // // // // // // ******************************** @@ -499,9 +505,6 @@ class WorldMagneticModel::GeoMag int WorldMagneticModel::GeoMag::calculateVariance(const simCore::Vec3& lla, int ordinalDay, int refYear, double& variance) { - // convert time to year decimal fraction - const double time = static_cast(refYear)+static_cast(ordinalDay) / 365.25; - // determine appropriate epoch year if (refYear >= 1985 && refYear < 1990) epochYear_ = 1985; @@ -521,6 +524,24 @@ int WorldMagneticModel::GeoMag::calculateVariance(const simCore::Vec3& lla, int // default to last updated WMM epochYear_ = 2020; + // Warn users when their refYear is beyond the available model, but continue with the latest available year + const auto maxYear = (epochYear_ + 5); + if (refYear > maxYear || (refYear == maxYear && ordinalDay > 0)) + { + if (!tooLateWarned_) + { + SIM_ERROR << "calculateVariance encountered a date (" << ordinalDay << " " << refYear << ") which is more than 5 years beyond the last available WMM (" << + epochYear_ << "). Proceeding with date clamped to: 00 " << maxYear << std::endl; + tooLateWarned_ = true; + } + // Calculation extends to 5 years beyond the epoch date, so set day to zero and cap the year + refYear = maxYear; + ordinalDay = 0; + } + + // convert time to year decimal fraction + const double time = static_cast(refYear) + (static_cast(ordinalDay) / 365.25); + const double dt = time - static_cast(epochYear_); // convert alt from m to km @@ -538,12 +559,6 @@ int WorldMagneticModel::GeoMag::calculateVariance(const simCore::Vec3& lla, int return 0; } - if (time > epochYear_ + 5 || time < epochYear_) - { - variance = 0.0; - return 1; - } - double *p = SNORM_COEFF; const double srlon = sin(lla.lon()); const double srlat = sin(lla.lat()); From 7469a82b0ad1a35c764c712909f2e109c7cc52b2 Mon Sep 17 00:00:00 2001 From: Colin McNulty Date: Tue, 21 Jan 2020 09:17:23 -0500 Subject: [PATCH 039/121] DEV: Refactor RFProp::Profile to avoid using simVis::PointSize. Part of SIM-10909. First commit of review 20432 --- SDK/simVis/RFProp/Profile.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/SDK/simVis/RFProp/Profile.cpp b/SDK/simVis/RFProp/Profile.cpp index 79241cac8..af2d6abc0 100644 --- a/SDK/simVis/RFProp/Profile.cpp +++ b/SDK/simVis/RFProp/Profile.cpp @@ -21,13 +21,14 @@ */ #include "osg/MatrixTransform" #include "osg/Texture2D" +#include "osgEarth/GLUtils" #include "osgEarth/ImageUtils" +#include "osgEarth/PointDrawable" #include "osgEarth/NodeUtils" #include "simCore/Calc/Angle.h" #include "simCore/Calc/Calculations.h" #include "simCore/Calc/Interpolation.h" #include "simVis/Constants.h" -#include "simVis/PointSize.h" #include "simVis/Utils.h" #include "simVis/RFProp/CompositeProfileProvider.h" #include "simVis/RFProp/Profile.h" @@ -988,9 +989,12 @@ void Profile::init3DPoints_() simCore::geodeticToSpherical(refCoord_.lat(), refCoord_.lon(), refCoord_.alt(), tpSphereXYZ); const unsigned int numVerts = (maxHeightIndex - minHeightIndex + 1) * numRanges; - verts_->reserve(numVerts); values_->reserve(numVerts); + osgEarth::PointDrawable* points = new osgEarth::PointDrawable(); + points->setDataVariance(osg::Object::DYNAMIC); + points->reserve(numVerts); + for (unsigned int r = 0; r < numRanges; r++) { const double range = minRange + rangeStep * r; @@ -1008,21 +1012,15 @@ void Profile::init3DPoints_() { adjustSpherical_(v, tpSphereXYZ); } - verts_->push_back(v); + points->pushVertex(v); values_->push_back(value); } } + points->setVertexAttribArray(osg::Drawable::ATTRIBUTE_6, values_.get()); + points->finish(); - osg::Geometry* geometry = new osg::Geometry(); - geometry->setDataVariance(osg::Object::DYNAMIC); - geometry->setVertexArray(verts_.get()); - geometry->setUseVertexBufferObjects(true); - - geometry->setVertexAttribArray(osg::Drawable::ATTRIBUTE_6, values_.get()); - - geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, verts_->size())); - geode_->addDrawable(geometry); - simVis::PointSize::setValues(geode_->getOrCreateStateSet(), 3.f, osg::StateAttribute::ON); + geode_->addChild(points); + osgEarth::GLUtils::setPointSize(geode_->getOrCreateStateSet(), 3.f, osg::StateAttribute::ON); } osg::Image* Profile::createImage_() From 2fd25175e076546195b1bd23e6cad3d5194a2f8f Mon Sep 17 00:00:00 2001 From: Colin McNulty Date: Tue, 21 Jan 2020 09:24:59 -0500 Subject: [PATCH 040/121] DEV: Remove PointSize. Addresses SIM-10909. Review 20432 --- SDK/simVis.h | 1 - SDK/simVis/CMakeLists.txt | 3 -- SDK/simVis/PointSize.cpp | 80 ---------------------------------- SDK/simVis/PointSize.h | 58 ------------------------ SDK/simVis/PointSize.vert.glsl | 14 ------ SDK/simVis/Scenario.cpp | 2 - SDK/simVis/SphericalVolume.cpp | 1 - SDK/simVis/TimeTicks.cpp | 1 - 8 files changed, 160 deletions(-) delete mode 100644 SDK/simVis/PointSize.cpp delete mode 100644 SDK/simVis/PointSize.h delete mode 100644 SDK/simVis/PointSize.vert.glsl diff --git a/SDK/simVis.h b/SDK/simVis.h index d6d950d21..729c99af3 100644 --- a/SDK/simVis.h +++ b/SDK/simVis.h @@ -106,7 +106,6 @@ #include "simVis/PlatformFilter.h" #include "simVis/PlatformInertialTransform.h" #include "simVis/PlatformModel.h" -#include "simVis/PointSize.h" #include "simVis/PolygonStipple.h" #include "simVis/Popup.h" #include "simVis/Projector.h" diff --git a/SDK/simVis/CMakeLists.txt b/SDK/simVis/CMakeLists.txt index 4bd925f8f..18bc00cea 100644 --- a/SDK/simVis/CMakeLists.txt +++ b/SDK/simVis/CMakeLists.txt @@ -24,7 +24,6 @@ set(SHADER_FILES Picker.vert.glsl Picker.frag.glsl PlatformAzimElevViewTool.vert.glsl - PointSize.vert.glsl PolygonStipple.frag.glsl Projector.vert.glsl Projector.frag.glsl @@ -99,7 +98,6 @@ set(VIS_HEADERS_CORE ${VIS_INC}PlatformFilter.h ${VIS_INC}PlatformInertialTransform.h ${VIS_INC}PlatformModel.h - ${VIS_INC}PointSize.h ${VIS_INC}PolygonStipple.h ${VIS_INC}Popup.h ${VIS_INC}Projector.h @@ -255,7 +253,6 @@ set(VIS_SOURCES_CORE ${VIS_SRC}PlatformFilter.cpp ${VIS_SRC}PlatformInertialTransform.cpp ${VIS_SRC}PlatformModel.cpp - ${VIS_SRC}PointSize.cpp ${VIS_SRC}PolygonStipple.cpp ${VIS_SRC}Popup.cpp ${VIS_SRC}Projector.cpp diff --git a/SDK/simVis/PointSize.cpp b/SDK/simVis/PointSize.cpp deleted file mode 100644 index eeee43642..000000000 --- a/SDK/simVis/PointSize.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** -***** ***** -***** Classification: UNCLASSIFIED ***** -***** Classified By: ***** -***** Declassify On: ***** -***** ***** -**************************************************************************** -* -* -* Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. -* EW Modeling & Simulation, Code 5773 -* 4555 Overlook Ave. -* Washington, D.C. 20375-5339 -* -* License for source code at https://simdis.nrl.navy.mil/License.aspx -* -* The U.S. Government retains all rights to use, duplicate, distribute, -* disclose, or release this software. -* -*/ -#include "osg/Point" -#include "osg/StateSet" -#include "osgEarth/Capabilities" -#include "osgEarth/Registry" -#include "osgEarth/VirtualProgram" -#include "simVis/Shaders.h" -#include "simVis/PointSize.h" - -namespace simVis { - -namespace -{ -const std::string POINT_SIZE_UNIFORM = "simvis_pointsize"; -} - -PointSize::PointSize() -{ -} - -PointSize::~PointSize() -{ -} - -void PointSize::installShaderProgram(osg::StateSet* intoStateSet) -{ - // Shader side: Install the shader. FFP: do nothing - if (osgEarth::Registry::capabilities().supportsGLSL(3.3f)) - { - osgEarth::VirtualProgram* vp = osgEarth::VirtualProgram::getOrCreate(intoStateSet); - simVis::Shaders shaders; - shaders.load(vp, shaders.pointSizeVertex()); - intoStateSet->setMode(GL_PROGRAM_POINT_SIZE, osg::StateAttribute::OFF); - intoStateSet->getOrCreateUniform(POINT_SIZE_UNIFORM, osg::Uniform::FLOAT)->set(1.f); - // Note that large point "rounding" to circles is not supported at this time - } -} - -void PointSize::setValues(osg::StateSet* stateset, float pointSize, int value) -{ - if (stateset == NULL) - return; - - // Need GLSL 3.3 to use point size shader, else fall back to FFP and hope for compatibility mode - const bool useShader = osgEarth::Registry::capabilities().supportsGLSL(3.3f); - if (useShader) - { - // GL 3.3 implementation uses a shader - stateset->setMode(GL_PROGRAM_POINT_SIZE, value); - osg::Uniform* uni = new osg::Uniform(POINT_SIZE_UNIFORM.c_str(), pointSize); - stateset->addUniform(uni, value); - } - else - { - // Fixed function pipeline; controlled by osg::StateAttribute - stateset->setAttributeAndModes(new osg::Point(pointSize), value); - } -} - -} diff --git a/SDK/simVis/PointSize.h b/SDK/simVis/PointSize.h deleted file mode 100644 index 425db84cf..000000000 --- a/SDK/simVis/PointSize.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** -***** ***** -***** Classification: UNCLASSIFIED ***** -***** Classified By: ***** -***** Declassify On: ***** -***** ***** -**************************************************************************** -* -* -* Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. -* EW Modeling & Simulation, Code 5773 -* 4555 Overlook Ave. -* Washington, D.C. 20375-5339 -* -* License for source code at https://simdis.nrl.navy.mil/License.aspx -* -* The U.S. Government retains all rights to use, duplicate, distribute, -* disclose, or release this software. -* -*/ -#ifndef SIMVIS_POINTSIZE_H -#define SIMVIS_POINTSIZE_H - -#include "osg/StateAttribute" -#include "simCore/Common/Common.h" - -namespace osg { class StateSet; } - -namespace simVis { - -/** -* OpenGL 3.3 shader implementation of PointSize. -* -* PointSize is not supported in the GL Core profile, so this is a simplified implementation of an -* point size shader that matches behavior in the fixed function pipeline (FFP) version of SIMDIS. -*/ -class SDKVIS_EXPORT PointSize -{ -public: - /** - * Before using this class, a call to installShaderProgram is required. This method installs - * the shader program and default uniform variables/defines for controlling the shader. - */ - static void installShaderProgram(osg::StateSet* intoStateSet); - - /** Static instance-less setting of point size on a state set. */ - static void setValues(osg::StateSet* stateset, float pointSize, int value = osg::StateAttribute::ON); - -protected: - /** Prevent construction/destruction, since there is no state. */ - PointSize(); - virtual ~PointSize(); -}; - -} - -#endif /* SIMVIS_POINTSIZE_H */ diff --git a/SDK/simVis/PointSize.vert.glsl b/SDK/simVis/PointSize.vert.glsl deleted file mode 100644 index 1dc4a83a1..000000000 --- a/SDK/simVis/PointSize.vert.glsl +++ /dev/null @@ -1,14 +0,0 @@ -#version 140 - -#pragma vp_entryPoint simvis_point_size -#pragma vp_location vertex_model -#pragma vp_order 1.0 - -// set a vp_order such that it executes before PointDrawable.glsl from osgEarth - -uniform float simvis_pointsize; - -void simvis_point_size(inout vec4 vertex) -{ - gl_PointSize = simvis_pointsize; -} diff --git a/SDK/simVis/Scenario.cpp b/SDK/simVis/Scenario.cpp index d066b6ca0..faa37ec42 100644 --- a/SDK/simVis/Scenario.cpp +++ b/SDK/simVis/Scenario.cpp @@ -47,7 +47,6 @@ #include "simVis/PlatformFilter.h" #include "simVis/Platform.h" #include "simVis/PlatformModel.h" -#include "simVis/PointSize.h" #include "simVis/PolygonStipple.h" #include "simVis/Projector.h" #include "simVis/ProjectorManager.h" @@ -464,7 +463,6 @@ ScenarioManager::ScenarioManager(LocatorFactory* factory, ProjectorManager* proj LobGroupNode::installShaderProgram(stateSet); OverrideColor::installShaderProgram(stateSet); PolygonStipple::installShaderProgram(stateSet); - PointSize::installShaderProgram(stateSet); TrackHistoryNode::installShaderProgram(stateSet); } diff --git a/SDK/simVis/SphericalVolume.cpp b/SDK/simVis/SphericalVolume.cpp index 5123eca66..6bf36ce23 100644 --- a/SDK/simVis/SphericalVolume.cpp +++ b/SDK/simVis/SphericalVolume.cpp @@ -35,7 +35,6 @@ #include "simCore/Calc/Angle.h" #include "simCore/Calc/Math.h" #include "simVis/Constants.h" -#include "simVis/PointSize.h" #include "simVis/PolygonStipple.h" #include "simVis/SphericalVolume.h" #include "simVis/Types.h" diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index 407180392..121a24361 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -41,7 +41,6 @@ #include "simVis/Locator.h" #include "simVis/OverheadMode.h" #include "simVis/PlatformFilter.h" -#include "simVis/PointSize.h" #include "simVis/Registry.h" #include "simVis/Shaders.h" #include "simVis/TimeTicksChunk.h" From a4297b2298de365f1cba6e82d971bb4844e1e24e Mon Sep 17 00:00:00 2001 From: Frank Bausch Date: Thu, 23 Jan 2020 08:43:38 -0500 Subject: [PATCH 041/121] SDK: antenna pattern table validates elevation data input, implements symmetry 1 tables more correctly (SIMDIS-3320) Release Note: SDK: Bug Fix: (SIMDIS-3320) Antenna Pattern Tables using symmetry 1 are not more correctly implemented. Notes: Test Environment: Windows 10, VC14.1, Debug, 64-bit Test: vsi builds, all tests pass Review: 20473 --- SDK/simCore/EM/AntennaPattern.cpp | 197 ++++++++++++++---------------- SDK/simVis/Antenna.cpp | 1 + 2 files changed, 95 insertions(+), 103 deletions(-) diff --git a/SDK/simCore/EM/AntennaPattern.cpp b/SDK/simCore/EM/AntennaPattern.cpp index 165892a76..f05c9212e 100644 --- a/SDK/simCore/EM/AntennaPattern.cpp +++ b/SDK/simCore/EM/AntennaPattern.cpp @@ -523,6 +523,50 @@ void AntennaPatternPedestal::minMaxGain(float *min, float *max, const AntennaGai /* ************************************************************************** */ +namespace +{ + /** + * @brief Convenience function that returns the gain for a specified angle from an antenna pattern lookup table, interpolating if necessary + * @param[in ] angle angle to lookup (rad) + * @param[in ] angle/gain lookup table + * @return table gain (dB), or SMALL_DB_VAL on invalid input + */ + float gainAtAngle(float angle, const std::map& table) + { + // gets the first element in map with an angle >= input angle + std::map::const_iterator iter = table.lower_bound(angle); + if (iter != table.end()) + { + // checks if the obtained element's angle is equal to the given angle, + // or if the obtained element is the first element in map + if ((iter->first == angle) || (iter == table.begin())) + return iter->second; + + // the obtained element's angle is > the given angle and it is not + // the first element in the map, so an interpolated angle between + // the current element and the previous element will be used + const float hiGain = iter->second; + const float hiAng = iter->first; + --iter; + const float loGain = iter->second; + const float loAng = iter->first; + // linearInterpolate casts to double as needed to avoid loss of precision + return linearInterpolate(loGain, hiGain, loAng, angle, hiAng); + } + + // if not found in table, double-check, possibly missed due to rounding errors due to casting + iter = table.begin(); + if (areEqual(angle, iter->first)) + return iter->second; + + const std::map::const_reverse_iterator riter = table.rbegin(); + if (areEqual(angle, riter->first)) + return riter->second; + + return SMALL_DB_VAL; + } +} + /* This function returns the gain for lookup table-based antennaPatterns */ float calculateGain(const std::map *azimData, @@ -547,13 +591,13 @@ float calculateGain(const std::map *azimData, std::map::const_iterator iter; if (applyWeight == false) { - iter = azimData->begin(); - std::map::const_reverse_iterator riter = azimData->rbegin(); + iter = azimData->cbegin(); + std::map::const_reverse_iterator riter = azimData->crbegin(); if (azim < iter->first || azim > riter->first) return SMALL_DB_VAL; - iter = elevData->begin(); - riter = elevData->rbegin(); + iter = elevData->cbegin(); + riter = elevData->crbegin(); if (elev < iter->first || elev > riter->first) return SMALL_DB_VAL; } @@ -575,88 +619,8 @@ float calculateGain(const std::map *azimData, const double azim_ang = applyWeight ? sdkMin(phi * hbw, M_PI) : azim; const double elev_ang = applyWeight ? sdkMin(phi * vbw, M_PI_2) : elev; - double az_gain = SMALL_DB_VAL; - double el_gain = SMALL_DB_VAL; - - // Azimuth data - // gets the first element in map with an angle >= dazim - iter = azimData->lower_bound(static_cast(azim_ang)); - - // checks if an element with a an angle >= azim_ang was found - if (iter != azimData->end()) - { - // checks if the obtained element's angle is equal to the given angle, - // or if the obtained element is the first element in map - if ((iter->first == azim_ang) || (iter == azimData->begin())) - { - az_gain = iter->second; - } - else - { - // the obtained element's angle is > the given angle and it is not - // the first element in the map, so an interpolated angle between - // the current element and the previous element will be used - double hiGain = iter->second; - double hiAng = iter->first; - --iter; - double loGain = iter->second; - double loAng = iter->first; - - az_gain = linearInterpolate(loGain, hiGain, loAng, azim_ang, hiAng); - } - } - else - { - // check for rounding errors due to casting - iter = azimData->begin(); - std::map::const_reverse_iterator riter = azimData->rbegin(); - if (areEqual(azim_ang, iter->first)) - az_gain = iter->second; - else if (areEqual(azim_ang, riter->first)) - az_gain = riter->second; - else - az_gain = SMALL_DB_VAL; - } - - // Elevation data - // gets the first element in map with an angle >= elev_ang - iter = elevData->lower_bound(static_cast(elev_ang)); - - // checks if an element with a an angle >= elev_ang was found - if (iter != elevData->end()) - { - // checks if the obtained element's angle is equal to the given angle, - // or if the obtained element is the first element in map - if ((iter->first == elev_ang) || (iter == elevData->begin())) - { - el_gain = iter->second; - } - else - { - // the obtained element's angle is > the given angle and it is not - // the first element in the map, so an interpolated angle between - // the current element and the previous element will be used - double hiGain = iter->second; - double hiAng = iter->first; - --iter; - double loGain = iter->second; - double loAng = iter->first; - - el_gain = linearInterpolate(loGain, hiGain, loAng, elev_ang, hiAng); - } - } - else - { - // check for rounding errors due to casting - iter = elevData->begin(); - std::map::const_reverse_iterator riter = elevData->rbegin(); - if (areEqual(elev_ang, iter->first)) - el_gain = iter->second; - else if (areEqual(elev_ang, riter->first)) - el_gain = riter->second; - else - el_gain = SMALL_DB_VAL; - } + const double az_gain = gainAtAngle(static_cast(azim_ang), *azimData); + const double el_gain = gainAtAngle(static_cast(elev_ang), *elevData); // Determine angles (alpha & beta) associated with normalized // azim / elev components. They will be used to obtain a @@ -840,23 +804,38 @@ int AntennaPatternTable::readPat(std::istream& fp) if (beamWidthType_) beamWidthType_ = false; + const float m_pi_2 = static_cast(M_PI_2); + // The antenna symmetry value indicates the number of tables the user is going to provide. switch (symmetry) { - // If the symmetry is 1, then the user will provide the [0, 180] azimuth table. + // If the symmetry is 1, then the user will provide one azimuth table. + // That table typically covers [0, 180], but that is not required. // This table will be reused for the other three tables. + // Elevation data [-PI/2, PI/2] will match azimuth data in [-PI/2, PI/2]. case 1: { for (i = 0; i < tableSize[0]; i++) { - azim = static_cast(angFixPI(value[0][i])); - elev = static_cast(angFixPI2(value[0][i])); - azimData_[azim] = gain[0][i]; - elevData_[elev] = gain[0][i]; - // mirror missing data - azimData_[-azim] = gain[0][i]; - elevData_[-elev] = gain[0][i]; + const float angFixPi = static_cast(angFixPI(value[0][i])); + const float gainVal = gain[0][i]; + azimData_[angFixPi] = gainVal; + azimData_[-angFixPi] = gainVal; + + // transfer only values within (-pi/2, pi/2) to elev table; do not clamp angle values outside of that into elev table. + if (angFixPi > -m_pi_2 && angFixPi < m_pi_2) + { + elevData_[angFixPi] = gainVal; + elevData_[-angFixPi] = gainVal; + } } + // ensure that elev table gets entries for -M_PI_2 and M_PI_2, if those values exist + float azGainVal = gainAtAngle(m_pi_2, azimData_); + if (azGainVal != SMALL_DB_VAL) + elevData_[m_pi_2] = azGainVal; + azGainVal = gainAtAngle(-m_pi_2, azimData_); + if (azGainVal != SMALL_DB_VAL) + elevData_[-m_pi_2] = azGainVal; } break; @@ -874,10 +853,14 @@ int AntennaPatternTable::readPat(std::istream& fp) } for (i = 0; i < tableSize[1]; i++) { - elev = static_cast(angFixPI2(value[1][i])); - elevData_[elev] = gain[1][i]; - // mirror missing data - elevData_[-elev] = gain[1][i]; + elev = static_cast(angFixPI(value[1][i])); + // elevation angles outside of [-PI/2, PI/2] are not valid and are ignored + if (elev >= -m_pi_2 && elev <= m_pi_2) + { + elevData_[elev] = gain[1][i]; + // mirror missing data + elevData_[-elev] = gain[1][i]; + } } } break; @@ -887,23 +870,31 @@ int AntennaPatternTable::readPat(std::istream& fp) { for (i = 0; i < tableSize[0]; i++) { + // this table is supposed to contain the negative azim angle values, but not strictly enforced azim = static_cast(angFixPI(value[0][i])); azimData_[azim] = gain[0][i]; } for (i = 0; i < tableSize[1]; i++) { + // this table is supposed to contain the positive azim angle values, but not strictly enforced azim = static_cast(angFixPI(value[1][i])); azimData_[azim] = gain[1][i]; } for (i = 0; i < tableSize[2]; i++) { - elev = static_cast(angFixPI2(value[2][i])); - elevData_[elev] = gain[2][i]; + // this table is supposed to contain the negative elev angle values, but not strictly enforced + elev = static_cast(angFixPI(value[2][i])); + // elevation angles outside of [-PI/2, PI/2] are not valid and are ignored + if (elev >= -m_pi_2 && elev <= m_pi_2) + elevData_[elev] = gain[2][i]; } for (i = 0; i < tableSize[3]; i++) { - elev = static_cast(angFixPI2(value[3][i])); - elevData_[elev] = gain[3][i]; + // this table is supposed to contain the positive elev angle values, but not strictly enforced + elev = static_cast(angFixPI(value[3][i])); + // elevation angles outside of [-PI/2, PI/2] are not valid and are ignored + if (elev >= -m_pi_2 && elev <= m_pi_2) + elevData_[elev] = gain[3][i]; } } break; @@ -3449,4 +3440,4 @@ int AntennaPatternXFDTD::readPat(const std::string& inFileName) return st; } -} \ No newline at end of file +} diff --git a/SDK/simVis/Antenna.cpp b/SDK/simVis/Antenna.cpp index 3b938f50a..038c96569 100644 --- a/SDK/simVis/Antenna.cpp +++ b/SDK/simVis/Antenna.cpp @@ -543,6 +543,7 @@ void AntennaNode::render_() // draw right and left sides of pattern + // if hRange == M_TWOPI, then there is no left or right side to be drawn - face comprises the complete graphic if (hRange < M_TWOPI) { // draw right side of pattern From 318b4c1352f163dfecc1b2c7cfc2e750a9777a42 Mon Sep 17 00:00:00 2001 From: Frank Bausch Date: Thu, 23 Jan 2020 09:27:20 -0500 Subject: [PATCH 042/121] simCore: cleanup of antennaPattern calculateGain() (SIMDIS-3320) Release Note: Notes: logic was too murky before. adds additional tests to return SMALL_DB_VALUE when there is no valid gain value. some simple gain calculations are done as float, not promoted to double. Test Environment: Windows 10, VC14.1, Debug, 64-bit Test: vsi builds, all tests pass Review: 20477 --- SDK/simCore/EM/AntennaPattern.cpp | 92 +++++++++++++++---------------- 1 file changed, 43 insertions(+), 49 deletions(-) diff --git a/SDK/simCore/EM/AntennaPattern.cpp b/SDK/simCore/EM/AntennaPattern.cpp index f05c9212e..1d1e6346f 100644 --- a/SDK/simCore/EM/AntennaPattern.cpp +++ b/SDK/simCore/EM/AntennaPattern.cpp @@ -588,18 +588,18 @@ float calculateGain(const std::map *azimData, return SMALL_DB_VAL; } - std::map::const_iterator iter; - if (applyWeight == false) + float gain = SMALL_DB_VAL; + + if (!applyWeight) { - iter = azimData->cbegin(); - std::map::const_reverse_iterator riter = azimData->crbegin(); - if (azim < iter->first || azim > riter->first) + const float az_gain = gainAtAngle(static_cast(azim), *azimData); + if (az_gain == SMALL_DB_VAL) return SMALL_DB_VAL; - - iter = elevData->cbegin(); - riter = elevData->crbegin(); - if (elev < iter->first || elev > riter->first) + const float el_gain = gainAtAngle(static_cast(elev), *elevData); + if (el_gain == SMALL_DB_VAL) return SMALL_DB_VAL; + + gain = maxGain + (az_gain + el_gain) / 2.0f; } // Compute angular distance in normalized beam widths @@ -617,50 +617,44 @@ float calculateGain(const std::map *azimData, else lastLobe = ANTENNA_LOBE_BACK; - const double azim_ang = applyWeight ? sdkMin(phi * hbw, M_PI) : azim; - const double elev_ang = applyWeight ? sdkMin(phi * vbw, M_PI_2) : elev; - const double az_gain = gainAtAngle(static_cast(azim_ang), *azimData); - const double el_gain = gainAtAngle(static_cast(elev_ang), *elevData); + if (!applyWeight) + return gain; + + const double azim_ang = sdkMin(phi * hbw, M_PI); + const float az_gain = gainAtAngle(static_cast(azim_ang), *azimData); + if (az_gain == SMALL_DB_VAL) + return SMALL_DB_VAL; + + const double elev_ang = sdkMin(phi * vbw, M_PI_2); + const float el_gain = gainAtAngle(static_cast(elev_ang), *elevData); + if (el_gain == SMALL_DB_VAL) + return SMALL_DB_VAL; // Determine angles (alpha & beta) associated with normalized // azim / elev components. They will be used to obtain a // 'weighted average' antenna loss value - - double gain; - if (applyWeight) - { - double alpha, beta; - if ((azim_bw == 0.0 && elev_bw == 0.0) || vbw == hbw) - { - gain = maxGain + (az_gain + el_gain) / 2.0; - } - else if (azim_bw <= elev_bw) - { - // since atan2 returns values between -pi and pi, - // alpha and beta should be in rad instead of deg - alpha = fabs(atan2(azim_bw, elev_bw)); - if (alpha > M_PI_2) - alpha = M_PI - alpha; - beta = M_PI_2 - alpha; - gain = maxGain + (alpha * az_gain + beta * el_gain) / M_PI_2; - } - else - { - // since atan2 returns values between -pi and pi, - // alpha and beta should be in rad instead of deg - beta = fabs(atan2(elev_bw, azim_bw)); - if (beta > M_PI_2) - beta = M_PI - beta; - alpha = M_PI_2 - beta; - gain = maxGain + (alpha * az_gain + beta * el_gain) / M_PI_2; - } - } - else - { - gain = maxGain + (az_gain + el_gain) / 2.0; - } - - return static_cast(gain); + if ((azim_bw == 0.0 && elev_bw == 0.0) || vbw == hbw) + return maxGain + (az_gain + el_gain) / 2.0f; + + double alpha, beta; + if (azim_bw <= elev_bw) + { + // since atan2 returns values between -pi and pi, + // alpha and beta should be in rad instead of deg + alpha = fabs(atan2(azim_bw, elev_bw)); + if (alpha > M_PI_2) + alpha = M_PI - alpha; + beta = M_PI_2 - alpha; + return static_cast(maxGain + (alpha * az_gain + beta * el_gain) / M_PI_2); + } + + // since atan2 returns values between -pi and pi, + // alpha and beta should be in rad instead of deg + beta = fabs(atan2(elev_bw, azim_bw)); + if (beta > M_PI_2) + beta = M_PI - beta; + alpha = M_PI_2 - beta; + return static_cast(maxGain + (alpha * az_gain + beta * el_gain) / M_PI_2); } // ---------------------------------------------------------------------------- From a0407a5392d44c729c6f31ad98afff24ba3cd94c Mon Sep 17 00:00:00 2001 From: Frank Bausch Date: Thu, 23 Jan 2020 10:39:59 -0500 Subject: [PATCH 043/121] simCore: added comments about angFixPI2 and angFix90 (SIMDIS-3320) Release Note: Notes: Test Environment: Windows 10, VC14.1, Debug, 64-bit Test: vsi builds, all tests pass Review: 20476 --- SDK/simCore/Calc/Angle.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/SDK/simCore/Calc/Angle.h b/SDK/simCore/Calc/Angle.h index f71386447..bc5468ac2 100644 --- a/SDK/simCore/Calc/Angle.h +++ b/SDK/simCore/Calc/Angle.h @@ -72,7 +72,10 @@ namespace simCore } /** - * Adjusts incoming angle to fit the range [-PI_2, PI_2] + * Clamps incoming angle to fit the range [-PI_2, PI_2] + * This is intended for use with latitude or elevation angle values that are already known to be valid. + * This routine does not ensure that inputs can be validly converted to [-PI_2, PI_2], + * and may have unintended outcomes if input is not validated before this is called. * @param[in ] in Input angle (rad) * @return equivalent angle between -PI_2 and PI_2 (rad) */ @@ -134,7 +137,10 @@ namespace simCore } /** - * Hard limits incoming angle to fit the range [-90, 90] + * Clamps incoming angle to fit the range [-90, 90] + * This is intended for use with latitude or elevation angle values that are already known to be valid. + * This routine does not ensure that inputs can be validly converted to [-90, 90], + * and may have unintended outcomes if input is not validated before this is called. * @param[in ] in angle (deg) * @return equivalent angle between -90 and 90 (deg) */ From c5449ceae8fb2d304b29ba1e7b2e2e332b0589fc Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 23 Jan 2020 12:55:34 -0500 Subject: [PATCH 044/121] SDK NEW FEATURE: simVis::Registry::setPseudoLoaderExtensions() and getPseudoLoaderExtensions() is used for specifying the extensions of known OSG pseudo-loaders. Filenames with these extensions do not go through the file search routines. Required for EW Symbols PSE format for SIM-10944. Review: 20483 --- SDK/simVis/Registry.cpp | 27 ++++++++++++++++++++++++++- SDK/simVis/Registry.h | 18 ++++++++++++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/SDK/simVis/Registry.cpp b/SDK/simVis/Registry.cpp index ac42e16e7..76f75796e 100644 --- a/SDK/simVis/Registry.cpp +++ b/SDK/simVis/Registry.cpp @@ -191,6 +191,13 @@ simVis::Registry::Registry() modelExtensions_.push_back("bmp"); modelExtensions_.push_back("jpg"); + // Known OSG and SIMDIS pseudo loaders + pseudoLoaderExtensions_.insert("osgs"); // encode OSG file as filename + pseudoLoaderExtensions_.insert("pse"); // EW symbology + pseudoLoaderExtensions_.insert("rot"); // rotate model + pseudoLoaderExtensions_.insert("scale"); // scale model + pseudoLoaderExtensions_.insert("trans"); // translate model + // initialize the default NOTIFY level from the environment variable const std::string val = simCore::getEnvVar("SIM_NOTIFY_LEVEL"); if (!val.empty()) @@ -292,6 +299,16 @@ void simVis::Registry::setModelSearchExtensions(const FileExtensionList& list) modelExtensions_ = list; } +void simVis::Registry::getPseudoLoaderExtensions(std::set& out_list) const +{ + out_list = pseudoLoaderExtensions_; +} + +void simVis::Registry::setPseudoLoaderExtensions(const std::set& list) +{ + pseudoLoaderExtensions_ = list; +} + void simVis::Registry::setShareArticulatedIconModels(bool value) { modelCache_->setShareArticulatedIconModels(value); @@ -308,6 +325,14 @@ std::string simVis::Registry::findModelFile(const std::string& name) const if (it != modelFilenameCache_.end()) return it->second; + // File extension might be in the pseudo-loader list, in which case we skip the search + const std::string& extension = osgDB::getFileExtension(name); + if (pseudoLoaderExtensions_.find(extension) != pseudoLoaderExtensions_.end()) + { + modelFilenameCache_[name] = name; + return name; + } + // First check the extension std::string fileSearchName = fileSearch_->findFile(name, simCore::FileSearch::MODEL); // Fall back on osgDB if it doesn't find it @@ -322,7 +347,7 @@ std::string simVis::Registry::findModelFile(const std::string& name) const } // Now check via osgDB which has different search paths than fileSearch_ - if (osgDB::getFileExtension(name).empty()) + if (extension.empty()) { // if the name has no extension, try tacking on extensions and trying to find the paths. for (FileExtensionList::const_iterator i = modelExtensions_.begin(); i != modelExtensions_.end(); ++i) diff --git a/SDK/simVis/Registry.h b/SDK/simVis/Registry.h index d139fc986..37c95562d 100644 --- a/SDK/simVis/Registry.h +++ b/SDK/simVis/Registry.h @@ -23,6 +23,7 @@ #define SIMVIS_REGISTRY_H #include +#include #include "OpenThreads/ReentrantMutex" #include "osg/observer_ptr" #include "osg/ref_ptr" @@ -76,16 +77,28 @@ class SDKVIS_EXPORT Registry /** * Gets a copy of the list of extensions to look for when searching for a platform model. - * @param out_list List to populate with search extensions (output param) + * @param out_list List to populate with search extensions (output param); values do not have dots (e.g. "png") */ void getModelSearchExtensions(FileExtensionList& out_list) const; /** * Sets the list of extensions to look for when searching for a platform model. - * @param list Model file extensions list + * @param list Model file extensions list; values do not have dots (e.g. "png") */ void setModelSearchExtensions(const FileExtensionList& list); + /** + * Gets a copy of the list of extensions that are registered known pseudo-loader extensions, which might not represent a file on disk. + * @param out_list List to populate with pseudo loader extensions (output param); values do not have dots (e.g. "rot") + */ + void getPseudoLoaderExtensions(std::set& out_list) const; + + /** + * Sets the list of extensions that are registered known pseudo-loader extensions, which might not represent a file on disk. + * @param list Pseudo loader file extensions list; values do not have dots (e.g. "rot") + */ + void setPseudoLoaderExtensions(const std::set& list); + /** * Searches for the named model, using the model search path list and the extensions list. * This method is thread safe @@ -206,6 +219,7 @@ class SDKVIS_EXPORT Registry FilePathList modelPaths_; FileExtensionList modelExtensions_; + std::set pseudoLoaderExtensions_; ModelCache* modelCache_; // A mapping between the supplied file name and the actual file name From 2021154b8e4ac59edf75c12331cc6618ae4b6499 Mon Sep 17 00:00:00 2001 From: Colin McNulty Date: Fri, 24 Jan 2020 13:57:58 -0500 Subject: [PATCH 045/121] DEV: Expose setTreeView in entityTreeComposite. Addresses SIM-8327. Review 20494 --- SDK/simQt/EntityTreeComposite.cpp | 14 ++++++++++++++ SDK/simQt/EntityTreeComposite.h | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/SDK/simQt/EntityTreeComposite.cpp b/SDK/simQt/EntityTreeComposite.cpp index 3da426788..09b921a0f 100644 --- a/SDK/simQt/EntityTreeComposite.cpp +++ b/SDK/simQt/EntityTreeComposite.cpp @@ -705,6 +705,14 @@ void EntityTreeComposite::setUseCenterAction(bool use, const QString& reason) centerAction_->setEnabled(false); } +void EntityTreeComposite::setTreeView(bool useTreeView) +{ + if (!treeViewUsable_) + return; + + setTreeView_(useTreeView); +} + void EntityTreeComposite::onItemsChanged_(const QList& ids) { bool empty = ids.isEmpty(); @@ -743,11 +751,17 @@ void EntityTreeComposite::centerOnSelection_() void EntityTreeComposite::setTreeView_(bool useTreeView) { + // Return early if nothing changed + if (entityTreeWidget_->isTreeView() == useTreeView && toggleTreeViewAction_->isChecked() == useTreeView) + return; + // Toggle the tree view entityTreeWidget_->toggleTreeView(useTreeView); // Update related UI components toggleTreeViewAction_->setChecked(useTreeView); updateActionEnables_(); + + emit treeViewChanged(useTreeView); } void EntityTreeComposite::updateActionEnables_() diff --git a/SDK/simQt/EntityTreeComposite.h b/SDK/simQt/EntityTreeComposite.h index 9e54b792f..e56b7b28d 100644 --- a/SDK/simQt/EntityTreeComposite.h +++ b/SDK/simQt/EntityTreeComposite.h @@ -143,6 +143,8 @@ class SDKQT_EXPORT EntityTreeComposite : public QWidget * @param reason The reason is appended to the end of the center action text */ void setUseCenterAction(bool use, const QString& reason = ""); + /** Toggle the tree/list view and update related UI component and action states if the tree view action is enabled */ + void setTreeView(bool useTreeView); /** Class to store information about an Entity Tab Filter Configuration */ class FilterConfiguration @@ -215,6 +217,9 @@ public slots: /** Fired before showing the right mouse click menu to allow external code to add and remove actions. */ void rightClickMenuRequested(QMenu* menu=NULL); + /** Fired when entityTreeComposite toggles between tree and list view */ + void treeViewChanged(bool useTreeView); + protected slots: /** Receive notice of an inserted row */ void rowsInserted_(const QModelIndex & parent, int start, int end); From 69650a5bbbba01d6d5d1fcb85787c3feba3193b6 Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Fri, 24 Jan 2020 14:26:52 -0500 Subject: [PATCH 046/121] SIM-10858 Fixed simQt::TimeWidget Signal Release: simQt::TimeWidget now always generates a valueEdited() signal when the user finishes editing the time. Notes: The focus was lost before this routine had a chance to process the change. Test Environment: Windows 10, Visual Studio 2015, Debug Test: Now get correct behavior with the TCS application Review: 20497 --- SDK/simQt/SegmentedSpinBox.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/SDK/simQt/SegmentedSpinBox.cpp b/SDK/simQt/SegmentedSpinBox.cpp index 504115e99..68ba84d20 100644 --- a/SDK/simQt/SegmentedSpinBox.cpp +++ b/SDK/simQt/SegmentedSpinBox.cpp @@ -292,9 +292,8 @@ class SegmentedEventFilter : public QObject if (lastEditedTime_ != completeLine_->timeStamp()) { completeLine_->valueChanged(); - // If we have focus assume the change was user initiated - if (hasFocus()) - completeLine_->valueEdited(); + // emit signal regardless of hasFocus() because this routine is only called by user initiated changes + completeLine_->valueEdited(); lastEditedTime_ = completeLine_->timeStamp(); } } From 1031e6360d31f74d93d22c510d9ad3b3e7cf1d43 Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Mon, 27 Jan 2020 08:21:50 -0500 Subject: [PATCH 047/121] SIM-10939 Added New Flush Type (1 of 4 SDK) Release: simData::DataStore::FlushType updated with NON_RECURSIVE_DATA to flush points, commands and data tables. Does not flush category data or generic data. simData::flushEntityData()'s signature was updated to handle the new flush type. Notes: N/A. Test Environment: Windows 10, Visual Studio 2015, Debug Test: Manual testing with the Scenario Editor Plug-in Review: 20499 --- SDK/simData/DataStore.h | 54 ++++++++++++++++++++++++++++++--- SDK/simData/MemoryDataStore.cpp | 32 ++++++++++--------- 2 files changed, 67 insertions(+), 19 deletions(-) diff --git a/SDK/simData/DataStore.h b/SDK/simData/DataStore.h index 16b4baff0..19e383b0c 100644 --- a/SDK/simData/DataStore.h +++ b/SDK/simData/DataStore.h @@ -304,10 +304,56 @@ class SDKDATA_EXPORT DataStore /// Types of flushes supported by the flush method enum FlushType { - NON_RECURSIVE, ///< Flush only the supplied entity and keep any static point - NON_RECURSIVE_TSPI_STATIC, ///< Flush only the supplied PLATFORM and flush any static TSPI point - RECURSIVE, ///< Flush the supplied entity and any children and keep any static point - NON_RECURSIVE_TSPI_ONLY ///< Flush TSPI only including static points, keep category data, generic data and data tables + /** + * Flush only the supplied entity and keep any static point + * Flushes Static points: Yes + * Flushes Commands: Yes + * Flushes Data Tables: No + * Flushes Generic Data: Yes + * Flushes Category Data: Yes + * Applies same operation to Children: No + */ + NON_RECURSIVE, + /** + * Flush only the supplied entity and flush any static point + * Flushes Static points: No + * Flushes Commands: Yes + * Flushes Data Tables: No + * Flushes Generic Data: Yes + * Flushes Category Data: Yes + * Applies same operation to Children: No + */ + NON_RECURSIVE_TSPI_STATIC, + /** + * Flush the supplied entity and any children and keep any static point + * Flushes Static points: Yes + * Flushes Commands: Yes + * Flushes Data Tables: Yes + * Flushes Generic Data: Yes + * Flushes Category Data: Yes + * Applies same operation to Children: Yes + */ + RECURSIVE, + /** + * Flush TSPI only including static points, keep category data, generic data and data tables + * Flushes Static points: No + * Flushes Commands: No + * Flushes Data Tables: No + * Flushes Generic Data: No + * Flushes Category Data: No + * Applies same operation to Children: No + */ + NON_RECURSIVE_TSPI_ONLY, + /** + * Flushes points, commands and data tables for the supplied entity. Does not flush category data or generic data. + * Flushes Static points: No + * Flushes Commands: Yes + * Flushes Data Tables: Yes + * Flushes Generic Data: No + * Flushes Category Data: No + * Applies same operation to Children: No + */ + NON_RECURSIVE_DATA }; /** diff --git a/SDK/simData/MemoryDataStore.cpp b/SDK/simData/MemoryDataStore.cpp index 2eb249b60..3d164e105 100644 --- a/SDK/simData/MemoryDataStore.cpp +++ b/SDK/simData/MemoryDataStore.cpp @@ -150,20 +150,21 @@ void updateSparseSlices(EntryListType& entries, double time) * @param id The entity to flush * @param catMap Category Data map * @param genMap Generic Data map -* @param dataOnly If true only remove the data for the update slice +* @param flushCommands If true remove commands +* @param flushCdGd If true remove Category Data and Generic data * @param keepTspiStatic If true static TSPI points are not removed. */ template -void flushEntityData(EntityMap& map, ObjectId id, MemoryDataStore::CategoryDataMap& catMap, MemoryDataStore::GenericDataMap& genMap, bool dataOnly, bool keepTspiStatic = true) +void flushEntityData(EntityMap& map, ObjectId id, MemoryDataStore::CategoryDataMap& catMap, MemoryDataStore::GenericDataMap& genMap, bool flushCommands, bool flushCdGd, bool keepTspiStatic = true) { typename EntityMap::const_iterator i = map.find(id); if (i != map.end()) { (*i).second->updates()->flush(keepTspiStatic); - if (!dataOnly) + if (flushCommands) (*i).second->commands()->flush(); } - if (!dataOnly) + if (flushCdGd) { typename MemoryDataStore::CategoryDataMap::const_iterator ci = catMap.find(id); if (ci != catMap.end()) @@ -811,13 +812,14 @@ void MemoryDataStore::updateCustomRenderings_(double time) void MemoryDataStore::flushEntity_(ObjectId flushId, simData::ObjectType type, FlushType flushType) { bool recursive = (flushType == RECURSIVE); - bool keepTspiStatic = ((flushType != NON_RECURSIVE_TSPI_STATIC) && (flushType != NON_RECURSIVE_TSPI_ONLY)); - bool dataOnly = (flushType == NON_RECURSIVE_TSPI_ONLY); + bool keepTspiStatic = ((flushType != NON_RECURSIVE_TSPI_STATIC) && (flushType != NON_RECURSIVE_TSPI_ONLY) && (flushType != NON_RECURSIVE_DATA)); + bool flushCommands = (flushType != NON_RECURSIVE_TSPI_ONLY); + bool flushCdGd = ((flushType != NON_RECURSIVE_TSPI_ONLY) && (flushType != NON_RECURSIVE_DATA)); IdList ids; switch (type) { case PLATFORM: - flushEntityData(platforms_, flushId, categoryData_, genericData_, dataOnly, keepTspiStatic); + flushEntityData(platforms_, flushId, categoryData_, genericData_, flushCommands, flushCdGd, keepTspiStatic); if (recursive) { beamIdListForHost(flushId, &ids); @@ -838,7 +840,7 @@ void MemoryDataStore::flushEntity_(ObjectId flushId, simData::ObjectType type, F } break; case BEAM: - flushEntityData(beams_, flushId, categoryData_, genericData_, dataOnly); + flushEntityData(beams_, flushId, categoryData_, genericData_, flushCommands, flushCdGd); if (recursive) { gateIdListForHost(flushId, &ids); @@ -847,27 +849,27 @@ void MemoryDataStore::flushEntity_(ObjectId flushId, simData::ObjectType type, F } break; case GATE: - flushEntityData(gates_, flushId, categoryData_, genericData_, dataOnly); + flushEntityData(gates_, flushId, categoryData_, genericData_, flushCommands, flushCdGd); break; case LASER: - flushEntityData(lasers_, flushId, categoryData_, genericData_, dataOnly); + flushEntityData(lasers_, flushId, categoryData_, genericData_, flushCommands, flushCdGd); break; case LOB_GROUP: - flushEntityData(lobGroups_, flushId, categoryData_, genericData_, dataOnly); + flushEntityData(lobGroups_, flushId, categoryData_, genericData_, flushCommands, flushCdGd); break; case PROJECTOR: - flushEntityData(projectors_, flushId, categoryData_, genericData_, dataOnly); + flushEntityData(projectors_, flushId, categoryData_, genericData_, flushCommands, flushCdGd); break; case CUSTOM_RENDERING: - flushEntityData(customRenderings_, flushId, categoryData_, genericData_, dataOnly); + flushEntityData(customRenderings_, flushId, categoryData_, genericData_, flushCommands, flushCdGd); break; case ALL: case NONE: break; } - // Only recursive flush deletes table data - if (recursive) + // Only recursive flush or non-recursive data deletes table data + if (recursive || (flushType == NON_RECURSIVE_DATA)) flushDataTables_(flushId); } From 4562ed5d0b45baef91ade089a009c5464e62c643 Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Mon, 27 Jan 2020 09:59:34 -0500 Subject: [PATCH 048/121] SIM-10939 Fixed New Flush Type (1 of 2 SDK) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Release: simData::DataStore::FlushType updated with NON_RECURSIVE_DATA to flush points and commands. Does not flush category data, generic data, or data tables. simData::flushEntityData()'s signature was updated to handle the new flush type. Notes: As soon as I started writing code for the data table in the scenario editor, I realized I don’t want tables cleared with this command. I also noticed I documented the flush static backwards. Test Environment: Windows 10, Visual Studio 2015, Debug Test: Manual testing with the Scenario Editor Plug-in Review: 20506 --- SDK/simData/DataStore.h | 14 +++++++------- SDK/simData/MemoryDataStore.cpp | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/SDK/simData/DataStore.h b/SDK/simData/DataStore.h index 19e383b0c..0314e3843 100644 --- a/SDK/simData/DataStore.h +++ b/SDK/simData/DataStore.h @@ -306,7 +306,7 @@ class SDKDATA_EXPORT DataStore { /** * Flush only the supplied entity and keep any static point - * Flushes Static points: Yes + * Flushes Static points: No * Flushes Commands: Yes * Flushes Data Tables: No * Flushes Generic Data: Yes @@ -316,7 +316,7 @@ class SDKDATA_EXPORT DataStore NON_RECURSIVE, /** * Flush only the supplied entity and flush any static point - * Flushes Static points: No + * Flushes Static points: Yes * Flushes Commands: Yes * Flushes Data Tables: No * Flushes Generic Data: Yes @@ -326,7 +326,7 @@ class SDKDATA_EXPORT DataStore NON_RECURSIVE_TSPI_STATIC, /** * Flush the supplied entity and any children and keep any static point - * Flushes Static points: Yes + * Flushes Static points: No * Flushes Commands: Yes * Flushes Data Tables: Yes * Flushes Generic Data: Yes @@ -336,7 +336,7 @@ class SDKDATA_EXPORT DataStore RECURSIVE, /** * Flush TSPI only including static points, keep category data, generic data and data tables - * Flushes Static points: No + * Flushes Static points: Yes * Flushes Commands: No * Flushes Data Tables: No * Flushes Generic Data: No @@ -345,10 +345,10 @@ class SDKDATA_EXPORT DataStore */ NON_RECURSIVE_TSPI_ONLY, /** - * Flushes points, commands and data tables for the supplied entity. Does not flush category data or generic data. - * Flushes Static points: No + * Flushes points and commands for the supplied entity. Does not flush category data, generic data or data tables. + * Flushes Static points: Yes * Flushes Commands: Yes - * Flushes Data Tables: Yes + * Flushes Data Tables: No * Flushes Generic Data: No * Flushes Category Data: No * Applies same operation to Children: No diff --git a/SDK/simData/MemoryDataStore.cpp b/SDK/simData/MemoryDataStore.cpp index 3d164e105..05c7d89b8 100644 --- a/SDK/simData/MemoryDataStore.cpp +++ b/SDK/simData/MemoryDataStore.cpp @@ -868,8 +868,8 @@ void MemoryDataStore::flushEntity_(ObjectId flushId, simData::ObjectType type, F break; } - // Only recursive flush or non-recursive data deletes table data - if (recursive || (flushType == NON_RECURSIVE_DATA)) + // Only recursive flush deletes table data + if (recursive) flushDataTables_(flushId); } From 209f476d249ae7c2eb876e284969714db52e4e39 Mon Sep 17 00:00:00 2001 From: Jason Beverage Date: Mon, 27 Jan 2020 11:58:20 -0500 Subject: [PATCH 049/121] Speed up 3d rf prop by merging all cells into a single drawable instead of having a triangle strip per cell. --- SDK/simVis/RFProp/Profile.cpp | 41 ++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/SDK/simVis/RFProp/Profile.cpp b/SDK/simVis/RFProp/Profile.cpp index 79241cac8..0ffffe939 100644 --- a/SDK/simVis/RFProp/Profile.cpp +++ b/SDK/simVis/RFProp/Profile.cpp @@ -646,6 +646,8 @@ void Profile::init3D_() osg::Geometry* geometry = new osg::Geometry(); + osg::DrawElementsUInt* idx = new osg::DrawElementsUInt(GL_TRIANGLES); + //Now build the indices that will actually be rendered for (unsigned int r = 0; r < numRanges - 1; r++) { @@ -663,33 +665,32 @@ void Profile::init3D_() const unsigned int v6 = v5 + 1; // back UR const unsigned int v7 = v6 + 1; // back UL - osg::DrawElementsUInt* idx = new osg::DrawElementsUInt(GL_TRIANGLE_STRIP); - idx->reserve(14); - // Wrap the voxel with a triangle strip - // Back Bottom - idx->push_back(v5); idx->push_back(v4); - - // Back to top - idx->push_back(v6); idx->push_back(v7); + // Front face + idx->push_back(v1); idx->push_back(v0); idx->push_back(v3); + idx->push_back(v0); idx->push_back(v2); idx->push_back(v3); - // Top to left - idx->push_back(v3); idx->push_back(v5); + // Back face + idx->push_back(v6); idx->push_back(v4); idx->push_back(v5); + idx->push_back(v7); idx->push_back(v6); idx->push_back(v5); - // Left to bottom - idx->push_back(v1); idx->push_back(v4); + // Top face + idx->push_back(v3); idx->push_back(v2); idx->push_back(v7); + idx->push_back(v2); idx->push_back(v6); idx->push_back(v7); - // Bottom to right - idx->push_back(v0); idx->push_back(v6); + // Bottom face + idx->push_back(v1); idx->push_back(v5); idx->push_back(v4); + idx->push_back(v1); idx->push_back(v4); idx->push_back(v0); - // Right to top - idx->push_back(v2); idx->push_back(v3); + // Left face + idx->push_back(v5); idx->push_back(v1); idx->push_back(v7); + idx->push_back(v1); idx->push_back(v3); idx->push_back(v7); - // Top to front - idx->push_back(v0); idx->push_back(v1); - - geometry->addPrimitiveSet(idx); + // Right face + idx->push_back(v0); idx->push_back(v4); idx->push_back(v6); + idx->push_back(v0); idx->push_back(v6); idx->push_back(v2); } } + geometry->addPrimitiveSet(idx); geometry->setDataVariance(osg::Object::DYNAMIC); geometry->setVertexArray(verts_.get()); From 0ade6f9d5ae46a8550a3384ebb96850944b14e01 Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Tue, 28 Jan 2020 16:12:35 -0500 Subject: [PATCH 050/121] DEV: SDK: TimeTicks reference from 0:00:00 rather than scenario start time, SIM-10983, review 20531 --- SDK/simVis/TimeTicks.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SDK/simVis/TimeTicks.cpp b/SDK/simVis/TimeTicks.cpp index 121a24361..93549a90b 100644 --- a/SDK/simVis/TimeTicks.cpp +++ b/SDK/simVis/TimeTicks.cpp @@ -594,8 +594,9 @@ void TimeTicks::updateTrackData_(double currentTime, const simData::PlatformUpda // check last draw time again, since it may have been updated in the block above if (!hasLastDrawTime_) { - // time ticks should reference from scenario start time - double firstTime = ds_.timeBounds(0).first; + // time ticks should all be referenced from 0:00:00.000 + double firstTime = 0.0; + // update begin time to always count up to a valid draw time from first time in case data limiting is occurring const double interval = lastPlatformPrefs_.trackprefs().timeticks().interval(); if (beginTime != firstTime) From 7a7a1de1afad756d146bac498a77bd6ea51056f0 Mon Sep 17 00:00:00 2001 From: Jason Beverage Date: Wed, 29 Jan 2020 13:56:04 -0500 Subject: [PATCH 051/121] Replaced TriStripVisitor with IndexMeshVisitor since TriStripVisitor is removed in the master osg --- SDK/simVis/Utils.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SDK/simVis/Utils.cpp b/SDK/simVis/Utils.cpp index 70e54389d..709e0611b 100644 --- a/SDK/simVis/Utils.cpp +++ b/SDK/simVis/Utils.cpp @@ -32,7 +32,7 @@ #include "osgDB/Registry" #include "osgSim/DOFTransform" #include "osgUtil/RenderBin" -#include "osgUtil/TriStripVisitor" +#include "osgUtil/MeshOptimizers" #include "osgViewer/ViewerEventHandlers" #include "osgEarth/Capabilities" @@ -1166,8 +1166,8 @@ void FixDeprecatedDrawModes::apply(osg::Geometry& geom) if (primSet->getMode() == GL_POLYGON || primSet->getMode() == GL_QUADS || primSet->getMode() == GL_QUAD_STRIP) { // Turn deprecated geometry into tri-strips; affects whole geometry - osgUtil::TriStripVisitor triStrip; - triStrip.stripify(geom); + osgUtil::IndexMeshVisitor mesher; + geom.accept(mesher); break; } } From 6f5224cae0b848b7e6e7062d3c175eb38489c7fc Mon Sep 17 00:00:00 2001 From: Jason Beverage Date: Thu, 30 Jan 2020 11:58:07 -0500 Subject: [PATCH 052/121] Removed duplicate ReadFile includes Deleted SDK/simVis/DB/Plugin.cpp and SDK/simVis/DB/RasterCommon.h that were removed in the master but got included in a previous merge. --- Examples/ASIViewer/ASIViewer.cpp | 1 - Examples/BasicViewerText/BasicViewerText.cpp | 1 - SDK/simVis/DB/Plugin.cpp | 56 -------------------- SDK/simVis/DB/RasterCommon.h | 0 4 files changed, 58 deletions(-) delete mode 100644 SDK/simVis/DB/Plugin.cpp delete mode 100644 SDK/simVis/DB/RasterCommon.h diff --git a/Examples/ASIViewer/ASIViewer.cpp b/Examples/ASIViewer/ASIViewer.cpp index 5431aa5af..89dfa97ff 100644 --- a/Examples/ASIViewer/ASIViewer.cpp +++ b/Examples/ASIViewer/ASIViewer.cpp @@ -47,7 +47,6 @@ #include "osgDB/ReadFile" #include "osgEarth/Controls" #include "osgEarth/StringUtils" -#include "osgDB/ReadFile" namespace ui = osgEarth::Util::Controls; diff --git a/Examples/BasicViewerText/BasicViewerText.cpp b/Examples/BasicViewerText/BasicViewerText.cpp index f7cf2d984..3c635b451 100644 --- a/Examples/BasicViewerText/BasicViewerText.cpp +++ b/Examples/BasicViewerText/BasicViewerText.cpp @@ -39,7 +39,6 @@ #include "simUtil/HudManager.h" #include "simUtil/Replaceables.h" #include "simUtil/StatusText.h" -#include "osgDB/ReadFile" #define LC "[BasicViewerText demo] " diff --git a/SDK/simVis/DB/Plugin.cpp b/SDK/simVis/DB/Plugin.cpp deleted file mode 100644 index 43635c2b5..000000000 --- a/SDK/simVis/DB/Plugin.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- mode: c++ -*- */ -/**************************************************************************** -***** ***** -***** Classification: UNCLASSIFIED ***** -***** Classified By: ***** -***** Declassify On: ***** -***** ***** -**************************************************************************** -* -* -* Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. -* EW Modeling & Simulation, Code 5773 -* 4555 Overlook Ave. -* Washington, D.C. 20375-5339 -* -* License for source code at https://simdis.nrl.navy.mil/License.aspx -* -* The U.S. Government retains all rights to use, duplicate, distribute, -* disclose, or release this software. -* -*/ -#include "osgEarth/TileSource" -#include "osgDB/FileNameUtils" -#include "osgDB/Registry" -#include -#include "DBTileSource.h" - -class SimSdkOSGEarthDBDriverPlugin : public osgEarth::Contrib::TileSourceDriver -{ -public: - SimSdkOSGEarthDBDriverPlugin() { } - - const char* className() - { - return "OSGEarth DB Driver"; - } - - bool acceptsExtension(const std::string& extension) const - { - return osgDB::equalCaseInsensitive("osgearth_db", extension); - } - - osgDB::ReaderWriter::ReadResult readObject(const std::string& uri, const osgDB::Options* options) const - { - std::string ext = osgDB::getFileExtension(uri); - if (!acceptsExtension(ext)) - { - return osgDB::ReaderWriter::ReadResult::FILE_NOT_HANDLED; - } - - return osgDB::ReaderWriter::ReadResult( - new simVis_db::DBTileSource(getTileSourceOptions(options))); - } -}; - -REGISTER_OSGPLUGIN(osgearth_db, SimSdkOSGEarthDBDriverPlugin) diff --git a/SDK/simVis/DB/RasterCommon.h b/SDK/simVis/DB/RasterCommon.h deleted file mode 100644 index e69de29bb..000000000 From 09596aa2e316a534e744f751b11b0d62f1aff6f4 Mon Sep 17 00:00:00 2001 From: Colin McNulty Date: Thu, 30 Jan 2020 11:58:41 -0500 Subject: [PATCH 053/121] DEV: Save out GOG altitude mode. Addresses SIM-10990. Review 20549 --- SDK/simVis/GOG/GOGNode.h | 3 ++- SDK/simVis/GOG/GogNodeInterface.cpp | 13 +++++++++++++ SDK/simVis/GOG/Parser.cpp | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/SDK/simVis/GOG/GOGNode.h b/SDK/simVis/GOG/GOGNode.h index 534006b15..495619880 100644 --- a/SDK/simVis/GOG/GOGNode.h +++ b/SDK/simVis/GOG/GOGNode.h @@ -55,7 +55,8 @@ namespace simVis { namespace GOG GOG_POINT_SIZE_SET, GOG_LINE_PROJECTION_SET, GOG_TEXT_OUTLINE_COLOR_SET, - GOG_TEXT_OUTLINE_THICKNESS_SET + GOG_TEXT_OUTLINE_THICKNESS_SET, + GOG_ALTITUDE_MODE_SET }; // stipple defines diff --git a/SDK/simVis/GOG/GogNodeInterface.cpp b/SDK/simVis/GOG/GogNodeInterface.cpp index 4fb534663..5078f24c3 100644 --- a/SDK/simVis/GOG/GogNodeInterface.cpp +++ b/SDK/simVis/GOG/GogNodeInterface.cpp @@ -539,6 +539,17 @@ void GogNodeInterface::serializeToStream(std::ostream& gogOutputStream) else if (metaData_.isSetExplicitly(GOG_TESSELLATE_SET)) gogOutputStream << "tessellate false\n"; + // altitude mode + simVis::GOG::AltitudeMode altMode; + getAltitudeMode(altMode); + if (altMode == simVis::GOG::ALTITUDE_NONE && metaData_.isSetExplicitly(GOG_ALTITUDE_MODE_SET)) + gogOutputStream << "altitudemode none\n"; + else if (altMode == simVis::GOG::ALTITUDE_GROUND_RELATIVE) + gogOutputStream << "altitudemode relativetoground\n"; + else if (altMode == simVis::GOG::ALTITUDE_GROUND_CLAMPED) + gogOutputStream << "altitudemode clamptoground\n"; + // simVis::GOG::ALTITUDE_EXTRUDE is covered by the extrude keyword + // Follow data is not currently serialized out } @@ -679,6 +690,7 @@ int GogNodeInterface::getTextOutline(osg::Vec4f& outlineColor, simData::TextOutl void GogNodeInterface::setAltitudeMode(AltitudeMode altMode) { + metaData_.setExplicitly(GOG_ALTITUDE_MODE_SET); if (altMode_ == altMode) return; altMode_ = altMode; @@ -1504,6 +1516,7 @@ void FeatureNodeInterface::setTessellation(TessellationStyle style) void FeatureNodeInterface::setAltitudeMode(AltitudeMode altMode) { + metaData_.setExplicitly(GOG_ALTITUDE_MODE_SET); if (altMode_ == altMode) return; altMode_ = altMode; diff --git a/SDK/simVis/GOG/Parser.cpp b/SDK/simVis/GOG/Parser.cpp index b9d1268fe..9070ad766 100644 --- a/SDK/simVis/GOG/Parser.cpp +++ b/SDK/simVis/GOG/Parser.cpp @@ -620,8 +620,8 @@ bool Parser::parse(std::istream& input, std::vector& output, std::v { if (tokens.size() >= 2) { - currentMetaData.metadata += line + "\n"; state.altitudeMode_ = tokens[1]; + currentMetaData.setExplicitly(GOG_ALTITUDE_MODE_SET); } else { From b8359a881655e9a4c599282fc53181d83b72f795 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 30 Jan 2020 12:03:49 -0500 Subject: [PATCH 054/121] DEV: Removed extraneous ReadFile includes, no review. --- Examples/Periscope/PeriscopeExample.cpp | 2 -- Examples/PlatformSymbology/PlatformSymbology.cpp | 2 -- Examples/RocketBurn/RocketBurn.cpp | 2 -- Examples/TimestampedLayer/ExampleTimestampedLayer.cpp | 1 - SDK/simVis/Compass.cpp | 1 - 5 files changed, 8 deletions(-) diff --git a/Examples/Periscope/PeriscopeExample.cpp b/Examples/Periscope/PeriscopeExample.cpp index 0a2248f52..f301cef07 100644 --- a/Examples/Periscope/PeriscopeExample.cpp +++ b/Examples/Periscope/PeriscopeExample.cpp @@ -47,8 +47,6 @@ #include "osgEarth/SimpleOceanLayer" #include "osgEarth/Version" -#include "osgDB/ReadFile" - #ifdef HAVE_TRITON_NODEKIT #include "osgEarthTriton/TritonLayer" #endif diff --git a/Examples/PlatformSymbology/PlatformSymbology.cpp b/Examples/PlatformSymbology/PlatformSymbology.cpp index 1cf1aa20a..77a99ac10 100644 --- a/Examples/PlatformSymbology/PlatformSymbology.cpp +++ b/Examples/PlatformSymbology/PlatformSymbology.cpp @@ -65,8 +65,6 @@ #include "osgEarth/StringUtils" #include "osgEarth/Style" -#include "osgDB/ReadFile" - #include "google/protobuf/stubs/common.h" using namespace osgEarth; diff --git a/Examples/RocketBurn/RocketBurn.cpp b/Examples/RocketBurn/RocketBurn.cpp index e32041074..0df9ef242 100644 --- a/Examples/RocketBurn/RocketBurn.cpp +++ b/Examples/RocketBurn/RocketBurn.cpp @@ -35,8 +35,6 @@ #include "simUtil/ExampleResources.h" #include "simUtil/PlatformSimulator.h" -#include "osgDB/ReadFile" - namespace { /// get time and platform removal notifications diff --git a/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp b/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp index af3168628..287973474 100644 --- a/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp +++ b/Examples/TimestampedLayer/ExampleTimestampedLayer.cpp @@ -31,7 +31,6 @@ #include "simVis/SceneManager.h" #include "simVis/Viewer.h" #include "simUtil/ExampleResources.h" -#include "osgDB/ReadFile" namespace ui = osgEarth::Util::Controls; diff --git a/SDK/simVis/Compass.cpp b/SDK/simVis/Compass.cpp index 59f2e4723..dc140a09f 100644 --- a/SDK/simVis/Compass.cpp +++ b/SDK/simVis/Compass.cpp @@ -29,7 +29,6 @@ #include "simVis/Utils.h" #include "simVis/View.h" #include "simVis/Compass.h" -#include "osgDB/ReadFile" namespace simVis { From ef032f7bc671da130deab2815b0ae705258b2d10 Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Fri, 31 Jan 2020 09:35:58 -0500 Subject: [PATCH 055/121] SIM-10171 Fixed SDK Scenario Start and End Times Release: simData::MemoryDataStore::timeBounds() for scenario times now account for deletes and flushes, but are now limited to platform TSPI points. Notes: Instead of maintaining the times, the times are calculate when needed. The calculated values only account for platform TSPI times, which is what SIMDIS expects. The original maintained times monitored all points and commands. The original times could have been larger than what SIMDIS expected. Test Environment: Windows 10, Visual Studio 2015, Debug Test: Ran SDK unit tests and manual testing with a Scenario Editor. Review: 20560 --- SDK/simData/MemoryDataStore.cpp | 27 ++++++++++++++------------- SDK/simData/MemoryDataStore.h | 4 ---- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/SDK/simData/MemoryDataStore.cpp b/SDK/simData/MemoryDataStore.cpp index 05c7d89b8..1a5ec9e54 100644 --- a/SDK/simData/MemoryDataStore.cpp +++ b/SDK/simData/MemoryDataStore.cpp @@ -331,7 +331,6 @@ MemoryDataStore::MemoryDataStore() hasChanged_(false), interpolationEnabled_(false), interpolator_(NULL), - timeBounds_(std::numeric_limits::max(), -std::numeric_limits::max()), newUpdatesListener_(new DefaultNewUpdatesListener), dataLimiting_(false), categoryNameManager_(new CategoryNameManager), @@ -353,7 +352,6 @@ MemoryDataStore::MemoryDataStore(const ScenarioProperties &properties) hasChanged_(false), interpolationEnabled_(false), interpolator_(NULL), - timeBounds_(std::numeric_limits::max(), -std::numeric_limits::max()), newUpdatesListener_(new DefaultNewUpdatesListener), dataLimiting_(false), categoryNameManager_(new CategoryNameManager), @@ -2655,7 +2653,6 @@ void MemoryDataStore::NewUpdateTransactionImpl::commit() dataStore_->hasChanged_ = true; if (isEntityUpdate_) { - dataStore_->newTimeBound_(updateTime); // Notify the data store's new-update callback dataStore_->newUpdatesListener().onEntityUpdate(dataStore_, id_, updateTime); } @@ -2739,15 +2736,6 @@ MemoryDataStore::NewScenarioGenericUpdateTransactionImpl::~NewScen } //---------------------------------------------------------------------------- -// Updates the scenario time bounds with a new time -void MemoryDataStore::newTimeBound_(double timeVal) -{ - if (timeVal < 0.0) - return; - - timeBounds_.first = simCore::sdkMin(timeVal, timeBounds_.first); - timeBounds_.second = simCore::sdkMax(timeVal, timeBounds_.second); -} /// Helper function to set a pair<> to min/max bounds for an XyzEntry; returns 0 when minMax is changed template MemoryDataStore::timeBounds(ObjectId entityId) const std::pair MemoryDataStore::timeBounds() const { - return timeBounds_; + double min = std::numeric_limits::max(); + double max = -std::numeric_limits::max(); + + for (auto it = platforms_.begin(); it != platforms_.end(); ++it) + { + const auto updates = it->second->updates(); + if ((updates->numItems() == 0) || (updates->firstTime() < 0.0)) + continue; + + min = simCore::sdkMin(min, updates->firstTime()); + max = simCore::sdkMax(max, updates->lastTime()); + } + + return std::pair(min, max); } } diff --git a/SDK/simData/MemoryDataStore.h b/SDK/simData/MemoryDataStore.h index 6261eb499..8503f8bf3 100644 --- a/SDK/simData/MemoryDataStore.h +++ b/SDK/simData/MemoryDataStore.h @@ -652,7 +652,6 @@ class SDKDATA_EXPORT MemoryDataStore : public DataStore CustomRenderings customRenderings_; GenericDataMap genericData_; // Map to hold references for GenericData update slice contained by the DataEntry object with the associated id CategoryDataMap categoryData_; // Map to hold references for CategoryData update slice contained by the DataEntry object with the associated id - std::pair timeBounds_; // First and last time recorded in scenario; might change when adding points or data limiting // default prefs objects PlatformPrefs defaultPlatformPrefs_; @@ -663,9 +662,6 @@ class SDKDATA_EXPORT MemoryDataStore : public DataStore ProjectorPrefs defaultProjectorPrefs_; CustomRenderingPrefs defaultCustomRenderingPrefs_; - // Updates the contents of timeBounds_ - void newTimeBound_(double timeVal); - /// Observers to receive notifications when things change ListenerList listeners_; /// Observers to receive notifications when things change From b4eb3b50e5fc74c9af53477588b1140c575322fa Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Mon, 3 Feb 2020 12:36:16 -0500 Subject: [PATCH 056/121] DEV: SDK: simVis GogNodeInterface checks if altmode is supported before using local variable, fixes valgrind complaint, review 20576 --- SDK/simVis/GOG/GogNodeInterface.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/SDK/simVis/GOG/GogNodeInterface.cpp b/SDK/simVis/GOG/GogNodeInterface.cpp index 5078f24c3..ae9b65825 100644 --- a/SDK/simVis/GOG/GogNodeInterface.cpp +++ b/SDK/simVis/GOG/GogNodeInterface.cpp @@ -541,15 +541,16 @@ void GogNodeInterface::serializeToStream(std::ostream& gogOutputStream) // altitude mode simVis::GOG::AltitudeMode altMode; - getAltitudeMode(altMode); - if (altMode == simVis::GOG::ALTITUDE_NONE && metaData_.isSetExplicitly(GOG_ALTITUDE_MODE_SET)) - gogOutputStream << "altitudemode none\n"; - else if (altMode == simVis::GOG::ALTITUDE_GROUND_RELATIVE) - gogOutputStream << "altitudemode relativetoground\n"; - else if (altMode == simVis::GOG::ALTITUDE_GROUND_CLAMPED) - gogOutputStream << "altitudemode clamptoground\n"; - // simVis::GOG::ALTITUDE_EXTRUDE is covered by the extrude keyword - + if (getAltitudeMode(altMode) == 0) + { + if (altMode == simVis::GOG::ALTITUDE_NONE && metaData_.isSetExplicitly(GOG_ALTITUDE_MODE_SET)) + gogOutputStream << "altitudemode none\n"; + else if (altMode == simVis::GOG::ALTITUDE_GROUND_RELATIVE) + gogOutputStream << "altitudemode relativetoground\n"; + else if (altMode == simVis::GOG::ALTITUDE_GROUND_CLAMPED) + gogOutputStream << "altitudemode clamptoground\n"; + // simVis::GOG::ALTITUDE_EXTRUDE is covered by the extrude keyword + } // Follow data is not currently serialized out } From 77389239c7da97fcd19e0cf99189177f323d0ba8 Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Mon, 3 Feb 2020 13:12:54 -0500 Subject: [PATCH 057/121] SIM-10991 Fixed A Failure To Delete Projectors Release: simData::MemoryDataStore::removeEntity() now correctly deletes projectors owned by a deleted beam. Notes: This fixes a problem, but not the problem. Found this problem while attempting to use the Scenario Editor to simplify the scenario for debugging purposes. Test Environment: Windows 10, Visual Studio 2015, Debug Test: Scenario Editor no longer crashes when editing projectedTexture.asi Review: 20572 --- SDK/simData/MemoryDataStore.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SDK/simData/MemoryDataStore.cpp b/SDK/simData/MemoryDataStore.cpp index 1a5ec9e54..302aa2a13 100644 --- a/SDK/simData/MemoryDataStore.cpp +++ b/SDK/simData/MemoryDataStore.cpp @@ -1508,8 +1508,9 @@ void MemoryDataStore::removeEntity(ObjectId id) Beams::iterator bi = beams_.find(id); if (bi != beams_.end()) { - // also delete any gates + // also delete any gates or projectors; projectorIdListForHost adds to the list gateIdListForHost(id, &ids); + projectorIdListForHost(id, &ids); // we will need to send notifications and recurse on them as well... for (IdList::const_iterator i = ids.begin(); i != ids.end(); ++i) removeEntity(*i); From 87c58d408963d559a699a6c2d1c8137d4ac978f9 Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Tue, 4 Feb 2020 11:55:34 -0500 Subject: [PATCH 058/121] SIM-10995 Updated simCore::getAngleString() to Handle 360 Degrees (1 of 2 SDK) Release: simCore::getAngleString() now shows 0 degrees for 360 degrees. Notes: The legacy PlotXY worked because it used the UTILS version of this routine that had a check for 360. Both Plot and SIMDIS-X have the same problem, so fixing it in a common area. Test Environment: Windows 10, Visual Studio 2015, Debug Test: Updated and ran unit test. Plot and SIMDIS-X now generate better results. Review: 20582 --- SDK/simCore/String/Angle.cpp | 9 +++++++++ Testing/SimCore/AngleTest.cpp | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/SDK/simCore/String/Angle.cpp b/SDK/simCore/String/Angle.cpp index 14f8a22ec..215bdd8b2 100644 --- a/SDK/simCore/String/Angle.cpp +++ b/SDK/simCore/String/Angle.cpp @@ -218,6 +218,9 @@ std::string getAngleString(double radianAngle, GeodeticFormat format, bool allNu } } + // degreeAngle was floor() above so just checking for 360 is OK + if (degreeAngle == 360.0) + degreeAngle = 0.0; degreeAngle = (negative && printNegativeSign) ? -degreeAngle : degreeAngle; std::stringstream strDeg; @@ -257,6 +260,9 @@ std::string getAngleString(double radianAngle, GeodeticFormat format, bool allNu } } + // degreeAngle was floor() above so just checking for 360 is OK + if (degreeAngle == 360.0) + degreeAngle = 0.0; degreeAngle = (negative && printNegativeSign) ? -degreeAngle : degreeAngle; std::stringstream strDeg; @@ -285,6 +291,9 @@ std::string getAngleString(double radianAngle, GeodeticFormat format, bool allNu case FMT_DEGREES: default: { + const double rounding = 5.0 / pow(10.0, precision + 1.0); + if ((degreeAngle + rounding > 360.0) || simCore::areEqual(degreeAngle + rounding, 360.0)) + degreeAngle = 0.0; degreeAngle = (negative && printNegativeSign) ? -degreeAngle : degreeAngle; std::stringstream str; str.setf(std::ios::fixed, std::ios::floatfield); diff --git a/Testing/SimCore/AngleTest.cpp b/Testing/SimCore/AngleTest.cpp index 93d78ec3a..c88ff2191 100644 --- a/Testing/SimCore/AngleTest.cpp +++ b/Testing/SimCore/AngleTest.cpp @@ -575,6 +575,38 @@ int testSim7284() return rv; } +int test360() +{ + int rv = 0; + + // test precision + rv += SDK_ASSERT(simCore::getAngleString(360.0 * simCore::DEG2RAD, simCore::FMT_DEGREES, true, 0, simCore::DEG_SYM_NONE, 0, 0) == "0"); + rv += SDK_ASSERT(simCore::getAngleString(360.0 * simCore::DEG2RAD, simCore::FMT_DEGREES, true, 1, simCore::DEG_SYM_NONE, 0, 0) == "0.0"); + rv += SDK_ASSERT(simCore::getAngleString(360.0 * simCore::DEG2RAD, simCore::FMT_DEGREES, true, 2, simCore::DEG_SYM_NONE, 0, 0) == "0.00"); + rv += SDK_ASSERT(simCore::getAngleString(360.0 * simCore::DEG2RAD, simCore::FMT_DEGREES, true, 3, simCore::DEG_SYM_NONE, 0, 0) == "0.000"); + rv += SDK_ASSERT(simCore::getAngleString(360.0 * simCore::DEG2RAD, simCore::FMT_DEGREES, true, 4, simCore::DEG_SYM_NONE, 0, 0) == "0.0000"); + rv += SDK_ASSERT(simCore::getAngleString(360.0 * simCore::DEG2RAD, simCore::FMT_DEGREES, true, 5, simCore::DEG_SYM_NONE, 0, 0) == "0.00000"); + rv += SDK_ASSERT(simCore::getAngleString(360.0 * simCore::DEG2RAD, simCore::FMT_DEGREES, true, 6, simCore::DEG_SYM_NONE, 0, 0) == "0.000000"); + rv += SDK_ASSERT(simCore::getAngleString(360.0 * simCore::DEG2RAD, simCore::FMT_DEGREES, true, 7, simCore::DEG_SYM_NONE, 0, 0) == "0.0000000"); + + // test degrees + rv += SDK_ASSERT(simCore::getAngleString(360.0005 * simCore::DEG2RAD, simCore::FMT_DEGREES, true, 3, simCore::DEG_SYM_NONE, 0, 0) == "0.000"); + rv += SDK_ASSERT(simCore::getAngleString(359.9995 * simCore::DEG2RAD, simCore::FMT_DEGREES, true, 3, simCore::DEG_SYM_NONE, 0, 0) == "0.000"); + rv += SDK_ASSERT(simCore::getAngleString(359.99949 * simCore::DEG2RAD, simCore::FMT_DEGREES, true, 3, simCore::DEG_SYM_NONE, 0, 0) == "359.999"); + + // test degree-minutes + rv += SDK_ASSERT(simCore::getAngleString(dmsAsRadian(359.0, 59.9995, 0.0), simCore::FMT_DEGREES_MINUTES, true, 3, simCore::DEG_SYM_NONE, 0, 0) == "0 00.000"); + rv += SDK_ASSERT(simCore::getAngleString(dmsAsRadian(359.0, 59.9995, 0.0), simCore::FMT_DEGREES_MINUTES, true, 3, simCore::DEG_SYM_NONE, 0, 0) == "0 00.000"); + rv += SDK_ASSERT(simCore::getAngleString(dmsAsRadian(359.0, 59.99949, 0.0), simCore::FMT_DEGREES_MINUTES, true, 3, simCore::DEG_SYM_NONE, 0, 0) == "359 59.999"); + + // test degree-minute-seconds + rv += SDK_ASSERT(simCore::getAngleString(dmsAsRadian(359.0, 59.0, 59.9995), simCore::FMT_DEGREES_MINUTES_SECONDS, true, 3, simCore::DEG_SYM_NONE, 0, 0) == "0 00 00.000"); + rv += SDK_ASSERT(simCore::getAngleString(dmsAsRadian(359.0, 59.0, 59.9995), simCore::FMT_DEGREES_MINUTES_SECONDS, true, 3, simCore::DEG_SYM_NONE, 0, 0) == "0 00 00.000"); + rv += SDK_ASSERT(simCore::getAngleString(dmsAsRadian(359.0, 59.0, 59.99949), simCore::FMT_DEGREES_MINUTES_SECONDS, true, 3, simCore::DEG_SYM_NONE, 0, 0) == "359 59 59.999"); + + return rv; +} + } int AngleTest(int argc, char* argv[]) @@ -589,6 +621,7 @@ int AngleTest(int argc, char* argv[]) rv += testSim2511(); rv += testSim4481(); rv += testSim7284(); + rv += test360(); return rv; } From 1e7d93acc7fa4a289d06a8edec1b2f96ba0fcde1 Mon Sep 17 00:00:00 2001 From: Andrew LaFrance Date: Wed, 5 Feb 2020 12:51:56 -0500 Subject: [PATCH 059/121] SDK BUGFIX: simCore::calculateRelAng() updated to more correctly calculate composite angle. Dev: Updated simCore::calculateRelAng() for correctness compared to UtilsRestricted and outside apps. Migrated test data from UtilsRestricted and outside apps to create unit test. Updated related unit test. SIM-10098, Review #20594. --- SDK/simCore/Calc/Calculations.cpp | 27 ++++++---- Testing/SimCore/CalculateInput.txt | 19 ++++--- Testing/SimCore/CalculateLibTest.cpp | 4 ++ Testing/SimCore/CalculationTest.cpp | 74 ++++++++++++++++++++++++---- 4 files changed, 97 insertions(+), 27 deletions(-) diff --git a/SDK/simCore/Calc/Calculations.cpp b/SDK/simCore/Calc/Calculations.cpp index 4e548cc79..8f9446293 100644 --- a/SDK/simCore/Calc/Calculations.cpp +++ b/SDK/simCore/Calc/Calculations.cpp @@ -1058,16 +1058,16 @@ void calculateRelAng(const Vec3 &enuVec, const Vec3 &refOri, double *azim, doubl return; } + // compute an inertial pointing vector based on ENU vector + Vec3 pntVec; + calculateBodyUnitX(atan2(enuVec[0], enuVec[1]), atan2(enuVec[2], sqrt(square(enuVec[0]) + square(enuVec[1]))), pntVec); + if (azim || elev) { // compute rotation matrix based on reference geodetic Euler angles double rotMat[3][3]; d3EulertoDCM(refOri, rotMat); - // compute an inertial pointing vector based on ENU vector - Vec3 pntVec; - calculateBodyUnitX(atan2(enuVec[0], enuVec[1]), atan2(enuVec[2], sqrt(square(enuVec[0]) + square(enuVec[1]))), pntVec); - // rotate inertial pointing vector to an body pointing vector Vec3 body; d3Mv3Mult(rotMat, pntVec, body); @@ -1083,14 +1083,13 @@ void calculateRelAng(const Vec3 &enuVec, const Vec3 &refOri, double *azim, doubl *elev = el; } - // compute composite angle between an ENU and a reference vector + // compute composite angle between body pointing vector and inertial pointing vector if (cmp) { - Vec3 pntVec; - pntVec[0] = sin(refOri[0]); - pntVec[1] = cos(refOri[0]); - pntVec[2] = tan(refOri[1]); - *cmp = v3Angle(pntVec, enuVec); + Vec3 bodyPnt; + calculateBodyUnitX(refOri.yaw(), refOri.pitch(), bodyPnt); + + *cmp = v3Angle(bodyPnt, pntVec); } } @@ -1477,6 +1476,14 @@ void calculateVelocity(const double speed, const double heading, const double pi */ void calculateAoaSideslipTotalAoa(const Vec3& enuVel, const Vec3& ypr, const bool useRoll, double* aoa, double* ss, double* totalAoa) { + if (v3Length(enuVel) == 0.0) + { + if (aoa) *aoa = 0.0; + if (ss) *ss = 0.0; + if (totalAoa) *totalAoa = 0.0; + return; + } + // aerodynamic version that accounts for roll Vec3 refOri = ypr; if (!useRoll) diff --git a/Testing/SimCore/CalculateInput.txt b/Testing/SimCore/CalculateInput.txt index c7d94bce5..a7c1aeb23 100644 --- a/Testing/SimCore/CalculateInput.txt +++ b/Testing/SimCore/CalculateInput.txt @@ -1,3 +1,4 @@ +#CommentsDenotedByPoundSymbols #TokensSeparatedByWhitespace SlantWGS84 0.0 0.0 0.0 -1.510 -2.7578684014 871.0 -1.132313619501204 0.84955592154 9.0 3124784.7428872650489211082458496 @@ -117,21 +118,22 @@ AltitudeWGS84 0.0 0.0 0.0 -1.433629385640828 2.159265359 -.21 1.183185307179587 -2.3 -23 -22.78999999999999914734871708788 +#DataGeneratedFromFunctionOutput #ValidatedByComparingToVisuals RelAzElWGS84 0.0 0.0 0.0 -1.510 -2.7578684014 871.0 -1.510 -2.7578684014 871.0 -1.132313619501204 0.84955592154 9.0 -1.811564973914540077 0.398742617007379 1.34924549366009 +1.811564973914540077 0.398742617007379 1.7923471599273946 RelAzElWGS84 0.0 0.0 0.0 0.6840734641 -2.6637061436 51.1 0.6840734641 -2.6637061436 51.1 -2.30044407846 0.1 121.3 --0.048195906359514699424106964897874 0.45782027167140448842275191054796 2.6814213599191192294313168531517 +-0.048195906359514699424106964897874 0.45782027167140448842275191054796 0.46017129367829990 RelAzElWGS84 0.0 0.0 0.0 0.35666117692 -1.657549333841125 -11.1023 0.35666117692 -1.657549333841125 -11.1023 2.632143634355323 -0.043985825177 3.0 --0.34565999739436814586213131406112 -0.8506080014202469508077797399892 2.2401976393892812922103985329159 +-0.34565999739436814586213131406112 -0.8506080014202469508077797399892 0.90139501420067314 RelAzElWGS84 0.0 0.0 0.0 -1.433629385640828 2.159265359 -.21 -1.433629385640828 2.159265359 -.21 1.183185307179587 -2.3 -23 -2.8872070110227614492259817779996 0.73938453896693745459600677349954 0.77402240546564760048653397461749 +2.8872070110227614492259817779996 0.73938453896693745459600677349954 2.3675702481027798 AspectAngleWGS84 0.0 0.0 0.0 0 0 0 0 0.001 0 0 0 0 @@ -350,21 +352,22 @@ AltitudeTangentPlaneWGS84 2.3 -70.0 0.0 -1.433629385640828 2.159265359 -.21 1.183185307179587 -2.3 -23 -12267014.51663341 +#DataGeneratedFromFunctionOutput #ValidatedByComparingToVisuals RelAzElTangentPlaneWGS84 2.3 -70.0 0.0 -1.510 -2.7578684014 871.0 -1.510 -2.7578684014 871.0 -1.132313619501204 0.84955592154 9.0 -1.8115649739145400776152428079513 0.3987426170073795628212565134163 1.3492454936600932757784221394104 +1.8115649739145400776152428079513 0.3987426170073795628212565134163 1.7923471599273946 RelAzElTangentPlaneWGS84 2.3 -70.0 0.0 0.6840734641 -2.6637061436 51.1 0.6840734641 -2.6637061436 51.1 -2.30044407846 0.1 121.3 --0.048195906359514699424106964897874 0.45782027167140448842275191054796 2.6814213599191192294313168531517 +-0.048195906359514699424106964897874 0.45782027167140448842275191054796 0.46017129367829990 RelAzElTangentPlaneWGS84 2.3 -70.0 0.0 0.35666117692 -1.657549333841125 -11.1023 0.35666117692 -1.657549333841125 -11.1023 2.632143634355323 -0.043985825177 3.0 --0.34565999739436814586213131406112 -0.8506080014202469508077797399892 2.2401976393892812922103985329159 +-0.34565999739436814586213131406112 -0.8506080014202469508077797399892 0.90139501420067314 RelAzElTangentPlaneWGS84 2.3 -70.0 0.0 -1.433629385640828 2.159265359 -.21 -1.433629385640828 2.159265359 -.21 1.183185307179587 -2.3 -23 -2.8872070110227614492259817779996 0.73938453896693745459600677349954 0.77402240546564760048653397461749 +2.8872070110227614492259817779996 0.73938453896693745459600677349954 2.3675702481027798 AbsAzElTangentPlaneWGS84 2.3 -70.0 0.0 -1.510 -2.7578684014 871.0 -1.132313619501204 0.84955592154 9.0 diff --git a/Testing/SimCore/CalculateLibTest.cpp b/Testing/SimCore/CalculateLibTest.cpp index 0d8f5e38c..f12bcd316 100644 --- a/Testing/SimCore/CalculateLibTest.cpp +++ b/Testing/SimCore/CalculateLibTest.cpp @@ -352,6 +352,10 @@ int readNextTest(std::istream& fd, bool& doneReading) return 0; } + // Check for comments + if (test.compare(0, 1, "#") == 0) + return 0; + int rv = 0; simCore::EarthModelCalculations earth = simCore::PERFECT_SPHERE; // set coordinate system / reference frame diff --git a/Testing/SimCore/CalculationTest.cpp b/Testing/SimCore/CalculationTest.cpp index 0d0fd5012..89408b8fc 100644 --- a/Testing/SimCore/CalculationTest.cpp +++ b/Testing/SimCore/CalculationTest.cpp @@ -1641,29 +1641,84 @@ int testTaos_intercept() return rv; } +int testAoaSideslipTotalAoa() +{ + int rv = 0; + + double testParams[24][9] = { + // Test data generated by the TAOS application. NOTE: "Expected SS" values are multiplied by -1 since SIMDIS looks at the angle from the opposite perspective + // Yaw (rad), Pitch (rad), Roll (rad), EastVel (any), NorthVel (any), UpVel (any), Expected AOA (rad), Expected SS (rad), Expected TotalAOA (rad) + { 1.5708, 1.10174, -0, 821.82, 0.00, 2361.06, -0.134094, 0.0, 0.134094}, + { 1.5708, 1.11942, 0, 1586.49, 0.00, 3415.72, -0.0165457, 0.0, 0.0165457}, + { -0.610534, 1.17927, 1.23123, -177.65, 253.79, 750.82, 0.0, 0.000226893, 0.000226893}, + { -0.61104, 1.17183, 2.55434, -234.34, 334.76, 969.44, -0.0, 0.000122173, 0.000122173}, + { -0.613221, 1.06195, -0.967192, -718.09, 1019.66, 2236.20, -0.000191986, -0.0, 0.000191986}, // 5 + { -0.613954, 1.04884, -1.68339, -797.25, 1131.13, 2406.03, 0.0, 0.0, 0.0}, + { -0.610499, 1.19477, 0.208253, -97.99, 139.93, 434.25, -0.00118682, 0.000401426, 0.00125664}, + { -0.609713, 1.18536, 0.393799, -119.45, 170.64, 519.99, -0.0039619, 0.00205949, 0.00445059}, + // Test values taken from UtilsRestricted::testCalculateAngleOfAttack. + // NOTE: Existing data only contained values for TotalAOA, so AOA and SS values are filled in based on results here + // Yaw (rad), Pitch (rad), Roll (rad), EastVel (any), NorthVel (any), UpVel (any), Expected AOA (rad), Expected SS (rad), Expected TotalAOA (rad) + { 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Should return all zeroes, since no Velocity + { 0.49037, 3.76566, 5.4944, 0, 0, 0, 0, 0, 0}, // 10 + { 0, 0, 0, 16644.39016, 29208.15583, -28846.88083, 0.709169, -0.517958, 0.85083}, + { 0.49037, 3.76566, 5.4944, 16644.39016, 29208.15583, -28846.88083, -0.734134, -1.89301, 1.808114}, + { 0.49037, 3.76566, 5.4944, 1, 1, -1, -0.504567, -1.91646, 1.871923}, + { 3.14159, 3.14159, 3.14159, 1, 1, -1, 0.615483, -0.785401, 0.95532}, + { 1, 1, 1, 1, 1, -1, 0.744443, -1.64536, 1.625611}, // 15 + { 10.84689, -9.9035, -0.86838, 1, 1, -1, -0.156555, -1.24436, 1.248493}, + { 10.84689, -9.9035, -0.86838, 0, 0, -1, -0.610694, -2.16793, 2.049518}, + { 10.84689, -9.9035, -0.86838, 1, 0, -1, -0.766407, -1.14895, 1.271375}, + { 10.84689, -9.9035, -0.86838, 0, 1, -1, 0.0972667, -1.80684, 1.805702}, + { 10.84689, -9.9035, -0.86838, 1, 1, 0, 0.216204, -0.751484, 0.776078}, // 20 + { 10.84689, -9.9035, -0.86838, 0, 1, 0, 0.7906, -1.38277, 1.43893}, + { -5.60301, 10.17163, 11.52466, 43166.64503, 15583.04935, -7141.456008, 0.094936, -2.11559, 2.112865}, + { -10.49650, 2.62059, -6.6306, 13531.13069, 13212.05930, -19061.39684, -0.791297, 2.43112, 2.132763}, + { -0.40684, -11.84026, -9.24658, 6985.30190, 37348.59157, -15209.51840, -0.754879, 1.10146, 1.235094} // 24 + }; + + const double tolerance = 0.01 * simCore::DEG2RAD; + size_t testCaseCount = sizeof(testParams) / sizeof(testParams[0]); + for (size_t i = 0; i < testCaseCount; ++i) + { + double* val = testParams[i]; + const simCore::Vec3 yprVec((*val), (*(val + 1)), (*(val + 2))); + const simCore::Vec3 enuVec(*(val + 3), *(val + 4), *(val + 5)); + double aoa; + double ss; + double totalAoa; + simCore::calculateAoaSideslipTotalAoa(enuVec, yprVec, true, &aoa, &ss, &totalAoa); + SDK_ASSERT(simCore::areAnglesEqual(aoa, *(val + 6), tolerance)); + SDK_ASSERT(simCore::areAnglesEqual(ss, *(val + 7), tolerance)); + SDK_ASSERT(simCore::areAnglesEqual(totalAoa, *(val + 8), tolerance)); + } + + return rv; +} + int testBoresightAlphaBeta() { - int rv = 0; // Test Data uses X-East coordinates in meters; Yaw, Pitch, and Roll as well as expected Azimuth, Elevation, and Composite are in degrees - // Before passed into calculateRelAzEl(), X-East coordinates are converted to LLA (decimal degrees) and degrees are converted into radians + int rv = 0; // Test Data uses X-East coordinates in meters; Yaw, Pitch, and Roll as well as expected Azimuth, Elevation, and Composite are in degrees + // Before passed into calculateRelAzEl(), X-East coordinates are converted to LLA (decimal degrees) and degrees are converted into radians //{ FromX, FromY, FromZ, Yaw, Pitch, Roll, ToX, ToY, ToZ, ExpAzim, ExpElev, ExpComAng} double paramsTest[15][12] = { { 0.0, 0.0, 0.0, 0.00, 0.00, 0.00, 0.0, 0.0, 0.0, 0.00, 0.00, 0.0}, // Changing Lat & Long { 0.0, 0.0, 0.0, 0.00, 0.00, 0.00, 0.0, 1000.0, 0.0, 0.00, 0.00, 0.0}, - { 0.0, 0.0, 0.0, 0.00, 0.00, 0.00, 1000.0, 1000.0, 0.0, 45.00, 0.00, 45.00}, + { 0.0, 0.0, 0.0, 0.00, 0.00, 0.00, 1000.0, 1000.0, 0.0, 45.00, 0.00, 45.00}, { 0.0, 0.0, 0.0, 0.00, 0.00, 0.00, 1000.0, 0.0, 0.0, 90.00, 0.00, 90.00}, { 0.0, 0.0, 0.0, 0.00, 0.00, 0.00, 1000.0, -1000.0, 0.0, 135.00, 0.00, 135.00}, // #5 { 0.0, 0.0, 0.0, 0.00, 0.00, 0.00, 0.0, 1000.0, 1000.0, 0.00, 45.00, 45.00}, // Changing Alt - { 0.0, 0.0, 0.0, 0.00, 0.00, 0.00, 1000.0, 1000.0, 1000.0, 45.00, 35.26, 54.73}, + { 0.0, 0.0, 0.0, 0.00, 0.00, 0.00, 1000.0, 1000.0, 1000.0, 45.00, 35.26, 54.73}, { 0.0, 0.0, 1000.0, 0.00, 0.00, 0.00, 1000.0, 0.0, 0.0, 90.00, -45.00, 90.00}, { 0.0, 1000.0, 1000.0, 0.00, 0.00, 0.00, 1000.0, -2000.0, 0.0, 161.56, -17.55, 154.75}, - { -3000.0, 4000.0, 3000.0, 0.00, 0.00, 0.00, -6000.0, -1000.0, 0.0, -149.01, -27.24, 139.65}, // #10 + { -3000.0, 4000.0, 3000.0, 0.00, 0.00, 0.00, -6000.0, -1000.0, 0.0, -149.01, -27.24, 139.65}, // #10 - { 0.0, 0.0, 0.0, 90.00, 0.00, 0.00, -1000.0, -1000.0, 0.0, 135.00, 0.00, 135.00}, // Changing YPR - { 0.0, 0.0, 0.0, 45.00, 45.00, 0.00, 0.0, -1000.0, 1000.0, 73.67, 58.60, 81.57}, + { 0.0, 0.0, 0.0, 90.00, 0.00, 0.00, -1000.0, -1000.0, 0.0, 135.00, 0.00, 135.00}, // Changing YPR + { 0.0, 0.0, 0.0, 45.00, 45.00, 0.00, 0.0, -1000.0, 1000.0, 73.67, 58.60, 81.57}, { 1000.0, -3000.0, 5000.0, 20.00, 20.00, -80.00, 1000.0, 1000.0, 2000.0, -59.67, 7.27, 59.94}, { 2000.0, 6000.0, 20000.0, -120.00, -30.00, 0.00, 1000.0, 1000.0, 0.0, -16.47, -49.30, 51.30}, - { 0.0, -4000.0, 0.0, 160.00, 45.00, 90.00, -3000.0, 2000.0, 5000.0, -98.15, 5.25, 98.11} // #15 - }; + { 0.0, -4000.0, 0.0, 160.00, 45.00, 90.00, -3000.0, 2000.0, 5000.0, -98.15, 5.25, 98.11} // #15 + }; const double tolerance = 0.01 * simCore::DEG2RAD; simCore::CoordinateConverter cc; @@ -1730,6 +1785,7 @@ int CalculationTest(int argc, char* argv[]) rv += testMidPointHighRes(); rv += testRandom(); rv += testTaos_intercept(); + rv += testAoaSideslipTotalAoa(); rv += testBoresightAlphaBeta(); return rv; From 563bd1741913d4f420b5a06d10f66cfb2f53d095 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Wed, 5 Feb 2020 13:34:07 -0500 Subject: [PATCH 060/121] DEV: NULL Safety checks added on pointer, turned into observer_ptr. Needed because owning class can be put in a shared_ptr and outlive the scenario. Part of SIM-10991. Review: 20605 --- SDK/simVis/ScenarioDataStoreAdapter.cpp | 39 ++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/SDK/simVis/ScenarioDataStoreAdapter.cpp b/SDK/simVis/ScenarioDataStoreAdapter.cpp index 7b9bd396e..6173b2c89 100644 --- a/SDK/simVis/ScenarioDataStoreAdapter.cpp +++ b/SDK/simVis/ScenarioDataStoreAdapter.cpp @@ -63,7 +63,8 @@ class MyListener : public simData::DataStore::Listener /// entity with the given id and type will be removed after all notifications are processed virtual void onRemoveEntity(simData::DataStore *source, simData::ObjectId removedId, simData::ObjectType ot) { - scenarioManager_->removeEntity(removedId); + if (scenarioManager_.valid()) + scenarioManager_->removeEntity(removedId); } /// prefs for the given entity have been changed @@ -87,7 +88,8 @@ class MyListener : public simData::DataStore::Listener /// current time has been changed virtual void onTimeChange(simData::DataStore *source) { - scenarioManager_->update(source); + if (scenarioManager_.valid()) + scenarioManager_->update(source); } /// something has changed in the entity category data @@ -105,7 +107,8 @@ class MyListener : public simData::DataStore::Listener /// entity's data was flushed, 0 means entire scenario was flushed virtual void onFlush(simData::DataStore *source, simData::ObjectId flushedId) { - scenarioManager_->flush(flushedId); + if (scenarioManager_.valid()) + scenarioManager_->flush(flushedId); } /// The scenario is about to be deleted @@ -117,6 +120,8 @@ class MyListener : public simData::DataStore::Listener private: // methods void addPlatform_(simData::DataStore &ds, simData::ObjectId newId) const { + if (!scenarioManager_.valid()) + return; simData::PlatformProperties props; simData::DataStore::Transaction xaction; const simData::PlatformProperties *liveProps = ds.platformProperties(newId, &xaction); @@ -129,6 +134,8 @@ class MyListener : public simData::DataStore::Listener void addBeam_(simData::DataStore &ds, simData::ObjectId newId) const { + if (!scenarioManager_.valid()) + return; simData::BeamProperties props; simData::DataStore::Transaction xaction; @@ -142,6 +149,8 @@ class MyListener : public simData::DataStore::Listener void addGate_(simData::DataStore &ds, simData::ObjectId newId) const { + if (!scenarioManager_.valid()) + return; simData::GateProperties props; simData::DataStore::Transaction xaction; const simData::GateProperties *liveProps = ds.gateProperties(newId, &xaction); @@ -154,6 +163,8 @@ class MyListener : public simData::DataStore::Listener void addProjector_(simData::DataStore &ds, simData::ObjectId newId) const { + if (!scenarioManager_.valid()) + return; simData::ProjectorProperties props; simData::DataStore::Transaction xaction; const simData::ProjectorProperties *liveProps = ds.projectorProperties(newId, &xaction); @@ -166,6 +177,8 @@ class MyListener : public simData::DataStore::Listener void addLaser_(simData::DataStore &ds, simData::ObjectId newId) const { + if (!scenarioManager_.valid()) + return; simData::LaserProperties props; simData::DataStore::Transaction xaction; const simData::LaserProperties *liveProps = ds.laserProperties(newId, &xaction); @@ -178,6 +191,8 @@ class MyListener : public simData::DataStore::Listener void addLobGroup_(simData::DataStore &ds, simData::ObjectId newId) const { + if (!scenarioManager_.valid()) + return; simData::LobGroupProperties props; simData::DataStore::Transaction xaction; const simData::LobGroupProperties *liveProps = ds.lobGroupProperties(newId, &xaction); @@ -190,6 +205,8 @@ class MyListener : public simData::DataStore::Listener void addCustomRendering_(simData::DataStore &ds, simData::ObjectId newId) const { + if (!scenarioManager_.valid()) + return; simData::CustomRenderingProperties props; simData::DataStore::Transaction xaction; const simData::CustomRenderingProperties *liveProps = ds.customRenderingProperties(newId, &xaction); @@ -202,6 +219,8 @@ class MyListener : public simData::DataStore::Listener void changePlatformPrefs_(simData::DataStore &ds, simData::ObjectId id) { + if (!scenarioManager_.valid()) + return; simData::PlatformPrefs prefs; simData::DataStore::Transaction xaction; const simData::PlatformPrefs* livePrefs = ds.platformPrefs(id, &xaction); @@ -213,6 +232,8 @@ class MyListener : public simData::DataStore::Listener void changeBeamPrefs_(simData::DataStore &ds, simData::ObjectId id) { + if (!scenarioManager_.valid()) + return; simData::BeamPrefs prefs; simData::DataStore::Transaction xaction; const simData::BeamPrefs* livePrefs = ds.beamPrefs(id, &xaction); @@ -224,6 +245,8 @@ class MyListener : public simData::DataStore::Listener void changeGatePrefs_(simData::DataStore &ds, simData::ObjectId id) { + if (!scenarioManager_.valid()) + return; simData::GatePrefs prefs; simData::DataStore::Transaction xaction; const simData::GatePrefs* livePrefs = ds.gatePrefs(id, &xaction); @@ -235,6 +258,8 @@ class MyListener : public simData::DataStore::Listener void changeProjectorPrefs_(simData::DataStore &ds, simData::ObjectId id) { + if (!scenarioManager_.valid()) + return; simData::ProjectorPrefs prefs; simData::DataStore::Transaction xaction; const simData::ProjectorPrefs* livePrefs = ds.projectorPrefs(id, &xaction); @@ -246,6 +271,8 @@ class MyListener : public simData::DataStore::Listener void changeLaserPrefs_(simData::DataStore &ds, simData::ObjectId id) { + if (!scenarioManager_.valid()) + return; simData::LaserPrefs prefs; simData::DataStore::Transaction xaction; const simData::LaserPrefs* livePrefs = ds.laserPrefs(id, &xaction); @@ -257,6 +284,8 @@ class MyListener : public simData::DataStore::Listener void changeLobGroupPrefs_(simData::DataStore &ds, simData::ObjectId id) { + if (!scenarioManager_.valid()) + return; simData::LobGroupPrefs prefs; simData::DataStore::Transaction xaction; const simData::LobGroupPrefs* livePrefs = ds.lobGroupPrefs(id, &xaction); @@ -268,6 +297,8 @@ class MyListener : public simData::DataStore::Listener void changeCustomRenderingPrefs_(simData::DataStore &ds, simData::ObjectId id) { + if (!scenarioManager_.valid()) + return; simData::CustomRenderingPrefs prefs; simData::DataStore::Transaction xaction; const simData::CustomRenderingPrefs* livePrefs = ds.customRenderingPrefs(id, &xaction); @@ -278,7 +309,7 @@ class MyListener : public simData::DataStore::Listener } private: // data - simVis::ScenarioManager *scenarioManager_; + osg::observer_ptr scenarioManager_; }; // Observer for time clock mode changes From b1c94efdeaa22a7c8cc54ad96e6e1f0e6b44754b Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 6 Feb 2020 09:22:25 -0500 Subject: [PATCH 061/121] SDK NEWFEATURE: simCore::coordinateSystemToString() and simCore::coordinateSystemFromString() provide to- and from-string functionality for simCore::CoordinateSystem. Intended to be used in SIMDIS to reduce dependencies for SIM-10860. Review: 20623 --- SDK/simCore/CMakeLists.txt | 1 + SDK/simCore/Calc/CoordinateSystem.cpp | 95 +++++++++++++++++++++++++ SDK/simCore/Calc/CoordinateSystem.h | 20 ++++++ Testing/SimCore/CoordConvertLibTest.cpp | 51 +++++++++++++ 4 files changed, 167 insertions(+) create mode 100644 SDK/simCore/Calc/CoordinateSystem.cpp diff --git a/SDK/simCore/CMakeLists.txt b/SDK/simCore/CMakeLists.txt index 2a8514275..74974457c 100644 --- a/SDK/simCore/CMakeLists.txt +++ b/SDK/simCore/CMakeLists.txt @@ -52,6 +52,7 @@ set(CORE_CALC_SOURCES ${CORE_CALC_SRC}Angle.cpp ${CORE_CALC_SRC}Calculations.cpp ${CORE_CALC_SRC}CoordinateConverter.cpp + ${CORE_CALC_SRC}CoordinateSystem.cpp ${CORE_CALC_SRC}DatumConvert.cpp ${CORE_CALC_SRC}Gars.cpp ${CORE_CALC_SRC}Geometry.cpp diff --git a/SDK/simCore/Calc/CoordinateSystem.cpp b/SDK/simCore/Calc/CoordinateSystem.cpp new file mode 100644 index 000000000..ecc020ebc --- /dev/null +++ b/SDK/simCore/Calc/CoordinateSystem.cpp @@ -0,0 +1,95 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ +#include +#include "simCore/String/Format.h" +#include "simCore/Calc/CoordinateSystem.h" + +namespace simCore +{ + +// Coordinate system string constants, matching Rule Evaluation names for SIMDIS +static const std::string COORD_SYS_NED_STR = "Topo_NED"; +static const std::string COORD_SYS_NWU_STR = "Topo_NWU"; +static const std::string COORD_SYS_ENU_STR = "Topo_ENU"; +static const std::string COORD_SYS_LLA_STR = "LLA_DD"; +static const std::string COORD_SYS_ECEF_STR = "ECEF_WGS84"; +static const std::string COORD_SYS_XEAST_STR = "TangentPlane_XEast"; +static const std::string COORD_SYS_GTP_STR = "TangentPlane_Generic"; +static const std::string COORD_SYS_ECI_STR = "ECI_WGS84"; + +// We will read these strings as "LLA", but do not write them +static const std::string COORD_SYS_LLA_DMD_STR = "LLA_DMD"; +static const std::string COORD_SYS_LLA_DMS_STR = "LLA_DMS"; + +std::string coordinateSystemToString(simCore::CoordinateSystem coordSystem) +{ + switch (coordSystem) + { + case simCore::COORD_SYS_NED: return COORD_SYS_NED_STR; + case simCore::COORD_SYS_NWU: return COORD_SYS_NWU_STR; + case simCore::COORD_SYS_ENU: return COORD_SYS_ENU_STR; + case simCore::COORD_SYS_LLA: return COORD_SYS_LLA_STR; + case simCore::COORD_SYS_ECEF: return COORD_SYS_ECEF_STR; + case simCore::COORD_SYS_XEAST: return COORD_SYS_XEAST_STR; + case simCore::COORD_SYS_GTP: return COORD_SYS_GTP_STR; + case simCore::COORD_SYS_ECI: return COORD_SYS_ECI_STR; + case simCore::COORD_SYS_NONE: + case simCore::COORD_SYS_MAX: + assert(0); // Not supported + break; + } + // Default to ENU (from legacy code) + return COORD_SYS_ENU_STR; +} + +int coordinateSystemFromString(const std::string& str, simCore::CoordinateSystem& outSystem) +{ + if (simCore::caseCompare(str, COORD_SYS_NED_STR) == 0) + outSystem = simCore::COORD_SYS_NED; + else if (simCore::caseCompare(str, COORD_SYS_NWU_STR) == 0) + outSystem = simCore::COORD_SYS_NWU; + else if (simCore::caseCompare(str, COORD_SYS_LLA_DMS_STR) == 0) + outSystem = simCore::COORD_SYS_LLA; + else if (simCore::caseCompare(str, COORD_SYS_LLA_DMD_STR) == 0) + outSystem = simCore::COORD_SYS_LLA; + else if (simCore::caseCompare(str, COORD_SYS_LLA_STR) == 0) + outSystem = simCore::COORD_SYS_LLA; + else if (simCore::caseCompare(str, COORD_SYS_ECEF_STR) == 0) + outSystem = simCore::COORD_SYS_ECEF; + else if (simCore::caseCompare(str, COORD_SYS_ECI_STR) == 0) + outSystem = simCore::COORD_SYS_ECI; + else if (simCore::caseCompare(str, COORD_SYS_ENU_STR) == 0) + outSystem = simCore::COORD_SYS_ENU; + else if (simCore::caseCompare(str, COORD_SYS_XEAST_STR) == 0) + outSystem = simCore::COORD_SYS_XEAST; + else if (simCore::caseCompare(str, COORD_SYS_GTP_STR) == 0) + outSystem = simCore::COORD_SYS_GTP; + else + { + outSystem = simCore::COORD_SYS_LLA; + return 1; + } + + return 0; +} + +} diff --git a/SDK/simCore/Calc/CoordinateSystem.h b/SDK/simCore/Calc/CoordinateSystem.h index 37cc66425..780cc8aa0 100644 --- a/SDK/simCore/Calc/CoordinateSystem.h +++ b/SDK/simCore/Calc/CoordinateSystem.h @@ -22,6 +22,9 @@ #ifndef SIMCORE_CALC_COORDINATESYSTEM_H #define SIMCORE_CALC_COORDINATESYSTEM_H +#include +#include "simCore/Common/Common.h" + /// Container for enumerations and constants relating to coordinate system calculations and conversion namespace simCore { @@ -73,6 +76,23 @@ namespace simCore const double EARTH_ROTATION_RATE = 7292115.1467e-11; ///< (rad/sec) Earth's rotation rate: International Astronomical Union (IAU) GRS 67 const double LATLON_ERR_TOL_DOUBLE = 1.0e-10; ///< floating point error tolerance for geodetic angle conversions + /** + * Given a coordinate system, returns an appropriate string constant. + * @param coordSystem Coordinate system to get string value; COORD_SYS_MAX and COORD_SYS_NONE not supported. + * @return String representation of the coordinate system + */ + SDKCORE_EXPORT std::string coordinateSystemToString(simCore::CoordinateSystem coordSystem); + + /** + * Given a coordinate system string constant, returns the appropriate system, returning 0 on success. + * Inverse of simCore::coordinateSystemToString(), accepting strings that it returns. + * @param str Coordinate string to process, from output of coordinateSystemToString(). Also accepts, for + * legacy reasons, LLA_DMD and LLA_DMS, returning a valid COORD_SYS_LLA flag. + * @param outSystem Output parameter for the coordinate system string. + * @return 0 on success, non-zero on error. In error conditions, outSystem is initialized to simCore::COORD_SYS_LLA. + */ + SDKCORE_EXPORT int coordinateSystemFromString(const std::string& str, simCore::CoordinateSystem& outSystem); + } // End of namespace simCore #endif /* SIMCORE_CALC_COORDINATESYSTEM_H */ diff --git a/Testing/SimCore/CoordConvertLibTest.cpp b/Testing/SimCore/CoordConvertLibTest.cpp index a3e55a161..78b80ba77 100644 --- a/Testing/SimCore/CoordConvertLibTest.cpp +++ b/Testing/SimCore/CoordConvertLibTest.cpp @@ -970,6 +970,56 @@ int testScaledFlatEarth() return rv; } +int testStringFunctions() +{ + int rv = 0; + + // To-string testing + rv += SDK_ASSERT(simCore::coordinateSystemToString(simCore::COORD_SYS_NED) == "Topo_NED"); + rv += SDK_ASSERT(simCore::coordinateSystemToString(simCore::COORD_SYS_NWU) == "Topo_NWU"); + rv += SDK_ASSERT(simCore::coordinateSystemToString(simCore::COORD_SYS_ENU) == "Topo_ENU"); + rv += SDK_ASSERT(simCore::coordinateSystemToString(simCore::COORD_SYS_LLA) == "LLA_DD"); + rv += SDK_ASSERT(simCore::coordinateSystemToString(simCore::COORD_SYS_ECEF) == "ECEF_WGS84"); + rv += SDK_ASSERT(simCore::coordinateSystemToString(simCore::COORD_SYS_ECI) == "ECI_WGS84"); + rv += SDK_ASSERT(simCore::coordinateSystemToString(simCore::COORD_SYS_XEAST) == "TangentPlane_XEast"); + rv += SDK_ASSERT(simCore::coordinateSystemToString(simCore::COORD_SYS_GTP) == "TangentPlane_Generic"); + + // From-string testing + simCore::CoordinateSystem coordSys; + rv += SDK_ASSERT(simCore::coordinateSystemFromString("Topo_NED", coordSys) == 0); + rv += SDK_ASSERT(coordSys == simCore::COORD_SYS_NED); + // Test capitalization + rv += SDK_ASSERT(simCore::coordinateSystemFromString("topo_ned", coordSys) == 0); + rv += SDK_ASSERT(coordSys == simCore::COORD_SYS_NED); + rv += SDK_ASSERT(simCore::coordinateSystemFromString("TOPO_NED", coordSys) == 0); + rv += SDK_ASSERT(coordSys == simCore::COORD_SYS_NED); + + rv += SDK_ASSERT(simCore::coordinateSystemFromString("Topo_NWU", coordSys) == 0); + rv += SDK_ASSERT(coordSys == simCore::COORD_SYS_NWU); + rv += SDK_ASSERT(simCore::coordinateSystemFromString("Topo_ENU", coordSys) == 0); + rv += SDK_ASSERT(coordSys == simCore::COORD_SYS_ENU); + rv += SDK_ASSERT(simCore::coordinateSystemFromString("LLA_DD", coordSys) == 0); + rv += SDK_ASSERT(coordSys == simCore::COORD_SYS_LLA); + rv += SDK_ASSERT(simCore::coordinateSystemFromString("ECEF_WGS84", coordSys) == 0); + rv += SDK_ASSERT(coordSys == simCore::COORD_SYS_ECEF); + rv += SDK_ASSERT(simCore::coordinateSystemFromString("ECI_WGS84", coordSys) == 0); + rv += SDK_ASSERT(coordSys == simCore::COORD_SYS_ECI); + rv += SDK_ASSERT(simCore::coordinateSystemFromString("TangentPlane_XEast", coordSys) == 0); + rv += SDK_ASSERT(coordSys == simCore::COORD_SYS_XEAST); + rv += SDK_ASSERT(simCore::coordinateSystemFromString("TangentPlane_Generic", coordSys) == 0); + rv += SDK_ASSERT(coordSys == simCore::COORD_SYS_GTP); + + // Test the oddball LLA legacy strings + rv += SDK_ASSERT(simCore::coordinateSystemFromString("LLA_DMD", coordSys) == 0); + rv += SDK_ASSERT(coordSys == simCore::COORD_SYS_LLA); + rv += SDK_ASSERT(simCore::coordinateSystemFromString("LLA_DMS", coordSys) == 0); + rv += SDK_ASSERT(coordSys == simCore::COORD_SYS_LLA); + + std::cout << std::endl << "String Functions test case: "; + std::cout << (rv==0 ? "PASSED" : "FAILED") << std::endl; + return rv; +} + } //=========================================================================== @@ -1038,5 +1088,6 @@ int CoordConvertLibTest(int _argc_, char *_argv_[]) rv += testGtpRotation(); rv += testScaledFlatEarthPole(); rv += testScaledFlatEarth(); + rv += testStringFunctions(); return rv; } From 762cbe9624af7f87523922430ed3eb7fd5bcb2ee Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Thu, 6 Feb 2020 10:05:27 -0500 Subject: [PATCH 062/121] SIM-10168 Added non-const version of index() to simQt::EntityTreeModel (2 of 3 SDK) Release: simQt::EntityTreeModel now has a non-const version of index() method, which processes the delayed entity if the initial search did not find the entity. Notes: Need to complete the interface. Test Environment: Windows 10, Visual Studio 2015, Debug Test: Compile, it is a copy with one change from the PluginUtils version. Review: 20625 --- .../QtDesignerWidgets/EntityTreeCompositePlugin.h | 1 + SDK/simQt/AbstractEntityTreeModel.h | 3 +++ SDK/simQt/EntityTreeModel.cpp | 14 ++++++++++++++ SDK/simQt/EntityTreeModel.h | 2 ++ 4 files changed, 20 insertions(+) diff --git a/Plugins/QtDesignerWidgets/EntityTreeCompositePlugin.h b/Plugins/QtDesignerWidgets/EntityTreeCompositePlugin.h index 0964fb676..ba9567f4a 100644 --- a/Plugins/QtDesignerWidgets/EntityTreeCompositePlugin.h +++ b/Plugins/QtDesignerWidgets/EntityTreeCompositePlugin.h @@ -68,6 +68,7 @@ class QtDesignerDisplayTree : public simQt::AbstractEntityTreeModel virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; virtual QModelIndex index(int row, int column, const QModelIndex &parent) const { return QModelIndex(); } virtual QModelIndex index(uint64_t id) const { return QModelIndex(); } + virtual QModelIndex index(uint64_t id) { return QModelIndex(); } virtual uint64_t uniqueId(const QModelIndex &index) const { return 0; } virtual QModelIndex parent(const QModelIndex &index) const { return QModelIndex(); } virtual int rowCount(const QModelIndex &parent) const { return 0; } diff --git a/SDK/simQt/AbstractEntityTreeModel.h b/SDK/simQt/AbstractEntityTreeModel.h index 044907086..84e229dbb 100644 --- a/SDK/simQt/AbstractEntityTreeModel.h +++ b/SDK/simQt/AbstractEntityTreeModel.h @@ -58,6 +58,9 @@ namespace simQt { /** Return an Index based on the entity's ID */ virtual QModelIndex index(uint64_t id) const = 0; + /** Return an Index based on the entity's ID; if necessary, process any pending adds */ + virtual QModelIndex index(uint64_t id) = 0; + /** Return the entity's ID for a given index */ virtual uint64_t uniqueId(const QModelIndex &index) const = 0; diff --git a/SDK/simQt/EntityTreeModel.cpp b/SDK/simQt/EntityTreeModel.cpp index 4c3a3acb4..f22555733 100644 --- a/SDK/simQt/EntityTreeModel.cpp +++ b/SDK/simQt/EntityTreeModel.cpp @@ -627,6 +627,20 @@ QModelIndex EntityTreeModel::index(uint64_t id) const return QModelIndex(); } +QModelIndex EntityTreeModel::index(uint64_t id) +{ + EntityTreeItem* item = findItem_(id); + if (item == NULL) + { + commitDelayedEntities_(); + item = findItem_(id); + if (item == NULL) + return QModelIndex(); + } + + return createIndex(item->row(), 0, item); +} + uint64_t EntityTreeModel::uniqueId(const QModelIndex &index) const { if (!index.isValid()) diff --git a/SDK/simQt/EntityTreeModel.h b/SDK/simQt/EntityTreeModel.h index b5adc8956..43eae62a5 100644 --- a/SDK/simQt/EntityTreeModel.h +++ b/SDK/simQt/EntityTreeModel.h @@ -80,6 +80,8 @@ class SDKQT_EXPORT EntityTreeModel : public simQt::AbstractEntityTreeModel virtual QModelIndex index(int row, int column, const QModelIndex &parent) const; /// Return the index for the given id virtual QModelIndex index(uint64_t id) const; + /// Return an Index based on the entity's ID; if necessary, process any pending adds + virtual QModelIndex index(uint64_t id); /// Return the index of the parent of the item given by index virtual QModelIndex parent(const QModelIndex &index) const; /// Return the number of rows in the data From fbf35156be6b09850fe796effdec147358f5be24 Mon Sep 17 00:00:00 2001 From: Colin McNulty Date: Thu, 6 Feb 2020 10:29:13 -0500 Subject: [PATCH 063/121] DEV: Add the ability to clear data from a DataTable. Part of SIM-11004. Review 20581 --- SDK/simData/DataTable.h | 5 ++- SDK/simData/MemoryTable/SubTable.cpp | 56 +++++++++++++++++++++++-- SDK/simData/MemoryTable/SubTable.h | 4 +- SDK/simData/MemoryTable/Table.cpp | 19 +++++++-- SDK/simData/MemoryTable/Table.h | 4 +- Testing/SimData/MemoryDataTableTest.cpp | 36 ++++++++++++++++ 6 files changed, 113 insertions(+), 11 deletions(-) diff --git a/SDK/simData/DataTable.h b/SDK/simData/DataTable.h index 70ecf4765..acc9aa994 100644 --- a/SDK/simData/DataTable.h +++ b/SDK/simData/DataTable.h @@ -419,13 +419,14 @@ class SDKDATA_EXPORT DataTable virtual TableStatus addRow(const TableRow& row) = 0; /** - * Deletes all the data in the data table columns, leaving the columns empty. + * Deletes all the data in the specified data table column, leaving the column empty. + * @param id Column ID of the column to flush or -1 to flush all columns in the table * @return Container to all of the dynamic memory stored in the table. When the * smart pointer falls out of scope, the data gets deleted. This enables a * delayed flush mechanism that can be used to flush in a thread for improved * performance and decreased application latency. */ - virtual DelayedFlushContainerPtr flush() = 0; + virtual DelayedFlushContainerPtr flush(TableColumnId id = -1) = 0; /** diff --git a/SDK/simData/MemoryTable/SubTable.cpp b/SDK/simData/MemoryTable/SubTable.cpp index d0cb580f3..06e610480 100644 --- a/SDK/simData/MemoryTable/SubTable.cpp +++ b/SDK/simData/MemoryTable/SubTable.cpp @@ -383,12 +383,52 @@ TableStatus SubTable::removeColumn_(TableColumnId columnId) return TableStatus::Error("Invalid column ID to remove from subtable."); } -simData::DelayedFlushContainerPtr SubTable::flush() +simData::DelayedFlushContainerPtr SubTable::flush(TableColumnId id, SplitObserverPtr splitObserver) { DelayedFlushContainerComposite* deq = new DelayedFlushContainerComposite(); - deq->push_back(timeContainer_->flush()); + // Simple case: Flushing all columns or flushing the only column in the sub table. No need to split + if (id == -1 || (columns_.size() == 1 && columns_.front()->columnId() == id)) + { + deq->push_back(timeContainer_->flush()); + for (std::vector::const_iterator i = columns_.begin(); i != columns_.end(); ++i) + deq->push_back((*i)->flush()); + + return DelayedFlushContainerPtr(deq); + } + + // Complex case: Flushing one column among many + if (splitObserver.get() == NULL) + { + // Split observer is required when flushing a single column. + // Without it, no one will take ownership of the new sub table + assert(0); + return DelayedFlushContainerPtr(deq); + } + + DataColumn* removedCol = NULL; for (std::vector::const_iterator i = columns_.begin(); i != columns_.end(); ++i) - deq->push_back((*i)->flush()); + { + if ((*i)->columnId() == id) + { + deq->push_back((*i)->flush()); + removedCol = *i; + break; + } + } + + // Didn't find the column in this sub table. Nothing to do, return + if (removedCol == NULL) + return DelayedFlushContainerPtr(deq); + + // Split off the flushed column to a new subtable + TimeContainer* newContainer = timeContainer_->clone(); + newContainer->flush(); + SubTable* newTable = new SubTable(newContainer, tableId_); + newTable->takeColumn_(removedCol); + removeColumn_(id); + std::vector idVec; + idVec.push_back(id); + splitObserver->notifySplit(this, newTable, idVec); return DelayedFlushContainerPtr(deq); } @@ -444,4 +484,14 @@ void SubTable::limitData(size_t maxPoints, double latestInvalidTime, DataTable* timeContainer_->limitData(maxPoints, latestInvalidTime, columns_, table, observers); } +void SubTable::takeColumn_(DataColumn* column) +{ + columns_.push_back(column); + // Assertion failure means vector had duplicate column IDs + assert(columnMap_.find((column)->columnId()) == columnMap_.end()); + columnMap_[(column)->columnId()] = column; + // Fix time container ownership so column points to our container and not old owner + column->replaceTimeContainer(timeContainer_); +} + } } diff --git a/SDK/simData/MemoryTable/SubTable.h b/SDK/simData/MemoryTable/SubTable.h index 095a8398a..53929de3e 100644 --- a/SDK/simData/MemoryTable/SubTable.h +++ b/SDK/simData/MemoryTable/SubTable.h @@ -139,7 +139,7 @@ class SDKDATA_EXPORT SubTable /** * Removes all rows from the subtable. */ - simData::DelayedFlushContainerPtr flush(); + simData::DelayedFlushContainerPtr flush(TableColumnId id = -1, SplitObserverPtr splitObserver = SplitObserverPtr()); /** Performs data limiting */ void limitData(size_t maxPoints, double latestInvalidTime, DataTable* table, const std::vector& observers); @@ -208,6 +208,8 @@ class SDKDATA_EXPORT SubTable TableStatus removeColumn_(TableColumnId columnId); /// Fills a row with our contents (but does not set the time), at the specified time void fillRow_(const TimeContainer::IteratorData& timeIdxData, TableRow& row) const; + /// Takes ownership of a previously existing column + void takeColumn_(DataColumn* column); }; } } diff --git a/SDK/simData/MemoryTable/Table.cpp b/SDK/simData/MemoryTable/Table.cpp index 1a5967f26..d3084c83c 100644 --- a/SDK/simData/MemoryTable/Table.cpp +++ b/SDK/simData/MemoryTable/Table.cpp @@ -504,11 +504,24 @@ void Table::limitData_(size_t numToKeep, double timeWindow) } } -simData::DelayedFlushContainerPtr Table::flush() +simData::DelayedFlushContainerPtr Table::flush(TableColumnId id) { DelayedFlushContainerComposite* deq = new DelayedFlushContainerComposite(); - for (std::vector::const_iterator i = subtables_.begin(); i != subtables_.end(); ++i) - deq->push_back((*i)->flush()); + // If flushing all columns, iterate through all subtables + if (id == -1) + { + for (std::vector::const_iterator i = subtables_.begin(); i != subtables_.end(); ++i) + deq->push_back((*i)->flush()); + } + // If flushing only one column, send the flush only to the subtable containing that column. + // Note that the flush can't go straight to the column because the subtable may need to split + else + { + SubTable::SplitObserverPtr splitObserver(new MoveColumnsToNewSubTable(*this)); + auto toFlush = columns_.find(id); + if (toFlush != columns_.end()) + toFlush->second.first->flush(id, splitObserver); + } return DelayedFlushContainerPtr(deq); } diff --git a/SDK/simData/MemoryTable/Table.h b/SDK/simData/MemoryTable/Table.h index 342053a00..a95e706f7 100644 --- a/SDK/simData/MemoryTable/Table.h +++ b/SDK/simData/MemoryTable/Table.h @@ -73,8 +73,8 @@ class SDKDATA_EXPORT Table : public simData::DataTable virtual void accept(DataTable::ColumnVisitor& visitor) const; /** Adds a row to the table. */ virtual TableStatus addRow(const TableRow& row); - /** Clears data out of all columns */ - virtual DelayedFlushContainerPtr flush(); + /** Clears data out of the given column or all columns if given -1 */ + virtual DelayedFlushContainerPtr flush(TableColumnId id = -1); /** Add an observer for notification when rows or columns are added or removed */ virtual void addObserver(TableObserverPtr callback); /** Remove an observer */ diff --git a/Testing/SimData/MemoryDataTableTest.cpp b/Testing/SimData/MemoryDataTableTest.cpp index 8e5632c52..a056fdc9a 100644 --- a/Testing/SimData/MemoryDataTableTest.cpp +++ b/Testing/SimData/MemoryDataTableTest.cpp @@ -2114,6 +2114,41 @@ int doubleBufferTimeContainerTest() return rv; } +int testPartialFlush() +{ + simData::MemoryDataStore ds; + simData::DataTableManager& mgr = ds.dataTableManager(); + simData::DataTable* table = NULL; + int rv = 0; + rv += SDK_ASSERT(mgr.addDataTable(1, "Test Table", &table).isSuccess()); + // Create two columns and add data to both + simData::TableColumn* column1; + simData::TableColumn* column2; + table->addColumn("Test Column 1", simData::VT_DOUBLE, 0, &column1); + table->addColumn("Test Column 2", simData::VT_DOUBLE, 0, &column2); + rv += SDK_ASSERT(table->columnCount() == 2); + rv += SDK_ASSERT(column1->empty()); + rv += SDK_ASSERT(column2->empty()); + for (double i = 0; i < 10; ++i) + { + simData::TableRow row; + row.setTime(i); + row.setValue(column1->columnId(), i); + row.setValue(column2->columnId(), i); + table->addRow(row); + } + rv += SDK_ASSERT(column1->size() == 10); + rv += SDK_ASSERT(column2->size() == 10); + + // Flush only the first column + table->flush(column1->columnId()); + rv += SDK_ASSERT(column1->size() == 0); + rv += SDK_ASSERT(column2->size() == 10); + rv += SDK_ASSERT(table->columnCount() == 2); + + return rv; +} + } int MemoryDataTableTest(int argc, char* argv[]) @@ -2132,5 +2167,6 @@ int MemoryDataTableTest(int argc, char* argv[]) rv += subTableIterationTest(new simData::MemoryTable::DoubleBufferTimeContainer()); rv += testColumnIteration(); rv += doubleBufferTimeContainerTest(); + rv += testPartialFlush(); return rv; } From 279ecd0b012f9ce5f8d9593a7eff50e67c604820 Mon Sep 17 00:00:00 2001 From: Martin Kinsey Date: Tue, 11 Feb 2020 14:07:17 -0500 Subject: [PATCH 064/121] SDK BUG FIX: simData::DoubleBufferTimeContainer::getTimeRange() now returns correct values in all cases. DEV: Also includes added unit test that illustrates the problem without these changes. Review: 20667. --- .../MemoryTable/DoubleBufferTimeContainer.cpp | 32 ++++-- Testing/SimData/MemoryDataTableTest.cpp | 106 ++++++++++++++++++ 2 files changed, 129 insertions(+), 9 deletions(-) diff --git a/SDK/simData/MemoryTable/DoubleBufferTimeContainer.cpp b/SDK/simData/MemoryTable/DoubleBufferTimeContainer.cpp index 7ff596212..05937bd79 100644 --- a/SDK/simData/MemoryTable/DoubleBufferTimeContainer.cpp +++ b/SDK/simData/MemoryTable/DoubleBufferTimeContainer.cpp @@ -22,6 +22,7 @@ #include #include #include +#include "simCore/Calc/Math.h" #include "simData/MemoryTable/DataColumn.h" #include "simData/MemoryTable/DoubleBufferTimeContainer.h" @@ -700,18 +701,31 @@ void DoubleBufferTimeContainer::limitData(size_t maxPoints, double latestInvalid int DoubleBufferTimeContainer::getTimeRange(double& begin, double& end) const { - if (times_[BIN_FRESH]->empty()) // Need to have some times in the fresh bin + const auto* fresh = times_[BIN_FRESH]; + const auto* stale = times_[BIN_STALE]; + + if (fresh->empty()) { - begin = 0.0; - end = 0.0; - return 1; + if (stale->empty()) + { + begin = 0.0; + end = 0.0; + return 1; + } + begin = stale->front().first; + end = stale->back().first; + return 0; } - begin = times_[BIN_FRESH]->front().first; - if (times_[BIN_STALE]->empty()) - end = times_[BIN_FRESH]->back().first; - else - end = times_[BIN_STALE]->back().first; + if (stale->empty()) + { + begin = fresh->front().first; + end = fresh->back().first; + return 0; + } + + begin = simCore::sdkMin(fresh->front().first, stale->front().first); + end = simCore::sdkMax(fresh->back().first, stale->back().first); return 0; } diff --git a/Testing/SimData/MemoryDataTableTest.cpp b/Testing/SimData/MemoryDataTableTest.cpp index a056fdc9a..2f39afdc0 100644 --- a/Testing/SimData/MemoryDataTableTest.cpp +++ b/Testing/SimData/MemoryDataTableTest.cpp @@ -1240,6 +1240,111 @@ int dataLimitingTest() return rv; }; +int getTimeRangeTest() +{ + int rv = 0; + + simUtil::DataStoreTestHelper testHelper; + simData::DataStore* ds = testHelper.dataStore(); + uint64_t plat1 = testHelper.addPlatform(); + ds->setDataLimiting(true); + simData::DataStore::Transaction t; + simData::PlatformPrefs* prefs = ds->mutable_platformPrefs(plat1, &t); + prefs->mutable_commonprefs()->set_datalimitpoints(6); // start out limiting to 6 points + t.commit(); + + simData::DataTable* table = NULL; + rv += SDK_ASSERT(ds->dataTableManager().addDataTable(plat1, "Data Limit Test Table", &table).isSuccess()); + + // Add a column + simData::TableColumn* column1 = NULL; + rv += SDK_ASSERT(table->addColumn("1", VT_INT32, 0, &column1).isSuccess()); + + // add some rows + simData::TableRow newRow; + newRow.setTime(1.0); + newRow.setValue(column1->columnId(), 40); + rv += SDK_ASSERT(table->addRow(newRow).isSuccess()); + newRow.clear(); + newRow.setTime(2.0); + newRow.setValue(column1->columnId(), 50); + rv += SDK_ASSERT(table->addRow(newRow).isSuccess()); + + // Verify expected results from getTimeRange() (all data in fresh) + double begin; + double end; + rv += SDK_ASSERT(column1->getTimeRange(begin, end) == 0); + rv += SDK_ASSERT(begin == 1.0); + rv += SDK_ASSERT(end == 2.0); + + newRow.clear(); + newRow.setTime(3.0); + newRow.setValue(column1->columnId(), 60); + rv += SDK_ASSERT(table->addRow(newRow).isSuccess()); + // Verify expected results from getTimeRange() (all data in stale) + rv += SDK_ASSERT(column1->getTimeRange(begin, end) == 0); + rv += SDK_ASSERT(begin == 1.0); + rv += SDK_ASSERT(end == 3.0); + + newRow.clear(); + newRow.setTime(4.0); + newRow.setValue(column1->columnId(), 70); + rv += SDK_ASSERT(table->addRow(newRow).isSuccess()); + newRow.clear(); + newRow.setTime(5.0); + newRow.setValue(column1->columnId(), 80); + rv += SDK_ASSERT(table->addRow(newRow).isSuccess()); + + // Verify expected results from getTimeRange() (data split between fresh and stale) + rv += SDK_ASSERT(column1->getTimeRange(begin, end) == 0); + rv += SDK_ASSERT(begin == 1.0); + rv += SDK_ASSERT(end == 5.0); + + // Test again, with data being added in reverse. Creates situation where the + // DoubleBufferTimeContainer's FRESH bin has earlier times than the STALE bin + simData::TableColumn* column2 = NULL; + rv += SDK_ASSERT(table->addColumn("2", VT_INT32, 0, &column2).isSuccess()); + + newRow.clear(); + newRow.setTime(5.0); + newRow.setValue(column2->columnId(), 40); + rv += SDK_ASSERT(table->addRow(newRow).isSuccess()); + newRow.clear(); + newRow.setTime(4.0); + newRow.setValue(column2->columnId(), 50); + rv += SDK_ASSERT(table->addRow(newRow).isSuccess()); + + // Verify expected results from getTimeRange() (all data in fresh) + rv += SDK_ASSERT(column2->getTimeRange(begin, end) == 0); + rv += SDK_ASSERT(begin == 4.0); + rv += SDK_ASSERT(end == 5.0); + + newRow.clear(); + newRow.setTime(3.0); + newRow.setValue(column2->columnId(), 60); + rv += SDK_ASSERT(table->addRow(newRow).isSuccess()); + // Verify expected results from getTimeRange() (all data in stale) + rv += SDK_ASSERT(column2->getTimeRange(begin, end) == 0); + rv += SDK_ASSERT(begin == 3.0); + rv += SDK_ASSERT(end == 5.0); + + newRow.clear(); + newRow.setTime(2.0); + newRow.setValue(column2->columnId(), 70); + rv += SDK_ASSERT(table->addRow(newRow).isSuccess()); + newRow.clear(); + newRow.setTime(1.0); + newRow.setValue(column2->columnId(), 80); + rv += SDK_ASSERT(table->addRow(newRow).isSuccess()); + + // Verify expected results from getTimeRange() (data split between fresh and stale) + rv += SDK_ASSERT(column2->getTimeRange(begin, end) == 0); + rv += SDK_ASSERT(begin == 1.0); + rv += SDK_ASSERT(end == 5.0); + + return rv; +} + int subTableIterationTest(simData::MemoryTable::TimeContainer* newTimeContainer) { // Create a mini typedef to reduce typing @@ -2168,5 +2273,6 @@ int MemoryDataTableTest(int argc, char* argv[]) rv += testColumnIteration(); rv += doubleBufferTimeContainerTest(); rv += testPartialFlush(); + rv += getTimeRangeTest(); return rv; } From b7def336f70cb75a6a7a38ad79d9a40ef8a08eec Mon Sep 17 00:00:00 2001 From: Colin McNulty Date: Wed, 12 Feb 2020 08:57:32 -0500 Subject: [PATCH 065/121] DEV: Don't set render bin to inherit in a special case that makes use of it. Addresses SIM-11048. Review 20668 --- SDK/simVis/ModelCache.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SDK/simVis/ModelCache.cpp b/SDK/simVis/ModelCache.cpp index 282f70ac0..a4d5d1854 100644 --- a/SDK/simVis/ModelCache.cpp +++ b/SDK/simVis/ModelCache.cpp @@ -93,7 +93,9 @@ class SetRenderBinsToInherit : public osg::NodeVisitor virtual void apply(osg::Node& node) { osg::StateSet* ss = node.getStateSet(); - if (ss) + // Catch Creator's Superface/Subface condition, where they use POLYGONOFFSET and render bin + // to try to superimpose polygons. Avoid clearing render bins in that particular case. + if (ss && !ss->getAttribute(osg::StateAttribute::POLYGONOFFSET)) { // Fix regularly occuring alpha issues by negating explicit render bin assignments // in the loaded model From 2130551deb1b1e5434b213eeff3ea5645aee3f6e Mon Sep 17 00:00:00 2001 From: Patrick Geissel Date: Wed, 12 Feb 2020 15:50:15 -0500 Subject: [PATCH 066/121] DEV: SDK: GOG parser sets the ref lla properly for annotations, SIMDIS-3359, review 20680 --- SDK/simVis/GOG/Utils.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SDK/simVis/GOG/Utils.cpp b/SDK/simVis/GOG/Utils.cpp index 0ac598795..b443e18a3 100644 --- a/SDK/simVis/GOG/Utils.cpp +++ b/SDK/simVis/GOG/Utils.cpp @@ -340,7 +340,7 @@ ParserData::ParserData(const ParsedShape& parsedShape, const GOGContext& context units_.altitudeUnits_.convertTo(simCore::Units::METERS, parsedShape.doubleValue(GOG_REF_ALT, 0.0))); } - // The centerLLA and centerXYZ doe not apply to points, lines, line segments and polygons + // The centerLLA and centerXYZ do not apply to points, lines, line segments and polygons if ((shape != GOG_POINTS) && (shape != GOG_POLYGON) && (shape != GOG_LINE) && (shape != GOG_LINESEGS)) { if (parsedShape.hasValue(GOG_CENTERLL)) @@ -355,12 +355,11 @@ ParserData::ParserData(const ParsedShape& parsedShape, const GOGContext& context parseAngle(p.x, 0.0), // latitude units_.altitudeUnits_.convertTo(simCore::Units::METERS, altitude)); } - - if (parsedShape.hasValue(GOG_CENTERXY)) + else if (parsedShape.hasValue(GOG_CENTERXY)) { const PositionStrings& p = parsedShape.positionValue(GOG_CENTERXY); // Convert Z value from string - double xyz[3] = {0.}; + double xyz[3] = { 0. }; simCore::isValidNumber(p.x, xyz[0]); simCore::isValidNumber(p.y, xyz[1]); simCore::isValidNumber(p.z, xyz[2]); @@ -373,6 +372,9 @@ ParserData::ParserData(const ParsedShape& parsedShape, const GOGContext& context if (!refPointLLA_.isSet()) refPointLLA_->set(context_.refPoint_->vec3d()); } + // annotations have a single center point but don't use centerxyz keyword for relative shapes, so make sure the refPointLLA_ is set for relative annotations + else if (shape == GOG_ANNOTATION && !refPointLLA_.isSet() && parsedShape.pointType() == ParsedShape::XYZ) + refPointLLA_->set(context_.refPoint_->vec3d()); } if (parsedShape.hasValue(GOG_LINEPROJECTION)) From b57659270c92a2738a8f6cceb961186a45572fc0 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 13 Feb 2020 10:13:12 -0500 Subject: [PATCH 067/121] DEV: Prepare for updated 3rd party libraries. Disable unity build for protobuf libraries. --- CMakeImport/ImportGDAL.cmake | 6 +++--- CMakeImport/ImportProtobuf.cmake | 1 + CMakeImport/ImportSQLite.cmake | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CMakeImport/ImportGDAL.cmake b/CMakeImport/ImportGDAL.cmake index cec6f2c5c..a219f7dd2 100644 --- a/CMakeImport/ImportGDAL.cmake +++ b/CMakeImport/ImportGDAL.cmake @@ -2,7 +2,7 @@ # Setting the GDAL_DIR environment variable will allow use of a custom built library set(LIBRARYNAME GDAL) -set(${LIBRARYNAME}_VERSION 2.1.1) +set(${LIBRARYNAME}_VERSION 2.4.4) set(${LIBRARYNAME}_INSTALL_COMPONENT ThirdPartyLibs) # Setup search paths based off GDAL_ROOT @@ -23,11 +23,11 @@ find_path(${LIBRARYNAME}_LIBRARY_INCLUDE_PATH PATHS ${${LIBRARYNAME}_ROOT}/include NO_DEFAULT_PATH) # GDAL_LIBRARY_RELEASE_PATH find_library(${LIBRARYNAME}_LIBRARY_RELEASE_NAME - NAMES gdal gdal_i gdal201 gdal111 + NAMES gdal gdal_i gdal204 gdal201 gdal111 PATHS ${${LIBRARYNAME}_ROOT}/lib NO_DEFAULT_PATH) # GDAL_LIBRARY_DEBUG_PATH find_library(${LIBRARYNAME}_LIBRARY_DEBUG_NAME - NAMES gdal_d gdal201_d gdal111_d + NAMES gdal_d gdal204_d gdal201_d gdal111_d PATHS ${${LIBRARYNAME}_ROOT}/lib NO_DEFAULT_PATH) # Fall back on release library explicitly, only on Windows if(WIN32 AND ${LIBRARYNAME}_LIBRARY_RELEASE_NAME AND NOT ${LIBRARYNAME}_LIBRARY_DEBUG_NAME) diff --git a/CMakeImport/ImportProtobuf.cmake b/CMakeImport/ImportProtobuf.cmake index 0f9d14f52..3dfddcc1e 100644 --- a/CMakeImport/ImportProtobuf.cmake +++ b/CMakeImport/ImportProtobuf.cmake @@ -261,6 +261,7 @@ function(CREATE_PROTOBUF_LIBRARY LIB_TARGETNAME LIB_PROJECTNAME FOLDER PROJECT_L set_target_properties(${LIB_TARGETNAME} PROPERTIES FOLDER "${FOLDER}" PROJECT_LABEL "${PROJECT_LABEL}" + UNITY_BUILD OFF ) endfunction() diff --git a/CMakeImport/ImportSQLite.cmake b/CMakeImport/ImportSQLite.cmake index df4495ada..3a0345a2b 100644 --- a/CMakeImport/ImportSQLite.cmake +++ b/CMakeImport/ImportSQLite.cmake @@ -1,7 +1,7 @@ # Setup SQLite library # Setting the SQLITE3_DIR environment variable will allow use of a custom built library -set(SQLITE_VERSION 3.29.0) +set(SQLITE_VERSION 3.31.1) # Setup search paths initialize_ENV(SQLITE3_DIR) From df5cc80af322d65d26e707018e6e9fb09caabf33 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Fri, 14 Feb 2020 07:52:16 -0500 Subject: [PATCH 068/121] DEV: Start of a wrapper for simCore in SWIG. Does not work currently with the SDK standalone build, requires more imports only in the SIMDIS inclusion build. Start of SIM-10526. Review: 20691 --- swig/CMakeLists.txt | 70 +++++++++++++++++++++ swig/Testing/CMakeLists.txt | 41 +++++++++++++ swig/Testing/TestSimCore.py | 40 ++++++++++++ swig/simCore/CMakeLists.txt | 40 ++++++++++++ swig/simCore/simCore.i | 117 ++++++++++++++++++++++++++++++++++++ 5 files changed, 308 insertions(+) create mode 100644 swig/CMakeLists.txt create mode 100644 swig/Testing/CMakeLists.txt create mode 100644 swig/Testing/TestSimCore.py create mode 100644 swig/simCore/CMakeLists.txt create mode 100644 swig/simCore/simCore.i diff --git a/swig/CMakeLists.txt b/swig/CMakeLists.txt new file mode 100644 index 000000000..8bb452cce --- /dev/null +++ b/swig/CMakeLists.txt @@ -0,0 +1,70 @@ +if(NOT SWIG_FOUND OR NOT TARGET PYTHON3) + return() +endif() + +# Avoid making SWIG targets with older CMake, to avoid extra complications +if("${CMAKE_VERSION}" VERSION_LESS 3.13) + return() +endif() + +project(SIMDIS_SDK_SWIG) + +mark_as_advanced(SWIG_EXECUTABLE) + +include(${SWIG_USE_FILE}) +set(CMAKE_SWIG_FLAGS "") +set(CMAKE_SWIG_OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/bin") +# Linux uses LIBRARY for .so, Windows uses RUNTIME for pyd +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") +include_directories("${PYTHON3_LIBRARY_INCLUDE_PATH}") +include_directories("${SIMDIS_SDK_SOURCE_DIR}") + +#macro for installing the specified Python file and the library +macro(InstallPythonFiles TARGET) + + if(WIN32) + set(PYD_EXTENSION "pyd") + set(PYD_DESTINATION "lib/${BUILD_SYSTEM_ARCH}-nt/python3.${PYTHON3_MINOR}") + else() + set(PYD_EXTENSION "so") + set(PYD_DESTINATION "lib/amd64-linux/python3.${PYTHON3_MINOR}/lib-dynload") + endif() + + install(FILES ${CMAKE_SWIG_OUTDIR}/${TARGET}.py + DESTINATION bin/pythonScripts + COMPONENT SIMDIS + ) + + if(WIN32) + install(PROGRAMS + ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/Release/_${TARGET}.${PYD_EXTENSION} + DESTINATION ${PYD_DESTINATION} + COMPONENT SIMDIS + CONFIGURATIONS Release + ) + install(PROGRAMS + ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/RelWithDebInfo/_${TARGET}.${PYD_EXTENSION} + DESTINATION ${PYD_DESTINATION} + COMPONENT SIMDIS + CONFIGURATIONS RelWithDebInfo + ) + install(PROGRAMS + ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/Debug/_${TARGET}_d.${PYD_EXTENSION} + DESTINATION ${PYD_DESTINATION} + COMPONENT SIMDIS + CONFIGURATIONS Debug + ) + else() + # The debug library does not have a _d so only one install is needed + install(PROGRAMS + ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/_${TARGET}.${PYD_EXTENSION} + DESTINATION ${PYD_DESTINATION} + COMPONENT SIMDIS + ) + endif() + +endmacro() + +add_subdirectory(simCore) +add_subdirectory(Testing) diff --git a/swig/Testing/CMakeLists.txt b/swig/Testing/CMakeLists.txt new file mode 100644 index 000000000..d625dfb22 --- /dev/null +++ b/swig/Testing/CMakeLists.txt @@ -0,0 +1,41 @@ +# Early return if no unit testing +if(NOT ENABLE_CDASH_PROJECTS AND NOT ENABLE_UNIT_TESTING) + return() +endif() + +# Pull the version from CMakeImport/ImportPython3.cmake +set(DESIRED_PYTHON_VERSION ${PYTHON3_MAJOR}.${PYTHON3_MINOR}.${PYTHON3_PATCH}) + +# FindPython3.cmake was added in 3.12 and is better than PythonInterp +if(WIN32) + # Need to match the version exactly on Windows for some reason or crash + find_package(Python3 ${DESIRED_PYTHON_VERSION} EXACT COMPONENTS Interpreter QUIET) + # Python3's find_package() EXACT does not work as advertised in all cases. + if(NOT DESIRED_PYTHON_VERSION VERSION_EQUAL Python3_VERSION) + return() + endif() +else() + # Linux is more forgiving + find_package(Python3 3.6 COMPONENTS Interpreter QUIET) +endif() + +# Return if there's no interpreter +if(NOT Python3_Interpreter_FOUND) + return() +endif() + +# Add the tests +add_test(NAME simCore_SWIG_Test COMMAND "${Python3_EXECUTABLE}" "TestSimCore.py" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") + +# Windows insists on installing under a CONFIG directory under the runtime output directory +if(WIN32) + set(PYTHON_PATH "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}\;${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/$") +else() + set(PYTHON_PATH "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") +endif() + +set_tests_properties( + simCore_SWIG_Test + PROPERTIES + ENVIRONMENT "PYTHONPATH=${PYTHON_PATH}" +) diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py new file mode 100644 index 000000000..c9601a1c3 --- /dev/null +++ b/swig/Testing/TestSimCore.py @@ -0,0 +1,40 @@ +import os, sys + +# Try to use SIMDIS_DIR to set up import paths +if 'SIMDIS_DIR' in os.environ: + # For _module shared object: + if os.name == "nt": + sys.path.insert(0, os.environ['SIMDIS_DIR'] + '/lib/amd64-nt/python3.8') + try: + # Python 3.8 does not want to respect PATH for loading dependent DLLs. It introduces + # a new method to attempt to fix the problem. Try/except ignores errors in older Python. + # Without this, the _simCore.pyd needs to go in the same place as simNotify/simCore. + os.add_dll_directory(os.environ['SIMDIS_DIR'] + '/bin/amd64-nt') + except: + pass + pass + else: + sys.path.insert(0, os.environ['SIMDIS_DIR'] + '/lib/amd64-linux/python3.8/lib-dynload') + # For module wrapper: + sys.path.insert(0, os.environ['SIMDIS_DIR'] + '/bin/pythonScripts') + +import simCore + +assert(simCore.Vec3() is not None) +v = simCore.Vec3(1, 2, 3) +assert(v is not None) +assert(v.x() == 1) +assert(v.y() == 2) +assert(v.z() == 3) +v.set(3, 1, 2) +assert(v.x() == 3) +assert(v.y() == 1) +assert(v.z() == 2) +v.scale(2) +assert(v.x() == 6) +assert(v.y() == 2) +assert(v.z() == 4) + +# TODO: More testing here + +print("Success!"); diff --git a/swig/simCore/CMakeLists.txt b/swig/simCore/CMakeLists.txt new file mode 100644 index 000000000..f708862de --- /dev/null +++ b/swig/simCore/CMakeLists.txt @@ -0,0 +1,40 @@ +vsi_require_target(PYTHON3) + +set(SIMCORE_FILES + simCore.i +) + +set_source_files_properties(simCore.i PROPERTIES + CPLUSPLUS ON + DEPENDS "${SIMCORE_FILES}" + SWIG_MODULE_NAME "simCore" +) +# SWIG does not define WIN32, _WIN32, _MSC_VER, etc. Need to provide it manually +if(MSVC) + set_source_files_properties(simCore.i PROPERTIES SWIG_FLAGS "-DMSVC") +endif() +# Avoid incorrect import declaration with debug libraries +set_source_files_properties(simCore.i PROPERTIES COMPILE_OPTIONS "-interface;_simCore") + +# LEGACY / STANDARD +set(UseSWIG_TARGET_NAME_PREFERENCE STANDARD) + +swig_add_library(SwigSimCore LANGUAGE python SOURCES simCore.i) +target_link_libraries(SwigSimCore PRIVATE PYTHON3 simCore) +set_target_properties(SwigSimCore PROPERTIES + FOLDER "SIMDIS SDK" + PROJECT_LABEL "Python Wrapper - simCore" + OUTPUT_NAME "simCore" +) + +# On Linux do not want the _d suffix on the library +if(NOT WIN32) + set_target_properties(SwigSimCore PROPERTIES DEBUG_POSTFIX "") +endif() + +InstallPythonFiles(simCore) + +install(FILES ${SIMCORE_FILES} + DESTINATION doc/SIMDIS/LabelScripting + COMPONENT SIMDIS +) diff --git a/swig/simCore/simCore.i b/swig/simCore/simCore.i new file mode 100644 index 000000000..12661b622 --- /dev/null +++ b/swig/simCore/simCore.i @@ -0,0 +1,117 @@ +%module(directors="1") simCore + +%feature("autodoc", "3"); + +%{ +#include "simCore.h" +%} + + +#ifdef _WIN32 +%include "windows.i" +#endif + +// Include STL support +%include "std_map.i" +%include "std_string.i" +%include "std_vector.i" + +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned int uint32_t; +typedef int int32_t; + +// Windows MSVC uses long long for 64 bit ints. Linux g++ uses long +#ifdef MSVC +typedef unsigned long long uint64_t; +typedef long long int64_t; +#else +typedef unsigned long uint64_t; +typedef long int64_t; +#endif + + +#define SDKCORE_EXPORT + +%ignore simCore::Vec3::operator=; +%ignore simCore::Vec3::operator[]; +%ignore simCore::Coordinate::operator=; + +// Note, order of inclusion matters + +//////////////////////////////////////////////// +// simCore/Common +%include "simCore/Common/Exception.h" +%include "simCore/Common/FileSearch.h" +%include "simCore/Common/HighPerformanceGraphics.h" +%include "simCore/Common/Time.h" + +//////////////////////////////////////////////// +// simCore/Calc +%include "simCore/Calc/Vec3.h" +%include "simCore/Calc/Angle.h" +%include "simCore/Calc/CoordinateSystem.h" +%include "simCore/Calc/Coordinate.h" + +// TODO: Add these and test them as you add them +/* +%include "simCore/Calc/Calculations.h" +%include "simCore/Calc/CoordinateConverter.h" +%include "simCore/Calc/DatumConvert.h" +%include "simCore/Calc/Gars.h" +%include "simCore/Calc/Geometry.h" +%include "simCore/Calc/GogToGeoFence.h" +%include "simCore/Calc/Interpolation.h" +%include "simCore/Calc/MagneticVariance.h" +%include "simCore/Calc/MathConstants.h" +%include "simCore/Calc/Math.h" +%include "simCore/Calc/Mgrs.h" +%include "simCore/Calc/MultiFrameCoordinate.h" +%include "simCore/Calc/NumericalAnalysis.h" +%include "simCore/Calc/Random.h" +%include "simCore/Calc/SquareMatrix.h" +%include "simCore/Calc/UnitContext.h" +%include "simCore/Calc/Units.h" +%include "simCore/Calc/VerticalDatum.h" + +//////////////////////////////////////////////// +// simCore/EM +%include "simCore/EM/AntennaPattern.h" +%include "simCore/EM/Constants.h" +%include "simCore/EM/Decibel.h" +%include "simCore/EM/ElectroMagRange.h" +%include "simCore/EM/Propagation.h" +%include "simCore/EM/RadarCrossSection.h" + +//////////////////////////////////////////////// +// simCore/LUT +%include "simCore/LUT/InterpTable.h" +%include "simCore/LUT/LUT1.h" +%include "simCore/LUT/LUT2.h" + +//////////////////////////////////////////////// +// simCore/String +%include "simCore/String/Angle.h" +%include "simCore/String/Constants.h" +%include "simCore/String/FilePatterns.h" +%include "simCore/String/Format.h" +%include "simCore/String/TextFormatter.h" +%include "simCore/String/TextReplacer.h" +%include "simCore/String/Tokenizer.h" +%include "simCore/String/UnitContextFormatter.h" +%include "simCore/String/Utils.h" +%include "simCore/String/ValidNumber.h" +%include "simCore/Time/Clock.h" +%include "simCore/Time/ClockImpl.h" +%include "simCore/Time/Constants.h" +%include "simCore/Time/CountDown.h" +%include "simCore/Time/DeprecatedStrings.h" +%include "simCore/Time/Exception.h" +%include "simCore/Time/Julian.h" +%include "simCore/Time/String.h" +%include "simCore/Time/TimeClass.h" +%include "simCore/Time/TimeClock.h" +%include "simCore/Time/Utils.h" +*/ From 2c10c0b04499d5eb4ba5614ff8e2269b55b7db0d Mon Sep 17 00:00:00 2001 From: Martin Kinsey Date: Fri, 14 Feb 2020 09:55:37 -0500 Subject: [PATCH 069/121] DEV: simUtil::HudManager constructor updated to be more generic and not dependent on simVis::View. Part of SIM-11010, Review: 20695. --- SDK/simUtil/HudManager.cpp | 17 ++++++----------- SDK/simUtil/HudManager.h | 18 ++++++++++-------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/SDK/simUtil/HudManager.cpp b/SDK/simUtil/HudManager.cpp index 3659fb50c..f22953c35 100644 --- a/SDK/simUtil/HudManager.cpp +++ b/SDK/simUtil/HudManager.cpp @@ -522,13 +522,13 @@ class HudManager::ResizeHandler : public osgGA::GUIEventHandler //------------------------------------------------------------------------------------------------------- -HudManager::HudManager(simVis::View* view) +HudManager::HudManager(osgViewer::View* view, osg::Group* parentNode) : renderLevel_(HUD_BASE_LEVEL), - view_(view) + view_(view), + parentNode_(parentNode) { group_ = new osg::Group(); - hud_ = view_->getOrCreateHUD(); - osg::StateSet* stateset = hud_->getOrCreateStateSet(); + osg::StateSet* stateset = parentNode_->getOrCreateStateSet(); simVis::setLighting(stateset, osg::StateAttribute::OFF); const osg::Viewport* vp = view->getCamera()->getViewport(); @@ -537,12 +537,12 @@ HudManager::HudManager(simVis::View* view) handler_ = new ResizeHandler(this); view_->addEventHandler(handler_); - hud_->addChild(group_); + parentNode_->addChild(group_); } HudManager::~HudManager() { - hud_->removeChild(group_); + parentNode_->removeChild(group_); view_->removeEventHandler(handler_); } @@ -625,11 +625,6 @@ void HudManager::resize_(int width, int height) (*it)->resize(windowWidth_, windowHeight_); } -osg::Camera* HudManager::hud() const -{ - return hud_.get(); -} - void HudManager::setRenderLevel(HudRenderLevel renderLevel) { group_->getOrCreateStateSet()->setRenderBinDetails(renderLevel, "RenderBin"); diff --git a/SDK/simUtil/HudManager.h b/SDK/simUtil/HudManager.h index 613c36a8e..c628fd23f 100644 --- a/SDK/simUtil/HudManager.h +++ b/SDK/simUtil/HudManager.h @@ -28,8 +28,9 @@ #include #include +#include #include "simCore/Common/Common.h" -#include "simVis/View.h" +#include "simVis/Types.h" namespace osgGA { class GUIEventHandler; } @@ -465,8 +466,12 @@ class SDKUTIL_EXPORT HudImage : public osg::Geode class SDKUTIL_EXPORT HudManager { public: - /** Constructor */ - HudManager(simVis::View* view); + /** + * Constructs a new HudManager. Passes in the View and the parent node for the HUD. For example: + * simVis::View* hudView = ...; + * HudManager* hudManager = new HudManager(hudView, hudView->getOrCreateHUD()); + */ + HudManager(osgViewer::View* view, osg::Group* parentNode); virtual ~HudManager(); /** @@ -548,9 +553,6 @@ class SDKUTIL_EXPORT HudManager /// Removes the specified image void removeImage(HudImage* hudImage); - /// Returns the current HUD - osg::Camera* hud() const; - /// Set the render level this HudManager should apply to all its hud items void setRenderLevel(HudRenderLevel renderLevel); @@ -569,8 +571,8 @@ class SDKUTIL_EXPORT HudManager osg::ref_ptr group_; ///< group node that holds all the hud text and images std::vector< osg::ref_ptr > textVector_; ///< The current overlay text std::vector< osg::ref_ptr > imageVector_; ///< The current overlay images - osg::observer_ptr view_; ///< The view for this manager - osg::observer_ptr hud_; ///< The HUD for this manager + osg::observer_ptr view_; ///< The view for this manager + osg::observer_ptr parentNode_; ///< The parent node where this manager adds itself to the scene osg::ref_ptr handler_; ///< The callback for window re-size int windowWidth_; ///< Save a copy of the window width int windowHeight_; ///< Save a copy of the window height From ffdd35fbcdd82e50b886e1820e4f693639bcf0c9 Mon Sep 17 00:00:00 2001 From: Martin Kinsey Date: Fri, 14 Feb 2020 10:42:29 -0500 Subject: [PATCH 070/121] Addendum to last to fix SDK examples. No review --- Examples/BasicViewerText/BasicViewerText.cpp | 2 +- Examples/Periscope/PeriscopeExample.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/BasicViewerText/BasicViewerText.cpp b/Examples/BasicViewerText/BasicViewerText.cpp index 3c635b451..0b3ce921c 100644 --- a/Examples/BasicViewerText/BasicViewerText.cpp +++ b/Examples/BasicViewerText/BasicViewerText.cpp @@ -234,7 +234,7 @@ int main(int argc, char** argv) simVis::View* superHUD = new simVis::View(); superHUD->setUpViewAsHUD(mainView); mainView->getViewManager()->addView(superHUD); - simUtil::HudManager hm(superHUD); + simUtil::HudManager hm(superHUD, superHUD->getOrCreateHUD()); // Create a background for some of the text using a large hyphen osg::ref_ptr background1 = hm.createText("-", 130, 132, false, false); diff --git a/Examples/Periscope/PeriscopeExample.cpp b/Examples/Periscope/PeriscopeExample.cpp index f301cef07..3c0ebd290 100644 --- a/Examples/Periscope/PeriscopeExample.cpp +++ b/Examples/Periscope/PeriscopeExample.cpp @@ -344,7 +344,7 @@ int main(int argc, char** argv) viewer->getMainView()->setCameraManipulator(NULL); // apply the reticle overlay. - simUtil::HudManager hudManager(viewer->getMainView()); + simUtil::HudManager hudManager(viewer->getMainView(), viewer->getMainView()->getOrCreateHUD()); if (reticle.valid()) hudManager.createImage(reticle.get(), 0, 0, 100, 100); From 7aea99158b2a61844dc424e4af564aa7d7cad6ad Mon Sep 17 00:00:00 2001 From: Frank Bausch Date: Wed, 19 Feb 2020 09:26:47 -0500 Subject: [PATCH 071/121] simRf: revisions to RFProp 3d algorithm (SDK-155) Release Note: N/A Notes: recent revision improved the algorithm but removed the previous reserve implementation. using reserve() does have a noticeable impact Test Environment: Windows 10, VC14, Debug, 64-bit Test: vsi builds, all tests pass Review: 20721 --- SDK/simVis/RFProp/Profile.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SDK/simVis/RFProp/Profile.cpp b/SDK/simVis/RFProp/Profile.cpp index 2fd34fdb3..1793bc12d 100644 --- a/SDK/simVis/RFProp/Profile.cpp +++ b/SDK/simVis/RFProp/Profile.cpp @@ -648,6 +648,8 @@ void Profile::init3D_() osg::Geometry* geometry = new osg::Geometry(); osg::DrawElementsUInt* idx = new osg::DrawElementsUInt(GL_TRIANGLES); + const size_t idxSize = 36 * (maxHeightIndex - minHeightIndex) * (numRanges - 1); + idx->reserve(idxSize); //Now build the indices that will actually be rendered for (unsigned int r = 0; r < numRanges - 1; r++) @@ -655,6 +657,7 @@ void Profile::init3D_() const unsigned int nextR = r + 1; for (unsigned int h = minHeightIndex; h < maxHeightIndex; h++) { + // 36 indices / cube //Compute the indices of the 8 corners of the cube const unsigned int v0 = startIndex + r * heightIndexCount * 2 + (h - minHeightIndex) * 2; // front LR const unsigned int v1 = v0 + 1; // front LL @@ -691,6 +694,8 @@ void Profile::init3D_() idx->push_back(v0); idx->push_back(v6); idx->push_back(v2); } } + // assertion fail means algorithm changed without correction to the reserve() + assert(idxSize == idx->size()); geometry->addPrimitiveSet(idx); geometry->setDataVariance(osg::Object::DYNAMIC); From 04f53842c4af5e3cf195c792e7f834c2586ca639 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Wed, 19 Feb 2020 13:00:03 -0500 Subject: [PATCH 072/121] DEV: Added simCore namespace for clarity, and to help with copy/paste. Review: 20725 --- SDK/simCore/Time/Clock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/simCore/Time/Clock.h b/SDK/simCore/Time/Clock.h index 63cb1fec0..25d35b583 100644 --- a/SDK/simCore/Time/Clock.h +++ b/SDK/simCore/Time/Clock.h @@ -162,7 +162,7 @@ class SDKCORE_EXPORT Clock /**@name callbacks for each event type *@{ */ - virtual void onModeChange(Clock::Mode newMode) = 0; + virtual void onModeChange(simCore::Clock::Mode newMode) = 0; virtual void onDirectionChange(simCore::TimeDirection newDirection) = 0; virtual void onScaleChange(double newValue) = 0; virtual void onBoundsChange(const simCore::TimeStamp& start, const simCore::TimeStamp& end) = 0; From c0c2bf89a5e50c644b95510e3cc500b168aa8e11 Mon Sep 17 00:00:00 2001 From: Frank Bausch Date: Wed, 19 Feb 2020 15:10:18 -0500 Subject: [PATCH 073/121] simQt: disallow MRU shortcuts for items > 9 (SIM-11072) Release Note: N/A Notes: the #1 shortcut now works, even when there are 10 items Test Environment: Windows 10, VC14, Debug, 64-bit, Linux RHEL6 gcc 8.3.1 x64 Test: vsi builds, all tests pass Review: 20727 --- SDK/simQt/MruList.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/SDK/simQt/MruList.cpp b/SDK/simQt/MruList.cpp index 636e598af..90ce1ea75 100644 --- a/SDK/simQt/MruList.cpp +++ b/SDK/simQt/MruList.cpp @@ -157,8 +157,11 @@ void MruList::fixActions_() action->setVisible(true); action->setEnabled(true); - // Text looks like: "&3 file.asi" - action->setText(tr("&%1 %2").arg(idx + 1).arg(fi.fileName())); + // Text looks like: "&3 file.asi"; can only specify shortcuts (&) for items numbered < 10. + if (idx < 9) + action->setText(tr("&%1 %2").arg(idx + 1).arg(fi.fileName())); + else + action->setText(tr("%1 %2").arg(idx + 1).arg(fi.fileName())); // We're showing an action, so we want to show the separators showSeparators = true; From 8edeb443dc61ad6af6ecb9883600b9298fd91ac0 Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Thu, 20 Feb 2020 07:54:24 -0500 Subject: [PATCH 074/121] SIM-11032 Added simQt::DndTreeView (1 of 2 SDK) Release: simQt::DndTreeView added to circumvent a Drag and Drop bug with QTreeView. Notes: N/A Test Environment: Windows 10, Visual Studio 2017, Debug Test: Manual testing with Scenario Editor Review: 20729 --- SDK/simQt.h | 1 + SDK/simQt/CMakeLists.txt | 2 ++ SDK/simQt/DndTreeView.cpp | 44 ++++++++++++++++++++++++++ SDK/simQt/DndTreeView.h | 53 ++++++++++++++++++++++++++++++++ SDK/simQt/EntityTreeComposite.ui | 7 ++++- 5 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 SDK/simQt/DndTreeView.cpp create mode 100644 SDK/simQt/DndTreeView.h diff --git a/SDK/simQt.h b/SDK/simQt.h index ab8d65128..56cdb3743 100644 --- a/SDK/simQt.h +++ b/SDK/simQt.h @@ -40,6 +40,7 @@ #include "simQt/DataTableComboBox.h" #include "simQt/DataTableModel.h" #include "simQt/DirectorySelectorWidget.h" +#include "simQt/DndTreeView.h #include "simQt/DockWidget.h" #include "simQt/EntityCategoryFilter.h" #include "simQt/EntityFilter.h" diff --git a/SDK/simQt/CMakeLists.txt b/SDK/simQt/CMakeLists.txt index 0eea03ac8..bdd8319b1 100644 --- a/SDK/simQt/CMakeLists.txt +++ b/SDK/simQt/CMakeLists.txt @@ -18,6 +18,7 @@ set(SIMQT_HEADERS_TO_MOC ${SIMQT_INC}ConsoleDataModel.h ${SIMQT_INC}ConsoleLogger.h ${SIMQT_INC}DirectorySelectorWidget.h + ${SIMQT_INC}DndTreeView.h ${SIMQT_INC}DockWidget.h ${SIMQT_INC}FileDescriptorReplacement.h ${SIMQT_INC}FileSelectorWidget.h @@ -144,6 +145,7 @@ set(SIMQT_SOURCES ${SIMQT_SRC}ConsoleDataModel.cpp ${SIMQT_SRC}ConsoleLogger.cpp ${SIMQT_SRC}DirectorySelectorWidget.cpp + ${SIMQT_SRC}DndTreeView.cpp ${SIMQT_SRC}DockWidget.cpp ${SIMQT_SRC}FileDescriptorReplacement.cpp ${SIMQT_SRC}FileDialog.cpp diff --git a/SDK/simQt/DndTreeView.cpp b/SDK/simQt/DndTreeView.cpp new file mode 100644 index 000000000..91658949d --- /dev/null +++ b/SDK/simQt/DndTreeView.cpp @@ -0,0 +1,44 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#include +#include "simQt/DndTreeView.h" + +namespace simQt { + +DndTreeView::DndTreeView(QWidget* parent) + : QTreeView(parent) +{ +} + +DndTreeView::~DndTreeView() +{ +} + +void DndTreeView::dragEnterEvent(QDragEnterEvent *event) +{ + QTreeView::dragEnterEvent(event); + event->acceptProposedAction(); +} + +} + diff --git a/SDK/simQt/DndTreeView.h b/SDK/simQt/DndTreeView.h new file mode 100644 index 000000000..896b63c88 --- /dev/null +++ b/SDK/simQt/DndTreeView.h @@ -0,0 +1,53 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ + +#ifndef SIMQT_DND_TREE_VIEW_H +#define SIMQT_DND_TREE_VIEW_H + +#include + +namespace simQt { + +/** + * Wrapper class to circumvent a Drag and Drop bug with QTreeView. + * For details see: https://bugreports.qt.io/browse/QTBUG-76418 + * and https://bugreports.qt.io/browse/QTBUG-44939 + */ +class SDKQT_EXPORT DndTreeView : public QTreeView +{ + Q_OBJECT; + +public: + /** Constructor */ + explicit DndTreeView(QWidget* parent = NULL); + + /** Destructor */ + virtual ~DndTreeView(); + +protected: + /** Override to circumvent a Drag and Drop bug */ + virtual void dragEnterEvent(QDragEnterEvent* event); +}; + +} + +#endif diff --git a/SDK/simQt/EntityTreeComposite.ui b/SDK/simQt/EntityTreeComposite.ui index abae5445c..44ad5ec64 100644 --- a/SDK/simQt/EntityTreeComposite.ui +++ b/SDK/simQt/EntityTreeComposite.ui @@ -25,7 +25,7 @@
- + Qt::ActionsContextMenu @@ -237,6 +237,11 @@ QLineEdit
simQt/EntityFilterLineEdit.h
+ + simQt::DndTreeView + QTreeView +
simQt/DndTreeView.h
+
From 50fc762eeca04e6ac6d9603c38e144691e3150bd Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Thu, 20 Feb 2020 08:16:12 -0500 Subject: [PATCH 075/121] Addendum to Review 20729 to fix missing include. --- SDK/simQt/DndTreeView.h | 1 + 1 file changed, 1 insertion(+) diff --git a/SDK/simQt/DndTreeView.h b/SDK/simQt/DndTreeView.h index 896b63c88..b80793bf4 100644 --- a/SDK/simQt/DndTreeView.h +++ b/SDK/simQt/DndTreeView.h @@ -24,6 +24,7 @@ #define SIMQT_DND_TREE_VIEW_H #include +#include "simCore/Common/Export.h" namespace simQt { From 878bc0208d5ff521cfdbe655c026a294e48252ad Mon Sep 17 00:00:00 2001 From: Frank Bausch Date: Fri, 21 Feb 2020 08:11:22 -0500 Subject: [PATCH 076/121] simUtil: fix HudText backgroundcolor/backdrop implementation (SIM-11063) Release Note: N/A Notes: draw mode has to be set first before other changes can take effect. since order was inverted previously, it took two update() calls to get it done - and a resize was one way of providing the second call. Test Environment: Windows 10, VC14, Debug, 64-bit Test: iNet plugin now displays net activity light as expected Review: 20749 --- SDK/simUtil/HudManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SDK/simUtil/HudManager.cpp b/SDK/simUtil/HudManager.cpp index f22953c35..5ac8547b9 100644 --- a/SDK/simUtil/HudManager.cpp +++ b/SDK/simUtil/HudManager.cpp @@ -220,10 +220,11 @@ void HudTextAdapter::update_() osgText->setDrawMode(osgText::TextBase::TEXT); else { + // set draw mode first, other changes depend on it + osgText->setDrawMode(osgText::TextBase::FILLEDBOUNDINGBOX | osgText::TextBase::TEXT); // Turn on the bounding box, which disables Halo osgText->setBackdropType(osgText::Text::NONE); osgText->setBoundingBoxColor(backgroundColor_); - osgText->setDrawMode(osgText::TextBase::FILLEDBOUNDINGBOX | osgText::TextBase::TEXT); } } From 79e29501b2b91730d810f6c138c22e937641ace2 Mon Sep 17 00:00:00 2001 From: Ferzam Mohammad Date: Fri, 21 Feb 2020 09:54:08 -0500 Subject: [PATCH 077/121] DEV: First pass on wrapping simCore into a python module using swig interface (.i) file. Can successfully access simCore/Common and part of simCore/Calc in python. SIM-10526, review: 20740. --- swig/Testing/TestSimCore.py | 168 +++++++++++++++++++++++++++++++++++- swig/simCore/simCore.i | 42 ++++++++- 2 files changed, 206 insertions(+), 4 deletions(-) diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index c9601a1c3..1b7545aad 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -1,4 +1,4 @@ -import os, sys +import os, sys, math, timeit # Try to use SIMDIS_DIR to set up import paths if 'SIMDIS_DIR' in os.environ: @@ -20,6 +20,46 @@ import simCore +# simCore/Common + +############################# +# Exception.h +e = simCore.Exception("ExceptionFromPython", "Test exception successfully generated. Ignore Error.", 37) +assert(e is not None) +assert(e.rawWhat() == "Test exception successfully generated. Ignore Error.") +assert(e.line() == 37) +e = None + +############################# +# FileSearch.h +assert(simCore.FileSearch.GOG is not None) +# TODO: Test FileSearch::findFile(). This could involve creating a small definition for it (possibly using %inline in the .i file), which is a technique that could help with testing other methods. +# assert(simCore.FileSearch.findFile()) + +############################# +# Time.h +# Wrapper function that sleeps for a second and takes no args, so that it can be passed through python's timeit() function easily. +# Sleeping for more than a second, as function occasionally executes in slightly less than a tenth of a second if given 100 ms as a parameter. +def sleepWrapper(): + simCore.Sleep(100) + +print("Sleeping for about a tenth of a second.") +assert(timeit.timeit(sleepWrapper, number=1) >= .05) +# Defined timezone struct in .i file so that it was exposed to python. +timezone = simCore.timezone() +assert(timezone is not None) +timezone.tz_minuteswest = 1 +assert(timezone.tz_minuteswest == 1) +timezone.tz_dsttime = 2 +assert(timezone.tz_dsttime == 2) +# TODO: Support timespec_t typedef struct. It is currently missing from the .cxx generated wrapper class, might need to use a typemap? +# timespec = simCore.timesepc_t() +# assert(timespec is not None) + +# simCore/Calc + +############################# +# Vec3.h assert(simCore.Vec3() is not None) v = simCore.Vec3(1, 2, 3) assert(v is not None) @@ -35,6 +75,132 @@ assert(v.y() == 2) assert(v.z() == 4) +############################# +# MathConstants.h +assert(simCore.M_TWOPI == 6.28318530717958647692) + +############################# +# Angle.h +assert(simCore.angFix360(720) == 0) +assert(simCore.areAnglesEqual(0, simCore.M_TWOPI) == True) +angleExtents = simCore.ANGLEEXTENTS_TWOPI +assert(angleExtents is not None) +assert(simCore.angFixDegrees(360, angleExtents) == 0) + +############################# +# CoordinateSystem.h +assert(simCore.WGS_84 is not None) +assert(simCore.GEOMETRIC_HORIZON is not None) +assert(simCore.WGS_E == 0.0818191908426) +assert(simCore.WGS_ESQ == simCore.WGS_E * simCore.WGS_E) +assert(simCore.EARTH_ROTATION_RATE == 7292115.1467e-11) +coordSystem = simCore.COORD_SYS_NED +assert(coordSystem is not None) +assert(simCore.coordinateSystemToString(coordSystem) == "Topo_NED") +rv, coordSystem = simCore.coordinateSystemFromString("Topo_NED") +assert(rv == 0) +assert(coordSystem == simCore.COORD_SYS_NED) + +############################# +# Coordinate.h +coordinateOne = simCore.Coordinate() +coordinateTwo = simCore.Coordinate(simCore.COORD_SYS_LLA, v) +assert(coordinateOne is not None) +assert(coordinateTwo is not None) +assert(coordinateOne.hasAcceleration() == False) +assert(coordinateTwo.x() == 6) +assert(coordinateTwo.y() == 2) +assert(coordinateTwo.z() == 4) + +############################# +# Math.h +assert(simCore.intSdkMax(-1, 2) == 2) +assert(simCore.intSdkMin(-1, 2) == -1) +assert(simCore.doubleSdkMax(-1, 2) == 2) +assert(simCore.doubleSdkMin(-1.0, 2) == -1) +assert(simCore.intSquare(2) == 4) +assert(simCore.intSign(2) == 1) +assert(simCore.intSign(0) == 0) +assert(simCore.doubleSign(-1.3) == -1) +assert(simCore.doubleSdkMax(-1.3, 2.0) == 2.0) +assert(simCore.doubleSdkMin(-1.3, 2.0) == -1.3) +assert(simCore.doubleSquare(2.0) == 4.0) +assert(simCore.doubleSign(-1.2) == -1) +assert(simCore.doubleSign(0.0) == 0) +assert(simCore.rint(1.1) == 1) +assert(simCore.rint(1.5) == 2) +assert(simCore.rint(2.5) == 2) +assert(simCore.rint(3.5) == 4) +assert(simCore.rint(2) == 2) +assert(simCore.round(1) == 1) +assert(simCore.round(1.1) == 1) +assert(simCore.round(1.5) == 2) +assert(not simCore.odd(2)) +assert(simCore.odd(3)) +assert(simCore.areEqual(1, 1.0000001)) +assert(simCore.guessStepSize(10, 0) == 1) +assert(simCore.isFinite(v)) +v2 = simCore.Vec3(1, 2, 3) +assert(v2 is not None) +assert(simCore.v3Distance(v, v2) == math.sqrt(26)) +# TODO: Test v3Scale in Math.h. Will need to make a fix to handle the class output parameter in order for this to function. +# v2 = simCore.v3Scale(2, v) +# assert(v2.x() == 12) +# assert(v2.y() == 4) +# assert(v2.z() == 8) +vecLen = simCore.v3Unit(v2) +assert(vecLen is not None) +assert(vecLen == math.sqrt(14)) +assert(v2.x() == 1 * 1/vecLen) +assert(v2.y() == 2 * 1/vecLen) +assert(v2.z() == 3 * 1/vecLen) +mantissa, numZeroes = simCore.toScientific(12345) +assert(mantissa is not None) +assert(numZeroes is not None) +mantissa, numZeroes = simCore.toScientific(12345) +assert(mantissa is not None) +assert(mantissa == 1.2345) +assert(numZeroes is not None) +assert(numZeroes == 4) + +############################# +# CoordinateConverter.h +coordConverter = simCore.CoordinateConverter() +assert(coordConverter is not None) +assert(not coordConverter.hasReferenceOrigin()) +refOrigin = simCore.Vec3(44.544, -72.782, 1699) +assert(refOrigin.x() == 44.544) +assert(refOrigin.y() == -72.782) +assert(refOrigin.z() == 1699) +coordConverter.setReferenceOriginDegrees(refOrigin) +assert(coordConverter.hasReferenceOrigin()) +llaVector = simCore.Vec3(0, 45, 1000) +assert(llaVector is not None) +assert(simCore.Coordinate() is not None) +coordinateObj = simCore.Coordinate(simCore.COORD_SYS_LLA, llaVector) +assert(coordinateObj is not None) +assert(coordinateObj.coordinateSystem() == simCore.COORD_SYS_LLA) +assert(coordinateObj.position() == llaVector) +# TODO: There are several places in CoordinateConverter.cpp that make use of Vec3& or Coordinate& output parameters. Create tests for these methods that allow you to use these more complex output parameters. +# inputEcefVector = simCore.Vec3(0, 0, 0) +# outputLlaVector = coordConverter.convertEcefToGeodeticPos(inputEcefVector) +# inputNedVector = simCore.Vec3(1334.3, -2543.6, 359.65) +# outputEnuVector = coordConverter.swapNedEnu(inputNedVector) +# assert(outputEnuVector.x() == inputNedVector.y()) +# assert(outputEnuVector.y() == inputNedVector.x()) +# assert(outputEnuVector.z() == -inputNedVector.z()) +# outputNwuVector = coordConverter.swapNedNwu(inputNedVector) +# assert(outputNwuVector.x() == inputNedVector.x()) +# assert(outputNwuVector.y() == -inputNedVector.y()) +# assert(outputNwuVector.z() == -inputNedVector.z()) +# outputNwuVector = coordConverter.convertEnuToNwu(outputEnuVector) +# assert(outputNwuVector.x() == inputNedVector.x()) +# assert(outputNwuVector.y() == -inputNedVector.y()) +# assert(outputNwuVector.z() == -inputNedVector.z()) +# outputEnuVector = coordConverter.convertNwuToEnu(outputNwuVector) +# assert(outputEnuVector.x() == inputNedVector.y()) +# assert(outputEnuVector.y() == inputNedVector.x()) +# assert(outputEnuVector.z() == -inputNedVector.z()) # TODO: More testing here print("Success!"); diff --git a/swig/simCore/simCore.i b/swig/simCore/simCore.i index 12661b622..60b3fb951 100644 --- a/swig/simCore/simCore.i +++ b/swig/simCore/simCore.i @@ -38,6 +38,7 @@ typedef long int64_t; %ignore simCore::Vec3::operator=; %ignore simCore::Vec3::operator[]; %ignore simCore::Coordinate::operator=; +%ignore simCore::CoordinateConverter::operator=; // Note, order of inclusion matters @@ -45,17 +46,54 @@ typedef long int64_t; // simCore/Common %include "simCore/Common/Exception.h" %include "simCore/Common/FileSearch.h" -%include "simCore/Common/HighPerformanceGraphics.h" %include "simCore/Common/Time.h" +/* + * TODO: Test this + * %include "simCore/Common/HighPerformanceGraphics.h" + */ +// Explicitly defining timezone struct so that it is wrapped successfully. +struct timezone +{ + int tz_minuteswest; /**< the number of minutes west of GMT */ + int tz_dsttime; /**< If nonzero, daylight savings time applies during some part of the year */ +}; + +// TODO: Support timespec struct. Might need to use typemap? + //////////////////////////////////////////////// // simCore/Calc %include "simCore/Calc/Vec3.h" +// TODO: Make tests using constants defined under #ifdef WIN32. +%include "simCore/Calc/MathConstants.h" %include "simCore/Calc/Angle.h" + +// simCore::coordinateSystemFromString() +%apply int& OUTPUT { simCore::CoordinateSystem& outSystem }; + %include "simCore/Calc/CoordinateSystem.h" + +// TODO: Implement typemap that allows simCore::Coordinate objects to be used as output parameters. %include "simCore/Calc/Coordinate.h" +// Handling output parameter for toScientific() from simCore/calc/Math.cpp +%apply int* OUTPUT { int* exp }; + +// TODO: Create a test for v3Scale in Math.h, which requires finding a way to handle the Vec3& output parameter. +%include "simCore/Calc/Math.h" +%include "simCore/Calc/CoordinateConverter.h" + +%template(intSdkMax) simCore::sdkMax; +%template(intSdkMin) simCore::sdkMin; +%template(intSquare) simCore::square; +%template(intSign) simCore::sign; +%template(doubleSdkMax) simCore::sdkMax; +%template(doubleSdkMin) simCore::sdkMin; +%template(doubleSquare) simCore::square; +%template(doubleSign) simCore::sign; + // TODO: Add these and test them as you add them +// Some of these may have to be added together, since they depend on eachother. /* %include "simCore/Calc/Calculations.h" %include "simCore/Calc/CoordinateConverter.h" @@ -65,8 +103,6 @@ typedef long int64_t; %include "simCore/Calc/GogToGeoFence.h" %include "simCore/Calc/Interpolation.h" %include "simCore/Calc/MagneticVariance.h" -%include "simCore/Calc/MathConstants.h" -%include "simCore/Calc/Math.h" %include "simCore/Calc/Mgrs.h" %include "simCore/Calc/MultiFrameCoordinate.h" %include "simCore/Calc/NumericalAnalysis.h" From 621182ea7b52376b578ce0b4679dc72007eff77a Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Fri, 21 Feb 2020 10:56:50 -0500 Subject: [PATCH 078/121] DEV: SWIG now works properly on Linux. Removed compatibility-intended timezone stuff and removed comments about similiar timespec methods. Removed testing of constants in MathConstants.h, which are only for compatibility on Windows and have their own values in Python. Updated unit test to use Python functions. Review: 20757 --- swig/Testing/TestSimCore.py | 13 +------------ swig/simCore/simCore.i | 15 --------------- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index 1b7545aad..a348e89a5 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -45,13 +45,6 @@ def sleepWrapper(): print("Sleeping for about a tenth of a second.") assert(timeit.timeit(sleepWrapper, number=1) >= .05) -# Defined timezone struct in .i file so that it was exposed to python. -timezone = simCore.timezone() -assert(timezone is not None) -timezone.tz_minuteswest = 1 -assert(timezone.tz_minuteswest == 1) -timezone.tz_dsttime = 2 -assert(timezone.tz_dsttime == 2) # TODO: Support timespec_t typedef struct. It is currently missing from the .cxx generated wrapper class, might need to use a typemap? # timespec = simCore.timesepc_t() # assert(timespec is not None) @@ -75,14 +68,10 @@ def sleepWrapper(): assert(v.y() == 2) assert(v.z() == 4) -############################# -# MathConstants.h -assert(simCore.M_TWOPI == 6.28318530717958647692) - ############################# # Angle.h assert(simCore.angFix360(720) == 0) -assert(simCore.areAnglesEqual(0, simCore.M_TWOPI) == True) +assert(simCore.areAnglesEqual(0, math.pi * 2) == True) angleExtents = simCore.ANGLEEXTENTS_TWOPI assert(angleExtents is not None) assert(simCore.angFixDegrees(360, angleExtents) == 0) diff --git a/swig/simCore/simCore.i b/swig/simCore/simCore.i index 60b3fb951..c5db2fee9 100644 --- a/swig/simCore/simCore.i +++ b/swig/simCore/simCore.i @@ -48,24 +48,9 @@ typedef long int64_t; %include "simCore/Common/FileSearch.h" %include "simCore/Common/Time.h" -/* - * TODO: Test this - * %include "simCore/Common/HighPerformanceGraphics.h" - */ -// Explicitly defining timezone struct so that it is wrapped successfully. -struct timezone -{ - int tz_minuteswest; /**< the number of minutes west of GMT */ - int tz_dsttime; /**< If nonzero, daylight savings time applies during some part of the year */ -}; - -// TODO: Support timespec struct. Might need to use typemap? - //////////////////////////////////////////////// // simCore/Calc %include "simCore/Calc/Vec3.h" -// TODO: Make tests using constants defined under #ifdef WIN32. -%include "simCore/Calc/MathConstants.h" %include "simCore/Calc/Angle.h" // simCore::coordinateSystemFromString() From e3b3d53e47d720282f4cdfe7a8a3105964466008 Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Fri, 21 Feb 2020 11:52:48 -0500 Subject: [PATCH 079/121] SIM-11076 Projectors now support override color Release: simVis::Projector now supports override color preferences. Notes: Used the equations in the JIRA issue Test Environment: Windows 10, Visual Studio 2017, Debug Test: Manual testing, I saw the color of the dot change as I enable/disabled override color. And, the color of the dot changed when I changed the override color. Review: 20760 --- SDK/simVis/Projector.cpp | 23 +++++++++++++++++++++++ SDK/simVis/Projector.frag.glsl | 26 +++++++++++++++++++++++--- SDK/simVis/Projector.h | 4 ++++ SDK/simVis/ProjectorManager.cpp | 2 ++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/SDK/simVis/Projector.cpp b/SDK/simVis/Projector.cpp index dae24dcbf..f9624c02c 100644 --- a/SDK/simVis/Projector.cpp +++ b/SDK/simVis/Projector.cpp @@ -207,9 +207,12 @@ void ProjectorNode::init_() projectorAlpha_ = new osg::Uniform(osg::Uniform::FLOAT, "projectorAlpha"); texProjPosUniform_ = new osg::Uniform(osg::Uniform::FLOAT_VEC3, "simProjPos"); texProjDirUniform_ = new osg::Uniform(osg::Uniform::FLOAT_VEC3, "simProjDir"); + useColorOverrideUniform_= new osg::Uniform(osg::Uniform::BOOL, "projectorUseColorOverride"); + colorOverrideUniform_ = new osg::Uniform(osg::Uniform::FLOAT_VEC4, "projectorColorOverride"); projectorActive_->set(false); projectorAlpha_->set(DEFAULT_ALPHA_VALUE); + useColorOverrideUniform_->set(false); // Set texture to default broken image texture_ = new osg::Texture2D(simVis::makeBrokenImage()); @@ -332,6 +335,8 @@ void ProjectorNode::setPrefs(const simData::ProjectorPrefs& prefs) projectorAlpha_->set(prefs.projectoralpha()); } + updateOverrideColor_(prefs); + // If override FOV changes, update the FOV with a sync-with-locator call bool syncAfterPrefsUpdate = false; if (!hasLastPrefs_ || PB_FIELD_CHANGED(&lastPrefs_, &prefs, overridefov) || @@ -349,6 +354,20 @@ void ProjectorNode::setPrefs(const simData::ProjectorPrefs& prefs) syncWithLocator(); } +void ProjectorNode::updateOverrideColor_(const simData::ProjectorPrefs& prefs) +{ + if (hasLastPrefs_ && + !PB_SUBFIELD_CHANGED(&lastPrefs_, &prefs, commonprefs, useoverridecolor) && + !PB_SUBFIELD_CHANGED(&lastPrefs_, &prefs, commonprefs, overridecolor) && + !PB_SUBFIELD_CHANGED(&lastPrefs_, &prefs, commonprefs, color)) + return; + + // using an override color? + auto color = simVis::Color(prefs.commonprefs().overridecolor(), simVis::Color::RGBA); + colorOverrideUniform_->set(color); + useColorOverrideUniform_->set(prefs.commonprefs().useoverridecolor()); +} + bool ProjectorNode::readVideoFile_(const std::string& filename) { osg::Node* result = NULL; @@ -633,6 +652,8 @@ void ProjectorNode::addProjectionToNode(osg::Node* node) stateSet->addUniform(projectorAlpha_.get()); stateSet->addUniform(texProjDirUniform_.get()); stateSet->addUniform(texProjPosUniform_.get()); + stateSet->addUniform(useColorOverrideUniform_.get()); + stateSet->addUniform(colorOverrideUniform_.get()); // to compute the texture generation matrix: node->addCullCallback(projectOnNodeCallback_.get()); @@ -663,6 +684,8 @@ void ProjectorNode::removeProjectionFromNode(osg::Node* node) stateSet->removeUniform(projectorAlpha_.get()); stateSet->removeUniform(texProjDirUniform_.get()); stateSet->removeUniform(texProjPosUniform_.get()); + stateSet->removeUniform(useColorOverrideUniform_.get()); + stateSet->removeUniform(colorOverrideUniform_.get()); } node->removeCullCallback(projectOnNodeCallback_.get()); diff --git a/SDK/simVis/Projector.frag.glsl b/SDK/simVis/Projector.frag.glsl index d26fbf8d7..92acec3b9 100644 --- a/SDK/simVis/Projector.frag.glsl +++ b/SDK/simVis/Projector.frag.glsl @@ -9,6 +9,9 @@ uniform bool projectorActive; uniform float projectorAlpha; uniform sampler2D simProjSampler; +uniform bool projectorUseColorOverride; +uniform vec4 projectorColorOverride; + in vec4 simProjTexCoord; in vec3 simProjToVert_VIEW; flat in vec3 simProjLookVector_VIEW; @@ -24,10 +27,18 @@ void sim_proj_frag(inout vec4 color) // clip to projected texture domain; otherwise the texture will project // even when the target is outside the projection frustum vec2 local = simProjTexCoord.st / simProjTexCoord.q; - if (clamp(local, 0.0, 1.0) == local) + if (clamp(local, 0.0, 1.0) == local) { vec4 textureColor = textureProj(simProjSampler, simProjTexCoord); - color.rgb = mix(color.rgb, textureColor.rgb, textureColor.a * projectorAlpha); + if (projectorUseColorOverride) + { + color.rgb = textureColor.rgb * projectorColorOverride.rgb; + color.a = textureColor.a * projectorAlpha; + } + else + { + color.rgb = mix(color.rgb, textureColor.rgb, textureColor.a * projectorAlpha); + } } } } @@ -54,10 +65,19 @@ void sim_proj_frag(inout vec4 color) { float vis = -dot(normalize(simProjToVert_VIEW), normalize(vp_Normal)); // >=0 is visible; <0 is over the horizon. if (vis <= 0) - discard; + discard; vec4 textureColor = texture(simProjSampler, local); outColor = vec4(textureColor.r, textureColor.g, textureColor.b, textureColor.a * projectorAlpha); + if (projectorUseColorOverride) + { + outColor.rgb = textureColor.rgb * projectorColorOverride.rgb; + outColor.a = textureColor.a * projectorAlpha; + } + else + { + outColor.rgb = mix(color.rgb, textureColor.rgb, textureColor.a * projectorAlpha); + } } } } diff --git a/SDK/simVis/Projector.h b/SDK/simVis/Projector.h index 971eeb51c..8706edd22 100644 --- a/SDK/simVis/Projector.h +++ b/SDK/simVis/Projector.h @@ -229,6 +229,8 @@ class SDKVIS_EXPORT ProjectorNode : public EntityNode osg::ref_ptr texProjPosUniform_; osg::ref_ptr texProjDirUniform_; osg::ref_ptr texProjSamplerUniform_; + osg::ref_ptr useColorOverrideUniform_; + osg::ref_ptr colorOverrideUniform_; osg::ref_ptr projectOnNodeCallback_; @@ -250,6 +252,8 @@ class SDKVIS_EXPORT ProjectorNode : public EntityNode /// Update label void updateLabel_(const simData::ProjectorPrefs& prefs); + /// Update override color + void updateOverrideColor_(const simData::ProjectorPrefs& prefs); }; } //namespace simVis diff --git a/SDK/simVis/ProjectorManager.cpp b/SDK/simVis/ProjectorManager.cpp index 32b2bb9b7..01987dc03 100644 --- a/SDK/simVis/ProjectorManager.cpp +++ b/SDK/simVis/ProjectorManager.cpp @@ -197,6 +197,8 @@ void ProjectorManager::registerProjector(ProjectorNode* proj) projStateSet->addUniform(proj->projectorAlpha_.get()); projStateSet->addUniform(proj->texProjDirUniform_.get()); projStateSet->addUniform(proj->texProjPosUniform_.get()); + projStateSet->addUniform(proj->useColorOverrideUniform_.get()); + projStateSet->addUniform(proj->colorOverrideUniform_.get()); } void ProjectorManager::unregisterProjector(const ProjectorNode* proj) From 152640f55a80dbc698f5d4b909fa1ed401bf3837 Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Fri, 21 Feb 2020 12:12:52 -0500 Subject: [PATCH 080/121] SIM-11076 Projectors and Projector Manager Are No Longer Friends Release: N/A. Notes: The use of friends should be strongly discouraged. There is now only one place that needs to be updated when a new Uniform is added. Test Environment: Windows 10, Visual Studio 2017, Debug Test: Projector override color still works Review: 20761 --- SDK/simVis/Projector.cpp | 34 +++++++++++++++++++++------------ SDK/simVis/Projector.h | 7 +++++-- SDK/simVis/ProjectorManager.cpp | 7 +------ 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/SDK/simVis/Projector.cpp b/SDK/simVis/Projector.cpp index f9624c02c..d97b6ecc1 100644 --- a/SDK/simVis/Projector.cpp +++ b/SDK/simVis/Projector.cpp @@ -262,6 +262,26 @@ const simData::ProjectorUpdate* ProjectorNode::getLastUpdateFromDS() const return hasLastUpdate_ ? &lastUpdate_ : NULL; } +void ProjectorNode::addUniforms(osg::StateSet* stateSet) const +{ + stateSet->addUniform(projectorActive_.get()); + stateSet->addUniform(projectorAlpha_.get()); + stateSet->addUniform(texProjDirUniform_.get()); + stateSet->addUniform(texProjPosUniform_.get()); + stateSet->addUniform(useColorOverrideUniform_.get()); + stateSet->addUniform(colorOverrideUniform_.get()); +} + +void ProjectorNode::removeUniforms(osg::StateSet* stateSet) const +{ + stateSet->removeUniform(projectorActive_.get()); + stateSet->removeUniform(projectorAlpha_.get()); + stateSet->removeUniform(texProjDirUniform_.get()); + stateSet->removeUniform(texProjPosUniform_.get()); + stateSet->removeUniform(useColorOverrideUniform_.get()); + stateSet->removeUniform(colorOverrideUniform_.get()); +} + std::string ProjectorNode::popupText() const { if (hasLastUpdate_ && hasLastPrefs_) @@ -648,12 +668,7 @@ void ProjectorNode::addProjectionToNode(osg::Node* node) // Set texture from projector into state set stateSet->setTextureAttribute(ProjectorManager::getTextureImageUnit(), getTexture()); - stateSet->addUniform(projectorActive_.get()); - stateSet->addUniform(projectorAlpha_.get()); - stateSet->addUniform(texProjDirUniform_.get()); - stateSet->addUniform(texProjPosUniform_.get()); - stateSet->addUniform(useColorOverrideUniform_.get()); - stateSet->addUniform(colorOverrideUniform_.get()); + addUniforms(stateSet); // to compute the texture generation matrix: node->addCullCallback(projectOnNodeCallback_.get()); @@ -680,12 +695,7 @@ void ProjectorNode::removeProjectionFromNode(osg::Node* node) stateSet->removeTextureAttribute(ProjectorManager::getTextureImageUnit(), getTexture()); - stateSet->removeUniform(projectorActive_.get()); - stateSet->removeUniform(projectorAlpha_.get()); - stateSet->removeUniform(texProjDirUniform_.get()); - stateSet->removeUniform(texProjPosUniform_.get()); - stateSet->removeUniform(useColorOverrideUniform_.get()); - stateSet->removeUniform(colorOverrideUniform_.get()); + removeUniforms(stateSet); } node->removeCullCallback(projectOnNodeCallback_.get()); diff --git a/SDK/simVis/Projector.h b/SDK/simVis/Projector.h index 8706edd22..b134b4e3f 100644 --- a/SDK/simVis/Projector.h +++ b/SDK/simVis/Projector.h @@ -111,6 +111,11 @@ class SDKVIS_EXPORT ProjectorNode : public EntityNode */ const simData::ProjectorUpdate* getLastUpdateFromDS() const; + /// Add projector uniforms to the given StateSet + void addUniforms(osg::StateSet* stateSet) const; + /// Remove projector uniforms to the given StateSet + void removeUniforms(osg::StateSet* stateSet) const; + public: // EntityNode interface /** * Whether the entity is active within the scenario at the current time. @@ -234,8 +239,6 @@ class SDKVIS_EXPORT ProjectorNode : public EntityNode osg::ref_ptr projectOnNodeCallback_; - friend class ProjectorManager; // manager wants access to the uniforms. - void getMatrices_( osg::Matrixd& out_projection, osg::Matrixd& out_locator, diff --git a/SDK/simVis/ProjectorManager.cpp b/SDK/simVis/ProjectorManager.cpp index 01987dc03..81935e90e 100644 --- a/SDK/simVis/ProjectorManager.cpp +++ b/SDK/simVis/ProjectorManager.cpp @@ -193,12 +193,7 @@ void ProjectorManager::registerProjector(ProjectorNode* proj) // Set texture from projector into state set projStateSet->setTextureAttribute(PROJECTOR_TEXTURE_UNIT, proj->getTexture()); - projStateSet->addUniform(proj->projectorActive_.get()); - projStateSet->addUniform(proj->projectorAlpha_.get()); - projStateSet->addUniform(proj->texProjDirUniform_.get()); - projStateSet->addUniform(proj->texProjPosUniform_.get()); - projStateSet->addUniform(proj->useColorOverrideUniform_.get()); - projStateSet->addUniform(proj->colorOverrideUniform_.get()); + proj->addUniforms(projStateSet); } void ProjectorManager::unregisterProjector(const ProjectorNode* proj) From ca89c414af33ccf313ff6b0be7e168ef8fb19ad4 Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Fri, 21 Feb 2020 12:17:45 -0500 Subject: [PATCH 081/121] Addendum to Review 20761 to fix documentation. --- SDK/simVis/Projector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/simVis/Projector.h b/SDK/simVis/Projector.h index b134b4e3f..f6b32a743 100644 --- a/SDK/simVis/Projector.h +++ b/SDK/simVis/Projector.h @@ -113,7 +113,7 @@ class SDKVIS_EXPORT ProjectorNode : public EntityNode /// Add projector uniforms to the given StateSet void addUniforms(osg::StateSet* stateSet) const; - /// Remove projector uniforms to the given StateSet + /// Remove projector uniforms from the given StateSet void removeUniforms(osg::StateSet* stateSet) const; public: // EntityNode interface From 30568609fc25f85d695f2d322c96b00febb5d271 Mon Sep 17 00:00:00 2001 From: Andrew LaFrance Date: Fri, 21 Feb 2020 13:34:11 -0500 Subject: [PATCH 082/121] Addendum to changeset: 1645 removing the simCore_SWIG test from the test list, due to build machine failures. No Review --- swig/Testing/CMakeLists.txt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/swig/Testing/CMakeLists.txt b/swig/Testing/CMakeLists.txt index d625dfb22..58bf64bce 100644 --- a/swig/Testing/CMakeLists.txt +++ b/swig/Testing/CMakeLists.txt @@ -25,7 +25,8 @@ if(NOT Python3_Interpreter_FOUND) endif() # Add the tests -add_test(NAME simCore_SWIG_Test COMMAND "${Python3_EXECUTABLE}" "TestSimCore.py" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") +# Commented out because of build machine test failures. +#add_test(NAME simCore_SWIG_Test COMMAND "${Python3_EXECUTABLE}" "TestSimCore.py" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") # Windows insists on installing under a CONFIG directory under the runtime output directory if(WIN32) @@ -34,8 +35,8 @@ else() set(PYTHON_PATH "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") endif() -set_tests_properties( - simCore_SWIG_Test - PROPERTIES - ENVIRONMENT "PYTHONPATH=${PYTHON_PATH}" -) +#set_tests_properties( +# simCore_SWIG_Test +# PROPERTIES +# ENVIRONMENT "PYTHONPATH=${PYTHON_PATH}" +#) From eb3450f3f014c1b1188fff99872ca5e13c012ef0 Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Mon, 24 Feb 2020 09:30:17 -0500 Subject: [PATCH 083/121] cppCheck on SDK Release: N/A. Notes: N/A Test Environment: Windows 10, Visual Studio 2017, Debug Test: Compile Review: 20768 --- SDK/simCore/Calc/Gars.cpp | 7 ++----- SDK/simData/MemoryDataStore.cpp | 12 ++++++------ SDK/simQt/BoundSettings.cpp | 5 +---- SDK/simQt/EntityTreeComposite.cpp | 1 + SDK/simQt/MapDataModel.cpp | 3 +-- SDK/simUtil/Capabilities.cpp | 2 +- SDK/simUtil/HudPositionManager.cpp | 2 +- SDK/simUtil/StatusText.cpp | 7 ++++++- SDK/simVis/AxisVector.cpp | 4 +--- SDK/simVis/ChromaKeyColorFilter.cpp | 3 +-- SDK/simVis/DB/QSNodeID96.h | 2 +- SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp | 3 +-- SDK/simVis/DBFormat.cpp | 1 + SDK/simVis/GOG/Annotation.cpp | 3 +-- SDK/simVis/GOG/GogNodeInterface.cpp | 4 ---- SDK/simVis/GOG/Parser.cpp | 2 +- SDK/simVis/OverheadMode.cpp | 2 +- SDK/simVis/Projector.cpp | 2 +- SDK/simVis/ProjectorManager.cpp | 2 +- SDK/simVis/SimdisMeasurement.cpp | 2 +- SDK/simVis/SphericalVolume.cpp | 2 -- 21 files changed, 30 insertions(+), 41 deletions(-) diff --git a/SDK/simCore/Calc/Gars.cpp b/SDK/simCore/Calc/Gars.cpp index 8565a9906..f4ea13973 100644 --- a/SDK/simCore/Calc/Gars.cpp +++ b/SDK/simCore/Calc/Gars.cpp @@ -151,14 +151,11 @@ int Gars::convertGarsToGeodetic(const std::string& gars, double& latRad, double& if (!Gars::isValidGars(gars, err, &lonBand, &latPrimaryIndex, &latSecondaryIndex, &quad15, &key5)) return 1; // Error was set by isValidGars() - double lat = 0.; - double lon = 0.; - // Convert from lonBand integer to longitude value - lon = (lonBand - 360 - 1) * 0.5; + double lon = (lonBand - 360 - 1) * 0.5; // Start latitude at -90 - lat = -90.0; + double lat = -90.0; // Move it up 12 degrees per primary letter lat += (latPrimaryIndex * DEG_PER_PRIMARY_LETTER); // Move it up 0.5 degrees per secondary letter diff --git a/SDK/simData/MemoryDataStore.cpp b/SDK/simData/MemoryDataStore.cpp index 302aa2a13..a3686be88 100644 --- a/SDK/simData/MemoryDataStore.cpp +++ b/SDK/simData/MemoryDataStore.cpp @@ -252,14 +252,15 @@ class MemoryDataStore::MemoryInternalsMemento : public InternalsMemento public: /** Constructor for a memento for the MemoryDataStore */ explicit MemoryInternalsMemento(const MemoryDataStore &ds) + : interpolator_(ds.interpolator_), + interpolationEnabled_(ds.interpolationEnabled_), + listeners_(ds.listeners_), + scenarioListeners_(ds.scenarioListeners_), + newUpdatesListener_(ds.newUpdatesListener_), + boundClock_(ds.boundClock_) { // fill in everything - interpolator_ = ds.interpolator_; - interpolationEnabled_ = ds.interpolationEnabled_; - listeners_ = ds.listeners_; - scenarioListeners_ = ds.scenarioListeners_; - newUpdatesListener_ = ds.newUpdatesListener_; ds.dataTableManager().getObservers(dtObservers_); ds.categoryNameManager().getListeners(catListeners_); defaultPlatformPrefs_.CopyFrom(ds.defaultPlatformPrefs_); @@ -269,7 +270,6 @@ class MemoryDataStore::MemoryInternalsMemento : public InternalsMemento defaultLobGroupPrefs_.CopyFrom(ds.defaultLobGroupPrefs_); defaultProjectorPrefs_.CopyFrom(ds.defaultProjectorPrefs_); defaultCustomRenderingPrefs_.CopyFrom(ds.defaultCustomRenderingPrefs_); - boundClock_ = ds.boundClock_; } virtual ~MemoryInternalsMemento() diff --git a/SDK/simQt/BoundSettings.cpp b/SDK/simQt/BoundSettings.cpp index de2010f3d..f2cf3ca79 100644 --- a/SDK/simQt/BoundSettings.cpp +++ b/SDK/simQt/BoundSettings.cpp @@ -400,10 +400,7 @@ void BoundColorSetting::bindTo(simQt::ColorWidget* colorWidget, bool populateToo { Settings::MetaData metaData; if (settings_.metaData(variableName_, metaData) == 0) - { - if (populateToolTip) - colorWidget->setToolTip(metaData.toolTip()); - } + colorWidget->setToolTip(metaData.toolTip()); } colorWidget->setColor(value_); connect(this, SIGNAL(valueChanged(const QColor&)), colorWidget, SLOT(setColor(const QColor&))); diff --git a/SDK/simQt/EntityTreeComposite.cpp b/SDK/simQt/EntityTreeComposite.cpp index 09b921a0f..0b7122c21 100644 --- a/SDK/simQt/EntityTreeComposite.cpp +++ b/SDK/simQt/EntityTreeComposite.cpp @@ -127,6 +127,7 @@ class EntityTreeComposite::ButtonActions private: /** Declared but not defined to keep cppCheck warning free */ ButtonActions(const ButtonActions& rhs); + ButtonActions& operator=(ButtonActions& rhs); /** Sets the text and tooltip on the "Load" button */ void setLoadTextAndTooltips_(const QString& filterName) diff --git a/SDK/simQt/MapDataModel.cpp b/SDK/simQt/MapDataModel.cpp index 4acef255e..058c04314 100644 --- a/SDK/simQt/MapDataModel.cpp +++ b/SDK/simQt/MapDataModel.cpp @@ -1371,10 +1371,9 @@ QVariant MapDataModel::layerMapIndex_(osgEarth::Layer* layer) const if (layer == NULL || !map_.valid()) return QVariant(); - unsigned int index = MapReindexer::INVALID_INDEX; osgEarth::LayerVector layers; map_->getLayers(layers); - index = indexOf(layers, layer); + unsigned int index = indexOf(layers, layer); if (index != MapReindexer::INVALID_INDEX) return index; diff --git a/SDK/simUtil/Capabilities.cpp b/SDK/simUtil/Capabilities.cpp index ee8e19839..dd44ddada 100644 --- a/SDK/simUtil/Capabilities.cpp +++ b/SDK/simUtil/Capabilities.cpp @@ -231,7 +231,7 @@ void Capabilities::init_(osg::GraphicsContext& gc) maxTextureCoords = maxTextureUnits; #endif } - else if (glVersion_ >= 1.3f || osg::isGLExtensionSupported(contextId, "GL_ARB_multitexture") || osg::isGLExtensionSupported(contextId, "GL_ARB_multitexture")) + else if (glVersion_ >= 1.3f || osg::isGLExtensionSupported(contextId, "GL_ARB_multitexture")) { // Fall back to multitexturing units for oldest OpenGL glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextureUnits); diff --git a/SDK/simUtil/HudPositionManager.cpp b/SDK/simUtil/HudPositionManager.cpp index b7b4fe43a..c6a17118f 100644 --- a/SDK/simUtil/HudPositionManager.cpp +++ b/SDK/simUtil/HudPositionManager.cpp @@ -238,7 +238,7 @@ int HudPositionManager::setSize(const std::string& name, const osg::Vec2d& minXy class RepositionPixelsCallback::ResizeCallback : public osgGA::GUIEventHandler { public: - ResizeCallback(RepositionPixelsCallback* parent) + explicit ResizeCallback(RepositionPixelsCallback* parent) : windowSize_(0.0, 0.0), parent_(parent) { diff --git a/SDK/simUtil/StatusText.cpp b/SDK/simUtil/StatusText.cpp index a4b612a86..da7ae7c72 100644 --- a/SDK/simUtil/StatusText.cpp +++ b/SDK/simUtil/StatusText.cpp @@ -89,7 +89,12 @@ class StatusText::FrameEventHandler : public osgGA::GUIEventHandler { public: /** Constructor */ - explicit FrameEventHandler(simUtil::StatusText* parent) : parent_(parent) {} + explicit FrameEventHandler(simUtil::StatusText* parent) + : parent_(parent), + widthPx_(-1), + heightPx_(-1) + { + } /** Handles frame updates and returns false so other handlers can process as well */ bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa) { diff --git a/SDK/simVis/AxisVector.cpp b/SDK/simVis/AxisVector.cpp index 630bc2efe..9cab305af 100644 --- a/SDK/simVis/AxisVector.cpp +++ b/SDK/simVis/AxisVector.cpp @@ -139,10 +139,8 @@ void AxisVector::setPositionOrientation(const osg::Vec3f& pos, const osg::Vec3f& void AxisVector::createAxisVectors_(osg::Geode* geode) const { - osgEarth::LineDrawable* line = NULL; - // draw x axis vector - line = new osgEarth::LineDrawable(GL_LINE_STRIP); + osgEarth::LineDrawable* line = new osgEarth::LineDrawable(GL_LINE_STRIP); line->setName("simVis::AxisVector"); line->allocate(AXIS_NUM_POINTS_PER_LINE_STRIP); VectorScaling::generatePoints(*line, osg::Vec3(), osg::X_AXIS); diff --git a/SDK/simVis/ChromaKeyColorFilter.cpp b/SDK/simVis/ChromaKeyColorFilter.cpp index 26c499e65..3eb5965e6 100644 --- a/SDK/simVis/ChromaKeyColorFilter.cpp +++ b/SDK/simVis/ChromaKeyColorFilter.cpp @@ -70,8 +70,7 @@ ChromaKeyColorFilter::ChromaKeyColorFilter(const osgEarth::Config& conf) val[2] = conf.value("b", 0.0); setColor(val); - float distance = 0.0f; - distance = conf.value("distance", 0.0f); + float distance = conf.value("distance", 0.0f); setDistance(distance); } diff --git a/SDK/simVis/DB/QSNodeID96.h b/SDK/simVis/DB/QSNodeID96.h index e738e2e95..d656ec1a1 100644 --- a/SDK/simVis/DB/QSNodeID96.h +++ b/SDK/simVis/DB/QSNodeID96.h @@ -31,7 +31,7 @@ namespace simVis_db { public: QSNodeID96(); - QSNodeID96(const uint32_t& value); + explicit QSNodeID96(const uint32_t& value); ~QSNodeID96(); bool operator==(const QSNodeID96& value) const; diff --git a/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp b/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp index 3fd642dd3..6f89b4d3c 100644 --- a/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp +++ b/SDK/simVis/DB/SQLiteDataBaseReadUtil.cpp @@ -182,13 +182,12 @@ QsErrorType SQLiteDataBaseReadUtil::readDataBuffer(sqlite3* sqlite3Db, // opens the database bool localDb = false; - QsErrorType tmpReturnValue; if (sqlite3Db == NULL) { if (allowLocalDB == false) return QS_IS_DB_NOT_INITIALIZED; localDb = true; - tmpReturnValue = openDatabaseFile(dbFileName, &sqlite3Db, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX); + QsErrorType tmpReturnValue = openDatabaseFile(dbFileName, &sqlite3Db, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX); if (tmpReturnValue != QS_IS_OK) return tmpReturnValue; } diff --git a/SDK/simVis/DBFormat.cpp b/SDK/simVis/DBFormat.cpp index 79ff5feb2..c649b2765 100644 --- a/SDK/simVis/DBFormat.cpp +++ b/SDK/simVis/DBFormat.cpp @@ -134,6 +134,7 @@ namespace deepLevel_ = 32; timeSpecified_ = false; timeStamp_ = simCore::INFINITE_TIME_STAMP; + db_ = NULL; } int rasterFormat_; diff --git a/SDK/simVis/GOG/Annotation.cpp b/SDK/simVis/GOG/Annotation.cpp index 21ddefdd7..e16fe5c11 100644 --- a/SDK/simVis/GOG/Annotation.cpp +++ b/SDK/simVis/GOG/Annotation.cpp @@ -44,8 +44,7 @@ GogNodeInterface* TextAnnotation::deserialize( p.parseGeometry(parsedShape); GogNodeInterface* rv = NULL; - osgEarth::LabelNode* label = NULL; - label = new osgEarth::LabelNode(text, p.style_); + osgEarth::LabelNode* label = new osgEarth::LabelNode(text, p.style_); label->setName("GOG Label"); if (nodeType == GOGNODE_GEOGRAPHIC) { diff --git a/SDK/simVis/GOG/GogNodeInterface.cpp b/SDK/simVis/GOG/GogNodeInterface.cpp index ae9b65825..8a6db9854 100644 --- a/SDK/simVis/GOG/GogNodeInterface.cpp +++ b/SDK/simVis/GOG/GogNodeInterface.cpp @@ -1722,10 +1722,6 @@ int LabelNodeInterface::getPosition(osg::Vec3d& position, osgEarth::GeoPoint* re int LabelNodeInterface::getTextOutline(osg::Vec4f& outlineColor, simData::TextOutline& outlineThickness) const { - if (!style_.has()) - return 1; - const osgEarth::TextSymbol* ts = style_.getSymbol(); - outlineColor = outlineColor_; outlineThickness = outlineThickness_; return 0; diff --git a/SDK/simVis/GOG/Parser.cpp b/SDK/simVis/GOG/Parser.cpp index 9070ad766..48cc75763 100644 --- a/SDK/simVis/GOG/Parser.cpp +++ b/SDK/simVis/GOG/Parser.cpp @@ -670,7 +670,7 @@ bool Parser::parse(std::istream& input, std::vector& output, std::v printError_(lineNumber, "angleunits command requires 1 argument"); } } - else if (tokens[0] == "verticaldatum" && tokens.size() >= 2) + else if (tokens[0] == "verticaldatum") { if (tokens.size() >= 2) { diff --git a/SDK/simVis/OverheadMode.cpp b/SDK/simVis/OverheadMode.cpp index f059b9132..ebefaa2ee 100644 --- a/SDK/simVis/OverheadMode.cpp +++ b/SDK/simVis/OverheadMode.cpp @@ -139,8 +139,8 @@ namespace osg::ref_ptr _stateset; OceanOverheadModeCallback() + : _stateset(new osg::StateSet()) { - _stateset = new osg::StateSet(); // draw the ocean in the same render bin as the terrain _stateset->setRenderBinDetails(simVis::BIN_TERRAIN, simVis::BIN_GLOBAL_SIMSDK, osg::StateSet::OVERRIDE_RENDERBIN_DETAILS); // disable depth buffer writes diff --git a/SDK/simVis/Projector.cpp b/SDK/simVis/Projector.cpp index d97b6ecc1..637ceefdf 100644 --- a/SDK/simVis/Projector.cpp +++ b/SDK/simVis/Projector.cpp @@ -128,7 +128,7 @@ namespace class UpdateProjMatrix : public osg::NodeCallback { public: - UpdateProjMatrix(simVis::ProjectorNode* node) : proj_(node) + explicit UpdateProjMatrix(simVis::ProjectorNode* node) : proj_(node) { //nop } diff --git a/SDK/simVis/ProjectorManager.cpp b/SDK/simVis/ProjectorManager.cpp index 81935e90e..963ed48be 100644 --- a/SDK/simVis/ProjectorManager.cpp +++ b/SDK/simVis/ProjectorManager.cpp @@ -62,7 +62,7 @@ simData::ObjectId ProjectorManager::ProjectorLayer::id() const class UpdateProjMatrix : public osgEarth::Layer::TraversalCallback { public: - UpdateProjMatrix(ProjectorNode* node) : proj_(node) + explicit UpdateProjMatrix(ProjectorNode* node) : proj_(node) { //nop } diff --git a/SDK/simVis/SimdisMeasurement.cpp b/SDK/simVis/SimdisMeasurement.cpp index 9fe413f37..7963a5932 100644 --- a/SDK/simVis/SimdisMeasurement.cpp +++ b/SDK/simVis/SimdisMeasurement.cpp @@ -349,7 +349,7 @@ double HorizonMeasurement::calcAboveHorizon_(RangeToolState& state, simCore::Hor osgEarth::GeoPoint currGeoPoint(state.mapNode_->getMapSRS()->getGeographicSRS(), 0, 0, 0, osgEarth::ALTMODE_ABSOLUTE); // Iterate over the points, sampling the elevation at each until the target becomes invisible: - for (std::vector::const_iterator iter = points.begin(); iter != points.end(); iter++) + for (std::vector::const_iterator iter = points.begin(); iter != points.end(); ++iter) { currGeoPoint.x() = iter->lon() * simCore::RAD2DEG; currGeoPoint.y() = iter->lat() * simCore::RAD2DEG; diff --git a/SDK/simVis/SphericalVolume.cpp b/SDK/simVis/SphericalVolume.cpp index 6bf36ce23..f824f96f7 100644 --- a/SDK/simVis/SphericalVolume.cpp +++ b/SDK/simVis/SphericalVolume.cpp @@ -559,8 +559,6 @@ namespace void svPyramidFactory::generateFaces_(osg::Geometry* faceGeom) { - std::vector& vertexMetaData = metaContainer_->vertMeta_; - // if we are drawing the face (not just the outline) add primitives that index into the vertex array const unsigned int numFaceElements = 2 * numPointsZ_; From 21a9928b8dab10066b7ca7019873606417d95f13 Mon Sep 17 00:00:00 2001 From: Colin McNulty Date: Mon, 24 Feb 2020 11:26:09 -0500 Subject: [PATCH 084/121] DEV: Fix cppCheck warnings. Addresses SIM-11094 AND SIM-11092. Review 20773 --- SDK/simUtil/DbConfigurationFile.cpp | 2 ++ SDK/simVis/VelocityVector.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/SDK/simUtil/DbConfigurationFile.cpp b/SDK/simUtil/DbConfigurationFile.cpp index 697ca79bf..5712fe4a7 100644 --- a/SDK/simUtil/DbConfigurationFile.cpp +++ b/SDK/simUtil/DbConfigurationFile.cpp @@ -377,6 +377,7 @@ void DbConfigurationFile::parseLayers_(const std::vector& tokens, o imageLayer->setOpacity(opacity); imageLayer->setVisible(active); imageLayer->setEnabled(active); + imageLayer->setName(layerName); map->addLayer(imageLayer); } if (altitudeSet) @@ -393,6 +394,7 @@ void DbConfigurationFile::parseLayers_(const std::vector& tokens, o iStr >> noDataValue; } newLayer->setNoDataValue(noDataValue); + newLayer->setName(layerName); } } } diff --git a/SDK/simVis/VelocityVector.cpp b/SDK/simVis/VelocityVector.cpp index ac9197bee..51093b818 100644 --- a/SDK/simVis/VelocityVector.cpp +++ b/SDK/simVis/VelocityVector.cpp @@ -67,7 +67,7 @@ int VelocityVector::rebuild_(const simData::PlatformPrefs& prefs) createVelocityVector_(prefs, geode.get()); // disable lighting - osg::StateSet* stateSet = geode->getOrCreateStateSet(); + simVis::setLighting(geode->getOrCreateStateSet(), osg::StateAttribute::OFF); setNodeMask(DISPLAY_MASK_PLATFORM); this->addChild(geode.get()); From 1f2640c2e6a8e22ecd40f7f0d6c898f50ed97b03 Mon Sep 17 00:00:00 2001 From: Colin McNulty Date: Mon, 24 Feb 2020 12:56:23 -0500 Subject: [PATCH 085/121] DEV: Fix cppCheck warning in QSNodeID96. Addresses SIM-11093. Review 20775 --- SDK/simVis/DB/QSNodeID96.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/SDK/simVis/DB/QSNodeID96.cpp b/SDK/simVis/DB/QSNodeID96.cpp index 88a8a98c3..05feac53a 100644 --- a/SDK/simVis/DB/QSNodeID96.cpp +++ b/SDK/simVis/DB/QSNodeID96.cpp @@ -132,7 +132,9 @@ QSNodeID96 QSNodeID96::operator>>(int numBitsToShift) const { returnValue.three_ = 0; returnValue.two_ = three_ >> (numBitsToShift-32); - returnValue.one_ = (two_ >> (numBitsToShift-32)) | (three_ << (64 - numBitsToShift)); + // Number of bits to shift the third field by. Separated into a local var to avoid cppCheck false positive + int thirdFieldBits = 64 - numBitsToShift; + returnValue.one_ = (two_ >> (numBitsToShift-32)) | (three_ << thirdFieldBits); } else if (numBitsToShift < 96) { @@ -187,7 +189,9 @@ QSNodeID96 QSNodeID96::operator<<(int numBitsToShift) const { returnValue.one_ = 0; returnValue.two_ = one_ << (numBitsToShift-32); - returnValue.three_ = (two_ << (numBitsToShift-32)) | (one_ >> (64 - numBitsToShift)); + // Number of bits to shift the third field by. Separated into a local var to avoid cppCheck false positive + int thirdFieldBits = 64 - numBitsToShift; + returnValue.three_ = (two_ << (numBitsToShift-32)) | (one_ >> thirdFieldBits); } else if (numBitsToShift < 96) { From 1f1a3b097efc0ed84bddbb4a8c5688e4bd104f19 Mon Sep 17 00:00:00 2001 From: Ferzam Mohammad Date: Mon, 24 Feb 2020 13:14:53 -0500 Subject: [PATCH 086/121] DEV: Second pass on wrapping simCore into a python module using SWIG. More of simCore/Calc is now accessible in python, and re-added simCore_SWIG test to test list. SIM-10526, review: 20772. --- swig/Testing/CMakeLists.txt | 3 +- swig/Testing/TestSimCore.py | 89 ++++++++++++++++++++++++++++++++++--- swig/simCore/simCore.i | 31 +++++++++---- 3 files changed, 106 insertions(+), 17 deletions(-) diff --git a/swig/Testing/CMakeLists.txt b/swig/Testing/CMakeLists.txt index 58bf64bce..a4d2f6393 100644 --- a/swig/Testing/CMakeLists.txt +++ b/swig/Testing/CMakeLists.txt @@ -25,8 +25,7 @@ if(NOT Python3_Interpreter_FOUND) endif() # Add the tests -# Commented out because of build machine test failures. -#add_test(NAME simCore_SWIG_Test COMMAND "${Python3_EXECUTABLE}" "TestSimCore.py" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") +add_test(NAME simCore_SWIG_Test COMMAND "${Python3_EXECUTABLE}" "TestSimCore.py" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") # Windows insists on installing under a CONFIG directory under the runtime output directory if(WIN32) diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index a348e89a5..370273f78 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -33,7 +33,7 @@ ############################# # FileSearch.h assert(simCore.FileSearch.GOG is not None) -# TODO: Test FileSearch::findFile(). This could involve creating a small definition for it (possibly using %inline in the .i file), which is a technique that could help with testing other methods. +# TODO: Test FileSearch::findFile(). This could involve creating a small definition for it (possibly using %inline in the .i file). # assert(simCore.FileSearch.findFile()) ############################# @@ -45,7 +45,7 @@ def sleepWrapper(): print("Sleeping for about a tenth of a second.") assert(timeit.timeit(sleepWrapper, number=1) >= .05) -# TODO: Support timespec_t typedef struct. It is currently missing from the .cxx generated wrapper class, might need to use a typemap? +# TODO: Support timespec_t typedef struct. # timespec = simCore.timesepc_t() # assert(timespec is not None) @@ -86,9 +86,10 @@ def sleepWrapper(): coordSystem = simCore.COORD_SYS_NED assert(coordSystem is not None) assert(simCore.coordinateSystemToString(coordSystem) == "Topo_NED") -rv, coordSystem = simCore.coordinateSystemFromString("Topo_NED") -assert(rv == 0) -assert(coordSystem == simCore.COORD_SYS_NED) +# TODO: Fix below test so that build errors are resolved. +# rv, coordSystem = simCore.coordinateSystemFromString("Topo_NED") +# assert(rv == 0) +# assert(coordSystem == simCore.COORD_SYS_NED) ############################# # Coordinate.h @@ -190,6 +191,82 @@ def sleepWrapper(): # assert(outputEnuVector.x() == inputNedVector.y()) # assert(outputEnuVector.y() == inputNedVector.x()) # assert(outputEnuVector.z() == -inputNedVector.z()) + +############################# +# Gars.h +# TODO: Test static methods to make sure output parameters work as intended. +g = simCore.Gars() +assert(g is not None) +assert(g.GARS_30 is not None) + +############################# +# Geometry.h +v1 = simCore.Vec3(0, 0, 0) +v2 = simCore.Vec3(0, 0, 0) +v3 = simCore.Vec3(0, 0, 0) +p = simCore.Plane(v1, v2, v3) +assert(p is not None) +v4 = simCore.Vec3(0, 0, 0) +assert(p.distance(v4) is not None) +poly = simCore.Polytope() +assert(poly is not None) +assert(poly.contains(v4) is not None) +fence = simCore.GeoFence() +assert(fence is not None) +assert(fence.valid() is not None) +assert(fence.contains(v4) is not None) +assert(fence.contains(coordinateTwo) is not None) + +############################# +# GogToGeoFence.h +# TODO: Successfully test simCore::GogToGeoFence::getFences() using its complex input parameter. +gogFence = simCore.GogToGeoFence() +assert(gogFence is not None) + +############################# +# Interpolation.h +# TODO: Successfully test the overloaded simCore::linearInterpolate() that uses a generic output variable. +assert(simCore.getFactor(10, 10, 10) is not None) +assert(simCore.nearestNeighborInterpolate(10, 10, 10) is not None) +outputVec = simCore.Vec3LinearInterpolate(v1, v2, 3, 4, 5) +assert(outputVec is not None and outputVec.x() is not None) +assert(simCore.linearInterpolateAngle(1, 2, 3, 4, 5) is not None) + +############################# +# MagneticVariance.h +assert(simCore.MAGVAR_TRUE == 1) +wmm = simCore.WorldMagneticModel() +assert(wmm is not None) +rv, varianceRad = wmm.calculateMagneticVariance(v, 1, 2) +assert(rv is not None and varianceRad is not None) + +############################# +# MultiFrameCoordinate.h +mfc = simCore.MultiFrameCoordinate() +assert(mfc is not None) +coord = simCore.Coordinate() +rv = mfc.setCoordinate(coord) +assert(rv is not None) +rv = mfc.setCoordinate(coord, coordConverter) +assert(rv is not None) +retCoord = mfc.llaCoordinate() +assert(retCoord is not None) +assert(retCoord.coordinateSystem() is not None) + +############################# +# NumericalAnalysis.h +# TODO: Test newtonInterp() and invLinearInterp(). +assert(simCore.SEARCH_MAX_ITER is not None) +biSearch = simCore.BisectionSearch() +assert(biSearch is not None) +assert(biSearch.count() is not None) +indicator, x, xlo, xhi = biSearch.searchX(1, 2, 3, 4, simCore.SEARCH_INIT_X) +assert(indicator is not None and x is not None and xlo is not None and xhi is not None) +liSearch = simCore.LinearSearch() +assert(liSearch is not None) +indicator, x = liSearch.searchX(1, 2, 3, 4, 5, simCore.SEARCH_INIT_X) +assert(indicator is not None and x is not None) + # TODO: More testing here -print("Success!"); +print("Success!") diff --git a/swig/simCore/simCore.i b/swig/simCore/simCore.i index c5db2fee9..2287d5ea5 100644 --- a/swig/simCore/simCore.i +++ b/swig/simCore/simCore.i @@ -67,6 +67,26 @@ typedef long int64_t; // TODO: Create a test for v3Scale in Math.h, which requires finding a way to handle the Vec3& output parameter. %include "simCore/Calc/Math.h" %include "simCore/Calc/CoordinateConverter.h" +%include "simCore/Calc/Gars.h" +%include "simCore/Calc/Geometry.h" +%include "simCore/Calc/GogToGeoFence.h" +%include "simCore/Calc/Interpolation.h" + +// simCore::WorldMagneticModel::calculateMagneticVariance() +%apply double& OUTPUT { double& varianceRad }; + +%include "simCore/Calc/MagneticVariance.h" + +// TODO: Resolve warnings generated by output parameters using default arguments in Mgrs.h +// %include "simCore/Calc/Mgrs.h" + +%include "simCore/Calc/MultiFrameCoordinate.h" + +// simCore::BisectionSearch::searchX() +%apply double& INOUT { double& x}; +%apply double& INOUT { double& xlo, double& xhi }; + +%include "simCore/Calc/NumericalAnalysis.h" %template(intSdkMax) simCore::sdkMax; %template(intSdkMin) simCore::sdkMin; @@ -77,20 +97,13 @@ typedef long int64_t; %template(doubleSquare) simCore::square; %template(doubleSign) simCore::sign; +%template(Vec3LinearInterpolate) simCore::linearInterpolate; + // TODO: Add these and test them as you add them // Some of these may have to be added together, since they depend on eachother. /* %include "simCore/Calc/Calculations.h" -%include "simCore/Calc/CoordinateConverter.h" %include "simCore/Calc/DatumConvert.h" -%include "simCore/Calc/Gars.h" -%include "simCore/Calc/Geometry.h" -%include "simCore/Calc/GogToGeoFence.h" -%include "simCore/Calc/Interpolation.h" -%include "simCore/Calc/MagneticVariance.h" -%include "simCore/Calc/Mgrs.h" -%include "simCore/Calc/MultiFrameCoordinate.h" -%include "simCore/Calc/NumericalAnalysis.h" %include "simCore/Calc/Random.h" %include "simCore/Calc/SquareMatrix.h" %include "simCore/Calc/UnitContext.h" From f6294c4be892a8fe39f6bace24acdf116f4406d3 Mon Sep 17 00:00:00 2001 From: Ferzam Mohammad Date: Mon, 24 Feb 2020 13:54:03 -0500 Subject: [PATCH 087/121] Addendum to fix some CDash errors. In-person review by Andrew. --- swig/Testing/TestSimCore.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index 370273f78..6cd4a0d1c 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -195,9 +195,6 @@ def sleepWrapper(): ############################# # Gars.h # TODO: Test static methods to make sure output parameters work as intended. -g = simCore.Gars() -assert(g is not None) -assert(g.GARS_30 is not None) ############################# # Geometry.h From e55fe72db479ba80f9ed4a7e0ecf4ba617713ee5 Mon Sep 17 00:00:00 2001 From: Ferzam Mohammad Date: Mon, 24 Feb 2020 14:19:06 -0500 Subject: [PATCH 088/121] Addendum that disables test to prevent build errors while trying to fix them. --- swig/Testing/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/swig/Testing/CMakeLists.txt b/swig/Testing/CMakeLists.txt index a4d2f6393..059101570 100644 --- a/swig/Testing/CMakeLists.txt +++ b/swig/Testing/CMakeLists.txt @@ -25,7 +25,8 @@ if(NOT Python3_Interpreter_FOUND) endif() # Add the tests -add_test(NAME simCore_SWIG_Test COMMAND "${Python3_EXECUTABLE}" "TestSimCore.py" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") +# Disabled test due to build errors. +# add_test(NAME simCore_SWIG_Test COMMAND "${Python3_EXECUTABLE}" "TestSimCore.py" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") # Windows insists on installing under a CONFIG directory under the runtime output directory if(WIN32) From 196b44f8dc0adc08bd45d56d759e15f3b599a6d6 Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Tue, 25 Feb 2020 06:37:58 -0500 Subject: [PATCH 089/121] Addendum to Review 20768 to pick up a review issue. --- SDK/simUtil/Capabilities.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/simUtil/Capabilities.cpp b/SDK/simUtil/Capabilities.cpp index dd44ddada..05d6b6ed6 100644 --- a/SDK/simUtil/Capabilities.cpp +++ b/SDK/simUtil/Capabilities.cpp @@ -231,7 +231,7 @@ void Capabilities::init_(osg::GraphicsContext& gc) maxTextureCoords = maxTextureUnits; #endif } - else if (glVersion_ >= 1.3f || osg::isGLExtensionSupported(contextId, "GL_ARB_multitexture")) + else if (glVersion_ >= 1.3f || osg::isGLExtensionSupported(contextId, "GL_ARB_multitexture") || osg::isGLExtensionSupported(contextId, "GL_EXT_multitexture")) { // Fall back to multitexturing units for oldest OpenGL glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextureUnits); From 6cd8aaf0306a57adb52f7ea0feae0c5abcb41f1a Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Tue, 25 Feb 2020 09:32:25 -0500 Subject: [PATCH 090/121] DEV: Fixed most SWIG TODOs: * latPimaryIdx spelling fix * Unique parameter name for GARS output parameter * Re-enabled unit test, after Linux testing shows no problems * Removed FileSearch interface, as it has no direct users in simCore * Removed outdated TODO on timespec, as it shouldn't be wrapped * Uncommented working code * Fixed math in vector scaling and unit calculations * Gars fully tested * GogToGeoFence removed * newtonInterp and invLinearInterp now tested Review: 20788 --- SDK/simCore/Calc/Gars.cpp | 10 +++--- SDK/simCore/Calc/Gars.h | 8 ++--- swig/Testing/CMakeLists.txt | 13 ++++---- swig/Testing/TestSimCore.py | 64 ++++++++++++++++++------------------- swig/simCore/simCore.i | 47 ++++++++++++++++++++++++--- 5 files changed, 90 insertions(+), 52 deletions(-) diff --git a/SDK/simCore/Calc/Gars.cpp b/SDK/simCore/Calc/Gars.cpp index f4ea13973..438d771db 100644 --- a/SDK/simCore/Calc/Gars.cpp +++ b/SDK/simCore/Calc/Gars.cpp @@ -43,7 +43,7 @@ namespace { namespace simCore { -bool Gars::isValidGars(const std::string& gars, std::string* err, int* lonBand, int* latPimaryIdx, int* latSecondaryIdx, int* quad15, int* key5) +bool Gars::isValidGars(const std::string& gars, std::string* err, int* lonBand, int* latPrimaryIdx, int* latSecondaryIdx, int* quad15, int* key5) { // Verify length of GARS coordinate if (gars.size() < 5 || gars.size() > 7) @@ -130,8 +130,8 @@ bool Gars::isValidGars(const std::string& gars, std::string* err, int* lonBand, // Assign values only on success if (lonBand) *lonBand = lonBandInt; - if (latPimaryIdx) - *latPimaryIdx = static_cast(latPrimaryIndex); + if (latPrimaryIdx) + *latPrimaryIdx = static_cast(latPrimaryIndex); if (latSecondaryIdx) *latSecondaryIdx = static_cast(latSecondaryIndex); @@ -188,7 +188,7 @@ int Gars::convertGarsToGeodetic(const std::string& gars, double& latRad, double& return 0; } -int Gars::convertGeodeticToGars(double latRad, double lonRad, std::string& gars, Level level, std::string* err) +int Gars::convertGeodeticToGars(double latRad, double lonRad, std::string& garsOut, Level level, std::string* err) { // Conversion algorithm below adapted from osgEarthUtil/GARSGraticule.cpp getGARSLabel() @@ -262,7 +262,7 @@ int Gars::convertGeodeticToGars(double latRad, double lonRad, std::string& gars, } - gars = buf.str(); + garsOut = buf.str(); return 0; } diff --git a/SDK/simCore/Calc/Gars.h b/SDK/simCore/Calc/Gars.h index fca27dd0c..e2d6afd3c 100644 --- a/SDK/simCore/Calc/Gars.h +++ b/SDK/simCore/Calc/Gars.h @@ -48,13 +48,13 @@ class SDKCORE_EXPORT Gars * @param[in ] gars GARS coordinate string to validate * @param[out] err Optional pointer to error string * @param[out] lonBand Optional int pointer set to longitude band of the GARS coordinate on success - * @param[out] latPimaryIdx Optional int pointer set to index [0, 14] of the primary latitudinal band letter + * @param[out] latPrimaryIdx Optional int pointer set to index [0, 14] of the primary latitudinal band letter * @param[out] latSecondaryIdx Optional int pointer set to index [0, 24] of the secondary latitudinal band letter * @param[out] quad15 Optional int pointer set to 15 minute quadrant specified in the GARS coordinate, if available * @param[out] key5 Optional int pointer set to 5 minute key specified in the GARS coordinate, if available * @return true if valid GARS coordinate string, false otherwise */ - static bool isValidGars(const std::string& gars, std::string* err = NULL, int* lonBand = NULL, int* latPimaryIdx = NULL, int* latSecondaryIdx = NULL, int* quad15 = NULL, int* key5 = NULL); + static bool isValidGars(const std::string& gars, std::string* err = NULL, int* lonBand = NULL, int* latPrimaryIdx = NULL, int* latSecondaryIdx = NULL, int* quad15 = NULL, int* key5 = NULL); /** * Converts a GARS coordinate to geodetic coordinates. The resulting latitude/longitude @@ -71,12 +71,12 @@ class SDKCORE_EXPORT Gars * Converts geodetic goordinates to a GARS coordinate. * @param[in ] latRad Latitude to convert in radians * @param[in ] lonRad Longitude to convert in radians - * @param[out] gars Resulting GARS coordinate string + * @param[out] garsOut Resulting GARS coordinate string * @param[in ] level Optional level of detail used when converting * @param[out] err Optional pointer to error string * @return 0 if conversion is successful, non-zero otherwise */ - static int convertGeodeticToGars(double latRad, double lonRad, std::string& gars, Level level = GARS_5, std::string* err = NULL); + static int convertGeodeticToGars(double latRad, double lonRad, std::string& garsOut, Level level = GARS_5, std::string* err = NULL); }; } diff --git a/swig/Testing/CMakeLists.txt b/swig/Testing/CMakeLists.txt index 059101570..d625dfb22 100644 --- a/swig/Testing/CMakeLists.txt +++ b/swig/Testing/CMakeLists.txt @@ -25,8 +25,7 @@ if(NOT Python3_Interpreter_FOUND) endif() # Add the tests -# Disabled test due to build errors. -# add_test(NAME simCore_SWIG_Test COMMAND "${Python3_EXECUTABLE}" "TestSimCore.py" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") +add_test(NAME simCore_SWIG_Test COMMAND "${Python3_EXECUTABLE}" "TestSimCore.py" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") # Windows insists on installing under a CONFIG directory under the runtime output directory if(WIN32) @@ -35,8 +34,8 @@ else() set(PYTHON_PATH "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") endif() -#set_tests_properties( -# simCore_SWIG_Test -# PROPERTIES -# ENVIRONMENT "PYTHONPATH=${PYTHON_PATH}" -#) +set_tests_properties( + simCore_SWIG_Test + PROPERTIES + ENVIRONMENT "PYTHONPATH=${PYTHON_PATH}" +) diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index 6cd4a0d1c..0d13d665e 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -30,24 +30,14 @@ assert(e.line() == 37) e = None -############################# -# FileSearch.h -assert(simCore.FileSearch.GOG is not None) -# TODO: Test FileSearch::findFile(). This could involve creating a small definition for it (possibly using %inline in the .i file). -# assert(simCore.FileSearch.findFile()) - ############################# # Time.h # Wrapper function that sleeps for a second and takes no args, so that it can be passed through python's timeit() function easily. # Sleeping for more than a second, as function occasionally executes in slightly less than a tenth of a second if given 100 ms as a parameter. def sleepWrapper(): simCore.Sleep(100) - print("Sleeping for about a tenth of a second.") assert(timeit.timeit(sleepWrapper, number=1) >= .05) -# TODO: Support timespec_t typedef struct. -# timespec = simCore.timesepc_t() -# assert(timespec is not None) # simCore/Calc @@ -86,10 +76,9 @@ def sleepWrapper(): coordSystem = simCore.COORD_SYS_NED assert(coordSystem is not None) assert(simCore.coordinateSystemToString(coordSystem) == "Topo_NED") -# TODO: Fix below test so that build errors are resolved. -# rv, coordSystem = simCore.coordinateSystemFromString("Topo_NED") -# assert(rv == 0) -# assert(coordSystem == simCore.COORD_SYS_NED) +rv, coordSystem = simCore.coordinateSystemFromString("Topo_NED") +assert(rv == 0) +assert(coordSystem == simCore.COORD_SYS_NED) ############################# # Coordinate.h @@ -133,17 +122,16 @@ def sleepWrapper(): v2 = simCore.Vec3(1, 2, 3) assert(v2 is not None) assert(simCore.v3Distance(v, v2) == math.sqrt(26)) -# TODO: Test v3Scale in Math.h. Will need to make a fix to handle the class output parameter in order for this to function. -# v2 = simCore.v3Scale(2, v) -# assert(v2.x() == 12) -# assert(v2.y() == 4) -# assert(v2.z() == 8) +v2 = simCore.v3Scale(2, v) +assert(v2.x() == 12) +assert(v2.y() == 4) +assert(v2.z() == 8) vecLen = simCore.v3Unit(v2) assert(vecLen is not None) -assert(vecLen == math.sqrt(14)) -assert(v2.x() == 1 * 1/vecLen) -assert(v2.y() == 2 * 1/vecLen) -assert(v2.z() == 3 * 1/vecLen) +assert(vecLen == math.sqrt(224)) +assert(v2.x() == 12 / vecLen) +assert(v2.y() == 4 / vecLen) +assert(v2.z() == 8 / vecLen) mantissa, numZeroes = simCore.toScientific(12345) assert(mantissa is not None) assert(numZeroes is not None) @@ -194,7 +182,15 @@ def sleepWrapper(): ############################# # Gars.h -# TODO: Test static methods to make sure output parameters work as intended. +isValid, err, lonBand, latPrimaryIdx, latSecondaryIdx, quad15, key5 = simCore.Gars.isValidGars("718KR45") +assert(isValid is not None and err is not None and lonBand is not None and latPrimaryIdx is not None and latSecondaryIdx is not None + and quad15 is not None and key5 is not None) +rv, latRad, lonRad, err = simCore.Gars.convertGarsToGeodetic("718KR45") +assert(rv is not None and latRad is not None and lonRad is not None and err is not None) +rv, gars, err = simCore.Gars.convertGeodeticToGars(1.0, 1.1, simCore.Gars.GARS_5) +assert(rv is not None and gars is not None and err is not None) +rv, gars, err = simCore.Gars.convertGeodeticToGars(1.0, 1.1) +assert(rv is not None and gars is not None and err is not None) ############################# # Geometry.h @@ -214,19 +210,13 @@ def sleepWrapper(): assert(fence.contains(v4) is not None) assert(fence.contains(coordinateTwo) is not None) -############################# -# GogToGeoFence.h -# TODO: Successfully test simCore::GogToGeoFence::getFences() using its complex input parameter. -gogFence = simCore.GogToGeoFence() -assert(gogFence is not None) - ############################# # Interpolation.h -# TODO: Successfully test the overloaded simCore::linearInterpolate() that uses a generic output variable. assert(simCore.getFactor(10, 10, 10) is not None) assert(simCore.nearestNeighborInterpolate(10, 10, 10) is not None) outputVec = simCore.Vec3LinearInterpolate(v1, v2, 3, 4, 5) assert(outputVec is not None and outputVec.x() is not None) +assert(simCore.DoubleLinearInterpolate(2.0, 4.0, 10.0, 25.0, 30.0) == 3.5) assert(simCore.linearInterpolateAngle(1, 2, 3, 4, 5) is not None) ############################# @@ -252,7 +242,6 @@ def sleepWrapper(): ############################# # NumericalAnalysis.h -# TODO: Test newtonInterp() and invLinearInterp(). assert(simCore.SEARCH_MAX_ITER is not None) biSearch = simCore.BisectionSearch() assert(biSearch is not None) @@ -263,6 +252,17 @@ def sleepWrapper(): assert(liSearch is not None) indicator, x = liSearch.searchX(1, 2, 3, 4, 5, simCore.SEARCH_INIT_X) assert(indicator is not None and x is not None) +times = simCore.DoubleArray(3) +values = simCore.DoubleArray(3) +for k in range(0, 3): + times[k] = k + values[k] = k + 3 +rv, value = simCore.newtonInterp(1.0, times, values) +assert(rv is not None) +assert(value == 4.0) +rv, value = simCore.invLinearInterp(4.5, times, values, 0.1) +assert(rv is not None) +assert(value == 1.5) # TODO: More testing here diff --git a/swig/simCore/simCore.i b/swig/simCore/simCore.i index 2287d5ea5..43bc82a64 100644 --- a/swig/simCore/simCore.i +++ b/swig/simCore/simCore.i @@ -45,7 +45,6 @@ typedef long int64_t; //////////////////////////////////////////////// // simCore/Common %include "simCore/Common/Exception.h" -%include "simCore/Common/FileSearch.h" %include "simCore/Common/Time.h" //////////////////////////////////////////////// @@ -64,12 +63,45 @@ typedef long int64_t; // Handling output parameter for toScientific() from simCore/calc/Math.cpp %apply int* OUTPUT { int* exp }; -// TODO: Create a test for v3Scale in Math.h, which requires finding a way to handle the Vec3& output parameter. +// v3Scale() needs a custom wrapper for proper return value +%rename("wrap_v3Scale") simCore::v3Scale; %include "simCore/Calc/Math.h" + +%pythoncode %{ +def v3Scale(scalar, inVec): + outVec = Vec3() + wrap_v3Scale(scalar, inVec, outVec) + return outVec +%} + %include "simCore/Calc/CoordinateConverter.h" + +// isValidGars() +%apply std::string* OUTPUT { std::string* err }; +%apply int* OUTPUT { int* lonBand }; +%apply int* OUTPUT { int* latPrimaryIdx }; +%apply int* OUTPUT { int* latSecondaryIdx }; +%apply int* OUTPUT { int* quad15 }; +%apply int* OUTPUT { int* key5 }; +// convertGarsToGeodetic() +%apply double& OUTPUT { double& latRad }; +%apply double& OUTPUT { double& lonRad }; +// convertGeodeticToGars() +%apply std::string* OUTPUT { std::string* garsOut }; +%extend simCore::Gars { + // Fixes ordering of parameters for SWIG + static int convertGeodeticToGars(double latRad, double lonRad, simCore::Gars::Level level, std::string* garsOut, std::string* err) { + return simCore::Gars::convertGeodeticToGars(latRad, lonRad, *garsOut, level, err); + } + static int convertGeodeticToGars(double latRad, double lonRad, std::string* garsOut, std::string* err) { + return simCore::Gars::convertGeodeticToGars(latRad, lonRad, *garsOut, simCore::Gars::GARS_5, err); + } +}; +%ignore simCore::Gars::convertGeodeticToGars; // Ignore the C++ header file version +%warnfilter(509) simCore::Gars; // Ignore the overload warnings since they're treated as output parameters %include "simCore/Calc/Gars.h" + %include "simCore/Calc/Geometry.h" -%include "simCore/Calc/GogToGeoFence.h" %include "simCore/Calc/Interpolation.h" // simCore::WorldMagneticModel::calculateMagneticVariance() @@ -85,7 +117,13 @@ typedef long int64_t; // simCore::BisectionSearch::searchX() %apply double& INOUT { double& x}; %apply double& INOUT { double& xlo, double& xhi }; - +// Required for double[3] in newtonInterp() +%include "carrays.i" +%array_class(double, DoubleArray); +// newtonInterp() +%apply double& OUTPUT { double& funcAtT0 }; +// invLinearInterp() +%apply double& OUTPUT { double& t0 }; %include "simCore/Calc/NumericalAnalysis.h" %template(intSdkMax) simCore::sdkMax; @@ -98,6 +136,7 @@ typedef long int64_t; %template(doubleSign) simCore::sign; %template(Vec3LinearInterpolate) simCore::linearInterpolate; +%template(DoubleLinearInterpolate) simCore::linearInterpolate; // TODO: Add these and test them as you add them // Some of these may have to be added together, since they depend on eachother. From 9cff57d0dc6d7213408f297eefe6ec633f1e6026 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Tue, 25 Feb 2020 10:07:10 -0500 Subject: [PATCH 091/121] SDK BUGFIX: simCore::Mgrs::convertMgrstoUtm() is renamed convertMgrsToUtm() to match SDK style. DEV: CoordinateConverter.convert() is now wrapped for SWIG. Most of Mgrs class is now wrapped. Review: 20790 --- SDK/simCore/Calc/Mgrs.cpp | 4 +- SDK/simCore/Calc/Mgrs.h | 2 +- swig/Testing/TestSimCore.py | 76 ++++++++++++++++++++++++------------- swig/simCore/simCore.i | 25 ++++++++++-- 4 files changed, 74 insertions(+), 33 deletions(-) diff --git a/SDK/simCore/Calc/Mgrs.cpp b/SDK/simCore/Calc/Mgrs.cpp index 2769688c9..936a3be56 100644 --- a/SDK/simCore/Calc/Mgrs.cpp +++ b/SDK/simCore/Calc/Mgrs.cpp @@ -67,7 +67,7 @@ int Mgrs::convertMgrsToGeodetic(const std::string& mgrs, double& lat, double& lo { double utmEasting; double utmNorthing; - if (convertMgrstoUtm(zone, gzdLetters, easting, northing, northPole, utmEasting, utmNorthing, err) != 0) + if (convertMgrsToUtm(zone, gzdLetters, easting, northing, northPole, utmEasting, utmNorthing, err) != 0) return 1; if (convertUtmToGeodetic(zone, northPole, utmEasting, utmNorthing, lat, lon, err) != 0) return 1; @@ -186,7 +186,7 @@ int Mgrs::breakMgrsString(const std::string& mgrs, int& zone, std::string& gzdLe return 0; } -int Mgrs::convertMgrstoUtm(int zone, const std::string& gzdLetters, double mgrsEasting, double mgrsNorthing, +int Mgrs::convertMgrsToUtm(int zone, const std::string& gzdLetters, double mgrsEasting, double mgrsNorthing, bool &northPole, double& utmEasting, double& utmNorthing, std::string* err) { const double ONEHT = 100000.; diff --git a/SDK/simCore/Calc/Mgrs.h b/SDK/simCore/Calc/Mgrs.h index 45f79f6bf..a77358e33 100644 --- a/SDK/simCore/Calc/Mgrs.h +++ b/SDK/simCore/Calc/Mgrs.h @@ -83,7 +83,7 @@ class SDKCORE_EXPORT Mgrs * @param[out] err Optional pointer to error string * @return 0 if conversion is successful, non-zero otherwise */ - static int convertMgrstoUtm(int zone, const std::string& gzdLetters, double mgrsEasting, double mgrsNorthing, + static int convertMgrsToUtm(int zone, const std::string& gzdLetters, double mgrsEasting, double mgrsNorthing, bool& northPole, double& utmEasting, double& utmNorthing, std::string* err = NULL); /** diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index 0d13d665e..983d818d7 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -152,33 +152,36 @@ def sleepWrapper(): assert(refOrigin.z() == 1699) coordConverter.setReferenceOriginDegrees(refOrigin) assert(coordConverter.hasReferenceOrigin()) -llaVector = simCore.Vec3(0, 45, 1000) -assert(llaVector is not None) assert(simCore.Coordinate() is not None) -coordinateObj = simCore.Coordinate(simCore.COORD_SYS_LLA, llaVector) -assert(coordinateObj is not None) -assert(coordinateObj.coordinateSystem() == simCore.COORD_SYS_LLA) -assert(coordinateObj.position() == llaVector) -# TODO: There are several places in CoordinateConverter.cpp that make use of Vec3& or Coordinate& output parameters. Create tests for these methods that allow you to use these more complex output parameters. -# inputEcefVector = simCore.Vec3(0, 0, 0) -# outputLlaVector = coordConverter.convertEcefToGeodeticPos(inputEcefVector) -# inputNedVector = simCore.Vec3(1334.3, -2543.6, 359.65) -# outputEnuVector = coordConverter.swapNedEnu(inputNedVector) -# assert(outputEnuVector.x() == inputNedVector.y()) -# assert(outputEnuVector.y() == inputNedVector.x()) -# assert(outputEnuVector.z() == -inputNedVector.z()) -# outputNwuVector = coordConverter.swapNedNwu(inputNedVector) -# assert(outputNwuVector.x() == inputNedVector.x()) -# assert(outputNwuVector.y() == -inputNedVector.y()) -# assert(outputNwuVector.z() == -inputNedVector.z()) -# outputNwuVector = coordConverter.convertEnuToNwu(outputEnuVector) -# assert(outputNwuVector.x() == inputNedVector.x()) -# assert(outputNwuVector.y() == -inputNedVector.y()) -# assert(outputNwuVector.z() == -inputNedVector.z()) -# outputEnuVector = coordConverter.convertNwuToEnu(outputNwuVector) -# assert(outputEnuVector.x() == inputNedVector.y()) -# assert(outputEnuVector.y() == inputNedVector.x()) -# assert(outputEnuVector.z() == -inputNedVector.z()) +llaCoordinate = simCore.Coordinate(simCore.COORD_SYS_LLA, simCore.Vec3(0, 45, 1000)) +assert(llaCoordinate is not None) +assert(llaCoordinate.coordinateSystem() == simCore.COORD_SYS_LLA) +assert(llaCoordinate.position() is not None) +assert(coordConverter.lonRadius() is not None) +assert(coordConverter.latRadius() is not None) +assert(coordConverter.tangentPlaneOffsetX() is not None) +assert(coordConverter.tangentPlaneOffsetY() is not None) +assert(coordConverter.tangentPlaneRotation() is not None) +assert(coordConverter.setTangentPlaneOffsetX(1.0) is None) +assert(coordConverter.setTangentPlaneOffsetY(1.0) is None) +assert(coordConverter.setTangentPlaneRotation(1.0) is None) +assert(coordConverter.setReferenceOriginDegrees() is None) +assert(coordConverter.setReferenceOriginDegrees(1.0) is None) +assert(coordConverter.setReferenceOriginDegrees(1.0, 2.0) is None) +assert(coordConverter.setReferenceOriginDegrees(1.0, 2.0, 3.0) is None) +assert(coordConverter.setReferenceOriginDegrees(simCore.Vec3(1.0, 2.0, 3.0)) is None) +assert(coordConverter.setReferenceOrigin() is None) +assert(coordConverter.setReferenceOrigin(1.0) is None) +assert(coordConverter.setReferenceOrigin(1.0, 2.0) is None) +assert(coordConverter.setReferenceOrigin(1.0, 2.0, 3.0) is None) +assert(coordConverter.setReferenceOrigin(simCore.Vec3(1.0, 2.0, 3.0)) is None) +assert(coordConverter.setTangentPlaneOffsets(1.0, 2.0, 3.0) is None) +assert(coordConverter.setTangentPlaneOffsets(1.0, 2.0) is None) +rv, outCoord = coordConverter.convert(llaCoordinate, simCore.COORD_SYS_ECEF) +assert(rv is not None and outCoord is not None) +assert(outCoord.coordinateSystem() == simCore.COORD_SYS_ECEF) +# Note, static conversion methods are called by CoordinateConverter.convert() internally. They +# are not explicitly tested in this script. ############################# # Gars.h @@ -227,6 +230,27 @@ def sleepWrapper(): rv, varianceRad = wmm.calculateMagneticVariance(v, 1, 2) assert(rv is not None and varianceRad is not None) +############################# +# Mgrs.h +mgrs = simCore.Mgrs() +rv, lat, lon, err = mgrs.convertMgrsToGeodetic("33CWM1974418352") +assert(rv is not None and lat is not None and lon is not None and err is not None) +rv, zone, gzdLetters, easting, northing, err = mgrs.breakMgrsString("33CWM1974418352") +assert(rv is not None and zone is not None and gzdLetters is not None and easting is not None + and northing is not None and err is not None) +# TODO: Boolean references are failing +#rv, northPole, utmEasting, utmNorthing, err = mgrs.convertMgrsToUtm(33, "CWM", 19744.0, 18352.0) +#assert(rv is not None and northPole is not None and utmEasting is not None +# and utmNorthing is not None and err is not None) +rv, lat, lon, err = mgrs.convertUtmToGeodetic(33, False, 19744.0, 18352.0) +assert(rv is not None and lat is not None and lon is not None and err is not None) +# TODO: Boolean references are failing +#rv, northPole, upsEasting, upsNorthing, err = mgrs.convertMgrsToUps("33CWM1974418352", 19744.0, 18352.0) +#assert(rv is not None and northPole is not None and upsEasting is not None +# and upsNorthing is not None and err is not None) +rv, lat, lon, err = mgrs.convertUpsToGeodetic(False, 19744.0, 18352.0) +assert(rv is not None and lat is not None and lon is not None and err is not None) + ############################# # MultiFrameCoordinate.h mfc = simCore.MultiFrameCoordinate() diff --git a/swig/simCore/simCore.i b/swig/simCore/simCore.i index 43bc82a64..98eed2be2 100644 --- a/swig/simCore/simCore.i +++ b/swig/simCore/simCore.i @@ -56,8 +56,6 @@ typedef long int64_t; %apply int& OUTPUT { simCore::CoordinateSystem& outSystem }; %include "simCore/Calc/CoordinateSystem.h" - -// TODO: Implement typemap that allows simCore::Coordinate objects to be used as output parameters. %include "simCore/Calc/Coordinate.h" // Handling output parameter for toScientific() from simCore/calc/Math.cpp @@ -74,7 +72,15 @@ def v3Scale(scalar, inVec): return outVec %} +%rename("wrap_convert") simCore::CoordinateConverter::convert; %include "simCore/Calc/CoordinateConverter.h" +%pythoncode %{ +def CoordConvert_convert(self, inCoord, outSystem): + outCoord = Coordinate() + rv = self.wrap_convert(inCoord, outCoord, outSystem) + return rv, outCoord +CoordinateConverter.convert = CoordConvert_convert +%} // isValidGars() %apply std::string* OUTPUT { std::string* err }; @@ -109,8 +115,19 @@ def v3Scale(scalar, inVec): %include "simCore/Calc/MagneticVariance.h" -// TODO: Resolve warnings generated by output parameters using default arguments in Mgrs.h -// %include "simCore/Calc/Mgrs.h" +%warnfilter(509) simCore::Mgrs; // Ignore the overload warnings since they're treated as output parameters +// convertMgrsToGeodetic() +%apply double& OUTPUT { double& lat }; +%apply double& OUTPUT { double& lon }; +// breakMgrsString() +%apply int& OUTPUT { int& zone }; +%apply std::string& OUTPUT { std::string& gzdLetters }; +%apply double& OUTPUT { double& easting }; +%apply double& OUTPUT { double& northing }; +// TODO: These two methods do not wrap cleanly due to boolean reference +%ignore simCore::Mgrs::convertMgrsToUtm; +%ignore simCore::Mgrs::convertMgrsToUps; +%include "simCore/Calc/Mgrs.h" %include "simCore/Calc/MultiFrameCoordinate.h" From 2bf98c382c8a7f288b1779f1b89fc4fcfe1bb740 Mon Sep 17 00:00:00 2001 From: SIMDIS Build Machine Date: Tue, 25 Feb 2020 10:48:37 -0500 Subject: [PATCH 092/121] DEV: Fixed build machine error where wrong .pyd and .py file were found when a make install was not done. --- swig/Testing/TestSimCore.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index 983d818d7..5ab6dea75 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -4,7 +4,7 @@ if 'SIMDIS_DIR' in os.environ: # For _module shared object: if os.name == "nt": - sys.path.insert(0, os.environ['SIMDIS_DIR'] + '/lib/amd64-nt/python3.8') + sys.path.append(os.environ['SIMDIS_DIR'] + '/lib/amd64-nt/python3.8') try: # Python 3.8 does not want to respect PATH for loading dependent DLLs. It introduces # a new method to attempt to fix the problem. Try/except ignores errors in older Python. @@ -14,9 +14,9 @@ pass pass else: - sys.path.insert(0, os.environ['SIMDIS_DIR'] + '/lib/amd64-linux/python3.8/lib-dynload') + sys.path.append(os.environ['SIMDIS_DIR'] + '/lib/amd64-linux/python3.8/lib-dynload') # For module wrapper: - sys.path.insert(0, os.environ['SIMDIS_DIR'] + '/bin/pythonScripts') + sys.path.append(os.environ['SIMDIS_DIR'] + '/bin/pythonScripts') import simCore From 1ee7ab6b511468f4b6ce1bde491fabd71072680f Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Tue, 25 Feb 2020 11:00:00 -0500 Subject: [PATCH 093/121] SIM-11095 Fixed cppCheck Warning on SphericalVolumn.cpp Release: N/A. Notes: I reviewed the history of the file and determined that the variable is left over from a previous approach. Test Environment: Windows 10, Visual Studio 2017, Debug Test: Compile Review: 20794 --- SDK/simVis/SphericalVolume.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/SDK/simVis/SphericalVolume.cpp b/SDK/simVis/SphericalVolume.cpp index f824f96f7..21069bf74 100644 --- a/SDK/simVis/SphericalVolume.cpp +++ b/SDK/simVis/SphericalVolume.cpp @@ -959,7 +959,6 @@ void SVFactory::createCone_(osg::Geode* geode, const SVData& d, const osg::Vec3& { // next, build the cone wall. we need out-facing normals. // yes this can be computed while we are building the faces but that is an optimization for later. - const int wallOffset = vptr; // ensure that cone is aligned to cap, since cap is drawn normally, but cone is drawn in alternating strips from bottom. bool evenSlice = ((numSlices % 2) == 0); From d3e5725548fd677e87386ed469766c749777607d Mon Sep 17 00:00:00 2001 From: Martin Kinsey Date: Wed, 26 Feb 2020 07:24:47 -0500 Subject: [PATCH 094/121] SDK NEW FEATURE: simCore::CsvReader is generic CSV reader class that is intended to mirror Python's csv module. DEV: Part of SIM-11103, Review: 20803. --- SDK/simCore.h | 1 + SDK/simCore/CMakeLists.txt | 2 + SDK/simCore/String/CsvReader.cpp | 92 ++++++++++++++++++++++++++++++++ SDK/simCore/String/CsvReader.h | 81 ++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+) create mode 100644 SDK/simCore/String/CsvReader.cpp create mode 100644 SDK/simCore/String/CsvReader.h diff --git a/SDK/simCore.h b/SDK/simCore.h index ad3ea0418..ad4e7d338 100644 --- a/SDK/simCore.h +++ b/SDK/simCore.h @@ -62,6 +62,7 @@ #include "simCore/LUT/LUT2.h" #include "simCore/String/Angle.h" #include "simCore/String/Constants.h" +#include "simCore/String/CsvReader.h" #include "simCore/String/FilePatterns.h" #include "simCore/String/Format.h" #include "simCore/String/TextFormatter.h" diff --git a/SDK/simCore/CMakeLists.txt b/SDK/simCore/CMakeLists.txt index 74974457c..c986afca8 100644 --- a/SDK/simCore/CMakeLists.txt +++ b/SDK/simCore/CMakeLists.txt @@ -108,6 +108,7 @@ set(CORE_STRING_SRC String/) set(CORE_STRING_HEADERS ${CORE_STRING_INC}Angle.h ${CORE_STRING_INC}Constants.h + ${CORE_STRING_INC}CsvReader.h ${CORE_STRING_INC}FilePatterns.h ${CORE_STRING_INC}Tokenizer.h ${CORE_STRING_INC}Format.h @@ -119,6 +120,7 @@ set(CORE_STRING_HEADERS ) set(CORE_STRING_SOURCES ${CORE_STRING_SRC}Angle.cpp + ${CORE_STRING_SRC}CsvReader.cpp ${CORE_STRING_SRC}Format.cpp ${CORE_STRING_SRC}Tokenizer.cpp ${CORE_STRING_SRC}TextFormatter.cpp diff --git a/SDK/simCore/String/CsvReader.cpp b/SDK/simCore/String/CsvReader.cpp new file mode 100644 index 000000000..bbb247f15 --- /dev/null +++ b/SDK/simCore/String/CsvReader.cpp @@ -0,0 +1,92 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ +#include "simCore/String/Format.h" +#include "simCore/String/Tokenizer.h" +#include "simCore/String/Utils.h" +#include "simCore/String/CsvReader.h" + +namespace simCore +{ + +CsvReader::CsvReader() + : commentChar_('#') +{ +} + +CsvReader::~CsvReader() +{ + close(); +} + +void CsvReader::setCommentChar(char commentChar) +{ + commentChar_ = commentChar; +} + +int CsvReader::open(const std::string& filename) +{ + if (file_.is_open()) + return 1; + file_.open(filename); + return file_.is_open() ? 0 : 1; +} + +void CsvReader::close() +{ + if (file_.is_open()) + file_.close(); +} + +int CsvReader::readLine(std::vector& tokens) +{ + tokens.clear(); + std::string line; + while (simCore::getStrippedLine(file_, line)) + { + // Ignore empty lines and comments + if (line.empty() || line[0] == commentChar_) + continue; + + simCore::stringTokenizer(tokens, line, ",", true, false); + return 0; + } + return 1; +} + +int CsvReader::readLineTrimmed(std::vector& tokens) +{ + const int rv = readLine(tokens); + if (rv != 0) + return rv; + + // Remove leading and trailing whitespace from all tokens + for (size_t i = 0; i < tokens.size(); ++i) + { + const std::string tok = tokens[i]; + if (tok.empty()) + continue; + tokens[i] = simCore::StringUtils::trim(tok); + } + return 0; +} + +} diff --git a/SDK/simCore/String/CsvReader.h b/SDK/simCore/String/CsvReader.h new file mode 100644 index 000000000..2d70a341c --- /dev/null +++ b/SDK/simCore/String/CsvReader.h @@ -0,0 +1,81 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ +#ifndef SIMCORE_CSV_READER_H +#define SIMCORE_CSV_READER_H + +#include +#include +#include "simCore/Common/Common.h" + +namespace simCore +{ + +/** + * Simple CSV Reader class. Open a file using open() then read each line as + * needed using readLine(). This class is intended to mirror Python's csv + * reader in that it allows forward-iteration through a csv file and gives + * a vector of tokens for each line as it's read. If functionality similar + * to Python's csv DictReader is desired, a new class will be needed. + */ +class SDKCORE_EXPORT CsvReader +{ +public: + CsvReader(); + virtual ~CsvReader(); + + /** Set the char that denotes a comment line. Defaults to '#'. */ + void setCommentChar(char commentChar); + + /** + * Open the given filename for reading as CSV. + * @param[in] filename Name of the file to open + * @return 0 on success, non-zero otherwise + */ + int open(const std::string& filename); + /** Close the open file, if any. Called on destruction of this class. */ + void close(); + + /** + * Read the next line of the file into the given vector. Will always clear + * the given vector. Will skip empty lines and lines that start with the + * configured comment char. Note that comment detection is rudimentary. + * Inline comments or indented comments will not be detected. + * @param[out] tokens Vector filled with tokens from the next line + * @return 0 on successful line read, 1 when the end of the file is reached + */ + int readLine(std::vector& tokens); + /** + * Reads the next line of the file into the given vector. This method reads + * identically to readLine(), but trims leading and trailing whitespace from + * each token before returning. + * @param[out] tokens Vector filled with tokens from the next line + * @return 0 on successful line read, 1 when the end of the file is reached + */ + int readLineTrimmed(std::vector& tokens); + +private: + std::ifstream file_; + char commentChar_; +}; + +} +#endif /* SIMCORE_CSV_READER_H */ From 3079e9144b583e93eb85cd53b54f97bdc00602fc Mon Sep 17 00:00:00 2001 From: Ferzam Mohammad Date: Wed, 26 Feb 2020 08:12:55 -0500 Subject: [PATCH 095/121] DEV: Third pass on wrapping simCore into a python module using SWIG. Additional support/testing for simCore/Calc added. SIM-10526, review: 20798. --- SDK/simCore/Calc/Calculations.h | 20 +++++----- swig/Testing/TestSimCore.py | 68 +++++++++++++++++++++++++++++++++ swig/simCore/simCore.i | 19 +++++++-- 3 files changed, 93 insertions(+), 14 deletions(-) diff --git a/SDK/simCore/Calc/Calculations.h b/SDK/simCore/Calc/Calculations.h index 8be976899..517262aae 100644 --- a/SDK/simCore/Calc/Calculations.h +++ b/SDK/simCore/Calc/Calculations.h @@ -538,22 +538,22 @@ namespace simCore /** * Calculates the angle of attack, side slip, and total angle of attack from a ENU * geodetic velocity vector and a set of geodetic Euler angles (yaw, pitch, roll) - * @param enuVel East, North, and Up geodetic velocity vector for the vehicle - * @param ypr Yaw, pitch, roll based geodetic Euler angles in radians - * @param useRoll Boolean, true: aerodynamic version, false: rocketry version (Air Ballistic Axis) that does not use roll - * @param aoa Vertical angle of attack for vehicle in radians; measure of difference between velocity and pointing direction - * @param ss Side slip angle for vehicle in radians; measure of difference between velocity and pointing direction - * @param totalAoA Total angle of attack for vehicle in radians + * @param[in ] enuVel East, North, and Up geodetic velocity vector for the vehicle + * @param[in ] ypr Yaw, pitch, roll based geodetic Euler angles in radians + * @param[in ] useRoll Boolean, true: aerodynamic version, false: rocketry version (Air Ballistic Axis) that does not use roll + * @param[out] aoa Vertical angle of attack for vehicle in radians; measure of difference between velocity and pointing direction + * @param[out] ss Side slip angle for vehicle in radians; measure of difference between velocity and pointing direction + * @param[out] totalAoA Total angle of attack for vehicle in radians */ SDKCORE_EXPORT void calculateAoaSideslipTotalAoa(const Vec3& enuVel, const Vec3& ypr, const bool useRoll, double* aoa, double* ss, double* totalAoA); /** * Returns the distance between a line segment and a point. The calculations are done in COORD_SYS_XEAST so the results are only approximate. * The code is taken from SIMDIS 9 code SimVisBeam::GetClosestPoint and generalized for WGS-84. - * @param startLla Start point of the line segment in (rad, rad, m) in WGS-84 - * @param endLla End point of the line segment in (rad, rad, m) in WGS-84 - * @param toLla The point for the distance calculation in (rad, rad, m) in WGS-84 - * @param closestLla The point on the line segment closest to the toLla point + * @param[in ] startLla Start point of the line segment in (rad, rad, m) in WGS-84 + * @param[in ] endLla End point of the line segment in (rad, rad, m) in WGS-84 + * @param[in ] toLla The point for the distance calculation in (rad, rad, m) in WGS-84 + * @param[out] closestLla The point on the line segment closest to the toLla point * @return The distance, in meters, between a line segment and the toLla point. */ SDKCORE_EXPORT double getClosestPoint(const simCore::Vec3& startLla, const simCore::Vec3& endLla, const simCore::Vec3& toLla, simCore::Vec3& closestLla); diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index 5ab6dea75..4e3017aae 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -288,6 +288,74 @@ def sleepWrapper(): assert(rv is not None) assert(value == 1.5) +############################# +# Calculations.h +# TODO: Following fail, fix output +# assert(simCore.tangentPlane2Sphere(v1, v2) is not None) +# assert(simCore.geodeticToSpherical(0, 0, 0) is not None) +# success, fromPos, toPos = simCore.convertLocations(simCore.Coordinate(), simCore.Coordinate(), simCore.WGS_84, coordConverter) +# assert(success is not None and fromPos is not None and toPos is not None) +# assert(simCore.calculateBodyUnitX(1, 1) is not None) +# assert(simCore.calculateBodyUnitY(1, 1, 1) is not None) +# assert(simCore.calculateBodyUnitZ(1, 1, 1) is not None) +# assert(simCore.calculateVelFromGeodeticPos(v1, v2, 1) is not None) +# success, velOut, oriOut = simCore.calculateVelOriFromPos(v1, v2, 1, simCore.WGS_84, v3) +# assert(success is not None and velOut is not None and oriOut is not None) +# assert(simCore.calculateGeodeticOriFromRelOri(v1, v2) is not None) +# assert(simCore.calculateGeodeticOffsetPos(v1, v2, v3) is not None) +# assert(simCore.calculateGeodeticEndPoint(v1, 1, 1, 1) is not None) +# midPoint, wrapsDateline = simCore.calculateGeodeticMidPoint(v1, v2, False) +# assert(midPoint is not None and wrapsDateline is not None) +# assert(simCore.calculateFlightPathAngles(v1) is not None) +# assert(simCore.calculateVelocity(1, 1, 1) is not None) +# aoa, ss, totalAoa = simCore.calculateAoaSideslipTotalAoa(v1, v2, True) +# assert(aoa is not None and ss is not None and totalAoa is not None) +# distance, closestLla = simCore.getClosestPoint(v1, v2, v3) +# assert(distance is not None and closestLla is not None) +azim, elev, cmp = simCore.calculateRelAzEl(v1, v2, v3, simCore.WGS_84, coordConverter) +assert(azim is not None and elev is not None and cmp is not None) +azim, elev, cmp = simCore.calculateAbsAzEl(v1, v2, simCore.WGS_84, coordConverter) +assert(azim is not None and elev is not None and cmp is not None) +assert(simCore.calculateSlant(v1, v2, simCore.WGS_84, coordConverter) is not None) +nst, dr, xr = simCore.calculateGeodesicDRCR(v1, 1, v2) +assert(nst is not None and dr is not None and xr is not None) +v5 = simCore.Vec3(1, 1, 1) +assert(simCore.calculateRangeRate(v, v1, v2, v3, simCore.WGS_84, coordConverter, v4, v5) is not None) +azim, elev, cmp = simCore.calculateRelAng(v1, v2) +assert(azim is not None and elev is not None and cmp is not None) +azim, elev, cmp = simCore.calculateRelAngToTrueAzEl(1, 2, v1) +assert(azim is not None and elev is not None and cmp is not None) +assert(simCore.positionInGate(v1, v2, 1, 2, 3, 4, 5, 6, simCore.WGS_84, coordConverter) is not None) +assert(simCore.laserInGate(v1, v2, 1, 2, 3, 4, 5, 6, 7, 8, 9, simCore.WGS_84, coordConverter) is not None) + +############################# +# Random.h +nv = simCore.NormalVariable() +assert(nv is not None) +assert(nv() is not None) +assert(nv.setMean(1) is None and nv.setStdDev(2) is None) +assert(nv.mean() == 1 and nv.stdDev() == 2) +gVar = simCore.GaussianVariable() +assert(gVar is not None) +assert(gVar.stdDev() == 1) +pv = simCore.PoissonVariable() +assert(pv is not None) +assert(pv.seeds() is not None) +assert(pv.setSeeds(1) is None) + +############################# +# SquareMatrix.h +sm = simCore.SquareMatrix() +# TODO: Implement. +# assert(sm.row(0) is not None) +assert(sm is not None) +assert(sm.makeIdentity() is not None) +assert(sm.transpose() is not None) +assert(sm.set(0, 0, 0) is not None) +assert(sm.get(0, 0) == 0) +assert(sm.data() is not None) +assert(sm.add(simCore.SquareMatrix()) is not None) + # TODO: More testing here print("Success!") diff --git a/swig/simCore/simCore.i b/swig/simCore/simCore.i index 98eed2be2..204582333 100644 --- a/swig/simCore/simCore.i +++ b/swig/simCore/simCore.i @@ -39,6 +39,7 @@ typedef long int64_t; %ignore simCore::Vec3::operator[]; %ignore simCore::Coordinate::operator=; %ignore simCore::CoordinateConverter::operator=; +%ignore simCore::SquareMatrix::operator=; // Note, order of inclusion matters @@ -112,7 +113,6 @@ CoordinateConverter.convert = CoordConvert_convert // simCore::WorldMagneticModel::calculateMagneticVariance() %apply double& OUTPUT { double& varianceRad }; - %include "simCore/Calc/MagneticVariance.h" %warnfilter(509) simCore::Mgrs; // Ignore the overload warnings since they're treated as output parameters @@ -143,6 +143,20 @@ CoordinateConverter.convert = CoordConvert_convert %apply double& OUTPUT { double& t0 }; %include "simCore/Calc/NumericalAnalysis.h" +// simCore::calculateRelAzEl() +%apply double* OUTPUT { double* azim, double* elev, double* cmp }; +// simCore::calculateGeodesicDRCR() +%apply double* OUTPUT { double* downRng, double* crossRng }; +// simCore::calculateRelAng() and simCore::calculateRelAngToTrueAzEl() +%apply double* OUTPUT { double* azim, double* elev, double* cmp }; +// TODO: calculateYawPitchFromBodyUnitX() +// TODO: sodanoDirect() +// TODO: sodanoInverse() +%include "simCore/Calc/Calculations.h" + +%include "simCore/Calc/Random.h" +%include "simCore/Calc/SquareMatrix.h" + %template(intSdkMax) simCore::sdkMax; %template(intSdkMin) simCore::sdkMin; %template(intSquare) simCore::square; @@ -158,10 +172,7 @@ CoordinateConverter.convert = CoordConvert_convert // TODO: Add these and test them as you add them // Some of these may have to be added together, since they depend on eachother. /* -%include "simCore/Calc/Calculations.h" %include "simCore/Calc/DatumConvert.h" -%include "simCore/Calc/Random.h" -%include "simCore/Calc/SquareMatrix.h" %include "simCore/Calc/UnitContext.h" %include "simCore/Calc/Units.h" %include "simCore/Calc/VerticalDatum.h" From 219b02c6f5e834278301f8342ff89d1127b96c71 Mon Sep 17 00:00:00 2001 From: Martin Kinsey Date: Wed, 26 Feb 2020 08:32:59 -0500 Subject: [PATCH 096/121] DEV: CsvReader now takes in an istream. Added unit test for CsvReader. Review: 20805. --- SDK/simCore/String/CsvReader.cpp | 22 +--- SDK/simCore/String/CsvReader.h | 25 ++-- Testing/SimCore/CMakeLists.txt | 2 + Testing/SimCore/CsvReaderTest.cpp | 182 ++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+), 35 deletions(-) create mode 100644 Testing/SimCore/CsvReaderTest.cpp diff --git a/SDK/simCore/String/CsvReader.cpp b/SDK/simCore/String/CsvReader.cpp index bbb247f15..573edaca1 100644 --- a/SDK/simCore/String/CsvReader.cpp +++ b/SDK/simCore/String/CsvReader.cpp @@ -27,14 +27,14 @@ namespace simCore { -CsvReader::CsvReader() - : commentChar_('#') +CsvReader::CsvReader(std::istream& stream) + : stream_(stream), + commentChar_('#') { } CsvReader::~CsvReader() { - close(); } void CsvReader::setCommentChar(char commentChar) @@ -42,25 +42,11 @@ void CsvReader::setCommentChar(char commentChar) commentChar_ = commentChar; } -int CsvReader::open(const std::string& filename) -{ - if (file_.is_open()) - return 1; - file_.open(filename); - return file_.is_open() ? 0 : 1; -} - -void CsvReader::close() -{ - if (file_.is_open()) - file_.close(); -} - int CsvReader::readLine(std::vector& tokens) { tokens.clear(); std::string line; - while (simCore::getStrippedLine(file_, line)) + while (simCore::getStrippedLine(stream_, line)) { // Ignore empty lines and comments if (line.empty() || line[0] == commentChar_) diff --git a/SDK/simCore/String/CsvReader.h b/SDK/simCore/String/CsvReader.h index 2d70a341c..c83424399 100644 --- a/SDK/simCore/String/CsvReader.h +++ b/SDK/simCore/String/CsvReader.h @@ -22,7 +22,7 @@ #ifndef SIMCORE_CSV_READER_H #define SIMCORE_CSV_READER_H -#include +#include #include #include "simCore/Common/Common.h" @@ -30,32 +30,23 @@ namespace simCore { /** - * Simple CSV Reader class. Open a file using open() then read each line as - * needed using readLine(). This class is intended to mirror Python's csv - * reader in that it allows forward-iteration through a csv file and gives + * Simple CSV Reader class. Pass in an istream on construction and read each + * line as needed using readLine(). This class is intended to mirror Python's + * csv reader in that it allows forward-iteration through a csv file and gives * a vector of tokens for each line as it's read. If functionality similar * to Python's csv DictReader is desired, a new class will be needed. */ class SDKCORE_EXPORT CsvReader { public: - CsvReader(); + explicit CsvReader(std::istream& stream); virtual ~CsvReader(); /** Set the char that denotes a comment line. Defaults to '#'. */ void setCommentChar(char commentChar); /** - * Open the given filename for reading as CSV. - * @param[in] filename Name of the file to open - * @return 0 on success, non-zero otherwise - */ - int open(const std::string& filename); - /** Close the open file, if any. Called on destruction of this class. */ - void close(); - - /** - * Read the next line of the file into the given vector. Will always clear + * Read the next line of the stream into the given vector. Will always clear * the given vector. Will skip empty lines and lines that start with the * configured comment char. Note that comment detection is rudimentary. * Inline comments or indented comments will not be detected. @@ -64,7 +55,7 @@ class SDKCORE_EXPORT CsvReader */ int readLine(std::vector& tokens); /** - * Reads the next line of the file into the given vector. This method reads + * Reads the next line of the stream into the given vector. This method reads * identically to readLine(), but trims leading and trailing whitespace from * each token before returning. * @param[out] tokens Vector filled with tokens from the next line @@ -73,7 +64,7 @@ class SDKCORE_EXPORT CsvReader int readLineTrimmed(std::vector& tokens); private: - std::ifstream file_; + std::istream& stream_; char commentChar_; }; diff --git a/Testing/SimCore/CMakeLists.txt b/Testing/SimCore/CMakeLists.txt index 6dc10f5f6..d7fb78841 100644 --- a/Testing/SimCore/CMakeLists.txt +++ b/Testing/SimCore/CMakeLists.txt @@ -34,6 +34,7 @@ create_test_sourcelist(SimCoreTestFiles SimCoreTests.cpp GogToGeoFenceTest.cpp CalculateLibTest.cpp MagneticVarianceTest.cpp + CsvReaderTest.cpp ) add_executable(SimCoreTests ${SimCoreTestFiles}) @@ -73,6 +74,7 @@ add_test(NAME CoreUnitsFormatter COMMAND SimCoreTests UnitsFormatter) add_test(NAME GogToGeoFenceTest COMMAND SimCoreTests GogToGeoFenceTest) add_test(NAME CalculateLibTest COMMAND SimCoreTests CalculateLibTest ${SimCore_UnitTests_SOURCE_DIR}/CalculateInput.txt) add_test(NAME MagneticVarianceTest COMMAND SimCoreTests MagneticVarianceTest) +add_test(NAME CsvReaderTest COMMAND SimCoreTests CsvReaderTest) # Try to locate the correct file for the RCS test... set(FILE_LOCATIONS diff --git a/Testing/SimCore/CsvReaderTest.cpp b/Testing/SimCore/CsvReaderTest.cpp new file mode 100644 index 000000000..f2bea9ae5 --- /dev/null +++ b/Testing/SimCore/CsvReaderTest.cpp @@ -0,0 +1,182 @@ +/* -*- mode: c++ -*- */ +/**************************************************************************** + ***** ***** + ***** Classification: UNCLASSIFIED ***** + ***** Classified By: ***** + ***** Declassify On: ***** + ***** ***** + **************************************************************************** + * + * + * Developed by: Naval Research Laboratory, Tactical Electronic Warfare Div. + * EW Modeling & Simulation, Code 5773 + * 4555 Overlook Ave. + * Washington, D.C. 20375-5339 + * + * License for source code at https://simdis.nrl.navy.mil/License.aspx + * + * The U.S. Government retains all rights to use, duplicate, distribute, + * disclose, or release this software. + * + */ +#include +#include "simCore/Common/SDKAssert.h" +#include "simCore/String/CsvReader.h" + +namespace { + +int testCsvReadLine() +{ + int rv = 0; + + std::istringstream stream("one,two,three\nfour,five,six"); + + simCore::CsvReader reader(stream); + std::vector tokens; + + // Test basic stream + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 3); + rv += SDK_ASSERT(tokens[0] == "one"); + rv += SDK_ASSERT(tokens[1] == "two"); + rv += SDK_ASSERT(tokens[2] == "three"); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 3); + rv += SDK_ASSERT(tokens[0] == "four"); + rv += SDK_ASSERT(tokens[1] == "five"); + rv += SDK_ASSERT(tokens[2] == "six"); + rv += SDK_ASSERT(reader.readLine(tokens) == 1); + + // Test rows of differing lengths + stream.clear(); + stream.str("one,two\nthree,four,five\nsix,seven"); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 2); + rv += SDK_ASSERT(tokens[0] == "one"); + rv += SDK_ASSERT(tokens[1] == "two"); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 3); + rv += SDK_ASSERT(tokens[0] == "three"); + rv += SDK_ASSERT(tokens[1] == "four"); + rv += SDK_ASSERT(tokens[2] == "five"); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 2); + rv += SDK_ASSERT(tokens[0] == "six"); + rv += SDK_ASSERT(tokens[1] == "seven"); + rv += SDK_ASSERT(reader.readLine(tokens) == 1); + + // Test stream with empty lines + stream.clear(); + stream.str("one,two\n \nthree,four,five\n \nsix,seven"); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 2); + rv += SDK_ASSERT(tokens[0] == "one"); + rv += SDK_ASSERT(tokens[1] == "two"); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 3); + rv += SDK_ASSERT(tokens[0] == "three"); + rv += SDK_ASSERT(tokens[1] == "four"); + rv += SDK_ASSERT(tokens[2] == "five"); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 2); + rv += SDK_ASSERT(tokens[0] == "six"); + rv += SDK_ASSERT(tokens[1] == "seven"); + rv += SDK_ASSERT(reader.readLine(tokens) == 1); + + // Test basic stream with odd whitespace thrown in + stream.clear(); + stream.str("one , two,thr ee\n four , five,six"); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 3); + rv += SDK_ASSERT(tokens[0] == "one "); + rv += SDK_ASSERT(tokens[1] == " two"); + rv += SDK_ASSERT(tokens[2] == "thr ee"); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 3); + rv += SDK_ASSERT(tokens[0] == " four "); + rv += SDK_ASSERT(tokens[1] == " five"); + rv += SDK_ASSERT(tokens[2] == "six"); + rv += SDK_ASSERT(reader.readLine(tokens) == 1); + + return rv; +} + +int testCsvReadLineTrimmed() +{ + int rv = 0; + + // Same leading and trailing whitespace test cases from testCsvReadLine(), but using readLineTrimmed + std::istringstream stream("one , two,thr ee\n four , five,six"); + + simCore::CsvReader reader(stream); + std::vector tokens; + + // Test basic stream + rv += SDK_ASSERT(reader.readLineTrimmed(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 3); + rv += SDK_ASSERT(tokens[0] == "one"); + rv += SDK_ASSERT(tokens[1] == "two"); + rv += SDK_ASSERT(tokens[2] == "thr ee"); + rv += SDK_ASSERT(reader.readLineTrimmed(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 3); + rv += SDK_ASSERT(tokens[0] == "four"); + rv += SDK_ASSERT(tokens[1] == "five"); + rv += SDK_ASSERT(tokens[2] == "six"); + rv += SDK_ASSERT(reader.readLineTrimmed(tokens) == 1); + + return 0; +} + +int testCsvWithComments() +{ + int rv = 0; + + std::istringstream stream("#column 1, column 2, column 3\none,two,three\nfour,five,six"); + + simCore::CsvReader reader(stream); + std::vector tokens; + + // Test comments + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 3); + rv += SDK_ASSERT(tokens[0] == "one"); + rv += SDK_ASSERT(tokens[1] == "two"); + rv += SDK_ASSERT(tokens[2] == "three"); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 3); + rv += SDK_ASSERT(tokens[0] == "four"); + rv += SDK_ASSERT(tokens[1] == "five"); + rv += SDK_ASSERT(tokens[2] == "six"); + rv += SDK_ASSERT(reader.readLine(tokens) == 1); + + // Test changing the comment char + reader.setCommentChar('$'); + stream.clear(); + stream.str("$column 1, column 2, column 3\none,two,three\nfour,five,six"); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 3); + rv += SDK_ASSERT(tokens[0] == "one"); + rv += SDK_ASSERT(tokens[1] == "two"); + rv += SDK_ASSERT(tokens[2] == "three"); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(tokens.size() == 3); + rv += SDK_ASSERT(tokens[0] == "four"); + rv += SDK_ASSERT(tokens[1] == "five"); + rv += SDK_ASSERT(tokens[2] == "six"); + rv += SDK_ASSERT(reader.readLine(tokens) == 1); + + return rv; +} + +} + +int CsvReaderTest(int argc, char *argv[]) +{ + int rv = 0; + + rv += SDK_ASSERT(testCsvReadLine() == 0); + rv += SDK_ASSERT(testCsvReadLineTrimmed() == 0); + rv += SDK_ASSERT(testCsvWithComments() == 0); + + return rv; +} From b59de9af96374ab818ff325bac4d5e1654cc0924 Mon Sep 17 00:00:00 2001 From: Martin Kinsey Date: Wed, 26 Feb 2020 10:24:09 -0500 Subject: [PATCH 097/121] DEV: CsvReader can now provide the line number of the line most recently read. Review: 20811. --- SDK/simCore/String/CsvReader.cpp | 9 ++++++++- SDK/simCore/String/CsvReader.h | 9 +++++++++ Testing/SimCore/CsvReaderTest.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/SDK/simCore/String/CsvReader.cpp b/SDK/simCore/String/CsvReader.cpp index 573edaca1..f249d5d2c 100644 --- a/SDK/simCore/String/CsvReader.cpp +++ b/SDK/simCore/String/CsvReader.cpp @@ -29,7 +29,8 @@ namespace simCore CsvReader::CsvReader(std::istream& stream) : stream_(stream), - commentChar_('#') + commentChar_('#'), + lineNumber_(0) { } @@ -37,6 +38,11 @@ CsvReader::~CsvReader() { } +size_t CsvReader::lineNumber() const +{ + return lineNumber_; +} + void CsvReader::setCommentChar(char commentChar) { commentChar_ = commentChar; @@ -48,6 +54,7 @@ int CsvReader::readLine(std::vector& tokens) std::string line; while (simCore::getStrippedLine(stream_, line)) { + lineNumber_++; // Ignore empty lines and comments if (line.empty() || line[0] == commentChar_) continue; diff --git a/SDK/simCore/String/CsvReader.h b/SDK/simCore/String/CsvReader.h index c83424399..16bddcb0d 100644 --- a/SDK/simCore/String/CsvReader.h +++ b/SDK/simCore/String/CsvReader.h @@ -42,6 +42,14 @@ class SDKCORE_EXPORT CsvReader explicit CsvReader(std::istream& stream); virtual ~CsvReader(); + /** + * Get the line number of the most recently read line. Line number is incremented + * during line reading and never reset, so if the std::istream& supplied during class + * construction is modified externally to this class, this line number might not be correct. + * @return line number of most recently read line + */ + size_t lineNumber() const; + /** Set the char that denotes a comment line. Defaults to '#'. */ void setCommentChar(char commentChar); @@ -66,6 +74,7 @@ class SDKCORE_EXPORT CsvReader private: std::istream& stream_; char commentChar_; + size_t lineNumber_; }; } diff --git a/Testing/SimCore/CsvReaderTest.cpp b/Testing/SimCore/CsvReaderTest.cpp index f2bea9ae5..64f1970fc 100644 --- a/Testing/SimCore/CsvReaderTest.cpp +++ b/Testing/SimCore/CsvReaderTest.cpp @@ -168,6 +168,30 @@ int testCsvWithComments() return rv; } + +int testCsvLineNumber() +{ + int rv = 0; + + std::istringstream stream("#col 1, col 2, col3\none,two\n \n \nthree,four,five\nsix,seven"); + + simCore::CsvReader reader(stream); + std::vector tokens; + + rv += SDK_ASSERT(reader.lineNumber() == 0); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + // Skips comment line + rv += SDK_ASSERT(reader.lineNumber() == 2); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + // Skips empty lines + rv += SDK_ASSERT(reader.lineNumber() == 5); + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(reader.lineNumber() == 6); + rv += SDK_ASSERT(reader.readLine(tokens) == 1); + + return rv; +} + } int CsvReaderTest(int argc, char *argv[]) @@ -177,6 +201,7 @@ int CsvReaderTest(int argc, char *argv[]) rv += SDK_ASSERT(testCsvReadLine() == 0); rv += SDK_ASSERT(testCsvReadLineTrimmed() == 0); rv += SDK_ASSERT(testCsvWithComments() == 0); + rv += SDK_ASSERT(testCsvLineNumber() == 0); return rv; } From c67ca1cbb00d3cf955993661fd99a0d2f77994f0 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Wed, 26 Feb 2020 11:28:02 -0500 Subject: [PATCH 098/121] DEV: Now builds against the latest push of osgEarth. CMake detects presence of old method and sets a private CMake flag, code checks the flag and behaves appropriately. Fixes SIM-11152. Review: 20573 --- SDK/simVis/CMakeLists.txt | 6 ++++++ SDK/simVis/LayerRefreshCallback.cpp | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/SDK/simVis/CMakeLists.txt b/SDK/simVis/CMakeLists.txt index 18bc00cea..6c22e0546 100644 --- a/SDK/simVis/CMakeLists.txt +++ b/SDK/simVis/CMakeLists.txt @@ -356,6 +356,9 @@ set(SDK_OSGEARTH_VERSION_MAJOR 1) set(SDK_OSGEARTH_VERSION_MINOR 12) set(SDK_OSGEARTH_VERSION_PATCH 0) +include(CheckOSGEarthMethodExists) +check_osgearth_method_exists(HAVE_INVALIDATE_LAYER_REGION osgEarth/TerrainEngineNode invalidateLayerRegion) + configure_file(${VIS_INC}osgEarthVersion.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/simVis/osgEarthVersion.h @ONLY) # Note that shaders do not go into simVis.h and header/cpp don't get installed @@ -442,6 +445,9 @@ if(SIM_HAVE_DB_SUPPORT) target_compile_definitions(simVis PRIVATE SIM_LITTLE_ENDIAN) endif() endif() +if(HAVE_INVALIDATE_LAYER_REGION) + target_compile_definitions(simVis PRIVATE HAVE_INVALIDATE_LAYER_REGION) +endif() if(INSTALL_SIMDIS_SDK_LIBRARIES) vsi_install_export(simVis ${SIMDIS_SDK_VERSION_STRING} AnyNewerVersion) diff --git a/SDK/simVis/LayerRefreshCallback.cpp b/SDK/simVis/LayerRefreshCallback.cpp index 736d232ed..f34555916 100644 --- a/SDK/simVis/LayerRefreshCallback.cpp +++ b/SDK/simVis/LayerRefreshCallback.cpp @@ -157,8 +157,17 @@ void LayerRefreshCallback::runImpl_() SIM_DEBUG_FP << "simVis::LayerRefreshCallback::run() attempting to refresh layer \"" << layer->getName() << "\".\n"; const auto extents = layer->getDataExtents(); + +#ifdef HAVE_INVALIDATE_LAYER_REGION for (const auto& extent : extents) terrainEngine->invalidateLayerRegion(layer.get(), extent); +#else + // New API as of osgEarth 3.0's 6dde49f410a, 2/21/20, merged/pushed 2/25/20 + std::vector layerVec; + layerVec.push_back(layer.get()); + for (const auto& extent : extents) + terrainEngine->invalidateRegion(layerVec, extent); +#endif // Reset the timer for this layer it->elapsedTime.reset(); From cfe78565192b437bc495d7fcee1762b83fb2f754 Mon Sep 17 00:00:00 2001 From: Ferzam Mohammad Date: Wed, 26 Feb 2020 13:58:58 -0500 Subject: [PATCH 099/121] DEV: Fourth pass on wrapping simCore into a python module using SWIG. Additional support/testing for simCore/Calc added, and began supporting simCore/EM. SIM-10526, review: 20813. --- swig/Testing/TestSimCore.py | 89 +++++++++++++++++++++++++++++++++++++ swig/simCore/simCore.i | 26 +++++++---- 2 files changed, 106 insertions(+), 9 deletions(-) diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index 4e3017aae..07a6f45eb 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -356,6 +356,95 @@ def sleepWrapper(): assert(sm.data() is not None) assert(sm.add(simCore.SquareMatrix()) is not None) +############################# +# Units.h +assert(simCore.Units.UNITLESS is not None) +assert(simCore.Units.MIL is not None) +assert(simCore.Units.DATA_MILES is not None) +assert(simCore.Units.DATA_MILES_PER_HOUR is not None) +assert(simCore.Units.NAUTICAL_MILES_PER_SECOND_SQUARED is not None) +assert(simCore.Units.RANKINE is not None) +assert(simCore.Units.REVOLUTIONS_PER_MINUTE is not None) +assert(simCore.Units.TEASPOON is not None) +assert(simCore.Units.PASCALS is not None) +assert(simCore.Units.VOLUME_FAMILY is not None) +assert(simCore.Units.FEET.name() is not None) +assert(simCore.Units.FEET.abbreviation() is not None) +assert(simCore.Units.FEET.family() is not None) +assert(simCore.Units.FEET.canConvert(simCore.Units.METERS)) +assert(simCore.Units.FEET.convertTo(simCore.Units.METERS, 1) is not None) +assert(simCore.Units.FEET == simCore.Units.FEET) +assert(simCore.Units.FEET != simCore.Units.METERS) +assert(simCore.Units.FEET.isValid()) +assert(simCore.Units.FEET.toBaseScalar() is not None) +assert(simCore.Units.offsetThenScaleUnit("Yard", "yd", 0, 1.0 / 3, simCore.Units.LENGTH_FAMILY).name() == "Yard") +ur = simCore.UnitsRegistry() +assert(ur is not None) +assert(ur.registerDefaultUnits() is None) +assert(ur.registerUnits(simCore.Units.FEET) is not None) +assert(ur.units(simCore.Units.LENGTH_FAMILY) is not None) +# TODO: Fix +# assert(ur.families() is not None) +assert(ur.unitsByName("feet") == simCore.Units.FEET) +assert(ur.unitsByAbbreviation("ft") == simCore.Units.FEET) + +############################# +# VerticalDatum.h +assert(simCore.VERTDATUM_WGS84 is not None) +assert(simCore.VERTDATUM_MSL is not None) +assert(simCore.VERTDATUM_USER is not None) + +# simCore/EM + +############################# +# Constants.h +assert(simCore.LIGHT_SPEED_VACUUM is not None) +assert(simCore.RRE_CONSTANT is not None) +assert(simCore.DEFAULT_ANTENNA_GAIN is not None) +assert(simCore.POLARITY_RIGHTCIRC is not None) +assert(simCore.POLARITY_STRING_UNKNOWN is not None) +assert(simCore.POLARITY_STRING_LEFTCIRC is not None) +assert(simCore.polarityString(simCore.POLARITY_LEFTCIRC) is not None) +assert(simCore.polarityType(simCore.POLARITY_STRING_LEFTCIRC) is not None) +assert(simCore.RCS_XPATCH is not None) +assert(simCore.RCS_SYM_LUT_TYPE is not None) +assert(simCore.RCS_LOG_NORMAL_FUNC is not None) +assert(simCore.ANTENNA_LOBE_BACK is not None) +assert(simCore.ANTENNA_ALGORITHM_SINXX is not None) +assert(simCore.ANTENNA_FORMAT_EZNEC is not None) +assert(simCore.ANTENNA_PATTERN_MONOPULSE is not None) +assert(simCore.ANTENNA_STRING_ALGORITHM_SINXX is not None) +assert(simCore.ANTENNA_STRING_FORMAT_MONOPULSE is not None) +assert(simCore.ANTENNA_STRING_EXTENSION_MONOPULSE is not None) + +############################# +# AntennaPattern.h +assert(simCore.antennaPatternTypeString(simCore.ANTENNA_PATTERN_SINXX) is not None) +assert(simCore.antennaPatternType(simCore.ANTENNA_STRING_ALGORITHM_SINXX) is not None) +assert(simCore.loadPatternFile(simCore.ANTENNA_STRING_ALGORITHM_SINXX, 1) is not None) +assert(simCore.AntennaGainParameters() is not None) +apg = simCore.AntennaPatternGauss() +assert(apg is not None) +# TODO: Test +# assert(apg.type() is not None) +assert(apg.gain(simCore.AntennaGainParameters()) is not None) +small, large = apg.minMaxGain(simCore.AntennaGainParameters()) +assert(small is not None and large is not None) +# TODO: Implement +# result, lastLobe = simCore.calculateGain({}, {}, 1, 2, 3, 4, 5. True) +# assert(result is not None and lastLobe is not None) +apt = simCore.AntennaPatternTable() +assert(apt is not None) +assert(apt.readPat("") is not None) +assert(apt.setValid(False) is None) +assert(apt.setFilename("") is None) +assert(apt.setAzimData(100, 10) is None) +# TODO: Test after installing LUT/InterpTable.h +# success, symmetricAntennaPattern = simCore.readPattern("", "", 1) +# assert(success is not None and symmetricAntennaPattern is not None) +# success, symmetricGainAntPattern = simCore.readPattern("", "", 1) +# assert(success is not None and symmetricAntennaPattern is not None) + # TODO: More testing here print("Success!") diff --git a/swig/simCore/simCore.i b/swig/simCore/simCore.i index 204582333..deaf29454 100644 --- a/swig/simCore/simCore.i +++ b/swig/simCore/simCore.i @@ -157,6 +157,15 @@ CoordinateConverter.convert = CoordConvert_convert %include "simCore/Calc/Random.h" %include "simCore/Calc/SquareMatrix.h" +%include "simCore/Calc/Units.h" +%include "simCore/Calc/VerticalDatum.h" + +// TODO: Implement after installing simCore/Time +/* +%include "simCore/Calc/DatumConvert.h" +%include "simCore/Calc/UnitContext.h" +*/ + %template(intSdkMax) simCore::sdkMax; %template(intSdkMin) simCore::sdkMin; %template(intSquare) simCore::square; @@ -169,18 +178,17 @@ CoordinateConverter.convert = CoordConvert_convert %template(Vec3LinearInterpolate) simCore::linearInterpolate; %template(DoubleLinearInterpolate) simCore::linearInterpolate; -// TODO: Add these and test them as you add them -// Some of these may have to be added together, since they depend on eachother. -/* -%include "simCore/Calc/DatumConvert.h" -%include "simCore/Calc/UnitContext.h" -%include "simCore/Calc/Units.h" -%include "simCore/Calc/VerticalDatum.h" - //////////////////////////////////////////////// // simCore/EM -%include "simCore/EM/AntennaPattern.h" + %include "simCore/EM/Constants.h" + +// AntennaPattern::minMaxGain() +%apply float* OUTPUT { float* min, float* max }; +%include "simCore/EM/AntennaPattern.h" + +// TODO: Add these and test them as you add them +/* %include "simCore/EM/Decibel.h" %include "simCore/EM/ElectroMagRange.h" %include "simCore/EM/Propagation.h" From 712f690c9d62575a9ac7732a045b01bb07fed39f Mon Sep 17 00:00:00 2001 From: Ferzam Mohammad Date: Wed, 26 Feb 2020 16:12:02 -0500 Subject: [PATCH 100/121] Addendum to remove test from build machines. Will address tomorrow, in-person review by Andrew. --- swig/Testing/CMakeLists.txt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/swig/Testing/CMakeLists.txt b/swig/Testing/CMakeLists.txt index d625dfb22..5fdf4ffdb 100644 --- a/swig/Testing/CMakeLists.txt +++ b/swig/Testing/CMakeLists.txt @@ -25,7 +25,8 @@ if(NOT Python3_Interpreter_FOUND) endif() # Add the tests -add_test(NAME simCore_SWIG_Test COMMAND "${Python3_EXECUTABLE}" "TestSimCore.py" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") +# Disabled due to build errors +# add_test(NAME simCore_SWIG_Test COMMAND "${Python3_EXECUTABLE}" "TestSimCore.py" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") # Windows insists on installing under a CONFIG directory under the runtime output directory if(WIN32) @@ -34,8 +35,8 @@ else() set(PYTHON_PATH "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") endif() -set_tests_properties( - simCore_SWIG_Test - PROPERTIES - ENVIRONMENT "PYTHONPATH=${PYTHON_PATH}" -) +# set_tests_properties( +# simCore_SWIG_Test +# PROPERTIES +# ENVIRONMENT "PYTHONPATH=${PYTHON_PATH}" +#) From eeb0f64646c81dcbfa4ce8e742261ba97595653c Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Thu, 27 Feb 2020 09:50:07 -0500 Subject: [PATCH 101/121] SDK BUGFIX: simQt::MapDataModel lost signals imageLayerColorFilterChanged(), imageLayerVisibleRangeChanged(), and imageLayerAltitudeChanged(), based on updates to osgEarth 3.0 API. Fixes compile errors against osgEarth 3.0. Fixes SIM-11155. Review: 20828 --- SDK/simQt/MapDataModel.cpp | 48 ++++++++++++++------------------------ SDK/simQt/MapDataModel.h | 10 ++------ 2 files changed, 20 insertions(+), 38 deletions(-) diff --git a/SDK/simQt/MapDataModel.cpp b/SDK/simQt/MapDataModel.cpp index 058c04314..cdb67322e 100644 --- a/SDK/simQt/MapDataModel.cpp +++ b/SDK/simQt/MapDataModel.cpp @@ -777,7 +777,7 @@ class MapDataModel::MapListener : public osgEarth::MapCallback }; /** Watch for image layer changes */ -class MapDataModel::ImageLayerListener : public osgEarth::ImageLayerCallback +class MapDataModel::ImageLayerListener : public osgEarth::TileLayerCallback { public: /** Constructor */ @@ -801,30 +801,12 @@ class MapDataModel::ImageLayerListener : public osgEarth::ImageLayerCallback emit dataModel_.imageLayerOpacityChanged(imageLayer); } - /** Inherited from VisibleLayerCallback */ - virtual void onVisibleRangeChanged(osgEarth::ImageLayer *layer) - { - emit dataModel_.imageLayerVisibleRangeChanged(layer); - } - - /** Inherited from VisibleLayerCallback */ - virtual void onColorFiltersChanged(osgEarth::ImageLayer *layer) - { - emit dataModel_.imageLayerColorFilterChanged(layer); - } - - /** Inherited from ImageLayerCallback */ - virtual void onAltitudeChanged(class osgEarth::ImageLayer *layer) - { - emit dataModel_.imageLayerAltitudeChanged(layer); - } - private: MapDataModel& dataModel_; }; /** Watch for elevation layer changes */ -class MapDataModel::ElevationLayerListener : public osgEarth::ElevationLayerCallback +class MapDataModel::ElevationLayerListener : public osgEarth::TileLayerCallback { public: /** Constructor */ @@ -967,7 +949,10 @@ void MapDataModel::removeAllCallbacks_(osgEarth::Map* map) for (osgEarth::ImageLayerVector::const_iterator iter = imageLayers.begin(); iter != imageLayers.end(); ++iter) { if (imageCallbacks_.contains(iter->get())) - iter->get()->removeCallback(imageCallbacks_.find(iter->get())->get()); + { + osgEarth::TileLayer* tileLayer = iter->get(); + tileLayer->removeCallback(imageCallbacks_.find(iter->get())->get()); + } } // Assertion failure means that we were out of sync with map; not a one-to-one with callback-to-layer assert(imageCallbacks_.size() == static_cast(imageLayers.size())); @@ -980,7 +965,10 @@ void MapDataModel::removeAllCallbacks_(osgEarth::Map* map) for (osgEarth::ElevationLayerVector::const_iterator iter = elevationLayers.begin(); iter != elevationLayers.end(); ++iter) { if (elevationCallbacks_.contains(iter->get())) - iter->get()->removeCallback(elevationCallbacks_.find(iter->get())->get()); + { + osgEarth::TileLayer* tileLayer = iter->get(); + tileLayer->removeCallback(elevationCallbacks_.find(iter->get())->get()); + } } // Assertion failure means that we were out of sync with map; not a one-to-one with callback-to-layer assert(elevationCallbacks_.size() == static_cast(elevationLayers.size())); @@ -1026,9 +1014,9 @@ void MapDataModel::fillModel_(osgEarth::Map *map) for (osgEarth::ImageLayerVector::const_reverse_iterator iter = imageLayers.rbegin(); iter != imageLayers.rend(); ++iter) { imageGroup_()->insertChild(new ImageLayerItem(imageGroup_(), iter->get()), 0); - osg::ref_ptr cb = new ImageLayerListener(*this); + osg::ref_ptr cb = new ImageLayerListener(*this); imageCallbacks_[iter->get()] = cb.get(); - (*iter)->addCallback(cb.get()); + static_cast(*iter)->addCallback(cb.get()); } osgEarth::ElevationLayerVector elevationLayers; @@ -1037,9 +1025,9 @@ void MapDataModel::fillModel_(osgEarth::Map *map) for (osgEarth::ElevationLayerVector::const_reverse_iterator iter = elevationLayers.rbegin(); iter != elevationLayers.rend(); ++iter) { elevationGroup_()->insertChild(new ElevationLayerItem(elevationGroup_(), iter->get()), 0); - osg::ref_ptr cb = new ElevationLayerListener(*this); + osg::ref_ptr cb = new ElevationLayerListener(*this); elevationCallbacks_[iter->get()] = cb.get(); - (*iter)->addCallback(cb.get()); + static_cast(*iter)->addCallback(cb.get()); } FeatureModelLayerVector featureLayers; @@ -1104,9 +1092,9 @@ void MapDataModel::addImageLayer_(osgEarth::ImageLayer *layer, unsigned int inde imageGroup_()->insertChild(new ImageLayerItem(imageGroup_(), layer), index); endInsertRows(); - osg::ref_ptr cb = new ImageLayerListener(*this); + osg::ref_ptr cb = new ImageLayerListener(*this); imageCallbacks_[layer] = cb.get(); - layer->addCallback(cb.get()); + static_cast(layer)->addCallback(cb.get()); emit imageLayerAdded(layer); } @@ -1118,9 +1106,9 @@ void MapDataModel::addElevationLayer_(osgEarth::ElevationLayer *layer, unsigned elevationGroup_()->insertChild(new ElevationLayerItem(elevationGroup_(), layer), index); endInsertRows(); - osg::ref_ptr cb = new ElevationLayerListener(*this); + osg::ref_ptr cb = new ElevationLayerListener(*this); elevationCallbacks_[layer] = cb.get(); - layer->addCallback(cb.get()); + static_cast(layer)->addCallback(cb.get()); emit elevationLayerAdded(layer); } diff --git a/SDK/simQt/MapDataModel.h b/SDK/simQt/MapDataModel.h index a42f13a69..a9afb6d23 100644 --- a/SDK/simQt/MapDataModel.h +++ b/SDK/simQt/MapDataModel.h @@ -154,12 +154,6 @@ public slots: /** Qt signal as described by the signal name */ void imageLayerOpacityChanged(osgEarth::ImageLayer* layer); /** Qt signal as described by the signal name */ - void imageLayerColorFilterChanged(osgEarth::ImageLayer* layer); - /** Qt signal as described by the signal name */ - void imageLayerVisibleRangeChanged(osgEarth::ImageLayer* layer); - /** Qt signal as described by the signal name */ - void imageLayerAltitudeChanged(osgEarth::ImageLayer* layer); - /** Qt signal as described by the signal name */ void imageLayerAdded(osgEarth::ImageLayer* layer); /** Qt signal as described by the signal name */ void elevationLayerVisibleChanged(osgEarth::ElevationLayer* layer); @@ -256,8 +250,8 @@ public slots: QIcon otherIcon_; /** Maps of terrain layer callbacks */ - QMap > imageCallbacks_; - QMap > elevationCallbacks_; + QMap > imageCallbacks_; + QMap > elevationCallbacks_; QMap > featureCallbacks_; QMap > otherCallbacks_; From 1b124fff23e0964b5d5a4605e93059d65da1cbd9 Mon Sep 17 00:00:00 2001 From: Ferzam Mohammad Date: Fri, 28 Feb 2020 08:42:37 -0500 Subject: [PATCH 102/121] DEV: Fifth pass on wrapping simCore into a python module using SWIG. Removed tests for simCore/EM to resolve build errors, began supporting simCore/LUT, and re-added test to build machines. SIM-10526, review: 20831. --- swig/Testing/CMakeLists.txt | 13 ++++---- swig/Testing/TestSimCore.py | 60 +++++++++++++++++++++++++++++++++++-- swig/simCore/simCore.i | 38 +++++++++++++++++++---- 3 files changed, 97 insertions(+), 14 deletions(-) diff --git a/swig/Testing/CMakeLists.txt b/swig/Testing/CMakeLists.txt index 5fdf4ffdb..d625dfb22 100644 --- a/swig/Testing/CMakeLists.txt +++ b/swig/Testing/CMakeLists.txt @@ -25,8 +25,7 @@ if(NOT Python3_Interpreter_FOUND) endif() # Add the tests -# Disabled due to build errors -# add_test(NAME simCore_SWIG_Test COMMAND "${Python3_EXECUTABLE}" "TestSimCore.py" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") +add_test(NAME simCore_SWIG_Test COMMAND "${Python3_EXECUTABLE}" "TestSimCore.py" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") # Windows insists on installing under a CONFIG directory under the runtime output directory if(WIN32) @@ -35,8 +34,8 @@ else() set(PYTHON_PATH "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") endif() -# set_tests_properties( -# simCore_SWIG_Test -# PROPERTIES -# ENVIRONMENT "PYTHONPATH=${PYTHON_PATH}" -#) +set_tests_properties( + simCore_SWIG_Test + PROPERTIES + ENVIRONMENT "PYTHONPATH=${PYTHON_PATH}" +) diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index 07a6f45eb..1af171582 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -221,6 +221,8 @@ def sleepWrapper(): assert(outputVec is not None and outputVec.x() is not None) assert(simCore.DoubleLinearInterpolate(2.0, 4.0, 10.0, 25.0, 30.0) == 3.5) assert(simCore.linearInterpolateAngle(1, 2, 3, 4, 5) is not None) +assert(simCore.intBilinearInterpolate(1, 2, 3, 4, 5, 6) is not None) +assert(simCore.doubleBilinearInterpolate(1, 2, 3, 4, 5, 6) is not None) ############################# # MagneticVariance.h @@ -394,6 +396,60 @@ def sleepWrapper(): assert(simCore.VERTDATUM_MSL is not None) assert(simCore.VERTDATUM_USER is not None) +# simCore/LUT + +############################# +# LUT1.h +dLut = simCore.doubleLUT1() +assert(dLut is not None) +assert(dLut.initialize(1, 2, 1, 1) is None) +iLut = simCore.intLUT1() +assert(iLut is not None) +assert(iLut.initialize(1, 2, 1, 1) is None) +assert(iLut.minX() is not None) +assert(iLut.numX() == 1) +assert(iLut(0) is not None) +assert(simCore.index(1, 1, 1) is not None) +assert(simCore.intIndex(iLut, 1) is not None) +assert(simCore.doubleIndex(dLut, 1) is not None) +assert(simCore.intLowValue(iLut, 1) is not None) +assert(simCore.doubleLowValue(dLut, 0) is not None) + +############################# +# LUT2.h +dLut2 = simCore.doubleLUT2() +assert(dLut2 is not None) +assert(dLut2.initialize(1, 2, 1, 1, 2, 1, 1) is None) +iLut2 = simCore.intLUT2() +assert(iLut2 is not None) +assert(iLut2.initialize(1, 2, 1, 1, 2, 1, 1) is None) +assert(iLut2.minX() is not None) +assert(iLut2.numX() is not None) +assert(iLut2(0, 0) is not None) + +############################# +# InterpTable.h +e = simCore.InterpTableException("InterpTableException test error message") +assert(e is not None) +assert(e.what() is not None) +e = simCore.intInterpTableLimitException("InterpTableLimitException test error message", 1, 2, 3) +assert(e is not None) +assert(e.what() is not None) +e = simCore.doubleInterpTableLimitException("InterpTableLimitException test error message", 1, 2, 3) +assert(e is not None) +iit = simCore.intInterpTable() +assert(iit is not None) +assert(iit.initialize(1, 2, 1, 1, 2, 1) is None) +assert(iit(0, 0) is not None) +dit = simCore.doubleInterpTable() +assert(dit is not None) +assert(dit.initialize(1, 2, 1, 1, 2, 1) is None) +assert(dit.lut() is not None) + +# TODO: More testing here + +""" +Not implemented due to MSVC 2019 errors. # simCore/EM ############################# @@ -444,7 +500,7 @@ def sleepWrapper(): # assert(success is not None and symmetricAntennaPattern is not None) # success, symmetricGainAntPattern = simCore.readPattern("", "", 1) # assert(success is not None and symmetricAntennaPattern is not None) - -# TODO: More testing here +""" print("Success!") + diff --git a/swig/simCore/simCore.i b/swig/simCore/simCore.i index deaf29454..eddbed790 100644 --- a/swig/simCore/simCore.i +++ b/swig/simCore/simCore.i @@ -177,28 +177,56 @@ CoordinateConverter.convert = CoordConvert_convert %template(Vec3LinearInterpolate) simCore::linearInterpolate; %template(DoubleLinearInterpolate) simCore::linearInterpolate; +%template(intBilinearInterpolate) simCore::bilinearInterpolate; +%template(doubleBilinearInterpolate) simCore::bilinearInterpolate; //////////////////////////////////////////////// // simCore/EM - +// TODO: Implement +/* %include "simCore/EM/Constants.h" // AntennaPattern::minMaxGain() %apply float* OUTPUT { float* min, float* max }; %include "simCore/EM/AntennaPattern.h" -// TODO: Add these and test them as you add them -/* + %include "simCore/EM/Decibel.h" %include "simCore/EM/ElectroMagRange.h" %include "simCore/EM/Propagation.h" %include "simCore/EM/RadarCrossSection.h" - +*/ //////////////////////////////////////////////// // simCore/LUT -%include "simCore/LUT/InterpTable.h" %include "simCore/LUT/LUT1.h" %include "simCore/LUT/LUT2.h" +%include "simCore/LUT/InterpTable.h" + +%template(intLUT1) simCore::LUT::LUT1; +%template(doubleLUT1) simCore::LUT::LUT1; +%template(intIndex) simCore::LUT::index; +%template(doubleIndex) simCore::LUT::index; +%template(intLowValue) simCore::LUT::lowValue; +%template(doubleLowValue) simCore::LUT::lowValue; +// TODO: interpolate() + +%template(intLUT2) simCore::LUT::LUT2; +%template(doubleLUT2) simCore::LUT::LUT2; +// TODO: index() +// TODO: nearValue() +// TODO: interpolate() + +// TODO: BilinearInterpolate class +%template(intInterpTableLimitException) simCore::InterpTableLimitException; +%template(doubleInterpTableLimitException) simCore::InterpTableLimitException; +%template(intInterpTable) simCore::InterpTable; +%template(doubleInterpTable) simCore::InterpTable; +// TODO: NearestLookup() +// TODO: BilinearLookup() +// TODO: BilinearLookupNoException() + +// TODO: Add these and test them as you add them +/* //////////////////////////////////////////////// // simCore/String From 2381fe77ae323ee4072023e492aab84e4ae782bf Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Fri, 28 Feb 2020 11:39:21 -0500 Subject: [PATCH 103/121] SDK BUGFIX: SIMDIS-3363: GOG Annotations using xy and xyz now project using X-East instead of ENU (curved/warped flat earth), matching line projections. SIMDIS BUGFIX: SIMDIS-3363: Annotations in GOG now project to the same location as lines when using relative coordinates. Review: 20851 --- SDK/simVis/GOG/Utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDK/simVis/GOG/Utils.cpp b/SDK/simVis/GOG/Utils.cpp index b443e18a3..3f637f8ab 100644 --- a/SDK/simVis/GOG/Utils.cpp +++ b/SDK/simVis/GOG/Utils.cpp @@ -673,7 +673,7 @@ GeoPoint ParserData::getMapPosition(bool ignoreOffset) const // apply any xyz offset to the map position ref point if there is one simCore::CoordinateConverter cc; cc.setReferenceOrigin(refPointLLA_->y() * simCore::DEG2RAD, refPointLLA_->x() * simCore::DEG2RAD, refPointLLA_->z()); - simCore::Coordinate coord(simCore::COORD_SYS_ENU, simCore::Vec3(xyz.x(), xyz.y(), xyz.z())); + simCore::Coordinate coord(simCore::COORD_SYS_XEAST, simCore::Vec3(xyz.x(), xyz.y(), xyz.z())); simCore::Coordinate outCoord; cc.convert(coord, outCoord, simCore::COORD_SYS_LLA); From 17c8de248f84dcc44afb5dabebb09edf88885306 Mon Sep 17 00:00:00 2001 From: Ferzam Mohammad Date: Fri, 28 Feb 2020 12:19:03 -0500 Subject: [PATCH 104/121] DEV: Sixth pass on wrapping simCore into a python module using SWIG. Added tests for simCore/String. SIM-10526, review: 20850. --- swig/Testing/TestSimCore.py | 35 +++++++++++++++++++++++++++++++++++ swig/simCore/simCore.i | 11 ++++++++--- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index 1af171582..ca26a9ddc 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -446,6 +446,41 @@ def sleepWrapper(): assert(dit.initialize(1, 2, 1, 1, 2, 1) is None) assert(dit.lut() is not None) +# simCore/String + +############################# +# Angle.h +assert(simCore.DEG_SYM_NONE is not None) +assert(simCore.getDegreeSymbol(simCore.DEG_SYM_NONE) is not None) +success, angle = simCore.getAngleFromDegreeString("20", True) +assert(success is not None and angle is not None) +assert(simCore.FMT_BAM is not None) +assert(simCore.getAngleString(1, simCore.FMT_BAM, True, 1, simCore.DEG_SYM_NONE, 0, 0) is not None) +assert(simCore.printLatitude(1, simCore.FMT_BAM, True, 1, simCore.DEG_SYM_NONE) is not None) +assert(simCore.printLongitude(1, simCore.FMT_BAM, True, 1, simCore.DEG_SYM_NONE) is not None) + +############################# +# Constants.h +assert(simCore.STR_WHITE_SPACE_CHARS is not None) +assert(simCore.STR_DEGREE_SYMBOL_ASCII is not None) +assert(simCore.STR_DEGREE_SYMBOL_UNICODE is not None) +assert(simCore.STR_DEGREE_SYMBOL_UTF8 is not None) + +############################# +# FilePatterns.h +assert(simCore.ALL_SIMDIS_FILE_PATTERNS is not None) +assert(simCore.SIMDIS_FILE_PATTERNS is not None) +assert(simCore.ALL_DATA_FILE_PATTERNS is not None) + +############################# +# Format.h +assert(simCore.caseCompare("a", "b") is not None) +assert(simCore.lowerCase("APPLE") == "apple") +assert(simCore.upperCase("apple") == "APPLE") +assert(simCore.stringCaseFind("Apple", "A") == 0) +assert(simCore.getExtension("hi.cpp") == ".cpp") +assert(simCore.hasExtension("hi.cpp", ".cpp")) +assert(simCore.buildString("hi", 1) is not None) # TODO: More testing here """ diff --git a/swig/simCore/simCore.i b/swig/simCore/simCore.i index eddbed790..435cc0a65 100644 --- a/swig/simCore/simCore.i +++ b/swig/simCore/simCore.i @@ -225,15 +225,20 @@ CoordinateConverter.convert = CoordConvert_convert // TODO: BilinearLookup() // TODO: BilinearLookupNoException() -// TODO: Add these and test them as you add them -/* - //////////////////////////////////////////////// // simCore/String +%apply double& OUTPUT { double& ang }; %include "simCore/String/Angle.h" + %include "simCore/String/Constants.h" %include "simCore/String/FilePatterns.h" %include "simCore/String/Format.h" + +// TODO: join() +// TODO: getStrippedLine() + +// TODO: Add these and test them as you add them +/* %include "simCore/String/TextFormatter.h" %include "simCore/String/TextReplacer.h" %include "simCore/String/Tokenizer.h" From 2dc5f5a5d16d1a44e14952de1143421ff2cd3fa8 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Mon, 2 Mar 2020 05:24:01 -0500 Subject: [PATCH 105/121] DEV: Seventh pass on wrapping simCore into a python module using SWIG. Continued to build on tests for simCore/String. SIM-10526, review: 20856. --- swig/Testing/TestSimCore.py | 31 +++++++++++++++++++++++++++++++ swig/simCore/simCore.i | 19 +++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index ca26a9ddc..f303e1d92 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -481,6 +481,37 @@ def sleepWrapper(): assert(simCore.getExtension("hi.cpp") == ".cpp") assert(simCore.hasExtension("hi.cpp", ".cpp")) assert(simCore.buildString("hi", 1) is not None) + +############################# +# Tokenizer.h +word, endWordPos = simCore.extractWord("Lots of words", 5) +assert(word == "of" and endWordPos == 7) +word, endWordPos = simCore.extractWordWithQuotes('Lots "of" words', 5) +assert(word == '"of"' and endWordPos == 9) +assert(simCore.getTerminateForStringPos("", 1) is not None) +assert(simCore.getFirstCharPosAfterString("abc", 0, "b") == 2) +assert(simCore.removeQuotes("'Too many quotes'") == "Too many quotes") +err, tokenName, tokenValue = simCore.getNameAndValueFromToken("key=value") +assert(err is not None and tokenName == "key" and tokenValue == "value") + +############################# +# Utils.h +assert(simCore.StringUtils.before("Testing function", " function") == "Testing") +assert(simCore.StringUtils.before("Testing function", " ") == "Testing") +assert(simCore.StringUtils.after("Testing function", "Testing ") == "function") +assert(simCore.StringUtils.after("Testing function", " ") == "function") +assert(simCore.StringUtils.beforeLast("Testing function", "ti") == "Testing func") +assert(simCore.StringUtils.beforeLast("Testing function", "n") == "Testing functio") +assert(simCore.StringUtils.afterLast("Testing function", "ti") == "on") +assert(simCore.StringUtils.afterLast("Testing function", "t") == "ion") +assert(simCore.StringUtils.substitute("Testing function", "t", "m") is not None) +assert(simCore.StringUtils.addEscapeSlashes('"') == '\\\"') +assert(simCore.StringUtils.removeEscapeSlashes('\\"') == '"') +assert(simCore.StringUtils.trim(' test ') == 'test') +assert(simCore.toNativeSeparators("Users\person\Documents") is not None) +assert(simCore.sanitizeFilename("") == "Documents") +assert(simCore.hasEnv("var") is not None) + # TODO: More testing here """ diff --git a/swig/simCore/simCore.i b/swig/simCore/simCore.i index 435cc0a65..d8074c627 100644 --- a/swig/simCore/simCore.i +++ b/swig/simCore/simCore.i @@ -234,16 +234,31 @@ CoordinateConverter.convert = CoordConvert_convert %include "simCore/String/FilePatterns.h" %include "simCore/String/Format.h" +%apply size_t& OUTPUT { size_t& endWordPos }; +%apply std::string& OUTPUT { std::string& tokenName, std::string& tokenValue }; +%include "simCore/String/Tokenizer.h" + +%include "simCore/String/Utils.h" + +// Format.h // TODO: join() // TODO: getStrippedLine() +// Tokenizer.h +// TODO: stringTokenizer() +// TODO: getTokens() +// TODO: removeQuotes() +// TODO: tokenizeWithQuotes() +// TODO: quoteTokenizer() +// TODO: removeCommentTokens() +// TODO: quoteCommentTokenizer() +// TODO: escapeTokenize() + // TODO: Add these and test them as you add them /* %include "simCore/String/TextFormatter.h" %include "simCore/String/TextReplacer.h" -%include "simCore/String/Tokenizer.h" %include "simCore/String/UnitContextFormatter.h" -%include "simCore/String/Utils.h" %include "simCore/String/ValidNumber.h" %include "simCore/Time/Clock.h" %include "simCore/Time/ClockImpl.h" From 8c0d1c8d1205e73d1ff94cf1d0357e3bc280e7e8 Mon Sep 17 00:00:00 2001 From: Martin Kinsey Date: Mon, 2 Mar 2020 06:25:52 -0500 Subject: [PATCH 106/121] DEV: simCore::CsvReader now allows making skipping empty lines optional. Part of SIM-11106, Review: 20854. --- SDK/simCore/String/CsvReader.cpp | 19 +++++++++++++----- SDK/simCore/String/CsvReader.h | 8 ++++++-- Testing/SimCore/CsvReaderTest.cpp | 32 +++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/SDK/simCore/String/CsvReader.cpp b/SDK/simCore/String/CsvReader.cpp index f249d5d2c..e8051778b 100644 --- a/SDK/simCore/String/CsvReader.cpp +++ b/SDK/simCore/String/CsvReader.cpp @@ -48,15 +48,24 @@ void CsvReader::setCommentChar(char commentChar) commentChar_ = commentChar; } -int CsvReader::readLine(std::vector& tokens) +int CsvReader::readLine(std::vector& tokens, bool skipEmptyLines) { tokens.clear(); std::string line; while (simCore::getStrippedLine(stream_, line)) { lineNumber_++; - // Ignore empty lines and comments - if (line.empty() || line[0] == commentChar_) + + if (line.empty()) + { + if (skipEmptyLines) + continue; + // Not skipping empty lines, return successfully with empty tokens vector + return 0; + } + + // Ignore comments + if (line[0] == commentChar_) continue; simCore::stringTokenizer(tokens, line, ",", true, false); @@ -65,9 +74,9 @@ int CsvReader::readLine(std::vector& tokens) return 1; } -int CsvReader::readLineTrimmed(std::vector& tokens) +int CsvReader::readLineTrimmed(std::vector& tokens, bool skipEmptyLines) { - const int rv = readLine(tokens); + const int rv = readLine(tokens, skipEmptyLines); if (rv != 0) return rv; diff --git a/SDK/simCore/String/CsvReader.h b/SDK/simCore/String/CsvReader.h index 16bddcb0d..9dbeb51d8 100644 --- a/SDK/simCore/String/CsvReader.h +++ b/SDK/simCore/String/CsvReader.h @@ -59,17 +59,21 @@ class SDKCORE_EXPORT CsvReader * configured comment char. Note that comment detection is rudimentary. * Inline comments or indented comments will not be detected. * @param[out] tokens Vector filled with tokens from the next line + * @param[in] skipEmptyLines If true, will skip empty lines when reading. If + * false, will break on empty lines and return 0 with an empty tokens vector. * @return 0 on successful line read, 1 when the end of the file is reached */ - int readLine(std::vector& tokens); + int readLine(std::vector& tokens, bool skipEmptyLines = true); /** * Reads the next line of the stream into the given vector. This method reads * identically to readLine(), but trims leading and trailing whitespace from * each token before returning. * @param[out] tokens Vector filled with tokens from the next line + * @param[in] skipEmptyLines If true, will skip empty lines when reading. If + * false, will break on empty lines and return 0 with an empty tokens vector. * @return 0 on successful line read, 1 when the end of the file is reached */ - int readLineTrimmed(std::vector& tokens); + int readLineTrimmed(std::vector& tokens, bool skipEmptyLines = true); private: std::istream& stream_; diff --git a/Testing/SimCore/CsvReaderTest.cpp b/Testing/SimCore/CsvReaderTest.cpp index 64f1970fc..d995bd3d1 100644 --- a/Testing/SimCore/CsvReaderTest.cpp +++ b/Testing/SimCore/CsvReaderTest.cpp @@ -192,6 +192,37 @@ int testCsvLineNumber() return rv; } +int testReadEmptyLines() +{ + int rv = 0; + + std::istringstream stream(" \n#col 1, col 2, col3\none,two\n \nthree,four,five\n \nsix,seven"); + + simCore::CsvReader reader(stream); + std::vector tokens; + + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(reader.lineNumber() == 3); + rv += SDK_ASSERT(tokens.size() == 2); // [one, two] + + // Read line skipping empty lines, will skip line 4 + rv += SDK_ASSERT(reader.readLine(tokens) == 0); + rv += SDK_ASSERT(reader.lineNumber() == 5); + rv += SDK_ASSERT(tokens.size() == 3); // [three, four, five] + + // Read line without skipping empty lines + rv += SDK_ASSERT(reader.readLine(tokens, false) == 0); + rv += SDK_ASSERT(reader.lineNumber() == 6); + rv += SDK_ASSERT(tokens.empty()); // empty line + + rv += SDK_ASSERT(reader.readLine(tokens, false) == 0); + rv += SDK_ASSERT(reader.lineNumber() == 7); + rv += SDK_ASSERT(tokens.size() == 2); // [six, seven] + rv += SDK_ASSERT(reader.readLine(tokens, false) == 1); + + return rv; +} + } int CsvReaderTest(int argc, char *argv[]) @@ -202,6 +233,7 @@ int CsvReaderTest(int argc, char *argv[]) rv += SDK_ASSERT(testCsvReadLineTrimmed() == 0); rv += SDK_ASSERT(testCsvWithComments() == 0); rv += SDK_ASSERT(testCsvLineNumber() == 0); + rv += SDK_ASSERT(testReadEmptyLines() == 0); return rv; } From b7680424248514f9230c373efbd21d8b80e637d2 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Mon, 2 Mar 2020 09:14:15 -0500 Subject: [PATCH 107/121] DEV: Internally using 3.0 tip everywhere, so invalidateLayerRegion() is gone. Review: 20864 --- SDK/simVis/CMakeLists.txt | 6 ------ SDK/simVis/LayerRefreshCallback.cpp | 7 ------- 2 files changed, 13 deletions(-) diff --git a/SDK/simVis/CMakeLists.txt b/SDK/simVis/CMakeLists.txt index 6c22e0546..18bc00cea 100644 --- a/SDK/simVis/CMakeLists.txt +++ b/SDK/simVis/CMakeLists.txt @@ -356,9 +356,6 @@ set(SDK_OSGEARTH_VERSION_MAJOR 1) set(SDK_OSGEARTH_VERSION_MINOR 12) set(SDK_OSGEARTH_VERSION_PATCH 0) -include(CheckOSGEarthMethodExists) -check_osgearth_method_exists(HAVE_INVALIDATE_LAYER_REGION osgEarth/TerrainEngineNode invalidateLayerRegion) - configure_file(${VIS_INC}osgEarthVersion.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/simVis/osgEarthVersion.h @ONLY) # Note that shaders do not go into simVis.h and header/cpp don't get installed @@ -445,9 +442,6 @@ if(SIM_HAVE_DB_SUPPORT) target_compile_definitions(simVis PRIVATE SIM_LITTLE_ENDIAN) endif() endif() -if(HAVE_INVALIDATE_LAYER_REGION) - target_compile_definitions(simVis PRIVATE HAVE_INVALIDATE_LAYER_REGION) -endif() if(INSTALL_SIMDIS_SDK_LIBRARIES) vsi_install_export(simVis ${SIMDIS_SDK_VERSION_STRING} AnyNewerVersion) diff --git a/SDK/simVis/LayerRefreshCallback.cpp b/SDK/simVis/LayerRefreshCallback.cpp index f34555916..7a670038b 100644 --- a/SDK/simVis/LayerRefreshCallback.cpp +++ b/SDK/simVis/LayerRefreshCallback.cpp @@ -157,17 +157,10 @@ void LayerRefreshCallback::runImpl_() SIM_DEBUG_FP << "simVis::LayerRefreshCallback::run() attempting to refresh layer \"" << layer->getName() << "\".\n"; const auto extents = layer->getDataExtents(); - -#ifdef HAVE_INVALIDATE_LAYER_REGION - for (const auto& extent : extents) - terrainEngine->invalidateLayerRegion(layer.get(), extent); -#else - // New API as of osgEarth 3.0's 6dde49f410a, 2/21/20, merged/pushed 2/25/20 std::vector layerVec; layerVec.push_back(layer.get()); for (const auto& extent : extents) terrainEngine->invalidateRegion(layerVec, extent); -#endif // Reset the timer for this layer it->elapsedTime.reset(); From f00cb373d53f93ce157090ce6c86a317e47c0011 Mon Sep 17 00:00:00 2001 From: Glenn Waldron Date: Tue, 3 Mar 2020 08:43:26 -0500 Subject: [PATCH 108/121] Fixes to support OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION=OFF --- Examples/RadialLOS/ExampleRadialLOS.cpp | 2 +- SDK/simUtil/DbConfigurationFile.cpp | 2 +- SDK/simUtil/LayerFactory.cpp | 2 +- SDK/simUtil/MapScale.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Examples/RadialLOS/ExampleRadialLOS.cpp b/Examples/RadialLOS/ExampleRadialLOS.cpp index f9aa120b9..55d879bf4 100644 --- a/Examples/RadialLOS/ExampleRadialLOS.cpp +++ b/Examples/RadialLOS/ExampleRadialLOS.cpp @@ -253,7 +253,7 @@ namespace */ osg::Node* createP2PGraphics(AppData& app) { - MapNode* mapNode = app.mapNode; + MapNode* mapNode = app.mapNode.get(); osgEarth::SphereDragger* dragger = new osgEarth::SphereDragger(mapNode); dragger->setPosition(GeoPoint(mapNode->getMapSRS(), RLOS_LON, RLOS_LAT)); dragger->setColor(simVis::Color::White); diff --git a/SDK/simUtil/DbConfigurationFile.cpp b/SDK/simUtil/DbConfigurationFile.cpp index 5712fe4a7..0e4ced220 100644 --- a/SDK/simUtil/DbConfigurationFile.cpp +++ b/SDK/simUtil/DbConfigurationFile.cpp @@ -107,7 +107,7 @@ int DbConfigurationFile::load(osg::ref_ptr& mapNode, const st osg::ref_ptr map = simUtil::DbConfigurationFile::loadLegacyConfigFile(adjustedConfigFile, quiet); mapNode = new osgEarth::MapNode(map.get()); - simVis::SceneManager::initializeTerrainOptions(mapNode); + simVis::SceneManager::initializeTerrainOptions(mapNode.get()); SAFETRYEND((std::string("legacy SIMDIS 9 .txt processing of file ") + configFile)); } diff --git a/SDK/simUtil/LayerFactory.cpp b/SDK/simUtil/LayerFactory.cpp index 6d05035cb..0248a5442 100644 --- a/SDK/simUtil/LayerFactory.cpp +++ b/SDK/simUtil/LayerFactory.cpp @@ -218,7 +218,7 @@ ShapeFileLayerFactory::~ShapeFileLayerFactory() osgEarth::FeatureModelLayer* ShapeFileLayerFactory::load(const std::string& url) const { osg::ref_ptr layer = new osgEarth::FeatureModelLayer(); - configureOptions(url, layer); + configureOptions(url, layer.get()); if (layer->getStatus().isError()) { diff --git a/SDK/simUtil/MapScale.cpp b/SDK/simUtil/MapScale.cpp index 4591d523a..9aa07d804 100644 --- a/SDK/simUtil/MapScale.cpp +++ b/SDK/simUtil/MapScale.cpp @@ -137,7 +137,7 @@ MapScale::MapScale() // Create colors bgColorArray_ = new osg::Vec4Array(osg::Array::BIND_OVERALL, 1); bgColorArray_->setDataVariance(osg::Object::DYNAMIC); - backgroundGeom->setColorArray(bgColorArray_); + backgroundGeom->setColorArray(bgColorArray_.get()); // Note that setting the background color to 0.f alpha hides the background setBackgroundColor(osg::Vec4f(0.f, 0.f, 0.f, 0.f)); From a5c94ef27b9347c5a4e5815a8ec8a2a05d27283f Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Tue, 3 Mar 2020 11:13:15 -0500 Subject: [PATCH 109/121] SIM-11163 Removed Invalid Assert in simCore::calculateGeodesicDRCR Release: N/A. Notes: I wrote my new approach and got basically the same answers. The approach by simCore::calculateGeodesicDRCR is correct. The angle between the Down Range line and the Cross Range line is 90 degrees. What is wrong is the assert that the angles of the triangle equals 180 degrees. The sum of the angles of a triangle on a sphere will be larger than 180 degrees. See: https://en.wikipedia.org/wiki/Spherical_geometry for details. Test Environment: Windows 10, Visual Studio 2017, Debug Test: All unit test still pass. Review: 20873 --- SDK/simCore/Calc/Calculations.cpp | 36 +++++++++---------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/SDK/simCore/Calc/Calculations.cpp b/SDK/simCore/Calc/Calculations.cpp index 8f9446293..9c6ad04e5 100644 --- a/SDK/simCore/Calc/Calculations.cpp +++ b/SDK/simCore/Calc/Calculations.cpp @@ -784,23 +784,11 @@ NumericalSearchType calculateGeodesicDRCR(const Vec3 &fromLla, const double &yaw *crossRng = crsrng; } - // algorithm (delaz/err) assumes we can model the shape formed by points refPt, lat2lon2, latlon as a right triangle. - // where refpt->lat2lon2->latlon forms the right angle; the sum of the other two angles should then be 90. - // but in some cases, the assumption of a right triangle is is incorrect: - // when latlon and lat2lon2 are near a pole, sodanoInverse may return angles that cut across the pole and do not fit the assumption. - // we can identify those cases when the sum of the two angles != 90. - - // angle from lat2lon2, refpt, latlon - const double angle1 = (a2 - a1); - - // angle from lat2lon2, latlon, refpt (where azb is the back azimuth from latlon to lat2lon2, corresponding to the calculated azf) - // angle2 = angFixPI(azb - a2); - // if we approximate azb = -(M_PI - azf), then we don't need to calculate azb at all - const double angle2 = (azf - M_PI) - a2; - const double angleSum = angFixPI(angle1 + angle2); - - // for valid calcs, angleSum should approach +/- M_PI_2 as the err approaches 0 - assert((type == SEARCH_FAILED) || simCore::areEqual(angleSum, M_PI_2, 0.04) || simCore::areEqual(angleSum, -M_PI_2, 0.04)); + // Previous versions of this code incorrectly attempted to verify the calculations by summing up the 3 angles + // of the triangle and comparing the results to 180 degrees. This is invalid for a triangle on the surface of + // a sphere. The 3 angles of a triangle on a surface of a sphere is greater then 180 degrees and the larger + // the triangle the more the angles exceed 180 degrees. See: https://en.wikipedia.org/wiki/Spherical_geometry + // for details. // note that SEARCH_FAILED may occur if tolerance is too tight: instead of iterating to max iterations, may be detected as failure if (type == SEARCH_FAILED) @@ -810,15 +798,11 @@ NumericalSearchType calculateGeodesicDRCR(const Vec3 &fromLla, const double &yaw if (maxrng > 1e7) return type; - // only message on failures that do not involve the condition described above - if (simCore::areEqual(angleSum, M_PI_2, 0.04) || simCore::areEqual(angleSum, -M_PI_2, 0.04)) - { - time_t currtime; - time(&currtime); - // notify when error occurred using current local time - SIM_ERROR << "calculateGeodesicDRCR linear search failed to converge to an answer @ " << ctime(&currtime) << std::endl; - // note that 15 decimal places may be necessary to reproduce a failing case - } + time_t currtime; + time(&currtime); + // notify when error occurred using current local time + SIM_ERROR << "calculateGeodesicDRCR linear search failed to converge to an answer @ " << ctime(&currtime) << std::endl; + // note that 15 decimal places may be necessary to reproduce a failing case } else if (type == SEARCH_MAX_ITER) { From 4802edc85cb3159ecde5d00cad53474dd2a12f8c Mon Sep 17 00:00:00 2001 From: Frank Bausch Date: Wed, 4 Mar 2020 16:13:31 -0500 Subject: [PATCH 110/121] SIMDIS 10: Add Vendor/Driver version checking to Capabilities (SIM-11078) Release Note: N/A Notes: anything older than nvidia 340 is declared USABLE_WITH_ARTIFACTS, others specifically tested marked as usable or unusable. Test Environment: Windows 10, VC14, Debug, 64-bit. Test: tested both Capabilities paths. Review: 20793 --- SDK/simUtil/Capabilities.cpp | 70 ++++++++++++++++++++++++++---------- SDK/simUtil/Capabilities.h | 2 ++ 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/SDK/simUtil/Capabilities.cpp b/SDK/simUtil/Capabilities.cpp index 05d6b6ed6..a924957c8 100644 --- a/SDK/simUtil/Capabilities.cpp +++ b/SDK/simUtil/Capabilities.cpp @@ -30,7 +30,6 @@ #include "osgEarth/Registry" #include "osgEarth/Capabilities" #include "osgEarth/StringUtils" -#include "simCore/String/Format.h" #include "simCore/String/Utils.h" #include "simUtil/Capabilities.h" @@ -97,14 +96,6 @@ void Capabilities::init_() glVersion_ = extractGlVersion_(caps.getVersion()); caps_.push_back(std::make_pair("Core Profile", toString_(caps.isCoreProfile()))); - // Based on recommendation from https://www.khronos.org/opengl/wiki/OpenGL_Context#Context_information_queries - // Note that Mesa, Gallium, and Direct3D renderers are all potentially backed by a hardware - // acceleration, and do not necessarily imply software acceleration. - if (caps.getVendor().find("Microsoft") != std::string::npos) - { - recordUsabilityConcern_(USABLE_WITH_ARTIFACTS, "Software renderer detected; possibly no 3D acceleration; performance concerns"); - } - // OpenGL version must be usable. OSG 3.6 with core profile support will not function // without support for VAO, which requires OpenGL 3.0, released in 2008. Although we // require interface blocks from GLSL 3.3, we only absolutely require OpenGL features @@ -114,6 +105,8 @@ void Capabilities::init_() recordUsabilityConcern_(UNUSABLE, osgEarth::Stringify() << "OpenGL version below 3.0 (detected " << glVersion_ << ")"); } + checkVendorOpenGlSupport_(caps.getVendor(), caps.getVersion()); + caps_.push_back(std::make_pair("Max FFP texture units", toString_(caps.getMaxFFPTextureUnits()))); caps_.push_back(std::make_pair("Max GPU texture units", toString_(caps.getMaxGPUTextureUnits()))); caps_.push_back(std::make_pair("Max GPU texture coordinate sets", toString_(caps.getMaxGPUTextureCoordSets()))); @@ -196,14 +189,6 @@ void Capabilities::init_(osg::GraphicsContext& gc) const bool isCoreProfile = (glVersion_ >= 3.2f && ((profileMask & GL_CONTEXT_CORE_PROFILE_BIT) != 0)); caps_.push_back(std::make_pair("Core Profile", toString_(isCoreProfile))); - // Based on recommendation from https://www.khronos.org/opengl/wiki/OpenGL_Context#Context_information_queries - // Note that Mesa, Gallium, and Direct3D renderers are all potentially backed by a hardware - // acceleration, and do not necessarily imply software acceleration. - if (vendorString.find("Microsoft") != std::string::npos) - { - recordUsabilityConcern_(USABLE_WITH_ARTIFACTS, "Software renderer detected; possibly no 3D acceleration; performance concerns"); - } - // OpenGL version must be usable. OSG 3.6 with core profile support will not function // without support for VAO, which requires OpenGL 3.0, released in 2008. Although we // require interface blocks from GLSL 3.3, we only absolutely require OpenGL features @@ -213,6 +198,8 @@ void Capabilities::init_(osg::GraphicsContext& gc) recordUsabilityConcern_(UNUSABLE, osgEarth::Stringify() << "OpenGL version below 3.0 (detected " << glVersion_ << ")"); } + checkVendorOpenGlSupport_(vendorString, glVersionString); + #if OSG_MIN_VERSION_REQUIRED(3,6,0) // OSG 3.6 auto-detects for us GLint maxTextureUnits = ext->glMaxTextureUnits; @@ -322,6 +309,54 @@ double Capabilities::extractGlVersion_(const std::string& glVersionString) const return atof(glVersionString.c_str()); } +void Capabilities::checkVendorOpenGlSupport_(const std::string& vendor, const std::string& glVersionString) +{ + // Based on recommendation from https://www.khronos.org/opengl/wiki/OpenGL_Context#Context_information_queries + // Note that Mesa, Gallium, and Direct3D renderers are all potentially backed by a hardware + // acceleration, and do not necessarily imply software acceleration. + if (vendor.find("Microsoft") != std::string::npos) + { + recordUsabilityConcern_(USABLE_WITH_ARTIFACTS, "Software renderer detected; possibly no 3D acceleration; performance concerns"); + return; + } + + if (vendor.find("NVIDIA") != std::string::npos) + { + // glVersionString is expected to look like: 3.3.0 NVIDIA major.minor + const std::string& nvidiaVersionStr = simCore::StringUtils::after(glVersionString, "NVIDIA"); + const std::string& nvidiaMajorStr = simCore::StringUtils::before(nvidiaVersionStr, "."); + const std::string& nvidiaMinorStr = simCore::StringUtils::after(nvidiaVersionStr, "."); + if (nvidiaVersionStr.empty() || nvidiaMajorStr.empty() || nvidiaMinorStr.empty()) + { + // nvidia driver that does not return version string as part of opengl version + // nothing to do + return; + } + const int nVidiaMajor = atoi(nvidiaMajorStr.c_str()); + const int nVidiaMinor = atoi(nvidiaMinorStr.c_str()); + // testing indicates that 304.125 and most drivers > 340 work + const bool usable = (nVidiaMajor >= 340) || (nVidiaMajor == 304 && nVidiaMinor >= 125); + if (usable) + return; + // testing indicates that: + // nvidia 331 drivers were not usable + // most drivers <= 340 had issues + const bool unusable = (nVidiaMajor == 331); + recordUsabilityConcern_((unusable ? UNUSABLE : USABLE_WITH_ARTIFACTS), osgEarth::Stringify() << "nVidia driver version " << nVidiaMajor << "." << nVidiaMinor); + return; + } + + if (vendor.find("Intel") != std::string::npos) + { + if (glVersionString.find("9.18.10.3186") != std::string::npos) + { + // driver 9.18.10.3186 known to have issues + recordUsabilityConcern_(UNUSABLE, osgEarth::Stringify() << "Intel driver version 9.18.10.3186"); + } + return; + } +} + Capabilities::Usability Capabilities::isUsable() const { return isUsable_; @@ -331,5 +366,4 @@ std::vector Capabilities::usabilityConcerns() const { return usabilityConcerns_; } - } diff --git a/SDK/simUtil/Capabilities.h b/SDK/simUtil/Capabilities.h index fccea5fae..dd746563b 100644 --- a/SDK/simUtil/Capabilities.h +++ b/SDK/simUtil/Capabilities.h @@ -84,6 +84,8 @@ class SDKUTIL_EXPORT Capabilities void recordUsabilityConcern_(Usability severity, const std::string& concern); /** Extracts the OpenGL version from the GL_VERSION string */ double extractGlVersion_(const std::string& glVersionString) const; + /** Checks for usability concerns wrt vendor-specific OpenGL support */ + void checkVendorOpenGlSupport_(const std::string& vendor, const std::string& glVersionString); /** Converts boolean to string */ std::string toString_(bool val) const; From eef564a488f861dc91b6b40c0b6e29d51d819c73 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Fri, 6 Mar 2020 07:00:46 -0500 Subject: [PATCH 111/121] DEV: No longer initializing a MapNode with a NULL Map when loading configuration files fails. Fixes crash with bad input. Fixes SIM-11198. Review: 20919 --- SDK/simUtil/DbConfigurationFile.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/SDK/simUtil/DbConfigurationFile.cpp b/SDK/simUtil/DbConfigurationFile.cpp index 0e4ced220..1dd990518 100644 --- a/SDK/simUtil/DbConfigurationFile.cpp +++ b/SDK/simUtil/DbConfigurationFile.cpp @@ -105,9 +105,11 @@ int DbConfigurationFile::load(osg::ref_ptr& mapNode, const st mapNode = NULL; SAFETRYBEGIN; osg::ref_ptr map = simUtil::DbConfigurationFile::loadLegacyConfigFile(adjustedConfigFile, quiet); - - mapNode = new osgEarth::MapNode(map.get()); - simVis::SceneManager::initializeTerrainOptions(mapNode.get()); + if (map.valid()) + { + mapNode = new osgEarth::MapNode(map.get()); + simVis::SceneManager::initializeTerrainOptions(mapNode.get()); + } SAFETRYEND((std::string("legacy SIMDIS 9 .txt processing of file ") + configFile)); } From bf11656e0e756bba713a3c369578db7eed6a6a35 Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Fri, 6 Mar 2020 09:19:03 -0500 Subject: [PATCH 112/121] SIM-11202 simQt::EntityProxyModel now correctly applies the alwaysShow_ identifier. Release: N/A Notes: The alwaysShow_ uses zero to indicate inactive which is also the ID for the Scenario entry. Test Environment: Windows 10, Visual Studio 2017, Debug Test: Manual testing, The Make Stationary tab now no longer displays the Scenario entry. Review: 20924 --- SDK/simQt/EntityProxyModel.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SDK/simQt/EntityProxyModel.cpp b/SDK/simQt/EntityProxyModel.cpp index 70af7517d..e5671676c 100644 --- a/SDK/simQt/EntityProxyModel.cpp +++ b/SDK/simQt/EntityProxyModel.cpp @@ -145,7 +145,9 @@ namespace simQt { return false; } - if (alwaysShow_ == id) + // Make sure alwaysShow_ is active before comparing; otherwise there is a conflict + // with the Scenario entry which uses an ID of 0. + if ((alwaysShow_ != 0) && (alwaysShow_ == id)) return true; // check against all filters From 7b3b088051443fbf1cc834445601f34594fc616f Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Fri, 6 Mar 2020 09:38:41 -0500 Subject: [PATCH 113/121] DEV: Hemisphere that have depth buffer off and are semitransparent will now turn on the backface culling to avoid show-through of interior walls. Works around SIM-11182. Review: 20920 --- SDK/simVis/GOG/GogNodeInterface.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SDK/simVis/GOG/GogNodeInterface.cpp b/SDK/simVis/GOG/GogNodeInterface.cpp index 8a6db9854..cfa8a6912 100644 --- a/SDK/simVis/GOG/GogNodeInterface.cpp +++ b/SDK/simVis/GOG/GogNodeInterface.cpp @@ -1121,6 +1121,11 @@ void GogNodeInterface::applyBackfaceCulling() // extrudes to a filled polygon instead of a 3D shape). bool isClosed3dShape = (shape() == GOG_SPHERE || shape() == GOG_ELLIPSOID || shape() == GOG_CYLINDER || shape() == GOG_LATLONALTBOX || shape() == GOG_CONE); + + // Semitransparent hemispheres without depth buffer need backface culling on else odd artifacts show through + if (shape() == GOG_HEMISPHERE && fillColor_.a() < 1.0 && !depthBuffer_) + isClosed3dShape = true; + const bool isLine = (shape() == GOG_LINE || shape() == GOG_LINESEGS); if (isClosed3dShape || (extruded_ && !isLine)) style_.getOrCreateSymbol()->backfaceCulling() = true; From fb9f4ffe41913a69e4408ff4d3e62eb48dad3c6a Mon Sep 17 00:00:00 2001 From: Frank Bausch Date: Fri, 6 Mar 2020 10:42:33 -0500 Subject: [PATCH 114/121] simCore: fix windows math defines issues (SIM-11204) Release Note: N/A Notes: probably a second pass to clean up will follow Test Environment: Windows 10, VC14, Debug, 64-bit. Test: full vsi build is clean, dis plugin builds cleanly with/without unity build Review: 20925 --- SDK/simCore/Calc/MathConstants.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SDK/simCore/Calc/MathConstants.h b/SDK/simCore/Calc/MathConstants.h index eb624e971..208b693b3 100644 --- a/SDK/simCore/Calc/MathConstants.h +++ b/SDK/simCore/Calc/MathConstants.h @@ -22,13 +22,15 @@ #ifndef SIMCORE_CALC_MATH_CONSTANTS_H #define SIMCORE_CALC_MATH_CONSTANTS_H -#include +// use and not here to get the Microsoft #defines consistently. +#include #ifdef WIN32 #if !defined(_MATH_DEFINES_DEFINED) -/* Support useful mathematical constants that maybe defined under windows - * if the _USE_MATH_DEFINES macro is defined. +/* Define useful mathematical constants, when they are not defined by Windows. + * Defining _USE_MATH_DEFINES tells Windows to define them; + * Windows defines _MATH_DEFINES_DEFINED to indicate that it has defined them. */ #ifndef M_E @@ -71,7 +73,7 @@ #define M_SQRT1_2 0.707106781186547524401 /* sqrt(1/2) */ #endif -#endif /* _USE_MATH_DEFINES */ +#endif /* _MATH_DEFINES_DEFINED */ #endif /* WIN32 */ From 69c228219a8564cf7f74d9659439f8658407e017 Mon Sep 17 00:00:00 2001 From: Glenn Waldron Date: Fri, 6 Mar 2020 14:48:16 -0500 Subject: [PATCH 115/121] Update the CoordinateClamping API to use the new ElevationEnvelope::Context object for more scalable precise clamping --- SDK/simVis/Entity.cpp | 51 +++++++++++++++++++++++++++++++++++++++++ SDK/simVis/Entity.h | 2 ++ SDK/simVis/Scenario.cpp | 5 +++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/SDK/simVis/Entity.cpp b/SDK/simVis/Entity.cpp index c11cc8099..d95b29d35 100644 --- a/SDK/simVis/Entity.cpp +++ b/SDK/simVis/Entity.cpp @@ -98,6 +98,57 @@ void CoordSurfaceClamping::clampCoordToMapSurface(simCore::Coordinate& coord) coord = llaCoord; } +void CoordSurfaceClamping::clampCoordToMapSurface(simCore::Coordinate& coord, osgEarth::ElevationEnvelope::Context& context) +{ + // nothing to do if we don't have valid ways of accessing elevation + if (!mapNode_.valid()) + { + assert(0); // called this method without setting the map node + return; + } + if (coord.coordinateSystem() != simCore::COORD_SYS_LLA && coord.coordinateSystem() != simCore::COORD_SYS_ECEF) + { + // coordinate type must be LLA to work with osgEarth elevation query + assert(0); + return; + } + + // convert from ECEF to LLA if necessary, since osgEarth Terrain getHeight requires LLA + simCore::Coordinate llaCoord; + if (coord.coordinateSystem() == simCore::COORD_SYS_ECEF) + simCore::CoordinateConverter::convertEcefToGeodetic(coord, llaCoord); + else + llaCoord = coord; + + // If getting the elevation fails, default to 0 to clamp to sea level + double elevation = 0; + + // Both methods for getting terrain elevation have drawbacks that make them undesirable in certain situations. SIM-10423 + // getHeight() can give inaccurate results depending on how much map data is loaded into the scene graph, while ElevationEnvelope can be prohibitively slow if there are many clamped entities + if (useMaxElevPrec_ && envelope_.valid()) + { + double hae = envelope_->getElevation(llaCoord.lon()*simCore::RAD2DEG, llaCoord.lat()*simCore::RAD2DEG, context); + if (hae != NO_DATA_VALUE) + elevation = hae; + } + else + { + double hamsl = 0.0; // not used + double hae = 0.0; // height above ellipsoid, the rough elevation + + if (mapNode_->getTerrain()->getHeight(mapNode_->getMapSRS(), llaCoord.lon()*simCore::RAD2DEG, llaCoord.lat()*simCore::RAD2DEG, &hamsl, &hae)) + elevation = hae; + } + + llaCoord.setPositionLLA(llaCoord.lat(), llaCoord.lon(), elevation); + + // convert back to ECEF if necessary + if (coord.coordinateSystem() == simCore::COORD_SYS_ECEF) + simCore::CoordinateConverter::convertGeodeticToEcef(llaCoord, coord); + else + coord = llaCoord; +} + bool CoordSurfaceClamping::isValid() const { return mapNode_.valid(); diff --git a/SDK/simVis/Entity.h b/SDK/simVis/Entity.h index 1ff6a1ad5..33e83237d 100644 --- a/SDK/simVis/Entity.h +++ b/SDK/simVis/Entity.h @@ -74,6 +74,8 @@ namespace simVis */ void clampCoordToMapSurface(simCore::Coordinate& coord); + void clampCoordToMapSurface(simCore::Coordinate& coord, osgEarth::ElevationEnvelope::Context& context); + /** Return true if able to apply clamping, false otherwise */ bool isValid() const; diff --git a/SDK/simVis/Scenario.cpp b/SDK/simVis/Scenario.cpp index faa37ec42..cd1053eb6 100644 --- a/SDK/simVis/Scenario.cpp +++ b/SDK/simVis/Scenario.cpp @@ -270,7 +270,9 @@ class ScenarioManager::SurfaceClamping : public PlatformTspiFilter if (!prefs.surfaceclamping() || !coordSurfaceClamping_.isValid()) return PlatformTspiFilterManager::POINT_UNCHANGED; - coordSurfaceClamping_.clampCoordToMapSurface(llaCoord); + osgEarth::ElevationEnvelope::Context& context = lut_[props.id()]; + + coordSurfaceClamping_.clampCoordToMapSurface(llaCoord, context); return PlatformTspiFilterManager::POINT_CHANGED; } @@ -288,6 +290,7 @@ class ScenarioManager::SurfaceClamping : public PlatformTspiFilter private: CoordSurfaceClamping coordSurfaceClamping_; + std::unordered_map lut_; }; From 3918a2e8bc41c31b499c04a936e3ffd3c0c8568f Mon Sep 17 00:00:00 2001 From: George Ruhlmann Date: Mon, 9 Mar 2020 09:51:35 -0400 Subject: [PATCH 116/121] SIM-11207 SDK Now Builds if simVis in not Available Release: N/A Notes: I edited the files in my downloaded version of SDK and moved the changes to the standard SDK. Test Environment: Windows 10, Visual Studio 2017, Debug Test: Build in my standard SDK directory and my downloaded version. Review: 20939 --- Plugins/QtDesignerWidgets/CMakeLists.txt | 8 ++++++-- Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp | 4 ++++ SDK/simQt/ResourceInitializer.cpp | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Plugins/QtDesignerWidgets/CMakeLists.txt b/Plugins/QtDesignerWidgets/CMakeLists.txt index 0a615f74d..4ae23a864 100644 --- a/Plugins/QtDesignerWidgets/CMakeLists.txt +++ b/Plugins/QtDesignerWidgets/CMakeLists.txt @@ -15,7 +15,6 @@ set(PROJ_HEADERS DirectorySelectorWidgetPlugin.h DockWidgetPlugin.h EntityFilterLineEditPlugin.h - EntityLineEditPlugin.h EntityTreeCompositePlugin.h EntityTypeFilterWidgetPlugin.h FileSelectorWidgetPlugin.h @@ -37,7 +36,6 @@ set(PROJ_SOURCES DirectorySelectorWidgetPlugin.cpp DockWidgetPlugin.cpp EntityFilterLineEditPlugin.cpp - EntityLineEditPlugin.cpp EntityTreeCompositePlugin.cpp EntityTypeFilterWidgetPlugin.cpp FileSelectorWidgetPlugin.cpp @@ -55,6 +53,11 @@ if(OSG_FOUND) list(APPEND PROJ_SOURCES ColorGradientWidgetPlugin.cpp) endif() +if(TARGET simVis) + list(APPEND PROJ_HEADERS EntityLineEditPlugin.h) + list(APPEND PROJ_SOURCES EntityLineEditPlugin.cpp) +endif() + source_group(Headers FILES ${PROJ_HEADERS}) source_group(Sources FILES ${PROJ_SOURCES}) @@ -89,6 +92,7 @@ add_library(simQtDesignerWidgets SHARED ${PROJ_SOURCES} ${PROJ_HEADERS} target_link_libraries(simQtDesignerWidgets PRIVATE simQt simData) if(TARGET simVis) target_link_libraries(simQtDesignerWidgets PRIVATE simVis) + target_compile_definitions(simQtDesignerWidgets PRIVATE HAVE_SIMVIS) endif() target_include_directories(simQtDesignerWidgets PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_compile_definitions(simQtDesignerWidgets PRIVATE QDESIGNER_EXPORT_WIDGETS) diff --git a/Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp b/Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp index 7fd640c40..1a80e8e3f 100644 --- a/Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp +++ b/Plugins/QtDesignerWidgets/simQtDesignerPlugins.cpp @@ -30,7 +30,9 @@ #include "DataTableComboBoxPlugin.h" #include "DirectorySelectorWidgetPlugin.h" #include "DockWidgetPlugin.h" +#ifdef HAVE_SIMVIS #include "EntityLineEditPlugin.h" +#endif #include "EntityTreeCompositePlugin.h" #include "EntityFilterLineEditPlugin.h" #include "EntityTypeFilterWidgetPlugin.h" @@ -57,7 +59,9 @@ simQtDesignerPlugins::simQtDesignerPlugins(QObject* parent) : QObject(parent) widgetFactories_.append(new DirectorySelectorWidgetPlugin(this)); widgetFactories_.append(new DockWidgetPlugin(this)); widgetFactories_.append(new EntityFilterLineEditPlugin(this)); +#ifdef HAVE_SIMVIS widgetFactories_.append(new EntityLineEditPlugin(this)); +#endif widgetFactories_.append(new EntityTreeCompositePlugin(this)); widgetFactories_.append(new EntityTypeFilterWidgetPlugin(this)); widgetFactories_.append(new FileSelectorWidgetPlugin(this)); diff --git a/SDK/simQt/ResourceInitializer.cpp b/SDK/simQt/ResourceInitializer.cpp index 6aa31cef4..0e546c900 100644 --- a/SDK/simQt/ResourceInitializer.cpp +++ b/SDK/simQt/ResourceInitializer.cpp @@ -24,7 +24,7 @@ #include #include "simQt/ConsoleDataModel.h" #ifdef HAVE_SIMDATA -#include "simQt/EntityLineEdit.h" +#include "simQt/EntityStateFilter.h" #include "simQt/EntityTreeComposite.h" #endif #include "simQt/SettingsModel.h" From 7ec59e69dde1c0f0778f685e6b771e89154c71e6 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Mon, 9 Mar 2020 10:16:13 -0400 Subject: [PATCH 117/121] DEV: Organize the simCore.i file into several sub-files based on the directory they wrap. Part of SIM-10526. Review: 20940 --- swig/simCore/simCore.i | 244 +---------------------------------- swig/simCore/simCoreCalc.i | 137 ++++++++++++++++++++ swig/simCore/simCoreCommon.i | 5 + swig/simCore/simCoreEM.i | 16 +++ swig/simCore/simCoreLUT.i | 29 +++++ swig/simCore/simCoreString.i | 36 ++++++ swig/simCore/simCoreTime.i | 21 +++ 7 files changed, 250 insertions(+), 238 deletions(-) create mode 100644 swig/simCore/simCoreCalc.i create mode 100644 swig/simCore/simCoreCommon.i create mode 100644 swig/simCore/simCoreEM.i create mode 100644 swig/simCore/simCoreLUT.i create mode 100644 swig/simCore/simCoreString.i create mode 100644 swig/simCore/simCoreTime.i diff --git a/swig/simCore/simCore.i b/swig/simCore/simCore.i index d8074c627..299a119c6 100644 --- a/swig/simCore/simCore.i +++ b/swig/simCore/simCore.i @@ -6,7 +6,6 @@ #include "simCore.h" %} - #ifdef _WIN32 %include "windows.i" #endif @@ -32,243 +31,12 @@ typedef unsigned long uint64_t; typedef long int64_t; #endif - #define SDKCORE_EXPORT -%ignore simCore::Vec3::operator=; -%ignore simCore::Vec3::operator[]; -%ignore simCore::Coordinate::operator=; -%ignore simCore::CoordinateConverter::operator=; -%ignore simCore::SquareMatrix::operator=; - -// Note, order of inclusion matters - -//////////////////////////////////////////////// -// simCore/Common -%include "simCore/Common/Exception.h" -%include "simCore/Common/Time.h" - -//////////////////////////////////////////////// -// simCore/Calc -%include "simCore/Calc/Vec3.h" -%include "simCore/Calc/Angle.h" - -// simCore::coordinateSystemFromString() -%apply int& OUTPUT { simCore::CoordinateSystem& outSystem }; - -%include "simCore/Calc/CoordinateSystem.h" -%include "simCore/Calc/Coordinate.h" - -// Handling output parameter for toScientific() from simCore/calc/Math.cpp -%apply int* OUTPUT { int* exp }; - -// v3Scale() needs a custom wrapper for proper return value -%rename("wrap_v3Scale") simCore::v3Scale; -%include "simCore/Calc/Math.h" - -%pythoncode %{ -def v3Scale(scalar, inVec): - outVec = Vec3() - wrap_v3Scale(scalar, inVec, outVec) - return outVec -%} - -%rename("wrap_convert") simCore::CoordinateConverter::convert; -%include "simCore/Calc/CoordinateConverter.h" -%pythoncode %{ -def CoordConvert_convert(self, inCoord, outSystem): - outCoord = Coordinate() - rv = self.wrap_convert(inCoord, outCoord, outSystem) - return rv, outCoord -CoordinateConverter.convert = CoordConvert_convert -%} - -// isValidGars() -%apply std::string* OUTPUT { std::string* err }; -%apply int* OUTPUT { int* lonBand }; -%apply int* OUTPUT { int* latPrimaryIdx }; -%apply int* OUTPUT { int* latSecondaryIdx }; -%apply int* OUTPUT { int* quad15 }; -%apply int* OUTPUT { int* key5 }; -// convertGarsToGeodetic() -%apply double& OUTPUT { double& latRad }; -%apply double& OUTPUT { double& lonRad }; -// convertGeodeticToGars() -%apply std::string* OUTPUT { std::string* garsOut }; -%extend simCore::Gars { - // Fixes ordering of parameters for SWIG - static int convertGeodeticToGars(double latRad, double lonRad, simCore::Gars::Level level, std::string* garsOut, std::string* err) { - return simCore::Gars::convertGeodeticToGars(latRad, lonRad, *garsOut, level, err); - } - static int convertGeodeticToGars(double latRad, double lonRad, std::string* garsOut, std::string* err) { - return simCore::Gars::convertGeodeticToGars(latRad, lonRad, *garsOut, simCore::Gars::GARS_5, err); - } -}; -%ignore simCore::Gars::convertGeodeticToGars; // Ignore the C++ header file version -%warnfilter(509) simCore::Gars; // Ignore the overload warnings since they're treated as output parameters -%include "simCore/Calc/Gars.h" - -%include "simCore/Calc/Geometry.h" -%include "simCore/Calc/Interpolation.h" - -// simCore::WorldMagneticModel::calculateMagneticVariance() -%apply double& OUTPUT { double& varianceRad }; -%include "simCore/Calc/MagneticVariance.h" - -%warnfilter(509) simCore::Mgrs; // Ignore the overload warnings since they're treated as output parameters -// convertMgrsToGeodetic() -%apply double& OUTPUT { double& lat }; -%apply double& OUTPUT { double& lon }; -// breakMgrsString() -%apply int& OUTPUT { int& zone }; -%apply std::string& OUTPUT { std::string& gzdLetters }; -%apply double& OUTPUT { double& easting }; -%apply double& OUTPUT { double& northing }; -// TODO: These two methods do not wrap cleanly due to boolean reference -%ignore simCore::Mgrs::convertMgrsToUtm; -%ignore simCore::Mgrs::convertMgrsToUps; -%include "simCore/Calc/Mgrs.h" - -%include "simCore/Calc/MultiFrameCoordinate.h" - -// simCore::BisectionSearch::searchX() -%apply double& INOUT { double& x}; -%apply double& INOUT { double& xlo, double& xhi }; -// Required for double[3] in newtonInterp() -%include "carrays.i" -%array_class(double, DoubleArray); -// newtonInterp() -%apply double& OUTPUT { double& funcAtT0 }; -// invLinearInterp() -%apply double& OUTPUT { double& t0 }; -%include "simCore/Calc/NumericalAnalysis.h" - -// simCore::calculateRelAzEl() -%apply double* OUTPUT { double* azim, double* elev, double* cmp }; -// simCore::calculateGeodesicDRCR() -%apply double* OUTPUT { double* downRng, double* crossRng }; -// simCore::calculateRelAng() and simCore::calculateRelAngToTrueAzEl() -%apply double* OUTPUT { double* azim, double* elev, double* cmp }; -// TODO: calculateYawPitchFromBodyUnitX() -// TODO: sodanoDirect() -// TODO: sodanoInverse() -%include "simCore/Calc/Calculations.h" - -%include "simCore/Calc/Random.h" -%include "simCore/Calc/SquareMatrix.h" - -%include "simCore/Calc/Units.h" -%include "simCore/Calc/VerticalDatum.h" - -// TODO: Implement after installing simCore/Time -/* -%include "simCore/Calc/DatumConvert.h" -%include "simCore/Calc/UnitContext.h" -*/ - -%template(intSdkMax) simCore::sdkMax; -%template(intSdkMin) simCore::sdkMin; -%template(intSquare) simCore::square; -%template(intSign) simCore::sign; -%template(doubleSdkMax) simCore::sdkMax; -%template(doubleSdkMin) simCore::sdkMin; -%template(doubleSquare) simCore::square; -%template(doubleSign) simCore::sign; - -%template(Vec3LinearInterpolate) simCore::linearInterpolate; -%template(DoubleLinearInterpolate) simCore::linearInterpolate; -%template(intBilinearInterpolate) simCore::bilinearInterpolate; -%template(doubleBilinearInterpolate) simCore::bilinearInterpolate; - -//////////////////////////////////////////////// -// simCore/EM -// TODO: Implement -/* -%include "simCore/EM/Constants.h" - -// AntennaPattern::minMaxGain() -%apply float* OUTPUT { float* min, float* max }; -%include "simCore/EM/AntennaPattern.h" - - -%include "simCore/EM/Decibel.h" -%include "simCore/EM/ElectroMagRange.h" -%include "simCore/EM/Propagation.h" -%include "simCore/EM/RadarCrossSection.h" -*/ -//////////////////////////////////////////////// -// simCore/LUT -%include "simCore/LUT/LUT1.h" -%include "simCore/LUT/LUT2.h" -%include "simCore/LUT/InterpTable.h" - -%template(intLUT1) simCore::LUT::LUT1; -%template(doubleLUT1) simCore::LUT::LUT1; -%template(intIndex) simCore::LUT::index; -%template(doubleIndex) simCore::LUT::index; -%template(intLowValue) simCore::LUT::lowValue; -%template(doubleLowValue) simCore::LUT::lowValue; -// TODO: interpolate() - -%template(intLUT2) simCore::LUT::LUT2; -%template(doubleLUT2) simCore::LUT::LUT2; -// TODO: index() -// TODO: nearValue() -// TODO: interpolate() - -// TODO: BilinearInterpolate class -%template(intInterpTableLimitException) simCore::InterpTableLimitException; -%template(doubleInterpTableLimitException) simCore::InterpTableLimitException; -%template(intInterpTable) simCore::InterpTable; -%template(doubleInterpTable) simCore::InterpTable; -// TODO: NearestLookup() -// TODO: BilinearLookup() -// TODO: BilinearLookupNoException() - -//////////////////////////////////////////////// -// simCore/String -%apply double& OUTPUT { double& ang }; -%include "simCore/String/Angle.h" - -%include "simCore/String/Constants.h" -%include "simCore/String/FilePatterns.h" -%include "simCore/String/Format.h" - -%apply size_t& OUTPUT { size_t& endWordPos }; -%apply std::string& OUTPUT { std::string& tokenName, std::string& tokenValue }; -%include "simCore/String/Tokenizer.h" - -%include "simCore/String/Utils.h" - -// Format.h -// TODO: join() -// TODO: getStrippedLine() - -// Tokenizer.h -// TODO: stringTokenizer() -// TODO: getTokens() -// TODO: removeQuotes() -// TODO: tokenizeWithQuotes() -// TODO: quoteTokenizer() -// TODO: removeCommentTokens() -// TODO: quoteCommentTokenizer() -// TODO: escapeTokenize() -// TODO: Add these and test them as you add them -/* -%include "simCore/String/TextFormatter.h" -%include "simCore/String/TextReplacer.h" -%include "simCore/String/UnitContextFormatter.h" -%include "simCore/String/ValidNumber.h" -%include "simCore/Time/Clock.h" -%include "simCore/Time/ClockImpl.h" -%include "simCore/Time/Constants.h" -%include "simCore/Time/CountDown.h" -%include "simCore/Time/DeprecatedStrings.h" -%include "simCore/Time/Exception.h" -%include "simCore/Time/Julian.h" -%include "simCore/Time/String.h" -%include "simCore/Time/TimeClass.h" -%include "simCore/Time/TimeClock.h" -%include "simCore/Time/Utils.h" -*/ +%include "simCoreCommon.i" +%include "simCoreCalc.i" +%include "simCoreEM.i" +%include "simCoreLUT.i" +%include "simCoreString.i" +%include "simCoreTime.i" diff --git a/swig/simCore/simCoreCalc.i b/swig/simCore/simCoreCalc.i new file mode 100644 index 000000000..ef4e3b6bf --- /dev/null +++ b/swig/simCore/simCoreCalc.i @@ -0,0 +1,137 @@ +%ignore simCore::Vec3::operator=; +%ignore simCore::Vec3::operator[]; +%ignore simCore::Coordinate::operator=; +%ignore simCore::CoordinateConverter::operator=; +%ignore simCore::SquareMatrix::operator=; + +//////////////////////////////////////////////// +// simCore/Calc +%include "simCore/Calc/Vec3.h" +%include "simCore/Calc/Angle.h" + +// simCore::coordinateSystemFromString() +%apply int& OUTPUT { simCore::CoordinateSystem& outSystem }; + +%include "simCore/Calc/CoordinateSystem.h" +%include "simCore/Calc/Coordinate.h" + +// Handling output parameter for toScientific() from simCore/calc/Math.cpp +%apply int* OUTPUT { int* exp }; + +// v3Scale() needs a custom wrapper for proper return value +%rename("wrap_v3Scale") simCore::v3Scale; +%include "simCore/Calc/Math.h" + +%pythoncode %{ +def v3Scale(scalar, inVec): + outVec = Vec3() + wrap_v3Scale(scalar, inVec, outVec) + return outVec +%} + +%rename("wrap_convert") simCore::CoordinateConverter::convert; +%include "simCore/Calc/CoordinateConverter.h" +%pythoncode %{ +def CoordConvert_convert(self, inCoord, outSystem): + outCoord = Coordinate() + rv = self.wrap_convert(inCoord, outCoord, outSystem) + return rv, outCoord +CoordinateConverter.convert = CoordConvert_convert +%} + +// isValidGars() +%apply std::string* OUTPUT { std::string* err }; +%apply int* OUTPUT { int* lonBand }; +%apply int* OUTPUT { int* latPrimaryIdx }; +%apply int* OUTPUT { int* latSecondaryIdx }; +%apply int* OUTPUT { int* quad15 }; +%apply int* OUTPUT { int* key5 }; +// convertGarsToGeodetic() +%apply double& OUTPUT { double& latRad }; +%apply double& OUTPUT { double& lonRad }; +// convertGeodeticToGars() +%apply std::string* OUTPUT { std::string* garsOut }; +%extend simCore::Gars { + // Fixes ordering of parameters for SWIG + static int convertGeodeticToGars(double latRad, double lonRad, simCore::Gars::Level level, std::string* garsOut, std::string* err) { + return simCore::Gars::convertGeodeticToGars(latRad, lonRad, *garsOut, level, err); + } + static int convertGeodeticToGars(double latRad, double lonRad, std::string* garsOut, std::string* err) { + return simCore::Gars::convertGeodeticToGars(latRad, lonRad, *garsOut, simCore::Gars::GARS_5, err); + } +}; +%ignore simCore::Gars::convertGeodeticToGars; // Ignore the C++ header file version +%warnfilter(509) simCore::Gars; // Ignore the overload warnings since they're treated as output parameters +%include "simCore/Calc/Gars.h" + +%include "simCore/Calc/Geometry.h" +%include "simCore/Calc/Interpolation.h" + +// simCore::WorldMagneticModel::calculateMagneticVariance() +%apply double& OUTPUT { double& varianceRad }; +%include "simCore/Calc/MagneticVariance.h" + +%warnfilter(509) simCore::Mgrs; // Ignore the overload warnings since they're treated as output parameters +// convertMgrsToGeodetic() +%apply double& OUTPUT { double& lat }; +%apply double& OUTPUT { double& lon }; +// breakMgrsString() +%apply int& OUTPUT { int& zone }; +%apply std::string& OUTPUT { std::string& gzdLetters }; +%apply double& OUTPUT { double& easting }; +%apply double& OUTPUT { double& northing }; +// TODO: These two methods do not wrap cleanly due to boolean reference +%ignore simCore::Mgrs::convertMgrsToUtm; +%ignore simCore::Mgrs::convertMgrsToUps; +%include "simCore/Calc/Mgrs.h" + +%include "simCore/Calc/MultiFrameCoordinate.h" + +// simCore::BisectionSearch::searchX() +%apply double& INOUT { double& x}; +%apply double& INOUT { double& xlo, double& xhi }; +// Required for double[3] in newtonInterp() +%include "carrays.i" +%array_class(double, DoubleArray); +// newtonInterp() +%apply double& OUTPUT { double& funcAtT0 }; +// invLinearInterp() +%apply double& OUTPUT { double& t0 }; +%include "simCore/Calc/NumericalAnalysis.h" + +// simCore::calculateRelAzEl() +%apply double* OUTPUT { double* azim, double* elev, double* cmp }; +// simCore::calculateGeodesicDRCR() +%apply double* OUTPUT { double* downRng, double* crossRng }; +// simCore::calculateRelAng() and simCore::calculateRelAngToTrueAzEl() +%apply double* OUTPUT { double* azim, double* elev, double* cmp }; +// TODO: calculateYawPitchFromBodyUnitX() +// TODO: sodanoDirect() +// TODO: sodanoInverse() +%include "simCore/Calc/Calculations.h" + +%include "simCore/Calc/Random.h" +%include "simCore/Calc/SquareMatrix.h" + +%include "simCore/Calc/Units.h" +%include "simCore/Calc/VerticalDatum.h" + +// TODO: Implement after installing simCore/Time +/* +%include "simCore/Calc/DatumConvert.h" +%include "simCore/Calc/UnitContext.h" +*/ + +%template(intSdkMax) simCore::sdkMax; +%template(intSdkMin) simCore::sdkMin; +%template(intSquare) simCore::square; +%template(intSign) simCore::sign; +%template(doubleSdkMax) simCore::sdkMax; +%template(doubleSdkMin) simCore::sdkMin; +%template(doubleSquare) simCore::square; +%template(doubleSign) simCore::sign; + +%template(Vec3LinearInterpolate) simCore::linearInterpolate; +%template(DoubleLinearInterpolate) simCore::linearInterpolate; +%template(intBilinearInterpolate) simCore::bilinearInterpolate; +%template(doubleBilinearInterpolate) simCore::bilinearInterpolate; diff --git a/swig/simCore/simCoreCommon.i b/swig/simCore/simCoreCommon.i new file mode 100644 index 000000000..9c502dcc9 --- /dev/null +++ b/swig/simCore/simCoreCommon.i @@ -0,0 +1,5 @@ +//////////////////////////////////////////////// +// simCore/Common +%include "simCore/Common/Exception.h" +%include "simCore/Common/Time.h" + diff --git a/swig/simCore/simCoreEM.i b/swig/simCore/simCoreEM.i new file mode 100644 index 000000000..a08003d56 --- /dev/null +++ b/swig/simCore/simCoreEM.i @@ -0,0 +1,16 @@ +//////////////////////////////////////////////// +// simCore/EM +// TODO: Implement +/* +%include "simCore/EM/Constants.h" + +// AntennaPattern::minMaxGain() +%apply float* OUTPUT { float* min, float* max }; +%include "simCore/EM/AntennaPattern.h" + + +%include "simCore/EM/Decibel.h" +%include "simCore/EM/ElectroMagRange.h" +%include "simCore/EM/Propagation.h" +%include "simCore/EM/RadarCrossSection.h" +*/ diff --git a/swig/simCore/simCoreLUT.i b/swig/simCore/simCoreLUT.i new file mode 100644 index 000000000..5ab73b6f7 --- /dev/null +++ b/swig/simCore/simCoreLUT.i @@ -0,0 +1,29 @@ +//////////////////////////////////////////////// +// simCore/LUT +%include "simCore/LUT/LUT1.h" +%include "simCore/LUT/LUT2.h" +%include "simCore/LUT/InterpTable.h" + +%template(intLUT1) simCore::LUT::LUT1; +%template(doubleLUT1) simCore::LUT::LUT1; +%template(intIndex) simCore::LUT::index; +%template(doubleIndex) simCore::LUT::index; +%template(intLowValue) simCore::LUT::lowValue; +%template(doubleLowValue) simCore::LUT::lowValue; +// TODO: interpolate() + +%template(intLUT2) simCore::LUT::LUT2; +%template(doubleLUT2) simCore::LUT::LUT2; +// TODO: index() +// TODO: nearValue() +// TODO: interpolate() + +// TODO: BilinearInterpolate class +%template(intInterpTableLimitException) simCore::InterpTableLimitException; +%template(doubleInterpTableLimitException) simCore::InterpTableLimitException; +%template(intInterpTable) simCore::InterpTable; +%template(doubleInterpTable) simCore::InterpTable; +// TODO: NearestLookup() +// TODO: BilinearLookup() +// TODO: BilinearLookupNoException() + diff --git a/swig/simCore/simCoreString.i b/swig/simCore/simCoreString.i new file mode 100644 index 000000000..4bde173b8 --- /dev/null +++ b/swig/simCore/simCoreString.i @@ -0,0 +1,36 @@ +//////////////////////////////////////////////// +// simCore/String +%apply double& OUTPUT { double& ang }; +%include "simCore/String/Angle.h" + +%include "simCore/String/Constants.h" +%include "simCore/String/FilePatterns.h" +%include "simCore/String/Format.h" + +%apply size_t& OUTPUT { size_t& endWordPos }; +%apply std::string& OUTPUT { std::string& tokenName, std::string& tokenValue }; +%include "simCore/String/Tokenizer.h" + +%include "simCore/String/Utils.h" + +// Format.h +// TODO: join() +// TODO: getStrippedLine() + +// Tokenizer.h +// TODO: stringTokenizer() +// TODO: getTokens() +// TODO: removeQuotes() +// TODO: tokenizeWithQuotes() +// TODO: quoteTokenizer() +// TODO: removeCommentTokens() +// TODO: quoteCommentTokenizer() +// TODO: escapeTokenize() + +// TODO: Add these and test them as you add them +/* +%include "simCore/String/TextFormatter.h" +%include "simCore/String/TextReplacer.h" +%include "simCore/String/UnitContextFormatter.h" +%include "simCore/String/ValidNumber.h" +*/ diff --git a/swig/simCore/simCoreTime.i b/swig/simCore/simCoreTime.i new file mode 100644 index 000000000..a135612cb --- /dev/null +++ b/swig/simCore/simCoreTime.i @@ -0,0 +1,21 @@ +//////////////////////////////////////////////// +// simCore/Time + +// TODO: Add these and test them as you add them +/* +%include "simCore/String/TextFormatter.h" +%include "simCore/String/TextReplacer.h" +%include "simCore/String/UnitContextFormatter.h" +%include "simCore/String/ValidNumber.h" +%include "simCore/Time/Clock.h" +%include "simCore/Time/ClockImpl.h" +%include "simCore/Time/Constants.h" +%include "simCore/Time/CountDown.h" +%include "simCore/Time/DeprecatedStrings.h" +%include "simCore/Time/Exception.h" +%include "simCore/Time/Julian.h" +%include "simCore/Time/String.h" +%include "simCore/Time/TimeClass.h" +%include "simCore/Time/TimeClock.h" +%include "simCore/Time/Utils.h" +*/ From 86248ac3e53e16e9e1c9841eb863749f1a175468 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Mon, 9 Mar 2020 11:29:59 -0400 Subject: [PATCH 118/121] DEV: Fixed C++11/0x unordered_map issue (unsupported in C++0x). Fixed leak in new elevation envelope context container. Review: 20937 --- SDK/simVis/Entity.h | 1 + SDK/simVis/Scenario.cpp | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/SDK/simVis/Entity.h b/SDK/simVis/Entity.h index 33e83237d..0cb661384 100644 --- a/SDK/simVis/Entity.h +++ b/SDK/simVis/Entity.h @@ -74,6 +74,7 @@ namespace simVis */ void clampCoordToMapSurface(simCore::Coordinate& coord); + /** clampCoordToMapSurface() variation that accepts a context for optimization. */ void clampCoordToMapSurface(simCore::Coordinate& coord, osgEarth::ElevationEnvelope::Context& context); /** Return true if able to apply clamping, false otherwise */ diff --git a/SDK/simVis/Scenario.cpp b/SDK/simVis/Scenario.cpp index cd1053eb6..8f5143e5f 100644 --- a/SDK/simVis/Scenario.cpp +++ b/SDK/simVis/Scenario.cpp @@ -271,7 +271,6 @@ class ScenarioManager::SurfaceClamping : public PlatformTspiFilter return PlatformTspiFilterManager::POINT_UNCHANGED; osgEarth::ElevationEnvelope::Context& context = lut_[props.id()]; - coordSurfaceClamping_.clampCoordToMapSurface(llaCoord, context); return PlatformTspiFilterManager::POINT_CHANGED; @@ -283,14 +282,21 @@ class ScenarioManager::SurfaceClamping : public PlatformTspiFilter coordSurfaceClamping_.setMapNode(map); } + /** Changes the flag for using maximum elevation precision */ void setUseMaxElevPrec(bool useMaxElev) { coordSurfaceClamping_.setUseMaxElevPrec(useMaxElev); } + /** Removes an entity from the optimization look-up table */ + void removeEntity(simData::ObjectId id) + { + lut_.erase(id); + } + private: CoordSurfaceClamping coordSurfaceClamping_; - std::unordered_map lut_; + std::map lut_; }; @@ -602,6 +608,9 @@ void ScenarioManager::removeEntity(simData::ObjectId id) EntityNode* entity = record->getEntityNode(); notifyToolsOfRemove_(entity); + // Remove it from the surface clamping algorithm + surfaceClamping_->removeEntity(id); + // If this is a projector node, delete this from the projector manager if (entity->type() == simData::PROJECTOR) { From ab3a4c7bd5a1966334905af805fd4dda5bc42031 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Mon, 9 Mar 2020 12:04:33 -0400 Subject: [PATCH 119/121] DEV: More SWIG methods are properly wrapped. Fixed dependencies on SWIG generation. Renamed a parameter to be more SWIG-friendly. Part of SIM-10526. Review: 20941 --- SDK/simCore/Calc/Calculations.cpp | 14 ++--- SDK/simCore/Calc/Calculations.h | 6 +-- swig/Testing/TestSimCore.py | 49 +++++++++-------- swig/simCore/CMakeLists.txt | 7 +++ swig/simCore/simCoreCalc.i | 90 ++++++++++++++++++++++++++++--- 5 files changed, 125 insertions(+), 41 deletions(-) diff --git a/SDK/simCore/Calc/Calculations.cpp b/SDK/simCore/Calc/Calculations.cpp index 9c6ad04e5..b0bac6cc6 100644 --- a/SDK/simCore/Calc/Calculations.cpp +++ b/SDK/simCore/Calc/Calculations.cpp @@ -1138,7 +1138,7 @@ void calculateBodyUnitZ(const double yaw, const double pitch, const double roll, } /// Decomposes the X component of the unit body vector into yaw and pitch angles -void calculateYawPitchFromBodyUnitX(const Vec3 &vecX, double &yaw, double &pitch) +void calculateYawPitchFromBodyUnitX(const Vec3 &vecX, double &yawOut, double &pitchOut) { // From Aircraft Control and Simulation 2nd Edition // B. Stevens & F. Lewis 2003 @@ -1149,21 +1149,21 @@ void calculateYawPitchFromBodyUnitX(const Vec3 &vecX, double &yaw, double &pitch // magnitude greater than unity if (areEqual(vecX[2], 1.0)) { - yaw = 0.0; - pitch = -M_PI_2; + yawOut = 0.0; + pitchOut = -M_PI_2; } else if (areEqual(vecX[2], -1.0)) { - yaw = 0.0; - pitch = M_PI_2; + yawOut = 0.0; + pitchOut = M_PI_2; } else { // no gimbal lock // atan2 returns in the range -pi to pi // inverseSine returns in the range -pi/2 to pi/2 - yaw = atan2(vecX[1], vecX[0]); - pitch = simCore::inverseSine(-vecX[2]); + yawOut = atan2(vecX[1], vecX[0]); + pitchOut = simCore::inverseSine(-vecX[2]); } } diff --git a/SDK/simCore/Calc/Calculations.h b/SDK/simCore/Calc/Calculations.h index 517262aae..0b522fc83 100644 --- a/SDK/simCore/Calc/Calculations.h +++ b/SDK/simCore/Calc/Calculations.h @@ -424,10 +424,10 @@ namespace simCore * Given the X component of the vehicle's body unit vector and a yaw-pitch-roll (1-2-3) rotation sequence * The yaw and pitch angles are computed * @param[in ] vecX Vec3 representing the X component of the body unit vector - * @param[out] yaw Yaw (psi) rotation in radians - * @param[out] pitch Pitch (theta) rotation in radians + * @param[out] yawOut Yaw (psi) rotation in radians + * @param[out] pitchOut Pitch (theta) rotation in radians */ - SDKCORE_EXPORT void calculateYawPitchFromBodyUnitX(const Vec3 &vecX, double &yaw, double &pitch); + SDKCORE_EXPORT void calculateYawPitchFromBodyUnitX(const Vec3 &vecX, double &yawOut, double &pitchOut); /** * @brief Calculates an ENU geodetic velocity vector based on a local (moving) tangent plane diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index f303e1d92..780c8cd07 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -240,15 +240,13 @@ def sleepWrapper(): rv, zone, gzdLetters, easting, northing, err = mgrs.breakMgrsString("33CWM1974418352") assert(rv is not None and zone is not None and gzdLetters is not None and easting is not None and northing is not None and err is not None) -# TODO: Boolean references are failing -#rv, northPole, utmEasting, utmNorthing, err = mgrs.convertMgrsToUtm(33, "CWM", 19744.0, 18352.0) -#assert(rv is not None and northPole is not None and utmEasting is not None +# rv, northPole, utmEasting, utmNorthing, err = mgrs.convertMgrsToUtm(33, "CWM", 19744.0, 18352.0) +# assert(rv is not None and northPole is not None and utmEasting is not None # and utmNorthing is not None and err is not None) rv, lat, lon, err = mgrs.convertUtmToGeodetic(33, False, 19744.0, 18352.0) assert(rv is not None and lat is not None and lon is not None and err is not None) -# TODO: Boolean references are failing -#rv, northPole, upsEasting, upsNorthing, err = mgrs.convertMgrsToUps("33CWM1974418352", 19744.0, 18352.0) -#assert(rv is not None and northPole is not None and upsEasting is not None +# rv, northPole, upsEasting, upsNorthing, err = mgrs.convertMgrsToUps("33CWM1974418352", 19744.0, 18352.0) +# assert(rv is not None and northPole is not None and upsEasting is not None # and upsNorthing is not None and err is not None) rv, lat, lon, err = mgrs.convertUpsToGeodetic(False, 19744.0, 18352.0) assert(rv is not None and lat is not None and lon is not None and err is not None) @@ -293,27 +291,30 @@ def sleepWrapper(): ############################# # Calculations.h # TODO: Following fail, fix output -# assert(simCore.tangentPlane2Sphere(v1, v2) is not None) -# assert(simCore.geodeticToSpherical(0, 0, 0) is not None) +sphereVec, sphereTpOrigin = simCore.tangentPlane2Sphere(v1, v2) +assert(sphereVec is not None and sphereTpOrigin is not None) +assert(simCore.geodeticToSpherical(0, 0, 0) is not None) # success, fromPos, toPos = simCore.convertLocations(simCore.Coordinate(), simCore.Coordinate(), simCore.WGS_84, coordConverter) # assert(success is not None and fromPos is not None and toPos is not None) -# assert(simCore.calculateBodyUnitX(1, 1) is not None) -# assert(simCore.calculateBodyUnitY(1, 1, 1) is not None) -# assert(simCore.calculateBodyUnitZ(1, 1, 1) is not None) -# assert(simCore.calculateVelFromGeodeticPos(v1, v2, 1) is not None) -# success, velOut, oriOut = simCore.calculateVelOriFromPos(v1, v2, 1, simCore.WGS_84, v3) -# assert(success is not None and velOut is not None and oriOut is not None) -# assert(simCore.calculateGeodeticOriFromRelOri(v1, v2) is not None) -# assert(simCore.calculateGeodeticOffsetPos(v1, v2, v3) is not None) -# assert(simCore.calculateGeodeticEndPoint(v1, 1, 1, 1) is not None) +assert(simCore.calculateBodyUnitX(1, 1) is not None) +assert(simCore.calculateBodyUnitY(1, 1, 1) is not None) +assert(simCore.calculateBodyUnitZ(1, 1, 1) is not None) +assert(simCore.calculateVelFromGeodeticPos(v1, v2, 1) is not None) +success, velOut, oriOut = simCore.calculateVelOriFromPos(v1, v2, 1, simCore.WGS_84, v3) +assert(success is not None and velOut is not None and oriOut is not None) +success, velOut, oriOut = simCore.calculateVelOriFromPos(v1, v2, 1, simCore.WGS_84, v3, simCore.COORD_SYS_XEAST) +assert(success is not None and velOut is not None and oriOut is not None) +assert(simCore.calculateGeodeticOriFromRelOri(v1, v2) is not None) +assert(simCore.calculateGeodeticOffsetPos(v1, v2, v3) is not None) +assert(simCore.calculateGeodeticEndPoint(v1, 1, 1, 1) is not None) # midPoint, wrapsDateline = simCore.calculateGeodeticMidPoint(v1, v2, False) # assert(midPoint is not None and wrapsDateline is not None) -# assert(simCore.calculateFlightPathAngles(v1) is not None) -# assert(simCore.calculateVelocity(1, 1, 1) is not None) -# aoa, ss, totalAoa = simCore.calculateAoaSideslipTotalAoa(v1, v2, True) -# assert(aoa is not None and ss is not None and totalAoa is not None) -# distance, closestLla = simCore.getClosestPoint(v1, v2, v3) -# assert(distance is not None and closestLla is not None) +assert(simCore.calculateFlightPathAngles(v1) is not None) +assert(simCore.calculateVelocity(1, 1, 1) is not None) +aoa, ss, totalAoa = simCore.calculateAoaSideslipTotalAoa(v1, v2, True) +assert(aoa is not None and ss is not None and totalAoa is not None) +distance, closestLla = simCore.getClosestPoint(v1, v2, v3) +assert(distance is not None and closestLla is not None) azim, elev, cmp = simCore.calculateRelAzEl(v1, v2, v3, simCore.WGS_84, coordConverter) assert(azim is not None and elev is not None and cmp is not None) azim, elev, cmp = simCore.calculateAbsAzEl(v1, v2, simCore.WGS_84, coordConverter) @@ -329,6 +330,8 @@ def sleepWrapper(): assert(azim is not None and elev is not None and cmp is not None) assert(simCore.positionInGate(v1, v2, 1, 2, 3, 4, 5, 6, simCore.WGS_84, coordConverter) is not None) assert(simCore.laserInGate(v1, v2, 1, 2, 3, 4, 5, 6, 7, 8, 9, simCore.WGS_84, coordConverter) is not None) +yaw, pitch = simCore.calculateYawPitchFromBodyUnitX(v1) +assert(yaw is not None and pitch is not None) ############################# # Random.h diff --git a/swig/simCore/CMakeLists.txt b/swig/simCore/CMakeLists.txt index f708862de..56d629e33 100644 --- a/swig/simCore/CMakeLists.txt +++ b/swig/simCore/CMakeLists.txt @@ -2,6 +2,13 @@ vsi_require_target(PYTHON3) set(SIMCORE_FILES simCore.i + simCoreCalc.i + simCoreCommon.i + simCoreEM.i + simCore.i + simCoreLUT.i + simCoreString.i + simCoreTime.i ) set_source_files_properties(simCore.i PROPERTIES diff --git a/swig/simCore/simCoreCalc.i b/swig/simCore/simCoreCalc.i index ef4e3b6bf..27646f926 100644 --- a/swig/simCore/simCoreCalc.i +++ b/swig/simCore/simCoreCalc.i @@ -22,13 +22,6 @@ %rename("wrap_v3Scale") simCore::v3Scale; %include "simCore/Calc/Math.h" -%pythoncode %{ -def v3Scale(scalar, inVec): - outVec = Vec3() - wrap_v3Scale(scalar, inVec, outVec) - return outVec -%} - %rename("wrap_convert") simCore::CoordinateConverter::convert; %include "simCore/Calc/CoordinateConverter.h" %pythoncode %{ @@ -105,7 +98,26 @@ CoordinateConverter.convert = CoordConvert_convert %apply double* OUTPUT { double* downRng, double* crossRng }; // simCore::calculateRelAng() and simCore::calculateRelAngToTrueAzEl() %apply double* OUTPUT { double* azim, double* elev, double* cmp }; -// TODO: calculateYawPitchFromBodyUnitX() + +%rename("wrap_tangentPlane2Sphere") simCore::tangentPlane2Sphere; +%rename("wrap_geodeticToSpherical") simCore::geodeticToSpherical; +%rename("wrap_calculateBodyUnitX") simCore::calculateBodyUnitX; +%rename("wrap_calculateBodyUnitY") simCore::calculateBodyUnitY; +%rename("wrap_calculateBodyUnitZ") simCore::calculateBodyUnitZ; +%rename("wrap_calculateVelFromGeodeticPos") simCore::calculateVelFromGeodeticPos; +%rename("wrap_calculateVelOriFromPos") simCore::calculateVelOriFromPos; +%rename("wrap_calculateGeodeticOriFromRelOri") simCore::calculateGeodeticOriFromRelOri; +%rename("wrap_calculateGeodeticOffsetPos") simCore::calculateGeodeticOffsetPos; +%rename("wrap_calculateGeodeticEndPoint") simCore::calculateGeodeticEndPoint; +%rename("wrap_calculateFlightPathAngles") simCore::calculateFlightPathAngles; +%rename("wrap_calculateVelocity") simCore::calculateVelocity; +%rename("wrap_getClosestPoint") simCore::getClosestPoint; + +// simCore::calculateAoaSideslipTotalAoa() +%apply double* OUTPUT { double* aoa, double* ss, double* totalAoA }; +// simCore::calculateYawPitchFromBodyUnitX() +%apply double& OUTPUT { double& yawOut, double& pitchOut }; + // TODO: sodanoDirect() // TODO: sodanoInverse() %include "simCore/Calc/Calculations.h" @@ -135,3 +147,65 @@ CoordinateConverter.convert = CoordConvert_convert %template(DoubleLinearInterpolate) simCore::linearInterpolate; %template(intBilinearInterpolate) simCore::bilinearInterpolate; %template(doubleBilinearInterpolate) simCore::bilinearInterpolate; + +// Various Python overrides +%pythoncode %{ +def v3Scale(scalar, inVec): + outVec = Vec3() + wrap_v3Scale(scalar, inVec, outVec) + return outVec +def tangentPlane2Sphere(llaVec, tpVec): + sphereVec = Vec3() + sphereTpOrigin = Vec3() + wrap_tangentPlane2Sphere(llaVec, tpVec, sphereVec, sphereTpOrigin) + return sphereVec, sphereTpOrigin +def geodeticToSpherical(lat, lon, alt): + point = Vec3() + wrap_geodeticToSpherical(lat, lon, alt, point) + return point +def calculateBodyUnitX(yaw, pitch): + vecX = Vec3() + wrap_calculateBodyUnitX(yaw, pitch, vecX) + return vecX +def calculateBodyUnitY(yaw, pitch, roll): + vecY = Vec3() + wrap_calculateBodyUnitY(yaw, pitch, roll, vecY) + return vecY +def calculateBodyUnitZ(yaw, pitch, roll): + vecZ = Vec3() + wrap_calculateBodyUnitZ(yaw, pitch, roll, vecZ) + return vecZ +def calculateVelFromGeodeticPos(currPos, prevPos, deltaTime): + velVec = Vec3() + wrap_calculateVelFromGeodeticPos(currPos, prevPos, deltaTime, velVec) + return velVec +def calculateVelOriFromPos(currPos, prevPos, deltaTime, sysIn, refLLA, sysOut=COORD_SYS_XEAST): + velOut = Vec3() + oriOut = Vec3() + success = wrap_calculateVelOriFromPos(currPos, prevPos, deltaTime, sysIn, velOut, oriOut, refLLA, sysOut) + return success, velOut, oriOut +def calculateGeodeticOriFromRelOri(hostYpr, relYpr): + ypr = Vec3() + wrap_calculateGeodeticOriFromRelOri(hostYpr, relYpr, ypr) + return ypr +def calculateGeodeticOffsetPos(llaBgnPos, bodyOriOffset, bodyPosOffset): + offsetLla = Vec3() + wrap_calculateGeodeticOffsetPos(llaBgnPos, bodyOriOffset, bodyPosOffset, offsetLla) + return offsetLla +def calculateGeodeticEndPoint(llaBgnPos, az, el, rng): + llaEndPos = Vec3() + wrap_calculateGeodeticEndPoint(llaBgnPos, az, el, rng, llaEndPos) + return llaEndPos +def calculateFlightPathAngles(velVec): + fpa = Vec3() + wrap_calculateFlightPathAngles(velVec, fpa) + return fpa +def calculateVelocity(speed, heading, pitch): + velVec = Vec3() + wrap_calculateVelocity(speed, heading, pitch, velVec) + return velVec +def getClosestPoint(startLla, endLla, toLla): + closestLla = Vec3() + dist = wrap_getClosestPoint(startLla, endLla, toLla, closestLla) + return dist, closestLla +%} From 2b7818a644a40b8bba6fd5c325bd312479b4ced0 Mon Sep 17 00:00:00 2001 From: Daniel Emminizer Date: Mon, 9 Mar 2020 13:11:33 -0400 Subject: [PATCH 120/121] DEV: sodanoDirect and sodanoIndirect are now implemented. Testing includes more functions. Part of SIM-10526. Review: 20942 --- SDK/simCore/Calc/Calculations.cpp | 10 +++++----- SDK/simCore/Calc/Calculations.h | 6 +++--- swig/Testing/TestSimCore.py | 13 +++++++++++++ swig/simCore/simCoreCalc.i | 8 ++++++-- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/SDK/simCore/Calc/Calculations.cpp b/SDK/simCore/Calc/Calculations.cpp index b0bac6cc6..bb28f808a 100644 --- a/SDK/simCore/Calc/Calculations.cpp +++ b/SDK/simCore/Calc/Calculations.cpp @@ -479,14 +479,14 @@ double calculateAspectAngle(const Vec3 &fromLla, const Vec3 &toLla, const Vec3 & * longitude and latitude and back azimuth given a geodetic reference longitude * and latitude, a geodesic length, a forward azimuth and an ellipsoid definition. */ -void sodanoDirect(const double refLat, const double refLon, const double refAlt, const double dist, const double azfwd, double *lat, double *lon, double *azbck) +void sodanoDirect(const double refLat, const double refLon, const double refAlt, const double dist, const double azfwd, double *latOut, double *lonOut, double *azbck) { // Reference: // E. M. Sodano and T. A. Robinson, // "Direct and Inverse Solutions in Geodesics Technical Report 7" // U.S. Army Map Service, Washington, DC 1963 pp. 15-27. - assert(lat || lon || azbck); - if (!lat && !lon && !azbck) + assert(latOut || lonOut || azbck); + if (!latOut && !lonOut && !azbck) { SIM_ERROR << "sodanoDirect, invalid output params: " << __LINE__ << std::endl; return; @@ -526,8 +526,8 @@ void sodanoDirect(const double refLat, const double refLon, const double refAlt, const double lamda = atan2((sdel*saz), (cbeta1*cdel - sbeta1*sdel*caz)); // Set second latitude and longitude point - if (lat) *lat = atan2(reqtr*sbeta2, rpolr*cbeta2); - if (lon) *lon = refLon + lamda + length; + if (latOut) *latOut = atan2(reqtr*sbeta2, rpolr*cbeta2); + if (lonOut) *lonOut = refLon + lamda + length; // Back azimuth if (azbck) *azbck = atan2(-h, (sbeta1*sdel - g*cdel)); diff --git a/SDK/simCore/Calc/Calculations.h b/SDK/simCore/Calc/Calculations.h index 0b522fc83..5619858be 100644 --- a/SDK/simCore/Calc/Calculations.h +++ b/SDK/simCore/Calc/Calculations.h @@ -308,12 +308,12 @@ namespace simCore * @param[in ] refAlt Height above ellipsoid of reference point (m) * @param[in ] dist Geodesic length from reference to second point along the forward azimuth (m) * @param[in ] azfwd Forward azimuth from reference to second point (rad) - * @param[out] lat Geodetic latitude of point 2 (rad) - * @param[out] lon Geodetic longitude of point 2 (rad) + * @param[out] latOut Geodetic latitude of point 2 (rad) + * @param[out] lonOut Geodetic longitude of point 2 (rad) * @param[out] azbck Backward azimuth from second point to reference (rad) * @pre one of the lat, lon or azbck params must be valid */ - SDKCORE_EXPORT void sodanoDirect(const double refLat, const double refLon, const double refAlt, const double dist, const double azfwd, double *lat, double *lon, double *azbck=NULL); + SDKCORE_EXPORT void sodanoDirect(const double refLat, const double refLon, const double refAlt, const double dist, const double azfwd, double *latOut, double *lonOut, double *azbck=NULL); /** * @brief Calculates the geodesic length, forward and backward azimuth using Sodano's indirect solution diff --git a/swig/Testing/TestSimCore.py b/swig/Testing/TestSimCore.py index 780c8cd07..9e3e66b8f 100644 --- a/swig/Testing/TestSimCore.py +++ b/swig/Testing/TestSimCore.py @@ -332,6 +332,19 @@ def sleepWrapper(): assert(simCore.laserInGate(v1, v2, 1, 2, 3, 4, 5, 6, 7, 8, 9, simCore.WGS_84, coordConverter) is not None) yaw, pitch = simCore.calculateYawPitchFromBodyUnitX(v1) assert(yaw is not None and pitch is not None) +lat, lon, azbck = simCore.sodanoDirect(1, 2, 3, 100.0, 3.14159) +assert(lat is not None and lon is not None and azbck is not None) +distance, azfwd, azbck, = simCore.sodanoInverse(1, 2, 3, 2, 3) +assert(distance is not None and azfwd is not None and azbck is not None) +assert(simCore.calculateEarthRadius(1.0) is not None) +# assert(simCore.clampEcefPointToGeodeticSurface(v1) is not None) +assert(simCore.calculateHorizonDist(v1) is not None) +assert(simCore.calculateHorizonDist(v1, simCore.GEOMETRIC_HORIZON) is not None) +assert(simCore.calculateHorizonDist(v1, simCore.GEOMETRIC_HORIZON, 1.06) is not None) +assert(simCore.calculateHorizonDist(v1, simCore.GEOMETRIC_HORIZON, 1.06, 1.333) is not None) +assert(simCore.positionInGate(v1, v2, 1.0, 0.0, 1.0, 1.0, 1000.0, 3000.0, simCore.WGS_84, coordConverter) is not None) +assert(simCore.laserInGate(v1, v2, 1.0, 0.0, 1.0, 1.0, 1000.0, 3000.0, 1.5, 1.5, 2000.0, simCore.WGS_84, coordConverter) is not None) +assert(simCore.laserInGate(v1, v2, 1.0, 0.0, 1.0, 1.0, 1000.0, 3000.0, 1.5, 1.5, 2000.0, simCore.WGS_84, coordConverter, 100) is not None) ############################# # Random.h diff --git a/swig/simCore/simCoreCalc.i b/swig/simCore/simCoreCalc.i index 27646f926..ed6b3f4f9 100644 --- a/swig/simCore/simCoreCalc.i +++ b/swig/simCore/simCoreCalc.i @@ -117,9 +117,13 @@ CoordinateConverter.convert = CoordConvert_convert %apply double* OUTPUT { double* aoa, double* ss, double* totalAoA }; // simCore::calculateYawPitchFromBodyUnitX() %apply double& OUTPUT { double& yawOut, double& pitchOut }; +// simCore::sodanoDirect() +%warnfilter(509) simCore::sodanoDirect; +%apply double* OUTPUT { double *latOut, double *lonOut, double *azbck }; +// simCore::sodanoInverse() +%warnfilter(509) simCore::sodanoInverse; +%apply double* OUTPUT { double *azfwd, double *azbck }; -// TODO: sodanoDirect() -// TODO: sodanoInverse() %include "simCore/Calc/Calculations.h" %include "simCore/Calc/Random.h" From 410c61946a751bf90f2862c3b9609bcdea4671df Mon Sep 17 00:00:00 2001 From: Frank Bausch Date: Wed, 11 Mar 2020 10:29:25 -0400 Subject: [PATCH 121/121] simUtil: remove unnecessary map setProfile for config.txt loading (SIM-11196) Release Note: N/A Notes: Test Environment: Windows 10, VC14, Debug, 64-bit. Test: tss: fixes artifacts with no apparent changes to map Review: 20957 --- SDK/simUtil/DbConfigurationFile.cpp | 10 +--------- SDK/simUtil/DbConfigurationFile.h | 7 ------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/SDK/simUtil/DbConfigurationFile.cpp b/SDK/simUtil/DbConfigurationFile.cpp index 1dd990518..7349ffd82 100644 --- a/SDK/simUtil/DbConfigurationFile.cpp +++ b/SDK/simUtil/DbConfigurationFile.cpp @@ -197,7 +197,7 @@ osgEarth::Map* DbConfigurationFile::loadLegacyConfigFile(const std::string& file gotValidFirstLine = true; if (!map) { - map = DbConfigurationFile::createDefaultMap_(); + map = new osgEarth::Map(); map->beginUpdate(); } @@ -499,14 +499,6 @@ std::string DbConfigurationFile::findTokenValue_(const std::vector& return std::string(); } -osgEarth::Map* DbConfigurationFile::createDefaultMap_() -{ - // configure an EGM96 MSL globe.for the Map - osgEarth::Map* map = new osgEarth::Map(); - map->setProfile(osgEarth::Profile::create("wgs84", "egm96")); - return map; -} - osg::Node* DbConfigurationFile::readEarthFile(std::istream& istream, const std::string& relativeTo) { osg::ref_ptr readWrite = osgDB::Registry::instance()->getReaderWriterForExtension("earth"); diff --git a/SDK/simUtil/DbConfigurationFile.h b/SDK/simUtil/DbConfigurationFile.h index 080e1d395..f4b5d901b 100644 --- a/SDK/simUtil/DbConfigurationFile.h +++ b/SDK/simUtil/DbConfigurationFile.h @@ -114,13 +114,6 @@ class SDKUTIL_EXPORT DbConfigurationFile static std::string findTokenValue_(const std::vector& tokens, const std::string& keyword); /// convert QuadSphere levels to osgEarth levels static unsigned int getOsgEarthLevel_(unsigned int QSlevel); - - /** - * Creates a default osgEarth::Map object with the EGM96 MSL globe - * Loads parts of a legacy .txt configuration file (typically consisting of .db files) - * @return the osgEarth::Map created - */ - static osgEarth::Map* createDefaultMap_(); }; }