From d23e12f0a30fd9ec84eb1eb8f26445451ef5d008 Mon Sep 17 00:00:00 2001 From: ponchio Date: Fri, 22 Oct 2004 10:34:13 +0000 Subject: [PATCH] added split. --- apps/nexus/fragment.cpp | 243 ++++++++++++++++++++++++++++++---------- apps/nexus/fragment.h | 44 ++++++-- 2 files changed, 219 insertions(+), 68 deletions(-) diff --git a/apps/nexus/fragment.cpp b/apps/nexus/fragment.cpp index 95edd7a1..ad849c11 100644 --- a/apps/nexus/fragment.cpp +++ b/apps/nexus/fragment.cpp @@ -8,7 +8,7 @@ using namespace vcg; using namespace nxs; using namespace pt; -void NxsPatch::write(outstm *out) { +void NxsPatch::Write(outstm *out) { int vsize = vert.size(); int fsize = face.size(); int bsize = bord.size(); @@ -23,7 +23,7 @@ void NxsPatch::write(outstm *out) { out->write(&*bord.begin(), bord.size() * sizeof(Link)); } -void NxsPatch::read(instm *in) { +void NxsPatch::Read(instm *in) { int vsize; int fsize; int bsize; @@ -40,50 +40,47 @@ void NxsPatch::read(instm *in) { 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(&error, sizeof(float)); - - unsigned int esize = update.erased.size(); - unsigned int csize = update.created.size(); - out->write(&esize, sizeof(unsigned int)); - out->write(&csize, sizeof(unsigned int)); - out->write(&*update.erased.begin(), esize * sizeof(unsigned int)); - out->write(&*update.created.begin(), csize * sizeof(unsigned int)); + + unsigned int ssize = seeds.size(); + out->write(&ssize, sizeof(unsigned int)); + + out->write(&*seeds.begin(), ssize * sizeof(Seed)); + out->write(&*seeds_id.begin(), ssize * sizeof(unsigned int)); unsigned int psize = pieces.size(); out->write(&psize, sizeof(unsigned int)); 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(&error, sizeof(float)); - unsigned int esize; - unsigned int csize; - in->read(&esize, sizeof(unsigned int)); - in->read(&csize, sizeof(unsigned int)); - update.erased.resize(esize); - update.created.resize(csize); - in->read(&*update.erased.begin(), esize * sizeof(unsigned int)); - in->read(&*update.created.begin(), csize * sizeof(unsigned int)); + unsigned int ssize; + in->read(&ssize, sizeof(unsigned int)); + seeds.resize(ssize); + seeds_id.resize(ssize); + in->read(&*seeds.begin(), ssize * sizeof(Seed)); + in->read(&*seeds_id.begin(), ssize * sizeof(unsigned int)); unsigned int psize; in->read(&psize, sizeof(unsigned int)); pieces.resize(psize); 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 &newvert, vector &newface, - vector &newbord) { + vector &newbord) { map patch_remap; vector offsets; @@ -98,7 +95,7 @@ void nxs::join(Fragment &in, vector remap; remap.resize(totvert, 0xffffffff); - //TODO what if totvert > 32768? + //TODO what if totvert > 1<<22? //todo we really need a set? // set newborders; unsigned int vcount = 0; @@ -132,31 +129,8 @@ void nxs::join(Fragment &in, 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 //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 internal_links; internal_links.resize(vcount, 0); - map newborders; + map newborders; for(unsigned int i = 0; i < in.pieces.size(); i++) { unsigned int offset = offsets[i]; vector &bord = in.pieces[i].bord; for(unsigned int k = 0; k < bord.size(); k++) { - Link link = bord[k]; - if(link.IsNull()) continue; - if(!patch_remap.count(link.end_patch)) {//external...may be erased though - link.start_vert = remap[offset + link.start_vert]; + Link llink = bord[k]; + if(llink.IsNull()) continue; + if(!patch_remap.count(llink.end_patch)) {//external...may be erased though + 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)) newborders[link] = 1; else newborders[link]++; } 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::iterator b; + map::iterator b; for(b = newborders.begin(); b != newborders.end(); b++) { //test that number of links on this vertex is equal to //number of internal links of the internal vertex - const Link &link = (*b).first; + const BigLink &link = (*b).first; unsigned int n = (*b).second; if(n * (n-1) == internal_links[link.start_vert]) newbord.push_back(link); } } -void nxs::split(Fragment &out, +void nxs::Split(Fragment &out, vector &newvert, vector &newface, - vector &newbord, + vector &newbord, VoronoiPartition &part) { + + unsigned int nseeds = out.seeds.size(); + vector &seeds = out.seeds; + vector &seeds_id = out.seeds_id; + //preliminary count + vector 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 newseeds; + vector 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 > vert_remap; + vector< vector > face_remap; + + vector vert_count; + vector 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 &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 &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 &v_remap = vert_remap[seed]; + + assert(vert_count[seed] > 0); + vector &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 &f_remap = face_remap[seed]; + + vector &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 &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 &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; } - diff --git a/apps/nexus/fragment.h b/apps/nexus/fragment.h index fc529745..d6df6891 100644 --- a/apps/nexus/fragment.h +++ b/apps/nexus/fragment.h @@ -5,20 +5,40 @@ #include #include "nexus.h" +#include "pvoronoi.h" namespace nxs { 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 { public: + //this fields is the patch number in the infragment + //and the seeds id in the outfragment unsigned int patch; std::vector vert; std::vector face; + //when this is an outfragment link.end_patch is (1<<31) + end_patch + //when it is an internal border! std::vector bord; - void write(pt::outstm *out); - void read(pt::instm *in); + void Write(pt::outstm *out); + void Read(pt::instm *in); }; class Fragment { @@ -26,22 +46,28 @@ class Fragment { unsigned int id; float error; - Nexus::Update update; + + std::vector seeds; + std::vector seeds_id; + std::vector pieces; - void write(pt::outstm *out); - void read(pt::instm *in); + void Write(pt::outstm *out); + 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 &newvert, std::vector &newface, - std::vector &newbord); + std::vector &newbord); - void split(Fragment &out, + void Split(Fragment &out, std::vector &newvert, std::vector &newface, - std::vector &newbord, + std::vector &newbord, VoronoiPartition &part); }