Пример #1
0
        /// <summary>
        /// Creates a weighted index list from a binary reader
        /// </summary>
        /// <param name="reader">The binary reader</param>
        public static WeightedIndexList ReadFrom(BinaryReader reader)
        {
            var len = reader.ReadInt32();
            var ret = new WeightedIndex[len];

            for (var i = 0; i < len; i++)
            {
                var category = new WeightedIndex
                {
                    Index = reader.ReadUInt32(), Weight = reader.ReadSingle()
                };
                ret[i] = category;
            }

            return(Create(ret));
        }
Пример #2
0
    public static RefinementResult Make(QuadTopology controlTopology, int[] controlSurfaceMap, int refinementLevel, bool derivativesOnly)
    {
        if (controlTopology.Faces.Length == 0 && controlTopology.VertexCount == 0)
        {
            return(RefinementResult.Empty);
        }

        PackedLists <WeightedIndex> limitStencils, limitDuStencils, limitDvStencils;
        QuadTopology            refinedTopology;
        SubdivisionTopologyInfo refinedTopologyInfo;

        int[] controlFaceMap;
        using (var refinement = new Refinement(controlTopology, refinementLevel)) {
            limitStencils   = refinement.GetStencils(StencilKind.LimitStencils);
            limitDuStencils = refinement.GetStencils(StencilKind.LimitDuStencils);
            limitDvStencils = refinement.GetStencils(StencilKind.LimitDvStencils);
            refinedTopology = refinement.GetTopology();

            var adjacentVertices = refinement.GetAdjacentVertices();
            var rules            = refinement.GetVertexRules();
            refinedTopologyInfo = new SubdivisionTopologyInfo(adjacentVertices, rules);

            controlFaceMap = refinement.GetFaceMap();
        }

        if (derivativesOnly)
        {
            if (refinementLevel != 0)
            {
                throw new InvalidOperationException("derivatives-only mode can only be used at refinement level 0");
            }

            limitStencils = PackedLists <WeightedIndex> .Pack(Enumerable.Range(0, controlTopology.VertexCount)
                                                              .Select(vertexIdx => {
                var selfWeight = new WeightedIndex(vertexIdx, 1);
                return(new List <WeightedIndex> {
                    selfWeight
                });
            }).ToList());
        }

        PackedLists <WeightedIndexWithDerivatives> stencils = WeightedIndexWithDerivatives.Merge(limitStencils, limitDuStencils, limitDvStencils);
        var refinedMesh = new SubdivisionMesh(controlTopology.VertexCount, refinedTopology, stencils);

        return(new RefinementResult(refinedMesh, refinedTopologyInfo, controlFaceMap));
    }
Пример #3
0
        internal void AddSplitPoint(int tiMul3, BspSplitPoint sp)
        {
            if (sp.VertexIndex >= 0)
            {
                return;                      // already inserted
            }
            if (sp.Parameter == 0.0)
            {
                sp.VertexIndex = m_triangleVertexIndexArray[tiMul3 + sp.TriangleVertexIndex];
                return;
            }

            int vi = VertexCount;
            int vc = vi + 1;

            EnsureVertexCapacity(vc);
            VertexCount = vc;
            int vi0 = m_triangleVertexIndexArray[tiMul3 + sp.TriangleVertexIndex];
            int vi1 = m_triangleVertexIndexArray[tiMul3 + (sp.TriangleVertexIndex + 1) % 3];
            V3d p0  = m_positionArray[vi0];

            m_positionArray[vi] = p0 + sp.Parameter * (m_positionArray[vi1] - p0);

            int wc   = 0;
            int dvi0 = vi0 - m_originalVertexCount;

            wc += dvi0 < 0 ? 1 : m_weightsArray[dvi0].Length;
            int dvi1 = vi1 - m_originalVertexCount;

            wc += dvi1 < 0 ? 1 : m_weightsArray[dvi1].Length;

            var weights  = new WeightedIndex[wc];
            var invParam = 1.0 - sp.Parameter;

            wc = 0;
            if (dvi0 < 0)
            {
                weights[wc++] = new WeightedIndex(invParam, vi0);
            }
            else
            {
                foreach (var widx in m_weightsArray[dvi0])
                {
                    weights[wc++] =
                        new WeightedIndex(invParam * widx.Weight, widx.Index);
                }
            }
            if (dvi1 < 0)
            {
                weights[wc++] = new WeightedIndex(sp.Parameter, vi1);
            }
            else
            {
                foreach (var widx in m_weightsArray[dvi1])
                {
                    weights[wc++] =
                        new WeightedIndex(sp.Parameter * widx.Weight, widx.Index);
                }
            }

            m_weightsArray[vi - m_originalVertexCount] = weights;
            sp.VertexIndex = vi;
        }
