Subversion Repositories gelsvn

Rev

Rev 642 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 642 Rev 643
Line 10... Line 10...
10
 
10
 
11
 
11
 
12
#include "harmonics.h"
12
#include "harmonics.h"
13
#include "polarize.h"
13
#include "polarize.h"
14
#include <CGLA/Vec2d.h>
14
#include <CGLA/Vec2d.h>
-
 
15
#include <CGLA/Mat4x4d.h>
-
 
16
#include <CGLA/Vec3i.h>
15
#include <LinAlg/LapackFunc.h>
17
#include <LinAlg/LapackFunc.h>
16
#include <HMesh/triangulate.h>
18
#include <HMesh/triangulate.h>
17
#include <HMesh/obj_save.h>
19
#include <HMesh/obj_save.h>
18
#include <HMesh/curvature.h>
20
#include <HMesh/curvature.h>
19
#include <HMesh/quadric_simplify.h>
21
#include <HMesh/quadric_simplify.h>
20
#include <HMesh/mesh_optimization.h>
22
#include <HMesh/mesh_optimization.h>
21
#include <HMesh/smooth.h>
23
#include <HMesh/smooth.h>
-
 
24
#include <HMesh/dual.h>
-
 
25
 
-
 
26
#include <Geometry/GridAlgorithm.h>
-
 
27
#include <Geometry/build_bbtree.h>
-
 
28
#include <Geometry/RGrid.h>
-
 
29
#include <Geometry/TrilinFilter.h>
-
 
30
#include <GLGraphics/ManifoldRenderer.h>
22
 
31
 
23
#include <complex>
32
#include <complex>
24
 
33
 
25
using namespace CGLA;
34
using namespace CGLA;
-
 
35
using namespace Geometry;
26
using namespace std;
36
using namespace std;
27
using namespace HMesh;
37
using namespace HMesh;
-
 
38
using namespace GLGraphics;
28
 
39
 
29
inline bool same_level(double a, double b) {return abs(a-b) < 1e-10;}
40
inline bool same_level(double a, double b) {return abs(a-b) < 1e-10;}
30
 
41
 
31
enum VertexStatus {
42
enum VertexStatus {
32
    RAW, POLE, SADDLE, COOKED
43
    RAW, COOKED
33
};
44
};
34
 
45
 
35
void kill_wedges(Manifold& m, const VertexAttributeVector<double>& fun, const VertexAttributeVector<VertexStatus>& status)
-
 
36
{
-
 
37
    for(auto hid : m.halfedges())
-
 
38
        if(m.in_use(hid)){
-
 
39
            Walker w = m.walker(hid);
-
 
40
            if(same_level(fun[w.vertex()], fun[w.opp().vertex()]) &&
-
 
41
               status[w.vertex()] == COOKED &&
-
 
42
               status[w.opp().vertex()] == COOKED &&
-
 
43
               no_edges(m, w.face())==3 &&
-
 
44
               status[w.next().vertex()] == COOKED &&
-
 
45
               precond_collapse_edge(m, hid))
-
 
46
                m.collapse_edge(hid);
-
 
47
        
-
 
48
    }
-
 
49
}
-
 
50
 
46
 
