/// <summary> /// Returns a ordered array of indices that the ray intersects with. These indices include the overlapping length of the ray as their weighting factor. /// </summary> /// <param name="origin">The origin.</param> /// <param name="target">The target.</param> /// <param name="cellularFloor">The cellular floor.</param> /// <param name="tolerance">The tolerance.</param> /// <returns>WeightedIndex[].</returns> public static WeightedIndex[] LoadWeightingFactors(UV origin, UV target, CellularFloorBaseGeometry cellularFloor, double tolerance = OSMDocument.AbsoluteTolerance) { UV direction = target - origin; double length = direction.GetLength(); direction /= length; Ray ray = new Ray(origin, direction, cellularFloor.Origin, cellularFloor.CellSize, tolerance); List <WeightedIndex> weightedIndices = new List <WeightedIndex>(); while (ray.Length + tolerance < length) { double d1 = ray.Length; UV p1 = ray.PointAt(d1); ray.Next(tolerance); double d2 = ray.Length; UV p2 = ray.PointAt(d2); UV p = (p1 + p2) / 2; double w = d2 - d1; if (w > tolerance) { double i = (p.U - cellularFloor.Origin.U) / cellularFloor.CellSize; int I = (int)i; double j = (p.V - cellularFloor.Origin.V) / cellularFloor.CellSize; int J = (int)j; WeightedIndex weightedIndex = new WeightedIndex(I, J, w); weightedIndices.Add(weightedIndex); } } return(weightedIndices.ToArray()); }
/// <summary> /// Visualizes the intersection in BIM environment. /// </summary> /// <param name="visualizer">The visualizer.</param> /// <param name="rayOrigin">The ray origin.</param> /// <param name="cellularFloor">The cellular floor.</param> /// <param name="elevation">The elevation.</param> /// <param name="pointSize">Size of the point.</param> public void Visualize(I_OSM_To_BIM visualizer, UV rayOrigin, CellularFloorBaseGeometry cellularFloor, double elevation, double pointSize = .3) { switch (this.Type) { case BarrierType.Visual: //visualizer.VisualizeBoundary(cellularFloor.VisualBarriers[this.BarrierIndex].BoundaryPoints, elevation); visualizer.VisualizeLine(cellularFloor.VisualBarrierEdges[this.EdgeIndexInCellularFloor], elevation); break; case BarrierType.Physical: //visualizer.VisualizeBoundary(cellularFloor.PhysicalBarriers[this.BarrierIndex].BoundaryPoints, elevation); visualizer.VisualizeLine(cellularFloor.PhysicalBarrierEdges[this.EdgeIndexInCellularFloor], elevation); break; case BarrierType.Field: //visualizer.VisualizeBoundary(cellularFloor.PhysicalBarriers[this.BarrierIndex].BoundaryPoints, elevation); visualizer.VisualizeLine(cellularFloor.FieldBarrierEdges[this.EdgeIndexInCellularFloor], elevation); break; default: break; } //visualizer.VisualizePoint(IntersectingPoint, pointSize, elevation); visualizer.VisualizeLine(new UVLine(rayOrigin, this.IntersectingPoint), elevation); }
/// <summary> /// Determines if a cell is on the edges of a cell collections /// </summary> /// <param name="cellID">The ID of the cell</param> /// <param name="cellularFloor">The CellularFloorBaseGeometry to which this cell belongs</param> /// <param name="collection">Cell ID collection</param> /// <returns>true for being on the edge false for not being on the edge</returns> private static bool onEdge(int cellID, CellularFloorBaseGeometry cellularFloor, HashSet <int> collection) { var index = cellularFloor.FindIndex(cellID); if (index.I == 0 || index.I == cellularFloor.GridWidth - 1 || index.J == 0 || index.J == cellularFloor.GridHeight - 1) { return(true); } int iMin = (index.I == 0) ? 0 : index.I - 1; int iMax = (index.I == cellularFloor.GridWidth - 1) ? cellularFloor.GridWidth - 1 : index.I + 1; int jMin = (index.J == 0) ? 0 : index.J - 1; int jMax = (index.J == cellularFloor.GridHeight - 1) ? cellularFloor.GridHeight - 1 : index.J + 1; for (int i = iMin; i <= iMax; i++) { for (int j = jMin; j <= jMax; j++) { if (cellularFloor.ContainsCell(i, j)) { if (!collection.Contains(cellularFloor.Cells[i, j].ID)) { return(true); } } } } return(false); }
/// <summary> /// Extracts the edges of a collection of cells /// </summary> /// <param name="cellularFloor">The CellularFloorBaseGeometry to which the cells belong</param> /// <param name="collection">A collection of cells IDs to find its edges</param> /// <returns>A collection of cell IDs on the edge</returns> public static HashSet <int> GetEdgeOfField(CellularFloorBaseGeometry cellularFloor, HashSet <int> collection) { HashSet <int> edge = new HashSet <int>(); foreach (var item in collection) { if (CellUtility.onEdge(item, cellularFloor, collection)) { edge.Add(item); } } return(edge); }
/// <summary> /// Extracts the edges of a collection of cells /// </summary> /// <param name="cellularFloor">The CellularFloorBaseGeometry to which the cells belong</param> /// <param name="collection">A collection of cells to find its edges</param> /// <returns>A collection of cell indices on the edge</returns> public static HashSet <Index> GetIndexEdgeOfField(CellularFloorBaseGeometry cellularFloor, HashSet <Cell> collection) { HashSet <Index> edge = new HashSet <Index>(); foreach (var item in collection) { Index index = cellularFloor.FindIndex(item); if (CellUtility.onEdge(index, cellularFloor, collection)) { edge.Add(index); } } return(edge); }
/// <summary> /// Determines if a cell is on the edges of a cell collections /// </summary> /// <param name="index">The index of the cell</param> /// <param name="cellularFloor">The CellularFloorBaseGeometry to which this cell belongs</param> /// <param name="collection">Cell ID collection</param> /// <returns>true for being on the edge false for not being on the edge</returns> private static bool onEdge(Index index, CellularFloorBaseGeometry cellularFloor, HashSet <Cell> collection) { foreach (Index item in Index.Neighbors) { Index neighbor = item + index; if (cellularFloor.ContainsCell(neighbor)) { if (!collection.Contains(cellularFloor.Cells[neighbor.I, neighbor.J])) { return(true); } } } return(false); }
/// <summary> /// Gets the boundary polygons of a collection of cells. /// </summary> /// <param name="cellIDs">The visible cells.</param> /// <param name="cellularFloor">The cellular floor.</param> /// <returns>List<BarrierPolygons>.</returns> public static List <BarrierPolygon> GetBoundary(ICollection <int> cellIDs, CellularFloorBaseGeometry cellularFloor) { Dictionary <UVLine, int> guid = new Dictionary <UVLine, int>(); foreach (var item in cellIDs) { var lines = cellularFloor.CellToLines(cellularFloor.FindCell(item)); foreach (var line in lines) { if (guid.ContainsKey(line)) { guid[line]++; } else { guid.Add(line, 1); } } } List <UVLine> boundaryLines = new List <UVLine>(); foreach (KeyValuePair <UVLine, int> item in guid) { if (item.Value == 1) { boundaryLines.Add(item.Key); } } guid.Clear(); guid = null; var plines = PLine.ExtractPLines(boundaryLines); List <BarrierPolygon> boundary = new List <BarrierPolygon>(); foreach (PLine item in plines) { var oneBoundary = item.Simplify(cellularFloor.CellSize / 10); if (oneBoundary != null) { boundary.Add(new BarrierPolygon(oneBoundary.ToArray())); } } boundaryLines.Clear(); boundaryLines = null; return(boundary); }
/// <summary> /// Creats an instance of the CollisionAnalyzer. /// </summary> /// <param name="point">The agent or target location</param> /// <param name="cellularFloor">The CellularFloorBaseGeometry which includes the agent or target</param> /// <param name="barrierType">Barrier type</param> /// <returns>An instance of the CollisionAnalyzer which can be null</returns> public static CollisionAnalyzer GetCollidingEdge(UV point, CellularFloorBaseGeometry cellularFloor, BarrierType barrierType) { Cell cell = cellularFloor.FindCell(point); if (cell == null) { return(null); } switch (barrierType) { case BarrierType.Visual: if (cell.VisualOverlapState == OverlapState.Inside) { return(null); } break; case BarrierType.Physical: if (cell.PhysicalOverlapState == OverlapState.Inside) { return(null); } break; case BarrierType.Field: if (cell.FieldOverlapState == OverlapState.Outside) { //cell.Visualize(MainDocument.TargetVisualizer, Cell.Size, Cell.Size, 0); return(null); } break; case BarrierType.BarrierBuffer: return(null); } var colision = new CollisionAnalyzer(point, cell, cellularFloor, barrierType); if (colision.Barrrier == null) { return(null); } return(colision); }
/// <summary> /// Get a list of ordered cells on the edge of a cell collection /// </summary> /// <param name="cellularFloor">The CellularFloorBaseGeometry to which the cells belong</param> /// <param name="collection">A collection of cells to find its edges</param> /// <returns>An ordered list of cells</returns> public static List <Cell> GetOrderedEdge(CellularFloorBaseGeometry cellularFloor, HashSet <Cell> collection) { HashSet <Index> edge = CellUtility.GetIndexEdgeOfField(cellularFloor, collection); IndexGraph indexGraph = new IndexGraph(edge); int zero = 0, one = 0, two = 0, three = 0, four = 0; foreach (var item in indexGraph.IndexNodeMap.Values) { switch (item.Connections.Count) { case 0: zero++; break; case 1: one++; break; case 2: two++; break; case 3: three++; break; case 4: four++; break; default: break; } } MessageBox.Show(string.Format("Zero: {0}\nOne: {1}\nTwo: {2}\nThree: {3}\nFour: {4}", zero.ToString(), one.ToString(), two.ToString(), three.ToString(), four.ToString())); return(null); }
/// <summary> /// Creats an instance of the CollisionAnalyzer. For internal use only. /// </summary> /// <param name="point">The agent or target location</param> /// <param name="cell">The cell to which the point belongs</param> /// <param name="cellularFloor">The CellularFloorBaseGeometry which includes the agent or target</param> /// <param name="barrierType">Barrier type</param> internal CollisionAnalyzer(UV point, Cell cell, CellularFloorBaseGeometry cellularFloor, BarrierType barrierType) { this.CollisionOccured = false; this.Location = point; Index index = cellularFloor.FindIndex(cell); int I = index.I + 2; //int I = index.I + 1; I = Math.Min(I, cellularFloor.GridWidth - 1); int J = index.J + 2; //int J = index.J + 1; J = Math.Min(J, cellularFloor.GridHeight - 1); index.I = Math.Max(0, index.I - 1); index.J = Math.Max(0, index.J - 1); double DistanceSquared = double.PositiveInfinity; for (int i = index.I; i <= I; i++) { for (int j = index.J; j <= J; j++) { switch (barrierType) { case BarrierType.Visual: if (cellularFloor.Cells[i, j].VisualOverlapState == OverlapState.Outside) { foreach (int item in cellularFloor.Cells[i, j].VisualBarrierEdgeIndices) { double d = point.GetDistanceSquared(cellularFloor.VisualBarrierEdges[item]); if (d < DistanceSquared) { DistanceSquared = d; Barrrier = cellularFloor.VisualBarrierEdges[item]; } } } break; case BarrierType.Physical: if (cellularFloor.Cells[i, j].PhysicalOverlapState != OverlapState.Outside) { foreach (int item in cellularFloor.Cells[i, j].PhysicalBarrierEdgeIndices) { double d = point.GetDistanceSquared(cellularFloor.PhysicalBarrierEdges[item]); if (d < DistanceSquared) { DistanceSquared = d; Barrrier = cellularFloor.PhysicalBarrierEdges[item]; } } } break; case BarrierType.Field: if (cellularFloor.Cells[i, j].BarrierBufferOverlapState != OverlapState.Inside) { foreach (int item in cellularFloor.Cells[i, j].FieldBarrierEdgeIndices) { double d = point.GetDistanceSquared(cellularFloor.FieldBarrierEdges[item]); if (d < DistanceSquared) { DistanceSquared = d; Barrrier = cellularFloor.FieldBarrierEdges[item]; } } } break; } } } if (!double.IsPositiveInfinity(DistanceSquared) && this.Barrrier != null) { bool isEndpoint = false; this.ClosestPointOnBarrier = point.GetClosestPoint(this.Barrrier, ref isEndpoint); this.IsClosestPointAnEndPoint = isEndpoint; this.NormalizedRepulsion = this.Location - this.ClosestPointOnBarrier; this.DistanceToBarrier = this.NormalizedRepulsion.GetLength(); this.NormalizedRepulsion /= this.DistanceToBarrier; } }
/// <summary> /// Checks the existence of a line of sight between two points. /// </summary> /// <param name="origin">The origin.</param> /// <param name="target">The target.</param> /// <param name="barrierType">Type of the barrier.</param> /// <param name="cellularFloor">The cellular floor.</param> /// <param name="tolerance">The tolerance.</param> /// <returns><c>true</c> if visible, <c>false</c> otherwise.</returns> public static bool Visible(UV origin, UV target, BarrierType barrierType, CellularFloorBaseGeometry cellularFloor, double tolerance = OSMDocument.AbsoluteTolerance) { UV direction = target - origin; double length = direction.GetLength(); direction /= length; Ray ray = new Ray(origin, direction, cellularFloor.Origin, cellularFloor.CellSize, tolerance); while (ray.Length + tolerance < length) { Index index = ray.NextIndex(cellularFloor.FindIndex, tolerance); if (cellularFloor.ContainsCell(index)) { switch (barrierType) { case BarrierType.Visual: if (cellularFloor.Cells[index.I, index.J].VisualOverlapState == OverlapState.Overlap) { foreach (int item in cellularFloor.Cells[index.I, index.J].VisualBarrierEdgeIndices) { double?distance = ray.DistanceToForIsovist(cellularFloor.VisualBarrierEdges[item], tolerance); if (distance != null && distance.Value + tolerance < length) { UVLine hitEdge = cellularFloor.VisualBarrierEdges[item]; return(false); } } } break; case BarrierType.Physical: if (cellularFloor.Cells[index.I, index.J].PhysicalOverlapState == OverlapState.Overlap) { foreach (int item in cellularFloor.Cells[index.I, index.J].PhysicalBarrierEdgeIndices) { double?distance = ray.DistanceToForIsovist(cellularFloor.PhysicalBarrierEdges[item], tolerance); if (distance != null && distance.Value + tolerance < length) { UVLine hitEdge = cellularFloor.PhysicalBarrierEdges[item]; return(false); } } } break; case BarrierType.Field: if (cellularFloor.Cells[index.I, index.J].FieldOverlapState == OverlapState.Overlap) { foreach (int item in cellularFloor.Cells[index.I, index.J].FieldBarrierEdgeIndices) { double?distance = ray.DistanceToForIsovist(cellularFloor.FieldBarrierEdges[item], tolerance); if (distance != null && distance.Value + tolerance < length) { UVLine hitEdge = cellularFloor.FieldBarrierEdges[item]; return(false); } } } break; default: break; } } } return(true); }
/// <summary> /// Determines whether a visual the event is raised. /// </summary> /// <param name="currentState">The current state of the agent.</param> /// <param name="visibilityCosineFactor">The visibility cosine factor.</param> /// <param name="cellularFloor">The cellular floor.</param> /// <returns><c>true</c> if visual the event is raised, <c>false</c> otherwise.</returns> public bool VisualEventRaised(StateBase currentState, double visibilityCosineFactor, CellularFloorBaseGeometry cellularFloor) { var vantageCell = cellularFloor.FindCell(currentState.Location); if (!this.AllVisibleCells.Contains(vantageCell.ID)) { return(false); } bool raised = false; foreach (var cellID in this.ReferencedVantageCells[vantageCell.ID]) { UV targetCell = cellularFloor.FindCell(cellID); UV direction = targetCell - currentState.Location; direction.Unitize(); if (direction.DotProduct(currentState.Direction) >= visibilityCosineFactor) { raised = true; break; } } return(raised); }
/// <summary> /// Targets the visibility test. /// </summary> /// <param name="currentState">The current state of the agent.</param> /// <param name="visibilityCosineFactor">The visibility cosine factor.</param> /// <param name="cellularFloor">The cellular floor.</param> /// <returns>UV.</returns> public UV TargetVisibilityTest(StateBase currentState, double visibilityCosineFactor, CellularFloorBaseGeometry cellularFloor) { var vantageCell = cellularFloor.FindCell(currentState.Location); if (!this.AllVisibleCells.Contains(vantageCell.ID)) { return(null); } UV target = null; foreach (var cellID in this.ReferencedVantageCells[vantageCell.ID]) { UV targetCell = cellularFloor.FindCell(cellID); UV direction = targetCell - currentState.Location; direction.Unitize(); if (direction.DotProduct(currentState.Direction) >= visibilityCosineFactor) { target = targetCell; break; } } return(target); }