2025-07-11 09:20:23 +08:00
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
|
|
|
|
|
|
using Autodesk.Revit.DB;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2025-04-24 20:56:44 +08:00
|
|
|
|
namespace ShrlAlgoToolkit.Revit.Assists
|
2024-09-22 11:05:41 +08:00
|
|
|
|
{
|
2025-07-11 09:20:23 +08:00
|
|
|
|
internal class GeometryAssist
|
|
|
|
|
|
{
|
2025-12-28 11:47:54 +08:00
|
|
|
|
/// <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
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2025-07-11 09:20:23 +08:00
|
|
|
|
/// <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();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|