Subversion Repositories gelsvn

Rev

Rev 667 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 667 Rev 677
Line 1... Line 1...
1
/* ----------------------------------------------------------------------- *
1
/* ----------------------------------------------------------------------- *
2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
3
 * Copyright (C) the authors and DTU Informatics
3
 * Copyright (C) the authors and DTU Informatics
4
 * For license and list of authors, see ../../doc/intro.pdf
4
 * For license and list of authors, see ../../doc/intro.pdf
5
 * ----------------------------------------------------------------------- */
5
 * ----------------------------------------------------------------------- */
6
 
6
 
7
#include <thread>
7
#include <thread>
8
#include "smooth.h"
8
#include "smooth.h"
9
 
9
 
10
#include <future>
10
#include <future>
11
#include <vector>
11
#include <vector>
12
#include <algorithm>
12
#include <algorithm>
13
#include "../CGLA/Mat3x3d.h"
13
#include "../CGLA/Mat3x3d.h"
14
#include "../CGLA/Vec3d.h"
14
#include "../CGLA/Vec3d.h"
15
#include "../CGLA/Quatd.h"
15
#include "../CGLA/Quatd.h"
16
#include "../Util/Timer.h"
16
#include "../Util/Timer.h"
17
 
17
 
18
#include "Manifold.h"
18
#include "Manifold.h"
19
#include "AttributeVector.h"
19
#include "AttributeVector.h"
20
 
20
 
21
namespace HMesh
21
namespace HMesh
22
{
22
{
23
    using namespace std;
23
    using namespace std;
24
    using namespace CGLA;
24
    using namespace CGLA;
25
    
25
    
26
    
26
    
27
    class range {
27
    class range {
28
    public:
28
    public:
29
        class iterator {
29
        class iterator {
30
            friend class range;
30
            friend class range;
31
        public:
31
        public:
32
            long int operator *() const { return i_; }
32
            long int operator *() const { return i_; }
33
            const iterator &operator ++() { ++i_; return *this; }
33
            const iterator &operator ++() { ++i_; return *this; }
34
            iterator operator ++(int) { iterator copy(*this); ++i_; return copy; }
34
            iterator operator ++(int) { iterator copy(*this); ++i_; return copy; }
35
            
35
            
36
            bool operator ==(const iterator &other) const { return i_ == other.i_; }
36
            bool operator ==(const iterator &other) const { return i_ == other.i_; }
37
            bool operator !=(const iterator &other) const { return i_ != other.i_; }
37
            bool operator !=(const iterator &other) const { return i_ != other.i_; }
38
            
38
            
39
        protected:
39
        protected:
40
            iterator(long int start) : i_ (start) { }
40
            iterator(long int start) : i_ (start) { }
41
            
41
            
42
        private:
42
        private:
43
            unsigned long i_;
43
            unsigned long i_;
44
        };
44
        };
45
        
45
        
46
        iterator begin() const { return begin_; }
46
        iterator begin() const { return begin_; }
47
        iterator end() const { return end_; }
47
        iterator end() const { return end_; }
48
        range(long int  begin, long int end) : begin_(begin), end_(end) {}
48
        range(long int  begin, long int end) : begin_(begin), end_(end) {}
49
    private:
49
    private:
50
        iterator begin_;
50
        iterator begin_;
51
        iterator end_;
51
        iterator end_;
52
    };
52
    };
53
 
53
    
54
    typedef std::vector<std::vector<VertexID>> VertexIDBatches;
54
    void for_each_vertex(Manifold& m, function<void(VertexID)> f) { for(auto v : m.vertices()) f(v); }
55
    
55
    void for_each_face(Manifold& m, function<void(FaceID)> f) { for(auto p : m.faces()) f(p); }
56
 
56
    void for_each_halfedge(Manifold& m, function<void(HalfEdgeID)> f) { for(auto h : m.halfedges()) f(h); }
57
    
57
 
58
    void for_each_vertex(Manifold& m, function<void(VertexID)> f) { for(auto v : m.vertices()) f(v); }
58
    
59
    void for_each_face(Manifold& m, function<void(FaceID)> f) { for(auto p : m.faces()) f(p); }
59
    inline Vec3d laplacian(const Manifold& m, VertexID v)
60
    void for_each_halfedge(Manifold& m, function<void(HalfEdgeID)> f) { for(auto h : m.halfedges()) f(h); }
60
    {
61
 
61
        Vec3d p(0);
62
    
62
        int n = circulate_vertex_ccw(m, v, (std::function<void(VertexID)>)[&](VertexID v){ p += m.pos(v); });
63
    inline Vec3d laplacian(const Manifold& m, VertexID v)
63
        return p / n - m.pos(v);
64
    {
64
    }
65
        Vec3d p(0);
65
    
66
        int n = circulate_vertex_ccw(m, v, (std::function<void(VertexID)>)[&](VertexID v){ p += m.pos(v); });
66
    
67
        return p / n - m.pos(v);
67
    int CORES = 8;
68
    }
68
    
69
    
69
    void laplacian_smooth_example(Manifold& m)
70
    
70
    {
71
    int CORES = 8;
71
        VertexAttributeVector<Vec3d> new_pos = m.positions_attribute_vector();
72
    
72
        for(VertexID v : m.vertices())
73
    void laplacian_smooth_example(Manifold& m)
73
            if(!boundary(m, v))
74
    {
74
            {
75
        VertexAttributeVector<Vec3d> new_pos = m.positions_attribute_vector();
75
                Vec3d L(0);
76
        for(VertexID v : m.vertices())
76
                int n = circulate_vertex_ccw(m, v, (std::function<void(VertexID)>)[&](VertexID v){ L += m.pos(v); });
77
            if(!boundary(m, v))
77
                new_pos[v] = L/n;
78
            {
78
            }
79
                Vec3d L(0);
79
        m.positions_attribute_vector() = new_pos;
80
                int n = circulate_vertex_ccw(m, v, (std::function<void(VertexID)>)[&](VertexID v){ L += m.pos(v); });
80
    
81
                new_pos[v] = L/n;
81
    }
82
            }
82
    
83
        m.positions_attribute_vector() = new_pos;
83
    void laplacian_smooth0(Manifold& m,float weight, int max_iter)
84
    
84
    {
85
    }
85
        for(int iter=0;iter<max_iter; ++iter) {
86
    
86
            VertexAttributeVector<Vec3d> L_attr(m.no_vertices());
87
    void laplacian_smooth0(Manifold& m,float weight, int max_iter)
87
            
88
    {
88
            for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v)
89
        for(int iter=0;iter<max_iter; ++iter) {
89
                if(!boundary(m, *v))
90
            VertexAttributeVector<Vec3d> L_attr(m.no_vertices());
90
                    L_attr[*v] =laplacian(m, *v);
91
            
91
            for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v){
92
            for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v)
92
                if(!boundary(m, *v))
93
                if(!boundary(m, *v))
93
                    m.pos(*v) += weight*L_attr[*v];
94
                    L_attr[*v] =laplacian(m, *v);
94
            }
95
            for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v){
95
        }
96
                if(!boundary(m, *v))
96
    }
97
                    m.pos(*v) += weight*L_attr[*v];
97
    
98
            }
