fig-laba6-shpury.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. # -*- coding: utf-8 -*-
  2. """
  3. Лаба 6, рисунок «Схема расположения шпуров на забое» (вариант 6):
  4. выработка S = 14,17 м2, B = 4,53 м; 48 шпуров: 8 врубовых (вертикальный
  5. клиновой вруб, 4 пары, 65°), 5 отбойных (сводом параллельно контуру),
  6. 9 подошвенных, 26 оконтуривающих.
  7. Номера шпуров; справа — разрез А-А со следами всех шпуров в массиве (условно),
  8. с глубинами l_зах и l_вр.
  9. """
  10. import numpy as np
  11. import matplotlib
  12. matplotlib.use('Agg')
  13. import matplotlib.pyplot as plt
  14. import matplotlib.patheffects as pe
  15. # Чертёжный шрифт ГОСТ 2.304-81 тип А (прямой, из системных шрифтов Windows)
  16. import matplotlib.font_manager as fm
  17. fm.fontManager.addfont('C:/Windows/Fonts/GOST2304A.ttf')
  18. matplotlib.rcParams['font.family'] = 'GOST 2.304 type A'
  19. matplotlib.rcParams['mathtext.default'] = 'regular'
  20. matplotlib.rcParams['mathtext.fontset'] = 'custom'
  21. matplotlib.rcParams['mathtext.rm'] = 'GOST 2.304 type A'
  22. matplotlib.rcParams['mathtext.it'] = 'GOST 2.304 type A'
  23. matplotlib.rcParams['mathtext.bf'] = 'GOST 2.304 type A'
  24. B = 4.53
  25. R = B / 2.0 # 2,265 — свод полуциркульный
  26. HW = 1.35 # высота стены: S = pi R^2/2 + B*HW = 14,17
  27. YC = HW
  28. OFF = 0.17 # отступ линии контурных шпуров
  29. fig = plt.figure(figsize=(16.2 / 2.54, 15.4 / 2.54), dpi=250)
  30. ax = fig.add_axes([0, 0, 1, 1])
  31. ax.set_aspect('equal'); ax.axis('off')
  32. XL, XR, YB, YT = -3.30, 7.35, -5.85, 4.75
  33. ax.set_xlim(XL, XR); ax.set_ylim(YB, YT)
  34. C_CUT, C_AUX, C_TOE, C_CONT = '#cc1f2d', '#1f5fb4', '#1d8a4b', '#111111'
  35. # --- контур выработки и линия контурных шпуров -------------------------------
  36. th = np.linspace(0, np.pi, 200)
  37. ax.plot(R * np.cos(th), YC + R * np.sin(th), color='black', lw=2.2)
  38. ax.plot([-R, -R], [0, YC], color='black', lw=2.2)
  39. ax.plot([R, R], [0, YC], color='black', lw=2.2)
  40. ax.plot([-R, R], [0, 0], color='black', lw=2.2)
  41. rc = R - OFF
  42. ax.plot(rc * np.cos(th), YC + rc * np.sin(th), color='0.4', lw=0.7, ls=(0, (4, 3)))
  43. ax.plot([-rc, -rc], [OFF, YC], color='0.4', lw=0.7, ls=(0, (4, 3)))
  44. ax.plot([rc, rc], [OFF, YC], color='0.4', lw=0.7, ls=(0, (4, 3)))
  45. ax.plot([-rc, rc], [OFF, OFF], color='0.4', lw=0.7, ls=(0, (4, 3)))
  46. # --- шпуры --------------------------------------------------------------------
  47. holes = [] # (x, y, color, n, inward)
  48. n = 1
  49. for dy in (1.05, 0.63, 0.21, -0.21): # врубовые 1-8: 4 пары,
  50. for sx in (-0.28, 0.28): # верхняя пара поднята выше
  51. holes.append((sx, YC + dy, C_CUT, n, False)); n += 1
  52. # отбойные 9-13 — сводом параллельно контуру: 5 точек на эллиптической дуге
  53. # (полуоси AUX_A × AUX_B) с равным шагом ПО ДУГЕ a_о = 0,6 м; полуоси выбраны
  54. # так, чтобы полудуга составляла ~2 шага (1,2 м) и дуга охватывала вруб
  55. AUX_A, AUX_B, AUX_Y0 = 0.70, 0.80, 1.75
  56. A_O = 0.60
  57. def _ell_pt(t):
  58. return np.array([AUX_A * np.cos(t), AUX_Y0 + AUX_B * np.sin(t)])
  59. _tt = np.linspace(np.pi / 2, 0.0, 2001) # от замка (t = 90°) к пяте (t = 0°)
  60. _seg = np.hypot(*np.diff(np.stack([_ell_pt(t) for t in _tt]).T, axis=1))
  61. _arc = np.concatenate([[0.0], np.cumsum(_seg)])
  62. def _t_at(s): # параметр t на дуговом расстоянии s от замка
  63. return float(np.interp(s, _arc, _tt))
  64. aux_pts = [tuple(_ell_pt(_t_at(s))) for s in (0.0, A_O, 2 * A_O)] # правая половина
  65. aux_pts = aux_pts + [(-x, y) for x, y in aux_pts[1:]] # зеркально влево
  66. # порядок номеров: против часовой стрелки, начиная с левой пяты (как на паспорте БВР)
  67. aux_pts = sorted(aux_pts, key=lambda p: np.arctan2(p[1] - AUX_Y0, p[0]))
  68. for (x, y) in aux_pts:
  69. holes.append((x, y, C_AUX, n, False)); n += 1
  70. for x in np.linspace(-2.2, 2.2, 9): # подошвенные 14-22, шаг 0,55
  71. holes.append((x, 0.52, C_TOE, n, False)); n += 1
  72. # контурные 23-48: дуга свода с шагом по дуге 0,5 м (13 точек), стены и подошва
  73. CONT_T = np.linspace(np.radians(8.1), np.pi - np.radians(8.1), 13)
  74. arc_pts = [(rc * np.cos(t), YC + rc * np.sin(t)) for t in CONT_T]
  75. for x, y in arc_pts:
  76. holes.append((x, y, C_CONT, n, True)); n += 1
  77. for y in (1.25, 0.86):
  78. holes.append((-rc, y, C_CONT, n, True)); n += 1
  79. holes.append((rc, y, C_CONT, n, True)); n += 1
  80. for x in np.linspace(-2.0, 2.0, 9): # подошвенная линия, шаг 0,5
  81. holes.append((x, OFF, C_CONT, n, True)); n += 1
  82. assert n - 1 == 48, n - 1
  83. AUX_LB = {} # подписи отбойных — радиально наружу от центра дуги
  84. for x, y, c, num, inward in holes:
  85. ax.plot(x, y, 'o', ms=4.6, mfc='white' if c == C_CONT else c,
  86. mec=c, mew=1.15, zorder=5)
  87. if inward: # подписи контурных — внутрь
  88. v = np.array([0 - x, YC - 0.45 - y]); v = v / np.hypot(*v)
  89. dx, dy = 0.14 * v[0], 0.14 * v[1]
  90. if y <= OFF + 0.13: # нижняя линия — над кружком
  91. dx, dy, ha = 0.0, 0.17, 'center'
  92. elif y < 0.7 and abs(x) > 1.8: # углы у подошвы — выше, наружу от штриховой
  93. dx, dy, ha = (-0.05 if x < 0 else 0.05), 0.18, 'center'
  94. elif abs(x) < 0.35 and y > YC + 1.5: # у замка — под кружком: сверху дуга и контур
  95. dx, dy, ha = 0.0, -0.20, 'center'
  96. else:
  97. ha = 'left' if dx > 0 else 'right'
  98. elif num in (9, 10, 11, 12, 13): # подписи отбойных — радиально наружу
  99. v = np.array([x / AUX_A, (y - AUX_Y0) / AUX_B]); v = v / np.hypot(*v)
  100. dx, dy = 0.15 * v[0], 0.15 * v[1]
  101. ha = 'left' if dx > 0.05 else ('right' if dx < -0.05 else 'center')
  102. if dy < 0:
  103. dy = -abs(dy)
  104. else:
  105. dx, dy, ha = 0.09, 0.09, 'left'
  106. if x > 2.1 or x < -2.1: # крайние подошвенные 14/22 — над точкой, внутрь от стены
  107. dx, dy, ha = (0.14 if x < 0 else -0.14), 0.20, 'center'
  108. elif x > 1.8: # шпур 21: подпись влево, чтобы не наезжать на номер 48
  109. dx, dy, ha = -0.09, 0.09, 'right'
  110. # белая подложка под цифрами: линии и штрихи не проходят сквозь номера
  111. ax.text(x + dx, y + dy, str(num), fontsize=6.3, color=c, zorder=6,
  112. ha=ha, va='center',
  113. path_effects=[pe.withStroke(linewidth=1.7, foreground='white')])
  114. # --- размеры: засечки 45°, выносные с выступом, число у размерной линии ---------
  115. TICK = 0.10 # полудлина засечки
  116. EXT = 0.13 # выступ выносной линии за размерную
  117. def tick(x, y, color='black'):
  118. ax.plot([x - TICK, x + TICK], [y - TICK, y + TICK], color=color, lw=1.4,
  119. solid_capstyle='butt', zorder=4)
  120. # B — ширина выработки: выносные от пят контура вниз с выступом
  121. yb = -0.62
  122. for xe in (-R, R):
  123. ax.plot([xe, xe], [0, yb - EXT], color='black', lw=0.55, zorder=1)
  124. ax.plot([-R, R], [yb, yb], color='black', lw=0.8, zorder=4)
  125. tick(-R, yb); tick(R, yb)
  126. ax.text(0, yb - 0.16, 'B = 4530', fontsize=6.4, ha='center', va='top',
  127. bbox=dict(facecolor='white', edgecolor='none', pad=1.0))
  128. # H — высота выработки: нижняя выносная от пяты, верхняя — от замка (верха выработки);
  129. # вынесена правее, чтобы не пересекать обозначение Б-Б у правой стены
  130. xh = R + 0.75
  131. ax.plot([R, xh + EXT], [0, 0], color='black', lw=0.55, zorder=1)
  132. ax.plot([0, xh + EXT], [YC + R, YC + R], color='black', lw=0.55, zorder=1)
  133. ax.plot([xh, xh], [0, YC + R], color='black', lw=0.8, zorder=4)
  134. tick(xh, 0); tick(xh, YC + R)
  135. ax.text(xh + 0.13, (YC + R) / 2, 'H = 3620', fontsize=6.4, rotation=90,
  136. ha='center', va='center', bbox=dict(facecolor='white', edgecolor='none', pad=1.0))
  137. # след секущей плоскости А-А (ГОСТ 2.305, как на паспорте БВР): тонкая линия
  138. # сечения сквозь весь вид, на концах — толстые штрихи за контуром; стрелка
  139. # взгляда вплотную остриём к штриху, буква «А» со стороны хвоста стрелки
  140. s_top, s_bot = YC + R + 0.36, -0.38
  141. ax.plot([0, 0], [-0.10, YC + R + 0.06], color='black', lw=0.6, zorder=3)
  142. for ys1, ys2 in ((YC + R + 0.06, s_top), (-0.10, s_bot)):
  143. ax.plot([0, 0], [ys1, ys2], color='black', lw=1.8, solid_capstyle='butt', zorder=4)
  144. for ys in (s_top - 0.05, s_bot + 0.05):
  145. ax.annotate('', xy=(0.0, ys), xytext=(-0.34, ys),
  146. arrowprops=dict(arrowstyle='-|>', color='black', lw=0.9,
  147. mutation_scale=11, shrinkA=0, shrinkB=0))
  148. ax.text(-0.44, ys, 'А', fontsize=9, color='black', va='center', ha='right')
  149. # след секущей плоскости Б-Б: горизонтальная линия сечения у обеих стен,
  150. # штрихи за контуром вида, стрелки взгляда вниз (к разрезу, расположенному ниже)
  151. y_cut = 0.7
  152. for xs in (-R - 0.33, R + 0.33):
  153. ax.plot([xs - 0.11, xs + 0.11], [y_cut, y_cut], color='black', lw=1.8,
  154. solid_capstyle='butt', zorder=4)
  155. ax.annotate('', xy=(xs, y_cut), xytext=(xs, y_cut + 0.28),
  156. arrowprops=dict(arrowstyle='-|>', color='black', lw=0.9,
  157. mutation_scale=11, shrinkA=0, shrinkB=0))
  158. ax.text(xs, y_cut + 0.40, 'Б', fontsize=9, color='black', ha='center')
  159. # --- вид слева: все шпуры в разрезе (условно) — забой слева, массив вправо -------
  160. x_f = 3.45 # линия забоя (толстая)
  161. K_D = 0.75 # горизонтальный масштаб глубины (условно)
  162. D_R, D_C = 3.0, 3.85 # глубина рядовых и врубовых шпуров, м
  163. x_dr, x_dc = x_f + K_D * D_R, x_f + K_D * D_C
  164. hgt = YC + R
  165. ax.plot([x_f, x_dr], [hgt, hgt], color='black', lw=1.0)
  166. ax.plot([x_f, x_dr], [0, 0], color='black', lw=1.0)
  167. ax.plot([x_dr] * 2, [0, hgt], color='black', lw=0.6)
  168. ax.plot([x_f] * 2, [0, hgt], color='black', lw=1.6)
  169. # тонкая вертикаль на уровне конца врубовых шпуров — от неё идёт размер l_вр
  170. ax.plot([x_dc] * 2, [0, 2.40], color='black', lw=0.6)
  171. ax.text((x_f + x_dc) / 2, hgt + 0.30, 'А–А', fontsize=8.6, ha='center')
  172. for y_k in (2.40, 1.98, 1.56, 1.14): # врубовые: горизонтальные следы пар
  173. ax.plot([x_f, x_dc], [y_k, y_k], color=C_CUT, lw=0.9)
  174. for y_k in sorted({round(y, 3) for x, y in aux_pts}): # отбойные
  175. ax.plot([x_f, x_dr], [y_k, y_k], color=C_AUX, lw=0.9)
  176. ax.plot([x_f, x_dr], [0.52, 0.52], color=C_TOE, lw=0.9) # подошвенные
  177. for y_k in sorted({round(YC + rc * np.sin(t), 3) for t in CONT_T} # оконтуривающие:
  178. | {1.25, 0.86, OFF}): # свод, стены,
  179. ax.plot([x_f, x_dr], [y_k, y_k], color='0.25', lw=0.7) # подошва
  180. # l_зах и l_вр — размерные линии глубин под видом слева; текст под размерной линией
  181. for xd, dim_y, txt in ((x_dr, -0.38, 'l$_з$$_а$$_х$ = 3000'),
  182. (x_dc, -0.86, 'l$_в$$_р$ = 3850')):
  183. ax.plot([x_f, x_f], [0, dim_y - 0.09], color='black', lw=0.55, zorder=1)
  184. ax.plot([xd, xd], [0, dim_y - 0.09], color='black', lw=0.55, zorder=1)
  185. ax.plot([x_f, xd], [dim_y, dim_y], color='black', lw=0.8, zorder=4)
  186. tick(x_f, dim_y); tick(xd, dim_y)
  187. ax.text((x_f + xd) / 2, dim_y - 0.16, txt, fontsize=6.4, ha='center', va='top',
  188. bbox=dict(facecolor='white', edgecolor='none', pad=1.0))
  189. # расстояния между рядами шпуров — по одному размеру на группу (в мм):
  190. # врубовые 420 (следы пар на виде А-А), отбойные 600 — по дуге на виде
  191. for y1, y2, txt in ((1.56, 1.98, '420'),):
  192. xd_c = x_dc + 0.30
  193. for yk in (y1, y2):
  194. ax.plot([x_dc, xd_c + 0.09], [yk, yk], color='black', lw=0.55, zorder=1)
  195. ax.plot([xd_c] * 2, [y1, y2], color='black', lw=0.8, zorder=4)
  196. tick(xd_c, y1); tick(xd_c, y2)
  197. ax.text(xd_c + 0.17, (y1 + y2) / 2, txt, fontsize=6.4, rotation=90,
  198. ha='center', va='center', bbox=dict(facecolor='white', edgecolor='none', pad=1.0))
  199. # a_о — на виде, между замком и соседним отбойным шпуром (размер вдоль хорды)
  200. def dim2(p1, p2, off, txt):
  201. p1, p2 = np.array(p1), np.array(p2)
  202. d = p2 - p1
  203. u = d / np.hypot(*d)
  204. nrm = np.array([-u[1], u[0]])
  205. if nrm[0] < 0:
  206. nrm = -nrm # нормаль наружу (вправо от хорды)
  207. q1, q2 = p1 + nrm * off, p2 + nrm * off
  208. for p, q in ((p1, q1), (p2, q2)):
  209. ax.plot([p[0], q[0] + nrm[0] * 0.09], [p[1], q[1] + nrm[1] * 0.09],
  210. color='black', lw=0.55, zorder=1)
  211. ax.plot([q1[0], q2[0]], [q1[1], q2[1]], color='black', lw=0.8, zorder=4)
  212. tick(*q1); tick(*q2)
  213. mid = (q1 + q2) / 2 + nrm * 0.55
  214. ax.text(mid[0], mid[1], txt, fontsize=6.4, ha='center', va='center',
  215. bbox=dict(facecolor='white', edgecolor='none', pad=1.0))
  216. _p_top = aux_pts[1] # отбойный 10 (соседний справа от замка)
  217. _p_low = aux_pts[0] # отбойный 9 (правая пята дуги)
  218. dim2(_p_top, _p_low, 0.30, 'а$_о$ = 600')
  219. # --- разрез Б-Б (план): забой сверху, массив вниз; врубовые сходятся к оси -------
  220. y_pf = -1.50 # линия забоя (толстая)
  221. y_pb = y_pf - K_D * D_C # нижняя граница плана (глубина врубовых)
  222. ax.plot([-R, R], [y_pf, y_pf], color='black', lw=1.6)
  223. ax.plot([-R, R], [y_pb, y_pb], color='black', lw=1.0)
  224. ax.plot([-R] * 2, [y_pf, y_pb], color='black', lw=1.0)
  225. ax.plot([R] * 2, [y_pf, y_pb], color='black', lw=1.0)
  226. ax.text(0, y_pf + 0.10, 'Б–Б', fontsize=8.6, ha='center')
  227. for xs in (-0.28, 0.28): # врубовые: веер к оси на глубине вруба
  228. ax.plot([xs, 0], [y_pf, y_pb], color=C_CUT, lw=0.9)
  229. for xs, c, lw in ([(0, C_AUX, 0.9), (-0.87, C_AUX, 0.9), (0.87, C_AUX, 0.9), # отбойные
  230. (-1.23, C_AUX, 0.9), (1.23, C_AUX, 0.9)]
  231. + [(x, C_TOE, 0.9) for x in np.linspace(-1.9, 1.9, 9)] # подошвенные
  232. + [(-2.095, '0.25', 0.7), (2.095, '0.25', 0.7)] # стены
  233. + [(x, '0.25', 0.7) for x in np.linspace(-rc + 0.4, rc - 0.4, 5)]): # подошва
  234. ax.plot([xs, xs], [y_pf, y_pf - K_D * D_R], color=c, lw=lw)
  235. # размеры Б-Б: расстояния между подошвенными (а_п = 550) и контурными
  236. # шпурами подошвенной линии (а_к = 500), глубина рядовых шпуров слева
  237. y_end = y_pf - K_D * D_R
  238. for xa, xb, txt in ((-2.2, -1.65, 'а$_п$ = 550'), (1.0, 1.5, 'а$_к$ = 500')):
  239. dim_y = -4.25 if txt != 'а$_к$ = 500' else -4.77
  240. for xe in (xa, xb):
  241. ax.plot([xe, xe], [y_end, dim_y - 0.09], color='black', lw=0.55, zorder=1)
  242. ax.plot([xa, xb], [dim_y, dim_y], color='black', lw=0.8, zorder=4)
  243. tick(xa, dim_y); tick(xb, dim_y)
  244. ax.text((xa + xb) / 2, dim_y - 0.16, txt, fontsize=6.4, ha='center', va='top',
  245. bbox=dict(facecolor='white', edgecolor='none', pad=1.0))
  246. xd_l = -(R + 0.35)
  247. ax.plot([xd_l, xd_l], [y_pf, y_end], color='black', lw=0.8, zorder=4)
  248. ax.plot([-R, xd_l - 0.09], [y_pf, y_pf], color='black', lw=0.55, zorder=1)
  249. ax.plot([-R, xd_l - 0.09], [y_end, y_end], color='black', lw=0.55, zorder=1)
  250. tick(xd_l, y_pf); tick(xd_l, y_end)
  251. ax.text(xd_l - 0.15, (y_pf + y_end) / 2, 'l$_з$$_а$$_х$ = 3000', fontsize=6.4,
  252. rotation=90, ha='center', va='center', bbox=dict(facecolor='white', edgecolor='none', pad=1.0))
  253. # B — ширина выработки (низ плана) и l_вр — глубина врубовых шпуров (справа)
  254. yb_bb = -5.30
  255. ax.plot([-R, -R], [y_pb, yb_bb - 0.09], color='black', lw=0.55, zorder=1)
  256. ax.plot([R, R], [y_pb, yb_bb - 0.09], color='black', lw=0.55, zorder=1)
  257. ax.plot([-R, R], [yb_bb, yb_bb], color='black', lw=0.8, zorder=4)
  258. tick(-R, yb_bb); tick(R, yb_bb)
  259. ax.text(0, yb_bb - 0.16, 'B = 4530', fontsize=6.4, ha='center', va='top',
  260. bbox=dict(facecolor='white', edgecolor='none', pad=1.0))
  261. xd_r = R + 0.35
  262. ax.plot([xd_r, xd_r], [y_pf, y_pb], color='black', lw=0.8, zorder=4)
  263. ax.plot([R, xd_r + 0.09], [y_pf, y_pf], color='black', lw=0.55, zorder=1)
  264. ax.plot([R, xd_r + 0.09], [y_pb, y_pb], color='black', lw=0.55, zorder=1)
  265. tick(xd_r, y_pf); tick(xd_r, y_pb)
  266. ax.text(xd_r + 0.15, (y_pf + y_pb) / 2, 'l$_в$$_р$ = 3850', fontsize=6.4, rotation=90,
  267. ha='center', va='center', bbox=dict(facecolor='white', edgecolor='none', pad=1.0))
  268. # --- легенда и заголовок ---------------------------------------------------------
  269. lx, ly = 3.45, -2.00 # легенда — в правой графе, под разрезом А-А
  270. items = [('врубовые — 1-8', C_CUT), ('отбойные — 9-13', C_AUX),
  271. ('подошвенные — 14-22', C_TOE), ('оконтуривающие — 23-48', C_CONT)]
  272. ax.text(lx, ly + 0.36, 'Условные обозначения:', fontsize=8.0, weight='normal')
  273. for i, (txt, c) in enumerate(items):
  274. yy = ly - i * 0.36
  275. ax.plot([lx, lx + 0.3], [yy, yy], color=c, lw=2.2)
  276. ax.plot(lx + 0.15, yy, 'o', ms=4.0, mfc='white' if c == C_CONT else c, mec=c, mew=1.1)
  277. ax.text(lx + 0.42, yy, txt, fontsize=7.6, va='center')
  278. ax.text(0.9, YT - 0.3, 'Схема расположения шпуров',
  279. fontsize=9.6, weight='normal', ha='center')
  280. fig.savefig('assets/images/laba6-shpury-zaboya.png', dpi=250, facecolor='white')
  281. print('сохранено: assets/images/laba6-shpury-zaboya.png')