Subversion Repositories gelsvn

Rev

Rev 652 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
514 s042372 1
/* ----------------------------------------------------------------------- *
572 jab 2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
3
 * Copyright (C) the authors and DTU Informatics
4
 * For license and list of authors, see ../../doc/intro.pdf
5
 * ----------------------------------------------------------------------- */
514 s042372 6
 
7
#include "curvature.h"
8
 
9
#include <iostream>
601 jab 10
#include "../CGLA/eigensolution.h"
11
#include "../CGLA/Vec2d.h"
12
#include "../CGLA/Vec3d.h"
13
#include "../CGLA/Mat3x3d.h"
14
#include "../CGLA/Mat2x2d.h"
15
#include "../CGLA/Mat2x3d.h"
514 s042372 16
 
601 jab 17
#include "Manifold.h"
18
#include "AttributeVector.h"
19
#include "x3d_save.h"
20
#include "x3d_load.h"
21
#include "obj_load.h"
22
#include "mesh_optimization.h"
514 s042372 23
 
601 jab 24
#include "../LinAlg/Matrix.h"
25
#include "../LinAlg/Vector.h"
26
#include "../LinAlg/LapackFunc.h"
514 s042372 27
 
28
using namespace std;
29
 
30
using namespace LinAlg;
31
using namespace CGLA;
32
using namespace HMesh;
33
 
34
namespace HMesh
35
{
36
    namespace 
37
    {
38
        //double scal = 0.001;
39
        //double vector_scal = 0.001;
40
 
41
        template<class T> 
42
        void smooth_something_on_mesh(const Manifold& m, VertexAttributeVector<T>& vec, int smooth_steps)
43
        {
44
            for(int iter=0;iter<smooth_steps;++iter){
586 jab 45
                VertexAttributeVector<T> new_vec(m.allocated_vertices());
514 s042372 46
                for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v){
47
                    new_vec[*v] = vec[*v];
587 jab 48
                    for(Walker w = m.walker(*v); !w.full_circle(); w = w.circulate_vertex_cw()){
514 s042372 49
                        new_vec[*v] += vec[w.vertex()];
50
                    }
51
                    new_vec[*v] /= (valency(m, *v) + 1.0);
52
                }
53
                swap(vec,new_vec);
54
            }		
55
        }
56
    }
57
 
662 janba 58
    double mixed_area(const Manifold& m, VertexID v)
514 s042372 59
    {
60
        double area_mixed = 0;
61
        //For each triangle T from the 1-ring neighborhood of x
587 jab 62
        for(Walker w = m.walker(v); !w.full_circle(); w = w.circulate_vertex_cw()){
514 s042372 63
            double f_area = area(m, w.face());
64
 
566 jab 65
            Vec3d v0(m.pos(v));
514 s042372 66
            Vec3d v1(m.pos(w.vertex()));
67
            Vec3d v2(m.pos(w.next().vertex()));
68
 
69
            double a0 = acos(dot(v1-v0, v2-v0)/(length(v1-v0)*length(v2-v0)));
70
            double a1 = acos(dot(v2-v1, v0-v1)/(length(v2-v1)*length(v0-v1)));
71
            double a2 = acos(dot(v0-v2, v1-v2)/(length(v0-v2)*length(v1-v2)));
72
 
73
            if(a0>(M_PI/2.0) && a1>(M_PI/2.0) && a2>(M_PI/2.0)) // f is non-obtuse
74
            {
75
                // Add Voronoi formula (see Section 3.3)
76
                area_mixed += (1.0/8) * 
77
                    ((1.0/tan(a1)) * sqr_length(v2-v0) + 
78
                    (1.0/tan(a2)) * sqr_length(v1-v0));
79
            }
80
            else // Voronoi inappropriate
81
            {
82
                // Add either area(f)/4 or area(f)/2
662 janba 83
                area_mixed += f_area/3;
514 s042372 84
            }
85
        }
86
        return area_mixed;
87
    }
88
 
89
    double barycentric_area(const Manifold& m, VertexID v)
90
    {
91
        double barea = 0;
92
        //For each triangle T from the 1-ring neighborhood of x
587 jab 93
        for(Walker w = m.walker(v); !w.full_circle(); w = w.circulate_vertex_cw()){
514 s042372 94
            barea += area(m, w.face())/3.0;
95
        }
96
        return barea;
97
    }
98
 
