Пример #1
0
        private void CheckMinPosition(int tileIndex, int vertexPosition)
        {
            var tolerance = 1.0f;

            if (SlurMath.ApproxEquals(_verts[vertexPosition].transform.position.y, _min, tolerance) && (tileIndex != 0))
            {
                _verts[vertexPosition].Body.isKinematic = true;
                _tilesTouchingGround++;
            }

            //Debug.Log("Touching ground " + _tilesTouchingGround);
        }
Пример #2
0
        private void LowestPosition()
        {
            _min = _verts.Min(v => v.transform.position.y);
            var tolerance = 1.0f;

            foreach (var v in _verts.Where(v => SlurMath.ApproxEquals(v.transform.position.y, _min, tolerance)))
            {
                _positionsAvailableToTouchGround++;
            }
            Debug.Log("lowest is " + _min);
            Debug.Log("Positions on the ground " + _positionsAvailableToTouchGround);
        }
Пример #3
0
        /// <summary>
        /// Shifts a subset of a list of items in place.
        /// </summary>
        public static void Shift <T>(this IList <T> list, int offset, int from, int to)
        {
            if (list is T[] arr)
            {
                ArrayExtensions.Shift(arr, offset, from, to);
                return;
            }

            offset = SlurMath.RepeatPositive(-offset, to - from);
            Reverse(list, from, from + offset);
            Reverse(list, from + offset, to);
            Reverse(list, from, to);
        }
Пример #4
0
            /// <summary>
            ///
            /// </summary>
            private void DisplayVNR2Density()
            {
                const string propName = "_Value";

                CellLayer[] layers = _stack.Layers;
                //int layer0 = _currentLayer + 1;
                int layer0 = 0;
                int layer1 = _stack.Layers.Length;

                //apply material props to each obj renderer
                for (int k = layer0; k < layer1; k++)
                {
                    Cell[,] cells = layers[k].Cells;
                    int nrows = cells.GetLength(0);
                    int ncols = cells.GetLength(1);

                    for (int i = 0; i < nrows; i++)
                    {
                        for (int j = 0; j < ncols; j++)
                        {
                            Cell cell = cells[i, j];

                            // skip dead cells
                            if (cell.State == 0)
                            {
                                continue;
                            }

                            // update cell material
                            Renderer renderer = cell.Renderer;
                            renderer.enabled        = true;
                            renderer.sharedMaterial = _densityMaterial;

                            // set material properties
                            renderer.GetPropertyBlock(_properties);

                            // normalize density
                            float density = GetNeighborDensity(cells, new Index2(i, j), Neighborhoods.VonNeumannR2);
                            float value   = SlurMath.Normalize(density, _densityDisplayMin, _densityDisplayMax);

                            _properties.SetFloat(propName, value);
                            cell.Renderer.SetPropertyBlock(_properties);
                        }
                    }
                }

                _currentLayer = layer1;
            }
Пример #5
0
            /// <summary>
            ///
            /// </summary>
            private void DisplayFitness()
            {
                const string propName   = "_Value";
                var          population = _population.Population;

                foreach (var stack in population)
                {
                    // normalize fitness
                    float value = SlurMath.Normalize(stack.Fitness, _population.MinFitness, _population.MaxFitness);
                    if (stack.Fitness == _population.MaxFitness)
                    {
                        value = .999f;
                    }

                    if (stack.Fitness == _population.MinFitness)
                    {
                        value = .001f;
                    }

                    if (stack.gameObject.active == false)
                    {
                        continue;
                    }

                    foreach (var layer in stack.Layers)
                    {
                        foreach (var cell in layer.Cells)
                        {
                            // skip dead cells
                            if (cell.State == 0)
                            {
                                continue;
                            }

                            // update cell material
                            MeshRenderer renderer = cell.Renderer;
                            renderer.sharedMaterial = _fitnessMaterial;

                            // set material properties
                            {
                                renderer.GetPropertyBlock(_properties);
                                _properties.SetFloat(propName, value);
                                renderer.SetPropertyBlock(_properties);
                            }
                        }
                    }
                }
            }
