pyautocad 基于线段包围盒聚类

性能:50张图纸 45000条线条耗时4分钟左右

把图纸里的内容全部变成块会极大提高聚类速度也不影响之后的打印

复制代码
9966.10), 终点(2249.70, -9963.3
5)
找到线段 40827: 起点(2250.55, -
9974.19), 终点(2250.13, -9966.1
0)
找到线段 40828: 起点(2250.92, -
9987.24), 终点(2250.55, -9974.1
9)
找到线段 40829: 起点(2251.23, -
10004.58), 终点(2250.92, -9987.
24)
找到线段 40830: 起点(2251.46, -
10025.34), 终点(2251.23, -10004
.58)
找到线段 40831: 起点(2251.61, -
10048.48), 终点(2251.46, -10025
.34)
找到线段 40832: 起点(2251.66, -
10072.85), 终点(2251.61, -10048
.48)
找到线段 40833: 起点(2313.40, -
9963.35), 终点(2246.77, -9963.3
5)
找到线段 40834: 起点(2313.40, -
10182.35), 终点(2246.77, -10182
.35)
找到线段 40835: 起点(2025.21, -
10182.35), 终点(2049.92, -10182
.35)
找到线段 40836: 起点(2059.95, -
10179.61), 终点(2052.85, -10182
.35)
找到线段 40837: 起点(2066.69, -
10171.51), 终点(2059.95, -10179
.61)
找到线段 40838: 起点(2072.74, -
10158.46), 终点(2066.69, -10171
.51)
找到线段 40839: 起点(2077.79, -
10141.12), 终点(2072.74, -10158
.46)
找到线段 40840: 起点(2081.59, -
10120.36), 终点(2077.79, -10141
.12)
找到线段 40841: 起点(2083.95, -
10097.22), 终点(2081.59, -10120
.36)
找到线段 40842: 起点(2084.75, -
10072.85), 终点(2083.95, -10097
.22)
找到线段 40843: 起点(2083.95, -
10048.48), 终点(2084.75, -10072
.85)
找到线段 40844: 起点(2081.59, -
10025.34), 终点(2083.95, -10048
.48)
找到线段 40845: 起点(2077.79, -
10004.58), 终点(2081.59, -10025
.34)
找到线段 40846: 起点(2072.74, -
9987.24), 终点(2077.79, -10004.
58)
找到线段 40847: 起点(2066.69, -
9974.19), 终点(2072.74, -9987.2
4)
找到线段 40848: 起点(2059.95, -
9966.10), 终点(2066.69, -9974.1
9)
找到线段 40849: 起点(2025.21, -
9963.35), 终点(2049.92, -9963.3
5)
找到线段 40850: 起点(2052.85, -
9963.35), 终点(2059.95, -9966.1
0)
找到线段 40851: 起点(2210.17, -
10182.35), 终点(2049.92, -10182
.35)
找到线段 40852: 起点(2210.17, -
9963.35), 终点(2049.92, -9963.3
5)
找到线段 40853: 起点(2827.39, -
9966.09), 终点(2803.04, -9963.3
5)
找到线段 40854: 起点(2850.52, -
9974.19), 终点(2827.39, -9966.0
9)
找到线段 40855: 起点(2871.26, -
9987.24), 终点(2850.52, -9974.1
9)
找到线段 40856: 起点(2888.59, -
10004.58), 终点(2871.26, -9987.
24)
找到线段 40857: 起点(2901.62, -
10025.34), 终点(2888.59, -10004
.58)
找到线段 40858: 起点(2909.71, -
10048.48), 终点(2901.62, -10025
.34)
找到线段 40859: 起点(2912.46, -
10072.85), 终点(2909.71, -10048
.48)
找到线段 40860: 起点(2909.71, -
10097.22), 终点(2912.46, -10072
.85)
找到线段 40861: 起点(2901.62, -
10120.36), 终点(2909.71, -10097
.22)
找到线段 40862: 起点(2888.59, -
10141.12), 终点(2901.62, -10120
.36)
找到线段 40863: 起点(2871.26, -
10158.46), 终点(2888.59, -10141
.12)
找到线段 40864: 起点(2850.52, -
10171.51), 终点(2871.26, -10158
.46)
找到线段 40865: 起点(2827.39, -
10179.60), 终点(2850.52, -10171
.51)
找到线段 40866: 起点(2803.04, -
10182.35), 终点(2827.39, -10179
.60)
找到线段 40867: 起点(2803.04, -
9963.35), 终点(2766.96, -9963.3
5)
找到线段 40868: 起点(2766.96, -
10182.35), 终点(2803.04, -10182
.35)
找到线段 40869: 起点(2313.40, -
10182.35), 终点(2766.96, -10182
.35)
找到线段 40870: 起点(2766.96, -
9963.35), 终点(2313.40, -9963.3
5)
找到线段 40871: 起点(2251.61, -
10097.22), 终点(2251.66, -10072
.85)
找到线段 40872: 起点(2026.73, -
10116.02), 终点(2024.59, -10094
.99)
找到线段 40873: 起点(2030.19, -
10134.89), 终点(2026.73, -10116
.02)
找到线段 40874: 起点(2034.78, -
10150.64), 终点(2030.19, -10134
.89)
找到线段 40875: 起点(2038.59, -
10158.88), 终点(2034.78, -10150
.64)
找到线段 40876: 起点(2038.60, -
9986.82), 终点(2034.78, -9995.0
6)
找到线段 40877: 起点(2030.19, -
10010.81), 终点(2034.78, -9995.
06)
找到线段 40878: 起点(2026.73, -
10029.68), 终点(2030.19, -10010
.81)
找到线段 40879: 起点(2024.59, -
10050.71), 终点(2026.73, -10029
.68)
找到线段 40880: 起点(2023.86, -
10072.85), 终点(2024.59, -10050
.71)
找到线段 40881: 起点(2024.59, -
10094.99), 终点(2023.86, -10072
.85)
共提取到 40881 条线段