Пример #4
0
 public void Merge(WeightedIndex weightedIndex, float weightCoefficient)
 {
     weights.TryGetValue(weightedIndex.Index, out float previousWeight);
     weights[weightedIndex.Index] = previousWeight + weightCoefficient * weightedIndex.Weight;
 }
Пример #5
0
        /// <summary>
        /// This method return a data field in which the values assigned to visible cells from a list of vantage cells are calculated through an interpolation function.
        /// </summary>
        /// <param name="vantageCells">The destinations.</param>
        /// <param name="initialValue">The initial value.</param>
        /// <param name="notVisibleCellIds">The cell IDs that are not visible.</param>
        /// <param name="notVisibleValue">The value of not visible cells.</param>
        /// <param name="name">The name of the data.</param>
        /// <param name="interpolation">The interpolation function.</param>
        /// <returns>SpatialAnalysis.Data.SpatialDataField.</returns>
        public SpatialAnalysis.Data.SpatialDataField GetSpatialDataField(HashSet <int> vantageCells, double initialValue, HashSet <int> notVisibleCellIds,
                                                                         double notVisibleValue, string name, Func <double, double> interpolation)
        {
            var timer = new System.Diagnostics.Stopwatch();

            timer.Start();
            #region set the initial potential to positive infinity; define heap and labeled where the potential is zero;
            SortedSet <WeightedIndex> heap = new SortedSet <WeightedIndex>();
            WeightedIndex[,] indices = new WeightedIndex[this._host.cellularFloor.GridWidth, this._host.cellularFloor.GridHeight];
            bool[,] marked           = new bool[this._host.cellularFloor.GridWidth, this._host.cellularFloor.GridHeight];
            for (int i = 0; i < this._host.cellularFloor.GridWidth; i++)
            {
                for (int j = 0; j < this._host.cellularFloor.GridHeight; j++)
                {
                    indices[i, j] = new WeightedIndex(i, j, double.PositiveInfinity);
                }
            }
            foreach (var id in vantageCells)
            {
                Cell cell = this._host.cellularFloor.FindCell(id);
                indices[cell.CellToIndex.I, cell.CellToIndex.J].WeightingFactor = initialValue;
                marked[cell.CellToIndex.I, cell.CellToIndex.J] = true;
                heap.Add(indices[cell.CellToIndex.I, cell.CellToIndex.J]);
            }
            foreach (int id in notVisibleCellIds)
            {
                var cell = this._host.cellularFloor.FindCell(id);
                marked[cell.CellToIndex.I, cell.CellToIndex.J] = true;
            }
            #endregion

            while (heap.Count != 0)
            {
                var current = heap.Min;
                heap.Remove(current);
                marked[current.I, current.J] = true;
                foreach (var item in this.Rays.Keys)
                {
                    int I = current.I + item.I;
                    int J = current.J + item.J;
                    if (this._host.cellularFloor.ContainsCell(I, J) &&
                        this._host.cellularFloor.Cells[I, J].FieldOverlapState == OverlapState.Inside &&
                        !marked[I, J])
                    {
                        var    neighborIndex = indices[I, J];
                        double edgeCost      = this.getEdgeLength(neighborIndex, current);
                        double newPotential  = current.WeightingFactor + edgeCost;
                        if (!heap.Contains(neighborIndex))
                        {
                            neighborIndex.WeightingFactor = newPotential;
                            heap.Add(neighborIndex);
                        }
                        else
                        {
                            if (neighborIndex.WeightingFactor > newPotential)
                            {
                                heap.Remove(neighborIndex);
                                neighborIndex.WeightingFactor = newPotential;
                                heap.Add(neighborIndex);
                            }
                        }
                    }
                }
            }
            heap   = null;
            marked = null;
            foreach (var item in indices)
            {
                if (notVisibleCellIds.Contains(this._host.cellularFloor.Cells[item.I, item.J].ID))
                {
                    item.WeightingFactor = notVisibleValue;
                }
            }
            Dictionary <Cell, double> potentials = new Dictionary <Cell, double>();
            foreach (var item in indices)
            {
                if (!double.IsInfinity(item.WeightingFactor))
                {
                    double value_ = interpolation(item.WeightingFactor);
                    if (!double.IsInfinity(value_))
                    {
                        potentials.Add(this._host.cellularFloor.Cells[item.I, item.J], value_);
                    }
                }
            }
            indices = null;
            timer.Stop();
            this.PotentialFieldGenerationTime = timer.Elapsed.TotalMilliseconds;
            return(new Data.SpatialDataField(name, potentials));
        }
