double _energyFromImage(pullTask *task, pullPoint *point, /* output */ double egradSum[4]) { char me[]="_energyFromImage"; double energy, grad3[3]; int probed; /* not sure I have the logic for this right int ptrue; if (task->pctx->probeProb < 1 && allowProbeProb) { if (egrad) { ptrue = (0 == task->pctx->iter || airDrandMT_r(task->rng) < task->pctx->probeProb); } else { ptrue = AIR_FALSE; } } else { ptrue = AIR_TRUE; } */ probed = AIR_FALSE; #define MAYBEPROBE \ if (!probed) { \ if (_pullProbe(task, point)) { \ fprintf(stderr, "%s: problem probing!!!\n%s\n", me, biffGetDone(PULL)); \ } \ probed = AIR_TRUE; \ } energy = 0; if (egradSum) { ELL_4V_SET(egradSum, 0, 0, 0, 0); } if (task->pctx->ispec[pullInfoHeight] && !task->pctx->ispec[pullInfoHeight]->constraint && (!task->pctx->ispec[pullInfoHeightLaplacian] || !task->pctx->ispec[pullInfoHeightLaplacian]->constraint)) { MAYBEPROBE; energy += _pullPointScalar(task->pctx, point, pullInfoHeight, grad3, NULL); if (egradSum) { ELL_3V_INCR(egradSum, grad3); } } if (task->pctx->ispec[pullInfoIsovalue] && !task->pctx->ispec[pullInfoIsovalue]->constraint) { /* we're only going towards an isosurface, not constrained to it ==> set up a parabolic potential well around the isosurface */ double val; MAYBEPROBE; val = _pullPointScalar(task->pctx, point, pullInfoIsovalue, grad3, NULL); energy += val*val; if (egradSum) { ELL_3V_SCALE_INCR(egradSum, 2*val, grad3); } } return energy; }
/* ** assign random signs to the vectors and measures the length of their ** mean, as quickly as possible */ static double party(Nrrd *npos, airRandMTState *rstate) { double *pos, mean[3]; unsigned int ii, num, rnd, rndBit; pos = (double *)(npos->data); num = AIR_UINT(npos->axis[1].size); rnd = airUIrandMT_r(rstate); rndBit = 0; ELL_3V_SET(mean, 0, 0, 0); for (ii=0; ii<num; ii++) { if (32 == rndBit) { rnd = airUIrandMT_r(rstate); rndBit = 0; } if (rnd & (1 << rndBit++)) { ELL_3V_SCALE(pos + 3*ii, -1, pos + 3*ii); } ELL_3V_INCR(mean, pos + 3*ii); } ELL_3V_SCALE(mean, 1.0/num, mean); return ELL_3V_LEN(mean); }
/* ******** echoTriMeshSet() ** ** This has to be called any time that the locations of the points are ** changing, even if the connectivity is not changed, because of how ** the bounding box and mean vert position is calculated here. ** ** NB: the TriMesh will directly use the given pos[] and vert[] arrays, ** so don't go freeing them after they've been passed here. */ void echoTriMeshSet(echoObject *trim, int numV, echoPos_t *pos, int numF, int *vert) { int i; if (trim && echoTypeTriMesh == trim->type) { TRIMESH(trim)->numV = numV; TRIMESH(trim)->numF = numF; TRIMESH(trim)->pos = pos; TRIMESH(trim)->vert = vert; ELL_3V_SET(TRIMESH(trim)->min, ECHO_POS_MAX, ECHO_POS_MAX, ECHO_POS_MAX); ELL_3V_SET(TRIMESH(trim)->max, ECHO_POS_MIN, ECHO_POS_MIN, ECHO_POS_MIN); ELL_3V_SET(TRIMESH(trim)->meanvert, 0.0, 0.0, 0.0); for (i=0; i<numV; i++) { ELL_3V_MIN(TRIMESH(trim)->min, TRIMESH(trim)->min, pos + 3*i); ELL_3V_MAX(TRIMESH(trim)->max, TRIMESH(trim)->max, pos + 3*i); ELL_3V_INCR(TRIMESH(trim)->meanvert, pos + 3*i); } ELL_3V_SCALE(TRIMESH(trim)->meanvert, 1.0/numV, TRIMESH(trim)->meanvert); } 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; }