Files
SzmediTools/Szmedi.Test/RevitAddin.cs
2026-01-16 17:07:43 +08:00

409 lines
17 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.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.UI;
using Autodesk.Windows;
using Nice3point.Revit.Toolkit.External;
//using Szmedi.Toolkit.Assists;
namespace Szmedi.Test
{
[Transaction(TransactionMode.Manual)]
internal class RevitAddin : ExternalCommand
{
public override void Execute()
{
//UiApplication.Application.DocumentOpening+= (s, e) =>
//{
// MessageBox.Show("DocumentOpening");
//};
//UiApplication.Application.FamilyLoadingIntoDocument += (s, e) =>
//{
// MessageBox.Show("FamilyLoadingIntoDocument");
//};
//UiApplication.Application.FamilyLoadedIntoDocument += (s, e) =>
//{
// MessageBox.Show("FamilyLoadedIntoDocument");
//};
//var ptr = ComponentManager.ApplicationWindow;
var win = GetWindowFromHwnd(Process.GetCurrentProcess().MainWindowHandle);
win?.Drop += (s, e) =>
{
MessageBox.Show("Drop");
};
//UIApplication.DoDragDrop(, new DropHandler());
return;
#if false
var refer = UiDocument.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);
var wall = Document.GetElement(refer);
//var point = UiDocument.Selection.PickPoint(Autodesk.Revit.UI.Selection.ObjectSnapTypes.Nearest);
#endif
Array builtInCategories = Enum.GetValues(typeof(BuiltInCategory));
StringBuilder sb = new StringBuilder();
var encoding = Encoding.GetEncoding(936);
var str = File.ReadAllText(@"E:\Users\Zhanggg\Downloads\exportlayers-dwg-SZMEDI.txt", encoding);
foreach (BuiltInCategory cate in builtInCategories)
{
try
{
var name = Enum.GetName(typeof(BuiltInCategory), cate).Remove(0, 4);
var category = Document.Settings.Categories.get_Item(cate);
//var category = Category.GetCategory(Document, cate);
// 使用正则表达式进行全字匹配替换
str = Regex.Replace(
str,
$@"\b{Regex.Escape(name)}\b", // 自动处理特殊字符
category.Name,
RegexOptions.None); // 可选:是否区分大小写
//str = str.Replace(name, category.Name);
//if (category != null
// && category.CategoryType == CategoryType.FacilityNumber && category.AllowsBoundParameters)
//{
// sb.AppendLine($"{category.Name},{Enum.GetName(typeof(BuiltInCategory), cate)},");
//}
}
catch (Exception)
{
}
}
File.WriteAllText(@"E:\Users\Zhanggg\Downloads\exportlayers-dwg-SZMEDI-Result.txt", str, encoding);
//LogAssists.WriteTxtFile("内建类别", sb.ToString());
}
/// <summary>
/// 通过窗口句柄安全地获取WPF窗口对象
/// </summary>
/// <param name="hwnd">窗口句柄</param>
/// <returns>对应的WPF窗口对象如果找不到则返回null</returns>
public static Window GetWindowFromHwnd(IntPtr hwnd)
{
try
{
// 从句柄获取HwndSource
var hwndSource = HwndSource.FromHwnd(hwnd);
if (hwndSource == null)
{
return null;
}
// 检查RootVisual是否为Window类型
if (hwndSource.RootVisual is DependencyObject rootVisual)
{
// 通过可视化树向上查找Window
DependencyObject current = rootVisual;
while (current != null)
{
if (current is Window window)
{
return window;
}
current = VisualTreeHelper.GetParent(current);
}
}
}
catch (Exception ex)
{
// 可以在此记录异常或进行其他处理
Console.WriteLine($"获取窗口失败: {ex.Message}");
}
return null;
}
private static void MoveElement(Element item, XYZ vector)
{
if (item.Pinned || !item.IsValidObject || item == null)
{
return;
}
var doc = item.Document;
var levels = doc.OfType<Level>().OrderBy(l => l.Elevation).ToList();
if (item is FamilyInstance instance)
{
var baseElev = instance.get_BoundingBox(null).Min.Z + vector.Z;
var topElev = instance.get_BoundingBox(null).Max.Z + vector.Z;
var baseLevel = GetClosetLevel(levels, baseElev);
var topLevel = GetClosetLevel(levels, topElev);
switch (instance.Symbol.Family.FamilyPlacementType)
{
//柱
case FamilyPlacementType.TwoLevelsBased:
{
instance.Location.Move(vector);
instance.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_PARAM).Set(baseLevel.Id);
instance.get_Parameter(BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM).Set(baseElev - baseLevel.Elevation);
instance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_PARAM).Set(topLevel.Id);
instance.get_Parameter(BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM).Set(topElev - topLevel.Elevation);
}
break;
case FamilyPlacementType.ViewBased:
break;
case FamilyPlacementType.WorkPlaneBased:
{
//instance.Location.Move(vector);
var param = instance.get_Parameter(BuiltInParameter.INSTANCE_ELEVATION_PARAM);
if (param != null && !param.IsReadOnly)
{
ElementTransformUtils.MoveElement(doc, instance.Id, XYZ.BasisZ * vector.Z);
//var value = param.AsDouble() + vector.Z;
//param.Set(value);
}
doc.Regenerate();
if (instance.Host == null)
{
ElementTransformUtils.MoveElement(doc, instance.Id, vector.Flatten());
}
}
break;
case FamilyPlacementType.OneLevelBased:
{
ElementTransformUtils.MoveElement(doc, instance.Id, vector);
}
break;
case FamilyPlacementType.OneLevelBasedHosted:
{
var ins = doc.Create
.NewFamilyInstance(
instance.GetLocXYZ(),
instance.Symbol,
instance.Host,
baseLevel,
StructuralType.NonStructural);
ins.get_Parameter(BuiltInParameter.INSTANCE_SILL_HEIGHT_PARAM)
.Set(baseElev - baseLevel.Elevation);
doc.Delete(instance.Id);
}
break;
case FamilyPlacementType.CurveBased:
{
instance.Location.Move(vector);
//var loc = instance.GetLocCurve().CreateTransformed(Transform.CreateTranslation(vector)) as Line;
//doc.Create.NewFamilyInstance(instance.HostFace, loc, instance.Symbol);
//doc.Delete(instance.Id);
}
break;
case FamilyPlacementType.CurveBasedDetail:
break;
//梁
case FamilyPlacementType.CurveDrivenStructural:
{
//instance.Location.Move(vector);
var loc = instance.GetLocCurve().CreateTransformed(Autodesk.Revit.DB.Transform.CreateTranslation(vector));
//var newLoc =
doc.Create.NewFamilyInstance(loc, instance.Symbol, baseLevel, StructuralType.Beam);
doc.Delete(instance.Id);
//ElementTransformUtils.MoveElement(doc, instance.Id, vector.Flatten());
}
break;
case FamilyPlacementType.Adaptive:
break;
case FamilyPlacementType.Invalid:
break;
default:
break;
}
}
else if (item is Wall wall)
{
var flat = vector.Flatten();
ElementTransformUtils.MoveElement(doc, wall.Id, flat);
doc.Regenerate();
SetWallHeight(vector, levels, wall);
var elemIds = wall.FindInserts(true, true, true, true);
foreach (var id in elemIds)
{
var elem = doc.GetElement(id);
if (elem is Wall nestWall)
{
SetWallHeight(vector, levels, nestWall);
}
else
{
MoveElement(elem, vector);
}
}
//墙饰条
var sweeps = doc.OfType<WallSweep>().Where(s => s.GetHostIds().Contains(wall.Id));
foreach (var sweep in sweeps)
{
//ElementTransformUtils.MoveElement(doc, sweep.Id, flat);
var boundingBox = sweep.get_BoundingBox(null);
var offset = boundingBox.Min.Z + vector.Z;
var baseLevel = levels.First(l => Math.Abs(l.Elevation - offset) == levels.Min(l => Math.Abs(l.Elevation - offset)));
sweep.get_Parameter(BuiltInParameter.WALL_SWEEP_LEVEL_PARAM).Set(baseLevel.Id);
sweep.get_Parameter(BuiltInParameter.WALL_SWEEP_OFFSET_PARAM).Set(offset - baseLevel.Elevation);
}
//依附在墙上的实例
var instances = doc.OfType<FamilyInstance>().Where(s =>
{
var stackedWallIds = wall.GetStackedWallMemberIds();
if (stackedWallIds.Count > 0)
{
return stackedWallIds.Any(id => s.Host?.Id == id);
}
return s.Host?.Id == wall.Id;
}).ToList();
foreach (var ins in instances)
{
//ins.Location.Move(vector);
ElementTransformUtils.MoveElement(doc, ins.Id, vector.Z * XYZ.BasisZ);
}
//ElementTransformUtils.CopyElements(v1, [wall.Id], v2, Transform.Identity, new CopyPasteOptions());
//var b = wall.Location.Move(vector);
//var loc = wall.GetLocCurve();
//var c = loc.CreateTransformed(Transform.CreateTranslation(vector));
//(wall.Location as LocationCurve).Curve = c; //可以移动,但是偏移量属性没更新
}
else if (item is Room room)
{
}
else if (item is Stairs stairs)
{
var flat = vector.Flatten();
ElementTransformUtils.MoveElement(doc, item.Id, flat);
}
else if (item is ModelCurve curve)//房间分割
{
}
else if (item is Railing railing)
{
if (railing.HasHost)
{
}
else//连带主体移动
{
ElementTransformUtils.MoveElement(doc, item.Id, vector);
}
}
//坡道
else if (item.Category.ToBuiltInCategory() == BuiltInCategory.OST_Ramps)
{
var flat = vector.Flatten();
ElementTransformUtils.MoveElement(doc, item.Id, flat);
}
else if (item is TopographySurface surface)
{
}
else if (item is SlabEdge or Fascia or Gutter)
{
return;
}
//else if (item is CeilingAndFloor ceilingAndFloor)
//{
// ElementTransformUtils.MoveElement(doc, ceilingAndFloor.Id, vector);
//}
else if (item is Opening opening)
{
if (opening.Host is Wall)
{
ElementTransformUtils.MoveElement(doc, opening.Id, vector.Z * XYZ.BasisZ);
}
}
else
{
ElementTransformUtils.MoveElement(doc, item.Id, vector);
}
}
/// <summary>
/// 设置墙高度
/// </summary>
/// <param name="vector"></param>
/// <param name="levels"></param>
/// <param name="wall"></param>
private static void SetWallHeight(XYZ vector, List<Level> levels, Wall wall)
{
var boundingBox = wall.get_BoundingBox(null);
//底部实际高度
var bottomElev = boundingBox.Min.Z + vector.Z;
var topElev = boundingBox.Max.Z + vector.Z;
//查找距离底部偏移最近的Level
var baseLevel = GetClosetLevel(levels, bottomElev);
wall.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT).Set(baseLevel.Id);
wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(bottomElev - baseLevel.Elevation);
//是否有顶部约束
var topContraint = wall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).AsElementId();
if (topContraint != ElementId.InvalidElementId)
{
var topLevel = GetClosetLevel(levels, topElev);
wall.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).Set(topLevel.Id);
wall.get_Parameter(BuiltInParameter.WALL_TOP_OFFSET).Set(topElev - topLevel.Elevation);
}
}
/// <summary>
/// 获取距离最近的标高
/// </summary>
/// <param name="levels"></param>
/// <param name="elev">高度</param>
/// <returns></returns>
private static Level GetClosetLevel(List<Level> levels, double elev)
{
return levels.First(l => Math.Abs(l.Elevation - elev) == levels.Min(l => Math.Abs(l.Elevation - elev)));
}
private void Application_DocumentChanged(object sender, Autodesk.Revit.DB.Events.DocumentChangedEventArgs e)
{
UiApplication.Application.DocumentChanged -= Application_DocumentChanged;
var sb = new StringBuilder();
var doc = e.GetDocument();
sb.AppendLine("删除的元素ID");
e.GetDeletedElementIds().ToList().ForEach(id => sb.AppendLine(id.IntegerValue.ToString()));
//Debug.WriteLine(e.GetDeletedElementIds().Count);
sb.AppendLine("修改的元素");
e.GetModifiedElementIds().Select(Document.GetElement).Where(e => e != null && e.Category != null && e.Category.CategoryType == CategoryType.Model && e.get_BoundingBox(null) != null).ToList().ForEach(e =>
{
sb.AppendLine(e?.Category.Name + "---------" + e?.Name);
});
File.WriteAllText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "修改的元素.txt"), sb.ToString());
}
}
public class DropHandler : IControllableDropHandler
{
public bool CanExecute(UIDocument document, object data, ElementId dropViewId)
{
throw new NotImplementedException();
}
public void Execute(UIDocument document, object data)
{
throw new NotImplementedException();
}
}
}