/// <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)); }
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)); }
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; }
public void Merge(WeightedIndex weightedIndex, float weightCoefficient) { weights.TryGetValue(weightedIndex.Index, out float previousWeight); weights[weightedIndex.Index] = previousWeight + weightCoefficient * weightedIndex.Weight; }
/// <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)); }
/// <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)); }
/// <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)); }