51
void high_gradient_triangulate(Manifold& m, FaceID _f, const VertexAttributeVector<double>& fun)
47
void shortest_edge_triangulate_face(Manifold& m, FaceID f0, const VertexAttributeVector<int>& level_set_id_vertex)
52
{
48
{
-
 
49
    queue<FaceID> face_queue;
53
    
50
    
54
    queue<FaceID> fq;
51
    face_queue.push(f0);
55
    fq.push(_f);
52
    
56
    while(!fq.empty()) {
53
    while(!face_queue.empty())
-
 
54
    {
57
        FaceID f = fq.front();
55
        FaceID f = face_queue.front();
58
        fq.pop();
56
        face_queue.pop();
59
        if(no_edges(m, f)<=3)
-
 
60
            continue;
57
        
61
        // Create a vector of vertices.
58
        // Create a vector of vertices.
62
        vector<VertexID> verts;
59
        vector<VertexID> verts;
63
        circulate_face_ccw(m, f, [&](VertexID v){verts.push_back(v);});
60
        for(Walker w = m.walker(f); !w.full_circle(); w = w.circulate_face_ccw())
-
 
61
        {
-
 
62
            FaceID fa = w.face();
-
 
63
            FaceID fb = f;
-
 
64
            assert(fa==fb);
-
 
65
            verts.push_back(w.vertex());
-
 
66
        }
-
 
67
        // If there are just three we are done.
-
 
68
        if(verts.size() == 3) continue;
64
        
69
        
65
        // Find vertex pairs that may be connected.
70
        // Find vertex pairs that may be connected.
66
        vector<pair<int,int> > vpairs;
71
        vector<pair<int,int> > vpairs;
67
        const int N = verts.size();
72
        const int N = verts.size();
68
        for(int i = 0; i < N - 2; ++i){
73
        for(int i = 0; i < N - 2; ++i){
69
            for(int j = i + 2; j < N; ++j){
74
            for(int j = i + 2; j < N; ++j){
-
 
75
                if(verts[i] != verts[j] &&
70
                if(verts[i] != verts[j] && !connected(m, verts[i], verts[j]))
76
                   !connected(m, verts[i], verts[j]) &&
-
 
77
                   (level_set_id_vertex[verts[i]] == 0 || level_set_id_vertex[verts[i]] != level_set_id_vertex[verts[j]])
-
 
78
                   )
71
                    vpairs.push_back(pair<int,int>(i, j));
79
                    vpairs.push_back(pair<int,int>(i, j));
72
            }
80
            }
73
        }
81
        }
74
        if(vpairs.empty()){
82
        if(vpairs.empty()){
75
            cout << "Warning: could not triangulate a face."
83
            cout << "Warning: could not triangulate a face."
Line 78... Line 86...
78
        }
86
        }
79
        
87
        
80
        /* For all vertex pairs, find the edge lengths. Combine the
88
        /* For all vertex pairs, find the edge lengths. Combine the
81
         vertices forming the shortest edge. */
89
         vertices forming the shortest edge. */
82
        
90
        
83
        float max_grad=-FLT_MAX;
91
        float min_len=FLT_MAX;
84
        size_t max_k = -1;
92
        int min_k = -1;
85
        for(size_t k = 0; k < vpairs.size(); ++k){
93
        for(size_t k = 0; k < vpairs.size(); ++k){
86
            int i = vpairs[k].first;
94
            int i = vpairs[k].first;
87
            int j = vpairs[k].second;
95
            int j = vpairs[k].second;
88
            double grad = abs(fun[verts[i]]-fun[verts[j]])/length(m.pos(verts[i]) - m.pos(verts[j]));
96
            float len = length(m.pos(verts[i]) - m.pos(verts[j]));
89
            
97
            //            cout << m.pos(verts[i]) << m.pos(verts[j]) << len << endl;
90
            if(grad>max_grad){
98
            if(len<min_len){
91
                max_grad = grad;
99
                min_len = len;
92
                max_k = k;
100
                min_k = k;
93
            }
101
            }
94
        }
102
        }
95
        assert(max_k != -1);
103
        assert(min_k != -1);
96
        
104
        
-
 
105
        if(min_k>=0)
97
        {
106
        {
-
 
107
            // Split faces along edge whose midpoint is closest to isovalue
98
            int i = vpairs[max_k].first;
108
            int i = vpairs[min_k].first;
99
            int j = vpairs[max_k].second;
109
            int j = vpairs[min_k].second;
100
            if(m.in_use(verts[i]) && m.in_use(verts[j])) {
110
            //           cout << i << " " << j << " " << min_k << " " << vpairs.size() << endl;
101
                FaceID f2 = m.split_face_by_edge(f, verts[i], verts[j]);
111
            FaceID f_new = m.split_face_by_edge(f, verts[i], verts[j]);
-
 
112
            
102
                fq.push(f);
113
            if(no_edges(m, f)>3)
103
                fq.push(f2);
114
                face_queue.push(f);
104
            }
115
            if(no_edges(m, f_new)>3)
-
 
116
                face_queue.push(f_new);
105
        }
117
        }
-
 
118
        else
-
 
119
            cout << "failed to triangle. Suspect NaN vertex positions!!" << endl;
-
 
120
        
106
    }
121
    }
107
}
122
}
108
 
123
 
109
FaceID merge_face_in_1_ring(Manifold& m, VertexID v)
124
void flip_edges(Manifold& m, VertexAttributeVector<int> ls_id)
110
{
125
{
111
    Walker w=m.walker(v);
126
    vector<HalfEdgeID> hvec;
112
    HalfEdgeID h = w.next().halfedge();
127
    for(HalfEdgeID hid : m.halfedges())
113
    if(m.remove_vertex(v))
-
 
114
    {
128
    {
-
 
129
        Walker w = m.walker(hid);
-
 
130
        if(hid< w.opp().halfedge() &&
-
 
131
           ls_id[w.vertex()] > 0 &&
-
 
132
           ls_id[w.opp().vertex()] > 0 &&
-
 
133
           ls_id[w.vertex()] != ls_id[w.opp().vertex()])
115
        return m.close_hole(h);
134
            hvec.push_back(hid);
116
    }
135
    }
-
 
136
    
117
    return InvalidFaceID;
137
    ValencyEnergy mae;
-
 
138
    bool did_work = false;
-
 
139
    int iter=0;
-
 
140
    do {
-
 
141
        did_work = false;
-
 
142
        random_shuffle(begin(hvec), end(hvec));
-
 
143
        for(auto hid : hvec)
-
 
144
        {
-
 
145
            Walker w =m.walker(hid);
-
 
146
            if(mae.delta_energy(m, hid)<=0 &&
-
 
147
               ls_id[w.next().vertex()] != ls_id[w.opp().next().vertex()]) {
-
 
148
                m.flip_edge(hid);
-
 
149
                did_work = true;
-
 
150
            }
-
 
151
        }
-
 
152
    }
-
 
153
    while (did_work && ++iter<1000);
-
 
154
    cout << "flip iter" << iter << endl;
118
}
155
}
119
 
