using System.Windows; using System.Windows.Input; using System.Windows.Media.Imaging; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Structure; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Microsoft.Xaml.Behaviors; using Nice3point.Revit.Toolkit.External.Handlers; // ReSharper disable ConditionIsAlwaysTrueOrFalse namespace ShrlAlgoToolkit.RevitAddins.RvCommon; public partial class InstanceCreatorViewModel : ObservableObject { public InstanceCreatorViewModel(UIDocument uiDocument) { this.uiDocument = uiDocument; document = uiDocument.Document; uiDocument.Application.Application.FamilyLoadedIntoDocument += Application_FamilyLoadedIntoDocument; GetAvailableFamilies(); } private readonly UIDocument uiDocument; ~InstanceCreatorViewModel() { uiDocument.Application.Application.FamilyLoadedIntoDocument -= Application_FamilyLoadedIntoDocument; } private void GetAvailableFamilies() { #if REVIT2018 || REVIT2020 //过滤掉栏杆族 var collector = document .OfClass() .Cast() .Where( f => f.IsEditable && !f.IsInPlace && f.GetFamilySymbolIds().Any() && f.FamilyCategory.Id.IntegerValue is not (-2000127 or -2009013 or -2005301 or -2009060) && f.FamilyPlacementType is FamilyPlacementType.OneLevelBased or FamilyPlacementType.TwoLevelsBased or FamilyPlacementType.WorkPlaneBased or FamilyPlacementType.OneLevelBasedHosted ) .OrderBy(f => f.Name) .ToList(); #elif REVIT2025 //过滤掉栏杆族 var collector = document .OfClass() .Cast() .Where( f => f.IsEditable && !f.IsInPlace && f.GetFamilySymbolIds().Any() && f.FamilyCategory.Id.Value is not (-2000127 or -2009013 or -2005301 or -2009060) && f.FamilyPlacementType is FamilyPlacementType.OneLevelBased or FamilyPlacementType.TwoLevelsBased or FamilyPlacementType.WorkPlaneBased or FamilyPlacementType.OneLevelBasedHosted ) .OrderBy(f => f.Name) .ToList(); #endif Families = collector; } private void Application_FamilyLoadedIntoDocument(object sender, Autodesk.Revit.DB.Events.FamilyLoadedIntoDocumentEventArgs e) { GetAvailableFamilies(); } private readonly ActionEventHandler handler = new(); [ObservableProperty] private BitmapSource image; [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(RevitAddins.RvCommon.InstanceCreatorViewModel.PlaceInstancesCommand))] private bool canPlaceInstance = true; private readonly Document document; [ObservableProperty] private double offset; [ObservableProperty] private Family selectedFamily; [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(RevitAddins.RvCommon.InstanceCreatorViewModel.PlaceInstancesCommand))] private FamilySymbol selectedFamilySymbol; [ObservableProperty] private List families; [ObservableProperty] private List familySymbols; private bool CanPlace() { return SelectedFamilySymbol != null && CanPlaceInstance; } [RelayCommand(CanExecute = nameof(CanPlace))] private void PlaceInstances() { CanPlaceInstance = false; handler.Raise(_ => { var family = SelectedFamily; var symbol = SelectedFamilySymbol; var d = Offset / 304.8; Reference reference; try { reference = uiDocument.Selection.PickObject(ObjectType.PointOnElement, new DwgElementSelection(), "请选择dwg链接的块参照"); } catch (Autodesk.Revit.Exceptions.OperationCanceledException) { CanPlaceInstance = true; return; } //图层ID; //Document.HideDwgLayer(referenceFunc, out ElementId columnGraphicStyleId, out GeometryElement columnGeoElem); var dwg = document.GetElement(reference) as ImportInstance; var geoInstances = dwg.GetBlocksByRef(reference); var dwgTransform = dwg!.GetTotalTransform(); if (geoInstances == null || !geoInstances.Any()) { MessageBox.Show("选中块为子块或选中块的嵌套层级过深,请使用Tab来选择整体快", "识别失败", MessageBoxButton.OK, MessageBoxImage.Error); CanPlaceInstance = true; return; } document.Invoke( _ => { if (!symbol.IsActive) { symbol.Activate(); } switch (family.FamilyPlacementType) { case FamilyPlacementType.OneLevelBased: foreach (var ins in geoInstances) { var level = document.ActiveView.GenLevel; var loc = ins.GetLocationPoint(dwgTransform, out var rotation); var familyInstance = document.Create.NewFamilyInstance(loc, symbol, level, StructuralType.NonStructural); document.Regenerate(); ElementTransformUtils.RotateElement(document, familyInstance.Id, Line.CreateUnbound(loc, XYZ.BasisZ), rotation); document.Regenerate(); var translation = XYZ.BasisZ * d; ElementTransformUtils.MoveElement(document, familyInstance.Id, translation); } break; case FamilyPlacementType.OneLevelBasedHosted: #if REVIT2018 || REVIT2020 if (family.FamilyCategory.Id.IntegerValue is -2000023 or -2000014) #elif REVIT2025 if (family.FamilyCategory.Id.Value is -2000023 or -2000014) #endif { var level = document.ActiveView.GenLevel; foreach (var ins in geoInstances) { var loc = ins.GetLocationPoint(dwgTransform, out var rotation); var minPoint = loc - new XYZ(0.4, 0.4, -level.Elevation); var maxPoint = loc + new XYZ(0.4, 0.4, level.Elevation + 1); var outline = new Outline(minPoint, maxPoint); var intersectsFilter = new BoundingBoxIntersectsFilter(outline); var intersect = document.OfClass().WherePasses(intersectsFilter).FirstElement() as Wall; var point = loc + (XYZ.BasisZ * level.Elevation); document.Create.NewFamilyInstance(point, symbol, intersect, level, StructuralType.NonStructural); } } break; case FamilyPlacementType.TwoLevelsBased: foreach (var ins in geoInstances) { var level = document.ActiveView.GenLevel; var loc = ins.GetLocationPoint(dwgTransform, out var rotation); var familyInstance = document.Create.NewFamilyInstance(loc, symbol, level, StructuralType.NonStructural); document.Regenerate(); ElementTransformUtils.RotateElement(document, familyInstance.Id, Line.CreateUnbound(loc, XYZ.BasisZ), rotation); document.Regenerate(); var translation = XYZ.BasisZ * d; ElementTransformUtils.MoveElement(document, familyInstance.Id, translation); } break; case FamilyPlacementType.WorkPlaneBased: foreach (var ins in geoInstances) { var loc = ins.GetLocationPoint(dwgTransform, out var rotation); var familyInstance = document.Create.NewFamilyInstance( loc, symbol, document.ActiveView.SketchPlane, StructuralType.NonStructural ); document.Regenerate(); ElementTransformUtils.RotateElement(document, familyInstance.Id, Line.CreateUnbound(loc, XYZ.BasisZ), rotation); document.Regenerate(); var translation = XYZ.BasisZ * d; ElementTransformUtils.MoveElement(document, familyInstance.Id, translation); } break; } CanPlaceInstance = true; }, "实例布置" ); }); } //private static Dictionary WriteCode(UIApplication uiapp) //{ // var application = uiapp.Application; // var uiDocument = uiapp.ActiveUIDocument; // var doc = uiDocument.Document; // Reference textRefer; // try // { // //图层ID; // textRefer = uiDocument.Selection.PickObject( // ObjectType.PointOnElement, // new FuncFilter(e => e is ImportInstance import && import.IsLinked && doc.GetElement(e.GetTypeId()) is CADLinkType), // "请选择“链接(非导入)”的Cad文字图层" // ); // } // catch (Autodesk.Revit.Exceptions.OperationCanceledException) // { // return null; // } // var dwg = doc.GetElement(textRefer) as ImportInstance; // var textLayerName = dwg.GetLayerName(textRefer); // var path = dwg.GetFilePath(); // var dwgTransform = dwg.GetTotalTransform(); // using ACadSharp.IO.DwgReader reader = new(path); // var cadDocument = reader.Read(); // return cadDocument.Entities // .OfType() // .Where(e => e.Layer.Name == textLayerName) // .ToDictionary( // v => // { // var loc = dwgTransform.OfPoint(new XYZ(v.InsertPoint.X, v.InsertPoint.Y, v.InsertPoint.Z)); // return new XYZ(loc.X, loc.Y, 0); // }, // e => e.Value // ); //} partial void OnSelectedFamilyChanged(Family value) { var doc = value.Document; FamilySymbols = value.GetFamilySymbolIds().Select(id => doc.GetElement(id)).OfType().ToList(); } partial void OnSelectedFamilySymbolChanged(FamilySymbol value) { Image = value.GetPreviewImage(new System.Drawing.Size(128, 128)).ToBitmapSource(); } }