添加项目文件。

This commit is contained in:
ShrlAlgo
2025-09-16 16:06:41 +08:00
parent 0e7807b826
commit 98c65ceb3d
922 changed files with 1009489 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
using System.Collections;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
namespace Szmedi.RvKits.DrawingTools;
public partial class CopyAnnotationViewModel : ObservableObject
{
public CopyAnnotationViewModel(UIApplication uiapp)
{
var doc = uiapp.ActiveUIDocument.Document;
View3Ds = new FilteredElementCollector(doc).OfClass(typeof(View3D)).Cast<View3D>().Where(v => !v.IsTemplate);
}
[ObservableProperty]
private IList<View3D> view3DsSelected;
[ObservableProperty] private IEnumerable view3Ds;
[RelayCommand]
private void Confirm(object obj)
{
if (obj is Window window)
{
if (View3DsSelected is { Count: > 0 })
{
window.DialogResult = true;
}
}
}
[RelayCommand]
private void SelectionChanged(object obj)
{
var type = obj.GetType();
View3DsSelected = ((ObservableCollection<object>)obj).Cast<View3D>().ToList();
}
}

View File

@@ -0,0 +1,37 @@
<controls:MaterialWindow
x:Class="Szmedi.RvKits.DrawingTools.CopyAnnotationWin"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:controls="clr-namespace:Szmedi.RvKits.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Szmedi.RvKits.DrawingTools"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="复制标注"
Width="300"
Height="300"
d:DataContext="{d:DesignInstance Type=local:CopyAnnotationViewModel}"
mc:Ignorable="d">
<controls:MaterialWindow.Resources>
<ResourceDictionary Source="pack://application:,,,/Szmedi.RvKits;component/WPFUI.xaml" />
</controls:MaterialWindow.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListBox DisplayMemberPath="Name" ItemsSource="{Binding View3Ds}" SelectionMode="Multiple">
<b:Interaction.Triggers>
<b:EventTrigger EventName="SelectionChanged">
<b:InvokeCommandAction Command="{Binding SelectionChangedCommand}" CommandParameter="{Binding SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBox}}" />
</b:EventTrigger>
</b:Interaction.Triggers>
</ListBox>
<Button
Grid.Row="1"
Command="{Binding ConfirmCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
Content="完成" />
</Grid>
</controls:MaterialWindow>

View File