Пример #6
0
        /// <inheritdoc />
        protected sealed override double ValueAtLinearUnsafe(Vector2d point)
        {
            (var u, var v) = Vector2d.Fract(ToGridSpace(point), out Vector2i whole);

            var x0 = whole.X;
            var y0 = whole.Y * CountX;

            var x1 = x0 + 1;
            var y1 = y0 + CountX;

            var vals = Values;

            return(SlurMath.Lerp(
                       SlurMath.Lerp(vals[x0 + y0], vals[x1 + y0], u),
                       SlurMath.Lerp(vals[x0 + y1], vals[x1 + y1], u),
                       v));
        }
Пример #7
0
        /// <inheritdoc />
        protected sealed override double ValueAtLinear(Vector2d point)
        {
            (var u, var v) = Vector2d.Fract(ToGridSpace(point), out Vector2i whole);

            var x0 = WrapX(whole.X);
            var y0 = WrapY(whole.Y) * CountX;

            int x1 = WrapX(whole.X + 1);
            int y1 = WrapY(whole.Y + 1) * CountX;

            var vals = Values;

            return(SlurMath.Lerp(
                       SlurMath.Lerp(vals[x0 + y0], vals[x1 + y0], u),
                       SlurMath.Lerp(vals[x0 + y1], vals[x1 + y1], u),
                       v));
        }
Пример #8
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            Mesh           mesh   = null;
            List <Point3d> points = new List <Point3d>();
            double         iso    = 0d;

            if (!DA.GetData(0, ref mesh))
            {
                return;
            }
            if (!DA.GetDataList <Point3d>(1, points))
            {
                return;
            }
            if (!DA.GetData(2, ref iso))
            {
                return;
            }

            var hem   = mesh.ToHeMesh();
            var field = MeshField3d.Double.Create(hem);

            var vecs = points.Select(p => (SpatialSlur.Vector3d)p).ToList();

            var kdTree  = KdTree.CreateBalanced(vecs.Select(v => (v.XY).ToArray()));
            var nearest = hem.Vertices.Select(p => kdTree.NearestL2(new double[] { p.Position.X, p.Position.Y })).ToList();

            List <double> val = new List <double>();

            for (int i = 0; i < hem.Vertices.Count; i++)
            {
                double d = hem.Vertices[i].Position.DistanceTo(points[nearest[i]]);
                val.Add(d);
            }

            Interval interval = GetInterval(val);

            for (int i = 0; i < val.Count; i++)
            {
                val[i] = (SlurMath.Remap(val[i], interval.T0, interval.T1, -1, 1)) - iso;
            }

            field.Set(val);

            DA.SetData(0, Field3d.Create(v => field.ValueAt(v)));
        }
Пример #9
0
        /// <inheritdoc />
        protected sealed override double ValueAtLinearUnsafe(Vec2d point)
        {
            point = ToGridSpace(point);
            double u = SlurMath.Fract(point.X, out int i0);
            double v = SlurMath.Fract(point.Y, out int j0);

            j0 *= CountX;
            int i1 = i0 + 1;
            int j1 = j0 + CountX;

            var vals = Values;

            return(SlurMath.Lerp(
                       SlurMath.Lerp(vals[i0 + j0], vals[i1 + j0], u),
                       SlurMath.Lerp(vals[i0 + j1], vals[i1 + j1], u),
                       v));
        }
Пример #10
0
            private void DisplayOldCells()
            {
                const string propName = "_Value";

                CellLayer[] layers = _model.Stack.Layers;
                int         layer0 = _currentLayer + 1;
                int         layer1 = _model.CurrentLayer;

                for (int i = layer0; i <= layer1; i++)
                {
                    foreach (var cell in layers[i].Cells)
                    {
                        // skip dead cells
                        if (cell.State == 0)
                        {
                            continue;
                        }

                        // update cell material
                        MeshRenderer renderer = cell.Renderer;
                        if (cell.Age < 10)
                        {
                            renderer.enabled = false;
                        }

                        if (cell.Age >= 10)
                        {
                            renderer.enabled = true;
                        }
                        renderer.sharedMaterial = _ageMaterial;

                        // set material properties
                        {
                            renderer.GetPropertyBlock(_properties);

                            // normalize age
                            float value = SlurMath.Normalize(cell.Age, _ageDisplayMin, _ageDisplayMax);
                            _properties.SetFloat(propName, value);

                            renderer.SetPropertyBlock(_properties);
                        }
                    }
                }

                _currentLayer = layer1;
            }
