Skip to content

Commit ad71cc7

Browse files
committed
Implemented Proection to get a deviation value after transform
Changes in Plot procedure, so calling Plot multiple times should not create duplicate plottables.
1 parent 9d58ebc commit ad71cc7

File tree

3 files changed

+165
-22
lines changed

3 files changed

+165
-22
lines changed

TRA.Lib/Trasse.cs

Lines changed: 116 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
using System.Globalization;
55
using System.Numerics;
66
using System.Runtime.CompilerServices;
7+
using System.Collections.Specialized;
8+
79
#if USE_SCOTTPLOT
10+
using ScottPlot.Plottables;
11+
using OpenTK.Platform.Windows;
812
using ScottPlot;
913
using SkiaSharp;
1014
#endif
@@ -188,18 +192,7 @@ public Interpolation Interpolate3D(TRATrasse stationierungsTrasse = null, double
188192
double s;
189193
if (trasseS != null) //If TrasseS is set, try projecting coordinate to trasseS, s = NaN if fails
190194
{
191-
TrassenElementExt stationierungsElement = trasseS.GetElementFromPoint(Interpolation.X[i], Interpolation.Y[i]);
192-
s = (stationierungsElement != null ? stationierungsElement.GetSAtPoint(Interpolation.X[i], Interpolation.Y[i]) : double.NaN);
193-
if (Double.IsNaN(s)) { Interpolation.H[i] = double.NaN; continue; }
194-
#if USE_SCOTTPLOT
195-
//Visualisation
196-
if (stationierungsElement != null)
197-
{
198-
double X_, Y_;
199-
(X_, Y_, _) = stationierungsElement.GetPointAtS(s);
200-
element.projections.Add(new ProjectionArrow(new Coordinates(Interpolation.Y[i], Interpolation.X[i]), new Coordinates(Y_, X_)));
201-
}
202-
#endif
195+
(s,_,_,_) = trasseS.ProjectPoints(Interpolation.X[i], Interpolation.Y[i], element.projections);
203196
}
204197
else //if no trasseS provided use original value S
205198
{
@@ -212,6 +205,50 @@ public Interpolation Interpolate3D(TRATrasse stationierungsTrasse = null, double
212205
}
213206
return interp;
214207
}
208+
/// <summary>
209+
/// Project an Array of X,Y coordinates on elements geoemtry
210+
/// </summary>
211+
/// <param name="X">array of X-coordinates</param>
212+
/// <param name="Y">array of Y-coordinates</param>
213+
/// <returns>mean deviation(distance) from point to geometry</returns>
214+
public float ProjectPoints(double[] X, double[] Y)
215+
{
216+
int num = Math.Min(X.Length, Y.Length);
217+
float deviation = 0;
218+
double dist = 0;
219+
for (int i =0;i<num; i++)
220+
{
221+
(_,dist,_,_) = ProjectPoints(X[i], Y[i]);
222+
deviation += (float)dist;
223+
}
224+
return deviation / num;
225+
}
226+
/// <summary>
227+
/// Projecting a Point on this trasse
228+
/// </summary>
229+
/// <param name="X">X-Coordinate</param>
230+
/// <param name="Y">Y-Coordinate</param>
231+
/// <returns>s(Milage),distance,X-Coordinate of the projection,Y-Coordinate of the projection</returns>
232+
internal (double,double,double,double) ProjectPoints(double X, double Y, List<ProjectionArrow> projections = null)
233+
{
234+
TrassenElementExt element = GetElementFromPoint(X, Y);
235+
double s = (element != null ? element.GetSAtPoint(X, Y) : double.NaN);
236+
double X_, Y_;
237+
if (element != null && !Double.IsNaN(s))
238+
{
239+
(X_, Y_, _) = element.GetPointAtS(s);
240+
#if USE_SCOTTPLOT
241+
if (projections == null)
242+
{
243+
projections = element.projections;
244+
}
245+
projections.Add(new ProjectionArrow(new Coordinates(Y, X), new Coordinates(Y_, X_)));
246+
#endif
247+
return (s,Math.Sqrt(Math.Pow(X - X_, 2) + Math.Pow(Y - Y_, 2)), X_, Y_);
248+
}
249+
return (double.NaN,double.NaN, double.NaN, double.NaN);
250+
251+
}
215252

216253
public void SaveCSV(StreamWriter outputFile)
217254
{
@@ -248,6 +285,8 @@ public void SaveCSV(StreamWriter outputFile)
248285
static Form Form;
249286
/// <value>Plot for a 2D overview of all plotted trassen</value>
250287
static ScottPlot.WinForms.FormsPlot Plot2D;
288+
/// <value>List of all Plottables of this element</value>
289+
List<IPlottable> Plottables = new();
251290
/// <value>Callout for right-click selected Coordinate and s-projection</value>
252291
static ScottPlot.Plottables.Callout selectedS;
253292
/// <value>Plot for TRA-Details heading and hurvature </value>
@@ -459,19 +498,30 @@ public void Plot()
459498
Plot2D.Plot.Axes.Link(PlotG, true, false);
460499
PlotG.Plot.Axes.Link(Plot2D, true, false);
461500

501+
gridView.Rows.Clear();
502+
//Remove previous Plottables from Plots
503+
foreach (IPlottable plottable in Plottables)
504+
{
505+
Plot2D.Plot.Remove(plottable);
506+
PlotT.Plot.Remove(plottable);
507+
PlotG.Plot.Remove(plottable);
508+
}
509+
462510
foreach (TrassenElementExt element in Elemente)
463511
{
464512
Interpolation interpolation = element.InterpolationResult;
465513
var scatter = Plot2D.Plot.Add.Scatter(interpolation.Y, interpolation.X);
514+
Plottables.Add(scatter);
466515
scatter.LegendText = Filename;
467516
ScottPlot.Color color = scatter.MarkerFillColor;
468517
ElementMarker marker = new(element, color);
469-
Plot2D.Plot.Add.Plottable(marker);
470-
518+
Plottables.Add(Plot2D.Plot.Add.Plottable(marker));
471519
var scatterT = PlotT.Plot.Add.Scatter(interpolation.Y, interpolation.T, color);
520+
Plottables.Add(scatterT);
472521
//scatterT.LegendText = "Heading";
473-
PlotT.Plot.Add.VerticalLine(element.Ystart, 2, color);
522+
Plottables.Add(PlotT.Plot.Add.VerticalLine(element.Ystart, 2, color));
474523
var scatterK = PlotT.Plot.Add.ScatterLine(interpolation.Y, interpolation.K, color);
524+
Plottables.Add(scatterK);
475525
//scatterK.LegendText = "Curvature";
476526
// tell each T and K plot to use a different axis
477527
scatterT.Axes.YAxis = PlotT.Plot.Axes.Left;
@@ -480,25 +530,28 @@ public void Plot()
480530
if (interpolation.H != null && interpolation.s != null)
481531
{
482532
var scatterH = PlotG.Plot.Add.Scatter(interpolation.Y, interpolation.H, color);
533+
Plottables.Add(scatterH);
483534
//scatterH.LegendText = "Elevation";
484535
scatterH.Axes.YAxis = PlotG.Plot.Axes.Left;
485536
var scatterSlope = PlotG.Plot.Add.ScatterLine(interpolation.Y, interpolation.s, color);
537+
Plottables.Add(scatterSlope);
486538
//scatterSlope.LegendText = "Slope";
487539
scatterSlope.Axes.YAxis = PlotG.Plot.Axes.Right;
488540
}
489541

490542
//Raw Data to GridView
491543
gridView.Rows.Add(element.ID, element.R1, element.R2, element.Ystart, element.Xstart, element.T, element.S, element.KzString, element.L, element.U1, element.U2, element.C);
492544
//Warnings
493-
foreach (var warning in element.GetWarnings)
545+
element.WarningCallouts.CollectionChanged += Warning_CollectionChanged;
546+
foreach (var warning in element.WarningCallouts)
494547
{
495548
Plot2D.Plot.Add.Plottable(warning);
496549
}
497550
//Visualize Projections
498551
foreach (ProjectionArrow projection in element.projections)
499552
{
500553
projection.IsVisible = false;
501-
Plot2D.Plot.Add.Plottable(projection);
554+
Plottables.Add(Plot2D.Plot.Add.Plottable(projection));
502555
}
503556
}
504557
if (GradientenElemente != null)
@@ -507,6 +560,7 @@ public void Plot()
507560
{
508561
if (element.Y == double.NaN) continue;
509562
var vline = PlotG.Plot.Add.VerticalLine(element.Y);
563+
Plottables.Add(vline);
510564
vline.Text = " NW " + element.Pkt.ToString() + " " + element.H.ToString() + "m";
511565
vline.LabelRotation = -90;
512566
vline.ManualLabelAlignment = Alignment.UpperLeft;
@@ -516,7 +570,7 @@ public void Plot()
516570
}
517571
else
518572
{
519-
PlotG.Plot.Add.Annotation("No Gradient Data available");
573+
Plottables.Add(PlotG.Plot.Add.Annotation("No Gradient Data available"));
520574
}
521575

522576
// Set the axis scale to be equal
@@ -527,6 +581,49 @@ public void Plot()
527581
Form.Update();
528582
}
529583

584+
public void UpdatePlot()
585+
{
586+
if (gridView != null)
587+
{
588+
gridView.Rows.Clear();
589+
foreach (TrassenElementExt element in Elemente)
590+
{
591+
gridView.Rows.Add(element.ID, element.R1, element.R2, element.Ystart, element.Xstart, element.T, element.S, element.KzString, element.L, element.U1, element.U2, element.C);
592+
}
593+
}
594+
595+
}
596+
private void Warning_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
597+
{
598+
switch (e.Action)
599+
{
600+
case NotifyCollectionChangedAction.Add:
601+
foreach(var item in e.NewItems)
602+
{
603+
Plot2D.Plot.Add.Plottable(item as GeometryWarning);
604+
}
605+
break;
606+
case NotifyCollectionChangedAction.Remove:
607+
foreach (var item in e.OldItems)
608+
{
609+
Plot2D.Plot.Remove(item as GeometryWarning);
610+
}
611+
break;
612+
case NotifyCollectionChangedAction.Replace:
613+
int i = 0;
614+
foreach (var item in e.OldItems)
615+
{
616+
Plot2D.Plot.Remove(item as GeometryWarning);
617+
Plot2D.Plot.Add.Plottable(e.NewItems[i] as GeometryWarning);
618+
i++;
619+
}
620+
break;
621+
case NotifyCollectionChangedAction.Move:
622+
break;
623+
case NotifyCollectionChangedAction.Reset:
624+
break;
625+
}
626+
}
530627
private void CheckProjections_CheckedChanged(object sender, EventArgs e)
531628
{
532629
CheckBox box = (CheckBox)sender;
@@ -559,7 +656,7 @@ private void CheckShowWarnings_CheckedChanged(object sender, EventArgs e)
559656
}
560657
Plot2D.Refresh();
561658
}
562-
659+
563660
private void Plot2D_MouseClick(object sender, MouseEventArgs e)
564661
{
565662
if (e.Button == MouseButtons.Left && Control.ModifierKeys.HasFlag(Keys.Control))

TRA.Lib/TrassenElementExt.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using Microsoft.Extensions.Logging;
22
using System.Globalization;
3+
using System.Collections.ObjectModel;
4+
using System.Collections.Specialized;
35

46
#if USE_SCOTTPLOT
57
using SkiaSharp;
@@ -8,6 +10,17 @@
810

911
namespace TRA_Lib
1012
{
13+
/// <summary>
14+
/// A Collection triggering the Remove Action for all Items on Clearing
15+
/// </summary>
16+
/// <typeparam name="T"></typeparam>
17+
public class CustomObservableCollection<T> : ObservableCollection<T>
18+
{
19+
protected override void ClearItems() {
20+
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, this, Count));
21+
base.ClearItems();
22+
}
23+
}
1124
public struct Interpolation
1225
{
1326
/// <value>Hochwert</value>
@@ -79,7 +92,8 @@ public class TrassenElementExt : TrassenElement
7992
/// <value>Interpolationsobjekt</value>
8093
Interpolation Interpolation;
8194

82-
List<GeometryWarning> WarningCallouts = new() { };
95+
/// <value>List of Warnings. Callouts to show on Plot if compiled with SCOTTPLOT</value>
96+
internal CustomObservableCollection<GeometryWarning> WarningCallouts = new() { };
8397

8498
#if USE_SCOTTPLOT
8599
/// <value>Arrows for visualisation of ProjectionS</value>
@@ -123,7 +137,7 @@ public class TrassenElementExt : TrassenElement
123137
public Interpolation InterpolationResult { get { return Interpolation; } }
124138

125139
/// <value>List of Warnings/ Callouts to show on Plot if compiled with SCOTTPLOT</value>
126-
public GeometryWarning[] GetWarnings { get { return WarningCallouts.ToArray(); } }
140+
//public GeometryWarning[] GetWarnings { get { return WarningCallouts.ToArray(); } }
127141
public TrassenElementExt(double r1, double r2, double y, double x, double t, double s, int kz, double l, double u1, double u2, float c, int idx, Trasse owner, TrassenElementExt predecessor = null)
128142
: base(r1, r2, y, x, t, s, kz, l, u1, u2, c)
129143
{

TRA.Tool/TransformPanel.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
using System.Runtime.CompilerServices;
1313
using TRA_Lib;
1414
using Microsoft.Extensions.Logging;
15+
using System.Xml.Linq;
16+
using System.Diagnostics;
1517

1618
namespace TRA.Tool
1719
{
@@ -58,6 +60,7 @@ private void btn_Transform_Click(object sender, EventArgs e)
5860
FlowLayoutPanel owner = Parent as FlowLayoutPanel;
5961
if (owner == null) { return; }
6062
int idx = owner.Controls.GetChildIndex(this) - 1;
63+
6164
while (idx >= 0 && owner.Controls[idx].GetType() != typeof(TransformPanel))
6265
{
6366
if (owner.Controls[idx].GetType() == typeof(TrassenPanel))
@@ -95,7 +98,36 @@ private void btn_Transform_Click(object sender, EventArgs e)
9598
}
9699
}
97100

98-
//panel.trasseL.Plot();
101+
if (panel.trasseL != null) {
102+
foreach (TrassenElementExt element in panel.trasseL.Elemente)
103+
{
104+
Interpolation interp = element.InterpolationResult;
105+
float deviation = panel.trasseL.ProjectPoints(interp.X, interp.Y);
106+
string ownerString = panel.trasseL.Filename + "_" + element.ID;
107+
TrassierungLog.Logger?.LogInformation(ownerString + " " + "Deviation to geometry after transform: " + deviation);
108+
}
109+
panel.trasseL.Plot();
110+
}
111+
if (panel.trasseS != null) {
112+
foreach (TrassenElementExt element in panel.trasseS.Elemente)
113+
{
114+
Interpolation interp = element.InterpolationResult;
115+
float deviation = panel.trasseS.ProjectPoints(interp.X, interp.Y);
116+
string ownerString = panel.trasseS.Filename + "_" + element.ID;
117+
TrassierungLog.Logger?.LogInformation(ownerString + " " + "Deviation to geometry after transform: " + deviation);
118+
}
119+
panel.trasseS.Plot();
120+
}
121+
if (panel.trasseR != null) {
122+
foreach (TrassenElementExt element in panel.trasseR.Elemente)
123+
{
124+
Interpolation interp = element.InterpolationResult;
125+
float deviation = panel.trasseR.ProjectPoints(interp.X, interp.Y);
126+
string ownerString = panel.trasseR.Filename + "_" + element.ID;
127+
TrassierungLog.Logger?.LogInformation(ownerString + " " + "Deviation to geometry after transform: " + deviation);
128+
}
129+
panel.trasseR.Plot();
130+
}
99131
}
100132
idx--;
101133
}

0 commit comments

Comments
 (0)