@@ -0,0 +1,14 @@
namespace Szmedi.RvKits.DrawingTools
{
/// <summary>
/// CopyAnnotationWin.xaml 的交互逻辑
/// </summary>
public partial class CopyAnnotationWin
{
public CopyAnnotationWin(CopyAnnotationViewModel viewModel)
{
DataContext = viewModel;
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,422 @@
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Nice3point.Revit.Toolkit.External;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Interop;
using Szmedi.RvKits.ModelManager;
namespace Szmedi.RvKits.DrawingTools;
[Transaction(TransactionMode.Manual)]
public class Dimension2DTo3DCmd : ExternalCommand
{
public override void Execute()
{
View viewPlan = Document.ActiveView;
CopyAnnotationViewModel viewModel = new(UiApplication);
CopyAnnotationWin win = null;
//AssemblyLoaderHelpers loader = new(GlobalVariables.DirAssembly);
//loader.HookAssemblyResolve();
List<MessageModel> models = new();
try
{
win = new CopyAnnotationWin(viewModel);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
LogAssists.WriteLog(e.StackTrace);
}
//finally
//{
// loader.UnhookAssemblyResolve();
//}
List<Dimension> dimensions = new FilteredElementCollector(Document, viewPlan.Id)
.OfClass(typeof(Dimension))
.WhereElementIsNotElementType()
.Cast<Dimension>()
.ToList();
if (win != null && win.ShowDialog() == true)
{
if (win.DialogResult == true)
{
using TransactionGroup group = new(Document, "复制平面标注");
group.Start();
foreach (View3D view3D in viewModel.View3DsSelected)
{
SketchPlane originSketch = view3D.SketchPlane;
using (Transaction ts = new(Document, "复制尺寸标注"))
{
foreach (Dimension dimension in dimensions)
{
try
{
ts.Start();
List<Reference> references = new();
Curve curve = dimension.Curve;
curve.MakeBound(0, 100);
Plane plane = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, curve.GetEndPoint(0));
view3D.SketchPlane = SketchPlane.Create(Document, plane);
switch (dimension.DimensionShape)
{
case DimensionShape.Linear:
bool isContainMepCurve = false;
Curve locCurve = null;
ReferenceArray array = new();
foreach (Reference reference in dimension.References)
{
//重新定义参照平面为管线的平面
if (Document.GetElement(reference) is MEPCurve mepCurve)
{
LocationCurve loc = mepCurve.Location as LocationCurve;
locCurve = loc.Curve;
plane = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, locCurve.GetEndPoint(0));
view3D.SketchPlane = SketchPlane.Create(Document, plane);
isContainMepCurve = true;
if (reference.ConvertToStableRepresentation(Document).EndsWith(":0:LINEAR"))
{
array.Append(new Reference(mepCurve));
continue;
}
}
array.Append(reference);
}
if (isContainMepCurve)
{
double dis = locCurve.GetEndPoint(0).Z - curve.GetEndPoint(0).Z;
Curve finalCurve = dimension.Curve.CreateTransformed(
Transform.CreateTranslation(dis * XYZ.BasisZ)
);
Document.Create.NewDimension(view3D, finalCurve as Line, array, dimension.DimensionType);
}
else
{
Document.Create.NewDimension(
view3D,
dimension.Curve as Line,
dimension.References,
dimension.DimensionType
);
//dim.Curve.CreateTransformed(Transform.CreateTranslation(10 * XYZ.BasisZ));
}
//var elem = doc.GetElement(dimension.References.get_Item(0));
break;
case DimensionShape.Angular:
foreach (Reference reference in dimension.References)
{
references.Add(reference);
}
AngularDimension.Create(
Document,
view3D,
dimension.Curve as Arc,
references,
dimension.DimensionType
);
break;
case DimensionShape.Radial:
break;
case DimensionShape.ArcLength:
break;
case DimensionShape.Spot:
int code = dimension.Category.GetHashCode();
Reference refer = dimension.References.get_Item(0);
if (code == -2000263) //高程点
{
SpotDimension spot = Document.Create.NewSpotElevation(
view3D,
refer,
dimension.Origin,
dimension.Origin,
dimension.Origin,
dimension.Origin,
true
);
continue;
}
if (code == -2000264) //坐标点
{
SpotDimension spot = Document.Create.NewSpotCoordinate(
view3D,
refer,
dimension.Origin,
dimension.Origin,
dimension.Origin,
dimension.Origin,
true
);
continue;
}
break;
case DimensionShape.Diameter:
break;
case DimensionShape.Unknown:
break;
}
ts.Commit();
}
catch (Exception)
{
models.Add(new MessageModel(dimension, "无法复制"));
if (ts.GetStatus() == TransactionStatus.Started)
{
ts.Commit();
}
//TaskDialog.Show("错误", e.Message);
}
}
//if (dimension.DimensionShape == DimensionShape.Radial)
//{
// continue;
//}
//if (dimension.DimensionShape == DimensionShape.Diameter)
//{
// continue;
//}
}
using (Transaction ts = new(Document, "重置工作平面"))
{
ts.Start();
view3D.SketchPlane = originSketch;
ts.Commit();
}
using Transaction trans = new(Document, "复制标记");
trans.Start();
bool canCopyTag = false;
if (view3D.CanBeLocked() && view3D.CanSaveOrientation())
{
view3D.SaveOrientationAndLock();
canCopyTag = true;
}
else
{
MessageBoxResult result = MessageBox.Show(
"视图名存在意外的字符,族的标记将不会复制,是否继续?",
"错误",
MessageBoxButton.OKCancel,
MessageBoxImage.Warning
);
if (result == MessageBoxResult.Cancel)
{
Result = Result.Cancelled;
return;
}
}
IEnumerable<TextNote> textList = new FilteredElementCollector(Document, viewPlan.Id)
.OfClass(typeof(TextNote))
.ToElements()
.Cast<TextNote>();
IEnumerable<IndependentTag> tags = new FilteredElementCollector(Document, viewPlan.Id)
.OfClass(typeof(IndependentTag))
.ToElements()
.Cast<IndependentTag>();
foreach (TextNote text in textList)
{
XYZ position = text.Coord + (viewPlan.GenLevel.Elevation * XYZ.BasisZ);
TextNoteOptions options =
new()
{
KeepRotatedTextReadable = false,
HorizontalAlignment = text.HorizontalAlignment,
Rotation = 0,
TypeId = text.TextNoteType.Id
};
TextNote note = TextNote.Create(Document, view3D.Id, position, text.Width, text.Text, options);
note.SetFormattedText(text.GetFormattedText());
note.LeaderLeftAttachment = text.LeaderLeftAttachment;
note.LeaderRightAttachment = text.LeaderRightAttachment;
}
//try
//{
if (canCopyTag)
{
foreach (IndependentTag tag in tags)
{
IndependentTag tagCopy;
double maxZ = Document.GetElement(tag.GetTaggedReference()).get_BoundingBox(view3D).Max.Z;
XYZ position = new(tag.TagHeadPosition.X, tag.TagHeadPosition.Y, maxZ);
if (tag.IsOrphaned)
{
continue;
}
tagCopy = tag.IsMaterialTag
? IndependentTag.Create(
Document,
view3D.Id,
tag.GetTaggedReference(),
tag.HasLeader,
TagMode.TM_ADDBY_MATERIAL,
tag.TagOrientation,
position
)
: tag.IsMulticategoryTag
? IndependentTag.Create(
Document,
view3D.Id,
tag.GetTaggedReference(),
tag.HasLeader,
TagMode.TM_ADDBY_MULTICATEGORY,
tag.TagOrientation,
position
)
: IndependentTag.Create(
Document,
view3D.Id,
tag.GetTaggedReference(),
tag.HasLeader,
TagMode.TM_ADDBY_CATEGORY,
tag.TagOrientation,
position
);
tagCopy.ChangeTypeId(tag.GetTypeId());
Document.Regenerate();
if (tagCopy.IsValidObject)
{
tagCopy.HasLeader = tag.HasLeader;
if (tagCopy.HasLeader)
{
switch (tag.LeaderEndCondition)
{
case LeaderEndCondition.Attached:
tagCopy.TagHeadPosition = position;
break;
case LeaderEndCondition.Free:
tagCopy.TagHeadPosition = position;
try
{
tagCopy.LeaderEnd = new XYZ(tag.LeaderEnd.X, tag.LeaderEnd.Y, maxZ);
}
catch (Exception e)
{
LogAssists.WriteLog(e.Message);
models.Add(new MessageModel(tag, "无法修改引线端点值,需重建"));
//stringBuilder.AppendLine($"{tag.Id.IntegerValue}");
}
break;
}
}
if (tagCopy.CanLeaderEndConditionBeAssigned(tag.LeaderEndCondition))
{
tagCopy.LeaderEndCondition = tag.LeaderEndCondition;
}
if (tag.HasLeader && tag.HasElbow)
{
tagCopy.LeaderElbow = new XYZ(tag.LeaderElbow.X, tag.LeaderElbow.Y, maxZ);
}
}
else
{
models.Add(new MessageModel(tag, "无法复制"));
//stringBuilder.AppendLine($"标注类型:{tag.Name}标注Id{tag.Id.IntegerValue}");
}
}
}
trans.Commit();
//}
//catch (Exception ex)
//{
// message = ex.InnerException.ToString();
// if (trans.GetStatus() == TransactionStatus.Started)
// {
// trans.RollBack();
// }
// return Result.Failed;
//}
}
if (group.GetStatus() == TransactionStatus.Started)
{
group.Assimilate();
}
//if (sb.ToString().Length > 0)
//{
// var result = TaskDialog.Show("标注复制问题", "需要手动解决的标注:\n\n" + sb + "\n是否保存到桌面并打开", TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No);
// if (result == TaskDialogResult.Yes)
// {
// var filePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) +
// $"\\标注问题 {DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss-ffff")}.txt";
// File.WriteAllText(filePath
// , sb.ToString());
// System.Diagnostics.Process.Start(filePath);
// }
//}
if (models.Count > 0)
{
MessageWin messageWin = new() { DataContext = new MessageViewModel(UiDocument, models) };
new WindowInteropHelper(messageWin) { Owner = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle };
messageWin.Show();
//var result = TaskDialog.Show("标记复制问题", "需要手动解决的标注:\n\n" + stringBuilder + "\n是否保存到桌面并打开", TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No);
//if (result == TaskDialogResult.Yes)
//{
// var filePath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) +
// $"\\标注问题 {DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss-ffff")}.txt";
// File.WriteAllText(filePath
// , stringBuilder.ToString());
// System.Diagnostics.Process.Start(filePath);
//}
}
}
}
}
private void AdjustTextDirection(Document Document)
{
IEnumerable<TextNote> textList = new FilteredElementCollector(Document, Document.ActiveView.Id)
.OfClass(typeof(TextNote))
.ToElements()
.Cast<TextNote>();
using Transaction trans = new(Document, "调整文字朝向");
foreach (TextNote text in textList)
{
try
{
trans.Start();
text.KeepRotatedTextReadable = false;
Document.Regenerate();
text.KeepRotatedTextReadable = true;
trans.Commit();
}
catch (Exception)
{
if (trans.GetStatus() == TransactionStatus.Started)
{
trans.RollBack();
}
}
}
}
}

View File

@@ -0,0 +1,90 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using Nice3point.Revit.Toolkit.External;
using System;
namespace Szmedi.RvKits.DrawingTools
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
public class DimensionBy2LineCmd : ExternalCommand
{
public override void Execute()
{
#region RepeatExecute
using Transaction trans = new(Document, "标注");
try
{
while (true)
{
ElementReferenceType referenceType1 = ElementReferenceType.REFERENCE_TYPE_LINEAR;
Reference refer = UiDocument.Selection.PickObject(
ObjectType.Edge,
new ReferenceSelectionFilter(referenceType1),
"请选择第一条边"
);
Reference refer1 = UiDocument.Selection.PickObject(
ObjectType.Edge,
new ReferenceSelectionFilter(referenceType1),
"请选择第二条边"
);
Element e = UiDocument.Document.GetElement(refer);
Element e1 = UiDocument.Document.GetElement(refer1);
var f = e.GetGeometryObjectFromReference(refer) as Edge;
var f1 = e1.GetGeometryObjectFromReference(refer1) as Edge;
var c1 = f.AsCurve();
var c2 = f1.AsCurve();
var p1 = c1.GetEndPoint(0);
c2.MakeUnbound();
var p2 = c2.Project(p1).XYZPoint;
Line l = Line.CreateBound(p1, p2);
ReferenceArray array = new();
array.Append(refer);
array.Append(refer1);
try
{
trans.Start();
Document.Create.NewDimension(Document.ActiveView, l, array);
trans.Commit();
}
catch (Autodesk.Revit.Exceptions.InvalidOperationException)
{
var plane = Plane.CreateByThreePoints(
f.AsCurve().GetEndPoint(0),
f.AsCurve().GetEndPoint(1),
f1.AsCurve().GetEndPoint(0)
);
var originSketch = Document.ActiveView.SketchPlane;
Document.ActiveView.SketchPlane = SketchPlane.Create(Document, plane);
Document.Create.NewDimension(Document.ActiveView, l, array);
Document.ActiveView.SketchPlane = originSketch;
trans.Commit();
}
}
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
if (trans.GetStatus() == TransactionStatus.Started)
{
trans.Commit();
}
}
catch (Exception)
{
//message = ex.InnerException.ToString();
if (trans.GetStatus() == TransactionStatus.Started)
{
trans.Commit();
}
}
#endregion RepeatExecute
}
}
}

