document.location的一点思考

本文深入探讨了在使用不同页面跳转方式时,JSTL标签在请求中绑定数据的传递差异。通过具体案例分析,揭示了`document.location`跳转方式下数据无法正确传递的原因,以及`request.getRequestDispatcher`方式的优势。

今天练习jstl标签的时候发现一个有意思的问题:

 

题目要求:tag1.jsp中往request中绑定一个list, tag2.jsp中读取list输出

 

我的代码:   

 

tag1.jsp中的js函数

 

             function toNextPage(){
                    <%
                           List<String> list = new ArrayList<String>();
                           list.add("first");
                           list.add("second");
                           list.add("third");
                           request.setAttribute("list", list);
                           request.getRequestDispatcher("tag2.jsp").forward(request, response);
                    %>
                    //document.location = "tag2.jsp";
             }

 

 

     tag2.jsp中的代码:

 

       <c:forEach var="i" begin="1" end="5" step="2">
              ${i }<br>
       </c:forEach>
       <c:forEach items="${requestScope.list }" var="str">
              ${ str}<br>
       </c:forEach>
       <%
              List<String> list = (List)request.getAttribute("list");
              for(String s : list){
       %>
                     <%=s %><br>
       <%
              }
        %>

 

 

运行结果:

       tag1.jsp中使用document.location方式跳转的话, tag2.jsp中不论是jstl方式还是java方式都不会读出任何数据; 如果使用request.getRequestDispatcher("tag2.jsp").forward(request, response);方式转发的话, tag2.jsp中不论是jstl还是java都能读取到正确的数据.

 

由此猜想: document.loaction=”” 这种方式跳转的话, 是否就不是一次请求了呢? 所以在request中绑定的数据在tag2.jsp中读取不到

 

 

