Subversion Repositories gelsvn

Rev

Rev 640 | 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
 
642 janba 11
 
12
#include "harmonics.h"
568 jab 13
#include "polarize.h"
631 janba 14
#include <CGLA/Vec2d.h>
15
#include <LinAlg/LapackFunc.h>
568 jab 16
#include <HMesh/triangulate.h>
631 janba 17
#include <HMesh/obj_save.h>
568 jab 18
#include <HMesh/curvature.h>
19
#include <HMesh/quadric_simplify.h>
20
#include <HMesh/mesh_optimization.h>
21
#include <HMesh/smooth.h>
22
 
572 jab 23
#include <complex>
24
 
568 jab 25
using namespace CGLA;
26
using namespace std;
27
using namespace HMesh;
28
 
642 janba 29
inline bool same_level(double a, double b) {return abs(a-b) < 1e-10;}
631 janba 30
 
642 janba 31
enum VertexStatus {
32
    RAW, POLE, SADDLE, COOKED
33
};
631 janba 34
 
642 janba 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
}
631 janba 50
 
642 janba 51
void high_gradient_triangulate(Manifold& m, FaceID _f, const VertexAttributeVector<double>& fun)
52
{
53
 
54
    queue<FaceID> fq;
55
    fq.push(_f);
56
    while(!fq.empty()) {
57
        FaceID f = fq.front();
58
        fq.pop();
59
        if(no_edges(m, f)<=3)
60
            continue;
61
        // Create a vector of vertices.
62
        vector<VertexID> verts;
63
        circulate_face_ccw(m, f, [&](VertexID v){verts.push_back(v);});
64
 
65
        // Find vertex pairs that may be connected.
66
        vector<pair<int,int> > vpairs;
67
        const int N = verts.size();
68
        for(int i = 0; i < N - 2; ++i){
69
            for(int j = i + 2; j < N; ++j){
70
                if(verts[i] != verts[j] && !connected(m, verts[i], verts[j]))
71
                    vpairs.push_back(pair<int,int>(i, j));
72
            }
73
        }
74
        if(vpairs.empty()){
75
            cout << "Warning: could not triangulate a face."
76
            << "Probably a vertex appears more than one time in other vertex's one-ring" << endl;
77
            continue;
78
        }
79
 
80
        /* For all vertex pairs, find the edge lengths. Combine the
81
         vertices forming the shortest edge. */
82
 
83
        float max_grad=-FLT_MAX;
84
        size_t max_k = -1;
85
        for(size_t k = 0; k < vpairs.size(); ++k){
86
            int i = vpairs[k].first;
87
            int j = vpairs[k].second;
88
            double grad = abs(fun[verts[i]]-fun[verts[j]])/length(m.pos(verts[i]) - m.pos(verts[j]));
89
 
90
            if(grad>max_grad){
91
                max_grad = grad;
92
                max_k = k;
93
            }
94
        }
95
        assert(max_k != -1);
96
 
97
        {
98
            int i = vpairs[max_k].first;
99
            int j = vpairs[max_k].second;
100
            if(m.in_use(verts[i]) && m.in_use(verts[j])) {
101
                FaceID f2 = m.split_face_by_edge(f, verts[i], verts[j]);
102
                fq.push(f);
103
                fq.push(f2);
104
            }
105
        }
106
    }
107
}
631 janba 108
 
642 janba 109
FaceID merge_face_in_1_ring(Manifold& m, VertexID v)
631 janba 110
{
642 janba 111
    Walker w=m.walker(v);
112
    HalfEdgeID h = w.next().halfedge();
113
    if(m.remove_vertex(v))
631 janba 114
    {
642 janba 115
        return m.close_hole(h);
631 janba 116
    }
642 janba 117
    return InvalidFaceID;
118
}
631 janba 119
 
642 janba 120
 
121
void compute_edge_weights(const Manifold& m, HalfEdgeAttributeVector<double>& edge_weights, FaceAttributeVector<int>& included)
631 janba 122
{
123
    edge_weights = HalfEdgeAttributeVector<double>(m.allocated_halfedges(), 0);
124
    for(FaceIDIterator f = m.faces_begin(); f != m.faces_end(); ++f)
125
        if(included[*f])
126
        {
127
            for(Walker wv = m.walker(*f); !wv.full_circle(); wv = wv.circulate_face_ccw())
128
            {
129
                HalfEdgeID h = wv.halfedge();
130
                Vec3d p1(m.pos(wv.vertex()));
131
                Vec3d p2(m.pos(wv.next().vertex()));
132
                Vec3d p0(m.pos(wv.opp().vertex()));
133
                double ang = acos(min(1.0, max(-1.0, dot(normalize(p1-p0), normalize(p2-p0)))));
134
                double ang_opp = acos(min(1.0, max(-1.0, dot(normalize(p2-p1), normalize(p0-p1)))));
135
                double l = (p1-p0).length();
136
                edge_weights[h] += tan(ang/2) / l;
137
                edge_weights[wv.opp().halfedge()] += tan(ang_opp/2) / l;
138
            }
139
        }
140
}
640 janba 141
 
