| 484 |
|
} |
| 485 |
|
} |
| 486 |
|
} |
| 487 |
+ |
|
| 488 |
+ |
/* Add normal direction if missing */ |
| 489 |
+ |
static void |
| 490 |
+ |
check_normal_incidence(void) |
| 491 |
+ |
{ |
| 492 |
+ |
const int saved_nprocs = nprocs; |
| 493 |
+ |
RBFNODE *near_rbf, *mir_rbf, *rbf; |
| 494 |
+ |
double bestd; |
| 495 |
+ |
int n, i, j; |
| 496 |
+ |
|
| 497 |
+ |
if (dsf_list == NULL) |
| 498 |
+ |
return; /* XXX should be error? */ |
| 499 |
+ |
near_rbf = dsf_list; |
| 500 |
+ |
bestd = input_orient*near_rbf->invec[2]; |
| 501 |
+ |
if (single_plane_incident) { /* ordered plane incidence? */ |
| 502 |
+ |
if (bestd >= 1.-2.*FTINY) |
| 503 |
+ |
return; /* already have normal */ |
| 504 |
+ |
} else { |
| 505 |
+ |
switch (inp_coverage) { |
| 506 |
+ |
case INP_QUAD1: |
| 507 |
+ |
case INP_QUAD2: |
| 508 |
+ |
case INP_QUAD3: |
| 509 |
+ |
case INP_QUAD4: |
| 510 |
+ |
break; /* quadrilateral symmetry? */ |
| 511 |
+ |
default: |
| 512 |
+ |
return; /* else we can interpolate */ |
| 513 |
+ |
} |
| 514 |
+ |
for (rbf = near_rbf->next; rbf != NULL; rbf = rbf->next) { |
| 515 |
+ |
const double d = input_orient*rbf->invec[2]; |
| 516 |
+ |
if (d >= 1.-2.*FTINY) |
| 517 |
+ |
return; /* seems we have normal */ |
| 518 |
+ |
if (d > bestd) { |
| 519 |
+ |
near_rbf = rbf; |
| 520 |
+ |
bestd = d; |
| 521 |
+ |
} |
| 522 |
+ |
} |
| 523 |
+ |
} |
| 524 |
+ |
if (mig_list != NULL) { /* need to be called first */ |
| 525 |
+ |
fprintf(stderr, "%s: Late call to check_normal_incidence()\n", |
| 526 |
+ |
progname); |
| 527 |
+ |
exit(1); |
| 528 |
+ |
} |
| 529 |
+ |
#ifdef DEBUG |
| 530 |
+ |
fprintf(stderr, "Interpolating normal incidence by mirroring (%.1f,%.1f)\n", |
| 531 |
+ |
get_theta180(near_rbf->invec), get_phi360(near_rbf->invec)); |
| 532 |
+ |
#endif |
| 533 |
+ |
/* mirror nearest incidence */ |
| 534 |
+ |
n = sizeof(RBFNODE) + sizeof(RBFVAL)*(near_rbf->nrbf-1); |
| 535 |
+ |
mir_rbf = (RBFNODE *)malloc(n); |
| 536 |
+ |
if (mir_rbf == NULL) |
| 537 |
+ |
goto memerr; |
| 538 |
+ |
memcpy(mir_rbf, near_rbf, n); |
| 539 |
+ |
mir_rbf->ord = near_rbf->ord - 1; /* not used, I think */ |
| 540 |
+ |
mir_rbf->next = NULL; |
| 541 |
+ |
rev_rbf_symmetry(mir_rbf, MIRROR_X|MIRROR_Y); |
| 542 |
+ |
nprocs = 1; /* compute migration matrix */ |
| 543 |
+ |
if (mig_list != create_migration(mir_rbf, near_rbf)) |
| 544 |
+ |
exit(1); /* XXX should never happen! */ |
| 545 |
+ |
n = 0; /* count migrating particles */ |
| 546 |
+ |
for (i = 0; i < mtx_nrows(mig_list); i++) |
| 547 |
+ |
for (j = 0; j < mtx_ncols(mig_list); j++) |
| 548 |
+ |
n += (mtx_coef(mig_list,i,j) > FTINY); |
| 549 |
+ |
rbf = (RBFNODE *)malloc(sizeof(RBFNODE) + sizeof(RBFVAL)*(n-1)); |
| 550 |
+ |
if (rbf == NULL) |
| 551 |
+ |
goto memerr; |
| 552 |
+ |
rbf->next = NULL; rbf->ejl = NULL; |
| 553 |
+ |
rbf->invec[0] = rbf->invec[1] = 0; rbf->invec[2] = 1.; |
| 554 |
+ |
rbf->nrbf = n; |
| 555 |
+ |
rbf->vtotal = .5 + .5*mig_list->rbfv[1]->vtotal/mig_list->rbfv[0]->vtotal; |
| 556 |
+ |
n = 0; /* advect RBF lobes halfway */ |
| 557 |
+ |
for (i = 0; i < mtx_nrows(mig_list); i++) { |
| 558 |
+ |
const RBFVAL *rbf0i = &mig_list->rbfv[0]->rbfa[i]; |
| 559 |
+ |
const float peak0 = rbf0i->peak; |
| 560 |
+ |
const double rad0 = R2ANG(rbf0i->crad); |
| 561 |
+ |
FVECT v0; |
| 562 |
+ |
float mv; |
| 563 |
+ |
ovec_from_pos(v0, rbf0i->gx, rbf0i->gy); |
| 564 |
+ |
for (j = 0; j < mtx_ncols(mig_list); j++) |
| 565 |
+ |
if ((mv = mtx_coef(mig_list,i,j)) > FTINY) { |
| 566 |
+ |
const RBFVAL *rbf1j = &mig_list->rbfv[1]->rbfa[j]; |
| 567 |
+ |
double rad2; |
| 568 |
+ |
FVECT v; |
| 569 |
+ |
int pos[2]; |
| 570 |
+ |
rad2 = R2ANG(rbf1j->crad); |
| 571 |
+ |
rad2 = .5*(rad0*rad0 + rad2*rad2); |
| 572 |
+ |
rbf->rbfa[n].peak = peak0 * mv * rbf->vtotal * |
| 573 |
+ |
rad0*rad0/rad2; |
| 574 |
+ |
rbf->rbfa[n].crad = ANG2R(sqrt(rad2)); |
| 575 |
+ |
ovec_from_pos(v, rbf1j->gx, rbf1j->gy); |
| 576 |
+ |
geodesic(v, v0, v, .5, GEOD_REL); |
| 577 |
+ |
pos_from_vec(pos, v); |
| 578 |
+ |
rbf->rbfa[n].gx = pos[0]; |
| 579 |
+ |
rbf->rbfa[n].gy = pos[1]; |
| 580 |
+ |
++n; |
| 581 |
+ |
} |
| 582 |
+ |
} |
| 583 |
+ |
rbf->vtotal *= mig_list->rbfv[0]->vtotal; |
| 584 |
+ |
nprocs = saved_nprocs; /* final clean-up */ |
| 585 |
+ |
free(mir_rbf); |
| 586 |
+ |
free(mig_list); |
| 587 |
+ |
mig_list = near_rbf->ejl = NULL; |
| 588 |
+ |
insert_dsf(rbf); /* insert interpolated normal */ |
| 589 |
+ |
return; |
| 590 |
+ |
memerr: |
| 591 |
+ |
fprintf(stderr, "%s: Out of memory in check_normal_incidence()\n", |
| 592 |
+ |
progname); |
| 593 |
+ |
exit(1); |
| 594 |
+ |
} |
| 595 |
|
|
| 596 |
|
/* Build our triangle mesh from recorded RBFs */ |
| 597 |
|
void |
| 600 |
|
double best2 = M_PI*M_PI; |
| 601 |
|
RBFNODE *shrt_edj[2]; |
| 602 |
|
RBFNODE *rbf0, *rbf1; |
| 603 |
+ |
/* add normal if needed */ |
| 604 |
+ |
check_normal_incidence(); |
| 605 |
|
/* check if isotropic */ |
| 606 |
|
if (single_plane_incident) { |
| 607 |
|
for (rbf0 = dsf_list; rbf0 != NULL; rbf0 = rbf0->next) |