98
    void laplacian_smooth1(Manifold& m,float weight, int max_iter)
99
        }
99
    {
100
    }
100
        for(int iter=0;iter<max_iter; ++iter) {
101
    
101
            VertexAttributeVector<Vec3d> L_attr(m.no_vertices());
102
    void laplacian_smooth1(Manifold& m,float weight, int max_iter)
102
            
103
    {
103
            for(VertexID v : m.vertices())
104
        for(int iter=0;iter<max_iter; ++iter) {
104
                if(!boundary(m, v))
105
            VertexAttributeVector<Vec3d> L_attr(m.no_vertices());
105
                    L_attr[v] =laplacian(m, v);
106
            
106
            for(VertexID v : m.vertices()){
107
            for(VertexID v : m.vertices())
107
                if(!boundary(m, v))
108
                if(!boundary(m, v))
108
                    m.pos(v) += weight*L_attr[v];
109
                    L_attr[v] =laplacian(m, v);
109
            }
110
            for(VertexID v : m.vertices()){
110
        }
111
                if(!boundary(m, v))
111
    }
112
                    m.pos(v) += weight*L_attr[v];
112
    
113
            }
113
    void laplacian_smooth2(Manifold& m,float weight, int max_iter)
114
        }
114
    {
115
    }
115
        auto new_pos = m.positions_attribute_vector();
116
    
116
        for(int iter=0;iter<max_iter; ++iter) {
117
    void laplacian_smooth2(Manifold& m,float weight, int max_iter)
117
            for(auto v : m.vertices())
118
    {
118
                if(!boundary(m, v))
119
        auto new_pos = m.positions_attribute_vector();
119
                    new_pos[v] = weight*laplacian(m, v)+m.pos(v);
120
        for(int iter=0;iter<max_iter; ++iter) {
120
            m.positions_attribute_vector() = new_pos;
121
            for(auto v : m.vertices())
121
        }
122
                if(!boundary(m, v))
122
    }
123
                    new_pos[v] = weight*laplacian(m, v)+m.pos(v);
123
 
124
            m.positions_attribute_vector() = new_pos;
124
 
125
        }
125
    
126
    }
126
    void laplacian_smooth3(Manifold& m, float weight, int max_iter)
127
 
127
    {
128
 
128
        for(int iter=0;iter<max_iter; ++iter) {
129
    
129
            auto new_pos = m.positions_attribute_vector();
130
    void laplacian_smooth3(Manifold& m, float weight, int max_iter)
130
            for(auto v : m.vertices())
131
    {
131
                if(!boundary(m, v))
132
        for(int iter=0;iter<max_iter; ++iter) {
132
                    new_pos[v] = weight*laplacian(m, v)+m.pos(v);
133
            auto new_pos = m.positions_attribute_vector();
133
            m.positions_attribute_vector() = move(new_pos);
134
            for(auto v : m.vertices())
134
        }
135
                if(!boundary(m, v))
135
    }
136
                    new_pos[v] = weight*laplacian(m, v)+m.pos(v);
136
 
137
            m.positions_attribute_vector() = move(new_pos);
137
    void laplacian_smooth4(Manifold& m,float weight, int max_iter)
138
        }
138
    {
139
    }
139
        auto new_pos = m.positions_attribute_vector();
140
 
140
        for(int iter=0;iter<max_iter; ++iter) {
141
    void laplacian_smooth4(Manifold& m,float weight, int max_iter)
141
            for(VertexID v : m.vertices())
142
    {
142
                if(!boundary(m, v))
143
        auto new_pos = m.positions_attribute_vector();
143
                    new_pos[v] = weight*laplacian(m, v)+m.pos(v);
144
        for(int iter=0;iter<max_iter; ++iter) {
144
            swap(m.positions_attribute_vector(),new_pos);
145
            for(VertexID v : m.vertices())
145
        }
146
                if(!boundary(m, v))
146
    }
147
                    new_pos[v] = weight*laplacian(m, v)+m.pos(v);
147
    
148
            swap(m.positions_attribute_vector(),new_pos);
148
    void laplacian_smooth4_5(Manifold& m,float weight, int max_iter)
149
        }
149
    {
150
    }
150
        auto new_pos = m.positions_attribute_vector();
151
    
151
        for(int iter=0;iter<max_iter; ++iter) {
152
    void laplacian_smooth4_5(Manifold& m,float weight, int max_iter)
152
            for_each_vertex(m, [&](VertexID v) {new_pos[v] = weight*laplacian(m, v)+m.pos(v);});
153
    {
153
            swap(m.positions_attribute_vector(),new_pos);
154
        auto new_pos = m.positions_attribute_vector();
154
        }
155
        for(int iter=0;iter<max_iter; ++iter) {
155
    }
156
            for_each_vertex(m, [&](VertexID v) {new_pos[v] = weight*laplacian(m, v)+m.pos(v);});
156
 
157
            swap(m.positions_attribute_vector(),new_pos);
157
 
158
        }
158
    
159
    }
