工具箱相关
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

JQXLabel_grid.cs 42KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Geometry;
  5. using GeoAPI.Geometries;
  6. using NetTopologySuite.Geometries;
  7. using NetTopologySuite.Operation.Linemerge;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.ComponentModel;
  11. using System.Data;
  12. using System.Drawing;
  13. using System.IO;
  14. using System.Linq;
  15. using System.Text;
  16. using System.Threading.Tasks;
  17. using System.Windows.Forms;
  18. namespace CADTools
  19. {
  20. public partial class JQXLabel_grid : Form
  21. {
  22. public JQXLabel_grid()
  23. {
  24. InitializeComponent();
  25. }
  26. public class PointPolylinePair
  27. {
  28. public Point3d Point { get; set; }
  29. public Polyline Polyline { get; set; }
  30. public double curvature { get; set; }
  31. }
  32. int nodirection = 0;
  33. private void JQXLabel_grid_Load(object sender, EventArgs e)
  34. {
  35. //自动填充下拉框
  36. Database database = Autodesk.AutoCAD.DatabaseServices.HostApplicationServices.WorkingDatabase;
  37. using (Transaction traction = database.TransactionManager.StartTransaction())
  38. {
  39. //存放所有图层名
  40. List<string> alllayername = new List<string>();
  41. LayerTable layertable = traction.GetObject(database.LayerTableId, OpenMode.ForRead) as LayerTable;
  42. foreach (ObjectId objid in layertable)
  43. {
  44. LayerTableRecord layertablerecord = traction.GetObject(objid, OpenMode.ForRead) as LayerTableRecord;
  45. alllayername.Add(layertablerecord.Name);
  46. }
  47. alllayername.Sort();
  48. for (int i = 0; i < alllayername.Count; i++)
  49. {
  50. this.comboBox_jqx.Items.Add(alllayername[i]);
  51. this.comboBox_sqx.Items.Add(alllayername[i]);
  52. this.comboBox_bz.Items.Add(alllayername[i]);
  53. this.comboBox_tk.Items.Add(alllayername[i]);
  54. }
  55. if (alllayername.Contains("8120"))
  56. {
  57. int index = alllayername.IndexOf("8120");
  58. this.comboBox_jqx.SelectedIndex = index;
  59. }
  60. if (alllayername.Contains("8110"))
  61. {
  62. int index = alllayername.IndexOf("8110");
  63. this.comboBox_sqx.SelectedIndex = index;
  64. }
  65. if (alllayername.Contains("tk") || alllayername.Contains("TK"))
  66. {
  67. if (alllayername.Contains("tk"))
  68. {
  69. int index = alllayername.IndexOf("tk");
  70. this.comboBox_tk.SelectedIndex = index;
  71. }
  72. else
  73. {
  74. int index = alllayername.IndexOf("TK");
  75. this.comboBox_tk.SelectedIndex = index;
  76. }
  77. }
  78. traction.Commit();
  79. }
  80. this.textBox_decimal.Text = "0";
  81. }
  82. private void button_ok_Click(object sender, EventArgs e)
  83. {
  84. if (comboBox_jqx.Text == "")
  85. {
  86. MessageBox.Show("计曲线图层不能为空!");
  87. return;
  88. }
  89. if (comboBox_sqx.Text == "")
  90. {
  91. MessageBox.Show("首曲线图层不能为空!");
  92. return;
  93. }
  94. if (comboBox_tk.Text == "")
  95. {
  96. MessageBox.Show("图框图层不能为空!");
  97. return;
  98. }
  99. if (comboBox_blc.Text == "")
  100. {
  101. MessageBox.Show("比例尺不能为空!");
  102. return;
  103. }
  104. if (comboBox_bz.Text == "")
  105. {
  106. MessageBox.Show("等高线标注图层不能为空!");
  107. return;
  108. }
  109. jqxLabelbyGrid();
  110. MessageBox.Show("标注完成。\n有" + nodirection.ToString() + "处无法确定方向,移动到“无法确定方向”图层");
  111. this.Close();
  112. }
  113. private void jqxLabelbyGrid()
  114. {
  115. //计曲线
  116. string jqx = comboBox_jqx.Text;
  117. //图框
  118. string tk = comboBox_tk.Text;
  119. //比例尺
  120. string blctext = comboBox_blc.Text;
  121. int blcindex = blctext.LastIndexOf(':');
  122. string strblc = blctext.Substring(blcindex + 1);
  123. int blc = Convert.ToInt32(strblc);
  124. //图框顶点列表
  125. List<Polyline> tks = new List<Polyline>();
  126. Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
  127. Database db = Autodesk.AutoCAD.DatabaseServices.HostApplicationServices.WorkingDatabase;
  128. //获取所有图框,记录图框的最大点和最小点
  129. TypedValue[] typedvalue = new TypedValue[2];
  130. typedvalue.SetValue(new TypedValue((int)DxfCode.LayerName, tk), 0);
  131. typedvalue.SetValue(new TypedValue((int)DxfCode.Start, "LWPOLYLINE"), 1);
  132. SelectionFilter selectionfilter = new SelectionFilter(typedvalue);
  133. PromptSelectionResult psr = ed.SelectAll(selectionfilter);
  134. if (psr.Status == PromptStatus.OK)
  135. {
  136. SelectionSet ss = psr.Value;
  137. ObjectId[] tkids = ss.GetObjectIds();
  138. for (int i = 0; i < tkids.Length; i++)
  139. {
  140. using (Transaction tr = db.TransactionManager.StartTransaction())
  141. {
  142. Polyline pl = tr.GetObject(tkids[i], OpenMode.ForRead) as Polyline;
  143. tks.Add(pl);
  144. tr.Commit();
  145. }
  146. }
  147. }
  148. else
  149. {
  150. MessageBox.Show("未找到图框!");
  151. return;
  152. }
  153. //创建标记字体
  154. CreateSheetMap cs = new CreateSheetMap();
  155. cs.createTextStyle();
  156. ObjectId HZ = cs.gettextstyleID("HZ");
  157. //遍历图框顶点列表,按顶点范围搜索等高线
  158. for (int i = 0; i < tks.Count; i++)
  159. {
  160. ZoomView(ed, tks[i].Bounds.Value.MinPoint, tks[i].Bounds.Value.MaxPoint);
  161. List<Polyline> pllist = new List<Polyline>();
  162. TypedValue[] typedvalue_pl = new TypedValue[2];
  163. typedvalue_pl.SetValue(new TypedValue((int)DxfCode.LayerName, jqx), 0);
  164. typedvalue_pl.SetValue(new TypedValue((int)DxfCode.Start, "LWPOLYLINE"), 1);
  165. SelectionFilter selectionfilter_pl = new SelectionFilter(typedvalue_pl);
  166. PromptSelectionResult psr_pl = ed.SelectCrossingWindow(tks[i].Bounds.Value.MinPoint, tks[i].Bounds.Value.MaxPoint, selectionfilter_pl);
  167. if (psr_pl.Status == PromptStatus.OK)
  168. {
  169. SelectionSet ss = psr_pl.Value;
  170. ObjectId[] plids = ss.GetObjectIds();
  171. using (Transaction tr = db.TransactionManager.StartTransaction())
  172. {
  173. for (int ii = 0; ii < plids.Length; ii++)
  174. {
  175. Polyline pl = tr.GetObject(plids[ii], OpenMode.ForRead) as Polyline;
  176. if (IsPolylineInsideOrIntersecting(pl, tks[i].Bounds.Value.MinPoint, tks[i].Bounds.Value.MaxPoint))
  177. {
  178. pllist.Add(pl);
  179. }
  180. }
  181. tr.Commit();
  182. }
  183. //绘制图框
  184. double x = (tks[i].Bounds.Value.MinPoint.X + tks[i].Bounds.Value.MaxPoint.X) / 2;
  185. double y = (tks[i].Bounds.Value.MinPoint.Y + tks[i].Bounds.Value.MaxPoint.Y) / 2;
  186. Point3d centralpt = new Point3d(x, y, 0);
  187. if (pllist.Count > 0)
  188. {
  189. //var result = getPll(pllist, tk1, centralpt);
  190. var target = getPosition(pllist, tks[i], centralpt);
  191. makeMark(target, db, blc, centralpt, HZ);
  192. pllist.Clear();
  193. }
  194. }
  195. }
  196. }
  197. private PointPolylinePair getPosition(List<Polyline> pllist, Polyline tk, Point3d central)
  198. {
  199. List<PointPolylinePair> ptpllist = new List<PointPolylinePair>();
  200. List<PointPolylinePair> ptpllist1 = new List<PointPolylinePair>();
  201. List<Polyline> plinsidetk = new List<Polyline>();
  202. Polyline labelpll = new Polyline();
  203. int index = 0;
  204. // 找到距离中心点最近的等高线
  205. var pllist_sorted = pllist.OrderBy(c => c.GetClosestPointTo(new Point3d(central.X, central.Y, c.Elevation), new Vector3d(0, 0, 1), false)
  206. .DistanceTo(new Point3d(central.X, central.Y, c.Elevation))).ToList();
  207. while (ptpllist1.Count == 0)
  208. {
  209. labelpll = pllist_sorted[index];
  210. plinsidetk = GetPolylineInsideFrame(labelpll, tk);
  211. ptpllist1.Clear();
  212. for (int i = 0; i < plinsidetk.Count; i++)
  213. {
  214. Polyline pl_temp = plinsidetk[i];
  215. // 获取顶点数量
  216. int vertexCount = pl_temp.NumberOfVertices;
  217. // 每5个点取一个点
  218. int step = 5;
  219. int sampleCount = Math.Max(1, vertexCount / step);
  220. // 存储连续平缓点的索引
  221. List<int> consecutiveFlatIndices = new List<int>();
  222. for (int j = 1; j <= sampleCount; j++)
  223. {
  224. // 计算顶点索引
  225. int vertexIndex = Math.Min(j * step, vertexCount - 1);
  226. double curvature = GetCurvatureAtVertex(pl_temp, vertexIndex, step);
  227. // 检查是否为平缓点
  228. if (curvature <= 0.05)
  229. {
  230. consecutiveFlatIndices.Add(vertexIndex);
  231. // 检查是否有连续10个平缓点
  232. if (consecutiveFlatIndices.Count >= 2)
  233. {
  234. // 使用弦高差法验证是否整体平缓
  235. bool isOverallFlat = ValidateFlatRegionByChordHeight(pl_temp, consecutiveFlatIndices);
  236. if (isOverallFlat)
  237. {
  238. // 取中间点
  239. int middleIndex = consecutiveFlatIndices[consecutiveFlatIndices.Count / 2];
  240. Point3d middlePoint = pl_temp.GetPoint3dAt(middleIndex);
  241. PointPolylinePair pair = new PointPolylinePair();
  242. pair.Point = middlePoint;
  243. pair.Polyline = pllist_sorted[index];
  244. pair.curvature = curvature;
  245. ptpllist.Add(pair);
  246. // 清空连续记录,避免重复添加
  247. consecutiveFlatIndices.Clear();
  248. }
  249. else
  250. {
  251. // 如果不平缓,清空并继续,避免从这个区域继续累积
  252. consecutiveFlatIndices.Clear();
  253. }
  254. }
  255. }
  256. else
  257. {
  258. // 遇到非平缓点,重置连续计数
  259. consecutiveFlatIndices.Clear();
  260. }
  261. }
  262. }
  263. // 筛选长度大于15的等高线对应的点
  264. ptpllist1 = ptpllist.Where(p => p.Polyline.Length > 15).ToList();
  265. index++;
  266. if (index == pllist_sorted.Count) break;
  267. }
  268. PointPolylinePair target = new PointPolylinePair();
  269. // 处理 ptpllist1 和 ptpllist 为空的情况
  270. if (ptpllist1.Count == 0)
  271. {
  272. // 如果 ptpllist 不为空,按曲率排序取最小的
  273. if (ptpllist.Count > 0)
  274. {
  275. target = ptpllist.OrderBy(p => p.curvature).First();
  276. }
  277. else
  278. {
  279. // 如果 ptpllist 也为空,获取离中心点最近点
  280. var pl_label = pllist.OrderBy(c => c.GetClosestPointTo(new Point3d(central.X, central.Y, c.Elevation), new Vector3d(0, 0, 1), false)
  281. .DistanceTo(new Point3d(central.X, central.Y, c.Elevation))).First();
  282. PointPolylinePair pair = new PointPolylinePair();
  283. pair.Point = pl_label.GetClosestPointTo(central, new Vector3d(0, 0, 1), false);
  284. pair.Polyline = pl_label;
  285. pair.curvature = 0;
  286. target = pair;
  287. }
  288. }
  289. else if (ptpllist1.Count > 0)
  290. {
  291. target = ptpllist1.OrderBy(p => p.Point.DistanceTo(central)).First();
  292. }
  293. else
  294. {
  295. // ptpllist1 为空但还有等高线未处理,返回最接近中心的点
  296. target = ptpllist.OrderBy(p => p.Point.DistanceTo(central)).FirstOrDefault();
  297. }
  298. return target;
  299. }
  300. #region
  301. //private Polyline mergePl(List<Polyline> plllist, Polyline tk)
  302. //{
  303. // List<Polyline> interse = new List<Polyline>();
  304. // List<Polyline> result = new List<Polyline>(plllist);
  305. // for (int i = 0; i < plllist.Count - 1; i++)
  306. // {
  307. // Point3d start1 = plllist[i].GetPoint3dAt(0);
  308. // Point3d end1 = plllist[i].GetPoint3dAt(plllist[i].NumberOfVertices - 1);
  309. // for (int j = i + 1; j < plllist.Count; j++)
  310. // {
  311. // Point3d start2 = plllist[j].GetPoint3dAt(0);
  312. // Point3d end2 = plllist[j].GetPoint3dAt(plllist[j].NumberOfVertices - 1);
  313. // if (start1 == start2 || start1 == end2 || end1 == start2 || end1 == end2)
  314. // {
  315. // interse.Add(plllist[i]);
  316. // interse.Add(plllist[j]);
  317. // if (result.Contains(plllist[i])) result.Remove(plllist[i]);
  318. // if (result.Contains(plllist[j])) result.Remove(plllist[j]);
  319. // }
  320. // }
  321. // }
  322. // if (interse.Count > 0)
  323. // {
  324. // // 转换为NTS线串
  325. // var lineStrings = new List<Geometry>();
  326. // foreach (var pl in interse)
  327. // {
  328. // var lineString1 = ConvertPolylineToNtsGeometry(pl);
  329. // lineStrings.Add(lineString1);
  330. // }
  331. // // 使用线合并器
  332. // var merger = new LineMerger();
  333. // merger.Add(lineStrings);
  334. // // 获取合并结果
  335. // var mergedCollection = merger.GetMergedLineStrings();
  336. // // 转换回AutoCAD多段线
  337. // foreach (var geometry in mergedCollection)
  338. // {
  339. // if (geometry is LineString mergedLineString)
  340. // {
  341. // var mergedPolyline = ConvertNtsLineStringToPolyline(mergedLineString);
  342. // if (mergedPolyline != null)
  343. // {
  344. // mergedPolyline.Elevation = plllist[0].Elevation;
  345. // result.Add(mergedPolyline);
  346. // }
  347. // }
  348. // }
  349. // }
  350. // var plinside = new List<Polyline>();
  351. // foreach (var item in result)
  352. // {
  353. // var pls = GetPolylineInsideFrame(item, tk);
  354. // foreach (var l in pls)
  355. // {
  356. // plinside.Add(l);
  357. // }
  358. // }
  359. // return plinside.OrderByDescending(g => g.Length).First();
  360. //}
  361. #endregion
  362. private double GetCurvatureAtVertex(Polyline pl, int vertexIndex, int step)
  363. {
  364. int vertexCount = pl.NumberOfVertices;
  365. // 获取前一个顶点
  366. int prevIndex = Math.Max(0, vertexIndex - step);
  367. Point3d p0 = pl.GetPoint3dAt(prevIndex);
  368. // 获取当前顶点
  369. Point3d p1 = pl.GetPoint3dAt(vertexIndex);
  370. // 获取后一个顶点
  371. int nextIndex = Math.Min(vertexCount - 1, vertexIndex + step);
  372. Point3d p2 = pl.GetPoint3dAt(nextIndex);
  373. // 计算向量
  374. Vector3d v1 = p1 - p0;
  375. Vector3d v2 = p2 - p1;
  376. double v1Len = v1.Length;
  377. double v2Len = v2.Length;
  378. // 计算曲率
  379. double curvature = 0;
  380. if (v1Len > 1e-6 && v2Len > 1e-6)
  381. {
  382. // 计算方向变化角度
  383. double cosAngle = v1.DotProduct(v2) / (v1Len * v2Len);
  384. cosAngle = Math.Max(-1, Math.Min(1, cosAngle));
  385. double angle = Math.Acos(cosAngle);
  386. // 计算弧长
  387. double arcLength = v1Len + v2Len;
  388. // 曲率 = 角度变化 / 弧长
  389. curvature = angle / arcLength;
  390. }
  391. return curvature;
  392. }
  393. /// <summary>
  394. /// 通过弦高差(中间点到首尾点连线的距离)验证区域是否平缓
  395. /// </summary>
  396. private bool ValidateFlatRegionByChordHeight(Polyline pl, List<int> sampledIndices)
  397. {
  398. // 获取首尾顶点索引(使用采样点的首尾)
  399. int startVertex = sampledIndices[0];
  400. int endVertex = sampledIndices[sampledIndices.Count - 1];
  401. // 获取首尾点坐标
  402. Point3d startPoint = pl.GetPoint3dAt(startVertex);
  403. Point3d endPoint = pl.GetPoint3dAt(endVertex);
  404. // 计算弦长
  405. Vector3d chordVector = endPoint - startPoint;
  406. double chordLength = chordVector.Length;
  407. if (chordLength < 1e-6) return false;
  408. // 检查从 startVertex 到 endVertex 之间的所有顶点
  409. double maxDistance = 0;
  410. int totalPoints = 0;
  411. double sumDistance = 0;
  412. for (int i = startVertex; i <= endVertex; i++)
  413. {
  414. Point3d point = pl.GetPoint3dAt(i);
  415. double distance = PointToLineDistance(point, startPoint, endPoint);
  416. maxDistance = Math.Max(maxDistance, distance);
  417. sumDistance += distance;
  418. totalPoints++;
  419. // 早期退出:如果任何点距离超过阈值,直接返回false
  420. if (maxDistance > 0.5)
  421. {
  422. return false;
  423. }
  424. }
  425. // 判断条件:最大距离和平均距离都满足要求
  426. bool isFlat = maxDistance <= 0.5;
  427. return isFlat;
  428. }
  429. /// <summary>
  430. /// 计算点到线段的距离
  431. /// </summary>
  432. private double PointToLineDistance(Point3d point, Point3d lineStart, Point3d lineEnd)
  433. {
  434. Vector3d lineVector = lineEnd - lineStart;
  435. Vector3d pointVector = point - lineStart;
  436. double lineLengthSq = lineVector.DotProduct(lineVector);
  437. if (lineLengthSq < 1e-6) return pointVector.Length;
  438. // 计算投影参数 t
  439. double t = pointVector.DotProduct(lineVector) / lineLengthSq;
  440. // 找到线段上的最近点
  441. Point3d closestPoint;
  442. if (t < 0)
  443. closestPoint = lineStart;
  444. else if (t > 1)
  445. closestPoint = lineEnd;
  446. else
  447. closestPoint = lineStart + lineVector * t;
  448. return point.DistanceTo(closestPoint);
  449. }
  450. private void makeMark(PointPolylinePair pair, Database db, int blc, Point3d central, ObjectId HZ)
  451. //private void makeMark(Polyline pll, Database db, int blc, Point3d central, ObjectId HZ)
  452. {
  453. Polyline pll = pair.Polyline;
  454. Point3d label_pos = pair.Point;
  455. Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
  456. Polyline labelpll = (Polyline)pll.Clone();
  457. //Point3d label_pos = labelpll.GetClosestPointTo(central, new Vector3d(0, 0, 1), false);
  458. if (labelpll.StartPoint.X > labelpll.EndPoint.X)
  459. labelpll.ReverseCurve();
  460. //计算放置注记处的方向
  461. Vector3d tangent = labelpll.GetFirstDerivative(labelpll.GetParameterAtPoint(label_pos));
  462. double angle = tangent.GetAngleTo(Vector3d.XAxis);
  463. //调整角度范围(0到2Π)
  464. if (tangent.Y < 0)
  465. angle = 2 * Math.PI - angle;
  466. //法线向量
  467. Vector3d normal = new Vector3d(-tangent.Y, tangent.X, 0);
  468. //单位化
  469. normal = normal.GetNormal();
  470. List<Polyline> pllist = new List<Polyline>();
  471. var angle1 = angle;
  472. var angle2 = angle + Math.PI;
  473. int trans_index1 = 0;
  474. int trans_index2 = 0;
  475. //以标注所在位置点为基点做基于该点的法线射线进行搜索(正向搜索)
  476. Point3d startPoint = label_pos;
  477. Point3d endPoint = label_pos + normal * 200;
  478. Point3dCollection ptcoll = new Point3dCollection() { startPoint, endPoint };
  479. List<Point3d> intersepts_y = new List<Point3d>();
  480. Line l = new Line(startPoint, endPoint);
  481. ZoomView(ed, startPoint, endPoint);
  482. TypedValue[] typedvalue_pl = new TypedValue[2];
  483. typedvalue_pl.SetValue(new TypedValue((int)DxfCode.LayerName, comboBox_jqx.Text + "," + comboBox_sqx.Text), 0);
  484. typedvalue_pl.SetValue(new TypedValue((int)DxfCode.Start, "LWPOLYLINE"), 1);
  485. SelectionFilter selectionfilter_pl = new SelectionFilter(typedvalue_pl);
  486. PromptSelectionResult psr_pl = ed.SelectFence(ptcoll, selectionfilter_pl);
  487. if (psr_pl.Status == PromptStatus.OK)
  488. {
  489. SelectionSet ss = psr_pl.Value;
  490. ObjectId[] plids = ss.GetObjectIds();
  491. using (Transaction tr = db.TransactionManager.StartTransaction())
  492. {
  493. for (int ii = 0; ii < plids.Length; ii++)
  494. {
  495. Polyline dgx = tr.GetObject(plids[ii], OpenMode.ForRead) as Polyline;
  496. if (dgx.Elevation == pll.Elevation && dgx.Length - labelpll.Length < 0.0001 &&
  497. (dgx.StartPoint == labelpll.EndPoint || dgx.StartPoint == labelpll.StartPoint))
  498. {
  499. intersepts_y = GetIntersections(dgx, l);
  500. continue;
  501. }
  502. pllist.Add(dgx);
  503. }
  504. tr.Commit();
  505. }
  506. if (pllist.Count != 0)
  507. trans_index1 = Iftransdirection(pllist, label_pos, intersepts_y, l);
  508. }
  509. //反向搜索
  510. if (trans_index1 != 1)
  511. {
  512. intersepts_y = new List<Point3d>();
  513. endPoint = label_pos - normal * 200;
  514. ptcoll = new Point3dCollection() { startPoint, endPoint };
  515. ZoomView(ed, startPoint, endPoint);
  516. PromptSelectionResult psr_pl1 = ed.SelectFence(ptcoll, selectionfilter_pl);
  517. if (psr_pl1.Status == PromptStatus.OK)
  518. {
  519. SelectionSet ss = psr_pl1.Value;
  520. ObjectId[] plids = ss.GetObjectIds();
  521. l = new Line(startPoint, endPoint);
  522. using (Transaction tr = db.TransactionManager.StartTransaction())
  523. {
  524. for (int ii = 0; ii < plids.Length; ii++)
  525. {
  526. Polyline dgx = tr.GetObject(plids[ii], OpenMode.ForRead) as Polyline;
  527. if (dgx.Elevation == pll.Elevation && dgx.Length - labelpll.Length < 0.0001 &&
  528. (dgx.StartPoint == labelpll.EndPoint || dgx.StartPoint == labelpll.StartPoint))
  529. {
  530. intersepts_y = GetIntersections(dgx, l);
  531. continue;
  532. }
  533. pllist.Add(dgx);
  534. }
  535. tr.Commit();
  536. }
  537. if (pllist.Count != 0)
  538. trans_index2 = Iftransdirection(pllist, label_pos, intersepts_y, l);
  539. }
  540. }
  541. if (trans_index1 != 0 || trans_index2 != 0)
  542. {
  543. if (trans_index1 == 0 && trans_index2 == 1 || trans_index1 == -1 && trans_index2 == 0||
  544. trans_index1 == -1 && trans_index2 == 1) angle = angle2;
  545. //1:2000字高4,以此为基础计算其他比例尺的字高
  546. double labelheight = 4;
  547. if (blc == 500)
  548. labelheight = labelheight * ((double)500 / 2000);
  549. if (blc == 1000)
  550. labelheight = labelheight * ((double)1000 / 2000);
  551. if (blc == 5000)
  552. labelheight = labelheight * ((double)5000 / 2000);
  553. if (blc == 10000)
  554. labelheight = labelheight * ((double)10000 / 2000);
  555. string ele = labelpll.Elevation.ToString("F" + textBox_decimal.Text);
  556. using (DocumentLock doclock = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.LockDocument())
  557. {
  558. using (Transaction tr = db.TransactionManager.StartTransaction())
  559. {
  560. BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
  561. BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
  562. DBText ele_txt = new DBText();
  563. ele_txt.Height = labelheight;
  564. ele_txt.TextString = ele;
  565. ele_txt.TextStyleId = HZ;
  566. ele_txt.HorizontalMode = TextHorizontalMode.TextMid;
  567. ele_txt.Position = label_pos;
  568. ele_txt.AlignmentPoint = label_pos;
  569. ele_txt.Rotation = angle;
  570. ele_txt.Layer = comboBox_bz.Text;
  571. ele_txt.WidthFactor = 0.75;
  572. btr.AppendEntity(ele_txt);
  573. tr.AddNewlyCreatedDBObject(ele_txt, true);
  574. tr.Commit();
  575. }
  576. }
  577. }
  578. else
  579. {
  580. nodirection = nodirection + 1;
  581. LayerControl layerscontrol = new LayerControl();
  582. string layname = "无法判断方向";
  583. if (layerscontrol.haslayername(layname) == false)
  584. {
  585. colorgb col = new colorgb(255, 0, 0);
  586. layerscontrol.creatlayer(layname, col);
  587. }
  588. //1:2000字高4,以此为基础计算其他比例尺的字高
  589. double labelheight = 4;
  590. if (blc == 500)
  591. labelheight = labelheight * ((double)500 / 2000);
  592. if (blc == 1000)
  593. labelheight = labelheight * ((double)1000 / 2000);
  594. if (blc == 5000)
  595. labelheight = labelheight * ((double)5000 / 2000);
  596. if (blc == 10000)
  597. labelheight = labelheight * ((double)10000 / 2000);
  598. string ele = labelpll.Elevation.ToString("F" + textBox_decimal.Text);
  599. using (DocumentLock doclock = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.LockDocument())
  600. {
  601. using (Transaction tr = db.TransactionManager.StartTransaction())
  602. {
  603. BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
  604. BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
  605. DBText ele_txt = new DBText();
  606. ele_txt.Height = labelheight;
  607. ele_txt.TextString = ele;
  608. ele_txt.TextStyleId = HZ;
  609. ele_txt.HorizontalMode = TextHorizontalMode.TextMid;
  610. ele_txt.Position = label_pos;
  611. ele_txt.AlignmentPoint = label_pos;
  612. ele_txt.Rotation = angle;
  613. ele_txt.Layer = "无法判断方向";
  614. ele_txt.WidthFactor = 0.75;
  615. btr.AppendEntity(ele_txt);
  616. tr.AddNewlyCreatedDBObject(ele_txt, true);
  617. tr.Commit();
  618. }
  619. }
  620. }
  621. pllist.Clear();
  622. psr_pl = null;
  623. #region
  624. //Polyline templine = pllist[0].Clone() as Polyline;
  625. //// 计算平移向量(以图框起点为基准,移动至原点)
  626. //Vector3d translation = -tk.StartPoint.GetAsVector();
  627. //Matrix3d translateMatrix = Matrix3d.Displacement(translation);
  628. //// 应用平移变换
  629. //tk.TransformBy(translateMatrix);
  630. //templine.TransformBy(translateMatrix);
  631. //Point3dCollection translatedPoints = new Point3dCollection();
  632. //var plane = new Plane(Point3d.Origin, Vector3d.ZAxis);
  633. //tk.IntersectWith(templine, Intersect.OnBothOperands, plane, translatedPoints, IntPtr.Zero, IntPtr.Zero);
  634. //// 计算逆平移矩阵
  635. //Matrix3d inverseMatrix = Matrix3d.Displacement(-translation);
  636. //if (translatedPoints.Count > 0)
  637. //{
  638. // // 获取平移后的交点
  639. // foreach (Point3d item in translatedPoints)
  640. // {
  641. // // 恢复交点坐标
  642. // var pt = item.TransformBy(inverseMatrix);
  643. // }
  644. //}
  645. #endregion
  646. }
  647. /// <summary>
  648. /// 获取多段线在图框内部的线段部分
  649. /// </summary>
  650. public static List<Polyline> GetPolylineInsideFrame(Polyline sourcePolyline, Polyline framePolygon)
  651. {
  652. var insidePolylines = new List<Polyline>();
  653. // 转换图框为NTS多边形
  654. var ntsFrame = ConvertPolylineToNtsPolygon(framePolygon);
  655. // 转换源多段线为NTS几何对象
  656. var ntsSource = ConvertPolylineToNtsGeometry(sourcePolyline);
  657. // 计算交集(图框 ∩ 多段线)
  658. var intersection = ntsFrame.Intersection(ntsSource);
  659. // 处理交集结果
  660. if (intersection != null && !intersection.IsEmpty)
  661. {
  662. if (intersection is LineString lineString)
  663. {
  664. // 单个线串
  665. var polyline = ConvertNtsLineStringToPolyline(lineString);
  666. polyline.Elevation = sourcePolyline.Elevation;
  667. insidePolylines.Add(polyline);
  668. }
  669. else if (intersection is MultiLineString multiLineString)
  670. {
  671. // 多个线串(多段线被分割成多段)
  672. for (int i = 0; i < multiLineString.NumGeometries; i++)
  673. {
  674. LineString segment = multiLineString.GetGeometryN(i) as LineString;
  675. var polyline = ConvertNtsLineStringToPolyline(segment);
  676. polyline.Elevation = sourcePolyline.Elevation;
  677. insidePolylines.Add(polyline);
  678. }
  679. }
  680. //else if (intersection is GeometryCollection collection)
  681. //{
  682. // // 几何集合
  683. // for (int i = 0; i < collection.NumGeometries; i++)
  684. // {
  685. // LineString segment = collection.GetGeometryN(i) as LineString;
  686. // var polyline = ConvertNtsLineStringToPolyline(segment);
  687. // polyline.Elevation = sourcePolyline.Elevation;
  688. // insidePolylines.Add(polyline);
  689. // }
  690. //}
  691. }
  692. ntsFrame = null;
  693. ntsSource = null;
  694. return insidePolylines;
  695. }
  696. /// <summary>
  697. /// 将AutoCAD多段线转换为NTS多边形
  698. /// </summary>
  699. private static Polygon ConvertPolylineToNtsPolygon(Polyline polyline)
  700. {
  701. var coordinates = new List<Coordinate>();
  702. for (int i = 0; i < polyline.NumberOfVertices; i++)
  703. {
  704. Point3d point = polyline.GetPoint3dAt(i);
  705. coordinates.Add(new Coordinate(point.X, point.Y));
  706. }
  707. // 闭合多边形
  708. if (polyline.Closed == true && coordinates[0] != coordinates[coordinates.Count - 1])
  709. coordinates.Add(new Coordinate(coordinates[0].X, coordinates[0].Y));
  710. var geometryFactory = new GeometryFactory();
  711. return (Polygon)geometryFactory.CreatePolygon(coordinates.ToArray());
  712. }
  713. /// <summary>
  714. /// 将AutoCAD多段线转换为NTS几何对象
  715. /// </summary>
  716. private static Geometry ConvertPolylineToNtsGeometry(Polyline polyline)
  717. {
  718. var coordinates = new List<Coordinate>();
  719. for (int i = 0; i < polyline.NumberOfVertices; i++)
  720. {
  721. Point3d point = polyline.GetPoint3dAt(i);
  722. coordinates.Add(new Coordinate(point.X, point.Y));
  723. }
  724. var geometryFactory = new GeometryFactory();
  725. return (LineString)geometryFactory.CreateLineString(coordinates.ToArray());
  726. }
  727. /// <summary>
  728. /// 将NTS线串转换回AutoCAD多段线
  729. /// </summary>
  730. private static Polyline ConvertNtsLineStringToPolyline(LineString lineString)
  731. {
  732. if (lineString == null || lineString.IsEmpty || lineString.NumPoints < 2)
  733. return null;
  734. var polyline = new Polyline();
  735. var coordinates = lineString.Coordinates;
  736. for (int i = 0; i < coordinates.Length; i++)
  737. {
  738. polyline.AddVertexAt(i, new Point2d(coordinates[i].X, coordinates[i].Y), 0, 0, 0);
  739. }
  740. return polyline;
  741. }
  742. // 检查多段线是否有部分在框内
  743. private bool IsPolylineInsideOrIntersecting(Polyline pl, Point3d minPoint, Point3d maxPoint)
  744. {
  745. // 方法1:检查是否有顶点在框内
  746. for (int j = 0; j < pl.NumberOfVertices; j++)
  747. {
  748. Point3d vertex = pl.GetPoint3dAt(j);
  749. if (IsPointInside(vertex, minPoint, maxPoint))
  750. return true; // 有顶点在框内,说明线有部分在框内
  751. }
  752. // 方法2:检查线的包围盒是否与选择框相交
  753. Extents3d plExtents = pl.GeometricExtents;
  754. if (plExtents.MinPoint.X <= maxPoint.X && plExtents.MaxPoint.X >= minPoint.X &&
  755. plExtents.MinPoint.Y <= maxPoint.Y && plExtents.MaxPoint.Y >= minPoint.Y)
  756. {
  757. // 包围盒相交,进一步检查线段
  758. return true;
  759. }
  760. return false;
  761. }
  762. // 检查点是否在矩形内(不包括边界)
  763. private bool IsPointInside(Point3d point, Point3d minPoint, Point3d maxPoint)
  764. {
  765. return point.X > minPoint.X && point.X < maxPoint.X &&
  766. point.Y > minPoint.Y && point.Y < maxPoint.Y;
  767. }
  768. // 检查点是否在矩形内或边界上
  769. private bool IsPointInsideOrOnBoundary(Point3d point, Point3d minPoint, Point3d maxPoint)
  770. {
  771. return point.X >= minPoint.X && point.X <= maxPoint.X &&
  772. point.Y >= minPoint.Y && point.Y <= maxPoint.Y;
  773. }
  774. private List<Point3d> GetIntersections(Polyline pll, Line line)
  775. {
  776. List<Point3d> result = new List<Point3d>();
  777. // 创建临时副本
  778. Polyline tempLine1 = (Polyline)pll.Clone();
  779. Point3d p1 = new Point3d(line.StartPoint.X, line.StartPoint.Y, pll.Elevation);
  780. Point3d p2 = new Point3d(line.EndPoint.X, line.EndPoint.Y, pll.Elevation);
  781. Line tempLine2 = new Line(p1, p2);
  782. // 计算平移向量(以线1起点为基准,移动至原点)
  783. Vector3d translation = -tempLine1.StartPoint.GetAsVector();
  784. Matrix3d translateMatrix = Matrix3d.Displacement(translation);
  785. // 应用平移变换
  786. tempLine1.TransformBy(translateMatrix);
  787. tempLine2.TransformBy(translateMatrix);
  788. Point3dCollection translatedPoints = new Point3dCollection();
  789. var plane = new Plane(Point3d.Origin, Vector3d.ZAxis);
  790. tempLine1.IntersectWith(tempLine2, Intersect.OnBothOperands, plane, translatedPoints, IntPtr.Zero, IntPtr.Zero);
  791. // 计算逆平移矩阵
  792. Matrix3d inverseMatrix = Matrix3d.Displacement(-translation);
  793. if (translatedPoints.Count > 0)
  794. {
  795. // 获取平移后的交点
  796. foreach (Point3d item in translatedPoints)
  797. {
  798. // 恢复交点坐标
  799. var pt = item.TransformBy(inverseMatrix);
  800. result.Add(pt);
  801. }
  802. }
  803. return result;
  804. }
  805. /// <summary>
  806. /// 计算点到线段的距离
  807. /// <returns>-1表示反向,1表示同向,0表示不确定</returns>
  808. /// </summary>
  809. int Iftransdirection(List<Polyline> pllist,Point3d label_pos, List<Point3d> intersepts_y,Line l)
  810. {
  811. Polyline closest = null;
  812. double minDistance = double.MaxValue;
  813. List<Point3d> intersepts_l = new List<Point3d>();
  814. foreach (Polyline dgx in pllist)
  815. {
  816. Polyline dgx_copy = dgx;
  817. var pts = GetIntersections(dgx_copy, l);
  818. // 计算距离
  819. if (pts.Count != 0)
  820. {
  821. foreach (Point3d item in pts)
  822. {
  823. // 避免创建新的Point3d对象
  824. double distance = Math.Sqrt(
  825. Math.Pow(item.X - label_pos.X, 2) +
  826. Math.Pow(item.Y - label_pos.Y, 2)
  827. );
  828. if (distance < minDistance)
  829. {
  830. minDistance = distance;
  831. closest = dgx;
  832. intersepts_l = pts;
  833. }
  834. }
  835. }
  836. }
  837. int count_intersepts_y = intersepts_y.Count;
  838. intersepts_y.AddRange(intersepts_l);
  839. var points = intersepts_y.OrderBy(p => Math.Sqrt(Math.Pow(l.StartPoint.X - p.X, 2) + Math.Pow(l.StartPoint.Y - p.Y, 2))).ToList();
  840. if (count_intersepts_y == 1&& intersepts_l.Count!=0&&Math.Abs(closest.Elevation-label_pos.Z)>0.001)
  841. {
  842. if (closest.Elevation > label_pos.Z) return 1;
  843. else if (closest.Elevation < label_pos.Z) return -1;
  844. }
  845. else if (intersepts_l.Count > 0 && intersepts_y.Count > 2 && Math.Abs(closest.Elevation - label_pos.Z) > 0.001)
  846. {
  847. double x = closest.Elevation;
  848. double y = label_pos.Z;
  849. // 找到第一个高程为y的点的索引
  850. int firstIndex = -1;
  851. for (int i = 0; i < points.Count; i++)
  852. {
  853. if (Math.Abs(points[i].Z - y) < 1e-6)
  854. {
  855. firstIndex = i;
  856. break;
  857. }
  858. }
  859. if (firstIndex == -1) return 0;
  860. // 找到第二个高程为y的点的索引
  861. int secondIndex = -1;
  862. for (int i = firstIndex + 1; i < points.Count; i++)
  863. {
  864. if (Math.Abs(points[i].Z - y) < 1e-6)
  865. {
  866. secondIndex = i;
  867. break;
  868. }
  869. }
  870. if (secondIndex == -1) return 0;
  871. bool haspt = false;
  872. // 检查两个索引之间是否存在高程为x的点
  873. for (int i = firstIndex + 1; i < secondIndex; i++)
  874. {
  875. if (Math.Abs(points[i].Z - x) < 1e-6)
  876. haspt = true;
  877. }
  878. if (haspt && closest.Elevation > label_pos.Z) return 1;
  879. else if (haspt && closest.Elevation < label_pos.Z) return -1;
  880. else if (!haspt) return 0;
  881. }
  882. return 0;
  883. }
  884. private void ZoomView(Editor edit, Point3d pt1, Point3d pt2)
  885. {
  886. var x_min = Math.Min(pt1.X, pt2.X);
  887. var y_min = Math.Min(pt1.Y, pt2.Y);
  888. using (ViewTableRecord currview1 = edit.GetCurrentView())
  889. {
  890. currview1.CenterPoint = new Point2d(Math.Abs((pt2.X - pt1.X) / 2) + x_min,
  891. Math.Abs((pt2.Y - pt1.Y) / 2) + y_min);
  892. currview1.Width = Math.Abs(pt2.X - pt1.X)+ 10;
  893. currview1.Height = Math.Abs(pt2.Y - pt1.Y) + 10;
  894. edit.SetCurrentView(currview1);
  895. }
  896. edit.UpdateScreen();
  897. }
  898. }
  899. }