25#include <QtConcurrentMap>
27using namespace Qt::StringLiterals;
35 , mAttribute( attribute )
38 QgsEventTracing::ScopedEvent _trace( u
"PointCloud"_s, u
"QgsPointCloudLayerUndoCommand constructor"_s );
40 QList<NodeProcessData> processData;
41 for (
auto it = mappedPoints.constBegin(); it != mappedPoints.constEnd(); ++it )
43 const int position = it.key();
48 index =
mLayer->subIndexes().at( position ).index();
49 const auto &nodes = it.value();
50 for (
auto nodeIt = nodes.constBegin(); nodeIt != nodes.constEnd(); ++nodeIt )
52 processData.append( { position, index, nodeIt.key(), nodeIt.value() } );
56 std::function mapFn = [attribute](
const NodeProcessData & data )
61 const QVector<int> &points = data.points;
63 PerNodeData perNodeData;
72 std::unique_ptr<QgsPointCloudBlock> block = index.
nodeData( n, req );
73 const char *ptr = block->data();
74 block->attributes().find( attribute.
name(), perNodeData.attributeOffset );
75 const int size = block->pointRecordSize();
76 for (
const int point : points )
78 const int offset = point * size + perNodeData.attributeOffset;
80 perNodeData.oldPointValues[point] = oldValue;
87 perNodeData.firstEdit =
true;
88 for (
const int point : points )
90 perNodeData.oldPointValues[point] = std::numeric_limits<double>::quiet_NaN();
94 return std::pair { data.position, std::pair { n, perNodeData } };
97 std::function reduceFn = []( QMap<int, QHash<QgsPointCloudNodeId, PerNodeData>> &res,
const std::pair<int, std::pair<QgsPointCloudNodeId, PerNodeData>> &pair )
99 res[pair.first][pair.second.first] = pair.second.second;
102 mPerNodeData = QtConcurrent::blockingMappedReduced<QMap<int, QHash<QgsPointCloudNodeId, PerNodeData>>>(
104 std::move( mapFn ), std::move( reduceFn )
110 undoRedoPrivate(
true );
115 undoRedoPrivate(
false );
118void QgsPointCloudLayerUndoCommandChangeAttribute::undoRedoPrivate(
bool isUndo )
120 QgsEventTracing::ScopedEvent _trace( u
"PointCloud"_s, u
"QgsPointCloudLayerUndoCommand::undoRedoPrivate"_s );
123 double newValue = mNewValue;
125 for (
auto it = mPerNodeData.begin(); it != mPerNodeData.end(); ++it )
127 const int position = it.key();
128 QHash<QgsPointCloudNodeId, PerNodeData> &nodesData = it.value();
136 QgsCopcPointCloudIndex *copcIndex =
dynamic_cast<QgsCopcPointCloudIndex *
>( editIndex->
backingIndex().get() );
138 QtConcurrent::blockingMap(
139 nodesData.keyValueBegin(),
140 nodesData.keyValueEnd(),
141 [editIndex, copcIndex, isUndo, attribute, newValue](
142 std::pair<const QgsPointCloudNodeId &, PerNodeData &> pair
145 QgsPointCloudNodeId node = pair.first;
146 PerNodeData &perNodeData = pair.second;
148 QByteArray chunkData = editIndex->rawEditedNodeData( node );
149 if ( chunkData.isEmpty() )
150 chunkData = copcIndex->rawNodeData( node );
153 if ( isUndo && perNodeData.firstEdit )
155 editIndex->resetNodeEdits( node );
170 for (
auto itNode = nodesData.constBegin(); itNode != nodesData.constEnd(); itNode++ )
172 emit
mLayer->chunkAttributeValuesChanged( itNode.key(), position );
A collection of point cloud attributes.
Attribute for point cloud data pair of name and size in bytes.
QString name() const
Returns name of the attribute.
double convertValueToDouble(const char *ptr) const
Returns the attribute's value as a double for data pointed to by ptr.
A QgsPointCloudIndex that is used as an editing buffer when editing point cloud data.
QgsPointCloudIndex backingIndex() const
Returns index for the underlying non-edited data.
bool isNodeModified(QgsPointCloudNodeId n) const
Returns true if this node was modified.
bool updateNodeData(const QHash< QgsPointCloudNodeId, QByteArray > &data) override
Tries to update the data for the specified nodes.
Smart pointer for QgsAbstractPointCloudIndex.
std::unique_ptr< QgsPointCloudBlock > nodeData(const QgsPointCloudNodeId &n, const QgsPointCloudRequest &request)
Returns node data block.
QgsAbstractPointCloudIndex * get()
Returns pointer to the implementation class.
QgsPointCloudAttributeCollection attributes() const
Returns all attributes that are stored in the file.
static QByteArray updateChunkValues(QgsCopcPointCloudIndex *copcIndex, const QByteArray &chunkData, const QgsPointCloudAttribute &attribute, const QgsPointCloudNodeId &n, const QHash< int, double > &pointValues, std::optional< double > newValue=std::nullopt)
Sets new classification value for the given points in voxel and return updated chunk data.
QgsPointCloudLayerUndoCommandChangeAttribute(QgsPointCloudLayer *layer, const QHash< int, QHash< QgsPointCloudNodeId, QVector< int > > > &mappedPoints, const QgsPointCloudAttribute &attribute, double value)
Constructor for QgsPointCloudLayerUndoCommandChangeAttribute.
QgsPointCloudLayerUndoCommand(QgsPointCloudLayer *layer)
Ctor.
QgsPointCloudLayer * mLayer
Represents a map layer supporting display of point clouds.
QgsPointCloudIndex index() const
Returns the point cloud index associated with the layer.
QVector< QgsPointCloudSubIndex > subIndexes() const
Returns point cloud indexes associated with the layer (only if the layer has a virtual point cloud da...
Represents an indexed point cloud node's position in octree.
Point cloud data request.
void setIgnoreIndexFilterEnabled(bool enable)
When enable is true, the request will ignore the point cloud index's filter expression and use an emp...
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Set attributes filter in the request.