using Emgu.CV;
|
using RichCreator.Utility;
|
using RichCreator.Utility.PathFindings;
|
using RichCreator.Utility.Structs;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
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.Shapes;
|
using ZTImage;
|
|
namespace RichCreator.Editor.Tools
|
{
|
/// <summary>
|
/// AStarTools.xaml 的交互逻辑
|
/// </summary>
|
public partial class DijkstraTools : Window
|
{
|
public DijkstraTools()
|
{
|
InitializeComponent();
|
}
|
|
// 寻路信息
|
private FindPathInfo info = null;
|
private Border[] rects = new Border[0];
|
private bool isDown = false;
|
|
//边线UI
|
private Line edgeLine = null;
|
//边线开始索引
|
private Int32 edgeStartIndex = 0;
|
|
// 当前图像
|
private System.Drawing.Image image;
|
|
/// <summary>
|
/// 加载图片
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void OpenFromFile(object sender, RoutedEventArgs e)
|
{
|
string imagePath = string.Empty;
|
Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
|
ofd.DefaultExt = ".jpg";
|
ofd.Filter = "image file|*.jpg;*.png;";
|
ofd.Multiselect = false;
|
if (ofd.ShowDialog() == true)
|
{
|
imagePath = ofd.FileName;
|
}
|
else
|
{
|
return;
|
}
|
|
Mat source = CvInvoke.Imread(imagePath, Emgu.CV.CvEnum.ImreadModes.Color);
|
this.image = source.Bitmap;
|
SetImage(this.SourceImage);
|
}
|
|
/// <summary>
|
/// 设置图像
|
/// </summary>
|
/// <param name="control"></param>
|
/// <param name="image"></param>
|
private void SetImage(Image control)
|
{
|
BitmapImage t = ImageHelper.BitmapToImageSource(image);
|
control.Source = t;
|
if (control == this.SourceImage)
|
{
|
mainContainer.Width = image.Width;
|
mainContainer.Height = image.Height;
|
}
|
}
|
|
/// <summary>
|
/// 生成方框
|
/// </summary>
|
private void GenericRect(Int32 width,Int32 height,Int32 row,Int32 col)
|
{
|
ImageOverflowLayer.Children.Clear();
|
|
this.info = new FindPathInfo(width,height,row,col);
|
Int32 count = this.info.RowCount * this.info.ColCount;
|
this.rects = new Border[count];
|
|
for (int y = 0; y < this.info.RowCount; y++)
|
{
|
for (int x = 0; x < this.info.ColCount; x++)
|
{
|
//生成
|
GenericRect(y * this.info.ColCount + x, y, x, this.info.Width, this.info.Height);
|
}
|
}
|
}
|
|
/// <summary>
|
/// 设为顶点
|
/// </summary>
|
private void SetVertexUI(FindPathInfo.VertexInfo vertexInfo)
|
{
|
Int32 row, col;
|
this.info.GetVertexRowColumn(out row, out col, vertexInfo.Index);
|
Border border = this.rects[vertexInfo.Index];
|
TextBlock tb = border.Child as TextBlock;
|
if (tb == null)
|
{
|
return;
|
}
|
|
this.info.AddVertex(vertexInfo);
|
switch (vertexInfo.VertexType)
|
{
|
case 0:
|
//普通顶点
|
border.Background = new SolidColorBrush(Colors.YellowGreen);
|
tb.Text = vertexInfo.Index.ToString() + "\r\n(" + col.ToString() + "," + row.ToString() + ")";
|
break;
|
case 1:
|
//靠近点
|
border.Background = new SolidColorBrush(Colors.Green);
|
tb.Text = vertexInfo.NearVertexIndex.ToString() + "\r\n(" + col.ToString() + "," + row.ToString() + ")";
|
break;
|
case 2:
|
//起点
|
border.Background = new SolidColorBrush(Colors.Yellow);
|
tb.Text = vertexInfo.Index.ToString() + "(s)\r\n(" + col.ToString() + "," + row.ToString() + ")";
|
break;
|
case 3:
|
//终点
|
border.Background = new SolidColorBrush(Colors.Yellow);
|
tb.Text = vertexInfo.Index.ToString() + "(e)\r\n(" + col.ToString() + "," + row.ToString() + ")";
|
break;
|
|
}
|
|
}
|
|
|
/// <summary>
|
/// 设置近顶点
|
/// </summary>
|
/// <param name="border"></param>
|
private void SetNearVertex(Int32 index, Int32 nearIndex)
|
{
|
Int32 col = index % this.info.ColCount;
|
Int32 row = index / this.info.ColCount;
|
|
Border border = this.rects[index];
|
border.Background = new SolidColorBrush(Colors.Green);
|
|
TextBlock tb = border.Child as TextBlock;
|
if (tb == null)
|
{
|
return;
|
}
|
|
tb.Text = nearIndex.ToString() + "\r\n(" + col.ToString() + "," + row.ToString() + ")";
|
}
|
|
|
|
/// <summary>
|
/// 生成定位方框
|
/// </summary>
|
/// <returns></returns>
|
private Border AddLocationPoint(Int32 x, Int32 y,Int32 number)
|
{
|
this.info.Positions.Add(new FindPathInfo.PointSerialize(x,y,number));
|
/*
|
<Border Width="60" Height="30" BorderBrush="GreenYellow" BorderThickness="1">
|
<StackPanel Orientation="Vertical">
|
<Ellipse Width="5" Height="5" Fill="Blue" StrokeThickness="1" HorizontalAlignment="Left" />
|
<TextBlock Text="(128,334)" HorizontalAlignment="Left"/>
|
</StackPanel>
|
</Border>
|
*/
|
Border border = new Border();
|
border.Width = 60;
|
border.Height = 40;
|
border.BorderBrush = new SolidColorBrush(Colors.Red);
|
border.BorderThickness = new Thickness(0);
|
border.Opacity = 0.7f;
|
border.IsHitTestVisible = false;
|
|
StackPanel panel = new StackPanel();
|
panel.Orientation = System.Windows.Controls.Orientation.Vertical;
|
panel.IsHitTestVisible = false;
|
border.Child = panel;
|
|
Ellipse ep = new Ellipse();
|
ep.Width = 5;
|
ep.Height = 5;
|
ep.Fill = new SolidColorBrush(Colors.Red);
|
ep.StrokeThickness = 1;
|
ep.HorizontalAlignment = HorizontalAlignment.Left;
|
ep.IsHitTestVisible = false;
|
panel.Children.Add(ep);
|
|
TextBlock tb = new TextBlock();
|
tb.Foreground = new SolidColorBrush(Colors.Red);
|
tb.Text = number.ToString() + "\r\n(" + x.ToString() + "," + y.ToString() + ")";
|
tb.HorizontalAlignment = HorizontalAlignment.Left;
|
tb.IsHitTestVisible = false;
|
panel.Children.Add(tb);
|
|
|
Canvas.SetLeft(border, x);
|
Canvas.SetTop(border, y);
|
PositionOverflowLayer.Children.Add(border);
|
return border;
|
}
|
|
/// <summary>
|
/// 生成顶点方框
|
/// </summary>
|
/// <param name="row"></param>
|
/// <param name="col"></param>
|
/// <param name="width"></param>
|
/// <param name="height"></param>
|
private void GenericRect(Int32 index,int row, int col, int width, int height)
|
{
|
//<Border Width="60" Height="60" BorderBrush="GreenYellow" BorderThickness="1" Background="GreenYellow" Opacity="0.7">
|
// <TextBlock Text="(425,334)" HorizontalAlignment="Right" VerticalAlignment="Bottom" />
|
//</Border>
|
Border border = new Border();
|
border.Width = width;
|
border.Height = height;
|
border.BorderBrush= new SolidColorBrush(Colors.GreenYellow);
|
border.BorderThickness=new Thickness (1);
|
border.Opacity = 0.7f;
|
border.IsHitTestVisible = false;
|
|
TextBlock tb = new TextBlock();
|
tb.Text = index.ToString()+ "\r\n(" + col.ToString()+","+row.ToString()+")";
|
tb.HorizontalAlignment = HorizontalAlignment.Right;
|
tb.VerticalAlignment = VerticalAlignment.Bottom;
|
tb.FontSize = 7;
|
tb.IsHitTestVisible = false;
|
border.Child = tb;
|
|
|
Canvas.SetLeft(border, col*width);
|
Canvas.SetTop(border, row*height);
|
|
ImageOverflowLayer.Children.Add(border);
|
this.rects[index] = border;
|
}
|
|
/// <summary>
|
/// 添加连接线
|
/// </summary>
|
private void GenericEdge(Int32 index)
|
{
|
Int32 col = index % this.info.ColCount;
|
Int32 row = index / this.info.ColCount;
|
//连接顶点
|
Int32 x = col * this.info.Width + this.info.Width / 2;
|
Int32 y = row * this.info.Height + this.info.Height / 2;
|
|
edgeLine = new Line();
|
edgeLine.Stroke = new SolidColorBrush(Colors.Red);
|
edgeLine.StrokeThickness = 1;
|
edgeLine.X1 = x;
|
edgeLine.Y1 = y;
|
|
edgeStartIndex = index;
|
this.ImageOverflowLayer.Children.Add(edgeLine);
|
}
|
|
/// <summary>
|
/// 设置连接线
|
/// </summary>
|
private void SetEdge(Int32 index)
|
{
|
Int32 row = index / this.info.ColCount;
|
Int32 col = index % this.info.ColCount;
|
//连接顶点
|
if (this.info.VertexCanAddEdge(index))
|
{
|
this.info.Edges.Add(new FindPathInfo.EdgeInfo() { StartIndex = edgeStartIndex, EndIndex = index });
|
|
Int32 x = col * this.info.Width + this.info.Width / 2;
|
Int32 y = row * this.info.Height + this.info.Height / 2;
|
edgeLine.X2 = x;
|
edgeLine.Y2 = y;
|
|
}
|
else
|
{
|
this.ImageOverflowLayer.Children.Remove(edgeLine);
|
}
|
}
|
|
/// <summary>
|
/// 添加顶点
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void GenericRect_Click(object sender, RoutedEventArgs e)
|
{
|
if (this.image == null)
|
{
|
MessageBox.Show("请选加载图片再生成方框");
|
return;
|
}
|
|
Int32 width = TypeConverter.StringToInt(this.rectWidth.Text, 0);
|
Int32 height = TypeConverter.StringToInt(this.rectHeight.Text, 0);
|
if (width <= 0 || height <= 0)
|
{
|
MessageBox.Show("宽高必须大于0");
|
return;
|
}
|
Int32 row = this.image.Height / height;
|
if (this.image.Height % height != 0)
|
{
|
row++;
|
}
|
Int32 col = this.image.Width / width;
|
if (this.image.Width % width!=0)
|
{
|
col++;
|
}
|
|
|
GenericRect(width, height, row, col);
|
}
|
|
/// <summary>
|
/// 鼠标按下
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void SourceImage_MouseDown(object sender, MouseButtonEventArgs e)
|
{
|
//是否添加障碍物
|
OperateActionD operateAction = (OperateActionD)(ClickOperate.SelectedIndex);
|
VertexTypeD vertexType = (VertexTypeD)(tagVertexType.SelectedIndex);
|
if (e.LeftButton == MouseButtonState.Released)
|
{
|
return;
|
}
|
Point point = GetPosition(e);
|
|
Int32 row = (Int32)point.Y / this.info.Height;
|
Int32 col = (Int32)point.X / this.info.Width;
|
|
Int32 index = row * this.info.ColCount + col;
|
Int32 number = TypeConverter.StringToInt(this.tagNumber.Text, 0);
|
if (operateAction == OperateActionD.AddVertex)
|
{
|
FindPathInfo.VertexInfo vertex = new FindPathInfo.VertexInfo() { Index = index, VertexType = (Int32)vertexType, NearVertexIndex = number };
|
SetVertexUI(vertex);
|
|
}
|
else if (operateAction == OperateActionD.Link)
|
{
|
//添加顶点连接线
|
GenericEdge(index);
|
edgeLine.X2 = point.X;
|
edgeLine.Y2 = point.Y;
|
}
|
else if (operateAction == OperateActionD.LocationPoint)
|
{
|
//添加定位点
|
AddLocationPoint((Int32)point.X, (Int32)point.Y,number);
|
}
|
isDown = true;
|
}
|
|
|
|
/// <summary>
|
/// 鼠标移动
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void SourceImage_MouseMove(object sender, MouseEventArgs e)
|
{
|
if (!isDown)
|
{
|
return;
|
}
|
|
OperateActionD operateAction = (OperateActionD)(ClickOperate.SelectedIndex);
|
VertexTypeD vertexType = (VertexTypeD)(tagVertexType.SelectedIndex);
|
|
|
Point point = GetPosition(e);
|
|
|
Int32 row = (Int32)point.Y / this.info.Height;
|
Int32 col = (Int32)point.X / this.info.Width;
|
Int32 index = row * this.info.ColCount + col;
|
Int32 number = ZTImage.TypeConverter.StringToInt(this.tagNumber.Text, 0);
|
if (operateAction == OperateActionD.AddVertex)
|
{
|
FindPathInfo.VertexInfo vertex = new FindPathInfo.VertexInfo() { Index = index, VertexType = (Int32)vertexType, NearVertexIndex = number };
|
SetVertexUI(vertex);
|
}
|
else if (operateAction == OperateActionD.Link)
|
{
|
//连接顶点
|
edgeLine.X2 = point.X;
|
edgeLine.Y2 = point.Y;
|
}
|
}
|
|
/// <summary>
|
/// 鼠标提起
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void SourceImage_MouseUp(object sender, MouseButtonEventArgs e)
|
{
|
if (!isDown)
|
{
|
return;
|
}
|
isDown = false;
|
Point point = GetPosition(e);
|
OperateActionD operateAction = (OperateActionD)(ClickOperate.SelectedIndex);
|
VertexTypeD vertexType = (VertexTypeD)(tagVertexType.SelectedIndex);
|
|
Int32 row = (Int32)point.Y / this.info.Height;
|
Int32 col = (Int32)point.X / this.info.Width;
|
|
Int32 index = row * this.info.ColCount + col;
|
if (operateAction == OperateActionD.Link)
|
{
|
//连接顶点并添加到边列表里
|
SetEdge(index);
|
}
|
}
|
|
/// <summary>
|
/// 清空定位点
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void ClearVex_Click(object sender, RoutedEventArgs e)
|
{
|
this.PositionOverflowLayer.Children.Clear();
|
}
|
|
/// <summary>
|
/// 清空顶点
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void ClearRect_Click(object sender, RoutedEventArgs e)
|
{
|
ImageOverflowLayer.Children.Clear();
|
}
|
|
|
|
/// <summary>
|
/// 计算当前鼠标位置和颜色
|
/// </summary>
|
/// <param name="e"></param>
|
/// <param name="point"></param>
|
/// <param name="color"></param>
|
/// <returns></returns>
|
private Point GetPosition(MouseEventArgs e )
|
{
|
Point point = e.GetPosition(this.scrollViewer);
|
|
Int32 x = (Int32)Math.Round(this.scrollViewer.HorizontalOffset + point.X);
|
Int32 y = (Int32)Math.Round(this.scrollViewer.VerticalOffset + point.Y);
|
|
return new Point(x, y);
|
}
|
|
|
/// <summary>
|
/// 操作类型
|
/// </summary>
|
public enum OperateActionD
|
{
|
AddVertex=0,//添加顶点
|
Link=1,//连接
|
LocationPoint=2//定位点
|
}
|
|
/// <summary>
|
/// 添加顶点类型
|
/// 顶点类型,0:普通顶点,1:依附顶点,2:起点,3:终点
|
/// </summary>
|
public enum VertexTypeD
|
{
|
Common=0,
|
Near=1,
|
Start=2,
|
End=3
|
}
|
|
/// <summary>
|
/// 复制JSON
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void CopyJSON_Click(object sender, RoutedEventArgs e)
|
{
|
string json = this.info.ToJsonString();
|
Clipboard.SetDataObject(json, true);
|
}
|
|
/// <summary>
|
/// 从JSON创建
|
/// </summary>
|
/// <param name="sender"></param>
|
/// <param name="e"></param>
|
private void CreateFromJSON_Click(object sender, RoutedEventArgs e)
|
{
|
SerializeInput input = new SerializeInput();
|
if (input.ShowDialog() != true)
|
{
|
return;
|
}
|
|
FindPathInfo pi = FindPathInfo.FromJsonString(input.ColorString);
|
|
|
|
//生成网格
|
this.rectWidth.Text = pi.Width.ToString();
|
this.rectHeight.Text = pi.Height.ToString();
|
GenericRect(pi.Width, pi.Height, pi.RowCount, pi.ColCount);
|
|
|
//生成顶点
|
for (int i = 0; i < pi.Vertexs.Count; i++)
|
{
|
SetVertexUI(pi.Vertexs[i]);
|
}
|
|
//生成连线
|
for (int i = 0; i < pi.Edges.Count; i++)
|
{
|
GenericEdge(pi.Edges[i].StartIndex);
|
SetEdge(pi.Edges[i].EndIndex);
|
}
|
|
|
this.PositionOverflowLayer.Children.Clear();
|
|
//生成定位点
|
for (int i = 0; i < pi.Positions.Count; i++)
|
{
|
AddLocationPoint(pi.Positions[i].X, pi.Positions[i].Y, pi.Positions[i].Parameter);
|
}
|
|
|
}
|
}
|
}
|