00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
#include <volume_io/internal_volume_io.h>
00016
#include <bicpl/objects.h>
00017
#include <bicpl/geom.h>
00018
#include <bicpl/trans.h>
00019
00020
#ifndef lint
00021
static char rcsid[] =
"$Header: /software/source//libraries/bicpl/Objects/polygons.c,v 1.43 2002/04/29 18:31:05 stever Exp $";
00022
#endif
00023
00024
00038
private void reverse_polygon_order(
00039
polygons_struct *polygons,
00040
int poly );
00041
private Real
estimate_polygon_curvature(
00042 Point *point,
00043
int n_neighs,
00044 Point neighs[],
00045 Point *centroid,
00046 Vector *normal,
00047 Real *base_length );
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00072 public void initialize_polygons(
00073
polygons_struct *polygons,
00074 Colour col,
00075 Surfprop *spr )
00076 {
00077 ALLOC( polygons->
colours, 1 );
00078
00079 polygons->
colour_flag =
ONE_COLOUR;
00080
00081 polygons->
colours[0] = col;
00082
00083
if( spr != (Surfprop *) 0 )
00084 polygons->
surfprop = *spr;
00085
else
00086
get_default_surfprop( &polygons->
surfprop );
00087
00088 polygons->
n_points = 0;
00089 polygons->
points = (Point *) 0;
00090 polygons->
normals = (Vector *) 0;
00091
00092 polygons->
line_thickness = 1.0f;
00093
00094 polygons->
n_items = 0;
00095 polygons->
end_indices = (
int *) 0;
00096 polygons->
indices = (
int *) 0;
00097
00098 polygons->
visibilities = (Smallest_int *) 0;
00099 polygons->
neighbours = (
int *) 0;
00100 polygons->
bintree = (
bintree_struct_ptr) NULL;
00101 }
00102
00103
00119 public void initialize_polygons_with_size(
00120
polygons_struct *polygons,
00121 Colour col,
00122 Surfprop *spr,
00123
int n_points,
00124
int n_polygons,
00125
int size )
00126 {
00127
int p;
00128
00129
initialize_polygons( polygons, col, spr );
00130
00131 polygons->
n_points = n_points;
00132 ALLOC( polygons->
points, polygons->
n_points );
00133 ALLOC( polygons->
normals, polygons->
n_points );
00134
00135 polygons->
n_items = n_polygons;
00136
00137 ALLOC( polygons->
end_indices, polygons->
n_items );
00138
00139 for_less( p, 0, polygons->
n_items )
00140 polygons->
end_indices[p] = (p+1) * size;
00141
00142 ALLOC( polygons->
indices, polygons->
end_indices[polygons->
n_items-1] );
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 public void free_polygon_neighbours(
00159
polygons_struct *polygons )
00160 {
00161
if( polygons->
neighbours != (
int *) NULL )
00162 {
00163 FREE( polygons->
neighbours );
00164 polygons->
neighbours = (
int *) NULL;
00165 }
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 public void delete_polygons(
polygons_struct *polygons )
00182 {
00183
free_colours( polygons->
colour_flag, polygons->
colours, polygons->
n_points,
00184 polygons->
n_items );
00185
00186
if( polygons->
n_points > 0 )
00187 FREE( polygons->
points );
00188
00189
if( polygons->
n_points > 0 && polygons->
normals != (Vector *) 0 )
00190 FREE( polygons->
normals );
00191
00192
if( polygons->
n_items > 0 )
00193 FREE( polygons->
indices );
00194
00195
if( polygons->
n_items > 0 )
00196 FREE( polygons->
end_indices );
00197
00198
if( polygons->
visibilities != (Smallest_int *) 0 )
00199 FREE( polygons->
visibilities );
00200
00201
free_polygon_neighbours( polygons );
00202
00203
delete_bintree_if_any( &polygons->
bintree );
00204
00205 polygons->
visibilities = (Smallest_int *) 0;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 public void copy_polygons(
00222
polygons_struct *src,
00223
polygons_struct *dest )
00224 {
00225
int i, n_indices, n_colours;
00226
00227 *dest = *src;
00228
00229 n_colours =
get_n_colours( src->colour_flag, src->n_points, src->n_items );
00230
00231 ALLOC( dest->
colours, n_colours );
00232 for_less( i, 0, n_colours )
00233 dest->
colours[i] = src->colours[i];
00234
00235 ALLOC( dest->
points, src->n_points );
00236
if( src->normals != (Vector *) NULL )
00237 ALLOC( dest->
normals, src->n_points );
00238
00239 for_less( i, 0, src->n_points )
00240 {
00241 dest->
points[i] = src->points[i];
00242
if( src->normals != (Vector *) NULL )
00243 dest->
normals[i] = src->normals[i];
00244
00245 }
00246
00247 ALLOC( dest->
end_indices, src->n_items );
00248 for_less( i, 0, src->n_items )
00249 dest->
end_indices[i] = src->end_indices[i];
00250
00251 n_indices =
NUMBER_INDICES( *src );
00252 ALLOC( dest->
indices, n_indices );
00253
00254 for_less( i, 0, n_indices )
00255 dest->
indices[i] = src->indices[i];
00256
00257 dest->
visibilities = (Smallest_int *) 0;
00258 dest->
neighbours = (
int *) 0;
00259 dest->
bintree = (
bintree_struct_ptr) NULL;
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 public void set_polygon_per_item_colours(
00276
polygons_struct *polygons )
00277 {
00278 Colour colour;
00279
int i;
00280
00281
if( polygons->
colour_flag !=
PER_ITEM_COLOURS )
00282 {
00283 colour = polygons->
colours[0];
00284 polygons->
colour_flag =
PER_ITEM_COLOURS;
00285 REALLOC( polygons->
colours, polygons->
n_items );
00286
00287 for_less( i, 0, polygons->
n_items )
00288 polygons->
colours[i] = colour;
00289
00290 }
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 public void create_polygons_visibilities(
00307
polygons_struct *polygons )
00308 {
00309
int i;
00310
00311
if( polygons->
visibilities == (Smallest_int *) 0 &&
00312 polygons->
n_items > 0 )
00313 {
00314 ALLOC( polygons->
visibilities, polygons->
n_items );
00315
00316 for_less( i, 0, polygons->
n_items )
00317 polygons->
visibilities[i] =
TRUE;
00318 }
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 public void set_polygons_visibilities(
00336
polygons_struct *polygons,
00337 BOOLEAN state )
00338 {
00339
int i;
00340
00341
if( polygons->
visibilities != (Smallest_int *) 0 )
00342 {
00343 for_less( i, 0, polygons->
n_items )
00344 polygons->
visibilities[i] = (Smallest_int) state;
00345 }
00346 }
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 public void start_new_polygon(
00362
polygons_struct *polygons )
00363 {
00364
int n_indices;
00365
00366 n_indices =
NUMBER_INDICES( *polygons );
00367
00368 ADD_ELEMENT_TO_ARRAY( polygons->
end_indices, polygons->
n_items,
00369 n_indices, DEFAULT_CHUNK_SIZE );
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 public void add_point_to_polygon(
00388
polygons_struct *polygons,
00389 Point *point,
00390 Vector *normal )
00391 {
00392
int n_points;
00393
00394
if( polygons->
n_items == 0 )
00395
start_new_polygon( polygons );
00396
00397
if( polygons->
n_points > 1 )
00398 {
00399
if( (normal != (Vector *) 0 && polygons->
normals == (Vector *) 0) ||
00400 (normal == (Vector *) 0 && polygons->
normals != (Vector *) 0) )
00401 {
00402 print_error(
00403
"Error: be consistent with normals in add_point_to_polygon.\n" );
00404 }
00405 }
00406
00407 ADD_ELEMENT_TO_ARRAY( polygons->
indices,
00408 polygons->
end_indices[polygons->
n_items-1],
00409 polygons->
n_points, DEFAULT_CHUNK_SIZE );
00410
00411
if( normal != (Vector *) 0 )
00412 {
00413 n_points = polygons->
n_points;
00414 ADD_ELEMENT_TO_ARRAY( polygons->
normals, n_points,
00415 *normal, DEFAULT_CHUNK_SIZE );
00416 }
00417
00418 ADD_ELEMENT_TO_ARRAY( polygons->
points, polygons->
n_points,
00419 *point, DEFAULT_CHUNK_SIZE );
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 public int get_polygon_points(
00437
polygons_struct *polygons,
00438
int poly,
00439 Point points[] )
00440 {
00441
int size, p;
00442
00443 size =
GET_OBJECT_SIZE( *polygons, poly );
00444
00445 for_less( p, 0, size )
00446 {
00447 points[p] = polygons->
points[
00448 polygons->
indices[
POINT_INDEX(polygons->
end_indices,poly,p)]];
00449 }
00450
00451
return( size );
00452 }
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 public void get_polygon_centroid(
00469
polygons_struct *polygons,
00470
int poly,
00471 Point *centroid )
00472 {
00473
int size, p;
00474 Point point;
00475
00476 fill_Point( *centroid, 0.0, 0.0, 0.0 );
00477
00478 size =
GET_OBJECT_SIZE( *polygons, poly );
00479
00480 for_less( p, 0, size )
00481 {
00482 point = polygons->
points[
00483 polygons->
indices[
POINT_INDEX(polygons->
end_indices,poly,p)]];
00484 ADD_POINTS( *centroid, *centroid, point );
00485 }
00486
00487
if( size > 0 )
00488 SCALE_POINT( *centroid, *centroid, 1.0 / (Real) size );
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 public int find_vertex_index(
00508
polygons_struct *polygons,
00509
int poly,
00510
int point_index )
00511 {
00512
int e, ind, size, p;
00513
00514 ind = -1;
00515
00516 size =
GET_OBJECT_SIZE( *polygons, poly );
00517
00518 for_less( e, 0, size )
00519 {
00520 p = polygons->
indices[
POINT_INDEX(polygons->
end_indices,poly,e)];
00521
00522
if( p == point_index )
00523 {
00524 ind = e;
00525
break;
00526 }
00527 }
00528
00529
return( ind );
00530 }
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 public int find_edge_index(
00549
polygons_struct *polygons,
00550
int poly,
00551
int point_index1,
00552
int point_index2 )
00553 {
00554
int e, ind, size, p1, p2;
00555
00556 ind = -1;
00557
00558 size =
GET_OBJECT_SIZE( *polygons, poly );
00559
00560 p2 = polygons->
indices[
POINT_INDEX(polygons->
end_indices,poly,0)];
00561 for_less( e, 0, size )
00562 {
00563 p1 = p2;
00564 p2 = polygons->
indices[
POINT_INDEX(polygons->
end_indices,poly,
00565 (e+1)%size)];
00566
00567
if( (p1 == point_index1 && p2 == point_index2) ||
00568 (p1 == point_index2 && p2 == point_index1) )
00569 {
00570 ind = e;
00571
break;
00572 }
00573 }
00574
00575
return( ind );
00576 }
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 public BOOLEAN
find_polygon_with_edge(
00595
polygons_struct *polygons,
00596
int point_index1,
00597
int point_index2,
00598
int *poly_containing_edge,
00599
int *edge_index )
00600 {
00601
int poly;
00602
00603 for_less( poly, 0, polygons->
n_items )
00604 {
00605 *edge_index =
find_edge_index( polygons, poly,
00606 point_index1, point_index2 );
00607
00608
if( *edge_index >= 0 )
00609 {
00610 *poly_containing_edge = poly;
00611
break;
00612 }
00613 }
00614
00615
return( poly < polygons->
n_items );
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 public BOOLEAN
find_polygon_with_vertex(
00634
polygons_struct *polygons,
00635
int point_index,
00636
int *poly_index,
00637
int *vertex_index )
00638 {
00639
int poly, size, i;
00640 BOOLEAN found;
00641
00642 found =
FALSE;
00643
00644 for_less( poly, 0, polygons->
n_items )
00645 {
00646 size =
GET_OBJECT_SIZE( *polygons, poly );
00647 for_less( i, 0, size )
00648 {
00649
if( polygons->
indices[
POINT_INDEX(polygons->
end_indices,poly,i)] ==
00650 point_index )
00651 {
00652 *poly_index = poly;
00653 *vertex_index = i;
00654 found =
TRUE;
00655
break;
00656 }
00657 }
00658 }
00659
00660
return( found );
00661 }
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677 public BOOLEAN
lookup_polygon_vertex(
00678
polygons_struct *polygons,
00679 Point *point,
00680
int *point_index )
00681 {
00682
int i;
00683
00684 for_less( i, 0, polygons->
n_points )
00685 {
00686
if( EQUAL_POINTS( polygons->
points[i], *point ) )
00687 {
00688 *point_index = i;
00689
break;
00690 }
00691 }
00692
00693
return( i < polygons->
n_points );
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717 public BOOLEAN
find_next_edge_around_point(
00718
polygons_struct *polygons,
00719
int poly,
00720
int index_1,
00721
int index_2,
00722
int *next_poly,
00723
int *next_index_1,
00724
int *next_index_2 )
00725 {
00726
int size, edge, point_index, neighbour_point_index;
00727
int next_neigh_index;
00728
00729 point_index = polygons->
indices[
00730
POINT_INDEX( polygons->
end_indices, poly, index_1 )];
00731
00732 neighbour_point_index = polygons->
indices[
00733
POINT_INDEX( polygons->
end_indices, poly, index_2 )];
00734
00735 size =
GET_OBJECT_SIZE( *polygons, poly );
00736
00737
if( index_2 == (index_1+1) % size )
00738 edge = index_1;
00739
else
00740 edge = index_2;
00741
00742 *next_poly = polygons->
neighbours[
00743
POINT_INDEX(polygons->
end_indices,poly,edge)];
00744
00745
if( *next_poly >= 0 )
00746 {
00747 size =
GET_OBJECT_SIZE(*polygons,*next_poly);
00748 *next_index_1 =
find_vertex_index( polygons, *next_poly, point_index );
00749
00750 *next_index_2 = (*next_index_1 + 1) % size;
00751 next_neigh_index = polygons->
indices[
00752
POINT_INDEX( polygons->
end_indices, *next_poly,
00753 *next_index_2 )];
00754
if( next_neigh_index == neighbour_point_index )
00755 {
00756 *next_index_2 = (*next_index_1 + size- 1) % size;
00757 }
00758 }
00759
00760
return( *next_poly >= 0 );
00761 }
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783 public int get_neighbours_of_point(
00784
polygons_struct *polygons,
00785
int poly,
00786
int vertex_index,
00787
int neighbours[],
00788
int max_neighbours,
00789 BOOLEAN *interior_point )
00790 {
00791
int p, n_neighbours, current_poly, current_index_within_poly;
00792
int size, neighbour_index_within_poly;
00793 BOOLEAN found;
00794
00795 size =
GET_OBJECT_SIZE( *polygons, poly );
00796
00797 current_poly = poly;
00798 current_index_within_poly = vertex_index;
00799 neighbour_index_within_poly = (vertex_index-1+size)%size;
00800
00801
if( max_neighbours > 0 )
00802 {
00803 neighbours[0] = polygons->
indices[
POINT_INDEX(polygons->
end_indices,
00804 poly,neighbour_index_within_poly)];
00805 }
00806
00807 n_neighbours = 1;
00808
00809
do
00810 {
00811 found =
find_next_edge_around_point( polygons,
00812 current_poly, current_index_within_poly,
00813 neighbour_index_within_poly,
00814 ¤t_poly, ¤t_index_within_poly,
00815 &neighbour_index_within_poly );
00816
00817
if( found && current_poly != poly )
00818 {
00819
if( n_neighbours < max_neighbours )
00820 {
00821 neighbours[n_neighbours] = polygons->
indices[
00822
POINT_INDEX(polygons->
end_indices,current_poly,
00823 neighbour_index_within_poly)];
00824 }
00825
00826 ++n_neighbours;
00827 }
00828 }
00829
while( found && current_poly != poly );
00830
00831
if( !found )
00832 {
00833 current_poly = poly;
00834 current_index_within_poly = vertex_index;
00835 neighbour_index_within_poly = (vertex_index+1+size)%size;
00836
00837
if( n_neighbours < max_neighbours )
00838 {
00839 for_down( p, n_neighbours, 1 )
00840 neighbours[p] = neighbours[p-1];
00841 neighbours[0] = polygons->
indices[
00842
POINT_INDEX(polygons->
end_indices,
00843 poly,neighbour_index_within_poly)];
00844 }
00845 ++n_neighbours;
00846
00847
do
00848 {
00849 found =
find_next_edge_around_point( polygons,
00850 current_poly, current_index_within_poly,
00851 neighbour_index_within_poly,
00852 ¤t_poly, ¤t_index_within_poly,
00853 &neighbour_index_within_poly );
00854
00855
if( found && current_poly != poly )
00856 {
00857
if( n_neighbours < max_neighbours )
00858 {
00859 for_down( p, n_neighbours, 1 )
00860 neighbours[p] = neighbours[p-1];
00861
00862 neighbours[0] = polygons->
indices[
00863
POINT_INDEX(polygons->
end_indices,current_poly,
00864 neighbour_index_within_poly)];
00865 }
00866
00867 ++n_neighbours;
00868 }
00869 }
00870
while( found && current_poly != poly );
00871
00872
if( current_poly == poly )
00873 print_error(
"get_neighbours_of_point: topology_error" );
00874 }
00875
00876 *interior_point = found;
00877
00878
return( n_neighbours );
00879 }
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900 public int get_polygons_around_vertex(
00901
polygons_struct *polygons,
00902
int poly,
00903
int vertex_index,
00904
int poly_indices[],
00905
int n_polys_alloced,
00906 BOOLEAN *closed_flag )
00907 {
00908
int current_poly, current_index_within_poly;
00909
int size, neighbour_index_within_poly;
00910
int n_polys, dir;
00911 BOOLEAN found;
00912
00913 size =
GET_OBJECT_SIZE( *polygons, poly );
00914
00915 poly_indices[0] = poly;
00916 n_polys = 1;
00917
00918
for( dir = -1; dir <= 1; dir +=2 )
00919 {
00920 current_poly = poly;
00921 current_index_within_poly = vertex_index;
00922 neighbour_index_within_poly = (vertex_index + size + dir) % size;
00923
00924
do
00925 {
00926 found =
find_next_edge_around_point( polygons,
00927 current_poly, current_index_within_poly,
00928 neighbour_index_within_poly,
00929 ¤t_poly, ¤t_index_within_poly,
00930 &neighbour_index_within_poly );
00931
00932
if( found && current_poly != poly )
00933 {
00934
if( n_polys < n_polys_alloced )
00935 {
00936 poly_indices[n_polys] = current_poly;
00937 ++n_polys;
00938 }
00939 }
00940 }
00941
while( found && current_poly != poly );
00942
00943
if( found )
break;
00944 }
00945
00946
if( dir == -1 )
00947 *closed_flag =
TRUE;
00948
else
00949 *closed_flag =
FALSE;
00950
00951
return( n_polys );
00952 }
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969 public void compute_polygon_normal(
00970
polygons_struct *polygons,
00971
int poly,
00972 Vector *normal )
00973 {
00974
#define MAX_TEMP_STORAGE 1000
00975
int e, size, point_index;
00976 Point polygon[
MAX_TEMP_STORAGE];
00977
00978 size =
GET_OBJECT_SIZE( *polygons, poly );
00979
if( size >
MAX_TEMP_STORAGE )
00980 size =
MAX_TEMP_STORAGE;
00981
00982 for_less( e, 0, size )
00983 {
00984 point_index =
00985 polygons->
indices[
POINT_INDEX(polygons->
end_indices,poly,e)];
00986
00987 polygon[e] = polygons->
points[point_index];
00988 }
00989
00990
find_polygon_normal( size, polygon, normal );
00991 }
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009 public void compute_polygon_normals(
01010
polygons_struct *polygons )
01011 {
01012
int e, poly, size, point_index, prev_index, next_index;
01013 Real scale;
01014 Vector normal, normal_scaled;
01015 progress_struct progress;
01016
01017 for_less( point_index, 0, polygons->
n_points )
01018 fill_Vector( polygons->
normals[point_index], 0.0, 0.0, 0.0 );
01019
01020 initialize_progress_report( &progress,
FALSE, polygons->
n_items,
01021
"Computing Normals" );
01022
01023 for_less( poly, 0, polygons->
n_items )
01024 {
01025
compute_polygon_normal( polygons, poly, &normal );
01026
01027 NORMALIZE_VECTOR( normal, normal );
01028
01029 size =
GET_OBJECT_SIZE( *polygons, poly );
01030
01031 point_index =
01032 polygons->
indices[
POINT_INDEX(polygons->
end_indices,poly,size-1)];
01033 next_index =
01034 polygons->
indices[
POINT_INDEX(polygons->
end_indices,poly,0)];
01035
01036 for_less( e, 0, size )
01037 {
01038 prev_index = point_index;
01039 point_index = next_index;
01040 next_index =
01041 polygons->
indices[
POINT_INDEX(polygons->
end_indices,poly,
01042 (e+1)%size)];
01043
01044
01045
01046
01047 scale =
get_angle_between_points( &polygons->
points[prev_index],
01048 &polygons->
points[point_index],
01049 &polygons->
points[next_index] );
01050
01051 scale = FABS( scale );
01052
if( scale > PI )
01053 scale = scale - PI;
01054
01055 SCALE_VECTOR( normal_scaled, normal, scale );
01056
01057 ADD_VECTORS( polygons->
normals[point_index],
01058 polygons->
normals[point_index],
01059 normal_scaled );
01060 }
01061
01062 update_progress_report( &progress, poly + 1 );
01063 }
01064
01065 terminate_progress_report( &progress );
01066
01067 for_less( point_index, 0, polygons->
n_points )
01068 {
01069 NORMALIZE_VECTOR( polygons->
normals[point_index],
01070 polygons->
normals[point_index] );
01071 }
01072 }
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092 public void average_polygon_normals(
01093
polygons_struct *polygons,
01094
int n_iters,
01095 Real neighbour_weight )
01096 {
01097 Real avg_dot_prod;
01098
int e, poly, size, point_index, neigh_index, i;
01099 Vector *neigh_normal_sum, *new_normals, new_normal;
01100 progress_struct progress;
01101
01102
if( polygons->
n_points <= 0 || polygons->
n_items <= 0 )
01103
return;
01104
01105
compute_polygon_normals( polygons );
01106
01107
if( n_iters <= 0 )
01108
return;
01109
01110 ALLOC( new_normals, polygons->
n_points );
01111 for_less( point_index, 0, polygons->
n_points )
01112 new_normals[point_index] = polygons->
normals[point_index];
01113
01114 ALLOC( neigh_normal_sum, polygons->
n_points );
01115
01116 for_less( i, 0, n_iters )
01117 {
01118 for_less( point_index, 0, polygons->
n_points )
01119 fill_Vector( neigh_normal_sum[point_index], 0.0, 0.0, 0.0 );
01120
01121 initialize_progress_report( &progress,
FALSE, polygons->
n_items,
01122
"Averaging Normals" );
01123
01124 for_less( poly, 0, polygons->
n_items )
01125 {
01126 size =
GET_OBJECT_SIZE( *polygons, poly );
01127
01128 for_less( e, 0, size )
01129 {
01130 point_index = polygons->
indices[
01131
POINT_INDEX(polygons->
end_indices,poly,e)];
01132 neigh_index = polygons->
indices[
01133
POINT_INDEX(polygons->
end_indices,poly,(e+1)%size)];
01134
01135 ADD_VECTORS( neigh_normal_sum[point_index],
01136 neigh_normal_sum[point_index],
01137 new_normals[neigh_index] );
01138 ADD_VECTORS( neigh_normal_sum[neigh_index],
01139 neigh_normal_sum[neigh_index],
01140 new_normals[point_index] );
01141 }
01142
01143 update_progress_report( &progress, poly + 1 );
01144 }
01145
01146 terminate_progress_report( &progress );
01147
01148 avg_dot_prod = 0.0;
01149
01150 for_less( point_index, 0, polygons->
n_points )
01151 {
01152 NORMALIZE_VECTOR( neigh_normal_sum[point_index],
01153 neigh_normal_sum[point_index] );
01154
01155 INTERPOLATE_VECTORS( new_normal,
01156 polygons->
normals[point_index],
01157 neigh_normal_sum[point_index],
01158 neighbour_weight );
01159
01160 NORMALIZE_VECTOR( new_normal, new_normal );
01161
01162 avg_dot_prod += DOT_VECTORS( new_normal, new_normals[point_index] );
01163 new_normals[point_index] = new_normal;
01164 }
01165
01166 avg_dot_prod /= (Real) polygons->
n_points;
01167
01168 print(
"Average dot product: %g\n", avg_dot_prod );
01169 }
01170
01171 for_less( point_index, 0, polygons->
n_points )
01172 polygons->
normals[point_index] = new_normals[point_index];
01173
01174 FREE( neigh_normal_sum );
01175 FREE( new_normals );
01176 }
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195 public BOOLEAN
get_plane_polygon_intersection(
01196 Vector *normal,
01197 Real d,
01198
polygons_struct *polygons,
01199
int poly,
01200 Point intersection_points[] )
01201 {
01202
int i1, i2, edge, size, n_intersections;
01203
01204 n_intersections = 0;
01205
01206 size =
GET_OBJECT_SIZE( *polygons, poly );
01207
01208 for_less( edge, 0, size )
01209 {
01210 i1 = polygons->
indices[
POINT_INDEX(polygons->
end_indices,poly,edge)];
01211 i2 = polygons->
indices[
01212
POINT_INDEX(polygons->
end_indices,poly,(edge+1)%size)];
01213
01214
if(
get_plane_segment_intersection( normal, d, &polygons->
points[i1],
01215 &polygons->
points[i2],
01216 &intersection_points[n_intersections] ))
01217 {
01218 ++n_intersections;
01219
01220
if( n_intersections == 2 )
01221
break;
01222 }
01223 }
01224
01225
return( n_intersections == 2 );
01226 }
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244 public BOOLEAN
get_plane_segment_intersection(
01245 Vector *normal,
01246 Real d,
01247 Point *p1,
01248 Point *p2,
01249 Point *intersection_point )
01250 {
01251 Real dist1, dist2, t;
01252 BOOLEAN intersects;
01253
01254 dist1 = DIST_FROM_PLANE( *normal, d, *p1 );
01255 dist2 = DIST_FROM_PLANE( *normal, d, *p2 );
01256
01257
if( dist1 == 0.0 )
01258 t = 0.0;
01259
else if( dist2 == 0.0 )
01260 t = 1.0;
01261
else if( dist1 == dist2 )
01262 t = -1.0;
01263
else
01264 t = dist1 / (dist1 - dist2);
01265
01266
if( t >= 0.0 && t <= 1.0 )
01267 {
01268 INTERPOLATE_POINTS( *intersection_point, *p1, *p2, t );
01269
01270 intersects =
TRUE;
01271 }
01272
else
01273 intersects =
FALSE;
01274
01275
return( intersects );
01276 }
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291 public void reverse_polygons_vertices(
01292
polygons_struct *polygons )
01293 {
01294
int poly;
01295
01296
if( polygons->
neighbours != NULL )
01297 FREE( polygons->
neighbours );
01298
01299 for_less( poly, 0, polygons->
n_items )
01300
reverse_polygon_order( polygons, poly );
01301 }
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317 public void make_polygons_front_facing(
01318
polygons_struct *polygons )
01319 {
01320
int poly;
01321
01322
if( polygons->
neighbours != (
int *) 0 )
01323 FREE( polygons->
neighbours );
01324
01325 for_less( poly, 0, polygons->
n_items )
01326 {
01327
if(
polygon_is_back_facing( polygons, poly ) )
01328
reverse_polygon_order( polygons, poly );
01329 }
01330 }
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347 public BOOLEAN
polygon_is_back_facing(
01348
polygons_struct *polygons,
01349
int poly )
01350 {
01351
int i, size, point_index;
01352 Vector avg_vertex_normal, polygon_normal;
01353
01354
compute_polygon_normal( polygons, poly, &polygon_normal );
01355
01356 size =
GET_OBJECT_SIZE( *polygons, poly );
01357
01358 fill_Vector( avg_vertex_normal, 0.0, 0.0, 0.0 );
01359
01360 for_less( i, 0, size )
01361 {
01362 point_index = polygons->
indices[
01363
POINT_INDEX(polygons->
end_indices,poly,i)];
01364 ADD_VECTORS( avg_vertex_normal, avg_vertex_normal,
01365 polygons->
normals[point_index] );
01366 }
01367
01368
return( DOT_VECTORS( avg_vertex_normal, polygon_normal ) > 0.0 );
01369 }
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385 private void reverse_polygon_order(
01386
polygons_struct *polygons,
01387
int poly )
01388 {
01389
int i, size, start, tmp_swap;
01390
01391 size =
GET_OBJECT_SIZE( *polygons, poly );
01392
01393 start =
POINT_INDEX( polygons->
end_indices, poly, 0 );
01394
01395 for_less( i, 0, size / 2 )
01396 {
01397 tmp_swap = polygons->
indices[start+(size-1 - i)];
01398 polygons->
indices[start+(size-1 - i)] = polygons->
indices[start+i];
01399 polygons->
indices[start+i] = tmp_swap;
01400 }
01401 }
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425 public void compute_points_centroid_and_normal(
01426
polygons_struct *polygons,
01427
int point_index,
01428
int n_neighbours,
01429
int neighbours[],
01430 Point *centroid,
01431 Vector *normal,
01432 Real *base_length,
01433 Real *curvature )
01434 {
01435
#define MAX_NEIGHBOURS 1000
01436
int i;
01437 Point neigh_points[
MAX_NEIGHBOURS];
01438
01439
if( n_neighbours > 2 )
01440 {
01441 for_less( i, 0, n_neighbours )
01442 neigh_points[i] = polygons->
points[neighbours[i]];
01443
01444
get_points_centroid( n_neighbours, neigh_points, centroid );
01445
01446
find_polygon_normal( n_neighbours, neigh_points, normal );
01447
01448 *curvature =
estimate_polygon_curvature( &polygons->
points[point_index],
01449 n_neighbours, neigh_points,
01450 centroid, normal, base_length );
01451 }
01452
else
01453 {
01454 *centroid = polygons->
points[point_index];
01455 fill_Vector( *normal, 0.0, 0.0, 0.0 );
01456 *base_length = 1.0;
01457 *curvature = 0.0;
01458 }
01459 }
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483 public void compute_polygon_point_centroid(
01484
polygons_struct *polygons,
01485
int poly,
01486
int vertex_index,
01487
int point_index,
01488 Point *centroid,
01489 Vector *normal,
01490 Real *base_length,
01491 Real *curvature )
01492 {
01493
int n_neighbours;
01494
int neighbours[
MAX_NEIGHBOURS];
01495 BOOLEAN interior_point;
01496
01497 n_neighbours =
get_neighbours_of_point( polygons, poly, vertex_index,
01498 neighbours,
MAX_NEIGHBOURS,
01499 &interior_point );
01500
01501
compute_points_centroid_and_normal( polygons, point_index,
01502 n_neighbours, neighbours,
01503 centroid, normal, base_length,
01504 curvature );
01505 }
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524 private Real
estimate_polygon_curvature(
01525 Point *point,
01526
int n_neighs,
01527 Point neighs[],
01528 Point *centroid,
01529 Vector *normal,
01530 Real *base_length )
01531 {
01532
int i;
01533 Real curvature, len;
01534 Vector to_point;
01535
01536 len = 0.0;
01537 for_less( i, 0, n_neighs )
01538 len +=
distance_between_points( &neighs[i], centroid );
01539
01540
if( n_neighs > 0 )
01541 len = 2.0 * len / (Real) n_neighs;
01542
01543
if( len == 0.0 )
01544 len = 1.0;
01545
01546 *base_length = len;
01547
01548 SUB_POINTS( to_point, *point, *centroid );
01549
01550 curvature = MAGNITUDE( to_point ) / len;
01551
01552
if( DOT_VECTORS( to_point, *normal ) < 0.0 )
01553 curvature = -curvature;
01554
01555
return( curvature );
01556 }
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572 public Real
compute_polygon_vertex_curvature(
01573
polygons_struct *polygons,
01574
int point_index )
01575 {
01576 Real curvature, base_length;
01577
int poly, vertex;
01578 Point centroid;
01579 Vector normal;
01580
01581
if( !
find_polygon_with_vertex( polygons, point_index, &poly, &vertex ) )
01582 {
01583 handle_internal_error(
"compute_polygon_vertex_curvature" );
01584
return( 0.0 );
01585 }
01586
01587
compute_polygon_point_centroid( polygons, poly, vertex, point_index,
01588 ¢roid, &normal, &base_length,
01589 &curvature );
01590
01591
return( curvature );
01592 }
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609 private void get_opposite_point(
01610
polygons_struct *polygons,
01611
int poly,
01612
int edge,
01613 Point *point )
01614 {
01615
int v, size;
01616
01617 size =
GET_OBJECT_SIZE( *polygons, poly );
01618
01619
if( size == 3 )
01620 v = (edge + 2) % size;
01621
else
01622 v = (edge + size/2) % size;
01623
01624 *point = polygons->
points[polygons->
indices[
01625
POINT_INDEX( polygons->
end_indices, poly, v)]];
01626 }
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643 public Real
get_polygon_edge_angle(
01644
polygons_struct *polygons,
01645
int poly,
01646
int edge )
01647 {
01648
int size, i, point_index1, point_index2, neighbour_poly;
01649 Real angle, edge_len_squared, scale, x,
y;
01650 Point p1, p2, poly1_point, poly2_point;
01651 Vector v1, v2, normal, diff, edge_vec;
01652
01653 neighbour_poly = polygons->
neighbours[
POINT_INDEX( polygons->
end_indices,
01654 poly, edge )];
01655
01656
if( neighbour_poly < 0 )
01657
return( PI );
01658
01659 size =
GET_OBJECT_SIZE( *polygons, poly );
01660
01661 point_index1 = polygons->
indices[
POINT_INDEX( polygons->
end_indices,
01662 poly, edge )];
01663 point_index2 = polygons->
indices[
POINT_INDEX( polygons->
end_indices,
01664 poly, (edge+1)%size )];
01665 p1 = polygons->
points[point_index1];
01666 p2 = polygons->
points[point_index2];
01667
01668
get_opposite_point( polygons, poly, edge, &poly1_point );
01669
01670 i =
find_edge_index( polygons, neighbour_poly, point_index1, point_index2 );
01671
get_opposite_point( polygons, neighbour_poly, i, &poly2_point );
01672
01673 SUB_POINTS( edge_vec, p2, p1 );
01674 SUB_POINTS( v1, poly1_point, p1 );
01675 SUB_POINTS( v2, poly2_point, p1 );
01676
01677 edge_len_squared = DOT_VECTORS( edge_vec, edge_vec );
01678
if( edge_len_squared == 0.0 )
01679 edge_len_squared = 1.0;
01680
01681 scale = DOT_VECTORS( v1, edge_vec ) / edge_len_squared;
01682 SCALE_VECTOR( diff, edge_vec, scale );
01683 SUB_VECTORS( v1, v1, diff );
01684 NORMALIZE_VECTOR( v1, v1 );
01685
01686 CROSS_VECTORS( normal, edge_vec, v1 );
01687 NORMALIZE_VECTOR( normal, normal );
01688
01689 scale = DOT_VECTORS( v2, edge_vec ) / edge_len_squared;
01690 SCALE_VECTOR( diff, edge_vec, scale );
01691 SUB_VECTORS( v2, v2, diff );
01692
01693 x = DOT_VECTORS( v2, v1 );
01694
y = -DOT_VECTORS( v2, normal );
01695
01696 angle =
compute_clockwise_rotation( x,
y );
01697
01698
if( angle < 0.0 )
01699 angle += 2.0 * PI;
01700
01701
return( angle );
01702 }
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718 public BOOLEAN
polygons_are_same_topology(
01719
polygons_struct *p1,
01720
polygons_struct *p2 )
01721 {
01722
return(
objects_are_same_topology( p1->
n_points, p1->
n_items,
01723 p1->
end_indices, p1->
indices,
01724 p2->
n_points, p2->
n_items,
01725 p2->
end_indices, p2->
indices ) );
01726 }
01727
01728