using System.Linq; using System.Text; using System.Windows; using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Architecture; using Autodesk.Revit.UI.Selection; using Nice3point.Revit.Toolkit.External; namespace Szmedi.RvKits.ModelManager { [Transaction(TransactionMode.Manual)] public class MoveModelCmd : ExternalCommand { private static bool IsSketchedStairsRun(Stairs stairs) { var id = stairs.GetStairsRuns().FirstOrDefault(); if (id == null) return false; var run = stairs.Document.GetElement(id) as StairsRun; return run?.StairsRunStyle == StairsRunStyle.Sketched; } public override void Execute() { //基于面主体的图元,不进行移动 var elementsBaseFace = Document.OfClass() .Where( e => e is FamilyInstance ins && ins.Symbol.Family.FamilyPlacementType == FamilyPlacementType.WorkPlaneBased && ins.Host == null && ins.HostFace == null); var ids = elementsBaseFace.Select(e => e.Id).ToList(); var collector = Document .OfParentModelCollector(); if (ids.Count > 0) { collector = collector.Excluding(ids); } var elems = collector.Where( element => element.GetType() != typeof(RevitLinkInstance) && element.GroupId == ElementId.InvalidElementId) .ToList(); if (elems == null) { MessageBox.Show("没有找到模型元素", "错误"); return; } //组 var groups = Document.QueryElementsByType().WhereElementIsNotElementType().ToElements(); //var basePoints = doc.QueryElementsByType().ToElements(); //标高 var levels = Document.QueryElementsByType().WhereElementIsNotElementType().ToElements(); //线条 var modelCurve = new FilteredElementCollector(Document).OfCategory(BuiltInCategory.OST_Lines).WhereElementIsNotElementType().ToElements(); //视图 var viewers = Document.QueryElementsByCategory(BuiltInCategory.OST_Viewers).WhereElementIsNotElementType().ToElements(); //常规注释族 var annotations = Document.QueryElementsByCategory(BuiltInCategory.OST_GenericAnnotation).WhereElementIsNotElementType().ToElements(); //立面 var elevs = Document.QueryElementsByCategory(BuiltInCategory.OST_Elev).WhereElementIsNotElementType().ToElements(); //轴网 var grids = Document.QueryElementsByType().WhereElementIsNotElementType().ToElements(); //尺寸标注 var dims = Document.QueryElementsByType().WhereElementIsNotElementType().ToElements(); //文字 var texts = Document.QueryElementsByType().WhereElementIsNotElementType().ToElements(); //标记 var tags = Document.QueryElementsByType().WhereElementIsNotElementType().ToElements(); //填充 var fillRegions = Document.QueryElementsByType().WhereElementIsNotElementType().ToElements(); //洞口 var openings = Document.QueryElementsByType().Cast().Where(open => open.Host is Floor).ToList(); var importInstances = Document.QueryElementsByType().Cast().ToList(); elems.AddRange(groups); //elems.AddRange(basePoints); elems.AddRange(modelCurve); elems.AddRange(levels); elems.AddRange(grids); elems.AddRange(viewers); elems.AddRange(elevs); elems.AddRange(dims); elems.AddRange(annotations); elems.AddRange(texts); elems.AddRange(tags); elems.AddRange(fillRegions); elems.AddRange(openings); elems.AddRange(importInstances); var elemIds = elems.ConvertAll(element => element.Id); if (elems.Count == 0) { return; } StringBuilder sb = new StringBuilder(); Document.Invoke(_ => { foreach (var element in elems) { if (element is Group g && g.GroupId != ElementId.InvalidElementId)//嵌套组 { continue; } if (element.Pinned) { try { element.Pinned = false; } catch (Autodesk.Revit.Exceptions.InvalidOperationException) { } } } Document.Regenerate(); const ObjectSnapTypes snapSettings = ObjectSnapTypes.Endpoints | ObjectSnapTypes.Midpoints | ObjectSnapTypes.Intersections | ObjectSnapTypes.Tangents | ObjectSnapTypes.Quadrants | ObjectSnapTypes.Points | ObjectSnapTypes.Perpendicular | ObjectSnapTypes.Nearest | ObjectSnapTypes.Centers; try { var originWorkPlane = ActiveView.SketchPlane; var sketch = ActiveView.SketchPlane; if (ActiveView is ViewSection section) { section.SketchPlane = SketchPlane.Create( Document, Plane.CreateByNormalAndOrigin(ActiveView.ViewDirection, XYZ.Zero) ); Document.Regenerate(); } var origin = UiDocument.Selection.PickPoint(snapSettings, "请点选模型移动的起点(起点)"); var target = UiDocument.Selection.PickPoint(snapSettings, "请点选模型移动的目标点(终点)"); //Thread.Sleep(1_000); var coordinationResult = MessageBox.Show( $"起点坐标:{origin * 304.8}mm\n终点坐标:{target * 304.8}mm", "确认坐标是否无误并进行移动?", MessageBoxButton.YesNo, MessageBoxImage.Question ); //if (Math.Abs(target.Z - origin.Z) > 10e-6) //{ // var stairs = elems.Where(e => e is Stairs stairs && IsSketchedStairsRun(stairs)).ToList(); // if (stairs.Count > 0) // { // MessageBox.Show("草图绘制的楼梯无法上下移动,请先剪切到剪切板,避免移动后被删除", "警告"); // UiDocument.Selection.SetElementIds(stairs.ConvertAll(e => e.Id)); // return; // } //} if (coordinationResult == MessageBoxResult.Yes) { var translateXyz = target - origin; try { ElementTransformUtils.MoveElements(Document, elemIds, translateXyz); } catch (Exception) { MessageBox.Show("模型移动失败,请检查是否有无法移动的图元", "错误"); } //foreach (var item in elemIds) //{ // try // { // ElementTransformUtils.MoveElement(Document, item, translateXyz); // } // catch (Exception) // { // sb.AppendLine($"元素ID:{item},{Document.GetElement(item).Name},图元移动失败,"); // } //} } } catch (Autodesk.Revit.Exceptions.OperationCanceledException) { } }, "移动模型"); if (elementsBaseFace.Any()) { foreach (var elem in elementsBaseFace) { sb.AppendLine($"{elem.Id},{elem.Name},基于面主体的图元,不进行移动,但可能会因为主体移动而错位,请检查,"); } } if (sb.Length > 0) { File.WriteAllText(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\移动模型失败.csv", sb.ToString(), Encoding.UTF8); MessageBox.Show( $"部分图元无法移动,请查阅桌面 移动模型失败 文件:\n{sb}", "提醒", MessageBoxButton.OK, MessageBoxImage.Information ); } } } }