Subversion Repositories gelsvn

Rev

Rev 631 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
568 jab 1
//
2
//  polarize.cpp
3
//  GEL
4
//
5
//  Created by J. Andreas Bærentzen on 18/03/12.
6
//  Copyright 2012 __MyCompanyName__. All rights reserved.
7
//
8
#include <queue>
640 janba 9
#include <iomanip>
568 jab 10
 
11
#include "polarize.h"
631 janba 12
#include <CGLA/Vec2d.h>
13
#include <LinAlg/LapackFunc.h>
568 jab 14
#include <HMesh/triangulate.h>
631 janba 15
#include <HMesh/obj_save.h>
568 jab 16
#include <HMesh/curvature.h>
17
#include <HMesh/quadric_simplify.h>
18
#include <HMesh/mesh_optimization.h>
19
#include <HMesh/smooth.h>
20
 
572 jab 21
#include <complex>
22
 
568 jab 23
using namespace CGLA;
24
using namespace std;
25
using namespace HMesh;
26
 
631 janba 27
 
28
 
640 janba 29
inline bool same_level(double a, double b) {return abs(a-b) < 1e-10;}
631 janba 30
 
31
 
32
struct LevelSetInfo
33
{
34
    int id;
35
    int no_vertices;
36
    Vec3d avg_pos;
37
    double rad;
38
    double length;
39
    int components;
40
    HalfEdgeID h;
41
    double fun_value;
42
 
43
    void print()
44
    {
45
        cout
46
        << " id : " << id
47
        << " no vertices : " << no_vertices
48
        << " avg pos : " << avg_pos
49
        << " rad : " << rad
50
        << " length : " << length
51
        << " # : " << components
52
        << " F : " << fun_value << endl;
53
    }
54
};
55
 
56
void compute_edge_weights(Manifold& m, HalfEdgeAttributeVector<double>& edge_weights, FaceAttributeVector<int>& included)
57
{
58
    edge_weights = HalfEdgeAttributeVector<double>(m.allocated_halfedges(), 0);
59
    for(FaceIDIterator f = m.faces_begin(); f != m.faces_end(); ++f)
60
        if(included[*f])
61
        {
62
            for(Walker wv = m.walker(*f); !wv.full_circle(); wv = wv.circulate_face_ccw())
63
            {
64
                HalfEdgeID h = wv.halfedge();
65
                Vec3d p1(m.pos(wv.vertex()));
66
                Vec3d p2(m.pos(wv.next().vertex()));
67
                Vec3d p0(m.pos(wv.opp().vertex()));
68
                double ang = acos(min(1.0, max(-1.0, dot(normalize(p1-p0), normalize(p2-p0)))));
69
                double ang_opp = acos(min(1.0, max(-1.0, dot(normalize(p2-p1), normalize(p0-p1)))));
70
                double l = (p1-p0).length();
71
                edge_weights[h] += tan(ang/2) / l;
72
                edge_weights[wv.opp().halfedge()] += tan(ang_opp/2) / l;
73
            }
74
        }
75
}
640 janba 76
 
77
template<typename T>
631 janba 78
void smooth_fun(Manifold& m,
640 janba 79
                VertexAttributeVector<int>& nailed,
80
                VertexAttributeVector<T>& fun, int iter=100)
631 janba 81
{
82
    HalfEdgeAttributeVector<double> edge_weights;
83
    FaceAttributeVector<int> included(m.allocated_faces(),1);
84
    compute_edge_weights(m,edge_weights, included);
640 janba 85
    VertexAttributeVector<T> new_fun(m.no_vertices());
86
    for(int i = 0; i < iter; ++i)
631 janba 87
    {
88
        for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v)
89
            if(!nailed[*v])
90
            {
91
                double w_sum = 0;
640 janba 92
                new_fun[*v] = T(0);
631 janba 93
                for(Walker wv = m.walker(*v); !wv.full_circle(); wv = wv.circulate_vertex_ccw())
94
                {
95
                    double w = edge_weights[wv.halfedge()];
96
                    new_fun[*v] += w * fun[wv.vertex()];
97
                    w_sum += w;
98
                }
99
                new_fun[*v] /= w_sum;
100
            }
101
            else
102
                new_fun[*v] = fun[*v];
640 janba 103
        fun = new_fun;
631 janba 104
    }
105
}
106
 
