/// <summary> /// /// </summary> /// <param name="parallel"></param> /// <returns></returns> public static GridField3d <double> GetDivergence(this GridField3d <Vec3d> field, bool parallel = false) { var result = GridField3d.Double.Create(field); GetDivergence(field, result, parallel); return(result); }
/// <summary> /// /// </summary> /// <param name="parallel"></param> /// <returns></returns> public static GridField3d <Vec3d> GetGradient(this GridField3d <double> field, bool parallel = false) { var result = GridField3d.Vec3d.Create(field); GetGradient(field, result, parallel); return(result); }
/// <summary> /// /// </summary> /// <param name="parallel"></param> /// <returns></returns> public static GridField3d <double> GetLaplacian(this GridField3d <double> field, bool parallel = false) { var result = GridField3d.Double.Create(field); GetLaplacian(field, result, parallel); return(result); }
/// <summary> /// /// </summary> /// <typeparam name="U"></typeparam> /// <param name="other"></param> /// <param name="converter"></param> /// <param name="parallel"></param> /// <returns></returns> public GridField3d <T> CreateCopy(GridField3d <T> other) { var result = Create(other); result.Set(other); return(result); }
/// <summary> /// /// </summary> /// <typeparam name="U"></typeparam> /// <param name="other"></param> /// <param name="converter"></param> /// <param name="parallel"></param> /// <returns></returns> public GridField3d <T> Create <U>(GridField3d <U> other) where U : struct { var result = Create((Grid3d)other); result.SampleMode = other.SampleMode; return(result); }
/// <summary> /// /// </summary> /// <typeparam name="U"></typeparam> /// <param name="other"></param> /// <param name="converter"></param> /// <param name="parallel"></param> /// <returns></returns> public GridField3d <T> CreateCopy <U>(GridField3d <U> other, Func <U, T> converter, bool parallel = false) where U : struct { var result = Create(other); other.Convert(converter, result, parallel); return(result); }
/// <summary> /// Sets this field to the values of another. /// </summary> /// <param name="other"></param> /// <param name="parallel"></param> public void Sample(GridField3d <T> other, bool parallel = false) { if (ResolutionEquals(other)) { _values.Set(other._values); return; } this.Sample((IField3d <T>)other, parallel); }
/* * /// <summary> * /// * /// </summary> * /// <typeparam name="F"></typeparam> * /// <typeparam name="T"></typeparam> * /// <param name="path"></param> * /// <param name="mapper"></param> * /// <param name="domain"></param> * /// <param name="wrapX"></param> * /// <param name="wrapY"></param> * /// <param name="wrapZ"></param> * /// <returns></returns> * public static F CreateFromImageStack<F, T>(string path, Func<Color, T> mapper, Domain3d domain, FieldWrapMode wrapX = FieldWrapMode.Clamp, FieldWrapMode wrapY = FieldWrapMode.Clamp, FieldWrapMode wrapZ = FieldWrapMode.Clamp) * where F : Field3d<T> * { * throw new NotImplementedException(); * } * * * /// <summary> * /// * /// </summary> * /// <param name="bitmaps"></param> * /// <param name="mapper"></param> * /// <param name="domain"></param> * /// <param name="wrapX"></param> * /// <param name="wrapY"></param> * /// <param name="wrapZ"></param> * /// <returns></returns> * public static F CreateFromImageStack<F, T>(IReadOnlyList<Bitmap> bitmaps, Func<Color, T> mapper, Domain3d domain, FieldWrapMode wrapX = FieldWrapMode.Clamp, FieldWrapMode wrapY = FieldWrapMode.Clamp, FieldWrapMode wrapZ = FieldWrapMode.Clamp) * where F : Field3d<T> * { * var bmp0 = bitmaps[0]; * int nx = bmp0.Width; * int ny = bmp0.Height; * int nz = bitmaps.Count; * * var result = (F)Activator.CreateInstance(typeof(F), new object[] { domain, nx, ny, nz, wrapX, wrapY, wrapZ }); * FieldIO.ReadFromImageStack<T>(result, bitmaps, mapper); * * return result; * } * * * /// <summary> * /// * /// </summary> * /// <typeparam name="F"></typeparam> * /// <typeparam name="T"></typeparam> * /// <param name="path"></param> * /// <param name="mapper"></param> * /// <param name="domain"></param> * /// <param name="wrapX"></param> * /// <param name="wrapY"></param> * /// <returns></returns> * public static F CreateFromImage<F, T>(string path, Func<Color, T> mapper, Domain2d domain, FieldWrapMode wrapX = FieldWrapMode.Clamp, FieldWrapMode wrapY = FieldWrapMode.Clamp) * where F : Field2d<T> * { * using (Bitmap bmp = new Bitmap(path)) * { * return CreateFromImage<F,T>(bmp, mapper, domain, wrapX, wrapX); * } * } * * * /// <summary> * /// * /// </summary> * /// <typeparam name="F"></typeparam> * /// <typeparam name="T"></typeparam> * /// <param name="bitmap"></param> * /// <param name="mapper"></param> * /// <param name="domain"></param> * /// <param name="wrapX"></param> * /// <param name="wrapY"></param> * /// <returns></returns> * public static F CreateFromImage<F, T>(Bitmap bitmap, Func<Color, T> mapper, Domain2d domain, FieldWrapMode wrapX = FieldWrapMode.Clamp, FieldWrapMode wrapY = FieldWrapMode.Clamp) * where F : Field2d<T> * { * int nx = bitmap.Width; * int ny = bitmap.Height; * * var result = (F)Activator.CreateInstance(typeof(F), new object[] { domain, nx, ny, wrapX, wrapY}); * FieldIO.ReadFromImage<T>(result, bitmap, mapper); * * return result; * } */ /// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="bitmaps"></param> /// <param name="field"></param> /// <param name="mapper"></param> public static void ReadFromImageStack <T>(IEnumerable <Bitmap> bitmaps, GridField3d <T> field, Func <Color, T> mapper) where T : struct { int nxy = field.CountXY; int count = 0; Parallel.ForEach(bitmaps, bitmap => { ReadFromImage(bitmap, field.Values, count * nxy, mapper); }); }
/// <summary> /// Sets this field to the values of another. /// </summary> /// <typeparam name="U"></typeparam> /// <param name="other"></param> /// <param name="converter"></param> /// <param name="parallel"></param> public void Sample <U>(GridField3d <U> other, Func <U, T> converter, bool parallel = false) where U : struct { if (ResolutionEquals(other)) { other._values.Convert(converter, _values); return; } this.Sample((IField3d <U>)other, converter, parallel); }
/// <summary> /// /// </summary> public static void GetCurl(this GridField3d <Vec3d> field, Vec3d[] result, bool parallel = false) { // implementation reference // http://www.math.harvard.edu/archive/21a_spring_09/PDF/13-05-curl-and-divergence.pdf if (parallel) { Parallel.ForEach(Partitioner.Create(0, field.Count), range => Body(range.Item1, range.Item2)); } else { Body(0, field.Count); } void Body(int from, int to) { var vals = field.Values; int nx = field.CountX; int ny = field.CountY; int nz = field.CountZ; int nxy = nx * ny; (var dx, var dy, var dz) = (0.5 / field.Scale); (int di, int dj, int dk) = field.GetBoundaryOffsets(); (int i, int j, int k) = field.IndicesAt(from); for (int index = from; index < to; index++, i++) { if (i == nx) { j++; i = 0; } if (j == ny) { k++; j = 0; } Vec3d tx0 = (i == 0) ? vals[index + di] : vals[index - 1]; Vec3d tx1 = (i == nx - 1) ? vals[index - di] : vals[index + 1]; Vec3d ty0 = (j == 0) ? vals[index + dj] : vals[index - nx]; Vec3d ty1 = (j == ny - 1) ? vals[index - dj] : vals[index + nx]; Vec3d tz0 = (k == 0) ? vals[index + dk] : vals[index - nxy]; Vec3d tz1 = (k == nz - 1) ? vals[index - dk] : vals[index + nxy]; result[index] = new Vec3d( (ty1.Z - ty0.Z) * dy - (tz1.Y - tz0.Y) * dz, (tz1.X - tz0.X) * dz - (tx1.Z - tx0.Z) * dx, (tx1.Y - tx0.Y) * dx - (ty1.X - ty0.X) * dy); } } }
/// <summary> /// Adds the Laplacian of the field to the deltas array. /// http://en.wikipedia.org/wiki/Discrete_Laplace_operator /// </summary> /// <param name="field"></param> /// <param name="deltas"></param> /// <param name="rate"></param> /// <param name="parallel"></param> public static void Diffuse(GridField3d <double> field, double[] deltas, double rate, bool parallel = false) { var vals = field.Values; int nx = field.CountX; int ny = field.CountY; int nz = field.CountZ; int nxy = field.CountXY; (double dx, double dy, double dz) = field.Scale.Components; dx = 1.0 / (dx * dx); dy = 1.0 / (dy * dy); dz = 1.0 / (dz * dz); (int di, int dj, int dk) = field.GetBoundaryOffsets(); Action <Tuple <int, int> > body = range => { (int i, int j, int k) = field.IndicesAt(range.Item1); for (int index = range.Item1; index < range.Item2; index++, i++) { if (i == nx) { j++; i = 0; } if (j == ny) { k++; j = 0; } double tx0 = (i == 0) ? vals[index + di] : vals[index - 1]; double tx1 = (i == nx - 1) ? vals[index - di] : vals[index + 1]; double ty0 = (j == 0) ? vals[index + dj] : vals[index - nx]; double ty1 = (j == ny - 1) ? vals[index - dj] : vals[index + nx]; double tz0 = (k == 0) ? vals[index + dk] : vals[index - nxy]; double tz1 = (k == nz - 1) ? vals[index - dk] : vals[index + nxy]; double t = vals[index] * 2.0; deltas[index] += ((tx0 + tx1 - t) * dx + (ty0 + ty1 - t) * dy + (tz0 + tz1 - t) * dz) * rate; } }; if (parallel) { Parallel.ForEach(Partitioner.Create(0, field.Count), body); } else { body(Tuple.Create(0, field.Count)); } }
/// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="images"></param> /// <param name="field"></param> /// <param name="mapper"></param> public static void ReadFromImageStack <T>(IEnumerable <Bitmap> images, GridField3d <T> field, Func <Color, T> mapper) where T : struct { int nxy = field.CountXY; int index = 0; Parallel.ForEach(images, image => { ReadFromImage(image, field.Values, index, mapper); index += nxy; }); }
/// <summary> /// /// </summary> /// <param name="result"></param> /// <param name="parallel"></param> public static void GetLaplacian(this GridField3d <double> field, double[] result, bool parallel = false) { if (parallel) { Parallel.ForEach(Partitioner.Create(0, field.Count), range => Body(range.Item1, range.Item2)); } else { Body(0, field.Count); } void Body(int from, int to) { var vals = field.Values; int nx = field.CountX; int ny = field.CountY; int nz = field.CountZ; int nxy = nx * ny; (var dx, var dy, var dz) = field.Scale; dx = 1.0 / (dx * dx); dy = 1.0 / (dy * dy); dz = 1.0 / (dz * dz); (int di, int dj, int dk) = field.GetBoundaryOffsets(); (int i, int j, int k) = field.IndicesAt(from); for (int index = from; index < to; index++, i++) { if (i == nx) { j++; i = 0; } if (j == ny) { k++; j = 0; } double tx0 = (i == 0) ? vals[index + di] : vals[index - 1]; double tx1 = (i == nx - 1) ? vals[index - di] : vals[index + 1]; double ty0 = (j == 0) ? vals[index + dj] : vals[index - nx]; double ty1 = (j == ny - 1) ? vals[index - dj] : vals[index + nx]; double tz0 = (k == 0) ? vals[index + dk] : vals[index - nxy]; double tz1 = (k == nz - 1) ? vals[index - dk] : vals[index + nxy]; double t = vals[index] * 2.0; result[index] = (tx0 + tx1 - t) * dx + (ty0 + ty1 - t) * dy + (tz0 + tz1 - t) * dz; } } }
/// <summary> /// /// </summary> /// <param name="field"></param> /// <param name="path"></param> /// <param name="mapper"></param> public static void SaveAsImageStack(GridField3d <T> field, string path, Func <T, Color> mapper) { string dir = Path.GetDirectoryName(path); string name = Path.GetFileNameWithoutExtension(path); string ext = Path.GetExtension(path); Parallel.For(0, field.CountZ, z => { using (Bitmap bmp = new Bitmap(field.CountX, field.CountY, PixelFormat.Format32bppArgb)) { FieldIO.WriteToImage(field, z, bmp, mapper); bmp.Save(String.Format(@"{0}\{1}_{2}{3}", dir, name, z, ext)); } }); }
/// <summary> /// /// </summary> /// <param name="result"></param> /// <param name="parallel"></param> public static void GetGradient(this GridField3d <double> field, Vec3d[] result, bool parallel = false) { if (parallel) { Parallel.ForEach(Partitioner.Create(0, field.Count), range => Body(range.Item1, range.Item2)); } else { Body(0, field.Count); } void Body(int from, int to) { var vals = field.Values; int nx = field.CountX; int ny = field.CountY; int nz = field.CountZ; int nxy = nx * ny; (var dx, var dy, var dz) = (0.5 / field.Scale); (int di, int dj, int dk) = field.GetBoundaryOffsets(); (int i, int j, int k) = field.IndicesAt(from); for (int index = from; index < to; index++, i++) { if (i == nx) { j++; i = 0; } if (j == ny) { k++; j = 0; } double tx0 = (i == 0) ? vals[index + di] : vals[index - 1]; double tx1 = (i == nx - 1) ? vals[index - di] : vals[index + 1]; double ty0 = (j == 0) ? vals[index + dj] : vals[index - nx]; double ty1 = (j == ny - 1) ? vals[index - dj] : vals[index + nx]; double tz0 = (k == 0) ? vals[index + dk] : vals[index - nxy]; double tz1 = (k == nz - 1) ? vals[index - dk] : vals[index + nxy]; result[index] = new Vec3d((tx1 - tx0) * dx, (ty1 - ty0) * dy, (tz1 - tz0) * dz); } } }
/// <summary> /// Writes a layer of the given field to an existing image. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="field"></param> /// <param name="layer"></param> /// <param name="mapper"></param> /// <param name="bitmap"></param> public static void WriteToImage <T>(GridField3d <T> field, int layer, Bitmap bitmap, Func <T, Color> mapper) where T : struct { WriteToImage(field.Values, layer * field.CountXY, bitmap, mapper); }
/// <summary> /// /// </summary> /// <param name="field"></param> public static void SaveAsFGA(GridField3d <Vec3d> field) { // TODO throw new NotImplementedException(); }
/// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="field"></param> /// <param name="layer"></param> /// <param name="mapper"></param> /// <param name="bitmap"></param> public static void ReadFromImage <T>(Bitmap bitmap, GridField3d <T> field, int layer, Func <Color, T> mapper) where T : struct { ReadFromImage(bitmap, field.Values, layer * field.CountXY, mapper); }
/// <summary> /// Adds the Laplacian of the field to the delta field. /// http://en.wikipedia.org/wiki/Discrete_Laplace_operator /// </summary> /// <param name="field"></param> /// <param name="delta"></param> /// <param name="rate"></param> /// <param name="parallel"></param> public static void Diffuse(GridField3d <double> field, GridField3d <double> delta, double rate, bool parallel = false) { Diffuse(field, delta.Values, rate, parallel); }
/// <summary> /// http://micsymposium.org/mics_2011_proceedings/mics2011_submission_30.pdf /// </summary> /// <param name="field"></param> /// <param name="delta"></param> /// <param name="slope"></param> /// <param name="rate"></param> /// <param name="parallel"></param> public static void ErodeThermal(GridField3d <double> field, GridField3d <double> delta, double slope, double rate, bool parallel = false) { ErodeThermal(field, delta.Values, slope, rate, parallel); }
/// <summary> /// /// </summary> /// <param name="point"></param> /// <param name="amount"></param> public static void IncrementAt(this GridField3d <Vec3d> field, GridPoint3d point, Vec3d amount) { FieldUtil.IncrementAt(field, point.Corners, point.Weights, amount); }
/// <inheritdoc/> /// <summary> /// /// </summary> /// <param name="point"></param> /// <param name="value"></param> /// <returns></returns> public static void SetAt(this GridField3d <Vec3d> field, GridPoint3d point, Vec3d value) { FieldUtil.SetAt(field, point.Corners, point.Weights, value); }
/// <summary> /// http://micsymposium.org/mics_2011_proceedings/mics2011_submission_30.pdf /// </summary> /// <param name="field"></param> /// <param name="deltas"></param> /// <param name="slope"></param> /// <param name="rate"></param> /// <param name="parallel"></param> public static void ErodeThermal(GridField3d <double> field, double[] deltas, double slope, double rate, bool parallel = false) { var vals = field.Values; int nx = field.CountX; int ny = field.CountY; int nz = field.CountZ; int nxy = field.CountXY; (double dx, double dy, double dz) = field.Scale.Components; dx = 1.0 / Math.Abs(dx); dy = 1.0 / Math.Abs(dy); dz = 1.0 / Math.Abs(dz); (int di, int dj, int dk) = field.GetBoundaryOffsets(); Action <Tuple <int, int> > body = range => { (int i, int j, int k) = field.IndicesAt(range.Item1); for (int index = range.Item1; index < range.Item2; index++, i++) { if (i == nx) { j++; i = 0; } if (j == ny) { k++; j = 0; } double value = vals[index]; double sum = 0.0; double m, md; //-x m = ((i == 0) ? vals[index + di] : vals[index - 1]) - value; md = Math.Abs(m * dx) - slope; if (md > 0.0) { sum += Math.Sign(m) * md; } //+x m = ((i == nx - 1) ? vals[index - di] : vals[index + 1]) - value; md = Math.Abs(m * dx) - slope; if (md > 0.0) { sum += Math.Sign(m) * md; } //-y m = ((j == 0) ? vals[index + dj] : vals[index - nx]) - value; md = Math.Abs(m * dy) - slope; if (md > 0.0) { sum += Math.Sign(m) * md; } //+y m = ((j == ny - 1) ? vals[index - dj] : vals[index + nx]) - value; md = Math.Abs(m * dy) - slope; if (md > 0.0) { sum += Math.Sign(m) * md; } //-z m = (k == 0) ? vals[index + dk] - value : vals[index - nxy] - value; md = Math.Abs(m * dz) - slope; if (md > 0.0) { sum += Math.Sign(m) * md; } //+z m = ((k == nz - 1) ? vals[index - dk] : vals[index + nxy]) - value; md = Math.Abs(m * dz) - slope; if (md > 0.0) { sum += Math.Sign(m) * md; } deltas[index] += sum * rate; } }; if (parallel) { Parallel.ForEach(Partitioner.Create(0, field.Count), body); } else { body(Tuple.Create(0, field.Count)); } }