142
template<typename T>
642 janba 143
void smooth_fun(const Manifold& m,
640 janba 144
                VertexAttributeVector<int>& nailed,
145
                VertexAttributeVector<T>& fun, int iter=100)
631 janba 146
{
147
    HalfEdgeAttributeVector<double> edge_weights;
148
    FaceAttributeVector<int> included(m.allocated_faces(),1);
149
    compute_edge_weights(m,edge_weights, included);
640 janba 150
    VertexAttributeVector<T> new_fun(m.no_vertices());
151
    for(int i = 0; i < iter; ++i)
631 janba 152
    {
153
        for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v)
154
            if(!nailed[*v])
155
            {
156
                double w_sum = 0;
640 janba 157
                new_fun[*v] = T(0);
631 janba 158
                for(Walker wv = m.walker(*v); !wv.full_circle(); wv = wv.circulate_vertex_ccw())
159
                {
160
                    double w = edge_weights[wv.halfedge()];
161
                    new_fun[*v] += w * fun[wv.vertex()];
162
                    w_sum += w;
163
                }
164
                new_fun[*v] /= w_sum;
165
            }
166
            else
167
                new_fun[*v] = fun[*v];
640 janba 168
        fun = new_fun;
631 janba 169
    }
170
}
171
 
642 janba 172
vector<VertexID> cut_mesh(Manifold& m, VertexAttributeVector<double>& fun, double cut_val, VertexAttributeVector<VertexStatus>& status)
631 janba 173
{
642 janba 174
    cout << "Cutting at " << cut_val << endl;
175
 
176
    vector<VertexID> new_verts;
177
    vector<HalfEdgeID> hidvec;
178
    for(HalfEdgeID hid : m.halfedges())
631 janba 179
    {
642 janba 180
        Walker w = m.walker(hid);
181
        double bval = fun[w.vertex()];
182
        double aval = fun[w.opp().vertex()];
183
        if(aval<bval && aval < cut_val && cut_val <= bval)
631 janba 184
        {
642 janba 185
            double t = (cut_val-aval)/(bval-aval);
186
            Vec3d p = t*m.pos(w.vertex()) + (1.0-t)*m.pos(w.opp().vertex());
187
            VertexID vnew = m.split_edge(hid);
188
            m.pos(vnew) = p;
189
            status[vnew] = COOKED;
190
            fun[vnew] = cut_val;
191
            new_verts.push_back(vnew);
192
        }
193
    }
194
 
195
    for(FaceID fid : m.faces())
196
        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))
631 janba 198
            {
642 janba 199
                Walker w0 = w;
200
                w = w.next().next();
201
                do
631 janba 202
                {
642 janba 203
                    if(status[w.vertex()] == COOKED &&
204
                       w.next().halfedge() != w0.halfedge() &&
205
                       same_level(fun[w.vertex()],cut_val))
631 janba 206
                    {
642 janba 207
                        m.split_face_by_edge(fid, w0.vertex(), w.vertex());
208
                        break;
631 janba 209
                    }
642 janba 210
                    w = w.next();
631 janba 211
                }
642 janba 212
                while(!w.full_circle());
213
                break;
631 janba 214
            }
642 janba 215
    return new_verts;
631 janba 216
}
217
 
642 janba 218
void smooth_cooked_vertices(Manifold& m, const vector<VertexID>& vertices, VertexAttributeVector<double>& fun,
219
                            VertexAttributeVector<VertexStatus>& status, int iter=1)
568 jab 220
{
642 janba 221
    for(int i=0;i<iter;++i)
568 jab 222
    {
642 janba 223
        VertexAttributeVector<Vec3d> npos(m.allocated_vertices(), Vec3d(0));
224
        VertexAttributeVector<int> cnt(m.allocated_vertices(), 0);
225
        for(auto vid : vertices)
226
           if(m.in_use(vid))
227
            for(Walker w = m.walker(vid); !w.full_circle(); w = w.circulate_vertex_ccw())
228
                if(status[vid]==COOKED) {
229
                    npos[vid] += m.pos(w.vertex());
230
                    ++cnt[vid];
231
                }
232
        for(auto vid : vertices)
233
            if(m.in_use(vid))
234
            m.pos(vid) = (npos[vid])/cnt[vid];
568 jab 235
    }
236
}
237
 
642 janba 238
int ssb(double a, double b)
568 jab 239
{
642 janba 240
    const double THRESH = 1e-6;
241
    double delta = a-b;
242
    if(delta<-THRESH) return -1;
243
    if(delta>THRESH) return 1;
244
    return 0;
568 jab 245
}
246
 
