Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 80802ee8d6 | |||
| 2bc0f2a67c | |||
| 90fd8ab375 |
@@ -2,14 +2,23 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
x:Class="DelaunayTriangulation.App"
|
x:Class="DelaunayTriangulation.App"
|
||||||
xmlns:local="using:DelaunayTriangulation"
|
xmlns:local="using:DelaunayTriangulation"
|
||||||
RequestedThemeVariant="Default">
|
RequestedThemeVariant="Dark">
|
||||||
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
|
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
|
||||||
|
|
||||||
<Application.DataTemplates>
|
<Application.DataTemplates>
|
||||||
<local:ViewLocator/>
|
<local:ViewLocator/>
|
||||||
</Application.DataTemplates>
|
</Application.DataTemplates>
|
||||||
|
|
||||||
|
<Application.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceInclude Source="Themes/ColorPalette.axaml"/>
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Application.Resources>
|
||||||
|
|
||||||
<Application.Styles>
|
<Application.Styles>
|
||||||
<FluentTheme />
|
<FluentTheme />
|
||||||
|
<StyleInclude Source="Themes/Styles.axaml"/>
|
||||||
</Application.Styles>
|
</Application.Styles>
|
||||||
</Application>
|
</Application>
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
<ResourceDictionary
|
||||||
|
xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
|
||||||
|
<ResourceDictionary.ThemeDictionaries>
|
||||||
|
|
||||||
|
<!-- LIGHT -->
|
||||||
|
<ResourceDictionary x:Key="Light">
|
||||||
|
<Color x:Key="C.Bg">#FFF6F7F9</Color>
|
||||||
|
<Color x:Key="C.Surface">#FFFFFFFF</Color>
|
||||||
|
<Color x:Key="C.Text">#FF111827</Color>
|
||||||
|
<Color x:Key="C.TextMuted">#FF6B7280</Color>
|
||||||
|
<Color x:Key="C.Border">#FFE5E7EB</Color>
|
||||||
|
<Color x:Key="C.Accent">#FF2563EB</Color>
|
||||||
|
<Color x:Key="C.Danger">#FFDC2626</Color>
|
||||||
|
|
||||||
|
<Color x:Key="C.Overlay">#14000000</Color>
|
||||||
|
<Color x:Key="C.OverlayBorder">#33000000</Color>
|
||||||
|
<Color x:Key="C.CanvasBg">#66FFFFFF</Color>
|
||||||
|
<Color x:Key="C.Shadow">#33000000</Color>
|
||||||
|
|
||||||
|
<Color x:Key="C.Edge">#FF16A34A</Color>
|
||||||
|
<Color x:Key="C.Circle">#FF6D28D9</Color>
|
||||||
|
<Color x:Key="C.Voronoi">#FFEA580C</Color>
|
||||||
|
<Color x:Key="C.Triangle">#FF2563EB</Color>
|
||||||
|
<Color x:Key="C.PointStroke">#FF111827</Color>
|
||||||
|
|
||||||
|
<SolidColorBrush x:Key="B.Bg" Color="{DynamicResource C.Bg}" />
|
||||||
|
<SolidColorBrush x:Key="B.Surface" Color="{DynamicResource C.Surface}" />
|
||||||
|
<SolidColorBrush x:Key="B.Text" Color="{DynamicResource C.Text}" />
|
||||||
|
<SolidColorBrush x:Key="B.TextMuted" Color="{DynamicResource C.TextMuted}" />
|
||||||
|
<SolidColorBrush x:Key="B.Border" Color="{DynamicResource C.Border}" />
|
||||||
|
<SolidColorBrush x:Key="B.Accent" Color="{DynamicResource C.Accent}" />
|
||||||
|
<SolidColorBrush x:Key="B.Danger" Color="{DynamicResource C.Danger}" />
|
||||||
|
|
||||||
|
<SolidColorBrush x:Key="B.Overlay" Color="{DynamicResource C.Overlay}" />
|
||||||
|
<SolidColorBrush x:Key="B.OverlayBorder" Color="{DynamicResource C.OverlayBorder}" />
|
||||||
|
<SolidColorBrush x:Key="B.CanvasBg" Color="{DynamicResource C.CanvasBg}" />
|
||||||
|
<SolidColorBrush x:Key="B.Shadow" Color="{DynamicResource C.Shadow}" />
|
||||||
|
|
||||||
|
<SolidColorBrush x:Key="B.Edge" Color="{DynamicResource C.Edge}" />
|
||||||
|
<SolidColorBrush x:Key="B.Circle" Color="{DynamicResource C.Circle}" />
|
||||||
|
<SolidColorBrush x:Key="B.Voronoi" Color="{DynamicResource C.Voronoi}" />
|
||||||
|
<SolidColorBrush x:Key="B.Triangle" Color="{DynamicResource C.Triangle}" />
|
||||||
|
<SolidColorBrush x:Key="B.PointStroke" Color="{DynamicResource C.PointStroke}" />
|
||||||
|
</ResourceDictionary>
|
||||||
|
|
||||||
|
<!-- DARK -->
|
||||||
|
<ResourceDictionary x:Key="Dark">
|
||||||
|
<Color x:Key="C.Bg">#FF0B1220</Color>
|
||||||
|
<Color x:Key="C.Surface">#FF111A2E</Color>
|
||||||
|
<Color x:Key="C.Text">#FFE5E7EB</Color>
|
||||||
|
<Color x:Key="C.TextMuted">#FF9CA3AF</Color>
|
||||||
|
<Color x:Key="C.Border">#FF263248</Color>
|
||||||
|
<Color x:Key="C.Accent">#FF60A5FA</Color>
|
||||||
|
<Color x:Key="C.Danger">#FFFB7185</Color>
|
||||||
|
|
||||||
|
<Color x:Key="C.Overlay">#30000000</Color>
|
||||||
|
<Color x:Key="C.OverlayBorder">#20FFFFFF</Color>
|
||||||
|
<Color x:Key="C.CanvasBg">#DD000000</Color>
|
||||||
|
<Color x:Key="C.Shadow">#AA000000</Color>
|
||||||
|
|
||||||
|
<Color x:Key="C.Edge">#FFADFF2F</Color>
|
||||||
|
<Color x:Key="C.Circle">#FF8A2BE2</Color>
|
||||||
|
<Color x:Key="C.Voronoi">#FFFF8C00</Color>
|
||||||
|
<Color x:Key="C.Triangle">#FF6495ED</Color>
|
||||||
|
<Color x:Key="C.PointStroke">#FFFFFFFF</Color>
|
||||||
|
|
||||||
|
<SolidColorBrush x:Key="B.Bg" Color="{DynamicResource C.Bg}" />
|
||||||
|
<SolidColorBrush x:Key="B.Surface" Color="{DynamicResource C.Surface}" />
|
||||||
|
<SolidColorBrush x:Key="B.Text" Color="{DynamicResource C.Text}" />
|
||||||
|
<SolidColorBrush x:Key="B.TextMuted" Color="{DynamicResource C.TextMuted}" />
|
||||||
|
<SolidColorBrush x:Key="B.Border" Color="{DynamicResource C.Border}" />
|
||||||
|
<SolidColorBrush x:Key="B.Accent" Color="{DynamicResource C.Accent}" />
|
||||||
|
<SolidColorBrush x:Key="B.Danger" Color="{DynamicResource C.Danger}" />
|
||||||
|
|
||||||
|
<SolidColorBrush x:Key="B.Overlay" Color="{DynamicResource C.Overlay}" />
|
||||||
|
<SolidColorBrush x:Key="B.OverlayBorder" Color="{DynamicResource C.OverlayBorder}" />
|
||||||
|
<SolidColorBrush x:Key="B.CanvasBg" Color="{DynamicResource C.CanvasBg}" />
|
||||||
|
<SolidColorBrush x:Key="B.Shadow" Color="{DynamicResource C.Shadow}" />
|
||||||
|
|
||||||
|
<SolidColorBrush x:Key="B.Edge" Color="{DynamicResource C.Edge}" />
|
||||||
|
<SolidColorBrush x:Key="B.Circle" Color="{DynamicResource C.Circle}" />
|
||||||
|
<SolidColorBrush x:Key="B.Voronoi" Color="{DynamicResource C.Voronoi}" />
|
||||||
|
<SolidColorBrush x:Key="B.Triangle" Color="{DynamicResource C.Triangle}" />
|
||||||
|
<SolidColorBrush x:Key="B.PointStroke" Color="{DynamicResource C.PointStroke}" />
|
||||||
|
</ResourceDictionary>
|
||||||
|
|
||||||
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<Styles xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
|
||||||
|
<Style Selector="Window">
|
||||||
|
<Setter Property="Background" Value="{DynamicResource B.Bg}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="TextBlock">
|
||||||
|
<Setter Property="Foreground" Value="{DynamicResource B.Text}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Border.card">
|
||||||
|
<Setter Property="Background" Value="{DynamicResource B.Surface}" />
|
||||||
|
<Setter Property="BorderBrush" Value="{DynamicResource B.Border}" />
|
||||||
|
<Setter Property="BorderThickness" Value="1" />
|
||||||
|
<Setter Property="CornerRadius" Value="12" />
|
||||||
|
<Setter Property="Padding" Value="16" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Button">
|
||||||
|
<Setter Property="Background" Value="{DynamicResource B.Surface}" />
|
||||||
|
<Setter Property="Foreground" Value="{DynamicResource B.Text}" />
|
||||||
|
<Setter Property="BorderBrush" Value="{DynamicResource B.Border}" />
|
||||||
|
<Setter Property="BorderThickness" Value="1" />
|
||||||
|
<Setter Property="CornerRadius" Value="10" />
|
||||||
|
<Setter Property="Padding" Value="12,8" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Button.accent">
|
||||||
|
<Setter Property="Background" Value="{DynamicResource B.Accent}" />
|
||||||
|
<Setter Property="Foreground" Value="#FFFFFFFF" />
|
||||||
|
<Setter Property="BorderBrush" Value="{DynamicResource B.Accent}" />
|
||||||
|
</Style>
|
||||||
|
</Styles>
|
||||||
@@ -6,8 +6,10 @@ using System.Globalization;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Avalonia;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Rendering.Composition.Animations;
|
using Avalonia.Rendering.Composition.Animations;
|
||||||
|
using Avalonia.Styling;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using DelaunatorSharp;
|
using DelaunatorSharp;
|
||||||
@@ -36,12 +38,18 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
[ObservableProperty] private bool _doNearestTriangle = false;
|
[ObservableProperty] private bool _doNearestTriangle = false;
|
||||||
[ObservableProperty] private bool _doDelaunayLib = false;
|
[ObservableProperty] private bool _doDelaunayLib = false;
|
||||||
[ObservableProperty] private bool _doBowyerWatson = true;
|
[ObservableProperty] private bool _doBowyerWatson = true;
|
||||||
|
[ObservableProperty] private bool _doDemonstration = false;
|
||||||
|
|
||||||
[ObservableProperty] private int? _generationDelay = 20;
|
[ObservableProperty] private int? _generationDelay = 20;
|
||||||
private CancellationTokenSource? _genCts;
|
private CancellationTokenSource? _genCts;
|
||||||
|
|
||||||
[ObservableProperty] private bool _isGenerationRunning = false;
|
[ObservableProperty] private bool _isGenerationRunning = false;
|
||||||
|
|
||||||
|
[ObservableProperty] private string _switchThemeBtnContent = StandardDarkIcon;
|
||||||
|
|
||||||
|
private const string StandardLightIcon = "\ud83c\udf1e";
|
||||||
|
private const string StandardDarkIcon = "\ud83c\udf1a";
|
||||||
|
|
||||||
public double Width { get; set; } = 1280;
|
public double Width { get; set; } = 1280;
|
||||||
public double Height { get; set; } = 720;
|
public double Height { get; set; } = 720;
|
||||||
|
|
||||||
@@ -56,6 +64,21 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
|
|
||||||
public IAsyncRelayCommand GenerateCommand { get; }
|
public IAsyncRelayCommand GenerateCommand { get; }
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void SwitchTheme()
|
||||||
|
{
|
||||||
|
if(Application.Current!.ActualThemeVariant == ThemeVariant.Light)
|
||||||
|
{
|
||||||
|
Application.Current!.RequestedThemeVariant = ThemeVariant.Dark;
|
||||||
|
SwitchThemeBtnContent = StandardDarkIcon;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Application.Current!.RequestedThemeVariant = ThemeVariant.Light;
|
||||||
|
SwitchThemeBtnContent = StandardLightIcon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// gets distance of a and b edge to calc hypotenuse aka dist of two points
|
// gets distance of a and b edge to calc hypotenuse aka dist of two points
|
||||||
double PointDistance(Geometries.Point p1, Geometries.Point p2) =>
|
double PointDistance(Geometries.Point p1, Geometries.Point p2) =>
|
||||||
Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
|
Math.Sqrt(Math.Pow(p1.X - p2.X, 2) + Math.Pow(p1.Y - p2.Y, 2));
|
||||||
@@ -102,6 +125,8 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
|
|
||||||
async Task GenerateRandomPoints(int count, CancellationToken ct)
|
async Task GenerateRandomPoints(int count, CancellationToken ct)
|
||||||
{
|
{
|
||||||
|
if (PointCount == null) return;
|
||||||
|
|
||||||
bool CheckAdd(Geometries.Point p1, IList<Geometries.Point> p) =>
|
bool CheckAdd(Geometries.Point p1, IList<Geometries.Point> p) =>
|
||||||
!p.Any(x => PointDistance(p1, x) <= MinPointDistance);
|
!p.Any(x => PointDistance(p1, x) <= MinPointDistance);
|
||||||
|
|
||||||
@@ -136,8 +161,6 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
i--;
|
i--;
|
||||||
retry++;
|
retry++;
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Sort(Geometries.PointComparer.Instance);
|
l.Sort(Geometries.PointComparer.Instance);
|
||||||
@@ -542,6 +565,149 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async Task DemonstrationDelaunay(CancellationToken ct)
|
||||||
|
{
|
||||||
|
async Task RunCancellationSafe(Action toRun)
|
||||||
|
{
|
||||||
|
toRun();
|
||||||
|
await DelayAsync(ct);
|
||||||
|
ct.ThrowIfCancellationRequested();
|
||||||
|
}
|
||||||
|
|
||||||
|
// first point
|
||||||
|
var c = new Geometries.Point(Width / 2, Height / 2);
|
||||||
|
await RunCancellationSafe(() => Points.Add(c));
|
||||||
|
|
||||||
|
// build super triangle
|
||||||
|
var t1 = new Geometries.Point(c.X, c.Y - 100);
|
||||||
|
var t2 = new Geometries.Point(c.X - 100, c.Y + 75);
|
||||||
|
var t3 = new Geometries.Point(c.X + 100, c.Y + 75);
|
||||||
|
|
||||||
|
await RunCancellationSafe(() => Points.Add(t1));
|
||||||
|
await RunCancellationSafe(() => Points.Add(t2));
|
||||||
|
await RunCancellationSafe(() => Points.Add(t3));
|
||||||
|
|
||||||
|
// combine Points
|
||||||
|
var e1 = new Geometries.Edge(t1.X, t1.Y, t2.X, t2.Y);
|
||||||
|
var e2 = new Geometries.Edge(t1.X, t1.Y, t3.X, t3.Y);
|
||||||
|
var e3 = new Geometries.Edge(t2.X, t2.Y, t3.X, t3.Y);
|
||||||
|
var e4 = new Geometries.Edge(t1.X, t1.Y, c.X, c.Y);
|
||||||
|
var e5 = new Geometries.Edge(t2.X, t2.Y, c.X, c.Y);
|
||||||
|
var e6 = new Geometries.Edge(t3.X, t3.Y, c.X, c.Y);
|
||||||
|
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e1));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e2));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e3));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e4));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e5));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e6));
|
||||||
|
|
||||||
|
// show circumcircles to ensure delaunay criteria
|
||||||
|
var c1 = new Geometries.Circle(t1, t2, c);
|
||||||
|
var c2 = new Geometries.Circle(t2, t3, c);
|
||||||
|
var c3 = new Geometries.Circle(t1, t3, c);
|
||||||
|
|
||||||
|
await RunCancellationSafe(() => Circles.Add(c1));
|
||||||
|
await RunCancellationSafe(() => Circles.Add(c2));
|
||||||
|
await RunCancellationSafe(() => Circles.Add(c3));
|
||||||
|
|
||||||
|
// add extra point which breaks delaunay criteria
|
||||||
|
var t4 = new Geometries.Point(c.X - 50, c.Y + 35);
|
||||||
|
await RunCancellationSafe(() => Points.Add(t4));
|
||||||
|
|
||||||
|
// Fix triangulation
|
||||||
|
await RunCancellationSafe(() => Circles.Remove(c1));
|
||||||
|
await RunCancellationSafe(() => Circles.Remove(c2));
|
||||||
|
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e1));
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e3));
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e5));
|
||||||
|
|
||||||
|
// add new edges
|
||||||
|
e5 = new Geometries.Edge(t2.X, t2.Y, t4.X, t4.Y);
|
||||||
|
var e7 = new Geometries.Edge(t1.X, t1.Y, t4.X, t4.Y);
|
||||||
|
var e8 = new Geometries.Edge(t3.X, t3.Y, t4.X, t4.Y);
|
||||||
|
var e9 = new Geometries.Edge(c.X, c.Y, t4.X, t4.Y);
|
||||||
|
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e1));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e3));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e5));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e7));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e8));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e9));
|
||||||
|
|
||||||
|
c1 = new Geometries.Circle(t1, t2, t4);
|
||||||
|
c2 = new Geometries.Circle(t2, t4, t3);
|
||||||
|
var c4 = new Geometries.Circle(t1, t4, c);
|
||||||
|
var c5 = new Geometries.Circle(t4, t3, c);
|
||||||
|
|
||||||
|
await RunCancellationSafe(() => Circles.Add(c1));
|
||||||
|
await RunCancellationSafe(() => Circles.Add(c2));
|
||||||
|
await RunCancellationSafe(() => Circles.Add(c4));
|
||||||
|
await RunCancellationSafe(() => Circles.Add(c5));
|
||||||
|
|
||||||
|
// add another point
|
||||||
|
var t5 = new Geometries.Point(c.X + 50, c.Y + 45);
|
||||||
|
await RunCancellationSafe(() => Points.Add(t5));
|
||||||
|
|
||||||
|
await RunCancellationSafe(() => Circles.Remove(c2));
|
||||||
|
await RunCancellationSafe(() => Circles.Remove(c3));
|
||||||
|
await RunCancellationSafe(() => Circles.Remove(c5));
|
||||||
|
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e3));
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e8));
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e6));
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e2));
|
||||||
|
|
||||||
|
e6 = new Geometries.Edge(c.X, c.Y, t5.X, t5.Y);
|
||||||
|
e8 = new Geometries.Edge(t2.X, t2.Y, t5.X, t5.Y);
|
||||||
|
var e10 = new Geometries.Edge(t5.X, t5.Y, t3.X, t3.Y);
|
||||||
|
var e11 = new Geometries.Edge(t5.X, t5.Y, t4.X, t4.Y);
|
||||||
|
var e12 = new Geometries.Edge(t5.X, t5.Y, t1.X, t1.Y);
|
||||||
|
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e3));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e2));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e6));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e8));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e10));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e11));
|
||||||
|
await RunCancellationSafe(() => Edges.Add(e12));
|
||||||
|
|
||||||
|
c2 = new Geometries.Circle(t2, t5, t3);
|
||||||
|
c3 = new Geometries.Circle(t1, t5, t3);
|
||||||
|
c5 = new Geometries.Circle(c, t4, t5);
|
||||||
|
var c6 = new Geometries.Circle(t2, t4, t5);
|
||||||
|
var c7 = new Geometries.Circle(t1, c, t5);
|
||||||
|
|
||||||
|
await RunCancellationSafe(() => Circles.Add(c2));
|
||||||
|
await RunCancellationSafe(() => Circles.Add(c3));
|
||||||
|
await RunCancellationSafe(() => Circles.Add(c5));
|
||||||
|
await RunCancellationSafe(() => Circles.Add(c6));
|
||||||
|
await RunCancellationSafe(() => Circles.Add(c7));
|
||||||
|
|
||||||
|
// remove super triangle
|
||||||
|
await RunCancellationSafe(() => Circles.Remove(c1));
|
||||||
|
await RunCancellationSafe(() => Circles.Remove(c2));
|
||||||
|
await RunCancellationSafe(() => Circles.Remove(c3));
|
||||||
|
await RunCancellationSafe(() => Circles.Remove(c4));
|
||||||
|
await RunCancellationSafe(() => Circles.Remove(c6));
|
||||||
|
await RunCancellationSafe(() => Circles.Remove(c7));
|
||||||
|
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e1));
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e2));
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e3));
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e4));
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e5));
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e7));
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e8));
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e10));
|
||||||
|
await RunCancellationSafe(() => Edges.Remove(e12));
|
||||||
|
|
||||||
|
await RunCancellationSafe(() => Points.Remove(t1));
|
||||||
|
await RunCancellationSafe(() => Points.Remove(t2));
|
||||||
|
await RunCancellationSafe(() => Points.Remove(t3));
|
||||||
|
}
|
||||||
|
|
||||||
public void CancelGeneration() => _genCts?.CancelAsync();
|
public void CancelGeneration() => _genCts?.CancelAsync();
|
||||||
|
|
||||||
private Task DelayAsync(CancellationToken ct) =>
|
private Task DelayAsync(CancellationToken ct) =>
|
||||||
@@ -571,12 +737,14 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
|
|
||||||
IsGenerationRunning = true;
|
IsGenerationRunning = true;
|
||||||
|
|
||||||
await GenerateRandomPoints(PointCount ?? 20, ct);
|
if(!DoDemonstration) await GenerateRandomPoints(PointCount ?? 20, ct);
|
||||||
|
|
||||||
if(DoConnectPoints) await ConnectPoints(ct);
|
if(DoConnectPoints) await ConnectPoints(ct);
|
||||||
else if(DoConnectPointsV2) await ConnectPointsV2(ct);
|
else if(DoConnectPointsV2) await ConnectPointsV2(ct);
|
||||||
else if(DoNearestTriangle) await Triangulate(ct);
|
else if(DoNearestTriangle) await Triangulate(ct);
|
||||||
else if(DoDelaunayLib) await DelaunayTriangulateAsync(ct);
|
else if(DoDelaunayLib) await DelaunayTriangulateAsync(ct);
|
||||||
else if(DoBowyerWatson) await BowyerWatson(ct);
|
else if(DoBowyerWatson) await BowyerWatson(ct);
|
||||||
|
else if (DoDemonstration) await DemonstrationDelaunay(ct);
|
||||||
|
|
||||||
IsGenerationRunning = false;
|
IsGenerationRunning = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
Height="{Binding Height, Mode=TwoWay}"
|
Height="{Binding Height, Mode=TwoWay}"
|
||||||
MinWidth="1200"
|
MinWidth="1200"
|
||||||
MinHeight="700"
|
MinHeight="700"
|
||||||
|
|
||||||
>
|
>
|
||||||
|
|
||||||
<Design.DataContext>
|
<Design.DataContext>
|
||||||
@@ -34,8 +35,8 @@
|
|||||||
<Window.Styles>
|
<Window.Styles>
|
||||||
<Style Selector="Border.InnerCard">
|
<Style Selector="Border.InnerCard">
|
||||||
<Setter Property="CornerRadius" Value="7.5"/>
|
<Setter Property="CornerRadius" Value="7.5"/>
|
||||||
<Setter Property="Background" Value="#30000000"/>
|
<Setter Property="Background" Value="{DynamicResource B.Overlay}"/>
|
||||||
<Setter Property="BorderBrush" Value="#20FFFFFF"/>
|
<Setter Property="BorderBrush" Value="{DynamicResource B.OverlayBorder}"/>
|
||||||
<Setter Property="BorderThickness" Value="2"/>
|
<Setter Property="BorderThickness" Value="2"/>
|
||||||
<Setter Property="Padding" Value="10"/>
|
<Setter Property="Padding" Value="10"/>
|
||||||
<Setter Property="Margin" Value="5"/>
|
<Setter Property="Margin" Value="5"/>
|
||||||
@@ -43,8 +44,8 @@
|
|||||||
</Window.Styles>
|
</Window.Styles>
|
||||||
<Panel>
|
<Panel>
|
||||||
<Grid RowDefinitions="30,*">
|
<Grid RowDefinitions="30,*">
|
||||||
<Border ZIndex="1000" Grid.Row="0" Background="#30000000" PointerPressed="OnTitleBarPointerPressed" DoubleTapped="OnTitleBarDoubleTapped">
|
<Border ZIndex="1000" Grid.Row="0" Background="{DynamicResource B.Overlay}" PointerPressed="OnTitleBarPointerPressed" DoubleTapped="OnTitleBarDoubleTapped">
|
||||||
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Background="Transparent" Foreground="White" Text="Delaunay Triangulation - Timo Niemann"/>
|
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Background="Transparent" Foreground="{DynamicResource B.Text}" Text="Delaunay Triangulation - Timo Niemann"/>
|
||||||
</Border>
|
</Border>
|
||||||
<Grid Grid.Row="1" ZIndex="1000" Margin="20">
|
<Grid Grid.Row="1" ZIndex="1000" Margin="20">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@@ -53,17 +54,17 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Border Classes="InnerCard">
|
<Border Classes="InnerCard">
|
||||||
<Border.Effect>
|
<Border.Effect>
|
||||||
<DropShadowEffect BlurRadius="20" Color="#aa000000" OffsetX="5" OffsetY="5"/>
|
<DropShadowEffect BlurRadius="20" Color="{DynamicResource C.Shadow}" OffsetX="5" OffsetY="5"/>
|
||||||
</Border.Effect>
|
</Border.Effect>
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||||
<Grid RowDefinitions="*, auto">
|
<Grid RowDefinitions="*, auto">
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<Border Classes="InnerCard">
|
<Border Classes="InnerCard">
|
||||||
<TextBlock Text="Delaunay Triangulation" FontSize="18" Foreground="White"/>
|
<TextBlock Text="Delaunay Triangulation" FontSize="18" Foreground="{DynamicResource B.Text}"/>
|
||||||
</Border>
|
</Border>
|
||||||
<Border Classes="InnerCard">
|
<Border Classes="InnerCard">
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<TextBlock Text="Maximal Point Count" Foreground="White"/>
|
<TextBlock Text="Maximal Point Count" Foreground="{DynamicResource B.Text}"/>
|
||||||
<Grid ColumnDefinitions="4*,1*">
|
<Grid ColumnDefinitions="4*,1*">
|
||||||
<Slider Grid.Column="0" Value="{Binding PointCount, Mode=TwoWay}" Margin="5" Minimum="20" Maximum="200"/>
|
<Slider Grid.Column="0" Value="{Binding PointCount, Mode=TwoWay}" Margin="5" Minimum="20" Maximum="200"/>
|
||||||
<NumericUpDown Height="20" Grid.Column="1" ShowButtonSpinner="False" Value="{Binding PointCount, Mode=TwoWay}" Minimum="1" Increment="1" FormatString="F0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
|
<NumericUpDown Height="20" Grid.Column="1" ShowButtonSpinner="False" Value="{Binding PointCount, Mode=TwoWay}" Minimum="1" Increment="1" FormatString="F0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
|
||||||
@@ -72,7 +73,7 @@
|
|||||||
</Border>
|
</Border>
|
||||||
<Border Classes="InnerCard">
|
<Border Classes="InnerCard">
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<TextBlock Text="Minimal Point Distance" Foreground="White"/>
|
<TextBlock Text="Minimal Point Distance" Foreground="{DynamicResource B.Text}"/>
|
||||||
<Grid ColumnDefinitions="4*,1*">
|
<Grid ColumnDefinitions="4*,1*">
|
||||||
<Slider Grid.Column="0" Value="{Binding MinPointDistance, Mode=TwoWay}" Margin="5" Minimum="1" Maximum="10"/>
|
<Slider Grid.Column="0" Value="{Binding MinPointDistance, Mode=TwoWay}" Margin="5" Minimum="1" Maximum="10"/>
|
||||||
<NumericUpDown Height="20" Grid.Column="1" ShowButtonSpinner="False" Value="{Binding MinPointDistance, Mode=TwoWay}" Minimum="1" Increment="1" FormatString="F0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/> </Grid>
|
<NumericUpDown Height="20" Grid.Column="1" ShowButtonSpinner="False" Value="{Binding MinPointDistance, Mode=TwoWay}" Minimum="1" Increment="1" FormatString="F0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/> </Grid>
|
||||||
@@ -80,7 +81,7 @@
|
|||||||
</Border>
|
</Border>
|
||||||
<Border Classes="InnerCard">
|
<Border Classes="InnerCard">
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<TextBlock Text="Genearation Speed" Foreground="White"/>
|
<TextBlock Text="Genearation Speed" Foreground="{DynamicResource B.Text}"/>
|
||||||
<Grid ColumnDefinitions="4*,1*">
|
<Grid ColumnDefinitions="4*,1*">
|
||||||
<Slider Grid.Column="0" Value="{Binding GenerationDelay, Mode=TwoWay}" Margin="5" Minimum="0" Maximum="1000"/>
|
<Slider Grid.Column="0" Value="{Binding GenerationDelay, Mode=TwoWay}" Margin="5" Minimum="0" Maximum="1000"/>
|
||||||
<NumericUpDown Height="20" Grid.Column="1" ShowButtonSpinner="False" Value="{Binding GenerationDelay, Mode=TwoWay}" Minimum="0" Increment="1" FormatString="F0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
|
<NumericUpDown Height="20" Grid.Column="1" ShowButtonSpinner="False" Value="{Binding GenerationDelay, Mode=TwoWay}" Minimum="0" Increment="1" FormatString="F0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
|
||||||
@@ -89,46 +90,46 @@
|
|||||||
</Border>
|
</Border>
|
||||||
<Border Classes="InnerCard">
|
<Border Classes="InnerCard">
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<TextBlock Text="Enabled Visuals:" Foreground="White"/>
|
<TextBlock Text="Enabled Visuals:" Foreground="{DynamicResource B.Text}"/>
|
||||||
<Grid ColumnDefinitions="1*, 1*">
|
<Grid ColumnDefinitions="1*, 1*">
|
||||||
<CheckBox HorizontalAlignment="Left" Content="Points" IsChecked="{Binding PointsVisible}" Foreground="White" Margin="10,0"/>
|
<CheckBox HorizontalAlignment="Left" Content="Points" IsChecked="{Binding PointsVisible}" Foreground="{DynamicResource B.Text}" Margin="10,0"/>
|
||||||
<CheckBox Grid.Column="1" HorizontalAlignment="Left" Content="Convex Hull" IsChecked="{Binding EdgesVisible}" Foreground="White" Margin="10,0"/>
|
<CheckBox Grid.Column="1" HorizontalAlignment="Left" Content="Convex Hull" IsChecked="{Binding EdgesVisible}" Foreground="{DynamicResource B.Text}" Margin="10,0"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid ColumnDefinitions="1*, 1*">
|
<Grid ColumnDefinitions="1*, 1*">
|
||||||
<CheckBox HorizontalAlignment="Left" Content="Circles" IsChecked="{Binding CirclesVisible}" Foreground="White" Margin="10,0"/>
|
<CheckBox HorizontalAlignment="Left" Content="Circles" IsChecked="{Binding CirclesVisible}" Foreground="{DynamicResource B.Text}" Margin="10,0"/>
|
||||||
<CheckBox Grid.Column="1" HorizontalAlignment="Left" Content="Triangles" IsChecked="{Binding TrianglesVisible}" Foreground="White" Margin="10,0"/>
|
<CheckBox Grid.Column="1" HorizontalAlignment="Left" Content="Triangles" IsChecked="{Binding TrianglesVisible}" Foreground="{DynamicResource B.Text}" Margin="10,0"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid ColumnDefinitions="1*, 1*">
|
<Grid ColumnDefinitions="1*, 1*">
|
||||||
<CheckBox HorizontalAlignment="Left" Content="Voronoi" IsChecked="{Binding VoronoiVisible}" Foreground="White" Margin="10,0"/>
|
<CheckBox HorizontalAlignment="Left" Content="Voronoi" IsChecked="{Binding VoronoiVisible}" Foreground="{DynamicResource B.Text}" Margin="10,0"/>
|
||||||
<!-- <CheckBox Content="Triangles" IsChecked="{Binding TrianglesVisible}" Foreground="White" Margin="10,0"/> -->
|
<!-- <CheckBox Content="Triangles" IsChecked="{Binding TrianglesVisible}" Foreground="{DynamicResource B.Overlay}" Margin="10,0"/> -->
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
<Border Classes="InnerCard">
|
<Border Classes="InnerCard">
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<TextBlock Text="Used Algorithm:" Foreground="White"/>
|
<TextBlock Text="Used Algorithm:" Foreground="{DynamicResource B.Text}"/>
|
||||||
<Grid ColumnDefinitions="1*, 1*">
|
<Grid ColumnDefinitions="1*, 1*">
|
||||||
<RadioButton GroupName="Algorithm" HorizontalAlignment="Left" Content="Connect Points" IsChecked="{Binding DoConnectPoints}" Foreground="White" Margin="10,0"/>
|
<RadioButton GroupName="Algorithm" HorizontalAlignment="Left" Content="Connect Points" IsChecked="{Binding DoConnectPoints}" Foreground="{DynamicResource B.Text}" Margin="10,0"/>
|
||||||
<RadioButton Grid.Column="1" GroupName="Algorithm" HorizontalAlignment="Left" Content="ConnectPointsV2" IsChecked="{Binding DoConnectPointsV2}" Foreground="White" Margin="10,0"/>
|
<RadioButton Grid.Column="1" GroupName="Algorithm" HorizontalAlignment="Left" Content="ConnectPointsV2" IsChecked="{Binding DoConnectPointsV2}" Foreground="{DynamicResource B.Text}" Margin="10,0"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid ColumnDefinitions="1*, 1*">
|
<Grid ColumnDefinitions="1*, 1*">
|
||||||
<RadioButton GroupName="Algorithm" HorizontalAlignment="Left" Content="Nearest Triangle" IsChecked="{Binding DoNearestTriangle}" Foreground="White" Margin="10,0"/>
|
<RadioButton GroupName="Algorithm" HorizontalAlignment="Left" Content="Nearest Triangle" IsChecked="{Binding DoNearestTriangle}" Foreground="{DynamicResource B.Text}" Margin="10,0"/>
|
||||||
<RadioButton Grid.Column="1" GroupName="Algorithm" HorizontalAlignment="Left" Content="BowyerWatson" IsChecked="{Binding DoBowyerWatson}" Foreground="White" Margin="10,0"/>
|
<RadioButton Grid.Column="1" GroupName="Algorithm" HorizontalAlignment="Left" Content="BowyerWatson" IsChecked="{Binding DoBowyerWatson}" Foreground="{DynamicResource B.Text}" Margin="10,0"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid ColumnDefinitions="1*, 1*">
|
<Grid ColumnDefinitions="1*, 1*">
|
||||||
<RadioButton GroupName="Algorithm" HorizontalAlignment="Left" Content="Delaunay (Delaunator)" IsChecked="{Binding DoDelaunayLib}" Foreground="White" Margin="10,0"/>
|
<RadioButton GroupName="Algorithm" HorizontalAlignment="Left" Content="Delaunay (Delaunator)" IsChecked="{Binding DoDelaunayLib}" Foreground="{DynamicResource B.Text}" Margin="10,0"/>
|
||||||
<!-- <RadioButton Grid.Column="1" GroupName="Algorithm" HorizontalAlignment="Left" Content="Delaunay (Delaunator)" IsChecked="{Binding DoDelaunayLib}" Foreground="White" Margin="10,0"/> -->
|
<RadioButton Grid.Column="1" GroupName="Algorithm" HorizontalAlignment="Left" Content="Demonstration" IsChecked="{Binding DoDemonstration}" Foreground="{DynamicResource B.Text}" Margin="10,0"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<Button Grid.Row="1" IsVisible="{Binding !IsGenerationRunning}" Foreground="White" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Content="Generate" Command="{Binding GenerateCommand}"/>
|
<Button Grid.Row="1" IsVisible="{Binding !IsGenerationRunning}" Foreground="{DynamicResource B.Text}" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Content="Generate" Command="{Binding GenerateCommand}"/>
|
||||||
<Button Grid.Row="1" IsVisible="{Binding IsGenerationRunning}" Foreground="White" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Content="Cancel" Command="{Binding CancelGeneration}"/>
|
<Button Grid.Row="1" IsVisible="{Binding IsGenerationRunning}" Foreground="{DynamicResource B.Text}" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Content="Cancel" Command="{Binding CancelGeneration}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Canvas Grid.Row="0" Grid.RowSpan="2" x:Name="Scene" Background="#dd000000" ClipToBounds="True" PointerPressed="Scene_OnPointerPressed" PointerMoved="Scene_OnPointerMoved" PointerReleased="Scene_OnPointerReleased" PointerWheelChanged="Scene_OnWheel">
|
<Canvas Grid.Row="0" Grid.RowSpan="2" x:Name="Scene" Background="{DynamicResource B.CanvasBg}" ClipToBounds="True" PointerPressed="Scene_OnPointerPressed" PointerMoved="Scene_OnPointerMoved" PointerReleased="Scene_OnPointerReleased" PointerWheelChanged="Scene_OnWheel">
|
||||||
<Canvas x:Name="SceneContent">
|
<Canvas x:Name="SceneContent">
|
||||||
<Canvas.RenderTransform>
|
<Canvas.RenderTransform>
|
||||||
<TransformGroup>
|
<TransformGroup>
|
||||||
@@ -150,7 +151,7 @@
|
|||||||
<DataTemplate x:DataType="models:Geometries+Edge">
|
<DataTemplate x:DataType="models:Geometries+Edge">
|
||||||
<Line StartPoint="{Binding Start}"
|
<Line StartPoint="{Binding Start}"
|
||||||
EndPoint="{Binding End}"
|
EndPoint="{Binding End}"
|
||||||
Stroke="GreenYellow" StrokeThickness="2"
|
Stroke="{DynamicResource B.Edge}" StrokeThickness="2"
|
||||||
>
|
>
|
||||||
<Line.RenderTransform>
|
<Line.RenderTransform>
|
||||||
<TranslateTransform X="{Binding Start}" Y="{Binding End}"/>
|
<TranslateTransform X="{Binding Start}" Y="{Binding End}"/>
|
||||||
@@ -171,7 +172,7 @@
|
|||||||
</ItemsControl.ItemsPanel>
|
</ItemsControl.ItemsPanel>
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate x:DataType="models:Geometries+Circle">
|
<DataTemplate x:DataType="models:Geometries+Circle">
|
||||||
<Ellipse Stroke="BlueViolet" StrokeThickness="1.5"
|
<Ellipse Stroke="{DynamicResource B.Circle}" StrokeThickness="1.5"
|
||||||
Width="{Binding Diameter}"
|
Width="{Binding Diameter}"
|
||||||
Height="{Binding Diameter}"
|
Height="{Binding Diameter}"
|
||||||
>
|
>
|
||||||
@@ -195,7 +196,7 @@
|
|||||||
<DataTemplate x:DataType="models:Geometries+Edge">
|
<DataTemplate x:DataType="models:Geometries+Edge">
|
||||||
<Line StartPoint="{Binding Start}"
|
<Line StartPoint="{Binding Start}"
|
||||||
EndPoint="{Binding End}"
|
EndPoint="{Binding End}"
|
||||||
Stroke="DarkOrange" StrokeThickness="2"
|
Stroke="{DynamicResource B.Voronoi}" StrokeThickness="2"
|
||||||
>
|
>
|
||||||
<Line.RenderTransform>
|
<Line.RenderTransform>
|
||||||
<TranslateTransform X="{Binding Start}" Y="{Binding End}"/>
|
<TranslateTransform X="{Binding Start}" Y="{Binding End}"/>
|
||||||
@@ -216,7 +217,7 @@
|
|||||||
</ItemsControl.ItemsPanel>
|
</ItemsControl.ItemsPanel>
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate x:DataType="models:Geometries+Point">
|
<DataTemplate x:DataType="models:Geometries+Point">
|
||||||
<Ellipse Fill="Transparent" Stroke="White" StrokeThickness="1"
|
<Ellipse Fill="Transparent" Stroke="{DynamicResource B.PointStroke}" StrokeThickness="1"
|
||||||
Width="{Binding Size}"
|
Width="{Binding Size}"
|
||||||
Height="{Binding Size}"
|
Height="{Binding Size}"
|
||||||
>
|
>
|
||||||
@@ -240,7 +241,7 @@
|
|||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate x:DataType="models:Geometries+Triangle">
|
<DataTemplate x:DataType="models:Geometries+Triangle">
|
||||||
<Canvas>
|
<Canvas>
|
||||||
<Polygon Points="{Binding Vertices}" Stroke="CornflowerBlue" StrokeThickness="1" Fill="Transparent"/>
|
<Polygon Points="{Binding Vertices}" Stroke="{DynamicResource B.Triangle}" StrokeThickness="1" Fill="Transparent"/>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
@@ -248,5 +249,6 @@
|
|||||||
</Canvas>
|
</Canvas>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Button HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="15" Command="{Binding SwitchThemeCommand}" Content="{Binding SwitchThemeBtnContent}" Width="50" Height="50" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
|
||||||
</Panel>
|
</Panel>
|
||||||
</Window>
|
</Window>
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# DelaunayTriangulation
|
||||||
|
|
||||||
|
`DelaunayTriangulation` ist eine interaktive Desktop-Anwendung zur Visualisierung der Delaunay-Triangulierung auf zufallsgenerierten Punktmengen. Ersichtlich sind ebenfalls die Umkreise, das Voronoi-Diagramm und die konvexe Hülle.
|
||||||
|
|
||||||
|
## Überblick
|
||||||
|
|
||||||
|
- Avalonia-Desktop-App auf Basis von .NET 10, C#
|
||||||
|
- Visualisierung mehrerer Triangulations- und Vergleichsmodi
|
||||||
|
- Konfigurierbare Punktanzahl, Mindestabstand und Animationsgeschwindigkeit
|
||||||
|
- Ein- und ausblendbare Darstellung für Punkte, Dreiecke, Umkreise, Voronoi-Diagramm und konvexe Hülle
|
||||||
|
- Pan und Zoom direkt im Zeichenbereich
|
||||||
|
- Abbruch laufender Generierung und Umschalten zwischen hellem und dunklem Theme
|
||||||
|
|
||||||
|
## Enthaltene Modi
|
||||||
|
|
||||||
|
- `BowyerWatson`: eigene inkrementelle Delaunay-Implementierung; erzeugt zusätzlich Umkreise, Voronoi-Diagramm und konvexe Hülle
|
||||||
|
- `Delaunay (Delaunator)`: bibliotheksgestützter Vergleichsmodus mit `Delaunator`
|
||||||
|
- `Demonstration`: feste, didaktische Schrittfolge zur Veranschaulichung des Delaunay-Kriteriums
|
||||||
|
- `Connect Points`: verbindet Punkte sukzessive anhand lokaler Nachbarschaft
|
||||||
|
- `ConnectPointsV2`: verbindet Punktpaare vollständig
|
||||||
|
- `Nearest Triangle`: einfacher Triangulationsansatz als Vergleichsmodus
|
||||||
|
|
||||||
|
Die letzten drei Varianten sind eher experimentell und dienen primär dem visuellen Vergleich mit den eigentlichen Delaunay-Modi.
|
||||||
|
|
||||||
|
## Bedienung
|
||||||
|
|
||||||
|
1. Punktanzahl, Mindestabstand und Generierungsverzögerung einstellen.
|
||||||
|
2. Sichtbare Ebenen im linken Panel auswählen.
|
||||||
|
3. Einen Algorithmus bzw. Modus auswählen oder Standardauswahl belassen.
|
||||||
|
4. `Generate` ausführen, mit `Cancel` abbrechbar.
|
||||||
|
5. Mit dem Mausrad zoomen und mit gedrückter linker Maustaste im Canvas verschieben.
|
||||||
|
|
||||||
|
## Relevante Dateien
|
||||||
|
|
||||||
|
- `DelaunayTriangulation/ViewModels/MainWindowViewModel.cs`: Generierung, Algorithmen und Visualisierungslogik
|
||||||
|
- `DelaunayTriangulation/Views/MainWindow.axaml`: Oberfläche und Steuerelemente
|
||||||
|
- `DelaunayTriangulation/Views/MainWindow.axaml.cs`: Pan- und Zoom-Verhalten
|
||||||
|
- `DelaunayTriangulation/Models/Geometries.cs`: Geometrieklassen für Punkte, Kanten, Kreise und Dreiecke
|
||||||
Reference in New Issue
Block a user