00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "srb.h"
00031
00032
00033 #define _SRB_ARRAY_LENGTH( array )\
00034 ( sizeof( (array) ) / sizeof( (array)[ 0 ] ) )
00035
00036
00037 #define _SRB_MIN3( a, b, c )\
00038 ( ( a < b ) ? ( ( a < c ) ? 0 : 2 ) : ( ( b < c ) ? 1 : 2 ) )
00039
00040
00041 #define _SRB_DISTANCE_SQUARED( x1, y1, z1, x2, y2, z2 )\
00042 ( ( (x2) - (x1) ) * ( (x2) - (x1) ) +\
00043 ( (y2) - (y1) ) * ( (y2) - (y1) ) +\
00044 ( (z2) - (z1) ) * ( (z2) - (z1) ) )
00045
00046
00047
00048
00049
00050 #define _SRB_VERTEX( vertices, at )\
00051 ( (vertices) + ( 3 * (at) ) )
00052
00053 #define _SRB_TRIANGLE( triangles, at )\
00054 ( (triangles) + ( 3 * (at) ) )
00055
00056
00057
00058
00059 struct _SRBVERTEX;
00060 typedef struct _SRBVERTEX SRBVERTEX;
00061
00062 struct _SRBEDGE;
00063 typedef struct _SRBEDGE SRBEDGE;
00064
00065 struct _SRBTRIANGLE;
00066 typedef struct _SRBTRIANGLE SRBTRIANGLE;
00067
00068
00069 struct _SRBVERTEX
00070 {
00071 double x;
00072 double y;
00073 double z;
00074 int index;
00075 SRBVERTEX *next;
00076 };
00077
00078
00079 struct _SRBEDGE
00080 {
00081 SRBVERTEX *V1;
00082 SRBVERTEX *V2;
00083 SRBTRIANGLE *T1;
00084 SRBTRIANGLE *T2;
00085 SRBVERTEX *M;
00086 SRBEDGE *E1;
00087 SRBEDGE *E2;
00088 SRBEDGE *O;
00089 int iteration;
00090 SRBEDGE *next;
00091 };
00092
00093
00094 #define _SRB_EDGE_MIDPOINT( E, _x, _y, _z )\
00095 (_x) = ( (E)->V1->x + (E)->V2->x ) / 2.0;\
00096 (_y) = ( (E)->V1->y + (E)->V2->y ) / 2.0;\
00097 (_z) = ( (E)->V1->z + (E)->V2->z ) / 2.0
00098
00099
00100 #define _SRB_EDGE_FIND_CHILD( P, V1, V2, E )\
00101 ( (E) = _SRB_IS_EDGE( (P)->E1, (V1), (V2) ) ? (P)->E1 : (P)->E2 )
00102
00103
00104
00105 #define _SRB_IS_EDGE( E, _V1, _V2 )\
00106 ( ( (E)->V1 == (_V1) && (E)->V2 == (_V2) ) || ( (E)->V1 == (_V2) && (E)->V2 == (_V1) ) )
00107
00108
00109 struct _SRBTRIANGLE
00110 {
00111 SRBEDGE *E1;
00112 SRBEDGE *E2;
00113 SRBEDGE *E3;
00114 SRBVERTEX *V1;
00115 SRBVERTEX *V2;
00116 SRBVERTEX *V3;
00117 int iteration;
00118 SRBTRIANGLE *next;
00119 };
00120
00121
00122 #define _SRB_TRIANGLE_CENTER( T, _x, _y, _z )\
00123 (_x) = ( (T)->V1->x + (T)->V2->x + (T)->V3->x ) / 3.0;\
00124 (_y) = ( (T)->V1->y + (T)->V2->y + (T)->V3->y ) / 3.0;\
00125 (_z) = ( (T)->V1->z + (T)->V2->z + (T)->V3->z ) / 3.0
00126
00127
00128 typedef struct _SRBRAY
00129 {
00130 double ox;
00131 double oy;
00132 double oz;
00133 double dx;
00134 double dy;
00135 double dz;
00136 double ex;
00137 double ey;
00138 double ez;
00139 }
00140 SRBRAY;
00141
00142
00143 typedef struct _SRBPYRAMID
00144 {
00145 double ox;
00146 double oy;
00147 double oz;
00148 double ax;
00149 double ay;
00150 double az;
00151 double bx;
00152 double by;
00153 double bz;
00154 double cx;
00155 double cy;
00156 double cz;
00157 double volume;
00158 double face_area;
00159 }
00160 SRBPYRAMID;
00161
00162
00163 typedef struct _SRB
00164 {
00165 SRBVERTEX *vertices;
00166 SRBEDGE *edges;
00167 SRBTRIANGLE *triangles;
00168 int iteration;
00169 SRBEDGE *tail;
00170
00171
00172 SRBVERTEX _vertex;
00173 SRBEDGE _edge;
00174 SRBTRIANGLE _triangle;
00175 }
00176 SRB;
00177
00178
00179 static SRBVERTEX* _srb_vertex_new
00180 (
00181 SRB *srb,
00182 double x,
00183 double y,
00184 double z
00185 )
00186 {
00187 SRBVERTEX *V;
00188
00189 if( NULL == ( V = malloc( sizeof( SRBVERTEX ) ) ) )
00190 return NULL;
00191
00192 V->x = x;
00193 V->y = y;
00194 V->z = z;
00195
00196 V->next = srb->vertices->next;
00197 srb->vertices->next = V;
00198
00199 return V;
00200 }
00201
00202
00203 static SRBVERTEX* _srb_vertex_new_at
00204 (
00205 SRB *srb,
00206 int at,
00207 double x,
00208 double y,
00209 double z
00210 )
00211 {
00212 SRBVERTEX *V, *head;
00213 int i;
00214
00215
00216 if( NULL == ( V = malloc( sizeof( SRBVERTEX ) ) ) )
00217 return NULL;
00218
00219 V->x = x;
00220 V->y = y;
00221 V->z = z;
00222
00223 head = srb->vertices;
00224 for( i = 0; i < at; ++i )
00225 head = head->next;
00226
00227 V->next = head->next;
00228 head->next = V;
00229
00230 return V;
00231 }
00232
00233
00234 static SRBVERTEX* _srb_vertex_at( SRB *srb, int at )
00235 {
00236 SRBVERTEX *V;
00237 int i;
00238
00239
00240 V = srb->vertices->next;
00241
00242 for( i = 0; i < at; ++i )
00243 V = V->next;
00244
00245 return V;
00246 }
00247
00248
00249 static SRBEDGE* _srb_edge_new
00250 (
00251 SRB *srb,
00252 SRBVERTEX *V1,
00253 SRBVERTEX *V2
00254 )
00255 {
00256 SRBEDGE *E;
00257
00258 if( NULL == ( E = malloc( sizeof( SRBEDGE ) ) ) )
00259 return NULL;
00260
00261 E->V1 = V1;
00262 E->V2 = V2;
00263 E->T1 = NULL;
00264 E->T2 = NULL;
00265 E->M = NULL;
00266 E->E1 = NULL;
00267 E->E2 = NULL;
00268 E->O = NULL;
00269
00270 E->iteration = srb->iteration;
00271
00272 E->next = srb->edges->next;
00273 srb->edges->next = E;
00274
00275 return E;
00276 }
00277
00278
00279 static SRBEDGE* _srb_edge_new_at_tail( SRB *srb, SRBVERTEX *V1, SRBVERTEX *V2 )
00280 {
00281 SRBEDGE *E;
00282
00283 if( NULL == ( E = _srb_edge_new( srb, V1, V2 ) ) )
00284 return NULL;
00285
00286
00287 srb->edges->next = E->next;
00288
00289 if( NULL == srb->tail )
00290 {
00291
00292 E->next = srb->edges->next;
00293 srb->edges->next = E;
00294 }
00295 else
00296 {
00297 E->next = srb->tail->next;
00298 srb->tail->next = E;
00299 }
00300
00301 srb->tail = E;
00302
00303 return E;
00304 }
00305
00306
00307 static SRBEDGE* _srb_edge_find( SRB *srb, SRBVERTEX *V1, SRBVERTEX *V2 )
00308 {
00309 SRBEDGE *E = srb->edges->next;
00310
00311 while( NULL != E )
00312 {
00313 if( _SRB_IS_EDGE( E, V1, V2 ) )
00314 return E;
00315
00316 E = E->next;
00317 }
00318
00319 return NULL;
00320 }
00321
00322
00323 static SRBEDGE* _srb_edge_new_unique( SRB *srb, SRBVERTEX *V1, SRBVERTEX *V2 )
00324 {
00325 SRBEDGE *E;
00326
00327 if( NULL == ( E = _srb_edge_find( srb, V1, V2 ) ) )
00328 return _srb_edge_new( srb, V1, V2 );
00329 else
00330 return E;
00331 }
00332
00333
00334 static void _srb_edge_set_triangle( SRBEDGE *E, SRBTRIANGLE *T )
00335 {
00336 if( NULL == E->T1 )
00337 E->T1 = T;
00338 else if( NULL == E->T2 )
00339 E->T2 = T;
00340 }
00341
00342
00343 static SRBTRIANGLE* _srb_triangle_new
00344 (
00345 SRB *srb,
00346 SRBEDGE *E1,
00347 SRBEDGE *E2,
00348 SRBEDGE *E3,
00349 SRBVERTEX *V1,
00350 SRBVERTEX *V2,
00351 SRBVERTEX *V3
00352 )
00353 {
00354 SRBTRIANGLE *T;
00355
00356 if( NULL == ( T = malloc( sizeof( SRBTRIANGLE ) ) ) )
00357 return NULL;
00358
00359 T->E1 = E1;
00360 T->E2 = E2;
00361 T->E3 = E3;
00362 T->V1 = V1;
00363 T->V2 = V2;
00364 T->V3 = V3;
00365
00366 T->iteration = srb->iteration;
00367
00368 T->next = srb->triangles->next;
00369 srb->triangles->next = T;
00370
00371 return T;
00372 }
00373
00374
00375 static void _srb_init( SRB *srb, SRBPARAMS *params )
00376 {
00377 srb->_vertex.next = NULL;
00378 srb->vertices = &srb->_vertex;
00379 srb->_edge.next = NULL;
00380 srb->edges = &srb->_edge;
00381 srb->_triangle.next = NULL;
00382 srb->triangles = &srb->_triangle;
00383
00384 srb->iteration = 0;
00385
00386
00387 params->origin_x = params->origin_x / params->voxel_width;
00388 params->origin_y = params->origin_y / params->voxel_height;
00389 params->origin_z = params->origin_z / params->voxel_length;
00390 }
00391
00392
00393 static int _srb_init_2d
00394 (
00395 SRB *srb,
00396 SRBPARAMS *params,
00397 double *vertices,
00398 int vertex_count
00399 )
00400 {
00401 int i, j;
00402 double *v;
00403 SRBVERTEX *V, *V1, *V2;
00404 SRBEDGE *E1, *E2;
00405
00406
00407 _srb_init( srb, params );
00408 srb->tail = NULL;
00409
00410 for( i = 0; i < vertex_count; ++i )
00411 {
00412 v = _SRB_VERTEX( vertices, i );
00413
00414 if( NULL == _srb_vertex_new_at( srb, i, v[0], v[1], v[2] ) )
00415 return 0;
00416 }
00417
00418 V = srb->vertices->next;
00419
00420 while( NULL != V )
00421 {
00422 V1 = V;
00423 V2 = NULL != V->next ? V->next : srb->vertices->next;
00424
00425 if( NULL == _srb_edge_new_at_tail( srb, V1, V2 ) )
00426 return 0;
00427
00428 V = V->next;
00429 }
00430
00431
00432
00433 E1 = srb->edges->next;
00434
00435 for( i = 0; i < vertex_count / 2; ++i )
00436 {
00437 E2 = E1;
00438
00439 for( j = 0; j < vertex_count / 2; ++j )
00440 E2 = E2->next;
00441
00442 E1->O = E2;
00443 E2->O = E1;
00444
00445 E1 = E1->next;
00446 }
00447
00448 return 1;
00449 }
00450
00451
00452 static int _srb_init_3d
00453 (
00454 SRB *srb,
00455 SRBPARAMS *params,
00456 double *vertices,
00457 int vertex_count,
00458 int *triangles,
00459 int triangle_count
00460 )
00461 {
00462 int i;
00463 double *v;
00464 int *t;
00465 SRBVERTEX *V1, *V2, *V3;
00466 SRBEDGE *E1, *E2, *E3;
00467 SRBTRIANGLE *T;
00468
00469
00470 _srb_init( srb, params );
00471
00472 for( i = 0; i < vertex_count; ++i )
00473 {
00474 v = _SRB_VERTEX( vertices, i );
00475
00476 if( NULL == _srb_vertex_new_at( srb, i, v[0], v[1], v[2] ) )
00477 return 0;
00478 }
00479
00480 for( i = 0; i < triangle_count; ++i )
00481 {
00482 t = _SRB_VERTEX( triangles, i );
00483
00484 V1 = _srb_vertex_at( srb, t[0] );
00485 V2 = _srb_vertex_at( srb, t[1] );
00486 V3 = _srb_vertex_at( srb, t[2] );
00487
00488 if( NULL == ( E1 = _srb_edge_new_unique( srb, V1, V2 ) ) ||
00489 NULL == ( E2 = _srb_edge_new_unique( srb, V2, V3 ) ) ||
00490 NULL == ( E3 = _srb_edge_new_unique( srb, V3, V1 ) ) )
00491 return 0;
00492
00493 if( NULL == ( T = _srb_triangle_new( srb, E1, E2, E3, V1, V2, V3 ) ) )
00494 return 0;
00495
00496 _srb_edge_set_triangle( E1, T );
00497 _srb_edge_set_triangle( E2, T );
00498 _srb_edge_set_triangle( E3, T );
00499 }
00500
00501 return 1;
00502 }
00503
00504
00505 static _srb_finalize( SRB *srb )
00506 {
00507 SRBVERTEX *V;
00508 SRBEDGE *E;
00509 SRBTRIANGLE *T;
00510 void *next;
00511
00512
00513 V = srb->vertices->next;
00514
00515 while( NULL != V )
00516 {
00517 next = V->next;
00518 free( V );
00519 V = next;
00520 }
00521
00522 E = srb->edges->next;
00523
00524 while( NULL != E )
00525 {
00526 next = E->next;
00527 free( E );
00528 E = next;
00529 }
00530
00531 T = srb->triangles->next;
00532
00533 while( NULL != T )
00534 {
00535 next = T->next;
00536 free( T );
00537 T = next;
00538 }
00539 }
00540
00541
00542 static void _srb_set_midpoint_2d( SRBEDGE *E, SRBVERTEX *V, SRBPARAMS *params )
00543 {
00544 double v1x, v1y, v1z, v2x, v2y, v2z;
00545 double m;
00546
00547
00548
00549
00550 v1x = E->V1->x - params->origin_x;
00551 v1y = E->V1->y - params->origin_y;
00552 v1z = E->V1->z - params->origin_z;
00553
00554 v2x = E->V2->x - params->origin_x;
00555 v2y = E->V2->y - params->origin_y;
00556 v2z = E->V2->z - params->origin_z;
00557
00558
00559
00560 m = sqrt( v1x * v1x + v1y * v1y + v1z * v1z );
00561 v1x /= m;
00562 v1y /= m;
00563 v1z /= m;
00564
00565 m = sqrt( v2x * v2x + v2y * v2y + v2z * v2z );
00566 v2x /= m;
00567 v2y /= m;
00568 v2z /= m;
00569
00570
00571 V->x = v1x + v2x;
00572 V->y = v1y + v2y;
00573 V->z = v1z + v2z;
00574 }
00575
00576
00577 static int _srb_tesselate_2d( SRB *srb, SRBEDGE *E, SRBPARAMS *params )
00578 {
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 if( NULL == E->M )
00600 {
00601 if( NULL == ( E->M = _srb_vertex_new( srb, 0.0, 0.0, 0.0 ) ) )
00602 return 0;
00603
00604 _srb_set_midpoint_2d( E, E->M, params );
00605
00606 if( NULL == ( E->E1 = _srb_edge_new_at_tail( srb, E->V1, E->M ) ) )
00607 return 0;
00608
00609 if( NULL == ( E->E2 = _srb_edge_new_at_tail( srb, E->M, E->V2 ) ) )
00610 return 0;
00611 }
00612
00613 if( NULL != E->O->M )
00614 {
00615
00616
00617
00618 E->E1->O = E->O->E1;
00619 E->O->E1->O = E->E1;
00620
00621 E->E2->O = E->O->E2;
00622 E->O->E2->O = E->E2;
00623 }
00624
00625 return 1;
00626 }
00627
00628
00629 static int _srb_tesselate_3d( SRB *srb, SRBTRIANGLE *T )
00630 {
00631 SRBEDGE *E1, *E2, *E3, *E4, *E5, *E6, *E7, *E8, *E9;
00632 SRBTRIANGLE *T1, *T2, *T3, *T4;
00633 double x, y, z;
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657 if( NULL == T->E1->M )
00658 {
00659 _SRB_EDGE_MIDPOINT( T->E1, x, y, z );
00660
00661 if( NULL == ( T->E1->M = _srb_vertex_new( srb, x, y, z ) ) )
00662 return 0;
00663
00664 if( NULL == ( T->E1->E1 = _srb_edge_new( srb, T->V1, T->E1->M ) ) )
00665 return 0;
00666
00667 if( NULL == ( T->E1->E2 = _srb_edge_new( srb, T->E1->M, T->V2 ) ) )
00668 return 0;
00669
00670 E1 = T->E1->E1;
00671 E4 = T->E1->E2;
00672 }
00673 else
00674 {
00675 _SRB_EDGE_FIND_CHILD( T->E1, T->V1, T->E1->M, E1 );
00676 _SRB_EDGE_FIND_CHILD( T->E1, T->E1->M, T->V2, E4 );
00677 }
00678
00679 if( NULL == T->E2->M )
00680 {
00681 _SRB_EDGE_MIDPOINT( T->E2, x, y, z );
00682
00683 if( NULL == ( T->E2->M = _srb_vertex_new( srb, x, y, z ) ) )
00684 return 0;
00685
00686 if( NULL == ( T->E2->E1 = _srb_edge_new( srb, T->V2, T->E2->M ) ) )
00687 return 0;
00688
00689 if( NULL == ( T->E2->E2 = _srb_edge_new( srb, T->E2->M, T->V3 ) ) )
00690 return 0;
00691
00692 E5 = T->E2->E1;
00693 E8 = T->E2->E2;
00694 }
00695 else
00696 {
00697 _SRB_EDGE_FIND_CHILD( T->E2, T->V2, T->E2->M, E5 );
00698 _SRB_EDGE_FIND_CHILD( T->E2, T->E2->M, T->V3, E8 );
00699 }
00700
00701 if( NULL == T->E3->M )
00702 {
00703 _SRB_EDGE_MIDPOINT( T->E3, x, y, z );
00704
00705 if( NULL == ( T->E3->M = _srb_vertex_new( srb, x, y, z ) ) )
00706 return 0;
00707
00708 if( NULL == ( T->E3->E1 = _srb_edge_new( srb, T->V3, T->E3->M ) ) )
00709 return 0;
00710
00711 if( NULL == ( T->E3->E2 = _srb_edge_new( srb, T->E3->M, T->V1 ) ) )
00712 return 0;
00713
00714 E9 = T->E3->E1;
00715 E3 = T->E3->E2;
00716 }
00717 else
00718 {
00719 _SRB_EDGE_FIND_CHILD( T->E3, T->V3, T->E3->M, E9 );
00720 _SRB_EDGE_FIND_CHILD( T->E3, T->E3->M, T->V1, E3 );
00721 }
00722
00723
00724 if( NULL == ( E6 = _srb_edge_new( srb, T->E1->M, T->E2->M ) ) )
00725 return 0;
00726
00727 if( NULL == ( E7 = _srb_edge_new( srb, T->E2->M, T->E3->M ) ) )
00728 return 0;
00729
00730 if( NULL == ( E2 = _srb_edge_new( srb, T->E3->M, T->E1->M ) ) )
00731 return 0;
00732
00733
00734 if( NULL == ( T1 = _srb_triangle_new( srb, E1, E2, E3, T->V1, T->E1->M, T->E3->M ) ) )
00735 return 0;
00736
00737 if( NULL == ( T2 = _srb_triangle_new( srb, E4, E5, E6, T->E1->M, T->V2, T->E2->M ) ) )
00738 return 0;
00739
00740 if( NULL == ( T3 = _srb_triangle_new( srb, E7, E8, E9, T->E3->M, T->E2->M, T->V3 ) ) )
00741 return 0;
00742
00743 if( NULL == ( T4 = _srb_triangle_new( srb, E6, E7, E2, T->E1->M, T->E2->M, T->E3->M ) ) )
00744 return 0;
00745
00746 _srb_edge_set_triangle( E1, T1 );
00747 _srb_edge_set_triangle( E2, T1 );
00748 _srb_edge_set_triangle( E2, T4 );
00749 _srb_edge_set_triangle( E3, T1 );
00750
00751 _srb_edge_set_triangle( E4, T2 );
00752 _srb_edge_set_triangle( E5, T2 );
00753 _srb_edge_set_triangle( E6, T2 );
00754 _srb_edge_set_triangle( E6, T4 );
00755
00756 _srb_edge_set_triangle( E7, T3 );
00757 _srb_edge_set_triangle( E7, T4 );
00758 _srb_edge_set_triangle( E8, T3 );
00759 _srb_edge_set_triangle( E9, T3 );
00760
00761 return 1;
00762 }
00763
00764
00765 static void _srb_mesh_delete( SRBMESH *mesh )
00766 {
00767 free( mesh->vertices );
00768 free( mesh->triangles );
00769 free( mesh );
00770 }
00771
00772
00773 static SRBMESH* _srb_mesh_new( int vertex_count, int triangle_count )
00774 {
00775 SRBMESH *mesh;
00776
00777 if( NULL == ( mesh = malloc( sizeof( SRBMESH ) ) ) )
00778 return NULL;
00779
00780 mesh->vertices = malloc( sizeof( double ) * 3 * vertex_count );
00781 mesh->triangles = malloc( sizeof( int ) * 3 * triangle_count );
00782
00783 if( NULL == mesh->vertices || NULL == mesh->triangles )
00784 {
00785 _srb_mesh_delete( mesh );
00786 return NULL;
00787 }
00788
00789 mesh->vertex_count = vertex_count;
00790 mesh->triangle_count = triangle_count;
00791
00792 mesh->volume = 0.0;
00793 mesh->surface_area = 0.0;
00794
00795 return mesh;
00796 }
00797
00798
00799 static void _srb_fan_delete( SRBFAN *fan )
00800 {
00801 free( fan->vertices );
00802 free( fan );
00803 }
00804
00805
00806 static SRBFAN* _srb_fan_new( int vertex_count )
00807 {
00808 SRBFAN *fan;
00809
00810 if( NULL == ( fan = malloc( sizeof( SRBFAN ) ) ) )
00811 return NULL;
00812
00813 fan->vertices = malloc( sizeof( double ) * 3 * vertex_count );
00814
00815 if( NULL == fan->vertices )
00816 {
00817 _srb_fan_delete( fan );
00818 return NULL;
00819 }
00820
00821 fan->vertex_count = vertex_count;
00822
00823 fan->diameter = 0.0;
00824 fan->area = 0.0;
00825
00826 return fan;
00827 }
00828
00829
00830 static void _srb_pyramid_face_area( SRBPYRAMID *triangle )
00831 {
00832 double nx, ny, nz;
00833 double oax, oay, oaz;
00834 double obx, oby, obz;
00835
00836
00837
00838 oax = triangle->ax - triangle->ox;
00839 oay = triangle->ay - triangle->oy;
00840 oaz = triangle->az - triangle->oz;
00841
00842 obx = triangle->bx - triangle->ox;
00843 oby = triangle->by - triangle->oy;
00844 obz = triangle->bz - triangle->oz;
00845
00846
00847 nx = oay * obz - oby * oaz;
00848 ny = oaz * obx - oax * obz;
00849 nz = oax * oby - obx * oay;
00850
00851
00852 triangle->face_area = 0.5 * sqrt( nx * nx + ny * ny + nz * nz );
00853 }
00854
00855
00856 static void _srb_pyramid_volume_and_surface_area( SRBPYRAMID *pyramid )
00857 {
00858 double nx, ny, nz;
00859 double acx, acy, acz;
00860 double abx, aby, abz;
00861 double aox, aoy, aoz;
00862
00863
00864
00865 acx = pyramid->cx - pyramid->ax;
00866 acy = pyramid->cy - pyramid->ay;
00867 acz = pyramid->cz - pyramid->az;
00868
00869 abx = pyramid->bx - pyramid->ax;
00870 aby = pyramid->by - pyramid->ay;
00871 abz = pyramid->bz - pyramid->az;
00872
00873
00874 nx = acy * abz - aby * acz;
00875 ny = abx * acz - acx * abz;
00876 nz = acx * aby - abx * acy;
00877
00878
00879 aox = pyramid->ox - pyramid->ax;
00880 aoy = pyramid->oy - pyramid->ay;
00881 aoz = pyramid->oz - pyramid->az;
00882
00883
00884 pyramid->face_area = 0.5 * sqrt( nx * nx + ny * ny + nz * nz );
00885
00886
00887 pyramid->volume = ( 1.0 / 6.0 ) * ( aox * nx + aoy * ny + aoz * nz );
00888
00889
00890
00891 if( pyramid->volume < 0.0 )
00892 pyramid->volume = -pyramid->volume;
00893 }
00894
00895
00896 static SRBMESH* _srb_to_mesh( SRB *srb, SRBPARAMS *params )
00897 {
00898 SRBMESH *mesh;
00899 SRBVERTEX *V;
00900 SRBTRIANGLE *T;
00901 int vertex_count;
00902 int triangle_count;
00903 double *v;
00904 int *t;
00905 int i;
00906 SRBPYRAMID P;
00907
00908
00909 vertex_count = 0;
00910 V = srb->vertices->next;
00911
00912 while( NULL != V )
00913 {
00914
00915 V->x = V->x * params->voxel_width;
00916 V->y = V->y * params->voxel_height;
00917 V->z = V->z * params->voxel_length;
00918
00919 V->index = vertex_count++;
00920 V = V->next;
00921 }
00922
00923 triangle_count = 0;
00924 T = srb->triangles->next;
00925
00926 while( NULL != T )
00927 {
00928 if( T->iteration == srb->iteration )
00929 ++triangle_count;
00930
00931 T = T->next;
00932 }
00933
00934 if( NULL == ( mesh = _srb_mesh_new( vertex_count, triangle_count ) ) )
00935 return NULL;
00936
00937 V = srb->vertices->next;
00938
00939 while( NULL != V )
00940 {
00941 v = _SRB_VERTEX( mesh->vertices, V->index );
00942
00943 v[0] = V->x;
00944 v[1] = V->y;
00945 v[2] = V->z;
00946
00947 V = V->next;
00948 }
00949
00950
00951 params->origin_x = params->origin_x * params->voxel_width;
00952 params->origin_y = params->origin_y * params->voxel_height;
00953 params->origin_z = params->origin_z * params->voxel_length;
00954
00955 P.ox = params->origin_x;
00956 P.oy = params->origin_y;
00957 P.oz = params->origin_z;
00958
00959 i = 0;
00960 T = srb->triangles->next;
00961
00962 while( NULL != T )
00963 {
00964 if( T->iteration == srb->iteration )
00965 {
00966 t = _SRB_TRIANGLE( mesh->triangles, i );
00967 ++i;
00968
00969 t[0] = T->V1->index;
00970 t[1] = T->V2->index;
00971 t[2] = T->V3->index;
00972
00973 P.ax = T->V1->x;
00974 P.ay = T->V1->y;
00975 P.az = T->V1->z;
00976 P.bx = T->V2->x;
00977 P.by = T->V2->y;
00978 P.bz = T->V2->z;
00979 P.cx = T->V3->x;
00980 P.cy = T->V3->y;
00981 P.cz = T->V3->z;
00982
00983 _srb_pyramid_volume_and_surface_area( &P );
00984
00985 mesh->volume += P.volume;
00986 mesh->surface_area += P.face_area;
00987 }
00988
00989 T = T->next;
00990 }
00991
00992 return mesh;
00993 }
00994
00995
00996 static SRBFAN* _srb_to_fan( SRB *srb, SRBPARAMS *params )
00997 {
00998 SRBFAN *fan;
00999 SRBVERTEX *V;
01000 SRBEDGE *E;
01001 SRBVERTEX *D1, *D2;
01002 int vertex_count;
01003 double *v;
01004 int i;
01005 SRBPYRAMID P;
01006 double min_diameter;
01007 double diameter;
01008
01009
01010 vertex_count = 0;
01011 V = srb->vertices->next;
01012
01013 while( NULL != V )
01014 {
01015
01016 V->x = V->x * params->voxel_width;
01017 V->y = V->y * params->voxel_height;
01018 V->z = V->z * params->voxel_length;
01019
01020 ++vertex_count;
01021 V = V->next;
01022 }
01023
01024 if( NULL == ( fan = _srb_fan_new( vertex_count ) ) )
01025 return NULL;
01026
01027
01028 params->origin_x = params->origin_x * params->voxel_width;
01029 params->origin_y = params->origin_y * params->voxel_height;
01030 params->origin_z = params->origin_z * params->voxel_length;
01031
01032
01033
01034
01035 i = 0;
01036 E = srb->edges->next;
01037
01038 min_diameter = -1.0;
01039
01040 while( NULL != E )
01041 {
01042 if( E->iteration == srb->iteration )
01043 {
01044 v = _SRB_VERTEX( fan->vertices, i );
01045
01046 v[0] = E->V1->x;
01047 v[1] = E->V1->y;
01048 v[2] = E->V1->z;
01049
01050 E->V1->index = i;
01051
01052
01053 diameter = _SRB_DISTANCE_SQUARED(
01054 E->V1->x,
01055 E->V1->y,
01056 E->V1->z,
01057 E->O->V2->x,
01058 E->O->V2->y,
01059 E->O->V2->z
01060 );
01061
01062 if( min_diameter < 0.0 || diameter < min_diameter )
01063 {
01064 min_diameter = diameter;
01065
01066 D1 = E->V1;
01067 D2 = E->O->V2;
01068 }
01069
01070 ++i;
01071 }
01072
01073 E = E->next;
01074 }
01075
01076 fan->diameter = sqrt( min_diameter );
01077
01078 P.ox = params->origin_x;
01079 P.oy = params->origin_y;
01080 P.oz = params->origin_z;
01081
01082 E = srb->edges->next;
01083
01084 while( NULL != E )
01085 {
01086 if( E->iteration == srb->iteration )
01087 {
01088 P.ax = E->V1->x;
01089 P.ay = E->V1->y;
01090 P.az = E->V1->z;
01091 P.bx = E->V2->x;
01092 P.by = E->V2->y;
01093 P.bz = E->V2->z;
01094
01095 _srb_pyramid_face_area( &P );
01096
01097 fan->area += P.face_area;
01098 }
01099
01100 E = E->next;
01101 }
01102
01103 return fan;
01104 }
01105
01106
01107 double _srb_interpolate_3d( SRBPARAMS *params, double x, double y, double z )
01108 {
01109 int lox, loy, loz;
01110 double i0, i1, i2, i3, i4, i5, i6, i7;
01111 double i01, i23, i45, i67, i0123, i4567, value;
01112 int imw, imh, iml, imwh;
01113
01114
01115 imw = params->image_width;
01116 imh = params->image_height;
01117 iml = params->image_length;
01118 imwh = imw * imh;
01119
01120
01121 if( x < 0.0 || x > ( imw - 1 ) ||
01122 y < 0.0 || y > ( imh - 1 ) ||
01123 z < 0.0 || z > ( iml - 1 ) )
01124 return 0.0;
01125
01126
01127 lox = ( int )x;
01128 loy = ( int )y;
01129 loz = ( int )z;
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142 i0 = ( double )params->image[ imwh * loz + imw * loy + lox ];
01143 i1 = ( double )params->image[ imwh * ( loz + 1 ) + imw * loy + lox ];
01144 i2 = ( double )params->image[ imwh * loz + imw * ( loy + 1 ) + lox ];
01145 i3 = ( double )params->image[ imwh * ( loz + 1 ) + imw * ( loy + 1 ) + lox ];
01146 i4 = ( double )params->image[ imwh * loz + imw * loy + ( lox + 1 ) ];
01147 i5 = ( double )params->image[ imwh * ( loz + 1 ) + imw * loy + ( lox + 1 ) ];
01148 i6 = ( double )params->image[ imwh * loz + imw * ( loy + 1 ) + ( lox + 1 ) ];
01149 i7 = ( double )params->image[ imwh * ( loz + 1 ) + imw * ( loy + 1 ) + ( lox + 1 ) ];
01150
01151
01152 i01 = ( z - loz ) * ( i1 - i0 ) + i0;
01153 i23 = ( z - loz ) * ( i3 - i2 ) + i2;
01154 i45 = ( z - loz ) * ( i5 - i4 ) + i4;
01155 i67 = ( z - loz ) * ( i7 - i6 ) + i6;
01156
01157
01158 i0123 = ( y - loy ) * ( i23 - i01 ) + i01;
01159 i4567 = ( y - loy ) * ( i67 - i45 ) + i45;
01160
01161
01162 value = ( x - lox ) * ( i4567 - i0123 ) + i0123;
01163
01164
01165 return value;
01166 }
01167
01168
01169 double _srb_interpolate_2d( SRBPARAMS *params, double x, double y, double z, int dir )
01170 {
01171 int lox, loy, loz;
01172 double i0, i1, i2, i3, i4, i5, i6;
01173 double i01, i23, i45, i02, i46, value;
01174 int imw, imh, iml, imwh;
01175
01176
01177 imw = params->image_width;
01178 imh = params->image_height;
01179 iml = params->image_length;
01180 imwh = imw * imh;
01181
01182
01183 if( x < 0.0 || x > ( imw - 1 ) ||
01184 y < 0.0 || y > ( imh - 1 ) ||
01185 z < 0.0 || z > ( iml - 1 ) )
01186 return 0.0;
01187
01188
01189 lox = ( int )x;
01190 loy = ( int )y;
01191 loz = ( int )z;
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203 switch( dir )
01204 {
01205 case 0:
01206
01207 i0 = ( double )params->image[ imwh * loz + imw * loy + lox ];
01208 i1 = ( double )params->image[ imwh * ( loz + 1 ) + imw * loy + lox ];
01209 i2 = ( double )params->image[ imwh * loz + imw * ( loy + 1 ) + lox ];
01210 i3 = ( double )params->image[ imwh * ( loz + 1 ) + imw * ( loy + 1 ) + lox ];
01211
01212
01213 i01 = ( z - loz ) * ( i1 - i0 ) + i0;
01214 i23 = ( z - loz ) * ( i3 - i2 ) + i2;
01215
01216
01217 value = ( y - loy ) * ( i23 - i01 ) + i01;
01218 break;
01219
01220 case 1:
01221
01222 i0 = ( double )params->image[ imwh * loz + imw * loy + lox ];
01223 i1 = ( double )params->image[ imwh * ( loz + 1 ) + imw * loy + lox ];
01224 i4 = ( double )params->image[ imwh * loz + imw * loy + ( lox + 1 ) ];
01225 i5 = ( double )params->image[ imwh * ( loz + 1 ) + imw * loy + ( lox + 1 ) ];
01226
01227
01228 i01 = ( z - loz ) * ( i1 - i0 ) + i0;
01229 i45 = ( z - loz ) * ( i5 - i4 ) + i4;
01230
01231
01232 value = ( x - lox ) * ( i45 - i01 ) + i01;
01233 break;
01234
01235 case 2:
01236
01237 i0 = ( double )params->image[ imwh * loz + imw * loy + lox ];
01238 i2 = ( double )params->image[ imwh * loz + imw * ( loy + 1 ) + lox ];
01239 i4 = ( double )params->image[ imwh * loz + imw * loy + ( lox + 1 ) ];
01240 i6 = ( double )params->image[ imwh * loz + imw * ( loy + 1 ) + ( lox + 1 ) ];
01241
01242
01243 i02 = ( y - loy ) * ( i2 - i0 ) + i0;
01244 i46 = ( y - loy ) * ( i6 - i4 ) + i4;
01245
01246
01247 value = ( x - lox ) * ( i46 - i02 ) + i02;
01248 break;
01249 }
01250
01251
01252 return value;
01253 }
01254
01255
01256 void _srb_cast_ray( SRBRAY *ray, SRBPARAMS *params )
01257 {
01258 double x, y, z, val;
01259 double newx, newy, newz, newval;
01260 double i, j, k, tx, ty, tz, tmin;
01261 int which;
01262
01263
01264
01265 x = ray->ox;
01266 y = ray->oy;
01267 z = ray->oz;
01268
01269
01270 val = _srb_interpolate_3d( params, x, y, z );
01271
01272
01273 if( val < params->threshold )
01274 {
01275 ray->ex = ray->ox;
01276 ray->ey = ray->oy;
01277 ray->ez = ray->oz;
01278
01279 return;
01280 }
01281
01282 while( 1 )
01283 {
01284
01285 i = ( ray->dx < 0.0 ) ? ceil( x - 1.0 ) : floor( x + 1.0 );
01286 j = ( ray->dy < 0.0 ) ? ceil( y - 1.0 ) : floor( y + 1.0 );
01287 k = ( ray->dz < 0.0 ) ? ceil( z - 1.0 ) : floor( z + 1.0 );
01288
01289
01290 tx = ( i - x ) / ray->dx;
01291 ty = ( j - y ) / ray->dy;
01292 tz = ( k - z ) / ray->dz;
01293
01294 which = _SRB_MIN3( tx, ty, tz );
01295
01296
01297 switch( which )
01298 {
01299 case 0: tmin = tx; break;
01300 case 1: tmin = ty; break;
01301 case 2: tmin = tz; break;
01302 }
01303
01304 newx = x + tmin * ray->dx;
01305 newy = y + tmin * ray->dy;
01306 newz = z + tmin * ray->dz;
01307
01308 newval = _srb_interpolate_2d( params, newx, newy, newz, which );
01309
01310
01311 if( newval < params->threshold )
01312 {
01313 ray->ex = ( params->threshold - val ) * ( newx - x ) / ( newval - val ) + x;
01314 ray->ey = ( params->threshold - val ) * ( newy - y ) / ( newval - val ) + y;
01315 ray->ez = ( params->threshold - val ) * ( newz - z ) / ( newval - val ) + z;
01316
01317 return;
01318 }
01319
01320
01321 x = newx;
01322 y = newy;
01323 z = newz;
01324 val = newval;
01325 }
01326 }
01327
01328
01329 static void _srb_initial_cast( SRB *srb, SRBPARAMS *params )
01330 {
01331 SRBVERTEX *V;
01332 SRBRAY R;
01333
01334
01335 R.ox = params->origin_x;
01336 R.oy = params->origin_y;
01337 R.oz = params->origin_z;
01338
01339 V = srb->vertices->next;
01340
01341 while( NULL != V )
01342 {
01343
01344
01345 R.dx = V->x;
01346 R.dy = V->y;
01347 R.dz = V->z;
01348
01349 _srb_cast_ray( &R, params );
01350
01351 V->x = R.ex;
01352 V->y = R.ey;
01353 V->z = R.ez;
01354
01355 V = V->next;
01356 }
01357 }
01358
01359
01360 static int _srb_cast_2d( SRB *srb, SRBPARAMS *params )
01361 {
01362 SRBEDGE *E;
01363 SRBRAY R;
01364
01365
01366 ++(srb->iteration);
01367 srb->tail = NULL;
01368
01369
01370
01371 E = srb->edges->next;
01372
01373 while( NULL != E )
01374 {
01375 if( E->iteration == srb->iteration - 1 )
01376 if( ! _srb_tesselate_2d( srb, E, params ) )
01377 return 0;
01378
01379 E = E->next;
01380 }
01381
01382
01383
01384 R.ox = params->origin_x;
01385 R.oy = params->origin_y;
01386 R.oz = params->origin_z;
01387
01388 E = srb->edges->next;
01389
01390 while( NULL != E )
01391 {
01392 if( E->iteration == srb->iteration - 1 )
01393 {
01394
01395 R.dx = E->M->x;
01396 R.dy = E->M->y;
01397 R.dz = E->M->z;
01398
01399 _srb_cast_ray( &R, params );
01400
01401 E->M->x = R.ex;
01402 E->M->y = R.ey;
01403 E->M->z = R.ez;
01404 }
01405
01406 E = E->next;
01407 }
01408
01409 return 1;
01410 }
01411
01412
01413 static int _srb_cast_3d( SRB *srb, SRBPARAMS *params )
01414 {
01415 SRBTRIANGLE *T;
01416 SRBEDGE *E;
01417 SRBRAY R;
01418
01419
01420 ++(srb->iteration);
01421
01422
01423
01424 T = srb->triangles->next;
01425
01426 while( NULL != T )
01427 {
01428 if( T->iteration == srb->iteration - 1 )
01429 if( ! _srb_tesselate_3d( srb, T ) )
01430 return 0;
01431
01432 T = T->next;
01433 }
01434
01435
01436
01437 R.ox = params->origin_x;
01438 R.oy = params->origin_y;
01439 R.oz = params->origin_z;
01440
01441 E = srb->edges->next;
01442
01443 while( NULL != E )
01444 {
01445 if( E->iteration == srb->iteration - 1 )
01446 {
01447
01448 R.dx = E->M->x - R.ox;
01449 R.dy = E->M->y - R.oy;
01450 R.dz = E->M->z - R.oz;
01451
01452 _srb_cast_ray( &R, params );
01453
01454 E->M->x = R.ex;
01455 E->M->y = R.ey;
01456 E->M->z = R.ez;
01457 }
01458
01459 E = E->next;
01460 }
01461
01462 return 1;
01463 }
01464
01465
01466 static void _srb_tolerance_cast
01467 (
01468 SRB *srb,
01469 SRBPARAMS *params,
01470 double x,
01471 double y,
01472 double z,
01473 double *sum_dm,
01474 double *sum_dc_minus_dm
01475 )
01476 {
01477 SRBRAY R;
01478 double dc, dm, dc_minus_dm;
01479
01480
01481 R.ox = params->origin_x;
01482 R.oy = params->origin_y;
01483 R.oz = params->origin_z;
01484
01485
01486 dm = sqrt( _SRB_DISTANCE_SQUARED( R.ox, R.oy, R.oz, x, y, z ) );
01487
01488 R.dx = x - R.ox;
01489 R.dy = y - R.oy;
01490 R.dz = z - R.oz;
01491
01492 _srb_cast_ray( &R, params );
01493
01494
01495 dc = sqrt( _SRB_DISTANCE_SQUARED( R.ox, R.oy, R.oz, R.ex, R.ey, R.ez ) );
01496
01497 (*sum_dm) += dm;
01498
01499 dc_minus_dm = dc - dm;
01500
01501 if( dc_minus_dm < 0.0 )
01502 dc_minus_dm = -dc_minus_dm;
01503
01504 (*sum_dc_minus_dm) += dc_minus_dm;
01505 }
01506
01507
01508 static int _srb_has_converged
01509 (
01510 SRB *srb,
01511 SRBPARAMS *params,
01512 double sum_dm,
01513 double sum_dc_minus_dm
01514 )
01515 {
01516 double f = ( sum_dc_minus_dm / sum_dm ) * 100.0;
01517
01518 if( f < 0.0 )
01519 f = -f;
01520
01521 return f <= params->fit_percent;
01522 }
01523
01524
01525 static int _srb_has_converged_3d( SRB *srb, SRBPARAMS *params )
01526 {
01527 SRBTRIANGLE *T;
01528 double x, y, z;
01529 double sum_dm, sum_dc_minus_dm;
01530
01531
01532 sum_dm = sum_dc_minus_dm = 0.0;
01533
01534 T = srb->triangles->next;
01535
01536 while( NULL != T )
01537 {
01538 if( T->iteration == srb->iteration )
01539 {
01540 _SRB_TRIANGLE_CENTER( T, x, y, z );
01541 _srb_tolerance_cast( srb, params, x, y, z, &sum_dm, &sum_dc_minus_dm );
01542 }
01543
01544 T = T->next;
01545 }
01546
01547 return _srb_has_converged( srb, params, sum_dm, sum_dc_minus_dm );
01548 }
01549
01550
01551 static int _srb_has_converged_2d( SRB *srb, SRBPARAMS *params )
01552 {
01553 SRBEDGE *E;
01554 double x, y, z;
01555 double sum_dm, sum_dc_minus_dm;
01556
01557
01558 sum_dm = sum_dc_minus_dm = 0.0;
01559
01560 E = srb->edges->next;
01561
01562 while( NULL != E )
01563 {
01564 if( E->iteration == srb->iteration )
01565 {
01566 _SRB_EDGE_MIDPOINT( E, x, y, z );
01567 _srb_tolerance_cast( srb, params, x, y, z, &sum_dm, &sum_dc_minus_dm );
01568 }
01569
01570 E = E->next;
01571 }
01572
01573 return _srb_has_converged( srb, params, sum_dm, sum_dc_minus_dm );
01574 }
01575
01576
01577 static double ____srb_octahedron_vertices[ 6 * 3 ] =
01578 {
01579 1.0, 0.0, 0.0,
01580 0.0, 1.0, 0.0,
01581 -1.0, 0.0, 0.0,
01582 0.0, -1.0, 0.0,
01583 0.0, 0.0, 1.0,
01584 0.0, 0.0, -1.0
01585 };
01586
01587
01588
01589 static int ____srb_octahedron_triangles[ 8 * 3 ] =
01590 {
01591 0, 1, 4,
01592 1, 2, 4,
01593 2, 3, 4,
01594 3, 0, 4,
01595 1, 0, 5,
01596 2, 1, 5,
01597 3, 2, 5,
01598 0, 3, 5
01599 };
01600
01601
01602 SRBMESH* srb_run_3d( SRBPARAMS *params )
01603 {
01604 SRB srb;
01605 SRBMESH *mesh;
01606 int i;
01607
01608
01609 if( ! _srb_init_3d(
01610 &srb,
01611 params,
01612 ____srb_octahedron_vertices,
01613 _SRB_ARRAY_LENGTH( ____srb_octahedron_vertices ) / 3,
01614 ____srb_octahedron_triangles,
01615 _SRB_ARRAY_LENGTH( ____srb_octahedron_triangles ) / 3
01616 ) )
01617 {
01618 _srb_finalize( &srb );
01619 return NULL;
01620 }
01621
01622 _srb_initial_cast( &srb, params );
01623
01624 for( i = 1; i <= params->max_iterations; ++i )
01625 {
01626 if( ! _srb_cast_3d( &srb, params ) )
01627 {
01628 _srb_finalize( &srb );
01629 return NULL;
01630 }
01631
01632 if( _srb_has_converged_3d( &srb, params ) )
01633 break;
01634 }
01635
01636 mesh = _srb_to_mesh( &srb, params );
01637 _srb_finalize( &srb );
01638
01639 return mesh;
01640 }
01641
01642
01643
01644
01645 static double ____srb_quadrilateral_vertices[ 4 * 3 ] =
01646 {
01647 1.0, 0.0, 0.0,
01648 0.0, 1.0, 0.0,
01649 -1.0, 0.0, 0.0,
01650 0.0, -1.0, 0.0
01651 };
01652
01653
01654 SRBFAN* srb_run_2d( SRBPARAMS *params )
01655 {
01656 SRB srb;
01657 SRBFAN *fan;
01658 int i;
01659
01660
01661 if( ! _srb_init_2d(
01662 &srb,
01663 params,
01664 ____srb_quadrilateral_vertices,
01665 _SRB_ARRAY_LENGTH( ____srb_quadrilateral_vertices ) / 3
01666 ) )
01667 {
01668 _srb_finalize( &srb );
01669 return NULL;
01670 }
01671
01672 _srb_initial_cast( &srb, params );
01673
01674 for( i = 1; i <= params->max_iterations; ++i )
01675 {
01676 if( ! _srb_cast_2d( &srb, params ) )
01677 {
01678 _srb_finalize( &srb );
01679 return NULL;
01680 }
01681
01682 if( _srb_has_converged_2d( &srb, params ) )
01683 break;
01684 }
01685
01686 fan = _srb_to_fan( &srb, params );
01687 _srb_finalize( &srb );
01688
01689 return fan;
01690 }
01691
01692
01693 void srb_mesh_destroy( SRBMESH *mesh )
01694 { _srb_mesh_delete( mesh ); }
01695
01696
01697 void srb_fan_destroy( SRBFAN *fan )
01698 { _srb_fan_delete( fan ); }