Files
SzmediTools/Szmedi.RvKits/Drawing/DimensionElemCmd.cs

309 lines
10 KiB
C#
Raw Normal View History

2025-09-16 16:06:41 +08:00

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);
}
}
}
}