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)