26 const float* viewMat) {
27 assert(poly && aCloud);
36 for (
unsigned i = 0; i <
count; ++i) {
46 if ((keepInside && pointInside) || (!keepInside && !pointInside)) {
64 unsigned vertCount = (polyVertices ? polyVertices->
size() : 0);
65 if (vertCount < 2)
return false;
71 for (
unsigned i = 1; i <= vertCount; ++i) {
73 polyVertices->
getPoint(i % vertCount, B);
77 if ((B.
y <= P.
y && P.
y < A.
y) || (A.
y <= P.
y && P.
y < B.
y)) {
79 (P.
x - B.
x) * (A.
y - B.
y) - (A.
x - B.
x) * (P.
y - B.
y);
80 if (A.
y < B.
y) t = -t;
81 if (t < 0) inside = !inside;
91 const CCVector2& P,
const std::vector<CCVector2>& polyVertices) {
93 std::size_t vertCount = polyVertices.size();
94 if (vertCount < 2)
return false;
98 for (
unsigned i = 1; i <= vertCount; ++i) {
100 const CCVector2& B = polyVertices[i % vertCount];
104 if ((B.
y <= P.
y && P.
y < A.
y) || (A.
y <= P.
y && P.
y < B.
y)) {
106 (P.
x - B.
x) * (A.
y - B.
y) - (A.
x - B.
x) * (P.
y - B.
y);
107 if (A.
y < B.
y) t = -t;
108 if (t < 0) inside = !inside;
128 for (
unsigned i = 0; i < cloud->
size(); ++i) {
132 if ((
dist >= minDist &&
dist <= maxDist) ^ outside) {
147 std::vector<ScalarType> values,
157 for (
unsigned i = 0; i < cloud->
size(); ++i) {
159 bool find_flag =
false;
160 for (
auto label : values) {
169 if (find_flag ^ outside) {
185 bool useSelectedVertices,
188 unsigned indexShift ,
189 std::vector<int>* triangleIndexMap ) {
190 if (!mesh || !selectedVertexIndexes ||
195 unsigned totalNumberOfVertices =
197 unsigned numberOfSelectedVertices = selectedVertexIndexes->
size();
202 std::vector<int> newPointIndexes;
205 newPointIndexes.resize(
206 totalNumberOfVertices,
208 }
catch (
const std::bad_alloc&) {
212 for (
unsigned i = 0; i < numberOfSelectedVertices; ++i) {
213 unsigned vertexIndex =
215 assert(vertexIndex < totalNumberOfVertices);
216 newPointIndexes[vertexIndex] =
static_cast<int>(i);
220 if (!useSelectedVertices) {
222 for (
unsigned i = 0; i < totalNumberOfVertices; ++i)
223 newPointIndexes[i] = (newPointIndexes[i] < 0 ? newIndex++ : -1);
230 unsigned numberOfTriangles = mesh->
size();
232 if (triangleIndexMap) {
234 triangleIndexMap->resize(numberOfTriangles);
235 }
catch (
const std::bad_alloc&) {
246 snprintf(buffer, 64,
"New vertex number: %u",
247 numberOfSelectedVertices);
255 destCloud ? destCloud
257 unsigned newTriangleCount = 0;
260 for (
unsigned i = 0; i < numberOfTriangles; ++i) {
268 bool keepTriangle =
true;
269 int newVertexIndexes[3];
270 for (
unsigned char j = 0; j < 3; ++j) {
271 int vertexIndex = tsi->
i[j];
272 assert(vertexIndex >= 0 &&
static_cast<unsigned>(vertexIndex) <
273 totalNumberOfVertices);
274 newVertexIndexes[j] = newPointIndexes[vertexIndex];
277 if (newVertexIndexes[j] < 0) {
278 keepTriangle =
false;
285 if (newTriangleCount == newMesh->
capacity() &&
295 newMesh->
addTriangle(indexShift + newVertexIndexes[0],
296 indexShift + newVertexIndexes[1],
297 indexShift + newVertexIndexes[2]);
299 if (triangleIndexMap) {
300 triangleIndexMap->at(i) =
301 static_cast<int>(newTriangleCount);
304 }
else if (triangleIndexMap) {
305 triangleIndexMap->at(i) = -1;
308 if (progressCb && !nprogress.
oneStep()) {
315 newPointIndexes.clear();
318 if (newMesh->
size() == 0) {
321 }
else if (newTriangleCount < newMesh->
size()) {
322 newMesh->
resize(newTriangleCount);
342 : insideIndex(inside), outsideIndex(outside) {}
351 unsigned vertCount = vertices->
size();
352 if (vertCount == vertices->
capacity() &&
369 unsigned char planeDim,
372 assert(outsideVertices || insideVertices);
377 unsigned minIndex = iA;
378 unsigned maxIndex = iB;
379 if (minIndex > maxIndex)
std::swap(minIndex, maxIndex);
380 key = (
static_cast<uint64_t
>(minIndex) << 32) |
381 static_cast<uint64_t
>(maxIndex);
392 CCVector3d I = A + (B - A) * (planeCoord - A.
u[planeDim]) /
393 (B.
u[planeDim] - A.
u[planeDim]);
397 if (insideVertices && !
AddVertex(I, insideVertices, iCinside))
401 if (outsideVertices && !
AddVertex(I, outsideVertices, iCoutside))
417 if (!mesh)
return true;
439 const std::vector<unsigned>& preservedTriangleIndexes,
440 std::vector<unsigned>* origTriIndexesMap =
nullptr) {
441 assert(origMesh && origVertices && newMesh && newVertices);
443 unsigned importedTriCount =
444 static_cast<unsigned>(preservedTriangleIndexes.size());
445 unsigned origVertCount = origVertices->
size();
446 unsigned newVertCount = newVertices->
size();
447 unsigned newTriCount = newMesh->
size();
452 std::vector<unsigned> newIndexMap;
453 newIndexMap.resize(origVertCount, 0);
457 for (
unsigned i = 0; i < importedTriCount; ++i) {
458 unsigned triIndex = preservedTriangleIndexes[i];
461 newIndexMap[tsi->
i1] = 1;
462 newIndexMap[tsi->
i2] = 1;
463 newIndexMap[tsi->
i3] = 1;
469 for (
unsigned i = 0; i < newTriCount; ++i) {
481 unsigned importedVertCount = 0;
483 for (
unsigned i = 0; i < origVertCount; ++i)
484 if (newIndexMap[i]) ++importedVertCount;
487 if (importedVertCount == 0) {
494 if (!newVertices->
reserve(newVertices->
size() + importedVertCount)) {
501 unsigned lastVertIndex = newVertCount;
502 for (
unsigned i = 0; i < origVertCount; ++i) {
503 if (newIndexMap[i]) {
505 newIndexMap[i] = lastVertIndex++;
512 for (
unsigned i = 0; i < newTriCount; ++i) {
523 if (importedTriCount) {
525 if (!newMesh->
reserve(newMesh->
size() + importedTriCount)) {
531 assert(!origTriIndexesMap ||
532 newMesh->
size() == origTriIndexesMap->size());
533 for (
unsigned i = 0; i < importedTriCount; ++i) {
534 unsigned triIndex = preservedTriangleIndexes[i];
538 newIndexMap[tsi->
i2],
539 newIndexMap[tsi->
i3]);
540 if (origTriIndexesMap)
541 origTriIndexesMap->push_back(triIndex);
545 }
catch (
const std::bad_alloc&) {
553 assert(!origTriIndexesMap || newMesh->
size() == origTriIndexesMap->size());
561 assert(srcVertices && newMesh && newVertices);
563 unsigned srcVertCount = srcVertices->
size();
564 unsigned newVertCount = newVertices->
size();
565 unsigned newTriCount = newMesh->
size();
569 std::vector<unsigned> newIndexMap;
570 newIndexMap.resize(srcVertCount, 0);
572 for (
unsigned i = 0; i < newTriCount; ++i) {
583 unsigned importedVertCount = 0;
585 for (
unsigned i = 0; i < srcVertCount; ++i)
586 if (newIndexMap[i]) ++importedVertCount;
589 if (importedVertCount == 0) {
596 if (!newVertices->
reserve(newVertices->
size() + importedVertCount)) {
603 unsigned lastVertIndex = newVertCount;
604 for (
unsigned i = 0; i < srcVertCount; ++i) {
605 if (newIndexMap[i]) {
607 newIndexMap[i] = lastVertIndex++;
614 for (
unsigned i = 0; i < newTriCount; ++i) {
624 }
catch (
const std::bad_alloc&) {
639 if (!mesh || !vertices || mesh->
size() == 0 || vertices->
size() < 3 ||
658 const double& epsilon = ioParams.
epsilon;
662 std::vector<unsigned> preservedTrianglesMinus;
663 std::vector<unsigned> preservedTrianglesPlus;
674 unsigned triCount = mesh->
size();
675 for (
unsigned i = 0; i < triCount; ++i) {
689 std::vector<unsigned char> minusVertIndexes, plusVertIndexes;
690 for (
unsigned char j = 0; j < 3; ++j) {
692 if (
std::abs(v.
u[Z] - planeZ) < epsilon) {
695 if (v.
u[Z] < planeZ) {
696 minusVertIndexes.push_back(j);
701 plusVertIndexes.push_back(j);
708 switch (minusVertIndexes.size() + plusVertIndexes.size()) {
712 preservedTrianglesMinus.push_back(i);
721 if (minusVertIndexes.empty()) {
724 preservedTrianglesPlus.push_back(i);
728 preservedTrianglesMinus.push_back(i);
735 if (minusVertIndexes.empty()) {
738 preservedTrianglesPlus.push_back(i);
739 }
else if (plusVertIndexes.empty()) {
742 preservedTrianglesMinus.push_back(i);
747 unsigned char iMinus = minusVertIndexes.front();
748 unsigned char iPlus = plusVertIndexes.front();
750 unsigned iCoutside, iCinside;
752 V[iMinus], origVertIndexes[iMinus],
753 V[iPlus], origVertIndexes[iPlus], iCoutside,
754 iCinside, planeZ, Z, outsideVertices,
763 unsigned char iCenter = 3 - iMinus - iPlus;
765 origVertIndexes[iMinus], iCinside,
767 ((iCenter + 1) % 3) == iMinus)
770 origVertIndexes[iPlus], iCoutside,
772 ((iCenter + 1) % 3) == iPlus)) {
783 if (minusVertIndexes.empty()) {
785 preservedTrianglesPlus.push_back(i);
786 }
else if (plusVertIndexes.empty()) {
788 preservedTrianglesMinus.push_back(i);
792 unsigned char iLeft, iRight1, iRight2;
793 bool leftIsMinus =
true;
794 if (minusVertIndexes.size() == 1) {
795 assert(plusVertIndexes.size() == 2);
796 iLeft = minusVertIndexes.front();
797 iRight1 = plusVertIndexes[0];
798 iRight2 = plusVertIndexes[1];
801 assert(minusVertIndexes.size() == 2);
802 iLeft = plusVertIndexes.front();
803 iRight1 = minusVertIndexes[0];
804 iRight2 = minusVertIndexes[1];
810 unsigned i1outside, i1inside;
811 unsigned i2outside, i2inside;
813 V[iRight1], origVertIndexes[iRight1],
814 V[iLeft], origVertIndexes[iLeft], i1outside,
815 i1inside, planeZ, Z, outsideVertices,
818 V[iRight2], origVertIndexes[iRight2],
819 V[iLeft], origVertIndexes[iLeft], i2outside,
820 i2inside, planeZ, Z, outsideVertices,
830 leftIsMinus ? i1inside : i1outside,
831 leftIsMinus ? i2inside : i2outside,
832 leftIsMinus ? minusMesh : plusMesh,
833 ((iLeft + 1) % 3) == iRight1)
835 || !
AddTriangle(leftIsMinus ? i1outside : i1inside,
836 leftIsMinus ? i2outside : i2inside,
837 origVertIndexes[iRight1],
838 leftIsMinus ? plusMesh : minusMesh,
839 ((iRight2 + 1) % 3) == iRight1)
842 leftIsMinus ? i2outside : i2inside,
843 origVertIndexes[iRight2],
844 leftIsMinus ? plusMesh : minusMesh,
845 ((iRight2 + 1) % 3) == iRight1)) {
858 }
catch (
const std::bad_alloc&) {
869 preservedTrianglesMinus) ||
871 preservedTrianglesPlus)) {
892 if (!origMesh || !origVertices || origMesh->
size() == 0 ||
905 const double& epsilon = ioParams.
epsilon;
910 std::vector<unsigned> preservedTrianglesInside1;
911 std::vector<unsigned> preservedTrianglesInside2;
912 std::vector<unsigned> preservedTrianglesOutside;
925 outsideMesh =
new SimpleMesh(outsideVertices,
true);
929 std::vector<unsigned>* preservedTrianglesInside =
930 &preservedTrianglesInside1;
931 std::vector<unsigned>* formerPreservedTriangles =
932 &preservedTrianglesInside2;
945 for (
unsigned d = 0; d < 6; ++d) {
948 unsigned char Z =
static_cast<unsigned char>(d / 2);
949 double planeCoord = ((d & 1) ? bbMax : bbMin).u[Z];
950 bool keepBelow = ((d & 1) ?
true :
false);
952 assert(preservedTrianglesInside && formerPreservedTriangles);
953 assert(insideVertices && insideMesh);
954 assert(sourceVertices && sourceMesh);
957 std::vector<unsigned> origTriIndexesMapInsideBackup;
959 origTriIndexesMapInsideBackup =
970 unsigned sourceTriCount =
971 sourceMesh ? sourceMesh->
size()
973 unsigned formerPreservedTriCount =
974 static_cast<unsigned>(formerPreservedTriangles->size());
975 unsigned triCount = sourceTriCount + formerPreservedTriCount;
977 for (
unsigned i = 0; i < triCount; ++i) {
978 bool triangleIsOriginal =
false;
979 unsigned souceTriIndex = 0;
981 if (i < sourceTriCount) {
983 triangleIsOriginal = (sourceMesh == origMesh);
987 (*formerPreservedTriangles)[i - sourceTriCount];
988 triangleIsOriginal =
true;
993 unsigned vertIndexes[3] = {tsi->
i1, tsi->
i2, tsi->
i3};
994 if (triangleIsOriginal) {
1016 ->getPoint(vertIndexes[0] &
1023 ->getPoint(vertIndexes[1] &
1030 ->getPoint(vertIndexes[2] &
1039 preservedTrianglesOutside.push_back(i);
1047 std::vector<unsigned char> insideLocalVertIndexes,
1048 outsideLocalVertIndexes;
1049 for (
unsigned char j = 0; j < 3; ++j) {
1051 if (
std::abs(v.
u[Z] - planeCoord) < epsilon) {
1054 if (v.
u[Z] < planeCoord) {
1055 insideLocalVertIndexes.push_back(j);
1060 outsideLocalVertIndexes.push_back(j);
1067 bool isFullyInside =
false;
1068 bool isFullyOutside =
false;
1069 switch (insideLocalVertIndexes.size() +
1070 outsideLocalVertIndexes.size()) {
1074 isFullyInside =
true;
1080 if (insideLocalVertIndexes.empty()) {
1083 isFullyOutside =
true;
1087 isFullyInside =
true;
1094 if (insideLocalVertIndexes.empty()) {
1096 isFullyOutside =
true;
1097 }
else if (outsideLocalVertIndexes.empty()) {
1099 isFullyInside =
true;
1104 unsigned char iInside =
1105 insideLocalVertIndexes.front();
1106 unsigned char iOuside =
1107 outsideLocalVertIndexes.front();
1109 unsigned char iCenter = 3 - iInside - iOuside;
1110 unsigned iCoutside, iCinside;
1114 V[iInside], vertIndexes[iInside],
1115 V[iOuside], vertIndexes[iOuside],
1116 iCoutside, iCinside, planeCoord, Z,
1117 outsideVertices, insideVertices)
1120 vertIndexes[iCenter],
1121 vertIndexes[iInside],
1122 keepBelow ? iCinside : iCoutside,
1123 keepBelow ? insideMesh : outsideMesh,
1124 ((iCenter + 1) % 3) == iInside)
1127 vertIndexes[iCenter],
1128 vertIndexes[iOuside],
1129 keepBelow ? iCoutside : iCinside,
1130 keepBelow ? outsideMesh : insideMesh,
1131 ((iCenter + 1) % 3) == iOuside)) {
1140 assert(triangleIsOriginal ||
1142 origTriIndexesMapInsideBackup
1144 unsigned origTriIndex =
1147 : origTriIndexesMapInsideBackup
1162 if (insideLocalVertIndexes.empty()) {
1164 isFullyOutside =
true;
1165 }
else if (outsideLocalVertIndexes.empty()) {
1167 isFullyInside =
true;
1171 unsigned char iLeft, iRight1, iRight2;
1172 bool leftIsInside =
true;
1173 if (insideLocalVertIndexes.size() == 1) {
1174 assert(outsideLocalVertIndexes.size() == 2);
1175 iLeft = insideLocalVertIndexes.front();
1176 iRight1 = outsideLocalVertIndexes[0];
1177 iRight2 = outsideLocalVertIndexes[1];
1178 leftIsInside = keepBelow;
1180 assert(insideLocalVertIndexes.size() == 2);
1181 iLeft = outsideLocalVertIndexes.front();
1182 iRight1 = insideLocalVertIndexes[0];
1183 iRight2 = insideLocalVertIndexes[1];
1184 leftIsInside = !keepBelow;
1190 unsigned i1outside, i1inside;
1191 unsigned i2outside, i2inside;
1193 V[iRight1], vertIndexes[iRight1],
1194 V[iLeft], vertIndexes[iLeft], i1outside,
1195 i1inside, planeCoord, Z,
1196 outsideVertices, insideVertices)
1199 V[iRight2], vertIndexes[iRight2],
1200 V[iLeft], vertIndexes[iLeft],
1201 i2outside, i2inside, planeCoord, Z,
1202 outsideVertices, insideVertices)
1207 leftIsInside ? i1inside : i1outside,
1208 leftIsInside ? i2inside : i2outside,
1209 leftIsInside ? insideMesh : outsideMesh,
1210 ((iLeft + 1) % 3) == iRight1)
1214 leftIsInside ? i1outside : i1inside,
1215 leftIsInside ? i2outside : i2inside,
1216 vertIndexes[iRight1],
1217 leftIsInside ? outsideMesh : insideMesh,
1218 ((iRight2 + 1) % 3) == iRight1)
1222 vertIndexes[iRight1],
1223 leftIsInside ? i2outside : i2inside,
1224 vertIndexes[iRight2],
1225 leftIsInside ? outsideMesh : insideMesh,
1226 ((iRight2 + 1) % 3) == iRight1)) {
1235 assert(triangleIsOriginal ||
1237 origTriIndexesMapInsideBackup
1239 unsigned origTriIndex =
1242 : origTriIndexesMapInsideBackup
1263 if (isFullyInside || isFullyOutside) {
1265 if (!keepBelow)
std::swap(isFullyInside, isFullyOutside);
1267 if (triangleIsOriginal) {
1269 preservedTrianglesInside->push_back(souceTriIndex);
1271 preservedTrianglesOutside.push_back(souceTriIndex);
1275 vertIndexes[0], vertIndexes[1],
1277 isFullyInside ? insideMesh : outsideMesh,
1284 assert(souceTriIndex <
1285 origTriIndexesMapInsideBackup.size());
1286 unsigned origTriIndex =
1287 origTriIndexesMapInsideBackup
1305 outsideVertices))) {
1311 if (insideMesh->
size() == 0 && preservedTrianglesInside->empty()) {
1318 if (insideMesh == insideMesh1) {
1319 assert(sourceMesh == insideMesh2 || sourceMesh == origMesh);
1320 insideMesh2->
clear();
1321 insideVertices2->
reset();
1322 sourceMesh = insideMesh1;
1323 sourceVertices = insideVertices1;
1324 insideMesh = insideMesh2;
1325 insideVertices = insideVertices2;
1326 preservedTrianglesInside2.
resize(0);
1327 preservedTrianglesInside = &preservedTrianglesInside2;
1328 formerPreservedTriangles = &preservedTrianglesInside1;
1330 assert(sourceMesh == insideMesh1 || sourceMesh == origMesh);
1331 insideMesh1->
clear();
1332 insideVertices1->
reset();
1333 sourceMesh = insideMesh2;
1334 sourceVertices = insideVertices2;
1335 insideMesh = insideMesh1;
1336 insideVertices = insideVertices1;
1337 preservedTrianglesInside1.
resize(0);
1338 preservedTrianglesInside = &preservedTrianglesInside1;
1339 formerPreservedTriangles = &preservedTrianglesInside2;
1346 }
catch (
const std::bad_alloc&) {
1353 formerPreservedTriangles->resize(0);
1358 insideVertices, *preservedTrianglesInside,
1364 outsideVertices, preservedTrianglesOutside,
1372 if (insideMesh == insideMesh1) {
1374 insideMesh2 =
nullptr;
1375 insideVertices2 =
nullptr;
1378 insideMesh1 =
nullptr;
1379 insideVertices1 =
nullptr;
constexpr double EPSILON_VALUE
Vector2Tpl< PointCoordinateType > CCVector2
Default 2D Vector.
float PointCoordinateType
Type of the coordinates of a (N-D) point.
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
virtual unsigned size() const =0
Returns the number of points.
virtual ScalarType getPointScalarValue(unsigned pointIndex) const =0
Returns the ith point associated scalar value.
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 VerticesIndexes * getNextTriangleVertIndexes()=0
virtual VerticesIndexes * getTriangleVertIndexes(unsigned triangleIndex)=0
Returns the indexes of the vertices of a given triangle.
virtual unsigned size() const =0
Returns the number of triangles.
virtual void placeIteratorAtBeginning()=0
Places the mesh iterator at the beginning.
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.
bool oneStep()
Increments total progress value of a single unit.
void reset()
Clears the cloud database.
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
unsigned capacity() const
Returns cloud capacity (i.e. reserved size)
bool resize(unsigned newCount) override
Resizes the point database.
A very simple point cloud (no point duplication)
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.
virtual unsigned getPointGlobalIndex(unsigned localIndex) const
A simple mesh structure, with index-based vertex access.
virtual bool resize(unsigned n)
Resizes the mesh database.
virtual unsigned size() const override
Returns the number of triangles.
unsigned capacity() const
Returns the mesh capacity.
void clear()
Clears the mesh.
virtual void addTriangle(unsigned i1, unsigned i2, unsigned i3)
Adds a triangle to the mesh.
VerticesIndexes * getTriangleVertIndexes(unsigned triangleIndex) override
Returns the indexes of the vertices of a given triangle.
virtual bool reserve(unsigned n)
Reserves the memory to store the triangles (as 3 indexes each)
__host__ __device__ int2 abs(int2 v)
static double dist(double x1, double y1, double x2, double y2)
static void error(char *msg)
::ccPointCloud PointCloud
Generic file read and write utility for python interface.
SquareMatrixTpl< PointCoordinateType > SquareMatrix
Default CC square matrix type (PointCoordinateType)
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
InsideOutsideIndexes(unsigned inside, unsigned outside)
Triangle described by the indexes of its 3 vertices.