156
 
120
 
-
 
121
void compute_edge_weights(const Manifold& m, HalfEdgeAttributeVector<double>& edge_weights, FaceAttributeVector<int>& included)
157
void compute_edge_weights(const Manifold& m, HalfEdgeAttributeVector<double>& edge_weights, FaceAttributeVector<int>& included)
122
{
158
{
123
    edge_weights = HalfEdgeAttributeVector<double>(m.allocated_halfedges(), 0);
159
    edge_weights = HalfEdgeAttributeVector<double>(m.allocated_halfedges(), 0);
124
    for(FaceIDIterator f = m.faces_begin(); f != m.faces_end(); ++f)
160
    for(FaceIDIterator f = m.faces_begin(); f != m.faces_end(); ++f)
125
        if(included[*f])
161
        if(included[*f])
Line 167... Line 203...
167
                new_fun[*v] = fun[*v];
203
                new_fun[*v] = fun[*v];
168
        fun = new_fun;
204
        fun = new_fun;
169
    }
205
    }
170
}
206
}
171
 
207
 
-
 
208
void label_connected_components(Manifold&m, int& cur_id, const vector<VertexID>& vertices,
-
 
209
                                const VertexAttributeVector<double>& fun,
172
vector<VertexID> cut_mesh(Manifold& m, VertexAttributeVector<double>& fun, double cut_val, VertexAttributeVector<VertexStatus>& status)
210
                                const VertexAttributeVector<VertexStatus>& status,
-
 
211
                                VertexAttributeVector<int>& level_id)