View File

@@ -0,0 +1,308 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using Nice3point.Revit.Toolkit.External;
using System;
using System.Linq;
namespace Szmedi.RvKits.DrawingTools
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
public class DimensionElemCmd : ExternalCommand
{
public override void Execute()
{
using Transaction transaction = new(Document, "标注对象");
try
{
while (true)
{
transaction.Start();
Reference refer = UiDocument.Selection.PickObject(ObjectType.Element, "请选择要标注的对象");
Element e = UiDocument.Document.GetElement(refer);
CreateDimensionsByFaces(Document, e);
transaction.Commit();
}
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
if (transaction.GetStatus() == TransactionStatus.Started)
{
transaction.RollBack();
}
}
catch (Exception ex)
{
ErrorMessage = ex.Message;
if (transaction.GetStatus() == TransactionStatus.Started)
{
transaction.RollBack();
}
}
}
private List<Face> GetElementFaces(Element elem)
{
List<Face> faces = new();
Options option =
new()
{
ComputeReferences = true,
DetailLevel = ViewDetailLevel.Fine,
IncludeNonVisibleObjects = true
};
GeometryElement geometry = elem.get_Geometry(option);
foreach (GeometryObject geomObj in geometry)
{
GeometryInstance geomInstance = geomObj as GeometryInstance;
if (geomInstance != null)
{
bool usesSymbolGeometry = elem is FamilyInstance && !(elem as FamilyInstance).HasModifiedGeometry();
GeometryElement instanceGeometry = usesSymbolGeometry
? geomInstance.GetSymbolGeometry()
: geomInstance.GetInstanceGeometry();
foreach (GeometryObject instObj in instanceGeometry)
{
Solid instSolid = instObj as Solid;
if (instSolid == null || instSolid.Faces.Size == 0 || instSolid.Edges.Size == 0 || instSolid.Volume < 0.0001)
{
continue;
}
foreach (Face face in instSolid.Faces)
{
faces.Add(face);
}
}
}
Solid solid = geomObj as Solid;
if (solid != null)
{
if (solid.Faces.Size == 0 || solid.Edges.Size == 0 || solid.Volume < 0.0001)
{
continue;
}
foreach (Face face in solid.Faces)
{
faces.Add(face);
}
}
}
return faces;
}
private void CreateDimensionsByFace(Document Document, Face face)
{
List<Line> lines = new();
if (face.EdgeLoops.Size > 0)
{
foreach (CurveLoop loop in face.GetEdgesAsCurveLoops())
{
foreach (Curve curve in loop)
{
if (curve is Line)
{
lines.Add(curve as Line);
}
}
}
}
foreach (Line line in lines)
{
ReferenceArray array = new();
array.Append(line.GetEndPointReference(0));
array.Append(line.GetEndPointReference(1));
Document.Create.NewDimension(Document.ActiveView, line, array);
}
//List<Line> l1 = new List<Line>();
//List<List<Line>> l2 = new List<List<Line>>();
//GetParallLineGroups(lines, lines.FirstOrDefault(), l1, l2);
//foreach (List<Line> list in l2)
//{
// if (list.Count <= 1)
// {
// continue;
// }
// ReferenceArray array = new ReferenceArray();
// var p1 = list.FirstOrDefault().Evaluate(0.5, true);
// var result = list.LastOrDefault().Project(p1);
// var p2 = result.XYZPoint;
// Line l = Line.CreateBound(p1, p2);
// foreach (Line line in list)
// {
// array.Append(line.GetEndPointReference(0));
// }
// doc.Create.NewDimension(doc.ActiveView, l, array);
//}
}
private void CreateDimensionsByFaces(Document Document, Element e)
{
List<Face> elementFaces = GetElementFaces(e);
if (e is Wall w)
{
IEnumerable<ElementId> elementIds = w.FindInserts(true, false, false, false)
.Where(id => Document.GetElement(id) is Opening);
foreach (var id in elementIds)
{
var opening = Document.GetElement(id);
elementFaces.AddRange(GetElementFaces(opening));
}
}
Location loc = e.Location;
var bounding = e.get_BoundingBox(Document.ActiveView);
//if (loc == null)
//{
// MessageBox.Show("元素无法被标注");
// return;
//}
//if (loc is LocationCurve)
//{
// p = (loc as LocationCurve).Curve.GetEndPoint(0);
//}
//else if (loc is LocationPoint)
//{
// p = (loc as LocationPoint).Point;
//}
List<List<Face>> groups = new();
GetParallFaces(elementFaces, groups);
foreach (List<Face> faces in groups)
{
XYZ p = bounding.Min;
if (faces.Count <= 1)
{
continue;
}
var face = faces[0];
var face1 = faces[faces.Count - 1];
ReferenceArray array = new();
foreach (var f in faces)
{
if (f.Reference == null)
{
//var elementIds = e.GetGeneratingElementIds(f);
//var openingId = elementIds.FirstOrDefault();
//var opening = doc.GetElement(openingId) as Opening;
//var fa = opening.GetGeometryObjectFromReference(f.Reference);
//if (fa != f)
//{
// array.Append(fa.Reference);
//}
continue;
}
array.Append(f.Reference);
}
try
{
Line line = null;
if (face is not null and PlanarFace)
{
var pf = face as PlanarFace;
var direction = pf.FaceNormal;
if (direction.CrossProduct(XYZ.BasisZ).IsAlmostEqualTo(XYZ.Zero))
{
p += direction * 2;
}
else
{
p += direction.CrossProduct(XYZ.BasisZ) * 2;
}
line = Line.CreateUnbound(p, direction);
}
Document.Create.NewDimension(Document.ActiveView, line, array);
}
catch (Exception) { }
}
}
private void GetParallFaces(List<Face> faces, List<List<Face>> groups)
{
var firstface = faces.FirstOrDefault();
faces = faces.FindAll(face => face is PlanarFace);
List<Face> group = new() { firstface };
groups.Add(group);
PlanarFace pf = firstface as PlanarFace;
faces.Remove(firstface);
for (var i = faces.Count - 1; i >= 0; i--)
{
if (faces[i] is not PlanarFace)
{
continue;
}
var tempFace = faces[i] as PlanarFace;
if (tempFace.FaceNormal.CrossProduct(pf.FaceNormal).IsAlmostEqualTo(XYZ.Zero))
{
group.Add(tempFace);
faces.Remove(tempFace);
//GetParallFaces(faces, tempFace, ZoomRBGroup, groups);
}
}
if (faces.Count >= 1)
{
GetParallFaces(faces, groups);
}
}
private void GetParallLineGroups(List<Curve> lines, List<List<Curve>> groups)
{
var firstLine = lines.FirstOrDefault();
lines = lines.FindAll(curve => curve is Line);
List<Curve> group = new() { firstLine };
groups.Add(group);
Line pf = firstLine as Line;
lines.Remove(firstLine);
for (var i = 0; i < lines.Count; i++)
{
if (lines[i] is not Line)
{
continue;
}
var tempLine = lines[i] as Line;
if (tempLine.Direction.CrossProduct(pf.Direction).IsAlmostEqualTo(XYZ.Zero))
{
group.Add(tempLine);
lines.Remove(tempLine);
//GetParallFaces(faces, tempFace, ZoomRBGroup, groups);
}
}
if (lines.Count >= 1)
{
GetParallLineGroups(lines, groups);
}
}
}
}

