12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373 |
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using System.Text.RegularExpressions;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Input;
- using System.Windows.Media;
- using System.Windows.Shapes;
- using Autodesk.Revit.DB;
- using DevExpress.Mvvm.Native;
- using SAGA.DotNetUtils.Extend;
- using SAGA.RevitUtils.Extends;
- using WPolyline = System.Windows.Shapes.Polyline;
- using Point = System.Windows.Point;
- using System.Windows.Media.Animation;
- using System.Windows.Threading;
- using Autodesk.Revit.UI;
- using Newtonsoft.Json.Linq;
- using SAGA.DotNetUtils.Logger;
- using SAGA.MBI.Common;
- using SAGA.MBI.DataArrange;
- using SAGA.MBI.JsonConvert;
- using SAGA.MBI.Model;
- using SAGA.MBI.RequestData;
- using SAGA.MBI.Tools;
- using SAGA.MBI.WinView.ModeInfoMaintenance;
- using SAGA.RevitUtils.Windows;
- using Visibility = System.Windows.Visibility;
- using Path = System.IO.Path;
- //TODO:1.目前存在的问题,如果只选两个已有的端点画线不能实现
- //TODO:2.画图过程中,ESC可取消当前画图
- //TODO:3.切换楼层检测是否有需要保存的数据,如果有则提示是否保存
- namespace SAGA.MBI.WinView.Space
- {
- /// <summary>
- /// 空间管理
- /// </summary>
- public partial class WinCreateSpaces : WinBase
- {
- public WinCreateSpaces()
- {
- this.IsLoadHistroyData = false;
- InitializeComponent();
- tv.ItemsSource = Items;
- this.Loaded += MainWindow_Loaded;
- this.Closed += WinCreateSpaces_Closed;
- }
- /// <summary>
- /// 窗体关闭,同时关闭空间属性窗
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void WinCreateSpaces_Closed(object sender, EventArgs e)
- {
- WinModeInfoMaintenance.GetWindow().Close();
- }
- /*
- 颜色分类:墙为黑色,
- 已有空间分隔符为绿色,
- 柱为蓝色
- 新的空间分隔符为红色
- */
- private List<List<XYZ>> m_wallsData;
- private List<PointPair> m_virXyzs;
- private List<XYZ> m_columnsLocation;
- public List<int> DeletedPolylines = new List<int>();//被删除的已存在的虚拟墙的Id
- //建筑与楼层列表数据
- private ObservableCollection<TreeNodeItem> items;
- //最大值X
- double m_minX = double.MaxValue;
- double m_maxX = 0.0;
- double m_minY = double.MaxValue;
- double m_maxY = 0.0;
- //初始缩放比例
- double m_scale = 15 / 1.5d;
- //起始点
- Point m_previousMousePoint = new Point(0, 0);
- //当前线段
- private Polyline m_polyline;
- //是否开始画线
- bool m_flag = false;
- //建筑与楼层列表数据
- public ObservableCollection<TreeNodeItem> Items
- {
- get => new ObservableCollection<TreeNodeItem>(DalModeFileManange.GetMissFileFloors(false));
- set => items = value;
- }
- //本层空间数据缓存
- private List<MSpace> m_spacesCache;
- private void MainWindow_Loaded(object sender, RoutedEventArgs e)
- {
- CanvasDefaultTips();
- }
- /// <summary>
- /// 初始化画布,并在画图上画出相关数据
- /// </summary>
- private bool InitData()
- {
- //获取边界值
- GetBoundary();
- //获取缩放比例
- m_scale = Math.Min((canvas.ActualWidth - 40) / (m_maxX - m_minX), (canvas.ActualHeight - 40) / (m_maxY - m_minY));
- //虚拟墙
- m_virXyzs?.ForEach(line =>
- {
- var pline = CreateDefaultPolyLine(line.Point, Brushes.Green, 2);
- pline.Tag = line.ElementId;
- });
- //墙
- m_wallsData.Select(row => row.Select(xyz => xyz.ToW2DPoint()).ToList()).ForEach(line =>
- {
- CreateDefaultPolyLine(line, Brushes.Black, 4);
- });
- //画柱
- DrawColumns();
- return true;
- }
- /// <summary>
- /// 获取数据的边界值
- /// </summary>
- void GetBoundary()
- {
- //Revit坐标与wpf的Y坐标相反,WPF Y向下
- var xs = new List<double>();
- var ys = new List<double>();
- this.m_wallsData.ForEach(list =>
- {
- list.ForEach((xyz) =>
- {
- xs.Add(xyz.X);
- ys.Add(xyz.Y);
- });
- });
- this.m_virXyzs.ForEach(list =>
- {
- list.Point.ForEach((point) =>
- {
- xs.Add(point.X);
- ys.Add(point.Y);
- });
- });
- this.m_columnsLocation.ForEach(point =>
- {
- xs.Add(point.X);
- ys.Add(point.Y);
- });
- if (xs.Count == 0 || ys.Count == 0) return;
- m_maxX = xs.Max();
- m_minX = xs.Min();
- m_maxY = ys.Max();
- m_minY = ys.Min();
- }
- /// <summary>
- /// 平移坐标点,使其更适应界面
- /// </summary>
- /// <param name="point"></param>
- /// <returns></returns>
- Point MovePoint(Point point)
- {
- var newPoint = new Point((point.X - m_minX) * m_scale, -(point.Y - m_maxY) * m_scale);
- newPoint.Offset(20, 20);
- return newPoint;
- }
- /// <summary>
- /// 画柱子
- /// </summary>
- void DrawColumns()
- {
- foreach (var xyz in m_columnsLocation)
- {
- var point = MovePoint(new Point(xyz.X, xyz.Y));
- var line = new WPolyline
- {
- Stroke = Brushes.Blue,
- StrokeThickness = 2,
- Tag = new Point(point.X, point.Y)
- };
- //这里为了方便后边计算,在线上记录柱中心
- var offset = 7;
- //左上角
- point.Offset(-offset, -offset);
- line.Points.Add(point);
- point.Offset(0, 2 * offset);
- line.Points.Add(point);
- point.Offset(2 * offset, 0);
- line.Points.Add(point);
- point.Offset(0, -2 * offset);
- line.Points.Add(point);
- point.Offset(-2 * offset, 0);
- line.Points.Add(point);
- this.canvas.Children.Add(line);
- }
- }
- /// <summary>
- /// 鼠标移动,实时显示虚拟墙动态
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void canvas_MouseMove(object sender, MouseEventArgs e)
- {
- if (m_flag == false)
- return;
- if (m_isDraw == true)
- {
- m_polyline.Points[m_polyline.Points.Count - 1] = e.GetPosition(canvas);
- Console.WriteLine("Move: " + m_polyline.Points[m_polyline.Points.Count - 1]);
- }
- }
- /// <summary>
- /// 开始画虚拟墙
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
- {
- if (m_isDraw != true) return;
- var point = e.GetPosition(canvas);
- if (m_polyline == null)
- {
- // if (flag == false) {
- m_polyline = new Polyline
- {
- Stroke = Brushes.Red,
- StrokeThickness = 2,
- FillRule = FillRule.EvenOdd
- };
- this.canvas.Children.Add(m_polyline);
- //如果是第一个点,则自动附着到现有的线段上
- point = GeometryHelper.ConvertOnLinePoint(point, this.canvas, m_polyline);
- }
- m_polyline.Points.Add(point);
- if (m_polyline.Points.Count == 1)
- m_polyline.Points.Add(e.GetPosition(canvas));
- m_flag = true;
- this.btnSave.IsEnabled = true;
- Console.WriteLine("Left Down: " + e.GetPosition(canvas));
- }
-
- /// <summary>
- /// 缩放画布
- /// </summary>
- /// <param name="scale"></param>
- /// <param name="center"></param>
- private void MoveElement(double scale, Point center, bool isReset = false)
- {
- //foreach (UIElement s in canvas.Children)
- {
- if (canvas.RenderTransform is TransformGroup tg)
- {
- //缩放
- if (tg.Children.FirstOrDefault(tr => tr is ScaleTransform) is ScaleTransform stf)
- {
- //重置
- if (isReset)
- {
- stf.ScaleX = 1;
- stf.ScaleY = 1;
- return;
- }
- //缩放的大小不能太小
- stf.ScaleX = Math.Max(stf.ScaleX + scale, 0.3);
- stf.ScaleY = Math.Max(stf.ScaleY + scale, 0.3);
- //if (center.X <= 0 || center.Y <= 0) {
- // return;
- //}
- // stf.CenterX = center.X;
- // stf.CenterY = center.Y;
- }
- else
- {
- scale = Math.Max(scale, 1);
- ScaleTransform scaleTransform = new ScaleTransform
- {
- ScaleX = scale,
- ScaleY = scale
- };
- tg.Children.Add(scaleTransform);
- }
- }
- else
- {
- TransformGroup transformGroup = new TransformGroup();
- ScaleTransform scaleTransform = new ScaleTransform();
- scaleTransform.ScaleX = 1;
- scaleTransform.ScaleY = 1;
- transformGroup.Children.Add(scaleTransform);
- canvas.RenderTransform = transformGroup;
- }
- }
- }
- /// <summary>
- /// TranslateTransform是平移画布
- /// </summary>
- /// <param name="dx"></param>
- /// <param name="dy"></param>
- private void MoveElement(double dx, double dy, bool isReset = false)
- {
- //foreach (UIElement s in canvas.Children)
- {
- if (canvas.RenderTransform is TransformGroup tg)
- {
- //平移
- if (tg.Children.FirstOrDefault(tr => tr is TranslateTransform) is TranslateTransform ttf)
- {
- var anim1 = new DoubleAnimation(ttf.X,
- (isReset ? 0 : (ttf.X + dx)),
- TimeSpan.FromSeconds(.01))
- { EasingFunction = new SineEase() };
- var anim2 = new DoubleAnimation(ttf.Y, (isReset ? 0 : (ttf.Y + dy)), TimeSpan.FromSeconds(.01)) { EasingFunction = new SineEase() };
- ttf.BeginAnimation(TranslateTransform.XProperty, anim1);
- ttf.BeginAnimation(TranslateTransform.YProperty, anim2);
- }
- else
- {
- TranslateTransform ttfNew = new TranslateTransform
- {
- // X = dx,
- // Y = dy
- };
- var anim1 = new DoubleAnimation(0, dx, TimeSpan.FromSeconds(.2)) { EasingFunction = new SineEase() };
- var anim2 = new DoubleAnimation(0, dy, TimeSpan.FromSeconds(.2)) { EasingFunction = new SineEase() };
- ttfNew.BeginAnimation(TranslateTransform.XProperty, anim1);
- ttfNew.BeginAnimation(TranslateTransform.YProperty, anim2);
- tg.Children.Add(ttfNew);
- }
- }
- else
- {
- TransformGroup transformGroup = new TransformGroup();
- TranslateTransform translateTransform = new TranslateTransform();
- //translateTransform.X = dx;
- //translateTransform.Y = dy;
- var anim1 = new DoubleAnimation(0, dx, TimeSpan.FromSeconds(.1)) { EasingFunction = new SineEase() };
- var anim2 = new DoubleAnimation(0, dy, TimeSpan.FromSeconds(.1)) { EasingFunction = new SineEase() };
- translateTransform.BeginAnimation(TranslateTransform.XProperty, anim1);
- translateTransform.BeginAnimation(TranslateTransform.YProperty, anim2);
- transformGroup.Children.Add(translateTransform);
- ScaleTransform scaleTransform = new ScaleTransform
- {
- ScaleX = 1,
- ScaleY = 1
- };
- // transformGroup.Children.Add(scaleTransform);
- canvas.RenderTransform = transformGroup;
- }
- }
- }
- /// <summary>
- /// 选择并删除虚拟墙
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void canvas_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
- {
- Point point = e.GetPosition(canvas);
- if (m_isDraw == false)//擦除线
- {
- foreach (var canvasChild in this.canvas.Children)
- {
- if (canvasChild is WPolyline line)
- {
- for (int i = 0; i < line.Points.Count - 1; i++)
- {
- if (PointIsInLine(point, line.Points[i], line.Points[i + 1], 4))
- {
- //黑线与蓝线不能删除,红线直接删除,绿线删除需记录
- if (line.Stroke == Brushes.Red)
- {
- canvas.Children.Remove(line);
- btnSave.IsEnabled = true;
- }
- else if (line.Stroke == Brushes.Green)
- {
- DeletedPolylines.Add((int)line.Tag);
- canvas.Children.Remove(line);
- btnSave.IsEnabled = true;
- }
- return;
- }
- }
- }
- }
- }
- }
- private bool? m_isDraw = null;
- /// <summary>
- /// 开始画图
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void btnDraw_Click(object sender, RoutedEventArgs e)
- {
- if (m_isDraw != true)
- {
- m_isDraw = true;
- this.Cursor = Cursors.Pen;
- }
- else
- {
- m_isDraw = null;
- this.Cursor = Cursors.Hand;
- }
- }
- /// <summary>
- ///
- /// 开始删除操作
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void btnClear_Click(object sender, RoutedEventArgs e)
- {
- m_isDraw = false;
- this.Cursor = Cursors.Cross;
- }
-
- /// <summary>
- /// 判断点是否在直线上
- /// </summary>
- /// <param name="pf"></param>
- /// <param name="p1"></param>
- /// <param name="p2"></param>
- /// <param name="range"></param>
- /// <returns></returns>
- public static bool PointIsInLine(Point pf, Point p1, Point p2, double range = 0)
- {
- //range 判断的的误差,不需要误差则赋值0
- //点在线段首尾两端之外则return false
- double cross = (p2.X - p1.X) * (pf.X - p1.X) + (p2.Y - p1.Y) * (pf.Y - p1.Y);
- if (cross <= 0) return false;
- double d2 = (p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y);
- if (cross >= d2) return false;
- double r = cross / d2;
- double px = p1.X + (p2.X - p1.X) * r;
- double py = p1.Y + (p2.Y - p1.Y) * r;
- //判断距离是否小于误差
- return Math.Sqrt((pf.X - px) * (pf.X - px) + (py - pf.Y) * (py - pf.Y)) <= range;
- }
- /// <summary>
- /// 创建虚拟墙
- /// </summary>
- /// <param name="xyzs"></param>
- /// <param name="brush"></param>
- /// <param name="thinkness"></param>
- /// <returns></returns>
- Polyline CreateDefaultPolyLine(List<Point> xyzs, Brush brush, double thinkness = 2)
- {
- var pl = new Polyline
- {
- Stroke = brush,
- StrokeThickness = thinkness,
- StrokeStartLineCap = PenLineCap.Flat,
- StrokeEndLineCap = PenLineCap.Flat,
- StrokeLineJoin = PenLineJoin.Round
- };
- this.AddPoints(xyzs, pl);
- canvas.Children.Add(pl);
- return pl;
- }
- /// <summary>
- /// 添加虚拟墙的点
- /// </summary>
- /// <param name="lstPt"></param>
- /// <param name="pl"></param>
- void AddPoints(IEnumerable<Point> lstPt, Polyline pl)
- {
- foreach (var pt in lstPt)
- {
- pl.Points.Add(MovePoint(new Point(pt.X, pt.Y)));
- }
- }
- /// <summary>
- /// 将画布坐标转换为Revit坐标
- /// </summary>
- /// <param name="point"></param>
- /// <returns></returns>
- XYZ WpfPointToReivt(Point point)
- {
- return new XYZ(((point.X - 20) / m_scale + m_minX), ((point.Y - 20) / (-m_scale) + (m_maxY)), 0);
- }
- /// <summary>
- /// 保存所画的线
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void btnSave_Click(object sender, RoutedEventArgs e)
- {
- m_isAsynFinished = false;
- //禁用界面,防止重复提交
- this.IsEnabled = false;
- m_isDraw = null;
- //需要保存的分隔符数据
- List<PointPair> saveDatas = new List<PointPair>();
- //取出所有的线
- for (var j = 0; j < this.canvas.Children.Count; j++)
- {
- var child = this.canvas.Children[j];
- if (child is WPolyline line && line.Stroke == Brushes.Red)
- {
- for (int i = 0; i < line.Points.Count - 1; i++)
- {
- //创建新的虚拟墙
- var newLine = new Polyline()
- {
- Stroke = Brushes.Green,
- StrokeThickness = 2,
- };
- newLine.Points.Add(line.Points[i]);
- newLine.Points.Add(line.Points[i + 1]);
- //将现有坐标转化
- saveDatas.Add(new PointPair()
- {
- RPoint = new List<XYZ>() { WpfPointToReivt(line.Points[i]), WpfPointToReivt(line.Points[i + 1]) },
- ShowLine = newLine
- });
- this.canvas.Children.Add(newLine);
- }
- //删除现有的虚拟墙
- this.canvas.Children.Remove(line);
- j = -1;
- }
- }
- //保存数据到Revit,创建空间分隔符
- var doc = m_document;
- ExecuteCmd.ExecuteCommand(() =>
- {
- Logs.Log($"空间分隔符开始");
- var create = new CreateSpaceCommand();
- //创建空间分隔符
- create.CreateSpaceSeqarate(doc, saveDatas, DeletedPolylines);
- //删除已有的空间分隔符
- DeletedPolylines.Clear();
- Logs.Log($"空间分隔符结束");
- // btnSaveToRevit.IsEnabled = true;
- return Result.Succeeded;
- });
- //保存后重新创建空间,并加载空间分隔符与空间数据
- CreateSpaceAndReload(doc, () =>
- {
- WinConfirm confirm = new WinConfirm()
- {
- ShowMessage = "空间已发生变化,是否现在就上传模型并计算空间?",
- TTitle = "空间计算确认",
- BtnSure = "上传模型并计算空间",
- BtnCancel = "暂不计算",
- Owner=this,
- };
- var result = confirm.ShowDialog();
- //选择以后界面可用
- this.IsEnabled = true;
- if (result == true)
- {
- // 由于上传需要关闭所有模型,所以这里需要对所有数据进行清空
- this.canvas.Children.Clear();
- //添加默认提示
- CanvasDefaultTips();
- lbSpaces.ItemsSource = new ObservableCollection<MSpace>();
- WinModeInfoMaintenance.GetWindow().Hide();
- m_isCreaded = true;
- return false;
- }
- else
- {
- return true;
- }
- });
- timer = new DispatcherTimer();
- timer.Tick += Timer_Elapsed;
- timer.Interval = TimeSpan.FromMilliseconds(1000);
- timer.Start();
- }
- private bool m_isCreaded = false;//是否上传数据的标志,用于定时器
- private bool m_isAsynFinished = false;
- private void Timer_Elapsed(object sender, EventArgs e)
- {
- if (m_isAsynFinished)
- {
- //所有的操作只在这里进行保存
- m_document.Save();
- Logs.Log($"{DateTime.Now}被保存!!!!!!!!!!!!!!!!!!");
- if (m_isCreaded)
- {
- //放在命令里面
- //ExecuteCmd.ExecuteCommand(() =>
- //{
- try
- {
- string str = "";
- UploadModeCommand command = new UploadModeCommand();
- command.Execute(null, ref str, null);
- }
- catch (Exception exception)
- {
- Console.WriteLine(exception);
- MessageBox.Show(exception.Message);
- }
- // return Result.Succeeded;
- //});
- m_isCreaded = false;
- }
- timer.Stop();
- m_isAsynFinished = false;
- }
- }
- /// <summary>
- /// 离开画布,改变鼠标样式
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void canvas_MouseLeave(object sender, MouseEventArgs e)
- {
- this.Cursor = Cursors.Arrow;
- }
- /// <summary>
- /// 鼠标进入画布,改变鼠标样式
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void canvas_MouseEnter(object sender, MouseEventArgs e)
- {
- if (m_isDraw == true)
- {
- this.Cursor = Cursors.Pen;
- }
- else if (m_isDraw == false)
- {
- this.Cursor = Cursors.Cross;
- }
- else
- {
- this.Cursor = Cursors.Hand;
- }
- }
- /// <summary>
- /// 鼠标右键,结束画线
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
- {
- if (m_polyline == null || m_isDraw != true) return;
- //结束,调整最后一个点,让其自动附着
- m_polyline.Points[m_polyline.Points.Count - 1] = GeometryHelper.ConvertOnLinePoint(m_polyline.Points[m_polyline.Points.Count - 1], canvas, m_polyline);
- m_polyline = null;
- m_flag = false;
- }
- private void viewer_MouseWheel(object sender, MouseWheelEventArgs e)
- {
- double val = (double)e.Delta / 2000; //描述鼠标滑轮滚动
- // scaleValue += val;
- var center = e.GetPosition(this.canvas);
- //if (center.X <= 0 || center.Y <= 0) {
- // return;
- //}
- MoveElement(val, center);
- }
- /// <summary>
- /// 鼠标up事件,获取鼠标抬起的位置,并根据移动距离平移画布
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void viewer_MouseUp(object sender, MouseButtonEventArgs e)
- {
- //如果按下的是中键
- if (e.ChangedButton == MouseButton.Middle)
- {
- Point position = e.GetPosition(viewer);
- var tempx = position.X - this.m_previousMousePoint.X;
- var tempy = position.Y - this.m_previousMousePoint.Y;
- //平移画布
- MoveElement(tempx, tempy);
- }
- }
- /// <summary>
- /// 鼠标down事件,获取点击初始位置
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void viewer_MouseDown(object sender, MouseButtonEventArgs e)
- {
- if (e.ChangedButton == MouseButton.Middle)
- {
- m_previousMousePoint = e.GetPosition(viewer);
- btnSave.IsEnabled = true;
- }
- }
- /// <summary>
- /// 鼠标中键滚轮事件,控制canvas的缩放
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void viewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
- {
- double val = (double)e.Delta / 2000; //描述鼠标滑轮滚动
- var center = e.GetPosition(this.canvas);
- MoveElement(val, center);
- }
- private string m_curFloorId = "";//当前选择项楼层Id
- private Document m_document;//当前操作的模型
- /// <summary>
- /// 楼层切换
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void Tv_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
- {
- //检测是否有未保存的数据,数据分两部分:新建的空间分隔符,删除的空间分隔符
- if (DeletedPolylines.Count > 0 || this.canvas.Children.OfType<UIElement>().Any(el => (el is WPolyline line && line.Stroke == Brushes.Red)))
- {
- WinConfirm confirm = new WinConfirm()
- {
- ShowMessage = "尚未保存空间变化,确认放弃修改?",
- TTitle = "空间修改确认",
- BtnSure = "保存并更改模型",
- BtnCancel = "放弃修改"
- };
- var result = confirm.ShowDialog();
- if (result == true)
- {
- btnSave_Click(null, null);
- return;
- }
- DeletedPolylines.Clear();
- }
- if (tv.SelectedItem is TreeNodeItem item && item.Item is MFloor floor)
- {
- try
- {
- //关闭空间属性窗
- WinModeInfoMaintenance.GetWindow().Hide();
- m_curFloorId = floor.Id;
- this.canvas.Children.Clear();
- this.canvas.IsEnabled = false;
- this.lbSpaces.ItemsSource = null;
- //模型文件路径
- var filePath = floor.FullPath;
- //检测文件是否存在
- if (!File.Exists(filePath))
- {
- MessageBox.Show("无法找到相关模型文件!");
- return;
- }
- //加载模型文件并激活
- // var uiDoc = ExternalDataWrapper.Current.App.OpenDocumentFile(filePath);
- Logs.Log("加载模型开始");
- var uiDoc = ExternalDataWrapper.Current.UiApp.OpenAndActivateDocument(filePath);
- Logs.Log("加载模型结束");
- var doc = uiDoc.Document;
- m_document = doc;
- var view = doc.GetElements<ViewPlan>().FirstOrDefault(t => t.GenLevel?.Name != null && t.Name?.IndexOf("-saga") > -1 && t.ViewType == ViewType.FloorPlan);
- if (view == null)
- {
- MessageBox.Show("无法找到名称以-saga结尾的视图!");
- return;
- }
- bool result = LoadData();
- if (!result)
- {
- MessageBox.Show("模型文件没有找到相关数据!");
- return;
- }
- this.canvas.IsEnabled = true;
- //重置画布
- btnOrigin_Click(null, null);
- //缓存所有空间数据
- m_spacesCache = SpaceConvert.GetFloorSpaceInfos(m_curFloorId).OfType<MSpace>().ToList();
- //创建空间
- //检测日志,是否有墙,虚拟墙,柱子数据的改变
- CreateSpaceAndReload(doc, InitData);
- }
- catch (Exception ex)
- {
- MessageBox.Show(ex.Message);
- }
- }
- }
- /// <summary>
- /// 创建空间并重新加载到列表
- /// </summary>
- /// <param name="doc"></param>
- /// <param name="callback">异步回调函数</param>
- private void CreateSpaceAndReload(Document doc, Func<bool> callback)
- {
- ExecuteCmd.ExecuteCommand(() =>
- {
- Logs.Log($"创建空间开始");
- //生成空间
- CreateSpaceCommand cmd = new CreateSpaceCommand();
- cmd.CreateSpace(doc);
- // doc.Regenerate();
- Logs.Log($"创建空间结束");
- return Result.Succeeded;
- });
- //因为异步执行,获取空间不能直接放到下面
- //删除冲突的空间
- ExecuteCmd.ExecuteCommand(() =>
- {
- Logs.Log($"删除空间开始");
- // DeleteFailuresPreprocessorData(doc);
- DeleteFailuresPreprocessorDataByManual(doc);
- //保存数据
- // doc.Save();
- bool? isReload = callback?.Invoke();
- if (isReload == true)
- {
- try
- {
- //加载空间
- var spaces = doc.GetElements<SpatialElement>().Where(s => s is Autodesk.Revit.DB.Mechanical.Space && s.Area > 0).ToList();
- //创建空间轮廓,这里必须放在初始化之后创建
- CreateAllSpaceSeq(spaces);
- //创建右侧空间树
- ShowSpacesListFrowServer(spaces);
- }
- catch (Exception e)
- {
- MessageBox.Show(e.Message);
- }
- }
- m_isAsynFinished = true;
- //btnSaveToRevit.IsEnabled = true;
- try
- {
- Logs.Log($"删除空间结束");
- doc.Save();
- DocumentChangedLog.RemoveInvalidLogs();
- }
- catch (Exception e)
- {
- MessageBox.Show(e.Message);
- }
- return Result.Succeeded;
- });
- }
- /// <summary>
- /// 创建边线
- /// </summary>
- /// <param name="spaces"></param>
- void CreateAllSpaceSeq(List<SpatialElement> spaces)
- {
- //清除已有的空间边线
- for (int i = 0; i < this.canvas.Children.Count; i++)
- {
- if (this.canvas.Children[i] is WPolyline line && line.Tag is Autodesk.Revit.DB.Mechanical.Space)
- {
- this.canvas.Children.RemoveAt(i);
- i -= 1;
- }
- }
- spaces.ForEach(s => CreateSpaceBoundary(s as Autodesk.Revit.DB.Mechanical.Space));
- }
- /// <summary>
- /// 获取所有空间对应的服务器端的信息
- /// </summary>
- /// <param name="spaces"></param>
- private void ShowSpacesListFrowServer(List<SpatialElement> spaces)
- {
- // var infosjobj = ConvertElementsToJArray(spaces);
- //var datas = CommonConvert.QueryObjectInfoByIds(m_curFloorId, infosjobj).OfType<MSpace>().ToList();
- var datas = GetSpaceFromCacheByIds(spaces.Select(t => t.Id).ToList());
- var localSpace = spaces.Where(t => !datas.Any(s => s.BimID.Split(':')[1] == t.Id.ToString()))
- .Select(t => new MSpace("", $"{Guid.NewGuid()}:{t.Id.ToString()}") { Name = t.Name });
- datas.AddRange(localSpace);
- //List<string> dd;
- //dd.AddRange();
- lbSpaces.ItemsSource = new ObservableCollection<MSpace>(datas);
- }
-
- /// <summary>
- /// 手动删除冲突的空间
- /// </summary>
- /// <param name="doc"></param>
- private void DeleteFailuresPreprocessorDataByManual(Document doc)
- {
- bool isReCreate = false;
- using (Transaction trans = new Transaction(doc, "删除多余的空间"))
- {
- trans.Start();
- try
- {
- //处理异常显示
- FailureHandlingOptions fho = trans.GetFailureHandlingOptions();
- fho.SetFailuresPreprocessor(new FailuresPreprocessor(false));
- trans.SetFailureHandlingOptions(fho);
- List<ServerSpace> serverSpaces = new List<ServerSpace>();
- Regex regex = new Regex("^\\d+$");
- var index = 1;
- //对冲突的空间进行删除
- foreach (List<ElementId> elementIds in StaticData.FailuresPreprocessorData)
- {
- Logs.Log(string.Join("-", elementIds));
- //取出空间的服务器信息
-
- var spacesServerInfo = GetSpaceFromCacheByIds(elementIds);
- //如果返回值小于等于1,自动处理
- //如果返回值大于1,则在界面处理
- if (spacesServerInfo == null || spacesServerInfo.Count == 0)
- {
- var firstElement = doc.GetElement(elementIds.FirstOrDefault());
- //对所有冲突的空间编号进行比较,保留较小编号的空间
- if (firstElement is Autodesk.Revit.DB.Mechanical.Space first)
- {
- foreach (var id in elementIds)
- {
- if (first.Id.IsEqual(id))
- continue;
- var curr = doc.GetElement(id) as Autodesk.Revit.DB.Mechanical.Space;
- Logs.Log("=============");
- Logs.Log($"当前空间Id:{id},Num:{curr.Number}");
- //如果编号非数字,删其中一个
- if (!regex.IsMatch(first.Number))
- {
- doc.Delete(new List<ElementId>() { first.Id });
- first = curr;
- continue;
- }
- if (!regex.IsMatch(curr.Number))
- {
- doc.Delete(new List<ElementId>() { id });
- continue;
- }
- if (int.Parse(first.Number) > int.Parse(curr.Number))
- {
- Logs.Log($"1.被删除的空间Id:{id},Num:{first.Number}");
- doc.Delete(new List<ElementId>() { first.Id });
- first = curr;
- }
- else
- {
- Logs.Log($"2.被删除的空间Id:{id},Num:{curr.Number}");
- doc.Delete(new List<ElementId>() { id });
- }
- Logs.Log("=============");
- }
- }
- }
- else if (spacesServerInfo.Count == 1)
- {
- var serverSpaceId = spacesServerInfo[0].BimID.Split(':')[1];
- doc.Delete(elementIds.Where(t => t.ToString() != serverSpaceId).ToList());
- }
- else
- {
- doc.Delete(elementIds.Where(t => !spacesServerInfo.Exists(sp => sp.BimID.Split(':')[1] == t.ToString())).ToList());
- var groupName = $"待合并元空间组{index}";
- foreach (var mRevitEquipBase in spacesServerInfo)
- {
- if (mRevitEquipBase is MSpace space)
- {
- serverSpaces.Add(new ServerSpace()
- {
- Space = space,
- GroupName = groupName
- });
- }
- }
- serverSpaces.Add(new ServerSpace()
- {
- Name = "不保留已有空间,创建新空间",
- GroupName = groupName
- });
- index++;
- }
- }
- if (serverSpaces.Count > 0)
- {
- var winDeal = new WinSelectSpace(serverSpaces);
- var result = winDeal.ShowDialog();
- if (result == true)
- {
- var ids = winDeal.DeleteElementIds.Select(t => new ElementId(int.Parse(t))).ToList();
- doc.Delete(ids);
- isReCreate = winDeal.IsReCreate;
- }
- }
- //提交事务
- trans.Commit();
- }
- catch (Exception e)
- {
- //回滚事务
- trans.RollBack();
- }
- }
- StaticData.FailuresPreprocessorData.Clear();
- if (isReCreate) CreateSpaceAndReload(doc, null);
- }
-
- /// <summary>
- /// 加载模型数据
- /// </summary>
- private bool LoadData()
- {
- var doc = m_document;
- //读取墙数据
- List<Wall> walls = doc.FilterElements<Wall>().ToList();
- if (walls.Count == 0) return false;
- // List<List<XYZ>> wallData = GroupWallByParallel(walls);//太慢改为直接获取墙线
- //获取虚拟墙(空间分隔符或者房间分隔符)
- var wallData = walls.Select(t => t.GetCurve().Tessellate().ToList()).ToList();
- var virWalls = doc.FilterElements<CurveElement>((line) =>
- {
- var categoryId = line.Category.Id.IntegerValue;
- return categoryId == (int)BuiltInCategory.OST_MEPSpaceSeparationLines ||
- categoryId == (int)BuiltInCategory.OST_RoomSeparationLines;
- }).Where(line => line is ModelLine).Select(line =>
- {
- var ml = line as ModelLine;
- var mlLine = ml.Location.GetLine();
- //return new SgLine(mlLine.StartPoint().ToW2DPoint(), mlLine.EndPoint().ToW2DPoint()); //return new SgLine(mlLine.StartPoint().ToW2DPoint(), mlLine.EndPoint().ToW2DPoint());
- return
- new PointPair(ml.Id.IntegerValue, new List<System.Windows.Point>()
- {
- mlLine.StartPoint().ToW2DPoint(),
- mlLine.EndPoint().ToW2DPoint()
- });
- }).ToList();
- //获取所有建筑柱子
- var columns = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_Columns);
- //结构柱
- var stColumns = doc.GetElements<FamilyInstance>(BuiltInCategory.OST_StructuralColumns);
- columns.AddRange(stColumns);
- m_columnsLocation = columns.Select(c => c.Location.GetPoint())
- .Where(t => !t.IsEqual(new XYZ(0, 0, 0), 0.000001)//TODO:临时处理
- ).ToList();
- this.m_wallsData = wallData;
- this.m_virXyzs = virWalls;
- return true;
- }
- /// <summary>
- /// 切换空间,亮显空间
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void lbSpaces_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (lbSpaces.SelectedItems.Count == 0) return;
- var space = lbSpaces.SelectedItems[0] as MSpace;
- var bimId = space.BimID.Split(':')[1];
- foreach (var polyline in this.canvas.Children.OfType<WPolyline>())
- {
- if (polyline.Tag is Autodesk.Revit.DB.Mechanical.Space s)
- {
- if (s.Id.ToString() == (bimId))
- {
- polyline.Fill = Brushes.Aquamarine;
- //显示属性窗口
- ShowSpaceProperty(s);
- }
- else if (polyline.Fill == Brushes.Aquamarine)
- {
- polyline.Fill = Brushes.Transparent;
- }
- }
- }
- }
- /// <summary>
- /// 显示空间属性窗体
- /// </summary>
- /// <param name="space"></param>
- private static void ShowSpaceProperty(Autodesk.Revit.DB.Mechanical.Space space)
- {
- MRevitEquipBase equipment = DalCommon.GetEquipmentQueryId(space);
- ShowSpaceProperty(equipment);
- }
-
- private static void ShowSpaceProperty(MRevitEquipBase equipment)
- {
- try
- {
- if (equipment != null)
- {
- var win = WinModeInfoMaintenanceForSpace.GetWindow();
- win.Topmost = true;
- win.Show(equipment);
- win.Visibility = Visibility.Visible;
- }
- }
- catch (Exception e)
- {
- MessageBox.Show("显示属性窗口出错" + e.Message, "系统提示");
- }
- }
- /// <summary>
- /// 从缓存获取空间信息
- /// </summary>
- /// <param name="ids"></param>
- /// <returns></returns>
- private List<MSpace> GetSpaceFromCacheByIds(List<ElementId> ids)
- {
- if (m_spacesCache != null)
- return m_spacesCache.Where(s => ids.Exists(id => id.ToString() == s.BimID.Split(':')[1])).ToList();
- return new List<MSpace>();
- }
- /// <summary>
- /// 创建空间边缘轮廓
- /// </summary>
- /// <param name="space"></param>
- private void CreateSpaceBoundary(Autodesk.Revit.DB.Mechanical.Space space)
- {
- if (space == null) return;
- //过滤未放置空间
- if (space.Area.IsEqual(0, 0.0001)) return;
- //取出边缘
- var mySegments = space.GetBoundarySegments(new SpatialElementBoundaryOptions());
- var seg = mySegments.FirstOrDefault();
- if (seg == null)
- {
- MessageBox.Show(space.Id.IntegerValue + "");
- return;
- }
- List<Point> datas = new List<Point>();
- foreach (BoundarySegment segment in seg)
- {
- datas.AddRange(segment.GetCurve().Tessellate().Select(xyz => xyz.ToW2DPoint()).ToList());
- }
- var polyLine = this.CreateDefaultPolyLine(datas, Brushes.Transparent);
- polyLine.Tag = space;//此处比较重要,这个是判断曲线是否为轮廓线的关键
- polyLine.Fill = Brushes.Transparent;
- polyLine.MouseLeftButtonDown += PolyLine_MouseDown;
- }
- /// <summary>
- /// 空间轮廓点击事件
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void PolyLine_MouseDown(object sender, MouseButtonEventArgs e)
- {
- if ((sender is WPolyline line) && m_isDraw == null)
- {
- //找到已亮显的空间
- var showSpaces = this.canvas.Children.OfType<WPolyline>().FirstOrDefault(t => t is WPolyline l && l.Fill == Brushes.Aquamarine);
- //先清除
- if (showSpaces != null) showSpaces.Fill = Brushes.Transparent;
- line.Fill = Brushes.Aquamarine;
- //MessageBox.Show(line.Tag+"");
- if (line.Tag is Autodesk.Revit.DB.Mechanical.Space space)
- {
- //反选右侧树
- for (int i = 0; i < lbSpaces.Items.Count; i++)
- {
- var showSpace = lbSpaces.Items[i] as MSpace;
- var spaceId = showSpace.BimID.Split(':')[1];
- if (spaceId == space.Id.ToString())
- {
- lbSpaces.SelectedIndex = i;
- break;
- }
- }
- //显示属性板
- ShowSpaceProperty(space);
- }
- }
- }
- private void btnZoomIn_Click(object sender, RoutedEventArgs e)
- {
- MoveElement(-0.1, new Point());
- }
- private void btnOrigin_Click(object sender, RoutedEventArgs e)
- {
- MoveElement(0.1, new Point(), isReset: true);
- MoveElement(0, 0, isReset: true);
- }
- private void btnZoomOut_Click(object sender, RoutedEventArgs e)
- {
- MoveElement(0.1, new Point());
- }
- //创建定时器,以检测所有操作是否全部保存完成
- private DispatcherTimer timer;
-
- private void CanvasDefaultTips()
- {
- string tips = "请选择一个需要进行空间管理的楼层";
- TextBlock txtTips = new TextBlock
- {
- FontSize = 21,
- Width = 345,
- Height = 40,
- Text = tips,
- Foreground = Brushes.LightCyan
- };
- this.canvas.Children.Add(txtTips);
- Canvas.SetLeft(txtTips, this.canvas.ActualWidth / 2.0d - 160);
- Canvas.SetTop(txtTips, canvas.ActualHeight / 2.0d);
- }
- }
- /// <summary>
- /// 已有空间分割线的数据实体
- /// </summary>
- public class PointPair
- {
- //空间分割线的端点(WPF)
- public List<Point> Point { get; set; }
- //空间分割线的端点(Revit)
- public List<XYZ> RPoint { get; set; } = new List<XYZ>();
- //空间分割线的Id
- public int ElementId { set; get; }
- //WPF中显示的线
- public Polyline ShowLine { get; set; }
- public PointPair()
- {
- }
- public PointPair(int elemId, List<Point> point)
- {
- this.Point = point;
- this.ElementId = elemId;
- }
- }
- }
|