173
{
212
{
174
    cout << "Cutting at " << cut_val << endl;
-
 
175
    
-
 
176
    vector<VertexID> new_verts;
-
 
177
    vector<HalfEdgeID> hidvec;
-
 
178
    for(HalfEdgeID hid : m.halfedges())
213
    for(auto vid : vertices)
179
    {
214
    {
180
        Walker w = m.walker(hid);
215
        if(level_id[vid]>0)
181
        double bval = fun[w.vertex()];
216
            continue;
-
 
217
        
182
        double aval = fun[w.opp().vertex()];
218
        queue<VertexID> vq;
-
 
219
        vq.push(vid);
183
        if(aval<bval && aval < cut_val && cut_val <= bval)
220
        while(!vq.empty())
184
        {
221
        {
185
            double t = (cut_val-aval)/(bval-aval);
222
            VertexID v = vq.front();
186
            Vec3d p = t*m.pos(w.vertex()) + (1.0-t)*m.pos(w.opp().vertex());
223
            vq.pop();
187
            VertexID vnew = m.split_edge(hid);
224
            level_id[v] = cur_id;
-
 
225
            for(Walker w = m.walker(v); !w.full_circle(); w = w.circulate_vertex_ccw())
188
            m.pos(vnew) = p;
226
            {
-
 
227
                if(status[w.vertex()]==COOKED && same_level(fun[v], fun[w.vertex()]))
189
            status[vnew] = COOKED;
228
                    if(level_id[w.vertex()]==0)
190
            fun[vnew] = cut_val;
229
                        vq.push(w.vertex());
191
            new_verts.push_back(vnew);
230
                    else if(level_id[w.vertex()] != cur_id)
-
 
231
                        cout << "previously labeled vertex encountered" << endl;
-
 
232
            }
192
        }
233
        }
-
 
234
        ++cur_id;
193
    }
235
    }
-
 
236
}
-
 
237
 
-
 
238
void connect_touched(Manifold& m, const VertexAttributeVector<int>& touched)
194
    
239
{
195
    for(FaceID fid : m.faces())
240
    for(FaceID fid : m.faces())
196
        for(Walker w = m.walker(fid);!w.full_circle(); w = w.next())
241
        for(Walker w = m.walker(fid);!w.full_circle(); w = w.next())
197
            if(status[w.vertex()] == COOKED && same_level(fun[w.vertex()],cut_val))
242
            if(touched[w.vertex()])
198
            {
243
            {
199
                Walker w0 = w;
244
                Walker w0 = w;
200
                w = w.next().next();
245
                w = w.next().next();
201
                do
246
                do
202
                {
247
                {
203
                    if(status[w.vertex()] == COOKED &&
-
 
204
                       w.next().halfedge() != w0.halfedge() &&
248
                    if(touched[w.vertex()] && w.next().halfedge() != w0.halfedge())
205
                       same_level(fun[w.vertex()],cut_val))
-
 
206
                    {
249
                    {
207
                        m.split_face_by_edge(fid, w0.vertex(), w.vertex());
250
                        m.split_face_by_edge(fid, w0.vertex(), w.vertex());
208
                        break;
251
                        break;
209
                    }
252
                    }
210
                    w = w.next();
253
                    w = w.next();
211
                }
254
                }
212
                while(!w.full_circle());
255
                while(!w.full_circle());
213
                break;
256
                break;
214
            }
257
            }
-
 
258
}
-
 
259
 
-
 
260
void remove_shorts(Manifold& m, VertexAttributeVector<int> ls_id)
-
 
261
{
-
 
262
    double avghlen=0;
-
 
263
    for(auto hid : m.halfedges())
-
 
264
        avghlen += length(m, hid);
-
 
265
    avghlen /= m.no_halfedges();
-
 
266
    
-
 
267
    for(auto hid : m.halfedges())
-
 
268
        if(m.in_use(hid))
-
 
269
        {
-
 
270
            Walker w = m.walker(hid);
-
 
271
            if(ls_id[w.vertex()] > 0 && 	
-
 
272
               ls_id[w.vertex()] == ls_id[w.opp().vertex()] &&
-
 
273
               length(m, w.halfedge()) < 0.1 * avghlen &&
-
 
274
               precond_collapse_edge(m, hid))
-
 
275
                m.collapse_edge(hid);
-
 
276
        }
-
 
277
}
-
 
278
 
-
 
279
vector<VertexID> separate_edges(Manifold& m, const vector<VertexID>& vertices, int id,
-
 
280
                                VertexAttributeVector<double>& fun,
-
 
281
                                VertexAttributeVector<VertexStatus>& status,
-
 
282
                                VertexAttributeVector<int>& ls_id)
-
 
283
{
-
 
284
    VertexAttributeVector<int> touched(m.allocated_vertices(),0);
-
 
285
    vector<VertexID> new_vertices;
-
 
286
    // Cut all edges to vertices on other LS ID
-
 
287
    for(auto vid: vertices)
-
 
288
        if(ls_id[vid]==id)
-
 
289
        {
-
 
290
            vector<HalfEdgeID> edges_to_split;
-
 
291
            for(Walker w = m.walker(vid); !w.full_circle(); w = w.circulate_vertex_ccw())
-
 
292
            {
-
 
293
                int id = ls_id[w.vertex()];
-
 
294
                if(id > 0 & id != ls_id[vid])
-
 
295
                    edges_to_split.push_back(w.halfedge());
-
 
296
            }
-
 
297
            
-
 
298
            for (auto hid : edges_to_split)
-
 
299
            {
-
 
300
                VertexID vnew = m.split_edge(hid);
-
 
301
                fun[vnew] = fun[vid];
-
 
302
                m.pos(vnew) = m.pos(vid);
-
 
303
                status[vnew] = COOKED;
-
 
304
                ls_id[vnew] = ls_id[vid];
-
 
305
                touched[vnew] = 1;
-
 
306
                new_vertices.push_back(vnew);
-
 
307
            }
-
 
308
        }
-
 
309
    
-
 
310
    // Label old vertices as plain (uncooked)
-
 
311
    for(auto vid: vertices)
-
 
312
        if(ls_id[vid]==id)
-
 
313
        {
-
 
314
            status[vid] = RAW;
-
 
315
            ls_id[vid] = 0;
-
 
316
        }
-
 
317
    connect_touched(m, touched);
-
 
318
    
-
 
319
    return new_vertices;
-
 
320
}
-
 
321
 
-
 
322
vector<VertexID> cut_mesh(Manifold& m, VertexAttributeVector<double>& fun, double cut_val,
-
 
323
                          VertexAttributeVector<VertexStatus>& status)
-
 
324
{
-
 
325
    cout << "cutting @ " << cut_val << endl;
-
 
326
    
-
 
327
    vector<VertexID> new_verts;
-
 
328
    vector<HalfEdgeID> hidvec;
-
 
329
    VertexAttributeVector<int> touched(m.allocated_vertices(), 0);
-
 
330
    for(HalfEdgeID hid : m.halfedges())
-
 
331
    {
-
 
332
        Walker w = m.walker(hid);
-
 
333
        double bval = fun[w.vertex()];
-
 
334
        double aval = fun[w.opp().vertex()];
-
 
335
        if(aval<bval && aval < cut_val && cut_val <= bval)
-
 
336
        {
-
 
337
            double t = (cut_val-aval)/(bval-aval);
-
 
338
            Vec3d p = t*m.pos(w.vertex()) + (1.0-t)*m.pos(w.opp().vertex());
-
 
339
            VertexID vnew = m.split_edge(hid);
-
 
340
            m.pos(vnew) = p;
-
 
341
            status[vnew] = COOKED;
-
 
342
            fun[vnew] = cut_val;
-
 
343
            touched[vnew] = 1;
-
 
344
            new_verts.push_back(vnew);
-
 
345
        }
-
 
346
    }
-
 
347
    
-
 
348
    connect_touched(m, touched);
-
 
349
    
215
    return new_verts;
350
    return new_verts;
216
}
351
}
217
 
