Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 26 additions & 15 deletions source/frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2860,13 +2860,12 @@ void get_connected_component_data_impl_detail(
std::stack<std::pair<vd_t, hd_t>> disjoint_seq_stack; // stores the next vertices on the left and right side of seed vertex

// find any seam vertex that is not traversed, use that as a starting point -> the "seed"
std::unordered_map<vd_t, bool>::iterator seed_fiter = std::find_if( // O(n)
auto seed_fiter = std::find_if( // O(n)
traversed_seam_vertices.begin(),
traversed_seam_vertices.end(),
[](const std::pair<vd_t, bool>& elem) {
return elem.second == false;
});

seed_fiter->second = true; // marked the seed as traversed

const McSize cur_seq_size_value_idx = seam_vertex_sequence_array.size();
Expand All @@ -2889,6 +2888,8 @@ void get_connected_component_data_impl_detail(
// are stored in "disjoint_vertex_sequences_of_same_seam".

const McUint32 seed_vertex_descr = (McUint32)seed_fiter->first;
// print coordinates of seed vertex
std::cout << "seed vertex: " << cc->vertex(seed_fiter->first) << std::endl;
seam_vertex_sequence_array.push_back(seed_vertex_descr);

//
Expand All @@ -2900,26 +2901,33 @@ void get_connected_component_data_impl_detail(
const std::vector<hd_t>& halfedges_around_seed_vertex = cc->get_halfedges_around_vertex(vd_t(seed_vertex_descr));

// for each halfedge whose target is the seed
for (std::vector<hd_t>::const_iterator it = halfedges_around_seed_vertex.cbegin(); it != halfedges_around_seed_vertex.cend(); ++it) {
const hd_t h = *it;
for (const auto& h : halfedges_around_seed_vertex) {
const vd_t src = cc->source(h); // get the halfedge's source
std::cout << "halfedge's source " << cc->vertex(src) << std::endl;

// is it even a seam vertex first of all?
std::unordered_map<vd_t, bool>::iterator fiter = traversed_seam_vertices.find(src);
auto fiter = traversed_seam_vertices.find(src);
const bool is_seam_vertex = fiter != traversed_seam_vertices.cend();

if (is_seam_vertex) {
bool& is_traversed = fiter->second;
std::cout << "halfedge's source is a seam vertex, traversed? " << is_traversed << std::endl;

if (!is_traversed) {
// push since this neighbour is a seam vertex that has not been traversed
disjoint_seq_stack.push(std::make_pair(src, h));
disjoint_seq_stack.emplace(src, h);

is_traversed = true; // mark the neighbour as traversed (because we immediately traverse it next)
}
}
}

std::cout << "disjoint_seq_stack.size() = " << disjoint_seq_stack.size() << std::endl;
// if (!(disjoint_seq_stack.size() == 1 || disjoint_seq_stack.size() == 2))
// {
// // print debug information
// std::cout << cc->vertex(disjoint_seq_stack.top().first) << std::endl;
// }
MCUT_ASSERT(disjoint_seq_stack.size() == 1 || disjoint_seq_stack.size() == 2);

// this means will we are guarranteed to find just one sequence i.e. the draft disjoint sequence
Expand All @@ -2930,10 +2938,13 @@ void get_connected_component_data_impl_detail(
// An iteration will find a single sequence (which may be a loop, or a an open sequence that does not form a loop,

do {

// take the next neighbour from the stack to process and extend the sequence
std::pair<vd_t, hd_t> cur_vh_pair = disjoint_seq_stack.top();
disjoint_seq_stack.pop();

// show which vertex we are currently processing
std::cout << "process rn: " << cc->vertex(cur_vh_pair.first) << std::endl;

const vd_t v = cur_vh_pair.first; // vertex, one of whose halfedges (along the seam) is h
const hd_t h = cur_vh_pair.second; // halfedge whose source is v

Expand All @@ -2944,32 +2955,31 @@ void get_connected_component_data_impl_detail(
// similar logic as above to find the neighours of the seed, which polulate the stack "disjoint_seq_stack"
const std::vector<hd_t>& halfedges_around_vertex = cc->get_halfedges_around_vertex(v);

for (std::vector<hd_t>::const_iterator it = halfedges_around_vertex.cbegin();
it != halfedges_around_vertex.cend();
++it) {
const hd_t incident_h = *it;

for (const auto& incident_h : halfedges_around_vertex) {
if (cc->edge(incident_h) == cc->edge(h)) {
continue; // skip! dont want to go backwards now...
}

const vd_t src = cc->source(incident_h);
std::unordered_map<vd_t, bool>::iterator fiter = traversed_seam_vertices.find(src);
auto fiter = traversed_seam_vertices.find(src);
const bool is_seam_vertex = fiter != traversed_seam_vertices.cend();

if (is_seam_vertex) {
bool& is_traversed = fiter->second;

if (!is_traversed) {
untraversed_adj_seam_vertex_count++;
disjoint_seq_stack.push(std::make_pair(src, incident_h));
std::cout << "stack populated with: " << cc->vertex(src) << std::endl;
disjoint_seq_stack.emplace(src, incident_h);

is_traversed = true;
}
}
}

// we fail here right now
MCUT_ASSERT(untraversed_adj_seam_vertex_count <= 1);
// if (untraversed_adj_seam_vertex_count > 1) continue;

// no further neighbours to walk/traverse but the stack still has seam vertices to be walked.
// This implies we have an open loop, and that we have finished finding the first disjoint part
Expand Down Expand Up @@ -3022,6 +3032,7 @@ void get_connected_component_data_impl_detail(
seam_vertex_sequence_array.cend());

MCUT_ASSERT(cur_seq_size_value_idx == seam_vertex_sequence_array_start_offset);
// if (cur_seq_size_value_idx != seam_vertex_sequence_array_start_offset) continue;

total_seq_count += 1; // increment number of sequences found

Expand Down Expand Up @@ -3262,7 +3273,7 @@ void get_connected_component_data_impl_detail(

for (std::vector<fd_t>::const_iterator f_iter = block_start_; f_iter != block_end_; ++f_iter) {

if ((elem_offset + 1) >= elems_to_copy) {
if ((elem_offset + 1) > elems_to_copy) {
break;
}

Expand Down
202 changes: 131 additions & 71 deletions tutorials/QuerySeamVerticesSorted/QuerySeamVerticesSorted.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include <string>
#include <vector>
#include <iostream>

#define my_assert(cond) \
if (!(cond)) { \
Expand Down Expand Up @@ -240,6 +241,123 @@ int main()
// ... and so on, until last sequence
// ]

// // check that connected component has correct source mesh
// api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_ORIGIN, 0, NULL, &numBytes);
// if (api_err != MC_NO_ERROR) {
// fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_ORIGIN) failed (api_err=%d)\n", (int)api_err);
// exit(1);
// }
// McSeamOrigin origin;
// api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_ORIGIN, numBytes, &origin, NULL);
// if (api_err != MC_NO_ERROR) {
// fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_ORIGIN) failed (api_err=%d)\n", (int)api_err);
// exit(1);
// }

// if (origin != MC_SEAM_ORIGIN_SRCMESH) {
// fprintf(stderr, "connected component %d does not have source mesh as origin\n", i);
// continue;
// }

// query the seam vertices (indices)
// ---------------------------------


api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX, 0, NULL, &numBytes);

if (api_err != MC_NO_ERROR) {
fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX) failed (api_err=%d)\n", (int)api_err);
exit(1);
}

std::vector<uint32_t> seamVertexIndices;
seamVertexIndices.resize(numBytes / sizeof(uint32_t));

api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX, numBytes, seamVertexIndices.data(), NULL);

if (api_err != MC_NO_ERROR) {
fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX) failed (api_err=%d)\n", (int)api_err);
exit(1);
}

uint32_t faceSizesStub = seamVertexIndices.size();

char seamFnameBuf[40];
sprintf(seamFnameBuf, "frag-%d-seam-vertices.txt", i);

// save seam vertices to file (.txt)
// ------------------------
writeOFF(seamFnameBuf,
NULL,
// We pretend that the list of seam vertices is a face, when in actual
// fact we are simply using the output file as storage for later inspection
seamVertexIndices.data(),
&faceSizesStub,
NULL,
0,
1, // one face
0);


// query the vertices (coordinates)
// --------------------------------
numBytes = 0;
api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes);

if (api_err != MC_NO_ERROR) {
fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE) failed (api_err=%d)\n", (int)api_err);
exit(1);
}

uint32_t numberOfVertices = (uint32_t)(numBytes / (sizeof(double) * 3));

std::vector<double> vertices(numberOfVertices * 3u);

api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)vertices.data(), NULL);

if (api_err != MC_NO_ERROR) {
fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE) failed (api_err=%d)\n", (int)api_err);
exit(1);
}

// query (triangulated) faces
// -----------------------------
numBytes = 0;
api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes);

if (api_err != MC_NO_ERROR) {
fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION) failed (api_err=%d)\n", (int)api_err);
exit(1);
}

uint32_t numberOfTriangles = (uint32_t)(numBytes / (sizeof(McIndex) * 3));

std::vector<McIndex> triangleIndices(numberOfTriangles * 3u);

api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, (void*)triangleIndices.data(), NULL);

if (api_err != MC_NO_ERROR) {
fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION) failed (api_err=%d)\n", (int)api_err);
exit(1);
}

