Enhance flow arrows
This commit is contained in:
@@ -431,13 +431,13 @@ namespace PamhagenSysCtrl.Helpers {
|
||||
}
|
||||
}
|
||||
|
||||
public void ColorPipesAdjacientToPath(Path path, Brush? color1, Brush? color2) {
|
||||
public void ColorPipesAdjacientToPath(Path path, Brush? color1, bool flowArrows, Brush? color2) {
|
||||
var color = color1;
|
||||
var flowPathOffset = 0.0;
|
||||
HashSet<IEdge> visited = [];
|
||||
foreach (var (edge, node) in path.Hops) {
|
||||
edge.Highlight = color1;
|
||||
edge.Flow = color1 == PamhagenBrushes.Green ? (edge.End == node, flowPathOffset) : null;
|
||||
edge.Flow = flowArrows ? (edge.End == node, flowPathOffset) : null;
|
||||
if (edge.Flow != null) flowPathOffset += edge.FlowLength;
|
||||
visited.Add(edge);
|
||||
if (node is Pump) color = color2;
|
||||
|
||||
@@ -7,10 +7,10 @@ using System.Windows.Shapes;
|
||||
namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
internal sealed class FlowArrow {
|
||||
|
||||
private const double Speed = 45;
|
||||
private const double Spacing = 40;
|
||||
private const double HalfLength = 5;
|
||||
private const double HalfWidth = 3.5;
|
||||
public const double SPEED = 20;
|
||||
public const double SPACING = 15;
|
||||
public const double LENGTH = 7;
|
||||
public const double WIDTH = 7;
|
||||
|
||||
private static readonly Stopwatch Clock = Stopwatch.StartNew();
|
||||
|
||||
@@ -51,17 +51,8 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
return;
|
||||
}
|
||||
|
||||
var points = flow.Value.TowardEnd
|
||||
? _path
|
||||
: [.. _path.Reverse()];
|
||||
var length = GetLength(points[0], points[1]) + GetLength(points[1], points[2]);
|
||||
if (length < 16) {
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
_points = points;
|
||||
_length = length;
|
||||
_points = flow.Value.TowardEnd ? _path : [.. _path.Reverse()];
|
||||
_length = GetLength(_points[0], _points[1]) + GetLength(_points[1], _points[2]);
|
||||
_pathOffset = flow.Value.PathOffset;
|
||||
if (!_isActive) {
|
||||
CompositionTarget.Rendering += OnRendering;
|
||||
@@ -76,13 +67,13 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
}
|
||||
|
||||
private void Render() {
|
||||
var distance = PositiveModulo(Clock.Elapsed.TotalSeconds * Speed - _pathOffset, Spacing);
|
||||
var distance = ((Clock.Elapsed.TotalSeconds * SPEED - _pathOffset) % SPACING + SPACING) % SPACING;
|
||||
var arrowIndex = 0;
|
||||
while (distance <= _length) {
|
||||
var arrow = GetArrow(arrowIndex++);
|
||||
SetPosition(arrow, distance);
|
||||
arrow.Visibility = Visibility.Visible;
|
||||
distance += Spacing;
|
||||
distance += SPACING;
|
||||
}
|
||||
while (arrowIndex < _layer.Children.Count) {
|
||||
_layer.Children[arrowIndex++].Visibility = Visibility.Collapsed;
|
||||
@@ -95,12 +86,15 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
}
|
||||
|
||||
var arrow = new Polygon() {
|
||||
Fill = Brushes.Black,
|
||||
Fill = new SolidColorBrush(Color.FromArgb(0x60, 0, 0, 0)),
|
||||
IsHitTestVisible = false,
|
||||
Points = [
|
||||
new Point(HalfLength, 0),
|
||||
new Point(-HalfLength, HalfWidth),
|
||||
new Point(-HalfLength, -HalfWidth),
|
||||
new(-LENGTH / 2, -WIDTH / 2),
|
||||
new(0, -WIDTH / 2),
|
||||
new(LENGTH / 2, 0),
|
||||
new(0, WIDTH / 2),
|
||||
new(-LENGTH / 2, WIDTH / 2),
|
||||
new(0, 0),
|
||||
],
|
||||
RenderTransform = new MatrixTransform(Matrix.Identity),
|
||||
};
|
||||
@@ -109,29 +103,51 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
}
|
||||
|
||||
private void SetPosition(Polygon arrow, double distance) {
|
||||
var firstLength = GetLength(_points[0], _points[1]);
|
||||
var secondLength = GetLength(_points[1], _points[2]);
|
||||
Point start;
|
||||
Point end;
|
||||
double segmentDistance;
|
||||
if ((firstLength > 0 && distance <= firstLength) || secondLength == 0) {
|
||||
start = _points[0];
|
||||
end = _points[1];
|
||||
segmentDistance = distance;
|
||||
const double blendDistance = WIDTH / 2;
|
||||
double firstLength = GetLength(_points[0], _points[1]);
|
||||
double blendStartDistance = firstLength - blendDistance;
|
||||
double blendEndDistance = firstLength + blendDistance;
|
||||
|
||||
Vector v1 = Normalize(_points[0], _points[1]);
|
||||
Vector v2 = Normalize(_points[1], _points[2]);
|
||||
Point blendStart = _points[1] - v1 * blendDistance;
|
||||
Point blendEnd = _points[1] + v2 * blendDistance;
|
||||
|
||||
Point position;
|
||||
Vector direction;
|
||||
if (distance < blendStartDistance) {
|
||||
position = _points[0] + v1 * distance;
|
||||
direction = v1;
|
||||
} else if (distance <= blendEndDistance) {
|
||||
double t = (distance - blendStartDistance) / (blendEndDistance - blendStartDistance);
|
||||
double u = 1.0 - t;
|
||||
|
||||
position = new Point(
|
||||
u * u * blendStart.X +
|
||||
2 * u * t * _points[1].X +
|
||||
t * t * blendEnd.X,
|
||||
|
||||
u * u * blendStart.Y +
|
||||
2 * u * t * _points[1].Y +
|
||||
t * t * blendEnd.Y);
|
||||
|
||||
direction = new Vector(
|
||||
2 * u * (_points[1].X - blendStart.X) +
|
||||
2 * t * (blendEnd.X - _points[1].X),
|
||||
|
||||
2 * u * (_points[1].Y - blendStart.Y) +
|
||||
2 * t * (blendEnd.Y - _points[1].Y));
|
||||
|
||||
direction.Normalize();
|
||||
} else {
|
||||
start = _points[1];
|
||||
end = _points[2];
|
||||
segmentDistance = distance - firstLength;
|
||||
double d = distance - firstLength;
|
||||
position = _points[1] + v2 * d;
|
||||
direction = v2;
|
||||
}
|
||||
|
||||
var segmentLength = GetLength(start, end);
|
||||
if (segmentLength == 0) return;
|
||||
var ux = (end.X - start.X) / segmentLength;
|
||||
var uy = (end.Y - start.Y) / segmentLength;
|
||||
var x = start.X + ux * segmentDistance;
|
||||
var y = start.Y + uy * segmentDistance;
|
||||
((MatrixTransform)arrow.RenderTransform).Matrix = new Matrix(
|
||||
ux, uy, -uy, ux, x, y);
|
||||
double ux = direction.X;
|
||||
double uy = direction.Y;
|
||||
(arrow.RenderTransform as MatrixTransform)?.Matrix = new Matrix(ux, uy, -uy, ux, position.X, position.Y);
|
||||
}
|
||||
|
||||
private void Stop() {
|
||||
@@ -142,14 +158,16 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
_layer.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private static double PositiveModulo(double value, double modulus) {
|
||||
return (value % modulus + modulus) % modulus;
|
||||
}
|
||||
|
||||
private static double GetLength(Point start, Point end) {
|
||||
var dx = end.X - start.X;
|
||||
var dy = end.Y - start.Y;
|
||||
return Math.Sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
private static Vector Normalize(Point p1, Point p2) {
|
||||
Vector v = p2 - p1;
|
||||
if (v.Length > 0) v.Normalize();
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
public void Update() {
|
||||
_inner1?.Stroke = Highlight ?? Brushes.DarkGray;
|
||||
_inner2?.Stroke = Highlight ?? Brushes.DarkGray;
|
||||
_flowArrow?.Update(Highlight == PamhagenBrushes.Green ? Flow : null);
|
||||
_flowArrow?.Update(Flow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
Y2 = y2,
|
||||
StrokeThickness = 10,
|
||||
Stroke = Brushes.Black,
|
||||
StrokeStartLineCap = PenLineCap.Flat,
|
||||
StrokeStartLineCap = PenLineCap.Round,
|
||||
StrokeEndLineCap = PenLineCap.Round,
|
||||
};
|
||||
_inner1 = new Line() {
|
||||
@@ -59,7 +59,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
Y2 = y2,
|
||||
StrokeThickness = 6,
|
||||
Stroke = Brushes.DarkGray,
|
||||
StrokeStartLineCap = PenLineCap.Flat,
|
||||
StrokeStartLineCap = PenLineCap.Round,
|
||||
StrokeEndLineCap = PenLineCap.Round,
|
||||
};
|
||||
_outer2 = new Line() {
|
||||
@@ -79,22 +79,22 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
Y2 = y3,
|
||||
StrokeThickness = 6,
|
||||
Stroke = Brushes.DarkGray,
|
||||
StrokeStartLineCap = PenLineCap.Square,
|
||||
StrokeEndLineCap = PenLineCap.Square,
|
||||
StrokeStartLineCap = PenLineCap.Round,
|
||||
StrokeEndLineCap = PenLineCap.Round,
|
||||
};
|
||||
canvas.Children.Add(_outer1);
|
||||
canvas.Children.Add(_outer2);
|
||||
canvas.Children.Add(_hopper);
|
||||
canvas.Children.Add(_inner1);
|
||||
canvas.Children.Add(_inner2);
|
||||
_flowArrow = FlowArrow.Create(canvas, _inner1!, _inner2!);
|
||||
canvas.Children.Add(_hopper);
|
||||
}
|
||||
|
||||
public void Update() {
|
||||
_inner1?.Stroke = Highlight ?? Brushes.DarkGray;
|
||||
_inner2?.Stroke = Highlight ?? Brushes.DarkGray;
|
||||
_hopper?.Fill = Highlight ?? Brushes.DarkGray;
|
||||
_flowArrow?.Update(Highlight == PamhagenBrushes.Green ? Flow : null);
|
||||
_flowArrow?.Update(Flow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
||||
|
||||
public void Update() {
|
||||
_inner?.Stroke = Highlight ?? Brushes.DarkGray;
|
||||
_flowArrow?.Update(Highlight == PamhagenBrushes.Green ? Flow : null);
|
||||
_flowArrow?.Update(Flow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user