WinCreateSpace.xaml.cs 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373
  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. if (DeletedPolylines.Count > 0 || this.canvas.Children.OfType<UIElement>().Any(el => (el is WPolyline line && line.Stroke == Brushes.Red)))
  710. {
  711. WinConfirm confirm = new WinConfirm()
  712. {
  713. ShowMessage = "尚未保存空间变化,确认放弃修改?",
  714. TTitle = "空间修改确认",
  715. BtnSure = "保存并更改模型",
  716. BtnCancel = "放弃修改"
  717. };
  718. var result = confirm.ShowDialog();
  719. if (result == true)
  720. {
  721. btnSave_Click(null, null);
  722. return;
  723. }
  724. DeletedPolylines.Clear();
  725. }
  726. if (tv.SelectedItem is TreeNodeItem item && item.Item is MFloor floor)
  727. {
  728. try
  729. {
  730. //关闭空间属性窗
  731. WinModeInfoMaintenance.GetWindow().Hide();
  732. m_curFloorId = floor.Id;
  733. this.canvas.Children.Clear();
  734. this.canvas.IsEnabled = false;
  735. this.lbSpaces.ItemsSource = null;
  736. //模型文件路径
  737. var filePath = floor.FullPath;
  738. //检测文件是否存在
  739. if (!File.Exists(filePath))
  740. {
  741. MessageBox.Show("无法找到相关模型文件!");
  742. return;
  743. }
  744. //加载模型文件并激活
  745. // var uiDoc = ExternalDataWrapper.Current.App.OpenDocumentFile(filePath);
  746. Logs.Log("加载模型开始");
  747. var uiDoc = ExternalDataWrapper.Current.UiApp.OpenAndActivateDocument(filePath);
  748. Logs.Log("加载模型结束");
  749. var doc = uiDoc.Document;
  750. m_document = doc;
  751. var view = doc.GetElements<ViewPlan>().FirstOrDefault(t => t.GenLevel?.Name != null && t.Name?.IndexOf("-saga") > -1 && t.ViewType == ViewType.FloorPlan);
  752. if (view == null)
  753. {
  754. MessageBox.Show("无法找到名称以-saga结尾的视图!");
  755. return;
  756. }
  757. bool result = LoadData();
  758. if (!result)
  759. {
  760. MessageBox.Show("模型文件没有找到相关数据!");
  761. return;
  762. }
  763. this.canvas.IsEnabled = true;
  764. //重置画布
  765. btnOrigin_Click(null, null);
  766. //缓存所有空间数据
  767. m_spacesCache = SpaceConvert.GetFloorSpaceInfos(m_curFloorId).OfType<MSpace>().ToList();
  768. //创建空间
  769. //检测日志,是否有墙,虚拟墙,柱子数据的改变
  770. CreateSpaceAndReload(doc, InitData);
  771. }
  772. catch (Exception ex)
  773. {
  774. MessageBox.Show(ex.Message);
  775. }
  776. }
  777. }
  778. /// <summary>
  779. /// 创建空间并重新加载到列表
  780. /// </summary>
  781. /// <param name="doc"></param>
  782. /// <param name="callback">异步回调函数</param>
  783. private void CreateSpaceAndReload(Document doc, Func<bool> callback)
  784. {
  785. ExecuteCmd.ExecuteCommand(() =>
  786. {
  787. Logs.Log($"创建空间开始");
  788. //生成空间
  789. CreateSpaceCommand cmd = new CreateSpaceCommand();
  790. cmd.CreateSpace(doc);
  791. // doc.Regenerate();
  792. Logs.Log($"创建空间结束");
  793. return Result.Succeeded;
  794. });
  795. //因为异步执行,获取空间不能直接放到下面
  796. //删除冲突的空间
  797. ExecuteCmd.ExecuteCommand(() =>
  798. {
  799. Logs.Log($"删除空间开始");
  800. // DeleteFailuresPreprocessorData(doc);
  801. DeleteFailuresPreprocessorDataByManual(doc);
  802. //保存数据
  803. // doc.Save();
  804. bool? isReload = callback?.Invoke();
  805. if (isReload == true)
  806. {
  807. try
  808. {
  809. //加载空间
  810. var spaces = doc.GetElements<SpatialElement>().Where(s => s is Autodesk.Revit.DB.Mechanical.Space && s.Area > 0).ToList();
  811. //创建空间轮廓,这里必须放在初始化之后创建
  812. CreateAllSpaceSeq(spaces);
  813. //创建右侧空间树
  814. ShowSpacesListFrowServer(spaces);
  815. }
  816. catch (Exception e)
  817. {
  818. MessageBox.Show(e.Message);
  819. }
  820. }
  821. m_isAsynFinished = true;
  822. //btnSaveToRevit.IsEnabled = true;
  823. try
  824. {
  825. Logs.Log($"删除空间结束");
  826. doc.Save();
  827. DocumentChangedLog.RemoveInvalidLogs();
  828. }
  829. catch (Exception e)
  830. {
  831. MessageBox.Show(e.Message);
  832. }
  833. return Result.Succeeded;
  834. });
  835. }
  836. /// <summary>
  837. /// 创建边线
  838. /// </summary>
  839. /// <param name="spaces"></param>
  840. void CreateAllSpaceSeq(List<SpatialElement> spaces)
  841. {
  842. //清除已有的空间边线
  843. for (int i = 0; i < this.canvas.Children.Count; i++)
  844. {
  845. if (this.canvas.Children[i] is WPolyline line && line.Tag is Autodesk.Revit.DB.Mechanical.Space)
  846. {
  847. this.canvas.Children.RemoveAt(i);
  848. i -= 1;
  849. }
  850. }
  851. spaces.ForEach(s => CreateSpaceBoundary(s as Autodesk.Revit.DB.Mechanical.Space));
  852. }
  853. /// <summary>
  854. /// 获取所有空间对应的服务器端的信息
  855. /// </summary>
  856. /// <param name="spaces"></param>
  857. private void ShowSpacesListFrowServer(List<SpatialElement> spaces)
  858. {
  859. // var infosjobj = ConvertElementsToJArray(spaces);
  860. //var datas = CommonConvert.QueryObjectInfoByIds(m_curFloorId, infosjobj).OfType<MSpace>().ToList();
  861. var datas = GetSpaceFromCacheByIds(spaces.Select(t => t.Id).ToList());
  862. var localSpace = spaces.Where(t => !datas.Any(s => s.BimID.Split(':')[1] == t.Id.ToString()))
  863. .Select(t => new MSpace("", $"{Guid.NewGuid()}:{t.Id.ToString()}") { Name = t.Name });
  864. datas.AddRange(localSpace);
  865. //List<string> dd;
  866. //dd.AddRange();
  867. lbSpaces.ItemsSource = new ObservableCollection<MSpace>(datas);
  868. }
  869. /// <summary>
  870. /// 手动删除冲突的空间
  871. /// </summary>
  872. /// <param name="doc"></param>
  873. private void DeleteFailuresPreprocessorDataByManual(Document doc)
  874. {
  875. bool isReCreate = false;
  876. using (Transaction trans = new Transaction(doc, "删除多余的空间"))
  877. {
  878. trans.Start();
  879. try
  880. {
  881. //处理异常显示
  882. FailureHandlingOptions fho = trans.GetFailureHandlingOptions();
  883. fho.SetFailuresPreprocessor(new FailuresPreprocessor(false));
  884. trans.SetFailureHandlingOptions(fho);
  885. List<ServerSpace> serverSpaces = new List<ServerSpace>();
  886. Regex regex = new Regex("^\\d+$");
  887. var index = 1;
  888. //对冲突的空间进行删除
  889. foreach (List<ElementId> elementIds in StaticData.FailuresPreprocessorData)
  890. {
  891. Logs.Log(string.Join("-", elementIds));
  892. //取出空间的服务器信息
  893. var spacesServerInfo = GetSpaceFromCacheByIds(elementIds);
  894. //如果返回值小于等于1,自动处理
  895. //如果返回值大于1,则在界面处理
  896. if (spacesServerInfo == null || spacesServerInfo.Count == 0)
  897. {
  898. var firstElement = doc.GetElement(elementIds.FirstOrDefault());
  899. //对所有冲突的空间编号进行比较,保留较小编号的空间
  900. if (firstElement is Autodesk.Revit.DB.Mechanical.Space first)
  901. {
  902. foreach (var id in elementIds)
  903. {
  904. if (first.Id.IsEqual(id))
  905. continue;
  906. var curr = doc.GetElement(id) as Autodesk.Revit.DB.Mechanical.Space;
  907. Logs.Log("=============");
  908. Logs.Log($"当前空间Id:{id},Num:{curr.Number}");
  909. //如果编号非数字,删其中一个
  910. if (!regex.IsMatch(first.Number))
  911. {
  912. doc.Delete(new List<ElementId>() { first.Id });
  913. first = curr;
  914. continue;
  915. }
  916. if (!regex.IsMatch(curr.Number))
  917. {
  918. doc.Delete(new List<ElementId>() { id });
  919. continue;
  920. }
  921. if (int.Parse(first.Number) > int.Parse(curr.Number))
  922. {
  923. Logs.Log($"1.被删除的空间Id:{id},Num:{first.Number}");
  924. doc.Delete(new List<ElementId>() { first.Id });
  925. first = curr;
  926. }
  927. else
  928. {
  929. Logs.Log($"2.被删除的空间Id:{id},Num:{curr.Number}");
  930. doc.Delete(new List<ElementId>() { id });
  931. }
  932. Logs.Log("=============");
  933. }
  934. }
  935. }
  936. else if (spacesServerInfo.Count == 1)
  937. {
  938. var serverSpaceId = spacesServerInfo[0].BimID.Split(':')[1];
  939. doc.Delete(elementIds.Where(t => t.ToString() != serverSpaceId).ToList());
  940. }
  941. else
  942. {
  943. doc.Delete(elementIds.Where(t => !spacesServerInfo.Exists(sp => sp.BimID.Split(':')[1] == t.ToString())).ToList());
  944. var groupName = $"待合并元空间组{index}";
  945. foreach (var mRevitEquipBase in spacesServerInfo)
  946. {
  947. if (mRevitEquipBase is MSpace space)
  948. {
  949. serverSpaces.Add(new ServerSpace()
  950. {
  951. Space = space,
  952. GroupName = groupName
  953. });
  954. }
  955. }
  956. serverSpaces.Add(new ServerSpace()
  957. {
  958. Name = "不保留已有空间,创建新空间",
  959. GroupName = groupName
  960. });
  961. index++;
  962. }
  963. }
  964. if (serverSpaces.Count > 0)
  965. {
  966. var winDeal = new WinSelectSpace(serverSpaces);
  967. var result = winDeal.ShowDialog();
  968. if (result == true)
  969. {
  970. var ids = winDeal.DeleteElementIds.Select(t => new ElementId(int.Parse(t))).ToList();
  971. doc.Delete(ids);
  972. isReCreate = winDeal.IsReCreate;
  973. }
  974. }
  975. //提交事务
  976. trans.Commit();
  977. }
  978. catch (Exception e)
  979. {
  980. //回滚事务
  981. trans.RollBack();
  982. }
  983. }
  984. StaticData.FailuresPreprocessorData.Clear();
  985. if (isReCreate) CreateSpaceAndReload(doc, null);
  986. }
  987. /// <summary>
  988. /// 加载模型数据
  989. /// </summary>
  990. private bool LoadData()
  991. {
  992. var doc = m_document;
  993. //读取墙数据
  994. List<Wall> walls = doc.FilterElements<Wall>().ToList();
  995. if (walls.Count == 0) return false;
  996. // List<List<XYZ>> wallData = GroupWallByParallel(walls);//太慢改为直接获取墙线
  997. //获取虚拟墙(空间分隔符或者房间分隔符)
  998. var wallData = walls.Select(t => t.GetCurve().Tessellate().ToList()).ToList();
  999. var virWalls = doc.FilterElements<CurveElement>((line) =>
  1000. {
  1001. var categoryId = line.Category.Id.IntegerValue;
  1002. return categoryId == (int)BuiltInCategory.OST_MEPSpaceSeparationLines ||
  1003. categoryId == (int)BuiltInCategory.OST_RoomSeparationLines;
  1004. }).Where(line => line is ModelLine).Select(line =>
  1005. {
  1006. var ml = line as ModelLine;
  1007. var mlLine = ml.Location.GetLine();
  1008. //return new SgLine(mlLine.StartPoint().ToW2DPoint(), mlLine.EndPoint().ToW2DPoint()); //return new SgLine(mlLine.StartPoint().ToW2DPoint(), mlLine.EndPoint().ToW2DPoint());
  1009. return
  1010. new PointPair(ml.Id.IntegerValue, new List<System.Windows.Point>()
  1011. {
  1012. mlLine.StartPoint().ToW2DPoint(),
  1013. mlLine.EndPoint().ToW2DPoint()
  1014. });
  1015. }).ToList();
  1016. //获取所有建筑柱子
  1017. var columns = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_Columns);
  1018. //结构柱
  1019. var stColumns = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_StructuralColumns);
  1020. columns.AddRange(stColumns);
  1021. m_columnsLocation = columns.Select(c => c.Location.GetPoint())
  1022. .Where(t => !t.IsEqual(new XYZ(0, 0, 0), 0.000001)//TODO:临时处理
  1023. ).ToList();
  1024. this.m_wallsData = wallData;
  1025. this.m_virXyzs = virWalls;
  1026. return true;
  1027. }
  1028. /// <summary>
  1029. /// 切换空间,亮显空间
  1030. /// </summary>
  1031. /// <param name="sender"></param>
  1032. /// <param name="e"></param>
  1033. private void lbSpaces_SelectionChanged(object sender, SelectionChangedEventArgs e)
  1034. {
  1035. if (lbSpaces.SelectedItems.Count == 0) return;
  1036. var space = lbSpaces.SelectedItems[0] as MSpace;
  1037. var bimId = space.BimID.Split(':')[1];
  1038. foreach (var polyline in this.canvas.Children.OfType<WPolyline>())
  1039. {
  1040. if (polyline.Tag is Autodesk.Revit.DB.Mechanical.Space s)
  1041. {
  1042. if (s.Id.ToString() == (bimId))
  1043. {
  1044. polyline.Fill = Brushes.Aquamarine;
  1045. //显示属性窗口
  1046. ShowSpaceProperty(s);
  1047. }
  1048. else if (polyline.Fill == Brushes.Aquamarine)
  1049. {
  1050. polyline.Fill = Brushes.Transparent;
  1051. }
  1052. }
  1053. }
  1054. }
  1055. /// <summary>
  1056. /// 显示空间属性窗体
  1057. /// </summary>
  1058. /// <param name="space"></param>
  1059. private static void ShowSpaceProperty(Autodesk.Revit.DB.Mechanical.Space space)
  1060. {
  1061. MRevitEquipBase equipment = DalCommon.GetEquipmentQueryId(space);
  1062. ShowSpaceProperty(equipment);
  1063. }
  1064. private static void ShowSpaceProperty(MRevitEquipBase equipment)
  1065. {
  1066. try
  1067. {
  1068. if (equipment != null)
  1069. {
  1070. var win = WinModeInfoMaintenanceForSpace.GetWindow();
  1071. win.Topmost = true;
  1072. win.Show(equipment);
  1073. win.Visibility = Visibility.Visible;
  1074. }
  1075. }
  1076. catch (Exception e)
  1077. {
  1078. MessageBox.Show("显示属性窗口出错" + e.Message, "系统提示");
  1079. }
  1080. }
  1081. /// <summary>
  1082. /// 从缓存获取空间信息
  1083. /// </summary>
  1084. /// <param name="ids"></param>
  1085. /// <returns></returns>
  1086. private List<MSpace> GetSpaceFromCacheByIds(List<ElementId> ids)
  1087. {
  1088. if (m_spacesCache != null)
  1089. return m_spacesCache.Where(s => ids.Exists(id => id.ToString() == s.BimID.Split(':')[1])).ToList();
  1090. return new List<MSpace>();
  1091. }
  1092. /// <summary>
  1093. /// 创建空间边缘轮廓
  1094. /// </summary>
  1095. /// <param name="space"></param>
  1096. private void CreateSpaceBoundary(Autodesk.Revit.DB.Mechanical.Space space)
  1097. {
  1098. if (space == null) return;
  1099. //过滤未放置空间
  1100. if (space.Area.IsEqual(0, 0.0001)) return;
  1101. //取出边缘
  1102. var mySegments = space.GetBoundarySegments(new SpatialElementBoundaryOptions());
  1103. var seg = mySegments.FirstOrDefault();
  1104. if (seg == null)
  1105. {
  1106. MessageBox.Show(space.Id.IntegerValue + "");
  1107. return;
  1108. }
  1109. List<Point> datas = new List<Point>();
  1110. foreach (BoundarySegment segment in seg)
  1111. {
  1112. datas.AddRange(segment.GetCurve().Tessellate().Select(xyz => xyz.ToW2DPoint()).ToList());
  1113. }
  1114. var polyLine = this.CreateDefaultPolyLine(datas, Brushes.Transparent);
  1115. polyLine.Tag = space;//此处比较重要,这个是判断曲线是否为轮廓线的关键
  1116. polyLine.Fill = Brushes.Transparent;
  1117. polyLine.MouseLeftButtonDown += PolyLine_MouseDown;
  1118. }
  1119. /// <summary>
  1120. /// 空间轮廓点击事件
  1121. /// </summary>
  1122. /// <param name="sender"></param>
  1123. /// <param name="e"></param>
  1124. private void PolyLine_MouseDown(object sender, MouseButtonEventArgs e)
  1125. {
  1126. if ((sender is WPolyline line) && m_isDraw == null)
  1127. {
  1128. //找到已亮显的空间
  1129. var showSpaces = this.canvas.Children.OfType<WPolyline>().FirstOrDefault(t => t is WPolyline l && l.Fill == Brushes.Aquamarine);
  1130. //先清除
  1131. if (showSpaces != null) showSpaces.Fill = Brushes.Transparent;
  1132. line.Fill = Brushes.Aquamarine;
  1133. //MessageBox.Show(line.Tag+"");
  1134. if (line.Tag is Autodesk.Revit.DB.Mechanical.Space space)
  1135. {
  1136. //反选右侧树
  1137. for (int i = 0; i < lbSpaces.Items.Count; i++)
  1138. {
  1139. var showSpace = lbSpaces.Items[i] as MSpace;
  1140. var spaceId = showSpace.BimID.Split(':')[1];
  1141. if (spaceId == space.Id.ToString())
  1142. {
  1143. lbSpaces.SelectedIndex = i;
  1144. break;
  1145. }
  1146. }
  1147. //显示属性板
  1148. ShowSpaceProperty(space);
  1149. }
  1150. }
  1151. }
  1152. private void btnZoomIn_Click(object sender, RoutedEventArgs e)
  1153. {
  1154. MoveElement(-0.1, new Point());
  1155. }
  1156. private void btnOrigin_Click(object sender, RoutedEventArgs e)
  1157. {
  1158. MoveElement(0.1, new Point(), isReset: true);
  1159. MoveElement(0, 0, isReset: true);
  1160. }
  1161. private void btnZoomOut_Click(object sender, RoutedEventArgs e)
  1162. {
  1163. MoveElement(0.1, new Point());
  1164. }
  1165. //创建定时器,以检测所有操作是否全部保存完成
  1166. private DispatcherTimer timer;
  1167. private void CanvasDefaultTips()
  1168. {
  1169. string tips = "请选择一个需要进行空间管理的楼层";
  1170. TextBlock txtTips = new TextBlock
  1171. {
  1172. FontSize = 21,
  1173. Width = 345,
  1174. Height = 40,
  1175. Text = tips,
  1176. Foreground = Brushes.LightCyan
  1177. };
  1178. this.canvas.Children.Add(txtTips);
  1179. Canvas.SetLeft(txtTips, this.canvas.ActualWidth / 2.0d - 160);
  1180. Canvas.SetTop(txtTips, canvas.ActualHeight / 2.0d);
  1181. }
  1182. }
  1183. /// <summary>
  1184. /// 已有空间分割线的数据实体
  1185. /// </summary>
  1186. public class PointPair
  1187. {
  1188. //空间分割线的端点(WPF)
  1189. public List<Point> Point { get; set; }
  1190. //空间分割线的端点(Revit)
  1191. public List<XYZ> RPoint { get; set; } = new List<XYZ>();
  1192. //空间分割线的Id
  1193. public int ElementId { set; get; }
  1194. //WPF中显示的线
  1195. public Polyline ShowLine { get; set; }
  1196. public PointPair()
  1197. {
  1198. }
  1199. public PointPair(int elemId, List<Point> point)
  1200. {
  1201. this.Point = point;
  1202. this.ElementId = elemId;
  1203. }
  1204. }
  1205. }