// save mesh to file (.off)
// ------------------------
char fnameBuf[32];
sprintf(fnameBuf, "frag-%d.off", i);

writeOFF(fnameBuf,
vertices.data(),
triangleIndices.data(),
NULL, // if null then function treat faceIndices array as made up of triangles
NULL, // we don't care about writing edges
numberOfVertices,
numberOfTriangles,
0 // zero edges since we don't care about writing edges
);

std::cout << "working component" << i << std::endl;

api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_SEAM_VERTEX_SEQUENCE, 0, NULL, &numBytes);

if (api_err != MC_NO_ERROR) {
Expand Down Expand Up @@ -274,54 +392,54 @@ int main()
// create entry to store own array and flag
seamVertexSequences.push_back(std::pair<std::vector<McUint32>, McBool>());
std::pair<std::vector<McUint32>, McBool>& currentSeamVertexSequenceData = seamVertexSequences.back();
std::vector<McUint32>& currentSeamVertexSequenceIndices = currentSeamVertexSequenceData.first; // Ordered list of vertex indices in CC defining the seam sequence

std::vector<McUint32>& currentSeamVertexSequenceIndices = currentSeamVertexSequenceData.first; // Ordered list of vertex indices in CC defining the seam sequence
McBool &isLoop = currentSeamVertexSequenceData.second; // does it form a loop? (auxilliary piece of info that might be useful to users)

// NOTE: order in which we do things here matter because of how we rely on "runningOffset++"
// So here, for each sequence we have 1) the number of vertex indices in that sequence 2)
// a flag telling us whether the sequence is a loop, and 3) the actually consecutive list of
// sorted vertex indices that for the sequence
// a flag telling us whether the sequence is a loop, and 3) the actually consecutive list of
// sorted vertex indices that for the sequence
const uint32_t currentSeamVertexSequenceIndicesArraySize = seamVertexSequenceArrayFromMCUT[runningOffset++];
currentSeamVertexSequenceIndices.resize(currentSeamVertexSequenceIndicesArraySize);

isLoop = seamVertexSequenceArrayFromMCUT[runningOffset++];

// copy seam vertex indices of current sequence into local array
memcpy(
currentSeamVertexSequenceIndices.data(),
seamVertexSequenceArrayFromMCUT.data() + runningOffset,
currentSeamVertexSequenceIndices.data(),
seamVertexSequenceArrayFromMCUT.data() + runningOffset,
sizeof(McUint32) * currentSeamVertexSequenceIndicesArraySize);

runningOffset += currentSeamVertexSequenceIndicesArraySize;
}

