1. ;|为了提高程序构建多边形的运行速度,需要对程序的数据结构和计算方法进行优化,下面我逐步详解我程序的思路:
    2. 1、根据处理后的直线、圆弧选择集生成的图元列表entList,数据结构:(图元名 图元名 ...),建立图元和各图元之间的节点对应关系数据表,
    3. 数据结构:'((图元名 起点的节点编号 端点的节点编号)...),表中图元名的排序和表entList的顺序一致,再建立节点和坐标数据对应表,
    4. 数据结构:'((节点编号 坐标)...),这样方便后面构建拓扑邻接表时,搜索只需要搜索节点编号进行比较,不需要在进行比较端点坐标,这样能大大提高运算速度。
    5. |;
    6. ;;;(gxl-ent->Nodes entList jd)根据弧段图元表建立弧段节点表,参数:图元表 精度值 返回值:图元名--节点编号表 '((图元名 首节点编号 末节点编号)...) 节点--坐标表 '((节点编号 坐标)...)
    7. (defun gxl-ent->Nodes (entList jd / ent ent_nodes Nodes n k p1 p2 flag flag1 flag2 bh coord p11 p21 nodes1 sortI1 sortI2)
    8. (grtext -2 "整理弧段节点表...")
    9. (setq n 1 )
    10. ;(setq t1 (getvar "cdate"))
    11. (setq ent_nodes (list (list (car entList) 0 1)))
    12. (setq Nodes (list (list 1 (vlax-curve-getendPoint (car entList))) (list 0 (vlax-curve-getStartPoint (car entList)))))
    13. (foreach ent (cdr entList)
    14. (setq flag1 t
    15. flag2 t
    16. )
    17. (setq p1 (vlax-curve-getStartPoint ent)
    18. p2 (vlax-curve-getendPoint ent)
    19. k 0
    20. )
    21. ;;;===========
    22. (while (and (setq node (nth k nodes)) (or flag1 flag2))
    23. ;(foreach node nodes
    24. (setq bh (car node)
    25. coord (cadr node)
    26. )
    27. (if (equal p1 coord jd) (setq bh1 bh flag1 nil))
    28. (if (equal p2 coord jd) (setq bh2 bh flag2 nil))
    29. (setq k (1+ k))
    30. ;) ;_ foreach
    31. )
    32. (if flag1
    33. (progn
    34. (setq bh1 (setq n (1+ n)))
    35. (setq nodes (cons (list bh1 p1) nodes)
    36. )
    37. )
    38. )
    39. (if flag2
    40. (progn
    41. (setq bh2 (setq n (1+ n)))
    42. (setq nodes (cons (list bh2 p2) nodes)
    43. )
    44. )
    45. )
    46. ;;;============
    47. (setq ent_nodes (cons (list ent bh1 bh2) ent_nodes))
    48. )
    49. (grtext)
    50. ;(GXL-SYS-TIMEOUT t1)
    51. (list (reverse ent_nodes) (reverse Nodes))
    52. )
    53. ;|
    54. 2、根据生成的段图元名--节点编号表'((图元名 首节点编号 末节点编号)...),构建一个二维坐标表,
    55. 数据结构:'((图元起点的节点编号 图元起点的方向点 图元弧段编号 图元末端点方向点 图元末端点节点编号) ...)
    56. 其中:图元起点的方向点指图元起点到终点的方向上任一点,如果图元为圆弧,则该方向点为切线方向任一点,
    57. 图元末端点的方向点指图元末端点到起点的方向上任一点,如果图元为圆弧,则该方向点为切线方向任一点,
    58. 图元弧段编号为图元在表段图元名--节点编号表中的顺序位置,顺序号从1开始
    59. |;
    60. ;;;(gxl-ent->Coordinates enlst) 根据线段图元名--节点编号表'((图元名 首节点编号 末节点编号)...) 构建二维坐标表
    61. ;;;返回值: 二维坐标表 '((首端点节点编号 首端点方向点 弧段编号 末端点方向点 末端点节点编号) ...)
    62. ;;;(gxl-ent->Coordinates enLst)
    63. (defun gxl-ent->Coordinates (enLst / rtn index a b jd n k )
    64. (setq index 0)
    65. ;(setq jd 3)
    66. (setq rtn
    67. (mapcar '(lambda (x)
    68. (list (cadr x) ;_ 首端点节点编号
    69. (COND
    70. ((= "LINE" (GXL-DXF (car x) 0))
    71. (list (car (setq a (vlax-curve-getendPoint (car x))))
    72. (cadr a)
    73. ) ;_ list
    74. )
    75. ((= "ARC" (GXL-DXF (car x) 0))
    76. (list (car (setq b (polar (setq a (vlax-curve-getStartPoint (car x))) (GXL-GETCURVETANGENT (car x) a) 1))) (cadr b))
    77. )
    78. ((WCMATCH (GXL-DXF (car x) 0) "*POLYLINE")
    79. (list (car (setq b (polar (setq a (vlax-curve-getStartPoint (car x))) (GXL-GETCURVETANGENT (car x) a) 1))) (cadr b))
    80. )
    81. ) ;_ COND 首端点方向点
    82. ;(gxl-dxf x 5) ;_ 图元句柄
    83. ;x ;_ 图元名
    84. (setq index (1+ index)) ;_ 弧段编号,从序号1开始
    85. (COND
    86. ((= "LINE" (GXL-DXF (car x) 0))
    87. (list (car (setq a (vlax-curve-getstartPoint (car x))))
    88. (cadr a)
    89. ) ;_ list
    90. )
    91. ((= "ARC" (GXL-DXF (car x) 0))
    92. (list (car (setq b (polar (setq a (vlax-curve-getStartPoint (car x))) (GXL-GETCURVETANGENT (car x) a) -1.0))) (cadr b))
    93. )
    94. ((WCMATCH (GXL-DXF (car x) 0) "*POLYLINE")
    95. (list (car (setq b (polar (setq a (vlax-curve-getStartPoint (car x))) (GXL-GETCURVETANGENT (car x) a) -1.0))) (cadr b))
    96. )
    97. ) ;_ 末端点方向点
    98. (caddr x) ;_ 末端点节点编号
    99. ) ;_ list
    100. ) ;_ lambda
    101. enlst
    102. ) ;_ mapcar
    103. )
    104. rtn
    105. ;_ vl-sort
    106. )
    107. ;|
    108. 3、根据二维坐标表 '((首端点节点编号 首端点方向点 弧段编号 末端点方向点 末端点节点编号) ...)
    109. 建立弧段拓扑邻接表,'((弧段序号 (首端点关联表 ...) (末端点关联表 ...))...),
    110. 建立弧段拓扑邻接表的方法:
    111. 若某一弧段N 的首端点与另一弧段
    112. 相关联, 则在弧段拓扑邻接关系表中标记为N ; 若
    113. 末端点与另一弧段相关联, 则标记为- N
    114. 如果拓扑表中有nil,则表明线段端点没有邻接边
    115. |;
    116. ;;;(gxl-Toupu-LineList Coordinates) 根据二维坐标表 '((首端点节点编号 首端点方向点 弧段编号 末端点方向点 末端点节点编号) ...)
    117. ;;;建立弧段拓扑邻接表,'((弧段序号 (首端点关联表 ...) (末端点关联表 ...))...)
    118. (defun gxl-Toupu-LineList (Coordinates
    119. / toupulist nn
    120. n k pstart pend
    121. pl new old t2
    122. Coordinates0 Coordinates1
    123. flag flag1 index pl to bh
    124. xh1 xh2 coord
    125. ) ;_ Coordinates
    126. (if (not *jd*) (setq *jd* 0.00001))
    127. ;;;点表倒置
    128. (setq Coordinates1 (mapcar 'reverse Coordinates))
    129. (grtext -2 "拓扑邻接表...")
    130. (foreach coord Coordinates
    131. (setq xh1 (car coord)
    132. xh2 (last coord)
    133. )
    134. (setq toupulist
    135. (cons
    136. (list
    137. (setq bh (nth 2 coord))
    138. (vl-remove-if
    139. '(lambda (x) (or (equal x bh) (equal x (* -1 bh))))
    140. (append (mapcar 'cadr (GXL-MASSOC xh1 Coordinates)) (mapcar '(lambda (x) (* -1 (cadr x))) (GXL-MASSOC xh1 Coordinates1)))
    141. )
    142. (vl-remove-if
    143. '(lambda (x) (or (equal x bh) (equal x (* -1 bh))))
    144. (append (mapcar 'cadr (GXL-MASSOC xh2 Coordinates)) (mapcar '(lambda (x) (* -1 (cadr x))) (GXL-MASSOC xh2 Coordinates1)))
    145. )
    146. )
    147. toupulist)
    148. )
    149. )
    150. (grtext)
    151. (reverse toupulist)
    152. )
    153. ;|
    154. 4、检查生成的弧段拓扑邻接表,如果有断头的弧段,将其删除,返回处理后的弧段拓扑邻接表和已经删除的弧段表
    155. |;
    156. ;;;(gxl-check-Toupu-LineList toupulist) 参数:弧段拓扑邻接表
    157. (defun gxl-check-Toupu-LineList (toupulist / delnil toupulist1 dellist)
    158. (setq toupulist1 toupulist)
    159. (defun delnil (toupl / tmp tmp1 dellist1 a b)
    160. (setq tmp toupulist1)
    161. (foreach a toupl
    162. (if (member nil a)
    163. (progn
    164. ;(setq dellist (append dellist (list (abs (car a)))))
    165. (setq dellist (append dellist (list (car a))))
    166. (setq toupulist1 (vl-remove (assoc (abs(car a)) toupulist1) toupulist1))
    167. (setq toupulist1
    168. (mapcar
    169. '(lambda (b)
    170. (list (car b)
    171. (vl-remove-if
    172. '(lambda (x) (= (abs (car a)) (abs x)))
    173. (cadr b)
    174. ) ;_ vl-remove-if
    175. (vl-remove-if
    176. '(lambda (x) (= (abs (car a)) (abs x)))
    177. (caddr b)
    178. ) ;_ vl-remove-if
    179. ) ;_ list
    180. ) ;_ lambda
    181. toupulist1
    182. ) ;_ mapcar
    183. ) ;_ setq
    184. )
    185. )
    186. )
    187. (if (not (equal tmp toupulist1)) (delnil toupulist1))
    188. )
    189. (delnil toupulist1)
    190. (list toupulist1 dellist)
    191. )
    192. ;|
    193. 5、根据建立的弧段拓扑邻接表,按照最小角法则搜索多边形,返回 弧段与多边形拓扑关联表 '((多边形序号 (弧段号 ...))...)
    194. 一条弧段可作为一个或两个多边形的组成边而
    195. 存在, 亦即从一条弧段出发最多可以搜索出两个正确
    196. 的多边形. 如图2 所示, 若从弧段A 1 的一端O 出发,
    197. 并把它作为起始弧段, 把与A 1 O 端拓扑关联的其
    198. 它弧段作为中止弧段, 然后比较并找出与A 1 夹角最
    199. 小的中止弧段A 2, 并把A 2 作为新的起始弧段, 再从
    200. 它的另一端点出发重复以上过程继续搜索, 直到回到
    201. 出发弧段A 1 的另一端为止, 则所有搜索出的弧段就
    202. 构成了一个多边形. 同样, A 1 O 端开始, 并把它
    203. 作为中止弧段, 把与它拓扑关联的其它弧段作为起始
    204. 弧段, 然后比较并找出与该弧段夹角最小的弧段,
    205. 把找出的弧段作为新的中止弧段, 再从新弧段的另一
    206. 端点出发重复以上搜索过程, 直到回到A 1 的另一端
    207. 为止, 则所有搜索出的弧段就构成了另一个多边形.
    208. 这样, 从一条弧段出发可以跟踪出两个多边形, 此方
    209. 法可称为多边形搜索的最小角法则.
    210. 多边形的搜索按照最小角法则进行. 从编号为
    211. 1 的弧段的始端出发, 查找弧段拓扑邻接表中与该
    212. 端点关联的弧段, 按照最小角法则可以搜索出两个
    213. 多边形. 依照上述方法, 依次把其它弧段作为开始弧
    214. 段, 共可找出2N (N 为总弧段数) 个多边形. 搜索过
    215. 程中, 记录构成多边形的弧段编号(一弧段首端与上
    216. 一弧段关联用正边号, 否则用负边号) 和弧段数,
    217. 形成多边形与弧段的拓扑关联表.
    218. |;
    219. ;;;(gxl-MakePolyList toupulist Coordinates nodes) 最小角法拓扑多边形,返回多边形数据表
    220. ;;;参数:
    221. ;;; toupulist 弧段邻接表 '((弧段序号 (首端点关联表 ...) (末端点关联表 ...))...),从 1 开始
    222. ;;; Coordinates 二维坐标表 '((首端点节点编号 首端点方向点 弧段编号 末端点方向点 末端点节点编号) ...) 按顺序从1开始
    223. ;;; nodes 节点--坐标表 '((节点编号 坐标)...)
    224. (defun gxl-MakePolyList (toupulist Coordinates nodes / PolyTouPuList nn
    225. n xh pstart pend flag p0 p1
    226. a0 a1 a2 B1 B2 polytoupu
    227. toupu0 next t2 kk ExitNum ExitFlag Nodestart
    228. NodeEnd node
    229. ) ;_ toupulist
    230. (if (not *jd*) (setq *jd* 0.00001))
    231. ;;;测试时间
    232. (setq t2 (getvar "cdate"))
    233. (setq nn (length Coordinates)
    234. n 0
    235. to nn)
    236. (GXL-SYS-PROGRESS-INIT "拓扑多边形" to)
    237. (repeat nn
    238. (setq xh (1+ n)) ;_ 弧段序号
    239. ;(setq bak xh)
    240. (if (assoc xh toupulist)
    241. ;;;如果该边在拓扑邻接表里
    242. (progn
    243. (GXL-SYS-PROGRESS to -1)
    244. (setq Nodestart (car (nth n Coordinates))
    245. NodeEnd (last (nth n Coordinates))
    246. Pstart (cadr (assoc Nodestart nodes))
    247. pEnd (cadr (assoc NodeEnd nodes))
    248. flag t
    249. ) ;_ setq
    250. ;;;首端点搜索多边形
    251. (setq p0 pstart
    252. p1 (cadr (nth n Coordinates))
    253. a0 (angle p0 p1) ;_ 首端点弧段角度
    254. toupu0 (cadr (assoc xh toupulist)) ;_ 首端点弧段拓扑邻接表
    255. polytoupu (list (* -1 xh))
    256. )
    257. (setq ExitNum 0 ;_ 循环次数
    258. ExitFlag nil) ;_ 陷入死循环标志
    259. ;;;移除重合的线
    260. (setq toupu0 (vl-remove-if
    261. '(lambda (x)
    262. (if (> x 0)
    263. (equal a0 (angle (cadr (assoc (car (nth (1- x) Coordinates)) nodes)) (cadr (nth (1- x) Coordinates))) *jd*)
    264. (equal a0 (angle (cadr (assoc (nth 4 (nth (abs (1+ x)) Coordinates)) nodes)) (nth 3 (nth (abs (1+ x)) Coordinates))) *jd*)
    265. )
    266. )
    267. toupu0
    268. )
    269. )
    270. (if (not (> (length toupu0) 0)) (setq flag nil ExitFlag t))
    271. (while flag
    272. ;;;toupu0a0按最小角度排序相邻边
    273. (setq toupu0
    274. (vl-sort toupu0
    275. '(lambda (e1 e2)
    276. (if (> e1 0)
    277. (setq a1 (angle (cadr (assoc (car (nth (1- e1) Coordinates)) nodes)) (cadr (nth (1- e1) Coordinates))))
    278. (setq a1 (angle (cadr (assoc (nth 4 (nth (abs (1+ e1)) Coordinates)) nodes)) (nth 3 (nth (abs (1+ e1)) Coordinates))))
    279. )
    280. (if (> e2 0)
    281. (setq a2 (angle (cadr (assoc (car (nth (1- e2) Coordinates)) nodes)) (cadr (nth (1- e2) Coordinates))))
    282. (setq a2 (angle (cadr (assoc (nth 4 (nth (abs (1+ e2)) Coordinates)) nodes)) (nth 3 (nth (abs (1+ e2)) Coordinates))))
    283. )
    284. (if (>= a0 a1) (setq B1 (- a0 a1)) (setq B1 (+ 2pi (- a0 a1))))
    285. (if (>= a0 a2) (setq B2 (- a0 a2)) (setq B2 (+ 2pi (- a0 a2))))
    286. (< B1 B2)
    287. )
    288. )
    289. )
    290. ;;;判断Next边是否已经在polytoupu里了
    291. ;(if (member next (mapcar 'abs polytoupu)) (setq exitflag t))
    292. (setq polytoupu (append polytoupu (list (setq next (car toupu0))))) ;_ next 下一邻接边序号
    293. ;;;验证next 下一邻接边序号的方位角是否和首端点弧段角度a0重合,如重合,找下一边,未找到,结束组多边形
    294. (setq falg1 t
    295. kk 1)
    296. (while flag1
    297. (if (> next 0)
    298. (setq a1 (angle (cadr (assoc (car (nth (1- next) Coordinates)) nodes)) (cadr (nth (1- next) Coordinates))))
    299. (setq a1 (angle (cadr (assoc (nth 4 (nth (abs (1+ next)) Coordinates)) nodes)) (nth 3 (nth (abs (1+ next)) Coordinates))))
    300. )
    301. (if (equal a0 a1 0.000001) (setq next (nth kk toupu0))(setq flag1 nil))
    302. (if (not next) (setq flag1 nil))
    303. (setq kk (1+ kk))
    304. )
    305. ;(if next (setq polytoupu (append polytoupu (list (setq next (car toupu0))))))
    306. (if next
    307. (if (> next 0)
    308. (progn
    309. (setq p0 (cadr (assoc (setq node (nth 4 (nth (1- next) Coordinates))) nodes))
    310. a0 (angle p0 (nth 3 (nth (1- next) Coordinates)))
    311. toupu0 (caddr (assoc next toupulist))
    312. )
    313. (if (equal node nodeEnd) (setq flag nil))
    314. )
    315. (progn
    316. (setq p0 (cadr (assoc (setq node (car (nth (abs (1+ next)) Coordinates))) nodes))
    317. a0 (angle p0 (cadr (nth (abs (1+ next)) Coordinates)))
    318. toupu0 (cadr (assoc (abs next) toupulist))
    319. )
    320. (if (equal node nodeEnd) (setq flag nil))
    321. )
    322. )
    323. (setq flag nil)
    324. )
    325. (setq ExitNum (1+ ExitNum))
    326. ;;;搜索边界次数超过2000次,程序陷入死循环,退出
    327. (if (> ExitNum 2000) (setq flag nil ExitFlag t))
    328. (if (and flag (not ExitFlag))
    329. (progn
    330. ;;;移除重合的线
    331. (setq toupu0 (vl-remove-if
    332. '(lambda (x)
    333. (if (> x 0)
    334. (equal a0 (angle (cadr (assoc (car (nth (1- x) Coordinates)) nodes)) (cadr (nth (1- x) Coordinates))) *jd*)
    335. (equal a0 (angle (cadr (assoc (nth 4 (nth (abs (1+ x)) Coordinates)) nodes)) (nth 3 (nth (abs (1+ x)) Coordinates))) *jd*)
    336. )
    337. )
    338. toupu0
    339. )
    340. )
    341. (if (not (> (length toupu0) 0)) (setq flag nil ExitFlag t))
    342. )
    343. )
    344. );_ while
    345. (if ExitFlag
    346. (setq ExitFlag nil)
    347. (setq PolyTouPuList (append PolyTouPuList (list polytoupu)))
    348. )
    349. ;;;末端点搜索
    350. (setq p0 pend
    351. p1 (nth 3 (nth n Coordinates))
    352. a0 (angle p0 p1) ;_ 起点角度
    353. toupu0 (caddr (assoc xh toupulist))
    354. polytoupu (list xh)
    355. flag t
    356. )
    357. (setq ExitNum 0 ;_ 循环次数
    358. ExitFlag nil) ;_ 陷入死循环标志
    359. ;;;移除重合的线
    360. (setq toupu0 (vl-remove-if
    361. '(lambda (x)
    362. (if (> x 0)
    363. (equal a0 (angle (cadr (assoc (car (nth (1- x) Coordinates)) nodes)) (cadr (nth (1- x) Coordinates))) *jd*)
    364. (equal a0 (angle (cadr (assoc (nth 4 (nth (abs (1+ x)) Coordinates)) nodes)) (nth 3 (nth (abs (1+ x)) Coordinates))) *jd*)
    365. )
    366. )
    367. toupu0
    368. )
    369. )
    370. (if (not (> (length toupu0) 0)) (setq flag nil ExitFlag t))
    371. (while flag
    372. ;;;计算最小角度相邻边
    373. (setq toupu0
    374. (vl-sort toupu0
    375. '(lambda (e1 e2)
    376. (if (> e1 0)
    377. (setq a1 (angle (cadr (assoc (car (nth (1- e1) Coordinates)) nodes)) (cadr (nth (1- e1) Coordinates))))
    378. (setq a1 (angle (cadr (assoc (nth 4 (nth (abs (1+ e1)) Coordinates)) nodes)) (nth 3 (nth (abs (1+ e1)) Coordinates))))
    379. )
    380. (if (> e2 0)
    381. (setq a2 (angle (cadr (assoc (car (nth (1- e2) Coordinates)) nodes)) (cadr (nth (1- e2) Coordinates))))
    382. (setq a2 (angle (cadr (assoc (nth 4 (nth (abs (1+ e2)) Coordinates)) nodes)) (nth 3 (nth (abs (1+ e2)) Coordinates))))
    383. )
    384. (if (>= a0 a1) (setq B1 (- a0 a1)) (setq B1 (+ 2pi (- a0 a1))))
    385. (if (>= a0 a2) (setq B2 (- a0 a2)) (setq B2 (+ 2pi (- a0 a2))))
    386. (< B1 B2)
    387. )
    388. )
    389. )
    390. ;;;判断Next边是否已经在polytoupu里了
    391. ;(if (member next (mapcar 'abs polytoupu)) (setq exitflag t))
    392. (setq polytoupu (append polytoupu (list (setq next (car toupu0))))) ;_ next 下一邻接边序号
    393. ;;;验证next 下一邻接边序号的方位角是否和首端点弧段角度a0重合,如重合,找下一边,未找到,结束组多边形
    394. (setq falg1 t
    395. kk 1)
    396. (while flag1
    397. (if (> next 0)
    398. (setq a1 (angle (cadr (assoc (car (nth (1- next) Coordinates)) nodes)) (cadr (nth (1- next) Coordinates))))
    399. (setq a1 (angle (cadr (assoc (nth 4 (nth (abs (1+ next)) Coordinates)) nodes)) (nth 3 (nth (abs (1+ next)) Coordinates))))
    400. )
    401. (if (equal a0 a1 0.000001) (setq next (nth kk toupu0))(setq flag1 nil))
    402. (if (not next) (setq flag1 nil))
    403. (setq kk (1+ kk))
    404. )
    405. ;(if next (setq polytoupu (append polytoupu (list (setq next (car toupu0))))))
    406. (if next
    407. (if (> next 0)
    408. (progn
    409. (setq p0 (cadr (assoc (setq node (nth 4 (nth (1- next) Coordinates))) nodes))
    410. a0 (angle p0 (nth 3 (nth (1- next) Coordinates)))
    411. toupu0 (caddr (assoc next toupulist))
    412. )
    413. (if (equal node nodestart) (setq flag nil))
    414. )
    415. (progn
    416. (setq p0 (cadr (assoc (setq node (car (nth (abs (1+ next)) Coordinates))) nodes))
    417. a0 (angle p0 (cadr (nth (abs (1+ next)) Coordinates)))
    418. toupu0 (cadr (assoc (abs next) toupulist))
    419. )
    420. (if (equal node nodestart) (setq flag nil))
    421. )
    422. )
    423. (setq flag nil)
    424. )
    425. (setq ExitNum (1+ ExitNum))
    426. ;;;搜索边界次数超过2000次,程序陷入死循环,退出
    427. (if (> ExitNum 2000) (setq flag nil ExitFlag t))
    428. (if (and flag (not ExitFlag))
    429. (progn
    430. ;;;移除重合的线
    431. (setq toupu0 (vl-remove-if
    432. '(lambda (x)
    433. (if (> x 0)
    434. (equal a0 (angle (cadr (assoc (car (nth (1- x) Coordinates)) nodes)) (cadr (nth (1- x) Coordinates))) *jd*)
    435. (equal a0 (angle (cadr (assoc (nth 4 (nth (abs (1+ x)) Coordinates)) nodes)) (nth 3 (nth (abs (1+ x)) Coordinates))) *jd*)
    436. )
    437. )
    438. toupu0
    439. )
    440. )
    441. (if (not (> (length toupu0) 0)) (setq flag nil ExitFlag t))
    442. )
    443. )
    444. ) ;_ while
    445. (if ExitFlag
    446. (setq ExitFlag nil)
    447. (setq PolyTouPuList (append PolyTouPuList (list polytoupu)))
    448. )
    449. )
    450. )
    451. (setq n (1+ n))
    452. )
    453. (GXL-SYS-PROGRESS-DONE)
    454. ;(princ " \n多边形拓扑 ")
    455. (GXL-SYS-TIMEOUT t2)
    456. ;;;删除多余多边形
    457. (gxl-dumpPolyTouPuList PolyTouPuList)
    458. )
    459. ;|
    460. 6、多余多边形的消除
    461. 由于按照最小角法则搜索出的多边形, 其中部
    462. 分是重复的(例如“岛”被搜索了两次) , 部分是错误
    463. 的(例如外围轮廓多边形) , 因此这两种多边形需要
    464. 去除. 其中重复多边形的去除是从多边形与弧段的
    465. 拓扑关联表中按照边数相等, 且边号绝对值相等的
    466. 原则来进行; 而错误多边形的去除则按照下面原则
    467. 进行: 一个多边形与另一多边形有公共边, 同时它又
    468. 包含另一多边形的非公共边上一点, 则该多边形是
    469. 错误多边形.
    470. |;
    471. ;;;(gxl-dumpPolyTouPuList PolyTouPuList) 删除多余多边形,本函数仅消除重复的多边形,
    472. ;;;外包多边形在实际生成多边形后再予以删除
    473. (defun gxl-dumpPolyTouPuList (PolyTouPuList / rtn pl nn n a)
    474. (setq pl PolyTouPuList
    475. nn (length pl)
    476. ) ;_ setq
    477. ;(grtext -2 "\n处理多余多边形...")
    478. ;(princ)
    479. (GXL-SYS-PROGRESS-INIT "处理多余多边形" nn)
    480. ;;;测试时间
    481. ;(setq t2 (getvar "cdate"))
    482. (while (setq a (car pl)
    483. rtn (cons a rtn)
    484. pl (vl-remove-if
    485. '(lambda (x)
    486. (if (= (length a) (length x))
    487. (if (equal (vl-sort (mapcar 'abs x) '<)
    488. (vl-sort (mapcar 'abs a) '<)
    489. ) ;_ equal
    490. t
    491. ) ;_ if
    492. ) ;_ if
    493. ) ;_ lambda
    494. pl
    495. ) ;_ vl-remove-if
    496. ) ;_ setq
    497. (GXL-SYS-PROGRESS nn -1)
    498. ) ;_ while
    499. (GXL-SYS-PROGRESS-DONE)
    500. ;(GXL-SYS-TIMEOUT t2)
    501. (setq rtn (reverse rtn))
    502. (vl-remove-if
    503. '(lambda (x) (/= (length x) (length (GXL-LISTDUMPATOM (mapcar 'abs x)))))
    504. rtn
    505. )
    506. ) ;_ defun
    507. ;|
    508. 7、根据生成的多边形拓扑表绘制多边形
    509. ;;;(gxl-DrawPolyLine PolyTouPuList ssl Coordinates closed)
    510. 由弧段与多边形拓扑关联表绘制多边形,参数 多边形拓扑关联表 图元名列表 坐标值列表 是否闭合 返回值:多边形选择集
    511. ;;;PolyTouPuList 多边形拓扑表
    512. ;;; ssl 图元名--节点编号表 '((图元名 首节点编号 末节点编号)...)
    513. ;;; nodes 节点--坐标表 '((节点编号 坐标)...)
    514. |;
    515. (defun gxl-DrawPolyLine (PolyTouPuList
    516. ssl nodes closed / Polytoupu pts
    517. _bulges mn ml mk num p1 p2
    518. np1 np2 en en1 rtn coords n
    519. gxl-DelOutPolyline La_LineType_Color Lay LineType Color xh1 xh2
    520. ) ;_ PolyTouPuList
    521. ;;;(gxl-DelOutPolyline ss) 删除拓扑出poly选择集中外边框,返回删除后的选择集
    522. ;;;(gxl-DelOutPolyline pss)
    523. (defun gxl-DelOutPolyline (ss / ssL ssL1 ent flag en1 rtn)
    524. (setq ssL (GXL-SEL-SS->LIST ss)
    525. rtn (ssadd)
    526. flag t
    527. )
    528. (setq ssL (vl-sort ssL '(lambda (e1 e2) (> (GXL-GETAREA e1) (GXL-GETAREA e2)))))
    529. (while flag
    530. (setq ent (car ssL)
    531. ssL (cdr ssL)
    532. ssL1 '()
    533. flag1 nil
    534. )
    535. (while ssL
    536. (setq en1 (car ssL)
    537. ssL (cdr ssL)
    538. ) ;_ setq
    539. (if (PolyInLwpolyLine en1 ent)
    540. (setq flag1 t)
    541. (setq ssL1 (cons en1 ssL1))
    542. ) ;_ if
    543. ) ;_ while
    544. (if flag1 (progn (ssdel ent ss)(entdel ent)(setq flag1 nil)))
    545. (if ssL1
    546. (setq ssL (vl-sort ssL1 '(lambda (e1 e2) (> (GXL-GETAREA e1) (GXL-GETAREA e2)))))
    547. (setq flag nil)
    548. )
    549. ) ;_ while
    550. ss
    551. )
    552. (setq rtn (ssadd))
    553. (if (not *jd*) (setq *jd* 0.0001))
    554. (foreach Polytoupu PolyTouPuList
    555. (setq pts nil
    556. _bulges nil
    557. mn (length Polytoupu)
    558. mk 0
    559. )
    560. ;(if closed (setq mk 0) (setq mk -1))
    561. (foreach num Polytoupu
    562. (setq mk (1+ mk))
    563. (setq en (car (nth (1- (abs num)) ssl))
    564. xh1 (cadr (nth (1- (abs num)) ssl))
    565. xh2 (caddr (nth (1- (abs num)) ssl))
    566. ;coords (nth (1- (abs num)) Coordinates)
    567. entype (gxl-dxf en 0)
    568. )
    569. (if (> num 0)
    570. (setq p1 (cadr (assoc xh1 nodes))
    571. p2 (cadr (assoc xh2 nodes))
    572. ) ;_ setq
    573. (setq p1 (cadr (assoc xh2 nodes))
    574. p2 (cadr (assoc xh1 nodes))
    575. ) ;_ setq
    576. ) ;_ if
    577. (cond ((= entype "LINE")
    578. (if pts
    579. (setq pts (append pts (list p2))
    580. _bulges (append _bulges (list 0))
    581. )
    582. (setq pts (append pts (list p1 p2))
    583. _bulges (append _bulges (list 0))
    584. )
    585. ) ;_ if
    586. )
    587. ((= entype "ARC")
    588. (if pts
    589. (setq pts (append pts (list p2))
    590. _bulges (append _bulges (list (cond ((> num 0) (gxl-GetArcBulge en)) (t (* -1.0 (gxl-GetArcBulge en))))))
    591. )
    592. (setq pts (append pts (list p1 p2))
    593. _bulges (append _bulges (list (cond ((> num 0) (gxl-GetArcBulge en)) (t (* -1.0 (gxl-GetArcBulge en))))))
    594. )
    595. )
    596. )
    597. ((= entype "LWPOLYLINE")
    598. (setq data (gxl-get_poly_data en))
    599. (if (> num 0)
    600. (progn
    601. (if pts
    602. (progn
    603. (setq pts (append pts (cdar data)))
    604. (setq _bulges (append _bulges (reverse (cdr (reverse (cadr data))))))
    605. )
    606. (progn
    607. (setq pts (append pts (cons p1 (cdar data))))
    608. (setq _bulges (append _bulges (cadr data)))
    609. )
    610. )
    611. ) ;_ progn
    612. (progn
    613. (GXL-REVERSELWPOLYLINE en)
    614. (setq data (gxl-get_poly_data en))
    615. (if pts
    616. (progn
    617. (setq pts (append pts (cdar data)))
    618. (setq _bulges (append _bulges (reverse (cdr (reverse (cadr data))))))
    619. )
    620. (progn
    621. (setq pts (append pts (cons p1 (cdar data))))
    622. (setq _bulges (append _bulges (cadr data)))
    623. )
    624. )
    625. (GXL-REVERSELWPOLYLINE en)
    626. ) ;_ progn
    627. ) ;_ if
    628. )
    629. )
    630. )
    631. ;(if (= entype "LWPOLYLINE") (setq _bulges (append _bulges (list (last (cadr data))))) (setq _bulges (append _bulges (list 0))))
    632. (if closed
    633. (vla-put-closed (GXL-AX:ADDLWPOLYLINE1 *MODEL-SPACE* (list pts _bulges )) :vlax-true)
    634. (GXL-AX:ADDLWPOLYLINE1 *MODEL-SPACE* (list pts _bulges))
    635. )
    636. (setq app pts
    637. bus _bulges)
    638. (ssadd (setq en (entlast)) rtn)
    639. ;;;修改多段线图层
    640. (setq La_LineType_Color (gxl-GetToupuPolyLayer_Linetype_color Polytoupu (mapcar 'car ssl)))
    641. (setq lay (car La_LineType_Color)
    642. LineType (cadr La_LineType_Color)
    643. Color (caddr La_LineType_Color)
    644. )
    645. (gxl-CH_Ent en 8 lay)
    646. (if LineType (gxl-CH_Ent en 6 LineType))
    647. (if color (gxl-CH_Ent en 62 color))
    648. (gxl-DumpPolyPoint en)
    649. ;(vla-put-closed (GXL-AX:ADDLWPOLYLINE *MODEL-SPACE* pts) :vlax-true)
    650. )
    651. (if closed (gxl-DelOutPolyline rtn) rtn) ;_ 返回删除外框后的选择集
    652. )
    653. ;;;测试
    654. (defun c:mkpoly ()
    655. (SETUNDOERR)
    656. (if (not *jd*) (setq *jd* 0.00001))
    657. (princ "\n基于方位角计算的拓扑多边形自动构建快速算法测试")
    658. (princ "\n****程序作者:Gu_xl 2010年8月****")
    659. (princ "\n选择直线、圆弧、圆:")
    660. (setq ss (ssget '((0 . "line,arc,circle"))))
    661. (gxl-makepoly ss)
    662. (reerr)
    663. )
    664. ;;;至此,基于方位角计算的拓扑多边形自动构建快速算法 的主要算法思路的函数功能全部完成,
    665. ;;;附件是打包的测试程序,调用命令:mkpoly