Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

polygons.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- 00002 @COPYRIGHT : 00003 Copyright 1993,1994,1995 David MacDonald, 00004 McConnell Brain Imaging Centre, 00005 Montreal Neurological Institute, McGill University. 00006 Permission to use, copy, modify, and distribute this 00007 software and its documentation for any purpose and without 00008 fee is hereby granted, provided that the above copyright 00009 notice appear in all copies. The author and McGill University 00010 make no representations about the suitability of this 00011 software for any purpose. It is provided "as is" without 00012 express or implied warranty. 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 /* ----------------------------- MNI Header ----------------------------------- 00050 @NAME : initialize_polygons 00051 @INPUT : col 00052 spr : optional 00053 @OUTPUT : polygons 00054 @RETURNS : 00055 @DESCRIPTION: Initializes the polygons to an empty set. 00056 @METHOD : 00057 @GLOBALS : 00058 @CALLS : 00059 @CREATED : 1993 David MacDonald 00060 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00146 @NAME : free_polygon_neighbours 00147 @INPUT : polygons 00148 @OUTPUT : 00149 @RETURNS : 00150 @DESCRIPTION: Deletes the polygon neighbours. 00151 @METHOD : 00152 @GLOBALS : 00153 @CALLS : 00154 @CREATED : 1993 David MacDonald 00155 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00169 @NAME : delete_polygons 00170 @INPUT : polygons 00171 @OUTPUT : 00172 @RETURNS : 00173 @DESCRIPTION: Deletes the polygons. 00174 @METHOD : 00175 @GLOBALS : 00176 @CALLS : 00177 @CREATED : 1993 David MacDonald 00178 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00209 @NAME : copy_polygons 00210 @INPUT : src 00211 @OUTPUT : dest 00212 @RETURNS : 00213 @DESCRIPTION: Copies the polygons. 00214 @METHOD : 00215 @GLOBALS : 00216 @CALLS : 00217 @CREATED : 1993 David MacDonald 00218 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00263 @NAME : set_polygon_per_item_colours 00264 @INPUT : polygons 00265 @OUTPUT : 00266 @RETURNS : 00267 @DESCRIPTION: Sets the polygons to per polygon colours. 00268 @METHOD : 00269 @GLOBALS : 00270 @CALLS : 00271 @CREATED : 1993 David MacDonald 00272 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00294 @NAME : create_polygons_visibilities 00295 @INPUT : polygons 00296 @OUTPUT : 00297 @RETURNS : 00298 @DESCRIPTION: Allocates a visibility flag for each polygon. 00299 @METHOD : 00300 @GLOBALS : 00301 @CALLS : 00302 @CREATED : 1993 David MacDonald 00303 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00322 @NAME : set_polygons_visibilities 00323 @INPUT : polygons 00324 state 00325 @OUTPUT : 00326 @RETURNS : 00327 @DESCRIPTION: Sets visibilities of all polygons to the state. 00328 @METHOD : 00329 @GLOBALS : 00330 @CALLS : 00331 @CREATED : 1993 David MacDonald 00332 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00349 @NAME : start_new_polygon 00350 @INPUT : polygons 00351 @OUTPUT : 00352 @RETURNS : 00353 @DESCRIPTION: Starts a new polygon in the structure, with size zero. 00354 @METHOD : 00355 @GLOBALS : 00356 @CALLS : 00357 @CREATED : 1993 David MacDonald 00358 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00373 @NAME : add_point_to_polygon 00374 @INPUT : polygons 00375 point 00376 normal 00377 @OUTPUT : 00378 @RETURNS : 00379 @DESCRIPTION: Adds the given point and normal to the last polygon. 00380 @METHOD : 00381 @GLOBALS : 00382 @CALLS : 00383 @CREATED : 1993 David MacDonald 00384 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00423 @NAME : get_polygon_points 00424 @INPUT : polygons 00425 poly 00426 @OUTPUT : points 00427 @RETURNS : number points 00428 @DESCRIPTION: Passes back the points of the specified poly. 00429 @METHOD : 00430 @GLOBALS : 00431 @CALLS : 00432 @CREATED : 1993 David MacDonald 00433 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00455 @NAME : get_polygon_centroid 00456 @INPUT : polygons 00457 poly 00458 @OUTPUT : centroid 00459 @RETURNS : 00460 @DESCRIPTION: Passes back the centroid of the specified poly. 00461 @METHOD : 00462 @GLOBALS : 00463 @CALLS : 00464 @CREATED : 1993 David MacDonald 00465 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00492 @NAME : find_vertex_index 00493 @INPUT : polygons 00494 poly 00495 point_index 00496 @OUTPUT : 00497 @RETURNS : index in poly of the point 00498 @DESCRIPTION: Finds which vertex index of the poly corresponds to the 00499 point_index. 00500 @METHOD : 00501 @GLOBALS : 00502 @CALLS : 00503 @CREATED : 1993 David MacDonald 00504 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00533 @NAME : find_edge_index 00534 @INPUT : polygons 00535 poly 00536 point_index1 00537 point_index2 00538 @OUTPUT : 00539 @RETURNS : edge index 00540 @DESCRIPTION: Finds the index of the edge in the poly between the two points. 00541 @METHOD : 00542 @GLOBALS : 00543 @CALLS : 00544 @CREATED : 1993 David MacDonald 00545 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00579 @NAME : find_polygon_with_edge 00580 @INPUT : polygons 00581 point_index1 00582 point_index2 00583 @OUTPUT : poly_containing_edge 00584 edge_index 00585 @RETURNS : TRUE if found 00586 @DESCRIPTION: Finds a polygon containing the given edge. 00587 @METHOD : 00588 @GLOBALS : 00589 @CALLS : 00590 @CREATED : 1993 David MacDonald 00591 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00619 @NAME : find_polygon_with_vertex 00620 @INPUT : polygons 00621 point_index 00622 @OUTPUT : poly_index 00623 vertex_index 00624 @RETURNS : TRUE if found 00625 @DESCRIPTION: Searches for a polygon containing the point. 00626 @METHOD : 00627 @GLOBALS : 00628 @CALLS : 00629 @CREATED : 1993 David MacDonald 00630 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00664 @NAME : lookup_polygon_vertex 00665 @INPUT : polygons 00666 point 00667 @OUTPUT : point_index 00668 @RETURNS : TRUE if successful 00669 @DESCRIPTION: Finds the point index of a given point. 00670 @METHOD : 00671 @GLOBALS : 00672 @CALLS : 00673 @CREATED : 1993 David MacDonald 00674 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00697 @NAME : find_next_edge_around_point 00698 @INPUT : polygons 00699 poly 00700 index_1 00701 index_2 00702 @OUTPUT : next_poly 00703 next_index_1 00704 next_index_2 00705 @RETURNS : TRUE if found 00706 @DESCRIPTION: Given a polygon and two vertex indices within the poly, 00707 corresponding to an edge, finds the neighbouring poly, and 00708 the two vertex indices corresponding to the next 00709 edge around the point corresponding to poly,index_1. 00710 @METHOD : 00711 @GLOBALS : 00712 @CALLS : 00713 @CREATED : 1993 David MacDonald 00714 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00764 @NAME : get_neighbours_of_point 00765 @INPUT : polygons 00766 poly 00767 vertex_index 00768 max_neighbours - max storage 00769 @OUTPUT : neighbours 00770 interior_point 00771 @RETURNS : number of neighbours 00772 @DESCRIPTION: Gets the points which are the neighbours of the specified point. 00773 interior_point is set to true if the point is totally 00774 surrounded by polygons. 00775 @METHOD : 00776 @GLOBALS : 00777 @CALLS : 00778 @CREATED : 1993 David MacDonald 00779 @MODIFIED : Sept. 12, 1996 D. MacDonald : fixed it for the case where not 00780 a closed surface. 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 &current_poly, &current_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 &current_poly, &current_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 /* ----------------------------- MNI Header ----------------------------------- 00882 @NAME : get_polygons_around_vertex 00883 @INPUT : polygons 00884 poly 00885 vertex_index 00886 n_polys_alloced - max space for poly_indices 00887 @OUTPUT : poly_indices 00888 closed_flag 00889 @RETURNS : number of polygons 00890 @DESCRIPTION: Returns a list of polygons, in order, around the vertex. If 00891 the vertex is surrounded by polygons, closed_flag will be set 00892 to true. 00893 @METHOD : 00894 @GLOBALS : 00895 @CALLS : 00896 @CREATED : 1993 David MacDonald 00897 @MODIFIED : 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 &current_poly, &current_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 /* ----------------------------- MNI Header ----------------------------------- 00955 @NAME : compute_polygon_normal 00956 @INPUT : polygons 00957 poly 00958 @OUTPUT : normal 00959 @RETURNS : 00960 @DESCRIPTION: Computes the polygon normal. 00961 Vertices after the 1000th are silently ignored. 00962 @METHOD : 00963 @GLOBALS : 00964 @CALLS : 00965 @CREATED : 1993 David MacDonald 00966 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 00994 @NAME : compute_polygon_normals 00995 @INPUT : polygons 00996 @OUTPUT : polygons 00997 @RETURNS : 00998 @DESCRIPTION: Computes the normals at the vertices of the polygons. Each is 00999 the average of the normals of the polygonal faces 01000 touching the vertex, weighted by the interior angle of the 01001 polygon at the vertex. 01002 @METHOD : 01003 @GLOBALS : 01004 @CALLS : 01005 @CREATED : 1993 David MacDonald 01006 @MODIFIED : 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 /*--- weight this contribution by the size of the angle around 01045 the vertex */ 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 /* ----------------------------- MNI Header ----------------------------------- 01075 @NAME : average_polygon_normals 01076 @INPUT : polygons 01077 n_iters 01078 neighbour_weight 01079 @OUTPUT : 01080 @RETURNS : 01081 @DESCRIPTION: Averages the normals of the polygons by iteratively setting each 01082 normal to some interpolation between its current value and the 01083 average of its neighbours. The interpolation is controlled by 01084 neighbour_weight which should be between 0 and 1. 01085 @METHOD : 01086 @GLOBALS : 01087 @CALLS : 01088 @CREATED : 1993 David MacDonald 01089 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 01179 @NAME : get_plane_polygon_intersection 01180 @INPUT : normal 01181 d 01182 polygons 01183 poly 01184 @OUTPUT : intersection_points 01185 @RETURNS : number of intersection points 01186 @DESCRIPTION: Computes the intersection of a plane with a polygon, returning 01187 0 or 2 points, (or more if non-convex polygon). 01188 @METHOD : 01189 @GLOBALS : 01190 @CALLS : 01191 @CREATED : 1993 David MacDonald 01192 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 01229 @NAME : get_plane_segment_intersection 01230 @INPUT : normal 01231 d 01232 p1 01233 p2 01234 @OUTPUT : intersection_point 01235 @RETURNS : TRUE if intersects 01236 @DESCRIPTION: Tests for a plane and segment intersection. 01237 @METHOD : 01238 @GLOBALS : 01239 @CALLS : 01240 @CREATED : 1993 David MacDonald 01241 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 01279 @NAME : reverse_polygons_vertices 01280 @INPUT : polygons 01281 @OUTPUT : 01282 @RETURNS : 01283 @DESCRIPTION: Reverses the order of the polygon vertices. 01284 @METHOD : 01285 @GLOBALS : 01286 @CALLS : 01287 @CREATED : 1993 David MacDonald 01288 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 01304 @NAME : make_polygons_front_facing 01305 @INPUT : polygons 01306 @OUTPUT : 01307 @RETURNS : 01308 @DESCRIPTION: Makes all polygons front facing, based on the normals at the 01309 vertices. 01310 @METHOD : 01311 @GLOBALS : 01312 @CALLS : 01313 @CREATED : 1993 David MacDonald 01314 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 01333 @NAME : polygon_is_back_facing 01334 @INPUT : polygons 01335 poly 01336 @OUTPUT : 01337 @RETURNS : TRUE if polygon is back facing 01338 @DESCRIPTION: Uses the average normal of the polygon vertices to see if the 01339 polygon is back facing. 01340 @METHOD : 01341 @GLOBALS : 01342 @CALLS : 01343 @CREATED : 1993 David MacDonald 01344 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 01372 @NAME : reverse_polygon_order 01373 @INPUT : polygons 01374 poly 01375 @OUTPUT : 01376 @RETURNS : 01377 @DESCRIPTION: Reverses the order of the specified poly. 01378 @METHOD : 01379 @GLOBALS : 01380 @CALLS : 01381 @CREATED : 1993 David MacDonald 01382 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 01404 @NAME : compute_points_centroid_and_normal 01405 @INPUT : polygons 01406 point_index 01407 n_neighbours 01408 neighbours 01409 @OUTPUT : centroid 01410 normal 01411 base_length 01412 curvature 01413 @RETURNS : 01414 @DESCRIPTION: Computes the centroid and normal of the neighbours of a vertex, 01415 as well as a measure of the size of the polygon defined by the 01416 neighbours, and the relative curvature of the surface at the 01417 vertex. 01418 @METHOD : 01419 @GLOBALS : 01420 @CALLS : 01421 @CREATED : 1993 David MacDonald 01422 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 01462 @NAME : compute_points_centroid_and_normal 01463 @INPUT : polygons 01464 poly 01465 vertex_index 01466 point_index 01467 @OUTPUT : centroid 01468 normal 01469 base_length 01470 curvature 01471 @RETURNS : 01472 @DESCRIPTION: Computes the centroid and normal of the neighbours of a vertex, 01473 as well as a measure of the size of the polygon defined by the 01474 neighbours, and the relative curvature of the surface at the 01475 vertex. 01476 @METHOD : 01477 @GLOBALS : 01478 @CALLS : 01479 @CREATED : 1993 David MacDonald 01480 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 01508 @NAME : estimate_polygon_curvature 01509 @INPUT : point 01510 n_neighs 01511 neighs 01512 centroid 01513 normal 01514 @OUTPUT : base_length 01515 @RETURNS : curvature 01516 @DESCRIPTION: Computes the curvature at a vertex of a polygon. 01517 @METHOD : 01518 @GLOBALS : 01519 @CALLS : 01520 @CREATED : 1993 David MacDonald 01521 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 01559 @NAME : compute_polygon_vertex_curvature 01560 @INPUT : polygons 01561 point_index 01562 @OUTPUT : 01563 @RETURNS : curvature 01564 @DESCRIPTION: Computes the curvature of the surface at a specified vertex. 01565 @METHOD : 01566 @GLOBALS : 01567 @CALLS : 01568 @CREATED : 1993 David MacDonald 01569 @MODIFIED : 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 &centroid, &normal, &base_length, 01589 &curvature ); 01590 01591 return( curvature ); 01592 } 01593 01594 /* ----------------------------- MNI Header ----------------------------------- 01595 @NAME : get_opposite_point 01596 @INPUT : polygons 01597 poly 01598 edge 01599 @OUTPUT : point 01600 @RETURNS : 01601 @DESCRIPTION: Gets the point opposite the given edge. 01602 @METHOD : 01603 @GLOBALS : 01604 @CALLS : 01605 @CREATED : 1993 David MacDonald 01606 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 01629 @NAME : get_polygon_edge_angle 01630 @INPUT : polygons 01631 poly 01632 edge 01633 @OUTPUT : 01634 @RETURNS : angle between -PI and PI 01635 @DESCRIPTION: Computes the angle across the edge. 01636 @METHOD : 01637 @GLOBALS : 01638 @CALLS : 01639 @CREATED : 1993 David MacDonald 01640 @MODIFIED : 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 /* ----------------------------- MNI Header ----------------------------------- 01705 @NAME : polygons_are_same_topology 01706 @INPUT : p1 01707 p2 01708 @OUTPUT : 01709 @RETURNS : TRUE if same 01710 @DESCRIPTION: Tests if two polygons are the same topology. 01711 @METHOD : 01712 @GLOBALS : 01713 @CALLS : 01714 @CREATED : 1993 David MacDonald 01715 @MODIFIED : 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

Generated on Wed Jul 28 09:10:57 2004 for BICPL by doxygen 1.3.7