//
// We are now going to save the sequences to file. To do so, we piggyback
// on the "writeOFF" function and pretend that we are writing a mesh where
// on the "writeOFF" function and pretend that we are writing a mesh where
// each sequence is a face.
//

// stub variables for writing to file
uint32_t numFacesStub = seamVertexSequences.size();
std::vector<uint32_t> faceSizesArrayStub(numFacesStub);
std::vector<uint32_t> faceIndicesArrayStub;

std::string flags_str;

// for each sequence
for(uint32_t j =0; j < seamVertexSequences.size(); ++j)
{
faceSizesArrayStub[j] = seamVertexSequences[j].first.size();
faceIndicesArrayStub.insert(
faceIndicesArrayStub.cend(),
seamVertexSequences[j].first.cbegin(),
faceIndicesArrayStub.cend(),
seamVertexSequences[j].first.cbegin(),
seamVertexSequences[j].first.cend());

flags_str.append("-id" +std::to_string(j) + ((seamVertexSequences[j].second == MC_TRUE) ? "_isLOOP" : "_isOPEN"));
}

char seamFnameBuf[1024];
// char seamFnameBuf[1024];
sprintf(seamFnameBuf, "frag-%d-seam-vertices%s.txt", i, flags_str.c_str());

// save seam vertices to file (.txt)
Expand All @@ -334,66 +452,8 @@ int main()
faceSizesArrayStub.data(),
NULL,
0,
(uint32_t)faceSizesArrayStub.size(),
(uint32_t)faceSizesArrayStub.size(),
0);