642 janba 247
void classify_vertices(Manifold& m, VertexAttributeVector<double>& fun, VertexAttributeVector<VertexStatus>& status)
568 jab 248
{
642 janba 249
    for(auto vid : m.vertices())
568 jab 250
    {
642 janba 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);
259
            if(above_below != above_below_new)
260
                ++changes;
261
            above_below=above_below_new;
640 janba 262
        }
642 janba 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);
640 janba 270
    }
271
}
272
 
642 janba 273
void remove_vertices(Manifold& m, VertexAttributeVector<double>& fun, VertexAttributeVector<VertexStatus>& status, double rmin, double rmax)
572 jab 274
{
642 janba 275
    vector<VertexID> vertices_to_push;
276
    for(auto vid: m.vertices())
277
        if(status[vid]==RAW &&
278
           fun[vid] >= rmin &&
279
           fun[vid] <= rmax)
280
            vertices_to_push.push_back(vid);
631 janba 281
 
642 janba 282
    random_shuffle(begin(vertices_to_push), end(vertices_to_push));
640 janba 283
 
642 janba 284
    for(auto vid : vertices_to_push)
572 jab 285
    {
642 janba 286
        FaceID fid = merge_face_in_1_ring(m,vid);
287
        if(fid != InvalidFaceID)
288
            high_gradient_triangulate(m, fid, fun);
572 jab 289
    }
290
}
291
 
568 jab 292
 
631 janba 293
void polarize_mesh(Manifold& m, VertexAttributeVector<double>& fun, double vmin, double vmax, const int divisions, VertexAttributeVector<Vec2d>& parametrization)
568 jab 294
{
642 janba 295
    VertexAttributeVector<VertexStatus> status(m.allocated_vertices(), RAW);
568 jab 296
 
642 janba 297
    classify_vertices(m, fun, status);
568 jab 298
 
642 janba 299
    double interval = (vmax-vmin)/(divisions+1);
300
    double base_cut_val = vmin + 0.02*(vmax-vmin);
568 jab 301
 
642 janba 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)
568 jab 306
    {
642 janba 307
        int _iter=iter;//%2==0?iter/2:-1-iter/2;
308
        double cut_val = base_cut_val + interval * _iter;
309
        cout << "i,c " << _iter << "," << cut_val << endl;
310
        remove_vertices(m, fun, status, cut_val, cut_val+interval);
311
        vector<VertexID> new_verts = cut_mesh(m, fun,_iter<0?cut_val:cut_val+interval, status);
312
        kill_wedges(m, fun, status);
313
        smooth_cooked_vertices(m, new_verts, fun, status, 1);
568 jab 314
    }
572 jab 315
 
642 janba 316
    int C=0, R=0, P=0,S=0;
317
    for(auto vid : m.vertices())
568 jab 318
    {
642 janba 319
        switch(status[vid]) {
320
            case RAW: ++R; break;
321
            case COOKED: ++C; break;
322
            case POLE: ++P; break;
323
            case SADDLE: ++S; break;
568 jab 324
        }
325
    }
642 janba 326
    cout << "R=" << R << " C=" << C << " P=" << P << " S=" << S << endl;
568 jab 327
}
328
 
572 jab 329
void make_height_fun(const HMesh::Manifold& m, HMesh::VertexAttributeVector<double>& fun,
330
                     double& vmin, double& vmax)
568 jab 331
{
332
    VertexIDIterator vid = m.vertices_begin();
642 janba 333
    VertexAttributeVector<int> nailed(m.allocated_vertices(), 0);
334
    smooth_fun(m, nailed, fun,0);
640 janba 335
    vmin = vmax = m.pos(*vid)[1];
568 jab 336
    for(; vid != m.vertices_end(); ++vid)
337
    {
631 janba 338
        double v = dot(m.pos(*vid),Vec3d(0.0,1,0.00));
568 jab 339
        fun[*vid] = v;
340
        vmin = min(v, vmin);
341
        vmax = max(v, vmax);
342
    }
642 janba 343
 
568 jab 344
}
640 janba 345
 
642 janba 346
void make_adf_fun(HMesh::Manifold& m, double t, HMesh::VertexAttributeVector<double>& F,
347
                     double& vmin, double& vmax)
348
{
349
    Harmonics harm(m);
350
    harm.compute_adf(F, t);
351
    VertexAttributeVector<int> nailed(m.allocated_vertices(), 0);
352
    vmin = vmax = F[*m.vertices_begin()];
353
    for(auto vid : m.vertices())
354
    {
355
        vmin = min(F[vid], vmin);
356
        vmax = max(F[vid], vmax);
357
    }
358
    cout << vmin << vmax << endl;
359
 
360
}
361