static void CreateNew() { // Create the actual object GameObject newObject = new GameObject("Line"); Mesh newMesh = new Mesh(); newMesh.name = "Line mesh"; MeshFilter newMeshFilter = newObject.AddComponent <MeshFilter>(); newMeshFilter.mesh = newMesh; // Create mesh collider newObject.AddComponent <MeshCollider>(); // Create mesh renderer newObject.AddComponent <MeshRenderer>(); // Attach script UVLine newLineScript = newObject.AddComponent <UVLine>(); newLineScript.start = new Vector2(0, 0); newLineScript.end = new Vector2(10, 0); // Make this action undoable Undo.RegisterCreatedObjectUndo(newObject, "Create Line"); // Select the new object Selection.objects = new GameObject[] { newObject }; //Selection.activeTransform = gameObject.transform; }
/// <summary> /// returns null if ray does not hit the line. When hit, returns the distance from the hit point /// </summary> /// <param name="line">Line barrier</param> /// <returns>distance of ray origins from the hit point along the ray direction</returns> public double?DistanceToForIsovist(UVLine line, double tolerance) { //checking if the lines intersect at all double vs = this.Direction.CrossProductValue(this.Origin - line.Start); double ve = this.Direction.CrossProductValue(this.Origin - line.End); if (vs * ve > -tolerance) { return(null); } //finding the intersection if (vs == 0) { return(this.Origin.DistanceTo(line.Start)); } else if (ve == 0) { return(this.Origin.DistanceTo(line.End)); } else { double _length = line.GetLength(); vs = Math.Abs(vs); ve = Math.Abs(ve); double lengthFromStart = _length * vs / (vs + ve); UV hitPoint = line.FindPoint(lengthFromStart); return(this.Origin.DistanceTo(hitPoint)); } }
public void VisualizeLine(UVLine line, double elevation) { SpatialAnalysis.Geometry.UV start = line.Start.Copy(); SpatialAnalysis.Geometry.UV end = line.End.Copy(); unitConversion.Transform(start); unitConversion.Transform(end); using (Transaction t = new Transaction(OSM_FOR_REVIT.RevitDocument, "Draw Barriers")) { t.Start(); FailureHandlingOptions failOpt = t.GetFailureHandlingOptions(); failOpt.SetFailuresPreprocessor(new CurveDrawingWarningSwallower()); t.SetFailureHandlingOptions(failOpt); Plane p = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, new XYZ(0, 0, elevation)); SketchPlane skp = SketchPlane.Create(OSM_FOR_REVIT.RevitDocument, p); try { XYZ p1 = new XYZ(start.U, start.V, elevation); XYZ p2 = new XYZ(end.U, end.V, elevation); Line l = Line.CreateBound(p1, p2); OSM_FOR_REVIT.RevitDocument.Create.NewModelCurve(l, skp); } catch (Exception e) { MessageBox.Show(e.Report()); } t.Commit(); } }
/// <summary> /// Determines if the ray intersects with a specified line. /// </summary> /// <param name="line">The line.</param> /// <param name="tolerance">The tolerance.</param> /// <returns><c>true</c> if intersects, <c>false</c> otherwise.</returns> public bool Intersects(UVLine line, double tolerance = 0) { double vs = this.Direction.CrossProductValue(this.Origin - line.Start); double ve = this.Direction.CrossProductValue(this.Origin - line.End); if (vs * ve > tolerance) { return(false); } return(true); }
/// <summary> /// Detects the collision that occurs between two states /// </summary> /// <param name="previous">Previous state</param> /// <param name="current">Current state</param> /// <param name="buffer">Offset buffer which is the radius of the body</param> /// <param name="tolerance">Tolerance set by default to the main document's absolute tolerance factor</param> /// <returns>An instance of the collision which can be null</returns> public static ICollision GetCollision(CollisionAnalyzer previous, CollisionAnalyzer current, double buffer, double tolerance = OSMDocument.AbsoluteTolerance) { Trajectory trajectory = new Trajectory(current.Location, previous.Location); List <ICollision> collisions = new List <ICollision>(); UVLine edgeBuffer1 = CollisionAnalyzer.OffsetLine(previous.Barrrier, previous.Location, buffer); ICollision collisionWithEdgeBuffer1 = new GetCollisionWithEdge(trajectory, edgeBuffer1); collisions.Add(collisionWithEdgeBuffer1); ICollision collisionWithPreviousBarrierEndPoint = new GetCollisionWithEndPoint(trajectory, previous.Barrrier.End, buffer); collisions.Add(collisionWithPreviousBarrierEndPoint); ICollision collisionWithPreviousBarrierStartPoint = new GetCollisionWithEndPoint(trajectory, previous.Barrrier.Start, buffer); collisions.Add(collisionWithPreviousBarrierStartPoint); if (!previous.Barrrier.Equals(current.Barrrier)) { UVLine edgeBuffer2 = CollisionAnalyzer.OffsetLine(current.Barrrier, previous.Location, buffer); ICollision collisionWithEdgeBuffer2 = new GetCollisionWithEdge(trajectory, edgeBuffer2); collisions.Add(collisionWithEdgeBuffer2); if (current.Barrrier.End != previous.Barrrier.End && current.Barrrier.End != previous.Barrrier.Start) { ICollision collisionWithCurrentBarrierEndPoint = new GetCollisionWithEndPoint(trajectory, current.Barrrier.End, buffer); collisions.Add(collisionWithCurrentBarrierEndPoint); } if (current.Barrrier.Start != previous.Barrrier.End && current.Barrrier.Start != previous.Barrrier.Start) { ICollision collisionWithCurrentBarrierStartPoint = new GetCollisionWithEndPoint(trajectory, current.Barrrier.Start, buffer); collisions.Add(collisionWithCurrentBarrierStartPoint); } } if (collisions.Count != 0) { collisions.Sort((a, b) => a.LengthToCollision.CompareTo(b.LengthToCollision)); ICollision firstCollision = collisions[0]; if (!double.IsInfinity(firstCollision.LengthToCollision)) { //if (double.IsNaN(firstCollision.TimeStepRemainderProportion)) //{ // System.Windows.MessageBox.Show(double.NaN.ToString() + " caught!"); // GetCollision(previous, current, buffer, tolerance); //} return(firstCollision); } } return(null); }
//Offsets an edge towards a line private static UVLine OffsetLine(UVLine edge, UV location, double offset) { UV vector = location - edge.Start; UV edgeDirection = edge.End - edge.Start; edgeDirection.Unitize(); UV vt = edgeDirection * edgeDirection.DotProduct(vector); UV vp = vector - vt; vp.Unitize(); UV start = edge.Start + vp * offset; UV end = edge.End + vp * offset; return(new UVLine(start, end)); }
/// <summary> /// Creates an instance of the collision /// </summary> /// <param name="displacementTrajectory">Displacement Trajectory</param> /// <param name="bufferEdge">Barrier edge offseted according to buffer</param> /// <param name="tolerance">Tolerance by default set to the tolerance absolute value of the main document</param> public GetCollisionWithEdge(Trajectory displacementTrajectory, UVLine bufferEdge, double tolerance = OSMDocument.AbsoluteTolerance) { this.DisplacementTrajectory = displacementTrajectory; this.BufferDirection = bufferEdge.End - bufferEdge.Start; double?t = this.DisplacementTrajectory.TrajectoryLine.Intersection(bufferEdge, this.DisplacementTrajectory.TrajectoryLength, tolerance); if (t == null) { this.LengthToCollision = double.PositiveInfinity; return; } this.CollisionPoint = this.DisplacementTrajectory.TrajectoryLine.Start + t.Value * this.DisplacementTrajectory.TrajectoryNormalizedVector; this.LengthToCollision = DisplacementTrajectory.TrajectoryLength - t.Value; this.TimeStepRemainderProportion = t.Value / this.DisplacementTrajectory.TrajectoryLength; }
private void DrawJG_MouseMove(object sender, MouseEventArgs e) { try { double y = this.rootVertex.Point.V; Point point = Mouse.GetPosition(this); UV p = new UV(point.X, point.Y); if (this._moveMode == MoveMode.Horizontally) { point.Y = y; p.V = y; } foreach (JGVertex item in this.rootVertex.Connections) { //create the UVLine UVLine uvLine = new UVLine(this.rootVertex.Point.Copy(), item.Point); //find the Line from the map Line line = this.edge_line.Find(uvLine); //clear the pair of UVLine and Line from the map this.edge_line.Remove(uvLine); //update the UVLine with deep copies of the endpoints uvLine.Start = p.Copy(); uvLine.End = item.Point.Copy(); //update the line line.X1 = uvLine.Start.U; line.Y1 = uvLine.Start.V; line.X2 = uvLine.End.U; line.Y2 = uvLine.End.V; // Add the pair of UVLine and Line to the map this.edge_line.Add(line, uvLine); } //updating the vertex and its mark this.vertex_mark.Remove(this.rootLine); this.rootVertex.Point = p; this.rootLine.X1 = point.X - this.lineThickness / 2; this.rootLine.X2 = point.X + this.lineThickness / 2; this.rootLine.Y1 = point.Y; this.rootLine.Y2 = point.Y; this.vertex_mark.Add(this.rootVertex, this.rootLine); } catch (Exception) { //MessageBox.Show("from mouse move event: \n" + error.Message); } }
private INTPolygon excludedArea(UV center, double r, UVLine edge) { INTPolygon area = new INTPolygon(); double ds = edge.Start.DistanceTo(center); double de = edge.End.DistanceTo(center); r = (r > ds) ? r : ds; r = (r > de) ? r : de; double R = 1.43 * r; // somthing larger than Math.Sqrt(2)*r UV os = edge.Start - center; os.Unitize(); UV oe = edge.End - center; oe.Unitize(); List <UV> pnts = new List <UV>(); double x = oe.DotProduct(os); if (x == 0) { return(area); } else if (x >= 0) { pnts.Add(edge.Start); pnts.Add(center + os * R); pnts.Add(center + oe * R); pnts.Add(edge.End); } else // if (x<0) { UV om = (os + oe) / 2; om.Unitize(); pnts.Add(edge.Start); pnts.Add(center + os * R); pnts.Add(center + om * R); pnts.Add(center + oe * R); pnts.Add(edge.End); } return(this.ConvertUVListToINTPolygon(pnts)); }
/// <summary> /// returns null if ray does not hit the line. When hit, returns the distance from the hit point /// </summary> /// <param name="hitPoint">Hit point on the barrier</param> /// <param name="line">Line barrier</param> /// <returns>distance of ray origins from the hit point along the ray direction</returns> public double?DistanceTo(UVLine line, ref UV hitPoint, double tolerance = 0.0001) { hitPoint = null; double?result = null; double vs = this.Direction.CrossProductValue(this.Origin - line.Start); double ve = this.Direction.CrossProductValue(this.Origin - line.End); if (vs * ve > tolerance) { return(null); } if (vs == 0) { result = this.Origin.DistanceTo(line.Start); hitPoint = line.Start; } else if (ve == 0) { result = this.Origin.DistanceTo(line.End); hitPoint = line.End; } else { double _length = line.GetLength(); vs = Math.Abs(vs); ve = Math.Abs(ve); double lengthFromStart = _length * vs / (vs + ve); hitPoint = line.FindPoint(lengthFromStart); result = this.Origin.DistanceTo(hitPoint); } if (result != null) { var hitDirection = hitPoint - this.Origin; if (hitDirection.DotProduct(this.Direction) < 0) { result = null; hitPoint = null; } } return(result); }
/// <summary> /// Finds the interval of a line at V direction /// </summary> /// <param name="line">A line to find the interval for</param> /// <returns>A new interval</returns> public static Interval LineVValues(UVLine line) { return(new Interval(line.Start.V, line.End.V)); }
/// <summary> /// Finds the interval of a line at U direction /// </summary> /// <param name="line">A line to find the interval for</param> /// <returns>A new interval</returns> public static Interval LineUValues(UVLine line) { return(new Interval(line.Start.U, line.End.U)); }
/// <summary> /// Create the barrier buffer polygons around the edges of the walkable field using Minkowski addition /// </summary> /// <param name="barrierEnvironment"></param> /// <param name="offsetValue"></param> public void LoadAllBarriersOffseted(BIM_To_OSM_Base barrierEnvironment, double offsetValue) { //offetting all of the boundaries this.BarrierBuffers = barrierEnvironment.ExpandAllBarrierPolygons(offsetValue); // creating lines for the boundaries int edgeNum = 0; foreach (BarrierPolygon item in this.BarrierBuffers) { edgeNum += item.Length; } this.BarrierBufferEdges = new UVLine[edgeNum]; edgeNum = 0; foreach (BarrierPolygon brr in this.BarrierBuffers) { for (int i = 0; i < brr.Length; i++) { UVLine line = new UVLine(brr.PointAt(i), brr.PointAt(brr.NextIndex(i))); this.BarrierBufferEdges[edgeNum] = line; edgeNum++; } } // cleaning up the cells from previous settings foreach (Cell cell in this.Cells) { if (cell.BarrierBufferEdgeIndices == null) { cell.BarrierBufferEdgeIndices = new HashSet <int>(); } else { cell.BarrierBufferEdgeIndices.Clear(); } cell.BarrierBufferOverlapState = OverlapState.Outside; cell.BufferBarrierEndPoints = null; } // loading the lines into the cells for (int i = 0; i < this.BarrierBufferEdges.Length; i++) { Index[] intersectingCellIndices = this.FindLineIndices(this.BarrierBufferEdges[i]); foreach (Index item in intersectingCellIndices) { if (this.ContainsCell(item)) { this.Cells[item.I, item.J].BarrierBufferEdgeIndices.Add(i); } } } //loading edge end points into the cells foreach (BarrierPolygon polygon in this.BarrierBuffers) { foreach (UV point in polygon.BoundaryPoints) { Cell cell = this.FindCell(point); if (cell != null) { if (cell.BufferBarrierEndPoints == null) { cell.BufferBarrierEndPoints = new List <UV>(); } cell.BufferBarrierEndPoints.Add(point); } } } // setting the overlapping states of the cells that overlap foreach (Cell cell in this.Cells) { if (cell.BarrierBufferEdgeIndices.Count > 0) { cell.BarrierBufferOverlapState = OverlapState.Overlap; } } HashSet <Index> edge = new HashSet <Index>(); foreach (Cell item in this.Cells) { if (item.FieldOverlapState == OverlapState.Overlap) { var index = this.FindIndex(item); if (index.I == 0 || index.I == this.GridWidth - 1 || index.J == 0 || index.J == this.GridHeight - 1) { } else { edge.Add(index); } } } HashSet <Index> temp_edge = new HashSet <Index>(); HashSet <Index> area = new HashSet <Index>(); area.UnionWith(edge); while (edge.Count != 0) { foreach (var item in edge) { foreach (var neighbor in Index.Neighbors) { var next = item + neighbor; if (this.ContainsCell(next)) { if (!area.Contains(next)) { if (this.Cells[next.I, next.J].FieldOverlapState == OverlapState.Inside && this.Cells[next.I, next.J].BarrierBufferOverlapState != OverlapState.Overlap) { temp_edge.Add(next); } } } } } edge.Clear(); edge.UnionWith(temp_edge); area.UnionWith(temp_edge); temp_edge.Clear(); } foreach (Index item in area) { this.Cells[item.I, item.J].BarrierBufferOverlapState = OverlapState.Inside; } edge.Clear(); edge = null; temp_edge.Clear(); temp_edge = null; area.Clear(); area = null; for (int i = 0; i < this.GridWidth; i++) { for (int j = 0; j < this.GridHeight; j++) { if (this.Cells[i, j].FieldOverlapState != OverlapState.Inside) { if (this.Cells[i, j].BarrierBufferOverlapState != OverlapState.Overlap) { this.Cells[i, j].BarrierBufferOverlapState = OverlapState.Inside; } } } } }
/// <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); }