总共识别到 70 个聚类

处理 70 个聚类:

聚类 0 包含 563 条线段 (574 个
点)
  AABB尺寸: 2817.600 * 1968.000

  AABB面积: 5545036.800
  OBB尺寸: 1968.000 x 2817.600
  OBB面积: 5545036.814
  旋转角度: 90.00度
  相比AABB节省: -0.00%
  已绘制聚类 0 的OBB框 (颜色索
引: 1)

聚类 1 包含 572 条线段 (583 个
点)
  AABB尺寸: 2629.760 * 1836.800

  AABB面积: 4830343.168
  OBB尺寸: 2629.760 x 1836.800
  OBB面积: 4830343.229
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 1 的OBB框 (颜色索
引: 2)

聚类 2 包含 537 条线段 (559 个
点)
  AABB尺寸: 2348.000 * 1640.000

  AABB面积: 3850720.000
  OBB尺寸: 1640.000 x 2348.000
  OBB面积: 3850720.010
  旋转角度: 90.00度
  相比AABB节省: -0.00%
  已绘制聚类 2 的OBB框 (颜色索
引: 3)

聚类 3 包含 544 条线段 (565 个
点)
  AABB尺寸: 2348.000 * 1640.000

  AABB面积: 3850720.000
  OBB尺寸: 2348.000 x 1640.000
  OBB面积: 3850720.049
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 3 的OBB框 (颜色索
引: 4)

聚类 4 包含 537 条线段 (552 个
点)
  AABB尺寸: 2348.000 * 1640.000

  AABB面积: 3850720.000
  OBB尺寸: 2348.000 x 1640.000
  OBB面积: 3850720.049
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 4 的OBB框 (颜色索
引: 5)

聚类 5 包含 541 条线段 (559 个
点)
  AABB尺寸: 2348.000 * 1640.000

  AABB面积: 3850720.000
  OBB尺寸: 1640.000 x 2348.000
  OBB面积: 3850720.010
  旋转角度: 90.00度
  相比AABB节省: -0.00%
  已绘制聚类 5 的OBB框 (颜色索
引: 6)

聚类 6 包含 539 条线段 (561 个
点)
  AABB尺寸: 2817.600 * 1968.000

  AABB面积: 5545036.800
  OBB尺寸: 2817.600 x 1968.000
  OBB面积: 5545036.870
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 6 的OBB框 (颜色索
引: 7)

聚类 7 包含 525 条线段 (551 个
点)
  AABB尺寸: 2301.040 * 1607.200

  AABB面积: 3698231.488
  OBB尺寸: 2301.040 x 1607.200
  OBB面积: 3698231.535
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 7 的OBB框 (颜色索
引: 8)

聚类 8 包含 644 条线段 (650 个
点)
  AABB尺寸: 4109.000 * 2870.000

  AABB面积: 11792830.000
  OBB尺寸: 2870.000 x 4109.000
  OBB面积: 11792830.031
  旋转角度: 90.00度
  相比AABB节省: -0.00%
  已绘制聚类 8 的OBB框 (颜色索
引: 9)

聚类 9 包含 435 条线段 (456 个
点)
  AABB尺寸: 3522.000 * 2460.000

  AABB面积: 8664120.000
  OBB尺寸: 3522.000 x 2460.000
  OBB面积: 8664120.109
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 9 的OBB框 (颜色索
引: 10)

