public static float CircleY(Vector vec) { float r = (float)Math.Sqrt(vec[0] * vec[0] + vec[1] * vec[1]) + 0.00001f; //if (r == 0 || Math.Abs(2- r) < 0) // return 0; return (vec[0] + 0.00001f) / r * (float)Math.Exp(-Math.Abs(r - RADIUS)) * 20; //vec[0] / r * (1 - (1- r)*(1 - r)) * 20; }
public static float BowlY(Vector vec) { float r = (float)Math.Sqrt(vec[0] * vec[0] + vec[1] * vec[1]) + 0.00001f; //if (r == 0 || Math.Abs(2- r)<0) // return 0; return (vec[0] + 0.00001f) / r * 20f; }
public SquareMatrix(Vector[] columns) { #if DEBUG foreach (Vector col in columns) Debug.Assert(columns.Length == col.Length); // Only sqare matrices allowed. #endif Columns = columns; }
public SquareMatrix(SquareMatrix m) { #if DEBUG foreach (Vector col in m.Columns) Debug.Assert(m.Columns.Length == col.Length); // Only sqare matrices allowed. #endif Columns = new Vector[m.Columns.Length]; for (int c = 0; c < Columns.Length; ++c) Columns[c] = new Vector(m.Columns[c]); }
public virtual Vector Sample(VectorField field, Vector position) { // Query relevant edges and their weights. Result varies with different grid types. int numCells = NumAdjacentPoints(); float[] weights; int[] indices = FindAdjacentIndices(position, out weights); Debug.Assert(indices.Length == weights.Length); Vector result = new Vector(0, field.NumVectorDimensions); // Add the other weightes grid points. for (int dim = 0; dim < indices.Length; ++dim) { Vector add = field.Sample(indices[dim]); if(add[0] == field.InvalidValue) { return new Vector(field.InvalidValue??float.MaxValue, field.NumVectorDimensions); } result += add * weights[dim]; } return result; }
public override bool InGrid(Vector position) { Debug.Assert(position.Length == Size.Length, "Trying to access " + Size.Length + "D field with " + position.Length + "D index."); //int dims = _timeOrigin == null ? Size.Length : Size.Length - 1; //Vector relPos = position - Origin.ToVec(dims); //for (int dim = 0; dim < dims; ++dim) //{ // if (relPos[dim] < 0 || relPos[dim] > Size[dim] - 1) // return false; //} //if (_timeOrigin != null && (position.T < _timeOrigin || position.T > _timeOrigin + Size.T - 1)) // return false; for (int dim = 0; dim < Size.Length; ++dim) if (position[dim] < Origin[dim] || position[dim] >= Origin[dim] + Size[dim]) return false; return true; }
/// <summary> /// Returns all cell points necessary to interpolate a value at the position. /// </summary> /// <param name="position">The position in either world or grid space.</param> /// <param name="weights">The weights used for linear interpolation.</param> /// <returns>Scalar indices for acessing the grid.</returns> public abstract int[] FindAdjacentIndices(Vector position, out float[] weights);
// private float? _timeOrigin; // private bool _timeDependent = false; //public override float? TimeOrigin //{ // get // { // return _timeOrigin; // } // set // { // //Debug.Assert((_timeDependent) == (value != null), "Please don't mess with time!"); // _timeOrigin = value;// ?? 0; // Origin.T = value ?? Origin.T; // } //} /// <summary> /// Create a new rectlinear grid descriptor. /// </summary> /// <param name="size">Number of cells in each dimension.</param> /// <param name="cellSize">Size of one cell, only used for rendering.</param> public RectlinearGrid(Index size, Vector origin = null, float? timeOrigin = null) { Size = new Index(size); Origin = origin ?? new Vector(0, size.Length); TimeDependant = timeOrigin != null; Origin.T = timeOrigin ?? Origin.T; //_timeDependent = (timeOrigin != null); //TimeOrigin = timeOrigin; }
/// <summary> /// Returns the adjacent grid point indices. /// Indices in ascending order. /// </summary> /// <param name="pos"></param> /// <param name="indices"></param> /// <param name="weights"></param> public override int[] FindAdjacentIndices(Vector pos, out float[] weights) { int numPoints = NumAdjacentPoints(); int[] indices = new int[numPoints]; weights = new float[numPoints]; Vector position = new Vector(pos); Debug.Assert(InGrid(position) || ((Vector)Size + Origin - pos).Min() == 0); Index gridPos = Index.Min((Index)(position - Origin), Size - new Index(1, Size.Length)); Vector relativePos = position - Origin - (Vector)gridPos; // Convert to int. int offsetScale = 1; int index = 0; // Have last dimension running fastest. Compute 1D index. for (int dim = 0; dim < Size.Length; ++dim) { index += offsetScale * gridPos[dim]; offsetScale *= Size[dim]; } // Linear interpolation in N dimensions. for (int point = 0; point < numPoints; ++point) { int stepDim = 1; int pointIndex = index; float pointWeight = 1.0f; // Compute the one dimensional index of each point. for (int dim = 0; dim < Size.Length; ++dim) { // Is the dimth bit set? if ((point & (1 << dim)) > 0) { // Extremum case: The value is on the outmost border. Clip that position. if (gridPos[dim] < Size[dim] - 1) pointIndex += stepDim; pointWeight *= relativePos[dim]; } else { pointWeight *= (1 - relativePos[dim]); } stepDim *= Size[dim]; } // Accumulated all dimensions. Save value to output arrays. indices[point] = pointIndex; weights[point] = pointWeight; } return indices; }
public override Vector Sample(Vector position) { Vector result = Grid.Sample(this, position); // Work against the small numerical deviations here. Debug.Assert(Math.Abs(result.T - 1) < 0.1f); result[NumVectorDimensions - 1] = 1; return result; }
public Vector(Vector copy) { _data = (float[])copy.Data.Clone(); }
public override float Sample(Vector position) { Debug.Assert(_operationsAllowed, "The field data is not scaled to its grid yet."); float time = position.T - Grid.TimeOrigin??0; Vector samplePos = position; Debug.Assert(time >= 0 && time < _slices.Length); Vector slicePos = new Vector(samplePos.Length - 1); Array.Copy(samplePos.Data, slicePos.Data, slicePos.Length); float valueT = _slices[(int)time].Sample(slicePos); float valueTNext = _slices[Math.Min((int)time + 1, NumTimeSlices-1)].Sample(slicePos); float t = time - (int)time; return (1 - t) * valueT + t * valueTNext; }
public static Vector operator *(Vector a, Vector b) { Debug.Assert(a.Length == b.Length); Vector prod = new Vector(a); for (int dim = 0; dim < a.Length; ++dim) prod[dim] *= b[dim]; return prod; }
public static Vector operator /(Vector a, Vector b) { Debug.Assert(a.Length == b.Length); Vector quot = new Vector(a); for (int dim = 0; dim < a.Length; ++dim) quot[dim] /= b[dim]; return quot; }
public virtual float Sample(ScalarField field, Vector position) { // Query relevant edges and their weights. Reault varies with different grid types. int numCells = NumAdjacentPoints(); float[] weights; int[] indices = FindAdjacentIndices(position, out weights); Debug.Assert(indices.Length == weights.Length); // Start with the first grid point. float result = field[indices[0]]; if (result == field.InvalidValue) return (float)field.InvalidValue; result *= weights[0]; // Add the other weightes grid points. for (int dim = 1; dim < indices.Length; ++dim) { if (field[indices[dim]] == field.InvalidValue) return (float)field.InvalidValue; result += weights[dim] * field[indices[dim]]; } return result; }
public static Vector operator -(Vector a) { Vector neg = new Vector(a); for (int dim = 0; dim < a.Length; ++dim) neg[dim] = -neg[dim]; return neg; }
public static Vector operator -(Vector a, Vector b) { Debug.Assert(a.Length == b.Length); Vector diff = new Vector(a); for (int dim = 0; dim < a.Length; ++dim) diff[dim] -= b[dim]; return diff; }
public static Vector operator +(Vector a, Vector b) { Debug.Assert(a.Length == b.Length); Vector sum = new Vector(a); for (int dim = 0; dim < a.Length; ++dim) sum[dim] += b[dim]; return sum; }
public abstract bool InGrid(Vector pos);
public override bool IsValid(Vector pos) { return ScalarsAsSFU[0].TimeSlices[0].Grid.InGrid(pos) && Scalars[0].IsValid(pos); }
public static Vector operator /(Vector a, float b) { Vector quot = new Vector(a); for (int dim = 0; dim < a.Length; ++dim) quot[dim] /= b; return quot; }
public static Vector operator *(Vector a, float b) { Vector prod = new Vector(a); for(int dim = 0; dim < a.Length; ++dim) prod[dim] *= b; return prod; }
public override bool IsValid(Vector pos) { float[] weights; int[] neighbors = _slices[0].Grid.FindAdjacentIndices(pos, out weights); foreach (int neighbor in neighbors) if (this[neighbor] == InvalidValue) return false; return true; }
public static float Dot(Vector a, Vector b) { return (a * b).Sum(); }
public override Vector SampleDerivative(Vector position) { Debug.Assert(_operationsAllowed, "The field data is not scaled to its grid yet."); float time = position.T; // Get spacial sample position in grid space. Vector samplePos = position; Debug.Assert(time >= 0 && time < _slices.Length); Vector slicePos = new Vector(samplePos.Length - 1); Array.Copy(samplePos.Data, slicePos.Data, slicePos.Length); // Sample data in current and next time slice. Vector valueT = _slices[(int)time].SampleDerivative(slicePos); Vector valueTNext = _slices[Math.Min((int)time + 1, NumTimeSlices - 1)].SampleDerivative(slicePos); float t = time - (int)time; Vector spaceGrad = (1 - t) * valueT + t * valueTNext; // Add derivative in last dimension - always 0. Vector gradient = new Vector(spaceGrad.Length + 1); Array.Copy(spaceGrad.Data, gradient.Data, spaceGrad.Length); gradient[spaceGrad.Length] = 1; return gradient; }
public Vector Abs() { Vector abs = new Vector(this); for (int dim = 0; dim < Length; ++dim) abs[dim] = Math.Abs(abs[dim]); return abs; }
/// <summary> /// Access field by scalar index. /// </summary> public override Vector Sample(int index) { Debug.Assert(index >= 0 && index < Size.Product(), "Index out of bounds: " + index + " not within [0, " + Size.Product() + ")."); Vector vec = new Vector(NumVectorDimensions); for (int dim = 0; dim < _scalarsUnsteady.Length; ++dim) vec[dim] = Scalars[dim][index]; // Unsteady! vec[NumVectorDimensions - 1] = 1; return vec; }
public Vector Normalized() { Vector norm = new Vector(this); norm.Normalize(); return norm; }
public virtual void ScaleToGrid(Vector scale) { Debug.Assert(Scalars.Length == scale.Length); for (int dim = 0; dim < Scalars.Length; ++dim) { ScalarFieldUnsteady field = _scalarsUnsteady[dim]; field.ScaleToGrid(scale[dim]); } SpreadInvalidValue(); }
/// <summary> /// Convert first N elements to a VecN. If less, fill with zeros. /// </summary> public Vector ToVec(int N) { Vector result = new Vector(0,N); for (int dim = 0; dim < Math.Min(Length, N); ++dim) result[dim] = this[dim]; return result; }