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 Autodesk.AutoCAD.Windows;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using static Autodesk.AutoCAD.LayerManager.LayerFilter;
using Application = Autodesk.AutoCAD.ApplicationServices.Application;
using DialogResult = System.Windows.Forms.DialogResult;
using Exception = Autodesk.AutoCAD.Runtime.Exception;
using SaveFileDialog = System.Windows.Forms.SaveFileDialog;
namespace QuadProcessor
{
public class QuadProcessor
{
[CommandMethod("PROCESSQUADS", CommandFlags.Modal)]
public void ProcessQuads()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
try
{
// 选择四边形(LWPOLYLINE)
PromptSelectionResult selRes = ed.GetSelection(new SelectionFilter(
new[] { new TypedValue(0, "LWPOLYLINE") }));
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\n操作已取消。");
return;
}
int totalCount = selRes.Value.Count;
int processedCount = 0;
int skippedCount = 0;
var results = new List<QuadResult>();
// 使用句柄作为键
var errors = new Dictionary<string, string>();
var skipReasons = new Dictionary<string, string>();
Stopwatch sw = Stopwatch.StartNew();
ObjectId[] ids = selRes.Value.GetObjectIds();
// 获取排序选项
var sortOption = GetSortOption(ed);
if (sortOption == null) return; // 用户取消
// 使用文档锁确保线程安全
using (DocumentLock docLock = doc.LockDocument())
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// 单线程处理所有选择的四边形
for (int i = 0; i < ids.Length; i++)
{
ObjectId id = ids[i];
string handle = id.Handle.ToString();
try
{
Polyline pl = tr.GetObject(id, OpenMode.ForRead) as Polyline;
if (pl != null)
{
if (pl.NumberOfVertices == 4 && pl.Closed)
{
string skipReason;
string textContent = GetTextInsidePolyline(tr, pl);
var result = ProcessQuad(pl, out skipReason, textContent, i + 1);
if (result != null)
{
results.Add(result);
processedCount++;
}
else
{
skippedCount++;
skipReasons[handle] = skipReason ?? "未知原因跳过";
}
}
else
{
skippedCount++;
skipReasons[handle] = "不是四边形(顶点数不为4或未闭合)";
}
}
else
{
skippedCount++;
skipReasons[handle] = "所选对象不是多段线";
}
}
catch (Exception ex)
{
errors[handle] = $"处理失败: {ex.Message}";
}
}
tr.Commit();
} // 这里会自动解锁文档
// 按用户选择的排序方式排序结果
SortResults(results, sortOption.Value);
// 获取默认桌面路径
string defaultPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
"InformationExport.csv");
// 显示保存文件对话框
string csvPath = ShowSaveFileDialog(defaultPath);
if (csvPath != null)
{
// 导出结果
ExportToCSV(results, csvPath);
// 显示统计信息
ed.WriteMessage($"\n处理完成: " +
$"\n总四边形数: {totalCount} " +
$"\n成功处理: {processedCount} " +
$"\n跳过: {skippedCount} " +
$"\n错误: {errors.Count} " +
$"\n耗时: {sw.Elapsed.TotalSeconds:F2}秒" +
$"\n结果已保存至: {csvPath}");
// 询问是否打开文件
ed.WriteMessage("\n\n**********************************************");
ed.WriteMessage("\n* 是否打开结果文件? [是(Y)/否(N)] <是>: *");
ed.WriteMessage("\n**********************************************");
PromptKeywordOptions openOptions = new PromptKeywordOptions("");
openOptions.Keywords.Add("是", "Y", "Y");
openOptions.Keywords.Add("否", "N", "N");
openOptions.Keywords.Default = "是";
openOptions.AllowNone = true;
PromptResult openRes = ed.GetKeywords(openOptions);
if (openRes.Status == PromptStatus.OK && openRes.StringResult == "是")
{
try
{
Process.Start(new ProcessStartInfo(csvPath) { UseShellExecute = true });
}
catch (Exception ex)
{
ed.WriteMessage($"\n打开文件失败: {ex.Message}");
}
}
// 询问是否在CAD中插入结果表格
PromptKeywordOptions tableOptions = new PromptKeywordOptions("\n是否在CAD图中插入结果表格? [是(Y)/否(N)] <是>: ");
tableOptions.Keywords.Add("是", "Y", "Y");
tableOptions.Keywords.Add("否", "N", "N");
tableOptions.Keywords.Default = "是";
tableOptions.AllowNone = true;
PromptResult tableRes = ed.GetKeywords(tableOptions);
if (tableRes.Status == PromptStatus.OK && tableRes.StringResult == "是")
{
// 提示用户指定表格插入点
PromptPointResult ppr = ed.GetPoint("\n指定表格插入点: ");
if (ppr.Status == PromptStatus.OK)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
InsertResultsTable(tr, results, ppr.Value);
tr.Commit();
ed.WriteMessage("\n结果表格已插入到图中。");
}
}
}
}
else
{
ed.WriteMessage("\n操作已取消,未保存结果。");
}
// 错误日志记录
if (errors.Count > 0 || skipReasons.Count > 0)
{
string logDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string logFileName = $"gs_{DateTime.Now:yyyyMMddHHmmss}.log";
string logPath = Path.Combine(logDir, logFileName);
using (StreamWriter logWriter = new StreamWriter(logPath))
{
logWriter.WriteLine($"四边形处理日志 - {DateTime.Now}");
logWriter.WriteLine("=================================");
if (errors.Count > 0)
{
logWriter.WriteLine("\n错误详情:");
foreach (var error in errors)
{
logWriter.WriteLine($"句柄 {error.Key}: {error.Value}");
}
}
if (skipReasons.Count > 0)
{
logWriter.WriteLine("\n跳过详情:");
foreach (var skip in skipReasons)
{
logWriter.WriteLine($"句柄 {skip.Key}: {skip.Value}");
}
}
}
ed.WriteMessage($"\n详细错误和跳过信息已保存至: {logPath}");
}
// 显示错误信息
if (errors.Count > 0)
{
ed.WriteMessage("\n\n错误详情:");
foreach (var error in errors)
{
ed.WriteMessage($"\n句柄 {error.Key}: {error.Value}");
}
}
// 显示跳过信息
if (skipReasons.Count > 0)
{
ed.WriteMessage("\n\n跳过详情:");
foreach (var skip in skipReasons)
{
ed.WriteMessage($"\n句柄 {skip.Key}: {skip.Value}");
}
}
}
catch (Exception ex)
{
ed.WriteMessage($"\n错误: {ex.Message}");
}
}
// 在CAD中插入结果表格 (修复版本)
private void InsertResultsTable(Transaction tr, List<QuadResult> results, Point3d insertionPoint)
{
try
{
Database db = Application.DocumentManager.MdiActiveDocument.Database;
// 创建表格
Table table = new Table();
table.TableStyle = db.Tablestyle; // 使用当前表格样式
table.SetSize(results.Count + 1, 13); // 行数:结果行数+标题行,列数:13
table.Position = insertionPoint;
// 设置行高和文本高度
for (int i = 0; i <= results.Count; i++)
{
table.SetRowHeight(i, i == 0 ? 15 : 10);
table.SetTextHeight(i, i == 0 ? 4 : 3.5);
}
// 设置单元格边距
for (int row = 0; row <= results.Count; row++)
{
for (int col = 0; col < 13; col++)
{
table.Cells[row, col].HorizontalMargin = 1;
table.Cells[row, col].VerticalMargin = 1;
}
}
// 设置标题行
string[] headers = { "序号", "对象句柄", "图形编号", "边1", "边2", "边3", "边4", "对角线1", "对角线2", "最小外接矩形宽度", "最小外接矩形高度", "中心点X", "中心点Y" };
for (int col = 0; col < headers.Length; col++)
{
table.Cells[0, col].TextString = headers[col];
table.Cells[0, col].Alignment = CellAlignment.MiddleCenter;
table.Cells[0, col].BackgroundColor = Color.FromColorIndex(ColorMethod.ByAci, 253); // 浅灰色背景
table.Cells[0, col].BorderColor = Color.FromColorIndex(ColorMethod.ByAci, 0); // 黑色边框
}
// 填充数据行
for (int row = 0; row < results.Count; row++)
{
QuadResult r = results[row];
table.Cells[row + 1, 0].TextString = r.SequenceNumber.ToString();
table.Cells[row + 1, 1].TextString = r.Handle;
table.Cells[row + 1, 2].TextString = r.TextContent;
table.Cells[row + 1, 3].TextString = r.Side1.ToString("F0");
table.Cells[row + 1, 4].TextString = r.Side2.ToString("F0");
table.Cells[row + 1, 5].TextString = r.Side3.ToString("F0");
table.Cells[row + 1, 6].TextString = r.Side4.ToString("F0");
table.Cells[row + 1, 7].TextString = r.Diagonal1.ToString("F0");
table.Cells[row + 1, 8].TextString = r.Diagonal2.ToString("F0");
table.Cells[row + 1, 9].TextString = r.OBBWidth.ToString("F0");
table.Cells[row + 1, 10].TextString = r.OBBHeight.ToString("F0");
table.Cells[row + 1, 11].TextString = r.CenterX.ToString("F0");
table.Cells[row + 1, 12].TextString = r.CenterY.ToString("F0");
// 设置数据对齐方式
for (int col = 0; col < 13; col++)
{
table.Cells[row + 1, col].Alignment = CellAlignment.MiddleCenter;
table.Cells[row + 1, col].BorderColor = Color.FromColorIndex(ColorMethod.ByAci, 0); // 黑色边框
}
}
// 设置列宽
double[] columnWidths = { 8, 15, 15, 8, 8, 8, 8, 10, 10, 15, 15, 12, 12 };
for (int col = 0; col < columnWidths.Length; col++)
{
table.Columns[col].Width = columnWidths[col];
}
// 添加到模型空间
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
btr.AppendEntity(table);
tr.AddNewlyCreatedDBObject(table, true);
}
catch (Exception ex)
{
Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage($"\n插入表格失败: {ex.Message}");
}
}
private SortOption? GetSortOption(Editor ed)
{
var options = new PromptKeywordOptions("\n选择排序方式 [图形编号(G)/选择顺序(S)/坐标位置(C)/序号(N)] <图形编号>: ");
// 添加关键字和别名
options.Keywords.Add("图形编号", "G", "G");
options.Keywords.Add("选择顺序", "S", "S");
options.Keywords.Add("坐标位置", "C", "C");
options.Keywords.Add("序号", "N", "N");
options.Keywords.Default = "图形编号";
options.AllowNone = true;
var res = ed.GetKeywords(options);
if (res.Status != PromptStatus.OK) return null;
// 根据用户输入返回排序选项
switch (res.StringResult)
{
case "图形编号":
case "G": return SortOption.TextID;
case "选择顺序":
case "S": return SortOption.SelectionOrder;
case "坐标位置":
case "C": return SortOption.Coordinate;
case "序号":
case "N": return SortOption.SequenceNumber;
default: return SortOption.TextID;
}
}
private void SortResults(List<QuadResult> results, SortOption sortOption)
{
switch (sortOption)
{
case SortOption.SequenceNumber:
break;
case SortOption.SelectionOrder:
break;
case SortOption.Coordinate:
results.Sort((a, b) =>
{
int cmp = a.CenterX.CompareTo(b.CenterX);
return cmp != 0 ? cmp : a.CenterY.CompareTo(b.CenterY);
});
break;
case SortOption.TextID:
results.Sort(new NaturalStringComparer());
break;
}
// 排序后重新设置序号
for (int i = 0; i < results.Count; i++)
{
results[i].SequenceNumber = i + 1;
}
}
// 自然排序比较器
public class NaturalStringComparer : IComparer<QuadResult>
{
public int Compare(QuadResult x, QuadResult y)
{
if (x == null && y == null) return 0;
if (x == null) return -1;
if (y == null) return 1;
return CompareNatural(x.TextContent, y.TextContent);
}
private int CompareNatural(string strA, string strB)
{
if (strA == null && strB == null) return 0;
if (strA == null) return -1;
if (strB == null) return 1;
int indexA = 0;
int indexB = 0;
while (indexA < strA.Length && indexB < strB.Length)
{
if (char.IsDigit(strA[indexA]) && char.IsDigit(strB[indexB]))
{
string numStrA = ExtractNumber(strA, ref indexA);
string numStrB = ExtractNumber(strB, ref indexB);
if (int.TryParse(numStrA, out int numA) && int.TryParse(numStrB, out int numB))
{
int numCompare = numA.CompareTo(numB);
if (numCompare != 0) return numCompare;
}
else
{
int strCompare = string.Compare(numStrA, numStrB, StringComparison.Ordinal);
if (strCompare != 0) return strCompare;
}
}
else
{
int charCompare = strA[indexA].CompareTo(strB[indexB]);
if (charCompare != 0) return charCompare;
indexA++;
indexB++;
}
}
return strA.Length.CompareTo(strB.Length);
}
private string ExtractNumber(string str, ref int index)
{
int start = index;
while (index < str.Length && char.IsDigit(str[index]))
{
index++;
}
return str.Substring(start, index - start);
}
}
private string ShowSaveFileDialog(string defaultPath)
{
try
{
SaveFileDialog saveDialog = new SaveFileDialog
{
Title = "导出四边形分析结果",
Filter = "CSV文件 (*.csv)|*.csv|所有文件 (*.*)|*.*",
FileName = Path.GetFileName(defaultPath),
InitialDirectory = Path.GetDirectoryName(defaultPath),
DefaultExt = ".csv",
AddExtension = true
};
IntPtr acadWindow = Application.MainWindow.Handle;
if (acadWindow != IntPtr.Zero)
{
System.Windows.Forms.IWin32Window owner = new WindowWrapper(acadWindow);
if (saveDialog.ShowDialog(owner) == DialogResult.OK)
{
return saveDialog.FileName;
}
}
else
{
if (saveDialog.ShowDialog() == DialogResult.OK)
{
return saveDialog.FileName;
}
}
}
catch (Exception)
{
return defaultPath;
}
return null;
}
private string GetTextInsidePolyline(Transaction tr, Polyline pl)
{
try
{
Extents3d extents = pl.GeometricExtents;
Point3d minPoint = extents.MinPoint;
Point3d maxPoint = extents.MaxPoint;
Point3dCollection points = new Point3dCollection
{
minPoint,
new Point3d(maxPoint.X, minPoint.Y, minPoint.Z),
maxPoint,
new Point3d(minPoint.X, maxPoint.Y, minPoint.Z),
minPoint
};
TypedValue[] filterList = new TypedValue[]
{
new TypedValue(0, "TEXT,MTEXT")
};
SelectionFilter filter = new SelectionFilter(filterList);
PromptSelectionResult selRes = Application.DocumentManager.MdiActiveDocument.Editor.SelectCrossingPolygon(points, filter);
if (selRes.Status == PromptStatus.OK)
{
SelectionSet selectionSet = selRes.Value;
List<TextInfo> textInfos = new List<TextInfo>();
foreach (SelectedObject selectedObject in selectionSet)
{
using (DBObject dbObj = tr.GetObject(selectedObject.ObjectId, OpenMode.ForRead))
{
Point3d position = Point3d.Origin;
string text = "";
if (dbObj is DBText dbText)
{
position = dbText.Position;
text = dbText.TextString;
}
else if (dbObj is MText mText)
{
position = mText.Location;
text = mText.Text;
}
if (!string.IsNullOrEmpty(text))
{
textInfos.Add(new TextInfo
{
Position = position,
Text = text,
DistanceToCenter = GetDistanceToPolylineCenter(pl, position)
});
}
}
}
if (textInfos.Count == 0) return "";
var closestText = textInfos.OrderBy(t => t.DistanceToCenter).First();
return closestText.Text;
}
}
catch
{
}
return "";
}
private double GetDistanceToPolylineCenter(Polyline pl, Point3d point)
{
double centerX = 0, centerY = 0;
for (int i = 0; i < 4; i++)
{
Point2d pt = pl.GetPoint2dAt(i);
centerX += pt.X;
centerY += pt.Y;
}
centerX /= 4;
centerY /= 4;
double dx = point.X - centerX;
double dy = point.Y - centerY;
return Math.Sqrt(dx * dx + dy * dy);
}
private Point2d[] ReorderVertices(Polyline pl, out string error)
{
error = null;
try
{
Point2d[] points = new Point2d[4];
for (int i = 0; i < 4; i++)
points[i] = pl.GetPoint2dAt(i);
var sortedByX = points.OrderBy(p => p.X).ToArray();
Point2d[] minXPoints = new Point2d[] { sortedByX[0], sortedByX[1] };
var sortedMinX = minXPoints.OrderBy(p => p.Y).ToArray();
Point2d bottomLeft = sortedMinX[0];
Point2d topLeft = sortedMinX[1];
Point2d[] remainingPoints = points.Except(minXPoints).ToArray();
var sortedRemaining = remainingPoints.OrderBy(p => p.Y).ToArray();
Point2d bottomRight = sortedRemaining[0];
Point2d topRight = sortedRemaining[1];
return new Point2d[] { bottomLeft, bottomRight, topRight, topLeft };
}
catch (Exception ex)
{
error = $"顶点排序失败: {ex.Message}";
return null;
}
}
private QuadResult ProcessQuad(Polyline pl, out string skipReason, string textContent, int sequenceNumber)
{
skipReason = null;
try
{
string error;
Point2d[] pts = ReorderVertices(pl, out error);
if (pts == null)
{
skipReason = error ?? "顶点排序失败";
return null;
}
if (pts.Length != 4)
{
skipReason = "顶点数不足4个";
return null;
}
double centerX = pts.Average(p => p.X);
double centerY = pts.Average(p => p.Y);
double side1 = pts[0].GetDistanceTo(pts[1]);
double side2 = pts[1].GetDistanceTo(pts[2]);
double side3 = pts[2].GetDistanceTo(pts[3]);
double side4 = pts[3].GetDistanceTo(pts[0]);
double diag1 = pts[0].GetDistanceTo(pts[2]);
double diag2 = pts[1].GetDistanceTo(pts[3]);
var obb = CalculateOBB(pts, out error);
if (obb == null)
{
skipReason = error ?? "无法计算最小外接矩形";
return null;
}
return new QuadResult(
sequenceNumber,
pl.ObjectId,
textContent,
side1, side2, side3, side4,
diag1, diag2,
obb.Width, obb.Height,
centerX, centerY);
}
catch (Exception ex)
{
skipReason = $"处理失败: {ex.Message}";
return null;
}
}
private OBBResult CalculateOBB(Point2d[] points, out string error)
{
error = null;
try
{
var hull = CalculateConvexHull(points);
if (hull == null || hull.Count < 3)
{
error = "无法计算凸包";
return null;
}
double minArea = double.MaxValue;
double width = 0, height = 0;
int hullCount = hull.Count;
if (hullCount == 3)
{
return ProcessTriangle(hull);
}
for (int i = 0; i < hullCount; i++)
{
Vector2d edge = hull[(i + 1) % hullCount] - hull[i];
double edgeLength = edge.Length;
if (edgeLength < 1e-9) continue;
Vector2d edgeDir = edge / edgeLength;
double angle = Math.Atan2(edgeDir.Y, edgeDir.X);
Matrix2d rot = Matrix2d.Rotation(-angle, Point2d.Origin);
double minX = double.MaxValue, maxX = double.MinValue;
double minY = double.MaxValue, maxY = double.MinValue;
for (int j = 0; j < hullCount; j++)
{
Point2d rotatedPt = hull[j].TransformBy(rot);
if (rotatedPt.X < minX) minX = rotatedPt.X;
if (rotatedPt.X > maxX) maxX = rotatedPt.X;
if (rotatedPt.Y < minY) minY = rotatedPt.Y;
if (rotatedPt.Y > maxY) maxY = rotatedPt.Y;
}
double w = maxX - minX;
double h = maxY - minY;
double area = w * h;
if (area < minArea)
{
minArea = area;
width = w;
height = h;
}
}
return new OBBResult(width, height);
}
catch (Exception ex)
{
error = $"OBB计算失败: {ex.Message}";
return null;
}
}
private List<Point2d> CalculateConvexHull(Point2d[] points)
{
try
{
if (points.Length < 3) return new List<Point2d>(points);
var sortedPoints = points.OrderBy(p => p.X).ThenBy(p => p.Y).ToArray();
List<Point2d> lowerHull = new List<Point2d>();
for (int i = 0; i < sortedPoints.Length; i++)
{
while (lowerHull.Count >= 2 &&
Cross(lowerHull[lowerHull.Count - 2], lowerHull[lowerHull.Count - 1], sortedPoints[i]) <= 0)
{
lowerHull.RemoveAt(lowerHull.Count - 1);
}
lowerHull.Add(sortedPoints[i]);
}
List<Point2d> upperHull = new List<Point2d>();
for (int i = sortedPoints.Length - 1; i >= 0; i--)
{
while (upperHull.Count >= 2 &&
Cross(upperHull[upperHull.Count - 2], upperHull[upperHull.Count - 1], sortedPoints[i]) <= 0)
{
upperHull.RemoveAt(upperHull.Count - 1);
}
upperHull.Add(sortedPoints[i]);
}
if (lowerHull.Count > 0) lowerHull.RemoveAt(lowerHull.Count - 1);
if (upperHull.Count > 0) upperHull.RemoveAt(upperHull.Count - 1);
lowerHull.AddRange(upperHull);
return lowerHull;
}
catch
{
return null;
}
}
private OBBResult ProcessTriangle(List<Point2d> triangle)
{
double minArea = double.MaxValue;
double width = 0, height = 0;
for (int i = 0; i < 3; i++)
{
Vector2d edge = triangle[(i + 1) % 3] - triangle[i];
double edgeLength = edge.Length;
if (edgeLength < 1e-9) continue;
Vector2d edgeDir = edge / edgeLength;
double angle = Math.Atan2(edgeDir.Y, edgeDir.X);
Matrix2d rot = Matrix2d.Rotation(-angle, Point2d.Origin);
double minX = double.MaxValue, maxX = double.MinValue;
double minY = double.MaxValue, maxY = double.MinValue;
for (int j = 0; j < 3; j++)
{
Point2d rotatedPt = triangle[j].TransformBy(rot);
if (rotatedPt.X < minX) minX = rotatedPt.X;
if (rotatedPt.X > maxX) maxX = rotatedPt.X;
if (rotatedPt.Y < minY) minY = rotatedPt.Y;
if (rotatedPt.Y > maxY) maxY = rotatedPt.Y;
}
double w = maxX - minX;
double h = maxY - minY;
double area = w * h;
if (area < minArea)
{
minArea = area;
width = w;
height = h;
}
}
return new OBBResult(width, height);
}
private double Cross(Point2d a, Point2d b, Point2d c)
{
return (b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X);
}
private void ExportToCSV(IEnumerable<QuadResult> results, string path)
{
try
{
using (StreamWriter sw = new StreamWriter(path))
{
sw.WriteLine("序号,对象句柄,图形编号,边1,边2,边3,边4,对角线1,对角线2,最小外接矩形宽度,最小外接矩形高度,中心点X,中心点Y");
foreach (var r in results)
{
sw.WriteLine($"{r.SequenceNumber}," +
$"{r.Handle}," +
$"\"{r.TextContent}\"," +
$"{r.Side1:F0},{r.Side2:F0},{r.Side3:F0},{r.Side4:F0}," +
$"{r.Diagonal1:F0},{r.Diagonal2:F0}," +
$"{r.OBBWidth:F0},{r.OBBHeight:F0}," +
$"{r.CenterX:F0},{r.CenterY:F0}");
}
}
}
catch (Exception ex)
{
Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(
$"\n保存文件时出错: {ex.Message}");
}
}
}
// 文字信息辅助类
public class TextInfo
{
public Point3d Position { get; set; }
public string Text { get; set; }
public double DistanceToCenter { get; set; }
}
// 排序选项枚举
public enum SortOption
{
TextID,
SelectionOrder,
Coordinate,
SequenceNumber
}
// 结果数据结构
public class QuadResult
{
public int SequenceNumber { get; set; }
public string Handle { get; }
public string TextContent { get; }
public double Side1 { get; }
public double Side2 { get; }
public double Side3 { get; }
public double Side4 { get; }
public double Diagonal1 { get; }
public double Diagonal2 { get; }
public double OBBWidth { get; }
public double OBBHeight { get; }
public double CenterX { get; }
public double CenterY { get; }
public QuadResult(
int sequenceNumber,
ObjectId objectId,
string textContent,
double side1, double side2, double side3, double side4,
double diag1, double diag2,
double width, double height,
double centerX, double centerY)
{
SequenceNumber = sequenceNumber;
Handle = objectId.Handle.ToString();
TextContent = textContent ?? "";
Side1 = side1;
Side2 = side2;
Side3 = side3;
Side4 = side4;
Diagonal1 = diag1;
Diagonal2 = diag2;
OBBWidth = width;
OBBHeight = height;
CenterX = centerX;
CenterY = centerY;
}
}
public class OBBResult
{
public double Width { get; }
public double Height { get; }
public OBBResult(double width, double height)
{
Width = width;
Height = height;
}
}
// 包装AutoCAD窗口的辅助类
public class WindowWrapper : System.Windows.Forms.IWin32Window
{
private readonly IntPtr _hwnd;
public WindowWrapper(IntPtr handle)
{
_hwnd = handle;
}
public IntPtr Handle
{
get { return _hwnd; }
}
}
}“Table.SetRowHeight(int, double)”已过时:“Use Table.Rows[col].Height instead.”
“Cell”未包含“BorderColor”的定义,并且找不到可接受第一个“Cell”类型参数的可访问扩展方法“BorderColor”(是否缺少 using 指令或程序集引用?)
“Cell”未包含“BorderColor”的定义,并且找不到可接受第一个“Cell”类型参数的可访问扩展方法“BorderColor”(是否缺少 using 指令或程序集引用?)
“Cell”未包含“HorizontalMargin”的定义,并且找不到可接受第一个“Cell”类型参数的可访问扩展方法“HorizontalMargin”(是否缺少 using 指令或程序集引用?)
“Cell”未包含“VerticalMargin”的定义,并且找不到可接受第一个“Cell”类型参数的可访问扩展方法“VerticalMargin”(是否缺少 using 指令或程序集引用?)
参数 2: 无法从“double”转换为“int”
可以内联变量声明
可以内联变量声明
可以简化对象初始化