debug 的三种单布执行方式(step)

本文介绍了在调试过程中使用的三种单步调试技巧:单步进入、单步跳跃与单步跳出。详细解释了它们在不同场景下的应用,并通过图标比喻帮助理解各自的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单步进入(Step Into)

一次执行一个语句

当不是在设计模式(程序正在建立的状态,比如添加项目),单布进入阻塞模式在当前执行的行,如果该语句是一个过程的调用,那么下一条出现的语句是这个过程的第一条语句。

在设计时间段,菜单项开始执行并在第一行代码执行前进入阻塞模式。
如果当前没有可执行的点,单布进入模式可能什么都不做,直到你做了什么触发代码,比如点击了一个文按钮。
我们可以用这个图标来比拟:

单步跳跃(Step Over)

与单步进入相似,在使用上的不同是当出现当前过程包含一个过程的调用。

单步跳跃将过程作为一个单元执行,然后会转移到当前过程的下一条语句。因此,下一条出现语句是就是当前过程的下一步,不管当前语句是否调用其他的过程,仅在阻塞模式。
我们可以用这个图标来比拟:这里写图片描述

单布跳出 (Step Out)

与单步进入相反
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.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; // 使用别名解决 Exception 冲突 using SysException = System.Exception; using AecException = Autodesk.AutoCAD.Runtime.Exception; namespace ScaffoldPlugin { public class ScaffoldCommands { #region 常量配置 // 杆件长度配置 private static readonly double[] BarLengths = { 300, 600, 900, 1200, 1500, 1800 }; // 斜拉杆长度配置 private static readonly double[] DiagonalBarLengths = { 600, 900, 1200, 1500, 1800 }; // 块目录路径 private static readonly string BlockDirectory = Path.Combine( Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ScaffoldBlocks"); // 容差参数 private const double ToleranceValue = 0.1; private const double SpacingTolerance = 150.0; private const double MinAxisLength = 100.0; private const double MinDistanceForBar = 50.0; private const double MaxGapFactor = 1.2; private const double SkipTolerance = 1.0; // 块名称定义 private const string PoleBlockName = "ScaffoldPole立杆"; private const string BarPrefix = "ScaffoldPole横杆"; private const string DiagonalBarPrefix = "ScaffoldPolexie水平斜拉杆"; // 图层定义 private const string PoleLayer = "盘扣-立杆"; private const string BarLayer = "盘扣-横杆"; private const string DiagonalBarLayer = "盘扣-斜杆"; private const string AxisLayer = "盘扣轴网"; private const string DebugLayer = "盘扣-调试"; // 材料统计块名 private static readonly string[] TargetBlockNames = { "ScaffoldPole横杆300mm", "ScaffoldPole横杆600mm", "ScaffoldPole横杆900mm", "ScaffoldPole横杆1200mm", "ScaffoldPole横杆1500mm", "ScaffoldPole横杆1800mm", "ScaffoldPolexie水平斜拉杆600mm", "ScaffoldPolexie水平斜拉杆900mm", "ScaffoldPolexie水平斜拉杆1200mm", "ScaffoldPolexie水平斜拉杆1500mm", "ScaffoldPolexie水平斜拉杆1800mm", "ScaffoldPole立杆" }; #endregion #region BP命令 - 置脚手架杆件 [CommandMethod("BuildPlatform", "BP", CommandFlags.Modal)] public void BuildPlatform() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { // 用户确认对话框 if (!ConfirmWithUser(ed, "⚠️ 框选置杆件数量建议不要超过40000个\n是否继续?")) return; // 检查块目录 if (!CheckBlockDirectory()) return; // 创建必要图层 CreateLayers(db); // 选择轴网线 var axisLines = GetAxisLines(ed); if (axisLines.Count == 0) return; // 计算交点 List<Point3d> intersections = CalculateIntersections(axisLines); ed.WriteMessage($"\n共找到 {intersections.Count} 个有效交点"); // 加载块定义 if (!LoadBlockDefinitions(db, ed)) return; // 缓存现有实体 BuildExistingEntityCache(db); // 置立杆 int poleCount = PlacePoles(db, intersections, ed); ed.WriteMessage($"\n已置 {poleCount} 根立杆"); // 置横杆 int barCount = PlaceBars(db, intersections, axisLines, ed); ed.WriteMessage($"\n已置 {barCount} 根横杆"); // 结果反馈 if (poleCount > 0 || barCount > 0) { Application.ShowAlertDialog($"成功置 {poleCount}根立杆和{barCount}根横杆!"); } else { ShowErrorDialog("脚手架置失败,未置任何构件!"); } } catch (AecException ex) // 使用别名处理AutoCAD异常 { HandleException(ed, ex); } catch (SysException ex) // 使用别名处理.NET异常 { HandleException(ed, ex); } } #endregion #region BD命令 - 置斜拉杆 [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); // 青色 // 步骤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; // 加载斜拉杆块定义 if (!LoadDiagonalBlockDefinitions(db, ed)) return; // 缓存现有实体 BuildExistingEntityCache(db); using (Transaction tr = db.TransactionManager.StartTransaction()) { // 收集所有横杆信息 var beams = CollectBeams(db, selResult, tr); if (beams.Count == 0) { ed.WriteMessage("\n未找到有效的横杆图块"); return; } // 按模式置斜拉杆 int diagonalCount = PlaceDiagonalBars(db, tr, beams, mode); tr.Commit(); ed.WriteMessage($"\n成功置 {diagonalCount} 根斜拉杆"); } } catch (AecException ex) { HandleException(ed, ex); } catch (SysException ex) { HandleException(ed, ex); } } 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.AllowNone = false; pko.AppendKeywordsToMessage = true; PromptResult pr = ed.GetKeywords(pko); if (pr.Status != PromptStatus.OK) return 0; return int.Parse(pr.StringResult); } private bool LoadDiagonalBlockDefinitions(Database db, Editor ed) { using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; // 加载斜拉杆块 foreach (double len in DiagonalBarLengths) { string blockName = $"{DiagonalBarPrefix}{len}mm"; string blockPath = Path.Combine(BlockDirectory, $"{blockName}.dwg"); if (!File.Exists(blockPath)) { ed.WriteMessage($"\n斜拉杆块文件未找到: {blockPath}"); continue; } if (!bt.Has(blockName)) { LoadBlockFromFile(db, blockPath, blockName); ed.WriteMessage($"\n已加载斜拉杆块: {blockName}"); } } tr.Commit(); return true; } } private List<(BlockReference Block, double Length)> CollectBeams(Database db, PromptSelectionResult selResult, Transaction tr) { var beams = new List<(BlockReference, double)>(); BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); foreach (ObjectId objId in selResult.Value.GetObjectIds()) { if (objId.ObjectClass.Name != "AcDbBlockReference") continue; BlockReference br = (BlockReference)tr.GetObject(objId, OpenMode.ForRead); BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForRead); // 检查是否是横杆图块 string blockName = btr.Name.ToUpper(); if (blockName.Contains("HORIZONTAL") || blockName.Contains("BEAM") || blockName.Contains("横杆")) { double length = GetBeamLength(br); if (length > 0) beams.Add((br, length)); } } return beams; } // 新增:获取横杆长度的方法 private double GetBeamLength(BlockReference br) { try { // 获取图块的几何范围 Extents3d ext = br.GeometricExtents; // 计算包围盒的宽度(X方向) double width = ext.MaxPoint.X - ext.MinPoint.X; // 计算包围盒的高度(Y方向) double height = ext.MaxPoint.Y - ext.MinPoint.Y; // 横杆通常是沿一个方向延伸的,取最大值作为长度 return Math.Max(width, height); } catch { return 0; } } private int PlaceDiagonalBars(Database db, Transaction tr, List<(BlockReference Block, double Length)> beams, int mode) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord; BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; // 按Y坐标分组并排序 var groups = beams .GroupBy(b => Math.Round(b.Block.Position.Y, 2)) .OrderBy(g => g.Key) .ToList(); if (groups.Count < 2) { Application.ShowAlertDialog("至少需要两排横杆才能置斜拉杆!"); return 0; } int diagonalCount = 0; int step = mode + 1; // 1=隔一(每2跨), 2=隔二(每3跨), 3=隔三(每4跨) for (int i = 0; i < groups.Count - 1; i++) { var currentRow = groups[i].OrderBy(b => b.Block.Position.X).ToList(); var nextRow = groups[i + 1].OrderBy(b => b.Block.Position.X).ToList(); // 计算起始偏移量 int startOffset = i % step; for (int j = startOffset; j < currentRow.Count - 1; j += step) { if (j >= nextRow.Count - 1) continue; // 获取当前网格四个角点 Point3d topLeft = currentRow[j].Block.Position; Point3d topRight = currentRow[j + 1].Block.Position; Point3d bottomLeft = nextRow[j].Block.Position; Point3d bottomRight = nextRow[j + 1].Block.Position; // 计算对角线长度 Vector3d diagonal1 = bottomRight - topLeft; double length1 = diagonal1.Length; Vector3d diagonal2 = bottomLeft - topRight; double length2 = diagonal2.Length; // 选择较短的对角线 bool useDiagonal1 = length1 <= length2; double requiredLength = useDiagonal1 ? length1 : length2; Vector3d diagonal = useDiagonal1 ? diagonal1 : diagonal2; Point3d startPoint = useDiagonal1 ? topLeft : topRight; // 获取最接近的标准长度 string lengthKey = GetClosestDiagonalLength(requiredLength); string blockName = $"{DiagonalBarPrefix}{lengthKey}mm"; if (!bt.Has(blockName)) { Application.ShowAlertDialog($"斜拉杆块 {blockName} 未加载!"); continue; } ObjectId blockId = bt[blockName]; // 计算中点 Point3d midPoint = new Point3d( (startPoint.X + (startPoint.X + diagonal.X) / 2), (startPoint.Y + (startPoint.Y + diagonal.Y) / 2), 0); // 计算旋转角度 double angle = diagonal.AngleOnPlane(new Plane(Point3d.Origin, Vector3d.ZAxis)); // 检查是否已存在相同位置的斜杆 if (IsCached(blockName, midPoint, angle)) continue; // 创建斜杆图块引用 BlockReference br = new BlockReference(midPoint, blockId); br.Layer = DiagonalBarLayer; br.Rotation = angle; // 添加到图形 btr.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); diagonalCount++; } } return diagonalCount; } private string GetClosestDiagonalLength(double actualLength) { double minDiff = double.MaxValue; double closestLength = 600; // 默认值 foreach (double len in DiagonalBarLengths) { double diff = Math.Abs(len - actualLength); if (diff < minDiff) { minDiff = diff; closestLength = len; } } return closestLength.ToString(); } #endregion #region BPS命令 - 材料统计 [CommandMethod("GenerateMaterialStats", "BPS", CommandFlags.Modal)] public void GenerateMaterialStats() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { // 选择要统计的块参照 PromptSelectionResult res = ed.GetSelection(new SelectionFilter(new TypedValue[] { new TypedValue(0, "INSERT") })); if (res.Status != PromptStatus.OK) { ed.WriteMessage("\n未选择对象或操作取消"); return; } // 统计块数量 Dictionary<string, int> stats = CountBlocks(db, res.Value.GetObjectIds()); if (stats.Count == 0) { ed.WriteMessage("\n选定区域中没有可统计的杆件"); return; } // 构建表格数据 List<TableRowData> tableData = BuildTableData(stats); // 插入统计表格 InsertStatTable(db, ed, tableData); ed.WriteMessage("\n材料统计表已成功插入!"); } catch (AecException ex) { HandleException(ed, ex); } catch (SysException ex) { HandleException(ed, ex); } } #endregion #region BP命令辅助方法 private bool ConfirmWithUser(Editor ed, string message) { PromptKeywordOptions options = new PromptKeywordOptions(message); options.Keywords.Add("Y"); options.Keywords.Add("N"); options.AllowNone = false; return ed.GetKeywords(options).StringResult == "Y"; } private bool CheckBlockDirectory() { if (!Directory.Exists(BlockDirectory)) { Directory.CreateDirectory(BlockDirectory); ShowErrorDialog($"块目录已创建: {BlockDirectory}\n请添加块文件后重新运行命令"); return false; } return true; } private void CreateLayers(Database db) { CreateLayerIfNotExists(db, PoleLayer, 7); // 白色 CreateLayerIfNotExists(db, BarLayer, 1); // 红色 CreateLayerIfNotExists(db, DiagonalBarLayer, 4); // 青色 CreateLayerIfNotExists(db, AxisLayer, 3); // 绿色 CreateLayerIfNotExists(db, DebugLayer, 2); // 黄色 } private List<Line> GetAxisLines(Editor ed) { var filter = new SelectionFilter(new[] { new TypedValue(0, "LINE"), new TypedValue(8, AxisLayer) }); PromptSelectionResult selection = ed.GetSelection( new PromptSelectionOptions { MessageForAdding = "\n选择盘扣轴网线: " }, filter ); if (selection.Status != PromptStatus.OK) return new List<Line>(); List<Line> lines = new List<Line>(); using (Transaction tr = ed.Document.TransactionManager.StartTransaction()) { foreach (ObjectId id in selection.Value.GetObjectIds()) { Line line = tr.GetObject(id, OpenMode.ForRead) as Line; if (line != null && line.Length > MinAxisLength) { lines.Add(line.Clone() as Line); } } tr.Commit(); } ed.WriteMessage($"\n已选择 {lines.Count} 条有效轴网线"); return lines; } private List<Point3d> CalculateIntersections(List<Line> lines) { var results = new HashSet<Point3d>(new Point3dComparer(ToleranceValue)); for (int i = 0; i < lines.Count; i++) { for (int j = i + 1; j < lines.Count; j++) { Point3dCollection pts = new Point3dCollection(); lines[i].IntersectWith(lines[j], Intersect.OnBothOperands, pts, IntPtr.Zero, IntPtr.Zero); foreach (Point3d pt in pts) { if (IsPointOnLineSegment(pt, lines[i], ToleranceValue) && IsPointOnLineSegment(pt, lines[j], ToleranceValue)) { results.Add(pt); } } } } return results.ToList(); } private bool IsPointOnLineSegment(Point3d pt, Line line, double tolerance) { Vector3d lineVec = line.EndPoint - line.StartPoint; Vector3d startToPt = pt - line.StartPoint; double dotProduct = lineVec.DotProduct(startToPt); if (dotProduct < -tolerance || dotProduct > lineVec.LengthSqrd + tolerance) return false; double distSq = startToPt.LengthSqrd - (dotProduct * dotProduct) / lineVec.LengthSqrd; return distSq <= tolerance * tolerance; } private bool LoadBlockDefinitions(Database db, Editor ed) { using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; // 加载立杆块 string polePath = Path.Combine(BlockDirectory, $"{PoleBlockName}.dwg"); if (!File.Exists(polePath)) { ShowErrorDialog($"立杆块文件未找到: {polePath}"); return false; } if (!bt.Has(PoleBlockName)) { LoadBlockFromFile(db, polePath, PoleBlockName); ed.WriteMessage($"\n已加载立杆块: {PoleBlockName}"); } // 加载横杆块 foreach (double len in BarLengths) { string barName = $"{BarPrefix}{len}mm"; string barPath = Path.Combine(BlockDirectory, $"{barName}.dwg"); if (!bt.Has(barName) && File.Exists(barPath)) { LoadBlockFromFile(db, barPath, barName); ed.WriteMessage($"\n已加载横杆块: {barName}"); } } tr.Commit(); return true; } } private void LoadBlockFromFile(Database db, string filePath, string blockName) { using (Database sourceDb = new Database(false, true)) { sourceDb.ReadDwgFile(filePath, FileOpenMode.OpenForReadAndAllShare, false, null); db.Insert(blockName, sourceDb, true); } } private void BuildExistingEntityCache(Database db) { _existingEntitiesCache = new HashSet<(string, Point3d, double)>(new EntityKeyComparer()); using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTableRecord btr = tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead) as BlockTableRecord; foreach (ObjectId id in btr) { BlockReference br = tr.GetObject(id, OpenMode.ForRead) as BlockReference; if (br != null && (br.Name == PoleBlockName || br.Name.StartsWith(BarPrefix) || br.Name.StartsWith(DiagonalBarPrefix))) { _existingEntitiesCache.Add((br.Name, br.Position, br.Rotation)); } } } } private int PlacePoles(Database db, List<Point3d> points, Editor ed) { int count = 0; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord btr = tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite) as BlockTableRecord; if (!bt.Has(PoleBlockName)) { ShowErrorDialog($"错误:立杆块 {PoleBlockName} 未加载!"); return 0; } ObjectId poleBlockId = bt[PoleBlockName]; foreach (Point3d pt in points) { if (double.IsNaN(pt.X) || double.IsNaN(pt.Y)) continue; if (IsCached(PoleBlockName, pt, 0)) continue; BlockReference br = new BlockReference(pt, poleBlockId); br.Layer = PoleLayer; btr.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); count++; } tr.Commit(); } return count; } private int PlaceBars(Database db, List<Point3d> points, List<Line> axisLines, Editor ed) { int count = 0; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord btr = tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite) as BlockTableRecord; foreach (Line axisLine in axisLines) { List<Point3d> linePoints = points.Where(p => IsPointOnLineSegment(p, axisLine, ToleranceValue)).ToList(); if (linePoints.Count < 2) continue; linePoints = SortPointsByLineParam(axisLine, linePoints); List<Segment> segments = GroupPointsIntoSegments(linePoints); foreach (Segment segment in segments) { for (int i = 0; i < segment.Points.Count - 1; i++) { Point3d start = segment.Points[i]; Point3d end = segment.Points[i + 1]; double distance = start.DistanceTo(end); if (distance < MinDistanceForBar) continue; double bestLength = FindBestBarLength(distance); if (bestLength < 0) continue; string blockName = $"{BarPrefix}{bestLength}mm"; if (!bt.Has(blockName)) continue; Point3d midPoint = new Point3d( (start.X + end.X) / 2, (start.Y + end.Y) / 2, (start.Z + end.Z) / 2); Vector3d direction = (end - start).GetNormal(); double angle = Math.Atan2(direction.Y, direction.X); if (IsCached(blockName, midPoint, angle)) continue; BlockReference br = new BlockReference(midPoint, bt[blockName]); br.Layer = BarLayer; br.Rotation = angle; btr.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); count++; } } } tr.Commit(); } return count; } private double FindBestBarLength(double distance) { double bestLength = -1; double minDiff = double.MaxValue; foreach (double len in BarLengths) { double diff = Math.Abs(len - distance); if (diff < minDiff && diff <= SpacingTolerance) { minDiff = diff; bestLength = len; } } return bestLength; } private List<Point3d> SortPointsByLineParam(Line line, List<Point3d> points) { Vector3d lineVec = line.EndPoint - line.StartPoint; double lineLength = lineVec.Length; return points .Select(p => new { Point = p, Param = lineVec.DotProduct(p - line.StartPoint) / lineLength }) .OrderBy(x => x.Param) .Select(x => x.Point) .ToList(); } private List<Segment> GroupPointsIntoSegments(List<Point3d> points) { List<Segment> segments = new List<Segment>(); if (points.Count < 2) return segments; double maxGap = BarLengths.Max() * MaxGapFactor; Segment currentSegment = new Segment { Points = { points[0] } }; for (int i = 1; i < points.Count; i++) { double distance = points[i - 1].DistanceTo(points[i]); if (distance > maxGap) { if (currentSegment.Points.Count > 1) segments.Add(currentSegment); currentSegment = new Segment { Points = { points[i] } }; } else { currentSegment.Points.Add(points[i]); } } if (currentSegment.Points.Count > 1) segments.Add(currentSegment); return segments; } private void CreateLayerIfNotExists(Database db, string layerName, short colorIndex) { using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable; if (lt.Has(layerName)) return; lt.UpgradeOpen(); LayerTableRecord ltr = new LayerTableRecord { Name = layerName, Color = Color.FromColorIndex(ColorMethod.ByAci, colorIndex) }; lt.Add(ltr); tr.AddNewlyCreatedDBObject(ltr, true); tr.Commit(); } } private bool IsCached(string blockName, Point3d pos, double angle) { return _existingEntitiesCache?.Contains((blockName, pos, angle)) ?? false; } #endregion #region BPS命令辅助方法 private Dictionary<string, int> CountBlocks(Database db, ObjectId[] ids) { var stats = new Dictionary<string, int>(); using (Transaction tr = db.TransactionManager.StartTransaction()) { foreach (ObjectId id in ids) { BlockReference br = tr.GetObject(id, OpenMode.ForRead) as BlockReference; if (br == null || !TargetBlockNames.Contains(br.Name)) continue; stats[br.Name] = stats.TryGetValue(br.Name, out int count) ? count + 1 : 1; } tr.Commit(); } return stats; } private List<TableRowData> BuildTableData(Dictionary<string, int> stats) { var tableData = new List<TableRowData>(); foreach (string blockName in TargetBlockNames) { string materialName = "其他"; if (blockName.Contains("横杆")) materialName = "横杆"; else if (blockName.Contains("斜拉杆")) materialName = "斜拉杆"; else if (blockName.Contains("立杆")) materialName = "立杆"; string length = Regex.Match(blockName, @"\d+").Value; string quantity = stats.TryGetValue(blockName, out int count) ? count.ToString() : "0"; tableData.Add(new TableRowData { MaterialName = materialName, Length = length, Quantity = quantity }); } return tableData; } private void InsertStatTable(Database db, Editor ed, List<TableRowData> data) { using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTableRecord btr = tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite) as BlockTableRecord; // 获取表格插入点 PromptPointResult ppr = ed.GetPoint("\n请选择表格插入点: "); if (ppr.Status != PromptStatus.OK) return; Point3d insertPoint = ppr.Value; // 创建表格对象 Table table = new Table(); table.Position = insertPoint; table.SetSize(data.Count + 2, 4); // 标题行+表头行+数据行 table.SetRowHeight(3.0); table.SetColumnWidth(0, 6.0); table.SetColumnWidth(1, 18.0); table.SetColumnWidth(2, 18.0); table.SetColumnWidth(3, 18.0); table.Layer = "0"; // 合并标题行元格 table.MergeCells(CellRange.Create(table, 0, 0, 0, 3)); // 设置标题行 table.Cells[0, 0].TextString = "平面盘扣置材料统计表"; table.Cells[0, 0].Alignment = CellAlignment.MiddleCenter; table.Cells[0, 0].TextHeight = 3.0; // 设置表头行 table.Cells[1, 0].TextString = "序号"; table.Cells[1, 1].TextString = "材料名称"; table.Cells[1, 2].TextString = "杆件长度(mm)"; table.Cells[1, 3].TextString = "合计数量/根"; // 设置表头样式 for (int col = 0; col < 4; col++) { table.Cells[1, col].Alignment = CellAlignment.MiddleCenter; table.Cells[1, col].TextHeight = 2.5; } // 填充数据行 for (int i = 0; i < data.Count; i++) { int row = i + 2; table.Cells[row, 0].TextString = (i + 1).ToString(); table.Cells[row, 1].TextString = data[i].MaterialName; table.Cells[row, 2].TextString = data[i].Length; table.Cells[row, 3].TextString = data[i].Quantity; // 设置数据行样式 table.Cells[row, 0].Alignment = CellAlignment.MiddleCenter; table.Cells[row, 1].Alignment = CellAlignment.MiddleLeft; table.Cells[row, 2].Alignment = CellAlignment.MiddleLeft; table.Cells[row, 3].Alignment = CellAlignment.MiddleLeft; table.Cells[row, 0].TextHeight = 2.5; } btr.AppendEntity(table); tr.AddNewlyCreatedDBObject(table, true); tr.Commit(); } } #endregion #region 通用辅助方法 private void ShowErrorDialog(string message) { Application.ShowAlertDialog(message); } private void HandleException(Editor ed, SysException ex) { string errorType = ".NET"; ed.WriteMessage($"\n{errorType}错误: {ex.Message}"); ShowErrorDialog($"发生{errorType}异常: {ex.Message}\n详细请查看命令行日志"); } private void HandleException(Editor ed, AecException ex) { string errorType = "AutoCAD"; ed.WriteMessage($"\n{errorType}错误: {ex.Message} (状态: {ex.ErrorStatus})"); ShowErrorDialog($"发生{errorType}异常: {ex.Message}\n详细请查看命令行日志"); } #endregion #region 数据结构 private class TableRowData { public string MaterialName { get; set; } public string Length { get; set; } public string Quantity { get; set; } } private class Segment { public List<Point3d> Points { get; set; } = new List<Point3d>(); } 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) => p.X.GetHashCode() ^ p.Y.GetHashCode() ^ p.Z.GetHashCode(); } private class EntityKeyComparer : IEqualityComparer<(string, Point3d, double)> { public bool Equals((string, Point3d, double) x, (string, Point3d, double) y) => x.Item1 == y.Item1 && x.Item2.DistanceTo(y.Item2) < SkipTolerance && Math.Abs(x.Item3 - y.Item3) < 0.01; public int GetHashCode((string, Point3d, double) obj) => obj.Item1.GetHashCode() ^ obj.Item2.GetHashCode() ^ obj.Item3.GetHashCode(); } private HashSet<(string blockName, Point3d pos, double angle)> _existingEntitiesCache; #endregion } } 置的斜拉杆不显示
07-10
<think>根据提供的代码,斜拉杆的置在`BD`命令中实现。斜拉杆不显示的可能原因包括: 1. 图层问题:斜拉杆被放置在`DiagonalBarLayer`("盘扣-斜杆")图层,该图层可能被关闭或冻结。 2. 块定义问题:斜拉杆块未正确加载,导致插入的块参照无效。 3. 插入点或旋转角度计算错误,导致块不在预期位置。 4. 块定义本身的问题:块中没有可见的几何图形。 让我们检查代码中与斜拉杆置相关的部分: 在`BuildDiagonal`方法中: - 首先创建了斜杆图层(如果不存在)。 - 然后加载斜拉杆块定义(在`LoadDiagonalBlockDefinitions`方法中)。 - 接着收集选择的横杆图块,按行分组。 - 最后在相邻两排横杆之间按模式(隔一一、隔二一等)置斜拉杆。 在置斜拉杆时,代码计算两个横杆之间的网格的对角线,然后选择较短的对角线作为斜拉杆的位置和方向。斜拉杆的插入点是对角线的中点,旋转角度是向量的角度。 为了解决斜拉杆不显示的问题,我们可以采取以下步骤: 1. **检查图层状态**:确保"盘扣-斜杆"图层是打开且解冻的。 2. **检查块定义**:确保斜拉杆块(如"ScaffoldPolexie水平斜拉杆600mm"等)已经正确加载到当前图形中。可以通过`INSERT`命令查看块列表。 3. **检查插入点和旋转角度**:在代码中,斜拉杆的插入点是对角线的中点。我们可以通过添加调试图形(如点或线)来验证这些点的位置是否正确。 4. **检查块定义内容**:打开块文件(位于`ScaffoldBlocks`目录下的dwg文件),确认块中有可见的图形。 为了辅助调试,我们可以在代码中临时添加一些调试图形(例如在中点处画点,或画出对角线)来观察。 修改`PlaceDiagonalBars`方法,在插入斜拉杆的同时,在调试图层上绘制一个点(在中点)和一条线(对角线)。这样可以帮助我们判断计算是否正确。 以下是修改后的`PlaceDiagonalBars`方法的部分代码(在创建斜拉杆块参照之前): ```csharp // ... 原有代码 ... // 计算中点 Point3d midPoint = new Point3d( (startPoint.X + (startPoint.X + diagonal.X) / 2), (startPoint.Y + (startPoint.Y + diagonal.Y) / 2), 0); // 计算旋转角度 double angle = diagonal.AngleOnPlane(new Plane(Point3d.Origin, Vector3d.ZAxis)); // 检查是否已存在相同位置的斜杆 if (IsCached(blockName, midPoint, angle)) continue; // 调试:绘制中点和对角线 using (Line debugLine = new Line(startPoint, startPoint + diagonal)) { debugLine.Layer = DebugLayer; debugLine.ColorIndex = 2; // 黄色 btr.AppendEntity(debugLine); tr.AddNewlyCreatedDBObject(debugLine, true); } using (DBPoint debugPoint = new DBPoint(midPoint)) { debugPoint.Layer = DebugLayer; debugPoint.ColorIndex = 1; // 红色 btr.AppendEntity(debugPoint); tr.AddNewlyCreatedDBObject(debugPoint, true); } // 创建斜杆图块引用 BlockReference br = new BlockReference(midPoint, blockId); br.Layer = DiagonalBarLayer; br.Rotation = angle; // ... 原有代码 ... ``` 注意:需要确保调试图层(`DebugLayer`,即"盘扣-调试")已经创建,并且在视图中可见。 另外,在`CreateLayers`方法中已经创建了调试图层(黄色),所以应该可以直接使用。 这样,在运行`BD`命令后,我们可以在图形中看到黄色的对角线(网格的对角线)和红色的中点(斜拉杆插入点)。如果这些点和线显示正确,但斜拉杆块不显示,则问题可能出在块本身。如果这些点和线没有显示,则说明计算有问题。 另外,还需要注意:在计算中点时,原代码中使用了两次起点坐标,这可能是错误的。正确的计算应该是: ```csharp Point3d midPoint = new Point3d( (startPoint.X + (startPoint.X + diagonal.X)) / 2, // 这样写实际上等于 (2*startPoint.X + diagonal.X)/2 (startPoint.Y + (startPoint.Y + diagonal.Y)) / 2, 0); ``` 实际上,对角线的终点是`startPoint + diagonal`,所以中点应该是起点和终点的中点: ```csharp Point3d endPoint = startPoint + diagonal; Point3d midPoint = new Point3d( (startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2, 0); ``` 因此,我们需要修正中点计算。 修正后的代码: ```csharp Point3d endPoint = startPoint + diagonal; Point3d midPoint = new Point3d( (startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2, 0); ``` 同时,在调试绘制对角线时,我们使用`startPoint`和`endPoint`来画线。 总结修改步骤: 1. 修正中点计算。 2. 添加调试图形(可选,用于验证)。 3. 确保块定义正确。 如果问题仍然存在,请检查块定义的位和插入比例。 由于代码较长,这里只给出修改后的`PlaceDiagonalBars`方法中关键部分的代码: ```csharp // ... 原有代码 ... // 选择较短的对角线 bool useDiagonal1 = length1 <= length2; double requiredLength = useDiagonal1 ? length1 : length2; Vector3d diagonal = useDiagonal1 ? diagonal1 : diagonal2; Point3d startPoint = useDiagonal1 ? topLeft : topRight; Point3d endPoint = startPoint + diagonal; // 计算终点 // 获取最接近的标准长度 string lengthKey = GetClosestDiagonalLength(requiredLength); string blockName = $"{DiagonalBarPrefix}{lengthKey}mm"; if (!bt.Has(blockName)) { Application.ShowAlertDialog($"斜拉杆块 {blockName} 未加载!"); continue; } ObjectId blockId = bt[blockName]; // 计算中点 Point3d midPoint = new Point3d( (startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2, 0); // 计算旋转角度 double angle = diagonal.AngleOnPlane(new Plane(Point3d.Origin, Vector3d.ZAxis)); // 检查是否已存在相同位置的斜杆 if (IsCached(blockName, midPoint, angle)) continue; // 调试:绘制中点和对角线(可选) // 注意:在发版本中应移除或注释掉调试图形 using (Line debugLine = new Line(startPoint, endPoint)) { debugLine.Layer = DebugLayer; debugLine.ColorIndex = 2; // 黄色 btr.AppendEntity(debugLine); tr.AddNewlyCreatedDBObject(debugLine, true); } using (DBPoint debugPoint = new DBPoint(midPoint)) { debugPoint.Layer = DebugLayer; debugPoint.ColorIndex = 1; // 红色 btr.AppendEntity(debugPoint); tr.AddNewlyCreatedDBObject(debugPoint, true); } // 创建斜杆图块引用 BlockReference br = new BlockReference(midPoint, blockId); br.Layer = DiagonalBarLayer; br.Rotation = angle; // ... 原有代码 ... ``` 注意:调试图形可能会影响性能,所以在确认问题后应移除或通过条件编译控制。 如果上述修改后斜拉杆仍然不显示,请进一步检查: - 块定义中是否有可见的图形?是否有在0层上绘制?颜色、线型等是否设置正确? - 块插入时的比例和旋转是否导致图形不可见? 另外,确保在`BuildDiagonal`方法中调用了`CreateLayerIfNotExists(db, DiagonalBarLayer, 4);`以创建斜杆图层。 如果问题仍然无法解决,请提供更多信息,例如: - 斜拉杆块文件(dwg)的内容。 - 图形中是否生成了调试图形(黄色的对角线和红色的中点)? 希望这些修改能解决问题。</think>您的代码中存在一个关键问题:斜拉杆不显示的原因是它们在置过程中没有正确插入到图形中。问题主要出在`PlaceDiagonalBars`方法中。以下是修复方案: ### 问题分析 1. **块定义加载问题**:斜拉杆块可能未正确加载 2. **块参照创建问题**:块参照创建后未添加到模型空间 3. **旋转角度计算问题**:角度计算未考虑对角线的实际方向 4. **位置计算问题**:中点位置计算有误 ### 修复后的`PlaceDiagonalBars`方法 ```csharp private int PlaceDiagonalBars(Database db, Transaction tr, List<(BlockReference Block, double Length)> beams, int mode) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); // 按Y坐标分组并排序 var groups = beams .GroupBy(b => Math.Round(b.Block.Position.Y, 2)) .OrderBy(g => g.Key) .ToList(); if (groups.Count < 2) { Application.ShowAlertDialog("至少需要两排横杆才能置斜拉杆!"); return 0; } int diagonalCount = 0; int step = mode + 1; // 1=隔一(每2跨), 2=隔二(每3跨), 3=隔三(每4跨) for (int i = 0; i < groups.Count - 1; i++) { var currentRow = groups[i].OrderBy(b => b.Block.Position.X).ToList(); var nextRow = groups[i + 1].OrderBy(b => b.Block.Position.X).ToList(); // 计算起始偏移量 int startOffset = i % step; for (int j = startOffset; j < currentRow.Count - 1; j += step) { if (j >= nextRow.Count - 1) continue; // 获取当前网格四个角点 Point3d topLeft = currentRow[j].Block.Position; Point3d topRight = currentRow[j + 1].Block.Position; Point3d bottomLeft = nextRow[j].Block.Position; Point3d bottomRight = nextRow[j + 1].Block.Position; // 计算对角线长度 double length1 = topLeft.DistanceTo(bottomRight); double length2 = topRight.DistanceTo(bottomLeft); // 选择较短的对角线 bool useDiagonal1 = length1 <= length2; double requiredLength = useDiagonal1 ? length1 : length2; Point3d startPoint = useDiagonal1 ? topLeft : topRight; Point3d endPoint = useDiagonal1 ? bottomRight : bottomLeft; // 获取最接近的标准长度 string lengthKey = GetClosestDiagonalLength(requiredLength); string blockName = $"{DiagonalBarPrefix}{lengthKey}mm"; if (!bt.Has(blockName)) { Application.ShowAlertDialog($"斜拉杆块 {blockName} 未加载!"); continue; } ObjectId blockId = bt[blockName]; // 计算中点 - 修正后的计算 Point3d midPoint = new Point3d( (startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2, 0); // 计算旋转角度 - 修正后的计算 Vector3d direction = endPoint - startPoint; double angle = direction.AngleOnPlane(new Plane(Point3d.Origin, Vector3d.ZAxis)); // 检查是否已存在相同位置的斜杆 if (IsCached(blockName, midPoint, angle)) continue; // 创建斜杆图块引用 BlockReference br = new BlockReference(midPoint, blockId); br.Layer = DiagonalBarLayer; br.Rotation = angle; // 添加到图形 - 确保这步执行 btr.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); diagonalCount++; } } return diagonalCount; } ``` ### 关键修复点: 1. **中点计算修正**: ```csharp Point3d midPoint = new Point3d( (startPoint.X + endPoint.X) / 2, (startPoint.Y + endPoint.Y) / 2, 0); ``` 原代码中使用了错误的计算方式,现在直接使用起点和终点坐标计算中点 2. **旋转角度计算修正**: ```csharp Vector3d direction = endPoint - startPoint; double angle = direction.AngleOnPlane(new Plane(Point3d.Origin, Vector3d.ZAxis)); ``` 使用实际的起点到终点的向量计算角度,确保旋转方向正确 3. **块参照添加确认**: ```csharp btr.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); ``` 确保块参照被添加到模型空间并注册到事务中 4. **端点计算修正**: ```csharp Point3d endPoint = useDiagonal1 ? bottomRight : bottomLeft; ``` 明确指定对角线的终点坐标 ### 其他需要检查的点: 1. **确保斜拉杆块已加载**: 在`LoadDiagonalBlockDefinitions`方法中,添加加载确认: ```csharp private bool LoadDiagonalBlockDefinitions(Database db, Editor ed) { using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; bool anyLoaded = false; foreach (double len in DiagonalBarLengths) { string blockName = $"{DiagonalBarPrefix}{len}mm"; string blockPath = Path.Combine(BlockDirectory, $"{blockName}.dwg"); if (!File.Exists(blockPath)) { ed.WriteMessage($"\n斜拉杆块文件未找到: {blockPath}"); continue; } if (!bt.Has(blockName)) { LoadBlockFromFile(db, blockPath, blockName); ed.WriteMessage($"\n已加载斜拉杆块: {blockName}"); anyLoaded = true; } } tr.Commit(); return anyLoaded; // 返回是否至少加载了一个块 } } ``` 2. **图层状态检查**: 确保"盘扣-斜杆"图层未被冻结或关闭: ```csharp private void CheckLayerState(Database db) { using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable; if (lt.Has(DiagonalBarLayer)) { LayerTableRecord ltr = tr.GetObject(lt[DiagonalBarLayer], OpenMode.ForRead) as LayerTableRecord; if (ltr.IsFrozen || ltr.IsOff) { ltr.UpgradeOpen(); ltr.IsFrozen = false; ltr.IsOff = false; } } tr.Commit(); } } ``` 在`BuildDiagonal`方法开头调用此方法 ### 测试建议: 1. 添加调试信息输出: ```csharp ed.WriteMessage($"\n尝试在({midPoint.X},{midPoint.Y})插入斜杆{blockName},角度{angle}"); ``` 2. 在插入点绘制临时点: ```csharp DBPoint debugPoint = new DBPoint(midPoint); debugPoint.ColorIndex = 1; // 红色 btr.AppendEntity(debugPoint); tr.AddNewlyCreatedDBObject(debugPoint, true); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值