Exemplo n.º 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="parallel"></param>
        /// <returns></returns>
        public static GridField2d <Vec2d> GetGradient(this GridField2d <double> field, bool parallel = false)
        {
            var result = GridField2d.Vec2d.Create(field);

            GetGradient(field, result, parallel);
            return(result);
        }
Exemplo n.º 2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="parallel"></param>
        /// <returns></returns>
        public static GridField2d <Vec2d> GetLaplacian(this GridField2d <Vec2d> field, bool parallel = false)
        {
            var result = GridField2d.Vec2d.Create(field);

            GetLaplacian(field, result, parallel);
            return(result);
        }
Exemplo n.º 3
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="U"></typeparam>
        /// <param name="other"></param>
        /// <param name="converter"></param>
        /// <param name="parallel"></param>
        /// <returns></returns>
        public GridField2d <T> CreateCopy(GridField2d <T> other)
        {
            var result = Create(other);

            result.Set(other);
            return(result);
        }
Exemplo n.º 4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="parallel"></param>
        /// <returns></returns>
        public static GridField2d <double> GetCurl(this GridField2d <Vec2d> field, bool parallel = false)
        {
            var result = GridField2d.Double.Create(field);

            GetCurl(field, result, parallel);
            return(result);
        }
Exemplo n.º 5
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="U"></typeparam>
        /// <param name="other"></param>
        /// <param name="converter"></param>
        /// <param name="parallel"></param>
        /// <returns></returns>
        public GridField2d <T> Create <U>(GridField2d <U> other)
            where U : struct
        {
            var result = Create((Grid2d)other);

            result.SampleMode = other.SampleMode;
            return(result);
        }
Exemplo n.º 6
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="field"></param>
 /// <param name="path"></param>
 /// <param name="mapper"></param>
 public static void SaveAsImage(GridField2d <T> field, string path, Func <T, Color> mapper)
 {
     using (Bitmap bmp = new Bitmap(field.CountX, field.CountY, PixelFormat.Format32bppArgb))
     {
         FieldIO.WriteToImage(field, bmp, mapper);
         bmp.Save(path);
     }
 }
