diff --git a/PamhagenSysCtrl/Helpers/PamhagenGraph.cs b/PamhagenSysCtrl/Helpers/PamhagenGraph.cs index 3950c60..740b5c2 100644 --- a/PamhagenSysCtrl/Helpers/PamhagenGraph.cs +++ b/PamhagenSysCtrl/Helpers/PamhagenGraph.cs @@ -32,6 +32,9 @@ namespace PamhagenSysCtrl.Helpers { double t8X = t7X + 80; double t9X = t8X + 80; + var trough = new EntryTrough("Übernahme-Trog", mw1X + 80, 20); + Nodes.Add(trough); + var rebler = new Rebler("Rebler", (mw1X + mw2X) / 2, 100); Nodes.Add(rebler); diff --git a/PamhagenSysCtrl/Helpers/Pipeline/Auger.cs b/PamhagenSysCtrl/Helpers/Pipeline/Auger.cs new file mode 100644 index 0000000..3f0b259 --- /dev/null +++ b/PamhagenSysCtrl/Helpers/Pipeline/Auger.cs @@ -0,0 +1,72 @@ +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; + +namespace PamhagenSysCtrl.Helpers.Pipeline { + public class Auger { + + public double CenterX { get; set; } + public double CenterY { get; set; } + public double Width { get; set; } + public double Height { get; set; } + + public bool IsActive { + set { + if (value) { + _storyboard?.Resume(); + } else { + _storyboard?.Pause(); + } + } + } + + private Polyline? _polyline; + private Storyboard? _storyboard; + + public Auger(double x, double y, double width, double height) { + CenterX = x; + CenterY = y; + Width = width; + Height = height; + } + + public void Draw(Canvas canvas) { + var d = Height / 4; + int n = (int)(Width / d / 4) + 2; + _polyline = new Polyline() { + Points = [.. Enumerable.Range(0, n).SelectMany(i => new List() { + new(i * 4 * d, Height / 2), new((i * 4 + 1) * d, 0), + new((i * 4 + 2) * d, Height / 2), new((i * 4 + 3) * d, Height) + }), new(n * 4 * d, Height / 2), new(0, Height / 2)], + Fill = Brushes.Transparent, + Stroke = Brushes.Black, + StrokeThickness = 2, + }; + _polyline.SetValue(Canvas.LeftProperty, 0.0); + + var slideLeft = new DoubleAnimation { + From = 0, + To = -d * 4, + Duration = new Duration(TimeSpan.FromSeconds(1)), + RepeatBehavior = RepeatBehavior.Forever, + }; + _storyboard = new Storyboard(); + _storyboard.Children.Add(slideLeft); + Storyboard.SetTarget(slideLeft, _polyline); + Storyboard.SetTargetProperty(slideLeft, new PropertyPath(Canvas.LeftProperty)); + var clipCanvas = new Canvas() { + Width = Width, + Height = Height, + ClipToBounds = true, + }; + clipCanvas.SetValue(Canvas.TopProperty, CenterY - Height / 2); + clipCanvas.SetValue(Canvas.LeftProperty, CenterX - Width / 2); + clipCanvas.Children.Add(_polyline); + canvas.Children.Add(clipCanvas); + _storyboard.Begin(); + _storyboard.Pause(); + } + } +} diff --git a/PamhagenSysCtrl/Helpers/Pipeline/EntryTrough.cs b/PamhagenSysCtrl/Helpers/Pipeline/EntryTrough.cs new file mode 100644 index 0000000..5944dfb --- /dev/null +++ b/PamhagenSysCtrl/Helpers/Pipeline/EntryTrough.cs @@ -0,0 +1,108 @@ +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; + +namespace PamhagenSysCtrl.Helpers.Pipeline { + class EntryTrough : INode { + + public const double WIDTH = 150; + public const double HEIGHT = 50; + + public double CenterX { get; set; } + public double CenterY { get; set; } + public string Label { get; set; } + public ISet Inputs { get; init; } + public ISet Outputs { get; init; } + + public bool IsActive { + get => _active; + set { + _active = value; + _auger?.IsActive = value; + if (value) { + _doorTransform?.BeginAnimation( + RotateTransform.AngleProperty, + new DoubleAnimation { + From = _doorTransform.Angle, + To = 60, + Duration = TimeSpan.FromSeconds(Math.Abs(_doorTransform.Angle - 60) / 60.0) + }); + } else { + _doorTransform?.BeginAnimation( + RotateTransform.AngleProperty, + new DoubleAnimation { + From = _doorTransform.Angle, + To = 0, + Duration = TimeSpan.FromSeconds(Math.Abs(_doorTransform.Angle - 0) / 60.0) + }); + } + } + } + + public EntryTrough(string label, double x, double y) { + CenterX = x; + CenterY = y; + Label = label; + Inputs = new HashSet(); + Outputs = new HashSet(); + } + + private bool _active; + private Shape? _inner; + private Shape? _outer; + private TextBlock? _text; + private Auger? _auger; + private Shape? _door; + private RotateTransform? _doorTransform; + + public void Draw(Canvas canvas) { + var top = CenterY - HEIGHT / 2; + var right = CenterX + WIDTH / 2; + var bottom = CenterY + HEIGHT / 2; + var left = CenterX - WIDTH / 2; + _outer = new Polygon() { + Points = [new(left, top), new(right, top), new(right - 20, bottom), new(left, bottom), new(left, bottom - 20), new(left + 12.5, bottom - 20)], + Fill = Brushes.Black, + }; + _inner = new Polygon() { + Points = [new(left + 2, top), new(right - 2, top), new(right - 20 - 2, bottom - 2), new(left, bottom - 2), new(left, bottom - 18), new(left + 15.5, bottom - 18)], + Fill = Brushes.WhiteSmoke, + }; + _doorTransform = new RotateTransform(0, left, bottom - 24); + _door = new Line() { + X1 = left, Y1 = bottom - 24, X2 = left, Y2 = bottom + 4, + Stroke = Brushes.Black, + StrokeThickness = 4, + RenderTransform = _doorTransform, + }; + _text = new() { + Text = Label, + FontSize = 12, + Width = WIDTH, + TextAlignment = TextAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + }; + _text.SetValue(Canvas.LeftProperty, CenterX - WIDTH / 2); + _text.SetValue(Canvas.TopProperty, CenterY - HEIGHT / 6 - 8); + canvas.Children.Add(_outer); + canvas.Children.Add(_inner); + canvas.Children.Add(_text); + canvas.Children.Add(_door); + _auger = new(CenterX - 11, CenterY + HEIGHT / 2 - 9, WIDTH - 25, 12); + _auger.Draw(canvas); + } + + public bool IsInside(double x, double y) { + return Math.Abs(x - CenterX) <= WIDTH / 2 && Math.Abs(y - CenterY) <= HEIGHT / 2; + } + + public void Update(bool isHovering, bool isPressed) { + _inner?.Fill = + isHovering && isPressed ? Brushes.DarkGray : + isHovering ? Brushes.LightGray : + Brushes.WhiteSmoke; + } + } +} diff --git a/PamhagenSysCtrl/Helpers/Pipeline/Pipe.cs b/PamhagenSysCtrl/Helpers/Pipeline/Pipe.cs index c10f022..eaa586f 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/Pipe.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/Pipe.cs @@ -1,5 +1,4 @@ -using System.Windows; -using System.Windows.Controls; +using System.Windows.Controls; using System.Windows.Media; using System.Windows.Shapes; @@ -12,10 +11,8 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { public bool Orientation { get; set; } public Brush? Highlight { get; set; } - private Line? _outer1; - private Line? _outer2; - private Line? _inner1; - private Line? _inner2; + private Polyline? _outer; + private Polyline? _inner; public Pipe(INode start, INode end, bool orientation = false, bool twoWay = false) { Start = start; @@ -31,43 +28,28 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { var y2 = Orientation ? End.CenterY : Start.CenterY; var x3 = End.CenterX; var y3 = End.CenterY; - _outer1 = new Line() { - X1 = x1, Y1 = y1, X2 = x2, Y2 = y2, + _outer = new Polyline() { + Points = [new(x1, y1), new(x2, y2), new(x3, y3)], StrokeThickness = 10, Stroke = Brushes.Black, StrokeStartLineCap = PenLineCap.Round, StrokeEndLineCap = PenLineCap.Round, + StrokeLineJoin = PenLineJoin.Round, }; - _inner1 = new Line() { - X1 = x1, Y1 = y1, X2 = x2, Y2 = y2, + _inner = new Polyline() { + Points = [new(x1, y1), new(x2, y2), new(x3, y3)], StrokeThickness = 6, Stroke = Brushes.DarkGray, StrokeStartLineCap = PenLineCap.Round, StrokeEndLineCap = PenLineCap.Round, + StrokeLineJoin = PenLineJoin.Round, }; - _outer2 = new Line() { - X1 = x2, Y1 = y2, X2 = x3, Y2 = y3, - StrokeThickness = 10, - Stroke = Brushes.Black, - StrokeStartLineCap = PenLineCap.Round, - StrokeEndLineCap = PenLineCap.Round, - }; - _inner2 = new Line() { - X1 = x2, Y1 = y2, X2 = x3, Y2 = y3, - StrokeThickness = 6, - Stroke = Brushes.DarkGray, - StrokeStartLineCap = PenLineCap.Round, - StrokeEndLineCap = PenLineCap.Round, - }; - canvas.Children.Add(_outer1); - canvas.Children.Add(_outer2); - canvas.Children.Add(_inner1); - canvas.Children.Add(_inner2); + canvas.Children.Add(_outer); + canvas.Children.Add(_inner); } public void Update() { - _inner1?.Stroke = Highlight ?? Brushes.DarkGray; - _inner2?.Stroke = Highlight ?? Brushes.DarkGray; + _inner?.Stroke = Highlight ?? Brushes.DarkGray; } } } diff --git a/PamhagenSysCtrl/Helpers/Pipeline/PipeJoin.cs b/PamhagenSysCtrl/Helpers/Pipeline/PipeJoin.cs index d0286dc..c39c4e1 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/PipeJoin.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/PipeJoin.cs @@ -11,7 +11,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { public double CenterX { get; set; } public double CenterY { get; set; } - public string Label { get; } = ""; + public string Label => ""; public ISet Inputs { get; init; } public ISet Outputs { get; init; } diff --git a/PamhagenSysCtrl/Helpers/Pipeline/Rebler.cs b/PamhagenSysCtrl/Helpers/Pipeline/Rebler.cs index 8c1b75f..f3200d4 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/Rebler.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/Rebler.cs @@ -15,6 +15,8 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { public ISet Inputs { get; init; } public ISet Outputs { get; init; } + public bool IsActive { get; set; } + private TextBlock? _text; private Shape? _rect; private Shape? _hopperOuter; @@ -42,15 +44,15 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { var right = CenterX + WIDTH / 2; var top = CenterY - HEIGHT / 2; var bottom = CenterY + HEIGHT / 2; - var hx = right - 10; + var hx = right - 20; var h = 15; var w = 25; _hopperOuter = new Polygon() { - Points = [new(hx - w, top - h), new(hx, top + 30), new(hx + w, top - h)], + Points = [new(hx - w, top - h), new(hx - w + 5, top + 2), new(hx + w - 5, top + 2), new(hx + w, top - h)], Fill = Brushes.Black, }; _hopperInner = new Polygon() { - Points = [new(hx - w + 2, top - h), new(hx, top + 26), new(hx + w - 2, top - h)], + Points = [new(hx - w + 2, top - h), new(hx - w + 5 + 2, top + 2), new(hx + w - 5 - 2, top + 2), new(hx + w - 2, top - h)], Fill = Brushes.WhiteSmoke, }; _bottomOuter = new Polygon() { diff --git a/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml.cs b/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml.cs index c5163b0..398bc9f 100644 --- a/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml.cs +++ b/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml.cs @@ -2,7 +2,6 @@ using PamhagenSysCtrl.Helpers.Pipeline; using System.Windows; using System.Windows.Input; -using System.Windows.Media; namespace PamhagenSysCtrl.Windows { public partial class PlantSchemeWindow : Window { @@ -58,6 +57,11 @@ namespace PamhagenSysCtrl.Windows { } else { _lastSource = null; } + if (c is EntryTrough trough) { + trough.IsActive = !trough.IsActive; + } else if (c is Rebler rebler) { + rebler.IsActive = !rebler.IsActive; + } } UpdateScheme(pos, evt.LeftButton == MouseButtonState.Pressed); }