// query the vertices (coordinates)
// --------------------------------
numBytes = 0;
api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, 0, NULL, &numBytes);

if (api_err != MC_NO_ERROR) {
fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE) failed (api_err=%d)\n", (int)api_err);
exit(1);
}

uint32_t numberOfVertices = (uint32_t)(numBytes / (sizeof(double) * 3));

std::vector<double> vertices(numberOfVertices * 3u);

api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE, numBytes, (void*)vertices.data(), NULL);

if (api_err != MC_NO_ERROR) {
fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_VERTEX_DOUBLE) failed (api_err=%d)\n", (int)api_err);
exit(1);
}

// query (triangulated) faces
// -----------------------------
numBytes = 0;
api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, 0, NULL, &numBytes);

if (api_err != MC_NO_ERROR) {
fprintf(stderr, "1:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION) failed (api_err=%d)\n", (int)api_err);
exit(1);
}

uint32_t numberOfTriangles = (uint32_t)(numBytes / (sizeof(McIndex) * 3));

std::vector<McIndex> triangleIndices(numberOfTriangles * 3u);

api_err = mcGetConnectedComponentData(context, connComp, MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION, numBytes, (void*)triangleIndices.data(), NULL);

if (api_err != MC_NO_ERROR) {
fprintf(stderr, "2:mcGetConnectedComponentData(MC_CONNECTED_COMPONENT_DATA_FACE_TRIANGULATION) failed (api_err=%d)\n", (int)api_err);
exit(1);
}

// save mesh to file (.off)
// ------------------------
char fnameBuf[32];
sprintf(fnameBuf, "frag-%d.off", i);

writeOFF(fnameBuf,
vertices.data(),
triangleIndices.data(),
NULL, // if null then function treat faceIndices array as made up of triangles
NULL, // we don't care about writing edges
numberOfVertices,
numberOfTriangles,
0 // zero edges since we don't care about writing edges
);
}

// 6. free connected component data
Expand Down
Loading