void get_value_pair(int i, int j, int k, out double a, out double b) { float fa, fb; Grid.get_x_pair(i, j, k, out fa, out fb); if (fa == Invalid) { Vector3d p = grid_position(i, j, k); a = AnalyticF.Value(ref p); Grid[i, j, k] = (float)a; } else { a = fa; } if (fb == Invalid) { Vector3d p = grid_position(i + 1, j, k); b = AnalyticF.Value(ref p); Grid[i + 1, j, k] = (float)b; } else { b = fb; } }
public double Value(ref Vector3d pt) { Vector3d gridPt = new Vector3d( ((pt.x - GridOrigin.x) / CellSize), ((pt.y - GridOrigin.y) / CellSize), ((pt.z - GridOrigin.z) / CellSize)); // clamp to grid if (gridPt.x < 0 || gridPt.x >= Grid.ni - 1 || gridPt.y < 0 || gridPt.y >= Grid.nj - 1 || gridPt.z < 0 || gridPt.z >= Grid.nk - 1) { return(Outside); } // compute integer coordinates int x0 = (int)gridPt.x; int y0 = (int)gridPt.y, y1 = y0 + 1; int z0 = (int)gridPt.z, z1 = z0 + 1; // convert double coords to [0,1] range double fAx = gridPt.x - (double)x0; double fAy = gridPt.y - (double)y0; double fAz = gridPt.z - (double)z0; double OneMinusfAx = 1.0 - fAx; // compute trilinear interpolant. The code below tries to do this with the fewest // number of variables, in hopes that optimizer will be clever about re-using registgers, etc. // Commented code at bottom is fully-expanded version. // [TODO] it is possible to implement lerps here as a+(b-a)*t, saving a multiply and a variable. // This is numerically worse, but since the grid values are floats and // we are computing in doubles, does it matter? double xa, xb; Grid.get_x_pair(x0, y0, z0, out xa, out xb); double yz = (1 - fAy) * (1 - fAz); double sum = (OneMinusfAx * xa + fAx * xb) * yz; Grid.get_x_pair(x0, y0, z1, out xa, out xb); yz = (1 - fAy) * (fAz); sum += (OneMinusfAx * xa + fAx * xb) * yz; Grid.get_x_pair(x0, y1, z0, out xa, out xb); yz = (fAy) * (1 - fAz); sum += (OneMinusfAx * xa + fAx * xb) * yz; Grid.get_x_pair(x0, y1, z1, out xa, out xb); yz = (fAy) * (fAz); sum += (OneMinusfAx * xa + fAx * xb) * yz; return(sum); // fV### is grid cell corner index //return // fV000 * (1 - fAx) * (1 - fAy) * (1 - fAz) + // fV001 * (1 - fAx) * (1 - fAy) * (fAz) + // fV010 * (1 - fAx) * (fAy) * (1 - fAz) + // fV011 * (1 - fAx) * (fAy) * (fAz) + // fV100 * (fAx) * (1 - fAy) * (1 - fAz) + // fV101 * (fAx) * (1 - fAy) * (fAz) + // fV110 * (fAx) * (fAy) * (1 - fAz) + // fV111 * (fAx) * (fAy) * (fAz); }