You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

159 lines
4.9 KiB

#pragma once
#include "TinyVector.h"
#include <vector>
#include <set>
#include <map>
#include <cstdio>
#include <fstream>
#include <queue>
#include "MyTuple.h"
using namespace std;
typedef TinyVector<double, 3> vec3d;
bool obj_loader(const char filename[], vector<vec3d> &vertices,
std::set<MySortedTuple<2>> &sharp_edges, vector<vector<size_t>> &facets, double sharp_angle_in_degree = 60)
{
vertices.resize(0);
facets.resize(0);
double threshold = cos(sharp_angle_in_degree / 180 * M_PI);
std::map<MySortedTuple<2>, std::vector<vec3d>> edge2facenormals;
FILE *m_pFile = fopen(filename, "r");
if (!m_pFile)
return false;
char temp[128];
char *tok;
fseek(m_pFile, 0, SEEK_SET);
char pLine[1024];
vec3d v;
while (fgets(pLine, 1024, m_pFile))
{
if (pLine[0] == 'v' && pLine[1] == ' ')
{
tok = strtok(pLine, " ");
for (int i = 0; i < 3; i++)
{
tok = strtok(NULL, " ");
strcpy(temp, tok);
temp[strcspn(temp, " ")] = 0;
v[i] = (double)atof(temp);
}
vertices.push_back(v);
}
}
fseek(m_pFile, 0, SEEK_SET);
std::vector<size_t> s_faceid;
while (fgets(pLine, 1024, m_pFile))
{
if (pLine[0] == 'f')
{
s_faceid.resize(0);
tok = strtok(pLine, " ");
while ((tok = strtok(NULL, " ")) != NULL)
{
strcpy(temp, tok);
temp[strcspn(temp, "/")] = 0;
int id = (int)strtol(temp, NULL, 10) - 1;
s_faceid.push_back(id);
}
facets.push_back(s_faceid);
vec3d normal(0, 0, 0);
for (size_t j = 0; j < s_faceid.size(); j++)
normal += vertices[s_faceid[j]].Cross(vertices[s_faceid[(j + 1) % s_faceid.size()]]);
normal.Normalize();
for (size_t j = 0; j < s_faceid.size(); j++)
edge2facenormals[MySortedTuple<2>(s_faceid[j], s_faceid[(j + 1) % s_faceid.size()])].push_back(normal);
}
}
fclose(m_pFile);
// ofstream sharpfeature("sharp.obj");
// size_t sharpcounter = 1;
for (auto iter = edge2facenormals.begin(); iter != edge2facenormals.end(); iter++)
{
if (iter->second.size() < 2)
continue;
for (size_t j = 0; j < iter->second.size(); j++)
{
if (fabs(iter->second[j].Dot(iter->second[(j + 1) % iter->second.size()])) < threshold)
{
sharp_edges.insert(iter->first);
// sharpfeature << "v " << vertices[iter->first.sorted_vert[0]] << std::endl;
// sharpfeature << "v " << vertices[iter->first.sorted_vert[1]] << std::endl;
// sharpfeature << "l " << sharpcounter << ' ' << sharpcounter + 1 << std::endl;
// sharpcounter += 2;
break;
}
}
}
// sharpfeature.close();
return true;
}
bool is_sharp_edge_list(const std::vector<size_t> &edge_list, const std::set<MySortedTuple<2>> &sharp_edges)
{
for (size_t i = 0; i + 1 < edge_list.size(); i++)
{
if (sharp_edges.count(MySortedTuple<2>(edge_list[i], edge_list[i + 1])) > 0)
return true;
}
return false;
}
int detect_num_loops(const std::vector<std::vector<size_t>> &facets, const std::vector<size_t> &selected_facets)
{
std::map<MySortedTuple<2>, int> edges;
for (size_t i = 0; i < selected_facets.size(); i++)
{
const size_t &fid = selected_facets[i];
for (int j = 0; j < facets[fid].size(); j++)
{
MySortedTuple<2> e(facets[fid][j], facets[fid][(j + 1) % facets[fid].size()]);
auto iter = edges.find(e);
if (iter != edges.end())
iter->second++;
else
edges[e] = 1;
}
}
std::map<size_t, std::set<size_t>> vertex_links;
for (auto &iter : edges)
{
if (iter.second == 1)
{
vertex_links[iter.first.sorted_vert[0]].insert(iter.first.sorted_vert[1]);
vertex_links[iter.first.sorted_vert[1]].insert(iter.first.sorted_vert[0]);
}
}
std::set<size_t> used_vertices;
int num_loop = 0;
for (auto &iter : vertex_links)
{
if (used_vertices.count(iter.first) > 0)
continue;
std::queue<size_t> myqueue;
myqueue.push(iter.first);
used_vertices.insert(iter.first);
while (!myqueue.empty())
{
size_t vid = myqueue.front();
myqueue.pop();
for (auto &n : vertex_links[vid])
{
if (used_vertices.count(n) > 0)
continue;
myqueue.push(n);
used_vertices.insert(n);
}
}
num_loop++;
}
std::cout << "loop: " << num_loop << std::endl;
return num_loop;
}