31 if (!cloud)
return nullptr;
33 unsigned char dim1 = (dim > 0 ? dim - 1 : 2);
34 unsigned char dim2 = (dim < 2 ? dim + 1 : 0);
47 C = (bbMin + bbMax) / 2;
56 snprintf(buffer, 32,
"Number of points = %u",
count);
68 sqrt(P.
u[dim1] * P.
u[dim1] + P.
u[dim2] * P.
u[dim2]);
73 if (progressCb && !nprogress.
oneStep()) {
94 if (!cloud)
return nullptr;
102 unsigned char dim1 = (dim > 0 ? dim - 1 : 2);
103 unsigned char dim2 = (dim < 2 ? dim + 1 : 0);
108 float q = 1.0f / (1.0f + tan_alpha * tan_alpha);
117 snprintf(buffer, 32,
"Number of points = %u",
count);
124 for (
unsigned i = 0; i <
count; i++) {
129 sqrt(P.
u[dim1] * P.
u[dim1] + P.
u[dim2] * P.
u[dim2]);
137 #ifdef ORTHO_CONIC_PROJECTION
139 if (lat * z2 < 0.0) lat = -lat;
149 if (x2 * P.
u[dim] - z2 * u < 0) alt = -alt;
153 if (progressCb && !nprogress.
oneStep()) {
181 snprintf(buffer, 32,
"Number of points = %u",
count);
196 if (progressCb && !nprogress.
oneStep()) {
207 return transformedCloud;
221 delete transformedCloud;
229 delete transformedCloud;
239 snprintf(buffer, 32,
"Number of points = %u",
count);
248 for (
unsigned i = 0; i <
count; ++i) {
263 if (progressCb && !nprogress.
oneStep()) {
272 return transformedCloud;
280 std::string& outputErrorStr) {
282 outputErrorStr =
"Invalid input cloud";
289 outputErrorStr =
"Invalid projection dimension";
292 const unsigned char Z =
static_cast<unsigned char>(dim);
293 const unsigned char X = Z == 2 ? 0 : Z + 1;
294 const unsigned char Y =
X == 2 ? 0 :
X + 1;
297 std::vector<CCVector2> the2DPoints;
299 the2DPoints.resize(
count);
302 outputErrorStr =
"Not enough memory";
307 for (
unsigned i = 0; i <
count; ++i) {
309 the2DPoints[i].
x = P->
u[
X];
310 the2DPoints[i].y = P->
u[Y];
322 if (maxEdgeLength > 0) {
324 if (dm->
size() == 0) {
326 outputErrorStr =
"No triangle left after pruning";
352 return a.
x < b.
x || (a.
x == b.
x && a.
y < b.
y);
356 std::vector<IndexedCCVector2>&
points,
357 std::list<IndexedCCVector2*>& hullPoints) {
358 std::size_t n =
points.size();
365 for (std::size_t i = 0; i < n; i++) {
366 while (hullPoints.size() >= 2) {
367 std::list<IndexedCCVector2*>::iterator itB = hullPoints.end();
369 std::list<IndexedCCVector2*>::iterator itA = itB;
371 if ((**itB - **itA).
cross(
points[i] - **itA) <= 0) {
372 hullPoints.pop_back();
379 hullPoints.push_back(&
points[i]);
380 }
catch (
const std::bad_alloc&) {
389 std::size_t t = hullPoints.size() + 1;
390 for (
int i =
static_cast<int>(n) - 2; i >= 0; i--) {
391 while (hullPoints.size() >= t) {
392 std::list<IndexedCCVector2*>::iterator itB = hullPoints.end();
394 std::list<IndexedCCVector2*>::iterator itA = itB;
396 if ((**itB - **itA).
cross(
points[i] - **itA) <= 0) {
397 hullPoints.pop_back();
404 hullPoints.push_back(&
points[i]);
405 }
catch (
const std::bad_alloc&) {
413 if (hullPoints.size() > 1 &&
414 hullPoints.front()->x == hullPoints.back()->x &&
415 hullPoints.front()->y == hullPoints.back()->y) {
416 hullPoints.pop_back();
433 if (cross_AB_AC * cross_AB_AD > 0) {
444 if (cross_CD_CA * cross_CD_CB > 0) {
463 if (dot_AB_AC >= 0 && dot_AB_AC < dAB * AC.
norm()) {
469 if (dot_AB_AD >= 0 && dot_AB_AD < dAB * AD.
norm()) {
475 return (dot_AB_AC * dot_AB_AD < 0);
492 Edge() : nearestPointIndex(0), nearestPointSquareDist(-1.0f) {}
495 unsigned _nearestPointIndex,
496 float _nearestPointSquareDist)
498 nearestPointIndex(_nearestPointIndex),
499 nearestPointSquareDist(_nearestPointSquareDist) {}
518 const std::vector<Vertex2D>&
points,
519 const std::vector<HullPointFlags>& pointFlags,
522 bool allowLongerChunks =
false) {
527 unsigned pointCount =
static_cast<unsigned>(
points.size());
528 for (
unsigned i = 0; i < pointCount; ++i) {
533 if (P.
index == (*itA)->index || P.
index == (*itB)->index)
continue;
537 if (AB.
x * AP.
y - AB.
y * AP.
x < 0) {
542 if (
dot >= 0 &&
dot <= squareLengthAB) {
545 if (minDist2 < 0 || dist2 < minDist2) {
551 if (squareLengthAP >= minSquareEdgeLength &&
552 squareLengthBP >= minSquareEdgeLength &&
553 (allowLongerChunks || (squareLengthAP < squareLengthAB ||
554 squareLengthBP < squareLengthAB))) {
561 return (minDist2 < 0 ? minDist2 : minDist2 / squareLengthAB);
565 std::vector<IndexedCCVector2>&
points,
566 std::list<IndexedCCVector2*>& hullPoints,
572 if (hullPoints.size() < 2 || maxSquareEdgeLength <= 0)
return true;
574 unsigned pointCount =
static_cast<unsigned>(
points.size());
576 std::vector<HullPointFlags> pointFlags;
588 for (std::size_t i = 0; i < pointCount; ++i) {
599 minSquareEdgeLength =
600 (maxP - minP).norm2() /
603 minSquareEdgeLength =
604 std::min(minSquareEdgeLength, maxSquareEdgeLength / 10);
607 for (std::list<IndexedCCVector2*>::iterator itA = hullPoints.begin();
608 itA != hullPoints.end(); ++itA) {
609 std::list<IndexedCCVector2*>::iterator itB = itA;
611 if (itB == hullPoints.end()) itB = hullPoints.begin();
612 if ((**itB - **itA).norm2() < minSquareEdgeLength) {
614 hullPoints.erase(itB);
618 if (hullPoints.size() < 2) {
627 bool somethingHasChanged =
true;
628 while (somethingHasChanged) {
630 somethingHasChanged =
false;
641 std::multiset<Edge> edges;
643 for (std::list<IndexedCCVector2*>::iterator itA =
645 itA != hullPoints.end(); ++itA) {
646 std::list<IndexedCCVector2*>::iterator itB = itA;
648 if (itB == hullPoints.end()) itB = hullPoints.begin();
652 if ((**itB - **itA).norm2() > maxSquareEdgeLength) {
653 unsigned nearestPointIndex = 0;
656 nearestPointIndex, itA, itB,
points,
657 pointFlags, minSquareEdgeLength,
658 maxSquareEdgeLength, step > 1);
660 if (minSquareDist >= 0) {
661 Edge e(itA, nearestPointIndex, minSquareDist);
670 while (!edges.empty()) {
673 Edge e = *edges.begin();
674 edges.erase(edges.begin());
679 if (itB == hullPoints.end()) itB = hullPoints.begin();
705 bool intersect =
false;
709 itI != hullPoints.end(); ++itI, ++itJ) {
710 if (itJ == hullPoints.end()) itJ = hullPoints.begin();
712 if (((*itI)->index != (*itA)->index &&
713 (*itJ)->index != (*itA)->index &&
717 ((*itI)->index != (*itB)->index &&
718 (*itJ)->index != (*itB)->index &&
731 itB == hullPoints.begin() ? hullPoints.end() : itB,
737 somethingHasChanged =
true;
741 if (!edges.empty()) {
742 std::vector<VertexIterator> removed;
743 std::multiset<Edge>::const_iterator lastValidIt =
745 for (std::multiset<Edge>::const_iterator it =
747 it != edges.end(); ++it) {
748 if ((*it).nearestPointIndex ==
751 removed.push_back((*it).itA);
754 if (edges.empty())
break;
755 if (lastValidIt != edges.end())
766 for (std::size_t i = 0; i < removed.size(); ++i) {
770 if (itD == hullPoints.end())
771 itD = hullPoints.begin();
773 unsigned nearestPointIndex = 0;
776 nearestPointIndex, itC, itD,
points,
777 pointFlags, minSquareEdgeLength,
778 maxSquareEdgeLength);
780 if (minSquareDist >= 0) {
781 Edge e(itC, nearestPointIndex, minSquareDist);
788 if ((P - **itA).norm2() > maxSquareEdgeLength) {
789 unsigned nearestPointIndex = 0;
794 maxSquareEdgeLength);
796 if (minSquareDist >= 0) {
797 Edge e(itA, nearestPointIndex, minSquareDist);
802 if ((**itB - P).norm2() > maxSquareEdgeLength) {
803 unsigned nearestPointIndex = 0;
808 maxSquareEdgeLength);
810 if (minSquareDist >= 0) {
811 Edge e(itP, nearestPointIndex, minSquareDist);
828 for (
unsigned i = 0; i < cloud.
size(); ++i) {
834 for (
unsigned i = 0; i < cloud.
size(); ++i) {
836 *N = (
R * (*N)).toPC();
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Type dot(const Vector2Tpl &v) const
Dot product.
Type norm() const
Returns vector norm.
Type cross(const Vector2Tpl &v) const
Cross product.
Type norm2() const
Returns vector square norm.
A class to compute and handle a Delaunay 2D mesh on a subset of points.
virtual unsigned size() const override
Returns the number of triangles.
bool removeTrianglesWithEdgesLongerThan(PointCoordinateType maxEdgeLength)
Filters out the triangles based on their edge length.
virtual bool buildMesh(const std::vector< CCVector2 > &points2D, std::size_t pointCountToUse, std::string &outputErrorStr)
Build the Delaunay mesh on top a set of 2D points.
virtual void linkMeshWith(GenericIndexedCloud *aCloud, bool passOwnership=false)
Associate this mesh to a point cloud.
static constexpr int USE_ALL_POINTS
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.
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.
virtual bool normalsAvailable() const
Returns whether normals are available.
virtual const CCVector3 * getNormal(unsigned index) const
If per-point normals are available, returns the one at a specific index.
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.
static constexpr bool DO_NOT_DUPLICATE_VERTICES
GenericIndexedMesh * triangulateOnPlane(bool duplicateVertices, PointCoordinateType maxEdgeLength, std::string &outputErrorStr)
Applies 2D Delaunay triangulation.
bool oneStep()
Increments total progress value of a single unit.
virtual bool reserve(unsigned newCapacity)
Reserves memory for the point database.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
bool reserveNormals(unsigned newCount)
Reserves memory to store the normals.
void addNormal(const CCVector3 &N)
Adds a normal.
__host__ __device__ float3 cross(float3 a, float3 b)
__host__ __device__ float dot(float2 a, float2 b)
__host__ __device__ int2 abs(int2 v)
::ccPointCloud PointCloud
Generic file read and write utility for python interface.
float DegreesToRadians(int degrees)
Convert degrees to radians.
TRIANGULATION_TYPES
Triangulation types.
@ DELAUNAY_2D_BEST_LS_PLANE
@ DELAUNAY_2D_AXIS_ALIGNED
unsigned nearestPointIndex
float nearestPointSquareDist
bool operator<(const Edge &e) const
Edge(const VertexIterator &A, unsigned _nearestPointIndex, float _nearestPointSquareDist)