99
    void unnormalized_mean_curvature_normal(const Manifold& m, VertexID v, Vec3d& curv_normal, double& w_sum)
100
    {
101
        if(boundary(m, v))
102
            return;
103
 
104
        Vec3d vertex(m.pos(v));
105
        curv_normal = Vec3d(0);
106
        w_sum = 0;
587 jab 107
        for(Walker walker = m.walker(v); !walker.full_circle(); walker = walker.circulate_vertex_ccw()){
514 s042372 108
            Vec3d nbr(m.pos(walker.vertex()));
109
            Vec3d left(m.pos(walker.next().vertex()));
566 jab 110
            Vec3d right(m.pos(walker.opp().next().vertex()));
514 s042372 111
 
566 jab 112
            double d_left = dot(cond_normalize(nbr-left),cond_normalize(vertex-left));
113
            double d_right = dot(cond_normalize(nbr-right),cond_normalize(vertex-right));
514 s042372 114
            double a_left  = acos(min(1.0, max(-1.0, d_left)));
115
            double a_right = acos(min(1.0, max(-1.0, d_right)));
116
 
662 janba 117
//            double w = 1.0/(1e-300+tan(a_left));
118
//            w += 1.0/(1e-300+tan(a_right));
119
            double w = sin(a_left + a_right) / (1e-300 + sin(a_left)*sin(a_right));
566 jab 120
            curv_normal += w * (nbr-vertex);
514 s042372 121
            w_sum += w;
122
        }
123
 
124
    }
125
 
126
    Vec3d mean_curvature_normal(const Manifold& m, VertexID v)
127
    {
128
        Vec3d curv_normal;
129
        double w_sum;
130
        unnormalized_mean_curvature_normal(m, v, curv_normal, w_sum);
131
 
662 janba 132
        return curv_normal / (4*mixed_area(m, v));
514 s042372 133
    }
134
 
135
    double sum_curvatures(const Manifold& m, VertexAttributeVector<double>& curvature)
136
    {
137
        double sum = 0;
138
        for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v){
139
            if(boundary(m, *v))
140
                continue;	
662 janba 141
            sum += curvature[*v] * mixed_area(m, *v);
514 s042372 142
        }
143
        return sum;
144
    }
145
 
146
 
147
    double gaussian_curvature_angle_defect(const Manifold& m, VertexID v)
148
    {
149
        if(boundary(m, v))
150
            return 0;
151
 
587 jab 152
        Vec3d vertex(m.pos(v));
514 s042372 153
        vector<Vec3d> edges;
587 jab 154
        for(Walker w = m.walker(v); !w.full_circle(); w = w.circulate_vertex_cw()){
514 s042372 155
            Vec3d e(normalize(m.pos(w.vertex()) - vertex));
156
            edges.push_back(e);
157
        }
585 jab 158
        size_t N=edges.size();
514 s042372 159
        double angle_sum = 0;
607 jrf 160
        for(size_t i = 0; i < N; ++i)
514 s042372 161
        {
162
            double dot_prod = 
632 janba 163
                std::max(-1.0, std::min(1.0, dot(edges[i],edges[(i+1)%N])));
514 s042372 164
            angle_sum += acos(dot_prod);
165
        }
662 janba 166
        return (2*M_PI - angle_sum)/mixed_area(m, v);
514 s042372 167
 
168
    }
169
 
170
    Mat3x3d curvature_tensor(const Manifold& m, HalfEdgeID h)
171
    {
172
        if(boundary(m, h))
173
            return Mat3x3d(0);
174
 
587 jab 175
        Walker w = m.walker(h);
514 s042372 176
        Vec3d edge(m.pos(w.vertex()) - m.pos(w.opp().vertex()));
177
        double edge_len = length(edge);
178
        edge /= edge_len;
179
 
180
        Vec3d h_norm(normal(m, w.face()));
181
        Vec3d h_opp_norm(normal(m, w.opp().face()));
182
 
183
        Vec3d nc = cross(h_norm, h_opp_norm);
184
 
185
        double sign = (dot(nc, edge) >= 0) ? 1 : -1;
186
        double beta = asin(nc.length());
187
 
188
        Mat3x3d mat;
189
        outer_product(edge, edge, mat);
190
        return sign * edge_len * beta * mat;
191
    }
192
 
193
    Mat3x3d curvature_tensor_from_edges(const Manifold& m, VertexID v)
