Math.abs(x)的一个记录

本文详细介绍了如何使用Java的Math类中的abs方法来获取不同数据类型(int, long, float, double)的绝对值,并解释了当输入特定最小负值时可能出现的特殊情况。

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

abs
public static int abs(int a)
返回 int 值的绝对值。如果参数为非负数,则返回该参数。如果参数为负数,则返回该参数的相反数。
注意,如果参数等于 Integer.MIN_VALUE 的值(即能够表示的最小负 int 值),那么结果与该值相同且为负。

如下代码:

int a=Integer.MIN_VALUE;
System.out.println(a);//-2147483648
int num=Math.abs(a);
System.out.println(num);//-2147483648

因为最大值为2147483647,而绝对值为2147483648已经溢出,+1后变为最小值

参数:
a - 要确定绝对值的参数。
返回:
参数的绝对值。
另请参见:
Integer.MIN_VALUE
abs
public static long abs(long a)
返回 long 值的绝对值。如果参数为非负数,则返回该参数。如果参数为负数,则返回该参数的相反数。
注意,如果参数等于 Long.MIN_VALUE 的值(即能够表示的最小负 long 值),则结果与该值相同且为负。

参数:
a - 要确定绝对值的参数。
返回:
参数的绝对值。
另请参见:
Long.MIN_VALUE
abs
public static float abs(float a)
返回 float 值的绝对值。如果参数为非负数,则返回该参数。如果参数为负数,则返回该参数的相反数。特殊情况如下:
如果参数为正 0 或负 0,那么结果为正 0。
如果参数为无穷大,那么结果为正无穷大。
如果参数为 NaN,那么结果为 NaN。
换句话说,结果等于以下表达式的值:
Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))
参数:
a - 要确定绝对值的参数。
返回:
参数的绝对值。
abs
public static double abs(double a)
返回 double 值的绝对值。如果参数为非负数,则返回该参数。如果参数为负数,则返回该参数的相反数。特殊情况如下:
如果参数为正 0 或负 0,那么结果为正 0。
如果参数为无穷大,那么结果为正无穷大。
如果参数为 NaN,那么结果为 NaN。
换句话说,结果等于以下表达式的值:
Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)