107
void segment_manifold(Manifold& m, HalfEdgeAttributeVector<int>& ls_id,
108
                      FaceAttributeVector<int>& segmentation,
109
                      vector<vector<int>>& boundaries)
110
{
111
    segmentation = FaceAttributeVector<int>(m.no_faces(), -1);
112
    int SEG_NO = 0;
113
    for(auto f = m.faces_begin(); f != m.faces_end(); ++f)
114
    {
115
        if (segmentation[*f] == -1)
116
        {
117
            queue<FaceID> q;
118
            q.push(*f);
119
            vector<int> bound(0);
120
            while (!q.empty())
121
            {
122
                FaceID face = q.front();
123
                q.pop();
124
                segmentation[face] = SEG_NO;
125
                for(Walker w = m.walker(face); !w.full_circle(); w = w.next())
126
                {
127
                    if(ls_id[w.halfedge()] == -1)
128
                    {
129
                        FaceID fopp = w.opp().face();
130
                        if(segmentation[fopp] == -1) {
131
                            q.push(fopp);
132
                        }
133
                    }
134
                    else {
135
                        bound.push_back(ls_id[w.halfedge()]);
136
                    }
137
 
138
                }
139
            }
140
            sort(begin(bound), end(bound));
141
            auto new_end = unique(begin(bound), end(bound));
142
            boundaries.push_back(vector<int>(begin(bound),new_end));
143
            cout << "Boundaries of seg# " << SEG_NO << " : ";
144
            for(auto be:boundaries[SEG_NO])
145
                cout << be << " ";
146
            cout << endl;
147
            SEG_NO += 1;
148
        }
640 janba 149
 
631 janba 150
    }
151
}
152
 
153
 
568 jab 154
void shortest_edge_triangulate_face(Manifold& m, FaceID f0, VertexAttributeVector<int>& level_set_id_vertex)
155
{
156
    queue<FaceID> face_queue;
157
 
158
    face_queue.push(f0);
159
 
160
    while(!face_queue.empty())
161
    {
162
        FaceID f = face_queue.front();
163
        face_queue.pop();
164
 
165
        // Create a vector of vertices.
166
        vector<VertexID> verts;
587 jab 167
        for(Walker w = m.walker(f); !w.full_circle(); w = w.circulate_face_ccw())
568 jab 168
        {
169
            FaceID fa = w.face();
170
            FaceID fb = f;
171
            assert(fa==fb);
172
            verts.push_back(w.vertex());
173
        }
174
        // If there are just three we are done.
175
        if(verts.size() == 3) continue;
176
 
177
        // Find vertex pairs that may be connected.
178
        vector<pair<int,int> > vpairs;
179
        const int N = verts.size();
180
        for(int i = 0; i < N - 2; ++i){
181
            for(int j = i + 2; j < N; ++j){
631 janba 182
                if(verts[i] != verts[j] &&
568 jab 183
                   !connected(m, verts[i], verts[j]) &&
640 janba 184
                   (level_set_id_vertex[verts[i]] == 0 || level_set_id_vertex[verts[i]] != level_set_id_vertex[verts[j]]) &&
185
                   valency(m, verts[i])<5 && valency(m,verts[j])<5
568 jab 186
                   )
187
                    vpairs.push_back(pair<int,int>(i, j));
188
            }
189
        }
190
        if(vpairs.empty()){
631 janba 191
            cout << "Warning: could not triangulate a face."
568 jab 192
            << "Probably a vertex appears more than one time in other vertex's one-ring" << endl;
193
            continue;
194
        }
195
 
196
        /* For all vertex pairs, find the edge lengths. Combine the
197
         vertices forming the shortest edge. */
198
 
199
        float min_len=FLT_MAX;
200
        int min_k = -1;
201
        for(size_t k = 0; k < vpairs.size(); ++k){
202
            int i = vpairs[k].first;
203
            int j = vpairs[k].second;
204
            float len = sqr_length(m.pos(verts[i]) - m.pos(verts[j]));
205
 
206
            if(len<min_len){
207
                min_len = len;
208
                min_k = k;
209
            }
210
        }
211
        assert(min_k != -1);
212
 
213
        {
214
            // Split faces along edge whose midpoint is closest to isovalue
215
            int i = vpairs[min_k].first;
216
            int j = vpairs[min_k].second;
217
            FaceID f_new = m.split_face_by_edge(f, verts[i], verts[j]);
218
 
219
            if(no_edges(m, f)>3)
220
                face_queue.push(f);
221
            if(no_edges(m, f_new)>3)
222
                face_queue.push(f_new);
223
        }
224
 
225
    }
226
}
227
 