194
    {
195
        Mat3x3d curv_tensor(0);
196
 
197
        if(boundary(m, v))
198
            return curv_tensor;
199
 
587 jab 200
        for(Walker w = m.walker(v); !w.full_circle(); w = w.circulate_vertex_cw())
514 s042372 201
            curv_tensor += 0.5*curvature_tensor(m, w.halfedge());
202
 
662 janba 203
        curv_tensor /= mixed_area(m, v);
514 s042372 204
 
205
        return curv_tensor;
206
    }
207
 
208
 
209
    void curvature_tensor_paraboloid(const Manifold& m, VertexID v, Mat2x2d& curv_tensor, Mat3x3d& frame)
210
    {
211
        if(boundary(m, v))
212
            return;
213
        // First estimate the normal and compute a transformation matrix
214
        // which takes us into tangent plane coordinates.
215
        Vec3d Norm = Vec3d(normal(m, v));
216
        Vec3d X,Y;
217
        orthogonal(Norm,X,Y);
218
        frame = Mat3x3d(X,Y,Norm);
219
        Vec3d centre(m.pos(v));
220
 
221
        vector<Vec3d> points;
587 jab 222
        for(Walker w = m.walker(v); !w.full_circle(); w = w.circulate_vertex_cw())
514 s042372 223
            points.push_back(Vec3d(m.pos(w.vertex())));
224
 
591 jab 225
        int N = int(points.size());
514 s042372 226
 
227
        CVector b(N);
228
        // Compute the matrix of parameter values
229
        CMatrix PMat(N, 3);
230
        for(int i = 0; i < N; ++i){
231
            Vec3d p = frame * (points[i]-centre);
232
            b[i] = p[2];
233
 
234
            PMat.set(i,0,0.5*sqr(p[0]));
235
            PMat.set(i,1,p[0]*p[1]);
236
            PMat.set(i,2,0.5*sqr(p[1]));
237
        }
238
 
239
        // Compute the coefficients of the polynomial surface
240
        CVector x(3);
241
        x = LinearLSSolve(PMat,b);
242
        if(isnan(x[0])) cout << __LINE__ << " " << PMat << b << endl ;
243
 
244
        // Finally compute the shape tensor from the coefficients
245
        // using the first and second fundamental forms.
646 janba 246
        curv_tensor = - Mat2x2d(x[0],x[1],x[1],x[2]);
514 s042372 247
 
248
    }
249
 
250
    void curvature_tensors_from_edges(const Manifold& m, VertexAttributeVector<Mat3x3d>& curvature_tensors)
251
    {
252
        for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v)
253
            curvature_tensors[*v] = curvature_tensor_from_edges(m, *v);
254
    }
255
 
256
    void smooth_curvature_tensors(const Manifold& m, VertexAttributeVector<Mat3x3d>& curvature_tensors)
257
    {
586 jab 258
        assert(curvature_tensors.size() == m.allocated_vertices());
259
        VertexAttributeVector<Mat3x3d> tmp_curvature_tensors(m.allocated_vertices());
514 s042372 260
        double tmp_area;
261
 
262
        for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v){
263
            if(boundary(m, *v))
264
                continue;
662 janba 265
            double a = mixed_area(m, *v);
514 s042372 266
            tmp_curvature_tensors[*v] = curvature_tensors[*v] * a;
267
            tmp_area = a;
587 jab 268
            for(Walker w = m.walker(*v); !w.full_circle(); w = w.circulate_vertex_cw()){
514 s042372 269
                if(!boundary(m, w.vertex())){
662 janba 270
                    double a = mixed_area(m, w.vertex());
514 s042372 271
                    tmp_curvature_tensors[*v] += curvature_tensors[w.vertex()]*a;
272
                    tmp_area += a;
273
                }
274
                tmp_curvature_tensors[*v] /= tmp_area;
275
            }
276
        }
631 janba 277
        curvature_tensors = move(tmp_curvature_tensors);
514 s042372 278
    }
279
 
280
    void gaussian_curvature_angle_defects(const Manifold& m, VertexAttributeVector<double>& curvature, int smooth_steps)
281
    {
282
        for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v)
283
            curvature[*v] = gaussian_curvature_angle_defect(m, *v);
284
 
285
        smooth_something_on_mesh(m, curvature, smooth_steps);
286
    }
287
 
288
    void mean_curvatures(const Manifold& m, VertexAttributeVector<double>& curvature, int smooth_steps)