聚类 10 包含 440 条线段 (469 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 10 的OBB框 (颜色索
引: 11)

聚类 11 包含 387 条线段 (413 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 11 的OBB框 (颜色索
引: 12)

聚类 12 包含 611 条线段 (625 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2050.000 x 2935.000
  OBB面积: 6016750.016
  旋转角度: 90.00度
  相比AABB节省: -0.00%
  已绘制聚类 12 的OBB框 (颜色索
引: 13)

聚类 13 包含 517 条线段 (542 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 13 的OBB框 (颜色索
引: 14)

聚类 14 包含 518 条线段 (532 个
点)
  AABB尺寸: 2348.000 * 1640.000

  AABB面积: 3850720.000
  OBB尺寸: 2348.000 x 1640.000
  OBB面积: 3850720.049
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 14 的OBB框 (颜色索
引: 15)

聚类 15 包含 625 条线段 (646 个
点)
  AABB尺寸: 3522.000 * 2460.000

  AABB面积: 8664120.000
  OBB尺寸: 3522.000 x 2460.000
  OBB面积: 8664120.109
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 15 的OBB框 (颜色索
引: 16)

聚类 16 包含 532 条线段 (551 个
点)
  AABB尺寸: 2817.600 * 1968.000

  AABB面积: 5545036.800
  OBB尺寸: 2817.600 x 1968.000
  OBB面积: 5545036.870
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 16 的OBB框 (颜色索
引: 17)

聚类 17 包含 562 条线段 (603 个
点)
  AABB尺寸: 2254.080 * 1574.400

  AABB面积: 3548823.552
  OBB尺寸: 2254.080 x 1574.400
  OBB面积: 3548823.597
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 17 的OBB框 (颜色索
引: 18)

聚类 18 包含 597 条线段 (635 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 18 的OBB框 (颜色索
引: 19)

聚类 19 包含 690 条线段 (732 个
点)
  AABB尺寸: 4109.000 * 2870.000

  AABB面积: 11792830.000
  OBB尺寸: 4109.000 x 2870.000
  OBB面积: 11792830.149
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 19 的OBB框 (颜色索
引: 20)

聚类 20 包含 602 条线段 (631 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2050.000 x 2935.000
  OBB面积: 6016750.016
  旋转角度: 90.00度
  相比AABB节省: -0.00%
  已绘制聚类 20 的OBB框 (颜色索
引: 1)

聚类 21 包含 453 条线段 (471 个
点)
  AABB尺寸: 2348.000 * 1640.000

  AABB面积: 3850720.000
  OBB尺寸: 2348.000 x 1640.000
  OBB面积: 3850720.049
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 21 的OBB框 (颜色索
引: 2)

聚类 22 包含 456 条线段 (480 个
点)
  AABB尺寸: 2348.000 * 1640.000

  AABB面积: 3850720.000
  OBB尺寸: 2348.000 x 1640.000
  OBB面积: 3850720.049
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 22 的OBB框 (颜色索
引: 3)

聚类 23 包含 608 条线段 (641 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2050.000 x 2935.000
  OBB面积: 6016750.016
  旋转角度: 90.00度
  相比AABB节省: -0.00%
  已绘制聚类 23 的OBB框 (颜色索
引: 4)

聚类 24 包含 608 条线段 (639 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 24 的OBB框 (颜色索
引: 5)

聚类 25 包含 553 条线段 (586 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 25 的OBB框 (颜色索
引: 6)

聚类 26 包含 553 条线段 (584 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2050.000 x 2935.000
  OBB面积: 6016750.016
  旋转角度: 90.00度
  相比AABB节省: -0.00%
  已绘制聚类 26 的OBB框 (颜色索
引: 7)

聚类 27 包含 531 条线段 (545 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 27 的OBB框 (颜色索
引: 8)

聚类 28 包含 537 条线段 (554 个
点)
  AABB尺寸: 3522.000 * 2460.000

  AABB面积: 8664120.000
  OBB尺寸: 3522.000 x 2460.000
  OBB面积: 8664120.109
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 28 的OBB框 (颜色索
引: 9)

聚类 29 包含 516 条线段 (549 个
点)
  AABB尺寸: 3522.000 * 2460.000

  AABB面积: 8664120.000
  OBB尺寸: 3522.000 x 2460.000
  OBB面积: 8664120.109
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 29 的OBB框 (颜色索
引: 10)

聚类 30 包含 497 条线段 (520 个
点)
  AABB尺寸: 3522.000 * 2460.000

  AABB面积: 8664120.000
  OBB尺寸: 3522.000 x 2460.000
  OBB面积: 8664120.109
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 30 的OBB框 (颜色索
引: 11)

聚类 31 包含 552 条线段 (597 个
点)
  AABB尺寸: 4696.000 * 3280.000

  AABB面积: 15402880.000
  OBB尺寸: 4696.000 x 3280.000
  OBB面积: 15402880.194
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 31 的OBB框 (颜色索
引: 12)

聚类 32 包含 521 条线段 (560 个
点)
  AABB尺寸: 3522.000 * 2460.000

  AABB面积: 8664120.000
  OBB尺寸: 3522.000 x 2460.000
  OBB面积: 8664120.109
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 32 的OBB框 (颜色索
引: 13)

聚类 33 包含 529 条线段 (568 个
点)
  AABB尺寸: 3522.000 * 2460.000

  AABB面积: 8664120.000
  OBB尺寸: 3522.000 x 2460.000
  OBB面积: 8664120.109
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 33 的OBB框 (颜色索
引: 14)

聚类 34 包含 544 条线段 (578 个
点)
  AABB尺寸: 4109.000 * 2870.000

  AABB面积: 11792830.000
  OBB尺寸: 4109.000 x 2870.000
  OBB面积: 11792830.149
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 34 的OBB框 (颜色索
引: 15)

聚类 35 包含 544 条线段 (581 个
点)
  AABB尺寸: 4109.000 * 2870.000

  AABB面积: 11792830.000
  OBB尺寸: 4109.000 x 2870.000
  OBB面积: 11792830.149
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 35 的OBB框 (颜色索
引: 16)

聚类 36 包含 670 条线段 (673 个
点)
  AABB尺寸: 4109.000 * 2870.000

  AABB面积: 11792830.000
  OBB尺寸: 4109.000 x 2870.000
  OBB面积: 11792830.149
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 36 的OBB框 (颜色索
引: 17)

聚类 37 包含 675 条线段 (678 个
点)
  AABB尺寸: 3756.800 * 2624.000

  AABB面积: 9857843.200
  OBB尺寸: 3756.800 x 2624.000
  OBB面积: 9857843.324
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 37 的OBB框 (颜色索
引: 18)

聚类 38 包含 573 条线段 (598 个
点)
  AABB尺寸: 4109.000 * 2870.000

  AABB面积: 11792830.000
  OBB尺寸: 4109.000 x 2870.000
  OBB面积: 11792830.149
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 38 的OBB框 (颜色索
引: 19)

聚类 39 包含 560 条线段 (580 个
点)
  AABB尺寸: 2935.000 * 2364.176

  AABB面积: 6938856.433
  OBB尺寸: 2935.000 x 2364.176
  OBB面积: 6938856.483
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 39 的OBB框 (颜色索
引: 20)

聚类 40 包含 225 条线段 (268 个
点)
  AABB尺寸: 2876.300 * 2009.000

  AABB面积: 5778486.700
  OBB尺寸: 2876.300 x 2009.000
  OBB面积: 5778486.773
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 40 的OBB框 (颜色索
引: 1)

聚类 41 包含 355 条线段 (391 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 41 的OBB框 (颜色索
引: 2)

聚类 42 包含 359 条线段 (394 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 42 的OBB框 (颜色索
引: 3)

聚类 43 包含 490 条线段 (516 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 43 的OBB框 (颜色索
引: 4)

聚类 44 包含 310 条线段 (346 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 44 的OBB框 (颜色索
引: 5)

聚类 45 包含 619 条线段 (636 个
点)
  AABB尺寸: 3522.000 * 2460.000

  AABB面积: 8664120.000
  OBB尺寸: 3522.000 x 2460.000
  OBB面积: 8664120.109
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 45 的OBB框 (颜色索
引: 6)

聚类 46 包含 839 条线段 (848 个
点)
  AABB尺寸: 3287.200 * 2296.000

  AABB面积: 7547411.200
  OBB尺寸: 3287.200 x 2296.000
  OBB面积: 7547411.295
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 46 的OBB框 (颜色索
引: 7)

聚类 47 包含 668 条线段 (677 个
点)
  AABB尺寸: 2665.612 * 1836.800

  AABB面积: 4896196.468
  OBB尺寸: 2665.612 x 1836.800
  OBB面积: 4896196.515
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 47 的OBB框 (颜色索
引: 8)

聚类 48 包含 686 条线段 (729 个
点)
  AABB尺寸: 4109.000 * 2870.000

  AABB面积: 11792830.000
  OBB尺寸: 4109.000 x 2870.000
  OBB面积: 11792830.149
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 48 的OBB框 (颜色索
引: 9)

聚类 49 包含 558 条线段 (602 个
点)
  AABB尺寸: 3756.800 * 2624.000

  AABB面积: 9857843.200
  OBB尺寸: 3756.800 x 2624.000
  OBB面积: 9857843.324
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 49 的OBB框 (颜色索
引: 10)

聚类 50 包含 498 条线段 (536 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 50 的OBB框 (颜色索
引: 11)

聚类 51 包含 937 条线段 (973 个
点)
  AABB尺寸: 4696.000 * 3280.000

  AABB面积: 15402880.000
  OBB尺寸: 4696.000 x 3280.000
  OBB面积: 15402880.194
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 51 的OBB框 (颜色索
引: 12)

聚类 52 包含 823 条线段 (861 个
点)
  AABB尺寸: 3287.200 * 2296.000

  AABB面积: 7547411.200
  OBB尺寸: 3287.200 x 2296.000
  OBB面积: 7547411.295
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 52 的OBB框 (颜色索
引: 13)

聚类 53 包含 811 条线段 (841 个
点)
  AABB尺寸: 3756.800 * 2624.000

  AABB面积: 9857843.200
  OBB尺寸: 3756.800 x 2624.000
  OBB面积: 9857843.324
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 53 的OBB框 (颜色索
引: 14)

聚类 54 包含 733 条线段 (781 个
点)
  AABB尺寸: 4109.000 * 2870.000

  AABB面积: 11792830.000
  OBB尺寸: 4109.000 x 2870.000
  OBB面积: 11792830.149
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 54 的OBB框 (颜色索
引: 15)

聚类 55 包含 738 条线段 (787 个
点)
  AABB尺寸: 4109.000 * 2870.000

  AABB面积: 11792830.000
  OBB尺寸: 4109.000 x 2870.000
  OBB面积: 11792830.149
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 55 的OBB框 (颜色索
引: 16)

聚类 56 包含 549 条线段 (583 个
点)
  AABB尺寸: 4109.000 * 2870.000

  AABB面积: 11792830.000
  OBB尺寸: 4109.000 x 2870.000
  OBB面积: 11792830.149
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 56 的OBB框 (颜色索
引: 17)

聚类 57 包含 546 条线段 (579 个
点)
  AABB尺寸: 3756.800 * 2624.000

  AABB面积: 9857843.200
  OBB尺寸: 3756.800 x 2624.000
  OBB面积: 9857843.324
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 57 的OBB框 (颜色索
引: 18)

聚类 58 包含 876 条线段 (902 个
点)
  AABB尺寸: 4696.000 * 3280.000

  AABB面积: 15402880.000
  OBB尺寸: 4696.000 x 3280.000
  OBB面积: 15402880.194
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 58 的OBB框 (颜色索
引: 19)

聚类 59 包含 857 条线段 (885 个
点)
  AABB尺寸: 5870.000 * 4100.000

  AABB面积: 24067000.000
  OBB尺寸: 5870.000 x 4100.000
  OBB面积: 24067000.303
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 59 的OBB框 (颜色索
引: 20)

聚类 60 包含 858 条线段 (877 个
点)
  AABB尺寸: 5870.000 * 4100.000

  AABB面积: 24067000.000
  OBB尺寸: 5870.000 x 4100.000
  OBB面积: 24067000.303
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 60 的OBB框 (颜色索
引: 1)

聚类 61 包含 694 条线段 (713 个
点)
  AABB尺寸: 4696.000 * 3280.000

  AABB面积: 15402880.000
  OBB尺寸: 4696.000 x 3280.000
  OBB面积: 15402880.194
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 61 的OBB框 (颜色索
引: 2)

聚类 62 包含 718 条线段 (750 个
点)
  AABB尺寸: 4696.000 * 3280.000

  AABB面积: 15402880.000
  OBB尺寸: 4696.000 x 3280.000
  OBB面积: 15402880.194
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 62 的OBB框 (颜色索
引: 3)

聚类 63 包含 694 条线段 (735 个
点)
  AABB尺寸: 4696.000 * 3280.000

  AABB面积: 15402880.000
  OBB尺寸: 4696.000 x 3280.000
  OBB面积: 15402880.194
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 63 的OBB框 (颜色索
引: 4)

聚类 64 包含 623 条线段 (652 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 64 的OBB框 (颜色索
引: 5)

聚类 65 包含 388 条线段 (414 个
点)
  AABB尺寸: 2935.000 * 2050.000

  AABB面积: 6016750.000
  OBB尺寸: 2935.000 x 2050.000
  OBB面积: 6016750.076
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 65 的OBB框 (颜色索
引: 6)

聚类 66 包含 728 条线段 (767 个
点)
  AABB尺寸: 4696.000 * 3280.000

  AABB面积: 15402880.000
  OBB尺寸: 3280.000 x 4696.000
  OBB面积: 15402880.040
  旋转角度: 90.00度
  相比AABB节省: -0.00%
  已绘制聚类 66 的OBB框 (颜色索
引: 7)

聚类 67 包含 723 条线段 (763 个
点)
  AABB尺寸: 4109.000 * 2870.000

  AABB面积: 11792830.000
  OBB尺寸: 4109.000 x 2870.000
  OBB面积: 11792830.149
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 67 的OBB框 (颜色索
引: 8)

聚类 68 包含 492 条线段 (544 个
点)
  AABB尺寸: 4109.000 * 2870.000

  AABB面积: 11792830.000
  OBB尺寸: 4109.000 x 2870.000
  OBB面积: 11792830.149
  旋转角度: 180.00度
  相比AABB节省: -0.00%
  已绘制聚类 68 的OBB框 (颜色索
引: 9)

聚类 69 包含 488 条线段 (534 个
点)
  AABB尺寸: 4109.000 * 2870.000

  AABB面积: 11792830.000
  OBB尺寸: 4109.000 x 2870.000
  OBB面积: 11792830.149
  旋转角度: 0.00度
  相比AABB节省: -0.00%
  已绘制聚类 69 的OBB框 (颜色索
引: 10)
python 复制代码
import math
import numpy as np
from pyautocad import Autocad, APoint
import tkinter as tk
from tkinter import filedialog

def get_selection_or_model_space(acad, doc):
    """获取用户选择的对象"""
    print("请选择对象")
    
    try:
        import time
        unique_name = f"Temp_Selection_Set_{int(time.time() * 1000) % 10000}"
        
        selection_set = doc.SelectionSets.Add(unique_name)
        selection_set.SelectOnScreen()
        
        if selection_set.Count > 0:
            print(f"检测到 {selection_set.Count} 个选中对象")
            selection = []
            for i in range(selection_set.Count):
                try:
                    entity = selection_set.Item(i)
                    selection.append(entity)
                except Exception as e:
                    print(f"无法访问选中对象 {i}: {e}")
            selection_set.Delete()
            return selection
        else:
            selection_set.Delete()
            return []
    except Exception as e:
        print(f"无法获取选择集: {e}")
        return None

def get_lines_from_entities(entities):
    """从AutoCAD实体中提取线段"""
    lines = []
    
    for i, entity in enumerate(entities):
        try:
            if entity.ObjectName == "AcDbLine":
                start = entity.StartPoint[:2]
                end = entity.EndPoint[:2]
                lines.append((tuple(start), tuple(end)))
                print(f"找到线段 {len(lines)}: 起点({start[0]:.2f}, {start[1]:.2f}), 终点({end[0]:.2f}, {end[1]:.2f})")
            # 可以根据需要添加对其他实体类型的处理...
        except Exception as e:
            print(f"处理对象 {i+1} 时出错: {e}")
            continue
    
    print(f"共提取到 {len(lines)} 条线段")
    return lines

class LineCluster:
    def __init__(self, lines=[], min_x=0, max_x=0, min_y=0, max_y=0):
        self.lines = lines
        self.min_x = min_x
        self.max_x = max_x
        self.min_y = min_y
        self.max_y = max_y

def cluster_lines(lines, distance_threshold=50.0):
    """对线段进行聚类,基于您之前成功的算法"""
    if not lines:
        return []
    
    clusters = []
    remaining_lines = list(lines)  # 创建副本用于处理

    while remaining_lines:
        # 取出第一条线段作为种子
        seed = remaining_lines.pop(0)
        current_cluster = [seed]
        
        # 初始化聚落的边界
        min_x = min(seed[0][0], seed[1][0])
        max_x = max(seed[0][0], seed[1][0])
        min_y = min(seed[0][1], seed[1][1])
        max_y = max(seed[0][1], seed[1][1])
        
        while True:
            # 扩展边界
            expanded_min_x = min_x - distance_threshold
            expanded_max_x = max_x + distance_threshold
            expanded_min_y = min_y - distance_threshold
            expanded_max_y = max_y + distance_threshold
            
            # 寻找在扩展边界内的线段
            to_add = []
            for line in list(remaining_lines):  # 遍历副本避免问题
                in_cluster = False
                # 检查线段的两个端点是否在扩展后的边界内
                for point in line:
                    if (expanded_min_x <= point[0] <= expanded_max_x and
                        expanded_min_y <= point[1] <= expanded_max_y):
                        in_cluster = True
                        break
                if in_cluster:
                    to_add.append(line)
            
            # 如果没有找到,结束循环
            if not to_add:
                break
            
            # 将找到的线段加入当前聚落,并更新边界
            for line in to_add:
                current_cluster.append(line)
                remaining_lines.remove(line)
                # 更新当前聚落的边界
                line_min_x = min(p[0] for p in line)
                line_max_x = max(p[0] for p in line)
                line_min_y = min(p[1] for p in line)
                line_max_y = max(p[1] for p in line)
                min_x = min(min_x, line_min_x)
                max_x = max(max_x, line_max_x)
                min_y = min(min_y, line_min_y)
                max_y = max(max_y, line_max_y)
        
        # 检查是否有其他聚落被当前聚落完全包含,如果有则合并
        clusters_to_remove = []
        for cluster in clusters:
            if (min_x <= cluster.min_x and min_y <= cluster.min_y and
                max_x >= cluster.max_x and max_y >= cluster.max_y):
                current_cluster.extend(cluster.lines)
                clusters_to_remove.append(cluster)
        
        # 移除被包含的聚落
        for cluster in clusters_to_remove:
            clusters.remove(cluster)
        
        # 将当前聚落加入结果列表
        current_cluster_obj = LineCluster(
            lines=current_cluster,
            min_x=min_x,
            max_x=max_x,
            min_y=min_y,
            max_y=max_y
        )
        clusters.append(current_cluster_obj)

    return clusters

def get_points_from_cluster(cluster):
    """从线段聚类中提取所有点"""
    points = []
    for line in cluster.lines:
        points.append(line[0])  # 起点
        points.append(line[1])  # 终点
    return list(set(points))  # 去重

def get_aabb_bounding_box(points):
    """获取轴对齐的最小包围矩形"""
    if len(points) < 1:
        return None
    
    # 处理单点情况
    if len(points) == 1:
        x, y = points[0]
        size = 1.0  # 创建一个很小的正方形包围框
        corners = [
            (x - size/2, y - size/2),
            (x + size/2, y - size/2),
            (x + size/2, y + size/2),
            (x - size/2, y + size/2)
        ]
        return {
            'type': 'AABB',
            'corners': corners,
            'width': size,
            'height': size,
            'area': size * size,
            'angle': 0,
            'center': (x, y)
        }
    
    x_coords = [p[0] for p in points]
    y_coords = [p[1] for p in points]
    
    min_x, max_x = min(x_coords), max(x_coords)
    min_y, max_y = min(y_coords), max(y_coords)
    
    width = max_x - min_x
    height = max_y - min_y
    
    # 计算四个角点
    corners = [
        (min_x, min_y),
        (max_x, min_y),
        (max_x, max_y),
        (min_x, max_y)
    ]
    
    return {
        'type': 'AABB',
        'corners': corners,
        'width': width,
        'height': height,
        'area': width * height,
        'angle': 0,
        'center': ((min_x + max_x) / 2, (min_y + max_y) / 2)
    }

def rotate_point(point, angle, center=(0, 0)):
    """绕指定中心点旋转点"""
    x, y = point
    cx, cy = center
    
    x -= cx
    y -= cy
    
    rad = math.radians(angle)
    cos_rad, sin_rad = math.cos(rad), math.sin(rad)
    new_x = x * cos_rad - y * sin_rad
    new_y = x * sin_rad + y * cos_rad
    
    new_x += cx
    new_y += cy
    
    return (new_x, new_y)

def get_bounding_box_area(points, angle):
    """计算给定角度下的包围盒面积和边界信息"""
    rotated_points = [rotate_point(p, -angle) for p in points]
    
    x_coords = [p[0] for p in rotated_points]
    y_coords = [p[1] for p in rotated_points]
    
    min_x, max_x = min(x_coords), max(x_coords)
    min_y, max_y = min(y_coords), max(y_coords)
    
    width = max_x - min_x
    height = max_y - min_y
    area = width * height
    
    return area, (min_x, max_x, min_y, max_y)

def ternary_search_min_area(points, left, right, eps=1e-6):
    """使用三分法搜索最小面积角度"""
    while right - left > eps:
        mid1 = left + (right - left) / 3
        mid2 = right - (right - left) / 3
        
        area1, _ = get_bounding_box_area(points, mid1)
        area2, _ = get_bounding_box_area(points, mid2)
        
        if area1 < area2:
            right = mid2
        else:
            left = mid1
    
    optimal_angle = (left + right) / 2
    min_area, bounds = get_bounding_box_area(points, optimal_angle)
    return optimal_angle, min_area, bounds

def get_oriented_bounding_box_approx(points):
    """使用三分搜索获取最小面积包围矩形"""
    # 处理单点情况
    if len(points) < 1:
        return None
    
    if len(points) == 1:
        x, y = points[0]
        size = 1.0  # 创建一个很小的正方形包围框
        corners = [
            (x - size/2, y - size/2),
            (x + size/2, y - size/2),
            (x + size/2, y + size/2),
            (x - size/2, y + size/2)
        ]
        return {
            'type': 'OBB',
            'corners': corners,
            'width': size,
            'height': size,
            'area': size * size,
            'angle': 0,
            'center': (x, y)
        }
    
    if len(points) < 2:
        return None
    
    # 首先找到一个较好的初始角度范围
    angles_to_check = []
    
    # 使用较小步长进行初步搜索
    for i in range(0, 180, 2):
        angles_to_check.append(i)
    
    # 找到距离最远的点对
    max_dist = 0
    farthest_pair = None
    for i in range(len(points)):
        for j in range(i+1, len(points)):
            dist = math.sqrt((points[i][0]-points[j][0])**2 + (points[i][1]-points[j][1])**2)
            if dist > max_dist:
                max_dist = dist
                farthest_pair = (points[i], points[j])
    
    if farthest_pair:
        p1, p2 = farthest_pair
        angle = math.degrees(math.atan2(p2[1] - p1[1], p2[0] - p1[0]))
        angles_to_check.extend([angle, angle + 90])
    
    angles_to_check = list(set([a % 180 for a in angles_to_check]))
    
    # 找到初步的最小面积角度
    min_area = float('inf')
    best_angle = 0
    best_bounds = None
    
    for angle in angles_to_check:
        area, bounds = get_bounding_box_area(points, angle)
        if area < min_area:
            min_area = area
            best_angle = angle
            best_bounds = bounds
    
    # 在最优角度附近使用三分法进行精细搜索
    search_range = 5  # 搜索范围±5度
    left_angle = (best_angle - search_range) % 180
    right_angle = (best_angle + search_range) % 180
    
    # 处理跨越0度的情况
    if left_angle > right_angle:
        # 在[0, right_angle]和[left_angle, 180]两个区间分别搜索
        optimal_angle1, min_area1, bounds1 = ternary_search_min_area(points, 0, right_angle)
        optimal_angle2, min_area2, bounds2 = ternary_search_min_area(points, left_angle, 180)
        
        if min_area1 < min_area2:
            optimal_angle = optimal_angle1
            min_area = min_area1
            best_bounds = bounds1
        else:
            optimal_angle = optimal_angle2
            min_area = min_area2
            best_bounds = bounds2
    else:
        optimal_angle, min_area, best_bounds = ternary_search_min_area(points, left_angle, right_angle)
    
    # 构造最终的包围盒
    min_x, max_x, min_y, max_y = best_bounds
    width = max_x - min_x
    height = max_y - min_y
    
    # 计算旋转后的四个角点
    rotated_corners = [
        (min_x, min_y),
        (max_x, min_y),
        (max_x, max_y),
        (min_x, max_y)
    ]
    
    # 将角点旋转回原始坐标系
    corners = [rotate_point(p, optimal_angle) for p in rotated_corners]
    
    center_x = (min_x + max_x) / 2
    center_y = (min_y + max_y) / 2
    center_original = rotate_point((center_x, center_y), optimal_angle)
    
    return {
        'type': 'OBB',
        'corners': corners,
        'width': width,
        'height': height,
        'area': min_area,
        'angle': optimal_angle,
        'center': center_original
    }

def ensure_layer_exists(acad, layer_name):
    """确保图层存在,如果不存在则创建它"""
    try:
        # 尝试获取现有图层
        layers = acad.doc.Layers
        layer = layers.Item(layer_name)
        return layer
    except:
        # 图层不存在,创建新图层
        try:
            layers = acad.doc.Layers
            new_layer = layers.Add(layer_name)
            return new_layer
        except Exception as e:
            print(f"创建图层 '{layer_name}' 时出错: {e}")
            return None

def draw_bounding_box_with_text(acad, box, color_index, cluster_id=None, width=None, height=None):
    """在AutoCAD中绘制包围框并在旁边添加长宽数字文本"""
    if not box or 'corners' not in box:
        return None
    
    corners = box['corners']
    model = acad.model
    
    # 确保"obb_clusters"图层存在
    obb_layer = ensure_layer_exists(acad, "obb_clusters")
    
    # 绘制四条边,形成闭合矩形
    lines = []
    for i in range(4):
        p1 = APoint(corners[i][0], corners[i][1], 0)
        p2 = APoint(corners[(i+1)%4][0], corners[(i+1)%4][1], 0)
        line = model.AddLine(p1, p2)
        line.Color = color_index
        # 如果图层创建成功,将线条也放到obb_clusters图层
        if obb_layer:
            try:
                line.Layer = "obb_clusters"
            except:
                pass  # 如果设置图层失败,保持默认图层
        lines.append(line)
    
    # 添加聚类编号
    if cluster_id is not None:
        # 在包围框中心放置编号
        center_x = sum(corner[0] for corner in corners) / 4
        center_y = sum(corner[1] for corner in corners) / 4
        text_position = APoint(center_x, center_y, 0)
        text_content = str(cluster_id)
        text = model.AddText(text_content, text_position, 5)  # 文本高度设为5
        text.Color = color_index
        if obb_layer:
            try:
                text.Layer = "obb_clusters"
            except Exception as e:
                print(f"设置文字图层时出错: {e}")
        lines.append(text)
    
    # 如果提供了宽度和高度,则添加文本标注
    if width is not None and height is not None:
        # 找到包围框的右上角点
        top_right = max(corners, key=lambda p: p[0] + p[1])
        
        # 在右上角附近放置文本
        text_position = APoint(top_right[0] + 5, top_right[1] + 5, 0)
        text_content = f"{width:.0f}*{height:.0f}"
        text = model.AddText(text_content, text_position, 5)  # 文本高度设为5
        text.Color = color_index
        
        # 将文字设置到"obb_clusters"图层
        if obb_layer:
            try:
                text.Layer = "obb_clusters"
            except Exception as e:
                print(f"设置文字图层时出错: {e}")
        
        lines.append(text)
    
    return lines

def process_clusters(acad, clusters):
    """处理聚类并绘制OBB框"""
    print(f"\n处理 {len(clusters)} 个聚类:")
    
    # 预定义颜色列表 (AutoCAD颜色索引)
    colors = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
    
    for i, cluster in enumerate(clusters):
        # 从线段聚类中提取点
        points = get_points_from_cluster(cluster)
        print(f"\n聚类 {i} 包含 {len(cluster.lines)} 条线段 ({len(points)} 个点)")
        
        # 计算AABB
        aabb = get_aabb_bounding_box(points)
        if aabb:
            print(f"  AABB尺寸: {aabb['width']:.3f} * {aabb['height']:.3f}")
            print(f"  AABB面积: {aabb['area']:.3f}")
        
        # 计算OBB
        obb = get_oriented_bounding_box_approx(points)
        if obb:
            print(f"  OBB尺寸: {obb['width']:.3f} x {obb['height']:.3f}")
            print(f"  OBB面积: {obb['area']:.3f}")
            if 'angle' in obb:
                print(f"  旋转角度: {obb['angle']:.2f}度")
            
            if aabb and aabb['area'] > 0:
                saving = (1 - obb['area'] / aabb['area']) * 100
                print(f"  相比AABB节省: {saving:.2f}%")
            
            # 绘制OBB框并标注编号和尺寸
            color_index = colors[i % len(colors)]
            draw_bounding_box_with_text(acad, obb, color_index, i, obb['width'], obb['height'])
            print(f"  已绘制聚类 {i} 的OBB框 (颜色索引: {color_index})")

def main():
    """主函数"""
    try:
        acad = Autocad(create_if_not_exists=True)
        doc = acad.doc
        print(f"成功连接到 AutoCAD 文档: {doc.Name}")
    except Exception as e:
        print("无法连接到 AutoCAD:", e)
        return
    
    try:
        entities = get_selection_or_model_space(acad, doc)
        
        if entities is None:
            print("获取对象过程中发生错误,程序退出")
            return
        
        if not entities:
            print("没有找到任何对象,程序退出")
            return
        
        print(f"处理 {len(entities)} 个对象")
        
        # 提取线段数据
        lines = get_lines_from_entities(entities)
        
        if len(lines) < 1:
            print("未找到有效线段")
            return
        
        # 对线段进行聚类
        clusters = cluster_lines(lines, distance_threshold=2000.0)  # 根据您的数据调整阈值
        print(f"\n总共识别到 {len(clusters)} 个聚类")
        
        # 处理每个聚类并绘制OBB框
        process_clusters(acad, clusters)
        
        print("\n处理完成!所有聚类的OBB框已绘制在'obb_clusters'图层中")
        print("每个框中心显示聚类编号,右上角显示尺寸信息")
        
    except Exception as e:
        print(f"处理对象时出错: {e}")

if __name__ == "__main__":
    main()
相关推荐
刘晓倩44 分钟前
Python的re
java·python·mysql
qq_233907031 小时前
GEO优化企业2025推荐,提升网站全球访问速度与用户体验
大数据·人工智能·python·ux
人大博士的交易之路1 小时前
龙虎榜——20251204
数学建模·数据挖掘·数据分析·缠论·龙虎榜·道琼斯结构
Q_Q5110082851 小时前
python+django/flask+vue的高考志愿咨询系统
spring boot·python·django·flask·node.js·php
Q_Q5110082851 小时前
python+django/flask+vue校园闲置物品交易系统
spring boot·python·django·flask·node.js
子午1 小时前
【鱼类识别系统】Python+TensorFlow+Django+人工智能+深度学习+卷积神经网络算法+resnet50
人工智能·python·深度学习
Q_Q5110082851 小时前
python+django/flask+vue基于web的产品管理系统
前端·spring boot·python·django·flask·node.js
Q_Q19632884751 小时前
python+django/flask+vue的电子产品销售系统
spring boot·python·django·flask·node.js·php
Q_Q5110082851 小时前
python+django/flask+vue的小型房屋租赁系统
spring boot·python·django·flask·node.js·php