228
 
229
void shortest_edge_split_face(Manifold& m, FaceID f0, VertexAttributeVector<int>& level_set_id_vertex)
230
{
231
    queue<FaceID> face_queue;
232
 
233
    face_queue.push(f0);
234
 
235
    while(!face_queue.empty())
236
    {
237
        FaceID f = face_queue.front();
238
        face_queue.pop();
239
 
240
        // Create a vector of vertices.
241
        vector<VertexID> verts;
587 jab 242
        for(Walker w = m.walker(f); !w.full_circle(); w = w.circulate_face_ccw())
568 jab 243
        {
244
            verts.push_back(w.vertex());
245
        }
246
 
247
        // Find vertex pairs that may be connected.
248
        vector<pair<int,int> > vpairs;
249
        const int N = verts.size();
250
        for(int i = 0; i < N ; ++i){
251
            for(int j = 3; j < N-2; ++j){
252
                int jj = (j+i)%N;
253
                if(!connected(m, verts[i], verts[jj]) &&
254
                   (level_set_id_vertex[verts[i]] != level_set_id_vertex[verts[jj]]) &&
572 jab 255
                   (level_set_id_vertex[verts[(i+1)%N]] == level_set_id_vertex[verts[i]]) &&
256
                   (level_set_id_vertex[verts[(i+N-1)%N]] == level_set_id_vertex[verts[i]]) &&
257
                   (level_set_id_vertex[verts[(jj+1)%N]] == level_set_id_vertex[verts[jj]]) &&
258
                   (level_set_id_vertex[verts[(jj+N-1)%N]] == level_set_id_vertex[verts[jj]]))
568 jab 259
                    vpairs.push_back(pair<int,int>(i, jj));
260
            }
261
        }
262
        if(vpairs.empty()) continue;
263
 
264
 
265
        /* For all vertex pairs, find the edge lengths. Combine the
266
         vertices forming the shortest edge. */
267
 
268
        float min_len=FLT_MAX;
269
        int min_k = -1;
270
        for(size_t k = 0; k < vpairs.size(); ++k){
271
            int i = vpairs[k].first;
272
            int j = vpairs[k].second;
273
            float len = sqr_length(m.pos(verts[i]) - m.pos(verts[j]));
274
 
275
            if(len<min_len){
276
                min_len = len;
277
                min_k = k;
278
            }
279
        }
280
        assert(min_k != -1);
281
 
282
        {
283
            // Split faces along edge whose midpoint is closest to isovalue
284
            int i = vpairs[min_k].first;
285
            int j = vpairs[min_k].second;
286
            FaceID f_new = m.split_face_by_edge(f, verts[i], verts[j]);
287
            if(no_edges(m, f)>5)
288
                face_queue.push(f);
289
            if(no_edges(m, f_new)>5)
290
                face_queue.push(f_new);
291
        }
292
 
293
    }
294
}
295
 
296
 
297
 
298
struct EdgeQElem {
299
    float priority;
300
    HalfEdgeID he;
301
    EdgeQElem(float _priority, HalfEdgeID _he): priority(_priority), he(_he) {}
302
};
303
 
304
bool operator<(const EdgeQElem& l, const EdgeQElem& r)
305
{
306
    return l.priority < r.priority;
307
}
308
 
309
class FunctionalDifference: public EnergyFun
310
{
311
    VertexAttributeVector<float>& fun;
312
    VertexAttributeVector<int>& status;
313
public:
314
    FunctionalDifference(VertexAttributeVector<float>& _fun, VertexAttributeVector<int>& _status): fun(_fun), status(_status) {}
631 janba 315
    virtual double delta_energy(const Manifold& m, HalfEdgeID h) const
568 jab 316
    {
587 jab 317
        Walker w = m.walker(h);
568 jab 318
        if(status[w.vertex()] == 1 && status[w.opp().vertex()]==1)
319
            return DBL_MAX;
320
        return sqr_length(m.pos(w.next().vertex())-m.pos(w.opp().next().vertex()))/(1e-6+abs(fun[w.next().vertex()]-fun[w.opp().next().vertex()])) - sqr_length(m.pos(w.vertex())-m.pos(w.opp().vertex()))/(1e-6+abs(fun[w.vertex()]-fun[w.opp().vertex()]));
321
    }
322
};
323
 