159
    void laplacian_smooth5(Manifold& m, float weight, int max_iter)
160
 
160
    {
161
 
161
        for(int iter=0;iter<max_iter; ++iter) {
162
    
162
            auto new_pos = m.positions_attribute_vector();
163
    void laplacian_smooth5(Manifold& m, float weight, int max_iter)
163
            vector<thread> t_vec;
164
    {
164
            for(auto v : m.vertices())
165
        for(int iter=0;iter<max_iter; ++iter) {
165
                if(!boundary(m, v))
166
            auto new_pos = m.positions_attribute_vector();
166
                    t_vec.push_back(thread([&](VertexID vid){
167
            vector<thread> t_vec;
167
                        if(!boundary(m, vid))
168
            for(auto v : m.vertices())
168
                            new_pos[vid] = weight*laplacian(m, vid)+ m.pos(vid);},v));
169
                if(!boundary(m, v))
169
            for(int i=0;i<t_vec.size();++i)
170
                    t_vec.push_back(thread([&](VertexID vid){
170
                t_vec[i].join();
171
                        if(!boundary(m, vid))
171
            m.positions_attribute_vector() = move(new_pos);
172
                            new_pos[vid] = weight*laplacian(m, vid)+ m.pos(vid);},v));
172
        }
173
            for(int i=0;i<t_vec.size();++i)
173
    }
174
                t_vec[i].join();
174
    
175
            m.positions_attribute_vector() = move(new_pos);
175
    
176
        }
176
    
177
    }
177
    inline void laplacian_smooth_vertex(Manifold& m, const vector<VertexID>& vids,
178
    
178
                                        VertexAttributeVector<Vec3d>& new_pos,
179
    
179
                                        float weight){
180
    
180
        for(VertexID v: vids)
181
    inline void laplacian_smooth_vertex(Manifold& m, const vector<VertexID>& vids,
181
            new_pos[v] = m.pos(v)+weight*laplacian(m, v);
182
                                        VertexAttributeVector<Vec3d>& new_pos,
182
    }
183
                                        float weight){
183
    
184
        for(VertexID v: vids)
184
    
185
            new_pos[v] = m.pos(v)+weight*laplacian(m, v);
185
    void laplacian_smooth6(Manifold& m, float weight, int max_iter)
186
    }
186
    {
187
    
187
        vector<vector<VertexID>> vertex_ids(CORES);
188
    
188
        auto batch_size = m.no_vertices()/CORES;
189
    void laplacian_smooth6(Manifold& m, float weight, int max_iter)
189
        int cnt = 0;
190
    {
190
        for_each_vertex(m, [&](VertexID v) {
191
        vector<vector<VertexID>> vertex_ids(CORES);
191
            if (!boundary(m, v))
192
        auto batch_size = m.no_vertices()/CORES;
192
                vertex_ids[(cnt++/batch_size)%CORES].push_back(v);
193
        int cnt = 0;
193
        });
194
        for_each_vertex(m, [&](VertexID v) {
194
        vector<thread> t_vec(CORES);
195
            if (!boundary(m, v))
195
        VertexAttributeVector<Vec3d> new_pos = m.positions_attribute_vector();
196
                vertex_ids[(cnt++/batch_size)%CORES].push_back(v);
196
        for(int iter=0;iter<max_iter; ++iter) {
197
        });
197
            for(int thread_no=0;thread_no<CORES;++thread_no)
198
        vector<thread> t_vec(CORES);
198
                t_vec[thread_no] = thread(laplacian_smooth_vertex,
199
        VertexAttributeVector<Vec3d> new_pos = m.positions_attribute_vector();
199
                                          ref(m), ref(vertex_ids[thread_no]),
200
        for(int iter=0;iter<max_iter; ++iter) {
200
                                          ref(new_pos), weight);
201
            for(int thread_no=0;thread_no<CORES;++thread_no)
201
            for(int thread_no=0;thread_no<CORES;++thread_no)
202
                t_vec[thread_no] = thread(laplacian_smooth_vertex,
202
                t_vec[thread_no].join();
203
                                          ref(m), ref(vertex_ids[thread_no]),
203
            swap(m.positions_attribute_vector(), new_pos);
204
                                          ref(new_pos), weight);
204
        }
205
            for(int thread_no=0;thread_no<CORES;++thread_no)
205
        
206
                t_vec[thread_no].join();
206
    }
207
            swap(m.positions_attribute_vector(), new_pos);
207
    
208
        }
208
    
209
        
209
    typedef std::vector<std::vector<VertexID>> VertexIDBatches;
210
    }
