-
Notifications
You must be signed in to change notification settings - Fork 6
/
compute_error.c
1537 lines (1438 loc) · 60.4 KB
/
compute_error.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* $Id$ */
/*
*
* Copyright (C) 2001-2004 EPFL (Swiss Federal Institute of Technology,
* Lausanne) This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* In addition, as a special exception, EPFL gives permission to link
* the code of this program with the Qt non-commercial edition library
* (or with modified versions of Qt non-commercial edition that use the
* same license as Qt non-commercial edition), and distribute linked
* combinations including the two. You must obey the GNU General
* Public License in all respects for all of the code used other than
* Qt non-commercial edition. If you modify this file, you may extend
* this exception to your version of the file, but you are not
* obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Authors : Nicolas Aspert, Diego Santa-Cruz and Davy Jacquet
*
* Web site : http://mesh.epfl.ch
*
* Reference :
* "MESH : Measuring Errors between Surfaces using the Hausdorff distance"
* in Proceedings of IEEE Intl. Conf. on Multimedia and Expo (ICME) 2002,
* vol. I, pp. 705-708, available on http://mesh.epfl.ch
*
*/
#include <compute_error.h>
#include <geomutils.h>
#include <xalloc.h>
#include <math.h>
#include <assert.h>
/* Use a bitmap for marking empty cells. Otherwise use array of a simple
* type. Using a bitmap uses less memory and can be faster than a simple type
* depending on the cache system and number of cells in the grid (number of
* cache misses).
*/
#define USE_EC_BITMAP
/* Ratio used to derive the cell size. It is the ratio between the cubic cell
* side length and the side length of an average equilateral triangle. */
#define CELL_TRIAG_RATIO 0.707
/* If defined statistics for the dist_pt_surf() function are computed */
/* #define DO_DIST_PT_SURF_STATS */
/* Margin factor from DBL_MIN to consider a triangle side length too small and
* mark it as degenerate. */
#define DMARGIN 1e10
/* Maximum number of cells in the grid. */
#define GRID_CELLS_MAX 512000
/* The value of 1/sqrt(3) */
#define SQRT_1_3 0.5773502691896258
/* Define inlining directive for C99 or as compiler specific C89 extension */
#if defined(_MSC_VER) /* Visual C++ */
# define INLINE __inline
#elif defined(__GNUC__) /* GCC's interpretation is inverse of C99 */
# define INLINE __inline__
#elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 500)
# define INLINE __inline
#elif defined(__PGI)
# define INLINE __inline
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
# define INLINE inline
#else
# define INLINE /* no inline */
#endif
/* --------------------------------------------------------------------------*
* Local data types *
* --------------------------------------------------------------------------*/
#ifdef USE_EC_BITMAP /* Use a bitmap */
/* Type for storing empty cell bitmap */
typedef int ec_bitmap_t;
/* The number of bytes used by ec_bitmap_t */
# define EC_BITMAP_T_SZ (sizeof(ec_bitmap_t))
/* The number of bits used by ec_bitmap_t, and also the divisor to obtain the
* bitmap element index from a cell index */
# define EC_BITMAP_T_BITS (EC_BITMAP_T_SZ*8)
/* Bitmask to obtain the bitmap bit index from the cell index. */
# define EC_BITMAP_T_MASK (EC_BITMAP_T_BITS-1)
/* Macro to test the bit corresponding to element i in the bitmap bm. */
# define EC_BITMAP_TEST_BIT(bm,i) \
((bm)[(i)/EC_BITMAP_T_BITS]&(1 << ((i)&EC_BITMAP_T_MASK)))
/* Macro to set the bit corresponding to element i in the bitmap bm. */
# define EC_BITMAP_SET_BIT(bm,i) \
((bm)[(i)/EC_BITMAP_T_BITS] |= 1 << ((i)&EC_BITMAP_T_MASK))
#else /* Fake bitmap macros to access simple type */
/* Type for marking empty cells. Small type uses less memory, but access to
* aligned type can be faster (but more memory can cause more cache misses) */
typedef char ec_bitmap_t;
/* The number of bytes used by ec_bitmap_t */
# define EC_BITMAP_T_SZ sizeof(ec_bitmap_t)
/* The number of bits used by ec_bitmap_t. Since here we don't use the
* individual bits it is 1. */
# define EC_BITMAP_T_BITS 1
/* Bitmask to obtain the bitmap bit index from the cell index. */
# define EC_BITMAP_T_MASK (EC_BITMAP_T_BITS-1)
/* Macro to test the element i in the map bm. */
# define EC_BITMAP_TEST_BIT(bm,i) (bm)[i]
/* Macro to set the element i in the map bm. */
# define EC_BITMAP_SET_BIT(bm,i) ((bm)[i] = 1)
#endif
/* Temporary struct to hold extra statistics */
struct misc_stats {
double *dist_smpl;/* The distance at each sample of model 1 */
int dist_smpl_sz; /* Size (in elements) of the buffer for dist_smpl */
};
/* List of triangles intersecting each cell */
struct t_in_cell_list {
int ** triag_idx; /* The list of the indices of the triangles
* intersecting each cell, terminated by -1
* (triag_idx[i] is the list for the cell with
* linear index i). If cell i is empty,
* triag_idx[i] is NULL. */
int n_cells; /* The number of cells in triag_idx */
ec_bitmap_t *empty_cell; /* A bitmap indicating which cells are empty. If
* cell i is empty, the bit (i&EC_BITMAP_T_MASK)
* of empty_cell[i/EC_BITMAP_T_BITS] is
* non-zero. */
int n_ne_cells; /* The number of non-empty cells */
double n_t_per_ne_cell; /* Average number of triangles per non-empty cell */
};
/* A list of samples of a surface in 3D space. */
struct sample_list {
dvertex_t* sample; /* Array of sample 3D coordinates */
int n_samples; /* The number of samples in the array */
int buf_sz; /* The size, in elements, of the sample buffer */
};
/* A list of cells */
struct cell_list {
int *cell; /* The array of the linear indices of the cells in the list */
int n_cells; /* The number of elemnts in the array */
};
/* A list of cells for different distances */
struct dist_cell_lists {
struct cell_list *list; /* list[k]: the list of cells at distance k in the
* X, Y or Z direction. */
int n_dists; /* The number of elements in list */
};
/* Storage for triangle sample errors. */
struct triag_sample_error {
double **err; /* Error array with 2D addressing. Sample (i,j) has the
* error stored at err[i][j], where i varies betwen 0 and
* n_samples-1 inclusive and j varies between 0 and
* n_samples-i-1 inclusive. */
int n_samples; /* The number of samples in each triangle direction */
double *err_lin; /* Error array with 1D adressing, which varies from 0 to
* n_samples_tot-1 inclusive. It refers to the same
* location as err, thus any change to err is reflected
* in err_lin and vice-versa. The order in the 1D array
* is all errors for i equal 0 and j from 0 to
* n_samples-1, followed by errors for i equal 1 and j
* from 0 to n_samples-2, and so on. */
int n_samples_tot; /* The total number of samples in the triangle */
int buf_sz; /* The allocated err_lin buffer size (number of elements)*/
};
/* A list of triangles with their associated information */
struct triangle_list {
struct triangle_info *triangles; /* The triangles */
int n_triangles; /* The number of triangles */
double area; /* The total triangle area */
};
/* A triangle and useful associated information. AB is always the longest side
* of the triangle. That way the projection of C on AB is always inside AB. */
struct triangle_info {
dvertex_t a; /* The A vertex of the triangle */
dvertex_t b; /* The B vertex of the triangle */
dvertex_t c; /* The C vertex of the triangle. The projection of C
* on AB is always inside the AB segment. */
dvertex_t ab; /* The AB vector */
dvertex_t ca; /* The CA vector */
dvertex_t cb; /* The CB vector */
double ab_len_sqr; /* The square of the length of AB */
double ca_len_sqr; /* The square of the length of CA */
double cb_len_sqr; /* The square of the length of CB */
double ab_1_len_sqr; /* One over the square of the length of AB */
double ca_1_len_sqr; /* One over the square of the length of CA */
double cb_1_len_sqr; /* One over the square of the length of CB */
dvertex_t normal; /* The (unit length) normal of the ABC triangle
* (orinted with the right hand rule turning from AB to
* AC). If the triangle is degenerate it is (0,0,0). */
dvertex_t nhsab; /* (unnormalized) normal of the plane trough AB,
* perpendicular to ABC and pointing outside of ABC */
dvertex_t nhsbc; /* (unnormalized) normal of the plane trough BC,
* perpendicular to ABC and pointing outside of ABC */
dvertex_t nhsca; /* (unnormalized) normal of the plane trough CA,
* perpendicular to ABC and pointing outside of ABC */
double chsab; /* constant of the plane equation: <p|npab>=cpab */
double chsbc; /* constant of the plane equation: <p|npbc>=cpbc */
double chsca; /* constant of the plane equation: <p|npca>=cpca */
double a_n; /* scalar product of A with the unit length normal */
double s_area; /* The surface area of the triangle */
int obtuse_at_c; /* Flag indicating if the angle at C is larger than 90
* degrees (i.e. obtuse) */
};
/* Statistics of dist_pt_surf() function */
struct dist_pt_surf_stats {
int n_cell_scans; /* Number of cells that are scanned (i.e. distance
* point to cell is calculated) */
int n_cell_t_scans; /* Number of cells that for which their triangles are
* scanned */
int n_triag_scans; /* Number of triangles that are scanned */
int sum_kmax; /* the sum of athe max k for each sample point */
};
/* --------------------------------------------------------------------------*
* Local utility functions *
* --------------------------------------------------------------------------*/
/* Finalizes the members of the me->fe array. The m_stats->dist_smpl array
* will now be referenced by me->fe->serror. */
static void finalize_face_error(struct model_error *me,
struct misc_stats *m_stats)
{
struct face_error *fe;
int n_faces,i,n;
n_faces = me->mesh->num_faces;
fe = me->fe;
fe[0].serror = m_stats->dist_smpl;
for (i=1; i<n_faces; i++) {
n = fe[i-1].sample_freq;
fe[i].serror = fe[i-1].serror+n*(n+1)/2;
}
}
/* Reallocates the buffers of tse to store the sample errors for a triangle
* sampling with n samples in each direction. If tse->err and tse->err_lin is
* NULL new buffers are allocated. The allocation never fails (if out of
* memory the program is stopped, as with xa_realloc()) */
static void realloc_triag_sample_error(struct triag_sample_error *tse, int n)
{
int i;
if (tse->n_samples == n) return;
tse->n_samples = n;
tse->n_samples_tot = n*(n+1)/2;
if (tse->n_samples_tot > tse->buf_sz) {
tse->err = xa_realloc(tse->err,n*sizeof(*(tse->err)));
tse->err_lin = xa_realloc(tse->err_lin,
tse->n_samples_tot*sizeof(**(tse->err)));
tse->buf_sz = tse->n_samples_tot;
}
if (n != 0) {
tse->err[0] = tse->err_lin;
for (i=1; i<n; i++) {
tse->err[i] = tse->err[i-1]+(n-(i-1));
}
}
}
/* Frees the buffers in tse (allocated with realloc_triag_sample_error()). */
static void free_triag_sample_error(struct triag_sample_error *tse)
{
if (tse == NULL) return;
free(tse->err);
free(tse->err_lin);
tse->err = NULL;
tse->err_lin = NULL;
}
/* Computes the normalized vertex normals assuming an oriented model. The
* triangle information already present in tl are used to speed up the
* calculation. If the model is not oriented, the resulting normals will be
* incorrect. Vertices that belong to no triangles or to degenerate ones only
* have a (0,0,0) normal vector set. */
static void calc_normals_as_oriented_model(struct model *m,
const struct triangle_list *tl)
{
int k,kmax;
vertex_t n;
/* initialize all normals to zero */
m->normals = xa_realloc(m->normals,m->num_vert*sizeof(*(m->normals)));
memset(m->normals,0,m->num_vert*sizeof(*(m->normals)));
/* add face normals to vertices, weighted by face area */
for (k=0, kmax=m->num_faces; k < kmax; k++) {
vertex_d2f_v(&(tl->triangles[k].normal),&n); /* convert double to float */
__prod_v(tl->triangles[k].s_area,n,n);
__add_v(n,m->normals[m->faces[k].f0],m->normals[m->faces[k].f0]);
__add_v(n,m->normals[m->faces[k].f1],m->normals[m->faces[k].f1]);
__add_v(n,m->normals[m->faces[k].f2],m->normals[m->faces[k].f2]);
}
/* normalize final normals */
for (k=0, kmax=m->num_vert; k<kmax; k++) {
/* skip vertices which have no triangles or only degenerated ones */
if (m->normals[k].x != 0 || m->normals[k].y != 0 || m->normals[k].z != 0) {
__normalize_v(m->normals[k]);
}
}
}
/* Returns the integer sample frequency for a triangle of area t_area, so that
* the sample density (number of samples per unit area) is s_density
* (statistically speaking). The returned sample frequency is the number of
* samples to take on each side. A random variable is used so that the
* resulting sampling density is s_density in average. */
static int get_sampling_freq(double t_area, double s_density)
{
double rv,p,n_samples;
int n;
/* NOTE: we use a random variable so that the expected (i.e. statistical
* average) number of samples is n_samples=t_area/s_density. Given a
* sampling freq. n the number of samples is n*(n+1)/2. Given the target
* number of samples n_samples we obtain the maximum sampling freq. n that
* gives no more than n_samples. The we choose n with probability p, or n+1
* with probability 1-p, so that p*n*(n+1)/2+(1-p)*(n+1)*(n+2)/2=n_samples,
* that is the expected value is n_samples. */
rv = rand()/(RAND_MAX+1.0); /* rand var. in [0,1) interval */
n_samples = t_area*s_density;
n = (int)floor(sqrt(0.25+2*n_samples)-0.5);
p = (n+2)*0.5-n_samples/(n+1);
return (rv<p) ? n : n+1;
}
/* Given a the triangle list tl of a model, and the minimum and maximum
* coordinates of the bounding box on which the cell grid is to be made,
* bbox_min and bbox_max, calculates the grid cell size as well as the grid
* size. The cubic cell side length is returned and the grid size is stored in
* *grid_sz. */
static double get_cell_size(const struct triangle_list *tl,
const dvertex_t *bbox_min,
const dvertex_t *bbox_max, struct size3d *grid_sz)
{
double cell_sz;
double f_gsz_x,f_gsz_y,f_gsz_z;
/* Derive the grid size. For that we derive the average triangle side length
* as the side of an equilateral triangle which's surface equals the average
* triangle surface of m2. The cubic cell side is then CELL_TRIAG_RATIO
* times that. */
cell_sz = CELL_TRIAG_RATIO*sqrt(tl->area/tl->n_triangles*4/sqrt(3));
/* Avoid values that can overflow or underflow */
if (cell_sz < DBL_MIN*DMARGIN) { /* Avoid division by zero with cell_sz */
cell_sz = DBL_MIN*DMARGIN;
} else if (cell_sz >= DBL_MAX/DMARGIN) {
fprintf(stderr,"ERROR: coordinate overflow. Are models OK?\n");
exit(1);
}
/* Limit to maximum number of cells */
f_gsz_x = ceil((bbox_max->x-bbox_min->x)/cell_sz);
if (f_gsz_x <= 0) f_gsz_x = 1;
f_gsz_y = ceil((bbox_max->y-bbox_min->y)/cell_sz);
if (f_gsz_y <= 0) f_gsz_y = 1;
f_gsz_z = ceil((bbox_max->z-bbox_min->z)/cell_sz);
if (f_gsz_z <= 0) f_gsz_z = 1;
if (f_gsz_x*f_gsz_y*f_gsz_z > GRID_CELLS_MAX) {
cell_sz *= pow(f_gsz_x*f_gsz_y*f_gsz_z/GRID_CELLS_MAX,1.0/3);
f_gsz_x = ceil((bbox_max->x-bbox_min->x)/cell_sz);
if (f_gsz_x <= 0) f_gsz_x = 1;
f_gsz_y = ceil((bbox_max->y-bbox_min->y)/cell_sz);
if (f_gsz_y <= 0) f_gsz_y = 1;
f_gsz_z = ceil((bbox_max->z-bbox_min->z)/cell_sz);
if (f_gsz_z <= 0) f_gsz_z = 1;
}
/* Return values */
grid_sz->x = (int) f_gsz_x;
grid_sz->y = (int) f_gsz_y;
grid_sz->z = (int) f_gsz_z;
return cell_sz;
}
/* Gets the list of non-empty cells that are at distance k in the X, Y or Z
* direction from the center cell with grid coordinates cell_gr_coord. The
* list is stored in dlists->list[k] and dlists->n_dists is updated to reflect
* the number of calculated distances. The list of empty cells is obtained
* from the list of faces in each cell, fic. The size of the cell grid is
* given by grid_sz. The distance between two cells is the minimum distance
* between points in each cell. For distance zero the center cell is also
* included in the list. The temporary buffer used to construct the list is
* given by *buf (can be NULL) and its size (in elements) by *buf_sz. If a
* larger buffer is required it is realloc'ed and the new address and size are
* returned in *buf and *buf_sz. */
static void get_cells_at_distance(struct dist_cell_lists *dlists,
struct size3d cell_gr_coord,
struct size3d grid_sz, int k,
const struct t_in_cell_list *fic,
int **buf, int *buf_sz)
{
int max_n_cells;
int cell_idx;
int cell_idx1,cell_idx2;
int cell_stride_z;
ec_bitmap_t *fic_empty_cell;
int *cur_cell;
int cll;
int m,n,o;
int m1,m2,n1,n2,o1,o2;
int min_m,max_m,min_n,max_n,min_o,max_o;
int d;
int tmp;
assert(k == 0 || dlists->n_dists <= k);
/* Initialize */
cell_stride_z = grid_sz.y*grid_sz.x;
fic_empty_cell = fic->empty_cell;
/* Expand storage for distance cell list */
dlists->list = xa_realloc(dlists->list,(k+1)*sizeof(*(dlists->list)));
if (k > dlists->n_dists){
/* set to NULL new elements that will not be filled */
memset(dlists->list+dlists->n_dists,0,
(k-dlists->n_dists)*sizeof(*(dlists->list)));
}
dlists->n_dists = k+1;
/* Get the cells that are at distance k in the X, Y or Z direction from the
* center cell. For the zero distance we also include the center cell. */
max_n_cells = 6*(2*k+1)*(2*k+1)+12*(2*k+1)+8;
if (k == 0) max_n_cells += 1; /* add center cell */
if (*buf == NULL || *buf_sz < max_n_cells) {
*buf_sz = max_n_cells;
*buf = xa_realloc(*buf,(*buf_sz)*sizeof(**buf));
}
cur_cell = *buf;
if (k == 0) { /* add center cell */
cell_idx = cell_gr_coord.x+cell_gr_coord.y*grid_sz.x+
cell_gr_coord.z*cell_stride_z;
if (!EC_BITMAP_TEST_BIT(fic_empty_cell,cell_idx)) {
*(cur_cell++) = cell_idx;
}
}
/* Try to put the cells in the order of increasing distances (minimizes
* number of cells and triangles to test). Doing a full ordering is too
* slow, we just do what we can fast. */
d = k+1; /* max displacement */
min_o = max(cell_gr_coord.z-d+1,0);
max_o = min(cell_gr_coord.z+d-1,grid_sz.z-1);
min_n = max(cell_gr_coord.y-d+1,0);
max_n = min(cell_gr_coord.y+d-1,grid_sz.y-1);
m1 = cell_gr_coord.x-d;
m2 = cell_gr_coord.x+d;
if (m1 >= 0) {
if (m2 < grid_sz.x) { /* left + right layer */
for (o = min_o; o <= max_o; o++) {
for (n = min_n; n <= max_n; n++) {
tmp = n*grid_sz.x+o*cell_stride_z;
cell_idx1 = m1+tmp;
cell_idx2 = m2+tmp;
if (!EC_BITMAP_TEST_BIT(fic_empty_cell,cell_idx1)) {
*(cur_cell++) = cell_idx1;
}
if (!EC_BITMAP_TEST_BIT(fic_empty_cell,cell_idx2)) {
*(cur_cell++) = cell_idx2;
}
}
}
} else { /* left layer */
for (o = min_o; o <= max_o; o++) {
for (n = min_n; n <= max_n; n++) {
cell_idx = m1+n*grid_sz.x+o*cell_stride_z;
if (!EC_BITMAP_TEST_BIT(fic_empty_cell,cell_idx)) {
*(cur_cell++) = cell_idx;
}
}
}
}
} else {
if (m2 < grid_sz.x) { /* right layer */
for (o = min_o; o <= max_o; o++) {
for (n = min_n; n <= max_n; n++) {
cell_idx = m2+n*grid_sz.x+o*cell_stride_z;
if (!EC_BITMAP_TEST_BIT(fic_empty_cell,cell_idx)) {
*(cur_cell++) = cell_idx;
}
}
}
}
}
min_m = max(cell_gr_coord.x-d,0);
max_m = min(cell_gr_coord.x+d,grid_sz.x-1);
n1 = cell_gr_coord.y-d;
n2 = cell_gr_coord.y+d;
if (n1 >= 0) {
if (n2 < grid_sz.y) { /* back + front layers */
for (o = min_o; o <= max_o; o++) {
for (m = min_m; m <= max_m; m++) {
tmp = m+o*cell_stride_z;
cell_idx1 = tmp+n1*grid_sz.x;
cell_idx2 = tmp+n2*grid_sz.x;
if (!EC_BITMAP_TEST_BIT(fic_empty_cell,cell_idx1)) {
*(cur_cell++) = cell_idx1;
}
if (!EC_BITMAP_TEST_BIT(fic_empty_cell,cell_idx2)) {
*(cur_cell++) = cell_idx2;
}
}
}
} else { /* back layer */
for (o = min_o; o <= max_o; o++) {
for (m = min_m; m <= max_m; m++) {
cell_idx = m+n1*grid_sz.x+o*cell_stride_z;
if (!EC_BITMAP_TEST_BIT(fic_empty_cell,cell_idx)) {
*(cur_cell++) = cell_idx;
}
}
}
}
} else {
if (n2 < grid_sz.y) { /* front layer */
for (o = min_o; o <= max_o; o++) {
for (m = min_m; m <= max_m; m++) {
cell_idx = m+n2*grid_sz.x+o*cell_stride_z;
if (!EC_BITMAP_TEST_BIT(fic_empty_cell,cell_idx)) {
*(cur_cell++) = cell_idx;
}
}
}
}
}
min_n = max(cell_gr_coord.y-d,0);
max_n = min(cell_gr_coord.y+d,grid_sz.y-1);
o1 = cell_gr_coord.z-d;
o2 = cell_gr_coord.z+d;
if (o1 >= 0) {
if (o2 < grid_sz.z) { /* bottom + top layers */
for (n = min_n; n <= max_n; n++) {
for (m = min_m; m <= max_m; m++) {
tmp = m+n*grid_sz.x;
cell_idx1 = tmp+o1*cell_stride_z;
cell_idx2 = tmp+o2*cell_stride_z;
if (!EC_BITMAP_TEST_BIT(fic_empty_cell,cell_idx1)) {
*(cur_cell++) = cell_idx1;
}
if (!EC_BITMAP_TEST_BIT(fic_empty_cell,cell_idx2)) {
*(cur_cell++) = cell_idx2;
}
}
}
} else { /* bottom */
for (n = min_n; n <= max_n; n++) {
for (m = min_m; m <= max_m; m++) {
cell_idx = m+n*grid_sz.x+o1*cell_stride_z;
if (!EC_BITMAP_TEST_BIT(fic_empty_cell,cell_idx)) {
*(cur_cell++) = cell_idx;
}
}
}
}
} else {
if (o2 < grid_sz.z) { /* top layer */
for (n = min_n; n <= max_n; n++) {
for (m = min_m; m <= max_m; m++) {
cell_idx = m+n*grid_sz.x+o2*cell_stride_z;
if (!EC_BITMAP_TEST_BIT(fic_empty_cell,cell_idx)) {
*(cur_cell++) = cell_idx;
}
}
}
}
}
/* Store resulting cell list */
cll = cur_cell-*buf;
if (cll != 0) {
dlists->list[k].cell = xa_malloc(cll*sizeof(*cur_cell));
memcpy(dlists->list[k].cell,*buf,cll*sizeof(*cur_cell));
dlists->list[k].n_cells = cll;
} else {
dlists->list[k].cell = NULL;
dlists->list[k].n_cells = 0;
}
}
/* --------------------------------------------------------------------------*
* Local functions *
* --------------------------------------------------------------------------*/
/* Initializes the triangle '*t' using the '*a' '*b' and '*c' vertices and
* calculates all the relative fields of the struct. */
static void init_triangle(const vertex_t *a, const vertex_t *b,
const vertex_t *c, struct triangle_info *t)
{
dvertex_t dv_a,dv_b,dv_c;
dvertex_t ab,ac,bc;
double ab_len_sqr,ac_len_sqr,bc_len_sqr;
double n_len;
/* Convert float vertices to double */
vertex_f2d_dv(a,&dv_a);
vertex_f2d_dv(b,&dv_b);
vertex_f2d_dv(c,&dv_c);
/* Get the vertices in the proper ordering (the orientation is not
* changed). AB should be the longest side. */
__substract_v(dv_b,dv_a,ab);
__substract_v(dv_c,dv_a,ac);
__substract_v(dv_c,dv_b,bc);
ab_len_sqr = __norm2_v(ab);
ac_len_sqr = __norm2_v(ac);
bc_len_sqr = __norm2_v(bc);
if (ab_len_sqr <= ac_len_sqr) {
if (ac_len_sqr <= bc_len_sqr) { /* BC longest side => A to C */
t->c = dv_a;
t->a = dv_b;
t->b = dv_c;
t->ab = bc;
t->ca = ab;
t->cb = ac;
t->ab_len_sqr = bc_len_sqr;
t->ca_len_sqr = ab_len_sqr;
t->cb_len_sqr = ac_len_sqr;
} else { /* AC longest side => B to C */
t->b = dv_a;
t->c = dv_b;
t->a = dv_c;
__neg_v(ac,t->ab);
t->ca = bc;
__neg_v(ab,t->cb);
t->ab_len_sqr = ac_len_sqr;
t->ca_len_sqr = bc_len_sqr;
t->cb_len_sqr = ab_len_sqr;
}
} else {
if (ab_len_sqr <= bc_len_sqr) { /* BC longest side => A to C */
t->c = dv_a;
t->a = dv_b;
t->b = dv_c;
t->ab = bc;
t->ca = ab;
t->cb = ac;
t->ab_len_sqr = bc_len_sqr;
t->ca_len_sqr = ab_len_sqr;
t->cb_len_sqr = ac_len_sqr;
} else { /* AB longest side => C remains C */
t->a = dv_a;
t->b = dv_b;
t->c = dv_c;
t->ab = ab;
__neg_v(ac,t->ca);
__neg_v(bc,t->cb);
t->ab_len_sqr = ab_len_sqr;
t->ca_len_sqr = ac_len_sqr;
t->cb_len_sqr = bc_len_sqr;
}
}
if (t->ab_len_sqr < DBL_MIN*DMARGIN) {
t->ab.x = 0;
t->ab.y = 0;
t->ab.z = 0;
t->cb = t->ab;
t->ca = t->ab;
t->ab_len_sqr = 0;
t->ca_len_sqr = 0;
t->cb_len_sqr = 0;
}
/* Get side lengths */
t->ab_1_len_sqr = 1/t->ab_len_sqr;
t->ca_1_len_sqr = 1/t->ca_len_sqr;
t->cb_1_len_sqr = 1/t->cb_len_sqr;
/* Get the triangle normal (normalized) */
__crossprod_dv(t->ca,t->ab,t->normal);
n_len = __norm_v(t->normal);
if (n_len < DBL_MIN*DMARGIN) {
t->normal.x = 0;
t->normal.y = 0;
t->normal.z = 0;
t->s_area = 0;
} else {
__prod_dv(1/n_len,t->normal,t->normal);
t->s_area = n_len*0.5;
}
/* Get planes trough sides */
__crossprod_dv(t->ab,t->normal,t->nhsab);
__crossprod_dv(t->normal,t->cb,t->nhsbc);
__crossprod_dv(t->ca,t->normal,t->nhsca);
/* Get constants for plane equations */
t->chsab = __scalprod_v(t->a,t->nhsab);
t->chsca = __scalprod_v(t->a,t->nhsca);
t->chsbc = __scalprod_v(t->b,t->nhsbc);
/* Miscellaneous fields */
t->obtuse_at_c = (t->ab_len_sqr > t->ca_len_sqr+t->cb_len_sqr);
t->a_n = __scalprod_v(t->a,t->normal);
}
/* Compute the square of the distance between point 'p' and triangle 't' in 3D
* space. The distance from a point p to a triangle is defined as the
* Euclidean distance from p to the closest point in the triangle. */
static double dist_sqr_pt_triag(const struct triangle_info *t,
const dvertex_t *p)
{
double dpp; /* (signed) distance point to ABC plane */
double ap_ab,cp_cb,cp_ca; /* scalar products */
dvertex_t ap,cp; /* Point to point vectors */
double dmin_sqr; /* minimum distance squared */
/* NOTE: If the triangle has a obtuse angle (i.e. angle larger than 90
* degrees) it is the angle at the C vertex (never at A or B). */
/* We get the distance from point P to triangle ABC by first testing on
* which side of the planes (hsab, hsbc and hsca) perpendicular to the ABC
* plane trough AB, BC and CA is P. If P is towards the triangle center from
* all three planes, the projection of P on the ABC plane is interior to ABC
* and thus the distance to ABC is the distance to the ABC plane. If P is
* towards the triangle exterior from the plane hsab, then the distance from
* P to ABC is the distance to the AB segment. Otherwise if P is towards the
* triangle exterior from the plane hsbc the distance from P to ABC is the
* minimum of the distance to the BC and CA segments (only BC is the angle
* at C is not obtuse). Otherwise P is towards the triangle exterior from the
* plane hsac and the distance from P to ABC is the distance to the CA
* segment. */
/* NOTE: if the triangle is degenerate t->npab and t->cpab are identically
* (0,0,0), so first 'if' test is true (other 'if's never get degenerated
* triangles). Furthermore, if the AB side is degenerate (that is the
* triangle degenerates to a point since AB is longest side) t->ab is
* identically (0,0,0) also and the distance to A is calculated. */
if (scalprod_dv(p,&(t->nhsab)) >= t->chsab) {
/* P in the exterior side of hsab plane => closest to AB */
substract_dv(p,&(t->a),&ap);
ap_ab = __scalprod_v(ap,t->ab);
if(ap_ab > 0) {
if (ap_ab < t->ab_len_sqr) { /* projection of P on AB is in AB */
dmin_sqr = __norm2_v(ap) - (ap_ab*ap_ab)*t->ab_1_len_sqr;
if (dmin_sqr < 0) dmin_sqr = 0; /* correct rounding problems */
return dmin_sqr;
} else { /* B is closer */
return dist2_dv(p,&(t->b));
}
} else { /* A is closer */
return __norm2_v(ap);
}
} else if (scalprod_dv(p,&(t->nhsbc)) >= t->chsbc) {
/* P in the exterior side of hsbc plane => closest to BC or AC */
substract_dv(p,&(t->c),&cp);
cp_cb = __scalprod_v(cp,t->cb);
if(cp_cb > 0) {
if (cp_cb < t->cb_len_sqr) { /* projection of P on BC is in BC */
dmin_sqr = __norm2_v(cp) - (cp_cb*cp_cb)*t->cb_1_len_sqr;
if (dmin_sqr < 0) dmin_sqr = 0; /* correct rounding problems */
return dmin_sqr;
} else { /* B is closer */
return dist2_dv(p,&(t->b));
}
} else if (!t->obtuse_at_c) { /* C is closer */
return __norm2_v(cp);
} else { /* AC is closer */
cp_ca = __scalprod_v(cp,t->ca);
if(cp_ca > 0) {
if (cp_ca < t->ca_len_sqr) { /* projection of P on AC is in AC */
dmin_sqr = __norm2_v(cp) - (cp_ca*cp_ca)*t->ca_1_len_sqr;
if (dmin_sqr < 0) dmin_sqr = 0; /* correct rounding problems */
return dmin_sqr;
} else { /* A is closer */
return dist2_dv(p,&(t->a));
}
} else { /* C is closer */
return __norm2_v(cp);
}
}
} else if (scalprod_dv(p,&(t->nhsca)) >= t->chsca) {
/* P in the exterior side of hsca plane => closest to AC */
substract_dv(p,&(t->c),&cp);
cp_ca = __scalprod_v(cp,t->ca);
if(cp_ca > 0) {
if (cp_ca < t->ca_len_sqr) { /* projection of P on AC is in AC */
dmin_sqr = __norm2_v(cp) - (cp_ca*cp_ca)*t->ca_1_len_sqr;
if (dmin_sqr < 0) dmin_sqr = 0; /* correct rounding problems */
return dmin_sqr;
} else { /* A is closer */
return dist2_dv(p,&(t->a));
}
} else { /* C is closer */
return __norm2_v(cp);
}
} else { /* P projects into triangle */
dpp = scalprod_dv(p,&(t->normal))-t->a_n;
return dpp*dpp;
}
}
/* Calculates the square of the distance between a point p in cell
* (gr_x,gr_y,gr_z) and cell cell_idx (linear index). The coordinates of p are
* relative to the minimum X,Y,Z coordinates of the bounding box from where
* the cell grid is derived. All the cells are cubic, with a side of length
* cell_sz. If the point p is in the cell (m,n,o) the distance is zero. The
* number of cells in the grid along X is given by grid_sz_x, and the
* separation between adjacent cells along Z is given by cell_stride_z. */
static INLINE double dist_sqr_pt_cell(const dvertex_t *p, int gr_x, int gr_y,
int gr_z, int cell_idx, int grid_sz_x,
int cell_stride_z, double cell_sz)
{
double d2,tmp;
int m,n,o,tmpi;
/* Get 3D indices of cell cell_idx */
o = cell_idx/cell_stride_z;
tmpi = cell_idx%cell_stride_z;
n = tmpi/grid_sz_x;
m = tmpi%grid_sz_x;
/* Calculate distance */
d2 = 0;
if (gr_x != m) { /* if not on same cell x wise */
tmp = (m > gr_x) ? m*cell_sz-p->x : p->x-(m+1)*cell_sz;
d2 += tmp*tmp;
}
if (gr_y != n) { /* if not on same cell y wise */
tmp = (n > gr_y) ? n*cell_sz-p->y : p->y-(n+1)*cell_sz;
d2 += tmp*tmp;
}
if (gr_z != o) { /* if not on same cell z wise */
tmp = (o > gr_z) ? o*cell_sz-p->z : p->z-(o+1)*cell_sz;
d2 += tmp*tmp;
}
return d2;
}
/* Convert the triangular model m to a triangle list (without connectivity
* information) with the associated information. All the information about the
* triangles (i.e. fields of struct triangle_info) is computed. */
static struct triangle_list* model_to_triangle_list(const struct model *m)
{
int i,n;
struct triangle_list *tl;
struct triangle_info *triags;
face_t *face_i;
/* Initialize and allocate storage */
n = m->num_faces;
tl = xa_malloc(sizeof(*tl));
tl->n_triangles = n;
triags = xa_malloc(sizeof(*tl->triangles)*n);
tl->triangles = triags;
tl->area = 0;
/* Convert triangles and update global data */
for (i=0; i<n; i++) {
face_i = &(m->faces[i]);
init_triangle(&(m->vertices[face_i->f0]),&(m->vertices[face_i->f1]),
&(m->vertices[face_i->f2]),&(triags[i]));
tl->area += triags[i].s_area;
}
return tl;
}
/* Calculates the statistics of the error samples in tse. For each triangle
* formed by neighboring samples the error at the vertices is averaged to
* obtain a single error for the sample triangle. The overall mean error is
* obtained by calculating the mean of the errors of the sample triangles. The
* other statistics are obtained analogously. Note that all sample triangles
* have exactly the same area, and thus the calculation is independent of the
* triangle shape. The overall statistics in dss_stats and m_stats are updated
* (dss_stats->mean_dist is cumulated with the total error and
* dss_stats->rms_dist is cumulated with the total squared error, instead of
* being really updated). */
static void error_stat_triag(const struct triag_sample_error *tse,
struct face_error *fe,
struct dist_surf_surf_stats *dss_stats,
struct misc_stats *m_stats)
{
int n,n_tot,i,j,imax,jmax;
double err_local;
double err_a,err_b,err_c;
double err_min, err_max, err_tot, err_sqr_tot;
double **s_err;
n = tse->n_samples;
fe->sample_freq = n;
dss_stats->m1_area += fe->face_area;
if (n == 0) { /* no samples in this triangle */
return;
}
n_tot = tse->n_samples_tot;
dss_stats->st_m1_area += fe->face_area;
if (m_stats->dist_smpl_sz < n_tot+dss_stats->m1_samples) {
m_stats->dist_smpl_sz += (m_stats->dist_smpl_sz+3)/4; /* 25% increase */
if (m_stats->dist_smpl_sz < n_tot+dss_stats->m1_samples) {
m_stats->dist_smpl_sz = n_tot+dss_stats->m1_samples;
}
m_stats->dist_smpl = xa_realloc(m_stats->dist_smpl,
sizeof(*(m_stats->dist_smpl))*
m_stats->dist_smpl_sz);
}
memcpy(m_stats->dist_smpl+dss_stats->m1_samples,
tse->err_lin,sizeof(*(m_stats->dist_smpl))*n_tot);
dss_stats->m1_samples += n_tot;
/* NOTE: In a triangle with values at the vertex e1, e2 and e3 and using
* linear interpolation to obtain the values within the triangle, the mean
* value (i.e. integral of the value divided by the surface) is
* (e1+e2+e3)/3; and the squared mean value (i.e. integral of the squared
* value divided by the surface) is (e1^2+e2^2+e3^2+e1*e2+e2*e3+e1*e3)/6. */
err_min = DBL_MAX;
err_max = 0;
err_tot = 0;
err_sqr_tot = 0;
s_err = tse->err;
/* Do sample triangles for which the point (i,j) is closer to the point
* (0,0) than the side of the sample triangle opposite (i,j). There are
* (n-1)*n/2 of these. */
for (i=0, imax=n-1; i<imax; i++) {
for (j=0, jmax=imax-i; j<jmax; j++) {
err_a = s_err[i][j];
err_b = s_err[i][j+1];
err_c = s_err[i+1][j];
err_tot += err_a+err_b+err_c;
err_sqr_tot += err_a*(err_a+err_b+err_c)+err_b*(err_b+err_c)+err_c*err_c;
}
}
/* Do the other triangles. There are (n-2)*(n-1)/2 of these. */
for (i=1; i<n; i++) {
for (j=1, jmax=n-i; j<jmax; j++) {
err_a = s_err[i-1][j];
err_b = s_err[i][j-1];
err_c = s_err[i][j];
err_tot += err_a+err_b+err_c;
err_sqr_tot += err_a*(err_a+err_b+err_c)+err_b*(err_b+err_c)+err_c*err_c;
}
}
/* Get min max */
for (i=0; i<tse->n_samples_tot; i++) {
err_local = tse->err_lin[i];
if (err_min > err_local) err_min = err_local;
if (err_max < err_local) err_max = err_local;
}
/* Finalize error measures */
fe->min_error = err_min;
fe->max_error = err_max;
if (n != 1) { /* normal case, (n-1)*n/2+(n-2)*(n-1)/2 = (n-1)*(n-1) */
fe->mean_error = err_tot/((n-1)*(n-1)*3);
fe->mean_sqr_error = err_sqr_tot/((n-1)*(n-1)*6);
} else { /* special case */
fe->mean_error = tse->err_lin[0];
fe->mean_sqr_error = tse->err_lin[0]*tse->err_lin[0];
}
/* Update overall statistics */
if (err_min < dss_stats->min_dist) dss_stats->min_dist = err_min;
if (err_max > dss_stats->max_dist) dss_stats->max_dist = err_max;
dss_stats->mean_dist += fe->mean_error*fe->face_area;
dss_stats->rms_dist += fe->mean_sqr_error*fe->face_area;
}
/* Samples a triangle (a,b,c) using n samples in each direction. The sample
* points are returned in the sample_list s. The dynamic array 's->sample' is
* realloc'ed to the correct size (if no storage has been previously allocated
* it should be NULL). The total number of samples is n*(n+1)/2. The order for
* samples (i,j) in s->sample is all samples for i equal 0 and j from 0 to n-1,
* followed by all samples for i equal 1 and j from 0 to n-2, and so on, where
* i and j are the sampling indices along the ab and ac sides,
* respectively. As a special case, if n equals 1, the triangle middle point
* is used as the sample. */
static void sample_triangle(const dvertex_t *a, const dvertex_t *b,
const dvertex_t *c, int n, struct sample_list* s)
{
dvertex_t u,v; /* basis parametrization vectors */
dvertex_t a_cache; /* local (on stack) copy of a for faster access */
int i,j,maxj,k; /* counters and limits */
/* initialize */
s->n_samples = n*(n+1)/2;
if (n == 0) return;
if (s->buf_sz < s->n_samples) {
s->sample = xa_realloc(s->sample,sizeof(*(s->sample))*s->n_samples);
s->buf_sz = s->n_samples;
}
if (n != 1) { /* normal case */
/* get basis vectors */
substract_dv(b,a,&u);