Initial
This commit is contained in:
Generated
+15
@@ -0,0 +1,15 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Rider ignored files
|
||||||
|
/modules.xml
|
||||||
|
/contentModel.xml
|
||||||
|
/projectSettingsUpdater.xml
|
||||||
|
/.idea.MCCAD.iml
|
||||||
|
# Ignored default folder with query files
|
||||||
|
/queries/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
Generated
+12
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="AvaloniaProject">
|
||||||
|
<option name="projectPerEditor">
|
||||||
|
<map>
|
||||||
|
<entry key="MCCAD/App.axaml" value="MCCAD/MCCAD.csproj" />
|
||||||
|
<entry key="MCCAD/Views/MainWindow.axaml" value="MCCAD/MCCAD.csproj" />
|
||||||
|
<entry key="MCCAD/Views/PositiionControl.axaml" value="MCCAD/MCCAD.csproj" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+8
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="UserContentModel">
|
||||||
|
<attachedFolders />
|
||||||
|
<explicitIncludes />
|
||||||
|
<explicitExcludes />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<Solution>
|
||||||
|
<Project Path="MCCAD/MCCAD.csproj" />
|
||||||
|
</Solution>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<Application xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
x:Class="MCCAD.App"
|
||||||
|
xmlns:local="using:MCCAD"
|
||||||
|
RequestedThemeVariant="Light">
|
||||||
|
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
|
||||||
|
|
||||||
|
<Application.DataTemplates>
|
||||||
|
<local:ViewLocator/>
|
||||||
|
</Application.DataTemplates>
|
||||||
|
|
||||||
|
<Application.Styles>
|
||||||
|
<FluentTheme />
|
||||||
|
</Application.Styles>
|
||||||
|
</Application>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
using MCCAD.ViewModels;
|
||||||
|
using MCCAD.Views;
|
||||||
|
|
||||||
|
namespace MCCAD;
|
||||||
|
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnFrameworkInitializationCompleted()
|
||||||
|
{
|
||||||
|
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||||
|
{
|
||||||
|
desktop.MainWindow = new MainWindow
|
||||||
|
{
|
||||||
|
DataContext = new MainWindowViewModel(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnFrameworkInitializationCompleted();
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 172 KiB |
@@ -0,0 +1,26 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
|
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<AvaloniaResource Include="Assets\**"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Avalonia" Version="11.3.13" />
|
||||||
|
<PackageReference Include="Avalonia.Desktop" Version="11.3.13" />
|
||||||
|
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.13" />
|
||||||
|
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.13" />
|
||||||
|
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||||
|
<PackageReference Include="Avalonia.Diagnostics" Version="11.3.13">
|
||||||
|
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
||||||
|
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="ReactiveUI.Avalonia" Version="11.4.12" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace MCCAD.Models;
|
||||||
|
|
||||||
|
public struct HPoint
|
||||||
|
{
|
||||||
|
|
||||||
|
public static readonly HPoint Zero = new HPoint(0, 0);
|
||||||
|
public double X, Y;
|
||||||
|
|
||||||
|
public HPoint(double x, double y)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
|
||||||
|
Y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HPoint operator +(HPoint p1, HPoint p2) => new HPoint(p1.X + p2.X, p1.Y + p2.Y);
|
||||||
|
public static HPoint operator -(HPoint p1, HPoint p2) => new HPoint(p1.X - p2.X, p1.Y - p2.Y);
|
||||||
|
public static HPoint operator *(HPoint p1, double k) => new HPoint(p1.X * k, p1.Y * k);
|
||||||
|
|
||||||
|
public void Round()
|
||||||
|
{
|
||||||
|
X = Math.Round(X);
|
||||||
|
Y = Math.Round(Y);
|
||||||
|
}
|
||||||
|
public static HPoint Vector(double angle)
|
||||||
|
{
|
||||||
|
return new HPoint(Math.Cos(angle), Math.Sin(angle));
|
||||||
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"X:{Math.Round(X, 3)}; Y:{Math.Round(Y, 3)}";
|
||||||
|
}
|
||||||
|
public IntPoint ToIntPoint()
|
||||||
|
{
|
||||||
|
var ret = new IntPoint();
|
||||||
|
ret.X = (int)Math.Round(X);
|
||||||
|
ret.Y = (int)Math.Round(Y);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
public double Lenght => Math.Sqrt(X * X + Y * Y);
|
||||||
|
public HPoint Resuffled() => new HPoint(Y, X);
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct IntPoint
|
||||||
|
{
|
||||||
|
public int X;
|
||||||
|
public int Y;
|
||||||
|
|
||||||
|
public int XPos { get => X; set => X = value; }
|
||||||
|
|
||||||
|
public IntPoint(int x, int y)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntPoint operator +(IntPoint x, IntPoint y)
|
||||||
|
{
|
||||||
|
return new IntPoint(x.X + y.X, x.Y + y.Y);
|
||||||
|
}
|
||||||
|
public static IntPoint operator -(IntPoint x, IntPoint y)
|
||||||
|
{
|
||||||
|
return new IntPoint(x.X - y.X, x.Y - y.Y);
|
||||||
|
}
|
||||||
|
public static bool operator ==(IntPoint x, IntPoint y) => x.X == y.X && x.Y == y.Y;
|
||||||
|
public static bool operator != (IntPoint x, IntPoint y) => x.X != y.X || x.Y != y.Y;
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"X:{X}; Y:{Y}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace MCCAD.Models;
|
||||||
|
|
||||||
|
class Line
|
||||||
|
{
|
||||||
|
public HPoint from;
|
||||||
|
public HPoint to;
|
||||||
|
public Line(HPoint start, HPoint end)
|
||||||
|
{
|
||||||
|
from = start;
|
||||||
|
to = end;
|
||||||
|
}
|
||||||
|
public List<IntPoint> GetPixels()
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"Line started");
|
||||||
|
var shape = new List<HPoint>();
|
||||||
|
HPoint vector = to - from;
|
||||||
|
if (Math.Abs(vector.X) >= Math.Abs(vector.Y))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Math.Abs(vector.X); i++)
|
||||||
|
{
|
||||||
|
var k = i / Math.Abs(vector.X);
|
||||||
|
var currentPoint = vector * k;
|
||||||
|
shape.Add(currentPoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i <= Math.Abs(vector.Y); i++)
|
||||||
|
{
|
||||||
|
var k = i / Math.Abs(vector.Y);
|
||||||
|
var currentPoint = vector * k;
|
||||||
|
shape.Add(currentPoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shape = shape.Select(i => i + from).ToList();
|
||||||
|
shape.ForEach(i => Debug.WriteLine($"{i} -> {i.ToIntPoint()}"));
|
||||||
|
var pts = shape.Select(i => i.ToIntPoint()).ToList();
|
||||||
|
return pts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<IntPoint> GetPixelsTrign(double angle, double len)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"Line {angle} rads started");
|
||||||
|
|
||||||
|
var shape = new List<HPoint>();
|
||||||
|
var s = Math.Sin(angle);
|
||||||
|
var c = Math.Cos(angle);
|
||||||
|
var tg = s / c;
|
||||||
|
var ctg = c / s;
|
||||||
|
var until = Math.Max(s, c) * len;
|
||||||
|
var k = Math.Min(tg, ctg);
|
||||||
|
var range = Enumerable.Range(0, (int)until);
|
||||||
|
foreach (var i in range)
|
||||||
|
{
|
||||||
|
shape.Add(new HPoint(i, i * Math.Min(s, c)));
|
||||||
|
}
|
||||||
|
if (s > c)
|
||||||
|
shape = shape.Select(i => i.Resuffled()).ToList();
|
||||||
|
shape.ForEach(i => Debug.WriteLine($"{i} -> {i.ToIntPoint()}"));
|
||||||
|
var pix = shape.Select(i => i.ToIntPoint()).ToList();
|
||||||
|
return pix;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using ReactiveUI.Avalonia;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MCCAD;
|
||||||
|
|
||||||
|
sealed class Program
|
||||||
|
{
|
||||||
|
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||||
|
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||||
|
// yet and stuff might break.
|
||||||
|
[STAThread]
|
||||||
|
public static void Main(string[] args) => BuildAvaloniaApp()
|
||||||
|
.StartWithClassicDesktopLifetime(args);
|
||||||
|
|
||||||
|
// Avalonia configuration, don't remove; also used by visual designer.
|
||||||
|
public static AppBuilder BuildAvaloniaApp()
|
||||||
|
=> AppBuilder.Configure<App>()
|
||||||
|
.UsePlatformDetect()
|
||||||
|
.WithInterFont()
|
||||||
|
.LogToTrace()
|
||||||
|
.UseReactiveUI(i => { });
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Templates;
|
||||||
|
using MCCAD.ViewModels;
|
||||||
|
|
||||||
|
namespace MCCAD;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Given a view model, returns the corresponding view if possible.
|
||||||
|
/// </summary>
|
||||||
|
[RequiresUnreferencedCode(
|
||||||
|
"Default implementation of ViewLocator involves reflection which may be trimmed away.",
|
||||||
|
Url = "https://docs.avaloniaui.net/docs/concepts/view-locator")]
|
||||||
|
public class ViewLocator : IDataTemplate
|
||||||
|
{
|
||||||
|
public Control? Build(object? param)
|
||||||
|
{
|
||||||
|
if (param is null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
|
||||||
|
var type = Type.GetType(name);
|
||||||
|
|
||||||
|
if (type != null)
|
||||||
|
{
|
||||||
|
return (Control)Activator.CreateInstance(type)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TextBlock { Text = "Not Found: " + name };
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Match(object? data)
|
||||||
|
{
|
||||||
|
return data is ViewModelBase;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,308 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Numerics;
|
||||||
|
using MCCAD.Models;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace MCCAD.ViewModels;
|
||||||
|
|
||||||
|
public delegate void ShemeUpdate(List<IntPoint> points, IFigureView view);
|
||||||
|
|
||||||
|
public delegate void ListUpdate();
|
||||||
|
|
||||||
|
public interface IFigureView
|
||||||
|
{
|
||||||
|
void Rebuild();
|
||||||
|
public event ShemeUpdate OnNewSheme;
|
||||||
|
PositionVM Position { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LineView : ReactiveObject, IFigureView
|
||||||
|
{
|
||||||
|
private static int _counter = 1;
|
||||||
|
|
||||||
|
public LineView () {
|
||||||
|
Position = new PositionVM
|
||||||
|
{
|
||||||
|
Chanded = Rebuild
|
||||||
|
};
|
||||||
|
Name = "Line " + _counter++;
|
||||||
|
}
|
||||||
|
public event ShemeUpdate OnNewSheme;
|
||||||
|
public PositionVM Position { get; set; } = new ();
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
private double angle = 45;
|
||||||
|
private int lenght = 10;
|
||||||
|
|
||||||
|
public int Lenght
|
||||||
|
{
|
||||||
|
get => lenght;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref lenght, value);
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Angle
|
||||||
|
{
|
||||||
|
get => (int)angle;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref angle, value);
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Rebuild()
|
||||||
|
{
|
||||||
|
var endPoint = HPoint.Vector(angle == 90 ? Math.PI / 2 : angle / 360 * Math.Tau) * lenght;
|
||||||
|
|
||||||
|
Line line = new Line(HPoint.Zero, endPoint);
|
||||||
|
var shape = line.GetPixels();
|
||||||
|
shape = shape.Select(i => new IntPoint(i.X, -i.Y)).ToList();
|
||||||
|
var yMove = shape.Select(p => p.Y).Min();
|
||||||
|
shape = shape.Select(p => new IntPoint(p.X, p.Y - yMove)).ToList();
|
||||||
|
OnNewSheme.Invoke(shape, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PolygonView : ReactiveObject, IFigureView
|
||||||
|
{
|
||||||
|
public event ShemeUpdate OnNewSheme;
|
||||||
|
public PositionVM Position { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
private int corners = 3;
|
||||||
|
private int radius = 5;
|
||||||
|
private int rotate;
|
||||||
|
|
||||||
|
private static int _counter = 1;
|
||||||
|
|
||||||
|
public PolygonView() {
|
||||||
|
Position = new PositionVM
|
||||||
|
{
|
||||||
|
Chanded = Rebuild
|
||||||
|
};
|
||||||
|
Name = "Polygon " + _counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Rotate
|
||||||
|
{
|
||||||
|
get { return rotate; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref rotate, value);
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Radius
|
||||||
|
{
|
||||||
|
get { return radius; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref radius, value);
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Corners
|
||||||
|
{
|
||||||
|
get { return corners; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref corners, value);
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Rebuild()
|
||||||
|
{
|
||||||
|
List<IntPoint> shape = new List<IntPoint>();
|
||||||
|
|
||||||
|
void DrawFromTo(HPoint s, HPoint e)
|
||||||
|
{
|
||||||
|
var line = new Line(s, e);
|
||||||
|
|
||||||
|
var linePixs = line.GetPixels();
|
||||||
|
shape.AddRange(linePixs);
|
||||||
|
}
|
||||||
|
|
||||||
|
var len = radius - 1;
|
||||||
|
double alpha = Math.Tau / corners;
|
||||||
|
var start = new HPoint();
|
||||||
|
for (int i = 0; i < corners; i++)
|
||||||
|
{
|
||||||
|
double a = alpha * i;
|
||||||
|
var vec = HPoint.Vector(a) * len + start;
|
||||||
|
vec.Round();
|
||||||
|
DrawFromTo(start, vec);
|
||||||
|
start = vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
shape = shape.Distinct().ToList();
|
||||||
|
var xMove = shape.Select(p => p.X).Min();
|
||||||
|
var yMove = shape.Select(p => p.Y).Min();
|
||||||
|
shape = shape.Select(p => new IntPoint(p.X - xMove, p.Y - yMove)).ToList();
|
||||||
|
//var line = new Line(pts[0], pts[1]);
|
||||||
|
//shape.AddRange(line.GetPixels());
|
||||||
|
//line = new Line(pts[1], pts[2]);
|
||||||
|
//shape.AddRange(line.GetPixels());
|
||||||
|
//line = new Line(pts[2], pts[0]);
|
||||||
|
//shape.AddRange(line.GetPixels());
|
||||||
|
//LinkedList<HPoint> vecs = new LinkedList<HPoint>(pts);
|
||||||
|
//var start = vecs.First;
|
||||||
|
//while (null != start.Next)
|
||||||
|
//{
|
||||||
|
// var end = start.Next.Value;
|
||||||
|
// DrawFromTo(start.Value, end);
|
||||||
|
// start = start.Next;
|
||||||
|
//}
|
||||||
|
//DrawFromTo(vecs.First.Value, vecs.Last.Value);
|
||||||
|
OnNewSheme.Invoke(shape, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OvalView : ReactiveObject, IFigureView
|
||||||
|
{
|
||||||
|
int width = 10;
|
||||||
|
int heigh = 10;
|
||||||
|
int top;
|
||||||
|
int bottom = 10;
|
||||||
|
int left = 0;
|
||||||
|
int right = 10;
|
||||||
|
|
||||||
|
public int Width
|
||||||
|
{
|
||||||
|
get => width;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref width, value);
|
||||||
|
if (width < right)
|
||||||
|
right = width;
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Heigth
|
||||||
|
{
|
||||||
|
get => heigh;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref heigh, value);
|
||||||
|
if (bottom > heigh)
|
||||||
|
bottom = heigh;
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int TopLimit
|
||||||
|
{
|
||||||
|
get => top;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref top, value);
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int BottomLimit
|
||||||
|
{
|
||||||
|
get => bottom;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref bottom, value);
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int LeftLimit
|
||||||
|
{
|
||||||
|
get => left;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref left, value);
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int RightLimit
|
||||||
|
{
|
||||||
|
get => right;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref right, value);
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public event ShemeUpdate OnNewSheme;
|
||||||
|
public PositionVM Position { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public double NormalizedLenth(double x, double y)
|
||||||
|
{
|
||||||
|
var hWidth = width / 2;
|
||||||
|
var hHeith = heigh / 2;
|
||||||
|
return new Vector2((float)(x / hWidth), (float)(y / hHeith)).Length();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int _counter = 1;
|
||||||
|
|
||||||
|
public OvalView()
|
||||||
|
{
|
||||||
|
Position = new PositionVM
|
||||||
|
{
|
||||||
|
Chanded = Rebuild
|
||||||
|
};
|
||||||
|
Name = "Oval " + _counter++;
|
||||||
|
}
|
||||||
|
public void Rebuild()
|
||||||
|
{
|
||||||
|
int RoundToInt(double value) => (int)Math.Round(value);
|
||||||
|
var shape = new List<IntPoint>();
|
||||||
|
var halfWidth = RoundToInt(width / 2);
|
||||||
|
var halfHeight = RoundToInt(heigh / 2);
|
||||||
|
List<int> yRange = Enumerable.Range(-halfHeight, heigh).ToList();
|
||||||
|
var xRange = Enumerable.Range(-halfWidth, width).ToList();
|
||||||
|
|
||||||
|
void addNormalized(int x, int y)
|
||||||
|
{
|
||||||
|
shape.Add(new IntPoint(x + RoundToInt(halfWidth), y + RoundToInt(halfHeight)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool evenWidth = width % 2 == 0;
|
||||||
|
bool evenHeight = heigh % 2 == 0;
|
||||||
|
int move = evenHeight ? 1 : 0;
|
||||||
|
int maxH = halfHeight - move;
|
||||||
|
foreach (var x in xRange)
|
||||||
|
{
|
||||||
|
double lX = x;
|
||||||
|
lX = x > 0 && evenWidth ? x + 1 : x;
|
||||||
|
int y = (int)Math.Ceiling(Math.Sqrt(1 - Math.Pow(lX / (double)halfWidth, 2)) * halfHeight);
|
||||||
|
shape.Add(new IntPoint(x, y - move));
|
||||||
|
shape.Add(new IntPoint(x, -y));
|
||||||
|
yRange.Remove(y - move);
|
||||||
|
yRange.Remove(-y);
|
||||||
|
}
|
||||||
|
|
||||||
|
move = width % 2 == 0 ? 1 : 0;
|
||||||
|
foreach (var y in yRange)
|
||||||
|
{
|
||||||
|
double lY = y;
|
||||||
|
lY = y > 0 && evenHeight ? y + 1 : y;
|
||||||
|
int x = (int)Math.Ceiling(Math.Sqrt(1 - Math.Pow(lY / (double)halfHeight, 2)) * halfWidth);
|
||||||
|
shape.Add(new IntPoint(x - move, y));
|
||||||
|
shape.Add(new IntPoint(-x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxW = halfWidth - move;
|
||||||
|
shape = shape.Select(i => new IntPoint(i.X + halfWidth, i.Y + halfHeight)).ToList();
|
||||||
|
shape = shape.Where(i => i.Y >= top && i.Y <= bottom && i.X <= right && i.X >= left).ToList();
|
||||||
|
OnNewSheme?.Invoke(shape, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace MCCAD.ViewModels;
|
||||||
|
|
||||||
|
public class MainWindowViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
private OvalView _ov;
|
||||||
|
private PolygonView _pv;
|
||||||
|
private LineView _lv;
|
||||||
|
|
||||||
|
public OvalView Ov
|
||||||
|
{
|
||||||
|
get => _ov;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _ov, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PolygonView Pv
|
||||||
|
{
|
||||||
|
get => _pv;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _pv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineView Lv
|
||||||
|
{
|
||||||
|
get => _lv;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _lv, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int A { get; set; }
|
||||||
|
public string Greeting { get; set; }
|
||||||
|
|
||||||
|
public ObservableCollection<IFigureView> Figures { get; set; } = [];
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace MCCAD.ViewModels;
|
||||||
|
|
||||||
|
public class PositionVM : ReactiveObject
|
||||||
|
{
|
||||||
|
private int _x;
|
||||||
|
private int _y;
|
||||||
|
|
||||||
|
public int X
|
||||||
|
{
|
||||||
|
get => _x;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref _x, value);
|
||||||
|
Chanded?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Y
|
||||||
|
{
|
||||||
|
get => _y;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.RaiseAndSetIfChanged(ref _y, value);
|
||||||
|
Chanded?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action Chanded;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace MCCAD.ViewModels;
|
||||||
|
|
||||||
|
public abstract class ViewModelBase : ReactiveObject
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
<Window xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:vm="using:MCCAD.ViewModels"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
xmlns:mcd="using:MCCAD.ViewModels"
|
||||||
|
xmlns:views="clr-namespace:MCCAD.Views"
|
||||||
|
x:Class="MCCAD.Views.MainWindow"
|
||||||
|
x:DataType="vm:MainWindowViewModel"
|
||||||
|
Icon="/Assets/avalonia-logo.ico"
|
||||||
|
Title="MCCAD">
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="250" />
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition Width="250"></ColumnDefinition>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition />
|
||||||
|
<RowDefinition Height="125" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<StackPanel Margin="5,5,5,5">
|
||||||
|
<HyperlinkButton Click="CreateShape" Tag="Ov">Новый элипс</HyperlinkButton>
|
||||||
|
<HyperlinkButton Click="CreateShape" Tag="Pv">Новый многоугольник</HyperlinkButton>
|
||||||
|
<HyperlinkButton Click="CreateShape" Tag="Lv">Новая линия</HyperlinkButton>
|
||||||
|
<Panel Name="ToolsTab" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||||
|
<ScrollViewer DataContext="{Binding Path=Ov}" IsVisible="False">
|
||||||
|
<StackPanel>
|
||||||
|
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
||||||
|
Header="Размеры">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock Text="Ширина" />
|
||||||
|
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Top">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Slider Minimum="3" Maximum="50" VerticalAlignment="Center"
|
||||||
|
Value="{Binding Width}" />
|
||||||
|
<TextBox x:Name="WStr" Grid.Column="1" Margin="3" MaxLength="4"
|
||||||
|
Text="{Binding Width}" />
|
||||||
|
</Grid>
|
||||||
|
<TextBlock Text="Высота" />
|
||||||
|
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Top">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Slider Minimum="3" Maximum="50" VerticalAlignment="Center"
|
||||||
|
Value="{Binding Heigth}" />
|
||||||
|
<TextBox x:Name="HStr" Grid.Column="1" Margin="3" MaxLength="4"
|
||||||
|
Text="{Binding Heigth}" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</Expander>
|
||||||
|
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
||||||
|
Header="Ограничения">
|
||||||
|
<DockPanel LastChildFill="False" Name="LimitsDP">
|
||||||
|
<StackPanel DockPanel.Dock="Top">
|
||||||
|
<Slider Minimum="0" Maximum="{Binding Heigth}" Width="85" Margin="3"
|
||||||
|
Value="{Binding TopLimit}" />
|
||||||
|
<TextBlock HorizontalAlignment="Center" Name="TopTB"
|
||||||
|
Text="{Binding TopLimit, StringFormat={}от {0}}" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel DockPanel.Dock="Bottom">
|
||||||
|
<Slider Minimum="0" Maximum="{Binding Heigth}" Width="85" Margin="3"
|
||||||
|
Value="{Binding BottomLimit}" />
|
||||||
|
<TextBlock HorizontalAlignment="Center" Name="BotTB"
|
||||||
|
Text="{Binding BottomLimit, StringFormat={}до {0}}" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel DockPanel.Dock="Left">
|
||||||
|
<Slider Minimum="0" Maximum="{Binding Width}" Width="85" Margin="3"
|
||||||
|
Value="{Binding LeftLimit}" />
|
||||||
|
<TextBlock HorizontalAlignment="Center" Name="LeftTB"
|
||||||
|
Text="{Binding LeftLimit, StringFormat={}от {0}}" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel DockPanel.Dock="Right" Width="85">
|
||||||
|
<Slider Minimum="0" Maximum="{Binding Width}" Width="85" Margin="3"
|
||||||
|
Value="{Binding RightLimit}" />
|
||||||
|
<TextBlock HorizontalAlignment="Center" Name="RightTB"
|
||||||
|
Text="{Binding RightLimit, StringFormat={}до {0}}" />
|
||||||
|
</StackPanel>
|
||||||
|
</DockPanel>
|
||||||
|
</Expander>
|
||||||
|
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
||||||
|
Header="Расположение">
|
||||||
|
<views:PositionControl DataContext="{Binding Position}" />
|
||||||
|
</Expander>
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
<ScrollViewer Margin="5" DataContext="{Binding Pv}" IsVisible="False">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock Text="Сторона" />
|
||||||
|
<Slider Minimum="5" Maximum="100" VerticalAlignment="Center" Value="{Binding Radius}" />
|
||||||
|
<TextBlock Text="{Binding Radius}" />
|
||||||
|
<TextBlock Text="Углы" />
|
||||||
|
<Slider Minimum="3" Maximum="10" VerticalAlignment="Center" Value="{Binding Corners}" />
|
||||||
|
<TextBlock Text="{Binding Corners}" />
|
||||||
|
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
||||||
|
Header="Расположение">
|
||||||
|
<views:PositionControl DataContext="{Binding Position}" />
|
||||||
|
</Expander>
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
<StackPanel Margin="5" DataContext="{Binding Lv}" IsVisible="False">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock>Угол</TextBlock>
|
||||||
|
<Slider Value="{Binding Angle}" Minimum="0" Maximum="90" />
|
||||||
|
<TextBlock Text="{Binding Angle}" />
|
||||||
|
<TextBlock>Длина</TextBlock>
|
||||||
|
<Slider Value="{Binding Lenght}" Minimum="5" Maximum="90" />
|
||||||
|
<TextBlock Text="{Binding Lenght}" />
|
||||||
|
<Expander HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"
|
||||||
|
Header="Расположение">
|
||||||
|
<views:PositionControl DataContext="{Binding Position}" />
|
||||||
|
</Expander>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
</Panel>
|
||||||
|
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Row="1" VerticalAlignment="Top">
|
||||||
|
<TextBlock x:Name="CurrentBlock" Margin="5" />
|
||||||
|
<Slider Minimum="50" Maximum="500" TickFrequency="5" ValueChanged="Slider_ValueChanged" Value="100" />
|
||||||
|
<TextBlock x:Name="ScaleTB" />
|
||||||
|
<TextBlock x:Name="TotalTB" Text="0" Margin="5" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
<ScrollViewer Grid.Column="1" Margin="5,5,5,5" HorizontalScrollBarVisibility="Visible">
|
||||||
|
<Grid>
|
||||||
|
<Ellipse x:Name="BaseElipse" Stroke="Black" StrokeThickness="10" Height="150" Margin="15" Width="150"
|
||||||
|
VerticalAlignment="Top" HorizontalAlignment="Left" IsVisible="False" />
|
||||||
|
<Canvas Name="ShemeChanvas" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="15" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</ScrollViewer>
|
||||||
|
<StackPanel Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10" Spacing="10">
|
||||||
|
<TextBlock>Слои</TextBlock>
|
||||||
|
<ListBox SelectionChanged="SetupSelected" ItemsSource="{Binding Figures}" Name="Layers">
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid ColumnDefinitions="Auto *">
|
||||||
|
<TextBox Grid.Column="1" Text="{Binding Name}" HorizontalAlignment="Stretch"></TextBox>
|
||||||
|
<Border Margin="5" Background="OrangeRed" Width="30"></Border>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
@@ -0,0 +1,230 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Interactivity;
|
||||||
|
using Avalonia.Layout;
|
||||||
|
using Avalonia.Media;
|
||||||
|
using MCCAD.Models;
|
||||||
|
using MCCAD.ViewModels;
|
||||||
|
|
||||||
|
namespace MCCAD.Views;
|
||||||
|
|
||||||
|
public partial class MainWindow : Window
|
||||||
|
{
|
||||||
|
public Dictionary<IFigureView, Canvas> _cache = new();
|
||||||
|
public bool mark = true;
|
||||||
|
int blockSize = 15;
|
||||||
|
|
||||||
|
private bool switching = false;
|
||||||
|
private MainWindowViewModel DC => DataContext as MainWindowViewModel;
|
||||||
|
|
||||||
|
public MainWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDataContextChanged(EventArgs e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DrawShape(List<IntPoint> points, IFigureView view)
|
||||||
|
{
|
||||||
|
if (!_cache.TryGetValue(view, out Canvas canvas))
|
||||||
|
{
|
||||||
|
canvas = new Canvas();
|
||||||
|
_cache.Add(view, canvas);
|
||||||
|
ShemeChanvas.Children.Add(canvas);
|
||||||
|
}
|
||||||
|
canvas.Children.Clear();
|
||||||
|
|
||||||
|
canvas.Width = points.Select(i => i.X).Max() * blockSize;
|
||||||
|
canvas.Height = points.Select(i => i.Y).Max() * blockSize;
|
||||||
|
Dictionary<IntPoint, string> markup = new Dictionary<IntPoint, string>();
|
||||||
|
|
||||||
|
if (mark)
|
||||||
|
{
|
||||||
|
var lined = points.OrderBy(i => i.Y).GroupBy(i => i.Y);
|
||||||
|
foreach (var l in lined)
|
||||||
|
{
|
||||||
|
if (l.Count() < 3)
|
||||||
|
continue;
|
||||||
|
var line = l.OrderBy(i => i.X).ToList();
|
||||||
|
var linePoint = new List<int> { 0 };
|
||||||
|
for (int i = 0; i < line.Count; i++)
|
||||||
|
{
|
||||||
|
if (i != line.Count - 1 && line[i].X != line[i + 1].X - 1)
|
||||||
|
{
|
||||||
|
linePoint.Add(i);
|
||||||
|
linePoint.Add(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
linePoint.Add(line.Count - 1);
|
||||||
|
|
||||||
|
var linesIds = linePoint.Chunk(2);
|
||||||
|
foreach (var microLineId in linesIds)
|
||||||
|
{
|
||||||
|
var micloLine = line.Skip(microLineId[0]).Take(microLineId[1] - microLineId[0] + 1).ToList();
|
||||||
|
if (micloLine.Count > 2)
|
||||||
|
{
|
||||||
|
markup.Add(micloLine.First(), "←");
|
||||||
|
markup.Add(micloLine.Last(), "→");
|
||||||
|
markup.Add(micloLine[micloLine.Count / 2], micloLine.Count.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lined = points.OrderBy(i => i.X).GroupBy(i => i.X);
|
||||||
|
foreach (var l in lined)
|
||||||
|
{
|
||||||
|
if (l.Count() < 3)
|
||||||
|
continue;
|
||||||
|
var line = l.OrderBy(i => i.Y).ToList();
|
||||||
|
var linePoint = new List<int>() { 0 };
|
||||||
|
for (int i = 0; i < line.Count; i++)
|
||||||
|
{
|
||||||
|
if (i != line.Count - 1 && line[i].Y != line[i + 1].Y - 1)
|
||||||
|
{
|
||||||
|
linePoint.Add(i);
|
||||||
|
linePoint.Add(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
linePoint.Add(line.Count - 1);
|
||||||
|
|
||||||
|
var linesIds = linePoint.Chunk(2);
|
||||||
|
foreach (var microLineId in linesIds)
|
||||||
|
{
|
||||||
|
var micloLine = line.Skip(microLineId[0]).Take(microLineId[1] - microLineId[0] + 1).ToList();
|
||||||
|
if (micloLine.Count > 2)
|
||||||
|
{
|
||||||
|
if (!markup.TryAdd(micloLine.First(), "↑"))
|
||||||
|
{
|
||||||
|
markup[micloLine.First()] = "+";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!markup.TryAdd(micloLine.Last(), "↓"))
|
||||||
|
{
|
||||||
|
markup[micloLine.Last()] = "+";
|
||||||
|
}
|
||||||
|
|
||||||
|
markup.Add(micloLine[micloLine.Count / 2], micloLine.Count.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var point in points)
|
||||||
|
{
|
||||||
|
Border block = new Border();
|
||||||
|
block.Height = blockSize;
|
||||||
|
block.Width = blockSize;
|
||||||
|
block.BorderThickness = new Thickness(2);
|
||||||
|
block.Background = new SolidColorBrush(Colors.LightGray);
|
||||||
|
block.DataContext = point;
|
||||||
|
block.PointerEntered += (sender, e) => { CurrentBlock.Text = (sender as Border).DataContext.ToString(); };
|
||||||
|
if (mark)
|
||||||
|
{
|
||||||
|
if (markup.TryGetValue(point, out var text))
|
||||||
|
block.Child = new TextBlock
|
||||||
|
{
|
||||||
|
Text = text, HorizontalAlignment = HorizontalAlignment.Center,
|
||||||
|
VerticalAlignment = VerticalAlignment.Center, FontSize = 10
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Canvas.SetLeft(block, (point.X + view.Position.X) * blockSize);
|
||||||
|
Canvas.SetTop(block, (point.Y + view.Position.Y) * blockSize);
|
||||||
|
canvas.Children.Add(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.Width = blockSize * (points.Select(i => i.X).Max() + 5);
|
||||||
|
canvas.Height = blockSize * (points.Select(i => i.Y).Max() + 5);
|
||||||
|
|
||||||
|
TotalTB.Text = points.Count.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void Slider_ValueChanged(object? sender, RangeBaseValueChangedEventArgs rangeBaseValueChangedEventArgs)
|
||||||
|
{
|
||||||
|
if (ShemeChanvas == null)
|
||||||
|
return;
|
||||||
|
var e = rangeBaseValueChangedEventArgs;
|
||||||
|
ShemeChanvas.RenderTransform = new ScaleTransform() { ScaleX = e.NewValue / 100, ScaleY = e.NewValue / 100 };
|
||||||
|
// ShemeChanvas.transf.LayoutTransform = new ScaleTransform() { ScaleX = e.NewValue / 95, ScaleY = e.NewValue / 95 };
|
||||||
|
ScaleTB.Text = Math.Round(rangeBaseValueChangedEventArgs.NewValue) + "%";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateShape(object? sender, RoutedEventArgs routedEventArgs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var x = (sender as Control).Tag;
|
||||||
|
switch (x)
|
||||||
|
{
|
||||||
|
case "Ov":
|
||||||
|
DC.Ov = new OvalView();
|
||||||
|
DC.Ov.OnNewSheme += DrawShape;
|
||||||
|
DC.Ov.Rebuild();
|
||||||
|
DC.Figures.Add(DC.Ov);
|
||||||
|
SetupVisiblePanel(0);
|
||||||
|
break;
|
||||||
|
case "Pv":
|
||||||
|
DC.Pv = new PolygonView();
|
||||||
|
DC.Pv.OnNewSheme += DrawShape;
|
||||||
|
DC.Pv.Rebuild();
|
||||||
|
DC.Figures.Add(DC.Pv);
|
||||||
|
SetupVisiblePanel(1);
|
||||||
|
break;
|
||||||
|
case "Lv":
|
||||||
|
DC.Lv = new LineView();
|
||||||
|
DC.Lv.OnNewSheme += DrawShape;
|
||||||
|
DC.Lv.Rebuild();
|
||||||
|
DC.Figures.Add(DC.Lv);
|
||||||
|
SetupVisiblePanel(2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupSelected(object? sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (Layers.SelectedItem == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switching = true;
|
||||||
|
switch (Layers.SelectedItem)
|
||||||
|
{
|
||||||
|
case OvalView ov:
|
||||||
|
DC.Ov = ov;
|
||||||
|
SetupVisiblePanel(0);
|
||||||
|
break;
|
||||||
|
case PolygonView pv:
|
||||||
|
DC.Pv = pv;
|
||||||
|
SetupVisiblePanel(1);
|
||||||
|
break;
|
||||||
|
case LineView lv:
|
||||||
|
DC.Lv = lv;
|
||||||
|
SetupVisiblePanel(2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupVisiblePanel(int index)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < ToolsTab.Children.Count; i++)
|
||||||
|
{
|
||||||
|
ToolsTab.Children[i].IsVisible = i == index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:models="clr-namespace:MCCAD.Models"
|
||||||
|
xmlns:viewModels="clr-namespace:MCCAD.ViewModels"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="MCCAD.Views.PositionControl"
|
||||||
|
x:DataType="viewModels:PositionVM">
|
||||||
|
<Grid RowDefinitions="Auto *" ColumnDefinitions="Auto *">
|
||||||
|
<TextBlock VerticalAlignment="Center" Margin="5">X: </TextBlock>
|
||||||
|
<TextBlock VerticalAlignment="Center" Grid.Row="1" Margin="5">Y: </TextBlock>
|
||||||
|
<TextBox Grid.Column="1" Text="{Binding X}" Margin="5"></TextBox>
|
||||||
|
<TextBox Grid.Column="1" Grid.Row="1" Text="{Binding Y}" Margin="5"></TextBox>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</UserControl>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
|
||||||
|
namespace MCCAD.Views;
|
||||||
|
|
||||||
|
public partial class PositionControl : UserControl
|
||||||
|
{
|
||||||
|
public PositionControl()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<!-- This manifest is used on Windows only.
|
||||||
|
Don't remove it as it might cause problems with window transparency and embedded controls.
|
||||||
|
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="MCCAD.Desktop"/>
|
||||||
|
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- A list of the Windows versions that this application has been tested on
|
||||||
|
and is designed to work with. Uncomment the appropriate elements
|
||||||
|
and Windows will automatically select the most compatible environment. -->
|
||||||
|
|
||||||
|
<!-- Windows 10 -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
</assembly>
|
||||||
Reference in New Issue
Block a user