commit 07680fc5ed47b08e4b4faf0d7c2a77598fb16267 Author: Mikhail Mitrofanov Date: Mon Apr 6 10:03:33 2026 +0300 Initial diff --git a/.idea/.idea.MCCAD/.idea/.gitignore b/.idea/.idea.MCCAD/.idea/.gitignore new file mode 100644 index 0000000..c1683c8 --- /dev/null +++ b/.idea/.idea.MCCAD/.idea/.gitignore @@ -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/ diff --git a/.idea/.idea.MCCAD/.idea/avalonia.xml b/.idea/.idea.MCCAD/.idea/avalonia.xml new file mode 100644 index 0000000..d1d87b8 --- /dev/null +++ b/.idea/.idea.MCCAD/.idea/avalonia.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/.idea.MCCAD/.idea/indexLayout.xml b/.idea/.idea.MCCAD/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.MCCAD/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.MCCAD/.idea/vcs.xml b/.idea/.idea.MCCAD/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/.idea.MCCAD/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/MCCAD.slnx b/MCCAD.slnx new file mode 100644 index 0000000..874947d --- /dev/null +++ b/MCCAD.slnx @@ -0,0 +1,3 @@ + + + diff --git a/MCCAD/App.axaml b/MCCAD/App.axaml new file mode 100644 index 0000000..eeb4a3e --- /dev/null +++ b/MCCAD/App.axaml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/MCCAD/App.axaml.cs b/MCCAD/App.axaml.cs new file mode 100644 index 0000000..36fa997 --- /dev/null +++ b/MCCAD/App.axaml.cs @@ -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(); + } +} \ No newline at end of file diff --git a/MCCAD/Assets/avalonia-logo.ico b/MCCAD/Assets/avalonia-logo.ico new file mode 100644 index 0000000..f7da8bb Binary files /dev/null and b/MCCAD/Assets/avalonia-logo.ico differ diff --git a/MCCAD/MCCAD.csproj b/MCCAD/MCCAD.csproj new file mode 100644 index 0000000..3768e4d --- /dev/null +++ b/MCCAD/MCCAD.csproj @@ -0,0 +1,26 @@ + + + WinExe + net9.0 + enable + app.manifest + true + + + + + + + + + + + + + + None + All + + + + diff --git a/MCCAD/Models/HPoint.cs b/MCCAD/Models/HPoint.cs new file mode 100644 index 0000000..4ae92de --- /dev/null +++ b/MCCAD/Models/HPoint.cs @@ -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}"; + } +} \ No newline at end of file diff --git a/MCCAD/Models/Line.cs b/MCCAD/Models/Line.cs new file mode 100644 index 0000000..e8ca156 --- /dev/null +++ b/MCCAD/Models/Line.cs @@ -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 GetPixels() + { + Debug.WriteLine($"Line started"); + var shape = new List(); + 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 GetPixelsTrign(double angle, double len) + { + Debug.WriteLine($"Line {angle} rads started"); + + var shape = new List(); + 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; + } + } \ No newline at end of file diff --git a/MCCAD/Program.cs b/MCCAD/Program.cs new file mode 100644 index 0000000..90711ae --- /dev/null +++ b/MCCAD/Program.cs @@ -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() + .UsePlatformDetect() + .WithInterFont() + .LogToTrace() + .UseReactiveUI(i => { }); +} \ No newline at end of file diff --git a/MCCAD/ViewLocator.cs b/MCCAD/ViewLocator.cs new file mode 100644 index 0000000..8892d45 --- /dev/null +++ b/MCCAD/ViewLocator.cs @@ -0,0 +1,37 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using Avalonia.Controls; +using Avalonia.Controls.Templates; +using MCCAD.ViewModels; + +namespace MCCAD; + +/// +/// Given a view model, returns the corresponding view if possible. +/// +[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; + } +} \ No newline at end of file diff --git a/MCCAD/ViewModels/LineView.cs b/MCCAD/ViewModels/LineView.cs new file mode 100644 index 0000000..87c97a4 --- /dev/null +++ b/MCCAD/ViewModels/LineView.cs @@ -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 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 shape = new List(); + + 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 vecs = new LinkedList(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(); + var halfWidth = RoundToInt(width / 2); + var halfHeight = RoundToInt(heigh / 2); + List 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); + } +} \ No newline at end of file diff --git a/MCCAD/ViewModels/MainWindowViewModel.cs b/MCCAD/ViewModels/MainWindowViewModel.cs new file mode 100644 index 0000000..5834d5e --- /dev/null +++ b/MCCAD/ViewModels/MainWindowViewModel.cs @@ -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 Figures { get; set; } = []; +} \ No newline at end of file diff --git a/MCCAD/ViewModels/PositionVM.cs b/MCCAD/ViewModels/PositionVM.cs new file mode 100644 index 0000000..a779a68 --- /dev/null +++ b/MCCAD/ViewModels/PositionVM.cs @@ -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; +} \ No newline at end of file diff --git a/MCCAD/ViewModels/ViewModelBase.cs b/MCCAD/ViewModels/ViewModelBase.cs new file mode 100644 index 0000000..5796e99 --- /dev/null +++ b/MCCAD/ViewModels/ViewModelBase.cs @@ -0,0 +1,7 @@ +using ReactiveUI; + +namespace MCCAD.ViewModels; + +public abstract class ViewModelBase : ReactiveObject +{ +} \ No newline at end of file diff --git a/MCCAD/Views/MainWindow.axaml b/MCCAD/Views/MainWindow.axaml new file mode 100644 index 0000000..55589ff --- /dev/null +++ b/MCCAD/Views/MainWindow.axaml @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + Новый элипс + Новый многоугольник + Новая линия + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Угол + + + Длина + + + + + + + + + + + + + + + + + + + + + + + + + + + Слои + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MCCAD/Views/MainWindow.axaml.cs b/MCCAD/Views/MainWindow.axaml.cs new file mode 100644 index 0000000..8d3e055 --- /dev/null +++ b/MCCAD/Views/MainWindow.axaml.cs @@ -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 _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 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 markup = new Dictionary(); + + 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 { 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() { 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; + } + } +} \ No newline at end of file diff --git a/MCCAD/Views/PositionControl.axaml b/MCCAD/Views/PositionControl.axaml new file mode 100644 index 0000000..8ad982e --- /dev/null +++ b/MCCAD/Views/PositionControl.axaml @@ -0,0 +1,17 @@ + + + X: + Y: + + + + + diff --git a/MCCAD/Views/PositionControl.axaml.cs b/MCCAD/Views/PositionControl.axaml.cs new file mode 100644 index 0000000..7ffa345 --- /dev/null +++ b/MCCAD/Views/PositionControl.axaml.cs @@ -0,0 +1,13 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace MCCAD.Views; + +public partial class PositionControl : UserControl +{ + public PositionControl() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/MCCAD/app.manifest b/MCCAD/app.manifest new file mode 100644 index 0000000..c74e6bb --- /dev/null +++ b/MCCAD/app.manifest @@ -0,0 +1,18 @@ + + + + + + + + + + + + + +