572 jab 324
class TriangleQualityValence: public EnergyFun
325
{
326
    VertexAttributeVector<int>& idv;
327
    MinAngleEnergy mae;
328
    ValencyEnergy vae;
329
public:
330
    TriangleQualityValence(VertexAttributeVector<int>& _idv): idv(_idv), mae(-1) {}
631 janba 331
    virtual double delta_energy(const Manifold& m, HalfEdgeID h) const
572 jab 332
    {
587 jab 333
        Walker w = m.walker(h);
631 janba 334
        if(idv[w.next().vertex()] == idv[w.opp().next().vertex()] ||
572 jab 335
           idv[w.vertex()] == idv[w.opp().vertex()])
336
            return DBL_MAX;
337
 
338
        VertexID v1 = w.opp().vertex();
339
        VertexID v2 = w.vertex();
340
        VertexID vo1 = w.next().vertex();
341
        VertexID vo2 = w.opp().next().vertex();
342
 
343
        int val1  = valency(m, v1);
344
        int val2  = valency(m, v2);
345
        int valo1 = valency(m, vo1);
346
        int valo2 = valency(m, vo2);
347
 
348
        // The optimal valency is four for a boundary vertex
349
        // and six elsewhere.
350
        int t1 = boundary(m, v1) ? 4 : 6;
351
        int t2 = boundary(m, v2) ? 4 : 6;
352
        int to1 = boundary(m, vo1) ? 4 : 6;
353
        int to2 = boundary(m, vo2) ? 4 : 6;
354
 
631 janba 355
        int before =
572 jab 356
        max(max(sqr(val1-t1),sqr(val2-t2)), max(sqr(valo1-to1), sqr(valo2-to2)));
631 janba 357
        int after =
572 jab 358
        max(max(sqr(valo1+1-to1),sqr(val1-1-t1)), max(sqr(val2-1-t2),sqr(valo2+1-to2)));
359
 
360
        return static_cast<double>(after-before);
361
 
362
        //        return vae.delta_energy(m,h);
363
        float la = length(m.pos(w.next().vertex())-m.pos(w.opp().next().vertex()));
364
        float lb = length(m.pos(w.vertex())-m.pos(w.opp().vertex()));
365
        return la-lb;
366
        return mae.delta_energy(m,h);
367
    }
368
};
369
 
568 jab 370
class TriangleQuality: public EnergyFun
371
{
372
    VertexAttributeVector<int>& idv;
373
    MinAngleEnergy mae;
374
    ValencyEnergy vae;
375
public:
376
    TriangleQuality(VertexAttributeVector<int>& _idv): idv(_idv), mae(-1) {}
631 janba 377
    virtual double delta_energy(const Manifold& m, HalfEdgeID h) const
568 jab 378
    {
587 jab 379
        Walker w = m.walker(h);
631 janba 380
        if(idv[w.next().vertex()] == idv[w.opp().next().vertex()] ||
568 jab 381
           idv[w.vertex()] == idv[w.opp().vertex()])
382
            return DBL_MAX;
383
        return mae.delta_energy(m,h);
384
    }
385
};
386
 
587 jab 387
Vec3d grad(HMesh::Manifold& m, HMesh::VertexAttributeVector<double>& fun, HMesh::FaceID f)
572 jab 388
{
389
    if(no_edges(m,f) != 3)
587 jab 390
        return Vec3d(0.0);
572 jab 391
 
392
 
587 jab 393
    Vec3d n = normal(m, f);
572 jab 394
 
587 jab 395
    Vec3d gsum(0.0);
396
    for(Walker w = m.walker(f); !w.full_circle(); w = w.next())
572 jab 397
    {
631 janba 398
        VertexID avid = w.opp().vertex();
399
        VertexID bvid = w.vertex();
400
        VertexID cvid = w.next().vertex();
401
        Vec3d gdir = normalize(cross(n, m.pos(bvid) - m.pos(avid)));
402
        double l = dot(m.pos(cvid)-m.pos(avid), gdir);
403
        gdir *= fun[cvid]/l;
572 jab 404
        gsum += gdir;
405
    }
406
    return gsum;
407
}
568 jab 408
 
