2020-06-03 07:31:06 +00:00
|
|
|
|
///
|
2021-03-05 11:36:25 +00:00
|
|
|
|
/// Copyright (c) 2020-2021 Sensus Slovensko a.s.
|
2020-06-03 07:31:06 +00:00
|
|
|
|
///
|
|
|
|
|
|
using System;
|
2020-05-26 08:28:40 +00:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
|
using System.Windows.Forms;
|
2020-06-03 07:31:06 +00:00
|
|
|
|
using Dirichlet.Numerics;
|
|
|
|
|
|
using System.Numerics;
|
2020-06-17 21:17:50 +00:00
|
|
|
|
using System.Diagnostics;
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
|
|
|
|
|
namespace SchematicDrawing
|
|
|
|
|
|
{
|
|
|
|
|
|
public partial class SchematicDrawingCtrl : UserControl
|
|
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
public bool BenchControlMode { get; set; }
|
|
|
|
|
|
public bool EditMode { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
private bool supressRedraws;
|
|
|
|
|
|
public bool SupressRedraws
|
|
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (supressRedraws != value)
|
|
|
|
|
|
{
|
|
|
|
|
|
supressRedraws = value;
|
|
|
|
|
|
if (!supressRedraws)
|
|
|
|
|
|
{
|
|
|
|
|
|
JoinPipeListsEtc();
|
|
|
|
|
|
Redraw();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-06-03 07:31:06 +00:00
|
|
|
|
get { return supressRedraws; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private IDrawingItem selectedItem;
|
|
|
|
|
|
public IDrawingItem SelectedItem
|
|
|
|
|
|
{
|
|
|
|
|
|
set { if (selectedItem != value) { selectedItem = value; Redraw(); } }
|
|
|
|
|
|
get { return selectedItem; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private Element selectedElement;
|
|
|
|
|
|
public Element SelectedElement
|
|
|
|
|
|
{
|
|
|
|
|
|
set { if (selectedElement != value) { selectedElement = value; Redraw(); } }
|
|
|
|
|
|
get { return selectedElement; }
|
|
|
|
|
|
}
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
|
|
|
|
|
///
|
2020-06-03 07:31:06 +00:00
|
|
|
|
/// Route
|
2020-05-26 08:28:40 +00:00
|
|
|
|
///
|
2020-06-03 07:31:06 +00:00
|
|
|
|
private UInt128 route;
|
|
|
|
|
|
public UInt128 Route
|
|
|
|
|
|
{
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (route != value)
|
|
|
|
|
|
{
|
|
|
|
|
|
route = value;
|
|
|
|
|
|
foreach (var it in items)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (it is IRouteBasedDrawingItem)
|
|
|
|
|
|
{
|
|
|
|
|
|
Utils.UpdateGraphEdges(route, it as IRouteBasedDrawingItem);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-06-17 21:17:50 +00:00
|
|
|
|
|
|
|
|
|
|
graph.RunDijkstraAlgo();
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Redraw();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
get { return route; }
|
|
|
|
|
|
}
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
2021-03-05 11:36:25 +00:00
|
|
|
|
///
|
|
|
|
|
|
/// Measurement available flags
|
|
|
|
|
|
///
|
|
|
|
|
|
private bool[] msrmntAvailableFlags;
|
|
|
|
|
|
public bool[] MsrmntAvailableFlags
|
|
|
|
|
|
{
|
|
|
|
|
|
set { if (msrmntAvailableFlags != value) { msrmntAvailableFlags = value; Redraw(); } }
|
|
|
|
|
|
get { return msrmntAvailableFlags; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-06-03 07:31:06 +00:00
|
|
|
|
///
|
|
|
|
|
|
/// Measured values
|
|
|
|
|
|
///
|
|
|
|
|
|
private double[] measuredValues;
|
|
|
|
|
|
public double[] MeasuredValues
|
|
|
|
|
|
{
|
|
|
|
|
|
set { if (measuredValues != value) { measuredValues = value; Redraw(); } }
|
|
|
|
|
|
get { return measuredValues; }
|
|
|
|
|
|
}
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
2021-02-25 12:38:24 +00:00
|
|
|
|
///
|
|
|
|
|
|
/// Alternative strings
|
|
|
|
|
|
///
|
|
|
|
|
|
private string[] altStrings;
|
|
|
|
|
|
public string[] AltStrings
|
|
|
|
|
|
{
|
|
|
|
|
|
set { if (altStrings != value) { altStrings = value; Redraw(); } }
|
|
|
|
|
|
get { return altStrings; }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-06-03 07:31:06 +00:00
|
|
|
|
///
|
|
|
|
|
|
/// Setpoints
|
|
|
|
|
|
///
|
|
|
|
|
|
private double[] setpoints;
|
|
|
|
|
|
public double[] Setpoints
|
|
|
|
|
|
{
|
|
|
|
|
|
set { if (setpoints != value) { setpoints = value; Redraw(); } }
|
|
|
|
|
|
get { return setpoints; }
|
|
|
|
|
|
}
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
|
|
|
|
|
///
|
2020-06-03 07:31:06 +00:00
|
|
|
|
/// Pipes
|
2020-05-26 08:28:40 +00:00
|
|
|
|
///
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Pen[] pensDry;
|
|
|
|
|
|
Pen[] pensWater;
|
|
|
|
|
|
Pen[] pensVacuum;
|
2020-06-18 15:17:24 +00:00
|
|
|
|
Pen[] pensDryBackgr;
|
|
|
|
|
|
Pen[] pensWaterBackgr;
|
|
|
|
|
|
Pen[] pensVacuumBackgr;
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Pen[] pensHighlighted;
|
|
|
|
|
|
|
|
|
|
|
|
IList<Pipe> pipesS;
|
|
|
|
|
|
IList<Pipe> pipesM;
|
|
|
|
|
|
IList<Pipe> pipesL;
|
|
|
|
|
|
IList<Pipe> pipesXL;
|
2020-06-18 15:17:24 +00:00
|
|
|
|
IList<Pipe> allPipes;
|
2020-06-03 07:31:06 +00:00
|
|
|
|
///
|
|
|
|
|
|
public string[] PipesS
|
|
|
|
|
|
{
|
|
|
|
|
|
get {
|
|
|
|
|
|
string[] retv = new string[pipesS.Count];
|
|
|
|
|
|
for (int i = 0; i < pipesS.Count; i++) retv[i] = pipesS[i].ToString();
|
|
|
|
|
|
return retv;
|
|
|
|
|
|
}
|
|
|
|
|
|
set {
|
|
|
|
|
|
pipesS.Clear();
|
|
|
|
|
|
if (value != null)
|
|
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
foreach (var pStr in value)
|
2020-06-03 07:31:06 +00:00
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
pipesS.Add(new Pipe(pStr, Sz.S, Name2Item));
|
2020-06-03 07:31:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-06-18 15:17:24 +00:00
|
|
|
|
|
|
|
|
|
|
if (!supressRedraws)
|
|
|
|
|
|
{
|
|
|
|
|
|
JoinPipeListsEtc();
|
|
|
|
|
|
Redraw();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-06-03 07:31:06 +00:00
|
|
|
|
}
|
2020-06-18 15:17:24 +00:00
|
|
|
|
///
|
2020-06-03 07:31:06 +00:00
|
|
|
|
public string[] PipesM
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
string[] retv = new string[pipesM.Count];
|
|
|
|
|
|
for (int i = 0; i < pipesM.Count; i++) retv[i] = pipesM[i].ToString();
|
|
|
|
|
|
return retv;
|
|
|
|
|
|
}
|
2020-05-26 08:28:40 +00:00
|
|
|
|
set
|
|
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
pipesM.Clear();
|
|
|
|
|
|
if (value != null)
|
|
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
foreach (var pStr in value)
|
2020-06-03 07:31:06 +00:00
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
pipesM.Add(new Pipe(pStr, Sz.M, Name2Item));
|
2020-06-03 07:31:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-06-18 15:17:24 +00:00
|
|
|
|
|
|
|
|
|
|
if (!supressRedraws)
|
|
|
|
|
|
{
|
|
|
|
|
|
JoinPipeListsEtc();
|
|
|
|
|
|
Redraw();
|
|
|
|
|
|
}
|
2020-05-26 08:28:40 +00:00
|
|
|
|
}
|
2020-06-03 07:31:06 +00:00
|
|
|
|
}
|
2020-06-18 15:17:24 +00:00
|
|
|
|
///
|
2020-06-03 07:31:06 +00:00
|
|
|
|
public string[] PipesL
|
|
|
|
|
|
{
|
|
|
|
|
|
get {
|
|
|
|
|
|
string[] retv = new string[pipesL.Count];
|
|
|
|
|
|
for (int i = 0; i < pipesL.Count; i++) retv[i] = pipesL[i].ToString();
|
|
|
|
|
|
return retv;
|
|
|
|
|
|
}
|
|
|
|
|
|
set {
|
|
|
|
|
|
pipesL.Clear();
|
|
|
|
|
|
if (value != null)
|
|
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
foreach (var pStr in value)
|
2020-06-03 07:31:06 +00:00
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
pipesL.Add(new Pipe(pStr, Sz.L, Name2Item));
|
2020-06-03 07:31:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-06-18 15:17:24 +00:00
|
|
|
|
|
|
|
|
|
|
if (!supressRedraws)
|
|
|
|
|
|
{
|
|
|
|
|
|
JoinPipeListsEtc();
|
|
|
|
|
|
Redraw();
|
|
|
|
|
|
}
|
2020-05-26 08:28:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-06-18 15:17:24 +00:00
|
|
|
|
///
|
2020-06-03 07:31:06 +00:00
|
|
|
|
public string[] PipesXL
|
|
|
|
|
|
{
|
|
|
|
|
|
get {
|
|
|
|
|
|
string[] retv = new string[pipesXL.Count];
|
|
|
|
|
|
for (int i = 0; i < pipesXL.Count; i++) retv[i] = pipesXL[i].ToString();
|
|
|
|
|
|
return retv;
|
|
|
|
|
|
}
|
|
|
|
|
|
set {
|
|
|
|
|
|
pipesXL.Clear();
|
|
|
|
|
|
if (value != null)
|
|
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
foreach (var pStr in value)
|
2020-06-03 07:31:06 +00:00
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
pipesXL.Add(new Pipe(pStr, Sz.XL, Name2Item));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-06-03 07:31:06 +00:00
|
|
|
|
|
2020-06-18 15:17:24 +00:00
|
|
|
|
if (!supressRedraws)
|
|
|
|
|
|
{
|
|
|
|
|
|
JoinPipeListsEtc();
|
|
|
|
|
|
Redraw();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 1. Join 4 pipe lists.
|
|
|
|
|
|
/// 2. Add graph edges in case EditMode is off.
|
|
|
|
|
|
/// 3. Determine intersections of pipes in case EditMode is off.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
void JoinPipeListsEtc()
|
|
|
|
|
|
{
|
|
|
|
|
|
allPipes.Clear();
|
|
|
|
|
|
foreach (var p in pipesS) allPipes.Add(p);
|
|
|
|
|
|
foreach (var p in pipesM) allPipes.Add(p);
|
|
|
|
|
|
foreach (var p in pipesL) allPipes.Add(p);
|
|
|
|
|
|
foreach (var p in pipesXL) allPipes.Add(p);
|
|
|
|
|
|
|
|
|
|
|
|
if ((allPipes.Count > 0) && !EditMode && !graph.Completed)
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Do the following just once in non edit mode
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < allPipes.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Pipe p = allPipes[i];
|
|
|
|
|
|
if (p.StartItem != null && p.StartItem.GNodes.Count > p.StartNodeId &&
|
|
|
|
|
|
p.EndItem != null && p.EndItem.GNodes.Count > p.EndNodeId)
|
|
|
|
|
|
{
|
|
|
|
|
|
int dist = p.GetCoordinates() ? (int)Math.Round(Math.Sqrt((double)((p.x2 - p.x1) * (p.x2 - p.x1) + (p.y2 - p.y1) * (p.y2 - p.y1)))) : 1;
|
|
|
|
|
|
graph.AddEdge(p.StartItem.GNodes[p.StartNodeId], p.EndItem.GNodes[p.EndNodeId], dist);
|
|
|
|
|
|
graph.AddEdge(p.EndItem.GNodes[p.EndNodeId], p.StartItem.GNodes[p.StartNodeId], dist);
|
2020-06-03 07:31:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-06-18 15:17:24 +00:00
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < allPipes.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int j = i + 1; j < allPipes.Count; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (allPipes[i].CalculateIntersectionWith(allPipes[j])) break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
graph.Completed = true;
|
2020-06-03 07:31:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Support for adding new pipes
|
|
|
|
|
|
IDrawingItem startItem;
|
|
|
|
|
|
int startNodeId;
|
|
|
|
|
|
Pipe tempPipe;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Dictionary that speeds up drawing edges between nodes
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public Dictionary<string, IDrawingItem> Name2Item;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Components: Added by AddItem()
|
|
|
|
|
|
/// Cleared by ClearItems()
|
|
|
|
|
|
///
|
|
|
|
|
|
IList<IDrawingItem> items;
|
|
|
|
|
|
|
|
|
|
|
|
Graph graph;
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Rectangles of elements of drawn items
|
|
|
|
|
|
///
|
|
|
|
|
|
IList<ItemElementRect> ItemElementRectangles;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Pipes and water
|
|
|
|
|
|
///
|
|
|
|
|
|
Brush brushDry;
|
|
|
|
|
|
Brush brushWater;
|
|
|
|
|
|
Brush brushVacuum;
|
2020-06-18 15:17:24 +00:00
|
|
|
|
Brush brushDryBackgr;
|
|
|
|
|
|
Brush brushWaterBackgr;
|
|
|
|
|
|
Brush brushVacuumBackgr;
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Brush brushHihglighted;
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Labels and values
|
|
|
|
|
|
///
|
|
|
|
|
|
Font labelFont;
|
|
|
|
|
|
Brush labelBrush;
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Brush labelBackColor;
|
|
|
|
|
|
///
|
|
|
|
|
|
Font measuredValueFont;
|
|
|
|
|
|
Brush measuredValueBrush;
|
|
|
|
|
|
Brush measuredValueBackColor;
|
|
|
|
|
|
///
|
|
|
|
|
|
Font setpointFont;
|
|
|
|
|
|
Brush setpointBrush;
|
|
|
|
|
|
Brush setpointBackColor;
|
|
|
|
|
|
///
|
|
|
|
|
|
Pen thinBlackPen;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Pen selectedRectPen;
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public SchematicDrawingCtrl()
|
|
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
SupressRedraws = true;
|
2020-05-26 08:28:40 +00:00
|
|
|
|
InitializeComponent();
|
|
|
|
|
|
|
|
|
|
|
|
this.AutoScaleMode = AutoScaleMode.None;
|
|
|
|
|
|
this.DoubleBuffered = true;
|
|
|
|
|
|
|
2020-06-03 07:31:06 +00:00
|
|
|
|
items = new List<IDrawingItem>();
|
|
|
|
|
|
Name2Item = new Dictionary<string, IDrawingItem>();
|
|
|
|
|
|
SelectedItem = null;
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
2020-06-03 07:31:06 +00:00
|
|
|
|
route = 0x55AA; /// Invalid value to be overwritten in the first write to Route
|
|
|
|
|
|
pipesS = new List<Pipe>();
|
|
|
|
|
|
pipesM = new List<Pipe>();
|
|
|
|
|
|
pipesL = new List<Pipe>();
|
|
|
|
|
|
pipesXL = new List<Pipe>();
|
2020-06-18 15:17:24 +00:00
|
|
|
|
allPipes = new List<Pipe>();
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
2020-06-03 07:31:06 +00:00
|
|
|
|
graph = new Graph();
|
|
|
|
|
|
|
|
|
|
|
|
ItemElementRectangles = new List<ItemElementRect>();
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
2020-06-03 07:31:06 +00:00
|
|
|
|
PrepareFontsPensBrushesEtc();
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
|
|
|
|
|
this.Paint += new System.Windows.Forms.PaintEventHandler(this.SchematicDrawingCtrl_Paint);
|
2020-06-03 07:31:06 +00:00
|
|
|
|
SupressRedraws = false;
|
2020-05-26 08:28:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-06-03 07:31:06 +00:00
|
|
|
|
public void AddItem(IDrawingItem item)
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
|
|
|
|
|
items.Add(item);
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Name2Item.Add(item.Name, item);
|
|
|
|
|
|
|
|
|
|
|
|
if (!EditMode)
|
|
|
|
|
|
{
|
|
|
|
|
|
DrawingShape dshape = DrawingShape.GetDrawingShape(item);
|
|
|
|
|
|
if (dshape != null && dshape.Nodes != null && dshape.Nodes.Length > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
item.GNodes.Clear();
|
|
|
|
|
|
for (int nid = 0; nid < dshape.Nodes.Length; nid++)
|
|
|
|
|
|
{
|
|
|
|
|
|
GNode gnode = new GNode(item, nid);
|
|
|
|
|
|
item.GNodes.Add(gnode);
|
2020-06-17 21:17:50 +00:00
|
|
|
|
graph.AddNode(gnode, dshape.Shape == Shape.Tank, dshape.Shape == Shape.Scale);
|
2020-06-03 07:31:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var edge in dshape.Edges)
|
|
|
|
|
|
{
|
|
|
|
|
|
GEdge gedge = graph.AddEdge(item.GNodes[edge.NodeId1], item.GNodes[edge.NodeId2], edge.DefaultDist, edge.RouteCouple);
|
|
|
|
|
|
if (item is IRouteBasedDrawingItem && edge.RouteCouple != RouteCouple.None)
|
|
|
|
|
|
{
|
|
|
|
|
|
(item as IRouteBasedDrawingItem).EdgesToSet.Add(gedge);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-05-26 08:28:40 +00:00
|
|
|
|
Redraw();
|
|
|
|
|
|
}
|
|
|
|
|
|
public void ClearItems()
|
|
|
|
|
|
{
|
|
|
|
|
|
items.Clear();
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Name2Item.Clear();
|
|
|
|
|
|
graph.Clear();
|
2020-05-26 08:28:40 +00:00
|
|
|
|
Redraw();
|
|
|
|
|
|
}
|
2020-06-03 07:31:06 +00:00
|
|
|
|
public IList<IDrawingItem> GetItems()
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
return items;
|
2020-05-26 08:28:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Support functions for adding new edges
|
|
|
|
|
|
///
|
2020-06-03 07:31:06 +00:00
|
|
|
|
public void ShowStartNode(IDrawingItem item, int nodeId)
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
startItem = item;
|
2020-05-26 08:28:40 +00:00
|
|
|
|
startNodeId = nodeId;
|
|
|
|
|
|
Redraw();
|
|
|
|
|
|
}
|
|
|
|
|
|
public void ClearStartNode()
|
|
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
startItem = null;
|
2020-05-26 08:28:40 +00:00
|
|
|
|
Redraw();
|
|
|
|
|
|
}
|
2020-06-03 07:31:06 +00:00
|
|
|
|
public IDrawingItem GetStartNode(out int nodeId)
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
nodeId = startNodeId;
|
|
|
|
|
|
return startItem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void ShowTempPipe(Pipe pipe)
|
|
|
|
|
|
{
|
|
|
|
|
|
tempPipe = pipe;
|
2020-05-26 08:28:40 +00:00
|
|
|
|
Redraw();
|
|
|
|
|
|
}
|
2020-06-03 07:31:06 +00:00
|
|
|
|
public void ClearTempPipe()
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
tempPipe = null;
|
2020-05-26 08:28:40 +00:00
|
|
|
|
Redraw();
|
|
|
|
|
|
}
|
2020-06-03 07:31:06 +00:00
|
|
|
|
public Pipe GetTempPipe()
|
|
|
|
|
|
{
|
|
|
|
|
|
return tempPipe;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrepareFontsPensBrushesEtc()
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Font for drawing labels
|
|
|
|
|
|
labelFont = new Font("Arial", 10, FontStyle.Regular);
|
|
|
|
|
|
labelBrush = Brushes.Black;
|
|
|
|
|
|
labelBackColor = new SolidBrush(Color.LightYellow);
|
|
|
|
|
|
|
|
|
|
|
|
/// Font for drawing measured values
|
|
|
|
|
|
measuredValueFont = new Font("Arial", 10, FontStyle.Regular);
|
|
|
|
|
|
measuredValueBrush = Brushes.Black;
|
|
|
|
|
|
measuredValueBackColor = new SolidBrush(Color.LightGreen);
|
|
|
|
|
|
|
|
|
|
|
|
/// Font for drawing setpoints
|
|
|
|
|
|
setpointFont = new Font("Arial", 10, FontStyle.Regular);
|
|
|
|
|
|
setpointBrush = Brushes.Black;
|
|
|
|
|
|
setpointBackColor = new SolidBrush(Color.LightSalmon);
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
2020-06-03 07:31:06 +00:00
|
|
|
|
/// Thin black pen for rounds of labels, measured values and setpoints
|
|
|
|
|
|
Brush blackBrush = new SolidBrush(Color.Black);
|
|
|
|
|
|
thinBlackPen = new Pen(blackBrush);
|
|
|
|
|
|
thinBlackPen.Width = 1;
|
|
|
|
|
|
thinBlackPen.LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
2020-06-03 07:31:06 +00:00
|
|
|
|
/// Pens for drawing edges/pipes
|
|
|
|
|
|
brushDry = new SolidBrush(Color.FromArgb(255, 127, 127, 127));
|
|
|
|
|
|
brushWater = new SolidBrush(Color.FromArgb(255, 0, 162, 232));
|
|
|
|
|
|
brushVacuum = new SolidBrush(Color.FromArgb(255, 64, 255, 64));
|
2020-06-18 15:17:24 +00:00
|
|
|
|
brushDryBackgr = new SolidBrush(Color.FromArgb(255, 80, 80, 80));
|
|
|
|
|
|
brushWaterBackgr = new SolidBrush(Color.FromArgb(255, 0, 108, 154));
|
|
|
|
|
|
brushVacuumBackgr = new SolidBrush(Color.FromArgb(255, 48, 196, 48));
|
2020-06-03 07:31:06 +00:00
|
|
|
|
brushHihglighted = new SolidBrush(Color.FromArgb(255, 255, 0, 0));
|
|
|
|
|
|
///
|
|
|
|
|
|
pensDry = new Pen[(int)Sz.XL + 1];
|
|
|
|
|
|
pensWater = new Pen[(int)Sz.XL + 1];
|
|
|
|
|
|
pensVacuum = new Pen[(int)Sz.XL + 1];
|
2020-06-18 15:17:24 +00:00
|
|
|
|
pensDryBackgr = new Pen[(int)Sz.XL + 1];
|
|
|
|
|
|
pensWaterBackgr = new Pen[(int)Sz.XL + 1];
|
|
|
|
|
|
pensVacuumBackgr = new Pen[(int)Sz.XL + 1];
|
2020-06-03 07:31:06 +00:00
|
|
|
|
pensHighlighted = new Pen[(int)Sz.XL + 1];
|
|
|
|
|
|
///
|
|
|
|
|
|
for (Sz sz = Sz.S; sz <= Sz.XL; sz++)
|
|
|
|
|
|
{
|
|
|
|
|
|
pensDry[(int)sz] = new Pen(brushDry);
|
|
|
|
|
|
pensWater[(int)sz] = new Pen(brushWater);
|
|
|
|
|
|
pensVacuum[(int)sz] = new Pen(brushVacuum);
|
2020-06-18 15:17:24 +00:00
|
|
|
|
pensDryBackgr[(int)sz] = new Pen(brushDryBackgr);
|
|
|
|
|
|
pensWaterBackgr[(int)sz] = new Pen(brushWaterBackgr);
|
|
|
|
|
|
pensVacuumBackgr[(int)sz] = new Pen(brushVacuumBackgr);
|
2020-06-03 07:31:06 +00:00
|
|
|
|
pensHighlighted[(int)sz] = new Pen(brushHihglighted);
|
|
|
|
|
|
float width;
|
|
|
|
|
|
switch (sz)
|
|
|
|
|
|
{
|
|
|
|
|
|
default:
|
|
|
|
|
|
case Sz.S: width = 8.0f; break;
|
|
|
|
|
|
case Sz.M: width = 10.0f; break;
|
|
|
|
|
|
case Sz.L: width = 14.0f; break;
|
|
|
|
|
|
case Sz.XL: width = 20.0f; break;
|
|
|
|
|
|
}
|
|
|
|
|
|
pensDry[(int)sz].Width = width;
|
|
|
|
|
|
pensDry[(int)sz].LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;
|
|
|
|
|
|
pensWater[(int)sz].Width = width;
|
|
|
|
|
|
pensWater[(int)sz].LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;
|
|
|
|
|
|
pensVacuum[(int)sz].Width = width;
|
|
|
|
|
|
pensVacuum[(int)sz].LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;
|
2020-06-18 15:17:24 +00:00
|
|
|
|
pensDryBackgr[(int)sz].Width = width;
|
|
|
|
|
|
pensDryBackgr[(int)sz].LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;
|
|
|
|
|
|
pensWaterBackgr[(int)sz].Width = width;
|
|
|
|
|
|
pensWaterBackgr[(int)sz].LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;
|
|
|
|
|
|
pensVacuumBackgr[(int)sz].Width = width;
|
|
|
|
|
|
pensVacuumBackgr[(int)sz].LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;
|
2020-06-03 07:31:06 +00:00
|
|
|
|
pensHighlighted[(int)sz].Width = width;
|
|
|
|
|
|
pensHighlighted[(int)sz].LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Pen for displaying selections (rectangle around a body, a label, a measured value or a setpoint)
|
|
|
|
|
|
Brush redBrush = new SolidBrush(Color.Red);
|
|
|
|
|
|
selectedRectPen = new Pen(redBrush);
|
|
|
|
|
|
selectedRectPen.Width = 3;
|
|
|
|
|
|
selectedRectPen.LineJoin = System.Drawing.Drawing2D.LineJoin.Bevel;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Redraw()
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
if (!supressRedraws)
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Invalidate();
|
2020-05-26 08:28:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-06-03 07:31:06 +00:00
|
|
|
|
|
2020-05-26 08:28:40 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Draw a complete hydraulical scheme
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="e">PaintEventArgs</param>
|
|
|
|
|
|
void SchematicDrawingCtrl_Paint(object sender, PaintEventArgs e)
|
|
|
|
|
|
{
|
2020-06-17 21:17:50 +00:00
|
|
|
|
/// Profiling
|
2020-06-18 15:17:24 +00:00
|
|
|
|
stopwatch.Reset();
|
|
|
|
|
|
stopwatch.Start();
|
2020-06-17 21:17:50 +00:00
|
|
|
|
|
2020-05-26 08:28:40 +00:00
|
|
|
|
e.Graphics.Clear(Color.White);
|
2020-06-03 07:31:06 +00:00
|
|
|
|
|
|
|
|
|
|
ItemElementRectangles.Clear();
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
|
|
|
|
|
if (items == null) return;
|
|
|
|
|
|
|
2020-06-03 07:31:06 +00:00
|
|
|
|
///
|
|
|
|
|
|
/// Draw pictures of junctions
|
|
|
|
|
|
///
|
|
|
|
|
|
foreach (var item in items)
|
|
|
|
|
|
{
|
|
|
|
|
|
DrawingShape dshape = DrawingShape.GetDrawingShape(item);
|
|
|
|
|
|
if (dshape != null && dshape.Shape == Shape.Junction && dshape.HasImg && (!Utils.IsHidden(item) || EditMode))
|
|
|
|
|
|
{
|
|
|
|
|
|
Rectangle rect = DrawItem(e, item, dshape);
|
|
|
|
|
|
ItemElementRectangles.Add(new ItemElementRect(item, Element.Body, rect));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-05-26 08:28:40 +00:00
|
|
|
|
///
|
|
|
|
|
|
/// Draw edges
|
|
|
|
|
|
///
|
2020-06-03 07:31:06 +00:00
|
|
|
|
if (EditMode)
|
|
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
/// Draw an empty pipe. Coordinates are always recalculated
|
|
|
|
|
|
for (int j = 0; j < allPipes.Count; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Pipe pipe = allPipes[j];
|
|
|
|
|
|
pipe.CoordinatesAreValid = false;
|
|
|
|
|
|
DrawPipe(e, pipe, int.MaxValue);
|
|
|
|
|
|
}
|
2020-06-03 07:31:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Draw pipes with a color determined by Dijkstra shortest path algorithm
|
2020-06-18 15:17:24 +00:00
|
|
|
|
for (int j = 0; j < allPipes.Count; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Pipe pipe = allPipes[j];
|
|
|
|
|
|
DrawPipe(e, pipe, pipe.StartItem.GNodes[pipe.StartNodeId].Dist);
|
|
|
|
|
|
}
|
2020-06-03 07:31:06 +00:00
|
|
|
|
}
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
|
|
|
|
|
///
|
2020-06-03 07:31:06 +00:00
|
|
|
|
/// Draw pictures of all items except of junctions
|
2020-05-26 08:28:40 +00:00
|
|
|
|
///
|
|
|
|
|
|
foreach (var item in items)
|
|
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
DrawingShape dshape = DrawingShape.GetDrawingShape(item);
|
2020-06-18 15:17:24 +00:00
|
|
|
|
if (dshape != null && dshape.Shape != Shape.Junction && dshape.HasImg && (!Utils.IsHidden(item) || (EditMode && item == selectedItem)))
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Rectangle rect = DrawItem(e, item, dshape);
|
|
|
|
|
|
ItemElementRectangles.Add(new ItemElementRect(item, Element.Body, rect));
|
2020-05-26 08:28:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Draw nodes and a temporary edge (edit mode only)
|
|
|
|
|
|
///
|
|
|
|
|
|
if (EditMode)
|
|
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
if (tempPipe != null)
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
DrawPipe(e, tempPipe, 0, true); /// TODO
|
2020-05-26 08:28:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item in items)
|
|
|
|
|
|
{
|
|
|
|
|
|
DrawingShape dshape;
|
2020-06-03 07:31:06 +00:00
|
|
|
|
if (item != null && !Utils.IsHidden(item) && (null != (dshape = DrawingShape.GetDrawingShape(item))))
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Draw nodes and node ID-s
|
|
|
|
|
|
///
|
|
|
|
|
|
for (int nid = 0; nid < dshape.Nodes.Length; nid++)
|
|
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
bool isStartNode = (item == startItem) && (nid == startNodeId);
|
2020-05-26 08:28:40 +00:00
|
|
|
|
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Node rfNode = dshape.GetRotatedFlippedNode(item, nid);
|
2020-05-26 08:28:40 +00:00
|
|
|
|
Point dir = Utils.GetVect(rfNode.Orient);
|
|
|
|
|
|
Point norm = Utils.GetNormalVect(rfNode.Orient);
|
|
|
|
|
|
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Point[] triangle = new Point[] { new Point(item.X + SchematicDrawing.Const.GridSize * rfNode.X + dir.X,
|
|
|
|
|
|
item.Y + SchematicDrawing.Const.GridSize * rfNode.Y + dir.Y),
|
|
|
|
|
|
new Point(item.X + SchematicDrawing.Const.GridSize * rfNode.X + 7 * dir.X + 4 * norm.X,
|
|
|
|
|
|
item.Y + SchematicDrawing.Const.GridSize * rfNode.Y + 7 * dir.Y + 4 * norm.Y),
|
|
|
|
|
|
new Point(item.X + SchematicDrawing.Const.GridSize * rfNode.X + 7 * dir.X - 4 * norm.X,
|
|
|
|
|
|
item.Y + SchematicDrawing.Const.GridSize * rfNode.Y + 7 * dir.Y - 4 * norm.Y) };
|
|
|
|
|
|
e.Graphics.DrawPolygon(isStartNode ? Pens.Red : Pens.LawnGreen, triangle);
|
|
|
|
|
|
e.Graphics.FillPolygon(isStartNode ? Brushes.Red : Brushes.LawnGreen, triangle);
|
|
|
|
|
|
e.Graphics.DrawString(nid.ToString(), labelFont, isStartNode ? Brushes.Red : Brushes.LawnGreen,
|
|
|
|
|
|
item.X + SchematicDrawing.Const.GridSize * rfNode.X + 14 * dir.X - 5,
|
|
|
|
|
|
item.Y + SchematicDrawing.Const.GridSize * rfNode.Y + 14 * dir.Y - 7);
|
2020-05-26 08:28:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Draw labels, Various.Drawing... component labels are drawn in edit mode only
|
|
|
|
|
|
///
|
|
|
|
|
|
foreach (var item in items)
|
|
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
if ((!Utils.IsHidden(item) || (EditMode && (item == selectedItem))) && /// 1. Do not show hidden items, only if they are selected
|
|
|
|
|
|
(!item.ClassName.StartsWith("Various.Drawing.") || EditMode) && /// 2. Do not show Various.Drawing... items, only in EditMode
|
|
|
|
|
|
!item.ClassName.Equals("Various.Drawing.Edges")) /// 3. Never show Various.Drawing.Edges components
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
string strVal = item.Name;
|
|
|
|
|
|
SizeF size = e.Graphics.MeasureString(strVal, labelFont);
|
|
|
|
|
|
Rectangle rect = new Rectangle(item.X + item.LblX, item.Y + item.LblY, (int)Math.Round(size.Width) + 4, (int)Math.Round(size.Height) + 2);
|
|
|
|
|
|
ItemElementRectangles.Add(new ItemElementRect(item, Element.Label, rect));
|
|
|
|
|
|
e.Graphics.FillRectangle(labelBackColor, rect);
|
|
|
|
|
|
e.Graphics.DrawRectangle(thinBlackPen, rect);
|
|
|
|
|
|
e.Graphics.DrawString(strVal, labelFont, labelBrush, rect.X + 2, rect.Y + 2);
|
|
|
|
|
|
|
|
|
|
|
|
if (EditMode && (item == selectedItem) && (selectedElement == Element.Label))
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Draw red rectangle around the selected item label
|
|
|
|
|
|
e.Graphics.DrawRectangle(selectedRectPen, rect.X - 1, rect.Y - 1, rect.Width + 2, rect.Height + 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Draw measured values
|
|
|
|
|
|
///
|
|
|
|
|
|
if (measuredValues != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
int msrdValIx = 0;
|
|
|
|
|
|
foreach (var item in items)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (msrdValIx >= measuredValues.Length) break;
|
|
|
|
|
|
if (item is IDrawingItemWithMeasuredVal)
|
|
|
|
|
|
{
|
|
|
|
|
|
IDrawingItemWithMeasuredVal itm = item as IDrawingItemWithMeasuredVal;
|
2021-03-05 11:36:25 +00:00
|
|
|
|
bool msrmntAvailable = msrmntAvailableFlags[msrdValIx];
|
2021-02-25 12:38:24 +00:00
|
|
|
|
double msrdVal = Config.Units.ConvertTo(itm.MsrdUnit, measuredValues[msrdValIx]);
|
|
|
|
|
|
string altString = altStrings[msrdValIx];
|
|
|
|
|
|
msrdValIx++;
|
|
|
|
|
|
|
2021-03-05 11:36:25 +00:00
|
|
|
|
if ((msrmntAvailable || EditMode) && !Utils.IsHidden(item))
|
2020-06-03 07:31:06 +00:00
|
|
|
|
{
|
2021-02-25 12:38:24 +00:00
|
|
|
|
string strVal = string.IsNullOrEmpty(itm.MsrdFormat) ? altString : string.Format(itm.MsrdFormat, msrdVal);
|
2020-06-03 07:31:06 +00:00
|
|
|
|
SizeF size = e.Graphics.MeasureString(strVal, measuredValueFont);
|
|
|
|
|
|
Rectangle rect = new Rectangle(itm.X + itm.MsrdX, itm.Y + itm.MsrdY, (int)Math.Round(size.Width) + 4, (int)Math.Round(size.Height) + 2);
|
|
|
|
|
|
ItemElementRectangles.Add(new ItemElementRect(item, Element.MeasuredVal, rect));
|
|
|
|
|
|
e.Graphics.FillRectangle(measuredValueBackColor, rect);
|
|
|
|
|
|
e.Graphics.DrawRectangle(thinBlackPen, rect);
|
|
|
|
|
|
e.Graphics.DrawString(strVal, measuredValueFont, measuredValueBrush, rect.X + 2, rect.Y + 2);
|
|
|
|
|
|
|
|
|
|
|
|
if (EditMode && (item == selectedItem) && (selectedElement == Element.MeasuredVal))
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Draw red rectangle around the selected item label
|
|
|
|
|
|
e.Graphics.DrawRectangle(selectedRectPen, rect.X - 1, rect.Y - 1, rect.Width + 2, rect.Height + 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Paint water in the tank on a scale
|
|
|
|
|
|
DrawingShape dshape = DrawingShape.GetDrawingShape(item.Shape, item.Sz);
|
|
|
|
|
|
if (dshape.Shape == Shape.Scale)
|
|
|
|
|
|
{
|
|
|
|
|
|
Rectangle r = dshape.GetRotatedFlippedImageRectangle(item);
|
|
|
|
|
|
int level = (int)Math.Round((r.Height - 2) * msrdVal / itm.MsrdValLimHi);
|
|
|
|
|
|
e.Graphics.FillRectangle(brushWater, r.X + 2, r.Y + r.Height - 2 - level, r.Width - 4, level);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Draw setpoints
|
|
|
|
|
|
///
|
|
|
|
|
|
if (setpoints != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
int setpointIx = 0;
|
|
|
|
|
|
foreach (var item in items)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (setpointIx >= setpoints.Length) break;
|
|
|
|
|
|
if (item is IDrawingItemWithSetpoint)
|
|
|
|
|
|
{
|
|
|
|
|
|
IDrawingItemWithSetpoint its = item as IDrawingItemWithSetpoint;
|
2021-02-25 12:38:24 +00:00
|
|
|
|
double setpoint = Config.Units.ConvertTo(its.SetpUnit, setpoints[setpointIx++]);
|
2020-06-03 07:31:06 +00:00
|
|
|
|
if (!Utils.IsHidden(item))
|
|
|
|
|
|
{
|
|
|
|
|
|
string strVal = string.IsNullOrEmpty(its.SetpFormat) ? setpoint.ToString() : string.Format(its.SetpFormat, setpoint);
|
2021-02-25 12:38:24 +00:00
|
|
|
|
SizeF size = (its.SetpUnit != Config.Unit.Pct) ? e.Graphics.MeasureString(strVal, setpointFont)
|
2020-06-03 07:31:06 +00:00
|
|
|
|
: e.Graphics.MeasureString(string.Format(its.SetpFormat, 100.0), setpointFont);
|
|
|
|
|
|
Rectangle rect = new Rectangle(its.X + its.SetpX, its.Y + its.SetpY, (int)Math.Round(size.Width) + 4, (int)Math.Round(size.Height) + 2);
|
|
|
|
|
|
ItemElementRectangles.Add(new ItemElementRect(item, Element.Setpoint, rect));
|
|
|
|
|
|
int barLen = (int)Math.Round(rect.Width * setpoint / 100.0);
|
|
|
|
|
|
e.Graphics.FillRectangle(setpointBackColor, rect.X, rect.Y, barLen, rect.Height);
|
|
|
|
|
|
e.Graphics.DrawRectangle(thinBlackPen, rect);
|
|
|
|
|
|
e.Graphics.DrawString(strVal, setpointFont, setpointBrush, rect.X + 2, rect.Y + 2);
|
|
|
|
|
|
|
|
|
|
|
|
if (EditMode && (item == selectedItem) && (selectedElement == Element.Setpoint))
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Draw red rectangle around the selected item label
|
|
|
|
|
|
e.Graphics.DrawRectangle(selectedRectPen, rect.X - 1, rect.Y - 1, rect.Width + 2, rect.Height + 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-05-26 08:28:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-06-17 21:17:50 +00:00
|
|
|
|
|
|
|
|
|
|
/// Profiling
|
2020-06-18 15:17:24 +00:00
|
|
|
|
stopwatch.Stop();
|
|
|
|
|
|
if (firstTime)
|
|
|
|
|
|
{
|
|
|
|
|
|
firstTime = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (totalTimes < long.MaxValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
totalMs += stopwatch.ElapsedMilliseconds;
|
|
|
|
|
|
totalTicks += stopwatch.ElapsedTicks;
|
|
|
|
|
|
totalTimes++;
|
|
|
|
|
|
Console.WriteLine("Average Paint duration is {0} ms = {1} ticks", totalMs / totalTimes, totalTicks / totalTimes);
|
|
|
|
|
|
}
|
2020-05-26 08:28:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-06-17 21:17:50 +00:00
|
|
|
|
/// Profiling
|
2020-06-18 15:17:24 +00:00
|
|
|
|
Stopwatch stopwatch = new Stopwatch();
|
|
|
|
|
|
bool firstTime = true;
|
|
|
|
|
|
long totalMs = 0;
|
|
|
|
|
|
long totalTicks = 0;
|
|
|
|
|
|
long totalTimes = 0;
|
2020-06-17 21:17:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
2020-05-26 08:28:40 +00:00
|
|
|
|
/// <summary>
|
2020-06-17 21:17:50 +00:00
|
|
|
|
/// Draw a pipe.
|
2020-05-26 08:28:40 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="e">PaintEventArgs</param>
|
2020-06-18 15:17:24 +00:00
|
|
|
|
/// <param name="p">Pipe object</param>
|
2020-06-17 21:17:50 +00:00
|
|
|
|
/// <param name="distance">Distance from source of water for coloring</param>
|
|
|
|
|
|
/// <param name="highlighted">true = highlighted (edit mode)</param>
|
2020-06-18 15:17:24 +00:00
|
|
|
|
void DrawPipe(PaintEventArgs e, Pipe p, int distance, bool highlighted = false)
|
2020-06-03 07:31:06 +00:00
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
if (!p.CoordinatesAreValid) p.GetCoordinates();
|
|
|
|
|
|
|
2021-03-02 06:55:19 +00:00
|
|
|
|
int eIx = Math.Max((int)Sz.S, Math.Min((int)Sz.XL, (int)p.Sz)); /// eIx is (int)p.Sz, but between Sz.S .. Sz.XL (1 .. 4)
|
2020-06-18 15:17:24 +00:00
|
|
|
|
Pen pen = (distance == int.MaxValue) ? pensDry[eIx] : (distance < Const.Vacuum) ? pensWater[eIx] : pensVacuum[eIx];
|
|
|
|
|
|
|
|
|
|
|
|
if (highlighted)
|
|
|
|
|
|
{
|
|
|
|
|
|
e.Graphics.DrawLine(pensHighlighted[eIx], p.x1, p.y1, p.x2, p.y2);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (!p.HasIntersection)
|
2020-06-03 07:31:06 +00:00
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
e.Graphics.DrawLine(pen, p.x1, p.y1, p.x2, p.y2);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Pen pen2 = (distance == int.MaxValue) ? pensDryBackgr[eIx] : (distance < Const.Vacuum) ? pensWaterBackgr[eIx] : pensVacuumBackgr[eIx];
|
|
|
|
|
|
|
|
|
|
|
|
float len = (float)Math.Sqrt(Convert.ToSingle((p.x2 - p.x1) * (p.x2 - p.x1) + (p.y2 - p.y1) * (p.y2 - p.y1)));
|
|
|
|
|
|
float PP = 1.0f - p.P;
|
|
|
|
|
|
if (p.P * len < 20 && PP * len < 20)
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Draw a straght line with darker color
|
|
|
|
|
|
e.Graphics.DrawLine(pen2, p.x1, p.y1, p.x2, p.y2);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Draw a line having normal color with a bow having darker color
|
|
|
|
|
|
|
|
|
|
|
|
float vx = 17.0f * (p.x2 - p.x1) / len; /// Fixed size vector in the direction of the line
|
|
|
|
|
|
float vy = 17.0f * (p.y2 - p.y1) / len;
|
|
|
|
|
|
|
|
|
|
|
|
float xm = p.x1 * PP + p.x2 * p.P; /// Intersection point
|
|
|
|
|
|
float ym = p.y1 * PP + p.y2 * p.P;
|
|
|
|
|
|
int x3 = Convert.ToInt32(Math.Round(xm - vx)); /// Points around the intersection point
|
|
|
|
|
|
int y3 = Convert.ToInt32(Math.Round(ym - vy));
|
|
|
|
|
|
int x4 = Convert.ToInt32(Math.Round(xm - 2 * vy / 3));
|
|
|
|
|
|
int y4 = Convert.ToInt32(Math.Round(ym + 2 * vx / 3));
|
|
|
|
|
|
int x5 = Convert.ToInt32(Math.Round(xm + vx));
|
|
|
|
|
|
int y5 = Convert.ToInt32(Math.Round(ym + vy));
|
|
|
|
|
|
|
|
|
|
|
|
/// Joints between straight parts of the line and the bow
|
|
|
|
|
|
DrawingShape dsh = DrawingShape.GetDrawingShape(Shape.Junction, p.Sz);
|
|
|
|
|
|
Image image = (distance == int.MaxValue) ? dsh.ImgRightOpenDry : (distance < Const.Vacuum) ? dsh.ImgRight : dsh.ImgRightVacuum;
|
|
|
|
|
|
e.Graphics.DrawImage(image, x3 - dsh.Wid / 2, y3 - dsh.Hgh / 2);
|
|
|
|
|
|
e.Graphics.DrawImage(image, x5 - dsh.Wid / 2, y5 - dsh.Hgh / 2);
|
|
|
|
|
|
|
|
|
|
|
|
e.Graphics.DrawLine(pen2, x3, y3, x4, y4); /// Bow
|
|
|
|
|
|
e.Graphics.DrawLine(pen2, x4, y4, x5, y5);
|
|
|
|
|
|
|
|
|
|
|
|
e.Graphics.DrawLine(pen, p.x1, p.y1, x3, y3); /// Straight parts of the line
|
|
|
|
|
|
e.Graphics.DrawLine(pen, x5, y5, p.x2, p.y2);
|
|
|
|
|
|
}
|
2020-06-03 07:31:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-06-17 21:17:50 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Draw an item (body).
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="e">PaintEventArgs</param>
|
|
|
|
|
|
/// <param name="item">IDrawingItem object</param>
|
|
|
|
|
|
/// <param name="dsh">DrawingShape</param>
|
|
|
|
|
|
/// <returns>Rectangle where item body is drawn</returns>
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Rectangle DrawItem(PaintEventArgs e, IDrawingItem item, DrawingShape dsh)
|
|
|
|
|
|
{
|
|
|
|
|
|
bool routeBit = false;
|
|
|
|
|
|
if (item is IRouteBasedDrawingItem)
|
|
|
|
|
|
{
|
|
|
|
|
|
UInt128 mask = ((UInt128)1) << (item as IRouteBasedDrawingItem).BitNr;
|
|
|
|
|
|
routeBit = (item as IRouteBasedDrawingItem).Inverted ? ((route & mask) == 0) : ((route & mask) != 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Draw the component image
|
|
|
|
|
|
Rectangle rect = dsh.GetRotatedFlippedImageRectangle(item);
|
|
|
|
|
|
|
|
|
|
|
|
if (dsh.HasClosed && item is IRouteBasedDrawingItem && routeBit == false)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (item.Flip)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (item.Orient)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Orient.R: e.Graphics.DrawImage(dsh.ImgRightFlippedClosed, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Up: e.Graphics.DrawImage(dsh.ImgUpFlippedClosed, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.L: e.Graphics.DrawImage(dsh.ImgLeftFlippedClosed, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Dn: e.Graphics.DrawImage(dsh.ImgDownFlippedClosed, rect.X, rect.Y); break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (item.Orient)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Orient.R: e.Graphics.DrawImage(dsh.ImgRightClosed, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Up: e.Graphics.DrawImage(dsh.ImgUpClosed, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.L: e.Graphics.DrawImage(dsh.ImgLeftClosed, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Dn: e.Graphics.DrawImage(dsh.ImgDownClosed, rect.X, rect.Y); break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (dsh.HasOpenDry && item.GNodes.Count > 0 && item.GNodes[0].Dist == int.MaxValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (item.Flip)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (item.Orient)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Orient.R: e.Graphics.DrawImage(dsh.ImgRightFlippedOpenDry, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Up: e.Graphics.DrawImage(dsh.ImgUpFlippedOpenDry, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.L: e.Graphics.DrawImage(dsh.ImgLeftFlippedOpenDry, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Dn: e.Graphics.DrawImage(dsh.ImgDownFlippedOpenDry, rect.X, rect.Y); break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (item.Orient)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Orient.R: e.Graphics.DrawImage(dsh.ImgRightOpenDry, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Up: e.Graphics.DrawImage(dsh.ImgUpOpenDry, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.L: e.Graphics.DrawImage(dsh.ImgLeftOpenDry, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Dn: e.Graphics.DrawImage(dsh.ImgDownOpenDry, rect.X, rect.Y); break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (dsh.HasVacuum && item.GNodes.Count > 0 && item.GNodes[0].Dist > Const.Vacuum)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (item.Flip)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (item.Orient)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Orient.R: e.Graphics.DrawImage(dsh.ImgRightFlippedVacuum, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Up: e.Graphics.DrawImage(dsh.ImgUpFlippedVacuum, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.L: e.Graphics.DrawImage(dsh.ImgLeftFlippedVacuum, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Dn: e.Graphics.DrawImage(dsh.ImgDownFlippedVacuum, rect.X, rect.Y); break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (item.Orient)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Orient.R: e.Graphics.DrawImage(dsh.ImgRightVacuum, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Up: e.Graphics.DrawImage(dsh.ImgUpVacuum, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.L: e.Graphics.DrawImage(dsh.ImgLeftVacuum, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Dn: e.Graphics.DrawImage(dsh.ImgDownVacuum, rect.X, rect.Y); break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (dsh.HasImg)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (item.Flip)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (item.Orient)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Orient.R: e.Graphics.DrawImage(dsh.ImgRightFlipped, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Up: e.Graphics.DrawImage(dsh.ImgUpFlipped, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.L: e.Graphics.DrawImage(dsh.ImgLeftFlipped, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Dn: e.Graphics.DrawImage(dsh.ImgDownFlipped, rect.X, rect.Y); break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (item.Orient)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Orient.R: e.Graphics.DrawImage(dsh.ImgRight, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Up: e.Graphics.DrawImage(dsh.ImgUp, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.L: e.Graphics.DrawImage(dsh.ImgLeft, rect.X, rect.Y); break;
|
|
|
|
|
|
case Orient.Dn: e.Graphics.DrawImage(dsh.ImgDown, rect.X, rect.Y); break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (EditMode && (item == selectedItem) && (selectedElement == Element.Body))
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Draw red rectangle around the selected item body
|
|
|
|
|
|
e.Graphics.DrawRectangle(selectedRectPen, rect.X - 1, rect.Y - 1, rect.Width + 2, rect.Height + 2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return rect;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Searches for an elemend out of 'elements' in the displayed schematic drawing.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="x">X-coordinate</param>
|
|
|
|
|
|
/// <param name="y">Y-coordinate</param>
|
|
|
|
|
|
/// <param name="elements">Bitfield of elements to be searched for</param>
|
2020-06-17 21:17:50 +00:00
|
|
|
|
/// <param name="item">Found item or null (in case of body, node, label, measured value or setpoint)</param>
|
|
|
|
|
|
/// <param name="pipe">Found pipe or null (in case of a pipe)</param>
|
|
|
|
|
|
/// <param name="nodeId">Found node id or 0 (in case of an item node)</param>
|
|
|
|
|
|
/// <returns>Element enum value (Element.None when nothing was found)</returns>
|
2020-06-03 07:31:06 +00:00
|
|
|
|
public Element FindElement(int x, int y, Element elements, out IDrawingItem item, out Pipe pipe, out int nodeId)
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
const int NodeTolerance = 5;
|
|
|
|
|
|
const int EdgeTolerance = 2;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (Element element in new Element[] { Element.Setpoint, Element.MeasuredVal, Element.Label, Element.Body })
|
|
|
|
|
|
{
|
|
|
|
|
|
if (((elements & element) != 0) && (null != (item = FindBodyLabelMeasuredValOrSetpoint(x, y, element))))
|
|
|
|
|
|
{
|
|
|
|
|
|
pipe = null;
|
|
|
|
|
|
nodeId = 0;
|
|
|
|
|
|
return element;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (((elements & Element.Node) != 0) && FindNode(x, y, NodeTolerance, out item, out nodeId))
|
|
|
|
|
|
{
|
|
|
|
|
|
pipe = null;
|
|
|
|
|
|
return Element.Node;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (((elements & Element.Pipe) != 0) && (null != (pipe = FindPipe(x, y, EdgeTolerance))))
|
|
|
|
|
|
{
|
|
|
|
|
|
item = null;
|
|
|
|
|
|
nodeId = 0;
|
|
|
|
|
|
return Element.Pipe;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
item = null;
|
|
|
|
|
|
pipe = null;
|
|
|
|
|
|
nodeId = 0;
|
|
|
|
|
|
return Element.None;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2020-06-17 21:17:50 +00:00
|
|
|
|
/// Searches for an item body, label, measured value or setpoint.
|
2020-06-03 07:31:06 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="x">X coordinate</param>
|
|
|
|
|
|
/// <param name="y">Y coordinate</param>
|
|
|
|
|
|
/// <param name="elementSpec">Element to find</param>
|
|
|
|
|
|
/// <returns>Found item</returns>
|
|
|
|
|
|
IDrawingItem FindBodyLabelMeasuredValOrSetpoint(int x, int y, Element elementSpec)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = ItemElementRectangles.Count - 1; i >= 0; i--)
|
|
|
|
|
|
{
|
|
|
|
|
|
var itElmRect = ItemElementRectangles[i];
|
|
|
|
|
|
if (itElmRect.Element == elementSpec && itElmRect.Rect.Contains(x, y))
|
|
|
|
|
|
{
|
|
|
|
|
|
return itElmRect.Item;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool FindNode(int x, int y, int tolerance, out IDrawingItem foundItem, out int nid)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var item in items)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Utils.IsHidden(item)) continue;
|
|
|
|
|
|
|
|
|
|
|
|
DrawingShape dshape = DrawingShape.GetDrawingShape(item);
|
|
|
|
|
|
if (dshape != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 0; i < dshape.Nodes.Length; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Node nd = dshape.GetRotatedFlippedNode(item, i);
|
|
|
|
|
|
int dx = Math.Abs(item.X + Const.GridSize * nd.X - x);
|
|
|
|
|
|
int dy = Math.Abs(item.Y + Const.GridSize * nd.Y - y);
|
|
|
|
|
|
if ((dx <= tolerance) && (dy <= tolerance))
|
|
|
|
|
|
{
|
|
|
|
|
|
nid = i;
|
|
|
|
|
|
foundItem = item;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nid = 0;
|
|
|
|
|
|
foundItem = null;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Pipe FindPipe(int x, int y, int tolerance)
|
|
|
|
|
|
{
|
|
|
|
|
|
/// Search between pipes
|
|
|
|
|
|
float maxDistSquared = (tolerance + 4.0f) * (tolerance + 4.0f);
|
|
|
|
|
|
if (pipesS != null) { foreach (var pipe in pipesS) if (SquaredDistanceFromLine(x, y, pipe) < maxDistSquared) return pipe; }
|
|
|
|
|
|
maxDistSquared = (tolerance + 5.0f) * (tolerance + 5.0f);
|
|
|
|
|
|
if (pipesM != null) { foreach (var pipe in pipesM) if (SquaredDistanceFromLine(x, y, pipe) < maxDistSquared) return pipe; }
|
|
|
|
|
|
maxDistSquared = (tolerance + 7.0f) * (tolerance + 7.0f);
|
|
|
|
|
|
if (pipesL != null) { foreach (var pipe in pipesL) if (SquaredDistanceFromLine(x, y, pipe) < maxDistSquared) return pipe; }
|
|
|
|
|
|
maxDistSquared = (tolerance + 10.0f) * (tolerance + 10.0f);
|
|
|
|
|
|
if (pipesXL != null) { foreach (var pipe in pipesXL) if (SquaredDistanceFromLine(x, y, pipe) < maxDistSquared) return pipe; }
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Calculates a squared distance of a point [x,y] from a line.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="x">Point X</param>
|
|
|
|
|
|
/// <param name="y">Point Y</param>
|
|
|
|
|
|
/// <param name="pipe">Pipe</param>
|
|
|
|
|
|
/// <returns>Squared distance</returns>
|
|
|
|
|
|
float SquaredDistanceFromLine(int x, int y, Pipe pipe)
|
|
|
|
|
|
{
|
2020-06-18 15:17:24 +00:00
|
|
|
|
if (!pipe.GetCoordinates() || (pipe.x1 == pipe.x2 && pipe.y1 == pipe.y2))
|
2020-06-03 07:31:06 +00:00
|
|
|
|
{
|
|
|
|
|
|
return float.MaxValue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Vector2 X = new Vector2(Convert.ToSingle(x), Convert.ToSingle(y));
|
2020-06-18 15:17:24 +00:00
|
|
|
|
Vector2 X1 = new Vector2(Convert.ToSingle(pipe.x1), Convert.ToSingle(pipe.y1));
|
|
|
|
|
|
Vector2 X2 = new Vector2(Convert.ToSingle(pipe.x2), Convert.ToSingle(pipe.y2));
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Vector2 vX = X - X1; /// |X1 X|
|
|
|
|
|
|
Vector2 v12 = X2 - X1; /// |X1 X2|
|
|
|
|
|
|
|
|
|
|
|
|
float projFactor = Vector2.Dot(vX, v12) / Vector2.Dot(v12, v12);
|
|
|
|
|
|
|
|
|
|
|
|
if (projFactor < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return (X - X1).LengthSquared();
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (projFactor > 1.0f)
|
|
|
|
|
|
{
|
|
|
|
|
|
return (X - X2).LengthSquared();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
2020-05-26 08:28:40 +00:00
|
|
|
|
{
|
2020-06-03 07:31:06 +00:00
|
|
|
|
Vector2 projX = projFactor * v12 + X1;
|
|
|
|
|
|
return (X - projX).LengthSquared();
|
2020-05-26 08:28:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|