727 lines
30 KiB
C#
727 lines
30 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|