640 janba 409
Vec2d extend_fun2(HMesh::Manifold& m, HMesh::HalfEdgeID h,
410
                  HMesh::VertexAttributeVector<double>& fun,
411
                  HMesh::VertexAttributeVector<Vec2d>& fun2)
412
{
413
    Walker w = m.walker(h);
414
    FaceID f = w.face();
415
    Vec3d a = m.pos(w.opp().vertex());
416
    Vec3d b = m.pos(w.vertex());
417
    Vec3d c = m.pos(w.next().vertex());
418
    Vec3d g = grad(m, fun, f);
419
    Vec3d n = normal(m, f);
420
    Vec3d N = normalize(cross(g, n));
421
    float dot_nba = dot(N,b-a);
422
    Vec2d cval;
423
    if(dot_nba > 1e-5)
424
    {
425
        float t = dot(N, c-a)/dot_nba;
426
        if(t>0 && t < 1) {
427
            Vec2d aval = fun2[w.opp().vertex()];
428
            Vec2d bval = fun2[w.vertex()];
429
            return (1-t)*aval + t*bval;
430
        }
431
    }
432
    return Vec2d(0);
433
}
434
 
435
 
631 janba 436
double solve_for_orthogonal_gradients(HMesh::Manifold& m, HMesh::VertexAttributeVector<double>& fun,
640 janba 437
                                      HalfEdgeID h, double beta, double gamma)
572 jab 438
{
631 janba 439
    Vec3d n = normal(m, m.walker(h).face());
440
 
441
    Vec3d uvw[3];
442
    Vec3d abc;
443
    Walker w = m.walker(h);
444
    VertexID vid[] = {w.next().vertex(), w.opp().vertex(),w.vertex()};
640 janba 445
 
631 janba 446
    for(int i=0; !w.full_circle(); w = w.next(),++  i)
572 jab 447
    {
631 janba 448
        uvw[i] = normalize(cross(n, m.pos(vid[(i+1)%3]) - m.pos(vid[(i+2)%3])));
449
        uvw[i] /= dot(m.pos(vid[i])-m.pos(vid[(i+1)%3]), uvw[i]);
450
        abc[i] = fun[vid[i]];
572 jab 451
    }
631 janba 452
    Vec3d A(dot(uvw[0],uvw[0]),dot(uvw[0],uvw[1]),dot(uvw[0],uvw[2]));
453
    Vec3d B(dot(uvw[1],uvw[0]),dot(uvw[1],uvw[1]),dot(uvw[1],uvw[2]));
454
    Vec3d C(dot(uvw[2],uvw[0]),dot(uvw[2],uvw[1]),dot(uvw[2],uvw[2]));
455
 
456
    return - (beta * dot(B, abc) + gamma * dot(C, abc))/dot(A, abc);
572 jab 457
}
458
 
568 jab 459
 
631 janba 460
void recompute_circle_param(Manifold& m, VertexID v, VertexAttributeVector<double>& fun, VertexAttributeVector<Vec2d>& circle_pos, double f_origin)
568 jab 461
{
631 janba 462
    Vec2d c_new(0);
463
    for(auto w = m.walker(v); !w.full_circle(); w = w.circulate_vertex_ccw())
464
    {
465
        Walker w_base = w.next();
466
        Vec2d X = circle_pos[w_base.opp().vertex()];
467
        Vec2d Y(-X[1], X[0]);
468
        Vec2d vec = circle_pos[w_base.vertex()];
469
        double angle = atan2(max(-1.0,min(1.0,dot(vec,Y))),
470
                             max(-1.0,min(1.0,dot(vec,X))));
471
        double new_angle = solve_for_orthogonal_gradients(m, fun, w_base.halfedge(), 0, angle);
472
        new_angle = max(-M_PI/4, min(M_PI/4,new_angle));
473
        c_new += cos(new_angle)*X + sin(new_angle)*Y;
568 jab 474
    }
631 janba 475
    circle_pos[v] = normalize(c_new);
568 jab 476
}
477
 
640 janba 478
template<typename T>
479
void orthogonal_trajectories(Manifold& m, VertexID v, VertexAttributeVector<double>& f, double min_length_fun,
480
                             VertexAttributeVector<T>& h_in, VertexAttributeVector<T>& h_out)
