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); |
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) |