System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)的问题

本文深入探讨了在VB.net代码转换过程中,由C#程序中的数学操作自动生成的复杂语句。解释了原因在于防止传递错误,并提供了详细链接以供进一步学习。

今天在学习一段VB.net的代码时看到了这样的语句System.Math.Min(System.Threading.Interlocked.Increment(i), i - 1)

百思不得其解,在Google上搜了一把,发现这段语句是C#程序转为VB.net时自动生成的。由于在C#程序中使用了诸如

i++之类得得语句,所以为了防止转换后的VB.net程序传递错误的值,就将源程序中的语句自动转换为如上的复杂的语句了。

下面的两个网址对此有解释。

http://www.telerik.com/community/forums/open-source-projects/code-converter/system-math-max-system-threading-interlocked-increment-k-k-1.aspx

http://stackoverflow.com/questions/1828728/why-use-system-threading-interlocked-decrement-instead-of-minus

using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.Colors; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; namespace ScaffoldAutomation { public class DiagonalBarPlacer { // 配置常量 private const string Diagonal极Layer = "斜拉杆"; private const string DiagonalBarPrefix = "ScaffoldPolexie水平斜拉杆"; private const string BlockDirectoryName = "ScaffoldBlocks"; private const string AxisLayer = "盘扣轴网"; // 标准斜拉杆长度(毫米) private static readonly double[] DiagonalBarLengths = { 600, 900, 1200, 1500, 1800 }; // 缓存已存在的斜拉杆 private readonly Dictionary<string, HashSet<string>> _existingDiagonalCache = new Dictionary<string, HashSet<string>>(); // 插件目录路径 private readonly string _pluginDirectory; // 网格数据结构 private GridStructure _grid; // 容差值(毫米) private const double Tolerance = 1.0; // 斜拉杆偏移距离(毫米) private const double OffsetDistance = 1.0; public DiagonalBarPlacer() { _pluginDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } [CommandMethod("BuildDiagonal", "BD", CommandFlags.Modal)] public void BuildDiagonal() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { // 创建斜杆图层 CreateLayerIfNotExists(db, DiagonalBarLayer, 4); // 青色 CheckLayerState(db, DiagonalBarLayer); // 步骤1:选择布置模式 int mode = GetDiagonalMode(ed); if (mode == 0) return; // 步骤2:选择轴网线段 PromptSelectionOptions selOpts = new PromptSelectionOptions(); selOpts.MessageForAdding = "\n选择盘扣轴网线段: "; PromptSelectionResult selResult = ed.GetSelection(sel极s); if (selResult.Status != PromptStatus.OK) return; // 加载斜拉杆块定义 LoadDiagonalBlockDefinitions(db, ed); // 构建现有斜拉杆缓存 BuildExistingDiagonalCache(db); using (Transaction tr = db.TransactionManager.StartTransaction()) { // 处理轴网并生成网格结构 if (!ProcessAxisLines(db, selResult, tr, ed)) { ed.WriteMessage("\n无法生成有效的网格结构"); return; } // 布置斜拉杆 int diagonalCount = PlaceDiagonalBars(db, tr, mode, ed); tr.Commit(); ed.WriteMessage($"\n成功布置 {diagonalCount} 根斜拉杆"); if (diagonalCount > 0) { Application.ShowAlertDialog($"已布置 {diagonalCount} 根斜拉杆!"); } } } catch (System.Exception ex) { ed.WriteMessage($"\n错误: {ex.Message}\n{ex.StackTrace}"); } } #region 新增自动检查功能 // 删除田字型框内及周边的斜拉杆 private int DeleteBarsInPatternTwoArea(Database db, Transaction tr, int row, int col, Editor ed) { int deletedCount = 0; BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); // 定义田字型区域 (3x3单元) int startRow = Math.Max(0, row - 1); int endRow = Math.Min(_grid.RowCount - 1, row + 1); int startCol = Math.Max(0, col - 1); int endCol = Math.Min(_grid.ColumnCount - 1, col + 1); // 收集要删除的边 var edgesToDelete = new List<GridEdge>(); // 收集水平边 for (int r = startRow; r <= endRow; r++) { for (int c = startCol; c <= endCol; c++) { // 上边 var topEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r && e.ColIndex == c); if (topEdge != null) edgesToDelete.Add(topEdge); // 下边 var bottomEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r + 1 && e.ColIndex == c); if (bottomEdge != null) edgesToDelete.Add(bottomEdge); // 左边 var leftEdge = _grid.VerticalEdges .FirstOrDefault(e => e.ColIndex == c && e.RowIndex == r); if (leftEdge != null) edgesToDelete.Add(leftEdge); // 右边 var rightEdge = _grid.VerticalEdges .FirstOrDefault(e => e.ColIndex == c + 极 && e.RowIndex == r); if (rightEdge != null) edgesToDelete.Add(rightEdge); } } // 删除中间跨的水平杆 for (int r = startRow; r <= endRow; r++) { // 中间列 int midCol = col + 1; if (midCol < _grid.ColumnCount) { var midEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r && e.ColIndex == midCol); if (midEdge != null) edgesToDelete.Add(midEdge); } } // 删除这些边上的斜拉杆 foreach (var edge in edgesToDelete) { Point3d midPoint = new Point3d( (edge.StartPoint.X + edge.EndPoint.X) / 2, (edge.StartPoint.Y + edge.EndPoint.Y) / 2, 0); // 查找并删除该位置的斜拉杆 foreach (ObjectId id in btr) { BlockReference br = tr.GetObject(id, OpenMode.ForRead) as BlockReference; if (br != null && br.Layer == DiagonalBarLayer && br.Position.DistanceTo(midPoint) < Tolerance) { br.UpgradeOpen(); br.Erase(); deletedCount++; ed.WriteMessage($"\n删除斜拉杆: ({midPoint.X:F0},{midPoint.Y:F0})"); break; } } } return deletedCount; } // 删除井字型框内及周边的斜拉杆 private int DeleteBarsInPatternThreeArea(Database db, Transaction tr, int row, int col, Editor ed) { int deletedCount = 0; BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); // 定义井字型区域 (4x4单元) int startRow = Math.Max(0, row - 1); int endRow = Math.Min(_grid.RowCount - 1, row + 2); int startCol = Math.Max(0, col - 1); int endCol = Math.Min(_grid.ColumnCount - 1, col + 2); // 收集要删除的边 var edgesToDelete = new List<GridEdge>(); // 收集水平边 for (int r = startRow; r <= endRow; r++) { for (int c = startCol; c <= endCol; c++) { // 上边 var topEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r && e.ColIndex == c); if (topEdge != null) edgesToDelete.Add(topEdge); // 下边 var bottomEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r + 1 && e.ColIndex == c); if (bottomEdge != null) edgesToDelete.Add(bottomEdge); // 左边 var leftEdge = _grid.VerticalEdges .FirstOrDefault(e => e.ColIndex == c && e.RowIndex == r); if (leftEdge != null) edgesToDelete.Add(leftEdge); // 右边 var rightEdge = _grid.VerticalEdges .FirstOrDefault(e => e.ColIndex == c + 1 && e.RowIndex == r); if (rightEdge != null) edgesToDelete.Add(rightEdge); } } // 删除中间跨的水平杆 for (int r = startRow; r <= endRow; r++) { // 中间列1 int midCol1 = col + 1; if (midCol1 < _grid.ColumnCount) { var midEdge1 = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r && e.ColIndex == midCol1); if (midEdge1 != null) edgesToDelete.Add(midEdge1); } // 中间列2 int midCol2 = col + 2; if (midCol2 < _grid.ColumnCount) { var midEdge2 = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r && e.ColIndex == midCol2); if (midEdge2 != null) edgesToDelete.Add(midEdge2); } } // 删除这些边上的斜拉杆 foreach (var edge in edgesToDelete) { Point3d midPoint = new Point3d( (edge.StartPoint.X + edge.EndPoint.X) / 2, (edge.StartPoint.Y + edge.EndPoint.Y) / 2, 0); // 查找并删除该位置的斜极杆 foreach (ObjectId id in btr) { BlockReference br = tr.GetObject(id, OpenMode.ForRead) as BlockReference; if (br != null && br.Layer == DiagonalBarLayer && br.Position.DistanceTo(midPoint) < Tolerance) { br.UpgradeOpen(); br.Erase(); deletedCount++; ed.WriteMessage($"\n删除斜拉杆: ({midPoint.X:F0},{midPoint.Y:F0})"); break; } } } return deletedCount; } #endregion #region 网格数据结构 // 网格结构 private class GridStructure { public List<double> XCoordinates { get; set; } = new List<double>(); public List<double> YCoordinates { get; set; } = new List<double>(); public List<GridEdge> HorizontalEdges { get; } = new List<GridEdge>(); public List<GridEdge> VerticalEdges { get; } = new List<GridEdge>(); public int RowCount => YCoordinates.Count - 1; public int ColumnCount => XCoordinates.Count - 1; } // 网格边 private class GridEdge { public Point3d StartPoint { get; set; } public Point3d EndPoint { get; set; } public double Length { get; set; } public int RowIndex { get; set; } // 行索引(水平边) public int ColIndex { get; set; } // 列索引(垂直边) public bool IsHorizontal { get; set; } public bool IsOuterEdge { get; set; } // 是否是最外侧边 public bool IsTopEdge { get; set; } // 是否是顶部边 public bool IsBottomEdge { get; set; } // 是否是底部边 public bool IsLeftEdge { get; set; } // 是否是左侧边 public bool IsRightEdge { get; set; } // 是否是右侧边 } // 点比较器(用于去重) private class Point3dComparer : IEqualityComparer<Point3d> { private readonly double _tolerance; public Point3dComparer(double tolerance) => _tolerance = tolerance; public bool Equals(Point3d p1, Point3d p2) => p1.DistanceTo(p2) <= _tolerance; public int GetHashCode(Point3d p) => (Math.Round(p.X / _tolerance), Math.Round(p.Y / _tolerance), Math.Round(p.Z / _tolerance)).GetHashCode(); } #endregion #region 轴网处理 // 处理轴网线段 private bool ProcessAxisLines(Database db, PromptSelectionResult selResult, Transaction tr, Editor ed) { List<Line> axisLines = new List<Line>(); // 收集轴网线段 foreach (ObjectId objId in selResult.Value.GetObjectIds()) { Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity; if (ent != null && ent.Layer == AxisLayer && ent is Line line) { axisLines.Add(line); } } if (axisLines.Count == 0) { ed.WriteMessage("\n未选择任何轴网线段"); return false; } ed.WriteMessage($"\n找到 {axisLines.Count} 条轴网线段"); // 计算所有网格交点 List<Point3d> intersections = CalculateIntersections(axisLines, ed); if (intersections.Count == 0) { ed.WriteMessage("\n未找到网格交点"); return false; } // 构建网格结构 _grid = BuildGridStructure(intersections, axisLines, ed); if (_grid == null || _grid.XCoordinates.Count < 2 || _grid.YCoordinates.Count < 2) { ed.WriteMessage("\n无法构建有效的网格结构"); return false; } ed.WriteMessage($"\n网格结构: {_grid.ColumnCount}列 x {_grid.RowCount}行"); ed.WriteMessage($"\n水平边数量: {_grid.HorizontalEdges.Count}, 垂直边数量: {_grid.VerticalEdges.Count}"); return true; } // 计算所有网格交点(优化性能) private List<Point3d> CalculateIntersections(List<Line> axisLines, Editor ed) { var intersections = new ConcurrentDictionary<Point3d, bool>(new Point3dComparer(Tolerance)); long totalIntersections = 0; // 使用空间分区提高性能 var lineBuckets = new Dictionary<(int, int), List<Line>>(); const double gridSize = 5000.0; // 网格大小5米 // 并行处理线段分配 Parallel.ForEach(axisLines, line => { Point3d min = new Point3d( Math.Min(line.StartPoint.X, line.EndPoint.X), Math.Min(line.StartPoint.Y, line.EndPoint.Y), 0); Point3d max = new Point3d( Math.Max(line.StartPoint.X, line.EndPoint.X), Math.Max(line.StartPoint.Y, line.EndPoint.Y), 0); int minX = (int)(min.X / gridSize); int minY = (int)(min.Y / gridSize); int maxX = (int)(max.X / gridSize); int maxY = (int)(max.Y / gridSize); for (int x = minX; x <= maxX; x++) { for (int y = minY; y <= maxY; y++) { var key = (x, y); lock (lineBuckets) { if (!lineBuckets.ContainsKey(key)) lineBuckets[key] = new List<Line>(); lineBuckets[key].Add(line); } } } }); // 并行处理交点计算 var keys = lineBuckets.Keys.ToArray(); Parallel.For(0, keys.Length, i => { var bucket = lineBuckets[keys[i]]; for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { var neighborKey = (keys[i].Item1 + dx, keys[i].Item2 + dy); if (!lineBuckets.ContainsKey(neighborKey)) continue; var neighborBucket = lineBuckets[neighborKey]; for (int a = 0; a < bucket.Count; a++) { for (int b = a + 1; b < neighborBucket.Count; b++) { Point3dCollection pts = new Point3dCollection(); bucket[a].IntersectWith( neighborBucket[b], Intersect.ExtendBoth, pts, IntPtr.Zero, IntPtr.Zero); foreach (Point3d pt in pts) { intersections[RoundPoint(pt, Tolerance)] = true; Interlocked.Increment(ref totalIntersections); } } } } } }); ed.WriteMessage($"\n找到 {intersections.Count} 个有效网格交点(总交点: {totalIntersections})"); return intersections.Keys.ToList(); } // 构建网格结构 private GridStructure BuildGridStructure(List<极3d> intersections, List<Line> axisLines, Editor ed) { var grid = new GridStructure(); // 分离X和Y坐标(带容差) var xCoords = intersections .Select(p => Math.Round(p.X / Tolerance) * Tolerance) .Distinct() .OrderBy(x => x) .ToList(); var yCoords = intersections .Select(p => Math.Round(p.Y / Tolerance) * Tolerance) .Distinct() .OrderByDescending(y => y) // Y坐标从大到小排序(顶部为0) .ToList(); grid.XCoordinates = xCoords; grid.YCoordinates = yCoords; // 创建水平边 for (int row = 0; row < yCoords.Count; row++) { for (int col = 0; col < xCoords.Count - 1; col++) { Point3d start = new Point3d(xCoords[col], yCoords[row], 0); Point3d end = new Point3d(xCoords[col + 1], yCoords[row], 0); // 检查是否为有效线段 if (IsValidSegment(axisLines, start, end, Tolerance)) { grid.HorizontalEdges.Add(new GridEdge { StartPoint = start, EndPoint = end, Length = start.DistanceTo(end), RowIndex = row, ColIndex = col, IsHorizontal = true, IsOuterEdge = (row == 0 || row == yCoords.Count - 1), IsTopEdge = (row == 极), IsBottomEdge = (row == yCoords.Count - 1) }); } } } // 创建垂直边(处理分段线段) for (int col = 0; col < xCoords.Count; col++) { double x = xCoords[col]; // 收集该列上的所有交点 var colPoints = intersections .Where(p => Math.Abs(p.X - x) < Tolerance) .OrderByDescending(p => p.Y) .ToList(); // 处理相邻交点间的线段 for (int i = 0; i < colPoints.Count - 1; i++) { Point3d start = colPoints[i]; Point3d end = colPoints[i + 1]; double segmentLength = start.DistanceTo(end); // 查找实际存在的线段 Line actualSegment = FindActualSegment(axisLines, start, end, Tolerance); if (actualSegment != null) { grid.VerticalEdges.Add(new GridEdge { StartPoint = start, EndPoint = end, Length = actualSegment.Length, // 使用实际线段长度 RowIndex = i, ColIndex = col, IsHorizontal = false, IsOuterEdge = (col == 0 || col == xCoords.Count - 1), IsLeftEdge = (col == 0), IsRightEdge = (col == xCoords.Count - 1) }); } } } return grid; } // 查找实际存在的线段 private Line FindActualSegment(List<Line> axisLines, Point3d start, Point3d end, double tolerance) { foreach (Line line in axisLines) { if (IsPointOnLine(line, start, tolerance) && IsPointOnLine(line, end, tolerance) && Math.Abs(line.Length - start.DistanceTo(end)) < tolerance) { return line; } } return null; } // 检查点是否在直线上(带容差) private bool IsPointOnLine(Line line, Point3d point, double tolerance) { // 检查点是否接近起点或终点 if (point.DistanceTo(line.StartPoint) <= tolerance || point.DistanceTo(line.EndPoint) <= tolerance) return true; // 计算点到直线的距离 Vector3d lineVec = line.EndPoint - line.StartPoint; Vector3d pointVec = point - line.StartPoint; // 检查点是否在线段范围内 double dotProduct = lineVec.DotProduct(pointVec); if (dotProduct < 0 || dotProduct > lineVec.LengthSqrd) return false; // 计算垂直距离 double distance = Math.Abs(lineVec.CrossProduct(pointVec).Length / lineVec.Length); return distance <= tolerance; } // 检查是否为有效线段(带容差) private bool IsValidSegment(List<Line> axisLines, Point3d start, Point3d end, double tolerance) { foreach (Line line in axisLines) { if (IsPointOnLine(line, start, tolerance) && IsPointOnLine(line, end, tolerance)) { return true; } } return false; } #endregion #region 斜拉杆布置核心逻辑(按模式实现) // 布置斜拉杆(根据不同的布置模式) private int PlaceDiagonalBars(Database db, Transaction tr, int mode, Editor ed) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); if (_grid == null || (_grid.HorizontalEdges.Count == 0 && _grid.VerticalEdges.Count == 0)) { ed.WriteMessage("\n没有可用的网格边"); return 0; } int diagonalCount = 0; var placedEdges = new HashSet<string>(); // 避免重复布置 // 添加整体进度报告 int totalEdges = _grid.HorizontalEdges.Count + _grid.VerticalEdges.Count; int processed = 0; int lastReported = 0; switch (mode) { case 1: // 隔一布一 diagonalCount += PlacePatternOne(db, tr, btr, bt, placedEdges, ed, ref processed, totalEdges, ref lastReported); break; case 2: // 隔二布一 diagonalCount += PlacePatternTwo(db, tr, btr, bt, placedEdges, ed, ref processed, totalEdges, ref lastReported); break; case 3: // 隔三布一 diagonalCount += PlacePatternThree(db, tr, btr, bt, placedEdges, ed, ref processed, totalEdges, ref lastReported); break; case 4: // 满布 diagonalCount += PlaceFullPattern(db, tr, btr, bt, placedEdges, ed, ref processed, totalEdges, ref lastReported); 极 break; } return diagonalCount; } // 模式1: 隔一布一 private int PlacePatternOne(Database db, Transaction tr, BlockTableRecord btr, BlockTable bt, HashSet<string> placedEdges, Editor ed, ref int processed, int totalEdges, ref int lastReported) { int count = 0; for (int row = 0; row < _grid.RowCount; row++) { // 每10行报告一次进度 if (row % 10 == 0) { ed.WriteMessage($"\n处理中: 行 {row}/{_grid.RowCount} ({(double)row / _grid.RowCount:P0})"); if (CheckForUserCancel(ed)) { ed.WriteMessage("\n操作已取消"); return count; } } for (int col = 0; col < _grid.ColumnCount; col++) { // 隔一布一:行和列索引都是偶数的单元 if (row % 2 == 0 && col % 2 == 0) { count += PlaceCellEdges(row, col, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } ed.WriteMessage($"\n隔一布一模式: 布置了 {count} 根斜拉杆"); return count; } // 模式2: 隔二布一(添加自动检查功能) private int PlacePatternTwo(Database db, Transaction tr, BlockTableRecord btr, BlockTable bt, HashSet<string> placedEdges, Editor ed, ref int processed, int totalEdges, ref int lastReported) { int count = 0; int deletedCount = 0; // 单元布置:只布置左上角单元(每3行3列) for (int row = 0; row < _grid.RowCount; row += 3) { for (int col = 0; col < _grid.ColumnCount; col += 3) { // 删除田字型区域内的斜拉杆 deletedCount += DeleteBarsInPatternTwoArea(db, tr, row, col, ed); // 布置单元四边 count += PlaceCellEdges(row, col, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } // 布置中间垂直边(第1列) for (int col = 1; col < _grid.ColumnCount; col += 3) { for (int row = 0; row < _grid.Row极Count; row++) { // 跳过中间行(行索引为1 mod 3) if (row % 3 == 1) continue; var edges = _grid.VerticalEdges .Where(e => e.ColIndex == col && e.RowIndex == row) .ToList(); foreach (var edge in edges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } // 布置中间水平边(第1行) for (int row = 1; row < _grid.RowCount; row += 3) { for (int col = 0; col < _grid.ColumnCount; col++) { // 跳过中间列(列索引为1 mod 3) if (col % 3 == 1) continue; var edges = _grid.HorizontalEdges .Where(e => e.RowIndex == row && e.ColIndex == col) .ToList(); foreach (var edge in edges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } ed.WriteMessage($"\n隔二布一模式: 删除了 {deletedCount} 根斜拉杆,布置了 {count极} 根斜拉杆"); return count; } // 模式3: 隔三布一(添加自动检查功能) private int PlacePatternThree(Database db, Transaction tr, BlockTableRecord btr, BlockTable bt, HashSet<string> placedEdges, Editor ed, ref int processed, int totalEdges, ref int lastReported) { int count = 0; int deletedCount = 0; // 单元布置:只布置左上角单元(每4行4列) for (int row = 0; row < _grid.RowCount; row += 4) { for (int col = 0; col < _grid.ColumnCount; col += 4) { // 删除井字型区域内的斜拉杆 deletedCount += DeleteBarsInPatternThreeArea(db, tr, row, col, ed); // 布置单元四边 count += PlaceCellEdges(row, col, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } // 布置中间垂直边(第1列和第2列) for (int col = 1; col < _grid.ColumnCount; col += 4) // 每4列的第1列 { for (int row = 0; row < _grid.RowCount; row++) { // 跳过中间行(行索引为1或2 mod 4) if (row % 4 == 1 || row % 4 == 2) continue; var edges = _grid.VerticalEdges .Where(e => e.ColIndex == col && e.RowIndex == row) .ToList(); foreach (var edge in edges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } for (int col = 2; col < _grid.ColumnCount; col += 4) // 每4列的第2列 { for (int row = 0; row < _grid.RowCount; row++) { // 跳过中间行(行索引为1或2 mod 4) if (row % 4 == 1 || row % 4 == 2) continue; var edges = _grid.VerticalEdges .Where(e => e.ColIndex == col && e.RowIndex == row) .ToList(); foreach (var edge in edges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } // 布置中间水平边(第1行和第2行) for (int row = 1; row < _grid.RowCount; row += 4) // 每4行的第1行 { for (int col = 0; col < _grid.ColumnCount; col++) { // 跳过中间列(列索引为1或2 mod 4) if (col % 4 == 1 || col % 4 == 2) continue; var edges = _grid.HorizontalEdges .Where(e => e.RowIndex == row && e.ColIndex == col) .ToList(); foreach (var edge in edges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } for (int row = 2; row < _grid.RowCount; row += 4) // 每4行的第2行 { for (int col = 0; col < _grid.ColumnCount; col++) { // 跳过中间列(列索引为1或2 mod 4) if (col % 4 == 1 || col % 4 == 2) continue; var edges = _grid.HorizontalEdges .Where(e => e.RowIndex == row && e.ColIndex == col) .ToList(); foreach (var edge in edges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } ed.WriteMessage($"\n隔三布一模式: 删除了 {deletedCount} 根斜拉杆,布置了 {count} 根斜拉杆"); return count; } // 模式4: 满布 private int PlaceFullPattern(Database db, Transaction tr, BlockTableRecord btr, BlockTable bt, HashSet<string> placedEdges, Editor ed, ref int processed, int totalEdges, ref int lastReported) { int count = 0; // 布置所有水平边 foreach (GridEdge edge in _grid.HorizontalEdges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } // 布置所有垂直边 foreach (GridEdge edge in _grid.VerticalEdges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } ed.WriteMessage($"\n满布模式: 布置了 {count} 根斜拉杆"); return count; } // 布置单个网格单元的四条边 private int PlaceCellEdges(int row, int col, BlockTableRecord btr, BlockTable bt, HashSet<string> placedEdges, Database db, Transaction tr, Editor ed, ref int processed, int totalEdges, ref int lastReported) { int count = 0; // 上边 var topEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == row && e.ColIndex == col); if (topEdge != null) { count += PlaceSingleBar(topEdge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } // 下边 var bottomEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == row + 1 && e.ColIndex == col); if (bottomEdge != null) { count += PlaceSingleBar(bottomEdge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } // 左边 var leftEdge = _grid.VerticalEdges .FirstOrDefault(e => e.ColIndex == col && e.RowIndex == row); if (leftEdge != null) { count += PlaceSingleBar(leftEdge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } // 右边 var rightEdge = _grid.VerticalEdges .FirstOrDefault(e => e.ColIndex == col + 1 && e.RowIndex == row); if (rightEdge != null) { count += PlaceSingleBar(rightEdge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } return count; } // 布置单根斜拉杆(优化旋转角度计算) private int PlaceSingleBar(GridEdge edge, BlockTableRecord btr, BlockTable bt, HashSet<string> placedEdges, Database db, Transaction tr, Editor ed, ref int processed, int totalEdges, ref int lastReported) { // 进度报告 if (processed - lastReported > 1000) { ed.WriteMessage($"\n布置进度: {processed}/{totalEdges} ({processed * 100.0 / totalEdges:F1}%)"); lastReported = processed; if (CheckForUserCancel(ed)) { ed.WriteMessage("\n操作已取消"); return 0; } } processed++; // 生成边唯一标识 string edgeKey = $"{edge.StartPoint.X:F3},{edge.StartPoint.Y:F3}-{edge.EndPoint.X:F3},{edge.EndPoint.Y:F3}"; // 检查是否已布置 if (placedEdges.Contains(edgeKey)) return 0; placedEdges.Add(edgeKey); // 获取最接近的标准长度 double closestLength = GetClosestDiagonalLength(edge.Length); // 检查长度匹配精度 if (Math.Abs(closestLength - edge.Length) > Tolerance) { ed.WriteMessage($"\n警告: 线段长度 {edge.Length:F0}mm 与标准长度 {closestLength}mm 不匹配 (差值: {Math.Abs(closestLength - edge.Length):极1}mm)"); ed.WriteMessage($"\n线段坐标: ({edge.StartPoint.X:F0},{edge.StartPoint.Y:F0}) -> ({edge.EndPoint.X:F0},{edge.EndPoint.Y:F0})"); return 0; } string blockName = $"{DiagonalBarPrefix}{closestLength:0}mm"; // 计算中点位置 Point3d midPoint = new Point3d( (edge.StartPoint.X + edge.EndPoint.X) / 2, (edge.StartPoint.Y + edge.EndPoint.Y) / 2, 0); // 精确旋转角度设置(核心优化) double rotation = CalculateRotationAngle(edge); // 对外侧边进行偏移处理 if (edge.IsOuterEdge) { Vector3d offsetDirection = Vector3d.ZAxis; if (edge.IsHorizontal) { // 上边向上偏移,下边向下偏移 offsetDirection = edge.IsTopEdge ? new Vector3d(0, OffsetDistance, 0) : new Vector3d(0, -OffsetDistance, 0); } else { // 左边向左偏移,右边向右偏移 offsetDirection = edge.IsLeftEdge ? new Vector3d(-OffsetDistance, 0, 0) : new Vector3d(OffsetDistance, 0, 0); } midPoint += offsetDirection; } // 检查是否已存在相同斜拉杆 if (IsDiagonalAlreadyExists(blockName, midPoint, rotation)) { ed.WriteMessage($"\n跳过已存在斜拉杆: {blockName} 在 ({midPoint.X:F0},{midPoint.Y:F0})"); return 0; } // 动态加载块(如果未加载) if (!bt.Has(blockName)) { if (!LoadDiagonalBlock(db, closestLength, ed)) { return 0; } bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); } ObjectId blockId = bt[blockName]; // 创建斜杆图块引用 BlockReference br = new BlockReference(midPoint, blockId) { Layer = DiagonalBarLayer, Rotation = rotation }; // 添加到图形 btr.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); // 添加到缓存 AddToDiagonalCache(blockName, midPoint, rotation); // 添加详细日志 string positionDesc = GetPositionDescription(edge); ed.WriteMessage($"\n布置: {blockName} ({edge.Length:F0}mm)({midPoint.X:F0},{midPoint.Y:F0}), " + $"位置={positionDesc}, " + $"角度={rotation * 180 / Math.PI:F0}度"); return 1; } // 计算旋转角度(优化逻辑) private double CalculateRotationAngle(GridEdge edge) { // 计算方向向量 Vector3d direction = edge.EndPoint - edge.StartPoint; // 水平边 if (edge.IsHorizontal) { // 水平边:顶部0度,底部180度 return edge.IsTopEdge ? 0.0 : Math.PI; } // 垂直边 else { // 垂直边:左侧90度,右侧270度 return edge.IsLeftEdge ? Math.PI / 2 : 3 * Math.PI / 2; } } // 获取位置描述 private string GetPositionDescription(GridEdge edge) { if (edge.IsLeftEdge) return "左侧"; if (edge.IsRightEdge) return "右侧"; if (edge.IsTopEdge) return "上方"; if (edge.IsBottomEdge) return "下方"; return "内部"; } // 获取最接近的标准长度(支持组合匹配) private double GetClosestDiagonalLength(double segmentLength) { // 精确匹配优先 foreach (double len in DiagonalBarLengths) { if (Math.Abs(len - segmentLength) < Tolerance) return len; } // 尝试组合匹配(如900=600+300) if (segmentLength > DiagonalBarLengths.Min()) { foreach (double len1 in DiagonalBarLengths) { double remaining = segmentLength - len1; if (remaining <= 0) continue; foreach (double len2 in DiagonalBarLengths) { if (Math.Abs(remaining - len2) < Tolerance) { // 返回较大的标准长度(主杆) return Math.Max(len1, len2); } } } } // 找不到精确匹配则返回最接近的 return DiagonalBarLengths .OrderBy(len => Math.Abs(len - segmentLength)) .First(); } #endregion #region 斜拉杆翻转功能 [CommandMethod("FlipDiagonals", "FD", CommandFlags.Modal)] public void FlipDiagonals() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { // 提示用户选择斜拉杆 PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\n选择要翻转的斜拉杆 (框选): "; pso.AllowSubSelections = true; pso.SingleOnly = false; pso.RejectObjectsFromNonCurrentSpace = true; // 设置图层过滤器 TypedValue[] filterList = { new TypedValue((int)DxfCode.LayerName, DiagonalBarLayer) }; SelectionFilter filter = new SelectionFilter(filterList); PromptSelectionResult selResult = ed.GetSelection(pso, filter); if (selResult.Status != PromptStatus.OK) return; int flipCount = 0; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); foreach (SelectedObject selObj in selResult.Value) { BlockReference br = tr.GetObject(selObj.ObjectId, OpenMode.ForWrite) as BlockReference; if (br != null && br.Layer == DiagonalBarLayer) { // 获取原始方向 string originalDirection = GetDiagonalDirection(br.Rotation); // 计算翻转角度(180度) double newRotation = br.Rotation + Math.PI; // 角度归一化到0-2π范围 if (newRotation > 2 * Math.PI) newRotation -= 2 * Math.PI; // 获取新方向 string newDirection = GetDiagonalDirection(newRotation); // 应用新角度 br.Rotation = newRotation; flipCount++; // 更新日志 ed.WriteMessage($"\n翻转: {originalDirection}→{newDirection} " + $"({br.Rotation * 180 / Math.PI:F0}°→{newRotation * 180 / Math.PI:F0}°)"); } } tr.Commit(); } ed.WriteMessage($"\n成功翻转 {flipCount} 根斜拉杆"); } catch (System.Exception ex) { ed.WriteMessage($"\n翻转错误: {ex.Message}"); } } // 获取斜拉杆方向描述 private string GetDiagonalDirection(double rotation) { double degrees = rotation * 180 / Math.PI; // 简化到0-360范围 degrees %= 360; if (degrees < 0) degrees += 360; // 方向分类 if (degrees >= 315 || degrees < 45) return "上"; if (degrees >= 45 && degrees < 135) return "右"; if (degrees >= 135 && degrees < 225) return "下"; return "左"; } #endregion #region 斜拉杆缓存管理 // 构建现有斜拉杆缓存 private void BuildExistingDiagonalCache(Database db) { _existingDiagonalCache.Clear(); using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead); foreach (ObjectId objId in btr) { BlockReference br = tr.GetObject(objId, OpenMode.ForRead) as BlockReference; if (br != null && br.Layer == DiagonalBarLayer) { string blockName = br.BlockName; Point3d roundedPos = RoundPoint(br.Position); double roundedAngle = Math.Round(br.Rotation, 4); AddToDiagonalCache(blockName, roundedPos, roundedAngle); } } tr.Commit(); } } // 添加斜拉杆到缓存 private void AddToDiagonalCache(string blockName, Point3d position, double angle) { string key = $"{position.X:F3},{position.Y:F3},{angle:F4}"; if (!_existingDiagonalCache.ContainsKey(blockName)) { _existingDiagonalCache[blockName] = new HashSet<string>(); } _existingDiagonalCache[blockName].Add(key); } // 检查斜拉杆是否已存在 private bool IsDiagonalAlreadyExists(string blockName, Point3d position, double angle) { Point3d roundedPos = RoundPoint(position); double roundedAngle = Math.Round(angle, 4); string key = $"{roundedPos.X:F3},{roundedPos.Y:F3},{roundedAngle:F4}"; return _existingDiagonalCache.Contains极(blockName) && _existingDiagonalCache[blockName].Contains(key); } // 四舍五入点坐标 private Point3d RoundPoint(Point3d point, double tolerance = Tolerance) { double roundFactor = 1.0 / tolerance; return new Point3d( Math.Round(point.X * roundFactor) / roundFactor, Math.Round(point.Y * roundFactor) / roundFactor, Math.Round(point.Z * roundFactor) / roundFactor); } #endregion #region 辅助方法 // 创建图层(如果不存在) private void CreateLayerIfNotExists(Database db, string layerName, int colorIndex) { using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); if (!lt.Has(layerName)) { lt.UpgradeOpen(); LayerTableRecord ltr = new LayerTableRecord { Name = layerName, Color = Color.FromColorIndex(ColorMethod.ByAci, (short)colorIndex) }; lt.Add(ltr); tr.AddNewlyCreatedDBObject(ltr, true); } tr.Commit(); } } // 确保图层可见 private void CheckLayerState(Database db, string layerName) { using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); if (lt.Has(layerName)) { ObjectId layerId = lt[layerName]; LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(layerId, OpenMode.ForRead); if (ltr.IsFrozen || ltr.IsOff) { ltr.UpgradeOpen(); ltr.IsFrozen = false; ltr.IsOff = false; } } tr.Commit(); } } // 获取布置模式 private int GetDiagonalMode(Editor ed) { PromptKeywordOptions pko = new PromptKeywordOptions("\n选择斜拉杆布置模式: "); pko.Keywords.Add("1", "1", "1. 隔一布一"); pko.Keywords.Add("2", "2", "2. 隔二布一"); pko.Keywords.Add("3", "3", "3. 隔三布一"); pko.Keywords.Add("4", "4", "4. 满布"); pko.AllowNone = false; pko.AppendKeywordsToMessage = true; PromptResult pr = ed.GetKeywords(pko); return pr.Status == PromptStatus.OK ? int.Parse(pr.StringResult) : 0; } // 加载斜拉杆块定义 private void LoadDiagonalBlockDefinitions(Database db, Editor ed) { using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); string blockDir = GetBlockDirectory(); foreach (double len in DiagonalBarLengths) { string blockName = $"{DiagonalBarPrefix}{len:0}mm"; if (bt.Has(blockName)) continue; LoadDiagonalBlock(db, len, ed); } tr.Commit(); } } // 加载单个斜拉杆块 private bool LoadDiagonalBlock(Database db, double length, Editor ed) { string blockName = $"{DiagonalBarPrefix}{length:0}mm"; string blockPath = GetBlockFilePath(length); if (string.IsNullOrEmpty(blockPath)) { ed.WriteMessage($"\n斜拉杆块文件未找到: {blockName}"); return false; } try { using (Database sourceDb = new Database(false, true)) { sourceDb.ReadDwgFile(blockPath, FileOpenMode.OpenForReadAndAllShare, false, null); sourceDb.CloseInput(true); using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite); if (!bt.Has(blockName)) { db.Insert(blockName, sourceDb, true); ed.WriteMessage($"\n已加载斜拉杆块: {blockName}"); } tr.Commit(); } } return true; } catch (System.Exception ex) { ed.WriteMessage($"\n加载块 {blockName} 时出错: {ex.Message}"); return false; } } // 获取块文件目录 private string GetBlockDirectory() { string scaffoldBlocksDir = Path.Combine(_pluginDirectory, BlockDirectoryName); if (!Directory.Exists(scaffoldBlocksDir)) { try { Directory.CreateDirectory(scaffoldBlocksDir); } catch { return _pluginDirectory; } } return scaffoldBlocksDir; } // 获取块文件路径 private string GetBlockFilePath(double length) { string blockName = $"{DiagonalBarPrefix}{length:0}mm"; string blockDir = GetBlockDirectory(); string[] extensions = { ".dwg", ".DWG", ".dx极", ".DXF" }; foreach (string ext in extensions) { string path = Path.Combine(blockDir, $"{blockName}{ext}"); if (File.Exists(path)) return path; } return null; } // 用户取消检查 private bool CheckForUserCancel(Editor ed) { try { PromptResult result = ed.GetString("\n按ESC取消操作 [按回车继续]"); return result.Status == PromptStatus.Cancel; } catch { return false; } } #endregion } } CS0103当前上下文中不存在名称DiagonalBarLayer CS0103当前上下文中不存在名称DiagonalBarLayer CS0103当前上下文中不存在名称“sel极s” CS0103当前上下文中不存在名称“极” CS0103当前上下文中不存在名称“DiagonalBarLayer” CS0103当前上下文中不存在名称“DiagonalBarLayer CS1503参数1:无法从“System.Collections.Generic.List<Autodesk.AutoCAD.Geometry.Point3d>"转换为“System.Collections.Generic.List<极3d>" CS0246未能找到类型或命名空间名“极3d”(是否缺少using 指令或程序集引用?) CS0103当前上下文中不存在名称极 CS0103当前上下文中不存在名称极 CS1002应输入; CS1061“DiagonalBarPlacer.GnidStructure"未包含”Row极Count"的定义,并且找不到可接受第一个"DiagonalBarPlacer.GridStructure"“类型参数的可访问扩展方法"Row极Count"(是否缺少using指令或程序集引用?) CS0103当前上下文中不存在名称count极 CS0103当前上下文中不存在名称DiagonalBarLayer" CS0103当前上下文中不存在名称“DiagonalBarLayer” CS0103当前上下文中不存在名称“DiagonalBarLayer CS0103当前上下文中不存在名称DiagonalBarLayer CS1061“Dictionary<string, HashSet<string>>"未包含”Contains极”的定义,并且找不到可接受第一个"Dictonary<string, HashSet<string>>“类型参数的可访问扩展方法"Contains极”(是否缺少using指令或程序集引用?)
07-11
using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.Colors; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; namespace ScaffoldAutomation { public class DiagonalBarPlacer { // 配置常量 private const string DiagonalBarLayer = “斜拉杆”; private const string DiagonalBarPrefix = “ScaffoldPolexie水平斜拉杆”; private极 const string BlockDirectoryName = “ScaffoldBlocks”; private const string AxisLayer = “盘扣轴网”; // 标准斜拉杆长度(毫米) private static readonly double[] DiagonalBarLengths = { 600, 900, 1200, 1500, 1800 }; // 缓存已存在的斜拉杆 private readonly Dictionary<string, HashSet<string>> _existingDiagonalCache = new Dictionary<string, HashSet<string>>(); // 插件目录路径 private readonly string _pluginDirectory; // 网格数据结构 private GridStructure _grid; // 容差值(毫米) private const double Tolerance = 1.0; // 斜拉杆偏移距离(毫米) private const double OffsetDistance = 1.0; public DiagonalBarPlacer() { _pluginDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } [CommandMethod("BuildDiagonal", "BD", CommandFlags.Modal)] public void BuildDiagonal() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { // 创建斜杆图层 CreateLayerIfNotExists(db, DiagonalBarLayer, 4); // 青色 CheckLayerState(db, DiagonalBarLayer); // 步骤1:选择布置模式 int mode = GetDiagonalMode(ed); if (mode == 0) return; // 步骤2:选择轴网线段 PromptSelectionOptions selOpts = new PromptSelectionOptions(); selOpts.MessageForAdding = "\n选择盘扣轴网线段: "; PromptSelectionResult selResult = ed.GetSelection(selOpts); if (selResult.Status != PromptStatus.OK) return; // 加载斜拉杆块定义 LoadDiagonalBlockDefinitions(db, ed); // 构建现有斜拉杆缓存 BuildExistingDiagonalCache(db); using (Transaction tr = db.TransactionManager.StartTransaction()) { // 处理轴网并生成网格结构 if (!ProcessAxisLines(db, selResult, tr, ed)) { ed.WriteMessage("\极无法生成有效的网格结构"); return; } // 布置斜拉杆 int diagonalCount = PlaceDiagonalBars(db, tr, mode, ed); tr.Commit(); ed.WriteMessage($"\n成功布置 {diagonalCount} 根斜拉杆"); if (diagonalCount > 0) { Application.ShowAlertDialog($"已布置 {diagonalCount} 根斜拉杆!"); } } } catch (System.Exception ex) { ed.WriteMessage($"\n错误: {ex.Message}\n{ex.StackTrace}"); } } #region 新增自动检查功能 // 删除田字型框内及周边的斜拉杆 private int DeleteBarsInPatternTwoArea(Database db, Transaction tr, int row, int col, Editor ed) { int deletedCount = 0; BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); // 定义田字型区域 (3x3单元) int startRow = Math.Max(0, row - 1); int endRow = Math.Min(_grid.RowCount - 1, row + 1); int startCol = Math.Max(0, col - 1); int endCol = Math.Min(_grid.ColumnCount - 1, col + 1); // 收集要删除的边 var edgesToDelete = new List<GridEdge>(); // 收集水平边 for (int r = startRow; r <= endRow; r++) { for (int c = startCol; c <= endCol; c++) { // 上边 var topEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r && e.ColIndex == c); if (topEdge != null) edgesToDelete.Add(topEdge); // 下边 var bottomEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r + 1 && e.ColIndex == c); if (bottomEdge != null) edgesToDelete.Add(bottomEdge); // 左边 var leftEdge = _grid.VerticalEdges .FirstOrDefault(e => e.ColIndex == c && e.RowIndex == r); if (leftEdge != null) edgesToDelete.Add(leftEdge); // 右边 var rightEdge = _grid.VerticalEdges .FirstOrDefault(e => e.ColIndex == c + 1 && e.RowIndex == r); if (rightEdge != null) edgesToDelete.Add(rightEdge); } } // 删除中间跨的水平杆 for (int r = startRow; r <= endRow; r++) { // 中间列 int midCol = col + 1; if (midCol < _grid.ColumnCount) { var midEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r && e.ColIndex == midCol); if (midEdge != null) edgesToDelete.Add(midEdge); } } // 删除这些边上的斜拉杆 foreach (var edge in edgesToDelete) { Point3d midPoint = new Point3d( (edge.StartPoint.X + edge.EndPoint.X) / 2, (edge.StartPoint.Y + edge.EndPoint.Y) / 2, 0); // 查找并删除该位置的斜拉杆 foreach (ObjectId id in btr) { BlockReference br = tr.GetObject(id, OpenMode.ForRead) as BlockReference; if (br != null && br.Layer == DiagonalBarLayer && br.Position.DistanceTo(midPoint) < Tolerance) { br.UpgradeOpen(); br.Erase(); deletedCount++; ed.WriteMessage($"\n删除斜拉杆: ({midPoint.X:F0},{midPoint.Y:F0})"); break; } } } return deletedCount; } // 删除井字型框内及周边的斜拉杆 private int DeleteBarsInPatternThreeArea(Database db, Transaction tr, int row, int col, Editor ed) { int deletedCount = 0; BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpace极, OpenMode.ForWrite); // 定义井字型区域 (4x4单元) int startRow = Math.Max(0, row - 1); int endRow = Math.Min(_grid.RowCount - 1, row + 2); int startCol = Math.Max(0, col - 1); int endCol = Math.Min(_grid.ColumnCount - 1, col + 2); // 收集要删除的边 var edgesToDelete = new List<GridEdge>(); // 收集水平边 for (int r = startRow; r <= endRow; r++) { for (int c = startCol; c <= endCol; c++) { // 上边 var topEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r && e.ColIndex == c); if (topEdge != null) edgesToDelete.Add(topEdge); // 下边 var bottomEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r + 1 && e.ColIndex == c); if (bottomEdge != null) edgesToDelete.Add(bottomEdge); // 左边 var leftEdge = _grid.VerticalEdges .FirstOrDefault(e => e.ColIndex == c && e.RowIndex == r); if (leftEdge != null) edgesToDelete.Add(leftEdge); // 右边 var rightEdge = _grid.VerticalEdges .FirstOrDefault(e => e.ColIndex == c + 1 && e.RowIndex == r); if (rightEdge != null) edgesToDelete.Add(rightEdge); } } // 删除中间跨的水平杆 for (int r = startRow; r <= endRow; r++) { // 中间列1 int midCol1 = col + 1; if (midCol1 < _grid.ColumnCount) { var midEdge1 = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r && e.ColIndex == mid极1); if (midEdge1 != null) edgesToDelete.Add(midEdge1); } // 中间列2 int midCol2 = col + 2; if (midCol2 < _grid.ColumnCount) { var midEdge2 = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == r && e.ColIndex == midCol2); if (midEdge2 != null) edgesToDelete.Add(midEdge2); } } // 删除这些边上的斜拉杆 foreach (var edge in edgesToDelete) { Point3d midPoint = new Point3d( (edge.StartPoint.X + edge.EndPoint.X) / 2, (edge.StartPoint.Y + edge.EndPoint.Y) / 2, 0); // 查找并删除该位置的斜拉杆 foreach (ObjectId id in btr) { BlockReference br = tr.GetObject(id, OpenMode.ForRead) as BlockReference; if (br != null && br.Layer == DiagonalBarLayer && br.Position.DistanceTo(midPoint) < Tolerance) { br.UpgradeOpen(); br.Erase(); deletedCount++; ed.WriteMessage($"\n删除斜拉杆: ({midPoint.X:F0},{midPoint.Y:F0})"); break; } } } return deletedCount; } #endregion #region 网格数据结构 // 网格结构 private class GridStructure { public List<double> XCoordinates { get; set; } = new List<double>(); public List<double> YCoordinates { get; set; } = new List<double>(); public List<GridEdge> HorizontalEdges { get; } = new List<GridEdge>(); public List<GridEdge> VerticalEdges { get; } = new List<GridEdge>(); public int RowCount => YCoordinates.Count - 1; public int ColumnCount => XCoordinates.Count - 1; } // 网格边 private class GridEdge { public Point3d StartPoint { get; set; } public Point3d EndPoint { get; set; } public double Length { get; set; } public int RowIndex { get; set; } // 行索引(水平边) public int ColIndex { get; set; } // 列索引(垂直边) public bool IsHorizontal { get; set; } public bool IsOuterEdge { get; set; } // 是否是最外侧极 public bool IsTopEdge { get; set; } // 是否是顶部边 public bool IsBottomEdge { get; set; } // 是否是底部边 public bool IsLeftEdge { get; set; } // 是否是左侧边 public bool IsRightEdge { get; set; } // 是否是右侧边 } // 点比较器(用于去重) private class Point3dComparer : IEqualityComparer<Point3d> { private readonly double _tolerance; public Point3dComparer(double tolerance) => _tolerance = tolerance; public bool Equals(Point3d p1, Point3d p2) => p1.DistanceTo(p2) <= _tolerance; public int GetHashCode(Point3d p) => (Math.Round(p.X / _tolerance), Math.Round(p.Y / _tolerance), Math.Round(p.Z / _tolerance)).GetHashCode(); } #endregion #region 轴网处理 // 处理轴网线段 private bool ProcessAxisLines(Database db, PromptSelectionResult selResult, Transaction tr, Editor ed) { List<Line> axisLines = new List<Line>(); // 收集轴网线段 foreach (ObjectId objId in selResult.Value.GetObjectIds()) { Entity ent = tr.GetObject(objId, OpenMode.ForRead) as Entity; if (ent != null && ent.Layer == AxisLayer && ent is Line line) { axisLines.Add(line); } } if (axisLines.Count == 0) { ed.WriteMessage("\n未选择任何轴网线段"); return false; } ed.WriteMessage($"\n找到 {axisLines.Count} 条轴网线段"); // 计算所有网格交点 List<Point3d> intersections = CalculateIntersections(axisLines, ed); if (intersections.Count == 0) { ed.WriteMessage("\n未找到网格交点"); return false; } // 构建网格结构 _grid = BuildGridStructure(intersections, axisLines, ed); if (_grid == null || _grid.XCoordinates.Count < 2 || _grid.YCoordinates.Count < 2) { ed.WriteMessage("\n无法构建有效的网格结构"); return false; } ed.WriteMessage($"\n网格结构: {_grid.ColumnCount}列 x {_grid.RowCount}行"); ed.WriteMessage($"\n水平边数量: {_grid.HorizontalEdges.Count}, 垂直边数量: {_grid.VerticalEdges.Count}"); return true; } // 计算所有网格交点(优化性能) private List<Point3d> CalculateIntersections(List<Line> axisLines, Editor ed) { var intersections = new ConcurrentDictionary<Point3d, bool>(new Point3dComparer(Tolerance)); long totalIntersections = 0; // 使用空间分区提高性能 var lineBuckets = new Dictionary<(int, int), List<Line>>(); const double gridSize = 5000.0; // 网格大小5米 // 并行处理线段分配 Parallel.ForEach(axisLines, line => { Point3d min = new Point3d( Math.Min(line.StartPoint.X, line.EndPoint.X), Math.Min(line.StartPoint.Y, line.EndPoint.Y), 0); Point3d max = new Point3d( Math.Max(line.StartPoint.X, line.EndPoint.X), Math.Max(line.StartPoint.Y, line.EndPoint.Y), 0); int minX = (int)(min.X / gridSize); int minY = (int)(min.Y / gridSize); int maxX = (int)(max.X / gridSize); int maxY = (int)(max.Y / gridSize); for (int x = minX; x <= maxX; x++) { for (int y = minY; y <= maxY; y++) { var key = (x, y); lock (lineBuckets) { if (!lineBuckets.ContainsKey(key)) lineBuckets[key] = new List<Line>(); lineBuckets[key].Add(line); } } } }); // 并行处理交点计算 var keys = lineBuckets.Keys.ToArray(); Parallel.For(0, keys.Length, i => { var bucket = lineBuckets[keys[i]]; for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { var neighborKey = (keys[i].Item1 + dx, keys[i].Item2 + dy); if (!lineBuckets.ContainsKey(neighborKey)) continue; var neighborBucket = lineBuckets[neighborKey]; for (int a = 0; a < bucket.Count; a++) { for (int b = a + 1; b < neighborBucket.Count; b++) { Point3dCollection pts = new Point3dCollection(); bucket[a].IntersectWith( neighborBucket[b], Intersect.ExtendBoth, pts, IntPtr.Zero, IntPtr.Zero); foreach (Point3d pt in pts) { intersections[RoundPoint(pt, Tolerance)] = true; Interlocked.Increment(ref totalIntersections); } } } } } }); ed.WriteMessage($"\n找到 {intersections.Count} 个有效网格交点(总交点: {totalIntersections})"); return intersections.Keys.ToList(); } // 构建网格结构 private GridStructure BuildGridStructure(List<Point3d> intersections, List<Line> axisLines, Editor ed) { var grid = new GridStructure(); // 分离X和Y坐标(带容差) var xCoords = intersections .Select(p => Math.Round(p.X / Tolerance) * Tolerance) .Distinct() .OrderBy(x => x) .ToList(); var yCoords = intersections .Select(p => Math.Round(p.Y / Tolerance) * Tolerance) .Distinct() .OrderByDescending(y => y) // Y坐标从大到小排序(顶部为0) .ToList(); grid.XCoordinates = x极Coords; grid.YCoordinates = yCoords; // 创建水平边 for (int row = 0; row < yCoords.Count; row++) { for (int col = 0; col < xCoords.Count - 1; col++) { Point3d start = new Point3d(xCoords[col], yCoords[row], 0); Point3d end = new Point3d(xCoords[col + 1], yCoords[row], 0); // 检查是否为有效线段 if (IsValidSegment(axisLines, start, end, Tolerance)) { grid.HorizontalEdges.Add(new GridEdge { StartPoint = start, EndPoint = end, Length = start.DistanceTo(end), RowIndex = row, ColIndex = col, IsHorizontal = true, IsOuterEdge = (row == 0 || row == yCoords.Count - 1), IsTopEdge = (row == 0), IsBottomEdge = (row == yCoords.Count - 1) }); } } } // 创建垂直边(处理分段线段) for (int col = 0; col < xCoords.Count; col++) { double x = xCoords[col]; // 收集该列上的所有交点 var colPoints = intersections .Where(p => Math.Abs(p.X - x) < Tolerance) .OrderByDescending(p => p.Y) .ToList(); // 处理相邻交点间的线段 for (int i = 0; i < colPoints.Count - 1; i++) { Point3d start = colPoints[i]; Point3d end = colPoints[i + 1]; double segmentLength = start.DistanceTo(end); // 查找实际存在的线段 Line actualSegment = FindActualSegment(axisLines, start, end, Tolerance); if (actualSegment != null) { grid.VerticalEdges.Add(new GridEdge { StartPoint = start, EndPoint = end, Length = actualSegment.Length, // 使用实际线段长度 RowIndex = i, ColIndex = col, IsHorizontal = false, IsOuterEdge = (col == 0 || col == xCoords.Count - 1), IsLeftEdge = (col == 0), IsRightEdge = (col == xCoords.Count - 1) }); } } } return grid; } // 查找实际存在的线段 private Line FindActualSegment(List<Line> axisLines, Point3d start, Point3d end, double tolerance) { foreach (Line line in axisLines) { if (IsPointOnLine(line, start, tolerance) && IsPointOnLine(line, end, tolerance) && Math.Abs(line.Length - start.DistanceTo(end)) < tolerance) { return line; } } return null; } // 检查点是否在直线上(带容差) private bool IsPointOnLine(Line line, Point3d point, double tolerance) { // 检查点是否接近起点或终点 if (point.DistanceTo(line.StartPoint) <= tolerance || point.DistanceTo(line.EndPoint) <= tolerance) return true; // 计算点到直线的距离 Vector3d lineVec = line.EndPoint - line.StartPoint; Vector3d pointVec = point - line.StartPoint; // 检查点是否在线段范围内 double dotProduct = lineVec.DotProduct(pointVec); if (dotProduct < 0 || dotProduct > lineVec.LengthSqrd) return false; // 计算垂直距离 double distance = Math.Abs(lineVec.CrossProduct(pointVec).Length / lineVec.Length); return distance <= tolerance; } // 检查是否为有效线段(带容差) private bool IsValidSegment(List<Line> axisLines, Point3极 start, Point3d end, double tolerance) { foreach (Line line in axisLines) { if (IsPointOnLine(line, start, tolerance) && IsPointOnLine(line, end, tolerance)) { return true; } } return false; } #endregion #region 斜拉杆布置核心逻辑(按模式实现) // 布置斜拉杆(根据不同的布置模式) private int PlaceDiagonalBars(Database db, Transaction tr, int mode, Editor ed) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); if (_grid == null || (_grid.HorizontalEdges.Count == 0 && _grid.VerticalEdges.Count == 0)) { ed.WriteMessage("\n没有可用的网格边"); return 0; } int diagonalCount = 0; var placedEdges = new HashSet<string>(); // 避免重复布置 // 添加整体进度报告 int totalEdges = _grid.HorizontalEdges.Count + _grid.VerticalEdges.Count; int processed = 0; int lastReported = 0; switch (mode) { case 1: // 隔一布一 diagonalCount += PlacePatternOne(db, tr, btr, bt, placedEdges, ed, ref processed, totalEdges, ref lastReported); break; case 2: // 隔二布一 diagonalCount += PlacePatternTwo(db, tr, btr, bt, placedEdges, ed, ref processed, totalEdges, ref lastReported); break; case 3: // 隔三布一 diagonalCount += PlacePatternThree(db, tr, btr, bt, placedEdges, ed, ref processed, totalEdges, ref lastReported); break; case 4: // 满布 diagonalCount += PlaceFullPattern(db, tr, btr, bt, placedEdges, ed, ref processed, totalEdges, ref lastReported); break; } return diagonalCount; } // 模式1: 隔一布一 private int PlacePatternOne(Database db, Transaction tr, BlockTableRecord btr, BlockTable bt, HashSet<string> placedEdges, Editor ed, ref int processed, int totalEdges, ref int lastReported) { int count = 0; for (int row = 0; row < _grid.RowCount; row++) { // 每10行报告一次进度 if (row % 10 == 0) { ed.WriteMessage($"\n处理中: 行 {row}/{_grid.RowCount} ({(double)row / _grid.RowCount:P0})"); if (CheckForUserCancel(ed)) { ed.WriteMessage("\n操作已取消"); return count; } } for (int col = 0; col < _grid.ColumnCount; col++) { // 隔一布一:行和列索引都是偶数的单元 if (row % 2 == 0 && col % 2 == 0) { count += PlaceCellEdges(row, col, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } ed.WriteMessage($"\n隔一布一模式: 布置了 {count} 根斜拉杆"); return count; } // 模式2: 隔二布一(添加自动检查功能) private int PlacePatternTwo(Database db, Transaction tr, BlockTableRecord btr, BlockTable bt, HashSet<string> placedEdges, Editor ed, ref int processed, int totalEdges, ref int lastReported) { int count = 0; int deletedCount = 0; // 单元布置:只布置左上角单元(每3行3列) for (int row = 0; row < _grid.RowCount; row += 3) { for (int col = 0; col < _grid.ColumnCount; col += 3) { // 删除田字型区域内的斜拉杆 deletedCount += DeleteBarsInPatternTwoArea(db, tr, row, col, ed); // 布置单元四边 count += PlaceCellEdges(row, col, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } // 布置中间垂直边(第1列) for (int col = 1; col < _grid.ColumnCount; col += 3) { for (int row = 0; row < _grid.RowCount; row++) { // 跳过中间行(行索引为1 mod 3) if (row % 3 == 1) continue; var edges = _grid.VerticalEdges .Where(e => e.ColIndex == col && e.RowIndex == row) .ToList(); foreach (var edge in edges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } // 布置中间水平边(第1行) for (int row = 1; row < _grid.RowCount; row += 3) { for (int col = 0; col < _grid.ColumnCount; col++) { // 跳过中间列(列索引为1 mod 3) if (col % 3 == 1) continue; var edges = _grid.HorizontalEdges .Where(e => e.RowIndex == row && e.ColIndex == col) .ToList(); foreach (var edge in edges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } ed.WriteMessage($"\n隔二布一模式: 删除了 {deletedCount} 根斜拉杆,布置了 {count} 根斜拉杆"); return count; } // 模式3: 隔三布一(添加自动检查功能) private int PlacePatternThree(Database db, Transaction tr, BlockTableRecord btr, BlockTable bt, HashSet<string> placedEdges, Editor ed, ref int processed, int totalEd极, ref int lastReported) { int count = 0; int deletedCount = 0; // 单元布置:只布置左上角单元(每4行4列) for (int row = 0; row < _grid.RowCount; row += 4) { for (int col = 0; col < _grid.ColumnCount; col += 4) { // 删除井字型区域内的斜拉杆 deletedCount += DeleteBarsInPatternThreeArea(db, tr, row, col, ed); // 布置单元四边 count += PlaceCellEdges(row, col, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } // 布置中间垂直边(第1列和第2列) for (int col = 1; col < _grid.ColumnCount; col += 4) // 每4列的第1列 { for (int row = 0; row < _grid.RowCount; row++) { // 跳过中间行(行索引为1或2 mod 4) if (row % 4 == 1 || row % 4 == 2) continue; var edges = _grid.VerticalEdges .Where(e => e.ColIndex == col && e.RowIndex == row) .ToList(); foreach (var edge in edges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } for (int col = 2; col < _grid.ColumnCount; col += 4) // 每4列的第2列 { for (int row = 0; row < _grid.RowCount; row++) { // 跳过中间行(行索引为1或2 mod 4) if (row % 4 == 1 || row % 4 == 2) continue; var edges = _grid.VerticalEdges .Where(e => e.ColIndex == col && e.RowIndex == row) .ToList(); foreach (var edge in edges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } // 布置中间水平边(第1行和第2行) for (int row = 1; row < _grid.RowCount; row极 += 4) // 每4行的第1行 { for (int col = 0; col < _grid.ColumnCount; col++) { // 跳过中间列(列索引为1或2 mod 4) if (col % 4 == 1 || col % 4 == 2) continue; var edges = _极.HorizontalEdges .Where(e => e.RowIndex == row && e.ColIndex == col) .ToList(); foreach (var edge in edges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } for (int row = 2; row < _grid.RowCount; row += 4) // 每4行的第2行 { for (int col = 0; col < _grid.ColumnCount; col++) { // 跳过中间列(列索引为1或2 mod 4) if (col % 4 == 1 || col % 4 == 2) continue; var edges = _grid.HorizontalEdges .Where(e => e.RowIndex == row && e.ColIndex == col) .ToList(); foreach (var edge in edges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } } } ed.WriteMessage($"\n隔三布一模式: 删除了 {deletedCount} 根斜拉杆,布置了 {count} 根斜拉杆"); return count; } // 模式4: 满布 private int PlaceFullPattern(Database db, Transaction tr, BlockTableRecord btr, BlockTable bt, HashSet<string> placedEdges, Editor ed, ref int processed, int totalEdges, ref int lastReported) { int count = 0; // 布置所有水平边 foreach (GridEdge edge in _grid.HorizontalEdges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } // 布置所有垂直边 foreach (GridEdge edge in _grid.VerticalEdges) { count += PlaceSingleBar(edge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } ed.WriteMessage($"\n满布模式: 布置了 {count} 根斜拉杆"); return count; } // 布置单个网格单元的四条边 private int PlaceCellEdges(int row, int col, BlockTableRecord btr, BlockTable bt, HashSet<string> placedEdges, Database db, Transaction tr, Editor ed, ref int processed, int totalEdges, ref int lastReported) { int count = 0; // 上边 var topEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == row && e.ColIndex == col); if (topEdge != null) { count += PlaceSingleBar(topEdge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } // 下边 var bottomEdge = _grid.HorizontalEdges .FirstOrDefault(e => e.RowIndex == row + 1 && e.ColIndex == col); if (bottomEdge != null) { count += PlaceSingleBar(bottomEdge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } // 左边 var leftEdge = _grid.VerticalEdges .FirstOrDefault(e => e.ColIndex == col && e.RowIndex == row); if (leftEdge != null) { count += PlaceSingleBar(leftEdge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } // 右边 var rightEdge = _grid.VerticalEdges .FirstOrDefault(e => e.ColIndex == col + 1 && e.RowIndex == row); if (rightEdge != null) { count += PlaceSingleBar(rightEdge, btr, bt, placedEdges, db, tr, ed, ref processed, totalEdges, ref lastReported); } return count; } // 布置单根斜拉杆(优化旋转角度计算) private int PlaceSingleBar(GridEdge edge, BlockTableRecord btr, BlockTable bt, HashSet<string> placedEdges, Database db, Transaction tr, Editor ed, ref int processed, int totalEdges, ref int lastReported) { // 进度报告 if (processed - lastReported > 1000) { ed.WriteMessage($"\n布置进度: {processed}/{totalEdges} ({processed * 100.0 / totalEdges:F1}%)"); lastReported = processed; if (CheckForUserCancel(ed)) { ed.WriteMessage("\n操作已取消"); return 0; } } processed++; // 生成边唯一标识 string edgeKey = $"{edge.StartPoint.X:F3},{edge.StartPoint.Y:F3}-{edge.EndPoint.X:F3},{edge.EndPoint.Y:F3}"; // 检查是否已布置 if (placedEdges.Contains(edgeKey)) return 0; placedEdges.Add(edgeKey); // 获取最接近的标准长度 double closestLength = GetClosestDiagonalLength(edge.Length); // 检查长度匹配精度 if (Math.Abs(closestLength - edge.Length) > Tolerance) { ed.WriteMessage($"\n警告: 线段长度 {edge.Length:F0}mm 与标准长度 {closestLength}mm 不匹配 (差值: {Math.Abs(closestLength - edge.Length):F1}mm)"); ed.WriteMessage($"\n线段坐标: ({edge.StartPoint.X:F0},{edge.StartPoint.Y:F0}) -> ({edge.EndPoint.X:F0},{edge.EndPoint.Y:F0})"); return 0; } string blockName = $"{DiagonalBarPrefix}{closestLength:0}mm"; // 计算中点位置 Point3d midPoint = new Point3d( (edge.StartPoint.X + edge.EndPoint.X) / 2, (edge.StartPoint.Y + edge.EndPoint.Y) / 2, 0); // 精确旋转角度设置(核心优化) double rotation = CalculateRotationAngle(edge); // 对外侧边进行偏移处理 if (edge.IsOuterEdge) { Vector3d offsetDirection = Vector3d.ZAxis; if (edge.IsHorizontal) { // 上边向上偏移,下边向下偏移 offsetDirection = edge.IsTopEdge ? new Vector3d(0, OffsetDistance, 0) : new Vector3d(0, -OffsetDistance, 0); } else { // 左边向左偏移,右边向右偏移 offsetDirection = edge.IsLeftEdge ? new Vector3d(-OffsetDistance, 0, 0) : new Vector3d(OffsetDistance, 0, 0); } midPoint += offsetDirection; } // 检查是否已存在相同斜拉杆 if (IsDiagonalAlreadyExists(blockName, midPoint, rotation)) { ed.WriteMessage($"\n跳过已存在斜拉杆: {blockName} 在 ({midPoint.X:F0},{midPoint.Y:F0})"); return 0; } // 动态加载块(如果未加载) if (!bt.Has(blockName)) { if (!LoadDiagonalBlock(db, closestLength, ed)) { return 0; } bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); } ObjectId blockId = bt[blockName]; // 创建斜杆图块引用 BlockReference br = new BlockReference(midPoint, blockId) { Layer = DiagonalBarLayer, Rotation = rotation }; // 添加到图形 btr.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); // 添加到缓存 AddToDiagonalCache(blockName, midPoint, rotation); // 添加详细日志 string positionDesc = GetPositionDescription(edge); ed.WriteMessage($"\n布置: {blockName} ({edge.Length:F0}mm)({midPoint.X:F0},{midPoint.Y:F0}), " + $"位置={positionDesc}, " + $"角度={rotation * 180 / Math.PI:F0}度"); return 1; } // 计算旋转角度(优化逻辑) private double CalculateRotationAngle(GridEdge edge) { // 计算方向向量 Vector3d direction = edge.EndPoint - edge.StartPoint; // 水平边 if (edge.IsHorizontal) { // 水平边:顶部0度,底部180度 return edge.IsTopEdge ? 0.0 : Math.PI; } // 垂直边 else { // 垂直边:左侧90度,右侧270度 return edge.IsLeftEdge ? Math.PI / 2 : 3 * Math.PI / 2; } } // 获取位置描述 private string GetPositionDescription(GridEdge edge) { if (edge.IsLeftEdge) return "左侧"; if (edge.IsRightEdge) return "右侧"; if (edge.IsTopEdge) return "上方"; if (edge.IsBottomEdge) return "下方"; return "内部"; } // 获取最接近的标准长度(支持组合匹配) private double GetClosestDiagonalLength(double segmentLength) { // 精确匹配优先 foreach (double len in DiagonalBarLengths) { if (Math.Abs(len - segmentLength) < Tolerance) return len; } // 尝试组合匹配(如900=600+300) if (segmentLength > DiagonalBarLengths.Min()) { foreach (double len1 in DiagonalBarLengths) { double remaining = segmentLength - len1; if (remaining <= 0) continue; foreach (double len2 in DiagonalBarLengths) { if (Math.Abs(remaining - len2) < Tolerance) { // 返回较大的标准长度(主杆) return Math.Max(len1, len2); } } } } // 找不到精确匹配则返回最接近的 return DiagonalBarLengths .OrderBy(len => Math.Abs(len - segmentLength)) .First(); } #endregion #region 斜拉杆翻转功能 [CommandMethod("FlipDiagonals", "FD", CommandFlags.Modal)] public void FlipDiagonals() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { // 提示用户选择斜拉杆 PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\n选择要翻转的斜拉杆 (框选): "; pso.AllowSubSelections = true; pso.SingleOnly = false; pso.RejectObjectsFromNonCurrentSpace = true; // 设置图层过滤器 TypedValue[] filterList = { new TypedValue((int)DxfCode.LayerName, DiagonalBarLayer) }; SelectionFilter filter = new SelectionFilter(filterList); PromptSelectionResult selResult = ed.GetSelection(pso, filter); if (selResult.Status != PromptStatus.OK) return; int flipCount = 0; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); foreach (SelectedObject selObj in selResult.Value) { BlockReference br = tr.GetObject(selObj.ObjectId, OpenMode.ForWrite) as BlockReference; if (br != null && br.Layer == DiagonalBarLayer) { // 获取原始方向 string originalDirection = GetDiagonalDirection(br.Rotation); // 计算翻转角度(180度) double newRotation = br.Rotation + Math.PI; // 角度归一化到0-2π范围 if (newRotation > 2 * Math.PI) newRotation -= 2 * Math.PI; // 获取新方向 string newDirection = GetDiagonalDirection(newRotation); // 应用新角度 br.Rotation = newRotation; flipCount++; // 更新日志 ed.WriteMessage($"\n翻转: {originalDirection}→{newDirection} " + $"({br.Rotation * 180 / Math.PI:F0}°→{newRotation * 180 / Math.PI:F0}°)"); } } tr.Commit(); } ed.WriteMessage($"\n成功翻转 {flipCount} 根斜拉杆"); } catch (System.Exception ex) { ed.WriteMessage($"\n翻转错误: {ex.Message}"); } } // 获取斜拉杆方向描述 private string GetDiagonalDirection(double rotation) { double degrees = rotation * 180 / Math.PI; // 简化到0-360范围 degrees %= 360; if (degrees < 0) degrees += 360; // 方向分类 if (degrees >= 315 || degrees < 45) return "上"; if (degrees >= 45 && degrees < 135) return "右"; if (degrees >= 135 && degrees < 225) return "下"; return "左"; } #endregion #region 斜拉杆缓存管理 // 构建现有斜拉杆缓存 private void BuildExistingDiagonalCache(Database db) { _existingDiagonalCache.Clear(); using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead); foreach (ObjectId objId in btr) { BlockReference br = tr.GetObject(objId, OpenMode.ForRead) as BlockReference; if (br != null && br.Layer == DiagonalBarLayer) { string blockName = br.BlockName; Point3d roundedPos = RoundPoint(br.Position); double roundedAngle = Math.Round(br.Rotation, 4); AddToDiagonalCache(blockName, roundedPos, roundedAngle); } } tr.Commit(); } } // 添加斜拉杆到缓存 private void AddToDiagonalCache(string blockName, Point3d position, double angle) { string key = $"{position.X:F3},{position.Y:F3},{angle:F4}"; if (!_existingDiagonalCache.ContainsKey(blockName)) { _existingDiagonalCache[blockName] = new HashSet<string>(); } _existingDiagonalCache[blockName].Add(key); } // 检查斜拉杆是否已存在 private bool IsDiagonalAlreadyExists(string blockName, Point3d position, double angle) { Point3d roundedPos = RoundPoint(position); double roundedAngle = Math.Round(angle, 4); string key = $"{roundedPos.X:F3},{rounded极.Y:F3},{roundedAngle:F4}"; return _existingDiagonalCache.ContainsKey(blockName) && _existingDiagonalCache[blockName].Contains(key); } // 四舍五入点坐标 private Point3d RoundPoint(Point3d point, double tolerance = Tolerance) { double roundFactor = 1.0 / tolerance; return new Point3d( Math.Round(point.X * roundFactor) / roundFactor, Math.Round(point.Y * roundFactor) / roundFactor, Math.Round(point.Z * roundFactor) / roundFactor); } #endregion #region 辅助方法 // 创建图层(如果不存在) private void CreateLayerIfNotExists(Database db, string layerName, int colorIndex) { using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); if (!lt.Has(layerName)) { lt.UpgradeOpen(); LayerTableRecord ltr = new LayerTableRecord { Name = layerName, Color = Color.FromColorIndex(ColorMethod.ByAci, (short)colorIndex) }; lt.Add(ltr); tr.AddNewlyCreatedDBObject(ltr, true); } tr.Commit(); } } // 确保图层可见 private void CheckLayerState(Database db, string layerName) { using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); if (lt.Has(layerName)) { ObjectId layerId = lt[layerName]; LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(layerId, OpenMode.ForRead); if (ltr.IsFrozen || ltr.IsOff) { ltr.UpgradeOpen(); ltr.IsFrozen = false; ltr.IsOff = false; } } tr.Commit(); } } // 获取布置模式 private int GetDiagonalMode(Editor ed) { PromptKeywordOptions pko = new PromptKeywordOptions("\n选择斜拉杆布置模式: "); pko.Keywords.Add("1", "1", "1. 隔一布一"); pko.Keywords.Add("2", "2", "2. 隔二布一"); pko.Keywords.Add("3", "3", "3. 隔三布一"); pko.Keywords.Add("4", "4", "4. 满布"); pko.AllowNone = false; pko.AppendKeywordsToMessage = true; PromptResult pr = ed.GetKeywords(pko); return pr.Status == PromptStatus.OK ? int.Parse(pr.StringResult) : 0; } // 加载斜拉杆块定义 private void LoadDiagonalBlockDefinitions(Database db, Editor ed) { using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); string blockDir = GetBlockDirectory(); foreach (double len in DiagonalBarLengths) { string blockName = $"{DiagonalBarPrefix}{len:0}mm"; if (bt.Has(blockName)) continue; LoadDiagonalBlock(db, len, ed); } tr.Commit(); } } // 加载单个斜拉杆块 private bool LoadDiagonalBlock(Database db, double length, Editor ed) { string blockName = $"{DiagonalBarPrefix}{length:0}mm"; string blockPath = GetBlockFilePath(length); if (string.IsNullOrEmpty(blockPath)) { ed.WriteMessage($"\n斜拉杆块文件未找到: {blockName}"); return false; } try { using (Database sourceDb = new Database(false, true)) { sourceDb.ReadDwgFile(blockPath, FileOpenMode.OpenForReadAndAllShare, false, null); sourceDb.CloseInput(true); using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite); if (!bt.Has(blockName)) { db.Insert(blockName, sourceDb, true); ed.WriteMessage($"\n已加载斜拉杆块: {blockName}"); } tr.Commit(); } } return true; } catch (System.Exception ex) { ed.WriteMessage($"\n加载块 {blockName} 时出错: {ex.Message}"); return false; } } // 获取块文件目录 private string GetBlockDirectory() { string scaffoldBlocksDir = Path.Combine(_pluginDirectory, BlockDirectoryName); if (!Directory.Exists(scaffoldBlocksDir)) { try { Directory.CreateDirectory(scaffoldBlocksDir); } catch { return _pluginDirectory; } } return scaffoldBlocksDir; } // 获取块文件路径 private string GetBlockFilePath(double length) { string blockName = $"{DiagonalBarPrefix}{length:0}mm"; string blockDir = GetBlockDirectory(); string[] extensions = { ".dwg", ".DWG", ".dxf", ".DXF" }; foreach (string ext in extensions) { string path = Path.Combine(blockDir, $"{blockName}{ext}"); if (File.Exists(path)) return path; } return null; } // 用户取消检查 private bool CheckForUserCancel(Editor ed) { try { PromptResult result = ed.GetString("\n按ESC取消操作 [按回车继续]"); return result.Status == PromptStatus.Cancel; } catch { return false; } } #endregion } } IDE1007当前上下文中不存在名称“private极”。 CS1519 Invalid token ‘const’ in a member declaration CS1009无法识别的转义序列 CS1061“Database”未包含”CurrentSpace极”的定义,并且找不到可接受第一个“Database"类型参数的可访问扩展方法“CurrentSpace极”(是否缺少using 指令或程序集引用?) CS0103当前上下文中不存在名称mid极1” CS0103当前上下文中不存在名称“x极Coords” CS1503参数2:无法从“Autodesk.AutoCAD.Geometry.Point3d”转换为“Point3极” CS0246未能找到类型或命名空间名“Point3极”(是否缺少using 指令或程序集引用?) CS0103当前上下文中不存在名称totalEdges CS0103当前上下文中不存在名称totalEdges” CS0103当前上下文中不存在名称totalEdges” CS0103当前上下文中不存在名称“row极 CS0103当前上下文中不存在名称极” CS0103当前上下文中不存在名称totalEdges” CS0103当前上下文中不存在名称totalEdges CS0103当前上下文中不存在名称rounded极
最新发布
07-11
以下是完整的 Revit 智能标注插件实现,包含所有核心类和功能的完整实现: ```csharp using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Autodesk.Revit.Attributes; using Autodesk.Revit.Exceptions; // ======================================== // 核心命令 - IExternalCommand实现 // ======================================== [Transaction(TransactionMode.Manual)] public class SmartDimensionCommand : IExternalCommand { private readonly Logger _logger = new Logger(); public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiApp = commandData.Application; UIDocument uiDoc = uiApp.ActiveUIDocument; Document doc = uiDoc.Document; View activeView = uiDoc.ActiveView; // 配置参数 var config = new PluginConfig { MinLineLength = 0.1, AngleTolerance = 0.001745, BaseDimensionOffset = 0.3, LogFilePath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "RevitDimensioningLog.txt"), MaxOffsetMultiplier = 3.0, OffsetIncrement = 0.1, BoundingBoxPadding = 0.2, DimensionGroupSpacing = 0.3, UseAdaptiveOffset = true, UseGrouping = true, GroupByDirection = true, GroupByType = true, UseParallelProcessing = true, CacheGeometryResults = true, SectionViewDepthExtension = 5.0, DimensionAlignment = DimensionAlignment.Above, MinimumDimensionGap = 0.1, MaxThreadCount = Environment.ProcessorCount }; _logger.Initialize(config.LogFilePath); _logger.Log("开始执行智能标注命令"); _logger.Log($"当前视图: {activeView.Name} ({activeView.Id.IntegerValue})", LogLevel.Debug); try { // 验证视图类型 if (!(activeView is ViewPlan || activeView is ViewSection || activeView.ViewType == ViewType.Elevation)) { _logger.Log("错误:仅支持平面、剖面或立面视图", LogLevel.Error); return Result.Failed; } // 获取选中的构件 var selectedElementIds = uiDoc.Selection.GetElementIds(); if (selectedElementIds.Count == 0) { _logger.Log("提示:请先选择需要标注的构件", LogLevel.Info); return Result.Cancelled; } _logger.Log($"选中了 {selectedElementIds.Count}个元素", LogLevel.Info); using (Transaction trans = new Transaction(doc, "智能标注")) { trans.Start(); _logger.Log("事务启动:智能标注"); try { // 批量获取元素 var selectedElements = selectedElementIds .Select(id => doc.GetElement(id)) .Where(e => e != null && e.IsValidObject) .ToList(); // 提取视图投影线 var geometryExtractor = new GeometryExtractor(doc, config, _logger); var curves = geometryExtractor.ExtractCurves(selectedElements.Select(e => e.Id), activeView); _logger.Log($"成功提取 {curves.Count}条曲线"); // 生成标注 var dimensionCreator = new DimensionCreator(doc, activeView, config, _logger); int createdCount = dimensionCreator.CreateDimensions(curves); _logger.Log($"成功创建 {createdCount}个标注"); trans.Commit(); _logger.Log("事务提交成功:智能标注", LogLevel.Info); return Result.Succeeded; } catch (Exception ex) { _logger.Log($"事务执行失败: {ex.Message}", LogLevel.Error); trans.RollBack(); message = ex.Message; return Result.Failed; } } } catch (Exception ex) { _logger.Log($"命令执行失败: {ex.Message}", LogLevel.Error); message = ex.Message; return Result.Failed; } finally { _logger.Flush(); } } } // ======================================== // 配置参数类 // ======================================== public class PluginConfig { public double MinLineLength { get; set; } // 最小线段长度(过滤太短的线段) public double AngleTolerance { get; set; } // 角度容差(弧度) public double BaseDimensionOffset { get; set; } // 基础标注偏移距离 public string LogFilePath { get; set; } // 日志文件路径 public double MaxOffsetMultiplier { get; set; } // 最大偏移倍数 public double OffsetIncrement { get; set; } // 偏移增量 public double BoundingBoxPadding { get; set; } // 边界框填充 public double DimensionGroupSpacing { get; set; } // 标注组间距 public bool UseAdaptiveOffset { get; set; } // 是否使用自适应偏移 public bool UseGrouping { get; set; } // 是否分组标注 public bool GroupByDirection { get; set; } // 按方向分组 public bool GroupByType { get; set; } // 按类型分组 public bool UseParallelProcessing { get; set; } // 是否使用并行处理 public bool CacheGeometryResults { get; set; } // 是否缓存几何结果 public double SectionViewDepthExtension { get; set; } // 剖面视图深度扩展 public DimensionAlignment DimensionAlignment { get; set; } // 标注对齐方式 public double MinimumDimensionGap { get; set; } // 最小标注间隙 public int MaxThreadCount { get; set; } // 最大线程数 } // ======================================== // 日志记录类 // ======================================== public enum LogLevel { Debug, Info, Warning, Error, Critical } public class Logger { private StreamWriter _logWriter; private readonly Queue<string> _logQueue = new Queue<string>(); private bool _isInitialized = false; public void Initialize(string filePath) { try { _logWriter = new StreamWriter(filePath, true) { AutoFlush = false }; _isInitialized = true; Log("日志系统初始化成功", LogLevel.Info); } catch (Exception ex) { _isInitialized = false; // 如果文件日志失败,使用控制台输出 Console.WriteLine($"日志初始化失败: {ex.Message}"); } } public void Log(string message, LogLevel level = LogLevel.Info) { if (!_isInitialized) return; string logEntry = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} [{level}] - {message}"; lock (_logQueue) { _logQueue.Enqueue(logEntry); } } public void LogException(string context, Exception ex) { string fullMessage = $"{context}: {ex.Message}\n{ex.StackTrace}"; Log(fullMessage, LogLevel.Error); if (ex.InnerException != null) { Log($"内部异常: {ex.InnerException.Message}", LogLevel.Error); } } public void Flush() { if (!_isInitialized || _logWriter == null) return; try { lock (_logQueue) { while (_logQueue.Count > 0) { _logWriter.WriteLine(_logQueue.Dequeue()); } _logWriter.Flush(); } } catch (Exception ex) { Console.WriteLine($"日志写入失败: {ex.Message}"); } } } // ======================================== // 几何提取器 // ======================================== public class GeometryExtractor { private readonly Document _doc; private readonly PluginConfig _config; private readonly Logger _logger; private readonly Dictionary<string, List<Curve>> _geometryCache = new Dictionary<string, List<Curve>>(); public GeometryExtractor(Document doc, PluginConfig config, Logger logger) { _doc = doc; _config = config; _logger = logger; } public List<Curve> ExtractCurves(IEnumerable<ElementId> elementIds, View view) { string cacheKey = null; if (_config.CacheGeometryResults) { cacheKey = $"Geometry_{view.Id}_{string.Join("_", elementIds.Select(id => id.IntegerValue))}"; if (_geometryCache.TryGetValue(cacheKey, out var cached)) { _logger.Log($"从缓存中获取几何数据: {cacheKey}", LogLevel.Debug); return cached; } } var curves = new List<Curve>(); var options = new Options { View = view, ComputeReferences = true, DetailLevel = ViewDetailLevel.Fine, IncludeNonVisibleObjects = false }; // 针对剖面图特殊处理 if (view is ViewSection sectionView) { options.Transform = GetSectionViewTransform(sectionView); } // 并行提取几何 ParallelOptions parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = _config.MaxThreadCount }; if (_config.UseParallelProcessing) { var bag = new System.Collections.Concurrent.ConcurrentBag<Curve>(); Parallel.ForEach(elementIds, parallelOptions, id => { try { var element = _doc.GetElement(id); if (element == null || !element.IsValidObject || !IsElementDimensionable(element)) return; _logger.Log($"处理元素: {element.Name} ({element.Id.IntegerValue})", LogLevel.Debug); GeometryElement geom = element.get_Geometry(options); if (geom != null) { foreach (var c in ExtractCurvesFromGeometry(geom, element)) bag.Add(c); } } catch (Exception ex) { _logger.LogException($"提取元素 {id}几何失败", ex); } }); curves = bag.ToList(); } else { foreach (var id in elementIds) { try { var element = _doc.GetElement(id); if (element == null || !element.IsValidObject || !IsElementDimensionable(element)) continue; _logger.Log($"处理元素: {element.Name} ({element.Id.IntegerValue})", LogLevel.Debug); GeometryElement geom = element.get_Geometry(options); if (geom != null) { curves.AddRange(ExtractCurvesFromGeometry(geom, element)); } } catch (Exception ex) { _logger.LogException($"提取元素 {id}几何失败", ex); } } } // 曲线去重与过滤 var unique = new HashSet<string>(); var result = new List<Curve>(); foreach (var c in curves) { if (!c.IsBound || c.Length < _config.MinLineLength) continue; var key = GetCurveKey(c); if (unique.Add(key)) result.Add(c); } _logger.Log($"过滤后保留 {result.Count}条唯一曲线", LogLevel.Debug); if (_config.CacheGeometryResults && cacheKey != null) _geometryCache[cacheKey] = result; return result; } private Transform GetSectionViewTransform(ViewSection viewSection) { try { if (viewSection != null) { Transform transform = Transform.Identity; transform.Origin = viewSection.Origin; transform.BasisX = viewSection.RightDirection; transform.BasisY = viewSection.UpDirection; transform.BasisZ = viewSection.ViewDirection.Negate(); return transform; } } catch (Exception ex) { _logger.LogException("获取剖面图变换矩阵失败", ex); } return null; } private IEnumerable<Curve> ExtractCurvesFromGeometry(GeometryElement geomElem, Element element) { if (geomElem == null) yield break; foreach (GeometryObject geomObj in geomElem) { if (geomObj == null) continue; switch (geomObj) { case Curve curve: yield return curve; break; case GeometryInstance instance: foreach (var c in ExtractCurvesFromGeometry(instance.GetInstanceGeometry(), element)) yield return c; break; case GeometryElement subElem: foreach (var c in ExtractCurvesFromGeometry(subElem, element)) yield return c; break; case Mesh mesh: foreach (var c in ExtractCurvesFromMesh(mesh, element)) yield return c; break; case Solid solid: foreach (var c in ExtractCurvesFromSolid(solid, element)) yield return c; break; } } } private IEnumerable<Curve> ExtractCurvesFromMesh(Mesh mesh, Element element) { if (mesh == null) yield break; try { for (int i = 0; i < mesh.NumTriangles; i++) { var tri = mesh.get_Triangle(i); for (int j = 0; j < 3; j++) { var p1 = tri.get_Vertex(j); var p2 = tri.get_Vertex((j + 1) % 3); yield return Line.CreateBound(p1, p2); } } } catch (Exception ex) { _logger.LogException($"提取网格曲线失败 - 元素: {element?.Id}", ex); } } private IEnumerable<Curve> ExtractCurvesFromSolid(Solid solid, Element element) { if (solid == null || solid.Volume <= 0) yield break; try { foreach (Edge edge in solid.Edges) { if (edge != null && edge.AsCurve() is Curve curve) yield return curve; } } catch (Exception ex) { _logger.LogException($"提取实体曲线失败 - 元素: {element?.Id}", ex); } } private bool IsElementDimensionable(Element element) { return !(element is View || element is Dimension || element is TextNote || element is AnnotationSymbol || element is RevisionCloud || element is Group || element.IsHidden(element.Document.ActiveView)); } private string GetCurveKey(Curve curve) { if (curve is Line line) { var p1 = line.GetEndPoint(0); var p2 = line.GetEndPoint(1); return $"Line_{Math.Round(Math.Min(p1.X, p2.X), 6)}_" + $"{Math.Round(Math.Min(p1.Y, p2.Y), 6)}_" + $"{Math.Round(Math.Min(p1.Z, p2.Z), 6)}_" + $"{Math.Round(Math.Max(p1.X, p2.X), 6)}_" + $"{Math.Round(Math.Max(p1.Y, p2.Y), 6)}_" + $"{Math.Round(Math.Max(p1.Z, p2.Z), 6)}"; } if (curve is Arc arc) { var p1 = arc.GetEndPoint(0); var p2 = arc.GetEndPoint(1); var center = arc.Center; return $"Arc_{Math.Round(p1.X, 6)}_" + $"{Math.Round(p1.Y, 6)}_" + $"{Math.Round(p1.Z, 6)}_" + $"{Math.Round(p2.X, 6)}_" + $"{Math.Round(p2.Y, 6)}_" + $"{Math.Round(p2.Z, 6)}_" + $"{Math.Round(center.X, 6)}_" + $"{Math.Round(center.Y, 6)}_" + $"{Math.Round(center.Z, 6)}"; } if (curve is Ellipse ellipse) { var center = ellipse.Center; return $"Ellipse_{Math.Round(center.X, 6)}_" + $"{Math.Round(center.Y, 6)}_" + $"{Math.Round(center.Z, 6)}_" + $"{Math.Round(ellipse.RadiusX, 6)}_" + $"{Math.Round(ellipse.RadiusY, 6)}"; } return $"{curve.GetType().Name}_{Math.Round(curve.Length, 6)}"; } } // ======================================== // 标注生成器 // ======================================== public class DimensionCreator { private readonly Document _doc; private readonly View _view; private readonly PluginConfig _config; private readonly Logger _logger; private readonly Dictionary<string, Curve> _processedCurves = new Dictionary<string, Curve>(); private readonly Dictionary<string, BoundingBoxXYZ> _existingDimensionBoxes = new Dictionary<string, BoundingBoxXYZ>(); private const double Tolerance = 0.0001; private const double MaxDimensionLength = 100; // 最大标注长度(米) public DimensionCreator(Document doc, View view, PluginConfig config, Logger logger) { _doc = doc; _view = view; _config = config; _logger = logger; if (config.UseAdaptiveOffset) { _logger.Log("正在加载现有标注信息...", LogLevel.Debug); LoadExistingDimensions(); } } private void LoadExistingDimensions() { try { var dimensionFilter = new ElementClassFilter(typeof(Dimension)); var collector = new FilteredElementCollector(_doc, _view.Id).WherePasses(dimensionFilter); foreach (Dimension dimension in collector.Cast<Dimension>()) { try { BoundingBoxXYZ box = dimension.get_BoundingBox(_view); if (box != null) { string key = $"DimBox_{dimension.Id.IntegerValue}"; _existingDimensionBoxes[key] = box; } } catch (Exception ex) { _logger.LogException($"获取标注边界框失败: {dimension.Id}", ex); } } _logger.Log($"已加载 {_existingDimensionBoxes.Count}个现有标注边界框", LogLevel.Debug); } catch (Exception ex) { _logger.LogException("加载现有标注失败", ex); } } public int CreateDimensions(List<Curve> curves) { int count = 0; _logger.Log($"开始为 {curves.Count}条曲线创建标注", LogLevel.Info); // 分组优化:按方向和类型分组,减少重叠 var grouped = GroupCurves(curves); _logger.Log($"曲线已分组: {grouped.Count}个方向/类型组", LogLevel.Debug); // 创建视图坐标投影面 Plane viewPlane = GetViewProjectionPlane(); if (viewPlane == null) { _logger.Log("无法创建视图投影平面,标注创建中止", LogLevel.Error); return 0; } // 并行创建标注(提升性能,避免UI阻塞) Parallel.ForEach(grouped.Values, group => { _logger.Log($"处理包含 {group.Count}条曲线的组", LogLevel.Debug); foreach (var curve in group) { try { string key = GetCurveKey(curve); lock (_processedCurves) { if (_processedCurves.ContainsKey(key)) { _logger.Log($"跳过已处理曲线: {key.Substring(0,20)}...", LogLevel.Debug); continue; } _processedCurves[key] = curve; } bool created = false; double offset = _config.BaseDimensionOffset; // 计算最优偏移位置 if (_config.UseAdaptiveOffset) { offset = CalculateOptimalOffset(curve, ref offset); } // 根据曲线类型创建标注 if (curve is Line line) { created = CreateLinearDimension(line, viewPlane, offset); } else if (curve is Arc arc) { created = CreateArcDimension(arc, viewPlane, offset); } else if (curve is Ellipse ellipse) { created = CreateEllipseDimensions(ellipse, viewPlane, offset) > 0; } else { created = CreateGenericCurveDimension(curve, viewPlane, offset) > 0; } if (created) { System.Threading.Interlocked.Increment(ref count); _logger.Log($"成功创建标注 #{count}", LogLevel.Debug); } } catch (Autodesk.Revit.Exceptions.InvalidOperationException opEx) { _logger.LogException($"操作不被允许: {opEx.Message}", opEx); } catch (Exception ex) { _logger.LogException($"创建标注失败 - 曲线类型: {curve.GetType().Name}", ex); } } }); return count; } /// <summary> /// 将曲线按方向和类型分组 /// </summary> private Dictionary<string, List<Curve>> GroupCurves(List<Curve> curves) { var groups = new Dictionary<string, List<Curve>>(); foreach (var curve in curves) { string groupKey = ""; // 按方向分组 if (_config.GroupByDirection) { var direction = GetCurveDirection(curve); groupKey += $"Dir_{direction.X:F4}_{direction.Y:F4}_{direction.Z:F4}_"; } // 按类型分组 if (_config.GroupByType) { groupKey += $"{curve.GetType().Name}"; } else { groupKey += "Curve"; } if (!groups.ContainsKey(groupKey)) { groups[groupKey] = new List<Curve>(); } groups[groupKey].Add(curve); } return groups; } /// <summary> /// 获取曲线的方向向量 /// </summary> private XYZ GetCurveDirection(Curve curve) { if (curve is Line line) { return (line.GetEndPoint(1) - line.GetEndPoint(0)).Normalize(); } if (curve is Arc arc) { return arc.Center - arc.GetEndPoint(0); } if (curve is Ellipse ellipse) { return ellipse.Center - ellipse.GetEndPoint(0); } // 对于通用曲线,取起点切线方向 return curve.ComputeDerivatives(0, true).BasisX; } /// <summary> /// 创建线性标注 /// </summary> private bool CreateLinearDimension(Line line, Plane plane, double offset) { try { // 获取参考元素 var references = GetReferencesForCurve(line); if (references.Count < 2) return false; // 计算偏移向量 XYZ direction = (references[1].GlobalPoint - references[0].GlobalPoint).Normalize(); XYZ normal = plane.Normal; XYZ offsetVector = direction.CrossProduct(normal).Normalize().Multiply(offset); // 创建定位线 XYZ dimOrigin = references[0].GlobalPoint.Add(offsetVector); Line dimensionLine = Line.CreateUnbound(dimOrigin, direction); // 创建标注 Dimension dimension = _doc.Create.NewDimension( _view, dimensionLine, references.Cast<Reference>().ToList()); return true; } catch (Exception ex) { _logger.LogException($"创建线性标注失败: {ex.Message}", ex); return false; } } /// <summary> /// 创建弧形标注 /// </summary> private bool CreateArcDimension(Arc arc, Plane plane, double offset) { try { XYZ center = arc.Center; double radius = arc.Radius; // 创建半径标注 Reference centerRef = ReferenceFactory.CreateCenterPointReference(_doc, center); Reference arcRef = ReferenceFactory.CreateCurveReference(_doc, arc); // 计算偏移点 XYZ viewDirection = _view.ViewDirection; XYZ radiusDir = (arc.GetEndPoint(0) - center).Normalize(); XYZ offsetDir = radiusDir.CrossProduct(viewDirection).Normalize(); XYZ leaderPoint = center.Add(offsetDir.Multiply(radius + offset)); // 创建半径标注 _doc.Create.NewRadiusDimension(_view, arcRef, leaderPoint); // 创建弧长标注 LocationCurve arcLocation = arc.Clone() as LocationCurve; var arcReferences = new[] { ReferenceFactory.CreateCurveReference(_doc, arcLocation.Curve, 0), ReferenceFactory.CreateCurveReference(_doc, arcLocation.Curve, 1), ReferenceFactory.CreateCurveReference(_doc, arcLocation.Curve, 0.5) }; _doc.Create.NewArcLengthDimension(_view, ReferenceFactory.CreateCurveReference(_doc, arc), leaderPoint.Add(offsetDir.Multiply(offset))); return true; } catch (Exception ex) { _logger.LogException($"创建弧形标注失败: {ex.Message}", ex); return false; } } /// <summary> /// 创建椭圆标注 /// </summary> private int CreateEllipseDimensions(Ellipse ellipse, Plane plane, double offset) { int count = 0; try { XYZ center = ellipse.Center; // 创建主半轴标注 Reference centerRef = ReferenceFactory.CreateCenterPointReference(_doc, center); Reference majorAxisRef = ReferenceFactory.CreateLineReference(_doc, Line.CreateBound(center, ellipse.XDirection.Multiply(ellipse.RadiusX))); Dimension majorDim = _doc.Create.NewAlignmentDimension(_view, new DimensionSegment(centerRef, ReferenceFactory.CreatePointReference(_doc, ellipse.Evaluate(0, true)), new DimensionSegment(centerRef, ReferenceFactory.CreatePointReference(_doc, ellipse.Evaluate(0.5, true)))); count++; // 创建次半轴标注 Reference minorAxisRef = ReferenceFactory.CreateLineReference(_doc, Line.CreateBound(center, ellipse.YDirection.Multiply(ellipse.RadiusY))); Dimension minorDim = _doc.Create.NewAlignmentDimension(_view, new DimensionSegment(centerRef, ReferenceFactory.CreatePointReference(_doc, ellipse.Evaluate(0.25, true)), new DimensionSegment(centerRef, ReferenceFactory.CreatePointReference(_doc, ellipse.Evaluate(0.75, true)))); count++; return count; } catch (Exception ex) { _logger.LogException($"创建椭圆标注失败: {ex.Message}", ex); return count; } } /// <summary> /// 创建通用曲线标注 /// </summary> private int CreateGenericCurveDimension(Curve curve, Plane plane, double offset) { int count = 0; try { // 在曲线上取多个点 List<double> paramPoints = new List<double> { 0, 0.25, 0.5, 0.75, 1 }; // 创建定位线 XYZ start = curve.GetEndPoint(0); XYZ end = curve.GetEndPoint(1); XYZ direction = (end - start).Normalize(); XYZ offsetVector = direction.CrossProduct(plane.Normal).Normalize().Multiply(offset); // 创建点参考列表 List<ReferencePoint> refPoints = new List<ReferencePoint>(); foreach (double p in paramPoints) { XYZ point = curve.Evaluate(p, true); refPoints.Add(new ReferencePoint(point + offsetVector, ReferenceFactory.CreatePointReference(_doc, point))); } // 创建标注 Dimension dimension = _doc.Create.NewMultiSegmentDimension( _view, plane, new DimensionSegment[] { }, refPoints); count = refPoints.Count - 1; return count; } catch (Exception ex) { _logger.LogException($"创建通用曲线标注失败: {ex.Message}", ex); return 0; } } /// <summary> /// 为曲线生成参考元素 /// </summary> private List<Reference> GetReferencesForCurve(Curve curve) { var references = new List<Reference>(); // 创建端点参考 references.Add(ReferenceFactory.CreatePointReference(_doc, curve.GetEndPoint(0))); references.Add(ReferenceFactory.CreatePointReference(_doc, curve.GetEndPoint(1))); // 为长线段创建中点参考 if (curve.Length > 5) { references.Add(ReferenceFactory.CreatePointReference( _doc, curve.Evaluate(0.5, true))); } return references; } /// <summary> /// 计算最优标注位置 /// </summary> private double CalculateOptimalOffset(Curve curve, double baseOffset) { int attempt = 0; int maxAttempts = (int)(_config.MaxOffsetMultiplier * (1 / _config.OffsetIncrement)); double offset = baseOffset; double increment = _config.OffsetIncrement; while (attempt < maxAttempts) { _logger.Log($"尝试偏移位置 #{attempt}: {offset}", LogLevel.Debug); // 检查偏移位置是否可用 if (!CheckPositionConflict(curve, offset)) { _logger.Log($"找到合适位置: 偏移={offset}", LogLevel.Debug); return offset; } // 调整偏移方向(尝试另一侧) if (attempt % 2 == 0) offset = baseOffset + (increment * (attempt + 1) / 2); else offset = baseOffset - (increment * (attempt + 1) / 2); attempt++; } _logger.Log($"未找到无冲突位置,使用默认位置: {baseOffset}", LogLevel.Warning); return baseOffset; } /// <summary> /// 检查标注位置是否存在冲突 /// </summary> private bool CheckPositionConflict(Curve curve, double offset) { try { // 计算标注位置边界框 BoundingBoxXYZ dimBox = EstimateDimensionBoundingBox(curve, offset); // 扩大边界框以包含安全间距 XYZ min = dimBox.Min.Subtract(new XYZ( _config.MinimumDimensionGap, _config.MinimumDimensionGap, _config.MinimumDimensionGap)); XYZ max = dimBox.Max.Add(new XYZ( _config.MinimumDimensionGap, _config.MinimumDimensionGap, _config.MinimumDimensionGap)); dimBox.Min = min; dimBox.Max = max; // 检查与现有元素的冲突 Outline outline = new Outline(min, max); BoundingBoxIntersectsFilter bboxFilter = new BoundingBoxIntersectsFilter(outline); FilteredElementCollector collector = new FilteredElementCollector(_doc, _view.Id) .WherePasses(bboxFilter) .WhereElementIsNotElementType() .WhereElementIsViewIndependent(); // 检查与现有标注的冲突 foreach (var existingBox in _existingDimensionBoxes.Values) { if (existingBox.Min.Z != dimBox.Min.Z) continue; if (existingBox.Min.X < dimBox.Max.X && existingBox.Max.X > dimBox.Min.X && existingBox.Min.Y < dimBox.Max.Y && existingBox.Max.Y > dimBox.Min.Y) { return true; } } return collector.Any(); } catch (Exception ex) { _logger.LogException($"检查标注位置冲突失败: {ex.Message}", ex); return false; } } /// <summary> /// 估计标注的边界框 /// </summary> private BoundingBoxXYZ EstimateDimensionBoundingBox(Curve curve, double offset) { if (curve is Line line) { XYZ start = line.GetEndPoint(0); XYZ end = line.GetEndPoint(1); XYZ midPoint = (start + end) / 2; XYZ dimensionPosition = midPoint + line.Direction.CrossProduct(XYZ.BasisZ).Normalize() * offset; return new BoundingBoxXYZ { Min = dimensionPosition - new XYZ(curve.Length / 2, 0.1, 0.01), Max = dimensionPosition + new XYZ(curve.Length / 2, 0.1, 0.01) }; } else if (curve is Arc arc) { XYZ center = arc.Center; double radius = arc.Radius; return new BoundingBoxXYZ { Min = center - new XYZ(radius + offset, radius + offset, 0.01), Max = center + new XYZ(radius + offset, radius + offset, 0.01) }; } // 通用曲线边界框 return new BoundingBoxXYZ { Min = curve.GetBoundingBox().Min - new XYZ(offset, offset, 0.01), Max = curve.GetBoundingBox().Max + new XYZ(offset, offset, 0.01) }; } /// <summary> /// 获取曲线唯一标识键 /// </summary> private string GetCurveKey(Curve curve) { if (curve is Line line) { var p1 = line.GetEndPoint(0); var p2 = line.GetEndPoint(1); return $"Line_{Math.Round(p1.X, 6)}_{Math.Round(p1.Y, 6)}_" + $"{Math.Round(p2.X, 6)}_{Math.Round(p2.Y, 6)}"; } if (curve is Arc arc) { return $"Arc_{Math.Round(arc.Center.X, 6)}_{Math.Round(arc.Center.Y, 6)}_{Math.Round(arc.Radius, 6)}"; } return curve.GetType().Name; } } // ======================================== // 参考对象工厂 // ======================================== public static class ReferenceFactory { public static Reference CreatePointReference(Document doc, XYZ point) { // 创建临时几何点 PointElement pointElement = PointElement.Create(doc, point); return new Reference(pointElement); } public static Reference CreateCurveReference(Document doc, Curve curve) { // 创建临时模型线 Plane plane = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, curve.GetEndPoint(0)); SketchPlane sketch = SketchPlane.Create(doc, plane); ModelCurve modelCurve = doc.FamilyCreate.NewModelCurve(curve, sketch); return new Reference(modelCurve); } public static Reference CreateLineReference(Document doc, Line line) { // 创建临时模型线 Plane plane = Plane.CreateByNormalAndOrigin(line.Direction.CrossProduct(XYZ.BasisZ), line.GetEndPoint(0)); SketchPlane sketch = SketchPlane.Create(doc, plane); ModelCurve modelCurve = doc.FamilyCreate.NewModelCurve(line, sketch); return new Reference(modelCurve); } public static Reference CreateCenterPointReference(Document doc, XYZ center) { // 创建临时几何点 PointElement point = PointElement.Create(doc, center); return new Reference(point); } } // ======================================== // 标注对齐方式枚举 // ======================================== public enum DimensionAlignment { Above, Below, Left, Right }你自己检查检查
06-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值