Пример #11
0
        /// <summary>
        /// Calcuated as the exterior between adjacent faces.
        /// Result is in range [0 - 2Pi].
        /// Assumes the given face normals are unitized.
        /// </summary>>
        public static double GetDihedralAngle <V, E, F>(this IHalfedge <V, E, F> hedge, Func <V, Vec3d> getPosition, Func <F, Vec3d> getNormal)
            where V : IHeVertex <V, E, F>
            where E : IHalfedge <V, E, F>
            where F : IHeFace <V, E, F>
        {
            Vec3d tangent = getPosition(hedge.End) - getPosition(hedge.Start);

            tangent.Unitize();

            Vec3d x = getNormal(hedge.Face);
            Vec3d y = Vec3d.Cross(x, tangent);

            Vec3d  d = getNormal(hedge.Twin.Face);
            double t = Math.Atan2(Vec3d.Dot(d, y), Vec3d.Dot(d, x));

            t = (t < 0.0) ? t + SlurMath.TwoPI : t;            // shift discontinuity to 0
            return(SlurMath.Mod(t + Math.PI, SlurMath.TwoPI)); // add angle bw normals and faces
        }
Пример #12
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            List <Mesh>       mesh = new List <Mesh>();
            IField3d <double> f0   = null;
            IField3d <double> f1   = null;
            List <double>     t    = new List <double>();

            if (!DA.GetDataList(0, mesh))
            {
                return;
            }
            if (!DA.GetData(1, ref f0))
            {
                return;
            }
            if (!DA.GetData(2, ref f1))
            {
                return;
            }
            if (!DA.GetDataList(3, t))
            {
                return;
            }

            List <MeshField3d> fields = new List <MeshField3d>();

            for (int i = 0; i < t.Count; i++)
            {
                List <double> currentBlend = new List <double>();
                var           currentField = MeshField3d.Double.Create(mesh[i].ToHeMesh());

                foreach (Point3d p in mesh[i].Vertices)
                {
                    double val = SlurMath.Lerp(f0.ValueAt(p), f1.ValueAt(p), t[i]);
                    currentBlend.Add(val);
                    currentField.Set(currentBlend);
                }

                fields.Add(currentField);
            }
            ;

            DA.SetDataList(0, fields);
        }
Пример #13
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            List <Mesh>       mesh = new List <Mesh>();
            IField3d <double> f0   = null;
            IField3d <double> f1   = null;
            List <double>     t    = new List <double>();

            if (!DA.GetDataList(0, mesh))
            {
                return;
            }
            if (!DA.GetData(1, ref f0))
            {
                return;
            }
            if (!DA.GetData(2, ref f1))
            {
                return;
            }
            if (!DA.GetDataList(3, t))
            {
                return;
            }

            List <MeshField3d> fields = new List <MeshField3d>();

            for (int i = 0; i < t.Count; i++)
            {
                var      currentField = MeshField3d.Double.Create(mesh[i].ToHeMesh());
                double[] currentBlend = new double[currentField.Mesh.Vertices.Count];

                Parallel.For(0, currentField.Mesh.Vertices.Count, j =>
                {
                    currentBlend[j] = SlurMath.Lerp(f0.ValueAt(currentField.Mesh.Vertices[j].Position),
                                                    f1.ValueAt(currentField.Mesh.Vertices[j].Position), t[i]);
                });

                currentField.Set(currentBlend);
                fields.Add(currentField);
            }

            DA.SetDataList(0, fields);
        }
