//
#include "SPV3D_CADSelection.h"
+#include "SPV3D_Prs.h"
#include <pqActiveObjects.h>
#include <pqRenderView.h>
-#include <pqUndoStack.h>
#include <pqCoreUtilities.h>
#include <vtkDataObject.h>
#include <vtkCollection.h>
-#include <vtkIdTypeArray.h>
-#include <vtkRenderWindowInteractor.h>
#include <vtkPVRenderView.h>
-#include <vtkPVDataInformation.h>
-#include <vtkPVArrayInformation.h>
#include <vtkPVRenderViewSettings.h>
+#include <vtkRenderWindowInteractor.h>
#include <vtkSMRenderViewProxy.h>
#include <vtkSMPropertyHelper.h>
-#include <vtkSMSelectionHelper.h>
#include <vtkSMSessionProxyManager.h>
-#include <vtkSMStringVectorProperty.h>
#include <vtkSMRepresentationProxy.h>
-#include <vtkPVDataSetAttributesInformation.h>
-#include <vtkSMSelectionHelper.h>
-#include <vtkSMOutputPort.h>
-#include <QDebug>
-#include <vtkSelectionSource.h>
-#include <vtkSelectionNode.h>
-#include <pqPVApplicationCore.h>
-#include <pqSelectionManager.h>
-#include <pqServerManagerModel.h>
-#include <vtkPVEncodeSelectionForServer.h>
-#include <vtkInformation.h>
+#include <vtkSmartPointer.h>
-#include "SPV3D_Prs.h"
+#include <QCursor>
+#include <QDebug>
-// TO REMOVE
#include <algorithm>
#include <iterator>
-#include "vtkSMProxyManager.h"
-#include <regex>
#include <set>
-#include <unordered_set>
-namespace
+
+namespace CADSelection
{
-void ReplaceString(std::string& source, const std::string& replace, const std::string& with)
+typedef std::set<std::pair<vtkIdType, vtkIdType>> SelectionValues;
+
+namespace Utilities
{
- const std::regex reg("[a-zA-Z0-9]+");
- for (auto match = std::sregex_iterator(source.begin(), source.end(), reg);
- match != std::sregex_iterator(); ++match)
- {
- if (match->str() == replace)
+//-----------------------------------------------------------------------------
+/**
+ * Create a new selection source for given selection values (process ID + array value).
+ * The values correspond to the IDs of objects being selected (solid, faces, edges, vertices).
+ * The type of object is determined by the array name (the array containing the values).
+ */
+bool SetSelectionFromValues(vtkSMRepresentationProxy* repr, const SelectionValues& values, const std::string& arrayName)
+{
+ if (repr)
+ {
+ vtkSMSessionProxyManager* pxm = repr->GetSessionProxyManager();
+ vtkSmartPointer<vtkSMProxy> newSelectionSource;
+ newSelectionSource.TakeReference(pxm->NewProxy("sources", "ValueSelectionSource"));
+ vtkSMPropertyHelper(newSelectionSource, "ArrayName").Set(arrayName.c_str());
+ vtkSMPropertyHelper(newSelectionSource, "FieldType").Set("CELL");
+ vtkSMPropertyHelper(newSelectionSource, "Values").SetNumberOfElements(values.size());
+ vtkSMPropertyHelper(newSelectionSource, "Values").RemoveAllValues();
+ for (const auto& pair: values)
{
- source.replace(match->position(), match->length(), with);
+ std::array<vtkIdType, 2> pairValues = {pair.first, pair.second};
+ vtkSMPropertyHelper(newSelectionSource, "Values").Append(pairValues.data(), 2);
}
+ newSelectionSource->UpdateVTKObjects();
+
+ vtkSMPropertyHelper(repr, "Selection").Set(newSelectionSource);
+ repr->UpdateVTKObjects();
+ return true;
}
+ return false;
}
-enum class CombineOperation
-{
- DEFAULT = 0,
- ADDITION = 1,
- SUBTRACTION = 2,
- TOGGLE = 3
-};
-const std::string SubSelectionBaseName = "s";
-bool CombineSelection(vtkSMSourceProxy* appendSelections1,
- vtkSMSourceProxy* appendSelections2, CombineOperation combineOperation, bool deepCopy)
+
+//-----------------------------------------------------------------------------
+// Get the selection values (process ID + array value) "contained" in the given selection source.
+bool GetValuesFromSelection(vtkSMProxy* selectionSourceProxy, SelectionValues& values)
{
- if (!appendSelections1 || !appendSelections2)
- {
- return false;
- }
- if (vtkSMPropertyHelper(appendSelections2, "Input").GetNumberOfElements() == 0)
- {
- return false;
- }
- if (deepCopy)
- {
- if (vtkSMPropertyHelper(appendSelections1, "Input").GetNumberOfElements() == 0)
- {
- // create a combined appendSelections which is deep copy of appendSelections2
- vtkSMSessionProxyManager* pxm = vtkSMProxyManager::GetProxyManager()->GetSessionProxyManager(
- appendSelections2->GetSession());
- vtkSmartPointer<vtkSMSourceProxy> combinedAppendSelections;
- combinedAppendSelections.TakeReference(
- vtkSMSourceProxy::SafeDownCast(pxm->NewProxy("filters", "AppendSelections")));
-
- vtkSMPropertyHelper(combinedAppendSelections, "Expression")
- .Set(vtkSMPropertyHelper(appendSelections2, "Expression").GetAsString());
- vtkSMPropertyHelper(combinedAppendSelections, "InsideOut")
- .Set(vtkSMPropertyHelper(appendSelections2, "InsideOut").GetAsInt());
-
- // add selection input and names of appendSelections2
- unsigned int numInputs =
- vtkSMPropertyHelper(appendSelections2, "Input").GetNumberOfElements();
- for (unsigned int i = 0; i < numInputs; ++i)
- {
- auto selectionSource = vtkSMPropertyHelper(appendSelections2, "Input").GetAsProxy(i);
- vtkSmartPointer<vtkSMSourceProxy> selectionSourceCopy;
- selectionSourceCopy.TakeReference(
- vtkSMSourceProxy::SafeDownCast(pxm->NewProxy("sources", selectionSource->GetXMLName())));
- selectionSourceCopy->Copy(selectionSource);
- selectionSourceCopy->UpdateVTKObjects();
-
- vtkSMPropertyHelper(combinedAppendSelections, "Input").Add(selectionSourceCopy);
- vtkSMPropertyHelper(combinedAppendSelections, "SelectionNames")
- .Set(i, vtkSMPropertyHelper(appendSelections2, "SelectionNames").GetAsString(i));
- }
- appendSelections2->Copy(combinedAppendSelections);
- appendSelections2->UpdateVTKObjects();
- return true;
- }
- }
- else
+ if (selectionSourceProxy)
{
- if (vtkSMPropertyHelper(appendSelections1, "Input").GetNumberOfElements() == 0)
+ auto allValues = vtkSMPropertyHelper(selectionSourceProxy, "Values").GetIdTypeArray();
+ for (std::size_t i = 0; i < allValues.size(); i+=2)
{
- return true;
+ values.insert(std::make_pair(allValues[i], allValues[i+1]));
}
- }
- if (combineOperation == CombineOperation::DEFAULT)
- {
return true;
}
- // appendSelections1 serves as input1 and appendSelections2 serves as input2.
- // The result of this function will be appended into appendSelections2.
-
- // The appendSelections1 is combine-able with the appendSelections2 if they have the same
- // FieldType/ElementType and if they have the same ContainingCells
- // Checking only one of the inputs is sufficient.
- vtkSMProxy* firstSelectionSourceAP1 =
- vtkSMPropertyHelper(appendSelections1, "Input").GetAsProxy(0);
- vtkSMProxy* firstSelectionSourceAP2 =
- vtkSMPropertyHelper(appendSelections2, "Input").GetAsProxy(0);
-
- // SelectionQuerySource has element type and not field type
- int fieldTypeOfFirstSelectionSourceAP1 = firstSelectionSourceAP1->GetProperty("FieldType")
- ? vtkSMPropertyHelper(firstSelectionSourceAP1, "FieldType").GetAsInt()
- : vtkSelectionNode::ConvertAttributeTypeToSelectionField(
- vtkSMPropertyHelper(firstSelectionSourceAP1, "ElementType").GetAsInt());
- int fieldTypeOfFirstSelectionSourceAP2 = firstSelectionSourceAP2->GetProperty("FieldType")
- ? vtkSMPropertyHelper(firstSelectionSourceAP2, "FieldType").GetAsInt()
- : vtkSelectionNode::ConvertAttributeTypeToSelectionField(
- vtkSMPropertyHelper(firstSelectionSourceAP2, "ElementType").GetAsInt());
- if (fieldTypeOfFirstSelectionSourceAP1 != fieldTypeOfFirstSelectionSourceAP2)
- {
- return false;
- }
-
- if (vtkSMPropertyHelper(firstSelectionSourceAP1, "ContainingCells", true).GetAsInt() !=
- vtkSMPropertyHelper(firstSelectionSourceAP2, "ContainingCells", true).GetAsInt())
- {
- return false;
- }
+ return false;
+}
- unsigned int numInputsAP1 = vtkSMPropertyHelper(appendSelections1, "Input").GetNumberOfElements();
- // find the largest selection name id of the appendSelections2
- int maxId = -1;
- for (unsigned int i = 0; i < numInputsAP1; ++i)
+//-----------------------------------------------------------------------------
+// Set the selection (described by the selection source) to the representation.
+void SetSelection(vtkSMRepresentationProxy* repr, vtkSMSourceProxy* selectionSource)
+{
+ if (repr && selectionSource)
{
- // get the selection name
- std::string selectionName =
- vtkSMPropertyHelper(appendSelections1, "SelectionNames").GetAsString(i);
- // remove the S prefix
- selectionName.erase(0, SubSelectionBaseName.size());
- // get the id
- maxId = std::max(maxId, std::stoi(selectionName));
+ selectionSource->UpdateVTKObjects();
+ vtkSMPropertyHelper(repr, "Selection").Set(selectionSource);
+ repr->UpdateVTKObjects();
}
+}
- // create new expression and selection names from appendSelections2's selections sources
- std::string newExpressionAP2 = vtkSMPropertyHelper(appendSelections2, "Expression").GetAsString();
- unsigned int numInputsAP2 = vtkSMPropertyHelper(appendSelections2, "Input").GetNumberOfElements();
- std::list<std::string> newSelectionNamesAP2;
- for (int i = static_cast<int>(numInputsAP2) - 1; i >= 0; --i)
+//-----------------------------------------------------------------------------
+// Set the preselection (described by the selection source) to the representation.
+void SetPreSelection(vtkSMRepresentationProxy* repr, vtkSMSourceProxy* selectionSource)
+{
+ if (repr && selectionSource)
{
- const std::string oldSelectionName = vtkSMPropertyHelper(appendSelections2, "SelectionNames")
- .GetAsString(static_cast<unsigned int>(i));
- std::string newSelectionName = oldSelectionName;
- // remove the S prefix
- newSelectionName.erase(0, SubSelectionBaseName.size());
- // compute new selection name id
- int selectionNameId = std::atoi(newSelectionName.c_str()) + maxId + 1;
- newSelectionName = SubSelectionBaseName + std::to_string(selectionNameId);
- // save new selection name
- newSelectionNamesAP2.push_front(newSelectionName);
- // update the expression
- ReplaceString(newExpressionAP2, oldSelectionName, newSelectionName);
+ selectionSource->UpdateVTKObjects();
+ vtkSMPropertyHelper(repr, "PreSelection").Set(selectionSource);
+ repr->UpdateVTKObjects();
}
+}
- // create a combined appendSelections
- vtkSMSessionProxyManager* pxm =
- vtkSMProxyManager::GetProxyManager()->GetSessionProxyManager(appendSelections2->GetSession());
- vtkSmartPointer<vtkSMSourceProxy> combinedAppendSelections;
- combinedAppendSelections.TakeReference(
- vtkSMSourceProxy::SafeDownCast(pxm->NewProxy("filters", "AppendSelections")));
- // add selection input and names of appendSelections1 to appendSelections2
- for (unsigned int i = 0; i < numInputsAP1; ++i)
- {
- auto selectionSource = vtkSMPropertyHelper(appendSelections1, "Input").GetAsProxy(i);
- if (deepCopy)
- {
- vtkSmartPointer<vtkSMSourceProxy> selectionSourceCopy;
- selectionSourceCopy.TakeReference(
- vtkSMSourceProxy::SafeDownCast(pxm->NewProxy("sources", selectionSource->GetXMLName())));
- selectionSourceCopy->Copy(selectionSource);
- selectionSourceCopy->UpdateVTKObjects();
- vtkSMPropertyHelper(combinedAppendSelections, "Input").Add(selectionSourceCopy);
- }
- else
- {
- vtkSMPropertyHelper(combinedAppendSelections, "Input").Add(selectionSource);
- }
- vtkSMPropertyHelper(combinedAppendSelections, "SelectionNames")
- .Set(i, vtkSMPropertyHelper(appendSelections1, "SelectionNames").GetAsString(i));
- }
- auto iter = newSelectionNamesAP2.begin();
- for (unsigned int i = 0; i < numInputsAP2; ++i, ++iter)
+//-----------------------------------------------------------------------------
+// Retrieve the selection (selection source) from the representation.
+vtkSMSourceProxy* GetSelection(vtkSMRepresentationProxy* repr)
+{
+ if (repr)
{
- auto selectionSource = vtkSMPropertyHelper(appendSelections2, "Input").GetAsProxy(i);
- if (deepCopy)
- {
- vtkSmartPointer<vtkSMSourceProxy> selectionSourceCopy;
- selectionSourceCopy.TakeReference(
- vtkSMSourceProxy::SafeDownCast(pxm->NewProxy("sources", selectionSource->GetXMLName())));
- selectionSourceCopy->Copy(selectionSource);
- selectionSourceCopy->UpdateVTKObjects();
- vtkSMPropertyHelper(combinedAppendSelections, "Input").Add(selectionSourceCopy);
- }
- else
- {
- vtkSMPropertyHelper(combinedAppendSelections, "Input").Add(selectionSource);
- }
- vtkSMPropertyHelper(combinedAppendSelections, "SelectionNames")
- .Set(numInputsAP1 + i, iter->c_str());
+ return vtkSMSourceProxy::SafeDownCast(vtkSMPropertyHelper(repr, "Selection").GetAsProxy());
}
+ return nullptr;
+}
- // add inside out qualifier to the expressions
- const int insideOutAP1 = vtkSMPropertyHelper(appendSelections1, "InsideOut").GetAsInt();
- std::string newExpressionAP1 = vtkSMPropertyHelper(appendSelections1, "Expression").GetAsString();
- if (numInputsAP1 > 1)
+//-----------------------------------------------------------------------------
+/**
+ * Remove the selection (desctrbed by the selection source) from the representation.
+ * Under the hood, this method creates an empty selection and sets it to the representation.
+ */
+void RemoveSelection(vtkSMRepresentationProxy* repr)
+{
+ if (repr)
{
- newExpressionAP1 = '(' + newExpressionAP1 + ')';
- }
- newExpressionAP1 = (insideOutAP1 ? "!" : "") + newExpressionAP1;
+ /**
+ * Under the hood, we simply add an empty selection source
+ * XXX: avoid creating a new proxy each time, and look for pre/post initialize
+ */
+ vtkSMSessionProxyManager* pxm = repr->GetSessionProxyManager();
+ vtkSmartPointer<vtkSMProxy> emptySelection;
+ emptySelection.TakeReference(pxm->NewProxy("sources", "ValueSelectionSource"));
+ emptySelection->UpdateVTKObjects();
- const int insideOutAP2 = vtkSMPropertyHelper(appendSelections2, "InsideOut").GetAsInt();
- if (numInputsAP2 > 1)
- {
- newExpressionAP2 = '(' + newExpressionAP2 + ')';
+ vtkSMPropertyHelper(repr, "Selection").Set(emptySelection);
+ repr->UpdateVTKObjects();
}
- newExpressionAP2 = (insideOutAP2 ? "!" : "") + newExpressionAP2;
+}
- // combine appendSelections1 and appendSelections2 expressions
- std::string newCombinedExpression;
- switch (combineOperation)
- {
- case CombineOperation::ADDITION:
- {
- newCombinedExpression = newExpressionAP1 + '|' + newExpressionAP2;
- break;
- }
- case CombineOperation::SUBTRACTION:
- {
- newCombinedExpression = newExpressionAP1 + "&!" + newExpressionAP2;
- break;
- }
- case CombineOperation::TOGGLE:
- default:
- {
- newCombinedExpression = newExpressionAP1 + '^' + newExpressionAP2;
- break;
- }
+//-----------------------------------------------------------------------------
+/**
+ * Remove the preselection (described by the selection source) from the representation.
+ * Under the hood, this method creates an empty selection and sets it to the representation.
+ */
+void RemovePreSelection(vtkSMRepresentationProxy* repr)
+{
+ if (repr)
+ {
+ /**
+ * Under the hood, we simply add an empty selection source
+ * XXX: avoid creating a new proxy each time, and look for pre/post initialize
+ */
+ vtkSMSessionProxyManager* pxm = repr->GetSessionProxyManager();
+ vtkSmartPointer<vtkSMProxy> emptySelection;
+ emptySelection.TakeReference(pxm->NewProxy("sources", "ValueSelectionSource"));
+ emptySelection->UpdateVTKObjects();
+
+ vtkSMPropertyHelper(repr, "PreSelection").Set(emptySelection);
+ repr->UpdateVTKObjects();
}
- vtkSMPropertyHelper(combinedAppendSelections, "Expression").Set(newCombinedExpression.c_str());
- appendSelections2->Copy(combinedAppendSelections);
- appendSelections2->UpdateVTKObjects();
- // cout << "Expression : " << newCombinedExpression << endl;
- return true;
}
-bool IgnoreSelection(
- vtkSMSourceProxy* appendSelections1, vtkSMSourceProxy* appendSelections2, bool deepCopy = false)
+} // namespace Utilities
+
+namespace Operations
{
- return CombineSelection(
- appendSelections1, appendSelections2, CombineOperation::DEFAULT, deepCopy);
-}
-bool AddSelection(
- vtkSMSourceProxy* appendSelections1, vtkSMSourceProxy* appendSelections2, bool deepCopy = false)
+//-----------------------------------------------------------------------------
+/**
+ * Return the selection values corresponding of the union of the selected values "contained"
+ * in the two selection sources. Selected values will be unique (no dupplicates).
+ */
+void Union(vtkSMProxy* selectionSourceProxy1, vtkSMProxy* selectionSourceProxy2, SelectionValues& result)
{
- return CombineSelection(
- appendSelections1, appendSelections2, CombineOperation::ADDITION, deepCopy);
+ result.clear();
+ SelectionValues values1, values2;
+ CADSelection::Utilities::GetValuesFromSelection(selectionSourceProxy1, values1);
+ CADSelection::Utilities::GetValuesFromSelection(selectionSourceProxy2, values2);
+
+ std::set_union(values1.begin(), values1.end(), values2.begin(), values2.end(), std::inserter(result, result.begin()));
}
-bool SubtractSelection(
- vtkSMSourceProxy* appendSelections1, vtkSMSourceProxy* appendSelections2, bool deepCopy = false)
+
+//-----------------------------------------------------------------------------
+/**
+ * Return the selection values corresponding of the difference of the selected values "contained"
+ * in the two selection sources. Selected values will be unique (no dupplicates).
+ */
+void Difference(vtkSMProxy* selectionSourceProxy1, vtkSMProxy* selectionSourceProxy2, SelectionValues& result)
{
- return CombineSelection(
- appendSelections1, appendSelections2, CombineOperation::SUBTRACTION, deepCopy);
+ result.clear();
+ SelectionValues values1, values2;
+ CADSelection::Utilities::GetValuesFromSelection(selectionSourceProxy1, values1);
+ CADSelection::Utilities::GetValuesFromSelection(selectionSourceProxy2, values2);
+
+ std::set_difference(values1.begin(), values1.end(), values2.begin(), values2.end(), std::inserter(result, result.begin()));
}
-bool ToggleSelection(
- vtkSMSourceProxy* appendSelections1, vtkSMSourceProxy* appendSelections2, bool deepCopy = false)
+
+//-----------------------------------------------------------------------------
+/**
+ * Return the selection values corresponding of the symmetric difference of the selected values
+ * "contained" in the two selection sources. Selected values will be unique (no dupplicates).
+ */
+void SymmetricDifference(vtkSMProxy* selectionSourceProxy1, vtkSMProxy* selectionSourceProxy2, SelectionValues& result)
{
- return CombineSelection(
- appendSelections1, appendSelections2, CombineOperation::TOGGLE, deepCopy);
-}
+ result.clear();
+ SelectionValues values1, values2;
+ CADSelection::Utilities::GetValuesFromSelection(selectionSourceProxy1, values1);
+ CADSelection::Utilities::GetValuesFromSelection(selectionSourceProxy2, values2);
+
+ std::set_symmetric_difference(values1.begin(), values1.end(), values2.begin(), values2.end(), std::inserter(result, result.begin()));
}
+} // namespace Operations
+} // namespace CADSelection
//-----------------------------------------------------------------------------
-SPV3D_CADSelection::SPV3D_CADSelection(QObject *parent,
- pqRenderView* view, SelectionMode mode):QObject(parent)
+SPV3D_CADSelection::SPV3D_CADSelection(QObject *parent, pqRenderView* view, SelectionMode mode)
+ : QObject(parent), View(view)
{
- this->View = view;
- this->Mode = mode;
- this->PreviousRenderViewMode = -1;
- this->MousePosition[0] = 0;
- this->MousePosition[1] = 0;
- //this->selectionComboBox = comboBox;
+ // Initialize the selection mode and the observers
+ this->SetMode(mode);
for (size_t i = 0; i < sizeof(this->ObserverIds) / sizeof(this->ObserverIds[0]); ++i)
{
this->ObserverIds[i] = 0;
}
- //QObject::connect(button, SIGNAL(toggled(bool)), this, SLOT(actionTriggered(bool)));
-
// if view == nullptr, we track the active view.
if (view == nullptr)
{
QObject::connect(
- &pqActiveObjects::instance(), SIGNAL(viewChanged(pqView*)), this, SLOT(setView(pqView*)));
- // this ensure that the enabled-state is set correctly.
- this->setView(nullptr);
+ &pqActiveObjects::instance(), &pqActiveObjects::viewChanged, this, &SPV3D_CADSelection::setView);
}
- this->setRepresentation(nullptr);
QObject::connect(&pqActiveObjects::instance(),
- SIGNAL(representationChanged(pqDataRepresentation*)), this,
- SLOT(setRepresentation(pqDataRepresentation*)));
+ QOverload<pqDataRepresentation*>::of(&pqActiveObjects::representationChanged), this, &SPV3D_CADSelection::setRepresentation);
+ // This info may be useful in vtkSMRenderViewProxy::MarkDirty
vtkPVRenderViewSettings::GetInstance()->SetEnableFastPreselection(true);
-
- this->updateEnableState();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void SPV3D_CADSelection::SetMode(const SPV3D_CADSelection::SelectionMode mode)
{
- this->Mode = mode;
-}
-
-//-----------------------------------------------------------------------------
-void SPV3D_CADSelection::updateEnableState()
-{
- this->endSelection();
-
- //auto paction = this->parentAction();
- //bool state = false;
- if (this->Representation)
+ // Set the array containing the values describing the entities (solid, faces, etc.).
+ switch (mode)
{
- vtkSMProxy* proxy = this->Representation->getProxy();
- vtkSMStringVectorProperty* prop =
- vtkSMStringVectorProperty::SafeDownCast(proxy->GetProperty("ColorArrayName"));
- if (prop)
- {
- int association = std::atoi(prop->GetElement(3));
- const char* arrayName = prop->GetElement(4);
-
- vtkPVDataInformation* dataInfo = this->Representation->getInputDataInformation();
-
- vtkPVDataSetAttributesInformation* info = nullptr;
- if (association == vtkDataObject::CELL &&
- this->Mode == SELECT_FACES)
- {
- info = dataInfo->GetCellDataInformation();
- }
- if (association == vtkDataObject::POINT &&
- this->Mode == SELECT_VERTICES)
- {
- info = dataInfo->GetPointDataInformation();
- }
-
- if (info)
- {
- /*vtkPVArrayInformation* arrayInfo = */info->GetArrayInformation(arrayName);
- //state = arrayInfo && arrayInfo->GetDataType() == VTK_ID_TYPE;
- }
- }
+ case SELECT_VERTICES:
+ this->SelectionArrayName = "Vertex id";
+ break;
+ case SELECT_EDGES:
+ this->SelectionArrayName = "Edge id";
+ break;
+ case SELECT_FACES:
+ this->SelectionArrayName = "Face id";
+ break;
+ case SELECT_SOLIDS:
+ default:
+ this->SelectionArrayName = "Solid id";
+ break;
}
- //paction->setEnabled(state);
}
//-----------------------------------------------------------------------------
{
// if we were currently in selection, finish that before changing the view.
this->endSelection();
+ this->View = qobject_cast<pqRenderView*>(view);
}
-
- this->View = qobject_cast<pqRenderView*>(view);
-
- // update enable state.
- //this->parentAction()->setEnabled(this->View != nullptr);
}
//-----------------------------------------------------------------------------
{
// if we are currently in selection, finish that before changing the representation.
this->endSelection();
-
- if (this->Representation != nullptr)
- {
- QObject::disconnect(this->RepresentationConnection);
- }
-
this->Representation = representation;
-
- if (this->Representation != nullptr)
- {
- this->RepresentationConnection = this->connect(
- this->Representation, SIGNAL(colorArrayNameModified()), SLOT(updateEnableState()));
- }
-
- // update enable state.
- this->updateEnableState();
}
}
return;
}
- //QAction* actn = this->parentAction();
- //if (actn->isCheckable())
- {
- //this->selectionComboBox->setEnabled(false);
-
- vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
- vtkSMPropertyHelper(rmp, "InteractionMode").Get(&this->PreviousRenderViewMode);
-
- //QString currentPrimitive = this->selectionComboBox->currentText();
- pqCoreUtilities::promptUser("SPV3D_CADSelection", QMessageBox::Information,
- "Interactive Selection Information",
- "You are entering interactive selection mode to highlight.\n"
- "Move the mouse point over the dataset to interactively highlight elements.\n\n"
- "Press Ctrl + click to add the currently highlighted element.\n"
- "Press Shift + click to remove the element.\n\n"
- "Click on Select button to exit this mode.",
- QMessageBox::Ok | QMessageBox::Save);
- this->View->setCursor(Qt::CrossCursor);
- vtkSMPropertyHelper(rmp, "InteractionMode").Set(vtkPVRenderView::INTERACTION_MODE_SELECTION);
-
- rmp->UpdateVTKObjects();
-
- // Setup observer.
- assert(this->ObserverIds[0] == 0 && this->ObservedObject == nullptr && this->ObserverIds[1] == 0);
- this->ObservedObject = rmp->GetInteractor();
- this->ObserverIds[0] = this->ObservedObject->AddObserver(
- vtkCommand::MouseMoveEvent, this, &SPV3D_CADSelection::onMouseMove);
- this->ObserverIds[1] = this->ObservedObject->AddObserver(vtkCommand::LeftButtonReleaseEvent,
- this, &SPV3D_CADSelection::onLeftButtonRelease);
- this->ObserverIds[2] = this->ObservedObject->AddObserver(vtkCommand::RightButtonPressEvent,
- this, &SPV3D_CADSelection::onRightButtonPress);
- this->ObserverIds[3] = this->ObservedObject->AddObserver(vtkCommand::RightButtonReleaseEvent,
- this, &SPV3D_CADSelection::onRightButtonRelease);
-
- //this->parentAction()->setChecked(true);
- }
+ // Save the current interaction mode to restore it when selection ends
+ vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
+ vtkSMPropertyHelper(rmp, "InteractionMode").Get(&this->PreviousInteractionMode);
+
+ pqCoreUtilities::promptUser("SPV3D_CADSelection", QMessageBox::Information,
+ "Interactive Selection Information",
+ "You are entering interactive selection mode to highlight.\n"
+ "Move the mouse point over the dataset to interactively highlight elements.\n\n"
+ "Press Ctrl + click to add the currently highlighted element.\n"
+ "Press Shift + click to remove the element.\n\n"
+ "Click on Select button to exit this mode.",
+ QMessageBox::Ok | QMessageBox::Save);
+ this->View->setCursor(Qt::CrossCursor);
+ vtkSMPropertyHelper(rmp, "InteractionMode").Set(vtkPVRenderView::INTERACTION_MODE_SELECTION);
+
+ rmp->UpdateVTKObjects();
+
+ // Setup observers.
+ assert(this->ObserverIds[0] == 0 && this->ObservedObject == nullptr && this->ObserverIds[1] == 0);
+ this->ObservedObject = rmp->GetInteractor();
+ this->ObserverIds[0] = this->ObservedObject->AddObserver(
+ vtkCommand::MouseMoveEvent, this, &SPV3D_CADSelection::onMouseMove);
+ this->ObserverIds[1] = this->ObservedObject->AddObserver(vtkCommand::LeftButtonReleaseEvent,
+ this, &SPV3D_CADSelection::onLeftButtonRelease);
+ this->ObserverIds[2] = this->ObservedObject->AddObserver(vtkCommand::RightButtonPressEvent,
+ this, &SPV3D_CADSelection::onRightButtonPress);
+ this->ObserverIds[3] = this->ObservedObject->AddObserver(vtkCommand::RightButtonReleaseEvent,
+ this, &SPV3D_CADSelection::onRightButtonRelease);
}
//-----------------------------------------------------------------------------
void SPV3D_CADSelection::endSelection()
{
- cout << "End Selection " << endl;
if (!this->View)
{
return;
}
- if (this->PreviousRenderViewMode == -1)
+ if (this->PreviousInteractionMode == -1)
{
return;
}
- //QAction* actn = this->parentAction();
- //if (actn->isCheckable())
- {
- vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
- vtkSMPropertyHelper(rmp, "InteractionMode").Set(this->PreviousRenderViewMode);
- this->PreviousRenderViewMode = -1;
- rmp->UpdateVTKObjects();
- this->View->setCursor(QCursor());
- this->cleanupObservers();
- //this->parentAction()->setChecked(false);
-
- if (this->CurrentRepresentation != nullptr)
- {
- cout << "???" << endl;
- vtkSMSessionProxyManager* pxm = rmp->GetSessionProxyManager();
- vtkSMProxy* emptySel = pxm->NewProxy("sources", "IDSelectionSource");
-
- this->CurrentRepresentation->UpdateVTKObjects();
- this->CurrentRepresentation = nullptr;
- emptySel->Delete();
-
- rmp->StillRender();
- }
-
- //this->selectionComboBox->setEnabled(true);
- }
+ // Restore the previous interaction mode and cursor
+ vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
+ vtkSMPropertyHelper(rmp, "InteractionMode").Set(this->PreviousInteractionMode);
+ this->PreviousInteractionMode = -1;
+ rmp->UpdateVTKObjects();
+ this->View->setCursor(QCursor());
+ this->cleanupObservers();
}
//-----------------------------------------------------------------------------
void SPV3D_CADSelection::onMouseMove()
{
- if (!this->DisablePreSelection && vtkPVRenderViewSettings::GetInstance()->GetEnableFastPreselection())
+ if (!this->DisablePreSelection)
{
- this->fastPreSelection();
- }
-
- // get preselected id here
- vtkSMProxy* proxyRepresentation = this->Representation->getProxy();
- if (!proxyRepresentation)
- {
- qWarning()<< "There is no representation in the active view for the Geometry Source.";
- return;
- }
-
-
- // Retrieve the wanted information property
- vtkSMProperty* PreselectedIDProperty =
- proxyRepresentation->GetProperty("PreSelectedID");
- if (!PreselectedIDProperty)
- {
- qWarning()<< "The representation named '" << proxyRepresentation->GetXMLName()<< "' didn't have a property named 'PreSelectedID'.";
- return;
+ this->preSelect();
}
-
- // Force to update the information property
- proxyRepresentation->UpdatePropertyInformation(PreselectedIDProperty);
-
- vtkIdType PreSelectedID =
- vtkSMPropertyHelper(proxyRepresentation,"PreSelectedID").GetAsInt(0);
- qInfo() << "entry from client: "<< SPV3D_Prs::FromVtkIdToEntry(PreSelectedID).c_str();
-
}
//-----------------------------------------------------------------------------
void SPV3D_CADSelection::onLeftButtonRelease()
{
- if (vtkPVRenderViewSettings::GetInstance()->GetEnableFastPreselection())
- {
- this->fastSelection();
- }
+ this->select();
emit selectionChanged();
}
this->DisablePreSelection = false;
}
-namespace SelectionUtilities
-{
-//-----------------------------------------------------------------------------
-bool SetSelectionFromValues(vtkSMRepresentationProxy* repr, const std::set<std::pair<vtkIdType, vtkIdType>>& values)
-{
- vtkSMSessionProxyManager* pxm = repr->GetSessionProxyManager();
- vtkSmartPointer<vtkSMProxy> newSelectionSource;
- newSelectionSource.TakeReference(pxm->NewProxy("sources", "ValueSelectionSource"));
- vtkSMPropertyHelper(newSelectionSource, "ArrayName").Set("Solid id");
- vtkSMPropertyHelper(newSelectionSource, "FieldType").Set("CELL");
- vtkSMPropertyHelper(newSelectionSource, "Values").SetNumberOfElements(values.size());
- vtkSMPropertyHelper(newSelectionSource, "Values").RemoveAllValues();
- for (const auto& pair: values)
- {
- std::array<vtkIdType, 2> pairValues = {pair.first, pair.second};
- vtkSMPropertyHelper(newSelectionSource, "Values").Append(pairValues.data(), 2);
- }
- newSelectionSource->UpdateVTKObjects();
-
- vtkSMPropertyHelper(repr, "Selection").Set(newSelectionSource);
- repr->UpdateVTKObjects();
- return true;
-}
-
//-----------------------------------------------------------------------------
-void SetSelection(vtkSMRepresentationProxy* repr, vtkSMSourceProxy* selectionSource)
-{
- selectionSource->UpdateVTKObjects();
-
- vtkSMPropertyHelper(repr, "Selection").Set(selectionSource);
- repr->UpdateVTKObjects();
-}
-
-//-----------------------------------------------------------------------------
-void RemoveSelection(vtkSMRepresentationProxy* repr)
-{
- // Under the hood, we simply add an empty selection source
- vtkSMSessionProxyManager* pxm = repr->GetSessionProxyManager();
- vtkSmartPointer<vtkSMProxy> emptySelection;
- emptySelection.TakeReference(pxm->NewProxy("sources", "ValueSelectionSource"));
- emptySelection->UpdateVTKObjects();
-
- vtkSMPropertyHelper(repr, "Selection").Set(emptySelection);
- repr->UpdateVTKObjects();
-}
-
-//-----------------------------------------------------------------------------
-bool GetSelectionValues(vtkSMProxy* selectionSourceProxy, std::set<std::pair<vtkIdType, vtkIdType>>& values)
-{
- if (selectionSourceProxy)
- {
- auto allValues = vtkSMPropertyHelper(selectionSourceProxy, "Values").GetIdTypeArray();
- for (int i = 0; i < allValues.size(); i+=2) // skip process ids
- {
- values.insert(std::make_pair(allValues[i], allValues[i+1]));
- }
- return true;
- }
- return false;
-}
-}
-
-namespace SelectionOperations
-{
-//-----------------------------------------------------------------------------
-void Union(vtkSMProxy* selectionSourceProxy1, vtkSMProxy* selectionSourceProxy2, std::set<std::pair<vtkIdType, vtkIdType>>& result)
-{
- result.clear();
- std::set<std::pair<vtkIdType, vtkIdType>> values1, values2;
- SelectionUtilities::GetSelectionValues(selectionSourceProxy1, values1);
- SelectionUtilities::GetSelectionValues(selectionSourceProxy2, values2);
-
- std::set_union(values1.begin(), values1.end(), values2.begin(), values2.end(), std::inserter(result, result.begin()));
-}
-
-//-----------------------------------------------------------------------------
-void Difference(vtkSMProxy* selectionSourceProxy1, vtkSMProxy* selectionSourceProxy2, std::set<std::pair<vtkIdType, vtkIdType>>& result)
-{
- result.clear();
- std::set<std::pair<vtkIdType, vtkIdType>> values1, values2;
- SelectionUtilities::GetSelectionValues(selectionSourceProxy1, values1);
- SelectionUtilities::GetSelectionValues(selectionSourceProxy2, values2);
-
- std::set_difference(values1.begin(), values1.end(), values2.begin(), values2.end(), std::inserter(result, result.begin()));
-}
-
-//-----------------------------------------------------------------------------
-void SymmetricDifference(vtkSMProxy* selectionSourceProxy1, vtkSMProxy* selectionSourceProxy2, std::set<std::pair<vtkIdType, vtkIdType>>& result)
-{
- result.clear();
- std::set<std::pair<vtkIdType, vtkIdType>> values1, values2;
- SelectionUtilities::GetSelectionValues(selectionSourceProxy1, values1);
- SelectionUtilities::GetSelectionValues(selectionSourceProxy2, values2);
-
- std::set_symmetric_difference(values1.begin(), values1.end(), values2.begin(), values2.end(), std::inserter(result, result.begin()));
-}
-}
-
-//-----------------------------------------------------------------------------
-void SPV3D_CADSelection::fastSelection()
-{
+bool SPV3D_CADSelection::hardwareSelect(vtkCollection* selectedRepresentations, vtkCollection* selectionSources)
+{
+ /**
+ * Perform the hardware selection, i.e. the first step in the selection mechanism of ParaView.
+ * Under the hood, a dedicated render pass will be executed, displaying the values contained in the
+ * selection array (identified by this->SelectionArrayName) at each cell. Then, the value of the cell
+ * under the cursor will be retrieved. This value will be used to retrieve all the cells sharing it
+ * in the CADMapper (second step of the selection mechanism).
+ *
+ * The selectedRepresentation will contain the selected representation proxy (i.e. representation proxy
+ * of the selected vtk object) and a selection source proxy. The selection source is a vtk source used to
+ * generate a vtkSelection. In the SPV3D_CADSelection, we only manipulate vtkPVSelectionSource proxies to
+ * keep track of the selection on the server side. This proxy notably allow to directly access the selected
+ * value(s) through the "Values" property (see ValueSelectionSource in extraction_filter.xml).
+ *
+ * For now, since we do not support yet the selection by rubber band or frustum, only one cell will be
+ * hardware selected at once. This means only one representation and selection source (containing an
+ * unique value) will be returned each time hardwareSelect is called.
+ */
vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
assert(rmp != nullptr);
int region[4] = { x, y, x, y };
// Do the selection on the current region (client side)
+ return rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, this->SelectionArrayName.c_str());
+}
+
+//-----------------------------------------------------------------------------
+void SPV3D_CADSelection::select()
+{
+ // Do hardware selection:
+ // - selectionSources will contain the selection source containing the selection values
+ // - selectionRepresentations will contain the representation of the vtk data object being selected
vtkNew<vtkCollection> selectedRepresentations;
vtkNew<vtkCollection> selectionSources;
- bool status = false;
- switch (this->Mode)
- {
- case SELECT_SOLIDS:
- status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Solid id");
- break;
- case SELECT_FACES:
- status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Face id");
- break;
- case SELECT_EDGES:
- status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Edge id");
- break;
- case SELECT_VERTICES:
- status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Vertex id");
- break;
- default:
- qCritical("Invalid call to SPV3D_CADSelection::fastSelection");
- return;
- }
-
- vtkSMRepresentationProxy* repr =
- vtkSMRepresentationProxy::SafeDownCast(selectedRepresentations->GetItemAsObject(0));
+ bool isSomethingSelected = this->hardwareSelect(selectedRepresentations, selectionSources);
- // If something has been preselected or selected
- if (status)
+ if (isSomethingSelected)
{
- // If the selection occurs on a new represention, clean the selection on the
- // current representation before continuing
- if (this->CurrentRepresentation != nullptr && repr != this->CurrentRepresentation)
+ // We only select one object at once, so we always have only one representation and one selection source
+ vtkSMRepresentationProxy* repr =
+ vtkSMRepresentationProxy::SafeDownCast(selectedRepresentations->GetItemAsObject(0));
+ vtkSMSourceProxy* selection = vtkSMSourceProxy::SafeDownCast(selectionSources->GetItemAsObject(0));
+
+ /**
+ * If the selection occurs on a new represention (new vtk data object), clean the selection on the
+ * current representation before continuing
+ */
+ if (repr != this->CurrentRepresentation)
{
- SelectionUtilities::RemoveSelection(this->CurrentRepresentation);
+ CADSelection::Utilities::RemoveSelection(this->CurrentRepresentation);
+ this->CurrentRepresentation = repr;
}
- this->CurrentRepresentation = repr;
-
- // Set the selection (selection source) to the current representation
- vtkSMSourceProxy* currentSelection = vtkSMSourceProxy::SafeDownCast(vtkSMPropertyHelper(repr, "Selection").GetAsProxy());
-
- vtkSMSourceProxy* newSelection = vtkSMSourceProxy::SafeDownCast(selectionSources->GetItemAsObject(0));
- // vtkSmartPointer<vtkSMSourceProxy> newAppendSelections;
- // newAppendSelections.TakeReference(vtkSMSourceProxy::SafeDownCast(
- // vtkSMSelectionHelper::NewAppendSelectionsFromSelectionSource(selectionSource)));
-
+ // Get the current selection source attached to the representation (if any)
+ vtkSMSourceProxy* currentSelection = CADSelection::Utilities::GetSelection(repr);
+
+ /**
+ * Combine the new selection with the current one, depending on the selection modifier
+ *
+ * XXX: If the approach of combining selection values directly shows limitations in
+ * the future, we can considerate using a vtkAppendSelection filter to do it instead
+ * (see pqRenderView::collectSelectionPorts method). However, since in our case we
+ * don't do selection extraction but display it directly with the vtkCADMapper, we
+ * need to add support for selection expressions in this mapper.
+ */
switch (this->getSelectionModifier())
{
- case pqView::PV_SELECTION_ADDITION:
- {
- std::set<std::pair<vtkIdType, vtkIdType>> values;
- SelectionOperations::Union(currentSelection, newSelection, values);
- SelectionUtilities::SetSelectionFromValues(repr, values);
- break;
- }
- case pqView::PV_SELECTION_SUBTRACTION:
- {
- std::set<std::pair<vtkIdType, vtkIdType>> values;
- SelectionOperations::Difference(currentSelection, newSelection, values);
- SelectionUtilities::SetSelectionFromValues(repr, values);
- break;
- }
- case pqView::PV_SELECTION_TOGGLE:
- {
- std::set<std::pair<vtkIdType, vtkIdType>> values;
- SelectionOperations::SymmetricDifference(currentSelection, newSelection, values);
- SelectionUtilities::SetSelectionFromValues(repr, values);
- break;
- }
- case pqView::PV_SELECTION_DEFAULT:
- default:
- // Just keep the current selection
- SelectionUtilities::SetSelection(repr, newSelection);
- break;
+ case pqView::PV_SELECTION_ADDITION:
+ {
+ CADSelection::SelectionValues values;
+ CADSelection::Operations::Union(currentSelection, selection, values);
+ CADSelection::Utilities::SetSelectionFromValues(repr, values, this->SelectionArrayName);
+ break;
+ }
+ case pqView::PV_SELECTION_SUBTRACTION:
+ {
+ CADSelection::SelectionValues values;
+ CADSelection::Operations::Difference(currentSelection, selection, values);
+ CADSelection::Utilities::SetSelectionFromValues(repr, values, this->SelectionArrayName);
+ break;
+ }
+ case pqView::PV_SELECTION_TOGGLE:
+ {
+ CADSelection::SelectionValues values;
+ CADSelection::Operations::SymmetricDifference(currentSelection, selection, values);
+ CADSelection::Utilities::SetSelectionFromValues(repr, values, this->SelectionArrayName);
+ break;
+ }
+ case pqView::PV_SELECTION_DEFAULT:
+ default:
+ // No modifier, so just keep the current selection
+ CADSelection::Utilities::SetSelection(repr, selection);
+ break;
}
- // vtkSMPropertyHelper(repr, "Selection").Set(newAppendSelections);
- // repr->UpdateVTKObjects();
}
else if (this->CurrentRepresentation != nullptr)
{
// If nothing has been selected then clean current representation
- // with an "empty" selection source
- SelectionUtilities::RemoveSelection(repr);
+ CADSelection::Utilities::RemoveSelection(this->CurrentRepresentation);
}
+ // XXX: improve this to avoid double render
this->View->forceRender();
this->View->forceRender();
- // TODO improve this to avoid double render
}
//-----------------------------------------------------------------------------
-void SPV3D_CADSelection::fastPreSelection()
+void SPV3D_CADSelection::preSelect()
{
- vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
- assert(rmp != nullptr);
-
- int x = rmp->GetInteractor()->GetEventPosition()[0];
- int y = rmp->GetInteractor()->GetEventPosition()[1];
- this->MousePosition[0] = x;
- this->MousePosition[1] = y;
-
- int region[4] = { x, y, x, y };
-
- // Do the selection on the current region (client side)
+ // Do hardware selection:
+ // - selectionSources will contain the selection source containing the selection values
+ // - selectionRepresentations will contain the representation of the entity being selected
vtkNew<vtkCollection> selectedRepresentations;
vtkNew<vtkCollection> selectionSources;
- bool status = false;
- switch (this->Mode)
- {
- case SELECT_SOLIDS:
- status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Solid id");
- break;
- case SELECT_FACES:
- status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Face id");
- break;
- case SELECT_EDGES:
- status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Edge id");
- break;
- case SELECT_VERTICES:
- status = rmp->SelectSurfaceCells(region, selectedRepresentations, selectionSources, false, 0, false, "Vertex id");
- break;
- default:
- qCritical("Invalid call to SPV3D_CADSelection::fastSelection");
- return;
- }
-
- vtkSMRepresentationProxy* repr =
- vtkSMRepresentationProxy::SafeDownCast(selectedRepresentations->GetItemAsObject(0));
+ bool isSomethingSelected = this->hardwareSelect(selectedRepresentations, selectionSources);
- // If something has been preselected or selected
- if (status)
+ if (isSomethingSelected)
{
+ // We only select one object at once, so we always have only one representation and one selection source
+ vtkSMRepresentationProxy* repr =
+ vtkSMRepresentationProxy::SafeDownCast(selectedRepresentations->GetItemAsObject(0));
+ vtkSMSourceProxy* selection = vtkSMSourceProxy::SafeDownCast(selectionSources->GetItemAsObject(0));
+
// If the selection occurs on a new represention, clean the selection on the
// current representation before continuing
- if (this->CurrentRepresentation != nullptr && repr != this->CurrentRepresentation)
+ if (repr != this->CurrentRepresentation)
{
- vtkSMSessionProxyManager* pxm = repr->GetSessionProxyManager();
- vtkSMProxy* emptySel = pxm->NewProxy("sources", "IDSelectionSource");
-
- vtkSMPropertyHelper(this->CurrentRepresentation, "PreSelection").Set(emptySel);
- this->CurrentRepresentation->UpdateVTKObjects();
- emptySel->Delete();
+ CADSelection::Utilities::RemovePreSelection(this->CurrentRepresentation);
+ this->CurrentRepresentation = repr;
}
- this->CurrentRepresentation = repr;
-
- // Set the selection (selection source) to the current representation
- // TODO: There should be some cases where we append instead. Which ones ? When a modifier is pressed ? (i.e. the Control Key)
- vtkSMSourceProxy* sel = vtkSMSourceProxy::SafeDownCast(selectionSources->GetItemAsObject(0));
- vtkSMPropertyHelper(repr, "PreSelection").Set(sel);
- repr->UpdateVTKObjects();
+ // Set the preselection
+ CADSelection::Utilities::SetPreSelection(repr, selection);
}
-
- // If nothing has been selected then clean current representation
- // with an "empty" selection source
else if (this->CurrentRepresentation != nullptr)
{
- vtkSMSessionProxyManager* pxm = rmp->GetSessionProxyManager();
- vtkSMProxy* emptySel = pxm->NewProxy("sources", "IDSelectionSource");
-
- vtkSMPropertyHelper(this->CurrentRepresentation, "PreSelection").Set(emptySel);
- this->CurrentRepresentation->UpdateVTKObjects();
- this->CurrentRepresentation = nullptr;
- emptySel->Delete();
+ // If nothing has been selected then clean current representation
+ CADSelection::Utilities::RemovePreSelection(this->CurrentRepresentation);
}
+ // XXX: improve this to avoid double render
this->View->forceRender();
this->View->forceRender();
- // TODO improve this to avoid double render
-}
-
-//-----------------------------------------------------------------------------
-void SPV3D_CADSelection::selectionChanged(vtkObject*, unsigned long, void* calldata)
-{
- BEGIN_UNDO_EXCLUDE();
-
- cout << "Selection changed: should not enter there !" << endl;
-
- int selectionModifier = this->getSelectionModifier();
- int* region = reinterpret_cast<int*>(calldata);
-// Simple version check to change once 5.10 support is dropped
- this->View->selectCellsOnSurface(region, selectionModifier);
- //this->View->selectOnSurface(region, selectionModifier);
- END_UNDO_EXCLUDE();
-
- // this->endSelection();
}
//-----------------------------------------------------------------------------
int SPV3D_CADSelection::getSelectionModifier()
{
- int selectionModifier = pqView::PV_SELECTION_DEFAULT;//this->Superclass::getSelectionModifier();
+ // Similar to pqRenderViewSelectionReaction::getSelectionModifier()
+ int selectionModifier = pqView::PV_SELECTION_DEFAULT;
vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
assert(rmp != nullptr);
- bool ctrl = rmp->GetInteractor()->GetControlKey() == 1;
- bool shift = rmp->GetInteractor()->GetShiftKey() == 1;
- // selectionModifier = pqView::PV_SELECTION_TOGGLE;
+ const bool ctrl = rmp->GetInteractor()->GetControlKey() == 1;
+ const bool shift = rmp->GetInteractor()->GetShiftKey() == 1;
- if (ctrl)
+ if (ctrl && shift)
+ {
+ selectionModifier = pqView::PV_SELECTION_TOGGLE;
+ }
+ else if (ctrl)
{
selectionModifier = pqView::PV_SELECTION_ADDITION;
}
//-----------------------------------------------------------------------------
std::set<std::string> SPV3D_CADSelection::GetSelectedObEntry()
{
- // std::cout << "Get Selected Ob Entry" << std::endl;
std::set<std::string> EntryList;
- // get preselected id here
if (this->Representation == nullptr)
{
return EntryList;
vtkSMProxy* proxyRepresentation = this->Representation->getProxy();
if (!proxyRepresentation)
{
- qWarning()<< "There is no representation in the active view for the Geometry Source.";
+ qWarning() << "There is no representation in the active view for the Geometry Source.";
return EntryList;
}
- vtkSMProxy* selInfo = vtkSMPropertyHelper(proxyRepresentation, "Selection").GetAsProxy(0);
- if (selInfo)
+ /**
+ * Retrieve the selection source currently attached to the active representation, and
+ * retrieve all the selected values (process ID + value) from it.
+ *
+ * XXX: since the EntryList cannot store the process IDs (at least for now), we need
+ * to drop them here. In order to eventually support the multi-process selection in the
+ * future, we will need to rework this to store this info.
+ */
+ vtkSMProxy* selection = vtkSMPropertyHelper(proxyRepresentation, "Selection").GetAsProxy(0);
+ if (selection)
{
- auto ids = vtkSMPropertyHelper(selInfo, "Values").GetIdTypeArray();
- for (const auto id : ids)
+ auto ids = vtkSMPropertyHelper(selection, "Values").GetIdTypeArray();
+
+ // Values came by pair of (process ID, value); drop the process ID.
+ for (std::size_t i = 1; i < ids.size(); i+=2)
{
- // cout << "Values : " << id << endl;
- EntryList.insert(SPV3D_Prs::FromVtkIdToEntry(id));
+ EntryList.insert(SPV3D_Prs::FromVtkIdToEntry(ids[i]));
}
}
}
//-----------------------------------------------------------------------------
-// TODO: Prefer passing parameters by const ref rather than by copy
-void SPV3D_CADSelection::SetSelectionFromEntrySet(std::set<std::string> EntryList)
+void SPV3D_CADSelection::SetSelectionFromEntrySet(const std::set<std::string>& EntryList)
{
- if (this->Representation == nullptr) {
+ if (this->Representation == nullptr)
+ {
qWarning() << "There is no pqDataRepresentation";
return;
}
- vtkSMProxy* proxyRepresentation = this->Representation->getProxy();
+ vtkSMRepresentationProxy* proxyRepresentation = vtkSMRepresentationProxy::SafeDownCast(this->Representation->getProxy());
if (!proxyRepresentation)
{
qWarning() << "There is no representation";
return;
}
- // this->View->forceRender();
-
- // proxyRepresentation->InvokeCommand("BeginSelect");
-
- // Create a new selection source on the server side and its proxy on the client side
- vtkSMRenderViewProxy* rmp = this->View->getRenderViewProxy();
- vtkSMSessionProxyManager* pxm = rmp->GetSessionProxyManager();
- vtkSMProxy* selectionSource = pxm->NewProxy("sources", "ValueSelectionSource");
- vtkSMPropertyHelper(selectionSource, "ArrayName").Set("Solid id");
- vtkSMPropertyHelper(selectionSource, "FieldType").Set("CELL");
- vtkSMPropertyHelper(selectionSource, "Values").SetNumberOfElements(EntryList.size());
-
- // TODO: How do i get that properly ?
- vtkIdType processNumber = 0;
-
- // Retrieve entry ids and put them in a vector
- // std::cout << "(Client) Sending selected entries to server:" << std::endl;
- // TODO: Make sure this works for multiple selections
+ /**
+ * From the selection values (process ID + value) given by the EntryList, generates a new
+ * selection source and set it to the representation.
+ *
+ * XXX: since the EntryList cannot store the process IDs (at least for now), we assume that
+ * the process ID is always 0. In order to eventually support the multi-process selection
+ * in the future, we will need to rework this to store this info.
+ */
+ CADSelection::SelectionValues selectionValues;
for (const std::string& entryName: EntryList)
{
- vtkIdType solidId = SPV3D_Prs::FromEntryToVtkId(entryName.c_str());
- // std::cout << "(Client) " << solidId << std::endl;
-
- // This takes pairs of values as (process number, value).
- std::array<vtkIdType, 2> values = {solidId, processNumber};
- vtkSMPropertyHelper(selectionSource, "Values").Append(values.data(), 2);
+ vtkIdType processNumber = 0;
+ vtkIdType value = SPV3D_Prs::FromEntryToVtkId(entryName.c_str());
+ selectionValues.emplace(processNumber, value);
}
- selectionSource->UpdateVTKObjects();
- // cout << "SetSelectionFromEntrySet" << endl;
- // vtkSMPropertyHelper(proxyRepresentation, "Selection").Set(selectionSource);
- proxyRepresentation->UpdateVTKObjects();
+ CADSelection::Utilities::SetSelectionFromValues(proxyRepresentation, selectionValues, this->SelectionArrayName);
- selectionSource->Delete();
-
- // TODO: Which render calls are necessary to display the selection right away ?
- // TODO: Before, after or during the slection ?
- // Force render to make sure the selection appears
+ // XXX: improve this to avoid double render
this->View->forceRender();
this->View->forceRender();
- rmp->StillRender();
-
- // proxyRepresentation->InvokeCommand("EndSelect");
-
-
}