30 typedef std::pair<unsigned, unsigned>
Key;
49 const unsigned&
v1()
const {
return m_key.first; }
51 const unsigned&
v2()
const {
return m_key.second; }
79 }
catch (
const std::bad_alloc&) {
98 float weight(
unsigned v1,
unsigned v2)
const {
102 std::map<Edge::Key, float>::const_iterator it =
105 return (it ==
m_edges.end() ? -1 : it->second);
157 std::priority_queue<Edge> priorityQueue;
158 std::vector<bool> visited;
159 unsigned visitedCount = 0;
161 unsigned vertexCount = graph.vertexCount();
163 unsigned vertexCount = cloud->
size();
168 visited.resize(vertexCount,
false);
173 progressCb->update(0);
174 progressCb->setMethodTitle(QObject::tr(
"Orient normals (MST)"));
176 progressCb->setInfo(QObject::tr(
"Compute Minimum spanning "
177 "tree\nPoints: %1\nEdges: %2")
179 .arg(graph.edgeCount()));
182 QObject::tr(
"Compute Minimum spanning tree\nPoints: %1")
196 unsigned firstUnvisitedIndex = 0;
197 size_t patchCount = 0;
198 size_t inversionCount = 0;
199 while (visitedCount < vertexCount) {
201 while (visited[firstUnvisitedIndex]) {
202 ++firstUnvisitedIndex;
207 visited[firstUnvisitedIndex] =
true;
212 graph.getVertexNeighbors(firstUnvisitedIndex);
213 for (Graph::IndexSet::const_iterator it = neighbors.begin();
214 it != neighbors.end(); ++it) {
216 Edge(firstUnvisitedIndex, *it,
217 graph.weight(firstUnvisitedIndex, *it)));
229 unsigned neighborCount =
232 neighborCount = std::min(neighborCount, kNN + 1);
237 for (
unsigned j = 0; j < neighborCount; ++j) {
239 unsigned neighborIndex =
241 if (firstUnvisitedIndex != neighborIndex &&
242 !visited[neighborIndex]) {
246 float weight = std::max(
248 1.0f -
static_cast<float>(fabs(N1.
dot(N2))));
262 priorityQueue.push(
Edge(firstUnvisitedIndex,
263 neighborIndex, weight));
275 cloud->
setPointColor(
static_cast<unsigned>(firstUnvisitedIndex),
277 sf->
setValue(
static_cast<unsigned>(firstUnvisitedIndex),
278 static_cast<ScalarType
>(visitedCount));
281 while (!priorityQueue.empty() && visitedCount < vertexCount) {
283 Edge element = priorityQueue.top();
288 static_cast<unsigned>(element.
v1()));
290 static_cast<unsigned>(element.
v2()));
291 bool inverNormal = (N1.
dot(N2) < 0);
294 if (!visited[element.
v1()]) {
300 }
else if (!visited[element.
v2()]) {
317 graph.getVertexNeighbors(v);
318 for (Graph::IndexSet::const_iterator it = neighbors.begin();
319 it != neighbors.end(); ++it)
320 priorityQueue.push(
Edge(v, *it, graph.weight(v, *it)));
332 unsigned neighborCount =
335 neighborCount = std::min(neighborCount, kNN + 1);
338 for (
unsigned j = 0; j < neighborCount; ++j) {
340 unsigned neighborIndex =
342 if (v != neighborIndex && !visited[neighborIndex]) {
346 float weight = std::max(
347 0.0f, 1.0f -
static_cast<float>(
362 priorityQueue.push(
Edge(v, neighborIndex, weight));
370 sf->
setValue(
static_cast<unsigned>(v),
371 static_cast<ScalarType
>(visitedCount));
375 static_cast<unsigned>(vertexCount);
394 QString(
"[ResolveNormalsWithMST] Patches = %1 / Inversions: %2")
396 .arg(inversionCount));
397 }
catch (
const std::bad_alloc&) {
407 void** additionalParameters,
410 Graph* graph =
static_cast<Graph*
>(additionalParameters[0]);
414 unsigned kNN = *
static_cast<unsigned*
>(additionalParameters[2]);
436 cloudViewer::DgmOctree::NeighboursSet::iterator it =
438 for (
unsigned i = 0; i < n; ++i, ++it) {
446 for (
unsigned i = 0; i < n; ++i) {
450 unsigned neighborCount =
453 neighborCount = std::min(neighborCount, kNN + 1);
459 for (
unsigned j = 0; j < neighborCount; ++j) {
462 if (index != neighborIndex) {
465 float weight = std::max(
466 0.0f, 1.0f -
static_cast<float>(fabs(N1.
dot(N2))));
480 graph->
addEdge(index, neighborIndex, weight);
497 QString(
"Cloud '%1' has no normals!").arg(cloud->
getName()));
504 CVLog::Warning(QString(
"[orientNormalsWithMST] Could not compute "
505 "octree on cloud '%1'")
525 void* additionalParameters[3] = {
reinterpret_cast<void*
>(&graph),
526 reinterpret_cast<void*
>(cloud),
527 reinterpret_cast<void*
>(&kNN)};
532 progressDlg,
"Build Spanning Tree") == 0) {
535 QString(
"Failed to compute Spanning Tree on cloud '%1'")
542 "Tree on cloud '%1'")
550 CVLog::Warning(QString(
"Failed to resolve normals orientation with "
551 "Minimum Spanning Tree on cloud '%1'")
558 QString(
"Process failed on cloud '%1'").arg(cloud->
getName()));
constexpr ScalarType NAN_VALUE
NaN as a ScalarType value.
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static bool Print(const char *format,...)
Prints out a formatted message in console.
static bool Error(const char *format,...)
Display an error dialog with formatted message.
void addEdge(unsigned v1, unsigned v2, float weight=0.0f)
Adds or updates the edge (v1,v2)
std::set< unsigned > IndexSet
Set of indexes.
std::map< Edge::Key, float > m_edges
Graph edges.
bool reserve(unsigned vertexCount)
Reserves memory for graph.
unsigned vertexCount() const
Returns the number of vertices.
size_t edgeCount() const
Returns the number of edges.
std::vector< IndexSet > m_vertexNeighbors
Set of neighbors for each vertex.
Graph()
Default constructor.
const IndexSet & getVertexNeighbors(unsigned index) const
Returns the set of edges connected to a given vertex.
float weight(unsigned v1, unsigned v2) const
Type dot(const Vector3Tpl &v) const
Dot product.
virtual void showColors(bool state)
Sets colors visibility.
virtual void showSF(bool state)
Sets active scalarfield visibility.
virtual ccOctree::Shared computeOctree(cloudViewer::GenericProgressCallback *progressCb=nullptr, bool autoAddChild=true)
Computes the cloud octree.
virtual ccOctree::Shared getOctree() const
Returns the associated octree (if any)
static bool OrientNormals(ccPointCloud *cloud, unsigned kNN=6, ecvProgressDialog *progressDlg=0)
Main entry point.
virtual QString getName() const
Returns object name.
QSharedPointer< ccOctree > Shared
Shared pointer.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void setCurrentDisplayedScalarField(int index)
Sets the currently displayed scalar field.
int addScalarField(const char *uniqueName) override
Creates a new scalar field and registers it.
bool hasNormals() const override
Returns whether normals are enabled or not.
void setPointColor(size_t pointIndex, const ecvColor::Rgb &col)
Sets a particular point color.
void setPointNormal(size_t pointIndex, const CCVector3 &N)
Sets a particular point normal (shortcut)
const CCVector3 & getPointNormal(unsigned pointIndex) const override
Returns normal corresponding to a given point.
bool setRGBColor(ColorCompType r, ColorCompType g, ColorCompType b)
Set a unique color for the whole cloud (shortcut)
A scalar field associated to display-related parameters.
void computeMinAndMax() override
Determines the min and max values.
void getCellPos(CellCode code, unsigned char level, Tuple3i &cellPos, bool isCodeTruncated) const
unsigned findNearestNeighborsStartingFromCell(NearestNeighboursSearchStruct &nNSS, bool getOnlyPointsWithValidScalar=false) const
void getTheCellPosWhichIncludesThePoint(const CCVector3 *thePoint, Tuple3i &cellPos) const
void computeCellCenter(CellCode code, unsigned char level, CCVector3 ¢er, bool isCodeTruncated=false) const
unsigned executeFunctionForAllCellsAtLevel(unsigned char level, octreeCellFunc func, void **additionalParameters, bool multiThread=false, GenericProgressCallback *progressCb=nullptr, const char *functionTitle=nullptr, int maxThreadCount=0)
unsigned char findBestLevelForAGivenPopulationPerCell(unsigned indicativeNumberOfPointsPerCell) const
bool oneStep()
Increments total progress value of a single unit.
int getScalarFieldIndexByName(const char *name) const
Returns the index of a scalar field represented by its name.
ScalarField * getScalarField(int index) const
Returns a pointer to a specific scalar field.
unsigned size() const override
const CCVector3 * getPoint(unsigned index) const override
unsigned size() const override
Returns the number of points.
virtual unsigned getPointGlobalIndex(unsigned localIndex) const
const CCVector3 * getPointPersistentPtr(unsigned index) override
Returns the ith point as a persistent pointer.
const CCVector3 * getPoint(unsigned index) const override
Returns the ith point.
void fill(ScalarType fillValue=0)
Fills the array with a particular value.
void setValue(std::size_t index, ScalarType value)
static Rgb Random(bool lightOnly=true)
Generates a random color.
Graphical progress indicator (thread-safe)
static bool ComputeMSTGraphAtLevel(const cloudViewer::DgmOctree::octreeCell &cell, void **additionalParameters, cloudViewer::NormalizedProgress *nProgress)
static bool ResolveNormalsWithMST(ccPointCloud *cloud, ccOctree::Shared &octree, unsigned char level, unsigned kNN, ecvProgressDialog *progressCb=0)
CLOUDVIEWER_HOST_DEVICE Pair< First, Second > make_pair(const First &_first, const Second &_second)
constexpr Rgb white(MAX, MAX, MAX)
const unsigned & v2() const
Returns second vertex (index)
Edge(unsigned v1, unsigned v2, float weight)
Default constructor.
const unsigned & v1() const
Returns first vertex (index)
std::pair< unsigned, unsigned > Key
Unique edge key type.
bool operator<(const Edge &other) const
Strict weak ordering operator (required by std::priority_queue)
static Key ConstructKey(unsigned v1, unsigned v2)
Returns the unique key of an edge (no vertex order)
float m_weight
Associated weight.
ReferenceCloud * points
Set of points lying inside this cell.
const DgmOctree * parentOctree
Octree to which the cell belongs.
unsigned char level
Cell level of subdivision.
CellCode truncatedCode
Truncated cell code.