| 176 |
|
pm->prow = pricerow(pm,i); |
| 177 |
|
srow = psortrow(pm,i); |
| 178 |
|
for (j = to_rbf->nrbf; j--; ) { |
| 179 |
< |
double dprod = DOT(vfrom, vto[j]); |
| 180 |
< |
pm->prow[j] = ((dprod >= 1.) ? .0 : acos(dprod)) + |
| 181 |
< |
fabs(R2ANG(to_rbf->rbfa[j].crad) - from_ang); |
| 179 |
> |
double d; /* quadratic cost function */ |
| 180 |
> |
d = DOT(vfrom, vto[j]); |
| 181 |
> |
d = (d >= 1.) ? .0 : acos(d); |
| 182 |
> |
pm->prow[j] = d*d; |
| 183 |
> |
d = R2ANG(to_rbf->rbfa[j].crad) - from_ang; |
| 184 |
> |
pm->prow[j] += d*d; |
| 185 |
|
srow[j] = j; |
| 186 |
|
} |
| 187 |
|
qsort_r(srow, pm->ncols, sizeof(short), pm, &msrt_cmp); |
| 239 |
|
{ |
| 240 |
|
const int max2check = 100; |
| 241 |
|
const double maxamt = 1./(double)pm->ncols; |
| 242 |
< |
const double minamt = maxamt*5e-6; |
| 242 |
> |
const double minamt = maxamt*1e-4; |
| 243 |
|
double *src_cost; |
| 244 |
|
short (*rord)[2]; |
| 245 |
|
struct { |
| 336 |
|
return(NULL); |
| 337 |
|
/* else allocate */ |
| 338 |
|
#ifdef DEBUG |
| 339 |
< |
fprintf(stderr, "Building path from (theta,phi) (%.0f,%.0f) ", |
| 339 |
> |
fprintf(stderr, "Building path from (theta,phi) (%.1f,%.1f) ", |
| 340 |
|
get_theta180(from_rbf->invec), |
| 341 |
|
get_phi360(from_rbf->invec)); |
| 342 |
< |
fprintf(stderr, "to (%.0f,%.0f) with %d x %d matrix\n", |
| 342 |
> |
fprintf(stderr, "to (%.1f,%.1f) with %d x %d matrix\n", |
| 343 |
|
get_theta180(to_rbf->invec), |
| 344 |
|
get_phi360(to_rbf->invec), |
| 345 |
|
from_rbf->nrbf, to_rbf->nrbf); |
| 407 |
|
return(vother[im_rev] != NULL); |
| 408 |
|
} |
| 409 |
|
|
| 410 |
< |
/* Find context hull vertex to complete triangle (oriented call) */ |
| 410 |
> |
/* Find convex hull vertex to complete triangle (oriented call) */ |
| 411 |
|
static RBFNODE * |
| 412 |
|
find_chull_vert(const RBFNODE *rbf0, const RBFNODE *rbf1) |
| 413 |
|
{ |
| 428 |
|
if (DOT(vp, vmid) <= FTINY) |
| 429 |
|
continue; /* wrong orientation */ |
| 430 |
|
area2 = .25*DOT(vp,vp); |
| 431 |
< |
VSUB(vp, rbf->invec, rbf0->invec); |
| 431 |
> |
VSUB(vp, rbf->invec, vmid); |
| 432 |
|
dprod = -DOT(vp, vejn); |
| 433 |
|
VSUM(vp, vp, vejn, dprod); /* above guarantees non-zero */ |
| 434 |
|
dprod = DOT(vp, vmid) / VLEN(vp); |
| 484 |
|
} |
| 485 |
|
} |
| 486 |
|
} |
| 487 |
+ |
|
| 488 |
+ |
/* Add normal direction if missing */ |
| 489 |
+ |
static void |
| 490 |
+ |
check_normal_incidence(void) |
| 491 |
+ |
{ |
| 492 |
+ |
static const FVECT norm_vec = {.0, .0, 1.}; |
| 493 |
+ |
const int saved_nprocs = nprocs; |
| 494 |
+ |
RBFNODE *near_rbf, *mir_rbf, *rbf; |
| 495 |
+ |
double bestd; |
| 496 |
+ |
int n; |
| 497 |
+ |
|
| 498 |
+ |
if (dsf_list == NULL) |
| 499 |
+ |
return; /* XXX should be error? */ |
| 500 |
+ |
near_rbf = dsf_list; |
| 501 |
+ |
bestd = input_orient*near_rbf->invec[2]; |
| 502 |
+ |
if (single_plane_incident) { /* ordered plane incidence? */ |
| 503 |
+ |
if (bestd >= 1.-2.*FTINY) |
| 504 |
+ |
return; /* already have normal */ |
| 505 |
+ |
} else { |
| 506 |
+ |
switch (inp_coverage) { |
| 507 |
+ |
case INP_QUAD1: |
| 508 |
+ |
case INP_QUAD2: |
| 509 |
+ |
case INP_QUAD3: |
| 510 |
+ |
case INP_QUAD4: |
| 511 |
+ |
break; /* quadrilateral symmetry? */ |
| 512 |
+ |
default: |
| 513 |
+ |
return; /* else we can interpolate */ |
| 514 |
+ |
} |
| 515 |
+ |
for (rbf = near_rbf->next; rbf != NULL; rbf = rbf->next) { |
| 516 |
+ |
const double d = input_orient*rbf->invec[2]; |
| 517 |
+ |
if (d >= 1.-2.*FTINY) |
| 518 |
+ |
return; /* seems we have normal */ |
| 519 |
+ |
if (d > bestd) { |
| 520 |
+ |
near_rbf = rbf; |
| 521 |
+ |
bestd = d; |
| 522 |
+ |
} |
| 523 |
+ |
} |
| 524 |
+ |
} |
| 525 |
+ |
if (mig_list != NULL) { /* need to be called first */ |
| 526 |
+ |
fprintf(stderr, "%s: Late call to check_normal_incidence()\n", |
| 527 |
+ |
progname); |
| 528 |
+ |
exit(1); |
| 529 |
+ |
} |
| 530 |
+ |
#ifdef DEBUG |
| 531 |
+ |
fprintf(stderr, "Interpolating normal incidence by mirroring (%.1f,%.1f)\n", |
| 532 |
+ |
get_theta180(near_rbf->invec), get_phi360(near_rbf->invec)); |
| 533 |
+ |
#endif |
| 534 |
+ |
/* mirror nearest incidence */ |
| 535 |
+ |
n = sizeof(RBFNODE) + sizeof(RBFVAL)*(near_rbf->nrbf-1); |
| 536 |
+ |
mir_rbf = (RBFNODE *)malloc(n); |
| 537 |
+ |
if (mir_rbf == NULL) |
| 538 |
+ |
goto memerr; |
| 539 |
+ |
memcpy(mir_rbf, near_rbf, n); |
| 540 |
+ |
mir_rbf->ord = near_rbf->ord - 1; /* not used, I think */ |
| 541 |
+ |
mir_rbf->next = NULL; |
| 542 |
+ |
rev_rbf_symmetry(mir_rbf, MIRROR_X|MIRROR_Y); |
| 543 |
+ |
nprocs = 1; /* compute migration matrix */ |
| 544 |
+ |
if (mig_list != create_migration(mir_rbf, near_rbf)) |
| 545 |
+ |
exit(1); /* XXX should never happen! */ |
| 546 |
+ |
/* interpolate normal dist. */ |
| 547 |
+ |
rbf = e_advect_rbf(mig_list, norm_vec, 2*near_rbf->nrbf); |
| 548 |
+ |
nprocs = saved_nprocs; /* final clean-up */ |
| 549 |
+ |
free(mir_rbf); |
| 550 |
+ |
free(mig_list); |
| 551 |
+ |
mig_list = near_rbf->ejl = NULL; |
| 552 |
+ |
insert_dsf(rbf); /* insert interpolated normal */ |
| 553 |
+ |
return; |
| 554 |
+ |
memerr: |
| 555 |
+ |
fprintf(stderr, "%s: Out of memory in check_normal_incidence()\n", |
| 556 |
+ |
progname); |
| 557 |
+ |
exit(1); |
| 558 |
+ |
} |
| 559 |
|
|
| 560 |
|
/* Build our triangle mesh from recorded RBFs */ |
| 561 |
|
void |
| 564 |
|
double best2 = M_PI*M_PI; |
| 565 |
|
RBFNODE *shrt_edj[2]; |
| 566 |
|
RBFNODE *rbf0, *rbf1; |
| 567 |
+ |
/* add normal if needed */ |
| 568 |
+ |
check_normal_incidence(); |
| 569 |
|
/* check if isotropic */ |
| 570 |
|
if (single_plane_incident) { |
| 571 |
|
for (rbf0 = dsf_list; rbf0 != NULL; rbf0 = rbf0->next) |