Exemplo n.º 7
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="U"></typeparam>
        /// <param name="other"></param>
        /// <param name="converter"></param>
        /// <param name="parallel"></param>
        /// <returns></returns>
        public GridField2d <T> CreateCopy <U>(GridField2d <U> other, Func <U, T> converter, bool parallel = false)
            where U : struct
        {
            var result = Create(other);

            other.Convert(converter, result, parallel);
            return(result);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Sets this field to the values of another.
        /// </summary>
        /// <param name="other"></param>
        /// <param name="parallel"></param>
        public void Sample(GridField2d <T> other, bool parallel = false)
        {
            if (ResolutionEquals(other))
            {
                _values.Set(other._values);
                return;
            }

            this.Sample((IField2d <T>)other, parallel);
        }
Exemplo n.º 9
0
        /// <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>(GridField2d <U> other, Func <U, T> converter, bool parallel = false)
            where U : struct
        {
            if (ResolutionEquals(other))
            {
                other._values.Convert(converter, _values);
                return;
            }

            this.Sample((IField2d <U>)other, converter, parallel);
        }
Exemplo n.º 10
0
        /// <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(GridField2d <double> field, double[] deltas, double rate, bool parallel = false)
        {
            var vals = field.Values;
            int nx   = field.CountX;
            int ny   = field.CountY;

            (double dx, double dy) = field.Scale.Components;
            dx = 1.0 / (dx * dx);
            dy = 1.0 / (dy * dy);

            (int di, int dj) = field.GetBoundaryOffsets();

            Action <Tuple <int, int> > body = range =>
            {
                (int i, int j) = field.IndicesAt(range.Item1);

                for (int index = range.Item1; index < range.Item2; index++, i++)
                {
                    if (i == nx)
                    {
                        j++; i = 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 t = vals[index] * 2.0;
                    deltas[index] += ((tx0 + tx1 - t) * dx + (ty0 + ty1 - t) * dy) * rate;
                }
            };

            if (parallel)
            {
                Parallel.ForEach(Partitioner.Create(0, field.Count), body);
            }
            else
            {
                body(Tuple.Create(0, field.Count));
            }
        }
Exemplo n.º 11
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="result"></param>
        /// <param name="parallel"></param>
        public static void GetLaplacian(this GridField2d <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;

                (var dx, var dy) = field.Scale;
                dx = 1.0 / (dx * dx);
                dy = 1.0 / (dy * dy);

                (int di, int dj) = field.GetBoundaryOffsets();
                (int i, int j)   = field.IndicesAt(from);

                for (int index = from; index < to; index++, i++)
                {
                    if (i == nx)
                    {
                        j++; i = 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 t = vals[index] * 2.0;
                    result[index] = (tx0 + tx1 - t) * dx + (ty0 + ty1 - t) * dy;
                }
            }
        }
Exemplo n.º 12
0
        /// <summary>
        ///
        /// </summary>
        public static void GetCurl(this GridField2d <Vec2d> field, double[] 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;

                (var tx, var ty) = (0.5 / field.Scale);
                (int di, int dj) = field.GetBoundaryOffsets();
                (int i, int j)   = field.IndicesAt(from);

                for (int index = from; index < to; index++, i++)
                {
                    if (i == nx)
                    {
                        j++; i = 0;
                    }

                    Vec2d tx0 = (i == 0) ? vals[index + di] : vals[index - 1];
                    Vec2d tx1 = (i == nx - 1) ? vals[index - di] : vals[index + 1];

                    Vec2d ty0 = (j == 0) ? vals[index + dj] : vals[index - nx];
                    Vec2d ty1 = (j == ny - 1) ? vals[index - dj] : vals[index + nx];

                    result[index] = (tx1.Y - tx0.Y) * tx - (ty1.X - ty0.X) * ty;
                }
            }
        }
Exemplo n.º 13
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="result"></param>
        /// <param name="parallel"></param>
        public static void GetGradient(this GridField2d <double> field, Vec2d[] 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;

                (var dx, var dy) = (0.5 / field.Scale);
                (int di, int dj) = field.GetBoundaryOffsets();
                (int i, int j)   = field.IndicesAt(from);

                for (int index = from; index < to; index++, i++)
                {
                    if (i == nx)
                    {
                        j++; i = 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];

                    result[index] = new Vec2d((tx1 - tx0) * dx, (ty1 - ty0) * dy);
                }
            }
        }
Exemplo n.º 14
0
        /// <summary>
        /// Calculates L1 (Manhattan) geodesic distance via Dijksta's algorithm as detailed in
        /// http://www.numerical-tours.com/matlab/fastmarching_0_implementing/
        /// </summary>
        /// <param name="cost"></param>
        /// <param name="sources"></param>
        /// <param name="field"></param>
        public static void GeodesicDistanceL1(GridField2d <double> field, IEnumerable <int> sources, IEnumerable <int> exclude = null)
        {
            // TODO handle additonal wrap modes

            var dists = field.Values;
            int nx    = field.CountX;
            int ny    = field.CountY;

            (double dx, double dy) = Vec2d.Abs(field.Scale);

            var queue = new Queue <int>();

            dists.Set(double.PositiveInfinity);

            // enqueue sources
            foreach (int i in sources)
            {
                dists[i] = 0.0;
                queue.Enqueue(i);
            }

            // exclude
            if (exclude != null)
            {
                foreach (int i in exclude)
                {
                    dists[i] = 0.0;
                }
            }

            // breadth first search from sources
            while (queue.Count > 0)
            {
                int i0 = queue.Dequeue();
                var d0 = dists[i0];

                (int x0, int y0) = field.IndicesAt(i0);

                // -x
                if (x0 > 0)
                {
                    TryUpdate(d0 + dx, i0 - 1);
                }

                // +x
                if (x0 < nx - 1)
                {
                    TryUpdate(d0 + dx, i0 + 1);
                }

                // -y
                if (y0 > 0)
                {
                    TryUpdate(d0 + dy, i0 - nx);
                }

                // +y
                if (y0 < ny - 1)
                {
                    TryUpdate(d0 + dy, i0 + nx);
                }

                // add to queue if less than current min
                void TryUpdate(double distance, int index)
                {
                    if (distance < dists[index])
                    {
                        dists[index] = distance;
                        queue.Enqueue(index);
                    }
                }
            }
        }
