using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace PamhagenSysCtrl.Helpers.Pipeline { public class PipeJoin : INode { public const double SIZE = 3.6; public const double POINT = 0.8; public double CenterX { get; set; } public double CenterY { get; set; } public string Label => ""; public Brush? Highlight { get; set; } public ISet Inputs { get; init; } public ISet Outputs { get; init; } private System.Windows.Shapes.Path? _rect; public PipeJoin(double x, double y) { CenterX = x; CenterY = y; Inputs = new HashSet(); Outputs = new HashSet(); } public void Draw(Canvas canvas) { _rect = new System.Windows.Shapes.Path() { Fill = Brushes.DarkGray, Stroke = Brushes.Black, }; canvas.Children.Add(_rect); } public void Scale(double scale) { var it = Inputs.Any(e => (e.Start.CenterY < CenterY && (!e.Orientation || e.Start.CenterX == CenterX)) || (e.IsTwoWay && e.End.CenterY < CenterY && (!e.Orientation || e.End.CenterX == CenterX))); var ot = Outputs.Any(e => (e.End.CenterY < CenterY && (e.Orientation || e.End.CenterX == CenterX)) || (e.IsTwoWay && e.Start.CenterY < CenterY && (e.Orientation || e.Start.CenterX == CenterX))); var ir = Inputs.Any(e => (e.Start.CenterX > CenterX && (e.Orientation || e.Start.CenterY == CenterY)) || (e.IsTwoWay && e.End.CenterX > CenterX && (e.Orientation || e.End.CenterY == CenterY))); var or = Outputs.Any(e => (e.End.CenterX > CenterX && (!e.Orientation || e.End.CenterY == CenterY)) || (e.IsTwoWay && e.Start.CenterX > CenterX && (!e.Orientation || e.Start.CenterY == CenterY))); var ib = Inputs.Any(e => (e.Start.CenterY > CenterY && (!e.Orientation || e.Start.CenterX == CenterX)) || (e.IsTwoWay && e.End.CenterY > CenterY && (!e.Orientation || e.End.CenterX == CenterX))); var ob = Outputs.Any(e => (e.End.CenterY > CenterY && (e.Orientation || e.End.CenterX == CenterX)) || (e.IsTwoWay && e.Start.CenterY > CenterY && (e.Orientation || e.Start.CenterX == CenterX))); var il = Inputs.Any(e => (e.Start.CenterX < CenterX && (e.Orientation || e.Start.CenterY == CenterY)) || (e.IsTwoWay && e.End.CenterX < CenterX && (e.Orientation || e.End.CenterY == CenterY))); var ol = Outputs.Any(e => (e.End.CenterX < CenterX && (!e.Orientation || e.End.CenterY == CenterY)) || (e.IsTwoWay && e.Start.CenterX < CenterX && (!e.Orientation || e.Start.CenterY == CenterY))); var size = new Size(SIZE / 2 * scale, SIZE / 2 * scale); var geo = new StreamGeometry(); using (var ctx = geo.Open()) { var points = new List { new(0, 0) }; ctx.BeginFigure(new((SIZE / 2 - POINT) * scale, 0), true, false); if (ot && it) { points.AddRange([new(SIZE / 2, -POINT / 2), new(SIZE / 2, POINT / 2), new(SIZE / 2 + POINT, 0)]); } else if (ot) { ctx.PolyLineTo([new(SIZE / 2 * scale, -POINT * scale), new((SIZE / 2 + POINT) * scale, 0)], true, false); } else if (it) { ctx.PolyLineTo([new(SIZE / 2 * scale, POINT * scale), new((SIZE / 2 + POINT) * scale, 0)], true, false); } else { ctx.ArcTo(new((SIZE / 2 + POINT) * scale, 0), size, 0, false, SweepDirection.Clockwise, true, false); } ctx.ArcTo(new(SIZE * scale, (SIZE / 2 - POINT) * scale), size, 0, false, SweepDirection.Clockwise, true, false); points.Add(new(SIZE, 0)); if (or && ir) { points.AddRange([new(SIZE, SIZE / 2 - POINT), new(SIZE + POINT / 2, SIZE / 2), new(SIZE - POINT / 2, SIZE / 2), new(SIZE, SIZE / 2 + POINT)]); } else if (or) { ctx.PolyLineTo([new((SIZE + POINT) * scale, SIZE / 2 * scale), new(SIZE * scale, (SIZE / 2 + POINT) * scale)], true, false); } else if (ir) { ctx.PolyLineTo([new((SIZE - POINT) * scale, SIZE / 2 * scale), new(SIZE * scale, (SIZE / 2 + POINT) * scale)], true, false); } else { ctx.ArcTo(new(SIZE * scale, (SIZE / 2 + POINT) * scale), size, 0, false, SweepDirection.Clockwise, true, false); } ctx.ArcTo(new((SIZE / 2 + POINT) * scale, SIZE * scale), size, 0, false, SweepDirection.Clockwise, true, false); points.Add(new(SIZE, SIZE)); if (ob && ib) { points.AddRange([new(SIZE / 2 + POINT, SIZE), new(SIZE / 2, SIZE + POINT / 2), new(SIZE / 2, SIZE - POINT / 2), new(SIZE / 2 - POINT, SIZE)]); } else if (ob) { ctx.PolyLineTo([new(SIZE / 2 * scale, (SIZE + POINT) * scale), new((SIZE / 2 - POINT) * scale, SIZE * scale)], true, false); } else if (ib) { ctx.PolyLineTo([new(SIZE / 2 * scale, (SIZE - POINT) * scale), new((SIZE / 2 - POINT) * scale, SIZE * scale)], true, false); } else { ctx.ArcTo(new((SIZE / 2 - POINT) * scale, SIZE * scale), size, 0, false, SweepDirection.Clockwise, true, false); } ctx.ArcTo(new(0, (SIZE / 2 + POINT) * scale), size, 0, false, SweepDirection.Clockwise, true, false); points.Add(new(0, SIZE)); if (ol && il) { points.AddRange([new(0, SIZE / 2 + POINT), new(-POINT / 2, SIZE / 2), new(POINT / 2, SIZE / 2), new(0, SIZE / 2 - POINT)]); } else if (ol) { ctx.PolyLineTo([new(-POINT * scale, SIZE / 2 * scale), new(0, (SIZE / 2 - POINT) * scale)], true, false); } else if (il) { ctx.PolyLineTo([new(POINT * scale, SIZE / 2 * scale), new(0, (SIZE / 2 - POINT) * scale)], true, false); } else { ctx.ArcTo(new(0, (SIZE / 2 - POINT) * scale), size, 0, false, SweepDirection.Clockwise, true, false); } ctx.ArcTo(new((SIZE / 2 - POINT) * scale, 0), size, 0, false, SweepDirection.Clockwise, true, false); } _rect?.Data = geo; // [.. points.Select(p => new Point(p.X * scale, p.Y * scale))]; _rect?.StrokeThickness = Graph.ToBorder(scale); _rect?.SetValue(Canvas.LeftProperty, (CenterX - SIZE / 2) * scale); _rect?.SetValue(Canvas.TopProperty, (CenterY - SIZE / 2) * scale); } public bool IsInside(double x, double y) { return Math.Abs(x - CenterX) <= SIZE / 2 && Math.Abs(y - CenterY) <= SIZE / 2; } public void Update(bool isHovering, bool isPressed) { _rect?.Fill = Highlight ?? Brushes.DarkGray; } } }