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;
}
}
}