using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; using SAGA.DotNetUtils; using SAGA.DotNetUtils.Data; using SAGA.DotNetUtils.Extend; using SAGA.DotNetUtils.Geometry; using SAGA.MBI.Calc; using SAGA.MBI.DataArrange; using SAGA.MBI.Interaction; using SAGA.MBI.Model; using SAGA.MBI.RevitExport; using SAGA.MBI.Test; using SAGA.MBI.Tools; using SAGA.MBI.WinView.Upload; using SAGA.RevitUtils; using SAGA.RevitUtils.Extends; using SAGA.RevitUtils.ExtensibleStorage; using SAGA.RevitUtils.MEP; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.RegularExpressions; using Color = Autodesk.Revit.DB.Color; namespace SAGA.MBI { #region 测试命令 /// /// /// [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class EquipInSpaceSpeedTest : ExternalCommand, IExternalCommandAvailability { public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { try { //var fi = ExternalDataWrapper.Current.UiApp.GetSelectedElement() as FamilyInstance; //var space = fi.GetReferenceSpace(); //string str = "",str2=""; //while (true) //{ // if (space != null) // { // List spaceVertex = space.GetBoundaryVertexes().FirstOrDefault(); // if (spaceVertex == null) // { // str = "Boundary 为Null"; // break; // } // var xyz = fi.GetLocationPointMBIXYZ(); // str = "Geometry Intersection Result:" + xyz.PointInPolygonByRay(spaceVertex); // str2 = "Geometry2D Intersection Result:" + Geometry2D.InSidePolygon(spaceVertex.Count, // spaceVertex.Select(t => t.ToPointD()).ToArray(), xyz.ToPointD()); // } // break; //} //MessageShowBase.Infomation($"{str}"+"\r\n"+$"{str2}"); var doc = commandData.View.Document; var spaces = doc.GetSpaces().Where(t => t.IsValidObject).ToList(); var fis = doc.GetMbiElements().Where(t => t.IsEquipmentPart() || t.IsEquipment()); List>> spaceVertexes = spaces.Select(t => t.GetBoundaryVertexes()).ToList(); List> keyValuePairs = fis.Select(t => new KeyValuePair(t, t.GetLocationPointMBIXYZ())).ToList(); List> keyValuePairs_bak = new List>(); long rtime = 0, gtime = 0; int rcount = 0, gcount = 0; Stopwatch watch = new Stopwatch(); #region 使用Revit计算 watch.Start(); foreach (var pair in keyValuePairs) { Element fi = pair.Key; var space = fi.GetReferenceSpace(spaces); if (space != null) { rcount++; keyValuePairs_bak.Add(pair); } } watch.Stop(); rtime = watch.ElapsedMilliseconds; #endregion #region 使用Geomety计算 List> spaceBorderVertexes = spaceVertexes.Select(t => t.FirstOrDefault()).ToList(); watch.Reset(); watch.Start(); foreach (var pair in keyValuePairs) { XYZ xyz = pair.Value; double z = xyz.Z; var point = xyz.ToPointD(); foreach (var spaceVertex in spaceBorderVertexes) { if (spaceVertex == null) continue; double minz = spaceVertex.Min(t => t.Z); double maxz = spaceVertex.Max(t => t.Z); //if (z.IsBetween(minz, maxz)) { if (Geometry2D.InSidePolygon(spaceVertex.Select(t => t.ToPointD()).ToArray(), point) != 2) //if (xyz.PointInPolygonByRay(spaceVertex) != -1) { gcount++; keyValuePairs_bak.Remove(pair); break; } } } } watch.Stop(); gtime = watch.ElapsedMilliseconds; #endregion MessageShow.Infomation($"Revit计算耗时{rtime},共识别出{rcount}个空间" + "\r\n" + $"Geometry计算耗时{gtime},共识别出{gcount}个空间" + "\r\n" + $"{string.Join(",", keyValuePairs_bak.Select(t => t.Key.Id))}"); } catch (Exception e) { MessageShow.Show(e); return Result.Cancelled; } return Result.Succeeded; } } #endregion /// /// 批量导出底图 /// [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class UpdateBaseMapCommand : ExternalCommand, IExternalCommandAvailability { public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { try { ReuploadBaseMap.Execute(); } catch (Exception e) { MessageShow.Show(e); return Result.Cancelled; } return Result.Succeeded; } } /// /// 上传当前楼层数据 /// [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class ExportMbiModelCommand : ExternalCommand, IExternalCommandAvailability { public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { try { var result = MessageShow.Question2("是否是整个项目导出"); switch (result) { case System.Windows.Forms.DialogResult.Yes: { var floors = DalUploadFloor.GetHasFileFloors(); List contexts = new List(); foreach (UploadFloor floor in floors) { contexts.Add(new CalcContext(floor.MFloor)); } MBIModelInfoUpload.UpdateMbiInfo(contexts); break; } case System.Windows.Forms.DialogResult.No: { var doc = ExternalDataWrapper.Current.Doc; MbiElementManager.ExecuteExport(doc); var floorId = ExternalDataWrapper.Current.Doc.PathName.GetFileName(); string sagaName = doc.GetUseView()?.Name; MBIModelInfoUpload.UploadMbiInfo(floorId, sagaName); break; } } } catch (Exception e) { MessageShow.Show(e); return Result.Cancelled; } return Result.Succeeded; } } /// /// 检查是否包含连接模型 /// [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class CheckContainLinkCommand : ExternalCommand, IExternalCommandAvailability { public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { var floors = DalUploadFloor.GetHasFileFloors(); List contexts = new List(); foreach (UploadFloor floor in floors) { contexts.Add(new CalcContext(floor.MFloor)); } #region 检测连接模型 Dictionary results = new Dictionary(); foreach (var context in contexts) { if (context == null) continue; try { context.OpenDocument(); Document doc = context.RevitDoc; MbiElementManager.ExecuteExport(doc); var floorId = doc.PathName.GetFileName(); var ins = doc.FilterElements(); if (ins.Any()) { results[floorId] = false; } } catch (Exception) { } finally { context.CloseDocument(); } #endregion } if (results.Any()) { MessageShow.Infomation(string.Join(";", results.Keys)); } else { MessageShow.Infomation("任何楼层,均不含连接模型"); } return Result.Succeeded; } public override bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories) { return true; } } /// /// 管道连接设备 /// [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class UpdatePipeSystemCommand : ExternalCommand { public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { try { var pickElement = ExternalDataWrapper.Current.UiApp.PickElement("请选择水管", new PipeFilter()); if (pickElement == null) { return Result.Succeeded; } using (Transaction tran = new Transaction(ExternalDataWrapper.Current.Doc, "连接")) { try { tran.Start(); var equipment = ExternalDataWrapper.Current.UiApp.PickElement("选择设备"); var pipeConnector = pickElement.GetConnectors(Domain.DomainPiping).FirstOrDefault(c => !c.IsConnected); var equipmentConnector = equipment.GetConnectors(Domain.DomainPiping).FirstOrDefault(c => !c.IsConnected); if (pipeConnector != null && equipmentConnector != null) { pipeConnector.ConnectTo(equipmentConnector); } tran.Commit(); } catch (Exception ex) { MessageShow.Show(ex); tran.RollBack(); } } } catch (Exception e) { MessageShow.Show(e); return Result.Cancelled; } return Result.Succeeded; } public class PipeFilter : ISelectionFilter { public bool AllowElement(Element elem) { return elem is Pipe; } public bool AllowReference(Reference reference, XYZ position) { return true; } } } /// /// 检测设备位置标记 /// [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class CheckLocationCommand : ExternalCommand, IExternalCommandAvailability { public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { try { var pickElement = ExternalDataWrapper.Current.UiApp.PickElement("请选择设备", new EquipmentFilter()) as FamilyInstance; if (pickElement == null) { return Result.Succeeded; } using (Transaction tran = new Transaction(ExternalDataWrapper.Current.Doc, "显示")) { try { tran.Start(); var doc = ExternalDataWrapper.Current.Doc; var s = pickElement.GetLocationPointMBIXYZ(); DirectShape ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel)); var solid = SolidUtil.CreateSphereAtPoint(s, 1); ds.AppendShape(new List() { solid }); SolidUtil.SetColor(ds, new Color(255, 0, 0)); tran.Commit(); ExternalDataWrapper.Current.UiApp.SetShowElements(new List() { ds }); } catch (Exception ex) { MessageShow.Show(ex); tran.RollBack(); } } } catch (Exception e) { MessageShow.Show(e); return Result.Cancelled; } return Result.Succeeded; } public class EquipmentFilter : ISelectionFilter { public bool AllowElement(Element elem) { return elem is FamilyInstance; } public bool AllowReference(Reference reference, XYZ position) { return true; } } } /// /// 测试多项目读取 /// [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class TestMultipleReadDocCommand : ExternalCommand { public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { try { var floors = DalProjectTree.GetAllFloors(false); var floor = floors.FirstOrDefault(); var doc = ExternalDataWrapper.Current.App.OpenDocumentFile(floor.FullPath); var eles = doc.GetAllElements(); string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), $"{floor}_{System.DateTime.Now.Millisecond}.txt"); //File.Create(path); foreach (Element element in eles) { File.AppendAllText(path, $"{element.Id}:{element.Name}\r\n"); } } catch (Exception e) { MessageShow.Show(e); return Result.Cancelled; } return Result.Succeeded; } public override bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories) { return true; } } /// /// 掉转阀件方向 /// [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class ReDirectionCommand : ExternalCommand { public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { using (Transaction tran = new Transaction(ExternalDataWrapper.Current.Doc, "调整阀门")) { tran.Start(); try { var pickElement = ExternalDataWrapper.Current.UiApp.PickElement("请选择阀件", typeof(FamilyInstance)) as FamilyInstance; if (pickElement == null) { return Result.Succeeded; } var handling = pickElement.HandOrientation; var facing = pickElement.FacingOrientation; var location = pickElement.GetLocationPoint(); var axis = location.NewLine(location + handling.CrossProduct(facing)); var connectors = pickElement.GetAllConnectors(); List refConnectors = new List(); foreach (var connector in connectors) { if (!ConnectorType.Physical.HasFlag(connector.ConnectorType)) { continue; } var tempRefs = connector.GetReferenceConnectors(); foreach (var tempRef in tempRefs) { if (ConnectorType.Physical.HasFlag(tempRef.ConnectorType) && tempRef.IsConnectedTo(connector)) { connector.DisconnectFrom(tempRef); refConnectors.Add(tempRef); } } } ElementTransformUtils.RotateElement(pickElement.Document, pickElement.Id, axis, Math.PI); pickElement.Document.Regenerate(); connectors = pickElement.GetAllConnectors(); for (int i = 0; i < refConnectors.Count; i++) { var refCon = refConnectors[i]; if (refCon == null) continue; var maxLength = double.MaxValue; Connector bConnector = null; foreach (var connector in connectors) { var newLength = refCon.Origin.Subtract(connector.Origin).GetLength(); if (newLength < maxLength && !connector.IsConnected) { maxLength = newLength; bConnector = connector; } } if (bConnector != null) { bConnector.ConnectTo(refCon); } } tran.Commit(); } catch (Exception e) { tran.RollBack(); MessageShow.Show(e); return Result.Cancelled; } } return Result.Succeeded; } public override bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories) { return true; } } /// /// 更新标高名称 /// [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class UpdateLevelNameCommand : ExternalCommand { public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { var document = ExternalDataWrapper.Current.Doc; using (Transaction tran = new Transaction(document, "版本测试")) { tran.Start(); try { var infoOld = ExternalDataWrapper.Current.Doc.ProjectInformation.GetSimpleClass(); if (infoOld == null) { infoOld = new ModelFileInformation() { ProjectId = "pj1" }; } else { infoOld.ProjectId = infoOld.ProjectId + "a"; } ExternalDataWrapper.Current.Doc.ProjectInformation.SetSimpleClass(infoOld); tran.Commit(); } catch (Exception e) { tran.RollBack(); MessageShow.Infomation(string.Format("{0}:失败", e.ToString())); } } return Result.Succeeded; var result = System.Windows.Forms.DialogResult.No;//MessageShow.Question2("是修改整个项目(【是】整个项目;【否】当前打开模型)"); switch (result) { case System.Windows.Forms.DialogResult.Yes: { var floors = DalUploadFloor.GetHasFileFloors(); List contexts = new List(); foreach (UploadFloor floor in floors) { contexts.Add(new CalcContext(floor.MFloor)); } #region 修改所有项目文件 foreach (var context in contexts) { if (context == null) continue; try { context.OpenDocument(); Document doc = context.RevitDoc; UpdateLevleName(doc); } catch (Exception) { } finally { context.CloseDocument(); } } #endregion break; } case System.Windows.Forms.DialogResult.No: { //MbiElementManager.ExecuteExport(ExternalDataWrapper.Current.Doc); UpdateLevleName(ExternalDataWrapper.Current.Doc); break; } } return Result.Succeeded; } private void UpdateLevleName(Document document) { using (Transaction tran = new Transaction(document, "修改标高名称")) { tran.Start(); try { Regex regex = new Regex(@"^[a-zA-Z]+(\d+)\s*\S*$"); List levels = document.GetLevels(); levels.Reverse(); for (int i = 0; i < levels.Count; i++) { var currentLevel = levels[i]; var name = currentLevel.GetParameterString(BuiltInParameter.DATUM_TEXT); if (string.IsNullOrWhiteSpace(name)) { continue; } var match1 = regex.Match(name); if (match1.Success) { var match = match1.Groups[1].ToString(); var index = name.IndexOf(match); if (index == -1) continue; var intNum = match.ToInt(); if (intNum < 14) { continue; } if (intNum < 23) { intNum = intNum + 1; } else { intNum = intNum + 2; } string newName = name.Substring(0, index) + intNum + name.Substring(index + match.Length); currentLevel.SetParameter(BuiltInParameter.DATUM_TEXT, newName); } } tran.Commit(); } catch (Exception e) { tran.RollBack(); MessageShow.Infomation(string.Format("{0}:失败", document.PathName)); } } } } /// /// 同步幕墙的本地名称、本地编码到幕墙嵌板中? /// [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class CopyLocalNameCurtainToPanelCommand : ExternalCommand { public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { try { //var tip = MessageShow.Question2("确定要执行同步幕墙的本地名称、本地编码到幕墙嵌板中?\r\n是:修正全部楼层\r\n否:修正当前楼层\r\n取消:取消修正。"); var tip = MessageShow.Question("确定要执行同步幕墙的本地名称、本地编码到幕墙嵌板中?\r\n是:修正当前楼层\r\n否:取消修正。"); switch (tip) { case true: MFloor floor = ExternalDataWrapper.Current.Doc.GetCurMFloor(); if (floor != null) SingleInstance.Instance.Execute(floor); break; default: break; } } catch (Exception e) { MessageShow.Show(e); return Result.Cancelled; } return Result.Succeeded; } } }