using System.IO; using System.Text; using System.Windows; using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Nice3point.Revit.Toolkit.External; namespace ShrlAlgo.RvKits.RvCivil; /// /// 按标高拆分成多个模型 /// [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class ModelSplitterCmd : ExternalCommand { public override void Execute() { var result = MessageBox.Show("执行前请手动备份文件避免出现意外情况!", "模型拆分", MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.No) { return; } #region FilterExecute var levels = Document .OfClass() .Cast() .OrderBy(l => l.Elevation) .ToList(); Dictionary levelOutlines = []; //获取标高范围 for (var i = 0; i < levels.Count; i++) { var baseLevel = levels[i]; XYZ min = new(double.MinValue, double.MinValue, baseLevel.Elevation); XYZ max; Outline outline; if (i < levels.Count - 1) { var topLevel = levels[i + 1]; max = new XYZ(double.MaxValue, double.MaxValue, topLevel.Elevation); outline = new Outline(min, max); } else { max = new XYZ(double.MaxValue, double.MaxValue, double.MaxValue); outline = new Outline(min, max); } levelOutlines.Add(baseLevel, outline); } StringBuilder sb = new(); //对比标高,得到实际分层位置 foreach (var keyPair in levelOutlines) { //得到在标高范围内的元素 BoundingBoxIsInsideFilter insideFilter = new(keyPair.Value); LogicalOrFilter logicalOr = new(new ElementClassFilter(typeof(HostObject)), new ElementClassFilter(typeof(FamilyInstance))); var insideCollector = Document.OfModelCollector()?.WherePasses(insideFilter).WherePasses(logicalOr).ToList(); if (insideCollector == null) { return; } var level = keyPair.Key; var elemIds = insideCollector.Where(elem => elem.get_BoundingBox(null) != null) .Select(elem => elem.Id) .ToList(); foreach (var elementId in elemIds) { sb.AppendLine(elementId.ToString()); } if (elemIds.Count == 0) { continue; } var folder = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + $"\\{Document.Title}"; var fileName = $"{level.Name}.rvt"; var filePath = $"{folder}\\{fileName}"; var targetDocument = Application.NewProjectDocument(UnitSystem.Metric); using (Transaction trans = new(targetDocument, "创建标高")) { trans.Start(); try { var targetLevel = Level.Create(targetDocument, level.Elevation); ElementTransformUtils.CopyElements(Document, elemIds, targetDocument, null, new CopyPasteOptions()); //targetLevel.Name = level.Name; trans.Commit(); } catch (Exception ex) { ErrorMessage = ex.Message + sb; Result = Result.Failed; if (trans.GetStatus() == TransactionStatus.Started) { trans.RollBack(); } targetDocument.Close(false); return; } } try { if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } targetDocument.SaveAs($"{folder}\\{fileName}"); targetDocument.Close(false); } catch (Exception e) { ErrorMessage = e.Message; Result = Result.Failed; return; } using (Transaction trans = new(Document, "按标高分割文件")) { trans.Start(); try { Document.Delete(elemIds); var mp = ModelPathUtils.ConvertUserVisiblePathToModelPath(filePath); RevitLinkOptions options = new(true); var linkType = RevitLinkType.Create(Document, mp, options); var instance = RevitLinkInstance.Create(Document, linkType.ElementId, ImportPlacement.Origin); trans.Commit(); } catch (Exception ex) { ErrorMessage = ex.Message + sb; Result = Result.Failed; if (trans.GetStatus() == TransactionStatus.Started) { trans.RollBack(); } return; } } } #endregion FilterExecute } }