Пример #6
0
        /// <summary>
        /// Calculates the activity (i.e. potential field) with respect to distance, static cost and angle.
        /// </summary>
        /// <param name="destination">The destination.</param>
        /// <param name="destinationArea">The destination area.</param>
        /// <param name="defaultState">The default state.</param>
        /// <param name="name">The name.</param>
        /// <param name="angleCost">The angle cost.</param>
        /// <param name="radius">The radius.</param>
        /// <returns>Activity.</returns>
        /// <exception cref="System.ArgumentException">Negative cost for edge found: " + edgeCost.ToString() +
        ///                                 "\nP1: " +
        ///                             this._cellularFloor.FindCell(current).Origin.ToString() + "\nP2: " + this._cellularFloor.FindCell(neighborIndex).Origin.ToString() +
        ///                             "\nDistance: " + this._cellularFloor.FindCell(current).Origin.DistanceTo(this._cellularFloor.FindCell(neighborIndex).Origin).ToString()</exception>
        public Activity GetDynamicActivity(Cell destination, BarrierPolygon destinationArea, StateBase defaultState, string name, double angleCost, double radius)
        {
            var timer = new System.Diagnostics.Stopwatch();

            timer.Start();
            //Calculating static costs
            double distance_cost_factor = Parameter.DefaultParameters[AgentParameters.MAN_DistanceCost].Value;

            if (distance_cost_factor < 0)
            {
                throw new ArgumentException("Parameter MAN_DistanceCost cannot have a negative value: " + distance_cost_factor.ToString());
            }
            Dictionary <Cell, double> costs = this._host.cellularFloor.GetStaticCost();

            #region set the initial potential to positive infinity; define heap and labeled where the potential is zero;
            SortedSet <WeightedIndex> heap = new SortedSet <WeightedIndex>();
            WeightedIndex[,] indices = new WeightedIndex[this._host.cellularFloor.GridWidth, this._host.cellularFloor.GridHeight];
            bool[,] marked           = new bool[this._host.cellularFloor.GridWidth, this._host.cellularFloor.GridHeight];
            UV[,] previousOrigins    = new UV[this._host.cellularFloor.GridWidth, this._host.cellularFloor.GridHeight];
            for (int i = 0; i < this._host.cellularFloor.GridWidth; i++)
            {
                for (int j = 0; j < this._host.cellularFloor.GridHeight; j++)
                {
                    indices[i, j] = new WeightedIndex(i, j, double.PositiveInfinity);
                }
            }
            indices[destination.CellToIndex.I, destination.CellToIndex.J].WeightingFactor = 0;
            marked[destination.CellToIndex.I, destination.CellToIndex.J] = true;
            heap.Add(indices[destination.CellToIndex.I, destination.CellToIndex.J]);
            #endregion
            var radiusSquared = radius * radius;
            var target        = this._host.cellularFloor.Cells[destination.CellToIndex.I, destination.CellToIndex.J];
            while (heap.Count != 0)
            {
                var current = heap.Min;
                heap.Remove(current);
                marked[current.I, current.J] = true;
                UV currentDirection = null;
                if (previousOrigins[current.I, current.J] != null)
                {
                    currentDirection = this._host.cellularFloor.Cells[current.I, current.J] - previousOrigins[current.I, current.J];
                    currentDirection.Unitize();
                }
                foreach (var item in this.Rays.Keys)
                {
                    int I = current.I + item.I;
                    int J = current.J + item.J;
                    if (this._host.cellularFloor.ContainsCell(I, J) &&
                        this._host.cellularFloor.Cells[I, J].FieldOverlapState == OverlapState.Inside &&
                        !marked[I, J] &&
                        radiusSquared >= UV.GetLengthSquared(this._host.cellularFloor.Cells[I, J], target))
                    {
                        var    neighborIndex = indices[I, J];
                        double edgeCost      = this.getStaticCostOfEdge(neighborIndex, current, distance_cost_factor, costs);
                        if (edgeCost <= 0)
                        {
                            throw new ArgumentException("Negative cost for edge found: " + edgeCost.ToString() +
                                                        "\nP1: " +
                                                        this._host.cellularFloor.FindCell(current).ToString() + "\nP2: " + this._host.cellularFloor.FindCell(neighborIndex).ToString() +
                                                        "\nDistance: " + this._host.cellularFloor.FindCell(current).DistanceTo(this._host.cellularFloor.FindCell(neighborIndex)).ToString());
                        }
                        double newPotential = current.WeightingFactor + edgeCost;
                        if (currentDirection != null)
                        {
                            var newDirection = this._host.cellularFloor.Cells[current.I, current.J] - this._host.cellularFloor.Cells[I, J];
                            newDirection.Unitize();
                            double angle = Math.Abs(newDirection.AngleTo(currentDirection));
                            newPotential += angleCost * (Math.PI - Math.Abs(angle));
                        }
                        if (!heap.Contains(neighborIndex))
                        {
                            previousOrigins[neighborIndex.I, neighborIndex.J] = this._host.cellularFloor.Cells[current.I, current.J];
                            neighborIndex.WeightingFactor = newPotential;
                            heap.Add(neighborIndex);
                        }
                        else
                        {
                            if (neighborIndex.WeightingFactor > newPotential)
                            {
                                previousOrigins[neighborIndex.I, neighborIndex.J] = this._host.cellularFloor.Cells[current.I, current.J];
                                heap.Remove(neighborIndex);
                                neighborIndex.WeightingFactor = newPotential;
                                heap.Add(neighborIndex);
                            }
                        }
                    }
                }
            }
            heap            = null;
            marked          = null;
            costs           = null;
            previousOrigins = null;
            Dictionary <Cell, double> potentials = new Dictionary <Cell, double>();
            foreach (var item in indices)
            {
                if (!double.IsInfinity(item.WeightingFactor))
                {
                    potentials.Add(this._host.cellularFloor.Cells[item.I, item.J], item.WeightingFactor);
                }
            }
            indices = null;
            timer.Stop();
            this.PotentialFieldGenerationTime = timer.Elapsed.TotalMilliseconds;
            return(new Activity(potentials, new HashSet <Cell> {
                destination
            }, destinationArea, defaultState, name, this._host.cellularFloor));
        }
