Files
SzmediTools/Szmedi.Test/TestCmd.cs
2025-09-16 16:06:41 +08:00

708 lines
30 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Xml.Linq;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using CommunityToolkit.Mvvm.DependencyInjection;
using Nice3point.Revit.Toolkit.External;
using Nice3point.Revit.Toolkit.Utils;
using OfficeOpenXml;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using RevitAddins;
using Szmedi.RvKits.Mvvm.Attributes;
using Wpf.Ui;
namespace Szmedi.Test
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
[ShortcutRep("TEST")]
public class TestCmd : ExternalCommand
{
//一个判断两条模型线是否平行的方法
/// <summary>
/// 扩展包围盒的大小
/// </summary>
/// <param name="boundingBox"></param>
/// <param name="distance"></param>
/// <returns></returns>
public static BoundingBoxXYZ Extend(BoundingBoxXYZ boundingBox, double distance = 2.0)
{
var transform = boundingBox.Transform;
var max = boundingBox.Max + (distance * (transform.BasisX + transform.BasisY + transform.BasisZ));
var min = boundingBox.Min - (distance * (transform.BasisX + transform.BasisY + transform.BasisZ));
return new BoundingBoxXYZ { Max = max, Min = min, Transform = transform };
}
// 合法化 Sheet 名称
private string MakeValidSheetName(string name)
{
var invalid = new[] { '\\', '/', '*', '[', ']', ':', '?' };
foreach (var ch in invalid)
{
name = name.Replace(ch, '_');
}
return name.Length > 31 ? name.Substring(0, 31) : name;
}
private void NewMethod(IEnumerable<IGrouping<string, ElementModel>> groupedModels)
{
using (var pkg = new ExcelPackage())
{
//深圳构件标识
foreach (var g in groupedModels)
{
var sheetName = MakeValidSheetName(g.Key);
var ws = pkg.Workbook.Worksheets.Add(sheetName);
//第一行
ws.Cells[1, 1].Value = g.Key;
var columns = g.Sum(m => m.Count);
//合并单元格
ws.Cells[1, 1, 1, columns].Merge = true;
ws.Cells[1, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
ws.Cells[1, 1].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center;
ws.Cells[1, 1].Style.Font.Size = 20;
ws.Cells[1, 1].Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.FromArgb(255, 255, 0));
ws.Cells[1, 1].Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin);
var currentColumns = 1;
var models = g.ToList();
foreach (var m in models)
{
var subColumns = m.Count;
//第二行
ws.Cells[2, currentColumns, 2, subColumns].Merge = true;
//合并单元格
ws.Cells[2, currentColumns].Value = models.FirstOrDefault().Groups.Keys;
currentColumns += 1 + subColumns;
}
}
}
}
private static bool IsParallel(Line line1, Line line2)
{
return line1.Direction.IsAlmostEqualTo(line2.Direction) ||
line1.Direction.IsAlmostEqualTo(-line2.Direction);
}
//private bool IsConnectToSystem(FamilyInstance ins)
//{
// bool hasConnectToSystem = false;
// if (ins.Category.CategoryType != CategoryType.FacilityNumber)
// {
// return true;
// }
// if (ins.get_BoundingBox(null) != null &&
// ins.MEPModel?.ConnectorManager != null)
// {
// var cons = ins.GetConnectors(false);
// foreach (Connector con in cons)
// {
// if (con.Domain != Domain.DomainElectrical && con.Domain != Domain.DomainUndefined)
// {
// try
// {
// if (con.IsConnected)
// {
// hasConnectToSystem = true;
// }
// }
// catch (Exception)
// {
// }
// }
// }
// }
// return hasConnectToSystem;
//}
public override void Execute()
{
var walls = new FilteredElementCollector(Document).WhereElementIsNotElementType()
.OfClass(typeof(Wall))
.ToElements()
.Cast<Wall>()
.ToList();
foreach (var wall in walls)
{
var inserts = wall.FindInserts(true, false, false, false);
foreach (var id in inserts)
{
var insert = Document.GetElement(id);
if (insert != null)
{
switch (insert)
{
//门窗
case FamilyInstance fi:
{
var symbol = fi.Symbol;
//Revit2018
//宽度
var width = symbol.get_Parameter(BuiltInParameter.DOOR_WIDTH).AsValueString();
//高度
var height = symbol.get_Parameter(BuiltInParameter.GENERIC_HEIGHT).AsValueString();
//Revit2020
var width2020 = symbol.get_Parameter(BuiltInParameter.FURNITURE_WIDTH).AsValueString();
var height2020 = symbol.get_Parameter(BuiltInParameter.FAMILY_HEIGHT_PARAM).AsValueString();
break;
}
//洞口
case Opening o:
{
var minPoint = o.BoundaryRect[0];
var maxPoint = o.BoundaryRect[1];
//高度
var height = Math.Abs(maxPoint.Z - minPoint.Z) * 304.8;
var minPointFlatten = new XYZ(minPoint.X, minPoint.Y, 0);
var maxPointFlatten = new XYZ(maxPoint.X, maxPoint.Y, 0);
//宽度
var width = minPointFlatten.DistanceTo(maxPointFlatten) * 304.8;
MessageBox.Show($"{width} x {height}");
break;
}
default:
break;
}
}
}
}
//var elements = UiDocument.Selection
// .GetElementIds()
// .Select(Document.GetElement)
// .Cast<FamilyInstance>()
// .Where(e => e.get_Parameter(BuiltInParameter.INSTANCE_ELEVATION_PARAM).AsDouble() < 10e-5)
// .Select(e => e.Id).ToList();
//UiDocument.Selection.SetElementIds(elements);
return;
//Document.Invoke(ts =>
//{
// elements.ForEach(e=>e.Host)
//})
//Material.Create(Document, "测试材质");
//var reference = UiDocument.Selection.PickObject(ObjectType.Element);
//var ins = Document.GetElement(reference) as FamilyInstance;
//var bo = IsConnectToSystem(ins);
//MessageBox.Show(bo.ToString());
//return;
#if false
var manager = Document.FamilyManager;
var names = manager.Types.OfType<FamilyType>().Select(t => t.Name);
bool b = names.Contains(" ");
MessageBox.Show(manager.Types.Size.ToString());
return;
var e = UiDocument.Selection.PickElementsByRectangle().Cast<MEPCurve>().FirstOrDefault();
//var b1 = e.Diameter == null;
//var b2 = e.Height == null;
//MessageBox.Show(.ToString());
return;
var refer1 = UiDocument.Selection.PickObject(ObjectType.Element, new GenericFilter<ModelCurve>(), "选择模型线");
var elem = Document.GetElement(refer1) as ModelCurve;
var col = new FilteredElementCollector(Document, Document.ActiveView.Id).WhereElementIsNotElementType()
.Where(e => e is ModelCurve mc && mc.LineStyle.Id == elem.LineStyle.Id).Select(e => e.Id).ToList();
UiDocument.Selection.SetElementIds(col);
//var refer2 = UiDocument.Selection.PickObject(ObjectType.Element, new GenericFilter<ModelCurve>(), "选择模型线");
//var elem2 = Document.GetElement(refer2) as ModelCurve;
//if (IsParallel(elem.GeometryCurve as Line, elem2.GeometryCurve as Line))
//{
// MessageBox.Show("平行");
//}
//var groups = Document.OfParentModelCollector().WhereElementIsNotElementType()
// .GroupBy(e => e.GetParameters("深圳构件标识").FirstOrDefault().AsString());
//StringBuilder sb = new StringBuilder();
//foreach (var element in groups)
//{
// sb.AppendLine(element.Key);
//}
//MessageBox.Show(sb.ToString());
//var reference = UiDocument.Selection.PickObject(ObjectType.PointOnElement, new GenericFilter<ImportInstance>(), "请选择CAD文字");
//var instance = doc.GetElement(reference) as ImportInstance;
//var ids = UiDocument.Selection.GetElementIds();
//Document.Modify(
// settings => settings.Transaction).Commit((doc, _) =>
// {
//var familyName = "族名称";
//using (Transaction ts = new Transaction(doc, "更新族类型名称"))
//{
// ts.Start();
// //获取某个族
// var element = new FilteredElementCollector(doc).OfClass(typeof(Family)).Where(e => e.Name == familyName).Cast<Family>().FirstOrDefault();
// if (element == null)
// {
// TaskDialog.Show("提示", "没有找到指定的族");
// ts.RollBack();
// return;
// }
// var ids = element.GetFamilySymbolIds();
// foreach (var id in ids)
// {
// //获取族类型
// var symbol = doc.GetElement(id) as FamilySymbol;
// //宽度
// var w = Convert.ToDouble(symbol.GetParameters("宽度").FirstOrDefault().AsValueString());
// //高度
// var h = Convert.ToDouble(symbol.GetParameters("高度").FirstOrDefault().AsValueString());
// if (ids != null)
// {
// //前缀
// var prefix = string.Empty;
// //后缀
// var suffix = string.Empty;
// string width = string.Empty;
// string height = string.Empty;
// if (w / 1000 < 1)
// {
// width = $"0{w}mm";
// }
// if (h / 1000 < 1)
// {
// height = $"0{h}mm";
// }
// //如果width和height最后一个数字是5则把5改成a
// if (width.Last() == '5')
// {
// width = width.Remove(width.Length - 1) + "a";
// }
// if (height.Last() == '5')
// {
// height = height.Remove(height.Length - 1) + "a";
// }
// var newName = $"{prefix}{width} x {height}{suffix}";
// symbol.Name = newName;
// }
// }
// ts.Commit();
//}
// });
//var ids = Document.ActiveView
// .OfCollector()
// .Where(e => e.get_Parameter(BuiltInParameter.DOOR_NUMBER)?.AsString() == "J4921321-11332-(005)DK0001").Select(e => e.Id).ToList();
//MessageBox.Show(ids.Count.ToString());
//UiDocument.Selection.SetElementIds(ids);
//var elemIds = GetElementIds();
//var ids = UiDocument.Selection.GetElementIds();
//var start = new XYZ(-61995.832703373, 4243.667605320, 5999.999999997);
//var end = new XYZ(0.000000000, 0.000000000, 5999.999999997);
//var translate = (end - start) / 304.8;
//using (Transaction ts = new Transaction(doc, "移动"))
//{
// ts.Start();
// ElementTransformUtils.MoveElements(doc, ids, translate);
// ts.Commit();
//}
//var id = UiDocument.Selection.GetElementIds().FirstOrDefault();
//var ids = doc.GetElement(id) as FamilyInstance;
//var n = ids.GetSubComponentIds().Count;
//MessageBox.Show(n.ToString());
//var ids = UiDocument.Selection.GetElementIds();
//var translate = XYZ.BasisZ * 20;
//using (Transaction ts = new Transaction(doc, "移动"))
//{
// ts.Start();
// ElementTransformUtils.CopyElements(doc, ids, translate);
// ElementTransformUtils.MoveElements(doc, ids, translate);
// ts.Commit();
//}
#endif
#if false
var symbols = new FilteredElementCollector(Document).OfClass(typeof(Wall)).ToElementIds();
foreach (var item in symbols)
{
var elem = Document.GetElement(item);
var cat = elem.Category.Name;
var cate = Category.GetCategory(Document, elem.Category.Id);
var cate1 = Category.GetCategory(Document, (BuiltInCategory)elem.Category.Id.IntegerValue);
}
var dict = new FilteredElementCollector(Document).OfClass(typeof(ElementType))
.OfType<ElementType>()
.Where(
t => t.CanBeRenamed && t.Category is { CategoryType: CategoryType.Model or CategoryType.Annotation })
.GroupBy(t => t.Category.Id)
.Where(g => !string.IsNullOrEmpty(g.FirstOrDefault().Category?.Name))
.ToDictionary(g => g.FirstOrDefault().Category.Name, g => g.ToList());
//UiDocument.Selection.SetElementIds(symbols);
StringBuilder sb = new StringBuilder();
foreach (var kv in dict)
{
foreach (var item in kv.Value)
{
if (item is WallType t)
{
sb.AppendLine($"{kv.Key}-{t.Kind}-{item.Name}");
}
}
}
MessageBox.Show(sb.ToString());
#endif
//foreach (BuiltInCategory id in Enum.GetValues(typeof(BuiltInCategory)))
//{
// var names = Enum.GetName(typeof(BuiltInCategory), id);
//}
//using (Transaction ts = new Transaction(doc, "修改类型名称"))
//{
// ts.Start();
// try
// {
// foreach (var id in symbols)
// {
// if (id.Name == "标准")
// {
// if (id is FamilySymbol ids)
// {
// id.Name = ids.FamilyName;
// }
// }
// }
// }
// catch (Exception)
// {
// throw;
// }
// ts.Commit();
//}
//UiDocument.Selection.SetElementIds([new ElementId(2222596)]);
//var dims = doc.QueryElementsByType<Dimension>().WhereElementIsNotElementType().ToElementIds();
//UiDocument.Selection.SetElementIds(dims);
//var refer = UiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
//var ids = doc.GetElement(refer);
//foreach (Parameter param in ids.Parameters)
//{
//}
#region MyRegion
////var service = new ricaun.Revit.ExtensibleShortcuts.Services.KeyboardShortcutService();
////service.SetRibbonItemShortcut("CustomCtrl_%CustomCtrl_%SZMEDI工具%机电工具%MoveConnectCmd", "MC");
//var dict = ShortcutsHelper.Commands;
//StringBuilder sb = new StringBuilder();
//sb.AppendLine("Name,CommandName,CommandId,CommandPaths,CommandScope,Shortcuts,ShortcutType,ShortcutsRep,");
//foreach (var id in dict)
//{
// string text = id.Value.CommandName;
// string commandName = string.Join("", text.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries));
// sb.AppendLine(
// $"{id.Key},{commandName},{id.Value.CommandId},{id.Value.CommandPaths},{id.Value.CommandScope},{id.Value.Shortcuts},{id.Value.ShortcutType},{id.Value.ShortcutsRep},");
// //if (ShortcutsHelper.Commands.TryGetValue("CustomCtrl_%CustomCtrl_%SZMEDI工具%机电工具%MoveConnectCmd", out var shortcutItem))
// //{
// // //为命令指定快捷键QQQQ
// // shortcutItem.Shortcuts.Add("MC");
// // break;
// // //为命令删除快捷键QQQQ
// // //shortcutItem.Shortcuts.Remove("QQQQ");
// // //为命令清空快捷键
// // //shortcutItem.Shortcuts.Clear();
// //}
//}
//LogUtil.WriteTxtFile("快捷键", sb.ToString());
////KeyboardShortcutService.applyShortcutChanges(dict);
#endregion
//var window = new MainWindow() { DataContext = new MainWindowViewModel(UiDocument) };
//window.Show();
//var refer = UiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
//var ids = doc.GetElement(refer);
//var boundingbox = ids.get_BoundingBox(null);
//using var ts = new Transaction(doc, "Test");
//ts.Start();
//if (doc.ActiveView is View3D view3D)
//{
// view3D.SetSectionBox(Extend(boundingbox));
//}
//ts.Commit();
//var ids = UiDocument.Selection.GetElementIds();
//using (var ts = new Transaction(doc, "Test"))
//{
// ts.Start();
// foreach (var id in ids)
// {
// var ids = doc.GetElement(id) as FamilyInstance;
// //ElementTransformUtils.RotateElement(doc, id, Line.CreateUnbound((ids.Location as LocationPoint).Point, XYZ.BasisZ), /*65.43 / 180 * */Math.PI);
// ElementTransformUtils.MoveElement(doc, id, ids.HandOrientation * 1200 / 304.8);
// doc.Regenerate();
// //ElementTransformUtils.RotateElement(doc, id, Line.CreateUnbound((ids.Location as LocationPoint).Point, XYZ.BasisZ), /*65.43 / 180 * */Math.PI);
// }
// ts.Commit();
//}
#region Updater
//ChangeTypeUpdater _updater = new(UiApplication, new Guid("{A3441B77-7558-41EF-A3BF-4690C99F67C0}"));
//UpdaterRegistry.RegisterUpdater(_updater, true);
//UpdaterRegistry.AddTrigger(_updater.GetUpdaterId(), new ElementClassFilter(typeof(FamilyInstance)), Element.GetChangeTypeAny());
#endregion
//var ids = UiDocument.Selection.GetElementIds().Select(id=>doc.GetElement(id)).OfType<ModelCurve>().Select(mc=>mc.GeometryCurve).ToList();
//SetComparisonResult comparisonR = ids[0].Intersect(ids[1], out var intersectionResult);
//System.Windows.MessageBox.Show($"{comparisonR}");
//try
//{
// var cl = CurveLoop.Create(ids);
//}
//catch (Exception)
//{
// throw;
//}
//Application.DocumentChanged -= Application_DocumentChanged;
//Application.DocumentChanged += Application_DocumentChanged;
#region MyRegion
var refer = UiDocument.Selection.PickObject(ObjectType.Element);
var ids = (Document.GetElement(refer) as FamilyInstance).Symbol;
Document.Modify(set => set.Transaction)
.Commit((d, _) =>
{
if (!ids.IsActive)
{
ids.Activate();
}
var level = new FilteredElementCollector(d).OfClass(typeof(Level))
.OfType<Level>()
.FirstOrDefault(l => l.Elevation > 0);
d.Create
.NewFamilyInstance(
new XYZ(0, 0, 0),
ids,
level,
Autodesk.Revit.DB.Structure.StructuralType.NonStructural);
});
#endregion
//XYZ p1 = new XYZ();
//XYZ p2 = XYZ.BasisX;
//XYZ p3 = XYZ.BasisY;
//XYZ p4 = XYZ.BasisZ;
//var list = new List<XYZ>() { p1, p2, p3 };
//HermiteSpline curve = HermiteSpline.Create(list, false);
//using (Transaction ts = new Transaction(doc, "test"))
//{
// ts.Start();
// SketchPlane sketch = SketchPlane.Create(doc, Plane.CreateByNormalAndOrigin(p4, p1));
// var mc = doc.Create.NewModelCurve(curve, sketch);
// ts.Commit();
//}
//Autodesk.Revit.DB.Reference e = UiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
}
private static void MoveRoomSeparator(Document doc, ICollection<ElementId> ids, double dis)
{
var distance = dis / 304.8;
foreach (var id in ids)
{
var element = doc.GetElement(id);
if (element is ModelCurve modelCurve)
{
var start = modelCurve.GeometryCurve.GetEndPoint(0);
var end = modelCurve.GeometryCurve.GetEndPoint(1);
var sketch = SketchPlane.Create(doc,
Plane.CreateByNormalAndOrigin(XYZ.BasisZ, start + (XYZ.BasisZ * distance)));
var line = Line.CreateBound(start + (XYZ.BasisZ * distance), end + (XYZ.BasisZ * distance));
var array = new CurveArray();
array.Append(line);
doc.Create.NewRoomBoundaryLines(sketch, array, doc.ActiveView);
}
}
doc.Delete(ids);
}
private static void DrawColumnsBoundLines(Document doc, List<Element> selectedColumns)
{
foreach (FamilyInstance column in selectedColumns)
{
// 获取结构柱的几何信息
var geomOptions = new Options();
var geomElement = column.get_Geometry(geomOptions);
foreach (var geomObj in geomElement)
{
var geometryInstance = geomObj as GeometryInstance;
if (geometryInstance != null)
{
// 处理几何实例
var instanceGeomElement = geometryInstance.GetInstanceGeometry();
foreach (var instanceGeomObj in instanceGeomElement)
{
if (instanceGeomObj is Solid solid)
{
foreach (Face face in solid.Faces)
{
if (face is PlanarFace planarFace &&
planarFace.FaceNormal.IsAlmostEqualTo(-XYZ.BasisZ))
{
var edgeLoops = planarFace.EdgeLoops;
foreach (EdgeArray edgeArray in edgeLoops)
{
var curveArray = new CurveArray();
foreach (Edge edge in edgeArray)
{
var curve = edge.AsCurve();
curveArray.Append(curve);
}
if (curveArray.Size > 0)
{
// 获取活动视图的 SketchPlane
var sketchPlane = SketchPlane.Create(
doc,
doc.ActiveView.GenLevel.Id);
// 绘制房间分割线
var lines = doc.Create
.NewRoomBoundaryLines(sketchPlane, curveArray, doc.ActiveView);
}
}
}
}
}
}
}
}
}
}
public class SelectionFilter : ISelectionFilter
{
public bool AllowElement(Element elem)
{
return elem is Wall;
}
public bool AllowReference(Reference reference, XYZ position)
{
return true;
}
}
public class ChangeTypeUpdater : IUpdater
{
private UpdaterId _uid;
public ChangeTypeUpdater(UIApplication uiapp, Guid guid)
{
_uid = new UpdaterId(uiapp.ActiveAddInId,
guid);
}
public void Execute(UpdaterData data)
{
Func<ICollection<ElementId>, string> toString = ids =>
ids.Aggregate(string.Empty, (ss, id) => ss + "," + id).TrimStart(',');
StringBuilder sb = new();
sb.AppendLine("added:" + toString(data.GetAddedElementIds()));
sb.AppendLine("modified:" + toString(data.GetModifiedElementIds()));
sb.AppendLine("deleted:" + toString(data.GetDeletedElementIds()));
TaskDialog.Show("Changes", sb.ToString());
}
public string GetAdditionalInformation()
{
return "N/A";
}
public ChangePriority GetChangePriority()
{
return ChangePriority.FreeStandingComponents;
}
public UpdaterId GetUpdaterId()
{
return _uid;
}
public string GetUpdaterName()
{
return "ChangeTypeUpdater";
}
}
private void Application_DocumentChanged(object sender, Autodesk.Revit.DB.Events.DocumentChangedEventArgs e)
{
var a = sender as Autodesk.Revit.ApplicationServices.Application;
var doc = e.GetDocument();
ElementClassFilter filter = new(typeof(FamilyInstance));
var modifyIds = e.GetModifiedElementIds(filter);
var addIds = e.GetAddedElementIds(filter);
var deleteIds = e.GetDeletedElementIds();
StringBuilder sb = new();
if (modifyIds.Count > 0)
{
sb.AppendLine("修改");
foreach (var id in modifyIds)
{
sb.AppendLine($"{id}-{doc.GetElement(id).Name}");
}
}
if (addIds.Count > 0)
{
sb.AppendLine("添加");
foreach (var id in addIds)
{
sb.AppendLine($"{id}-{doc.GetElement(id).Name}");
}
}
if (deleteIds.Count > 0)
{
sb.AppendLine("删除");
foreach (var id in deleteIds)
{
sb.AppendLine($"{id}-{doc.GetElement(id).Name}");
}
}
MessageBox.Show(sb.ToString(), "文档修改");
}
}
}