289
    {
543 jab 290
        for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v)
291
			if(!boundary(m,*v))
292
			{
566 jab 293
				Vec3d N = -mean_curvature_normal(m, *v);
543 jab 294
				curvature[*v] = length(N) * sign(dot(N,Vec3d(normal(m, *v))));
295
			}	
514 s042372 296
        smooth_something_on_mesh(m, curvature, smooth_steps);	
297
    }
298
 
299
 
300
    void curvature_paraboloids( const Manifold& m, 
301
                                VertexAttributeVector<Vec3d>& min_curv_direction, 
302
                                VertexAttributeVector<Vec3d>& max_curv_direction,
646 janba 303
                                VertexAttributeVector<Vec2d>& curvature)
514 s042372 304
    {
305
 
306
        for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v){
307
            Mat2x2d tensor;
308
            Mat3x3d frame;
309
            curvature_tensor_paraboloid(m, *v, tensor, frame);
310
 
311
            Mat2x2d Q,L;
312
            int s = power_eigensolution(tensor, Q, L);
313
 
314
            if(s < 2)	
315
                cout << tensor << Q << L << endl;
316
 
317
            int max_idx = 0;
318
            int min_idx = 1;
319
 
646 janba 320
            if(L[max_idx][max_idx]<L[min_idx][min_idx]) swap(max_idx, min_idx);
514 s042372 321
 
322
            Mat3x3d frame_t = transpose(frame);
323
 
566 jab 324
            max_curv_direction[*v] = cond_normalize(frame_t * Vec3d(Q[max_idx][0], Q[max_idx][1], 0));
514 s042372 325
 
566 jab 326
            min_curv_direction[*v] = cond_normalize(frame_t * Vec3d(Q[min_idx][0], Q[min_idx][1], 0));
514 s042372 327
 
646 janba 328
            curvature[*v][0] = L[min_idx][min_idx];
329
            curvature[*v][1] = L[max_idx][max_idx];
514 s042372 330
        }
331
    }
332
 
333
 
334
    void curvature_from_tensors(const Manifold& m,
335
                                const VertexAttributeVector<Mat3x3d>& curvature_tensors,
336
                                VertexAttributeVector<Vec3d>& min_curv_direction,
337
                                VertexAttributeVector<Vec3d>& max_curv_direction,
646 janba 338
                                VertexAttributeVector<Vec2d>& curvature)
514 s042372 339
    {
586 jab 340
        assert(curvature_tensors.size() == m.allocated_vertices());
514 s042372 341
 
342
        double max_val = -1e30;
343
        for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v){
344
            Mat3x3d C,Q,L;
345
            C = curvature_tensors[*v];
346
            int s = power_eigensolution(C, Q, L);
347
            Vec3d dmin, dmax;
348
            if(s == 0)
349
            {
350
                Vec3d n(normal(m, *v));
351
                orthogonal(n, dmin, dmax);
646 janba 352
                curvature[*v] = Vec2d(0);
514 s042372 353
                cout << " rank 0 " << endl;
354
            }
355
            else if(s == 1)
356
            {
357
                Vec3d n(normal(m, *v));
358
                dmin = normalize(Q[0]);
359
                dmax = cross(n, dmin);
646 janba 360
                curvature[*v] = Vec2d(0);
514 s042372 361
                cout << " rank 1 " << endl;
362
            }
363
            else
364
            {
646 janba 365
                Vec2d l(fabs(L[0][0]), fabs(L[1][1]));
514 s042372 366
 
646 janba 367
                int max_idx = 0;
368
                int min_idx = 1;
514 s042372 369
 
370
                if(l[max_idx] < l[min_idx]) swap(max_idx, min_idx);
646 janba 371
 
514 s042372 372
                // Yes - the biggest eigenvalue corresponds to the min direction
373
                // and vice versa.
374
                dmin = normalize(Q[max_idx]);
375
                dmax = normalize(Q[min_idx]);
376
 
646 janba 377
                curvature[*v][0] = L[min_idx][min_idx];
378
                curvature[*v][1] = L[max_idx][max_idx];
514 s042372 379
 
380
            }
381
            min_curv_direction[*v] = dmin;
382
            max_curv_direction[*v] = dmax;
646 janba 383
            max_val = max(fabs(curvature[*v][1]), max_val);
514 s042372 384
 
385
        }
386
        //scal = 1.0/max_val;
387
    }
388
}
389