210
 
211
    
211
//    template<typename  T>
212
    
212
//    void for_each_vertex_parallel(int no_threads, const VertexIDBatches& batches, const T& f) {
213
//    template<typename  T>
213
//        vector<future<void>> f_vec(no_threads);
214
//    void for_each_vertex_parallel(int no_threads, const VertexIDBatches& batches, const T& f) {
214
//        for(auto t : range(0, no_threads))
215
//        vector<future<void>> f_vec(no_threads);
215
//            f_vec[t] = async(launch::async, f, ref(batches[t]));
216
//        for(auto t : range(0, no_threads))
216
//    }
217
//            f_vec[t] = async(launch::async, f, ref(batches[t]));
217
    
218
//    }
218
    
219
    template<typename  T>
219
    template<typename  T>
220
    void for_each_vertex_parallel(int no_threads, const VertexIDBatches& batches, const T& f) {
220
    void for_each_vertex_parallel(int no_threads, const VertexIDBatches& batches, const T& f) {
221
        vector<thread> t_vec(no_threads);
221
        vector<thread> t_vec(no_threads);
222
        for(auto t : range(0, no_threads))
222
        for(auto t : range(0, no_threads))
223
            t_vec[t] = thread(f, ref(batches[t]));
223
            t_vec[t] = thread(f, ref(batches[t]));
224
        for(auto t : range(0, no_threads))
224
        for(auto t : range(0, no_threads))
225
            t_vec[t].join();
225
            t_vec[t].join();
226
    }
226
    }
227
    
227
    
228
    VertexIDBatches batch_vertices(Manifold& m) {
228
    VertexIDBatches batch_vertices(Manifold& m) {
229
        VertexIDBatches vertex_ids(CORES);
229
        VertexIDBatches vertex_ids(CORES);
230
        auto batch_size = m.no_vertices()/CORES;
230
        auto batch_size = m.no_vertices()/CORES;
231
        int cnt = 0;
231
        int cnt = 0;
232
        for_each_vertex(m, [&](VertexID v) {
232
        for_each_vertex(m, [&](VertexID v) {
233
            //if (!boundary(m, v))
233
            //if (!boundary(m, v))
234
                vertex_ids[(cnt++/batch_size)%CORES].push_back(v);
234
                vertex_ids[(cnt++/batch_size)%CORES].push_back(v);
235
        });
235
        });
236
        return vertex_ids;
236
        return vertex_ids;
237
    }
237
    }
238
 
238
 
239
    void laplacian_smooth7(Manifold& m, float weight, int max_iter)
239
    void laplacian_smooth7(Manifold& m, float weight, int max_iter)
240
    {
240
    {
241
        auto vertex_ids = batch_vertices(m);
241
        auto vertex_ids = batch_vertices(m);
242
        auto new_pos = m.positions_attribute_vector();
242
        auto new_pos = m.positions_attribute_vector();
243
        auto f = [&](const vector<VertexID>& vids) {
243
        auto f = [&](const vector<VertexID>& vids) {
244
            for(VertexID v: vids)
244
            for(VertexID v: vids)
245
                new_pos[v] = m.pos(v)+weight*laplacian(m, v);
245
                new_pos[v] = m.pos(v)+weight*laplacian(m, v);
246
        };
246
        };
247
 
247
 
248
        for(auto _ : range(0, max_iter)) {
248
        for(auto _ : range(0, max_iter)) {
249
            for_each_vertex_parallel(CORES, vertex_ids, f);
249
            for_each_vertex_parallel(CORES, vertex_ids, f);
250
            swap(m.positions_attribute_vector(), new_pos);
250
            swap(m.positions_attribute_vector(), new_pos);
251
        }
251
        }
252
    }
252
    }
253
 
253
 
254
 
254
 
255
 
255
 
256
 
256
 
257
    void laplacian_smooth(Manifold& m,float weight, int max_iter)
257
    void laplacian_smooth(Manifold& m,float weight, int max_iter)