481
{
482
    h_out[v] = T(0);
483
 
484
    T num(0);
485
    double denom = 0.0001;
486
    for(Walker w = m.walker(v); !w.full_circle(); w = w.circulate_vertex_ccw())
487
    {
488
        double weight = area(m, w.face());
489
 
490
        Vec3d a = m.pos(v);
491
        Vec3d b = m.pos(w.vertex());
492
        Vec3d c = m.pos(w.next().vertex());
493
 
494
 
495
        Vec3d fvec(f[v],f[w.vertex()], f[w.next().vertex()]);
496
        if(sqr_length(fvec)>0)
497
            fvec.normalize();
498
        double f_a = fvec[0];
499
        double f_b = fvec[1];
500
        double f_c = fvec[2];
501
 
502
        T h_b = h_in[w.vertex()];
503
        T h_c = h_in[w.next().vertex()];
504
 
505
        Vec3d e_a = c-b;
506
        Vec3d e_b = a-c;
507
        Vec3d e_c = b-a;
508
 
509
        Vec3d N = normalize(cross(e_b,e_c)+cross(e_c,e_a)+cross(e_a,e_b));
510
        Vec3d g_a = cross(N, normalize(e_a));
511
        g_a /= dot(g_a, e_b);
512
 
513
        Vec3d g_b = cross(N, normalize(e_b));
514
        g_b /= dot(g_b, e_c);
515
 
516
        Vec3d g_c = cross(N, normalize(e_c));
517
        g_c /= dot(g_c, e_a);
518
 
519
        num -= weight * (h_b * (f_a*dot(g_a, g_b) + f_b*dot(g_b,g_b) + f_c*dot(g_b,g_c)) +
520
                         h_c * (f_a*dot(g_a, g_c) + f_b*dot(g_b,g_c) + f_c*dot(g_c, g_c)));
521
        denom += weight * (f_a * dot(g_a,g_a)+ f_b*dot(g_a,g_b) +f_c*dot(g_a, g_c));
522
 
523
    }
524
    h_out[v] = num / denom;
525
}
526
 