352
 
218
void smooth_cooked_vertices(Manifold& m, const vector<VertexID>& vertices, VertexAttributeVector<double>& fun,
353
void smooth_cooked_vertices(Manifold& m, const vector<VertexID>& vertices,
219
                            VertexAttributeVector<VertexStatus>& status, int iter=1)
354
                            VertexAttributeVector<VertexStatus>& status, int iter=7)
220
{
355
{
221
    for(int i=0;i<iter;++i)
356
    for(int i=0;i<iter;++i)
222
    {
357
    {
223
        VertexAttributeVector<Vec3d> npos(m.allocated_vertices(), Vec3d(0));
358
        VertexAttributeVector<Vec3d> npos = m.positions_attribute_vector();
224
        VertexAttributeVector<int> cnt(m.allocated_vertices(), 0);
359
        VertexAttributeVector<int> cnt(m.allocated_vertices(), 1);
225
        for(auto vid : vertices)
360
        for(auto vid : vertices)
226
           if(m.in_use(vid))
361
            if(m.in_use(vid))
227
            for(Walker w = m.walker(vid); !w.full_circle(); w = w.circulate_vertex_ccw())
362
                for(Walker w = m.walker(vid); !w.full_circle(); w = w.circulate_vertex_ccw())
228
                if(status[vid]==COOKED) {
363
                    if(status[vid]==COOKED) {
229
                    npos[vid] += m.pos(w.vertex());
364
                        npos[vid] += m.pos(w.vertex());
230
                    ++cnt[vid];
365
                        ++cnt[vid];
231
                }
366
                    }
232
        for(auto vid : vertices)
367
        for(auto vid : vertices)
233
            if(m.in_use(vid))
368
            if(m.in_use(vid))
234
            m.pos(vid) = (npos[vid])/cnt[vid];
369
                m.pos(vid) = (npos[vid])/cnt[vid];
235
    }
370
    }
236
}
371
}
237
 
372
 
-
 
373
void remove_v5_vertices(Manifold& m, VertexAttributeVector<int>& ls_id, int id_ceiling)
-
 
374
{
-
 
375
    for(auto vid: m.vertices())
-
 
376
    {
-
 
377
        int id = ls_id[vid];
-
 
378
        if(id>0 && id<id_ceiling)
-
 
379
        {
-
 
380
            vector<HalfEdgeID> hit_list;
-
 
381
            for(Walker w = m.walker(vid); !w.full_circle(); w=w.circulate_vertex_ccw())
-
 
382
                if(ls_id[w.vertex()] >= id_ceiling)
-
 
383
                    hit_list.push_back(w.halfedge());
-
 
384
            
-
 
385
            if(hit_list.size()>1)
-
 
386
            {
-
 
387
                sort(begin(hit_list),end(hit_list),
-
 
388
                     [&m](HalfEdgeID a, HalfEdgeID b){return length(m,a)>length(m, b);});
-
 
389
                for(int i=1;i<hit_list.size();++i)
-
 
390
                {
-
 
391
                    HalfEdgeID hid = hit_list[i];
-
 
392
                    Walker w = m.walker(hid);
-
 
393
                    HalfEdgeID surplus_h = w.opp().prev().halfedge();
-
 
394
                    if(precond_collapse_edge(m,surplus_h))
-
 
395
                    {
-
 
396
                        m.collapse_edge(surplus_h,true);
-
 
397
                        m.merge_faces(m.walker(hid).face(), hid);
-
 
398
                    }
-
 
399
                }
-
 
400
            }
-
 
401
            
-
 
402
        }
-
 
403
    }
-
 
404
    
-
 
405
}
-
 
406
 
-
 
407
void remove_wedges(Manifold& m, VertexAttributeVector<int>& ls_id)
-
 
408
{
-
 
409
    for(auto hid : m.halfedges())
-
 
410
        if(m.in_use(hid))
-
 
411
        {
-
 
412
            Walker w = m.walker(hid);
-
 
413
            if(ls_id[w.vertex()]>0 &&
-
 
414
               ls_id[w.vertex()] == ls_id[w.opp().vertex()] &&
-
 
415
               ls_id[w.next().vertex()]>0 &&
-
 
416
               no_edges(m, w.face())==3 &&
-
 
417
               precond_collapse_edge(m, hid))
-
 
418
                m.collapse_edge(hid, true);
-
 
419
            
-
 
420
        }
-
 
421
}
-
 
422
 
-
 
423
 
-
 
424
 
238
int ssb(double a, double b)
425
int ssb(double a, double b)
239
{
426
{
240
    const double THRESH = 1e-6;
427
    const double THRESH = 1e-6;
241
    double delta = a-b;
428
    double delta = a-b;
242
    if(delta<-THRESH) return -1;
429
    if(delta<-THRESH) return -1;
243
    if(delta>THRESH) return 1;
430
    if(delta>THRESH) return 1;
244
    return 0;
431
    return 0;
245
}
432
}
246
 
433
 