View File

@@ -0,0 +1,88 @@
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Nice3point.Revit.Toolkit.External;
using System;
namespace Szmedi.RvKits.DrawingTools
{
[Transaction(TransactionMode.Manual)]
public class DimensionPointLineCmd : ExternalCommand
{
public override void Execute()
{
using Transaction trans = new(Document, "点线标注");
try
{
while (true)
{
ElementReferenceType referenceType1 = ElementReferenceType.REFERENCE_TYPE_LINEAR;
ElementReferenceType referenceType2 = ElementReferenceType.REFERENCE_TYPE_NONE;
Reference refer = UiDocument.Selection.PickObject(
ObjectType.Edge,
new ReferenceSelectionFilter(referenceType1),
"请选择边"
);
Reference refer1 = UiDocument.Selection.PickObject(
ObjectType.PointOnElement,
new ReferenceSelectionFilter(referenceType2),
"请选择点"
);
Element e = UiDocument.Document.GetElement(refer);
var f = e.GetGeometryObjectFromReference(refer) as Edge;
var c1 = f.AsCurve();
var p1 = refer1.GlobalPoint;
c1.MakeUnbound();
var p2 = c1.Project(p1).XYZPoint;
Line l = Line.CreateBound(p1, p2);
ReferenceArray array = new();
array.Append(refer);
array.Append(refer1);
try
{
trans.Start();
Document.Create.NewDimension(Document.ActiveView, l, array);
trans.Commit();
}
catch (Autodesk.Revit.Exceptions.InvalidOperationException)
{
var plane = Plane.CreateByThreePoints(f.AsCurve().GetEndPoint(0), f.AsCurve().GetEndPoint(1), p1);
var originSketch = Document.ActiveView.SketchPlane;
Document.ActiveView.SketchPlane = SketchPlane.Create(Document, plane);
Document.Create.NewDimension(Document.ActiveView, l, array);
Document.ActiveView.SketchPlane = originSketch;
trans.Commit();
}
}
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
if (trans.GetStatus() == TransactionStatus.Started)
{
trans.Commit();
}
}
catch (Exception ex)
{
if (ex.Message == "Invalid number of references.")
{
ErrorMessage = "选择的参考不可用于生成标注";
}
if (trans.GetStatus() == TransactionStatus.Started)
{
trans.Commit();
}
Result = Result.Failed;
}
}
}
}

View File