Пример #7
0
        /// <summary>
        /// Gets the static potential field for training.
        /// </summary>
        /// <param name="destination">The destination.</param>
        /// <param name="destinationArea">The destination area.</param>
        /// <param name="defaultState">The default state.</param>
        /// <param name="name">The name.</param>
        /// <param name="trail">The trail.</param>
        /// <returns>Activity.</returns>
        /// <exception cref="System.ArgumentException">Negative cost for edge found: " + edgeCost.ToString() +
        ///                                 "\nP1: " +
        ///                             this._cellularFloor.FindCell(current).Origin.ToString() + "\nP2: " + this._cellularFloor.FindCell(neighborIndex).Origin.ToString() +
        ///                             "\nDistance: " + this._cellularFloor.FindCell(current).Origin.DistanceTo(this._cellularFloor.FindCell(neighborIndex).Origin).ToString()</exception>
        public Activity GetStaticPotentialFieldForTraining(Cell destination, BarrierPolygon destinationArea, StateBase defaultState, string name, HashSet <Index> trail)
        {
            var timer = new System.Diagnostics.Stopwatch();

            timer.Start();
            //Calculating static costs
            double distance_cost_factor = Parameter.DefaultParameters[AgentParameters.MAN_DistanceCost].Value;

            if (distance_cost_factor < 0)
            {
                throw new ArgumentException("Parameter MAN_DistanceCost cannot have a negative value: " + distance_cost_factor.ToString());
            }
            Dictionary <Cell, double> costs = this._host.cellularFloor.GetStaticCost();

            #region set the initial potential to positive infinity; define heap and labeled where the potential is zero;
            SortedSet <WeightedIndex> heap = new SortedSet <WeightedIndex>();
            WeightedIndex[,] indices = new WeightedIndex[this._host.cellularFloor.GridWidth, this._host.cellularFloor.GridHeight];
            bool[,] marked           = new bool[this._host.cellularFloor.GridWidth, this._host.cellularFloor.GridHeight];
            for (int i = 0; i < this._host.cellularFloor.GridWidth; i++)
            {
                for (int j = 0; j < this._host.cellularFloor.GridHeight; j++)
                {
                    indices[i, j] = new WeightedIndex(i, j, double.PositiveInfinity);
                }
            }
            var destinations = new HashSet <Cell> {
                destination
            };
            foreach (var item in destinations)
            {
                indices[item.CellToIndex.I, item.CellToIndex.J].WeightingFactor = 0;
                marked[item.CellToIndex.I, item.CellToIndex.J] = true;
                heap.Add(indices[item.CellToIndex.I, item.CellToIndex.J]);
            }
            #endregion
            HashSet <Index> trailIndices = new HashSet <Index>(trail);
            while (!(heap.Count == 0 || trailIndices.Count == 0))
            {
                var current = heap.Min;
                heap.Remove(current);
                marked[current.I, current.J] = true;
                if (trailIndices.Contains(current))
                {
                    trailIndices.Remove(current);
                }
                foreach (var item in this.Rays.Keys)
                {
                    int I = current.I + item.I;
                    int J = current.J + item.J;
                    if (this._host.cellularFloor.ContainsCell(I, J) &&
                        this._host.cellularFloor.Cells[I, J].FieldOverlapState == OverlapState.Inside &&
                        !marked[I, J])
                    {
                        var    neighborIndex = indices[I, J];
                        double edgeCost      = this.getStaticCostOfEdge(neighborIndex, current, distance_cost_factor, costs);
                        if (edgeCost <= 0)
                        {
                            throw new ArgumentException("Negative cost for edge found: " + edgeCost.ToString() +
                                                        "\nP1: " +
                                                        this._host.cellularFloor.FindCell(current).ToString() + "\nP2: " + this._host.cellularFloor.FindCell(neighborIndex).ToString() +
                                                        "\nDistance: " + this._host.cellularFloor.FindCell(current).DistanceTo(this._host.cellularFloor.FindCell(neighborIndex)).ToString());
                        }
                        double newPotential = current.WeightingFactor + edgeCost;
                        if (!heap.Contains(neighborIndex))
                        {
                            neighborIndex.WeightingFactor = newPotential;
                            heap.Add(neighborIndex);
                        }
                        else
                        {
                            if (neighborIndex.WeightingFactor > newPotential)
                            {
                                heap.Remove(neighborIndex);
                                neighborIndex.WeightingFactor = newPotential;
                                heap.Add(neighborIndex);
                            }
                        }
                    }
                }
            }
            heap   = null;
            marked = null;
            costs  = null;
            Dictionary <Cell, double> potentials = new Dictionary <Cell, double>();
            foreach (var item in indices)
            {
                if (!double.IsInfinity(item.WeightingFactor))
                {
                    potentials.Add(this._host.cellularFloor.Cells[item.I, item.J], item.WeightingFactor);
                }
            }
            indices = null;
            timer.Stop();
            this.PotentialFieldGenerationTime = timer.Elapsed.TotalMilliseconds;
            return(new Activity(potentials, destinations, destinationArea, defaultState, name, this._host.cellularFloor));
        }