Files
Shrlalgo.RvKits/ShrlAlgoToolkit.Revit/Assists/GeometryAssist.cs
2025-12-28 11:47:54 +08:00

263 lines
11 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.Diagnostics;
using Autodesk.Revit.DB;
namespace ShrlAlgoToolkit.Revit.Assists
{
internal class GeometryAssist
{
/// <summary>
///获取元素的包围框
/// </summary>
/// <param name="elements"></param>
/// <returns></returns>
public static BoundingBoxXYZ GetBoundingBox(List<Element> elements)
{
if (elements == null || elements.Count == 0)
{
return new BoundingBoxXYZ();
}
var gmax = XYZ.Zero;
var gmin = XYZ.Zero;
var elementIds = elements.Select(e => e.Id).ToList();
var doc = elements.FirstOrDefault()?.Document;
using (SubTransaction sub = new SubTransaction(doc))
{
sub.Start();
Group g;
if (doc.IsFamilyDocument)
{
g = doc.FamilyCreate.NewGroup(elementIds);
}
else
{
g = doc.Create.NewGroup(elementIds);
}
gmax = g.get_BoundingBox(null).Max;
gmin = g.get_BoundingBox(null).Min;
sub.RollBack();
}
return new BoundingBoxXYZ
{
Max = gmax,
Min = gmin
};
}
/// <summary>
/// 对曲线列表进行排序,使其正确排序和定向,形成线串。
/// </summary>
public static void SortCurvesContiguous(IList<Curve> curves, bool debug_output = false)
{
const double _inch = 1.0 / 12.0;
const double _sixteenth = _inch / 16.0;
int n = curves.Count;
for (int i = 0; i < n; ++i)
{
Curve curve = curves[i];
XYZ endPoint = curve.GetEndPoint(1);
XYZ p;
// 查找起点 = 终点的曲线
bool found = (i + 1 >= n);
for (int j = i + 1; j < n; ++j)
{
p = curves[j].GetEndPoint(0);
// 如果匹配 end->start、
// 这是下一条曲线
if (_sixteenth > p.DistanceTo(endPoint))
{
if (debug_output)
{
Debug.Print("{0} 起始点, 换成 {1}", j, i + 1);
}
if (i + 1 != j)
{
Curve tmp = curves[i + 1];
curves[i + 1] = curves[j];
curves[j] = tmp;
}
found = true;
break;
}
p = curves[j].GetEndPoint(1);
// 如果有匹配结果 end->end、
// 反转下一条曲线
if (_sixteenth > p.DistanceTo(endPoint))
{
if (i + 1 == j)
{
if (debug_output)
{
Debug.Print("{0} 终点, 反向 {1}", j, i + 1);
}
curves[i + 1] = curves[j].CreateReversed();
}
else
{
if (debug_output)
{
Debug.Print("{0} 终点, 倒换 {1}", j, i + 1);
}
Curve tmp = curves[i + 1];
curves[i + 1] = curves[j].CreateReversed();
curves[j] = tmp;
}
found = true;
break;
}
}
if (!found)
{
throw new Exception("SortCurvesContiguous:" + " 非连续输入曲线");
}
}
}
public static void CreateDirectShape(
Document doc,
List<XYZ> vertices,
List<Face> faces,
ElementId graphicsStyleId,
ElementId categoryId,
string appGuid,
string shapeName
)
{
var nFaces = 0;
var builder = new TessellatedShapeBuilder { LogString = shapeName };
var corners = new List<XYZ>();
builder.OpenConnectedFaceSet(false);
foreach (var f in faces)
{
builder.LogInteger = nFaces;
//if (corners.Capacity < f.Indices.Count)//设置corner的Capacity值减少内存开销
//{
// corners = new ErrorModels<XYZ>(f.Indices.Count);
//}
//corners.Clear();
//foreach (Index i in f.Indices)
//{
// if (i.vertex >= vertices.Count)
// {
// return;
// }
// corners.Add(vertices[i.vertex]);
//}
try
{
builder.AddFace(new TessellatedFace(corners, ElementId.InvalidElementId));
}
catch (Autodesk.Revit.Exceptions.ArgumentException) { }
}
builder.CloseConnectedFaceSet();
builder.Target = TessellatedShapeBuilderTarget.AnyGeometry;
builder.Fallback = TessellatedShapeBuilderFallback.Mesh;
builder.GraphicsStyleId = graphicsStyleId;
builder.Build();
var ds = DirectShape.CreateElement(doc, categoryId);
ds.ApplicationId = appGuid;
ds.ApplicationDataId = shapeName;
ds.SetShape(builder.GetBuildResult().GetGeometricalObjects());
ds.Name = shapeName;
}
//public BRepBuilder CreateGeo()
//{
//BRepBuilder bRepBuilder=new BRepBuilder(BRepType.Solid);
//BRepBuilderEdgeGeometry.Create();
//BRepBuilderSurfaceGeometry.Create();
//BRepBuilderSurfaceGeometry.CreateNURBSSurface();
//}
public static void CreateDirectShapeFromCylinder(Document doc)
{
// Naming convention for faces and edges: we assume that x is to the left and pointing down, y is horizontal and pointing to the right, z is up
var brepBuilder = new BRepBuilder(BRepType.Solid);
// The surfaces of the four faces.
var basis = new Frame(new XYZ(50, -100, 0), new XYZ(0, 1, 0), new XYZ(-1, 0, 0), new XYZ(0, 0, 1));
var cylSurf = CylindricalSurface.Create(basis, 50);
var top = Plane.CreateByNormalAndOrigin(new XYZ(0, 0, 1), new XYZ(0, 0, 100)); // normal points outside the cylinder
var bottom = Plane.CreateByNormalAndOrigin(new XYZ(0, 0, 1), new XYZ(0, 0, 0)); // normal points inside the cylinder
// Add the four faces
var frontCylFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(cylSurf, null), false);
var backCylFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(cylSurf, null), false);
var topFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(top, null), false);
var bottomFaceId = brepBuilder.AddFace(BRepBuilderSurfaceGeometry.Create(bottom, null), true);
// Geometry for the four semi-circular edges and two vertical linear edges
var frontEdgeBottom = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(0, -100, 0), new XYZ(100, -100, 0), new XYZ(50, -50, 0)));
var backEdgeBottom = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(100, -100, 0), new XYZ(0, -100, 0), new XYZ(50, -150, 0)));
var frontEdgeTop = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(0, -100, 100), new XYZ(100, -100, 100), new XYZ(50, -50, 100)));
var backEdgeTop = BRepBuilderEdgeGeometry.Create(Arc.Create(new XYZ(0, -100, 100), new XYZ(100, -100, 100), new XYZ(50, -150, 100)));
var linearEdgeFront = BRepBuilderEdgeGeometry.Create(new XYZ(100, -100, 0), new XYZ(100, -100, 100));
var linearEdgeBack = BRepBuilderEdgeGeometry.Create(new XYZ(0, -100, 0), new XYZ(0, -100, 100));
// Add the six edges
var frontEdgeBottomId = brepBuilder.AddEdge(frontEdgeBottom);
var frontEdgeTopId = brepBuilder.AddEdge(frontEdgeTop);
var linearEdgeFrontId = brepBuilder.AddEdge(linearEdgeFront);
var linearEdgeBackId = brepBuilder.AddEdge(linearEdgeBack);
var backEdgeBottomId = brepBuilder.AddEdge(backEdgeBottom);
var backEdgeTopId = brepBuilder.AddEdge(backEdgeTop);
// Loops of the four faces
var loopIdTop = brepBuilder.AddLoop(topFaceId);
var loopIdBottom = brepBuilder.AddLoop(bottomFaceId);
var loopIdFront = brepBuilder.AddLoop(frontCylFaceId);
var loopIdBack = brepBuilder.AddLoop(backCylFaceId);
// Add coedges for the loop of the front face
brepBuilder.AddCoEdge(loopIdFront, linearEdgeBackId, false);
brepBuilder.AddCoEdge(loopIdFront, frontEdgeTopId, false);
brepBuilder.AddCoEdge(loopIdFront, linearEdgeFrontId, true);
brepBuilder.AddCoEdge(loopIdFront, frontEdgeBottomId, true);
brepBuilder.FinishLoop(loopIdFront);
brepBuilder.FinishFace(frontCylFaceId);
// Add coedges for the loop of the back face
brepBuilder.AddCoEdge(loopIdBack, linearEdgeBackId, true);
brepBuilder.AddCoEdge(loopIdBack, backEdgeBottomId, true);
brepBuilder.AddCoEdge(loopIdBack, linearEdgeFrontId, false);
brepBuilder.AddCoEdge(loopIdBack, backEdgeTopId, true);
brepBuilder.FinishLoop(loopIdBack);
brepBuilder.FinishFace(backCylFaceId);
// Add coedges for the loop of the top face
brepBuilder.AddCoEdge(loopIdTop, backEdgeTopId, false);
brepBuilder.AddCoEdge(loopIdTop, frontEdgeTopId, true);
brepBuilder.FinishLoop(loopIdTop);
brepBuilder.FinishFace(topFaceId);
// Add coedges for the loop of the bottom face
brepBuilder.AddCoEdge(loopIdBottom, frontEdgeBottomId, false);
brepBuilder.AddCoEdge(loopIdBottom, backEdgeBottomId, false);
brepBuilder.FinishLoop(loopIdBottom);
brepBuilder.FinishFace(bottomFaceId);
brepBuilder.Finish();
using var tr = new Transaction(doc, "Create a DirectShape");
tr.Start();
var ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel));
ds.SetShape(brepBuilder);
tr.Commit();
}
}
}