在百度上搜了一下, 没有得到相关的结论, 所以把思考写出来, 奇文共欣赏, 疑义相与析. 希望各路大神能够不吝教导~~~给我释疑解惑一下

 

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 SystemException = System.Exception; // 修复Polyline命名歧义 using DbPolyline = Autodesk.AutoCAD.DatabaseServices.Polyline; [assembly: CommandClass(typeof(MyCadCommands.CadPlugin))] namespace MyCadCommands { /// <summary> /// 多段线扩展方法类(存放所有扩展方法,符合非泛型静态类要求) /// </summary> public static class PolylineExtensions { public static bool ContainsPoint(this DbPolyline pl, Point3d point, double tolerance) { for (int i = 0; i < pl.NumberOfVertices; i++) { if (pl.GetPoint3dAt(i).DistanceTo(point) < tolerance) return true; } return false; } /// <summary> /// 预缓存多段线的线段信息(起点+终点),避免重复API调用 /// </summary> public static List<(Point3d Start, Point3d End)> GetSegments(this DbPolyline pl) { var segments = new List<(Point3d, Point3d)>(); int vertCount = pl.NumberOfVertices; for (int i = 0; i < vertCount; i++) { int nextIdx = (i + 1) % vertCount; segments.Add((pl.GetPoint3dAt(i), pl.GetPoint3dAt(nextIdx))); } return segments; } /// <summary> /// 【修复】移到静态类中的Vector3d扩展方法:获取向量的垂直向量 /// </summary> public static Vector3d GetPerpendicularVector(this Vector3d vector) { return new Vector3d(-vector.Y, vector.X, vector.Z); } } /// <summary> /// AutoCAD插件主类(保留DS和GP命令) /// </summary> public class CadPlugin { // 脚手架绘制常量 private const double DEFAULT_OFFSET_DISTANCE = 250; // 默认离楼层外沿距离(mm) private const double DEFAULT_SCAFFOLD_WIDTH = 900; // 默认外架宽度(mm) private const double DEFAULT_MAX_SPACING = 1800; // 默认立杆最大纵距(mm) private const double OVERLAP_TOLERANCE = 10; // 重叠容差(mm) private const double RECT_SIDE_LENGTH = 900; // 矩形分隔线边长(mm) private const double OUTLINE_TOLERANCE = 50; // 轮廓线识别容差(mm) private Editor _ed; // 日志输出用Editor private List<Entity> _entitiesToAdd; // 批量添加实体列表(减少数据库交互) #region DS命令 - 脚手架绘制(优化卡顿版) [CommandMethod("DS", CommandFlags.Modal)] public void DrawScaffold() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; _ed = doc.Editor; _entitiesToAdd = new List<Entity>(); // 初始化批量实体列表 int lineCount = 0, rectCount = 0; // 统计绘制数量(替代频繁日志) // 保存原始自动保存设置 object oldSaveTime = Application.GetSystemVariable("SAVETIME"); try { // 禁用自动保存(避免绘制过程中触发保存) Application.SetSystemVariable("SAVETIME", 0); // 1. 获取用户输入参数(无优化,保持原有逻辑) _ed.WriteMessage("\n=== 脚手架布置参数输入 ===\n"); double offsetDistance = GetInputWithDefault("①请输入离楼层外沿距离(mm)", DEFAULT_OFFSET_DISTANCE); double scaffoldWidth = GetInputWithDefault("②请输入外架宽(mm)", DEFAULT_SCAFFOLD_WIDTH); double maxSpacing = GetInputWithDefault("③请输入立杆最大纵距(mm)", DEFAULT_MAX_SPACING); if (offsetDistance < 0 || scaffoldWidth < 0 || maxSpacing < 0) { _ed.WriteMessage("\n❌ 输入参数不能为负数!"); return; } // 2. 选择边界线(无优化,保持原有逻辑) _ed.WriteMessage("\n=== 选择边界线 ===\n"); PromptSelectionOptions pso = new PromptSelectionOptions { MessageForAdding = "\n请选择边界线(直线、多段线): ", RejectObjectsFromNonCurrentSpace = true, RejectObjectsOnLockedLayers = true }; TypedValue[] filterList = new TypedValue[] { new TypedValue((int)DxfCode.Start, "LINE,POLYLINE,LWPOLYLINE") }; PromptSelectionResult psr = _ed.GetSelection(pso, new SelectionFilter(filterList)); if (psr.Status == PromptStatus.Cancel) { _ed.WriteMessage("\n用户取消操作!"); return; } if (psr.Status != PromptStatus.OK || psr.Value.Count == 0) { _ed.WriteMessage("\n未选中有效边界线!"); return; } // 3. 事务处理(核心优化:批量添加实体) using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); // 创建必要图层(无优化) CreateLayerIfNotExists(tr, db, "盘扣轴网"); CreateLayerIfNotExists(tr, db, "标注"); // 检查块引用(无优化) bool hasBlockRef = psr.Value.Cast<SelectedObject>() .Any(so => so != null && so.ObjectId.IsValid && tr.GetObject(so.ObjectId, OpenMode.ForRead) is BlockReference); if (hasBlockRef) { _ed.WriteMessage("\n检测到选择了块引用,请直接选择边界线而不是块!"); tr.Abort(); return; } // 4. 创建闭合轮廓(无优化) DbPolyline outline = CreateOutlineFromSelectedLines(tr, psr.Value); if (outline == null) { tr.Abort(); return; } // 绘制原始轮廓(加入批量列表) DbPolyline originalOutline = (DbPolyline)outline.Clone(); originalOutline.SetDatabaseDefaults(db); originalOutline.Layer = "盘扣轴网"; originalOutline.ColorIndex = 5; // 蓝色 originalOutline.Closed = true; _entitiesToAdd.Add(originalOutline); // 5. 计算内外轮廓偏移(无优化) bool isClockwise = IsClockwise(outline); double outerOffset = offsetDistance + scaffoldWidth; double innerOffsetVal = isClockwise ? -offsetDistance : offsetDistance; double outerOffsetVal = isClockwise ? -outerOffset : outerOffset; DBObjectCollection innerCurves = outline.GetOffsetCurves(innerOffsetVal); DBObjectCollection outerCurves = outline.GetOffsetCurves(outerOffsetVal); if (innerCurves.Count == 0 || outerCurves.Count == 0) { innerOffsetVal = -innerOffsetVal; outerOffsetVal = -outerOffsetVal; innerCurves = outline.GetOffsetCurves(innerOffsetVal); outerCurves = outline.GetOffsetCurves(outerOffsetVal); if (innerCurves.Count == 0 || outerCurves.Count == 0) { _ed.WriteMessage("\n轮廓偏移失败!"); tr.Abort(); return; } } // 转换偏移曲线(无优化) DbPolyline innerPl = ConvertToDbPolyline(innerCurves[0], db); DbPolyline outerPl = ConvertToDbPolyline(outerCurves[0], db); if (innerPl == null || outerPl == null) { _ed.WriteMessage("\n偏移曲线转换失败!"); tr.Abort(); return; } // 设置内外轮廓(加入批量列表) SetPolylineProperties(innerPl, db, "盘扣轴网", 1); // 红色内轮廓 SetPolylineProperties(outerPl, db, "盘扣轴网", 3); // 绿色外轮廓 _entitiesToAdd.Add(innerPl); _entitiesToAdd.Add(outerPl); // ---------------------- 优化核心:分隔线绘制 ---------------------- // 预缓存原始轮廓的线段信息(避免重复调用GetPoint3dAt) var originalSegments = originalOutline.GetSegments(); // 6. 绘制角点分隔线(优化:批量添加+预缓存线段) if (innerPl.NumberOfVertices >= 3) { for (int i = 0; i < innerPl.NumberOfVertices; i++) { Point3d innerPt = innerPl.GetPoint3dAt(i); int nextInnerIdx = (i + 1) % innerPl.NumberOfVertices; Vector3d tangentDir = (innerPl.GetPoint3dAt(nextInnerIdx) - innerPt).GetNormal(); Vector3d normalDir = GetSegmentNormal(innerPl, i); // 优化:使用预缓存的线段检测重叠(减少API调用) bool isOverlap = IsPointOnSegments(innerPt, originalSegments, OVERLAP_TOLERANCE); if (isOverlap) { // 绘制矩形(加入批量列表) DrawRectangle(innerPt, normalDir, tangentDir, db); rectCount++; } else { // 绘制直线(加入批量列表) DrawLine(innerPt, innerPt + normalDir * scaffoldWidth, db); lineCount++; } } } else { _ed.WriteMessage("\n内轮廓顶点不足,无法绘制角点分隔线!"); } // 7. 绘制立杆纵距分隔线(优化:批量添加+预计算参数) if (innerPl.NumberOfVertices >= 2) { for (int i = 0; i < innerPl.NumberOfVertices; i++) { int nextIdx = (i + 1) % innerPl.NumberOfVertices; Point3d start = innerPl.GetPoint3dAt(i); Point3d end = innerPl.GetPoint3dAt(nextIdx); double length = start.DistanceTo(end); // 预计算方向向量(避免循环内重复计算) Vector3d dir = (end - start).GetNormal(); Vector3d normal = GetSegmentNormal(innerPl, i); if (length < maxSpacing + 100) { continue; // 跳过过短线段(减少日志) } double currentOffset = 0; double remainingLength = length; // 起点分隔线 bool startOverlap = IsPointOnSegments(start, originalSegments, OVERLAP_TOLERANCE); if (!startOverlap) { DrawLine(start, start + normal * scaffoldWidth, db); lineCount++; } else { DrawRectangle(start, normal, dir, db); rectCount++; } // 中间分隔线 while (remainingLength > 0) { double nextSpacing = GetNextSpacing(remainingLength, maxSpacing); if (nextSpacing == 0) break; currentOffset += nextSpacing; remainingLength = length - currentOffset; if (currentOffset > length) break; Point3d innerPoint = start + dir * currentOffset; bool midOverlap = IsPointOnSegments(innerPoint, originalSegments, OVERLAP_TOLERANCE); if (!midOverlap) { DrawLine(innerPoint, innerPoint + normal * scaffoldWidth, db); lineCount++; } else { DrawRectangle(innerPoint, normal, dir, db); rectCount++; } } // 终点分隔线 bool endOverlap = IsPointOnSegments(end, originalSegments, OVERLAP_TOLERANCE); if (!endOverlap) { DrawLine(end, end + normal * scaffoldWidth, db); lineCount++; } else { DrawRectangle(end, normal, dir, db); rectCount++; } } } else { _ed.WriteMessage("\n内轮廓线段不足,无法绘制立杆分隔线!"); } // ---------------------- 批量添加实体(核心优化) ---------------------- foreach (var entity in _entitiesToAdd) { if (entity != null) { modelSpace.AppendEntity(entity); tr.AddNewlyCreatedDBObject(entity, true); } } // 提交事务(仅1次提交,减少数据库开销) tr.Commit(); // 优化:合并日志输出(减少AutoCAD编辑器交互) _ed.WriteMessage($"\n✅ 脚手架布置成功!"); _ed.WriteMessage($"\n📋 参数:外沿距离{offsetDistance:F0}mm | 外架宽{scaffoldWidth:F0}mm | 立杆纵距{maxSpacing:F0}mm"); _ed.WriteMessage($"\n📌 生成:原始轮廓(蓝) | 内轮廓(红) | 外轮廓(绿) | 直线分隔线({lineCount}条) | 矩形分隔线({rectCount}个)"); } } catch (System.Exception ex) { _ed.WriteMessage($"\n❌ 脚手架绘制错误:{ex.Message}\n堆栈:{ex.StackTrace}"); } finally { // 恢复自动保存设置 if (oldSaveTime != null) { Application.SetSystemVariable("SAVETIME", oldSaveTime); } _entitiesToAdd?.Clear(); // 释放资源 } } #endregion #region GP命令 - 钢踏板布置(修改版:不再依赖DS命令,用户手动选择轮廓线) [CommandMethod("GP", CommandFlags.Modal)] public void ArrangeSteelPedal() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; _ed = doc.Editor; try { _ed.WriteMessage("\n=== 钢踏板布置 ===\n"); // 1. 提示用户选择内外轮廓线 _ed.WriteMessage("\n请选择内轮廓线(第一道轮廓线): "); PromptEntityOptions peoInner = new PromptEntityOptions("\n请选择内轮廓线(第一道轮廓线): "); peoInner.SetRejectMessage("\n请选择多段线!"); peoInner.AddAllowedClass(typeof(DbPolyline), true); PromptEntityResult perInner = _ed.GetEntity(peoInner); if (perInner.Status == PromptStatus.Cancel) { _ed.WriteMessage("\n用户取消操作!"); return; } _ed.WriteMessage("\n请选择外轮廓线(第二道轮廓线): "); PromptEntityOptions peoOuter = new PromptEntityOptions("\n请选择外轮廓线(第二道轮廓线): "); peoOuter.SetRejectMessage("\n请选择多段线!"); peoOuter.AddAllowedClass(typeof(DbPolyline), true); PromptEntityResult perOuter = _ed.GetEntity(peoOuter); if (perOuter.Status == PromptStatus.Cancel) { _ed.WriteMessage("\n用户取消操作!"); return; } // 2. 选择所有横杆图块 _ed.WriteMessage("\n请框选所有横杆图块: "); PromptSelectionOptions pso = new PromptSelectionOptions { MessageForAdding = "\n选择所有横杆图块: ", RejectObjectsFromNonCurrentSpace = true, RejectObjectsOnLockedLayers = true }; TypedValue[] filterList = new TypedValue[] { new TypedValue((int)DxfCode.Start, "INSERT") }; PromptSelectionResult psr = _ed.GetSelection(pso, new SelectionFilter(filterList)); if (psr.Status == PromptStatus.Cancel) { _ed.WriteMessage("\n用户取消操作!"); return; } if (psr.Status != PromptStatus.OK || psr.Value.Count == 0) { _ed.WriteMessage("\n未选中有效横杆图块!"); return; } // 3. 获取插件目录下的ScaffoldBlocks文件夹路径 string pluginPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); string scaffoldBlocksPath = Path.Combine(pluginPath, "ScaffoldBlocks"); if (!Directory.Exists(scaffoldBlocksPath)) { _ed.WriteMessage($"\n❌ 找不到ScaffoldBlocks文件夹: {scaffoldBlocksPath}"); return; } // 4. 检查所需的钢踏板图块文件是否存在 Dictionary<string, string> pedalBlockPaths = new Dictionary<string, string> { {"900", Path.Combine(scaffoldBlocksPath, "ScaffoldPole钢踏板900mm.dwg")}, {"1200", Path.Combine(scaffoldBlocksPath, "ScaffoldPole钢踏板1200mm.dwg")}, {"1500", Path.Combine(scaffoldBlocksPath, "ScaffoldPole钢踏板1500mm.dwg")}, {"1800", Path.Combine(scaffoldBlocksPath, "ScaffoldPole钢踏板1800mm.dwg")}, {"single", Path.Combine(scaffoldBlocksPath, "ScaffoldPole单片钢踏板.dwg")} }; foreach (var blockPath in pedalBlockPaths) { if (!File.Exists(blockPath.Value)) { _ed.WriteMessage($"\n❌ 找不到钢踏板图块文件: {blockPath.Value}"); return; } } _ed.WriteMessage($"\n✅ 所有钢踏板图块文件都存在"); // 5. 处理选中的横杆图块 using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); // 获取内外轮廓线 DbPolyline innerPl = tr.GetObject(perInner.ObjectId, OpenMode.ForRead) as DbPolyline; DbPolyline outerPl = tr.GetObject(perOuter.ObjectId, OpenMode.ForRead) as DbPolyline; if (innerPl == null || outerPl == null) { _ed.WriteMessage("\n❌ 选择的轮廓线无效!"); return; } int processedCount = 0; int pedalCount = 0; int skippedCount = 0; foreach (SelectedObject so in psr.Value) { if (so == null || !so.ObjectId.IsValid) continue; BlockReference blockRef = tr.GetObject(so.ObjectId, OpenMode.ForRead) as BlockReference; if (blockRef == null) continue; // 获取图块名称 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blockRef.BlockTableRecord, OpenMode.ForRead); string blockName = btr.Name; // 解析横杆长度 double beamLength = ParseBeamLength(blockName); if (beamLength <= 0) continue; // 检查横杆是否靠近第二道轮廓线(外轮廓) Point3d blockPosition = blockRef.Position; double distanceToInner = GetDistanceToPolyline(blockPosition, innerPl); double distanceToOuter = GetDistanceToPolyline(blockPosition, outerPl); // 如果横杆不靠近外轮廓,则跳过(忽略第一道轮廓线和分隔线上的横杆) if (distanceToOuter > OUTLINE_TOLERANCE) { skippedCount++; continue; } // 确定对应的钢踏板图块 string pedalBlockName = GetPedalBlockName(beamLength); if (string.IsNullOrEmpty(pedalBlockName)) continue; // 导入钢踏板图块定义(如果尚未导入) if (!bt.Has(pedalBlockName)) { using (Database sourceDb = new Database(false, true)) { try { sourceDb.ReadDwgFile(pedalBlockPaths[pedalBlockName], FileShare.Read, true, ""); ObjectId mappingId = db.Insert(pedalBlockName, sourceDb, true); if (!mappingId.IsValid) { _ed.WriteMessage($"\n❌ 导入钢踏板图块失败: {pedalBlockName}"); continue; } } catch (SystemException ex) { _ed.WriteMessage($"\n❌ 读取图块文件失败: {pedalBlockPaths[pedalBlockName]}, 错误: {ex.Message}"); continue; } } } // 计算钢踏板布置数量和位置 int pedalQuantity = CalculatePedalQuantity(beamLength, pedalBlockName); if (pedalQuantity <= 0) continue; // 布置钢踏板 if (PlacePedals(tr, modelSpace, blockRef, pedalBlockName, pedalQuantity, beamLength)) { processedCount++; pedalCount += pedalQuantity; } } tr.Commit(); _ed.WriteMessage($"\n✅ 钢踏板布置完成!处理了 {processedCount} 根第二道轮廓线上的横杆,共布置 {pedalCount} 块钢踏板"); if (skippedCount > 0) { _ed.WriteMessage($"\n⚠️ 跳过了 {skippedCount} 根第一道轮廓线及分隔线上的横杆"); } } } catch (System.Exception ex) { _ed.WriteMessage($"\n❌ 钢踏板布置错误:{ex.Message}\n堆栈:{ex.StackTrace}"); } } /// <summary> /// 计算点到多段线的最短距离 /// </summary> private double GetDistanceToPolyline(Point3d point, DbPolyline pl) { double minDistance = double.MaxValue; for (int i = 0; i < pl.NumberOfVertices; i++) { int nextIdx = (i + 1) % pl.NumberOfVertices; Point3d start = pl.GetPoint3dAt(i); Point3d end = pl.GetPoint3dAt(nextIdx); double distance = PointToLineDistance(point, start, end); if (distance < minDistance) { minDistance = distance; } } return minDistance; } /// <summary> /// 从横杆图块名称中解析长度 /// </summary> private double ParseBeamLength(string blockName) { if (blockName.Contains("横杆")) { if (blockName.Contains("1800mm")) return 1800; if (blockName.Contains("1500mm")) return 1500; if (blockName.Contains("1200mm")) return 1200; if (blockName.Contains("900mm")) return 900; if (blockName.Contains("600mm")) return 600; if (blockName.Contains("300mm")) return 300; } return 0; } /// <summary> /// 根据横杆长度确定钢踏板图块名称 /// </summary> private string GetPedalBlockName(double beamLength) { switch (beamLength) { case 1800: return "1800"; case 1500: return "1500"; case 1200: return "1200"; case 900: return "900"; case 600: case 300: default: return "single"; } } /// <summary> /// 计算钢踏板布置数量 /// </summary> private int CalculatePedalQuantity(double beamLength, string pedalBlockName) { if (pedalBlockName == "single") { // 单片钢踏板宽度为240mm return (int)Math.Ceiling(beamLength / 240.0); } return 1; // 标准长度只需一块钢踏板 } /// <summary> /// 布置钢踏板(调用GetPerpendicularVector扩展方法,语法不变) /// </summary> private bool PlacePedals(Transaction tr, BlockTableRecord modelSpace, BlockReference beamRef, string pedalBlockName, int quantity, double beamLength) { try { BlockTable bt = (BlockTable)tr.GetObject(beamRef.Database.BlockTableId, OpenMode.ForRead); // 获取钢踏板图块定义 if (!bt.Has(pedalBlockName)) return false; ObjectId pedalBlockId = bt[pedalBlockName]; // 获取横杆的插入点和旋转角度 Point3d insertionPoint = beamRef.Position; double rotation = beamRef.Rotation; // 计算钢踏板布置方向和间距(此处调用扩展方法,因已移到静态类,可正常使用) Vector3d direction = new Vector3d(Math.Cos(rotation), Math.Sin(rotation), 0); Vector3d perpendicular = direction.GetPerpendicularVector(); // 计算单片钢踏板宽度 double singlePedalWidth = 240.0; if (pedalBlockName != "single") { // 标准钢踏板直接使用横杆长度 singlePedalWidth = beamLength; } // 计算总宽度和起始位置 double totalWidth = quantity * singlePedalWidth; // 修改起始位置:从负的钢踏板长度开始布置 double startOffset = -singlePedalWidth; // 从负的钢踏板长度开始 for (int i = 0; i < quantity; i++) { // 计算当前钢踏板的位置 double offset = startOffset + i * singlePedalWidth + singlePedalWidth / 2.0; Point3d pedalPosition = insertionPoint + direction * offset; // 创建钢踏板图块引用 BlockReference pedalRef = new BlockReference(pedalPosition, pedalBlockId); pedalRef.Rotation = rotation; // 设置钢踏板图层和属性 pedalRef.Layer = "盘扣轴网"; pedalRef.ColorIndex = 6; // 洋红色 // 添加到模型空间 modelSpace.AppendEntity(pedalRef); tr.AddNewlyCreatedDBObject(pedalRef, true); } return true; } catch (SystemException ex) { _ed.WriteMessage($"\n❌ 布置钢踏板失败: {ex.Message}"); return false; } } #endregion #region 优化后的辅助方法 /// <summary> /// 获取带默认值的用户输入(无优化) /// </summary> private double GetInputWithDefault(string prompt, double defaultValue) { PromptDoubleOptions pdo = new PromptDoubleOptions($"\n{prompt} [默认: {defaultValue}]: "); pdo.DefaultValue = defaultValue; pdo.AllowNone = true; PromptDoubleResult pdr = _ed.GetDouble(pdo); if (pdr.Status == PromptStatus.Cancel) return -1; if (pdr.Status == PromptStatus.None) return defaultValue; return pdr.Value; } /// <summary> /// 预计算下一个间距(提取重复逻辑,减少循环内代码量) /// </summary> private double GetNextSpacing(double remainingLength, double maxSpacing) { if (remainingLength >= maxSpacing) return maxSpacing; if (remainingLength >= 1500) return 1500; if (remainingLength >= 1200) return 1200; if (remainingLength >= 900) return 900; if (remainingLength >= 600) return 600; if (remainingLength >= 300) return 300; return 0; // 小于300mm跳过 } /// <summary> /// 使用预缓存的线段检测点重叠(减少AutoCAD API调用) /// </summary> private bool IsPointOnSegments(Point3d point, List<(Point3d Start, Point3d End)> segments, double tolerance) { foreach (var (start, end) in segments) { double dist = PointToLineDistance(point, start, end); if (dist < tolerance) return true; // 找到重叠立即返回,减少循环 } return false; } /// <summary> /// 绘制直线(仅创建对象,不立即添加到数据库) /// </summary> private void DrawLine(Point3d start, Point3d end, Database db) { Line line = new Line(start, end); line.SetDatabaseDefaults(db); line.Layer = "盘扣轴网"; line.ColorIndex = 4; // 青色 _entitiesToAdd.Add(line); } /// <summary> /// 绘制矩形(仅创建对象,不立即添加到数据库) /// </summary> private void DrawRectangle(Point3d startPoint, Vector3d normalDir, Vector3d tangentDir, Database db) { Vector3d normal = normalDir.GetNormal(); Vector3d tangent = tangentDir.GetNormal(); // 计算矩形顶点(无逻辑变化) Point3d p0 = startPoint; Point3d p1 = p0 + normal * RECT_SIDE_LENGTH; Point3d p3 = p0 + tangent * RECT_SIDE_LENGTH; Point3d p2 = p1 + tangent * RECT_SIDE_LENGTH; DbPolyline rectPoly = new DbPolyline(); rectPoly.SetDatabaseDefaults(db); rectPoly.Layer = "盘扣轴网"; rectPoly.ColorIndex = 4; // 青色 rectPoly.Closed = true; rectPoly.AddVertexAt(0, new Point2d(p0.X, p0.Y), 0, 0, 0); rectPoly.AddVertexAt(1, new Point2d(p1.X, p1.Y), 0, 0, 0); rectPoly.AddVertexAt(2, new Point2d(p2.X, p2.Y), 0, 0, 0); rectPoly.AddVertexAt(3, new Point2d(p3.X, p3.Y), 0, 0, 0); _entitiesToAdd.Add(rectPoly); } /// <summary> /// 设置多段线属性(移除事务参数,仅处理对象本身) /// </summary> private void SetPolylineProperties(DbPolyline pl, Database db, string layer, int colorIndex) { pl.SetDatabaseDefaults(db); pl.Closed = true; pl.Layer = layer; pl.ColorIndex = colorIndex; } // 以下辅助方法无核心逻辑变化,仅适配优化后的参数传递 private DbPolyline CreateOutlineFromSelectedLines(Transaction tr, SelectionSet ss) { try { List<Line> selectedLines = new List<Line>(); List<DbPolyline> selectedPolylines = new List<DbPolyline>(); foreach (SelectedObject so in ss) { if (so == null || !so.ObjectId.IsValid) continue; Entity ent = tr.GetObject(so.ObjectId, OpenMode.ForRead) as Entity; if (ent is Line line) selectedLines.Add(line); else if (ent is DbPolyline pl) selectedPolylines.Add(pl); } if (selectedPolylines.Count > 0) { if (selectedPolylines.Count == 1 && selectedPolylines[0].Closed) return selectedPolylines[0].Clone() as DbPolyline; return JoinPolylines(selectedPolylines); } if (selectedLines.Count < 2) { _ed.WriteMessage("\n至少需要选择两条线段才能形成闭合轮廓!"); return null; } List<Point3d> intersectionPoints = new List<Point3d>(); for (int i = 0; i < selectedLines.Count; i++) { for (int j = i + 1; j < selectedLines.Count; j++) { Point3dCollection intersectPoints = new Point3dCollection(); selectedLines[i].IntersectWith(selectedLines[j], Intersect.OnBothOperands, intersectPoints, IntPtr.Zero, IntPtr.Zero); foreach (Point3d pt in intersectPoints) intersectionPoints.Add(pt); } } if (intersectionPoints.Count < 2) { _ed.WriteMessage("\n选择的线段没有足够的交点形成闭合轮廓!"); return null; } return CreatePolylineFromIntersections(selectedLines, intersectionPoints); } catch (System.Exception ex) { _ed.WriteMessage($"\n轮廓生成错误:{ex.Message}"); return null; } } private DbPolyline CreatePolylineFromIntersections(List<Line> lines, List<Point3d> intersections) { try { List<Point3d> boundaryPoints = new List<Point3d>(intersections); Point3dComparer comparer = new Point3dComparer(0.001); foreach (Line line in lines) { if (!boundaryPoints.Contains(line.StartPoint, comparer)) boundaryPoints.Add(line.StartPoint); if (!boundaryPoints.Contains(line.EndPoint, comparer)) boundaryPoints.Add(line.EndPoint); } List<Point3d> convexHull = ComputeConvexHull(boundaryPoints); DbPolyline polyline = new DbPolyline(); for (int i = 0; i < convexHull.Count; i++) { polyline.AddVertexAt(i, new Point2d(convexHull[i].X, convexHull[i].Y), 0, 0, 0); } polyline.Closed = true; return polyline; } catch (System.Exception ex) { _ed.WriteMessage($"\n创建轮廓错误:{ex.Message}"); return null; } } private List<Point3d> ComputeConvexHull(List<Point3d> points) { if (points.Count < 3) return points; Point3d startPoint = points[0]; foreach (Point3d p in points) { if (p.X < startPoint.X || (Math.Abs(p.X - startPoint.X) < 0.001 && p.Y < startPoint.Y)) { startPoint = p; } } List<Point3d> sortedPoints = new List<Point3d>(points); sortedPoints.Sort((a, b) => { if (a == startPoint) return -1; if (b == startPoint) return 1; double cross = CrossProduct(startPoint, a, b); if (Math.Abs(cross) < 0.001) return startPoint.DistanceTo(a).CompareTo(startPoint.DistanceTo(b)); return cross > 0 ? -1 : 1; }); List<Point3d> hull = new List<Point3d> { startPoint }; if (sortedPoints.Count > 1) hull.Add(sortedPoints[1]); for (int i = 2; i < sortedPoints.Count; i++) { while (hull.Count >= 2 && CrossProduct(hull[hull.Count - 2], hull[hull.Count - 1], sortedPoints[i]) <= 0) { hull.RemoveAt(hull.Count - 1); } hull.Add(sortedPoints[i]); } return hull; } private double CrossProduct(Point3d o, Point3d a, Point3d b) { return (a.X - o.X) * (b.Y - o.Y) - (a.Y - o.Y) * (b.X - o.X); } private DbPolyline JoinPolylines(List<DbPolyline> polylines) { return polylines[0].Clone() as DbPolyline; } private DbPolyline ConvertToDbPolyline(DBObject obj, Database db) { if (obj is DbPolyline pl) { pl.SetDatabaseDefaults(db); return pl; } if (obj is Line line) { DbPolyline newPl = new DbPolyline(); newPl.SetDatabaseDefaults(db); newPl.AddVertexAt(0, new Point2d(line.StartPoint.X, line.StartPoint.Y), 0, 0, 0); newPl.AddVertexAt(1, new Point2d(line.EndPoint.X, line.EndPoint.Y), 0, 0, 0); newPl.Closed = false; return newPl; } if (obj is Arc arc) { DbPolyline newPl = new DbPolyline(); newPl.SetDatabaseDefaults(db); double startAng = arc.StartAngle; double endAng = arc.EndAngle; double centralAng = endAng - startAng; if (centralAng < 0) centralAng += 2 * Math.PI; if (IsArcClockWise(arc)) centralAng = -centralAng; double bulge = Math.Tan(centralAng / 4); newPl.AddVertexAt(0, new Point2d(arc.StartPoint.X, arc.StartPoint.Y), bulge, 0, 0); newPl.AddVertexAt(1, new Point2d(arc.EndPoint.X, arc.EndPoint.Y), 0, 0, 0); newPl.Closed = false; return newPl; } return null; } private bool IsArcClockWise(Arc arc) { Point3d center = arc.Center; Point3d start = arc.StartPoint; Point3d end = arc.EndPoint; Vector2d vec1 = new Vector2d(start.X - center.X, start.Y - center.Y); Vector2d vec2 = new Vector2d(end.X - center.X, end.Y - center.Y); double crossProduct = vec1.X * vec2.Y - vec1.Y * vec2.X; return crossProduct < 0; } private bool IsClockwise(DbPolyline pl) { if (pl == null || pl.NumberOfVertices < 3) return false; double area = 0; int vertCount = pl.NumberOfVertices; for (int i = 0; i < vertCount; i++) { Point2d p1 = pl.GetPoint2dAt(i); Point2d p2 = pl.GetPoint2dAt((i + 1) % vertCount); area += p1.X * p2.Y - p2.X * p1.Y; } return area < 0; } private Vector3d GetSegmentNormal(DbPolyline pl, int segmentIndex) { if (pl == null || segmentIndex < 0 || segmentIndex >= pl.NumberOfVertices) return Vector3d.ZAxis; int nextIdx = (segmentIndex + 1) % pl.NumberOfVertices; Point3d start = pl.GetPoint3dAt(segmentIndex); Point3d end = pl.GetPoint3dAt(nextIdx); Vector3d dir = (end - start).GetNormal(); Vector3d normal = new Vector3d(-dir.Y, dir.X, 0).GetNormal(); Point3d midPoint = start + (end - start) * 0.5; Point3d testPoint = midPoint + normal * 10; if (IsPointInsidePolyline(pl, testPoint)) normal = -normal; return normal; } private bool IsPointInsidePolyline(DbPolyline pl, Point3d point) { if (pl == null || !pl.Closed) return false; int crossings = 0; int vertexCount = pl.NumberOfVertices; for (int i = 0; i < vertexCount; i++) { int j = (i + 1) % vertexCount; Point3d vi = pl.GetPoint3dAt(i); Point3d vj = pl.GetPoint3dAt(j); if (((vi.Y <= point.Y) && (vj.Y > point.Y)) || ((vj.Y <= point.Y) && (vi.Y > point.Y))) { double vt = (point.Y - vi.Y) / (vj.Y - vi.Y); if (point.X < vi.X + vt * (vj.X - vi.X)) crossings++; } } return (crossings % 2) != 0; } private double PointToLineDistance(Point3d point, Point3d lineStart, Point3d lineEnd) { Vector3d lineVec = lineEnd - lineStart; Vector3d pointVec = point - lineStart; double lineLength = lineVec.Length; if (lineLength < 1e-10) return pointVec.Length; Vector3d normalizedLineVec = lineVec / lineLength; double projLength = pointVec.X * normalizedLineVec.X + pointVec.Y * normalizedLineVec.Y + pointVec.Z * normalizedLineVec.Z; if (projLength < 0) return pointVec.Length; if (projLength > lineLength) return (point - lineEnd).Length; Point3d projPoint = lineStart + normalizedLineVec * projLength; return point.DistanceTo(projPoint); } private void CreateLayerIfNotExists(Transaction tr, Database db, string layerName) { if (string.IsNullOrEmpty(layerName)) return; LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); if (!lt.Has(layerName)) { lt.UpgradeOpen(); LayerTableRecord ltr = new LayerTableRecord { Name = layerName }; lt.Add(ltr); tr.AddNewlyCreatedDBObject(ltr, true); lt.DowngradeOpen(); _ed.WriteMessage($"\n创建图层:{layerName}"); } } #endregion } /// <summary> /// Point3d比较器(含容差) /// </summary> public class Point3dComparer : IEqualityComparer<Point3d> { private double _tolerance; public Point3dComparer(double tolerance) { _tolerance = tolerance; } public bool Equals(Point3d x, Point3d y) { return x.DistanceTo(y) < _tolerance; } public int GetHashCode(Point3d obj) { return obj.X.GetHashCode() ^ obj.Y.GetHashCode() ^ obj.Z.GetHashCode(); } } } 第二道轮廓线转角处X方向900mm横杆和Y方向900mm横杆,只布置X方向900mm横杆的900mm钢踏板Y方向900mm横杆处不布置钢踏板
09-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值