void tenQGLInterpTwoEvalK(double oeval[3], const double evalA[3], const double evalB[3], const double tt) { double RThZA[3], RThZB[3], oRThZ[3], bb; tenTripleConvertSingle_d(RThZA, tenTripleTypeRThetaZ, evalA, tenTripleTypeEigenvalue); tenTripleConvertSingle_d(RThZB, tenTripleTypeRThetaZ, evalB, tenTripleTypeEigenvalue); if (rr1 > rr0) { /* the bb calculation below could blow up, so we recurse with flipped order */ tenQGLInterpTwoEvalK(oeval, evalB, evalA, 1-tt); } else { rr = AIR_LERP(tt, rr0, rr1); zz = AIR_LERP(tt, zz0, zz1); bb = rr0 ? (rr1/rr0 - 1) : 0; /* bb can't be positive, because rr1 <= rr0 enforced above, so below is really test for -0.001 < bb <= 0 */ if (bb > -0.0001) { double dth; dth = th1 - th0; /* rr0 and rr1 are similar, use stable approximation */ th = th0 + tt*(dth + (0.5 - tt/2)*dth*bb + (-1.0/12 - tt/4 + tt*tt/3)*dth*bb*bb + (1.0/24 + tt/24 + tt*tt/6 - tt*tt*tt/4)*dth*bb*bb*bb); } else { /* use original formula */ /* have to clamp value of b so that log() values don't explode */ bb = AIR_MAX(bb, -1 + 100*FLT_EPSILON); th = th0 + (th1 - th0)*log(1 + bb*tt)/log(1 + bb); } tenTripleConvertSingle_d(oeval, tenTripleTypeEigenvalue, oRThZ, tenTripleTypeRThetaZ); /* fprintf(stderr, "%s: (b = %g) %g %g %g <-- %g %g %g\n", "blah", bb, oeval[0], oeval[1], oeval[2], oRThZ[0], oRThZ[1], oRThZ[2]); */ } }
/* ** its in here that we scale from "energy gradient" to "force" */ double _pullPointEnergyTotal(pullTask *task, pullBin *bin, pullPoint *point, /* output */ double force[4]) { char me[]="_pullPointEnergyTotal"; double enrIm, enrPt, egradIm[4], egradPt[4], energy; ELL_4V_SET(egradIm, 0, 0, 0, 0); /* sssh */ ELL_4V_SET(egradPt, 0, 0, 0, 0); /* sssh */ enrIm = _energyFromImage(task, point, force ? egradIm : NULL); enrPt = _energyFromPoints(task, bin, point, force ? egradPt : NULL); energy = AIR_LERP(task->pctx->alpha, enrIm, enrPt); /* fprintf(stderr, "!%s(%u): energy = lerp(%g, im %g, pt %g) = %g\n", me, point->idtag, task->pctx->alpha, enrIm, enrPt, energy); */ if (force) { ELL_4V_LERP(force, task->pctx->alpha, egradIm, egradPt); ELL_4V_SCALE(force, -1, force); /* fprintf(stderr, "!%s(%u): egradIm = %g %g %g %g\n", me, point->idtag, egradIm[0], egradIm[1], egradIm[2], egradIm[3]); fprintf(stderr, "!%s(%u): egradPt = %g %g %g %g\n", me, point->idtag, egradPt[0], egradPt[1], egradPt[2], egradPt[3]); fprintf(stderr, "!%s(%u): ---> force = %g %g %g %g\n", me, point->idtag, force[0], force[1], force[2], force[3]); */ } if (task->pctx->wall) { unsigned int axi; double frc; for (axi=0; axi<4; axi++) { frc = task->pctx->bboxMin[axi] - point->pos[axi]; if (frc < 0) { /* not below min */ frc = task->pctx->bboxMax[axi] - point->pos[axi]; if (frc > 0) { /* not above max */ frc = 0; } } energy += task->pctx->wall*frc*frc/2; if (force) { force[axi] += task->pctx->wall*frc; } } } if (!AIR_EXISTS(energy)) { fprintf(stderr, "!%s(%u): HEY! non-exist energy %g\n", me, point->idtag, energy); } return energy; }
static double _nrrdTernaryOpLerp(double a, double b, double c) { /* we do something more than the simple lerp here because we want to facilitate usage as something which can get around non-existent values (b and c as NaN or Inf) without getting polluted by them. */ if (0.0 == a) { return b; } else if (1.0 == a) { return c; } else { return AIR_LERP(a, b, c); } }
/* ** parm[0]: lerp between 1 and the stuff below ** parm[1]: "t": (parm[1],0) is control point between (0,0) and (1,1) ** parm[2]: "d": parabolic blend between parm[1]-parm[2] and parm[1]+parm[2] */ void _tenFiberAnisoSpeed(double *step, double xx, double parm[3]) { double aa, dd, tt, yy; tt = parm[1]; dd = parm[2]; aa = 1.0/(DBL_EPSILON + 4*dd*(1.0-tt)); yy = xx - tt + dd; xx = (xx < tt - dd ? 0 : (xx < tt + dd ? aa*yy*yy : (xx - tt)/(1 - tt))); xx = AIR_LERP(parm[0], 1, xx); ELL_3V_SCALE(step, xx, step); }
static void simulate(double *dwiSim, const double *parm, const tenExperSpec *espec) { unsigned int ii; double th0, frac, th1, vec0[3], vec1[3]; /* not used: b0 = parm[0]; */ th0 = parm[1]; frac = parm[2]; th1 = parm[3]; ELL_3V_SET(vec0, cos(th0), sin(th0), 0.0); ELL_3V_SET(vec1, cos(th1), sin(th1), 0.0); for (ii=0; ii<espec->imgNum; ii++) { double dot0, dot1; dot0 = ELL_3V_DOT(vec0, espec->grad + 3*ii); dot1 = ELL_3V_DOT(vec1, espec->grad + 3*ii); dwiSim[ii] = AIR_LERP(frac, dot0, dot1); } return; }
void tenQGLInterpTwo(double oten[7], const double tenA[7], const double tenB[7], int ptype, double tt, tenInterpParm *tip) { double oeval[3], evalA[3], evalB[3], oevec[9], evecA[9], evecB[9], cc; AIR_UNUSED(tip); tenEigensolve_d(evalA, evecA, tenA); tenEigensolve_d(evalB, evecB, tenB); cc = AIR_LERP(tt, tenA[0], tenB[0]); if (tenInterpTypeQuatGeoLoxK == ptype) { tenQGLInterpTwoEvalK(oeval, evalA, evalB, tt); } else { tenQGLInterpTwoEvalR(oeval, evalA, evalB, tt); } tenQGLInterpTwoEvec(oevec, evecA, evecB, tt); tenMakeSingle_d(oten, cc, oeval, oevec); return; }
void tend_helixDoit(Nrrd *nout, double bnd, double orig[3], double i2w[9], double mf[9], double r, double R, double S, double angle, int incrtwist, double ev[3], double bgEval) { int sx, sy, sz, xi, yi, zi; double th, t0, t1, t2, t3, v1, v2, wpos[3], vpos[3], mfT[9], W2H[9], H2W[9], H2C[9], C2H[9], fv[3], rv[3], uv[3], mA[9], mB[9], inside, tmp[3], len; float *out; sx = nout->axis[1].size; sy = nout->axis[2].size; sz = nout->axis[3].size; out = (float*)nout->data; ELL_3M_TRANSPOSE(mfT, mf); for (zi=0; zi<sz; zi++) { fprintf(stderr, "zi = %d/%d\n", zi, sz); for (yi=0; yi<sy; yi++) { for (xi=0; xi<sx; xi++) { ELL_3V_SET(tmp, xi, yi, zi); ELL_3MV_MUL(vpos, i2w, tmp); ELL_3V_INCR(vpos, orig); #define WPOS(pos, th) ELL_3V_SET((pos),R*cos(th), R*sin(th), S*(th)/(2*AIR_PI)) #define VAL(th) (WPOS(wpos, th), ELL_3V_DIST(wpos, vpos)) #define RR 0.61803399 #define CC (1.0-RR) #define SHIFT3(a,b,c,d) (a)=(b); (b)=(c); (c)=(d) #define SHIFT2(a,b,c) (a)=(b); (b)=(c) th = atan2(vpos[1], vpos[0]); th += 2*AIR_PI*floor(0.5 + vpos[2]/S - th/(2*AIR_PI)); if (S*th/(2*AIR_PI) > vpos[2]) { t0 = th - AIR_PI; t3 = th; } else { t0 = th; t3 = th + AIR_PI; } t1 = RR*t0 + CC*t3; t2 = CC*t0 + RR*t3; v1 = VAL(t1); v2 = VAL(t2); while ( t3-t0 > 0.000001*(AIR_ABS(t1)+AIR_ABS(t2)) ) { if (v1 < v2) { SHIFT3(t3, t2, t1, CC*t0 + RR*t2); SHIFT2(v2, v1, VAL(t1)); } else { SHIFT3(t0, t1, t2, RR*t1 + CC*t3); SHIFT2(v1, v2, VAL(t2)); } } /* t1 (and t2) are now the th for which the point on the helix (R*cos(th), R*sin(th), S*(th)/(2*AIR_PI)) is closest to vpos */ WPOS(wpos, t1); ELL_3V_SUB(wpos, vpos, wpos); ELL_3V_SET(fv, -R*sin(t1), R*cos(t1), S/AIR_PI); /* helix tangent */ ELL_3V_NORM(fv, fv, len); ELL_3V_COPY(rv, wpos); ELL_3V_NORM(rv, rv, len); len = ELL_3V_DOT(rv, fv); ELL_3V_SCALE(tmp, -len, fv); ELL_3V_ADD2(rv, rv, tmp); ELL_3V_NORM(rv, rv, len); /* rv now normal to helix, closest to pointing to vpos */ ELL_3V_CROSS(uv, rv, fv); ELL_3V_NORM(uv, uv, len); /* (rv,fv,uv) now right-handed frame */ ELL_3MV_ROW0_SET(W2H, uv); /* as is (uv,rv,fv) */ ELL_3MV_ROW1_SET(W2H, rv); ELL_3MV_ROW2_SET(W2H, fv); ELL_3M_TRANSPOSE(H2W, W2H); inside = 0.5 - 0.5*airErf((ELL_3V_LEN(wpos)-r)/(bnd + 0.0001)); if (incrtwist) { th = angle*ELL_3V_LEN(wpos)/r; } else { th = angle; } ELL_3M_ROTATE_Y_SET(H2C, th); ELL_3M_TRANSPOSE(C2H, H2C); ELL_3M_SCALE_SET(mA, AIR_LERP(inside, bgEval, ev[1]), AIR_LERP(inside, bgEval, ev[2]), AIR_LERP(inside, bgEval, ev[0])); ELL_3M_MUL(mB, mA, H2C); ELL_3M_MUL(mA, mB, W2H); ELL_3M_MUL(mB, mA, mf); ELL_3M_MUL(mA, C2H, mB); ELL_3M_MUL(mB, H2W, mA); ELL_3M_MUL(mA, mfT, mB); TEN_M2T_TT(out, float, mA); out[0] = 1.0; out += 7; } } } return; }
/* ** parm vector: ** 0 1 2 3 4 5 (6) ** step K_perp K_tan lerp X_ring Y_ring */ void _coilKindScalarFilterModifiedCurvatureRings(coil_t *delta, int xi, int yi, int zi, coil_t **iv3, double spacing[3], double parm[COIL_PARMS_NUM]) { coil_t forwX[3], backX[3], forwY[3], backY[3], forwZ[3], backZ[3], grad[3], gm, eps, KK, LL, denom, rspX, rspY, rspZ, lerp; double bas0[3], bas1[3], bas2[3], len, norm[3], sk; AIR_UNUSED(zi); ELL_3V_SET(bas0, 0, 0, 1); ELL_3V_SET(bas1, xi - parm[4], yi - parm[5], 0); ELL_3V_NORM(bas1, bas1, len); ELL_3V_CROSS(bas2, bas0, bas1); rspX = AIR_CAST(coil_t, 1.0/spacing[0]); rspY = AIR_CAST(coil_t, 1.0/spacing[1]); rspZ = AIR_CAST(coil_t, 1.0/spacing[2]); _coilKindScalar3x3x3Gradients(forwX, backX, forwY, backY, forwZ, backZ, iv3, rspX, rspY, rspZ); grad[0] = rspX*(iv3[2][4] - iv3[0][4]); grad[1] = rspY*(iv3[1][5] - iv3[1][3]); grad[2] = rspZ*(iv3[1][7] - iv3[1][1]); gm = AIR_CAST(coil_t, ELL_3V_LEN(grad)); if (gm) { double tc, rcsq; ELL_3V_SCALE(norm, 1.0/gm, grad); tc = ELL_3V_DOT(norm, bas2); rcsq = 1 - tc*tc; sk = AIR_LERP(rcsq, parm[1], parm[2]); } else { sk = parm[1]; } /* compute fluxes */ eps = 0.0000000001f; KK = AIR_CAST(coil_t, sk*sk); LL = ELL_3V_DOT(forwX, forwX); denom = AIR_CAST(coil_t, 1.0/(eps + sqrt(LL))); forwX[0] *= _COIL_CONDUCT(LL, KK)*denom; LL = ELL_3V_DOT(forwY, forwY); denom = AIR_CAST(coil_t, 1.0/(eps + sqrt(LL))); forwY[1] *= _COIL_CONDUCT(LL, KK)*denom; LL = ELL_3V_DOT(forwZ, forwZ); denom = AIR_CAST(coil_t, 1.0/(eps + sqrt(LL))); forwZ[2] *= _COIL_CONDUCT(LL, KK)*denom; LL = ELL_3V_DOT(backX, backX); denom = AIR_CAST(coil_t, 1.0/(eps + sqrt(LL))); backX[0] *= _COIL_CONDUCT(LL, KK)*denom; LL = ELL_3V_DOT(backY, backY); denom = AIR_CAST(coil_t, 1.0/(eps + sqrt(LL))); backY[1] *= _COIL_CONDUCT(LL, KK)*denom; LL = ELL_3V_DOT(backZ, backZ); denom = AIR_CAST(coil_t, 1.0/(eps + sqrt(LL))); backZ[2] *= _COIL_CONDUCT(LL, KK)*denom; lerp = AIR_CAST(coil_t, parm[2]); delta[0] = (lerp*_coilLaplacian3(iv3, spacing) + (1-lerp)*gm*(rspX*(forwX[0] - backX[0]) + rspY*(forwY[1] - backY[1]) + rspZ*(forwZ[2] - backZ[2]))); delta[0] *= AIR_CAST(coil_t, parm[0]); }
static int theFunc(Nrrd *nout, const Nrrd *nin, int func, funcParm *parm) { static const char me[]="theFunc"; float *tin, *tout, eval[3], evec[9], weight[3], size, mean; size_t NN, II; unsigned int ri; if (!AIR_IN_OP(funcUnknown, func, funcLast)) { biffAddf(TEN, "%s: given func %d out of range [%d,%d]", me, func, funcUnknown+1, funcLast-1); return 1; } if (!(nout && nin && parm)) { biffAddf(TEN, "%s: got NULL pointer", me); return 1; } if (tenTensorCheck(nin, nrrdTypeFloat, AIR_FALSE, AIR_TRUE)) { biffAddf(TEN, "%s: didn't get a tensor nrrd", me); return 1; } if (nout != nin) { if (nrrdCopy(nout, nin)) { biffMovef(TEN, NRRD, "%s: couldn't allocate output", me); return 1; } } tin = (float*)(nin->data); tout = (float*)(nout->data); NN = nrrdElementNumber(nin)/7; switch(func) { case funcSizeNormalize: ELL_3V_COPY_TT(weight, float, parm->weight); size = weight[0] + weight[1] + weight[2]; if (!size) { biffAddf(TEN, "%s: some of eigenvalue weights is zero", me); return 1; } weight[0] /= size; weight[1] /= size; weight[2] /= size; for (II=0; II<=NN-1; II++) { tenEigensolve_f(eval, evec, tin); size = (weight[0]*AIR_ABS(eval[0]) + weight[1]*AIR_ABS(eval[1]) + weight[2]*AIR_ABS(eval[2])); ELL_3V_SET_TT(eval, float, AIR_AFFINE(0, parm->amount, 1, eval[0], parm->target*eval[0]/size), AIR_AFFINE(0, parm->amount, 1, eval[1], parm->target*eval[1]/size), AIR_AFFINE(0, parm->amount, 1, eval[2], parm->target*eval[2]/size)); tenMakeSingle_f(tout, tin[0], eval, evec); tin += 7; tout += 7; } break; case funcSizeScale: for (II=0; II<=NN-1; II++) { TEN_T_SET_TT(tout, float, tin[0], parm->amount*tin[1], parm->amount*tin[2], parm->amount*tin[3], parm->amount*tin[4], parm->amount*tin[5], parm->amount*tin[6]); tin += 7; tout += 7; } break; case funcAnisoScale: for (II=0; II<=NN-1; II++) { tenEigensolve_f(eval, evec, tin); if (parm->fixDet) { eval[0] = AIR_MAX(eval[0], 0.00001f); eval[1] = AIR_MAX(eval[1], 0.00001f); eval[2] = AIR_MAX(eval[2], 0.00001f); ELL_3V_SET_TT(eval, float, log(eval[0]), log(eval[1]), log(eval[2])); } mean = (eval[0] + eval[1] + eval[2])/3.0f; ELL_3V_SET_TT(eval, float, AIR_LERP(parm->scale, mean, eval[0]), AIR_LERP(parm->scale, mean, eval[1]), AIR_LERP(parm->scale, mean, eval[2])); if (parm->fixDet) { ELL_3V_SET_TT(eval, float, exp(eval[0]), exp(eval[1]), exp(eval[2])); } if (eval[2] < 0 && parm->makePositive) { eval[0] = AIR_MAX(eval[0], 0.0f); eval[1] = AIR_MAX(eval[1], 0.0f); eval[2] = AIR_MAX(eval[2], 0.0f); } tenMakeSingle_f(tout, tin[0], eval, evec); tin += 7; tout += 7; } break; case funcEigenvalueClamp: for (II=0; II<=NN-1; II++) { tenEigensolve_f(eval, evec, tin); if (AIR_EXISTS(parm->min)) { ELL_3V_SET_TT(eval, float, AIR_MAX(eval[0], parm->min), AIR_MAX(eval[1], parm->min), AIR_MAX(eval[2], parm->min)); } if (AIR_EXISTS(parm->max)) { ELL_3V_SET_TT(eval, float, AIR_MIN(eval[0], parm->max), AIR_MIN(eval[1], parm->max), AIR_MIN(eval[2], parm->max)); } tenMakeSingle_f(tout, tin[0], eval, evec); tin += 7; tout += 7; }