// -*- c++ -*- /*========================================================================= Program: Visualization Toolkit Module: pqPlotter.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /*------------------------------------------------------------------------- Copyright 2009 Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. -------------------------------------------------------------------------*/ #include "warningState.h" #include "pqPlotter.h" #include "pqSierraPlotToolsManager.h" #include "pqActiveObjects.h" #include "pqApplicationCore.h" #include "pqDataRepresentation.h" #include "pqXYChartView.h" #include "pqObjectBuilder.h" #include "pqPipelineRepresentation.h" #include "pqPipelineSource.h" #include "pqPlotVariablesDialog.h" #include "pqRenderView.h" #include #include #include "pqSierraPlotToolsUtils.h" #include "pqSMAdaptor.h" #include "pqView.h" #include #include #include #include #include #include "ui_pqSierraToolsRichTextDocs.h" #include "vtkPVArrayInformation.h" #include "vtkPVDataInformation.h" #include "vtkPVDataSetAttributesInformation.h" #include "vtkSMOutputPort.h" #include "vtkSMProperty.h" #include "vtkSMProxy.h" #include "vtkSMStringVectorProperty.h" #include "vtkSMSourceProxy.h" // used to show line number in #pragma messages #define STRING2(x) #x #define STRING(x) STRING2(x) class pqPlotter::pqInternal { public: pqInternal(); ~pqInternal(); QStringList validTensorComponentSuffixes; QStringList validSeriesComponentSuffixes; QString stripTensorComponent(QString variableAsString); QString stripSeriesComponent(QString variableAsString); QString seriesComponentSuffixString(QString variableAsString); QString tensorComponentSuffixString(QString variableAsString); QString tensorOrVectorSuffixToSeriesSuffix(QString shortVarName, QString suffix, QMap & seriesCounter); pqSierraPlotToolsUtils util; QMap > tensorLookup; QWidget *richTextDocsPlaceholder; Ui::pqSierraPlotToolsRichTextDocs richTextDocs; }; /////////////////////////////////////////////////////////////////////////////// pqPlotter::pqInternal::pqInternal() { // This widget serves no real purpose other than initializing the QTextEdit // structure created with designer that holds the Rich Text documents that // we want to be able to display (as tooltip pop-ups or whatever) in this // application at run-time this->richTextDocsPlaceholder = new QWidget(NULL); this->richTextDocs.setupUi(this->richTextDocsPlaceholder); validTensorComponentSuffixes.append("_x"); validTensorComponentSuffixes.append("_y"); validTensorComponentSuffixes.append("_z"); // The Symmetric Tensor – six components index order is defined // by the VTK Exodus reader // see vtkExodusIIReaderPrivate.h // and vtkExodusIIReader.cxx in VTK library validTensorComponentSuffixes.append("_xx"); validTensorComponentSuffixes.append("_xy"); // symetric -- could be xz, or zx, but Exodus reader stores as zx validTensorComponentSuffixes.append("_zx"); validTensorComponentSuffixes.append("_yy"); validTensorComponentSuffixes.append("_yz"); validTensorComponentSuffixes.append("_zz"); validTensorComponentSuffixes.append("_magnitude"); validSeriesComponentSuffixes.append(" (0)"); validSeriesComponentSuffixes.append(" (1)"); validSeriesComponentSuffixes.append(" (2)"); validSeriesComponentSuffixes.append(" (3)"); validSeriesComponentSuffixes.append(" (4)"); validSeriesComponentSuffixes.append(" (5)"); validSeriesComponentSuffixes.append(" (Magnitude)"); QMap tensorToSeries; tensorToSeries["_xx"] = QString(" (0)"); tensorToSeries["_yy"] = QString(" (1)"); tensorToSeries["_zz"] = QString(" (2)"); tensorToSeries["_xy"] = QString(" (3)"); tensorToSeries["_yz"] = QString(" (4)"); tensorToSeries["_zx"] = QString(" (5)"); tensorToSeries["_magnitude"] = QString(" (Magnitude)"); // The Symmetric Tensor – 6 components + 1 (magnitude) const int SYMETIC_SIX_PLUS_MAGNITUDE = 7; this->tensorLookup[SYMETIC_SIX_PLUS_MAGNITUDE] = tensorToSeries; tensorToSeries.clear(); tensorToSeries["_x"] = QString(" (0)"); tensorToSeries["_y"] = QString(" (1)"); tensorToSeries["_z"] = QString(" (2)"); tensorToSeries["_magnitude"] = QString(" (Magnitude)"); // A vector – 3 components + 1 (magnitude) const int VECTOR_PLUS_MAGNITUDE = 4; this->tensorLookup[VECTOR_PLUS_MAGNITUDE] = tensorToSeries; } /////////////////////////////////////////////////////////////////////////////// pqPlotter::pqInternal::~pqInternal() { } //----------------------------------------------------------------------------- QString pqPlotter::pqInternal::seriesComponentSuffixString(QString variableAsString) { for (int i = 0; i < this->validSeriesComponentSuffixes.size(); i++) { if (variableAsString.endsWith(this->validSeriesComponentSuffixes[i])) { return this->validSeriesComponentSuffixes[i]; } } return QString(""); } /////////////////////////////////////////////////////////////////////////////// QString pqPlotter::pqInternal::stripSeriesComponent(QString variableAsString) { QString suffixString = this->seriesComponentSuffixString(variableAsString); if (suffixString.size() > 0) { int positionToTruncate = variableAsString.size() - suffixString.size(); if (positionToTruncate > 0) { variableAsString.truncate(positionToTruncate); } } return variableAsString; } //----------------------------------------------------------------------------- QString pqPlotter::pqInternal::stripTensorComponent(QString variableAsString) { QString retString = this->util.removeAllWhiteSpace(variableAsString); QString suffixString = this->tensorComponentSuffixString(retString); if (suffixString.size() > 0) { int positionToTruncate = retString.size() - suffixString.size(); if (positionToTruncate > 0) { retString.truncate(positionToTruncate); } } return retString; } //----------------------------------------------------------------------------- QString pqPlotter::pqInternal::tensorComponentSuffixString(QString variableAsString) { for (int i = 0; i < this->validTensorComponentSuffixes.size(); i++) { if (variableAsString.endsWith(this->validTensorComponentSuffixes[i])) { return this->validTensorComponentSuffixes[i]; } } return QString(""); } //----------------------------------------------------------------------------- QString pqPlotter::pqInternal::tensorOrVectorSuffixToSeriesSuffix(QString shortVarName, QString suffix, QMap & seriesCounter) { QMap tensorToSeries; int numComponents = seriesCounter[shortVarName]; tensorToSeries = this->tensorLookup[numComponents]; QString seriesString = tensorToSeries[suffix]; return seriesString; } /////////////////////////////////////////////////////////////////////////////// pqPlotter::pqPlotter() { this->Internal = new pqPlotter::pqInternal(); } /////////////////////////////////////////////////////////////////////////////// pqPlotter::~pqPlotter() { } /////////////////////////////////////////////////////////////////////////////// QStringList pqPlotter::getTheVars(vtkSMProxy * /*meshReaderProxy*/) { QStringList theVars; theVars.clear(); return theVars; } /////////////////////////////////////////////////////////////////////////////// void pqPlotter::setDomain(plotDomain /*theDomain*/) { } /////////////////////////////////////////////////////////////////////////////// pqPlotter::plotDomain pqPlotter::getDomain() { return this->domain; } /////////////////////////////////////////////////////////////////////////////// QStringList pqPlotter::getStringsFromProperty(vtkSMProperty * prop) { QStringList theVars; theVars.clear(); vtkSMStringVectorProperty * stringVecProp = dynamic_cast(prop); if (stringVecProp != NULL) { unsigned int uNumElems = stringVecProp->GetNumberOfElements (); unsigned int i; for (i = 0; i < uNumElems; i += 2) { const char * elemPtr = stringVecProp->GetElement(i); theVars.append(QString(elemPtr)); } } return theVars; } //----------------------------------------------------------------------------- vtkPVDataSetAttributesInformation * pqPlotter::getDataSetAttributesInformation(vtkPVDataInformation * /*pvDataInfo*/) { // should never get here, but the default behaviour is... return NULL; } //----------------------------------------------------------------------------- vtkSMProperty * pqPlotter::getSMVariableProperty(vtkSMProxy * /*meshReaderProxy*/) { // should never get here, but the default behaviour is... return NULL; } //----------------------------------------------------------------------------- bool pqPlotter::amIAbleToSelectByNumber() { // should never get here, but the default behaviour is... return false; } //----------------------------------------------------------------------------- pqPipelineSource * pqPlotter::getPlotFilter() { // should never get here, but the default behaviour is... return NULL; } //----------------------------------------------------------------------------- // // NOTE: DUPLICATED METHOD (other in pqSierraPlotToolsManager) // pqPipelineSource * pqPlotter::findPipelineSource(const char *SMName) { pqApplicationCore *core = pqApplicationCore::instance(); pqServerManagerModel *smModel = core->getServerManagerModel(); QList sources = smModel->findItems(this->getActiveServer()); foreach(pqPipelineSource *s, sources) { if (strcmp(s->getProxy()->GetXMLName(), SMName) == 0) return s; } return NULL; } //----------------------------------------------------------------------------- vtkSMProperty * pqPlotter::getSMNamedVariableProperty(vtkSMProxy *meshReaderProxy, QString propName) { vtkSMProperty * prop = meshReaderProxy->GetProperty(qPrintable(propName)); if (prop == NULL) { qWarning() << "pqPlotter::getSMNamedVariableProperty; Error: property is NULL for " << propName << " in mesh reader with VTKClassName: " << meshReaderProxy->GetVTKClassName() << " And GetXMLName: " << meshReaderProxy->GetXMLName(); } return prop; } //----------------------------------------------------------------------------- // // NOTE: DUPLICATED METHOD (other in pqSierraPlotToolsManager) // pqServer * pqPlotter::getActiveServer() { pqApplicationCore *app = pqApplicationCore::instance(); pqServerManagerModel *smModel = app->getServerManagerModel(); pqServer *server = smModel->getItemAtIndex(0); return server; } //----------------------------------------------------------------------------- void pqPlotter::setVarsStatus(vtkSMProxy * /*meshReaderProxy*/, bool /*flag*/) { // should never get here, but the default behaviour is... return; } //----------------------------------------------------------------------------- void pqPlotter::setVarElementsStatus(vtkSMProperty * prop, bool flag) { if (prop != NULL) { // add variable names for all the global variables vtkSMStringVectorProperty * stringVecProp = dynamic_cast(prop); if (stringVecProp != NULL) { unsigned int uNumElems = stringVecProp->GetNumberOfElements (); unsigned int i; for (i = 0; i < uNumElems; i += 2) { # if 0 const char * elemPtr = stringVecProp->GetElement(i); const char * elemPtr_status = stringVecProp->GetElement(i+1); # endif if (flag) { stringVecProp->SetElement(i+1, "1"); } else { stringVecProp->SetElement(i+1, "0"); } } } else { // No global variables return; } } else { // error condition qWarning() << "pqPlotter::setVarElementsStatus: vtkSMProperty * prop IS NULL"; return; } } //----------------------------------------------------------------------------- void pqPlotter::setVarsActive(vtkSMProxy * /*meshReaderProxy*/, QString /*varName*/, bool /*activeFlag*/) { // should never get here, but the default behaviour is... return; } //----------------------------------------------------------------------------- void pqPlotter::setVarElementsActive(vtkSMProperty * prop, QString varName, bool activeFlag) { if (prop != NULL) { // add variable names for all the global variables vtkSMStringVectorProperty * stringVecProp = dynamic_cast(prop); //#pragma message (__FILE__ "[" STRING(__LINE__) "]: pqPlotter::setVarElementsActive: CAUTION: vtkSMStringVectorProperty * stringVecProp being used to directly update data, i.e. not using pqSMAdaptor::setElementProperty()") if (stringVecProp != NULL) { unsigned int uNumElems = stringVecProp->GetNumberOfElements (); unsigned int i; for (i = 0; i < uNumElems; i += 2) { # if 0 const char * elemPtr_status = stringVecProp->GetElement(i+1); # endif const char * elemPtr = stringVecProp->GetElement(i); QString elemStr(elemPtr); if (elemStr.compare(varName) == 0) { if (activeFlag) { stringVecProp->SetElement(i+1, "1"); } else { stringVecProp->SetElement(i+1, "0"); } break; // GET OUTTA THIS LOOP } else { //stillLooking } } } } } //----------------------------------------------------------------------------- QString pqPlotter::getFilterName() { // should never get here, but the default behaviour is... return QString(""); } //----------------------------------------------------------------------------- QMap > pqPlotter::buildNamedInputs( pqPipelineSource * meshReader, QList /*itemList*/, bool & success) { success = true; QMap > namedInputs; QList inputs; inputs.push_back(meshReader->getOutputPort(0)); namedInputs["Input"] = inputs; return namedInputs; } //----------------------------------------------------------------------------- QString pqPlotter::getNumberItemsLabel() { // should never get here, but the default behaviour is... return QString(""); } //----------------------------------------------------------------------------- vtkPVArrayInformation * pqPlotter::getArrayInformation(vtkPVDataSetAttributesInformation *) { // should never get here, but the default behaviour is... return NULL; } //----------------------------------------------------------------------------- bool pqPlotter::selectionWithinRange(QList selectedItems, pqPipelineSource * meshReader) { vtkSMProxy *meshReaderProxy = meshReader->getProxy(); vtkSMSourceProxy * sourceProxy = dynamic_cast(meshReaderProxy); if (sourceProxy != NULL) { vtkSMOutputPort * smOutputPort = sourceProxy->GetOutputPort((unsigned int)(0)); vtkPVDataInformation * pvDataInfo = smOutputPort->GetDataInformation(); if (pvDataInfo != NULL) { vtkPVDataSetAttributesInformation * pvDataSetAttributesInformation = this->getDataSetAttributesInformation(pvDataInfo); vtkPVArrayInformation * arrayInfo = this->getArrayInformation(pvDataSetAttributesInformation); if (arrayInfo != NULL) { int numComponents = arrayInfo->GetNumberOfComponents (); if (numComponents > 1) { // some sort of crazy error! qWarning() << "pqPlotter::selectionWithinRange: ERROR - array returned more than one component!"; return false; } double range[2]; arrayInfo->GetComponentRange(0, range); int rangeLow = int(range[0]); int rangeHigh = int(range[1]); int i; long int max = -1; long int min = LONG_MAX; for (i = 0; i < selectedItems.size(); i++) { int val = selectedItems[i]; if (val < min) { min = val; } if (val > max) { max = val; } } if (min >= rangeLow && max <= rangeHigh) { return true; } } } } return false; } //----------------------------------------------------------------------------- pqView * pqPlotter::findView(pqPipelineSource *source, int port, const QString &viewType) { // Step 1, try to find a view in which the source is already shown. if (source) { foreach (pqView *view, source->getViews()) { pqDataRepresentation *repr = source->getRepresentation(port, view); if (repr && repr->isVisible()) return view; } } // Step 2, check to see if the active view is the right type. pqView *view = pqActiveObjects::instance().activeView(); if (view == NULL) { qWarning() << "You have the wrong view type... a new view type needs to be created"; return NULL; } if (view->getViewType() == viewType) return view; // Step 3, check all the views and see if one is the right type and not // showing anything. pqApplicationCore *core = pqApplicationCore::instance(); pqServerManagerModel *smModel = core->getServerManagerModel(); foreach (view, smModel->findItems()) { if ( view && (view->getViewType() == viewType) && (view->getNumberOfVisibleRepresentations() < 1) ) { return view; } } // Give up. A new view needs to be created. return NULL; } //----------------------------------------------------------------------------- pqView * pqPlotter::getPlotView(pqPipelineSource * plotFilter) { return this->findView(plotFilter, 0, pqXYChartView::XYChartViewType()); } //----------------------------------------------------------------------------- pqView * pqPlotter::getMeshView(pqPipelineSource * meshReader) { if (! meshReader) { return NULL; } return this->findView(meshReader, 0, pqRenderView::renderViewType()); } //----------------------------------------------------------------------------- void pqPlotter::setDisplayOfVariables(pqPipelineSource * meshReader, const QMap & vars) { if (!meshReader) return; // Get the plot source, view, and representation. pqPipelineSource *plotFilter = this->getPlotFilter(); if (!plotFilter) return; pqView *plotView = this->getPlotView(plotFilter); if (!plotView) return; vtkSMProxy *viewProxy = plotView->getProxy(); //viewProxy->UpdateVTKObjects(); pqDataRepresentation *repr = plotFilter->getRepresentation(plotView); if (!repr) return; vtkSMProxy *reprProxy = repr->getProxy(); // Get the information property that lists all the available series (as well // as their current visibility). QList visibilityInfo = pqSMAdaptor::getMultipleElementProperty( reprProxy->GetProperty("SeriesVisibilityInfo")); QMap seriesCounter; // First find all and the number of components for (int i = 0; i < visibilityInfo.size(); i += 2) { QString varComponent = visibilityInfo[i].toString(); QString simpleVar = this->Internal->stripSeriesComponent(varComponent); seriesCounter[simpleVar]++; } QList visibility; // Iterate over all the series, turn everything off first for (int i = 0; i < visibilityInfo.size(); i += 2) { QString varComponent = visibilityInfo[i].toString(); visibility << varComponent << 0; } // now turn on the ones the user selected QList keys; keys = vars.keys(); //QMap::iterator iter = vars.begin(); QList::iterator iter = keys.begin(); while ( iter != keys.end()) { QString var = *iter; QString simpleVar = this->Internal->stripTensorComponent(var); QString seriesToShow = var; if (simpleVar != var) { QString suffix = this->Internal->tensorComponentSuffixString(var); // only get the mapping for tensors, or vectors QString seriesSuffix = this->Internal->tensorOrVectorSuffixToSeriesSuffix(simpleVar, suffix, seriesCounter); seriesToShow = simpleVar + seriesSuffix; } // now turn on this series visibility << seriesToShow << 1; iter++; } pqSMAdaptor::setMultipleElementProperty( reprProxy->GetProperty("SeriesVisibility"), visibility); reprProxy->UpdateVTKObjects(); viewProxy->UpdateVTKObjects(); } //----------------------------------------------------------------------------- void pqPlotter::popUpHelp() { } //----------------------------------------------------------------------------- QString pqPlotter::getPlotterTextEditObjectName() { // should never get here, derived classes should handle this, // but the default behaviour is... return QString(""); } //----------------------------------------------------------------------------- QString pqPlotter::getPlotterHeadingHoverText() { QString textEditObjName = this->getPlotterTextEditObjectName(); QString richText(""); QTextEdit * textEdit = this->Internal->richTextDocsPlaceholder->findChild(textEditObjName); if (textEdit != NULL) { richText = textEdit->toHtml(); } return richText; }