/// /// Copyright (c) 2020-2021 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; namespace SchematicDrawing { public class Pipe { public IDrawingItem StartItem; public int StartNodeId; public IDrawingItem EndItem; public int EndNodeId; public Sz Sz; public bool CoordinatesAreValid; public int x1, y1, x2, y2; public bool HasIntersection; public float P; public Pipe(IDrawingItem startItem, int startNodeId, IDrawingItem endItem, int endNodeId, Sz sz) { StartItem = startItem; StartNodeId = startNodeId; EndItem = endItem; EndNodeId = endNodeId; Sz = sz; CoordinatesAreValid = false; HasIntersection = false; } public Pipe(string pipeStr, Sz sz, Dictionary id2Item) { String2Items(pipeStr, id2Item, out StartItem, out StartNodeId, out EndItem, out EndNodeId); Sz = sz; CoordinatesAreValid = false; HasIntersection = false; } public override string ToString() { return (StartItem != null && EndItem != null) ? string.Format("{0}~{1}~{2}~{3}", StartItem.Id, StartNodeId, EndItem.Id, EndNodeId) : string.Empty; } /// /// Calculates coordinates of the start- and the end-point /// /// Start point X /// Start point Y /// End point X /// End point Y /// true when calculation successful public bool GetCoordinates() { DrawingShape startDShape = DrawingShape.GetDrawingShape(StartItem); DrawingShape endDShape = DrawingShape.GetDrawingShape(EndItem); if (StartItem != null && EndItem != null && startDShape != null && endDShape != null) { Node startNode = startDShape.GetRotatedFlippedNode(StartItem, StartNodeId); Node endNode = endDShape.GetRotatedFlippedNode(EndItem, EndNodeId); x1 = StartItem.X + startNode.X * Const.GridSize; y1 = StartItem.Y + startNode.Y * Const.GridSize; x2 = EndItem.X + endNode.X * Const.GridSize; y2 = EndItem.Y + endNode.Y * Const.GridSize; CoordinatesAreValid = true; return true; } else { return false; } } /// /// Converts pipe string to start and end items /// /// Edge string /// Dictionary of items /// Start item /// End item /// true when conversion successful public static bool String2Items(string pipeStr, Dictionary id2Item, out IDrawingItem startItem, out int startNid, out IDrawingItem endItem, out int endNid) { string[] fields = pipeStr.Split(new char[] { '~' }); int startId, endId; IDrawingItem start, end; DrawingShape dshapeFrom, dshapeTo; if (fields.Length == 4 && int.TryParse(fields[0], out startId) && id2Item.TryGetValue(startId, out start) && (null != (dshapeFrom = DrawingShape.Shapes[DrawingShape.DrShIx(start.Shape, start.Sz)])) && int.TryParse(fields[1], out startNid) && (startNid >= 0) && (startNid < dshapeFrom.Nodes.Length) && int.TryParse(fields[2], out endId) && id2Item.TryGetValue(endId, out end) && (null != (dshapeTo = DrawingShape.Shapes[DrawingShape.DrShIx(end.Shape, end.Sz)])) && int.TryParse(fields[3], out endNid) && (endNid >= 0) && (endNid < dshapeTo.Nodes.Length)) { startItem = start; endItem = end; return true; } startItem = null; endItem = null; startNid = 0; endNid = 0; return false; } /// /// Returns true when two pipes have an intersection /// /// Second pipe /// true when ipes intersect public bool CalculateIntersectionWith(Pipe pipe2) { if (!this.CoordinatesAreValid) GetCoordinates(); if (!pipe2.CoordinatesAreValid) pipe2.GetCoordinates(); int D = (x2 - x1) * (pipe2.y2 - pipe2.y1) - (y2 - y1) * (pipe2.x2 - pipe2.x1); float Dp = Convert.ToSingle((pipe2.x1 - x1) * (pipe2.y2 - pipe2.y1) - (pipe2.y1 - y1) * (pipe2.x2 - pipe2.x1)); float Dq = Convert.ToSingle((x2 - x1) * (pipe2.y1 - y1) - (y2 - y1) * (pipe2.x1 - x1)); if (D == 0) { return false; /// Parallel pipes -> no intersection } float Df = Convert.ToSingle(D); float p = Dp / Df; float q = -Dq / Df; if (p > 0.01 && p < 0.99 && q > 0.01 && q < 0.99) { this.HasIntersection = true; this.P = p; return true; /// Pipes intersect, pipes touching by their ends are not considered } return false; /// Pipes do not intersect } } }