WinCreateSpace.xaml.cs 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Reflection;
  7. using System.Text.RegularExpressions;
  8. using System.Windows;
  9. using System.Windows.Controls;
  10. using System.Windows.Input;
  11. using System.Windows.Media;
  12. using System.Windows.Shapes;
  13. using Autodesk.Revit.DB;
  14. using DevExpress.Mvvm.Native;
  15. using SAGA.DotNetUtils.Extend;
  16. using SAGA.RevitUtils.Extends;
  17. using WPolyline = System.Windows.Shapes.Polyline;
  18. using Point = System.Windows.Point;
  19. using System.Windows.Media.Animation;
  20. using System.Windows.Threading;
  21. using Autodesk.Revit.UI;
  22. using Newtonsoft.Json.Linq;
  23. using SAGA.DotNetUtils.Logger;
  24. using SAGA.MBI.Common;
  25. using SAGA.MBI.DataArrange;
  26. using SAGA.MBI.JsonConvert;
  27. using SAGA.MBI.Model;
  28. using SAGA.MBI.RequestData;
  29. using SAGA.MBI.Tools;
  30. using SAGA.MBI.WinView.ModeInfoMaintenance;
  31. using SAGA.RevitUtils.Windows;
  32. using Visibility = System.Windows.Visibility;
  33. using Path = System.IO.Path;
  34. //TODO:1.目前存在的问题,如果只选两个已有的端点画线不能实现
  35. //TODO:2.画图过程中,ESC可取消当前画图
  36. //TODO:3.切换楼层检测是否有需要保存的数据,如果有则提示是否保存
  37. namespace SAGA.MBI.WinView.Space
  38. {
  39. /// <summary>
  40. /// 空间管理
  41. /// </summary>
  42. public partial class WinCreateSpaces : WinBase
  43. {
  44. public WinCreateSpaces()
  45. {
  46. this.IsLoadHistroyData = false;
  47. InitializeComponent();
  48. tv.ItemsSource = Items;
  49. this.Loaded += MainWindow_Loaded;
  50. this.Closed += WinCreateSpaces_Closed;
  51. }
  52. /// <summary>
  53. /// 窗体关闭,同时关闭空间属性窗
  54. /// </summary>
  55. /// <param name="sender"></param>
  56. /// <param name="e"></param>
  57. private void WinCreateSpaces_Closed(object sender, EventArgs e)
  58. {
  59. WinModeInfoMaintenance.GetWindow().Close();
  60. }
  61. /*
  62. 颜色分类:墙为黑色,
  63. 已有空间分隔符为绿色,
  64. 柱为蓝色
  65. 新的空间分隔符为红色
  66. */
  67. private List<List<XYZ>> m_wallsData;
  68. private List<PointPair> m_virXyzs;
  69. private List<XYZ> m_columnsLocation;
  70. public List<int> DeletedPolylines = new List<int>();//被删除的已存在的虚拟墙的Id
  71. //建筑与楼层列表数据
  72. private ObservableCollection<TreeNodeItem> items;
  73. //最大值X
  74. double m_minX = double.MaxValue;
  75. double m_maxX = 0.0;
  76. double m_minY = double.MaxValue;
  77. double m_maxY = 0.0;
  78. //初始缩放比例
  79. double m_scale = 15 / 1.5d;
  80. //起始点
  81. Point m_previousMousePoint = new Point(0, 0);
  82. //当前线段
  83. private Polyline m_polyline;
  84. //是否开始画线
  85. bool m_flag = false;
  86. //建筑与楼层列表数据
  87. public ObservableCollection<TreeNodeItem> Items
  88. {
  89. get => new ObservableCollection<TreeNodeItem>(DalModeFileManange.GetMissFileFloors(false));
  90. set => items = value;
  91. }
  92. //本层空间数据缓存
  93. private List<MSpace> m_spacesCache;
  94. private void MainWindow_Loaded(object sender, RoutedEventArgs e)
  95. {
  96. CanvasDefaultTips();
  97. }
  98. /// <summary>
  99. /// 初始化画布,并在画图上画出相关数据
  100. /// </summary>
  101. private bool InitData()
  102. {
  103. //获取边界值
  104. GetBoundary();
  105. //获取缩放比例
  106. m_scale = Math.Min((canvas.ActualWidth - 40) / (m_maxX - m_minX), (canvas.ActualHeight - 40) / (m_maxY - m_minY));
  107. //虚拟墙
  108. m_virXyzs?.ForEach(line =>
  109. {
  110. var pline = CreateDefaultPolyLine(line.Point, Brushes.Green, 2);
  111. pline.Tag = line.ElementId;
  112. });
  113. //墙
  114. m_wallsData.Select(row => row.Select(xyz => xyz.ToW2DPoint()).ToList()).ForEach(line =>
  115. {
  116. CreateDefaultPolyLine(line, Brushes.Black, 4);
  117. });
  118. //画柱
  119. DrawColumns();
  120. return true;
  121. }
  122. /// <summary>
  123. /// 获取数据的边界值
  124. /// </summary>
  125. void GetBoundary()
  126. {
  127. //Revit坐标与wpf的Y坐标相反,WPF Y向下
  128. var xs = new List<double>();
  129. var ys = new List<double>();
  130. this.m_wallsData.ForEach(list =>
  131. {
  132. list.ForEach((xyz) =>
  133. {
  134. xs.Add(xyz.X);
  135. ys.Add(xyz.Y);
  136. });
  137. });
  138. this.m_virXyzs.ForEach(list =>
  139. {
  140. list.Point.ForEach((point) =>
  141. {
  142. xs.Add(point.X);
  143. ys.Add(point.Y);
  144. });
  145. });
  146. this.m_columnsLocation.ForEach(point =>
  147. {
  148. xs.Add(point.X);
  149. ys.Add(point.Y);
  150. });
  151. if (xs.Count == 0 || ys.Count == 0) return;
  152. m_maxX = xs.Max();
  153. m_minX = xs.Min();
  154. m_maxY = ys.Max();
  155. m_minY = ys.Min();
  156. }
  157. /// <summary>
  158. /// 平移坐标点,使其更适应界面
  159. /// </summary>
  160. /// <param name="point"></param>
  161. /// <returns></returns>
  162. Point MovePoint(Point point)
  163. {
  164. var newPoint = new Point((point.X - m_minX) * m_scale, -(point.Y - m_maxY) * m_scale);
  165. newPoint.Offset(20, 20);
  166. return newPoint;
  167. }
  168. /// <summary>
  169. /// 画柱子
  170. /// </summary>
  171. void DrawColumns()
  172. {
  173. foreach (var xyz in m_columnsLocation)
  174. {
  175. var point = MovePoint(new Point(xyz.X, xyz.Y));
  176. var line = new WPolyline
  177. {
  178. Stroke = Brushes.Blue,
  179. StrokeThickness = 2,
  180. Tag = new Point(point.X, point.Y)
  181. };
  182. //这里为了方便后边计算,在线上记录柱中心
  183. var offset = 7;
  184. //左上角
  185. point.Offset(-offset, -offset);
  186. line.Points.Add(point);
  187. point.Offset(0, 2 * offset);
  188. line.Points.Add(point);
  189. point.Offset(2 * offset, 0);
  190. line.Points.Add(point);
  191. point.Offset(0, -2 * offset);
  192. line.Points.Add(point);
  193. point.Offset(-2 * offset, 0);
  194. line.Points.Add(point);
  195. this.canvas.Children.Add(line);
  196. }
  197. }
  198. /// <summary>
  199. /// 鼠标移动,实时显示虚拟墙动态
  200. /// </summary>
  201. /// <param name="sender"></param>
  202. /// <param name="e"></param>
  203. private void canvas_MouseMove(object sender, MouseEventArgs e)
  204. {
  205. if (m_flag == false)
  206. return;
  207. if (m_isDraw == true)
  208. {
  209. m_polyline.Points[m_polyline.Points.Count - 1] = e.GetPosition(canvas);
  210. Console.WriteLine("Move: " + m_polyline.Points[m_polyline.Points.Count - 1]);
  211. }
  212. }
  213. /// <summary>
  214. /// 开始画虚拟墙
  215. /// </summary>
  216. /// <param name="sender"></param>
  217. /// <param name="e"></param>
  218. private void canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  219. {
  220. if (m_isDraw != true) return;
  221. var point = e.GetPosition(canvas);
  222. if (m_polyline == null)
  223. {
  224. // if (flag == false) {
  225. m_polyline = new Polyline
  226. {
  227. Stroke = Brushes.Red,
  228. StrokeThickness = 2,
  229. FillRule = FillRule.EvenOdd
  230. };
  231. this.canvas.Children.Add(m_polyline);
  232. //如果是第一个点,则自动附着到现有的线段上
  233. point = GeometryHelper.ConvertOnLinePoint(point, this.canvas, m_polyline);
  234. }
  235. m_polyline.Points.Add(point);
  236. if (m_polyline.Points.Count == 1)
  237. m_polyline.Points.Add(e.GetPosition(canvas));
  238. m_flag = true;
  239. this.btnSave.IsEnabled = true;
  240. Console.WriteLine("Left Down: " + e.GetPosition(canvas));
  241. }
  242. /// <summary>
  243. /// 缩放画布
  244. /// </summary>
  245. /// <param name="scale"></param>
  246. /// <param name="center"></param>
  247. private void MoveElement(double scale, Point center, bool isReset = false)
  248. {
  249. //foreach (UIElement s in canvas.Children)
  250. {
  251. if (canvas.RenderTransform is TransformGroup tg)
  252. {
  253. //缩放
  254. if (tg.Children.FirstOrDefault(tr => tr is ScaleTransform) is ScaleTransform stf)
  255. {
  256. //重置
  257. if (isReset)
  258. {
  259. stf.ScaleX = 1;
  260. stf.ScaleY = 1;
  261. return;
  262. }
  263. //缩放的大小不能太小
  264. stf.ScaleX = Math.Max(stf.ScaleX + scale, 0.3);
  265. stf.ScaleY = Math.Max(stf.ScaleY + scale, 0.3);
  266. //if (center.X <= 0 || center.Y <= 0) {
  267. // return;
  268. //}
  269. // stf.CenterX = center.X;
  270. // stf.CenterY = center.Y;
  271. }
  272. else
  273. {
  274. scale = Math.Max(scale, 1);
  275. ScaleTransform scaleTransform = new ScaleTransform
  276. {
  277. ScaleX = scale,
  278. ScaleY = scale
  279. };
  280. tg.Children.Add(scaleTransform);
  281. }
  282. }
  283. else
  284. {
  285. TransformGroup transformGroup = new TransformGroup();
  286. ScaleTransform scaleTransform = new ScaleTransform();
  287. scaleTransform.ScaleX = 1;
  288. scaleTransform.ScaleY = 1;
  289. transformGroup.Children.Add(scaleTransform);
  290. canvas.RenderTransform = transformGroup;
  291. }
  292. }
  293. }
  294. /// <summary>
  295. /// TranslateTransform是平移画布
  296. /// </summary>
  297. /// <param name="dx"></param>
  298. /// <param name="dy"></param>
  299. private void MoveElement(double dx, double dy, bool isReset = false)
  300. {
  301. //foreach (UIElement s in canvas.Children)
  302. {
  303. if (canvas.RenderTransform is TransformGroup tg)
  304. {
  305. //平移
  306. if (tg.Children.FirstOrDefault(tr => tr is TranslateTransform) is TranslateTransform ttf)
  307. {
  308. var anim1 = new DoubleAnimation(ttf.X,
  309. (isReset ? 0 : (ttf.X + dx)),
  310. TimeSpan.FromSeconds(.01))
  311. { EasingFunction = new SineEase() };
  312. var anim2 = new DoubleAnimation(ttf.Y, (isReset ? 0 : (ttf.Y + dy)), TimeSpan.FromSeconds(.01)) { EasingFunction = new SineEase() };
  313. ttf.BeginAnimation(TranslateTransform.XProperty, anim1);
  314. ttf.BeginAnimation(TranslateTransform.YProperty, anim2);
  315. }
  316. else
  317. {
  318. TranslateTransform ttfNew = new TranslateTransform
  319. {
  320. // X = dx,
  321. // Y = dy
  322. };
  323. var anim1 = new DoubleAnimation(0, dx, TimeSpan.FromSeconds(.2)) { EasingFunction = new SineEase() };
  324. var anim2 = new DoubleAnimation(0, dy, TimeSpan.FromSeconds(.2)) { EasingFunction = new SineEase() };
  325. ttfNew.BeginAnimation(TranslateTransform.XProperty, anim1);
  326. ttfNew.BeginAnimation(TranslateTransform.YProperty, anim2);
  327. tg.Children.Add(ttfNew);
  328. }
  329. }
  330. else
  331. {
  332. TransformGroup transformGroup = new TransformGroup();
  333. TranslateTransform translateTransform = new TranslateTransform();
  334. //translateTransform.X = dx;
  335. //translateTransform.Y = dy;
  336. var anim1 = new DoubleAnimation(0, dx, TimeSpan.FromSeconds(.1)) { EasingFunction = new SineEase() };
  337. var anim2 = new DoubleAnimation(0, dy, TimeSpan.FromSeconds(.1)) { EasingFunction = new SineEase() };
  338. translateTransform.BeginAnimation(TranslateTransform.XProperty, anim1);
  339. translateTransform.BeginAnimation(TranslateTransform.YProperty, anim2);
  340. transformGroup.Children.Add(translateTransform);
  341. ScaleTransform scaleTransform = new ScaleTransform
  342. {
  343. ScaleX = 1,
  344. ScaleY = 1
  345. };
  346. // transformGroup.Children.Add(scaleTransform);
  347. canvas.RenderTransform = transformGroup;
  348. }
  349. }
  350. }
  351. /// <summary>
  352. /// 选择并删除虚拟墙
  353. /// </summary>
  354. /// <param name="sender"></param>
  355. /// <param name="e"></param>
  356. private void canvas_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  357. {
  358. Point point = e.GetPosition(canvas);
  359. if (m_isDraw == false)//擦除线
  360. {
  361. foreach (var canvasChild in this.canvas.Children)
  362. {
  363. if (canvasChild is WPolyline line)
  364. {
  365. for (int i = 0; i < line.Points.Count - 1; i++)
  366. {
  367. if (PointIsInLine(point, line.Points[i], line.Points[i + 1], 4))
  368. {
  369. //黑线与蓝线不能删除,红线直接删除,绿线删除需记录
  370. if (line.Stroke == Brushes.Red)
  371. {
  372. canvas.Children.Remove(line);
  373. btnSave.IsEnabled = true;
  374. }
  375. else if (line.Stroke == Brushes.Green)
  376. {
  377. DeletedPolylines.Add((int)line.Tag);
  378. canvas.Children.Remove(line);
  379. btnSave.IsEnabled = true;
  380. }
  381. return;
  382. }
  383. }
  384. }
  385. }
  386. }
  387. }
  388. private bool? m_isDraw = null;
  389. /// <summary>
  390. /// 开始画图
  391. /// </summary>
  392. /// <param name="sender"></param>
  393. /// <param name="e"></param>
  394. private void btnDraw_Click(object sender, RoutedEventArgs e)
  395. {
  396. if (m_isDraw != true)
  397. {
  398. m_isDraw = true;
  399. this.Cursor = Cursors.Pen;
  400. }
  401. else
  402. {
  403. m_isDraw = null;
  404. this.Cursor = Cursors.Hand;
  405. }
  406. }
  407. /// <summary>
  408. ///
  409. /// 开始删除操作
  410. /// </summary>
  411. /// <param name="sender"></param>
  412. /// <param name="e"></param>
  413. private void btnClear_Click(object sender, RoutedEventArgs e)
  414. {
  415. m_isDraw = false;
  416. this.Cursor = Cursors.Cross;
  417. }
  418. /// <summary>
  419. /// 判断点是否在直线上
  420. /// </summary>
  421. /// <param name="pf"></param>
  422. /// <param name="p1"></param>
  423. /// <param name="p2"></param>
  424. /// <param name="range"></param>
  425. /// <returns></returns>
  426. public static bool PointIsInLine(Point pf, Point p1, Point p2, double range = 0)
  427. {
  428. //range 判断的的误差,不需要误差则赋值0
  429. //点在线段首尾两端之外则return false
  430. double cross = (p2.X - p1.X) * (pf.X - p1.X) + (p2.Y - p1.Y) * (pf.Y - p1.Y);
  431. if (cross <= 0) return false;
  432. double d2 = (p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y);
  433. if (cross >= d2) return false;
  434. double r = cross / d2;
  435. double px = p1.X + (p2.X - p1.X) * r;
  436. double py = p1.Y + (p2.Y - p1.Y) * r;
  437. //判断距离是否小于误差
  438. return Math.Sqrt((pf.X - px) * (pf.X - px) + (py - pf.Y) * (py - pf.Y)) <= range;
  439. }
  440. /// <summary>
  441. /// 创建虚拟墙
  442. /// </summary>
  443. /// <param name="xyzs"></param>
  444. /// <param name="brush"></param>
  445. /// <param name="thinkness"></param>
  446. /// <returns></returns>
  447. Polyline CreateDefaultPolyLine(List<Point> xyzs, Brush brush, double thinkness = 2)
  448. {
  449. var pl = new Polyline
  450. {
  451. Stroke = brush,
  452. StrokeThickness = thinkness,
  453. StrokeStartLineCap = PenLineCap.Flat,
  454. StrokeEndLineCap = PenLineCap.Flat,
  455. StrokeLineJoin = PenLineJoin.Round
  456. };
  457. this.AddPoints(xyzs, pl);
  458. canvas.Children.Add(pl);
  459. return pl;
  460. }
  461. /// <summary>
  462. /// 添加虚拟墙的点
  463. /// </summary>
  464. /// <param name="lstPt"></param>
  465. /// <param name="pl"></param>
  466. void AddPoints(IEnumerable<Point> lstPt, Polyline pl)
  467. {
  468. foreach (var pt in lstPt)
  469. {
  470. pl.Points.Add(MovePoint(new Point(pt.X, pt.Y)));
  471. }
  472. }
  473. /// <summary>
  474. /// 将画布坐标转换为Revit坐标
  475. /// </summary>
  476. /// <param name="point"></param>
  477. /// <returns></returns>
  478. XYZ WpfPointToReivt(Point point)
  479. {
  480. return new XYZ(((point.X - 20) / m_scale + m_minX), ((point.Y - 20) / (-m_scale) + (m_maxY)), 0);
  481. }
  482. /// <summary>
  483. /// 保存所画的线
  484. /// </summary>
  485. /// <param name="sender"></param>
  486. /// <param name="e"></param>
  487. private void btnSave_Click(object sender, RoutedEventArgs e)
  488. {
  489. m_isAsynFinished = false;
  490. //禁用界面,防止重复提交
  491. this.IsEnabled = false;
  492. m_isDraw = null;
  493. //需要保存的分隔符数据
  494. List<PointPair> saveDatas = new List<PointPair>();
  495. //取出所有的线
  496. for (var j = 0; j < this.canvas.Children.Count; j++)
  497. {
  498. var child = this.canvas.Children[j];
  499. if (child is WPolyline line && line.Stroke == Brushes.Red)
  500. {
  501. for (int i = 0; i < line.Points.Count - 1; i++)
  502. {
  503. //创建新的虚拟墙
  504. var newLine = new Polyline()
  505. {
  506. Stroke = Brushes.Green,
  507. StrokeThickness = 2,
  508. };
  509. newLine.Points.Add(line.Points[i]);
  510. newLine.Points.Add(line.Points[i + 1]);
  511. //将现有坐标转化
  512. saveDatas.Add(new PointPair()
  513. {
  514. RPoint = new List<XYZ>() { WpfPointToReivt(line.Points[i]), WpfPointToReivt(line.Points[i + 1]) },
  515. ShowLine = newLine
  516. });
  517. this.canvas.Children.Add(newLine);
  518. }
  519. //删除现有的虚拟墙
  520. this.canvas.Children.Remove(line);
  521. j = -1;
  522. }
  523. }
  524. //保存数据到Revit,创建空间分隔符
  525. var doc = m_document;
  526. ExecuteCmd.ExecuteCommand(() =>
  527. {
  528. Logs.Log($"空间分隔符开始");
  529. var create = new CreateSpaceCommand();
  530. //创建空间分隔符
  531. create.CreateSpaceSeqarate(doc, saveDatas, DeletedPolylines);
  532. //删除已有的空间分隔符
  533. DeletedPolylines.Clear();
  534. Logs.Log($"空间分隔符结束");
  535. // btnSaveToRevit.IsEnabled = true;
  536. return Result.Succeeded;
  537. });
  538. //保存后重新创建空间,并加载空间分隔符与空间数据
  539. CreateSpaceAndReload(doc, () =>
  540. {
  541. WinConfirm confirm = new WinConfirm()
  542. {
  543. ShowMessage = "空间已发生变化,是否现在就上传模型并计算空间?",
  544. TTitle = "空间计算确认",
  545. BtnSure = "上传模型并计算空间",
  546. BtnCancel = "暂不计算",
  547. Owner=this,
  548. };
  549. var result = confirm.ShowDialog();
  550. //选择以后界面可用
  551. this.IsEnabled = true;
  552. if (result == true)
  553. {
  554. // 由于上传需要关闭所有模型,所以这里需要对所有数据进行清空
  555. this.canvas.Children.Clear();
  556. //添加默认提示
  557. CanvasDefaultTips();
  558. lbSpaces.ItemsSource = new ObservableCollection<MSpace>();
  559. WinModeInfoMaintenance.GetWindow().Hide();
  560. m_isCreaded = true;
  561. return false;
  562. }
  563. else
  564. {
  565. return true;
  566. }
  567. });
  568. timer = new DispatcherTimer();
  569. timer.Tick += Timer_Elapsed;
  570. timer.Interval = TimeSpan.FromMilliseconds(1000);
  571. timer.Start();
  572. }
  573. private bool m_isCreaded = false;//是否上传数据的标志,用于定时器
  574. private bool m_isAsynFinished = false;
  575. private void Timer_Elapsed(object sender, EventArgs e)
  576. {
  577. if (m_isAsynFinished)
  578. {
  579. //所有的操作只在这里进行保存
  580. m_document.Save();
  581. Logs.Log($"{DateTime.Now}被保存!!!!!!!!!!!!!!!!!!");
  582. if (m_isCreaded)
  583. {
  584. //放在命令里面
  585. //ExecuteCmd.ExecuteCommand(() =>
  586. //{
  587. try
  588. {
  589. string str = "";
  590. UploadModeCommand command = new UploadModeCommand();
  591. command.Execute(null, ref str, null);
  592. }
  593. catch (Exception exception)
  594. {
  595. Console.WriteLine(exception);
  596. MessageBox.Show(exception.Message);
  597. }
  598. // return Result.Succeeded;
  599. //});
  600. m_isCreaded = false;
  601. }
  602. timer.Stop();
  603. m_isAsynFinished = false;
  604. }
  605. }
  606. /// <summary>
  607. /// 离开画布,改变鼠标样式
  608. /// </summary>
  609. /// <param name="sender"></param>
  610. /// <param name="e"></param>
  611. private void canvas_MouseLeave(object sender, MouseEventArgs e)
  612. {
  613. this.Cursor = Cursors.Arrow;
  614. }
  615. /// <summary>
  616. /// 鼠标进入画布,改变鼠标样式
  617. /// </summary>
  618. /// <param name="sender"></param>
  619. /// <param name="e"></param>
  620. private void canvas_MouseEnter(object sender, MouseEventArgs e)
  621. {
  622. if (m_isDraw == true)
  623. {
  624. this.Cursor = Cursors.Pen;
  625. }
  626. else if (m_isDraw == false)
  627. {
  628. this.Cursor = Cursors.Cross;
  629. }
  630. else
  631. {
  632. this.Cursor = Cursors.Hand;
  633. }
  634. }
  635. /// <summary>
  636. /// 鼠标右键,结束画线
  637. /// </summary>
  638. /// <param name="sender"></param>
  639. /// <param name="e"></param>
  640. private void canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
  641. {
  642. if (m_polyline == null || m_isDraw != true) return;
  643. //结束,调整最后一个点,让其自动附着
  644. m_polyline.Points[m_polyline.Points.Count - 1] = GeometryHelper.ConvertOnLinePoint(m_polyline.Points[m_polyline.Points.Count - 1], canvas, m_polyline);
  645. m_polyline = null;
  646. m_flag = false;
  647. }
  648. private void viewer_MouseWheel(object sender, MouseWheelEventArgs e)
  649. {
  650. double val = (double)e.Delta / 2000; //描述鼠标滑轮滚动
  651. // scaleValue += val;
  652. var center = e.GetPosition(this.canvas);
  653. //if (center.X <= 0 || center.Y <= 0) {
  654. // return;
  655. //}
  656. MoveElement(val, center);
  657. }
  658. /// <summary>
  659. /// 鼠标up事件,获取鼠标抬起的位置,并根据移动距离平移画布
  660. /// </summary>
  661. /// <param name="sender"></param>
  662. /// <param name="e"></param>
  663. private void viewer_MouseUp(object sender, MouseButtonEventArgs e)
  664. {
  665. //如果按下的是中键
  666. if (e.ChangedButton == MouseButton.Middle)
  667. {
  668. Point position = e.GetPosition(viewer);
  669. var tempx = position.X - this.m_previousMousePoint.X;
  670. var tempy = position.Y - this.m_previousMousePoint.Y;
  671. //平移画布
  672. MoveElement(tempx, tempy);
  673. }
  674. }
  675. /// <summary>
  676. /// 鼠标down事件,获取点击初始位置
  677. /// </summary>
  678. /// <param name="sender"></param>
  679. /// <param name="e"></param>
  680. private void viewer_MouseDown(object sender, MouseButtonEventArgs e)
  681. {
  682. if (e.ChangedButton == MouseButton.Middle)
  683. {
  684. m_previousMousePoint = e.GetPosition(viewer);
  685. btnSave.IsEnabled = true;
  686. }
  687. }
  688. /// <summary>
  689. /// 鼠标中键滚轮事件,控制canvas的缩放
  690. /// </summary>
  691. /// <param name="sender"></param>
  692. /// <param name="e"></param>
  693. private void viewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
  694. {
  695. double val = (double)e.Delta / 2000; //描述鼠标滑轮滚动
  696. var center = e.GetPosition(this.canvas);
  697. MoveElement(val, center);
  698. }
  699. private string m_curFloorId = "";//当前选择项楼层Id
  700. private Document m_document;//当前操作的模型
  701. /// <summary>
  702. /// 楼层切换
  703. /// </summary>
  704. /// <param name="sender"></param>
  705. /// <param name="e"></param>
  706. private void Tv_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
  707. {
  708. //检测是否有未保存的数据,数据分两部分:新建的空间分隔符,删除的空间分隔符
  709. #region 切换前节点处理
  710. if (DeletedPolylines.Count > 0 || this.canvas.Children.OfType<UIElement>().Any(el => (el is WPolyline line && line.Stroke == Brushes.Red)))
  711. {
  712. WinConfirm confirm = new WinConfirm()
  713. {
  714. ShowMessage = "尚未保存空间变化,确认放弃修改?",
  715. TTitle = "空间修改确认",
  716. BtnSure = "保存并更改模型",
  717. BtnCancel = "放弃修改"
  718. };
  719. var result = confirm.ShowDialog();
  720. if (result == true)
  721. {
  722. btnSave_Click(null, null);
  723. return;
  724. }
  725. DeletedPolylines.Clear();
  726. }
  727. #endregion
  728. if (tv.SelectedItem is TreeNodeItem item && item.Item is MFloor floor)
  729. {
  730. try
  731. {
  732. //关闭空间属性窗
  733. WinModeInfoMaintenance.GetWindow().Hide();
  734. m_curFloorId = floor.Id;
  735. this.canvas.Children.Clear();
  736. this.canvas.IsEnabled = false;
  737. this.lbSpaces.ItemsSource = null;
  738. //模型文件路径
  739. var filePath = floor.FullPath;
  740. //检测文件是否存在
  741. if (!File.Exists(filePath))
  742. {
  743. MessageBox.Show("无法找到相关模型文件!");
  744. return;
  745. }
  746. //加载模型文件并激活
  747. // var uiDoc = ExternalDataWrapper.Current.App.OpenDocumentFile(filePath);
  748. Logs.Log("加载模型开始");
  749. var uiDoc = ExternalDataWrapper.Current.UiApp.OpenAndActivateDocument(filePath);
  750. Logs.Log("加载模型结束");
  751. var doc = uiDoc.Document;
  752. m_document = doc;
  753. var view = doc.GetElements<ViewPlan>().FirstOrDefault(t => t.GenLevel?.Name != null && t.Name?.IndexOf("-saga") > -1 && t.ViewType == ViewType.FloorPlan);
  754. if (view == null)
  755. {
  756. MessageBox.Show("无法找到名称以-saga结尾的视图!");
  757. return;
  758. }
  759. bool result = LoadData();
  760. if (!result)
  761. {
  762. MessageBox.Show("模型文件没有找到相关数据!");
  763. return;
  764. }
  765. this.canvas.IsEnabled = true;
  766. //重置画布
  767. btnOrigin_Click(null, null);
  768. //缓存所有空间数据
  769. m_spacesCache = SpaceConvert.GetFloorSpaceInfos(m_curFloorId).OfType<MSpace>().ToList();
  770. //创建空间
  771. //检测日志,是否有墙,虚拟墙,柱子数据的改变
  772. CreateSpaceAndReload(doc, InitData);
  773. }
  774. catch (Exception ex)
  775. {
  776. MessageBox.Show(ex.Message);
  777. }
  778. }
  779. }
  780. /// <summary>
  781. /// 创建空间并重新加载到列表
  782. /// </summary>
  783. /// <param name="doc"></param>
  784. /// <param name="callback">异步回调函数</param>
  785. private void CreateSpaceAndReload(Document doc, Func<bool> callback)
  786. {
  787. ExecuteCmd.ExecuteCommand(() =>
  788. {
  789. Logs.Log($"创建空间开始");
  790. //生成空间
  791. CreateSpaceCommand cmd = new CreateSpaceCommand();
  792. cmd.CreateSpace(doc);
  793. // doc.Regenerate();
  794. Logs.Log($"创建空间结束");
  795. return Result.Succeeded;
  796. });
  797. //因为异步执行,获取空间不能直接放到下面
  798. //删除冲突的空间
  799. ExecuteCmd.ExecuteCommand(() =>
  800. {
  801. Logs.Log($"删除空间开始");
  802. // DeleteFailuresPreprocessorData(doc);
  803. DeleteFailuresPreprocessorDataByManual(doc);
  804. //保存数据
  805. // doc.Save();
  806. bool? isReload = callback?.Invoke();
  807. if (isReload == true)
  808. {
  809. try
  810. {
  811. //加载空间
  812. var spaces = doc.GetElements<SpatialElement>().Where(s => s is Autodesk.Revit.DB.Mechanical.Space && s.Area > 0).ToList();
  813. //创建空间轮廓,这里必须放在初始化之后创建
  814. CreateAllSpaceSeq(spaces);
  815. //创建右侧空间树
  816. ShowSpacesListFrowServer(spaces);
  817. }
  818. catch (Exception e)
  819. {
  820. MessageBox.Show(e.Message);
  821. }
  822. }
  823. m_isAsynFinished = true;
  824. //btnSaveToRevit.IsEnabled = true;
  825. try
  826. {
  827. Logs.Log($"删除空间结束");
  828. doc.Save();
  829. DocumentChangedLog.RemoveInvalidLogs();
  830. }
  831. catch (Exception e)
  832. {
  833. MessageBox.Show(e.Message);
  834. }
  835. return Result.Succeeded;
  836. });
  837. }
  838. /// <summary>
  839. /// 创建边线
  840. /// </summary>
  841. /// <param name="spaces"></param>
  842. void CreateAllSpaceSeq(List<SpatialElement> spaces)
  843. {
  844. //清除已有的空间边线
  845. for (int i = 0; i < this.canvas.Children.Count; i++)
  846. {
  847. if (this.canvas.Children[i] is WPolyline line && line.Tag is Autodesk.Revit.DB.Mechanical.Space)
  848. {
  849. this.canvas.Children.RemoveAt(i);
  850. i -= 1;
  851. }
  852. }
  853. spaces.ForEach(s => CreateSpaceBoundary(s as Autodesk.Revit.DB.Mechanical.Space));
  854. }
  855. /// <summary>
  856. /// 获取所有空间对应的服务器端的信息
  857. /// </summary>
  858. /// <param name="spaces"></param>
  859. private void ShowSpacesListFrowServer(List<SpatialElement> spaces)
  860. {
  861. // var infosjobj = ConvertElementsToJArray(spaces);
  862. //var datas = CommonConvert.QueryObjectInfoByIds(m_curFloorId, infosjobj).OfType<MSpace>().ToList();
  863. var datas = GetSpaceFromCacheByIds(spaces.Select(t => t.Id).ToList());
  864. var localSpace = spaces.Where(t => !datas.Any(s => s.BimID.Split(':')[1] == t.Id.ToString()))
  865. .Select(t => new MSpace("", $"{Guid.NewGuid()}:{t.Id.ToString()}") { Name = t.Name });
  866. datas.AddRange(localSpace);
  867. //List<string> dd;
  868. //dd.AddRange();
  869. lbSpaces.ItemsSource = new ObservableCollection<MSpace>(datas);
  870. }
  871. /// <summary>
  872. /// 手动删除冲突的空间
  873. /// </summary>
  874. /// <param name="doc"></param>
  875. private void DeleteFailuresPreprocessorDataByManual(Document doc)
  876. {
  877. bool isReCreate = false;
  878. using (Transaction trans = new Transaction(doc, "删除多余的空间"))
  879. {
  880. trans.Start();
  881. try
  882. {
  883. //处理异常显示
  884. FailureHandlingOptions fho = trans.GetFailureHandlingOptions();
  885. fho.SetFailuresPreprocessor(new FailuresPreprocessor(false));
  886. trans.SetFailureHandlingOptions(fho);
  887. List<ServerSpace> serverSpaces = new List<ServerSpace>();
  888. Regex regex = new Regex("^\\d+$");
  889. var index = 1;
  890. //对冲突的空间进行删除
  891. foreach (List<ElementId> elementIds in StaticData.FailuresPreprocessorData)
  892. {
  893. Logs.Log(string.Join("-", elementIds));
  894. //取出空间的服务器信息
  895. var spacesServerInfo = GetSpaceFromCacheByIds(elementIds);
  896. //如果返回值小于等于1,自动处理
  897. //如果返回值大于1,则在界面处理
  898. if (spacesServerInfo == null || spacesServerInfo.Count == 0)
  899. {
  900. var firstElement = doc.GetElement(elementIds.FirstOrDefault());
  901. //对所有冲突的空间编号进行比较,保留较小编号的空间
  902. if (firstElement is Autodesk.Revit.DB.Mechanical.Space first)
  903. {
  904. foreach (var id in elementIds)
  905. {
  906. if (first.Id.IsEqual(id))
  907. continue;
  908. var curr = doc.GetElement(id) as Autodesk.Revit.DB.Mechanical.Space;
  909. Logs.Log("=============");
  910. Logs.Log($"当前空间Id:{id},Num:{curr.Number}");
  911. //如果编号非数字,删其中一个
  912. if (!regex.IsMatch(first.Number))
  913. {
  914. doc.Delete(new List<ElementId>() { first.Id });
  915. first = curr;
  916. continue;
  917. }
  918. if (!regex.IsMatch(curr.Number))
  919. {
  920. doc.Delete(new List<ElementId>() { id });
  921. continue;
  922. }
  923. if (int.Parse(first.Number) > int.Parse(curr.Number))
  924. {
  925. Logs.Log($"1.被删除的空间Id:{id},Num:{first.Number}");
  926. doc.Delete(new List<ElementId>() { first.Id });
  927. first = curr;
  928. }
  929. else
  930. {
  931. Logs.Log($"2.被删除的空间Id:{id},Num:{curr.Number}");
  932. doc.Delete(new List<ElementId>() { id });
  933. }
  934. Logs.Log("=============");
  935. }
  936. }
  937. }
  938. else if (spacesServerInfo.Count == 1)
  939. {
  940. var serverSpaceId = spacesServerInfo[0].BimID.Split(':')[1];
  941. doc.Delete(elementIds.Where(t => t.ToString() != serverSpaceId).ToList());
  942. }
  943. else
  944. {
  945. doc.Delete(elementIds.Where(t => !spacesServerInfo.Exists(sp => sp.BimID.Split(':')[1] == t.ToString())).ToList());
  946. var groupName = $"待合并元空间组{index}";
  947. foreach (var mRevitEquipBase in spacesServerInfo)
  948. {
  949. if (mRevitEquipBase is MSpace space)
  950. {
  951. serverSpaces.Add(new ServerSpace()
  952. {
  953. Space = space,
  954. GroupName = groupName
  955. });
  956. }
  957. }
  958. serverSpaces.Add(new ServerSpace()
  959. {
  960. Name = "不保留已有空间,创建新空间",
  961. GroupName = groupName
  962. });
  963. index++;
  964. }
  965. }
  966. if (serverSpaces.Count > 0)
  967. {
  968. var winDeal = new WinSelectSpace(serverSpaces);
  969. var result = winDeal.ShowDialog();
  970. if (result == true)
  971. {
  972. var ids = winDeal.DeleteElementIds.Select(t => new ElementId(int.Parse(t))).ToList();
  973. doc.Delete(ids);
  974. isReCreate = winDeal.IsReCreate;
  975. }
  976. }
  977. //提交事务
  978. trans.Commit();
  979. }
  980. catch (Exception e)
  981. {
  982. //回滚事务
  983. trans.RollBack();
  984. }
  985. }
  986. StaticData.FailuresPreprocessorData.Clear();
  987. if (isReCreate) CreateSpaceAndReload(doc, null);
  988. }
  989. /// <summary>
  990. /// 加载模型数据
  991. /// </summary>
  992. private bool LoadData()
  993. {
  994. var doc = m_document;
  995. //读取墙数据
  996. List<Wall> walls = doc.FilterElements<Wall>().ToList();
  997. if (walls.Count == 0) return false;
  998. // List<List<XYZ>> wallData = GroupWallByParallel(walls);//太慢改为直接获取墙线
  999. //获取虚拟墙(空间分隔符或者房间分隔符)
  1000. var wallData = walls.Select(t => t.GetCurve().Tessellate().ToList()).ToList();
  1001. var virWalls = doc.FilterElements<CurveElement>((line) =>
  1002. {
  1003. var categoryId = line.Category.Id.IntegerValue;
  1004. return categoryId == (int)BuiltInCategory.OST_MEPSpaceSeparationLines ||
  1005. categoryId == (int)BuiltInCategory.OST_RoomSeparationLines;
  1006. }).Where(line => line is ModelLine).Select(line =>
  1007. {
  1008. var ml = line as ModelLine;
  1009. var mlLine = ml.Location.GetLine();
  1010. //return new SgLine(mlLine.StartPoint().ToW2DPoint(), mlLine.EndPoint().ToW2DPoint()); //return new SgLine(mlLine.StartPoint().ToW2DPoint(), mlLine.EndPoint().ToW2DPoint());
  1011. return
  1012. new PointPair(ml.Id.IntegerValue, new List<System.Windows.Point>()
  1013. {
  1014. mlLine.StartPoint().ToW2DPoint(),
  1015. mlLine.EndPoint().ToW2DPoint()
  1016. });
  1017. }).ToList();
  1018. //获取所有建筑柱子
  1019. var columns = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_Columns);
  1020. //结构柱
  1021. var stColumns = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_StructuralColumns);
  1022. columns.AddRange(stColumns);
  1023. m_columnsLocation = columns.Select(c => c.Location.GetPoint())
  1024. .Where(t => !t.IsEqual(new XYZ(0, 0, 0), 0.000001)//TODO:临时处理
  1025. ).ToList();
  1026. this.m_wallsData = wallData;
  1027. this.m_virXyzs = virWalls;
  1028. return true;
  1029. }
  1030. /// <summary>
  1031. /// 切换空间,亮显空间
  1032. /// </summary>
  1033. /// <param name="sender"></param>
  1034. /// <param name="e"></param>
  1035. private void lbSpaces_SelectionChanged(object sender, SelectionChangedEventArgs e)
  1036. {
  1037. if (lbSpaces.SelectedItems.Count == 0) return;
  1038. var space = lbSpaces.SelectedItems[0] as MSpace;
  1039. var bimId = space.BimID.Split(':')[1];
  1040. foreach (var polyline in this.canvas.Children.OfType<WPolyline>())
  1041. {
  1042. if (polyline.Tag is Autodesk.Revit.DB.Mechanical.Space s)
  1043. {
  1044. if (s.Id.ToString() == (bimId))
  1045. {
  1046. polyline.Fill = Brushes.Aquamarine;
  1047. //显示属性窗口
  1048. ShowSpaceProperty(s);
  1049. }
  1050. else if (polyline.Fill == Brushes.Aquamarine)
  1051. {
  1052. polyline.Fill = Brushes.Transparent;
  1053. }
  1054. }
  1055. }
  1056. }
  1057. /// <summary>
  1058. /// 显示空间属性窗体
  1059. /// </summary>
  1060. /// <param name="space"></param>
  1061. private static void ShowSpaceProperty(Autodesk.Revit.DB.Mechanical.Space space)
  1062. {
  1063. MRevitEquipBase equipment = DalCommon.GetEquipmentQueryId(space);
  1064. ShowSpaceProperty(equipment);
  1065. }
  1066. private static void ShowSpaceProperty(MRevitEquipBase equipment)
  1067. {
  1068. try
  1069. {
  1070. if (equipment != null)
  1071. {
  1072. var win = WinModeInfoMaintenanceForSpace.GetWindow();
  1073. win.Topmost = true;
  1074. win.Show(equipment);
  1075. win.Visibility = Visibility.Visible;
  1076. }
  1077. }
  1078. catch (Exception e)
  1079. {
  1080. MessageBox.Show("显示属性窗口出错" + e.Message, "系统提示");
  1081. }
  1082. }
  1083. /// <summary>
  1084. /// 从缓存获取空间信息
  1085. /// </summary>
  1086. /// <param name="ids"></param>
  1087. /// <returns></returns>
  1088. private List<MSpace> GetSpaceFromCacheByIds(List<ElementId> ids)
  1089. {
  1090. if (m_spacesCache != null)
  1091. return m_spacesCache.Where(s => ids.Exists(id => id.ToString() == s.BimID.Split(':')[1])).ToList();
  1092. return new List<MSpace>();
  1093. }
  1094. /// <summary>
  1095. /// 创建空间边缘轮廓
  1096. /// </summary>
  1097. /// <param name="space"></param>
  1098. private void CreateSpaceBoundary(Autodesk.Revit.DB.Mechanical.Space space)
  1099. {
  1100. if (space == null) return;
  1101. //过滤未放置空间
  1102. if (space.Area.IsEqual(0, 0.0001)) return;
  1103. //取出边缘
  1104. var mySegments = space.GetBoundarySegments(new SpatialElementBoundaryOptions());
  1105. var seg = mySegments.FirstOrDefault();
  1106. if (seg == null)
  1107. {
  1108. MessageBox.Show(space.Id.IntegerValue + "");
  1109. return;
  1110. }
  1111. List<Point> datas = new List<Point>();
  1112. foreach (BoundarySegment segment in seg)
  1113. {
  1114. datas.AddRange(segment.GetCurve().Tessellate().Select(xyz => xyz.ToW2DPoint()).ToList());
  1115. }
  1116. var polyLine = this.CreateDefaultPolyLine(datas, Brushes.Transparent);
  1117. polyLine.Tag = space;//此处比较重要,这个是判断曲线是否为轮廓线的关键
  1118. polyLine.Fill = Brushes.Transparent;
  1119. polyLine.MouseLeftButtonDown += PolyLine_MouseDown;
  1120. }
  1121. /// <summary>
  1122. /// 空间轮廓点击事件
  1123. /// </summary>
  1124. /// <param name="sender"></param>
  1125. /// <param name="e"></param>
  1126. private void PolyLine_MouseDown(object sender, MouseButtonEventArgs e)
  1127. {
  1128. if ((sender is WPolyline line) && m_isDraw == null)
  1129. {
  1130. //找到已亮显的空间
  1131. var showSpaces = this.canvas.Children.OfType<WPolyline>().FirstOrDefault(t => t is WPolyline l && l.Fill == Brushes.Aquamarine);
  1132. //先清除
  1133. if (showSpaces != null) showSpaces.Fill = Brushes.Transparent;
  1134. line.Fill = Brushes.Aquamarine;
  1135. //MessageBox.Show(line.Tag+"");
  1136. if (line.Tag is Autodesk.Revit.DB.Mechanical.Space space)
  1137. {
  1138. //反选右侧树
  1139. for (int i = 0; i < lbSpaces.Items.Count; i++)
  1140. {
  1141. var showSpace = lbSpaces.Items[i] as MSpace;
  1142. var spaceId = showSpace.BimID.Split(':')[1];
  1143. if (spaceId == space.Id.ToString())
  1144. {
  1145. lbSpaces.SelectedIndex = i;
  1146. break;
  1147. }
  1148. }
  1149. //显示属性板
  1150. ShowSpaceProperty(space);
  1151. }
  1152. }
  1153. }
  1154. private void btnZoomIn_Click(object sender, RoutedEventArgs e)
  1155. {
  1156. MoveElement(-0.1, new Point());
  1157. }
  1158. private void btnOrigin_Click(object sender, RoutedEventArgs e)
  1159. {
  1160. MoveElement(0.1, new Point(), isReset: true);
  1161. MoveElement(0, 0, isReset: true);
  1162. }
  1163. private void btnZoomOut_Click(object sender, RoutedEventArgs e)
  1164. {
  1165. MoveElement(0.1, new Point());
  1166. }
  1167. //创建定时器,以检测所有操作是否全部保存完成
  1168. private DispatcherTimer timer;
  1169. private void CanvasDefaultTips()
  1170. {
  1171. string tips = "请选择一个需要进行空间管理的楼层";
  1172. TextBlock txtTips = new TextBlock
  1173. {
  1174. FontSize = 21,
  1175. Width = 345,
  1176. Height = 40,
  1177. Text = tips,
  1178. Foreground = Brushes.LightCyan
  1179. };
  1180. this.canvas.Children.Add(txtTips);
  1181. Canvas.SetLeft(txtTips, this.canvas.ActualWidth / 2.0d - 160);
  1182. Canvas.SetTop(txtTips, canvas.ActualHeight / 2.0d);
  1183. }
  1184. }
  1185. /// <summary>
  1186. /// 已有空间分割线的数据实体
  1187. /// </summary>
  1188. public class PointPair
  1189. {
  1190. //空间分割线的端点(WPF)
  1191. public List<Point> Point { get; set; }
  1192. //空间分割线的端点(Revit)
  1193. public List<XYZ> RPoint { get; set; } = new List<XYZ>();
  1194. //空间分割线的Id
  1195. public int ElementId { set; get; }
  1196. //WPF中显示的线
  1197. public Polyline ShowLine { get; set; }
  1198. public PointPair()
  1199. {
  1200. }
  1201. public PointPair(int elemId, List<Point> point)
  1202. {
  1203. this.Point = point;
  1204. this.ElementId = elemId;
  1205. }
  1206. }
  1207. }