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/geom.h>
00017
#include <bicpl/trans.h>
00018
00019
#ifndef lint
00020
static char rcsid[] =
"$Header: /software/source//libraries/bicpl/Geometry/map_polygons.c,v 1.13 2000/02/06 15:30:15 stever Exp $";
00021
#endif
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 private Real
get_baricentric(
00041 Point *point,
00042 Point *p1,
00043 Point *p2,
00044 Point *p3 )
00045 {
00046 Real weight;
00047 Vector hor, up, normal, vert, point_offset;
00048
00049 SUB_POINTS( point_offset, *point, *p1 );
00050 SUB_POINTS( hor, *p2, *p1 );
00051 SUB_POINTS( up, *p3, *p1 );
00052
00053 CROSS_VECTORS( normal, hor, up );
00054 CROSS_VECTORS( vert, normal, hor );
00055
00056 weight = DOT_VECTORS( point_offset, vert ) / DOT_VECTORS( up, vert );
00057
00058
return( weight );
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 private void get_triangle_interpolation_weights(
00080 Point *point,
00081 Point points[],
00082 Real weights[] )
00083 {
00084 weights[0] =
get_baricentric( point, &points[1], &points[2], &points[0] );
00085 weights[1] =
get_baricentric( point, &points[2], &points[0], &points[1] );
00086 weights[2] =
get_baricentric( point, &points[0], &points[1], &points[2] );
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 private BOOLEAN
intersect_lines_2d(
00107 Real p1[],
00108 Real p2[],
00109 Real q1[],
00110 Real q2[],
00111 Real intersect[] )
00112 {
00113 BOOLEAN intersects;
00114 Real t, bottom;
00115 Real dp[2], dq[2];
00116
00117 dp[0] = p2[0] - p1[0];
00118 dp[1] = p2[1] - p1[1];
00119 dq[0] = q2[0] - q1[0];
00120 dq[1] = q2[1] - q1[1];
00121
00122 bottom = dp[0] * dq[1] - dp[1] * dq[0];
00123
00124
if( bottom == 0.0 )
00125 {
00126 intersects =
FALSE;
00127 }
00128
else
00129 {
00130 t = (dq[0] * (p1[1] - q1[1]) + dq[1] * (q1[0] - p1[0])) / bottom;
00131 intersect[0] = p1[0] + t * (dp[0] - p1[0]);
00132 intersect[1] = p1[1] + t * (dp[1] - p1[1]);
00133 intersects =
TRUE;
00134 }
00135
00136
return( intersects );
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 private Real
get_two_d_coordinate(
00158 Point *p,
00159 Point *p1,
00160 Point *p2,
00161 Point *q1,
00162 Point *q2 )
00163 {
00164 Real coords[4][2], coord[2], intersect[2];
00165 Real intersect_point[2], len2, dx, dy, idx, idy, factor;
00166 Vector cross, offset, hor, vert, v1, v2;
00167
int i, j;
00168 Point points[4];
00169 BOOLEAN found;
00170
00171 points[0] = *p1;
00172 points[1] = *p2;
00173 points[2] = *q2;
00174 points[3] = *q1;
00175
00176 found =
FALSE;
00177 for_less( i, 0, 3 )
00178 {
00179 SUB_POINTS( v1, points[i], points[0] );
00180 for_less( j, i+1, 4 )
00181 {
00182 SUB_POINTS( v2, points[j], points[0] );
00183 CROSS_VECTORS( cross, v1, v2 );
00184
if( !
null_Vector(&cross) )
00185 {
00186 found =
TRUE;
00187
break;
00188 }
00189 }
00190
00191
if( found )
00192
break;
00193 }
00194
00195
if( !found )
00196 print_error(
"get_two_d_coordinate: degenerate polygons\n" );
00197
00198 create_two_orthogonal_vectors( &cross, &hor, &vert );
00199
00200 for_less( i, 0, 4 )
00201 {
00202 SUB_POINTS( offset, points[i], points[0] );
00203 coords[i][0] = DOT_VECTORS( hor, offset );
00204 coords[i][1] = DOT_VECTORS( vert, offset );
00205 }
00206
00207 SUB_POINTS( offset, *p, points[0] );
00208 coord[0] = DOT_VECTORS( hor, offset );
00209 coord[1] = DOT_VECTORS( vert, offset );
00210
00211
if(
intersect_lines_2d( coords[0], coords[1], coords[3], coords[2],
00212 intersect ) )
00213 {
00214
if( !
intersect_lines_2d( intersect, coord, coords[0], coords[3],
00215 intersect_point ) )
00216
return( 0.0 );
00217 }
00218
else
00219 {
00220 intersect_point[0] = coord[0];
00221 intersect_point[1] = coord[1];
00222 }
00223
00224 dx = coords[3][0] - coords[0][0];
00225 dy = coords[3][1] - coords[0][1];
00226
00227 len2 = dx * dx + dy * dy;
00228
00229 idx = intersect_point[0] - coords[0][0];
00230 idy = intersect_point[1] - coords[0][1];
00231
00232 factor = (dx * idx + dy * idy) / len2;
00233
00234
return( factor );
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 private void get_quadrilateral_interpolation_weights(
00253 Point *point,
00254 Point points[],
00255 Real weights[] )
00256 {
00257 Real u, v;
00258
00259 u =
get_two_d_coordinate( point,
00260 &points[0], &points[3], &points[1], &points[2] );
00261 v =
get_two_d_coordinate( point,
00262 &points[0], &points[1], &points[3], &points[2] );
00263
00264 weights[0] = (1.0 - u) * (1.0 - v);
00265 weights[1] = u * (1.0 - v);
00266 weights[2] = u * v;
00267 weights[3] = (1.0 - u) * v;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 private void get_arbitrary_polygon_interpolation_weights(
00285 Point *point,
00286
int n_points,
00287 Point points[],
00288 Real weights[] )
00289 {
00290
int i, j;
00291 Real sum_weights, alpha, dist;
00292
00293 for_less( i, 0, n_points )
00294 weights[i] = 0.0;
00295
00296 sum_weights = 0.0;
00297
00298 for_less( i, 0, n_points )
00299 {
00300 dist =
get_distance_to_line_segment( point,
00301 &points[i], &points[(i+1)%n_points],
00302 &alpha );
00303
00304
if( dist == 0.0 )
00305 {
00306 for_less( j, 0, n_points )
00307 weights[j] = 0.0;
00308 weights[i] = 1.0 - alpha;
00309 weights[(i+1)%n_points] = alpha;
00310 sum_weights = 1.0;
00311
break;
00312 }
00313
00314 weights[i] += (1.0 - alpha) / dist;
00315 weights[(i+1)%n_points] += alpha / dist;
00316
00317 sum_weights += 1.0 / dist;
00318 }
00319
00320 for_less( i, 0, n_points )
00321 weights[i] /= sum_weights;
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 public void get_polygon_interpolation_weights(
00340 Point *point,
00341
int n_points,
00342 Point points[],
00343 Real weights[] )
00344 {
00345
if( n_points == 3 )
00346 {
00347
get_triangle_interpolation_weights( point, points, weights );
00348 }
00349
else if( n_points == 4 )
00350 {
00351
get_quadrilateral_interpolation_weights( point, points, weights );
00352 }
00353
else
00354 {
00355
get_arbitrary_polygon_interpolation_weights( point, n_points,
00356 points, weights );
00357 }
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 public void map_point_between_polygons(
00378
polygons_struct *p1,
00379
int poly_index,
00380 Point *p1_point,
00381
polygons_struct *p2,
00382 Point *p2_point )
00383 {
00384
int i, size;
00385 Point poly1_points[
MAX_POINTS_PER_POLYGON];
00386 Point poly2_points[
MAX_POINTS_PER_POLYGON];
00387 Point scaled_point;
00388 Real weights[
MAX_POINTS_PER_POLYGON];
00389
00390 size =
get_polygon_points( p1, poly_index, poly1_points );
00391
00392
get_polygon_interpolation_weights( p1_point, size, poly1_points, weights );
00393
00394
if(
get_polygon_points( p2, poly_index, poly2_points ) != size )
00395 handle_internal_error(
"map_point_between_polygons" );
00396
00397 fill_Point( *p2_point, 0.0, 0.0, 0.0 );
00398
00399 for_less( i, 0, size )
00400 {
00401 SCALE_POINT( scaled_point, poly2_points[i], weights[i] );
00402 ADD_POINTS( *p2_point, *p2_point, scaled_point );
00403 }
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 public Real
map_point_to_unit_sphere(
00428
polygons_struct *p,
00429 Point *point,
00430
polygons_struct *unit_sphere,
00431 Point *unit_sphere_point )
00432 {
00433 Real mag, dist;
00434 Point poly_point;
00435 Vector offset;
00436
int poly;
00437
00438 poly =
find_closest_polygon_point( point, p, &poly_point );
00439
00440 dist =
distance_between_points( point, &poly_point );
00441
00442
map_point_between_polygons( p, poly, &poly_point, unit_sphere,
00443 unit_sphere_point );
00444
00445 CONVERT_POINT_TO_VECTOR( offset, *unit_sphere_point );
00446
00447 mag = MAGNITUDE( offset );
00448
00449
00450
00451
if( mag != 1.0 )
00452 {
00453 SCALE_POINT( *unit_sphere_point, *unit_sphere_point, 1.0 / mag );
00454 }
00455
00456
return( dist );
00457 }
00458
00459 public void map_unit_sphere_to_point(
00460
polygons_struct *unit_sphere,
00461 Point *unit_sphere_point,
00462
polygons_struct *p,
00463 Point *point )
00464 {
00465 Point poly_point;
00466
int poly;
00467
00468 poly =
find_closest_polygon_point( unit_sphere_point, unit_sphere,
00469 &poly_point );
00470
00471
map_point_between_polygons( unit_sphere, poly, &poly_point, p,
00472 point );
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492 private void polygon_transform_point(
00493
object_struct *src_object,
00494
object_struct *dest_object,
00495 Point *src_point,
00496 Point *dest_point )
00497 {
00498
int obj_index;
00499 Point point;
00500
00501 (
void)
find_closest_point_on_object( src_point, src_object, &obj_index,
00502 &point );
00503
00504
map_point_between_polygons(
get_polygons_ptr(src_object), obj_index,
00505 &point,
get_polygons_ptr(dest_object),
00506 dest_point );
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 public void polygon_transform_points(
00526
polygons_struct *src_polygons,
00527
polygons_struct *dest_polygons,
00528
int n_points,
00529 Point src_points[],
00530 Point dest_points[] )
00531 {
00532
int i;
00533
object_struct *src_object, *dest_object;
00534
00535
if( !
polygons_are_same_topology( src_polygons, dest_polygons ) )
00536 {
00537 print_error(
00538
"polygon_transform_points: polygons are not same topology.\n" );
00539
return;
00540 }
00541
00542 src_object =
create_object(
POLYGONS );
00543 *
get_polygons_ptr(src_object) = *src_polygons;
00544 dest_object =
create_object(
POLYGONS );
00545 *
get_polygons_ptr(dest_object) = *dest_polygons;
00546
00547 for_less( i, 0, n_points )
00548 {
00549
polygon_transform_point( src_object, dest_object,
00550 &src_points[i], &dest_points[i] );
00551 }
00552 }
00553
00554 public void map_sphere_to_uv(
00555 Real x,
00556 Real y,
00557 Real z,
00558 Real *u,
00559 Real *v )
00560 {
00561 Real angle_up, angle_around;
00562
00563 angle_up = acos( z );
00564
00565 *v = 1.0 - angle_up / PI;
00566
00567 angle_around =
compute_clockwise_rotation( x, -
y );
00568
00569 *u = angle_around / (2.0*PI);
00570 }
00571
00572 public void map_uv_to_sphere(
00573 Real u,
00574 Real v,
00575 Real *x,
00576 Real *y,
00577 Real *z )
00578 {
00579 Real r;
00580
00581 *z = cos( (1.0 - v) * PI );
00582 r = sin( (1.0 - v) * PI );
00583
00584 *x = r * cos( u * 2.0 * PI );
00585 *
y = r * sin( u * 2.0 * PI );
00586 }