247
void classify_vertices(Manifold& m, VertexAttributeVector<double>& fun, VertexAttributeVector<VertexStatus>& status)
434
void remove_vertices(Manifold& m, VertexAttributeVector<double>& fun,
248
{
-
 
249
    for(auto vid : m.vertices())
-
 
250
    {
-
 
251
        double val = fun[vid];
-
 
252
        auto w = m.walker(vid);
-
 
253
        int above_below = ssb(fun[w.vertex()],val);
-
 
254
        int changes = 0;
-
 
255
        w = w.circulate_vertex_ccw();
-
 
256
        for(; !w.full_circle();w = w.circulate_vertex_ccw())
-
 
257
        {
-
 
258
            int above_below_new = ssb(fun[w.vertex()],val);
435
                     const VertexAttributeVector<VertexStatus>& status,
259
            if(above_below != above_below_new)
-
 
260
                ++changes;
-
 
261
            above_below=above_below_new;
-
 
262
        }
-
 
263
        if(changes==0)
-
 
264
            status[vid]=POLE;
-
 
265
        else if(changes>=4)
-
 
266
            status[vid]=SADDLE;
-
 
267
        else if(changes==2)
-
 
268
            status[vid]=RAW;
-
 
269
        else assert(0);
-
 
270
    }
-
 
271
}
-
 
272
 
-
 
273
void remove_vertices(Manifold& m, VertexAttributeVector<double>& fun, VertexAttributeVector<VertexStatus>& status, double rmin, double rmax)
436
                     const VertexAttributeVector<int>& level_id, double rmin, double rmax)
