/* ******** ell_3m_2d_nullspace_d() ** ** the given matrix is assumed to have a nullspace of dimension two. ** ** The given nullspace matrix is NOT modified ** ** This does NOT use biff */ void ell_3m_2d_nullspace_d(double ans0[3], double ans1[3], const double _n[9]) { double n[9], tmp[3], norm; ELL_3M_TRANSPOSE(n, _n); _ell_align3_d(n); ELL_3V_ADD3(tmp, n+0, n+3, n+6); ELL_3V_NORM(tmp, tmp, norm); /* any two vectors which are perpendicular to the (supposedly 1D) span of the column vectors span the nullspace */ ell_3v_perp_d(ans0, tmp); ELL_3V_NORM(ans0, ans0, norm); ELL_3V_CROSS(ans1, tmp, ans0); return; }
/* ******** ell_3m_1d_nullspace_d() ** ** the given matrix is assumed to have a nullspace of dimension one. ** A normalized vector which spans the nullspace is put into ans. ** ** The given nullspace matrix is NOT modified. ** ** This does NOT use biff */ void ell_3m_1d_nullspace_d(double ans[3], const double _n[9]) { double t[9], n[9], norm; ELL_3M_TRANSPOSE(n, _n); /* find the three cross-products of pairs of column vectors of n */ ELL_3V_CROSS(t+0, n+0, n+3); ELL_3V_CROSS(t+3, n+0, n+6); ELL_3V_CROSS(t+6, n+3, n+6); /* lop A */ _ell_align3_d(t); /* lop B */ /* add them up (longer, hence more accurate, should dominate) */ ELL_3V_ADD3(ans, t+0, t+3, t+6); /* normalize */ ELL_3V_NORM(ans, ans, norm); return; }
void * _hooverThreadBody(void *_arg) { _hooverThreadArg *arg; void *thread; int ret, /* to catch return values from callbacks */ sampleI, /* which sample we're on */ inside, /* we're inside the volume */ vI, uI; /* integral coords in image */ double tmp, mm, /* lowest position in index space, for all axes */ Mx, My, Mz, /* highest position in index space on each axis */ u, v, /* floating-point coords in image */ uvScale, /* how to scale (u,v) to go from image to near plane, according to ortho or perspective */ lx, ly, lz, /* half edge-lengths of volume */ rayLen=0, /* length of segment formed by ray line intersecting the near and far clipping planes */ rayT, /* current position along ray (world-space) */ rayDirW[3], /* unit-length ray direction (world-space) */ rayDirI[3], /* rayDirW transformed into index space; not unit length, but a unit change in world space along rayDirW translates to this change in index space along rayDirI */ rayPosW[3], /* current ray location (world-space) */ rayPosI[3], /* current ray location (index-space) */ rayStartW[3], /* ray start on near plane (world-space) */ rayStartI[3], /* ray start on near plane (index-space) */ rayStep, /* distance between samples (world-space) */ vOff[3], uOff[3]; /* offsets in arg->ec->wU and arg->ec->wV directions towards start of ray */ arg = (_hooverThreadArg *)_arg; if ( (ret = (arg->ctx->threadBegin)(&thread, arg->render, arg->ctx->user, arg->whichThread)) ) { arg->errCode = ret; arg->whichErr = hooverErrThreadBegin; return arg; } lx = arg->ec->volHLen[0]; ly = arg->ec->volHLen[1]; lz = arg->ec->volHLen[2]; if (nrrdCenterNode == arg->ctx->volCentering) { mm = 0; Mx = arg->ctx->volSize[0]-1; My = arg->ctx->volSize[1]-1; Mz = arg->ctx->volSize[2]-1; } else { mm = -0.5; Mx = arg->ctx->volSize[0]-0.5; My = arg->ctx->volSize[1]-0.5; Mz = arg->ctx->volSize[2]-0.5; } if (arg->ctx->cam->orthographic) { ELL_3V_COPY(rayDirW, arg->ctx->cam->N); rayDirI[0] = AIR_DELTA(-lx, rayDirW[0], lx, mm, Mx); rayDirI[1] = AIR_DELTA(-ly, rayDirW[1], ly, mm, My); rayDirI[2] = AIR_DELTA(-lz, rayDirW[2], lz, mm, Mz); rayLen = arg->ctx->cam->vspFaar - arg->ctx->cam->vspNeer; uvScale = 1.0; } else { uvScale = arg->ctx->cam->vspNeer/arg->ctx->cam->vspDist; } while (1) { /* the work assignment is simply the next scanline to be rendered: the result of all this is setting vI */ if (arg->ctx->workMutex) { airThreadMutexLock(arg->ctx->workMutex); } vI = arg->ctx->workIdx; if (arg->ctx->workIdx < arg->ctx->imgSize[1]) { arg->ctx->workIdx += 1; } if (arg->ctx->workMutex) { airThreadMutexUnlock(arg->ctx->workMutex); } if (vI == arg->ctx->imgSize[1]) { /* we're done! */ break; } if (nrrdCenterCell == arg->ctx->imgCentering) { v = uvScale*AIR_AFFINE(-0.5, vI, arg->ctx->imgSize[1]-0.5, arg->ctx->cam->vRange[0], arg->ctx->cam->vRange[1]); } else { v = uvScale*AIR_AFFINE(0.0, vI, arg->ctx->imgSize[1]-1.0, arg->ctx->cam->vRange[0], arg->ctx->cam->vRange[1]); } ELL_3V_SCALE(vOff, v, arg->ctx->cam->V); for (uI=0; uI<arg->ctx->imgSize[0]; uI++) { if (nrrdCenterCell == arg->ctx->imgCentering) { u = uvScale*AIR_AFFINE(-0.5, uI, arg->ctx->imgSize[0]-0.5, arg->ctx->cam->uRange[0], arg->ctx->cam->uRange[1]); } else { u = uvScale*AIR_AFFINE(0.0, uI, arg->ctx->imgSize[0]-1.0, arg->ctx->cam->uRange[0], arg->ctx->cam->uRange[1]); } ELL_3V_SCALE(uOff, u, arg->ctx->cam->U); ELL_3V_ADD3(rayStartW, uOff, vOff, arg->ec->rayZero); rayStartI[0] = AIR_AFFINE(-lx, rayStartW[0], lx, mm, Mx); rayStartI[1] = AIR_AFFINE(-ly, rayStartW[1], ly, mm, My); rayStartI[2] = AIR_AFFINE(-lz, rayStartW[2], lz, mm, Mz); if (!arg->ctx->cam->orthographic) { ELL_3V_SUB(rayDirW, rayStartW, arg->ctx->cam->from); ELL_3V_NORM(rayDirW, rayDirW, tmp); rayDirI[0] = AIR_DELTA(-lx, rayDirW[0], lx, mm, Mx); rayDirI[1] = AIR_DELTA(-ly, rayDirW[1], ly, mm, My); rayDirI[2] = AIR_DELTA(-lz, rayDirW[2], lz, mm, Mz); rayLen = ((arg->ctx->cam->vspFaar - arg->ctx->cam->vspNeer)/ ELL_3V_DOT(rayDirW, arg->ctx->cam->N)); } if ( (ret = (arg->ctx->rayBegin)(thread, arg->render, arg->ctx->user, uI, vI, rayLen, rayStartW, rayStartI, rayDirW, rayDirI)) ) { arg->errCode = ret; arg->whichErr = hooverErrRayBegin; return arg; } sampleI = 0; rayT = 0; while (1) { ELL_3V_SCALE_ADD2(rayPosW, 1.0, rayStartW, rayT, rayDirW); ELL_3V_SCALE_ADD2(rayPosI, 1.0, rayStartI, rayT, rayDirI); inside = (AIR_IN_CL(mm, rayPosI[0], Mx) && AIR_IN_CL(mm, rayPosI[1], My) && AIR_IN_CL(mm, rayPosI[2], Mz)); rayStep = (arg->ctx->sample)(thread, arg->render, arg->ctx->user, sampleI, rayT, inside, rayPosW, rayPosI); if (!AIR_EXISTS(rayStep)) { /* sampling failed */ arg->errCode = 0; arg->whichErr = hooverErrSample; return arg; } if (!rayStep) { /* ray decided to finish itself */ break; } /* else we moved to a new location along the ray */ rayT += rayStep; if (!AIR_IN_CL(0, rayT, rayLen)) { /* ray stepped outside near-far clipping region, its done. */ break; } sampleI++; } if ( (ret = (arg->ctx->rayEnd)(thread, arg->render, arg->ctx->user)) ) { arg->errCode = ret; arg->whichErr = hooverErrRayEnd; return arg; } } /* end this scanline */ } /* end while(1) assignment of scanlines */ if ( (ret = (arg->ctx->threadEnd)(thread, arg->render, arg->ctx->user)) ) { arg->errCode = ret; arg->whichErr = hooverErrThreadEnd; return arg; } /* returning NULL actually indicates that there was NOT an error */ return NULL; }
void _tenGageAnswer (gageContext *ctx, gagePerVolume *pvl) { /* char me[]="_tenGageAnswer"; */ gage_t epsilon=1.0E-10f; gage_t *tenAns, *evalAns, *evecAns, *vecTmp=NULL, *gradDtA=NULL, *gradDtB=NULL, *gradDtC=NULL, *gradDtD=NULL, *gradDtE=NULL, *gradDtF=NULL, gradDdXYZ[21]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, *gradCbS=NULL, *gradCbB=NULL, *gradCbQ=NULL, *gradCbR=NULL; gage_t tmp0, tmp1, magTmp=0, gradCbA[3]={0,0,0}, gradCbC[3]={0,0,0}, dtA=0, dtB=0, dtC=0, dtD=0, dtE=0, dtF=0, cbQQQ=0, cbQ=0, cbR=0, cbA=0, cbB=0, cbC=0, cbS=0; #if !GAGE_TYPE_FLOAT int ci; float evalAnsF[3], aniso[TEN_ANISO_MAX+1]; #endif tenAns = pvl->directAnswer[tenGageTensor]; evalAns = pvl->directAnswer[tenGageEval]; evecAns = pvl->directAnswer[tenGageEvec]; if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTensor)) { /* done if doV */ tenAns[0] = AIR_CLAMP(0.0f, tenAns[0], 1.0f); dtA = tenAns[1]; dtB = tenAns[2]; dtC = tenAns[3]; dtD = tenAns[4]; dtE = tenAns[5]; dtF = tenAns[6]; if (ctx->verbose) { fprintf(stderr, "tensor = (%g) %g %g %g %g %g %g\n", tenAns[0], dtA, dtB, dtC, dtD, dtE, dtF); } } /* done if doV if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageConfidence)) { } */ if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTrace)) { cbA = -(pvl->directAnswer[tenGageTrace][0] = dtA + dtD + dtF); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageB)) { cbB = pvl->directAnswer[tenGageB][0] = dtA*dtD + dtA*dtF + dtD*dtF - dtB*dtB - dtC*dtC - dtE*dtE; } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageDet)) { cbC = -(pvl->directAnswer[tenGageDet][0] = 2.0f*dtB*dtC*dtE + dtA*dtD*dtF - dtC*dtC*dtD - dtA*dtE*dtE - dtB*dtB*dtF); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageS)) { cbS = (pvl->directAnswer[tenGageS][0] = dtA*dtA + dtD*dtD + dtF*dtF + 2.0f*dtB*dtB + 2.0f*dtC*dtC + 2.0f*dtE*dtE); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageQ)) { cbQ = pvl->directAnswer[tenGageQ][0] = (cbS - cbB)/9.0f; } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageFA)) { pvl->directAnswer[tenGageFA][0] = AIR_CAST(gage_t, 3*sqrt(cbQ/(epsilon + cbS))); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageR)) { cbR = pvl->directAnswer[tenGageR][0] = (5.0f*cbA*cbB - 27.0f*cbC - 2.0f*cbA*cbS)/54.0f; } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTheta)) { cbQQQ = cbQ*cbQ*cbQ; tmp0 = AIR_CAST(gage_t, cbR/(epsilon + sqrt(cbQQQ))); tmp0 = AIR_CLAMP(-1.0f, tmp0, 1.0f); pvl->directAnswer[tenGageTheta][0] = AIR_CAST(gage_t, acos(tmp0)/AIR_PI); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageEvec)) { /* we do the longer process to get eigenvectors, and in the process we always find the eigenvalues, whether or not they were asked for */ #if GAGE_TYPE_FLOAT tenEigensolve_f(evalAns, evecAns, tenAns); #else tenEigensolve_d(evalAns, evecAns, tenAns); #endif } else if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageEval)) { /* else eigenvectors are NOT needed, but eigenvalues ARE needed */ #if GAGE_TYPE_FLOAT tenEigensolve_f(evalAns, NULL, tenAns); #else tenEigensolve_d(evalAns, NULL, tenAns); #endif } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTensorGrad)) { /* done if doD1 */ /* still have to set up pointer variables that item answers below will rely on as short-cuts */ vecTmp = pvl->directAnswer[tenGageTensorGrad]; gradDtA = vecTmp + 1*3; gradDtB = vecTmp + 2*3; gradDtC = vecTmp + 3*3; gradDtD = vecTmp + 4*3; gradDtE = vecTmp + 5*3; gradDtF = vecTmp + 6*3; TEN_T_SET(gradDdXYZ + 0*7, tenAns[0], gradDtA[0], gradDtB[0], gradDtC[0], gradDtD[0], gradDtE[0], gradDtF[0]); TEN_T_SET(gradDdXYZ + 1*7, tenAns[0], gradDtA[1], gradDtB[1], gradDtC[1], gradDtD[1], gradDtE[1], gradDtF[1]); TEN_T_SET(gradDdXYZ + 2*7, tenAns[0], gradDtA[2], gradDtB[2], gradDtC[2], gradDtD[2], gradDtE[2], gradDtF[2]); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTensorGradMag)) { vecTmp = pvl->directAnswer[tenGageTensorGradMag]; vecTmp[0] = AIR_CAST(gage_t, sqrt(TEN_T_DOT(gradDdXYZ + 0*7, gradDdXYZ + 0*7))); vecTmp[1] = AIR_CAST(gage_t, sqrt(TEN_T_DOT(gradDdXYZ + 1*7, gradDdXYZ + 1*7))); vecTmp[2] = AIR_CAST(gage_t, sqrt(TEN_T_DOT(gradDdXYZ + 2*7, gradDdXYZ + 2*7))); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTensorGradMag)) { pvl->directAnswer[tenGageTensorGradMagMag][0] = AIR_CAST(gage_t, ELL_3V_LEN(vecTmp)); } /* --- Trace --- */ if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTraceGradVec)) { vecTmp = pvl->directAnswer[tenGageTraceGradVec]; ELL_3V_ADD3(vecTmp, gradDtA, gradDtD, gradDtF); ELL_3V_SCALE(gradCbA, -1, vecTmp); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTraceGradMag)) { magTmp = pvl->directAnswer[tenGageTraceGradMag][0] = AIR_CAST(gage_t, ELL_3V_LEN(vecTmp)); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageTraceNormal)) { ELL_3V_SCALE(pvl->directAnswer[tenGageTraceNormal], 1.0f/(epsilon + magTmp), vecTmp); } /* --- B --- */ if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageBGradVec)) { gradCbB = vecTmp = pvl->directAnswer[tenGageBGradVec]; ELL_3V_SCALE_ADD6(vecTmp, dtD + dtF, gradDtA, -2.0f*dtB, gradDtB, -2.0f*dtC, gradDtC, dtA + dtF, gradDtD, -2.0f*dtE, gradDtE, dtA + dtD, gradDtF); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageBGradMag)) { magTmp = pvl->directAnswer[tenGageBGradMag][0] = AIR_CAST(gage_t, ELL_3V_LEN(vecTmp)); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageBNormal)) { ELL_3V_SCALE(pvl->directAnswer[tenGageBNormal], 1.0f/(epsilon + magTmp), vecTmp); } /* --- Det --- */ if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageDetGradVec)) { vecTmp = pvl->directAnswer[tenGageDetGradVec]; ELL_3V_SCALE_ADD6(vecTmp, dtD*dtF - dtE*dtE, gradDtA, 2.0f*(dtC*dtE - dtB*dtF), gradDtB, 2.0f*(dtB*dtE - dtC*dtD), gradDtC, dtA*dtF - dtC*dtC, gradDtD, 2.0f*(dtB*dtC - dtA*dtE), gradDtE, dtA*dtD - dtB*dtB, gradDtF); ELL_3V_SCALE(gradCbC, -1, vecTmp); } if (GAGE_QUERY_ITEM_TEST(pvl->query, tenGageDetGradMag)) { magTmp = pvl->directAnswer[tenGageDetGradMag][0] = AIR_CAST(float, ELL_3V_LEN(vecTmp)); }