Пример #14
0
        /// <inheritdoc />
        protected sealed override double ValueAtLinear(Vec2d point)
        {
            point = ToGridSpace(point);
            double u = SlurMath.Fract(point.X, out int i0);
            double v = SlurMath.Fract(point.Y, out int j0);

            int i1 = WrapX(i0 + 1);
            int j1 = WrapY(j0 + 1) * CountX;

            i0 = WrapX(i0);
            j0 = WrapY(j0) * CountX;

            var vals = Values;

            return(SlurMath.Lerp(
                       SlurMath.Lerp(vals[i0 + j0], vals[i1 + j0], u),
                       SlurMath.Lerp(vals[i0 + j1], vals[i1 + j1], u),
                       v));
        }
Пример #15
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            Mesh   mesh      = null;
            Mesh   inputMesh = null;
            double iso       = 0d;

            if (!DA.GetData(0, ref mesh))
            {
                return;
            }
            if (!DA.GetData(1, ref inputMesh))
            {
                return;
            }
            if (!DA.GetData(2, ref iso))
            {
                return;
            }

            var hem   = mesh.ToHeMesh();
            var field = MeshField3d.Double.Create(hem);

            List <double> val = new List <double>();

            foreach (Point3d v in mesh.Vertices)
            {
                Point3d closestPt = inputMesh.ClosestPoint(v);
                double  dist      = v.DistanceTo(closestPt);
                val.Add(dist);
            }

            Interval interval = GetInterval(val);

            for (int i = 0; i < val.Count; i++)
            {
                val[i] = (SlurMath.Remap(val[i], interval.T0, interval.T1, -1, 1)) - iso;
            }

            field.Set(val);

            DA.SetData(0, Field3d.Create(v => field.ValueAt(v)));
        }
        /// <summary>
        ///
        /// </summary>
        private IEnumerator DisplayColor()
        {
            while (true)
            {
                yield return(new WaitForSeconds(1f));


                const string propName = "_Value";
                CellLayer[]  layers   = _model.Stack.Layers;
                int          layer0   = _currentLayer + 1;
                int          layer1   = _model.CurrentLayer;

                for (int i = layer0; i <= layer1; i++)
                {
                    foreach (var cell in layers[i].Cells)
                    {
                        // skip dead cells
                        if (cell.State == 0)
                        {
                            continue;
                        }

                        // update cell material
                        MeshRenderer renderer = cell.Renderer;
                        renderer.sharedMaterial = _ageMaterial;

                        // set material properties
                        {
                            renderer.GetPropertyBlock(_properties);

                            // normalize age
                            float value = SlurMath.Normalize(cell.Age, _ageDisplayMin, _ageDisplayMax);
                            _properties.SetFloat(propName, value);

                            renderer.SetPropertyBlock(_properties);
                        }
                    }
                }
                _currentLayer = layer1;
                yield return(new WaitForSeconds(0.1f));
            }
        }
Пример #17
0
        /// <summary>
        /// Returns a grid point at the given point.
        /// Assumes the point is within the bounds of the grid.
        /// </summary>
        /// <param name="point"></param>
        /// <param name="result"></param>
        public void GridPointAtUnsafe(Vec2d point, GridPoint2d result)
        {
            point = ToGridSpace(point);

            result.SetWeights(
                SlurMath.Fract(point.X, out int i0),
                SlurMath.Fract(point.Y, out int j0)
                );

            j0 *= _nx;
            int i1 = i0 + 1;
            int j1 = j0 + _nx;

            var corners = result.Corners;

            corners[0] = i0 + j0;
            corners[1] = i1 + j0;
            corners[2] = i0 + j1;
            corners[3] = i1 + j1;
        }
Пример #18
0
        private void AddKinematicToLowest()
        {
            _kinematicPercent = 0.0f;
            int roundN = 0;

            var minDistance = MinDistance();
            var tolerance   = 1.0f;

            foreach (var v in _verts)
            {
                v.Body.isKinematic = false;
            }

            foreach (var kinematic in _meshedTiles.Where
                         (kinematic => SlurMath.ApproxEquals(kinematic.transform.position.y, minDistance, tolerance)))
            {
                kinematic.Body.isKinematic = true;
                _kinematicTiles++;
            }
        }