258
    {
258
    {
259
//        laplacian_smooth_example(m);
259
//        laplacian_smooth_example(m);
260
        laplacian_smooth7(m,weight,max_iter);
260
        laplacian_smooth7(m,weight,max_iter);
261
 
261
 
262
//        Util::Timer tim;
262
//        Util::Timer tim;
263
//        cout << "Method 0: ";
263
//        cout << "Method 0: ";
264
//        for(int i=0;i<5;++i) {
264
//        for(int i=0;i<5;++i) {
265
//            Manifold m2 = m;
265
//            Manifold m2 = m;
266
//            tim.start();
266
//            tim.start();
267
//            laplacian_smooth0(m2, 1, 1000);
267
//            laplacian_smooth0(m2, 1, 1000);
268
//            cout << tim.get_secs() << ", ";
268
//            cout << tim.get_secs() << ", ";
269
//        }
269
//        }
270
//        cout << endl;
270
//        cout << endl;
271
//
271
//
272
//        cout << "Method 1: ";
272
//        cout << "Method 1: ";
273
//        for(int i=0;i<5;++i) {
273
//        for(int i=0;i<5;++i) {
274
//            Manifold m2 = m;
274
//            Manifold m2 = m;
275
//            tim.start();
275
//            tim.start();
276
//            laplacian_smooth1(m2, 1, 1000);
276
//            laplacian_smooth1(m2, 1, 1000);
277
//            cout << tim.get_secs() << ", ";
277
//            cout << tim.get_secs() << ", ";
278
//        }
278
//        }
279
//        cout << endl;
279
//        cout << endl;
280
//
280
//
281
//        cout << "Method 2: ";
281
//        cout << "Method 2: ";
282
//        for(int i=0;i<5;++i) {
282
//        for(int i=0;i<5;++i) {
283
//            Manifold m2 = m;
283
//            Manifold m2 = m;
284
//            tim.start();
284
//            tim.start();
285
//            laplacian_smooth2(m2, 1, 1000);
285
//            laplacian_smooth2(m2, 1, 1000);
286
//            cout << tim.get_secs() << ", ";
286
//            cout << tim.get_secs() << ", ";
287
//        }
287
//        }
288
//        cout << endl;
288
//        cout << endl;
289
//
289
//
290
//        cout << "Method 3: ";
290
//        cout << "Method 3: ";
291
//        for(int i=0;i<5;++i) {
291
//        for(int i=0;i<5;++i) {
292
//            Manifold m2 = m;
292
//            Manifold m2 = m;
293
//            tim.start();
293
//            tim.start();
294
//            laplacian_smooth3(m2, 1, 1000);
294
//            laplacian_smooth3(m2, 1, 1000);
295
//            cout << tim.get_secs() << ", ";
295
//            cout << tim.get_secs() << ", ";
296
//        }
296
//        }
297
//        cout << endl;
297
//        cout << endl;
298
//
298
//
299
//        cout << "Method 4: ";
299
//        cout << "Method 4: ";
300
//        for(int i=0;i<5;++i) {
300
//        for(int i=0;i<5;++i) {
301
//            Manifold m2 = m;
301
//            Manifold m2 = m;
302
//            tim.start();
302
//            tim.start();
303
//            laplacian_smooth4(m2, 1, 1000);
303
//            laplacian_smooth4(m2, 1, 1000);
304
//            cout << tim.get_secs() << ", ";
304
//            cout << tim.get_secs() << ", ";
305
//        }
305
//        }
306
//        cout << endl;
306
//        cout << endl;
307
//
307
//
308
//        cout << "Method 5: ";
308
//        cout << "Method 5: ";
309
//        for(int i=0;i<3;++i) {
309
//        for(int i=0;i<3;++i) {
310
//            Manifold m2 = m;
310
//            Manifold m2 = m;
311
//            tim.start();
311
//            tim.start();
312
//            laplacian_smooth5(m2, 1, 1000);
312
//            laplacian_smooth5(m2, 1, 1000);
313
//            cout << " sec: "<< tim.get_secs() << ",";
313
//            cout << " sec: "<< tim.get_secs() << ",";
314
//        }
314
//        }
315
//        cout << endl;
315
//        cout << endl;
316
//
316
//
317
//        CORES = 2;
317
//        CORES = 2;
318
//        cout << "Method 6 (2): ";
318
//        cout << "Method 6 (2): ";
319
//        for(int i=0;i<5;++i) {
319
//        for(int i=0;i<5;++i) {
320
//            Manifold m2 = m;
320
//            Manifold m2 = m;
321
//            tim.start();
321
//            tim.start();
322
//            laplacian_smooth6(m2, 1, 1000);
322
//            laplacian_smooth6(m2, 1, 1000);
323
//            cout << tim.get_secs() << ", ";
323
//            cout << tim.get_secs() << ", ";
324
//        }
324
//        }
325
//        cout << endl;
325
//        cout << endl;
326
//        
326
//        
327
//        CORES = 4;
327
//        CORES = 4;
328
//        cout << "Method 7 (4): ";
328
//        cout << "Method 7 (4): ";
329
//        for(int i=0;i<5;++i) {
329
//        for(int i=0;i<5;++i) {
330
//            Manifold m2 = m;
330
//            Manifold m2 = m;
331
//            tim.start();
331
//            tim.start();
332
//            laplacian_smooth6(m2, 1, 1000);
332
//            laplacian_smooth6(m2, 1, 1000);
333
//            cout << tim.get_secs() << ", ";
333
//            cout << tim.get_secs() << ", ";
334
//        }
334
//        }
335
//        cout << endl;
335
//        cout << endl;
336
//
336
//
337
//        CORES = 8;
337
//        CORES = 8;
338
//        cout << "Method 7 (8): ";
338
//        cout << "Method 7 (8): ";
339
//        for(int i=0;i<5;++i) {
339
//        for(int i=0;i<5;++i) {
340
//            Manifold m2 = m;
340
//            Manifold m2 = m;
341
//            tim.start();
341
//            tim.start();
342
//            laplacian_smooth6(m2, 1, 1000);
342
//            laplacian_smooth6(m2, 1, 1000);
343
//            cout << tim.get_secs() << ", ";
343
//            cout << tim.get_secs() << ", ";
344
//        }
344
//        }
345
//        cout << endl;
345
//        cout << endl;
346
 
346
 
347
 
347
 
348
    }
348
    }
349
 
349
 
350
    
350
    
351
 
351
 
352
    
352
    
353
    
353
    
354
    void taubin_smooth(Manifold& m, int max_iter)
354
    void taubin_smooth(Manifold& m, int max_iter)
