Question

I have a QList consist of QVector3D. A QVector3D represents a vertex or a point. This List holds also all vertices of a STL-File. The problem is that a vertex exist multiple times in the list. In need a list of the unique vertices of a STL-File. How can i implement it with Qt 5.0.2?

Was it helpful?

Solution

QSet uses a hash-function for ensuring the uniqueness of the value (QMap uses operator <) There is no qHash implementation for QVector3D in Qt. You could implement your own one e.g. as in example:

//place anywhere in Qt-code
#include <QSet>
#include <QVector3D>
#include <QList>

uint qHash(const QVector3D &v)
{
    return qHash( QString( "%1x%2x%3" ).arg(v.x()).arg(v.y()).arg(v.z()) ) ;
}

int foo()
{
    QList<QVector3D> uvector3D_1;
    QSet<QVector3D> uvector3D_2;

    uvector3D_2 = QSet<QVector3D>::fromList(uvector3D_1);
return 0;
}

static int testFoo = foo();

Of cause it is not the fastest one, it relies on Qt's function qHash for QString. But I think it's good for demonstration.

OTHER TIPS

QList<QVector3D> originalVector = ...;

then either:

QSet<QVector3D> noDublicatesSet = QSet<QVector3D>::fromList(originalVector);

or

QSet<QVector3D> noDublicatesSet = originalVector.toSet();

also you can add something like if you need QList back..

QList<QVector3D> destinationVector = QList<QVector3D>::fromSet(noDublicatesSet);

you also will need those things (sorry has them in my code for ages.. forgot that they are external).. you might want to change hash function:

#define ROTL10(x) (((x) << 10) | (((x) >> 22) & 0x000000ff))
#define ROTL20(x) (((x) << 20) | (((x) >> 12) & 0x0000ffff))

uint qHash(double data)
{
union U {
    quint64 n;
    double f;
};
U u;
u.f = data;
return u.f;
}

inline uint qHash(const QVector3D &v, uint seed)
{
return qHash(v.x()) ^ ROTL10(qHash(v.y())) ^ ROTL20(qHash(v.z()));
}

P.S. that's a code for Qt 5.0, actually to add missing qHash() for vectors, that's why they dont fit in QSet/QHash by default

Starting from Qt 5.14, you can use the new constructor:

template <typename InputIterator> QSet::QSet(InputIterator first, InputIterator last

Here is an example taken from the docs:

// For example, if you have code like

QStringList list;

QSet<QString> set = QSet<QString>::fromList(list);

// you can rewrite it as

QStringList list;

QSet<QString> set(list.begin(), list.end());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top