34 const CCVector3& toBeAlignedGravityCenter,
41 if (inTrans.
R.
isValid() && (rotationFilter != 0)) {
64 }
else if (rotationFilter ==
83 }
else if (rotationFilter ==
112 (referenceGravityCenter.
toDouble() - alignedGravityCenter);
133 rotatedCloud(nullptr),
136 CPSetPlain(nullptr) {}
152 unsigned& finalPointCount,
154 if (!inputModelCloud || !inputDataCloud) {
170 unsigned dataSamplingLimit =
171 params.finalOverlapRatio != 1.0
172 ?
static_cast<unsigned>(
params.samplingLimit /
177 if (inputDataCloud->
size() > dataSamplingLimit) {
179 inputDataCloud, dataSamplingLimit);
192 for (
unsigned i = 0; i < destCount; ++i) {
193 unsigned pointIndex =
196 i,
params.dataWeights->getValue(pointIndex));
226 unsigned char meshDistOctreeLevel = 8;
230 if (inputModelMesh) {
231 assert(!
params.modelWeights);
237 modelOctree.
build() <
static_cast<int>(inputModelCloud->
size())) {
243 meshDistOctreeLevel =
248 if (inputModelCloud->
size() >
params.samplingLimit) {
251 inputModelCloud,
params.samplingLimit);
252 if (!subModelCloud) {
256 cloudGarbage.
add(subModelCloud);
259 if (
params.modelWeights) {
263 unsigned destCount = subModelCloud->
size();
265 for (
unsigned i = 0; i < destCount; ++i) {
266 unsigned pointIndex =
269 i,
params.modelWeights->getValue(pointIndex));
277 model.
cloud = subModelCloud;
280 model.
cloud = inputModelCloud;
287 unsigned maxOverlapCount = 0;
288 std::vector<ScalarType> overlapDistances;
289 if (
params.finalOverlapRatio < 1.0) {
292 overlapDistances.resize(data.
cloud->
size());
293 }
catch (
const std::bad_alloc&) {
297 maxOverlapCount =
static_cast<unsigned>(
params.finalOverlapRatio *
299 assert(maxOverlapCount != 0);
303 if (inputModelMesh) {
315 sfGarbage.
add(coupleWeights);
321 if (inputModelMesh) {
329 data.
cloud, inputModelMesh, c2mDistParams, progressCb) <
334 }
else if (inputModelCloud) {
341 data.
cloud, model.
cloud, c2cDistParams, progressCb) < 0) {
349 FILE* fTraceFile =
nullptr;
351 fTraceFile = fopen(
"registration_trace_log.csv",
"wt");
352 if (fTraceFile) fprintf(fTraceFile,
"Iteration; RMS; Point count;\n");
355 double lastStepRMS = -1.0, initialDeltaRMS = -1.0;
359 for (
unsigned iteration = 0;; ++iteration) {
366 bool pointOrderHasBeenChanged =
false;
367 if (
params.filterOutFarthestPoints) {
371 ScalarType mu, sigma2;
373 ScalarType maxDistance =
374 static_cast<ScalarType
>(mu + 2.5 * sqrt(sigma2));
379 cloudGarbage.
add(filteredData.
cloud);
400 unsigned pointCount = data.
cloud->
size();
414 for (
unsigned i = 0; i < pointCount; ++i) {
454 pointOrderHasBeenChanged =
true;
460 unsigned pointCount = data.
cloud->
size();
461 if (maxOverlapCount != 0 && pointCount > maxOverlapCount) {
462 assert(overlapDistances.size() >= pointCount);
463 for (
unsigned i = 0; i < pointCount; ++i) {
465 assert(overlapDistances[i] == overlapDistances[i]);
469 overlapDistances.begin() + pointCount);
471 assert(maxOverlapCount != 0);
472 ScalarType maxOverlapDist = overlapDistances[maxOverlapCount - 1];
488 cloudGarbage.
add(filteredData.
cloud);
510 for (
unsigned i = 0; i < pointCount; ++i) {
525 assert(filteredData.
cloud->
size() >= maxOverlapCount);
558 for (
unsigned i = 0; i <
count; ++i) {
560 :
static_cast<ScalarType
>(1.0));
566 :
static_cast<ScalarType
>(
570 coupleWeights->
setValue(i, wd * wm);
580 double meanSquareValue = 0.0;
583 for (
unsigned i = 0; i < data.
cloud->
size(); ++i) {
588 ScalarType w = coupleWeights->
getValue(i);
594 meanSquareValue += Vd * Vd;
600 double meanSquareError =
602 ?
static_cast<ScalarType
>(meanSquareValue / wiSum)
605 double rms = sqrt(meanSquareError);
609 fprintf(fTraceFile,
"%u; %f; %u;\n", iteration, rms,
612 if (iteration == 0) {
619 sprintf(buffer,
"Initial RMS = %f\n", rms);
635 assert(lastStepRMS >= 0.0);
637 if (rms > lastStepRMS)
645 double deltaRMS = lastStepRMS - rms;
647 assert(deltaRMS >= 0.0);
652 transform.
R = currentTrans.
R * transform.
R;
654 transform.
R = currentTrans.
R;
656 transform.
T = currentTrans.
R * transform.
T;
660 transform.
s *= currentTrans.
s;
661 transform.
T *= currentTrans.
s;
664 transform.
T += currentTrans.
T;
671 deltaRMS <
params.minRMSDecrease)
685 sprintf(buffer,
"RMS = %f [-%f]\n", rms, deltaRMS);
688 if (iteration == 1) {
689 initialDeltaRMS = deltaRMS;
692 assert(initialDeltaRMS >= 0.0);
693 float progressPercent =
static_cast<float>(
694 (initialDeltaRMS - deltaRMS) /
695 (initialDeltaRMS -
params.minRMSDecrease) *
697 progressCb->
update(progressPercent);
707 CCVector3 dataGravityCenter, modelGravityCenter;
714 currentTrans,
params.adjustScale, coupleWeights,
PC_ONE,
715 &dataGravityCenter, &modelGravityCenter)) {
721 if (trueData.
cloud) {
735 dataGravityCenter, modelGravityCenter,
745 if (!rotatedDataCloud) {
774 if (inputModelMesh) {
781 data.
cloud, inputModelMesh, c2mDistParams) < 0) {
786 }
else if (inputDataCloud) {
792 data.
cloud, model.
cloud, c2cDistParams) < 0) {
805 fTraceFile =
nullptr;
827 assert(rCloud && lCloud);
828 if (!rCloud || !lCloud || rCloud->
size() != lCloud->
size() ||
838 for (
unsigned i = 0; i <
count; i++) {
843 rms += (*Ri - Lit).norm2();
846 return sqrt(rms /
count);
864 if (P ==
nullptr ||
X ==
nullptr || P->
size() !=
X->size() || P->
size() < 3)
881 if (P->
size() == 3) {
889 Np = (*Bp - *Ap).
cross(*Cp - *Ap);
890 double norm = Np.
normd();
897 X->placeIteratorAtBeginning();
903 Nx = (*Bx - *Ax).
cross(*Cx - *Ax);
904 double norm = Nx.
normd();
915 if (Np.
dot(Nx) < 0) {
919 double cos_t = Np.
dot(Nx);
920 assert(cos_t > -1.0 && cos_t < 1.0);
921 double s = sqrt((1 + cos_t) * 2);
923 s / 2, a.
x / s, a.
y / s,
926 q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3];
937 double sumNormP = (*Bp - *Ap).norm() + (*Cp - *Bp).norm() +
939 sumNormP *= aPrioriScale;
943 double sumNormX = (*Bx - *Ax).norm() + (*Cx - *Bx).norm() +
946 sumNormX / sumNormP);
951 trans.
T = Gx.
toDouble() - (trans.
R * Gp) * (aPrioriScale * trans.
s);
973 Ssum += rx.
cross(rp);
978 Ssum += rx.
cross(rp);
981 double Q = sqrt(S * S + C * C);
999 R.
m_values[0][0] = cos_t + l1 * l1_inv_cos_t;
1000 R.
m_values[0][1] = l2 * l1_inv_cos_t + l3 * sin_t;
1001 R.
m_values[0][2] = l3 * l1_inv_cos_t - l2 * sin_t;
1004 R.
m_values[1][0] = l2 * l1_inv_cos_t - l3 * sin_t;
1005 R.
m_values[1][1] = cos_t + l2 * l2 * inv_cos_t;
1006 R.
m_values[1][2] = l2 * l3_inv_cos_t + l1 * sin_t;
1009 R.
m_values[2][0] = l3 * l1_inv_cos_t + l2 * sin_t;
1010 R.
m_values[2][1] = l2 * l3_inv_cos_t - l1 * sin_t;
1011 R.
m_values[2][2] = cos_t + l3 * l3_inv_cos_t;
1013 trans.
R = R * trans.
R;
1015 trans.
T = Gx.
toDouble() - (trans.
R * Gp) * (aPrioriScale * trans.
s);
1020 X->getBoundingBox(bbMin, bbMax);
1028 trans.
T = Gx - Gp * aPrioriScale;
1037 P,
X, Gp, Gx, coupleWeights)
1040 if (!Sigma_px.
isValid())
return false;
1047 double trace = Sigma_px.
trace();
1081 std::vector<double> eigValues;
1083 eigValues,
false)) {
1091 double maxEigValue = 0;
1101 double acc_num = 0.0;
1102 double acc_denom = 0.0;
1106 X->placeIteratorAtBeginning();
1109 unsigned count =
X->size();
1111 for (
unsigned i = 0; i <
count; ++i) {
1120 acc_num += b_tilde.
dot(a_tilde);
1121 acc_denom += a_tilde.
dot(a_tilde);
1126 assert(acc_denom > 0.0);
1133 trans.
T = Gx.
toDouble() - (trans.
R * Gp) * (aPrioriScale * trans.
s);
1148 unsigned nbMaxCandidates) {
1162 srand(
static_cast<unsigned>(time(
nullptr)));
1164 unsigned bestScore = 0, score = 0;
1173 overlap *= diff.
norm() / 2;
1192 for (
unsigned i = 0; i < nbBases; i++) {
1195 if (!
FindBase(modelCloud, overlap, nbTries, reference))
continue;
1198 std::vector<Base> candidates;
1200 candidates.reserve(
count);
1201 if (candidates.capacity() <
count)
1208 const CCVector3* referenceBasePoints[4];
1210 for (
unsigned j = 0; j < 4; j++)
1211 referenceBasePoints[j] =
1228 std::vector<ScaledTransformation> transforms;
1230 nbMaxCandidates, transforms)) {
1237 for (
unsigned j = 0; j < candidates.size(); j++) {
1247 if (score > bestScore) {
1259 sprintf(buffer,
"Trial %u/%u [best score = %u]\n", i + 1,
1260 nbBases, bestScore);
1262 progressCb->
update(((i + 1) * 100.0f) / nbBases);
1281 return (bestScore > 0);
1294 for (
unsigned i = 0; i <
count; ++i) {
1297 Q = (dataToModel.
R * Q + dataToModel.
T).toPC();
1310 unsigned a, b, c, d;
1323 for (i = 0; i < nbTries; i++) {
1324 unsigned t1 = (rand() %
size);
1325 unsigned t2 = (rand() %
size);
1326 if (t1 == a || t2 == a || t1 == t2)
continue;
1333 if (u.
norm2() > overlap)
continue;
1335 if (u.
norm2() > overlap)
continue;
1338 x = ((p1->
y - p0->y) * (p2->
z - p0->z)) -
1339 ((p1->
z - p0->z) * (p2->
y - p0->y));
1340 y = ((p1->
z - p0->z) * (p2->
x - p0->x)) -
1341 ((p1->
x - p0->x) * (p2->
z - p0->z));
1342 z = ((p1->
x - p0->x) * (p2->
y - p0->y)) -
1343 ((p1->
y - p0->y) * (p2->
x - p0->x));
1346 f = x * x + y * y + z * z;
1357 if (b == c)
return false;
1361 if (f <= 0)
return false;
1367 w = -(x * p0->
x) - (y * p0->
y) - (z * p0->
z);
1372 for (i = 0; i < nbTries; i++) {
1373 unsigned t1 = (rand() %
size);
1374 if (t1 == a || t1 == b || t1 == c)
continue;
1378 d0 = (*p3 - *p0).norm2();
1379 d1 = (*p3 - *p1).norm2();
1380 d2 = (*p3 - *p2).norm2();
1381 if ((d0 >= overlap && d1 >= overlap) ||
1382 (d0 >= overlap && d2 >= overlap) ||
1383 (d1 >= overlap && d2 >= overlap))
1386 f =
std::abs((x * p3->
x) + (y * p3->
y) + (z * p3->
z) + w);
1389 f = (f + 1.0f) / (sqrt(d0) + sqrt(d1) + sqrt(d2));
1390 if ((best < 0.) || (f < best)) {
1406 u = (*p1 - *p0) * (*p2 - *p0);
1407 v = (*p1 - *p0) * (*p3 - *p0);
1408 if (u.
dot(v) <= 0) {
1410 base.
init(a, b, c, d);
1413 u = (*p2 - *p1) * (*p0 - *p1);
1414 v = (*p2 - *p1) * (*p3 - *p1);
1415 if (u.
dot(v) <= 0) {
1417 base.
init(b, c, d, a);
1420 base.
init(a, c, b, d);
1433 std::vector<Base>& results) {
1442 d1 = (*p1 - *p0).norm();
1443 d2 = (*p3 - *p2).norm();
1452 std::vector<IndexPair> pairs1, pairs2;
1454 unsigned count =
static_cast<unsigned>(cloud->
size());
1455 std::vector<unsigned> pointsIndexes;
1457 pointsIndexes.reserve(
count);
1463 for (
unsigned i = 0; i <
count; i++) {
1469 pointsIndexes.clear();
1471 delta, pointsIndexes);
1473 for (std::size_t j = 0; j < pointsIndexes.size(); j++) {
1476 if (pointsIndexes[j] > i) {
1477 idxPair.second = pointsIndexes[j];
1478 pairs1.push_back(idxPair);
1484 pointsIndexes.clear();
1486 delta, pointsIndexes);
1488 for (std::size_t j = 0; j < pointsIndexes.size(); j++) {
1489 if (pointsIndexes[j] > i) {
1490 idxPair.second = pointsIndexes[j];
1491 pairs2.push_back(idxPair);
1499 std::vector<IndexPair> match;
1503 unsigned count =
static_cast<unsigned>(pairs1.size());
1506 for (
unsigned i = 0; i <
count; i++) {
1518 unsigned count =
static_cast<unsigned>(pairs2.size());
1521 for (
unsigned i = 0; i <
count; i++) {
1539 unsigned count =
static_cast<unsigned>(tmpCloud2.
size());
1540 match.reserve(
count);
1541 if (match.capacity() <
count)
1544 for (
unsigned i = 0; i <
count; i++) {
1551 match.push_back(idxPair);
1560 std::size_t
count = match.size();
1563 results.reserve(
count);
1564 }
catch (
const std::bad_alloc&) {
1568 for (std::size_t i = 0; i <
count; i++) {
1570 unsigned b = match[i].second / 2;
1571 if ((match[i].second % 2) == 0) {
1572 quad.
a = pairs1[b].first;
1573 quad.
b = pairs1[b].second;
1575 quad.
a = pairs1[b].second;
1576 quad.
b = pairs1[b].first;
1579 unsigned a = match[i].first / 2;
1580 if ((match[i].first % 2) == 0) {
1581 quad.
c = pairs2[a].first;
1582 quad.
d = pairs2[a].second;
1584 quad.
c = pairs2[a].second;
1585 quad.
d = pairs2[a].first;
1587 results.push_back(quad);
1592 return static_cast<int>(results.size());
1612 num = (p02.
dot(p32) * p32.
dot(p10)) - (p02.
dot(p10) * p32.
dot(p32));
1613 denom = (p10.
dot(p10) * p32.
dot(p32)) - (p32.
dot(p10) * p32.
dot(p10));
1614 if (
std::abs(denom) < 0.00001)
return false;
1615 lambda = num / denom;
1616 num = p02.
dot(p32) + (lambda * p32.
dot(p10));
1617 denom = p32.
dot(p32);
1618 if (
std::abs(denom) < 0.00001)
return false;
1620 A.
x = p0.
x + (lambda * p10.
x);
1621 A.
y = p0.
y + (lambda * p10.
y);
1622 A.
z = p0.
z + (lambda * p10.
z);
1623 B.
x = p2.
x + (mu * p32.
x);
1624 B.
y = p2.
y + (mu * p32.
y);
1625 B.
z = p2.
z + (mu * p32.
z);
1626 inter.
x = (A.
x + B.
x) / 2.0f;
1627 inter.
y = (A.
y + B.
y) / 2.0f;
1628 inter.
z = (A.
z + B.
z) / 2.0f;
1637 std::vector<Base>& candidates,
1638 unsigned nbMaxCandidates,
1639 std::vector<ScaledTransformation>& transforms) {
1640 std::vector<Base> table;
1641 std::vector<float> scores, sortedscores;
1644 std::vector<ScaledTransformation> tarray;
1645 PointCloud referenceBaseCloud, dataBaseCloud;
1647 unsigned candidatesCount =
static_cast<unsigned>(candidates.size());
1648 if (candidatesCount == 0)
return false;
1650 bool filter = (nbMaxCandidates > 0 && candidatesCount > nbMaxCandidates);
1653 table.
resize(candidatesCount);
1658 for (
unsigned i = 0; i < candidatesCount; i++)
1659 table[i].
copy(candidates[i]);
1662 if (!referenceBaseCloud.
reserve(4))
1666 for (
unsigned j = 0; j < 4; j++) {
1668 referenceBaseCloud.
addPoint(*p[j]);
1673 scores.reserve(candidatesCount);
1674 sortedscores.reserve(candidatesCount);
1675 tarray.reserve(candidatesCount);
1676 transforms.reserve(candidatesCount);
1683 if (scores.capacity() < candidatesCount ||
1684 sortedscores.capacity() < candidatesCount ||
1685 tarray.capacity() < candidatesCount ||
1686 transforms.capacity() < candidatesCount) {
1691 for (
unsigned i = 0; i < table.size(); i++) {
1692 dataBaseCloud.
reset();
1693 if (!dataBaseCloud.
reserve(4))
1695 for (
unsigned j = 0; j < 4; j++)
1697 *dataCloud->
getPoint(table[i].getIndex(j)));
1700 &dataBaseCloud, &referenceBaseCloud, t,
false))
1703 tarray.push_back(t);
1709 if (!b)
return false;
1710 for (
unsigned j = 0; j < 4; j++) {
1712 score +=
static_cast<float>((*q - *(p[j])).norm());
1715 scores.push_back(score);
1716 sortedscores.push_back(score);
1722 transforms.resize(0);
1724 candidates.resize(nbMaxCandidates);
1732 sort(sortedscores.begin(), sortedscores.end());
1733 float score = sortedscores[nbMaxCandidates - 1];
1735 for (
unsigned i = 0; i < scores.size(); i++) {
1736 if (scores[i] <= score && j < nbMaxCandidates) {
1737 candidates[i].copy(table[i]);
1738 transforms.push_back(tarray[i]);
1743 transforms = tarray;
constexpr PointCoordinateType PC_ONE
'1' as a PointCoordinateType value
constexpr double ZERO_TOLERANCE_D
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
float PointCoordinateType
Type of the coordinates of a (N-D) point.
cmdLineReadable * params[]
Garbage container (automatically deletes pointers when destroyed)
void add(C *item)
Puts an item in the trash.
void destroy(C *item)
To manually delete an item already in the trash.
Jacobi eigen vectors/values decomposition.
static bool GetMaxEigenValueAndVector(const SquareMatrix &eigenVectors, const EigenValues &eigenValues, Scalar &maxEigenValue, Scalar maxEigenVector[])
Returns the biggest eigenvalue and its associated eigenvector.
double normd() const
Returns vector norm (forces double precision output)
Type dot(const Vector3Tpl &v) const
Dot product.
Type norm2() const
Returns vector square norm.
Type norm() const
Returns vector norm.
Vector3Tpl cross(const Vector3Tpl &v) const
Cross product.
Vector3Tpl< double > toDouble() const
Cast operator to a double vector (explicit call version)
The octree structure used throughout the library.
unsigned char findBestLevelForComparisonWithOctree(const DgmOctree *theOtherOctree) const
int build(GenericProgressCallback *progressCb=nullptr)
Builds the structure.
virtual void getBoundingBox(CCVector3 &bbMin, CCVector3 &bbMax)=0
Returns the cloud bounding box.
virtual void placeIteratorAtBeginning()=0
Sets the cloud iterator at the beginning.
virtual const CCVector3 * getNextPoint()=0
Returns the next point (relatively to the global iterator position)
virtual unsigned size() const =0
Returns the number of points.
virtual bool isValid() const
Indicates if the distribution parameters are valid.
A generic 3D point cloud with index-based and presistent access to points.
A generic 3D point cloud with index-based point access.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
A generic mesh with index-based vertex access.
virtual void stop()=0
Notifies the fact that the process has ended.
virtual void setInfo(const char *infoStr)=0
Notifies some information about the ongoing process.
virtual void setMethodTitle(const char *methodTitle)=0
Notifies the algorithm title.
virtual bool textCanBeEdited() const
Returns whether the dialog title and info can be updated or not.
virtual void update(float percent)=0
Notifies the algorithm progress.
virtual bool isCancelRequested()=0
Checks if the process should be canceled.
unsigned findPointsLyingToDistance(const PointCoordinateType *queryPoint, ScalarType distance, ScalarType tolerance, std::vector< unsigned > &points)
bool findNearestNeighbour(const PointCoordinateType *queryPoint, unsigned &nearestPointIndex, ScalarType maxDist)
Nearest point search.
bool findPointBelowDistance(const PointCoordinateType *queryPoint, ScalarType maxDist)
Optimized version of nearest point search method.
GenericIndexedCloud * getAssociatedCloud() const
Gets the point cloud from which the tree has been build.
bool buildFromCloud(GenericIndexedCloud *cloud, GenericProgressCallback *progressCb=nullptr)
Builds the KD-tree.
The Normal/Gaussian statistical distribution.
bool computeParameters(const ScalarContainer &values) override
Computes the distribution parameters from a set of values.
bool getParameters(ScalarType &_mu, ScalarType &_sigma2) const
Returns the distribution parameters.
void reset()
Clears the cloud database.
virtual void invalidateBoundingBox()
Invalidates bounding box.
virtual bool reserve(unsigned newCapacity)
Reserves memory for the point database.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
unsigned size() const override
const CCVector3 * getPoint(unsigned index) const override
bool resize(unsigned newCount) override
Resizes the point database.
A very simple point cloud (no point duplication)
bool enableScalarField() override
Enables the scalar field associated to the cloud.
virtual bool addPointIndex(unsigned globalIndex)
Point global index insertion mechanism.
virtual GenericIndexedCloudPersist * getAssociatedCloud()
Returns the associated (source) cloud.
unsigned size() const override
Returns the number of points.
void invalidateBoundingBox()
Invalidates the bounding-box.
virtual unsigned getPointGlobalIndex(unsigned localIndex) const
virtual bool resize(unsigned n)
Presets the size of the vector used to store point references.
virtual void clear(bool releaseMemory=false)
Clears the cloud.
virtual void setAssociatedCloud(GenericIndexedCloudPersist *cloud)
Sets the associated (source) cloud.
virtual bool reserve(unsigned n)
Reserves some memory for hosting the point references.
ScalarType getPointScalarValue(unsigned pointIndex) const override
Returns the ith point associated scalar value.
A simple scalar field (to be associated to a point cloud)
virtual void computeMinAndMax()
Determines the min and max values.
void addElement(ScalarType value)
ScalarType & getValue(std::size_t index)
void setValue(std::size_t index, ScalarType value)
bool reserveSafe(std::size_t count)
Reserves memory (no exception thrown)
bool resizeSafe(std::size_t count, bool initNewElements=false, ScalarType valueForNewElements=0)
Resizes memory (no exception thrown)
static bool ValidValue(ScalarType value)
Returns whether a scalar value is valid or not.
unsigned currentSize() const
void toIdentity()
Sets matrix to identity.
Scalar ** m_values
The matrix rows.
Scalar trace() const
Returns trace.
bool isValid() const
Returns matrix validity.
void invalidate()
Invalidates matrix.
SquareMatrixTpl transposed() const
Returns the transposed version of this matrix.
void initFromQuaternion(const float q[])
Creates a rotation matrix from a quaternion (float version)
void setValue(unsigned row, unsigned column, Scalar value)
Sets a particular matrix value.
void scale(Scalar coef)
Scales matrix (all elements are multiplied by the same coef.)
Scalar getValue(unsigned row, unsigned column) const
Returns a particular matrix value.
__host__ __device__ float3 cross(float3 a, float3 b)
__host__ __device__ int2 abs(int2 v)
::ccPointCloud PointCloud
Generic file read and write utility for python interface.
SquareMatrixTpl< PointCoordinateType > SquareMatrix
Default CC square matrix type (PointCoordinateType)
bool LessThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
flann::Index< flann::L2< float > > KDTree
PointCloud * rotatedCloud
ReferenceCloud * CPSetRef
GenericIndexedCloudPersist * cloud
ModelCloud(const ModelCloud &m)