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指令或程序集引用?)