Пример #19
0
        /// <summary>
        /// TODO move into SlurUnity
        /// </summary>
        /// <param name="colors"></param>
        /// <param name="factor"></param>
        /// <returns></returns>
        public static Color Lerp(IReadOnlyList <Color> colors, float factor)
        {
            int last = colors.Count - 1;
            int i;

            //  object SlurMathf = null;
            factor = SlurMath.Fract(factor * last, out i);
            //Fract(factor * last, out i);

            if (i < 0)
            {
                return(colors[0]);
            }
            else if (i >= last)
            {
                return(colors[last]);
            }

            return(Color.LerpUnclamped(colors[i], colors[i + 1], factor));
        }
Пример #20
0
        private void AddKinematicToLowest()
        {
            var lowest    = SmallestDistance();
            var tolerance = 1.0f;

            foreach (var v in _meshedTiles)
            {
                if (v.transform.position.y == lowest)
                {
                    v.Body.isKinematic = true;
                }
            }


            var meanKinematicPosition = _meshedTiles.Where(v => v.Body.isKinematic).Mean(v => v.transform.position);


            foreach (var v in _meshedTiles.Where(v => SlurMath.ApproxEquals(v.transform.position.y, lowest, tolerance)))
            {
            }
        }
        /// <summary>
        /// Calcuated as the exterior between adjacent faces.
        /// Result is in range [0 - 2Pi].
        /// Assumes the given face normals are unitized.
        /// </summary>>
        public static double GetDihedralAngle <V, E, F>(this IHalfedge <V, E, F> hedge, Func <V, Vec3d> getPosition, Func <F, Vec3d> getNormal)
            where V : IHeVertex <V, E, F>
            where E : IHalfedge <V, E, F>
            where F : IHeFace <V, E, F>
        {
            // TODO
            // refactor as per http://brickisland.net/DDGFall2017/2017/10/12/assignment-1-coding-investigating-curvature/

            Vec3d tangent = getPosition(hedge.End) - getPosition(hedge.Start);

            tangent.Unitize();

            Vec3d x = getNormal(hedge.Face);
            Vec3d y = Vec3d.Cross(x, tangent);

            Vec3d  d = getNormal(hedge.Twin.Face);
            double t = Math.Atan2(Vec3d.Dot(d, y), Vec3d.Dot(d, x));

            t = (t < 0.0) ? t + SlurMath.TwoPI : t;            // shift discontinuity to 0
            return(SlurMath.Mod(t + Math.PI, SlurMath.TwoPI)); // add angle bw normals and faces
        }
Пример #22
0
            /// <summary>
            /// Returns the noise value at the given coordinates
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <param name="z"></param>
            /// <returns></returns>
            public static double ValueAt(double x, double y, double z)
            {
                // separate whole and fractional components
                x = SlurMath.Fract(x, out int i);
                y = SlurMath.Fract(y, out int j);
                z = SlurMath.Fract(z, out int k);

                // wrap to perm table
                i &= 255;
                j &= 255;
                k &= 255;

                // calculate noise contributions from each corner
                double n000 = GradDot(ToIndex(i, j, k), x, y, z);
                double n100 = GradDot(ToIndex(i + 1, j, k), x - 1.0, y, z);
                double n010 = GradDot(ToIndex(i, j + 1, k), x, y - 1.0, z);
                double n110 = GradDot(ToIndex(i + 1, j + 1, k), x - 1.0, y - 1.0, z);

                double n001 = GradDot(ToIndex(i, j, k + 1), x, y, z - 1.0);
                double n101 = GradDot(ToIndex(i + 1, j, k + 1), x - 1.0, y, z - 1.0);
                double n011 = GradDot(ToIndex(i, j + 1, k + 1), x, y - 1.0, z - 1.0);
                double n111 = GradDot(ToIndex(i + 1, j + 1, k + 1), x - 1.0, y - 1.0, z - 1.0);

                // eased values for each dimension
                x = SlurMath.HermiteC2(x);
                y = SlurMath.HermiteC2(y);
                z = SlurMath.HermiteC2(z);

                // trilinear interpolation
                return(SlurMath.Lerp(
                           SlurMath.Lerp(
                               SlurMath.Lerp(n000, n100, x),
                               SlurMath.Lerp(n010, n110, x),
                               y),
                           SlurMath.Lerp(
                               SlurMath.Lerp(n001, n101, x),
                               SlurMath.Lerp(n011, n111, x),
                               y),
                           z));
            }
