added split.

This commit is contained in:
Federico Ponchio 2004-10-22 10:34:13 +00:00
parent 2bfda63cc5
commit d23e12f0a3
2 changed files with 219 additions and 68 deletions

View File

@ -8,7 +8,7 @@ using namespace vcg;
using namespace nxs; using namespace nxs;
using namespace pt; using namespace pt;
void NxsPatch::write(outstm *out) { void NxsPatch::Write(outstm *out) {
int vsize = vert.size(); int vsize = vert.size();
int fsize = face.size(); int fsize = face.size();
int bsize = bord.size(); int bsize = bord.size();
@ -23,7 +23,7 @@ void NxsPatch::write(outstm *out) {
out->write(&*bord.begin(), bord.size() * sizeof(Link)); out->write(&*bord.begin(), bord.size() * sizeof(Link));
} }
void NxsPatch::read(instm *in) { void NxsPatch::Read(instm *in) {
int vsize; int vsize;
int fsize; int fsize;
int bsize; int bsize;
@ -40,50 +40,47 @@ void NxsPatch::read(instm *in) {
in->read(&*bord.begin(), bord.size() * sizeof(Link)); in->read(&*bord.begin(), bord.size() * sizeof(Link));
} }
void Fragment::write(outstm *out) { void Fragment::Write(outstm *out) {
out->write(&id, sizeof(unsigned int)); out->write(&id, sizeof(unsigned int));
out->write(&error, sizeof(float)); out->write(&error, sizeof(float));
unsigned int esize = update.erased.size(); unsigned int ssize = seeds.size();
unsigned int csize = update.created.size(); out->write(&ssize, sizeof(unsigned int));
out->write(&esize, sizeof(unsigned int));
out->write(&csize, sizeof(unsigned int)); out->write(&*seeds.begin(), ssize * sizeof(Seed));
out->write(&*update.erased.begin(), esize * sizeof(unsigned int)); out->write(&*seeds_id.begin(), ssize * sizeof(unsigned int));
out->write(&*update.created.begin(), csize * sizeof(unsigned int));
unsigned int psize = pieces.size(); unsigned int psize = pieces.size();
out->write(&psize, sizeof(unsigned int)); out->write(&psize, sizeof(unsigned int));
for(unsigned int i = 0; i < pieces.size(); i++) for(unsigned int i = 0; i < pieces.size(); i++)
pieces[i].write(out); pieces[i].Write(out);
} }
void Fragment::read(instm *in) { void Fragment::Read(instm *in) {
in->read(&id, sizeof(unsigned int)); in->read(&id, sizeof(unsigned int));
in->read(&error, sizeof(float)); in->read(&error, sizeof(float));
unsigned int esize; unsigned int ssize;
unsigned int csize; in->read(&ssize, sizeof(unsigned int));
in->read(&esize, sizeof(unsigned int)); seeds.resize(ssize);
in->read(&csize, sizeof(unsigned int)); seeds_id.resize(ssize);
update.erased.resize(esize); in->read(&*seeds.begin(), ssize * sizeof(Seed));
update.created.resize(csize); in->read(&*seeds_id.begin(), ssize * sizeof(unsigned int));
in->read(&*update.erased.begin(), esize * sizeof(unsigned int));
in->read(&*update.created.begin(), csize * sizeof(unsigned int));
unsigned int psize; unsigned int psize;
in->read(&psize, sizeof(unsigned int)); in->read(&psize, sizeof(unsigned int));
pieces.resize(psize); pieces.resize(psize);
for(unsigned int i = 0; i < psize; i++) for(unsigned int i = 0; i < psize; i++)
pieces[i].read(in); pieces[i].Read(in);
} }
void nxs::join(Fragment &in, void nxs::Join(Fragment &in,
vector<Point3f> &newvert, vector<Point3f> &newvert,
vector<unsigned int> &newface, vector<unsigned int> &newface,
vector<Link> &newbord) { vector<BigLink> &newbord) {
map<unsigned int, unsigned int> patch_remap; map<unsigned int, unsigned int> patch_remap;
vector<unsigned int> offsets; vector<unsigned int> offsets;
@ -98,7 +95,7 @@ void nxs::join(Fragment &in,
vector<unsigned int> remap; vector<unsigned int> remap;
remap.resize(totvert, 0xffffffff); remap.resize(totvert, 0xffffffff);
//TODO what if totvert > 32768? //TODO what if totvert > 1<<22?
//todo we really need a set? //todo we really need a set?
// set<Link> newborders; // set<Link> newborders;
unsigned int vcount = 0; unsigned int vcount = 0;
@ -132,31 +129,8 @@ void nxs::join(Fragment &in,
remap[extoffset + link.end_vert] = remap[offset + link.start_vert]; remap[extoffset + link.end_vert] = remap[offset + link.start_vert];
} }
} }
/* assert(link.start_vert < remap.size());
assert(remap[offset + link.start_vert] != 0xffffffff);
if(!patch_remap.count(link.end_patch)) { //external
//test if erased in history... in wich case we do not add border
// if(!erased.count(link.end_patch)) { ?/????
link.start_vert = remap[offset + link.start_vert];
newborders.insert(link);
} else {
//internal
//TODO unsigned int &rmpv = remap[link.end_patch][link.end_vert];
unsigned int idx = patch_remap[link.end_patch];
unsigned int extoffset = offsets[idx];
if(extoffset + link.end_vert >= remap.size()) {
cerr << "extoffset: " << extoffset << endl;
cerr << "end_V: " << link.end_vert << endl;
cerr << "remsz: " << remap.size() << endl;
for(unsigned int i = 0; i < in.pieces.size(); i++)
cerr << "size: " << i << " =" << in.pieces[i].vert.size() << endl;
}
assert(extoffset + link.end_vert < remap.size());
if(remap[extoffset + link.end_vert] == 0xffffffff) //first time
remap[extoffset + link.end_vert] = remap[offset + link.start_vert];
}
}*/
} }
assert(vcount < (1<<16));
//L(a, b): Exist link between a, b //L(a, b): Exist link between a, b
//An external link L(e, v) where v belongs to the patches (and e not) //An external link L(e, v) where v belongs to the patches (and e not)
@ -167,21 +141,24 @@ void nxs::join(Fragment &in,
vector<unsigned int> internal_links; vector<unsigned int> internal_links;
internal_links.resize(vcount, 0); internal_links.resize(vcount, 0);
map<Link, unsigned int> newborders; map<BigLink, unsigned int> newborders;
for(unsigned int i = 0; i < in.pieces.size(); i++) { for(unsigned int i = 0; i < in.pieces.size(); i++) {
unsigned int offset = offsets[i]; unsigned int offset = offsets[i];
vector<Link> &bord = in.pieces[i].bord; vector<Link> &bord = in.pieces[i].bord;
for(unsigned int k = 0; k < bord.size(); k++) { for(unsigned int k = 0; k < bord.size(); k++) {
Link link = bord[k]; Link llink = bord[k];
if(link.IsNull()) continue; if(llink.IsNull()) continue;
if(!patch_remap.count(link.end_patch)) {//external...may be erased though if(!patch_remap.count(llink.end_patch)) {//external...may be erased though
link.start_vert = remap[offset + link.start_vert]; BigLink link;
link.start_vert = remap[offset + llink.start_vert];
link.end_patch = llink.end_patch;
link.end_vert = llink.end_vert;
if(!newborders.count(link)) if(!newborders.count(link))
newborders[link] = 1; newborders[link] = 1;
else else
newborders[link]++; newborders[link]++;
} else { //internal } else { //internal
internal_links[remap[offset + link.start_vert]]++; internal_links[remap[offset + llink.start_vert]]++;
} }
} }
} }
@ -211,22 +188,170 @@ void nxs::join(Fragment &in,
} }
} }
map<Link, unsigned int>::iterator b; map<BigLink, unsigned int>::iterator b;
for(b = newborders.begin(); b != newborders.end(); b++) { for(b = newborders.begin(); b != newborders.end(); b++) {
//test that number of links on this vertex is equal to //test that number of links on this vertex is equal to
//number of internal links of the internal vertex //number of internal links of the internal vertex
const Link &link = (*b).first; const BigLink &link = (*b).first;
unsigned int n = (*b).second; unsigned int n = (*b).second;
if(n * (n-1) == internal_links[link.start_vert]) if(n * (n-1) == internal_links[link.start_vert])
newbord.push_back(link); newbord.push_back(link);
} }
} }
void nxs::split(Fragment &out, void nxs::Split(Fragment &out,
vector<Point3f> &newvert, vector<Point3f> &newvert,
vector<unsigned int> &newface, vector<unsigned int> &newface,
vector<Link> &newbord, vector<BigLink> &newbord,
VoronoiPartition &part) { VoronoiPartition &part) {
unsigned int nseeds = out.seeds.size();
vector<Seed> &seeds = out.seeds;
vector<unsigned int> &seeds_id = out.seeds_id;
//preliminary count
vector<unsigned int> count;
count.resize(nseeds, 0);
for(unsigned int f = 0; f < newface.size(); f += 3) {
Point3f bari = (newvert[newface[f]] +
newvert[newface[f+1]] +
newvert[newface[f+2]])/3;
unsigned int seed = out.Locate(bari);
assert(seed < nseeds);
count[seed]++;
}
//pruning small patches
float min_size = (newface.size()/3) / 20.0f;
vector<Seed> newseeds;
vector<unsigned int> newseeds_id;
for(unsigned int seed = 0; seed < nseeds; seed++) {
if(count[seed] > min_size) {
newseeds.push_back(seeds[seed]);
newseeds_id.push_back(seeds_id[seed]);
}
if(count[seed] > (1<<16)) {
cerr << "Ooops a cell came too big... quitting\n";
exit(0);
}
}
seeds = newseeds;
seeds_id = newseeds_id;
nseeds = seeds.size();
//if != -1 remap global index to cell index (first arg)
vector< vector<int> > vert_remap;
vector< vector<int> > face_remap;
vector<int> vert_count;
vector<int> face_count;
vert_remap.resize(nseeds);
face_remap.resize(nseeds);
vert_count.resize(nseeds, 0);
face_count.resize(nseeds, 0);
for(unsigned int seed = 0; seed < nseeds; seed++)
vert_remap[seed].resize(newvert.size(), -1);
for(unsigned int f = 0; f < newface.size(); f += 3) {
Point3f bari = (newvert[newface[f]] +
newvert[newface[f+1]] +
newvert[newface[f+2]])/3;
unsigned int seed = out.Locate(bari);
vector<int> &f_remap = face_remap[seed];
f_remap.push_back(newface[f]);
f_remap.push_back(newface[f+1]);
f_remap.push_back(newface[f+2]);
face_count[seed]++;
vector<int> &v_remap = vert_remap[seed];
for(int i = 0; i < 3; i++)
if(v_remap[newface[f+i]] == -1)
v_remap[newface[f+i]] = vert_count[seed]++;
}
//TODO assure no big ones.
out.pieces.resize(nseeds);
for(unsigned int seed = 0; seed != nseeds; seed++) {
NxsPatch &patch = out.pieces[seed];
patch.patch = seeds_id[seed];
//vertices first
vector<int> &v_remap = vert_remap[seed];
assert(vert_count[seed] > 0);
vector<Point3f> &verts = patch.vert;
verts.resize(vert_count[seed]);
for(unsigned int i = 0; i < newvert.size(); i++) {
if(v_remap[i] != -1)
verts[v_remap[i]] = newvert[i];
}
//faces now
vector<int> &f_remap = face_remap[seed];
vector<unsigned short> &faces = patch.face;
faces.resize(face_count[seed]*3);
for(unsigned int i = 0; i < f_remap.size(); i++) {
assert(v_remap[f_remap[i]] != -1);
faces[i] = v_remap[f_remap[i]];
}
//borders last
vector<Link> &bords = patch.bord;
//process external borders
//for every esternal link we must update external patches!
for(unsigned int i = 0; i < newbord.size(); i++) {
BigLink link = newbord[i];
if(v_remap[link.start_vert] == -1) continue;
link.start_vert = v_remap[link.start_vert];
assert(link.start_vert < (1<<16));
Link llink;
llink.start_vert = link.start_vert;
llink.end_patch = link.end_patch;
llink.end_vert = link.end_vert;
bords.push_back(llink);
}
//process internal borders;
//TODO higly inefficient!!!
for(unsigned int rseed = 0; rseed < nseeds; rseed++) {
if(seed == rseed) continue;
vector<int> &vremapclose = vert_remap[rseed];
for(unsigned int i = 0; i < newvert.size(); i++) {
if(v_remap[i] != -1 && vremapclose[i] != -1) {
Link link;
link.end_patch = rseed + (1<<31);
link.start_vert = v_remap[i];
link.end_vert = vremapclose[i];
bords.push_back(link);
}
}
}
}
}
unsigned int Fragment::Locate(const Point3f &p) {
float max_dist = 1e20;
unsigned int id = 0xffffffff;
for(unsigned int i = 0; i < seeds.size(); i++) {
float dist = seeds[i].Dist(p);
if(dist < max_dist) {
max_dist = dist;
id = i;
}
}
assert(id != 0xffffffff);
return id;
} }