Exemplo n.º 15
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="field"></param>
        /// <param name="cost"></param>
        /// <param name="sources"></param>
        /// <param name="exclude"></param>
        public static void GeodesicDistanceL2(GridField2d <double> field, double[] cost, IEnumerable <int> sources, IEnumerable <int> exclude = null)
        {
            // TODO handle additonal wrap modes

            var dists = field.Values;
            var nx    = field.CountX;
            var ny    = field.CountY;

            (var dx, var dy) = Vec2d.Abs(field.Scale);
            var eikonal = new Eikonal2d(dx, dy);

            var queue = new PriorityQueue <double, int>();

            dists.Set(double.PositiveInfinity);

            // enqueue sources
            foreach (int i in sources)
            {
                dists[i] = 0.0;
                queue.Insert(0.0, i);
            }

            // exclude
            if (exclude != null)
            {
                foreach (var i in exclude)
                {
                    dists[i] = 0.0;
                }
            }

            // breadth first search from sources
            while (queue.Count > 0)
            {
                (double d0, int i0) = queue.RemoveMin();
                if (dists[i0] < d0)
                {
                    continue;                 // skip if lower value has been assigned
                }
                (int x0, int y0) = field.IndicesAt(i0);

                if (x0 > 0)
                {
                    X(i0 - 1);
                }
                if (x0 < nx - 1)
                {
                    X(i0 + 1);
                }

                if (y0 > 0)
                {
                    Y(i0 - nx);
                }
                if (y0 < ny - 1)
                {
                    Y(i0 + nx);
                }

                // process x neighbor
                void X(int index)
                {
                    var d1 = dists[index];

                    if (d1 < d0)
                    {
                        return;          // no backtracking
                    }
                    double d2;
                    double minY = GetMinY(index); // will return infinity if neither neighbor has been visited

                    if (minY > double.MaxValue || !eikonal.Evaluate(d0, minY, cost[index], out d2))
                    {
                        d2 = d0 + dx * cost[index];
                    }

                    // add to queue if less than current min
                    if (d2 < d1)
                    {
                        dists[index] = d2;
                        queue.Insert(d2, index);
                    }
                }

                // process y neighbor
                void Y(int index)
                {
                    var d1 = dists[index];

                    if (d1 < d0)
                    {
                        return;          // no backtracking
                    }
                    double d2;
                    double minX = GetMinX(index); // will return infinity if neither neighbor has been visited

                    if (minX > double.MaxValue || !eikonal.Evaluate(minX, d0, cost[index], out d2))
                    {
                        d2 = d0 + dy * cost[index];
                    }

                    // add to queue if less than current min
                    if (d2 < d1)
                    {
                        dists[index] = d2;
                        queue.Insert(d2, index);
                    }
                }

                // returns the minimum adjacent value in the x
                double GetMinX(int index)
                {
                    if (x0 == 0)
                    {
                        return(dists[index + 1]);
                    }
                    else if (x0 == nx - 1)
                    {
                        return(dists[index - 1]);
                    }
                    return(Math.Min(dists[index - 1], dists[index + 1]));
                }

                // returns the minimum adjacent value in the y
                double GetMinY(int index)
                {
                    if (y0 == 0)
                    {
                        return(dists[index + nx]);
                    }
                    else if (y0 == ny - 1)
                    {
                        return(dists[index - nx]);
                    }
                    return(Math.Min(dists[index - nx], dists[index + nx]));
                }
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// Calculates L1 (Manhattan) geodesic distance via Dijksta's algorithm as detailed in
        /// http://www.numerical-tours.com/matlab/fastmarching_0_implementing/
        /// </summary>
        /// <param name="cost"></param>
        /// <param name="sources"></param>
        /// <param name="result"></param>
        public static void GeodesicDistanceL1(GridField2d <double> field, double[] cost, IEnumerable <int> sources, IEnumerable <int> exclude = null)
        {
            // TODO handle additonal wrap modes

            var dists = field.Values;
            int nx    = field.CountX;
            int ny    = field.CountY;

            (double dx, double dy) = Vec2d.Abs(field.Scale);

            var queue = new PriorityQueue <double, int>();

            dists.Set(double.PositiveInfinity);

            // enqueue sources
            foreach (int i in sources)
            {
                dists[i] = 0.0;
                queue.Insert(0.0, i);
            }

            // exclude
            if (exclude != null)
            {
                foreach (int i in exclude)
                {
                    dists[i] = 0.0;
                }
            }

            // breadth first search from sources
            while (queue.Count > 0)
            {
                (var d0, int i0) = queue.RemoveMin();
                if (dists[i0] < d0)
                {
                    continue;                 // skip if lower value has been assigned
                }
                (int x0, int y0) = field.IndicesAt(i0);

                // -x
                if (x0 > 0)
                {
                    TryUpdate(d0 + dx * cost[i0 - 1], i0 - 1);
                }

                // +x
                if (x0 < nx - 1)
                {
                    TryUpdate(d0 + dx * cost[i0 + 1], i0 + 1);
                }

                // -y
                if (y0 > 0)
                {
                    TryUpdate(d0 + dy * cost[i0 - nx], i0 - nx);
                }

                // +y
                if (y0 < ny - 1)
                {
                    TryUpdate(d0 + dy * cost[i0 + nx], i0 + nx);
                }

                // add to queue if less than current min
                void TryUpdate(double distance, int index)
                {
                    if (distance < dists[index])
                    {
                        dists[index] = distance;
                        queue.Insert(distance, index);
                    }
                }
            }
        }
Exemplo n.º 17
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="cost"></param>
        /// <param name="sources"></param>
        /// <param name="tags"></param>
        /// <param name="result"></param>
        private static void GeodesicDistanceL2Impl(GridField2d <double> cost, IEnumerable <int> sources, bool[] tags, double[] result)
        {
            // TODO handle wrap modes

            var costVals = cost.Values;
            var nx       = cost.CountX;
            var ny       = cost.CountY;

            (var dx, var dy) = Vec2d.Abs(cost.Scale).Components;

            var pq      = new PriorityQueue <(double, int)>((a, b) => a.Item1.CompareTo(b.Item1));
            var eikonal = new Eikonal2d(dx, dy);

            result.SetRange(double.PositiveInfinity, 0, cost.Count);

            // enqueue sources
            foreach (int index in sources)
            {
                result[index] = 0.0;
                pq.Insert((0.0, index));
            }

            // breadth first search from sources
            while (pq.Count > 0)
            {
                (double dist0, int index0) = pq.RemoveMin();

                if (tags[index0])
                {
                    continue;               // skip if already accepted
                }
                tags[index0] = true;

                (int i0, int j0) = cost.IndicesAt(index0);

                // x neigbours
                for (int i = -1; i < 2; i += 2)
                {
                    if (!SlurMath.Contains(i0 + i, nx))
                    {
                        continue;                                 // skip if out of bounds
                    }
                    int index1 = index0 + i;

                    if (!tags[index1])
                    {
                        double minAdj =
                            (j0 == 0) ? result[index1 + nx] :
                            (j0 == ny - 1) ? result[index1 - nx] :
                            Math.Min(result[index1 - nx], result[index1 + nx]);

                        double dist1 =
                            (minAdj > double.MaxValue) ? dist0 + dx * costVals[index1] :
                            eikonal.Evaluate(dist0, minAdj, costVals[index1]);

                        if (dist1 < result[index1])
                        {
                            result[index1] = dist1;
                            pq.Insert((dist1, index1));
                        }
                    }
                }

                // y neigbours
                for (int j = -1; j < 2; j += 2)
                {
                    if (!SlurMath.Contains(j0 + j, ny))
                    {
                        continue;                                 // skip if out of bounds
                    }
                    int index1 = index0 + j * nx;

                    if (!tags[index1])
                    {
                        double minAdj =
                            (i0 == 0) ? result[index1 + 1] :
                            (i0 == nx - 1) ? result[index1 - 1] :
                            Math.Min(result[index1 - 1], result[index1 + 1]);

                        double dist1 =
                            (minAdj > double.MaxValue) ? dist0 + dy * costVals[index1] :
                            eikonal.Evaluate(minAdj, dist0, costVals[index1]);

                        if (dist1 < result[index1])
                        {
                            result[index1] = dist1;
                            pq.Insert((dist1, index1));
                        }
                    }
                }
            }
        }
Exemplo n.º 18
0
 /// <summary>
 /// Calculates L2 (Euclidean) geodesic distance via the Fast marching algorithm as detailed in
 /// http://www.numerical-tours.com/matlab/fastmarching_0_implementing/
 /// </summary>
 /// <param name="cost"></param>
 /// <param name="sources"></param>
 /// <param name="tags"></param>
 /// <param name="result"></param>
 public static void GeodesicDistanceL2(GridField2d <double> cost, IEnumerable <int> sources, bool[] tags, double[] result)
 {
     tags.Clear();
     GeodesicDistanceL2Impl(cost, sources, tags, result);
 }
Exemplo n.º 19
0
        /// <summary>
        /// Calculates L2 (Euclidean) geodesic distance via the Fast marching algorithm as detailed in
        /// http://www.numerical-tours.com/matlab/fastmarching_0_implementing/
        /// </summary>
        /// <param name="cost"></param>
        /// <param name="sources"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static void GeodesicDistanceL2(GridField2d <double> cost, IEnumerable <int> sources, double[] result)
        {
            var tags = new bool[cost.Count];

            GeodesicDistanceL2Impl(cost, sources, tags, result);
        }
Exemplo n.º 20
0
        /// <summary>
        /// Calculates L2 (Euclidean) geodesic distance via the Fast marching algorithm as detailed in
        /// http://www.numerical-tours.com/matlab/fastmarching_0_implementing/
        /// </summary>
        /// <param name="cost"></param>
        /// <param name="sources"></param>
        /// <param name="result"></param>
        public static void GeodesicDistanceL2(GridField2d <double> cost, IEnumerable <int> sources, GridField2d <double> result)
        {
            var states = new bool[cost.Count];

            GeodesicDistanceL2Impl(cost, sources, states, result.Values);
        }
Exemplo n.º 21
0
        /// <summary>
        /// Calculates L1 (Manhattan) geodesic distance via Dijksta's algorithm as detailed in
        /// http://www.numerical-tours.com/matlab/fastmarching_0_implementing/
        /// </summary>
        /// <param name="cost"></param>
        /// <param name="sources"></param>
        /// <param name="result"></param>
        public static void GeodesicDistanceL1(GridField2d <double> cost, IEnumerable <int> sources, double[] result)
        {
            // TODO handle wrap modes

            var costVals = cost.Values;
            int nx       = cost.CountX;
            int ny       = cost.CountY;

            (double dx, double dy) = Vec2d.Abs(cost.Scale).Components;

            var pq = new PriorityQueue <(double, int)>((a, b) => a.Item1.CompareTo(b.Item1));

            result.SetRange(double.PositiveInfinity, 0, cost.Count);

            // enqueue sources
            foreach (int index in sources)
            {
                result[index] = 0.0;
                pq.Insert((0.0, index));
            }

            // breadth first search from sources
            while (pq.Count > 0)
            {
                (double dist0, int index0) = pq.RemoveMin();
                if (dist0 > result[index0])
                {
                    continue;                         // skip if node has already been processed
                }
                (int i0, int j0) = cost.IndicesAt(index0);

                // x neighbours
                for (int i = -1; i < 2; i += 2)
                {
                    if (!SlurMath.Contains(i0 + i, nx))
                    {
                        continue;
                    }

                    int    index1 = index0 + i;
                    double dist1  = dist0 + costVals[index1] * dx;

                    if (dist1 < result[index1])
                    {
                        result[index1] = dist1;
                        pq.Insert((dist1, index1));
                    }
                }

                // y neigbours
                for (int j = -1; j < 2; j += 2)
                {
                    if (!SlurMath.Contains(j0 + j, ny))
                    {
                        continue;
                    }

                    int    index1 = index0 + j * nx;
                    double dist1  = dist0 + costVals[index1] * dy;

                    if (dist1 < result[index1])
                    {
                        result[index1] = dist1;
                        pq.Insert((dist1, index1));
                    }
                }
            }
        }
Exemplo n.º 22
0
 /// <summary>
 /// Calculates L1 (Manhattan) geodesic distance via Dijksta's algorithm as detailed in
 /// http://www.numerical-tours.com/matlab/fastmarching_0_implementing/
 /// </summary>
 /// <param name="cost"></param>
 /// <param name="sources"></param>
 /// <param name="result"></param>
 public static void GeodesicDistanceL1(GridField2d <double> cost, IEnumerable <int> sources, GridField2d <double> result)
 {
     GeodesicDistanceL1(cost, sources, result.Values);
 }
Exemplo n.º 23
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="point"></param>
 /// <param name="value"></param>
 public static void SetAt(this GridField2d <Vec2d> field, GridPoint2d point, Vec2d value)
 {
     FieldUtil.SetAt(field, point.Corners, point.Weights, value);
 }
Exemplo n.º 24
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="point"></param>
 /// <param name="amount"></param>
 public static void IncrementAt(this GridField2d <Vec2d> field, GridPoint2d point, Vec2d amount)
 {
     FieldUtil.IncrementAt(field, point.Corners, point.Weights, amount);
 }
Exemplo n.º 25
0
 /// <summary>
 ///
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="field"></param>
 /// <param name="mapper"></param>
 /// <param name="bitmap"></param>
 public static void ReadFromImage <T>(Bitmap bitmap, GridField2d <T> field, Func <Color, T> mapper)
     where T : struct
 {
     ReadFromImage(bitmap, field.Values, 0, mapper);
 }
Exemplo n.º 26
0
 /// <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(GridField2d <double> field, GridField2d <double> delta, double rate, bool parallel = false)
 {
     Diffuse(field, delta.Values, rate, parallel);
 }
Exemplo n.º 27
0
 /// <summary>
 /// Writes the given field to an existing image.
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="field"></param>
 /// <param name="mapper"></param>
 /// <param name="bitmap"></param>
 public static void WriteToImage <T>(GridField2d <T> field, Bitmap bitmap, Func <T, Color> mapper)
     where T : struct
 {
     WriteToImage(field.Values, 0, bitmap, mapper);
 }
Exemplo n.º 28
0
        /*
         * /// <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(HeVertexScalarField field, HeVertexScalarField delta, double rate, bool parallel = false)
         * {
         *  Diffuse(field, delta.Values, rate, parallel);
         * }
         *
         *
         * /// <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(HeVertexScalarField field, double[] deltas, double rate, bool parallel = false)
         * {
         *  var vals = field.Values;
         *  var verts = field.Vertices;
         *
         *  Action<Tuple<int, int>> func = range =>
         *  {
         *      for (int i = range.Item1; i < range.Item2; i++)
         *      {
         *          double sum = 0.0;
         *          int n = 0;
         *
         *          foreach (var he in verts[i].IncomingHalfedges)
         *          {
         *              sum += vals[he.Start.Index];
         *              n++;
         *          }
         *
         *          deltas[i] += (sum / n - vals[i]) * rate;
         *      }
         *  };
         *
         *  if (parallel)
         *      Parallel.ForEach(Partitioner.Create(0, field.Count), func);
         *  else
         *      func(Tuple.Create(0, field.Count));
         * }
         *
         *
         * /// <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="hedgeWeights"></param>
         * /// <param name="parallel"></param>
         * public static void Diffuse(HeVertexScalarField field, HeVertexScalarField delta, double rate, IReadOnlyList<double> hedgeWeights, bool parallel = false)
         * {
         *  Diffuse(field, delta.Values, rate, hedgeWeights, parallel);
         * }
         *
         *
         * /// <summary>
         * /// Adds the Laplacian of the field to the deltas array.
         * /// The Laplacian is calculated with a user-defined weighting scheme.
         * /// http://www.cs.princeton.edu/courses/archive/fall10/cos526/papers/sorkine05.pdf
         * /// http://www.igl.ethz.ch/projects/Laplacian-mesh-processing/Laplacian-mesh-optimization/lmo.pdf
         * /// </summary>
         * /// <param name="field"></param>
         * /// <param name="deltas"></param>
         * /// <param name="rate"></param>
         * /// <param name="hedgeWeights"></param>
         * /// <param name="parallel"></param>
         * public static void Diffuse(HeVertexScalarField field, double[] deltas, double rate, IReadOnlyList<double> hedgeWeights, bool parallel = false)
         * {
         *  var vals = field.Values;
         *  var verts = field.Vertices;
         *
         *  Action<Tuple<int, int>> func = range =>
         *  {
         *      for (int i = range.Item1; i < range.Item2; i++)
         *      {
         *          double value = vals[i];
         *          double sum = 0.0;
         *
         *          foreach (var he in verts[i].OutgoingHalfedges)
         *              sum += (vals[he.End.Index] - value) * hedgeWeights[he.Index];
         *
         *          deltas[i] += sum * rate;
         *      }
         *  };
         *
         *  if (parallel)
         *      Parallel.ForEach(Partitioner.Create(0, field.Count), func);
         *  else
         *      func(Tuple.Create(0, field.Count));
         * }
         */


        /// <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(GridField2d <double> field, GridField2d <double> delta, double slope, double rate, bool parallel = false)
        {
            ErodeThermal(field, delta.Values, slope, rate, parallel);
        }
Exemplo n.º 29
0
        /// <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(GridField2d <double> field, double[] deltas, double slope, double rate, bool parallel = false)
        {
            var vals = field.Values;
            int nx   = field.CountX;
            int ny   = field.CountY;

            (double dx, double dy) = field.Scale.Components;
            dx = 1.0 / Math.Abs(dx);
            dy = 1.0 / Math.Abs(dy);

            (int di, int dj) = field.GetBoundaryOffsets();

            Action <Tuple <int, int> > body = range =>
            {
                (int i, int j) = field.IndicesAt(range.Item1);

                for (int index = range.Item1; index < range.Item2; index++, i++)
                {
                    if (i == nx)
                    {
                        j++; i = 0;
                    }

                    double value = vals[index];
                    double sum = 0.0;
                    double m, md;

                    //-x
                    m  = ((i == 0) ? vals[index + di] : vals[index - 1]) - value;
                    m *= dx;
                    md = Math.Abs(m) - slope;
                    if (md > 0.0)
                    {
                        sum += Math.Sign(m) * md;
                    }

                    //+x
                    m  = ((i == nx - 1) ? vals[index - di] : vals[index + 1]) - value;
                    m *= dx;
                    md = Math.Abs(m) - slope;
                    if (md > 0.0)
                    {
                        sum += Math.Sign(m) * md;
                    }

                    //-y
                    m  = ((j == 0) ? vals[index + dj] : vals[index - nx]) - value;
                    m *= dy;
                    md = Math.Abs(m) - slope;
                    if (md > 0.0)
                    {
                        sum += Math.Sign(m) * md;
                    }

                    //+y
                    m  = ((j == ny - 1) ? vals[index - dj] : vals[index + nx]) - value;
                    m *= dy;
                    md = Math.Abs(m) - 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));
            }
        }
Exemplo n.º 30
0
        /// <summary>
        /// Calculates L1 (Manhattan) geodesic distance via Dijksta's algorithm as detailed in
        /// http://www.numerical-tours.com/matlab/fastmarching_0_implementing/
        /// </summary>
        /// <param name="cost"></param>
        /// <param name="sources"></param>
        /// <param name="result"></param>
        public static void GeodesicDistanceL1(GridField2d <double> cost, IEnumerable <int> sources, double[] result)
        {
            // TODO
            // handle additonal wrap modes
            // add simplified bfs based version with obstacle threshold

            var costVals = cost.Values;
            int nx       = cost.CountX;
            int ny       = cost.CountY;

            (double dx, double dy) = Vec2d.Abs(cost.Scale);

            var pq = new PriorityQueue <double, int>();

            result.SetRange(double.PositiveInfinity, 0, cost.Count);

            // enqueue sources
            foreach (int index in sources)
            {
                result[index] = 0.0;
                pq.Insert(0.0, index);
            }

            // breadth first search from sources
            while (pq.Count > 0)
            {
                (double dist0, int index0) = pq.RemoveMin();
                if (dist0 > result[index0])
                {
                    continue;                         // skip if node has already been processed (TODO check if necessary)
                }
                (int i0, int j0) = cost.IndicesAt(index0);

                // x neighbours
                for (int i = -1; i < 2; i += 2)
                {
                    if (!SlurMath.Contains(i0 + i, nx))
                    {
                        continue;
                    }

                    int    index1 = index0 + i;
                    double dist1  = dist0 + costVals[index1] * dx;

                    if (dist1 < result[index1])
                    {
                        result[index1] = dist1;
                        pq.Insert(dist1, index1);
                    }
                }

                // y neigbours
                for (int j = -1; j < 2; j += 2)
                {
                    if (!SlurMath.Contains(j0 + j, ny))
                    {
                        continue;
                    }

                    int    index1 = index0 + j * nx;
                    double dist1  = dist0 + costVals[index1] * dy;

                    if (dist1 < result[index1])
                    {
                        result[index1] = dist1;
                        pq.Insert(dist1, index1);
                    }
                }
            }
        }