Пример #23
0
        /// <summary>
        /// Returns the noise value at the given coordinates.
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static double ValueAt(double x, double y)
        {
            // separate whole and fractional components
            x = SlurMath.Fract(x, out int i);
            y = SlurMath.Fract(y, out int j);

            // calculate noise contributions from each corner
            double n00 = GradDot(ToIndex(i, j), x, y);
            double n10 = GradDot(ToIndex(i + 1, j), x - 1.0, y);
            double n01 = GradDot(ToIndex(i, j + 1), x, y - 1.0);
            double n11 = GradDot(ToIndex(i + 1, j + 1), x - 1.0, y - 1.0);

            // eased values for x and y
            x = SlurMath.HermiteC2(x);
            y = SlurMath.HermiteC2(y);

            // bilinear interpolation
            return(SlurMath.Lerp(
                       SlurMath.Lerp(n00, n10, x),
                       SlurMath.Lerp(n01, n11, x),
                       y));
        }
Пример #24
0
        /// <summary>
        /// Returns a grid point at the given point.
        /// </summary>
        /// <param name="point"></param>
        /// <param name="result"></param>
        public void GridPointAt(Vec2d point, GridPoint2d result)
        {
            point = ToGridSpace(point);

            result.SetWeights(
                SlurMath.Fract(point.X, out int i0),
                SlurMath.Fract(point.Y, out int j0)
                );

            int i1 = WrapX(i0 + 1);
            int j1 = WrapY(j0 + 1) * _nx;

            i0 = WrapX(i0);
            j0 = WrapY(j0) * _nx;

            var corners = result.Corners;

            corners[0] = i0 + j0;
            corners[1] = i1 + j0;
            corners[2] = i0 + j1;
            corners[3] = i1 + j1;
        }
Пример #25
0
            /// <summary>
            ///
            /// </summary>
            private void DisplayLayerDensity()
            {
                const string propName = "_Value";

                CellLayer[] layers = _stack.Layers;
                //int layer0 = _currentLayer + 1;
                int layer0 = 0;
                int layer1 = _stack.Layers.Length;

                for (int i = layer0; i < layer1; i++)
                {
                    CellLayer layer = layers[i];
                    float     value = SlurMath.Normalize(layer.Density, _densityDisplayMin, _densityDisplayMax);

                    foreach (var cell in layer.Cells)
                    {
                        // skip dead cells
                        if (cell.State == 0)
                        {
                            continue;
                        }

                        // update cell material
                        Renderer renderer = cell.Renderer;
                        renderer.enabled        = true;
                        renderer.sharedMaterial = _densityMaterial;

                        // set material properties
                        renderer.GetPropertyBlock(_properties);
                        _properties.SetFloat(propName, value);
                        renderer.SetPropertyBlock(_properties);
                    }
                }

                _currentLayer = layer1;
            }
Пример #26
0
 private bool AreaAnalyzer()
 {
     return(SlurMath.ApproxEquals(AreaDeviation(), _neededArea, _areaTolerance));
 }
Пример #27
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));
                    }
                }
            }
        }
Пример #28
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="weight"></param>
        /// <returns></returns>
        public float ToScale(float weight)
        {
            var t = SlurMath.Saturate(SlurMath.Normalize(weight, _weight0, _weight1));

            return(SlurMath.Lerp(_scale0, _scale1, t));
        }
Пример #29
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));
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Returns a linearly interpolated value at the given parameter along the halfedge.
 /// </summary>
 public static double Lerp <V, E>(this IHalfedge <V, E> hedge, Func <V, double> getValue, double t)
     where V : IHeVertex <V, E>
     where E : IHalfedge <V, E>
 {
     return(SlurMath.Lerp(getValue(hedge.Start), getValue(hedge.End), t));
 }