using HslCommunication;
using Microsoft.Windows.Controls.Ribbon;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace _106_CreatePLC
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void CreatePLC_Click(object sender, RoutedEventArgs e)
{
}
private ObservableCollection<Point> itemsSource = new ObservableCollection<Point>();
public ObservableCollection<Point> ItemsSource { get => itemsSource; set => itemsSource = value; }
private void ItemsSource_CollectionChanged()
{
var originalPt = new Ellipse { Width = 8, Height = 8, Margin = new Thickness(0, 0, 0, 0), Fill = Brushes.Yellow };
originalPt.HorizontalAlignment = HorizontalAlignment.Left;
originalPt.VerticalAlignment = VerticalAlignment.Top;
Can2.Children.Add(originalPt);
DrawPath(ItemsSource);
}
private void DrawPath(ObservableCollection<Point> itemsSource)
{
//var orderSource = from pt in itemsSource orderby pt.X ascending select pt;
//var li = orderSource.ToList();
var li = itemsSource.ToList();
var pf = new PathFigure { StartPoint = li[0] };
for (var i = 0; i < li.Count - 1; i++)
{
int current = i, last = i - 1, next = i + 1, next2 = i + 2;
if (last == -1)
{
last = 0;
}
if (next == li.Count)
{
next = li.Count - 1;
}
if (next2 == li.Count)
{
next2 = li.Count - 1;
}
var bzs = GetBezierSegment(li[current], li[last], li[next], li[next2]);
pf.Segments.Add(bzs);
}
//画点的圆圈
li.ForEach(lipt => Can2.Children.Add(new Ellipse { Width = 4, Height = 4, Margin = new Thickness(lipt.X - 2, lipt.Y - 2, 0, 0), HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Top, Fill = Brushes.Red, ToolTip = string.Format("x:{0},y:{1} ", lipt.X, lipt.Y) }));
//添加曲线到图上
var pfc = new PathFigureCollection { pf };
var pg = new PathGeometry(pfc);
var path = new Path { StrokeThickness = 1, Stroke = Brushes.Green, Data = pg };
Can2.Children.Add(path);
}
/// <summary>
/// 获得贝塞尔曲线
/// </summary>
/// <param name="currentPt">当前点</param>
/// <param name="lastPt">上一个点</param>
/// <param name="nextPt1">下一个点1</param>
/// <param name="nextPt2">下一个点2</param>
/// <returns></returns>
private BezierSegment GetBezierSegment(Point currentPt, Point lastPt, Point nextPt1, Point nextPt2)
{
//计算中点
var lastC = GetCenterPoint(lastPt, currentPt);
var nextC1 = GetCenterPoint(currentPt, nextPt1); //贝塞尔控制点
var nextC2 = GetCenterPoint(nextPt1, nextPt2);
//计算相邻中点连线跟目的点的垂足
//效果并不算太好,因为可能点在两个线上或者线的延长线上,计算会有误差
//所以就直接使用中点平移方法。
//var C1 = GetFootPoint(lastC, nextC1, currentPt);
//var C2 = GetFootPoint(nextC1, nextC2, nextPt1);
//计算“相邻中点”的中点
var c1 = GetCenterPoint(lastC, nextC1);
var c2 = GetCenterPoint(nextC1, nextC2);
//计算【"中点"的中点】需要的点位移
var controlPtOffset1 = currentPt - c1;
var controlPtOffset2 = nextPt1 - c2;
//移动控制点
var controlPt1 = nextC1 + controlPtOffset1;
var controlPt2 = nextC1 + controlPtOffset2;
//如果觉得曲线幅度太大,可以将控制点向当前点靠近一定的系数。
controlPt1 = controlPt1 + 0 * (currentPt - controlPt1);
controlPt2 = controlPt2 + 0 * (nextPt1 - controlPt2);
var bzs = new BezierSegment(controlPt1, controlPt2, nextPt1, true);
return bzs;
}
private Point GetCenterPoint(Point pt1, Point pt2)
{
return new Point((pt1.X + pt2.X) / 2, (pt1.Y + pt2.Y) / 2);
}
Point arcsP = new Point();
Point arceP = new Point();
Point arcM42P = new Point();
Point arcM43P = new Point();
private void Can2_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
sel2 = 0;
if (sel2 == 0)
{
Can2.Children.Clear();
arcsP = e.GetPosition((Canvas)sender);
sel2 = 1;
}
}
int sel2 = 0;
private void Can2_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (sel2 == 1 && e.LeftButton == MouseButtonState.Pressed)
{
Can2.Children.Clear();
ItemsSource.Clear();
arceP = e.GetPosition((Canvas)sender);
arcM42P.X = arcsP.X + (arceP.X - arcsP.X) / 4 * 2+25;
arcM42P.Y = arcsP.Y + (arceP.Y - arcsP.Y) / 4 * 2+35;
arcM43P.X = arcsP.X + (arceP.X - arcsP.X) / 4 * 3;
arcM43P.Y = arcsP.Y + (arceP.Y - arcsP.Y) / 4 * 3+10;
ItemsSource.Add(arcsP);
ItemsSource.Add(arcM42P);
ItemsSource.Add(arcM43P);
ItemsSource.Add(arceP);
ItemsSource_CollectionChanged();
}
if (sel2 == 1 && e.LeftButton == MouseButtonState.Released)
{
Can2.Children.Clear();
ItemsSource.Clear();
arceP = e.GetPosition((Canvas)sender);
arcM42P.X = arcsP.X + (arceP.X - arcsP.X) / 4 * 2 + 25;
arcM42P.Y = arcsP.Y + (arceP.Y - arcsP.Y) / 4 * 2 + 35;
arcM43P.X = arcsP.X + (arceP.X - arcsP.X) / 4 * 3 ;
arcM43P.Y = arcsP.Y + (arceP.Y - arcsP.Y) / 4 * 3 + 10;
ItemsSource.Add(arcsP);
ItemsSource.Add(arcM42P);
ItemsSource.Add(arcM43P);
ItemsSource.Add(arceP);
ItemsSource_CollectionChanged();
sel2 = 2;
}
}
Point sP = new Point();
Point eP = new Point();
int sel = 0;
private void Can1_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
sel = 0;
if (sel == 0)
{
sP = e.GetPosition((Canvas)sender);
sel = 1;
}
}
private void Can1_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
sel = 2;
if (true)
{
if (Can1.Children.Contains(l2) == true) Can1.Children.Remove(l2);
eP = e.GetPosition((Canvas)sender);
Line l1 = new Line();
l1.Stroke = Brushes.Black;
l1.StrokeThickness = 2;
l1.X1 = sP.X;
l1.Y1 = sP.Y;
l1.X2 = eP.X;
l1.Y2 = eP.Y;
Can1.Children.Add(l1);
sel = 3;
}
}
Line l2 = new Line();
private void Can1_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (sel == 1)
{
if (Can1.Children.Contains(l2) == true) Can1.Children.Remove(l2);
eP = e.GetPosition((Canvas)sender);
l2.Stroke = Brushes.Black;
l2.StrokeThickness = 2;
l2.X1 = sP.X;
l2.Y1 = sP.Y;
l2.X2 = eP.X;
l2.Y2 = eP.Y;
Can1.Children.Add(l2);
}
}
private void DrawPath()
{
Path path = new Path();
//300,300起始坐标
//A Arc圆弧
//100,100圆弧的X,Y值
//0 (图形旋转角度) 1(当设置旋转角度时,1取大圆弧0取小圆弧) 1(1为顺时针0为逆时针)
//300,0 表示终止坐标
path.Data = Geometry.Parse("M 300,300 A 100,100 0 1 1 300,0");
path.Stroke = Brushes.Black;
path.StrokeThickness = 2;
mainGrid.Children.Add(path);
}
}
}
xaml代码:
<Window x:Class="_106_CreatePLC.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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:local="clr-namespace:_106_CreatePLC"
mc:Ignorable="d"
Title="MainWindow" Height="1000" Width="1800">
<Grid Name="mainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="300"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition ></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Button Name="CreatePLC" Content="创建PLC" Click="CreatePLC_Click" Grid.Row="0" Grid.Column="0"></Button>
</Grid>
<Canvas Name="Can1" Grid.Row="0" Grid.Column="2"
Background="WhiteSmoke" Grid.RowSpan="2"
Grid.ColumnSpan="1" PreviewMouseDown="Can1_PreviewMouseDown"
PreviewMouseUp="Can1_PreviewMouseUp"
PreviewMouseMove="Can1_PreviewMouseMove"
>
<local:ReadImage x:Name="readImageFB1"
Margin="156,99,-156,-99"
></local:ReadImage>
<local:ReadImage x:Name="readImageFB2"
Margin="161,316,-161,-316"
></local:ReadImage>
</Canvas>
<Canvas Name="Can2" Grid.Row="0" Grid.Column="1"
Background="WhiteSmoke" Grid.RowSpan="2"
Grid.ColumnSpan="1" PreviewMouseDown="Can2_PreviewMouseDown"
PreviewMouseMove="Can2_PreviewMouseMove"
Margin="0,0,5,0"
>
</Canvas>
</Grid>
</Window>