View File

@ -5,20 +5,40 @@
#include <ptypes/pstreams.h> #include <ptypes/pstreams.h>
#include "nexus.h" #include "nexus.h"
#include "pvoronoi.h"
namespace nxs { namespace nxs {
class VoronoiPartition; class VoronoiPartition;
struct BigLink {
unsigned int start_vert;
unsigned int end_patch;
unsigned int end_vert;
bool operator<(const BigLink &l) const {
if(end_patch == l.end_patch) {
if(start_vert == l.start_vert) {
return end_vert < l.end_vert;
} else
return start_vert < l.start_vert;
} else
return end_patch < l.end_patch;
}
};
class NxsPatch { class NxsPatch {
public: public:
//this fields is the patch number in the infragment
//and the seeds id in the outfragment
unsigned int patch; unsigned int patch;
std::vector<vcg::Point3f> vert; std::vector<vcg::Point3f> vert;
std::vector<unsigned short> face; std::vector<unsigned short> face;
//when this is an outfragment link.end_patch is (1<<31) + end_patch
//when it is an internal border!
std::vector<Link> bord; std::vector<Link> bord;
void write(pt::outstm *out); void Write(pt::outstm *out);
void read(pt::instm *in); void Read(pt::instm *in);
}; };
class Fragment { class Fragment {
@ -26,22 +46,28 @@ class Fragment {
unsigned int id; unsigned int id;
float error; float error;
Nexus::Update update;
std::vector<Seed> seeds;
std::vector<unsigned int> seeds_id;
std::vector<NxsPatch> pieces; std::vector<NxsPatch> pieces;
void write(pt::outstm *out); void Write(pt::outstm *out);
void read(pt::instm *in); void Read(pt::instm *in);
//returns the index of the seed
unsigned int Locate(const vcg::Point3f &p);
}; };
void join(Fragment &in, void Join(Fragment &in,
std::vector<vcg::Point3f> &newvert, std::vector<vcg::Point3f> &newvert,
std::vector<unsigned int> &newface, std::vector<unsigned int> &newface,
std::vector<Link> &newbord); std::vector<BigLink> &newbord);
void split(Fragment &out, void Split(Fragment &out,
std::vector<vcg::Point3f> &newvert, std::vector<vcg::Point3f> &newvert,
std::vector<unsigned int> &newface, std::vector<unsigned int> &newface,
std::vector<Link> &newbord, std::vector<BigLink> &newbord,
VoronoiPartition &part); VoronoiPartition &part);
} }