@@ -0,0 +1,726 @@
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Nice3point.Revit.Toolkit.External;
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Media;
namespace Szmedi.RvKits.DrawingTools
{
[Transaction(TransactionMode.Manual)]
public class DimensionView3dCmd : ExternalCommand
{
public override void Execute()
{
ViewFamilyType viewFamilyType = new FilteredElementCollector(Document)
.OfClass(typeof(ViewFamilyType))
.Cast<ViewFamilyType>()
.FirstOrDefault(t => t.ViewFamily == ViewFamily.ThreeDimensional);
IEnumerable<Grid> grids = new FilteredElementCollector(Document).OfClass(typeof(Grid)).Cast<Grid>();
View3D myView = null;
int n = 100;
if (!grids.Any())
{
Result = Result.Cancelled;
return;
}
Document.Invoke(
_ =>
{
if (viewFamilyType != null)
{
myView = View3D.CreateIsometric(Document, viewFamilyType.Id);
}
for (int i = 0; i < n; i++)
{
try
{
myView.Name = $"三维轴测视图_{i}";
break;
}
catch (Autodesk.Revit.Exceptions.ArgumentException) { }
}
myView.SaveOrientationAndLock();
List<ModelCurve> mcurves = Create3dGrid(myView, grids);
Document.Regenerate();
CreateDimension(Document, myView, mcurves);
},
"三维标注"
);
UiDocument.ActiveView = myView;
}
/// <summary>
/// 获取族实例所有面(实际为族类型的所有面)
/// </summary>
/// <param name="instance"></param>
/// <param name="options"></param>
/// <returns></returns>
public static List<Face> GetFacesByFamilyInstance(FamilyInstance instance, Options options)
{
List<Face> faces = new();
//根据打开的方式得到几何信息
GeometryElement geometry = instance.get_Geometry(options);
foreach (GeometryObject geomObj in geometry)
{
//geomObj为几何实例
GeometryInstance geomInstance = geomObj as GeometryInstance;
if (geomInstance == null)
{
continue;
}
//族实例未修改过(连接,剪切,复制,扩展)
bool usesSymbolGeometry = instance is not null && !instance.HasModifiedGeometry();
bool bo = instance.HasModifiedGeometry();
GeometryElement instanceGeometry = usesSymbolGeometry
? geomInstance.GetSymbolGeometry()
: geomInstance.GetInstanceGeometry();
if (instanceGeometry != null)
{
//instanceGeometry.GetTransformed();
//从实例中找到实例的几何体
foreach (GeometryObject instObj in instanceGeometry)
{
//三维的实体
Solid instSolid = instObj as Solid;
if (instSolid == null || instSolid.Faces.Size == 0 || instSolid.Edges.Size == 0)
{
continue;
}
foreach (Face face in instSolid.Faces)
{
faces.Add(face);
}
}
}
//geomObj为几何体
Solid solid = geomObj as Solid;
if (solid != null)
{
if (solid.Faces.Size == 0 || solid.Edges.Size == 0)
{
continue;
}
foreach (Face face in solid.Faces)
{
faces.Add(face);
}
}
}
return faces;
}
/// <summary>
/// 获取元素侧面
/// </summary>
/// <param name="elem"></param>
/// <returns></returns>
public static List<Face> GetSideFacesByElement(Element elem)
{
Options opt = new() { ComputeReferences = true, DetailLevel = ViewDetailLevel.Fine };
GeometryElement ge = elem.get_Geometry(opt);
List<Face> lstpf = new();
foreach (GeometryObject obj in ge)
{
Solid solid = obj as Solid;
if (solid != null)
{
foreach (Face face in solid.Faces)
{
PlanarFace pf = face as PlanarFace;
if (pf != null)
{
//点乘即面的法向与Z轴始终垂直
double dotp = pf.FaceNormal.DotProduct(XYZ.BasisZ);
if (dotp is < 1.0e-09 and > (-1.0e-09)) //近似为0
{
lstpf.Add(pf);
}
//if (pf.FaceNormal.CrossProduct(wall.Orientation).IsZeroLength())
//{
// lstpf.Add(pf);
//}
}
CylindricalFace cy = face as CylindricalFace;
if (cy != null)
{
lstpf.Add(cy);
}
}
return lstpf;
}
}
return lstpf;
}
private List<ModelCurve> Create3dGrid(View view, IEnumerable<Grid> grids)
{
Document Document = view.Document;
List<TextNoteType> textnotetypes = new FilteredElementCollector(Document)
.OfClass(typeof(TextNoteType))
.Cast<TextNoteType>()
.ToList();
TextNoteType textnotetype = textnotetypes.FirstOrDefault();
List<ModelCurve> curves = new();
IEnumerable<bool> gridGroups = grids
.GroupBy(g => g.Curve.ComputeDerivatives(0, true).BasisX.Normalize().X)
.Select(s => s.Count() > 1);
Plane plane = Plane.CreateByOriginAndBasis(XYZ.Zero, XYZ.BasisX, XYZ.BasisY);
SketchPlane sketch = SketchPlane.Create(Document, plane);
foreach (Grid grid in grids)
{
Curve curve = grid.Curve;
XYZ startp = curve.GetEndPoint(0);
XYZ endp = curve.GetEndPoint(1);
int radius = 2;
XYZ direction = curve.ComputeDerivatives(0, true).BasisX.Normalize().Negate();
XYZ direction1 = curve.ComputeDerivatives(1, true).BasisX.Normalize();
SketchPlane gridSketch = SketchPlane.Create(Document, new Reference(grid));
XYZ loc = startp + (direction * radius);
XYZ loc1 = endp + (direction1 * radius);
Arc circle = Arc.Create(loc, radius, 0, Math.PI * 2, XYZ.BasisX, XYZ.BasisY);
Arc circle1 = Arc.Create(loc1, radius, 0, Math.PI * 2, XYZ.BasisX, XYZ.BasisY);
TextNoteOptions options =
new(textnotetype.Id)
{
HorizontalAlignment = HorizontalTextAlignment.Center,
#if REVIT2019 || REVIT2020
VerticalAlignment = VerticalTextAlignment.Middle
#endif
};
//Text.FromStringOriginAndScale(grid.Name, loc, size);
//Text.FromStringOriginAndScale(grid.Name, loc1, size);
TextNote.Create(Document, view.Id, loc, grid.Name, options);
TextNote.Create(Document, view.Id, loc1, grid.Name, options);
ModelCurve gridLine = Document.Create.NewModelCurve(grid.Curve, gridSketch);
Document.Create.NewModelCurve(circle, sketch);
Document.Create.NewModelCurve(circle1, sketch);
curves.Add(gridLine);
}
return curves;
}
internal static MethodInfo GenerateTransientDisplayMethod()
{
Type geometryElementType = typeof(GeometryElement);
MethodInfo[] geometryElementTypeMethods = geometryElementType.GetMethods(
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic
);
MethodInfo method = geometryElementTypeMethods.FirstOrDefault(x => x.Name == "SetForTransientDisplay");
return method;
}
private ReferenceArray RemoveZeroSegements(Wall wall, ReferenceArray wallLengthRefernceArray, Dimension lengthdim)
{
List<Reference> referencesdelete = new();
ReferenceArray finallengthreferenceArray = new();
for (int i = 0; i < lengthdim.NumberOfSegments; i++)
{
if (lengthdim.Segments.get_Item(i).ValueString == "0")
{
if (lengthdim.References.get_Item(i).ElementId == wall.Id)
{
referencesdelete.Add(lengthdim.References.get_Item(i));
}
if (lengthdim.References.get_Item(i + 1).ElementId == wall.Id)
{
referencesdelete.Add(lengthdim.References.get_Item(i + 1));
}
}
}
for (int i = 0; i < wallLengthRefernceArray.Size; i++)
{
bool isContain = false;
Reference reference = wallLengthRefernceArray.get_Item(i);
foreach (Reference referdelete in referencesdelete)
{
if (reference.EqualTo(referdelete))
{
isContain = true;
}
}
if (!isContain)
{
finallengthreferenceArray.Append(reference);
}
}
return finallengthreferenceArray;
}
public void CreateBeamsDimension(Document Document)
{
FilteredElementCollector col = new(Document, Document.ActiveView.Id);
ElementCategoryFilter categoryFilter1 = new(BuiltInCategory.OST_StructuralFraming);
col.WherePasses(categoryFilter1);
IEnumerable<Element> beams = col.GroupBy(g => g.Name).Select(s => s.FirstOrDefault());
foreach (FamilyInstance familyInstance in beams)
{
XYZ loc = (familyInstance.Location as LocationPoint).Point;
List<Face> faces = GetSideFacesByElement(familyInstance);
if (faces.Count == 0) //找不到实例的几何元素时,需从类型集合查找
{
Options options = new() { ComputeReferences = true };
faces = GetFacesByFamilyInstance(familyInstance, options);
for (int i = faces.Count - 1; i >= 0; i--)
{
PlanarFace pf = faces[i] as PlanarFace;
if (pf.FaceNormal.CrossProduct(XYZ.BasisZ).IsAlmostEqualTo(XYZ.Zero))
{
faces.Remove(faces[i]); //移除顶面底面
}
}
}
ReferenceArray referenceArray = new();
ReferenceArrayArray referenceArrayArray = new();
GetParallFacesReferenceArray(faces, faces.FirstOrDefault(), referenceArray, referenceArrayArray);
foreach (ReferenceArray array in referenceArrayArray)
{
PlanarFace face = familyInstance.GetGeometryObjectFromReference(array.get_Item(0)) as PlanarFace;
Line line = Line.CreateUnbound(loc, face.FaceNormal).CreateOffset(600 / 304.8, XYZ.BasisZ) as Line;
Document.Create.NewDimension(Document.ActiveView, line, array);
}
}
}
public void CreateColumnsDimension(Document Document, View view)
{
FilteredElementCollector col = new(Document, view.Id);
ElementCategoryFilter categoryFilter1 = new(BuiltInCategory.OST_StructuralColumns);
ElementCategoryFilter categoryFilter2 = new(BuiltInCategory.OST_Columns);
LogicalOrFilter andFilter = new(categoryFilter1, categoryFilter2);
col.WherePasses(andFilter);
IEnumerable<Element> columns = col.GroupBy(g => g.Name).Select(s => s.FirstOrDefault());
foreach (FamilyInstance familyInstance in columns)
{
XYZ loc = (familyInstance.Location as LocationPoint).Point;
List<Face> faces = GetSideFacesByElement(familyInstance);
if (faces.Count == 0) //找不到实例的几何元素时,需从类型集合查找
{
Options options = new() { ComputeReferences = true };
faces = GetFacesByFamilyInstance(familyInstance, options);
for (int i = faces.Count - 1; i >= 0; i--)
{
if (faces[i] is PlanarFace)
{
PlanarFace pf = faces[i] as PlanarFace;
if (pf.FaceNormal.CrossProduct(XYZ.BasisZ).IsAlmostEqualTo(XYZ.Zero))
{
faces.Remove(faces[i]); //移除顶面底面
}
}
}
}
ReferenceArray referenceArray = new();
ReferenceArrayArray referenceArrayArray = new();
GetParallFacesReferenceArray(faces, faces.FirstOrDefault(), referenceArray, referenceArrayArray);
foreach (ReferenceArray array in referenceArrayArray)
{
if (array.Size == 0)
{
continue;
}
PlanarFace face = familyInstance.GetGeometryObjectFromReference(array.get_Item(0)) as PlanarFace;
Line line = Line.CreateUnbound(loc, face.FaceNormal).CreateOffset(600 / 304.8, XYZ.BasisZ) as Line;
Document.Create.NewDimension(Document.ActiveView, line, array);
}
}
}
private void CreateDimension(Document Document, View view, List<ModelCurve> mcurves)
{
List<Curve> lines = mcurves.Where(c => c is ModelLine).Select(mc => mc.GeometryCurve).ToList();
List<List<Curve>> groups = new();
GetParallLineGroups(lines, groups);
foreach (List<Curve> g in groups)
{
List<Line> gx = g.ConvertAll(x => x as Line);
if (!gx.Any())
{
continue;
}
XYZ direction = gx.FirstOrDefault()?.Direction;
//IOrderedEnumerable<Line> orderedlist = null;
//if (direction.AngleTo(XYZ.BasisX) >= direction.AngleTo(XYZ.BasisY))
//{
// orderedlist = gx.OrderBy(l => l.Direction.X);
//}
//else
//{
// orderedlist = gx.OrderBy(l => l.Direction.Y);
//}
if (g.Count <= 1)
{
continue;
}
Line line =
Line.CreateUnbound(g.FirstOrDefault()?.GetEndPoint(0), direction.CrossProduct(XYZ.BasisZ))
.CreateOffset(1500 / 304.8, XYZ.BasisZ) as Line;
Line line1 =
Line.CreateUnbound(g.FirstOrDefault()?.GetEndPoint(1), direction.CrossProduct(XYZ.BasisZ))
.CreateOffset(1500 / 304.8, XYZ.BasisZ) as Line;
ReferenceArray arrayAll = new();
foreach (Curve l in g)
{
arrayAll.Append(l.Reference);
}
Dimension dimension1 = Document.Create.NewDimension(view, line, arrayAll);
Dimension dimension2 = Document.Create.NewDimension(view, line1, arrayAll);
Document.Regenerate();
Line line3 =
Line.CreateUnbound(g.FirstOrDefault()?.GetEndPoint(0), direction.CrossProduct(XYZ.BasisZ))
.CreateOffset(1000 / 304.8, XYZ.BasisZ) as Line;
Line line4 =
Line.CreateUnbound(g.FirstOrDefault()?.GetEndPoint(1), direction.CrossProduct(XYZ.BasisZ))
.CreateOffset(1000 / 304.8, XYZ.BasisZ) as Line;
ReferenceArray array = new();
array.Append(dimension1.References.get_Item(0));
array.Append(dimension1.References.get_Item(arrayAll.Size - 1));
Document.Create.NewDimension(view, line3, array);
Document.Create.NewDimension(view, line4, array);
Document.Regenerate();
}
}
private void CreateWallDimension(Document Document, View view)
{
FilteredElementCollector wallCol = new FilteredElementCollector(Document, view.Id).OfClass(typeof(Wall));
foreach (Wall wall in wallCol)
{
if (wall.WallType.Kind != WallKind.Basic)
{
continue;
}
LocationCurve loc = wall.Location as LocationCurve;
ReferenceArray wallThickReferenceArray = new();
ReferenceArray wallLengthRefernceArray = new();
List<Face> faces = GetSideFacesByElement(wall);
foreach (Face face in faces)
{
PlanarFace pf = face as PlanarFace;
if (pf == null || face.Reference == null || pf.OrientationMatchesSurfaceOrientation == false)
{
continue;
}
if (pf.FaceNormal.CrossProduct(wall.Orientation).IsAlmostEqualTo(XYZ.Zero))
{
if (Document.GetElement(face.Reference).Id == wall.Id)
{
wallThickReferenceArray.Append(face.Reference);
}
}
else if (pf.FaceNormal.DotProduct(wall.Orientation) < 0.001)
{
wallLengthRefernceArray.Append(face.Reference);
}
}
try
{
int scale = Document.ActiveView.Scale;
Autodesk.Revit.DB.Transform tranform = Autodesk.Revit.DB.Transform.CreateTranslation(
wall.Orientation * scale * 15 / 304.8
);
Line wallcurve = (wall.Location as LocationCurve).Curve as Line;
Line lengthLine = wallcurve.CreateTransformed(tranform) as Line;
Dimension lengthdim = Document.Create.NewDimension(Document.ActiveView, lengthLine, wallLengthRefernceArray);
Document.Regenerate();
ReferenceArray finallengthreferenceArray = RemoveZeroSegements(wall, wallLengthRefernceArray, lengthdim);
Document.Delete(lengthdim.Id);
Document.Create.NewDimension(Document.ActiveView, lengthLine, finallengthreferenceArray);
Line thickLine = Line.CreateUnbound(wallcurve.Evaluate(0.2, true), wall.Orientation);
Dimension thickdim = Document.Create.NewDimension(Document.ActiveView, thickLine, wallThickReferenceArray);
if (lengthdim.Segments.Size > 2)
{
ReferenceArray referenceArray = new();
Reference refer1 = lengthdim.References.get_Item(0);
Reference refer2 = lengthdim.References.get_Item(lengthdim.References.Size - 1);
referenceArray.Append(refer1);
referenceArray.Append(refer2);
Autodesk.Revit.DB.Transform tranform1 = Autodesk.Revit.DB.Transform.CreateTranslation(
wall.Orientation * scale * 25 / 304.8
);
Line lengthLine1 = wallcurve.CreateTransformed(tranform1) as Line;
Document.Create.NewDimension(Document.ActiveView, lengthLine1, referenceArray);
}
}
catch (Exception) { }
}
}
public void GetParallFacesReferenceArray(
List<Face> faces,
Face firstFace,
ReferenceArray referenceArray,
ReferenceArrayArray referenceArrayArray
)
{
if (referenceArrayArray.Size == 0)
{
referenceArrayArray.Append(referenceArray);
}
for (int i = 0; i < faces.Count; i++)
{
if (faces[i] is not PlanarFace)
{
continue;
}
PlanarFace tempFace = faces[i] as PlanarFace;
PlanarFace pf = firstFace as PlanarFace;
XYZ facenormal = pf.FaceNormal;
//把初始的第一个添加进集合
if (tempFace.FaceNormal.CrossProduct(facenormal).IsAlmostEqualTo(XYZ.Zero))
{
referenceArray.Append(tempFace.Reference);
faces.Remove(tempFace);
GetParallFacesReferenceArray(faces, tempFace, referenceArray, referenceArrayArray);
}
if (i == faces.Count() - 1)
{
referenceArray = new ReferenceArray();
GetParallFacesReferenceArray(faces, faces.FirstOrDefault(), referenceArray, referenceArrayArray);
if (!faces.Any())
{
referenceArrayArray.Append(referenceArray);
}
}
}
}
/// <summary>
/// 递归找到所有平行线集合
/// </summary>
public static void GetParallLineGroups(List<Curve> lines, List<List<Curve>> groups)
{
Curve firstLine = lines.FirstOrDefault();
lines = lines.FindAll(curve => curve is Line);
List<Curve> group = new() { firstLine };
groups.Add(group);
Line line = firstLine as Line;
lines.Remove(firstLine);
for (int i = lines.Count - 1; i >= 0; i--)
{
if (lines[i] is not Line)
{
continue;
}
Line tempLine = lines[i] as Line;
if (
tempLine.Direction.CrossProduct(line.Direction).IsAlmostEqualTo(XYZ.Zero)
&& Math.Abs(tempLine.Length - line.Length) < 0.00001
)
{
group.Add(tempLine);
lines.Remove(tempLine);
//GetParallFaces(faces, tempFace, ZoomRBGroup, groups);
}
}
if (lines.Count >= 1)
{
GetParallLineGroups(lines, groups);
}
}
private void TransientGrid(Document Document, Grid grid)
{
double radius = 1.5;
double size = 1.8;
XYZ startp = grid.Curve.GetEndPoint(0);
XYZ endp = grid.Curve.GetEndPoint(1);
XYZ direction = grid.Curve.ComputeDerivatives(0, true).BasisX.Normalize().Negate();
XYZ direction1 = grid.Curve.ComputeDerivatives(1, true).BasisX.Normalize();
XYZ loc = startp + (direction * radius);
XYZ loc1 = endp + (direction1 * radius);
IEnumerable<Curve> text = Text.FromStringOriginAndScale(grid.Name, loc, size);
IEnumerable<Curve> text1 = Text.FromStringOriginAndScale(grid.Name, loc1, size);
Arc circle = Arc.Create(loc, radius, 0, Math.PI * 2, XYZ.BasisX, XYZ.BasisY);
Arc circle1 = Arc.Create(loc1, radius, 0, Math.PI * 2, XYZ.BasisX, XYZ.BasisY);
List<GeometryObject> geoms = new() { grid.Curve, circle, circle1 };
geoms.AddRange(text);
geoms.AddRange(text1);
MethodInfo method = GenerateTransientDisplayMethod();
object[] argsM = new object[4];
argsM[0] = Document;
argsM[1] = ElementId.InvalidElementId;
argsM[2] = geoms;
argsM[3] = ElementId.InvalidElementId;
ElementId transientElementId = (ElementId)method.Invoke(null, argsM);
MessageBox.Show(transientElementId.IntegerValue.ToString(), "元素ID");
//doc.Delete(transientElementId);
}
}
public class TransientElementMaker : ITransientElementMaker
{
private readonly Document _document;
public List<GeometryObject> GeometryObjects { get; set; }
public TransientElementMaker(Document document)
{
_document = document;
}
public void Execute()
{
if (GeometryObjects != null)
{
DirectShape ds = DirectShape.CreateElement(_document, new ElementId(BuiltInCategory.OST_GenericModel));
//CreateUtils.CreateCube(), CreateUtils.CreateSphere()为创建一个立方体与球体Solid,文略
//ds.AppendShape(GeometryObjects);
ds.AppendShape(new List<GeometryObject> { CreateCube() });
}
}
public Solid CreateCube()
{
CurveLoop cubeBaseLines = new();
cubeBaseLines.Append(Line.CreateBound(new XYZ(0, 0, 0), new XYZ(100, 0, 0)));
cubeBaseLines.Append(Line.CreateBound(new XYZ(100, 0, 0), new XYZ(100, 100, 0)));
cubeBaseLines.Append(Line.CreateBound(new XYZ(100, 100, 0), new XYZ(0, 100, 0)));
cubeBaseLines.Append(Line.CreateBound(new XYZ(0, 100, 0), new XYZ(0, 0, 0)));
Solid solidCube = GeometryCreationUtilities.CreateExtrusionGeometry(new List<CurveLoop> { cubeBaseLines }, XYZ.BasisZ, 100);
return solidCube;
}
}
public static class Text
{
public static IEnumerable<Curve> FromStringOriginAndScale(string text, XYZ origin, double scale)
{
//http://msdn.microsoft.com/en-us/library/ms745816(v=vs.110).aspx
List<Curve> crvs = new();
FontFamily font = new("Arial");
FontStyle fontStyle = FontStyles.Normal;
FontWeight fontWeight = FontWeights.Medium;
//if (Bold == true) fontWeight = FontWeights.Bold;
//if (Italic == true) fontStyle = FontStyles.Italic;
// Create the formatted text based on the properties set.
#if REVIT2019||REVIT2020
System.Windows.Media.FormattedText formattedText =
new(
text,
CultureInfo.GetCultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface(font, fontStyle, fontWeight, FontStretches.Normal),
1,
Brushes.Black,
1 // This brush does not matter since we use the geometry of the text.
);
#elif REVIT2018
var formattedText = new System.Windows.Media.FormattedText(
text,
CultureInfo.GetCultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface(font, fontStyle, fontWeight, FontStretches.Normal),
1,
Brushes.Black // This brush does not matter since we use the geometry of the text.
,
1.25
);
#endif
// Build the geometry object that represents the text.
Geometry textGeometry = formattedText.BuildGeometry(new System.Windows.Point(0, 0));
foreach (PathFigure figure in textGeometry.GetFlattenedPathGeometry().Figures)
{
System.Windows.Point init = figure.StartPoint;
System.Windows.Point a = figure.StartPoint;
System.Windows.Point b;
foreach (PathSegment segment in figure.GetFlattenedPathFigure().Segments)
{
if (segment is System.Windows.Media.LineSegment lineSeg)
{
b = lineSeg.Point;
Line crv = LineBetweenPoints(origin, scale, a, b);
a = b;
crvs.Add(crv);
}
if (segment is PolyLineSegment plineSeg)
{
foreach (System.Windows.Point segPt in plineSeg.Points)
{
Line crv = LineBetweenPoints(origin, scale, a, segPt);
a = segPt;
crvs.Add(crv);
}
}
}
}
return crvs;
}
private static Line LineBetweenPoints(XYZ origin, double scale, System.Windows.Point a, System.Windows.Point b)
{
XYZ pt1 = new((a.X * scale) + origin.X, ((-a.Y + 1) * scale) + origin.Y, origin.Z);
XYZ pt2 = new((b.X * scale) + origin.X, ((-b.Y + 1) * scale) + origin.Y, origin.Z);
Line crv = Line.CreateBound(pt1, pt2);
return crv;
}
}
}

