using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
// 使用别名解决Exception冲突
using AcadException = Autodesk.AutoCAD.Runtime.Exception;
using SysException = System.Exception;
namespace ScaffoldPlugin
{
public class ScaffoldGenerator
{
// 图块尺寸映射
private static readonly Dictionary<string, int> BlockSizes = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
{
// 立杆
{"ScaffoldPole立杆200mm", 200},
{"ScaffoldPole立杆350mm", 350},
{"ScaffoldPole立杆500mm", 500},
{"ScaffoldPole立杆1000mm", 1000},
{"ScaffoldPole立杆1500mm", 1500},
{"ScaffoldPole立杆2000mm", 2000},
{"ScaffoldPole立杆2500mm", 2500},
// 横杆
{"ScaffoldPole立横杆300mm", 300},
{"ScaffoldPole立横杆600mm", 600},
{"ScaffoldPole立横杆900mm", 900},
{"ScaffoldPole立横杆1200mm", 1200},
{"ScaffoldPole立横杆1500mm", 1500},
{"ScaffoldPole立横杆1800mm", 1800},
// 附件
{"ScaffoldPole顶托", 0}, // 顶托高度
{"ScaffoldPole顶托螺母", 0}, // 螺母高度
{"ScaffoldPole连接盘", 0} // 连接盘高度
};
// 常量定义
private const double FirstBarHeight = 250.0; // 第一道横杆高度
private const double HorizontalBarSpacing = 1500.0; // 横杆步距
private const double StandardDiskOffset = 250.0; // 标准立杆第一个盘距根部高度
private const double Tolerance = 5.0; // 位置容差
private const double NutOffset = 75.0; // 螺母相对于立杆顶部的偏移量
private const double MinTopGap = 200.0; // 最小顶部间隙
private const double MaxTopGap = 400.0; // 最大顶部间隙
private const double RelaxedTolerance = 50.0; // 放大的容差用于连接盘检测
private const double MaxBarDistance = 1800.0; // 最大横杆跨度
private const double MaxDiskSearchDistance = 500.0; // 最大连接盘搜索距离
private const double HeightDifferenceThreshold = 50.0; // 顶部连接盘高度差阈值
private const double TopControlLineTolerance = 10.0; // 顶部控制线检测容差
private const double DimensionOffset = 600.0; // 标注偏移距离
private Editor _ed;
private string _blocksFolderPath;
private Curve _topControlLine;
private bool _isAscending; // 整体方向(上升/下降)
// 存储所有连接盘位置 [X坐标 -> 连接盘Y坐标列表]
private readonly Dictionary<double, List<double>> _diskPositions = new Dictionary<double, List<double>>();
// 存储顶托位置 [X坐标 -> 顶托Y坐标]
private readonly Dictionary<double, double> _adjusterPositions = new Dictionary<double, double>();
// 存储最后一根立杆信息 [X坐标 -> 最后一根立杆尺寸]
private readonly Dictionary<double, int> _lastPoleSizes = new Dictionary<double, int>();
// 存储立杆底部位置 [X坐标 -> 底部Y坐标]
private readonly Dictionary<double, double> _poleBasePositions = new Dictionary<double, double>();
// 存储顶部连接盘位置 [X坐标 -> 顶部连接盘Y坐标]
private readonly Dictionary<double, double> _topDiskPositions = new Dictionary<double, double>();
[CommandMethod("GS", CommandFlags.Modal)]
public void GenerateScaffold()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
_ed = doc.Editor;
try
{
// 初始化图块文件夹路径
_blocksFolderPath = GetBlocksFolderPath();
if (string.IsNullOrEmpty(_blocksFolderPath))
{
return;
}
// 加载所有图块定义
LoadAllBlockDefinitions(db);
// 框选图块
var blockRefs = SelectBlocks();
if (blockRefs == null || blockRefs.Count == 0) return;
// 选择控制线
_ed.WriteMessage("\n选择底标高水平控制线");
var baseLine = SelectControlLine();
if (baseLine == null) return;
_ed.WriteMessage("\n选择顶部控制线");
_topControlLine = SelectControlLine();
if (_topControlLine == null) return;
// 获取控制线高度
double baseElev = GetLineElevation(baseLine);
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
// 清空位置记录
_diskPositions.Clear();
_adjusterPositions.Clear();
_lastPoleSizes.Clear();
_poleBasePositions.Clear();
_topDiskPositions.Clear();
// 立杆布置
LayoutVerticalPoles(tr, bt, btr, blockRefs, baseElev);
// 横杆布置
LayoutHorizontalBars(tr, bt, btr, blockRefs, baseElev);
// 添加尺寸标注 - 传入数据库对象
AddDimensions(tr, btr, db, baseElev);
tr.Commit();
}
}
catch (AcadException acadEx) // AutoCAD特有异常
{
HandleAcadException(acadEx);
}
catch (SysException sysEx) // 系统异常
{
}
}
// 处理AutoCAD特有异常
private void HandleAcadException(AcadException acadEx)
{
if (acadEx.ErrorStatus != ErrorStatus.UserBreak)
{
}
}
// 获取图块文件夹路径
private string GetBlocksFolderPath()
{
try
{
string assemblyPath = Assembly.GetExecutingAssembly().Location;
string pluginDir = Path.GetDirectoryName(assemblyPath);
return Path.Combine(pluginDir, "ScaffoldBlocks");
}
catch
{
return null;
}
}
// 加载所有图块定义
private void LoadAllBlockDefinitions(Database db)
{
if (string.IsNullOrEmpty(_blocksFolderPath)) return;
try
{
string[] blockFiles = Directory.GetFiles(_blocksFolderPath, "*.dwg");
if (blockFiles.Length == 0) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
foreach (string filePath in blockFiles)
{
string fileName = Path.GetFileNameWithoutExtension(filePath);
if (!BlockSizes.ContainsKey(fileName) || bt.Has(fileName)) continue;
using (Database sourceDb = new Database(false, true))
{
sourceDb.ReadDwgFile(filePath, FileShare.Read, true, null);
db.Insert(fileName, sourceDb, true);
}
}
tr.Commit();
}
}
catch
{
}
}
// 选择控制线
private Curve SelectControlLine()
{
try
{
var opts = new PromptEntityOptions("\n选择控制线: ")
{
AllowNone = false,
AllowObjectOnLockedLayer = true
};
opts.SetRejectMessage("\n必须选择直线或多段线");
opts.AddAllowedClass(typeof(Line), true);
opts.AddAllowedClass(typeof(Polyline), true);
PromptEntityResult result = _ed.GetEntity(opts);
if (result.Status != PromptStatus.OK) return null;
using (Transaction tr = _ed.Document.TransactionManager.StartTransaction())
{
Curve curve = tr.GetObject(result.ObjectId, OpenMode.ForRead) as Curve;
tr.Commit();
return curve;
}
}
catch
{
return null;
}
}
// 获取直线/多段线的Y坐标
private double GetLineElevation(Curve curve)
{
if (curve == null) return 0;
try
{
if (curve is Line line) return line.StartPoint.Y;
if (curve is Polyline pline) return pline.GetPoint3dAt(0).Y;
return 0;
}
catch
{
return 0;
}
}
// 选择图块
private List<BlockReference> SelectBlocks()
{
try
{
var filter = new SelectionFilter(new[]
{
new TypedValue(0, "INSERT"),
new TypedValue(2, "ScaffoldPole*")
});
var selOptions = new PromptSelectionOptions
{
MessageForAdding = "\n框选脚手架图块: ",
AllowDuplicates = false
};
PromptSelectionResult selResult = _ed.GetSelection(selOptions, filter);
if (selResult.Status != PromptStatus.OK) return null;
var references = new List<BlockReference>();
using (var resBuf = selResult.Value)
{
Database db = _ed.Document.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
foreach (ObjectId objId in resBuf.GetObjectIds())
{
var bref = tr.GetObject(objId, OpenMode.ForRead) as BlockReference;
if (bref != null) references.Add(bref);
}
tr.Commit();
}
}
return references;
}
catch
{
return null;
}
}
// 立杆布置 - 严格保证顶部间隙200-400mm
private void LayoutVerticalPoles(
Transaction tr,
BlockTable bt,
BlockTableRecord btr,
List<BlockReference> blocks,
double baseElev)
{
try
{
// 获取所有立杆位置
var polePositions = blocks
.Where(b => b.Name.Contains("立杆") && !b.Name.Contains("横杆"))
.Select(b => b.Position.X)
.Distinct()
.OrderBy(x => x)
.ToList();
if (polePositions.Count == 0) return;
// 确定整体方向
double minY = polePositions.Min(x => GetElevationAtX(x));
double maxY = polePositions.Max(x => GetElevationAtX(x));
_isAscending = maxY > minY; // 保存到成员变量
// 标准杆件尺寸
int[] standardSizes = { 2500, 2000, 1500, 1000, 500, 350, 200 };
foreach (var xPos in polePositions)
{
// 记录立杆底部位置
_poleBasePositions[xPos] = baseElev;
// 获取该位置精确的顶部高度
double topElev = GetElevationAtX(xPos);
double totalHeight = Math.Abs(topElev - baseElev);
double currentY = baseElev;
List<int> usedSizes = new List<int>();
// 精确配杆算法
double remaining = totalHeight;
// 1. 先配标准杆(保留顶部间隙空间)
while (remaining > MinTopGap + 350) // 保留至少350mm+200mm间隙
{
// 计算最大可用尺寸(考虑最小间隙200mm)
double maxUsableSize = remaining - MinTopGap;
// 选择不超过最大可用尺寸的最大标准杆
int bestSize = standardSizes
.Where(s => s <= maxUsableSize)
.OrderByDescending(s => s)
.FirstOrDefault();
if (bestSize <= 0) break;
usedSizes.Add(bestSize);
remaining -= bestSize;
currentY += _isAscending ? bestSize : -bestSize;
}
// 2. 顶部配杆算法(关键:确保间隙在200-400mm)
int lastPoleSize = 0;
double gap = 0;
// 计算理想顶部间隙(200-400mm)
double minGap = MinTopGap;
double maxGap = MaxTopGap;
// 可选的最后一根杆尺寸(考虑间隙要求)
var validLastSizes = standardSizes
.Where(s =>
s <= remaining - minGap &&
s >= remaining - maxGap)
.OrderByDescending(s => s)
.ToList();
if (validLastSizes.Any())
{
// 优先选择满足间隙要求的最大杆
lastPoleSize = validLastSizes.First();
gap = remaining - lastPoleSize;
}
else
{
// 次选:最接近300mm间隙的杆
lastPoleSize = standardSizes
.OrderBy(s => Math.Abs((remaining - s) - 300)) // 300是理想间隙
.First();
gap = remaining - lastPoleSize;
// 确保间隙至少200mm
if (gap < minGap)
{
// 减少一根标准杆来增加空间
if (usedSizes.Count > 0)
{
int lastStandard = usedSizes.Last();
usedSizes.RemoveAt(usedSizes.Count - 1);
remaining += lastStandard;
currentY += _isAscending ? -lastStandard : lastStandard;
// 重新计算最后一根杆
lastPoleSize = standardSizes
.Where(s => s <= remaining - minGap)
.OrderByDescending(s => s)
.First();
gap = remaining - lastPoleSize;
}
else
{
// 无法调整时使用350mm杆
lastPoleSize = 350;
gap = remaining - lastPoleSize;
}
}
}
// 添加最后一根立杆
usedSizes.Add(lastPoleSize);
gap = remaining - lastPoleSize;
// 记录最后一根立杆尺寸
_lastPoleSizes[xPos] = lastPoleSize;
// 3. 布置所有立杆
currentY = baseElev; // 重置当前高度
foreach (int size in usedSizes)
{
string blockName = $"ScaffoldPole立杆{size}mm";
if (bt.Has(blockName))
{
InsertBlock(tr, btr, bt, blockName, xPos, currentY);
// 记录连接盘位置
RecordDiskPositions(xPos, currentY, size);
currentY += _isAscending ? size : -size;
}
}
// 4. 布置顶托和螺母
if (bt.Has("ScaffoldPole顶托"))
{
// 顶托顶部精确对齐控制线
double topPosition = topElev;
InsertBlock(tr, btr, bt, "ScaffoldPole顶托", xPos, topPosition);
_adjusterPositions[xPos] = topPosition;
// 螺母位置(在最后一根立杆顶部上方75mm)
double nutPosition = _isAscending ?
(currentY + NutOffset) :
(currentY - NutOffset);
if (bt.Has("ScaffoldPole顶托螺母"))
{
InsertBlock(tr, btr, bt, "ScaffoldPole顶托螺母", xPos, nutPosition);
}
}
}
}
catch
{
}
}
// 记录立杆上的连接盘位置
private void RecordDiskPositions(double x, double startY, int poleSize)
{
try
{
if (!_diskPositions.ContainsKey(x))
_diskPositions[x] = new List<double>();
// 关键修复:使用实际控制线计算真实高度
double actualTopY = GetElevationAtX(x);
double actualHeight = Math.Abs(actualTopY - startY);
double direction = _isAscending ? 1 : -1;
// 1. 第一道横杆位置(250mm)
double firstDiskY = startY + FirstBarHeight * direction;
if (!_diskPositions[x].Contains(firstDiskY))
_diskPositions[x].Add(firstDiskY);
// 2. 中间步距连接盘(1500mm步距)
int stepCount = 1;
while (true)
{
double diskHeight = FirstBarHeight + stepCount * HorizontalBarSpacing;
// 修复:使用实际高度限制
if (diskHeight > actualHeight - MinTopGap) break;
double diskY = startY + diskHeight * direction;
if (!_diskPositions[x].Contains(diskY))
_diskPositions[x].Add(diskY);
stepCount++;
}
// 3. 顶部连接盘(立杆实际顶部位置)
// 关键修复:使用实际控制线位置,而非理论计算
if (!_diskPositions[x].Contains(actualTopY))
_diskPositions[x].Add(actualTopY);
// 更新顶部连接盘记录
_topDiskPositions[x] = actualTopY;
}
catch
{
}
}
// 横杆布置 - 严格按250mm起始和1500mm步距
private void LayoutHorizontalBars(
Transaction tr,
BlockTable bt,
BlockTableRecord btr,
List<BlockReference> blocks,
double baseElev)
{
try
{
// 获取所有立杆位置
var poleXPositions = _poleBasePositions.Keys
.OrderBy(x => x)
.ToList();
if (poleXPositions.Count < 2) return;
// 计算横杆布置高度序列(250mm起始,1500mm步距)
List<double> barHeights = CalculateBarHeights(poleXPositions, baseElev);
// 为每个横杆高度布置横杆
foreach (var height in barHeights)
{
PlaceBarsAtHeight(tr, bt, btr, poleXPositions, height);
}
// 在顶部立杆圆盘处布置横杆(基于连接盘位置)
PlaceTopBarsOnDisks(tr, bt, btr, poleXPositions);
}
catch
{
}
}
// 计算横杆布置高度序列(250mm起始,1500mm步距)
private List<double> CalculateBarHeights(List<double> polePositions, double baseElev)
{
var barHeights = new List<double>();
try
{
// 1. 添加第一道横杆(250mm高度)
double firstBarHeight = _isAscending ?
baseElev + FirstBarHeight :
baseElev - FirstBarHeight;
barHeights.Add(firstBarHeight);
// 2. 使用顶部连接盘位置计算最大高度
double maxHeight = _isAscending ?
_topDiskPositions.Values.Max() :
_topDiskPositions.Values.Min();
// 3. 计算1500mm步距序列(关键修复)
double step = _isAscending ? HorizontalBarSpacing : -HorizontalBarSpacing;
int stepCount = 1;
while (true)
{
// 计算当前步距的高度:firstBarHeight + (stepCount * HorizontalBarSpacing)
double currentHeight = _isAscending ?
firstBarHeight + (stepCount * HorizontalBarSpacing) :
firstBarHeight - (stepCount * HorizontalBarSpacing);
// 检查是否超出最大高度(考虑容差)
if (_isAscending && currentHeight > maxHeight + Tolerance)
break;
if (!_isAscending && currentHeight < maxHeight - Tolerance)
break;
// 检查是否接近顶部(保留顶部间隙)
double topGap = _isAscending ?
(maxHeight - currentHeight) :
(currentHeight - maxHeight);
if (topGap < MinTopGap)
break;
barHeights.Add(currentHeight);
stepCount++;
}
}
catch
{
}
return barHeights;
}
// 在指定高度布置横杆
private void PlaceBarsAtHeight(
Transaction tr, BlockTable bt, BlockTableRecord btr,
List<double> poleXPositions, double height)
{
try
{
for (int i = 0; i < poleXPositions.Count - 1; i++)
{
double x1 = poleXPositions[i];
double x2 = poleXPositions[i + 1];
double distance = Math.Abs(x2 - x1);
// 跳过过大的跨度
if (distance > MaxBarDistance) continue;
// 选择最匹配的横杆尺寸
int bestSize = GetBestBarSize(distance);
if (bestSize <= 0) continue;
string blockName = $"ScaffoldPole立横杆{bestSize}mm";
if (!bt.Has(blockName)) continue;
// 声明变量用于记录两端找到的替代高度
double? altHeight1 = null;
double? altHeight2 = null;
double actualHeight = height;
// 检查两端是否都有连接盘(使用放宽的容差)
bool hasDisk1 = HasDiskAtHeight(x1, height, RelaxedTolerance);
bool hasDisk2 = HasDiskAtHeight(x2, height, RelaxedTolerance);
// 如果某端缺少连接盘,尝试向下1000mm内寻找替代位置
if (!hasDisk1 || !hasDisk2)
{
// 尝试在左端向下寻找连接盘
if (!hasDisk1)
{
altHeight1 = FindNearestDiskBelow(x1, height, MaxDiskSearchDistance);
if (altHeight1.HasValue)
{
hasDisk1 = true;
actualHeight = altHeight1.Value;
}
}
// 尝试在右端向下寻找连接盘
if (!hasDisk2)
{
altHeight2 = FindNearestDiskBelow(x2, height, MaxDiskSearchDistance);
if (altHeight2.HasValue)
{
// 如果左端已调整,检查高度是否匹配
if (altHeight1.HasValue && Math.Abs(altHeight2.Value - actualHeight) > RelaxedTolerance)
{
continue;
}
hasDisk2 = true;
actualHeight = altHeight2.Value;
}
}
}
// 确保两端都有连接盘
if (hasDisk1 && hasDisk2)
{
double midX = (x1 + x2) / 2;
// 检查是否在顶部控制线上
if (IsOnTopControlLine(midX, actualHeight)) continue;
InsertBlock(tr, btr, bt, blockName, midX, actualHeight);
}
}
}
catch
{
}
}
// 在顶部立杆圆盘处布置横杆(基于连接盘位置)
private void PlaceTopBarsOnDisks(
Transaction tr, BlockTable bt, BlockTableRecord btr,
List<double> poleXPositions)
{
try
{
for (int i = 0; i < poleXPositions.Count - 1; i++)
{
double x1 = poleXPositions[i];
double x2 = poleXPositions[i + 1];
double distance = Math.Abs(x2 - x1);
if (distance > MaxBarDistance) continue;
// 获取两端顶部连接盘高度
if (!_topDiskPositions.TryGetValue(x1, out double topDisk1) ||
!_topDiskPositions.TryGetValue(x2, out double topDisk2))
{
continue;
}
// 计算高度差
double heightDiff = Math.Abs(topDisk1 - topDisk2);
// 检查高度差是否在允许范围内
if (heightDiff > HeightDifferenceThreshold) continue;
// 使用平均值作为横杆高度
double barHeight = (topDisk1 + topDisk2) / 2.0;
// 检查是否在顶部控制线上
if (IsOnTopControlLine((x1 + x2) / 2.0, barHeight)) continue;
// 选择最匹配的横杆尺寸
int bestSize = GetBestBarSize(distance);
if (bestSize <= 0) continue;
string blockName = $"ScaffoldPole立横杆{bestSize}mm";
if (!bt.Has(blockName)) continue;
// 在跨中位置布置横杆
double midX = (x1 + x2) / 2.0;
InsertBlock(tr, btr, bt, blockName, midX, barHeight);
}
}
catch
{
}
}
// 添加尺寸标注
private void AddDimensions(Transaction tr, BlockTableRecord btr, Database db, double baseElev)
{
try
{
// 1. 标注立杆间距
DimensionPoleSpacing(tr, btr, db, baseElev);
// 2. 标注横杆步距
DimensionBarSpacing(tr, btr, db, baseElev);
}
catch
{
}
}
// 标注立杆间距
private void DimensionPoleSpacing(Transaction tr, BlockTableRecord btr, Database db, double baseElev)
{
if (_poleBasePositions.Count < 2) return;
// 获取所有立杆位置并按X坐标排序
var positions = _poleBasePositions.Keys.OrderBy(x => x).ToList();
// 标注位置在底部控制线下方600mm处
double dimensionY = baseElev - DimensionOffset;
// 标注每个相邻立杆之间的间距
for (int i = 0; i < positions.Count - 1; i++)
{
double x1 = positions[i];
double x2 = positions[i + 1];
double distance = Math.Abs(x2 - x1);
// 创建线性标注
using (AlignedDimension dim = new AlignedDimension())
{
dim.XLine1Point = new Point3d(x1, dimensionY, 0);
dim.XLine2Point = new Point3d(x2, dimensionY, 0);
dim.DimLinePoint = new Point3d((x1 + x2) / 2, dimensionY - 50, 0);
// 设置标注样式
dim.DimensionStyle = db.Dimstyle;
// 添加标注到图形
btr.AppendEntity(dim);
tr.AddNewlyCreatedDBObject(dim, true);
}
}
}
// 标注横杆步距
private void DimensionBarSpacing(Transaction tr, BlockTableRecord btr, Database db, double baseElev)
{
if (_poleBasePositions.Count == 0) return;
// 获取第一个立杆位置
double firstPoleX = _poleBasePositions.Keys.OrderBy(x => x).First();
// 标注位置在立杆左侧600mm处
double dimensionX = firstPoleX - DimensionOffset;
// 计算横杆布置高度序列(250mm起始,1500mm步距)
List<double> barHeights = CalculateBarHeightsForDimension(baseElev);
// 按高度排序
barHeights.Sort();
// 只标注步距(相邻横杆之间的高度差)
for (int i = 0; i < barHeights.Count - 1; i++)
{
double y1 = barHeights[i];
double y2 = barHeights[i + 1];
// 创建线性标注
using (AlignedDimension dim = new AlignedDimension())
{
dim.XLine1Point = new Point3d(dimensionX, y1, 0);
dim.XLine2Point = new Point3d(dimensionX, y2, 0);
// 计算标注线位置(在左侧600mm处)
dim.DimLinePoint = new Point3d(dimensionX - 50, (y1 + y2) / 2, 0);
// 设置标注样式
dim.DimensionStyle = db.Dimstyle;
// 添加标注到图形
btr.AppendEntity(dim);
tr.AddNewlyCreatedDBObject(dim, true);
}
}
}
// 计算用于标注的横杆高度序列(250mm起始,1500mm步距)
private List<double> CalculateBarHeightsForDimension(double baseElev)
{
var barHeights = new List<double>();
try
{
// 1. 添加第一道横杆(250mm高度)
double firstBarHeight = _isAscending ?
baseElev + FirstBarHeight :
baseElev - FirstBarHeight;
barHeights.Add(firstBarHeight);
// 2. 使用顶部连接盘位置计算最大高度
double maxHeight = _isAscending ?
_topDiskPositions.Values.Max() :
_topDiskPositions.Values.Min();
// 3. 计算1500mm步距序列
double step = _isAscending ? HorizontalBarSpacing : -HorizontalBarSpacing;
int stepCount = 1;
while (true)
{
// 计算当前步距的高度:firstBarHeight + (stepCount * HorizontalBarSpacing)
double currentHeight = _isAscending ?
firstBarHeight + (stepCount * HorizontalBarSpacing) :
firstBarHeight - (stepCount * HorizontalBarSpacing);
// 检查是否超出最大高度(考虑容差)
if (_isAscending && currentHeight > maxHeight + Tolerance)
break;
if (!_isAscending && currentHeight < maxHeight - Tolerance)
break;
// 检查是否接近顶部(保留顶部间隙)
double topGap = _isAscending ?
(maxHeight - currentHeight) :
(currentHeight - maxHeight);
if (topGap < MinTopGap)
break;
barHeights.Add(currentHeight);
stepCount++;
}
}
catch
{
}
return barHeights;
}
// 检查在指定位置和高度是否存在连接盘
private bool HasDiskAtHeight(double x, double height, double tolerance)
{
if (!_diskPositions.TryGetValue(x, out List<double> heights))
return false;
// 检查是否有高度在[height-tolerance, height+tolerance]范围内
return heights.Any(h => Math.Abs(h - height) <= tolerance);
}
// 在指定位置向下寻找最近的连接盘
private double? FindNearestDiskBelow(double x, double height, double maxDistance)
{
if (!_diskPositions.TryGetValue(x, out List<double> heights))
return null;
// 筛选在高度以下(考虑方向)的连接盘
var belowHeights = heights
.Where(h =>
(_isAscending && h <= height) || // 如果是上升,则找height以下的
(!_isAscending && h >= height)) // 如果是下降,则找height以上的(因为高度递减)
.ToList();
if (!belowHeights.Any())
return null;
// 计算与目标高度的距离(取绝对值)
var closest = belowHeights
.OrderBy(h => Math.Abs(h - height))
.First();
// 检查是否在最大搜索距离内
if (Math.Abs(closest - height) <= maxDistance)
return closest;
return null;
}
// 获取最佳横杆尺寸
private int GetBestBarSize(double distance)
{
if (distance <= 0) return 0;
int[] validSizes = { 300, 600, 900, 1200, 1500, 1800 };
return validSizes
.Where(s => s >= distance * 0.8 && s <= distance * 1.2) // 允许20%误差
.OrderBy(s => Math.Abs(s - distance))
.FirstOrDefault();
}
// 获取指定X坐标在控制线上的Y值
private double GetElevationAtX(double x)
{
if (_topControlLine == null) return 0;
try
{
if (_topControlLine is Line line)
{
Vector3d direction = line.EndPoint - line.StartPoint;
if (Math.Abs(direction.X) < 0.001) return line.StartPoint.Y;
double t = (x - line.StartPoint.X) / direction.X;
return line.StartPoint.Y + t * direction.Y;
}
if (_topControlLine is Polyline pline)
{
for (int i = 0; i < pline.NumberOfVertices - 1; i++)
{
Point3d start = pline.GetPoint3dAt(i);
Point3d end = pline.GetPoint3dAt(i + 1);
if ((x >= start.X && x <= end.X) || (x <= start.X && x >= end.X))
{
if (Math.Abs(end.X - start.X) < 0.001) return start.Y;
double t = (x - start.X) / (end.X - start.X);
return start.Y + t * (end.Y - start.Y);
}
}
return pline.GetPoint3dAt(0).Y;
}
}
catch
{
}
return 0;
}
// 插入图块
private void InsertBlock(Transaction tr, BlockTableRecord btr, BlockTable bt, string blockName, double x, double y)
{
if (!bt.Has(blockName)) return;
try
{
BlockReference bref = new BlockReference(new Point3d(x, y, 0), bt[blockName]);
btr.AppendEntity(bref);
tr.AddNewlyCreatedDBObject(bref, true);
}
catch
{
}
}
}
}
CS0103当前上下文中不存在名称“IsOnTopControlLine”
CS0103当前上下文中不存在名称“IsOnTopControlLine”
t添加标注引线600mm长
最新发布