355
    {
355
    {
356
        auto new_pos = m.positions_attribute_vector();
356
        auto new_pos = m.positions_attribute_vector();
357
        for(int iter = 0; iter < 2*max_iter; ++iter) {
357
        for(int iter = 0; iter < 2*max_iter; ++iter) {
358
            for(VertexID v : m.vertices())
358
            for(VertexID v : m.vertices())
359
                if(!boundary(m, v))
359
                if(!boundary(m, v))
360
                    new_pos[v] = (iter%2 == 0 ? 0.5 : -0.52) * laplacian(m, v) + m.pos(v);
360
                    new_pos[v] = (iter%2 == 0 ? 0.5 : -0.52) * laplacian(m, v) + m.pos(v);
361
            swap(m.positions_attribute_vector(), new_pos);
361
            swap(m.positions_attribute_vector(), new_pos);
362
        }
362
        }
363
    }
363
    }
364
    
364
    
365
    void face_neighbourhood(Manifold& m, FaceID f, vector<FaceID>& nbrs)
365
    void face_neighbourhood(Manifold& m, FaceID f, vector<FaceID>& nbrs)
366
    {
366
    {
367
        FaceAttributeVector<int> touched(m.allocated_faces(), -1);
367
        FaceAttributeVector<int> touched(m.allocated_faces(), -1);
368
        touched[f] = 1;
368
        touched[f] = 1;
369
        nbrs.push_back(f);
369
        nbrs.push_back(f);
370
        for(Walker wf = m.walker(f); !wf.full_circle(); wf = wf.circulate_face_cw()){
370
        for(Walker wf = m.walker(f); !wf.full_circle(); wf = wf.circulate_face_cw()){
371
            for(Walker wv = m.walker(wf.vertex()); !wv.full_circle(); wv = wv.circulate_vertex_cw()){
371
            for(Walker wv = m.walker(wf.vertex()); !wv.full_circle(); wv = wv.circulate_vertex_cw()){
372
                FaceID fn = wv.face();
372
                FaceID fn = wv.face();
373
                if(fn != InvalidFaceID && touched[fn] != touched[f]){
373
                if(fn != InvalidFaceID && touched[fn] != touched[f]){
374
                    nbrs.push_back(fn);
374
                    nbrs.push_back(fn);
375
                    touched[fn] = 1;
375
                    touched[fn] = 1;
376
                }
376
                }
377
            }
377
            }
378
        }
378
        }
379
    }
379
    }
380
    
380
    
381
    
381
    
382
    
382
    
383
    Vec3d fvm_filtered_normal(Manifold& m, FaceID f)
383
    Vec3d fvm_filtered_normal(Manifold& m, FaceID f)
384
    {
384
    {
385
        const float sigma = .1f;
385
        const float sigma = .1f;
386
        
386
        
387
        vector<FaceID> nbrs;
387
        vector<FaceID> nbrs;
388
        face_neighbourhood(m, f, nbrs);
388
        face_neighbourhood(m, f, nbrs);
389
        float min_dist_sum=1e32f;
389
        float min_dist_sum=1e32f;
390
        long int median=-1;
390
        long int median=-1;
391
        
391
        
392
        vector<Vec3d> normals(nbrs.size());
392
        vector<Vec3d> normals(nbrs.size());
393
        for(size_t i=0;i<nbrs.size();++i)
393
        for(size_t i=0;i<nbrs.size();++i)
394
        {
394
        {
395
            normals[i] = normal(m, nbrs[i]);
395
            normals[i] = normal(m, nbrs[i]);
396
            float dist_sum = 0;
396
            float dist_sum = 0;
397
            for(size_t j=0;j<nbrs.size(); ++j)
397
            for(size_t j=0;j<nbrs.size(); ++j)
398
                dist_sum += 1.0f - dot(normals[i], normals[j]);
398
                dist_sum += 1.0f - dot(normals[i], normals[j]);
399
            if(dist_sum < min_dist_sum)
399
            if(dist_sum < min_dist_sum)
400
            {
400
            {
401
                min_dist_sum = dist_sum;
401
                min_dist_sum = dist_sum;
402
                median = i;
402
                median = i;
403
            }
403
            }
404
        }
404
        }
405
        assert(median != -1);
405
        assert(median != -1);
406
        Vec3d median_norm = normals[median];
406
        Vec3d median_norm = normals[median];
407
        Vec3d avg_norm(0);
407
        Vec3d avg_norm(0);
408
        for(size_t i=0;i<nbrs.size();++i)
408
        for(size_t i=0;i<nbrs.size();++i)
409
        {
409
        {
410
            float w = exp((dot(median_norm, normals[i])-1)/sigma);
410
            float w = exp((dot(median_norm, normals[i])-1)/sigma);
411
            if(w<1e-2) w = 0;
411
            if(w<1e-2) w = 0;
412
            avg_norm += w*normals[i];
412
            avg_norm += w*normals[i];
413
        }
413
        }
414
        return normalize(avg_norm);
414
        return normalize(avg_norm);
415
    }
415
    }
416
    Vec3d bilateral_filtered_normal(Manifold& m, FaceID f, double avg_len)
416
    Vec3d bilateral_filtered_normal(Manifold& m, FaceID f, double avg_len)
