Files
ShrlAlgoToolkit/ShrlAlgoToolkit.RevitAddins/RvCommon/InstanceCreatorViewModel.cs
ShrlAlgo 4d35cadb56 更新
2025-07-11 09:20:23 +08:00

290 lines
12 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.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<Family>()
.Cast<Family>()
.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<Family>()
.Cast<Family>()
.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<Family> families;
[ObservableProperty]
private List<FamilySymbol> 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<Wall>().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<XYZ, string> 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<ACadSharp.Entities.TextEntity>()
// .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<FamilySymbol>().ToList();
}
partial void OnSelectedFamilySymbolChanged(FamilySymbol value)
{
Image = value.GetPreviewImage(new System.Drawing.Size(128, 128)).ToBitmapSource();
}
}