参数:
a - 要确定绝对值的参数。
返回:
参数的绝对值。

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; namespace ScaffoldPlugin { public class ScaffoldCommands { // 水平杆标准尺寸及对应图块名称 private static readonly Dictionary<double, string> PoleBlocks = new Dictionary<double, string> { { 600, "ScaffoldPolexie水平杆600mm.dwg" }, { 900, "ScaffoldPolexie水平杆900mm.dwg" }, { 1200, "ScaffoldPolexie水平杆1200mm.dwg" }, { 1500, "ScaffoldPolexie水平杆1500mm.dwg" }, { 1800, "ScaffoldPolexie水平杆1800mm.dwg" } }; // 存储已布置的水平杆位置(用于避免重复) private static readonly HashSet<string> PlacedPoles = new HashSet<string>(); [CommandMethod("HPD", CommandFlags.Modal)] public void HorizontalPoleDistribution() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { // 清除之前的布置记录 PlacedPoles.Clear(); // 选择布置模式 PromptIntegerOptions modeOpts = new PromptIntegerOptions("\n选择布置模式: [1隔一布一/2隔二布一/3隔三布一/4满布]") { AllowZero = false, AllowNegative = false, LowerLimit = 1, UpperLimit = 4, UseDefaultValue = true, DefaultValue = 4 }; PromptIntegerResult modeRes = ed.GetInteger(modeOpts); if (modeRes.Status != PromptStatus.OK) return; int mode = modeRes.Value; // 框选盘扣轴网 PromptSelectionOptions selOpts = new PromptSelectionOptions { MessageForAdding = "\n框选盘扣轴网: ", AllowDuplicates = false }; PromptSelectionResult selRes = ed.GetSelection(selOpts); if (selRes.Status != PromptStatus.OK) return; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; // 收集所有网格线 List<Line> gridLines = new List<Line>(); foreach (SelectedObject selObj in selRes.Value) { Entity ent = tr.GetObject(selObj.ObjectId, OpenMode.ForRead) as Entity; if (ent is Line line && IsGridLine(line)) gridLines.Add(line); } if (gridLines.Count == 0) { ed.WriteMessage("\n未找到有效的网格线"); return; } // 构建网格拓扑 - 完全重构 GridTopology grid = new GridTopology(gridLines, ed); if (!grid.IsValid) { ed.WriteMessage("\n错误:无法构建有效网格拓扑"); return; } ed.WriteMessage($"\n构建网格拓扑成功:{grid.Rows}行 x {grid.Cols}列"); // 执行布置逻辑 int poleCount = 0; switch (mode) { case 1: poleCount = PlacePolesMode1(grid, btr, tr, db, ed); break; case 2: poleCount = PlacePolesMode2(grid, btr, tr, db, ed); break; case 3: poleCount = PlacePolesMode3(grid, btr, tr, db, ed); break; case 4: poleCount = PlacePolesMode4(grid, btr, tr, db, ed); break; } tr.Commit(); ed.WriteMessage($"\n成功布置{poleCount}根水平杆"); } } catch (System.Exception ex) { ed.WriteMessage($"\n错误: {ex.Message}\n{ex.StackTrace}"); } } [CommandMethod("FLP", CommandFlags.Modal)] public void FlipHorizontalPoles() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; try { // 选择要翻转的水平杆 PromptSelectionOptions opts = new PromptSelectionOptions { MessageForAdding = "\n选择要翻转的水平杆: " }; PromptSelectionResult selRes = ed.GetSelection(opts); if (selRes.Status != PromptStatus.OK) return; int flipCount = 0; using (Transaction tr = doc.TransactionManager.StartTransaction()) { Database db = doc.Database; BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; foreach (SelectedObject selObj in selRes.Value) { BlockReference br = tr.GetObject(selObj.ObjectId, OpenMode.ForWrite) as BlockReference; if (br != null && IsPoleBlock(br)) { // 计算新旋转角度(旋转180度) br.TransformBy(Matrix3d.Rotation(Math.PI, Vector3d.ZAxis, br.Position)); flipCount++; } } tr.Commit(); } ed.WriteMessage($"\n成功翻转{flipCount}根水平杆"); } catch (System.Exception ex) { ed.WriteMessage($"\n错误: {ex.Message}"); } } // 判断是否为网格线 (带容差) private bool IsGridLine(Line line, double angleTolerance = 0.01) { if (line == null) return false; Vector3d vec = line.EndPoint - line.StartPoint; if (vec.Length < 0.001) return false; // 忽略零长度线段 // 检查是否为水平或垂直线 double angleToX = vec.GetAngleTo(Vector3d.XAxis); double angleToY = vec.GetAngleTo(Vector3d.YAxis); return angleToX < angleTolerance || Math.Abs(angleToX - Math.PI) < angleTolerance || angleToY < angleTolerance || Math.Abs(angleToY - Math.PI) < angleTolerance; } // 判断是否为水平杆图块 private bool IsPoleBlock(BlockReference br) { return PoleBlocks.Values.Any(name => br.Name.Equals(name, StringComparison.OrdinalIgnoreCase)); } // 生成唯一标识符用于检测重复 private string GetSegmentKey(LineSegment seg) { return $"{Math.Round(seg.StartPoint.X, 3)},{Math.Round(seg.StartPoint.Y, 3)}|" + $"{Math.Round(seg.EndPoint.X, 3)},{Math.Round(seg.EndPoint.Y, 3)}"; } // 模式1:隔一布一 (2x2单元) private int PlacePolesMode1(GridTopology grid, BlockTableRecord btr, Transaction tr, Database db, Editor ed) { int count = 0; for (int row = 0; row < grid.Rows; row += 2) // 每2行一个单元 { for (int col = 0; col < grid.Cols; col += 2) // 每2列一个单元 { // 布置当前单元的4条边 if (PlacePoleOnSegment(grid.GetHorizontalSegment(row, col), btr, tr, db, ed, grid)) count++; // 上边 if (PlacePoleOnSegment(grid.GetHorizontalSegment(row + 1, col), btr, tr, db, ed, grid)) count++; // 下边 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col), btr, tr, db, ed, grid)) count++; // 左边 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col + 1), btr, tr, db, ed, grid)) count++; // 右边 } } return count; } // 模式2:隔二布一 (3跨单元) private int PlacePolesMode2(GridTopology grid, BlockTableRecord btr, Transaction tr, Database db, Editor ed) { int count = 0; // 遍历所有行 for (int row = 0; row < grid.Rows; row++) { // 按3一个单元循环 for (int col = 0; col < grid.Cols; col += 3) { // 第一个方格 (满布四边) if (col < grid.Cols) { // 布置四边 if (PlacePoleOnSegment(grid.GetHorizontalSegment(row, col), btr, tr, db, ed, grid)) count++; // 上边 if (PlacePoleOnSegment(grid.GetHorizontalSegment(row + 1, col), btr, tr, db, ed, grid)) count++; // 下边 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col), btr, tr, db, ed, grid)) count++; // 左边 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col + 1), btr, tr, db, ed, grid)) count++; // 右边 } // 第二个方格 (中间方格(第二、三跨),只布置上下水平杆) int col2 = col + 2; if (col2 < grid.Cols) { // 只布置水平方向左右边的水平杆 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col2), btr, tr, db, ed, grid)) count++; // 左边 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col2 + 1), btr, tr, db, ed, grid)) count++; // 右边 // 严禁布置垂直杆件上的水平杆(不布置左右边) } // 第四个方格 (在下一个单元的第一个位置) int col4 = col + 3; if (col4 < grid.Cols) { // 布置四边 if (PlacePoleOnSegment(grid.GetHorizontalSegment(row, col4), btr, tr, db, ed, grid)) count++; // 上边 if (PlacePoleOnSegment(grid.GetHorizontalSegment(row + 1, col4), btr, tr, db, ed, grid)) count++; // 下边 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col4), btr, tr, db, ed, grid)) count++; // 左边 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col4 + 1), btr, tr, db, ed, grid)) count++; // 右边 } } } return count; } // 模式3:隔三布一 (4跨单元) private int PlacePolesMode3(GridTopology grid, BlockTableRecord btr, Transaction tr, Database db, Editor ed) { int count = 0; // 遍历所有行 for (int row = 0; row < grid.Rows; row++) { // 按4跨一个单元循环 for (int col = 0; col < grid.Cols; col += 4) { // 第一个方格 (满布四边) if (col < grid.Cols) { // 布置四边 if (PlacePoleOnSegment(grid.GetHorizontalSegment(row, col), btr, tr, db, ed, grid)) count++; // 上边 if (PlacePoleOnSegment(grid.GetHorizontalSegment(row + 1, col), btr, tr, db, ed, grid)) count++; // 下边 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col), btr, tr, db, ed, grid)) count++; // 左边 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col + 1), btr, tr, db, ed, grid)) count++; // 右边 } // 第五个方格 (在下一个单元的第一个位置) int col5 = col + 4; if (col5 < grid.Cols) { // 布置四边 if (PlacePoleOnSegment(grid.GetHorizontalSegment(row, col5), btr, tr, db, ed, grid)) count++; // 上边 if (PlacePoleOnSegment(grid.GetHorizontalSegment(row + 1, col5), btr, tr, db, ed, grid)) count++; // 下边 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col5), btr, tr, db, ed, grid)) count++; // 左边 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col5 + 1), btr, tr, db, ed, grid)) count++; // 右边 } // 中间三个方格 (第二、三、四跨) - 只布置左右水平杆 for (int i = 1; i <= 3; i++) { int midCol = col + i; if (midCol < grid.Cols) { // 只布置左右边水平杆 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col5), btr, tr, db, ed, grid)) count++; // 左边 if (PlacePoleOnSegment(grid.GetVerticalSegment(row, col5 + 1), btr, tr, db, ed, grid)) count++; // 右边 // 严禁布置垂直杆件上的水平杆(不布置上下边) } } } } return count; } // 模式4:满布 private int PlacePolesMode4(GridTopology grid, BlockTableRecord btr, Transaction tr, Database db, Editor ed) { int count = 0; // 所有水平线段 for (int row = 0; row <= grid.Rows; row++) { for (int col = 0; col < grid.Cols; col++) { var seg = grid.GetHorizontalSegment(row, col); if (seg != null && PlacePoleOnSegment(seg, btr, tr, db, ed, grid)) count++; } } // 所有垂直线段 for (int col = 0; col <= grid.Cols; col++) { for (int row = 0; row < grid.Rows; row++) { var seg = grid.GetVerticalSegment(row, col); if (seg != null && PlacePoleOnSegment(seg, btr, tr, db, ed, grid)) count++; } } return count; } // 在指定线段上布置水平杆(新增端点验证) private bool PlacePoleOnSegment(LineSegment seg, BlockTableRecord btr, Transaction tr, Database db, Editor ed, GridTopology grid) { // 新增端点验证 if (seg == null || !grid.HasEndpoints(seg) || seg.Length < 301) { return false; } // 匹配最接近的标准尺寸 double closestSize = PoleBlocks.Keys .OrderBy(size => Math.Abs(size - seg.Length)) .FirstOrDefault(size => Math.Abs(size - seg.Length) <= 50); if (closestSize <= 0 || !PoleBlocks.TryGetValue(closestSize, out string blockName)) { return false; } // 获取插件目录下的图块路径 string pluginPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); string blockDir = Path.Combine(pluginPath, "ScaffoldBlocks"); string blockPath = Path.Combine(blockDir, blockName); // 确保图块文件存在 if (!File.Exists(blockPath)) { ed.WriteMessage($"\n图块文件不存在: {blockPath}"); return false; } BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; // 如果图块未定义,从文件插入 if (!bt.Has(blockName)) { using (Database sourceDb = new Database(false, true)) { try { sourceDb.ReadDwgFile(blockPath, FileShare.Read, true, null); ObjectId blockId = db.Insert(blockName, sourceDb, true); } catch (System.Exception ex) { ed.WriteMessage($"\n插入图块失败: {ex.Message}"); return false; } } } // 计算插入点和旋转角度 Point3d midPoint = seg.MidPoint; double angle = seg.Direction.AngleOnPlane(new Plane()); // 插入图块 using (BlockReference br = new BlockReference(midPoint, bt[blockName])) { br.Rotation = angle; btr.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); return true; } } } // 完全重构的网格拓扑类 internal class GridTopology { public int Rows { get; private set; } // 网格行数 (单元行数) public int Cols { get; private set; } // 网格列数 (单元列数) public bool IsValid => Rows > 0 && Cols > 0; // 存储原始网格线 private List<Line> HorizontalLines { get; } = new List<Line>(); private List<Line> VerticalLines { get; } = new List<Line>(); // 网格交点 public SortedSet<double> XCoords { get; } = new SortedSet<double>(); public SortedSet<double> YCoords { get; } = new SortedSet<double>(); // 容差 private const double Tolerance = 0.05; // 1mm容差 private readonly Editor _ed; public GridTopology(List<Line> gridLines, Editor ed = null) { _ed = ed; try { // 1. 分类所有网格线 foreach (Line line in gridLines) { Vector3d vec = line.EndPoint - line.StartPoint; // 水平线 (Y变化很小) if (Math.Abs(vec.Y) < Tolerance) { HorizontalLines.Add(line); YCoords.Add(Math.Round(line.StartPoint.Y, 3)); } // 垂直线 (X变化很小) else if (Math.Abs(vec.X) < Tolerance) { VerticalLines.Add(line); XCoords.Add(Math.Round(line.StartPoint.X, 3)); } } if (_ed != null) { _ed.WriteMessage($"\n水平线: {HorizontalLines.Count}条, 垂直线: {VerticalLines.Count}条"); } // 2. 验证网格完整性 if (XCoords.Count < 2 || YCoords.Count < 2) { if (_ed != null) _ed.WriteMessage("\n错误:网格坐标不足,无法形成有效网格"); return; } // 3. 确定网格大小 Rows = YCoords.Count - 1; Cols = XCoords.Count - 1; if (_ed != null) { _ed.WriteMessage($"\nX坐标: {XCoords.Count}, Y坐标: {YCoords.Count}"); _ed.WriteMessage($"\n网格单元: {Rows}行 x {Cols}列"); } } catch (System.Exception ex) { if (_ed != null) _ed.WriteMessage($"\n网格拓扑错误: {ex.Message}"); Rows = 0; Cols = 0; } } // 检查线段是否在网格线上 public bool IsSegmentOnGrid(LineSegment seg) { if (seg == null) return false; // 检查是否为水平线 if (Math.Abs(seg.StartPoint.Y - seg.EndPoint.Y) < Tolerance) { return HorizontalLines.Any(line => IsSameLine(seg, line, Tolerance)); } // 检查是否为垂直线 else if (Math.Abs(seg.StartPoint.X - seg.EndPoint.X) < Tolerance) { return VerticalLines.Any(line => IsSameLine(seg, line, Tolerance)); } return false; } // 检查两个线段是否相同 private bool IsSameLine(LineSegment seg, Line line, double tolerance) { // 检查起点匹配 bool startMatch = (line.StartPoint.DistanceTo(seg.StartPoint) < tolerance && line.EndPoint.DistanceTo(seg.EndPoint) < tolerance); // 检查反向匹配 bool reverseMatch = (line.StartPoint.DistanceTo(seg.EndPoint) < tolerance && line.EndPoint.DistanceTo(seg.StartPoint) < tolerance); return startMatch || reverseMatch; } public LineSegment GetHorizontalSegment(int row, int col) { if (row < 0 || row > Rows || col < 0 || col >= Cols) return null; double y = YCoords.ElementAt(row); double x1 = XCoords.ElementAt(col); double x2 = XCoords.ElementAt(col + 1); // 查找匹配的水平线 foreach (var line in HorizontalLines) { if (Math.Abs(line.StartPoint.Y - y) > Tolerance && Math.Abs(line.EndPoint.Y - y) > Tolerance) continue; double minX = Math.Min(line.StartPoint.X, line.EndPoint.X); double maxX = Math.Max(line.StartPoint.X, line.EndPoint.X); if (Math.Abs(minX - x1) < Tolerance && Math.Abs(maxX - x2) < Tolerance) { return new LineSegment(line.StartPoint, line.EndPoint); } } return null; } public LineSegment GetVerticalSegment(int row, int col) { if (row < 0 || row >= Rows || col < 0 || col > Cols) return null; double x = XCoords.ElementAt(col); double y1 = YCoords.ElementAt(row); double y2 = YCoords.ElementAt(row + 1); // 查找匹配的垂直线 foreach (var line in VerticalLines) { if (Math.Abs(line.StartPoint.X - x) > Tolerance && Math.Abs(line.EndPoint.X - x) > Tolerance) continue; double minY = Math.Min(line.StartPoint.Y, line.EndPoint.Y); double maxY = Math.Max(line.StartPoint.Y, line.EndPoint.Y); if (Math.Abs(minY - y1) < Tolerance && Math.Abs(maxY - y2) < Tolerance) { return new LineSegment(line.StartPoint, line.EndPoint); } } return null; } } internal class LineSegment { public Point3d StartPoint { get; } public Point3d EndPoint { get; } public double Length => StartPoint.DistanceTo(EndPoint); public Vector3d Direction => (EndPoint - StartPoint).GetNormal(); public Point3d MidPoint => new Point3d( (StartPoint.X + EndPoint.X) / 2, (StartPoint.Y + EndPoint.Y) / 2, (StartPoint.Z + EndPoint.Z) / 2); public LineSegment(Point3d start, Point3d end) { StartPoint = start; EndPoint = end; } } } CS1061“GnidTopology"未包含”HasEndpoints”的定义,并且找不到可接受第一个“GridTopology"类型参数的可访问扩展方法“HasEndpoints"(是否缺少using 指令或程序集引用?)
最新发布
07-12
using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.GraphicsInterface; using Autodesk.AutoCAD.Runtime; using System; using System.Collections.Generic; using System.Linq; // 解决Exception命名冲突 using SysException = System.Exception; using AcException = Autodesk.AutoCAD.Runtime.Exception; namespace GridLinePlugin { public class GridLineCommands { // 固定线段长度选项(毫米) private static readonly double[] FixedLengths = { 300, 600, 900, 1200, 1500, 1800 }; private const string LAYER_NAME = "盘扣轴网"; // 参数记忆静态变量 private static double _lastOffsetX = 0.0; private static double _lastOffsetY = 0.0; private static double _lastStartLengthX = 900.0; private static double _lastStartLengthY = 1500.0; // 辅助方法移动到类顶部 private double GetOffset(string message, double defaultValue, Editor ed) { string formattedMessage = string.Format(message, defaultValue); PromptDoubleOptions opts = new PromptDoubleOptions(formattedMessage) { AllowNegative = true, AllowZero = true, DefaultValue = defaultValue, UseDefaultValue = true }; PromptDoubleResult res = ed.GetDouble(opts); return res.Status == PromptStatus.OK ? res.Value : defaultValue; } private double GetSegmentLength(string message, double defaultValue, Editor ed) { string formattedMessage = string.Format(message, defaultValue); PromptDoubleOptions opts = new PromptDoubleOptions(formattedMessage) { AllowNegative = false, AllowZero = false, AllowNone = false, DefaultValue = defaultValue, UseDefaultValue = true }; PromptDoubleResult res; do { res = ed.GetDouble(opts); if (res.Status != PromptStatus.OK) return defaultValue; if (res.Value <= 0) { ed.WriteMessage("\n长度必须大于0! 请重新输入: "); } } while (res.Value <= 0); return res.Value; } [CommandMethod("DG", CommandFlags.Modal)] public void DrawGridInteractive() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; try { // 1. 获取偏移值 double offsetX = GetOffset("\nX方向偏移值 (mm) <{0}>: ", _lastOffsetX, ed); double offsetY = GetOffset("\nY方向偏移值 (mm) <{0}>: ", _lastOffsetY, ed); // 2. 获取起始长度 double startLengthX = GetSegmentLength("\n横向起始线段长度 (mm) <{0}>: ", _lastStartLengthX, ed); double startLengthY = GetSegmentLength("\n纵向起始线段长度 (mm) <{0}>: ", _lastStartLengthY, ed); // 更新记忆参数 _lastOffsetX = offsetX; _lastOffsetY = offsetY; _lastStartLengthX = startLengthX; _lastStartLengthY = startLengthY; // 3. 获取起始点 PromptPointResult startPtRes = ed.GetPoint("\n选择网格起始点: "); if (startPtRes.Status != PromptStatus.OK) return; Point3d basePoint = startPtRes.Value; // 应用偏移 Point3d actualStartPoint = basePoint + new Vector3d(offsetX, offsetY, 0); // 4. 创建并运行拖拽器 GridJig jig = new GridJig(actualStartPoint, startLengthX, startLengthY, doc); PromptResult jigResult = ed.Drag(jig); if (jigResult.Status == PromptStatus.OK) { jig.CommitGrid(LAYER_NAME); int shortLines = jig.GetShortLineCount(300.0); if (shortLines > 0) { ed.WriteMessage($"\n警告: 有 {shortLines} 条线段长度小于300mm!"); } ed.WriteMessage($"\n成功绘制网格! 共生成 {jig.LineCount} 条线段"); } } catch (SysException ex) // 使用别名解决冲突 { ed.WriteMessage($"\n错误: {ex.Message}"); } } [CommandMethod("CO", CommandFlags.Modal)] public void CheckOverlap() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { // 让用户框选线段 PromptSelectionOptions selOpts = new PromptSelectionOptions { MessageForAdding = "请框选需要检查重叠的线段: " }; PromptSelectionResult selRes = ed.GetSelection(selOpts); if (selRes.Status != PromptStatus.OK) return; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTableRecord btr = tr.GetObject( SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite) as BlockTableRecord; // 收集选中的线段 List<Line> allLines = new List<Line>(); foreach (SelectedObject so in selRes.Value) { Line line = tr.GetObject(so.ObjectId, OpenMode.ForRead) as Line; if (line != null && line.Layer == LAYER_NAME) { allLines.Add(line); } } // 分组处理:水平线和垂直线 List<Line> horizontalLines = new List<Line>(); List<Line> verticalLines = new List<Line>(); const double angleTolerance = 0.01; // 角度容差(弧度) foreach (Line line in allLines) { Vector3d dir = (line.EndPoint - line.StartPoint).GetNormal(); double angle = dir.GetAngleTo(Vector3d.XAxis); // 水平线(0°或180°) if (angle < angleTolerance || Math.Abs(angle - Math.PI) < angleTolerance) { horizontalLines.Add(line); } // 垂直线(90°或270°) else if (Math.Abs(angle - Math.PI / 2) < angleTolerance || Math.Abs(angle - 3 * Math.PI / 2) < angleTolerance) { verticalLines.Add(line); } } // 处理水平线重叠 - 直接删除重叠线段(保留一条) ProcessOverlappingLines(horizontalLines, true, tr); // 处理垂直线重叠 - 直接删除重叠线段(保留一条) ProcessOverlappingLines(verticalLines, false, tr); tr.Commit(); ed.WriteMessage("\n重叠处理完成!"); } } catch (SysException ex) { ed.WriteMessage($"\n错误: {ex.Message}"); } } // 处理同一方向上的线段重叠 - 新方法:直接删除重叠线段(保留一条) private void ProcessOverlappingLines(List<Line> lines, bool isHorizontal, Transaction tr) { if (lines.Count < 2) return; // 按坐标排序(水平线按Y,垂直线按X) lines.Sort((a, b) => isHorizontal ? a.StartPoint.Y.CompareTo(b.StartPoint.Y) : a.StartPoint.X.CompareTo(b.StartPoint.X)); // 分组:相同坐标位置的线段为一组 var groups = lines.GroupBy(line => isHorizontal ? Math.Round(line.StartPoint.Y, 4) : Math.Round(line.StartPoint.X, 4) ); // 记录要删除的线段ID List<ObjectId> linesToDelete = new List<ObjectId>(); foreach (var group in groups) { // 每组内按起点位置排序 List<Line> sortedLines = isHorizontal ? group.OrderBy(l => Math.Min(l.StartPoint.X, l.EndPoint.X)).ToList() : group.OrderBy(l => Math.Min(l.StartPoint.Y, l.EndPoint.Y)).ToList(); // 创建已检查线段的集合 HashSet<ObjectId> processedLines = new HashSet<ObjectId>(); for (int i = 0; i < sortedLines.Count; i++) { Line line1 = sortedLines[i]; if (processedLines.Contains(line1.ObjectId)) continue; for (int j = i + 1; j < sortedLines.Count; j++) { Line line2 = sortedLines[j]; if (processedLines.Contains(line2.ObjectId)) continue; // 获取线段范围 double start1, end1, start2, end2; GetLineRange(line1, isHorizontal, out start1, out end1); GetLineRange(line2, isHorizontal, out start2, out end2); // 检查重叠 if (end1 > start2 && end2 > start1) { // 将第二条线段标记为删除 linesToDelete.Add(line2.ObjectId); processedLines.Add(line2.ObjectId); } } } } // 删除所有标记的线段 foreach (ObjectId id in linesToDelete) { Line line = tr.GetObject(id, OpenMode.ForWrite) as Line; if (!line.IsErased) { line.Erase(); } } } // 获取线段在指定方向的范围 private void GetLineRange(Line line, bool isHorizontal, out double start, out double end) { if (isHorizontal) { start = Math.Min(line.StartPoint.X, line.EndPoint.X); end = Math.Max(line.StartPoint.X, line.EndPoint.X); } else { start = Math.Min(line.StartPoint.Y, line.EndPoint.Y); end = Math.Max(line.StartPoint.Y, line.EndPoint.Y); } } // 检查两条线是否重叠 private bool AreLinesOverlapping(Line line1, Line line2) { const double tolerance = 0.001; Vector3d dir1 = line1.EndPoint - line1.StartPoint; Vector3d dir2 = line2.EndPoint - line2.StartPoint; if (!dir1.IsParallelTo(dir2, new Tolerance(tolerance, tolerance))) return false; Vector3d toLine2Start = line2.StartPoint - line1.StartPoint; if (!toLine2Start.IsPerpendicularTo(dir1, new Tolerance(tolerance, tolerance))) return false; double min1 = Math.Min(0, 1); double max1 = Math.Max(0, 1); double startParam = GetLineParameter(line1, line2.StartPoint); double endParam = GetLineParameter(line1, line2.EndPoint); double min2 = Math.Min(startParam, endParam); double max2 = Math.Max(startParam, endParam); return (min1 <= max2 + tolerance && max1 >= min2 - tolerance); } // 计算点在直线上的参数位置 private double GetLineParameter(Line line, Point3d point) { Vector3d lineVec = line.EndPoint - line.StartPoint; Vector3d pointVec = point - line.StartPoint; double dotProduct = lineVec.DotProduct(pointVec); double lineLengthSq = lineVec.DotProduct(lineVec); return lineLengthSq > 0 ? dotProduct / lineLengthSq : 0; } // 网格拖拽器类 private class GridJig : DrawJig { private readonly Point3d _startPoint; private Point3d _currentPoint; private readonly double _startLengthX; private readonly double _startLengthY; private readonly Document _doc; private readonly List<Line> _lines = new List<Line>(); private List<double> _xSegments = new List<double>(); private List<double> _ySegments = new List<double>(); public int LineCount => _lines.Count; public int GetShortLineCount(double minLength) { return _lines.Count(line => line.Length < minLength); } public GridJig(Point3d startPoint, double startLengthX, double startLengthY, Document doc) { _startPoint = startPoint; _currentPoint = startPoint; _startLengthX = startLengthX; _startLengthY = startLengthY; _doc = doc; } // 实现抽象成员 protected override SamplerStatus Sampler(JigPrompts prompts) { JigPromptPointOptions opts = new JigPromptPointOptions("\n指定网格终点或输入长度: ") { UserInputControls = UserInputControls.Accept3dCoordinates | UserInputControls.NoZeroResponseAccepted | UserInputControls.NoNegativeResponseAccepted, BasePoint = _startPoint, UseBasePoint = true, Cursor = CursorType.RubberBand }; PromptPointResult result = prompts.AcquirePoint(opts); if (result.Status == PromptStatus.Cancel) return SamplerStatus.Cancel; if (_currentPoint.DistanceTo(result.Value) < 0.001) return SamplerStatus.NoChange; _currentPoint = result.Value; return SamplerStatus.OK; } protected override bool WorldDraw(WorldDraw draw) { try { // 清除临时图形 foreach (var line in _lines) { if (!line.IsDisposed) line.Dispose(); } _lines.Clear(); // 计算方向向量 Vector3d delta = _currentPoint - _startPoint; double dx = delta.X; double dy = delta.Y; // 计算总长度和方向 double totalX = Math.Abs(dx); double totalY = Math.Abs(dy); int signX = Math.Sign(dx); int signY = Math.Sign(dy); // 生成分段点 - 使用指定的起始长度 _xSegments = GenerateSegments(totalX, _startLengthX, true); _ySegments = GenerateSegments(totalY, _startLengthY, false); // 调试输出 _doc.Editor.WriteMessage($"\nX方向分段数: {_xSegments.Count}, Y方向分段数: {_ySegments.Count}"); // 计算实际终点 Point3d actualEndPoint = new Point3d( _startPoint.X + signX * _xSegments.Last(), _startPoint.Y + signY * _ySegments.Last(), _startPoint.Z ); // 绘制横向网格线 DrawHorizontalLines(signX, signY, actualEndPoint, draw); // 绘制纵向网格线 DrawVerticalLines(signX, signY, actualEndPoint, draw); } catch (SysException ex) { _doc.Editor.WriteMessage($"\n绘图错误: {ex.Message}"); } return true; } // 分段生成算法 - 修复:优先使用起始长度进行连续布置 private List<double> GenerateSegments(double totalLength, double spacing, bool isXDirection) { List<double> segments = new List<double> { 0 }; if (totalLength <= 0) return segments; double currentPos = 0; int segmentCount = 0; // 优先使用起始长度进行连续布置 while (currentPos < totalLength && segmentCount < 100) { // 尝试使用起始长度 if (currentPos + spacing <= totalLength) { currentPos += spacing; segments.Add(currentPos); segmentCount++; continue; } // 起始长度不适用时,尝试固定长度 double maxFixed = FixedLengths .Where(len => currentPos + len <= totalLength) .DefaultIfEmpty(0) .Max(); if (maxFixed >= 300) { currentPos += maxFixed; segments.Add(currentPos); segmentCount++; } else { // 如果固定长度也不适用,尝试剩余长度 double remaining = totalLength - currentPos; if (remaining >= 300) { currentPos = totalLength; segments.Add(currentPos); } break; } } // 确保包含终点(如果剩余长度不足300mm则跳过) if (segments.Last() < totalLength && (totalLength - segments.Last()) >= 300) { segments.Add(totalLength); } // 确保至少有两个分段点 if (segments.Count < 2) { segments.Add(totalLength); } return segments; } // 绘制横向线 private void DrawHorizontalLines(int signX, int signY, Point3d actualEndPoint, WorldDraw draw) { if (_ySegments.Count == 0) return; for (int i = 0; i < _ySegments.Count; i++) { double yPos = _ySegments[i]; Point3d start = _startPoint + new Vector3d(0, signY * yPos, 0); // 终点自动修剪到实际终点 Point3d end = new Point3d(actualEndPoint.X, start.Y, start.Z); Line line = new Line(start, end); line.ColorIndex = 1; if (line.Length < 0.001) continue; if (!IsOverlapping(line)) { _lines.Add(line); draw.Geometry.Draw(line); } } } // 绘制纵向线 private void DrawVerticalLines(int signX, int signY, Point3d actualEndPoint, WorldDraw draw) { if (_xSegments.Count == 0) return; for (int i = 0; i < _xSegments.Count; i++) { double xPos = _xSegments[i]; Point3d start = _startPoint + new Vector3d(signX * xPos, 0, 0); // 终点自动修剪到实际终点 Point3d end = new Point3d(start.X, actualEndPoint.Y, start.Z); Line line = new Line(start, end); line.ColorIndex = 1; if (line.Length < 0.001) continue; if (!IsOverlapping(line)) { _lines.Add(line); draw.Geometry.Draw(line); } } } // 重叠检测方法 private bool IsOverlapping(Line newLine) { const double toleranceValue = 0.1; Tolerance tolerance = new Tolerance(toleranceValue, toleranceValue); foreach (Line existingLine in _lines) { bool sameStart = newLine.StartPoint.IsEqualTo(existingLine.StartPoint, tolerance) || newLine.StartPoint.IsEqualTo(existingLine.EndPoint, tolerance); bool sameEnd = newLine.EndPoint.IsEqualTo(existingLine.StartPoint, tolerance) || newLine.EndPoint.IsEqualTo(existingLine.EndPoint, tolerance); if (sameStart && sameEnd) { return true; } } return false; } // 提交网格到图纸 public void CommitGrid(string layerName) { using (Transaction tr = _doc.Database.TransactionManager.StartTransaction()) { try { BlockTable bt = tr.GetObject(_doc.Database.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; // 创建图层 LayerTable lt = tr.GetObject(_doc.Database.LayerTableId, OpenMode.ForRead) as LayerTable; if (!lt.Has(layerName)) { lt.UpgradeOpen(); LayerTableRecord layer = new LayerTableRecord { Name = layerName, Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex( Autodesk.AutoCAD.Colors.ColorMethod.ByAci, 1) }; lt.Add(layer); tr.AddNewlyCreatedDBObject(layer, true); } // 添加所有线段(最终修剪) foreach (Line line in _lines) { if (!line.IsDisposed) { // 精确修剪到网格边界 TrimToGridBoundary(line); // 跳过小于300mm的线段 if (line.Length < 300) continue; line.Layer = layerName; line.ColorIndex = 256; // ByLayer btr.AppendEntity(line); tr.AddNewlyCreatedDBObject(line, true); } } tr.Commit(); } catch (SysException) { tr.Abort(); throw; } } } // 精确修剪线段到网格边界 private void TrimToGridBoundary(Line line) { // 计算实际网格边界 double maxX = _xSegments.Last(); double maxY = _ySegments.Last(); // 获取线段的实际方向 Vector3d direction = line.EndPoint - line.StartPoint; // 横向线修剪到最大Y位置 if (Math.Abs(direction.X) > Math.Abs(direction.Y)) { double currentY = Math.Abs(line.EndPoint.Y - _startPoint.Y); if (currentY > maxY) { line.EndPoint = new Point3d( line.EndPoint.X, _startPoint.Y + Math.Sign(direction.Y) * maxY, line.EndPoint.Z); } } // 纵向线修剪到最大X位置 else { double currentX = Math.Abs(line.EndPoint.X - _startPoint.X); if (currentX > maxX) { line.EndPoint = new Point3d( _startPoint.X + Math.Sign(direction.X) * maxX, line.EndPoint.Y, line.EndPoint.Z); } } } } } } 将“CO”功能改为框选需要检查重叠的线段后对重叠段的线段进行合并成一根线,只针对指定的“盘扣轴网”作"CO”功能的处理
07-07
import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.*; public class OrthogonalPathFinder { private static final float GRID_SIZE = 0.5f; // 网格步长,可根据需要调整 private static final float EPSILON = 1e-5f; // 浮点数比较容差 static class Node implements Comparable<Node> { Point2D.Float point; Node parent; double gScore; // 从起点到当前节点的实际代价 double fScore; // 总估计代价 (gScore + 启发式代价) Node(Point2D.Float point, Node parent, double gScore, double fScore) { this.point = point; this.parent = parent; this.gScore = gScore; this.fScore = fScore; } @Override public int compareTo(Node other) { return Double.compare(this.fScore, other.fScore); } } public static List<Point2D.Float> findPath(List<Rectangle2D.Float> obstacles, Point2D.Float start, Point2D.Float end) { // 检查起点和终点是否在障碍物内 if (isPointInObstacle(start, obstacles) || isPointInObstacle(end, obstacles)) { return Collections.emptyList(); } // 计算搜索边界 float[] bounds = calculateBounds(obstacles, start, end); float minX = bounds[0], minY = bounds[1], maxX = bounds[2], maxY = bounds[3]; // A* 算法初始化 PriorityQueue<Node> openSet = new PriorityQueue<>(); Map<Point2D.Float, Double> gScoreMap = new HashMap<>(); Map<Point2D.Float, Node> nodeMap = new HashMap<>(); Node startNode = new Node(start, null, 0, heuristic(start, end)); openSet.add(startNode); gScoreMap.put(start, 0.0); while (!openSet.isEmpty()) { Node current = openSet.poll(); Point2D.Float currentPoint = current.point; // 到达终点,回溯路径 if (isEqual(currentPoint, end)) { return reconstructPath(current); } // 生成四个方向的邻居点 Point2D.Float[] neighbors = { new Point2D.Float(currentPoint.x + GRID_SIZE, currentPoint.y), // 右 new Point2D.Float(currentPoint.x - GRID_SIZE, currentPoint.y), // 左 new Point2D.Float(currentPoint.x, currentPoint.y + GRID_SIZE), // 上 new Point2D.Float(currentPoint.x, currentPoint.y - GRID_SIZE) // 下 }; for (Point2D.Float neighbor : neighbors) { // 检查邻居点是否在边界内 if (neighbor.x < minX || neighbor.x > maxX || neighbor.y < minY || neighbor.y > maxY) { continue; } // 检查线段是否与障碍物相交 if (isLineIntersectingObstacle(currentPoint, neighbor, obstacles)) { continue; } // 计算新的代价 double tentativeGScore = current.gScore + GRID_SIZE; double oldGScore = gScoreMap.getOrDefault(neighbor, Double.POSITIVE_INFINITY); // 如果新路径更好,更新节点 if (tentativeGScore < oldGScore) { double fScore = tentativeGScore + heuristic(neighbor, end); Node neighborNode = new Node(neighbor, current, tentativeGScore, fScore); gScoreMap.put(neighbor, tentativeGScore); openSet.add(neighborNode); } } } return Collections.emptyList(); // 无路径 } // 回溯重建路径 private static List<Point2D.Float> reconstructPath(Node endNode) { LinkedList<Point2D.Float> path = new LinkedList<>(); Node current = endNode; while (current != null) { path.addFirst(current.point); current = current.parent; } return path; } // 计算曼哈顿距离作为启发式函数 private static double heuristic(Point2D.Float a, Point2D.Float b) { return Math.abs(a.x - b.x) + Math.abs(a.y - b.y); } // 检查点是否在障碍物内 private static boolean isPointInObstacle(Point2D.Float point, List<Rectangle2D.Float> obstacles) { for (Rectangle2D.Float rect : obstacles) { if (rect.contains(point.x, point.y)) { return true; } } return false; } // 检查线段是否与障碍物相交 private static boolean isLineIntersectingObstacle(Point2D.Float a, Point2D.Float b, List<Rectangle2D.Float> obstacles) { if (Math.abs(a.y - b.y) < EPSILON) { // 水平线段 float y = a.y; float x1 = Math.min(a.x, b.x); float x2 = Math.max(a.x, b.x); for (Rectangle2D.Float rect : obstacles) { if (y >= rect.getMinY() && y <= rect.getMaxY()) { if (x1 <= rect.getMaxX() && x2 >= rect.getMinX()) { return true; } } } } else if (Math.abs(a.x - b.x) < EPSILON) { // 垂直线段 float x = a.x; float y1 = Math.min(a.y, b.y); float y2 = Math.max(a.y, b.y); for (Rectangle2D.Float rect : obstacles) { if (x >= rect.getMinX() && x <= rect.getMaxX()) { if (y1 <= rect.getMaxY() && y2 >= rect.getMinY()) { return true; } } } } return false; } // 计算搜索边界 private static float[] calculateBounds(List<Rectangle2D.Float> obstacles, Point2D.Float start, Point2D.Float end) { float minX = Math.min(start.x, end.x); float minY = Math.min(start.y, end.y); float maxX = Math.max(start.x, end.x); float maxY = Math.max(start.y, end.y); for (Rectangle2D.Float rect : obstacles) { minX = Math.min(minX, rect.x); minY = Math.min(minY, rect.y); maxX = Math.max(maxX, rect.x + rect.width); maxY = Math.max(maxY, rect.y + rect.height); } // 扩展边界 minX -= 1.0f; minY -= 1.0f; maxX += 1.0f; maxY += 1.0f; return new float[]{minX, minY, maxX, maxY}; } // 浮点数比较(容差) private static boolean isEqual(Point2D.Float a, Point2D.Float b) { return Math.abs(a.x - b.x) < EPSILON && Math.abs(a.y - b.y) < EPSILON; } }
05-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值