tbf/SchematicDrawing/Pipe.cs

147 lines
5.5 KiB
C#

///
/// 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<int, IDrawingItem> 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;
}
/// <summary>
/// Calculates coordinates of the start- and the end-point
/// </summary>
/// <param name="x1">Start point X</param>
/// <param name="y1">Start point Y</param>
/// <param name="x2">End point X</param>
/// <param name="y2">End point Y</param>
/// <returns>true when calculation successful</returns>
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;
}
}
/// <summary>
/// Converts pipe string to start and end items
/// </summary>
/// <param name="pipeStr">Edge string</param>
/// <param name="name2Item">Dictionary of items</param>
/// <param name="startItem">Start item</param>
/// <param name="endItem">End item</param>
/// <returns>true when conversion successful</returns>
public static bool String2Items(string pipeStr, Dictionary<int, IDrawingItem> 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;
}
/// <summary>
/// Returns true when two pipes have an intersection
/// </summary>
/// <param name="pipe2">Second pipe</param>
/// <returns>true when ipes intersect</returns>
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
}
}
}