417
    {
417
    {
418
        vector<FaceID> nbrs;
418
        vector<FaceID> nbrs;
419
        face_neighbourhood(m, f, nbrs);
419
        face_neighbourhood(m, f, nbrs);
420
        Vec3d p0 = centre(m, f);
420
        Vec3d p0 = centre(m, f);
421
        Vec3d n0 = normal(m, f);
421
        Vec3d n0 = normal(m, f);
422
        vector<Vec3d> normals(nbrs.size());
422
        vector<Vec3d> normals(nbrs.size());
423
        vector<Vec3d> pos(nbrs.size());
423
        vector<Vec3d> pos(nbrs.size());
424
        Vec3d fn(0);
424
        Vec3d fn(0);
425
        for(FaceID nbr : nbrs)
425
        for(FaceID nbr : nbrs)
426
        {
426
        {
427
            Vec3d n = normal(m, nbr);
427
            Vec3d n = normal(m, nbr);
428
            Vec3d p = centre(m, nbr);
428
            Vec3d p = centre(m, nbr);
429
            double w_a = exp(-acos(max(-1.0,min(1.0,dot(n,n0))))/(M_PI/32.0));
429
            double w_a = exp(-acos(max(-1.0,min(1.0,dot(n,n0))))/(M_PI/32.0));
430
            double w_s = exp(-length(p-p0)/avg_len);
430
            double w_s = exp(-length(p-p0)/avg_len);
431
            
431
            
432
            fn += area(m, nbr)* w_a * w_s * n;
432
            fn += area(m, nbr)* w_a * w_s * n;
433
            
433
            
434
        }
434
        }
435
        return normalize(fn);
435
        return normalize(fn);
436
    }
436
    }
437
    
437
    
438
    void anisotropic_smooth(HMesh::Manifold& m, int max_iter, NormalSmoothMethod nsm)
438
    void anisotropic_smooth(HMesh::Manifold& m, int max_iter, NormalSmoothMethod nsm)
439
    {
439
    {
440
        double avg_len=0;
440
        double avg_len=0;
441
        for(HalfEdgeID hid : m.halfedges())
441
        for(HalfEdgeID hid : m.halfedges())
442
            avg_len += length(m, hid);
442
            avg_len += length(m, hid);
443
        avg_len /= 2.0;
443
        avg_len /= 2.0;
444
        for(int iter = 0;iter<max_iter; ++iter)
444
        for(int iter = 0;iter<max_iter; ++iter)
445
        {
445
        {
446
            
446
            
447
            FaceAttributeVector<Vec3d> filtered_norms(m.allocated_faces());
447
            FaceAttributeVector<Vec3d> filtered_norms(m.allocated_faces());
448
            
448
            
449
            for(FaceID f: m.faces()){
449
            for(FaceID f: m.faces()){
450
                filtered_norms[f] = (nsm == BILATERAL_NORMAL_SMOOTH)?
450
                filtered_norms[f] = (nsm == BILATERAL_NORMAL_SMOOTH)?
451
                bilateral_filtered_normal(m, f, avg_len):
451
                bilateral_filtered_normal(m, f, avg_len):
452
                fvm_filtered_normal(m, f);
452
                fvm_filtered_normal(m, f);
453
            }
453
            }
454
            
454
            
455
            VertexAttributeVector<Vec3d> vertex_positions(m.allocated_vertices(), Vec3d(0));
455
            VertexAttributeVector<Vec3d> vertex_positions(m.allocated_vertices(), Vec3d(0));
456
            VertexAttributeVector<int> count(m.allocated_vertices(), 0);
456
            VertexAttributeVector<int> count(m.allocated_vertices(), 0);
457
            for(int sub_iter=0;sub_iter<100;++sub_iter)
457
            for(int sub_iter=0;sub_iter<100;++sub_iter)
458
            {
458
            {
459
                for(HalfEdgeID hid : m.halfedges())
459
                for(HalfEdgeID hid : m.halfedges())
460
                {
460
                {
461
                    Walker w = m.walker(hid);
461
                    Walker w = m.walker(hid);
462
                    FaceID f = w.face();
462
                    FaceID f = w.face();
463
                    
463
                    
464
                    if(f != InvalidFaceID){
464
                    if(f != InvalidFaceID){
465
                        VertexID v = w.vertex();
465
                        VertexID v = w.vertex();
466
                        Vec3d dir = m.pos(w.opp().vertex()) - m.pos(v);
466
                        Vec3d dir = m.pos(w.opp().vertex()) - m.pos(v);
467
                        Vec3d n = filtered_norms[f];
467
                        Vec3d n = filtered_norms[f];
468
                        vertex_positions[v] += m.pos(v) + 0.5 * n * dot(n, dir);
468
                        vertex_positions[v] += m.pos(v) + 0.5 * n * dot(n, dir);
469
                        count[v] += 1;
469
                        count[v] += 1;
470
                    }
470
                    }
471
                    
471
                    
472
                }
472
                }
473
                double max_move= 0;
473
                double max_move= 0;
474
                for(VertexID v : m.vertices())
474
                for(VertexID v : m.vertices())
475
                {
475
                {
476
                    Vec3d npos = vertex_positions[v] / double(count[v]);
476
                    Vec3d npos = vertex_positions[v] / double(count[v]);
477
                    double move = sqr_length(npos - m.pos(v));
477
                    double move = sqr_length(npos - m.pos(v));
478
                    if(move > max_move)
478
                    if(move > max_move)
479
                        max_move = move;
479
                        max_move = move;
480
                    
480
                    
481
                    m.pos(v) = npos;
481
                    m.pos(v) = npos;
482
                }
482
                }
483
                if(max_move<sqr(1e-8*avg_len))
483
                if(max_move<sqr(1e-8*avg_len))
484
                {
484
                {
485
                    cout << "iters " << sub_iter << endl;
485
                    cout << "iters " << sub_iter << endl;
486
                    break;
486
                    break;
487
                }
487
                }
488
            }
488
            }
489
        }
489
        }
490
    }
490
    }
491
    
491
    
492
    void TAL_smoothing(Manifold& m, float w, int max_iter)
492
    void TAL_smoothing(Manifold& m, float w, int max_iter)
