DxfView.xaml.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. using netDxf.Entities;
  2. using OxyPlot;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using System.Windows;
  9. using System.Windows.Controls;
  10. using System.Windows.Data;
  11. using System.Windows.Documents;
  12. using System.Windows.Input;
  13. using System.Windows.Media;
  14. using System.Windows.Media.Imaging;
  15. using System.Windows.Navigation;
  16. using System.Windows.Shapes;
  17. using WpfLine = System.Windows.Shapes.Line;
  18. using DxfLine = netDxf.Entities.Line;
  19. using DxfLwPolyline = netDxf.Entities.Polyline2D;
  20. using Microsoft.Win32;
  21. using System.Drawing;
  22. namespace TeamAAS_VP.DxfModule
  23. {
  24. /// <summary>
  25. /// DxfView.xaml 的交互逻辑
  26. /// </summary>
  27. public partial class DxfView : UserControl
  28. {
  29. private DxfParserService _dxfParser;
  30. private InteractionController _interactionController;
  31. private double _currentScale = 1.0;
  32. private double _zoomFactor = 1.2;
  33. public DxfView()
  34. {
  35. InitializeComponent();
  36. _dxfParser = new DxfParserService();
  37. InitializeInteractionController();
  38. }
  39. #region 依赖属性-PointF集合
  40. public static readonly DependencyProperty PointsProperty =
  41. DependencyProperty.Register("Points", typeof(List<PointF>), typeof(DxfView),
  42. new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnPointsChanged)));
  43. public List<PointF> Points
  44. {
  45. get { return (List<PointF>)GetValue(PointsProperty); }
  46. set { SetValue(PointsProperty, value); }
  47. }
  48. private static void OnPointsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  49. {
  50. var view = d as DxfView;
  51. if (view != null)
  52. {
  53. // Handle points changed
  54. }
  55. }
  56. #endregion
  57. //需要导入的点位表开始点编号
  58. public int StartIndex { get;private set; } = 1;
  59. private void InitializeInteractionController()
  60. {
  61. _interactionController = new InteractionController(DrawingCanvas);
  62. _interactionController.SelectionChanged += OnSelectionChanged;
  63. }
  64. private void BtnLoadDxf_Click(object sender, RoutedEventArgs e)
  65. {
  66. var openFileDialog = new OpenFileDialog
  67. {
  68. Filter = "DXF文件 (*.dxf)|*.dxf|所有文件 (*.*)|*.*",
  69. Title = "选择DXF文件"
  70. };
  71. if (openFileDialog.ShowDialog() == true)
  72. {
  73. LoadDxfFile(openFileDialog.FileName);
  74. }
  75. }
  76. private void LoadDxfFile(string filePath)
  77. {
  78. TxtStatus.Text = "正在加载DXF文件...";
  79. DrawingCanvas.Children.Clear();
  80. _interactionController?.ClearSelection();
  81. if (_dxfParser.LoadDxfFile(filePath))
  82. {
  83. var entities = _dxfParser.GetAllEntities();
  84. TxtStatus.Text = $"成功加载: {System.IO.Path.GetFileName(filePath)}";
  85. TxtEntityCount.Text = $"实体数: {entities.Count}";
  86. // Calculate bounds and scale
  87. var bounds = _dxfParser.GetBounds();
  88. double boundsWidth = bounds.maxX - bounds.minX;
  89. double boundsHeight = bounds.maxY - bounds.minY;
  90. if (boundsWidth > 0 && boundsHeight > 0)
  91. {
  92. double scaleX = (DrawingCanvas.Width * 0.8) / boundsWidth;
  93. double scaleY = (DrawingCanvas.Height * 0.8) / boundsHeight;
  94. _currentScale = Math.Min(scaleX, scaleY);
  95. }
  96. // Render entities
  97. foreach (var entity in entities)
  98. {
  99. var renderedElements = GraphicsRenderer.RenderEntity(entity, _currentScale);
  100. foreach (var element in renderedElements)
  101. {
  102. DrawingCanvas.Children.Add(element);
  103. }
  104. }
  105. // Center the drawing
  106. CenterDrawing(bounds);
  107. // Update statistics
  108. UpdateStatistics();
  109. }
  110. else
  111. {
  112. TxtStatus.Text = "加载DXF文件失败";
  113. MessageBox.Show("无法加载DXF文件,请检查文件是否有效。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  114. }
  115. }
  116. private void CenterDrawing((double minX, double minY, double maxX, double maxY) bounds)
  117. {
  118. double centerX = (bounds.minX + bounds.maxX) / 2 * _currentScale;
  119. double centerY = -(bounds.minY + bounds.maxY) / 2 * _currentScale;
  120. double offsetX = DrawingCanvas.Width / 2 - centerX;
  121. double offsetY = DrawingCanvas.Height / 2 - centerY;
  122. // Translate all elements
  123. foreach (UIElement element in DrawingCanvas.Children)
  124. {
  125. if (element is WpfLine line)
  126. {
  127. line.X1 += offsetX;
  128. line.X2 += offsetX;
  129. line.Y1 += offsetY;
  130. line.Y2 += offsetY;
  131. }
  132. else if (element is FrameworkElement fe)
  133. {
  134. double left = Canvas.GetLeft(fe);
  135. double top = Canvas.GetTop(fe);
  136. Canvas.SetLeft(fe, left + offsetX);
  137. Canvas.SetTop(fe, top + offsetY);
  138. }
  139. }
  140. }
  141. private void UpdateStatistics()
  142. {
  143. var stats = _dxfParser.GetEntityStatistics();
  144. var sb = new StringBuilder();
  145. foreach (var stat in stats.OrderByDescending(s => s.Value))
  146. {
  147. if (stat.Value > 0)
  148. {
  149. sb.AppendLine($"{stat.Key}: {stat.Value}");
  150. }
  151. }
  152. TxtStatistics.Text = sb.ToString();
  153. }
  154. private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
  155. {
  156. TxtSelectedCount.Text = $"选中: {e.SelectedEntities.Count}";
  157. var sb = new StringBuilder();
  158. if (e.SelectedEntities.Count > 0)
  159. {
  160. sb.AppendLine($"已选择 {e.SelectedEntities.Count} 个图形实体:\n");
  161. var grouped = e.SelectedEntities.GroupBy(entity => entity.Type.ToString());
  162. foreach (var group in grouped)
  163. {
  164. sb.AppendLine($"{group.Key}: {group.Count()}");
  165. }
  166. sb.AppendLine("\n详细信息:");
  167. int index = 1;
  168. foreach (var entity in e.SelectedEntities.Take(10))
  169. {
  170. sb.AppendLine($"\n[{index}] {GetEntityInfo(entity)}");
  171. index++;
  172. }
  173. if (e.SelectedEntities.Count > 10)
  174. {
  175. sb.AppendLine($"\n... 还有 {e.SelectedEntities.Count - 10} 个实体");
  176. }
  177. //如果选中的是圆,则输出圆心坐标,如果是直线,则输出中心点坐标,如果是矩形,则输出中心点坐标,如果是点,则输出点坐标,如果是圆弧,则输出中心点坐标
  178. if (Points!=null)
  179. {
  180. Points = new List<PointF>();
  181. }
  182. Points.Clear();
  183. foreach (var item in e.SelectedEntities)
  184. {
  185. if (item is Circle circle)
  186. {
  187. Points.Add(new PointF((float)circle.Center.X, (float)circle.Center.Y));
  188. }
  189. else if (item is DxfLine line)
  190. {
  191. float centerX = (float)((line.StartPoint.X + line.EndPoint.X) / 2);
  192. float centerY = (float)((line.StartPoint.Y + line.EndPoint.Y) / 2);
  193. Points.Add(new PointF(centerX, centerY));
  194. }
  195. else if (item is DxfLwPolyline polyline && polyline.IsClosed)
  196. {
  197. //计算多边形中心点
  198. float centerX = 0;
  199. float centerY = 0;
  200. foreach (var vertex in polyline.Vertexes)
  201. {
  202. centerX += (float)vertex.Position.X;
  203. centerY += (float)vertex.Position.Y;
  204. }
  205. centerX /= polyline.Vertexes.Count;
  206. centerY /= polyline.Vertexes.Count;
  207. Points.Add(new PointF(centerX, centerY));
  208. }
  209. else if (item is netDxf.Entities.Point point)
  210. {
  211. Points.Add(new PointF((float)point.Position.X, (float)point.Position.Y));
  212. }
  213. else if (item is Arc arc)
  214. {
  215. Points.Add(new PointF((float)arc.Center.X, (float)arc.Center.Y));
  216. }
  217. }
  218. }
  219. else
  220. {
  221. sb.AppendLine("未选择任何图形");
  222. }
  223. TxtSelectedInfo.Text = sb.ToString();
  224. }
  225. private string GetEntityInfo(EntityObject entity)
  226. {
  227. switch (entity)
  228. {
  229. case DxfLine line:
  230. return $"直线: ({line.StartPoint.X:F2}, {line.StartPoint.Y:F2}) → ({line.EndPoint.X:F2}, {line.EndPoint.Y:F2})";
  231. case Circle circle:
  232. return $"圆: 中心({circle.Center.X:F2}, {circle.Center.Y:F2}), 半径={circle.Radius:F2}";
  233. case Arc arc:
  234. return $"圆弧: 中心({arc.Center.X:F2}, {arc.Center.Y:F2}), 半径={arc.Radius:F2}, 角度={arc.StartAngle:F1}°~{arc.EndAngle:F1}°";
  235. case Text text:
  236. return $"文本: \"{text.Value}\" 位置({text.Position.X:F2}, {text.Position.Y:F2})";
  237. case MText mtext:
  238. return $"多行文本: \"{mtext.Value}\" 位置({mtext.Position.X:F2}, {mtext.Position.Y:F2})";
  239. case DxfLwPolyline lwPoly:
  240. return $"轻量多段线: {lwPoly.Vertexes.Count} 个顶点{(lwPoly.IsClosed ? " (闭合)" : "")}";
  241. case Spline spline:
  242. // return $"样条曲线: {spline.ControlPoints.Count} 个控制点";
  243. default:
  244. return $"{entity.Type}: {entity.CodeName}";
  245. }
  246. }
  247. private void BtnClearSelection_Click(object sender, RoutedEventArgs e)
  248. {
  249. Points?.Clear();
  250. _interactionController?.ClearSelection();
  251. }
  252. private void BtnExtractSelected_Click(object sender, RoutedEventArgs e)
  253. {
  254. var selectedEntities = _interactionController?.GetSelectedEntities();
  255. if (selectedEntities == null || selectedEntities.Count == 0)
  256. {
  257. MessageBox.Show("请先选择要提取的图形。", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
  258. return;
  259. }
  260. var sb = new StringBuilder();
  261. sb.AppendLine($"提取的图形信息 (共 {selectedEntities.Count} 个):\n");
  262. var grouped = selectedEntities.GroupBy(p => p.Type.ToString());
  263. foreach (var group in grouped)
  264. {
  265. sb.AppendLine($"\n{group.Key} ({group.Count()} 个):");
  266. sb.AppendLine(new string('-', 50));
  267. foreach (var entity in group)
  268. {
  269. sb.AppendLine(GetEntityInfo(entity));
  270. }
  271. }
  272. MessageBox.Show(sb.ToString(), "提取的图形信息", MessageBoxButton.OK, MessageBoxImage.Information);
  273. }
  274. private void BtnZoomIn_Click(object sender, RoutedEventArgs e)
  275. {
  276. Zoom(_zoomFactor);
  277. }
  278. private void BtnZoomOut_Click(object sender, RoutedEventArgs e)
  279. {
  280. Zoom(1.0 / _zoomFactor);
  281. }
  282. private void BtnFitToScreen_Click(object sender, RoutedEventArgs e)
  283. {
  284. CanvasScaleTransform.ScaleX = 1.0;
  285. CanvasScaleTransform.ScaleY = 1.0;
  286. UpdateZoomDisplay();
  287. }
  288. private void DrawingCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
  289. {
  290. double zoom = e.Delta > 0 ? _zoomFactor : 1.0 / _zoomFactor;
  291. Zoom(zoom);
  292. }
  293. private void Zoom(double factor)
  294. {
  295. CanvasScaleTransform.ScaleX *= factor;
  296. CanvasScaleTransform.ScaleY *= factor;
  297. UpdateZoomDisplay();
  298. }
  299. private void UpdateZoomDisplay()
  300. {
  301. TxtZoom.Text = $"缩放: {CanvasScaleTransform.ScaleX * 100:F0}%";
  302. }
  303. private void TxtStartIndex_ValueChanged(object sender, RoutedPropertyChangedEventArgs<int> e)
  304. {
  305. StartIndex= e.NewValue;
  306. }
  307. }
  308. }