2#include <boost/container/small_vector.hpp>
21 std::vector<SimplexId> offsets(cellNumber + 1);
23 std::vector<SimplexId> neighborsId(cellNumber);
25 for(
SimplexId i = 0; i < edgeNumber; i++) {
26 if(edgeStars.
size(i) == 2) {
28 const auto cs0 = edgeStars.
get(i, 0);
29 const auto cs1 = edgeStars.
get(i, 1);
36 for(
size_t i = 1; i < offsets.size(); ++i) {
37 offsets[i] += offsets[i - 1];
41 std::vector<SimplexId> neighbors(offsets.back());
44 for(
SimplexId i = 0; i < edgeNumber; i++) {
45 if(edgeStars.
size(i) == 2) {
47 const auto cs0 = edgeStars.
get(i, 0);
48 const auto cs1 = edgeStars.
get(i, 1);
49 neighbors[offsets[cs0] + neighborsId[cs0]] = cs1;
51 neighbors[offsets[cs1] + neighborsId[cs1]] = cs0;
57 cellNeighbors.
setData(std::move(neighbors), std::move(offsets));
59 printMsg(
"Built " + std::to_string(cellNumber) +
" cell neighbors", 1,
71 auto localVertexStars = vertexStars;
74 if(!localVertexStars) {
75 localVertexStars = &defaultVertexStars;
78 if(localVertexStars->empty()) {
91 using boost::container::small_vector;
93 std::vector<small_vector<SimplexId, 3>> neighbors(cellNumber);
95#ifdef TTK_ENABLE_OPENMP
96#pragma omp parallel for num_threads(threadNumber_)
98 for(
SimplexId cid = 0; cid < cellNumber; cid++) {
101 for(
SimplexId j = 0; j < nbVertCell; j++) {
110 while(pos0 < localVertexStars->size(v0)
111 && pos1 < localVertexStars->size(v1)) {
113 SimplexId biggest = localVertexStars->get(v0, pos0);
114 if(localVertexStars->get(v1, pos1) > biggest) {
115 biggest = localVertexStars->get(v1, pos1);
118 for(
SimplexId l = pos0; l < localVertexStars->size(v0); l++) {
119 if(localVertexStars->get(v0, l) < biggest) {
125 for(
SimplexId l = pos1; l < localVertexStars->size(v1); l++) {
126 if(localVertexStars->get(v1, l) < biggest) {
133 if(localVertexStars->get(v0, pos0) == localVertexStars->get(v1, pos1)) {
134 if(localVertexStars->get(v0, pos0) != cid) {
135 intersection = localVertexStars->get(v0, pos0);
144 if(intersection != -1) {
145 neighbors[cid].emplace_back(intersection);
153 printMsg(
"Built " + std::to_string(cellNumber) +
" cell neighbors", 1,
163 const std::vector<std::array<SimplexId, 2>> &edgeList,
164 std::vector<std::array<SimplexId, 3>> *triangleEdgeList)
const {
167#ifndef TTK_ENABLE_KAMIKAZE
168 if(vertexNumber <= 0)
172 auto localTriangleEdgeList = triangleEdgeList;
173 std::vector<std::array<SimplexId, 3>> defaultTriangleEdgeList{};
174 if(!localTriangleEdgeList) {
175 localTriangleEdgeList = &defaultTriangleEdgeList;
178 if(localTriangleEdgeList->empty()) {
180 vertexNumber, cellArray, *localTriangleEdgeList, edgeList);
183 const auto edgeNumber{edgeList.size()};
185 std::vector<SimplexId> offsets(edgeNumber + 1);
187 std::vector<SimplexId> trianglesId(edgeNumber);
195 for(
const auto &te : *localTriangleEdgeList) {
196 offsets[te[0] + 1]++;
197 offsets[te[1] + 1]++;
198 offsets[te[2] + 1]++;
202 for(
size_t i = 1; i < offsets.size(); ++i) {
203 offsets[i] += offsets[i - 1];
207 std::vector<SimplexId> edgeTriangles(offsets.back());
210 for(
size_t i = 0; i < localTriangleEdgeList->size(); ++i) {
211 const auto &te{(*localTriangleEdgeList)[i]};
212 edgeTriangles[offsets[te[0]] + trianglesId[te[0]]] = i;
213 trianglesId[te[0]]++;
214 edgeTriangles[offsets[te[1]] + trianglesId[te[1]]] = i;
215 trianglesId[te[1]]++;
216 edgeTriangles[offsets[te[2]] + trianglesId[te[2]]] = i;
217 trianglesId[te[2]]++;
221 edgeTriangleList.
setData(std::move(edgeTriangles), std::move(offsets));
223 printMsg(
"Built " + std::to_string(edgeNumber) +
" edge triangles", 1,
232 std::vector<std::array<SimplexId, 3>> *triangleList,
234 std::vector<std::array<SimplexId, 4>> *cellTriangleList)
const {
239#ifndef TTK_ENABLE_KAMIKAZE
240 if(vertexNumber <= 0)
242 if((!triangleList) && (!triangleStars) && (!cellTriangleList)) {
251 this->
printWrn(
"Calling buildTriangleList is useless in "
252 + std::to_string(dim) +
"D, skipping...");
262 std::vector<std::array<SimplexId, 4>> defaultCellTriangleList{};
263 if(triangleStars !=
nullptr && cellTriangleList ==
nullptr) {
264 cellTriangleList = &defaultCellTriangleList;
267 if(cellTriangleList) {
268 cellTriangleList->resize(cellNumber, {-1, -1, -1, -1});
271 struct TriangleData {
273 std::array<SimplexId, 2> highVerts{};
276 TriangleData(std::array<SimplexId, 2> hVerts,
SimplexId i)
277 : highVerts{hVerts},
id{i} {
281 using boost::container::small_vector;
283 std::vector<small_vector<TriangleData, 8>> triangleTable(vertexNumber);
290 for(
SimplexId cid = 0; cid < cellNumber; cid++) {
292 for(
size_t j = 0; j < 4; j++) {
293 std::array<SimplexId, 3> triangle{};
294 for(
size_t k = 0; k < 3; k++) {
298 std::sort(triangle.begin(), triangle.end());
299 auto &ttable = triangleTable[triangle[0]];
304 for(
auto &d : ttable) {
305 if(d.highVerts[0] == triangle[1] && d.highVerts[1] == triangle[2]) {
307 if(cellTriangleList !=
nullptr) {
308 (*cellTriangleList)[cid][j] = d.id;
316 TriangleData{{triangle[1], triangle[2]}, nTriangles});
317 if(cellTriangleList !=
nullptr) {
318 (*cellTriangleList)[cid][j] = nTriangles;
330 triangleList->resize(nTriangles);
335#ifdef TTK_ENABLE_OPENMP
336#pragma omp parallel for num_threads(this->threadNumber_)
338 for(
SimplexId i = 0; i < vertexNumber; ++i) {
339 const auto &ttable = triangleTable[i];
340 for(
const auto &data : ttable) {
341 if(triangleList !=
nullptr) {
342 (*triangleList)[data.id] = {i, data.highVerts[0], data.highVerts[1]};
350 if(cellTriangleList !=
nullptr && triangleStars !=
nullptr) {
351 std::vector<SimplexId> offsets(nTriangles + 1);
353 std::vector<SimplexId> starIds(nTriangles);
356 for(
const auto &c : *cellTriangleList) {
364 for(
size_t i = 1; i < offsets.size(); ++i) {
365 offsets[i] += offsets[i - 1];
369 std::vector<SimplexId> triangleSt(offsets.back());
372 for(
size_t i = 0; i < cellTriangleList->size(); ++i) {
373 const auto &ct{(*cellTriangleList)[i]};
374 triangleSt[offsets[ct[0]] + starIds[ct[0]]] = i;
376 triangleSt[offsets[ct[1]] + starIds[ct[1]]] = i;
378 triangleSt[offsets[ct[2]] + starIds[ct[2]]] = i;
380 triangleSt[offsets[ct[3]] + starIds[ct[3]]] = i;
385 triangleStars->
setData(std::move(triangleSt), std::move(offsets));
388 printMsg(
"Built " + std::to_string(nTriangles) +
" triangles", 1,
403 std::vector<std::array<SimplexId, 3>> &triangleEdgeList,
404 const std::vector<std::array<SimplexId, 2>> &edgeList,
406 std::vector<std::array<SimplexId, 3>> *triangleList,
408 std::vector<std::array<SimplexId, 4>> *cellTriangleList)
const {
410 auto localVertexEdgeList = vertexEdgeList;
412 if(!localVertexEdgeList) {
413 localVertexEdgeList = &defaultVertexEdgeList;
416 if(localVertexEdgeList->empty()) {
423 vertexNumber, edgeList, (*localVertexEdgeList));
430 auto localTriangleList = triangleList;
431 std::vector<std::array<SimplexId, 3>> defaultTriangleList{};
432 if(!localTriangleList) {
433 localTriangleList = &defaultTriangleList;
435 if(!localTriangleList->size()) {
438 triangleStarList, cellTriangleList);
441 triangleEdgeList.resize(localTriangleList->size());
451#ifdef TTK_ENABLE_OPENMP
452#pragma omp parallel for num_threads(threadNumber_)
454 for(
size_t i = 0; i < localTriangleList->size(); i++) {
455 const auto &t = (*localTriangleList)[i];
456 const auto beg0 = localVertexEdgeList->get_ptr(t[0], 0);
457 const auto end0 = beg0 + localVertexEdgeList->size(t[0]);
458 const auto beg1 = localVertexEdgeList->get_ptr(t[1], 0);
459 const auto end1 = beg1 + localVertexEdgeList->size(t[1]);
460 const auto beg2 = localVertexEdgeList->get_ptr(t[2], 0);
461 const auto end2 = beg2 + localVertexEdgeList->size(t[2]);
462 std::set_intersection(beg0, end0, beg1, end1, &triangleEdgeList[i][0]);
463 std::set_intersection(beg0, end0, beg2, end2, &triangleEdgeList[i][1]);
464 std::set_intersection(beg1, end1, beg2, end2, &triangleEdgeList[i][2]);
465 std::sort(triangleEdgeList[i].
begin(), triangleEdgeList[i].
end());
468 SimplexId const triangleNumber = localTriangleList->size();
470 printMsg(
"Built " + std::to_string(triangleNumber) +
" triangle edges", 1,
477 const std::vector<std::array<SimplexId, 3>> &triangleList,
482#ifndef TTK_ENABLE_KAMIKAZE
483 if(triangleList.empty())
485 if((triangleStars.
empty()) || (triangleStars.
size() != triangleList.size()))
494 this->
printWrn(
"Calling buildTriangleLinks is useless in 2D, skipping...");
498 const SimplexId triangleNumber = triangleList.size();
499 std::vector<SimplexId> offsets(triangleNumber + 1);
501 std::vector<SimplexId> links(triangleStars.
dataSize());
506#ifdef TTK_ENABLE_OPENMP
507#pragma omp parallel for num_threads(threadNumber_)
509 for(
SimplexId i = 0; i < triangleNumber; i++) {
512 offsets[i] = triangleStars.
offset(i);
514 const auto &t = triangleList[i];
517 for(
size_t k = 0; k < 4; k++) {
519 if(v != t[0] && v != t[1] && v != t[2]) {
520 links[offsets[i] + j] = v;
528 offsets[triangleNumber] = triangleStars.
offset(triangleNumber);
530 triangleLinks.
setData(std::move(links), std::move(offsets));
532 printMsg(
"Built " + std::to_string(triangleNumber) +
" triangle links", 1,
540 const std::vector<std::array<SimplexId, 3>> &triangleList,
547 std::vector<SimplexId> offsets(vertexNumber + 1);
549 std::vector<SimplexId> trianglesId(vertexNumber);
552 for(
const auto &t : triangleList) {
559 for(
size_t i = 1; i < offsets.size(); ++i) {
560 offsets[i] += offsets[i - 1];
564 std::vector<SimplexId> data(offsets.back());
567 for(
size_t i = 0; i < triangleList.size(); ++i) {
568 const auto &t{triangleList[i]};
569 data[offsets[t[0]] + trianglesId[t[0]]] = i;
571 data[offsets[t[1]] + trianglesId[t[1]]] = i;
573 data[offsets[t[2]] + trianglesId[t[2]]] = i;
578 vertexTriangles.
setData(std::move(data), std::move(offsets));
580 printMsg(
"Built " + std::to_string(vertexNumber) +
" vertex triangles", 1,
virtual int setThreadNumber(const int threadNumber)
CellArray generic array of cells
LongSimplexId getCellVertex(const LongSimplexId cellId, const SimplexId localVertId) const
LongSimplexId getNbCells() const
Get the number of cells in the array.
SimplexId getCellVertexNumber(const LongSimplexId cellId) const
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
void setDebugMsgPrefix(const std::string &prefix)
virtual int setDebugLevel(const int &debugLevel)
Replacement for std::vector<std::vector<SimplexId>>
size_t dataSize() const
Returns the size of the data_ member.
SimplexId get(SimplexId id, SimplexId local) const
Returns the data inside the sub-vectors.
void setData(std::vector< SimplexId > &&data, std::vector< SimplexId > &&offsets)
Set internal data from pre-existing vectors.
void fillFrom(const std::vector< T > &src, int threadNumber=1)
Fill buffers from a std::vector<std::vector<SimplexId>>
SimplexId size(SimplexId id) const
Get the size of a particular sub-vector.
SimplexId offset(SimplexId id) const
Get the offset of a particular sub-vector.
bool empty() const
If the underlying buffers are empty.
int buildTriangleEdgeList(const SimplexId &vertexNumber, const CellArray &cellArray, std::vector< std::array< SimplexId, 3 > > &triangleEdgeList, const std::vector< std::array< SimplexId, 2 > > &edgeList, FlatJaggedArray *vertexEdgeList=nullptr, std::vector< std::array< SimplexId, 3 > > *triangleList=nullptr, FlatJaggedArray *triangleStarList=nullptr, std::vector< std::array< SimplexId, 4 > > *cellTriangleList=nullptr) const
int buildVertexTriangles(const SimplexId &vertexNumber, const std::vector< std::array< SimplexId, 3 > > &triangleList, FlatJaggedArray &vertexTriangles) const
int buildCellNeighborsFromEdges(const CellArray &cellArray, FlatJaggedArray &cellNeighbors, const FlatJaggedArray &edgeStars) const
int buildTriangleLinks(const std::vector< std::array< SimplexId, 3 > > &triangleList, const FlatJaggedArray &triangleStars, const CellArray &cellArray, FlatJaggedArray &triangleLinks) const
int buildTriangleList(const SimplexId &vertexNumber, const CellArray &cellArray, std::vector< std::array< SimplexId, 3 > > *triangleList=nullptr, FlatJaggedArray *triangleStars=nullptr, std::vector< std::array< SimplexId, 4 > > *cellTriangleList=nullptr) const
int buildEdgeTriangles(const SimplexId &vertexNumber, const CellArray &cellArray, FlatJaggedArray &edgeTriangleList, const std::vector< std::array< SimplexId, 2 > > &edgeList, std::vector< std::array< SimplexId, 3 > > *triangleEdgeList=nullptr) const
int buildCellNeighborsFromVertices(const SimplexId &vertexNumber, const CellArray &cellArray, FlatJaggedArray &cellNeighbors, FlatJaggedArray *vertexStars=nullptr) const
ZeroSkeleton processing package.
int buildVertexEdges(const SimplexId &vertexNumber, const std::vector< std::array< SimplexId, 2 > > &edgeList, FlatJaggedArray &vertexEdges) const
int buildVertexStars(const SimplexId &vertexNumber, const CellArray &cellArray, FlatJaggedArray &vertexStars) const
int SimplexId
Identifier type for simplices of any dimension.
T end(std::pair< T, T > &p)
T begin(std::pair< T, T > &p)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)