Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21dfc5493c |
@@ -4,3 +4,4 @@ bin/
|
|||||||
.vs
|
.vs
|
||||||
.idea
|
.idea
|
||||||
*.exe
|
*.exe
|
||||||
|
*.zip
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
Pamhagen
|
||||||
|
========
|
||||||
|
|
||||||
|
Source code
|
||||||
|
C:\Program Files\Pamhagen\src\PamhagenSysCtrl-source.zip
|
||||||
|
https://git.necronda.net/winzer/pamhagen-sysctrl
|
||||||
|
|
||||||
|
Installation folder
|
||||||
|
C:\Program Files\Pamhagen\
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||||
|
<Fragment>
|
||||||
|
<StandardDirectory Id="ProgramFiles64Folder">
|
||||||
|
<Directory Id="INSTALLFOLDER" Name="!(bind.Property.ProductName)">
|
||||||
|
<Directory Id="SourceFolder" Name="src" />
|
||||||
|
</Directory>
|
||||||
|
</StandardDirectory>
|
||||||
|
|
||||||
|
<StandardDirectory Id="ProgramMenuFolder">
|
||||||
|
<Directory Id="StartMenuProgramsFolder" Name="!(bind.Property.ProductName)" />
|
||||||
|
</StandardDirectory>
|
||||||
|
|
||||||
|
<StandardDirectory Id="DesktopFolder" />
|
||||||
|
</Fragment>
|
||||||
|
</Wix>
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<Project Sdk="WixToolset.Sdk/7.0.0">
|
||||||
|
<PropertyGroup>
|
||||||
|
<InstallerPlatform>x64</InstallerPlatform>
|
||||||
|
<OutputName>PamhagenSysCtrl</OutputName>
|
||||||
|
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||||
|
<Cultures>de-AT</Cultures>
|
||||||
|
<AcceptEula>wix7</AcceptEula>
|
||||||
|
<SuppressValidation>false</SuppressValidation>
|
||||||
|
<PublishDirectory>$(MSBuildProjectDirectory)\..\PamhagenSysCtrl\bin\Publish</PublishDirectory>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<UsingTask TaskName="GetFileVersion"
|
||||||
|
TaskFactory="RoslynCodeTaskFactory"
|
||||||
|
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
||||||
|
<ParameterGroup>
|
||||||
|
<AssemblyPath ParameterType="System.String" Required="true" />
|
||||||
|
<Version ParameterType="System.String" Output="true" />
|
||||||
|
</ParameterGroup>
|
||||||
|
<Task>
|
||||||
|
<Using Namespace="System.Diagnostics" />
|
||||||
|
<Code Type="Fragment" Language="cs"><![CDATA[
|
||||||
|
Version = FileVersionInfo.GetVersionInfo(AssemblyPath).ProductVersion.Split('+')[0];
|
||||||
|
]]></Code>
|
||||||
|
</Task>
|
||||||
|
</UsingTask>
|
||||||
|
|
||||||
|
<Target Name="PublishApplication" BeforeTargets="BeforeBuild">
|
||||||
|
<RemoveDir Directories="$(PublishDirectory)" Condition="Exists('$(PublishDirectory)')" />
|
||||||
|
<Exec Command="dotnet publish "$(MSBuildProjectDirectory)\..\PamhagenSysCtrl\PamhagenSysCtrl.csproj" --configuration "$(Configuration)" --runtime win-x64 --self-contained true --output "$(PublishDirectory)" --nologo" />
|
||||||
|
<GetFileVersion AssemblyPath="$(PublishDirectory)\PamhagenSysCtrl.exe">
|
||||||
|
<Output TaskParameter="Version" PropertyName="ProductVersion" />
|
||||||
|
</GetFileVersion>
|
||||||
|
<PropertyGroup>
|
||||||
|
<DefineConstants>ProductVersion=$(ProductVersion);BuildPath=$(PublishDirectory)</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CreateSourceArchive" BeforeTargets="BeforeBuild">
|
||||||
|
<Exec Command="git -C "$(MSBuildProjectDirectory)\.." archive --format=zip --output "$(MSBuildProjectDirectory)\Files\PamhagenSysCtrl-source.zip" HEAD" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\PamhagenSysCtrl\PamhagenSysCtrl.csproj"
|
||||||
|
ReferenceOutputAssembly="false" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||||
|
<Fragment>
|
||||||
|
<ComponentGroup Id="MainComponents">
|
||||||
|
<Component Directory="INSTALLFOLDER">
|
||||||
|
<File Source="$(var.BuildPath)\PamhagenSysCtrl.exe"
|
||||||
|
Id="PamhagenSysCtrl.exe" />
|
||||||
|
</Component>
|
||||||
|
|
||||||
|
<Component Directory="SourceFolder">
|
||||||
|
<File Source="$(ProjectDir)\Files\PamhagenSysCtrl-source.zip"
|
||||||
|
Id="PamhagenSysCtrlSource.zip" />
|
||||||
|
</Component>
|
||||||
|
|
||||||
|
<Component Directory="INSTALLFOLDER">
|
||||||
|
<File Source="$(ProjectDir)\Files\README.txt"
|
||||||
|
Id="README.txt" />
|
||||||
|
</Component>
|
||||||
|
|
||||||
|
<Files Directory="INSTALLFOLDER" Include="$(var.BuildPath)\**">
|
||||||
|
<Exclude Files="$(var.BuildPath)\PamhagenSysCtrl.exe" />
|
||||||
|
<Exclude Files="$(var.BuildPath)\**.pdb" />
|
||||||
|
</Files>
|
||||||
|
</ComponentGroup>
|
||||||
|
</Fragment>
|
||||||
|
</Wix>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl"
|
||||||
|
Culture="de-AT">
|
||||||
|
<String Id="DowngradeError"
|
||||||
|
Value="Eine neuere Version von [ProductName] ist bereits installiert." />
|
||||||
|
</WixLocalization>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||||
|
<Package Name="Pamhagen"
|
||||||
|
Manufacturer="Pamhagen"
|
||||||
|
Version="$(var.ProductVersion)"
|
||||||
|
Language="3079"
|
||||||
|
UpgradeCode="f214bfc6-1cd0-4971-807e-a4830e3b82a3"
|
||||||
|
Scope="perMachine"
|
||||||
|
Compressed="true">
|
||||||
|
<MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)"
|
||||||
|
AllowSameVersionUpgrades="no" />
|
||||||
|
<MediaTemplate EmbedCab="true" CompressionLevel="high" />
|
||||||
|
|
||||||
|
<Feature Id="Main" Title="Pamhagen" Level="1">
|
||||||
|
<ComponentGroupRef Id="MainComponents" />
|
||||||
|
<ComponentGroupRef Id="ShortcutComponents" />
|
||||||
|
</Feature>
|
||||||
|
</Package>
|
||||||
|
</Wix>
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||||
|
<Fragment>
|
||||||
|
<ComponentGroup Id="ShortcutComponents">
|
||||||
|
<Component Id="StartMenuFolderShortcut"
|
||||||
|
Directory="StartMenuProgramsFolder"
|
||||||
|
Guid="6101b33f-9bc8-4d44-aad0-0f3eddc840c6">
|
||||||
|
<Shortcut Id="ApplicationStartMenuShortcut"
|
||||||
|
Name="!(bind.Property.ProductName)"
|
||||||
|
Description="!(bind.Property.ProductName)"
|
||||||
|
Target="[INSTALLFOLDER]PamhagenSysCtrl.exe"
|
||||||
|
WorkingDirectory="INSTALLFOLDER" />
|
||||||
|
<RemoveFolder Id="StartMenuProgramsFolder" On="uninstall" />
|
||||||
|
<RegistryValue Root="HKCU"
|
||||||
|
Key="Software\!(bind.Property.Manufacturer)\!(bind.Property.ProductName)"
|
||||||
|
Name="start_menu_installed"
|
||||||
|
Type="integer"
|
||||||
|
Value="1"
|
||||||
|
KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
|
||||||
|
<Component Id="DesktopFolderShortcut"
|
||||||
|
Directory="DesktopFolder"
|
||||||
|
Guid="58b61147-4e5c-4581-8593-fc7bcb591048">
|
||||||
|
<Shortcut Id="DesktopShortcut"
|
||||||
|
Name="!(bind.Property.ProductName)"
|
||||||
|
Description="!(bind.Property.ProductName)"
|
||||||
|
Target="[INSTALLFOLDER]PamhagenSysCtrl.exe"
|
||||||
|
WorkingDirectory="INSTALLFOLDER" />
|
||||||
|
<RegistryValue Root="HKCU"
|
||||||
|
Key="Software\!(bind.Property.Manufacturer)\!(bind.Property.ProductName)"
|
||||||
|
Name="desktop_installed"
|
||||||
|
Type="integer"
|
||||||
|
Value="1"
|
||||||
|
KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</ComponentGroup>
|
||||||
|
</Fragment>
|
||||||
|
</Wix>
|
||||||
@@ -1,3 +1,10 @@
|
|||||||
<Solution>
|
<Solution>
|
||||||
|
<Configurations>
|
||||||
|
<Platform Name="Any CPU" />
|
||||||
|
</Configurations>
|
||||||
|
<Project Path="Installer/Installer.wixproj">
|
||||||
|
<Platform Solution="*|Any CPU" Project="x64" />
|
||||||
|
<Build Solution="*|Any CPU" Project="true" />
|
||||||
|
</Project>
|
||||||
<Project Path="PamhagenSysCtrl/PamhagenSysCtrl.csproj" />
|
<Project Path="PamhagenSysCtrl/PamhagenSysCtrl.csproj" />
|
||||||
</Solution>
|
</Solution>
|
||||||
|
|||||||
@@ -431,13 +431,13 @@ namespace PamhagenSysCtrl.Helpers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ColorPipesAdjacientToPath(Path path, Brush? color1, bool flowArrows, Brush? color2) {
|
public void ColorPipesAdjacientToPath(Path path, Brush? color1, Brush? color2) {
|
||||||
var color = color1;
|
var color = color1;
|
||||||
var flowPathOffset = 0.0;
|
var flowPathOffset = 0.0;
|
||||||
HashSet<IEdge> visited = [];
|
HashSet<IEdge> visited = [];
|
||||||
foreach (var (edge, node) in path.Hops) {
|
foreach (var (edge, node) in path.Hops) {
|
||||||
edge.Highlight = color1;
|
edge.Highlight = color1;
|
||||||
edge.Flow = flowArrows ? (edge.End == node, flowPathOffset) : null;
|
edge.Flow = color1 == PamhagenBrushes.Green ? (edge.End == node, flowPathOffset) : null;
|
||||||
if (edge.Flow != null) flowPathOffset += edge.FlowLength;
|
if (edge.Flow != null) flowPathOffset += edge.FlowLength;
|
||||||
visited.Add(edge);
|
visited.Add(edge);
|
||||||
if (node is Pump) color = color2;
|
if (node is Pump) color = color2;
|
||||||
|
|||||||
@@ -0,0 +1,155 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Media;
|
||||||
|
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;
|
||||||
|
|
||||||
|
private static readonly Stopwatch Clock = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
private readonly Canvas _layer;
|
||||||
|
private readonly Point[] _path;
|
||||||
|
private Point[] _points = [];
|
||||||
|
private double _length;
|
||||||
|
private double _pathOffset;
|
||||||
|
private bool _isActive;
|
||||||
|
|
||||||
|
public double Length => GetLength(_path[0], _path[1]) + GetLength(_path[1], _path[2]);
|
||||||
|
|
||||||
|
private FlowArrow(Canvas canvas, Point[] path) {
|
||||||
|
_path = path;
|
||||||
|
_layer = new Canvas() {
|
||||||
|
IsHitTestVisible = false,
|
||||||
|
Visibility = Visibility.Collapsed,
|
||||||
|
};
|
||||||
|
_layer.Unloaded += (_, _) => Stop();
|
||||||
|
canvas.Children.Add(_layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FlowArrow Create(Canvas canvas, Line first, Line second) {
|
||||||
|
return new FlowArrow(canvas, [
|
||||||
|
new Point(first.X1, first.Y1),
|
||||||
|
new Point(first.X2, first.Y2),
|
||||||
|
new Point(second.X2, second.Y2),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FlowArrow Create(Canvas canvas, Polyline path) {
|
||||||
|
return new FlowArrow(canvas, [.. path.Points]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update((bool TowardEnd, double PathOffset)? flow) {
|
||||||
|
if (flow == null) {
|
||||||
|
Stop();
|
||||||
|
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;
|
||||||
|
_pathOffset = flow.Value.PathOffset;
|
||||||
|
if (!_isActive) {
|
||||||
|
CompositionTarget.Rendering += OnRendering;
|
||||||
|
_isActive = true;
|
||||||
|
}
|
||||||
|
_layer.Visibility = Visibility.Visible;
|
||||||
|
Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRendering(object? sender, EventArgs args) {
|
||||||
|
Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Render() {
|
||||||
|
var distance = PositiveModulo(Clock.Elapsed.TotalSeconds * Speed - _pathOffset, Spacing);
|
||||||
|
var arrowIndex = 0;
|
||||||
|
while (distance <= _length) {
|
||||||
|
var arrow = GetArrow(arrowIndex++);
|
||||||
|
SetPosition(arrow, distance);
|
||||||
|
arrow.Visibility = Visibility.Visible;
|
||||||
|
distance += Spacing;
|
||||||
|
}
|
||||||
|
while (arrowIndex < _layer.Children.Count) {
|
||||||
|
_layer.Children[arrowIndex++].Visibility = Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Polygon GetArrow(int index) {
|
||||||
|
if (index < _layer.Children.Count) {
|
||||||
|
return (Polygon)_layer.Children[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
var arrow = new Polygon() {
|
||||||
|
Fill = Brushes.Black,
|
||||||
|
IsHitTestVisible = false,
|
||||||
|
Points = [
|
||||||
|
new Point(HalfLength, 0),
|
||||||
|
new Point(-HalfLength, HalfWidth),
|
||||||
|
new Point(-HalfLength, -HalfWidth),
|
||||||
|
],
|
||||||
|
RenderTransform = new MatrixTransform(Matrix.Identity),
|
||||||
|
};
|
||||||
|
_layer.Children.Add(arrow);
|
||||||
|
return arrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
} else {
|
||||||
|
start = _points[1];
|
||||||
|
end = _points[2];
|
||||||
|
segmentDistance = distance - firstLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Stop() {
|
||||||
|
if (_isActive) {
|
||||||
|
CompositionTarget.Rendering -= OnRendering;
|
||||||
|
_isActive = false;
|
||||||
|
}
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Shapes;
|
|
||||||
|
|
||||||
namespace PamhagenSysCtrl.Helpers.Pipeline {
|
|
||||||
internal sealed class FlowArrows {
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
private readonly Canvas _layer;
|
|
||||||
private readonly Point[] _path;
|
|
||||||
private Point[] _points = [];
|
|
||||||
private double _length;
|
|
||||||
private double _pathOffset;
|
|
||||||
private bool _isActive;
|
|
||||||
|
|
||||||
public double Length => GetLength(_path[0], _path[1]) + GetLength(_path[1], _path[2]);
|
|
||||||
|
|
||||||
private FlowArrows(Canvas canvas, Point[] path) {
|
|
||||||
_path = path;
|
|
||||||
_layer = new Canvas() {
|
|
||||||
IsHitTestVisible = false,
|
|
||||||
Visibility = Visibility.Collapsed,
|
|
||||||
};
|
|
||||||
_layer.Unloaded += (_, _) => Stop();
|
|
||||||
canvas.Children.Add(_layer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static FlowArrows Create(Canvas canvas, Line first, Line second) {
|
|
||||||
return new FlowArrows(canvas, [
|
|
||||||
new Point(first.X1, first.Y1),
|
|
||||||
new Point(first.X2, first.Y2),
|
|
||||||
new Point(second.X2, second.Y2),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static FlowArrows Create(Canvas canvas, Polyline path) {
|
|
||||||
return new FlowArrows(canvas, [.. path.Points]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update((bool TowardEnd, double PathOffset)? flow) {
|
|
||||||
if (flow == null) {
|
|
||||||
Stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_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;
|
|
||||||
_isActive = true;
|
|
||||||
}
|
|
||||||
_layer.Visibility = Visibility.Visible;
|
|
||||||
Render();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnRendering(object? sender, EventArgs args) {
|
|
||||||
Render();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Render() {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
while (arrowIndex < _layer.Children.Count) {
|
|
||||||
_layer.Children[arrowIndex++].Visibility = Visibility.Collapsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Polygon GetArrow(int index) {
|
|
||||||
if (index < _layer.Children.Count) {
|
|
||||||
return (Polygon)_layer.Children[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
var arrow = new Polygon() {
|
|
||||||
Fill = new SolidColorBrush(Color.FromArgb(0x60, 0, 0, 0)),
|
|
||||||
IsHitTestVisible = false,
|
|
||||||
Points = [
|
|
||||||
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),
|
|
||||||
};
|
|
||||||
_layer.Children.Add(arrow);
|
|
||||||
return arrow;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetPosition(Polygon arrow, double 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 {
|
|
||||||
double d = distance - firstLength;
|
|
||||||
position = _points[1] + v2 * d;
|
|
||||||
direction = v2;
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
|
||||||
if (_isActive) {
|
|
||||||
CompositionTarget.Rendering -= OnRendering;
|
|
||||||
_isActive = false;
|
|
||||||
}
|
|
||||||
_layer.Visibility = Visibility.Collapsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,13 +12,13 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
|||||||
public bool Orientation { get; set; }
|
public bool Orientation { get; set; }
|
||||||
public Brush? Highlight { get; set; }
|
public Brush? Highlight { get; set; }
|
||||||
public (bool TowardEnd, double PathOffset)? Flow { get; set; }
|
public (bool TowardEnd, double PathOffset)? Flow { get; set; }
|
||||||
public double FlowLength => _flowArrows?.Length ?? 0;
|
public double FlowLength => _flowArrow?.Length ?? 0;
|
||||||
|
|
||||||
private Line? _outer1;
|
private Line? _outer1;
|
||||||
private Line? _outer2;
|
private Line? _outer2;
|
||||||
private Line? _inner1;
|
private Line? _inner1;
|
||||||
private Line? _inner2;
|
private Line? _inner2;
|
||||||
private FlowArrows? _flowArrows;
|
private FlowArrow? _flowArrow;
|
||||||
|
|
||||||
public Inlet(INode start, ISink end, bool orientation = false) {
|
public Inlet(INode start, ISink end, bool orientation = false) {
|
||||||
Start = start;
|
Start = start;
|
||||||
@@ -77,13 +77,13 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
|||||||
canvas.Children.Add(_outer2);
|
canvas.Children.Add(_outer2);
|
||||||
canvas.Children.Add(_inner1);
|
canvas.Children.Add(_inner1);
|
||||||
canvas.Children.Add(_inner2);
|
canvas.Children.Add(_inner2);
|
||||||
_flowArrows = FlowArrows.Create(canvas, _inner1!, _inner2!);
|
_flowArrow = FlowArrow.Create(canvas, _inner1!, _inner2!);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update() {
|
public void Update() {
|
||||||
_inner1?.Stroke = Highlight ?? Brushes.DarkGray;
|
_inner1?.Stroke = Highlight ?? Brushes.DarkGray;
|
||||||
_inner2?.Stroke = Highlight ?? Brushes.DarkGray;
|
_inner2?.Stroke = Highlight ?? Brushes.DarkGray;
|
||||||
_flowArrows?.Update(Flow);
|
_flowArrow?.Update(Highlight == PamhagenBrushes.Green ? Flow : null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
|||||||
public bool Orientation { get; set; }
|
public bool Orientation { get; set; }
|
||||||
public Brush? Highlight { get; set; }
|
public Brush? Highlight { get; set; }
|
||||||
public (bool TowardEnd, double PathOffset)? Flow { get; set; }
|
public (bool TowardEnd, double PathOffset)? Flow { get; set; }
|
||||||
public double FlowLength => _flowArrows?.Length ?? 0;
|
public double FlowLength => _flowArrow?.Length ?? 0;
|
||||||
|
|
||||||
private Polygon? _hopper;
|
private Polygon? _hopper;
|
||||||
private FlowArrows? _flowArrows;
|
private FlowArrow? _flowArrow;
|
||||||
private Line? _outer1;
|
private Line? _outer1;
|
||||||
private Line? _outer2;
|
private Line? _outer2;
|
||||||
private Line? _inner1;
|
private Line? _inner1;
|
||||||
@@ -49,7 +49,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
|||||||
Y2 = y2,
|
Y2 = y2,
|
||||||
StrokeThickness = 10,
|
StrokeThickness = 10,
|
||||||
Stroke = Brushes.Black,
|
Stroke = Brushes.Black,
|
||||||
StrokeStartLineCap = PenLineCap.Round,
|
StrokeStartLineCap = PenLineCap.Flat,
|
||||||
StrokeEndLineCap = PenLineCap.Round,
|
StrokeEndLineCap = PenLineCap.Round,
|
||||||
};
|
};
|
||||||
_inner1 = new Line() {
|
_inner1 = new Line() {
|
||||||
@@ -59,7 +59,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
|||||||
Y2 = y2,
|
Y2 = y2,
|
||||||
StrokeThickness = 6,
|
StrokeThickness = 6,
|
||||||
Stroke = Brushes.DarkGray,
|
Stroke = Brushes.DarkGray,
|
||||||
StrokeStartLineCap = PenLineCap.Round,
|
StrokeStartLineCap = PenLineCap.Flat,
|
||||||
StrokeEndLineCap = PenLineCap.Round,
|
StrokeEndLineCap = PenLineCap.Round,
|
||||||
};
|
};
|
||||||
_outer2 = new Line() {
|
_outer2 = new Line() {
|
||||||
@@ -79,22 +79,22 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
|||||||
Y2 = y3,
|
Y2 = y3,
|
||||||
StrokeThickness = 6,
|
StrokeThickness = 6,
|
||||||
Stroke = Brushes.DarkGray,
|
Stroke = Brushes.DarkGray,
|
||||||
StrokeStartLineCap = PenLineCap.Round,
|
StrokeStartLineCap = PenLineCap.Square,
|
||||||
StrokeEndLineCap = PenLineCap.Round,
|
StrokeEndLineCap = PenLineCap.Square,
|
||||||
};
|
};
|
||||||
canvas.Children.Add(_outer1);
|
canvas.Children.Add(_outer1);
|
||||||
canvas.Children.Add(_outer2);
|
canvas.Children.Add(_outer2);
|
||||||
canvas.Children.Add(_hopper);
|
|
||||||
canvas.Children.Add(_inner1);
|
canvas.Children.Add(_inner1);
|
||||||
canvas.Children.Add(_inner2);
|
canvas.Children.Add(_inner2);
|
||||||
_flowArrows = FlowArrows.Create(canvas, _inner1!, _inner2!);
|
_flowArrow = FlowArrow.Create(canvas, _inner1!, _inner2!);
|
||||||
|
canvas.Children.Add(_hopper);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update() {
|
public void Update() {
|
||||||
_inner1?.Stroke = Highlight ?? Brushes.DarkGray;
|
_inner1?.Stroke = Highlight ?? Brushes.DarkGray;
|
||||||
_inner2?.Stroke = Highlight ?? Brushes.DarkGray;
|
_inner2?.Stroke = Highlight ?? Brushes.DarkGray;
|
||||||
_hopper?.Fill = Highlight ?? Brushes.DarkGray;
|
_hopper?.Fill = Highlight ?? Brushes.DarkGray;
|
||||||
_flowArrows?.Update(Flow);
|
_flowArrow?.Update(Highlight == PamhagenBrushes.Green ? Flow : null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
|||||||
public bool Orientation { get; set; }
|
public bool Orientation { get; set; }
|
||||||
public Brush? Highlight { get; set; }
|
public Brush? Highlight { get; set; }
|
||||||
public (bool TowardEnd, double PathOffset)? Flow { get; set; }
|
public (bool TowardEnd, double PathOffset)? Flow { get; set; }
|
||||||
public double FlowLength => _flowArrows?.Length ?? 0;
|
public double FlowLength => _flowArrow?.Length ?? 0;
|
||||||
|
|
||||||
private Polyline? _outer;
|
private Polyline? _outer;
|
||||||
private Polyline? _inner;
|
private Polyline? _inner;
|
||||||
private FlowArrows? _flowArrows;
|
private FlowArrow? _flowArrow;
|
||||||
|
|
||||||
public Pipe(INode start, INode end, bool orientation = false, bool twoWay = false) {
|
public Pipe(INode start, INode end, bool orientation = false, bool twoWay = false) {
|
||||||
Start = start;
|
Start = start;
|
||||||
@@ -49,12 +49,12 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
|
|||||||
};
|
};
|
||||||
canvas.Children.Add(_outer);
|
canvas.Children.Add(_outer);
|
||||||
canvas.Children.Add(_inner);
|
canvas.Children.Add(_inner);
|
||||||
_flowArrows = FlowArrows.Create(canvas, _inner);
|
_flowArrow = FlowArrow.Create(canvas, _inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update() {
|
public void Update() {
|
||||||
_inner?.Stroke = Highlight ?? Brushes.DarkGray;
|
_inner?.Stroke = Highlight ?? Brushes.DarkGray;
|
||||||
_flowArrows?.Update(Flow);
|
_flowArrow?.Update(Highlight == PamhagenBrushes.Green ? Flow : null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net10.0-windows</TargetFramework>
|
<TargetFramework>net10.0-windows</TargetFramework>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
|
<Product>Pamhagen</Product>
|
||||||
|
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ namespace PamhagenSysCtrl.Windows {
|
|||||||
e.Flow = null;
|
e.Flow = null;
|
||||||
}
|
}
|
||||||
foreach (var p in Graph.SelectedPaths) {
|
foreach (var p in Graph.SelectedPaths) {
|
||||||
Graph.ColorPipesAdjacientToPath(p, PamhagenBrushes.Green, true, PamhagenBrushes.DimOrange);
|
Graph.ColorPipesAdjacientToPath(p, PamhagenBrushes.Green, PamhagenBrushes.DimOrange);
|
||||||
}
|
}
|
||||||
var hover = Graph.GetHover(pos.X, pos.Y);
|
var hover = Graph.GetHover(pos.X, pos.Y);
|
||||||
if (_lastSource != null && (hover.Count > 0 || _path.Count > 0)) {
|
if (_lastSource != null && (hover.Count > 0 || _path.Count > 0)) {
|
||||||
@@ -87,16 +87,17 @@ namespace PamhagenSysCtrl.Windows {
|
|||||||
if (points.Count >= 2) {
|
if (points.Count >= 2) {
|
||||||
var res = Graph.GetPath(points, (n) => n is not ISink && (n is not Valve v || !v.IsLocked));
|
var res = Graph.GetPath(points, (n) => n is not ISink && (n is not Valve v || !v.IsLocked));
|
||||||
if (res is Path path) {
|
if (res is Path path) {
|
||||||
Graph.ColorPipesAdjacientToPath(path, PamhagenBrushes.Green, false, PamhagenBrushes.DimOrange);
|
Graph.ColorPipesAdjacientToPath(path, PamhagenBrushes.Green, PamhagenBrushes.DimOrange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (_lastSource == null && hover.Count > 0 && Graph.SelectedPaths.Any(p => p.Start == hover.First())) {
|
} else if (_lastSource == null && hover.Count > 0 && Graph.SelectedPaths.Any(p => p.Start == hover.First())) {
|
||||||
var path = Graph.SelectedPaths.First(p => p.Start == hover.First());
|
var path = Graph.SelectedPaths.First(p => p.Start == hover.First());
|
||||||
Graph.ColorPipesAdjacientToPath(path, PamhagenBrushes.Red, true, null);
|
Graph.ColorPipesAdjacientToPath(path, PamhagenBrushes.Red, null);
|
||||||
}
|
}
|
||||||
if (_lastSource != null) {
|
if (_lastSource != null) {
|
||||||
foreach (var edge in _lastSource.Outputs) {
|
foreach (var edge in _lastSource.Outputs) {
|
||||||
edge.Highlight = PamhagenBrushes.Green;
|
edge.Highlight = PamhagenBrushes.Green;
|
||||||
|
edge.Flow = (true, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Graph.Update(hover, down);
|
Graph.Update(hover, down);
|
||||||
|
|||||||
Reference in New Issue
Block a user