|
18 | 18 | #include <widgets/ViewPluginLearningCenterOverlayWidget.h> |
19 | 19 |
|
20 | 20 | #include <actions/PluginTriggerAction.h> |
| 21 | +#include <actions/ViewPluginSamplerAction.h> |
21 | 22 |
|
22 | 23 | #include <DatasetsMimeData.h> |
23 | 24 |
|
|
29 | 30 | #include <QtCore> |
30 | 31 |
|
31 | 32 | #include <algorithm> |
32 | | -#include <functional> |
| 33 | +#include <cassert> |
33 | 34 | #include <vector> |
34 | | -#include <actions/ViewPluginSamplerAction.h> |
35 | 35 |
|
36 | 36 | #define VIEW_SAMPLING_HTML |
37 | 37 | //#define VIEW_SAMPLING_WIDGET |
@@ -172,24 +172,33 @@ ScatterplotPlugin::ScatterplotPlugin(const PluginFactory* factory) : |
172 | 172 | }); |
173 | 173 | } |
174 | 174 |
|
175 | | - if (candidateDataset->getNumPoints() == _positionDataset->getNumPoints()) { |
176 | | - |
177 | | - // The number of points is equal, so offer the option to use the points dataset as source for points colors |
| 175 | + // Accept both data with the same number if points and data which is derived from |
| 176 | + // a parent that has the same number of points (e.g. for HSNE embeddings) |
| 177 | + const auto numPointsCandidate = candidateDataset->getNumPoints(); |
| 178 | + const auto numPointsPosition = _positionDataset->getNumPoints(); |
| 179 | + const bool sameNumPoints = numPointsPosition == numPointsCandidate; |
| 180 | + const bool sameNumPointsAsFull = |
| 181 | + /*if*/ _positionDataset->isDerivedData() ? |
| 182 | + /*then*/ _positionDataset->getSourceDataset<Points>()->getFullDataset<Points>()->getNumPoints() == numPointsCandidate : |
| 183 | + /*else*/ false; |
| 184 | + |
| 185 | + if (sameNumPoints || sameNumPointsAsFull) { |
| 186 | + // Offer the option to use the points dataset as source for points colors |
178 | 187 | dropRegions << new DropWidget::DropRegion(this, "Point color", QString("Colorize %1 points with %2").arg(_positionDataset->text(), candidateDataset->text()), "palette", true, [this, candidateDataset]() { |
179 | | - _settingsAction.getColoringAction().addColorDataset(candidateDataset); |
180 | | - _settingsAction.getColoringAction().setCurrentColorDataset(candidateDataset); |
| 188 | + _settingsAction.getColoringAction().setCurrentColorDataset(candidateDataset); // calls addColorDataset internally |
181 | 189 | }); |
182 | 190 |
|
183 | | - // The number of points is equal, so offer the option to use the points dataset as source for points size |
| 191 | + } |
| 192 | + |
| 193 | + if (sameNumPoints) { |
| 194 | + // Offer the option to use the points dataset as source for points size |
184 | 195 | dropRegions << new DropWidget::DropRegion(this, "Point size", QString("Size %1 points with %2").arg(_positionDataset->text(), candidateDataset->text()), "ruler-horizontal", true, [this, candidateDataset]() { |
185 | | - _settingsAction.getPlotAction().getPointPlotAction().addPointSizeDataset(candidateDataset); |
186 | | - _settingsAction.getPlotAction().getPointPlotAction().getSizeAction().setCurrentDataset(candidateDataset); |
| 196 | + _settingsAction.getPlotAction().getPointPlotAction().setCurrentPointSizeDataset(candidateDataset); |
187 | 197 | }); |
188 | 198 |
|
189 | | - // The number of points is equal, so offer the option to use the points dataset as source for points opacity |
| 199 | + // Offer the option to use the points dataset as source for points opacity |
190 | 200 | dropRegions << new DropWidget::DropRegion(this, "Point opacity", QString("Set %1 points opacity with %2").arg(_positionDataset->text(), candidateDataset->text()), "brush", true, [this, candidateDataset]() { |
191 | | - _settingsAction.getPlotAction().getPointPlotAction().addPointOpacityDataset(candidateDataset); |
192 | | - _settingsAction.getPlotAction().getPointPlotAction().getOpacityAction().setCurrentDataset(candidateDataset); |
| 201 | + _settingsAction.getPlotAction().getPointPlotAction().setCurrentPointOpacityDataset(candidateDataset); |
193 | 202 | }); |
194 | 203 | } |
195 | 204 | } |
@@ -647,14 +656,37 @@ void ScatterplotPlugin::loadColors(const Dataset<Points>& points, const std::uin |
647 | 656 | // Generate point scalars for color mapping |
648 | 657 | std::vector<float> scalars; |
649 | 658 |
|
650 | | - if (_positionDataset->getNumPoints() != _numPoints) |
651 | | - { |
652 | | - qWarning("Number of points used for coloring does not match number of points in data, aborting attempt to color plot"); |
653 | | - return; |
| 659 | + points->extractDataForDimension(scalars, dimensionIndex); |
| 660 | + |
| 661 | + const auto numColorPoints = points->getNumPoints(); |
| 662 | + |
| 663 | + |
| 664 | + if (numColorPoints != _numPoints) { |
| 665 | + |
| 666 | + const bool sameNumPointsAsFull = |
| 667 | + /*if*/ _positionDataset->isDerivedData() ? |
| 668 | + /*then*/ _positionSourceDataset->getFullDataset<Points>()->getNumPoints() == numColorPoints : |
| 669 | + /*else*/ false; |
| 670 | + |
| 671 | + if (sameNumPointsAsFull) { |
| 672 | + std::vector<std::uint32_t> globalIndices; |
| 673 | + _positionDataset->getGlobalIndices(globalIndices); |
| 674 | + |
| 675 | + std::vector<float> localScalars(_numPoints, 0); |
| 676 | + std::int32_t localColorIndex = 0; |
| 677 | + |
| 678 | + for (const auto& globalIndex : globalIndices) |
| 679 | + localScalars[localColorIndex++] = scalars[globalIndex]; |
| 680 | + |
| 681 | + std::swap(localScalars, scalars); |
| 682 | + } |
| 683 | + else { |
| 684 | + qWarning("Number of points used for coloring does not match number of points in data, aborting attempt to color plot"); |
| 685 | + return; |
| 686 | + } |
654 | 687 | } |
655 | 688 |
|
656 | | - // Populate point scalars |
657 | | - points->extractDataForDimension(scalars, dimensionIndex); |
| 689 | + assert(scalars.size() == _numPoints); |
658 | 690 |
|
659 | 691 | // Assign scalars and scalar effect |
660 | 692 | _scatterPlotWidget->setScalars(scalars); |
|
0 commit comments