631 janba 527
void polarize_mesh(Manifold& m, VertexAttributeVector<double>& fun, double vmin, double vmax, const int divisions, VertexAttributeVector<Vec2d>& parametrization)
568 jab 528
{
640 janba 529
    double interval = (vmax-vmin)/(divisions+1);
568 jab 530
 
586 jab 531
    VertexAttributeVector<int> status(m.allocated_vertices(), 0);
568 jab 532
 
533
 
534
    // ----------------------------------------
535
    cout << "Tracing level set curves" << endl;
536
 
537
 
640 janba 538
    for(int cut_no=1; cut_no<divisions+1;++cut_no)
568 jab 539
    {
640 janba 540
        double cut_val = vmin + cut_no * interval;
568 jab 541
 
640 janba 542
        vector<HalfEdgeID> hidvec;
543
        for(HalfEdgeID hid : m.halfedges())
568 jab 544
        {
640 janba 545
            Walker w = m.walker(hid);
546
            double bval = fun[w.vertex()];
547
            double aval = fun[w.opp().vertex()];
548
            if(aval<bval && aval <= cut_val && cut_val < bval)
549
            {
550
                double t = (cut_val-aval)/(bval-aval);
551
                Vec3d p = t*m.pos(w.vertex()) + (1.0-t)*m.pos(w.opp().vertex());
552
                VertexID vnew = m.split_edge(hid);
553
                m.pos(vnew) = p;
554
                status[vnew] = 1;
555
                fun[vnew] = cut_val;
556
            }
568 jab 557
        }
558
 
640 janba 559
        for(FaceID fid : m.faces())
560
                for(Walker w = m.walker(fid);!w.full_circle(); w = w.next())
561
                    if(status[w.vertex()] == 1 && same_level(fun[w.vertex()],cut_val))
568 jab 562
                    {
640 janba 563
                        Walker w0 = w;
564
                        w = w.next().next();
565
                        do
568 jab 566
                        {
640 janba 567
                            if(status[w.vertex()] == 1 &&
568
                               w.next().halfedge() != w0.halfedge() &&
569
                               same_level(fun[w0.vertex()],cut_val))
570
                            {
571
                                m.split_face_by_edge(fid, w0.vertex(), w.vertex());
572
                                break;
573
                            }
574
                            w = w.next();
568 jab 575
                        }
640 janba 576
                        while(!w.full_circle());
577
                        break;
568 jab 578
                    }
579
    }
640 janba 580
 
631 janba 581
    shortest_edge_triangulate(m);
572 jab 582
 
640 janba 583
 
584
 
568 jab 585
    // ----------------------------
586
    cout << "Numbering the level sets" << endl;
631 janba 587
    vector<LevelSetInfo> level_set_info;
588
    HalfEdgeAttributeVector<int> level_set_id(m.allocated_halfedges(), -1);
589
    VertexAttributeVector<int> level_set_id_vertex(m.allocated_vertices(), -1);
590
    int no_id=0;
640 janba 591
    for(HalfEdgeID hid : m.halfedges())
568 jab 592
    {
640 janba 593
        Walker w = m.walker(hid);
568 jab 594
        if(status[w.vertex()] == 1 && status[w.opp().vertex()] == 1 &&
595
           same_level(fun[w.vertex()], fun[w.opp().vertex()]) &&
631 janba 596
           level_set_id[w.halfedge()] == -1)
568 jab 597
        {
631 janba 598
            LevelSetInfo lsi;
599
            lsi.id = no_id;
600
            lsi.fun_value = fun[w.vertex()];
601
            lsi.components = 1;
602
            lsi.no_vertices = 0;
640 janba 603
            double level_set_length = 0;
568 jab 604
            while(level_set_id[w.halfedge()] != no_id)
605
            {
572 jab 606
                level_set_length += length(m,w.halfedge());
568 jab 607
                level_set_id[w.halfedge()] = no_id;
608
                level_set_id[w.opp().halfedge()] = no_id;
609
                level_set_id_vertex[w.vertex()] = no_id;
610
                w = w.next();
640 janba 611
                while(!(status[w.vertex()] == 1 && same_level(fun[w.vertex()], fun[w.opp().vertex()])))
568 jab 612
                    w = w.circulate_vertex_cw();
631 janba 613
                lsi.no_vertices += 1;
614
            }
615
            lsi.h = w.halfedge();
616
            lsi.length = level_set_length;
617
            level_set_info.push_back(lsi);
618
            level_set_info.back().print();
572 jab 619
            ++no_id;
631 janba 620
            assert(level_set_info.size()==no_id);
568 jab 621
        }
622
    }
623
 
631 janba 624
    cout << "ids" << no_id << " " << level_set_info.size() << endl;
625
    for(int i=0;i<level_set_info.size(); ++i)
626
        for(int j=0;j<level_set_info.size(); ++j)
627
            if(i != j && same_level(level_set_info[i].fun_value, level_set_info[j].fun_value))
628
                level_set_info[i].components += 1;
572 jab 629
 
631 janba 630
    HalfEdgeID min_length_h;
631
    double min_length_fun;
632
    double min_length=FLT_MAX;
633
    int min_length_id = -1;
634
    for(int i=0;i<level_set_info.size(); ++i)
635
    {
636
        LevelSetInfo& lsi = level_set_info[i];
637
        if(lsi.components==1 && lsi.length<min_length)
638
        {
639
            min_length_h = lsi.h;
640
            min_length_fun = lsi.fun_value;
641
            min_length = lsi.length;
642
            min_length_id = lsi.id;
640 janba 643
 
631 janba 644
        }
645
    }
572 jab 646
 
568 jab 647
    // ----------------------------
648
    cout << "Remove vertices not on level set curves" << endl;
572 jab 649
 
568 jab 650
 
651
}
652
 
572 jab 653
void make_height_fun(const HMesh::Manifold& m, HMesh::VertexAttributeVector<double>& fun,
654
                     double& vmin, double& vmax)
568 jab 655
{
656
    VertexIDIterator vid = m.vertices_begin();
640 janba 657
    vmin = vmax = m.pos(*vid)[1];
568 jab 658
    for(; vid != m.vertices_end(); ++vid)
659
    {
631 janba 660
        double v = dot(m.pos(*vid),Vec3d(0.0,1,0.00));
568 jab 661
        fun[*vid] = v;
662
        vmin = min(v, vmin);
663
        vmax = max(v, vmax);
664
    }
665
}
640 janba 666