274
{
437
{
275
    vector<VertexID> vertices_to_push;
438
    vector<VertexID> vertices_to_push;
276
    for(auto vid: m.vertices())
439
    for(auto vid: m.vertices())
277
        if(status[vid]==RAW &&
440
        if(status[vid]==RAW &&
278
           fun[vid] >= rmin &&
441
           fun[vid] >= rmin &&
Line 281... Line 444...
281
    
444
    
282
    random_shuffle(begin(vertices_to_push), end(vertices_to_push));
445
    random_shuffle(begin(vertices_to_push), end(vertices_to_push));
283
    
446
    
284
    for(auto vid : vertices_to_push)
447
    for(auto vid : vertices_to_push)
285
    {
448
    {
286
        FaceID fid = merge_face_in_1_ring(m,vid);
449
        FaceID fid = m.merge_one_ring(vid);
287
        if(fid != InvalidFaceID)
450
        if(fid != InvalidFaceID)
288
            high_gradient_triangulate(m, fid, fun);
451
            shortest_edge_triangulate_face(m, fid, level_id);
289
    }
452
    }
290
}
453
}
291
 
454
 
292
 
455
 
293
void polarize_mesh(Manifold& m, VertexAttributeVector<double>& fun, double vmin, double vmax, const int divisions, VertexAttributeVector<Vec2d>& parametrization)
456
void polarize_mesh(Manifold& m, VertexAttributeVector<double>& fun, double vmin, double vmax, const int divisions, VertexAttributeVector<Vec2d>& parametrization)
294
{
457
{
295
    VertexAttributeVector<VertexStatus> status(m.allocated_vertices(), RAW);
458
    VertexAttributeVector<VertexStatus> status(m.allocated_vertices(), RAW);
296
    
-
 
-
 
459
    VertexAttributeVector<int> level_id(m.allocated_vertices(), 0);
297
    classify_vertices(m, fun, status);
460
    int cur_id = 1;
298
    
461
    
299
    double interval = (vmax-vmin)/(divisions+1);
462
    double interval = (vmax-vmin)/(divisions+1);
300
    double base_cut_val = vmin + 0.02*(vmax-vmin);
463
    double cut_val = vmin + 0.065*(vmax-vmin);
-
 
464
    
-
 
465
    vector<VertexID> cut_verts = cut_mesh(m, fun, cut_val, status);
-
 
466
    label_connected_components(m, cur_id, cut_verts, fun, status, level_id);
-
 
467
    remove_vertices(m, fun, status, level_id, vmin, cut_val);
-
 
468
    flip_edges(m, level_id);
-
 
469
    
-
 
470
    for(int id=1;id<cur_id;++id) {
-
 
471
        vector<VertexID> loop_verts = separate_edges(m, cut_verts, id, fun, status, level_id);
-
 
472
        smooth_cooked_vertices(m, loop_verts, status, 50);
-
 
473
    }
301
    
474
    
302
    vector<VertexID> new_verts = cut_mesh(m, fun, base_cut_val, status);
-
 
303
    smooth_cooked_vertices(m, new_verts, fun, status, 1);
-
 
304
    cout << "Base " << base_cut_val << endl;
-
 
305
    for(int iter=0;iter<divisions+2;++iter)
475
    for(int iter=0;iter<divisions+2;++iter)
306
    {
476
    {
307
        int _iter=iter;//%2==0?iter/2:-1-iter/2;
477
        cut_val += interval;
308
        double cut_val = base_cut_val + interval * _iter;
478
        vector<VertexID> cut_verts = cut_mesh(m, fun,cut_val, status);
-
 
479
        
-
 
480
        int old_id = cur_id;
309
        cout << "i,c " << _iter << "," << cut_val << endl;
481
        label_connected_components(m, cur_id, cut_verts, fun, status, level_id);
310
        remove_vertices(m, fun, status, cut_val, cut_val+interval);
482
        remove_vertices(m, fun, status, level_id, cut_val-1.01*interval, cut_val);
-
 
483
        
-
 
484
        vector<VertexID> loop_verts;
-
 
485
        for(int id=old_id;id<cur_id;++id)
-
 
486
        {
311
        vector<VertexID> new_verts = cut_mesh(m, fun,_iter<0?cut_val:cut_val+interval, status);
487
            vector<VertexID> tmp = separate_edges(m, cut_verts, id, fun, status, level_id);
-
 
488
            loop_verts.insert(loop_verts.end(), tmp.begin(),tmp.end());
-
 
489
        }
312
        kill_wedges(m, fun, status);
490
        remove_wedges(m, level_id);
-
 
491
        remove_v5_vertices(m, level_id, old_id);
-
 
492
        
313
        smooth_cooked_vertices(m, new_verts, fun, status, 1);
493
        smooth_cooked_vertices(m, loop_verts, status);
-
 
494
        
314
    }
495
    }
-
 
496
    dual(m);
-
 
497
    m.cleanup();
-
 
498
}
-
 
499
 
-
 
500
void simplify_polar_mesh(Manifold& m, double frac)
-
 
501
{
-
 
502
    int N_orig = m.no_vertices();
-
 
503
    HalfEdgeAttributeVector<int> touched(m.allocated_halfedges(),0);
315
    
504
    
-
 
505
    vector<pair<double,vector<HalfEdgeID>>> work_vector;
-
 
506
    for(auto hid : m.halfedges())
-
 
507
    {
-
 
508
        Walker w = m.walker(hid);
-
 
509
        if(!touched[hid] &&
-
 
510
           no_edges(m, w.face()) == 4 &&
-
 
511
           no_edges(m, w.opp().face()) == 4)
-
 
512
        {
-
 
513
            
316
    int C=0, R=0, P=0,S=0;
514
            double l_sum=0;
-
 
515
            int n=0;
-
 
516
            vector<HalfEdgeID> hvec;
-
 
517
            
-
 
518
            bool abort=false;
-
 
519
            for(int i=0;i<2;++i)
-
 
520
            {
-
 
521
                Walker w0 = (i==0?w:w.opp().next().next().opp());
-
 
522
                while(!touched[w0.halfedge()])
-
 
523
                {
-
 
524
                    touched[w0.halfedge()] = 1;
-
 
525
                    touched[w0.opp().halfedge()] = 1;
-
 
526
                    hvec.push_back(w0.halfedge());
-
 
527
                    ++n;
-
 
528
                    l_sum += sqr(area(m,w0.face()));
-
 
529
                    if(valency(m,w0.vertex()) != 4 || valency(m, w0.opp().vertex()) != 4)
-
 
530
                        abort = true;
-
 
531
                    if(no_edges(m, w0.face())==4)
-
 
532
                        w0 = w0.next().next().opp();
-
 
533
                    else {
-
 
534
                        if (valency(m,w0.next().vertex())<5)
-
 
535
                            abort = true;
-
 
536
                        break;
-
 
537
                    }
-
 
538
                }
-
 
539
            }
-
 
540
            if(abort)
-
 
541
                continue;
-
 
542
            else
-
 
543
                work_vector.push_back(make_pair(l_sum/sqr(n),hvec));
-
 
544
        }
-
 
545
    }
-
 
546
    
-
 
547
    sort(begin(work_vector),end(work_vector));
-
 
548
    
-
 
549
    for(auto work : work_vector)
-
 
550
    {
-
 
551
        for(HalfEdgeID h :work.second)
-
 
552
            if(m.in_use(h) && precond_collapse_edge(m, h))
-
 
553
                m.collapse_edge(h,true);
-
 
554
            else cout << "Collapse failed ..." << endl;
-
 
555
        
-
 
556
        if(N_orig * frac > m.no_vertices())
-
 
557
            break;
-
 
558
    }
-
 
559
    m.cleanup();
-
 
560
    
-
 
561
}
-
 
562
 
-
 
563
using namespace Geometry;
-
 
564
 
-
 
565
const Mat4x4d fit_bounding_volume(const Vec3d& p0,
-
 
566
                                  const Vec3d& p7,
-
 
567
                                  float buf_reg,
-
 
568
                                  int vol_dim)
-
 
569
{
-
 
570
    Vec3d sz = p7 - p0;
-
 
571
    Vec3i dims(vol_dim);
-
 
572
    Vec3d scal_vec = (Vec3d(dims)-Vec3d(2*buf_reg+2))/sz;
-
 
573
    float scal = min(scal_vec[0], min(scal_vec[1],scal_vec[2]));
-
 
574
    
-
 
575
    Mat4x4d m = translation_Mat4x4d(Vec3d(0)+Vec3d(buf_reg+1));
-
 
576
    m *= scaling_Mat4x4d(Vec3d(scal));
-
 
577
    m *= translation_Mat4x4d(-p0);
-
 
578
    return m;
-
 
579
}
-
 
580
 
-
 
581
void smooth_and_refit(HMesh::Manifold& m_in,  HMesh::Manifold& m_ref, int iter, int vol_dim)
-
 
582
{
-
 
583
    AABBTree tree;
-
 
584
    
-
 
585
    Manifold m_tmp = m_ref;
-
 
586
    Vec3d p0,p7;
-
 
587
    bbox(m_tmp, p0, p7);
-
 
588
    Mat4x4d mat = fit_bounding_volume(p0, p7, 3, vol_dim);
-
 
589
    Mat4x4d imat = invert(mat);
317
    for(auto vid : m.vertices())
590
    for(auto vid : m_tmp.vertices())
-
 
591
        m_tmp.pos(vid) = mat.mul_3D_point(m_tmp.pos(vid));
-
 
592
    build_AABBTree(m_tmp, tree);
-
 
593
    
-
 
594
    cout << "Done building AABB tree" << endl;
-
 
595
    RGrid<float> grid(Vec3i(vol_dim),FLT_MAX);
-
 
596
    auto F = [&](const Vec3i& p,float& v)
-
 
597
    {
-
 
598
        v =  tree.compute_signed_distance(Vec3f(p));
-
 
599
    };
-
 
600
    for_each_voxel(grid, F);
-
 
601
    cout << "Made distance field" << endl;
-
 
602
    TrilinFilter<RGrid<float>> df(&grid);
-
 
603
    for (int i=0;i<iter; ++i)
318
    {
604
    {
-
 
605
        auto vsafe = m_in.positions_attribute_vector();
-
 
606
        laplacian_smooth(m_in,.25,10);
-
 
607
        for(auto vid : m_in.vertices())
-
 
608
        {
-
 
609
            double w = exp(4-valency(m_in, vid));
319
        switch(status[vid]) {
610
            m_in.pos(vid) *= w;
-
 
611
            m_in.pos(vid) += (1-w) * vsafe[vid];
-
 
612
        }
320
            case RAW: ++R; break;
613
        float avg = 0;
-
 
614
        for(auto hid : m_in.halfedges())
321
            case COOKED: ++C; break;
615
            avg += length(m_in, hid);
322
            case POLE: ++P; break;
616
        avg /= m_in.no_halfedges();
-
 
617
        auto npos = m_in.positions_attribute_vector();
-
 
618
        for(auto vid : m_in.vertices())
-
 
619
        {
-
 
620
            npos[vid] += 0.5 * avg * normal(m_in, vid);
-
 
621
        }
-
 
622
        m_in.positions_attribute_vector() = npos;
-
 
623
        for(auto vid : m_in.vertices())
-
 
624
        {
-
 
625
            Vec3f pos = Vec3f(mat.mul_3D_point(m_in.pos(vid)));
323
            case SADDLE: ++S; break;
626
            if(df.in_domain(pos))
-
 
627
                m_in.pos(vid) = imat.mul_3D_point(Vec3d(pos - df(pos) * df.grad(pos)));
-
 
628
            else
-
 
629
                cout << "outside domain" << endl;
324
        }
630
        }
325
    }
631
    }
326
    cout << "R=" << R << " C=" << C << " P=" << P << " S=" << S << endl;
-
 
-
 
632
    
327
}
633
}
328
 
634
 
329
void make_height_fun(const HMesh::Manifold& m, HMesh::VertexAttributeVector<double>& fun,
635
void make_height_fun(const HMesh::Manifold& m, HMesh::VertexAttributeVector<double>& fun,
330
                     double& vmin, double& vmax)
636
                     double& vmin, double& vmax)
331
{
637
{
Line 342... Line 648...
342
    }
648
    }
343
    
649
    
344
}
650
}
345
 
651
 
346
void make_adf_fun(HMesh::Manifold& m, double t, HMesh::VertexAttributeVector<double>& F,
652
void make_adf_fun(HMesh::Manifold& m, double t, HMesh::VertexAttributeVector<double>& F,
347
                     double& vmin, double& vmax)
653
                  double& vmin, double& vmax)
348
{
654
{
349
    Harmonics harm(m);
655
    Harmonics harm(m);
350
    harm.compute_adf(F, t);
656
    harm.compute_adf(F, t);
351
    VertexAttributeVector<int> nailed(m.allocated_vertices(), 0);
657
    VertexAttributeVector<int> nailed(m.allocated_vertices(), 0);
352
    vmin = vmax = F[*m.vertices_begin()];
658
    vmin = vmax = F[*m.vertices_begin()];