View File

@@ -0,0 +1,279 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Nice3point.Revit.Toolkit.External;
using System;
using System.Collections;
using System.Linq;
namespace Szmedi.RvKits.DrawingTools;
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
public class MergeDimensionsCmd : ExternalCommand
{
public override void Execute()
{
MergeExecute(UiDocument);
//Result = Result.Succeeded;
}
public void MergeExecute(UIDocument uidoc)
{
var doc = uidoc.Document;
//视图中所有可见元素Id
var list = (
from e in new FilteredElementCollector(doc, doc.ActiveView.Id).WhereElementIsNotElementType()
select e.Id.IntegerValue
).ToList();
try
{
var selectedDims = uidoc.Selection
.PickElementsByRectangle(new GenericFilter<Dimension>(), "请框选尺寸标注")
.OfType<Dimension>()
.ToList();
var dictionary = new Dictionary<Line, List<Dimension>>();
foreach (Dimension dimension in selectedDims)
{
Line line = dimension.Curve as Line;
if (line != null)
{
bool flag = false;
foreach (var keyValuePair in dictionary)
{
bool flag3 =
(
Math.Abs(keyValuePair.Key.Origin.DistanceTo(line.Origin)) < 0.0001
&& Math.Abs(Math.Abs(keyValuePair.Key.Direction.DotProduct(line.Direction)) - 1.0) < 0.0001
)
|| Math.Abs(
Math.Abs(
keyValuePair.Key.Direction.DotProduct(Line.CreateBound(keyValuePair.Key.Origin, line.Origin).Direction)
) - 1.0
) < 0.0001;
if (flag3)
{
flag = true;
keyValuePair.Value.Add(dimension);
break;
}
}
if (!flag)
{
dictionary.Add(line, new List<Dimension> { dimension });
}
}
}
doc.InvokeGroup(_ =>
{
foreach (var keyValuePair in dictionary)
{
if (keyValuePair.Value.Count >= 1)
{
try
{
doc.Invoke(_ =>
{
ReferenceArray referenceArray = new();
View view = keyValuePair.Value.First().View;
DimensionType dimensionType = keyValuePair.Value.First().DimensionType;
List<DimData> dimsData = new();
foreach (Dimension dim in keyValuePair.Value)
{
if (dim.NumberOfSegments > 0)
{
dimsData.AddRange(from DimensionSegment segment in dim.Segments select new DimData(segment));
}
else
{
dimsData.Add(new DimData(dim));
}
foreach (Reference reference in dim.References)
{
bool flag8 =
reference.ElementId != ElementId.InvalidElementId
&& !list.Contains(reference.ElementId.IntegerValue);
if (!flag8 && reference.ElementId != ElementId.InvalidElementId)
{
if (doc.GetElement(reference.ElementId) is Grid grid)
{
referenceArray.Append(new Reference(grid));
}
else
{
if (reference.ElementId == ElementId.InvalidElementId)
{
continue;
}
referenceArray.Append(
doc.GetElement(reference.ElementId) is Level level ? new Reference(level) : reference
);
}
}
}
}
Dimension dimension3 = doc.Create.NewDimension(view, keyValuePair.Key, referenceArray, dimensionType);
if (dimension3 != null)
{
bool flag14 = TryRemoveZeroes(dimension3, out referenceArray);
if (flag14)
{
Dimension dimension4 = doc.Create.NewDimension(
view,
keyValuePair.Key,
referenceArray,
dimensionType
);
if (dimension4 != null)
{
doc.Delete(dimension3.Id);
RestoreTextFields(dimension4, dimsData);
}
}
else
{
RestoreTextFields(dimension3, dimsData);
}
doc.Delete((from d in keyValuePair.Value select d.Id).ToList());
}
});
}
catch (Exception)
{
// ignored
}
}
}
});
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
//break;
}
}
public static bool TryRemoveZeroes(Dimension dimension, out ReferenceArray referenceArray)
{
referenceArray = new ReferenceArray();
Document document = dimension.Document;
bool isEmpty = dimension.Segments.IsEmpty;
bool result;
if (isEmpty)
{
result = false;
}
else
{
for (int i = 0; i < dimension.NumberOfSegments; i++)
{
DimensionSegment dimensionSegment = dimension.Segments.get_Item(i);
double? value = dimensionSegment.Value;
bool flag = value != null && Math.Abs(value.Value) < 0.0001;
if (!flag)
{
bool isEmpty2 = referenceArray.IsEmpty;
if (isEmpty2)
{
var refer = dimension.References.get_Item(i);
Element element = document.GetElement(refer);
if (element is Grid or Level)
{
refer = new Reference(element);
}
referenceArray.Append(refer);
}
var refer1 = dimension.References.get_Item(i + 1);
Element element1 = document.GetElement(refer1);
if (element1 is Grid or Level)
{
refer1 = new Reference(element1);
}
referenceArray.Append(refer1);
}
}
result = referenceArray.Size < dimension.References.Size;
}
return result;
}
private static void RestoreTextFields(Dimension dimension, IReadOnlyCollection<DimData> dimsData)
{
IEnumerator enumerator = dimension.Segments.GetEnumerator();
while (enumerator.MoveNext())
{
DimensionSegment segment = (DimensionSegment)enumerator.Current;
DimData dimData = dimsData.FirstOrDefault(
d => d.IsMatchValue(segment?.Value) && Math.Abs(d.Origin.DistanceTo(segment.Origin)) < 0.0001
);
if (dimData != null && segment != null)
{
segment.Prefix = dimData.Prefix;
segment.Suffix = dimData.Suffix;
segment.Above = dimData.Above;
segment.Below = dimData.Below;
segment.TextPosition = dimData.TextPosition;
}
}
}
}
internal class DimData
{
public DimData(Dimension dimension)
{
Value = dimension.Value;
Origin = dimension.Origin;
TextPosition = dimension.TextPosition;
Prefix = dimension.Prefix;
Suffix = dimension.Suffix;
Above = dimension.Above;
Below = dimension.Below;
}
public DimData(DimensionSegment dimension)
{
Value = dimension.Value;
Origin = dimension.Origin;
TextPosition = dimension.TextPosition;
Prefix = dimension.Prefix;
Suffix = dimension.Suffix;
Above = dimension.Above;
Below = dimension.Below;
}
public double? Value { get; }
public string Prefix { get; }
public string Suffix { get; }
public string Above { get; }
public string Below { get; }
public XYZ Origin { get; }
public XYZ TextPosition { get; }
public bool IsMatchValue(double? value)
{
bool flag = Value != null && value != null;
bool result = flag ? Math.Abs(Value.Value - value.Value) < 0.0001 : Value == null && value == null;
return result;
}
}