493
    {
493
    {
494
        for(int iter=0;iter<max_iter;++iter) {
494
        for(int iter=0;iter<max_iter;++iter) {
495
            VertexAttributeVector<float> vertex_areas;
495
            VertexAttributeVector<float> vertex_areas;
496
            VertexAttributeVector<Vec3d> laplacians;
496
            VertexAttributeVector<Vec3d> laplacians;
497
            
497
            
498
            for(VertexIDIterator vid = m.vertices_begin(); vid != m.vertices_end(); ++vid)
498
            for(VertexIDIterator vid = m.vertices_begin(); vid != m.vertices_end(); ++vid)
499
            {
499
            {
500
                vertex_areas[*vid] = 0;
500
                vertex_areas[*vid] = 0;
501
                for(Walker w = m.walker(*vid); !w.full_circle(); w = w.circulate_vertex_ccw())
501
                for(Walker w = m.walker(*vid); !w.full_circle(); w = w.circulate_vertex_ccw())
502
                    if(w.face() != InvalidFaceID)
502
                    if(w.face() != InvalidFaceID)
503
                        vertex_areas[*vid] += area(m, w.face());
503
                        vertex_areas[*vid] += area(m, w.face());
504
            }
504
            }
505
            
505
            
506
            for(VertexIDIterator vid = m.vertices_begin(); vid != m.vertices_end(); ++vid)
506
            for(VertexIDIterator vid = m.vertices_begin(); vid != m.vertices_end(); ++vid)
507
            {
507
            {
508
                laplacians[*vid] = Vec3d(0);
508
                laplacians[*vid] = Vec3d(0);
509
                double weight_sum = 0.0;
509
                double weight_sum = 0.0;
510
                if(boundary(m, *vid))
510
                if(boundary(m, *vid))
511
                {
511
                {
512
                    double angle_sum = 0;
512
                    double angle_sum = 0;
513
                    for(Walker w = m.walker(*vid); !w.full_circle(); w = w.circulate_vertex_ccw())
513
                    for(Walker w = m.walker(*vid); !w.full_circle(); w = w.circulate_vertex_ccw())
514
                    {
514
                    {
515
                        if (w.face() != InvalidFaceID)
515
                        if (w.face() != InvalidFaceID)
516
                        {
516
                        {
517
                            Vec3d vec_a = normalize(m.pos(w.vertex()) - m.pos(*vid));
517
                            Vec3d vec_a = normalize(m.pos(w.vertex()) - m.pos(*vid));
518
                            Vec3d vec_b = normalize(m.pos(w.circulate_vertex_ccw().vertex()) -
518
                            Vec3d vec_b = normalize(m.pos(w.circulate_vertex_ccw().vertex()) -
519
                                                    m.pos(*vid));
519
                                                    m.pos(*vid));
520
                            angle_sum += acos(max(-1.0,min(1.0,dot(vec_a,vec_b))));
520
                            angle_sum += acos(max(-1.0,min(1.0,dot(vec_a,vec_b))));
521
                        }
521
                        }
522
                        if(boundary(m,w.vertex()))
522
                        if(boundary(m,w.vertex()))
523
                        {
523
                        {
524
                            laplacians[*vid] += m.pos(w.vertex()) - m.pos(*vid);
524
                            laplacians[*vid] += m.pos(w.vertex()) - m.pos(*vid);
525
                            weight_sum += 1.0;
525
                            weight_sum += 1.0;
526
                        }
526
                        }
527
                    }
527
                    }
528
                    laplacians[*vid] /= weight_sum;
528
                    laplacians[*vid] /= weight_sum;
529
                    laplacians[*vid] *= exp(-3.0*sqr(max(0.0, M_PI-angle_sum)));
529
                    laplacians[*vid] *= exp(-3.0*sqr(max(0.0, M_PI-angle_sum)));
530
                }
530
                }
531
                else
531
                else
532
                {
532
                {
533
                    for(Walker w = m.walker(*vid); !w.full_circle(); w = w.circulate_vertex_ccw())
533
                    for(Walker w = m.walker(*vid); !w.full_circle(); w = w.circulate_vertex_ccw())
534
                    {
534
                    {
535
                        float weight = vertex_areas[w.vertex()];
535
                        float weight = vertex_areas[w.vertex()];
536
                        Vec3d l = m.pos(w.vertex()) - m.pos(*vid);
536
                        Vec3d l = m.pos(w.vertex()) - m.pos(*vid);
537
                        laplacians[*vid] +=  weight * l;
537
                        laplacians[*vid] +=  weight * l;
538
                        weight_sum += weight;
538
                        weight_sum += weight;
539
                    }
539
                    }
540
                    laplacians[*vid] /= weight_sum;
540
                    laplacians[*vid] /= weight_sum;
541
                    //                Vec3d n = normal(m, *vid);
541
                    //                Vec3d n = normal(m, *vid);
542
                    //                if(sqr_length(n)>0.9)
542
                    //                if(sqr_length(n)>0.9)
543
                    //                    laplacians[*vid] -= n * dot(n, laplacians[*vid]);
543
                    //                    laplacians[*vid] -= n * dot(n, laplacians[*vid]);
544
                }
544
                }
545
            }
545
            }
546
            for(VertexIDIterator vid = m.vertices_begin(); vid != m.vertices_end(); ++vid)
546
            for(VertexIDIterator vid = m.vertices_begin(); vid != m.vertices_end(); ++vid)
547
                m.pos(*vid) += w*laplacians[*vid];
547
                m.pos(*vid) += w*laplacians[*vid];
548
        }
548
        }
549
    }
549
    }
550
 
550
 
551
    
551
    
552
    
552
    
553
}
553
}