View File

@@ -0,0 +1,117 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Nice3point.Revit.Toolkit.External;
using System;
using System.Linq;
namespace Szmedi.RvKits.DrawingTools;
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
public class SplitDimensionsCmd : ExternalCommand
{
public override void Execute()
{
SplitExecute(UiDocument);
}
public void SplitExecute(UIDocument uidoc)
{
var doc = uidoc.Document;
try
{
List<Dimension> list = uidoc.Selection
.PickElementsByRectangle(new GenericFilter<Dimension>(), "框选尺寸标注")
.OfType<Dimension>()
.ToList();
bool flag = !list.Any();
if (!flag)
{
doc.InvokeGroup(
transactionGroup =>
{
foreach (Dimension dimension in list)
{
try
{
Line line = dimension.Curve as Line;
if (line != null)
{
doc.Invoke(ts =>
{
for (int i = 0; i < dimension.NumberOfSegments; i++)
{
DimensionSegment dimensionSegment = dimension.Segments.get_Item(i);
Reference reference = dimension.References.get_Item(i);
if (reference.ElementId != ElementId.InvalidElementId)
{
if (doc.GetElement(reference.ElementId) is Grid grid)
{
reference = new Reference(grid);
}
}
if (reference.ElementId != ElementId.InvalidElementId)
{
if (doc.GetElement(reference.ElementId) is Level level)
{
reference = new Reference(level);
}
}
Reference reference2 = dimension.References.get_Item(i + 1);
if (reference2.ElementId != ElementId.InvalidElementId)
{
if (doc.GetElement(reference2.ElementId) is Grid grid2)
{
reference2 = new Reference(grid2);
}
}
if (reference2.ElementId != ElementId.InvalidElementId)
{
if (doc.GetElement(reference2.ElementId) is Level level2)
{
reference2 = new Reference(level2);
}
}
ReferenceArray referenceArray = new();
referenceArray.Append(reference);
referenceArray.Append(reference2);
Dimension dimension2 = doc.Create.NewDimension(
dimension.View,
line,
referenceArray,
dimension.DimensionType
);
if (dimension2 != null)
{
dimension2.Prefix = dimensionSegment.Prefix;
dimension2.Suffix = dimensionSegment.Suffix;
dimension2.Above = dimensionSegment.Above;
dimension2.Below = dimensionSegment.Below;
dimension2.TextPosition = dimensionSegment.TextPosition;
}
}
doc.Delete(dimension.Id);
});
}
}
catch (Exception)
{
// ignored
}
}
},
"拆分尺寸标注"
);
}
}
catch (Autodesk.Revit.Exceptions.OperationCanceledException) { }
}
}