standards.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. # Purpose: Define standard linetypes, text styles
  2. # Created: 23.03.2016
  3. # Copyright (c) 2016-2019, Manfred Moitzi
  4. # License: MIT License
  5. from typing import TYPE_CHECKING, List, Tuple, Sequence, Union, cast
  6. from ezdxf.render.arrows import ARROWS
  7. from ezdxf.options import options
  8. import logging
  9. if TYPE_CHECKING: # import forward declarations
  10. from ezdxf.eztypes import Drawing, DimStyle
  11. logger = logging.getLogger('ezdxf')
  12. def setup_drawing(dwg: 'Drawing', topics: Union[str, bool, Sequence] = 'all'):
  13. """
  14. Setup default linetypes, text styles or dimension styles.
  15. Args:
  16. dwg: DXF document
  17. topics: 'all' or True to setup everything
  18. Tuple of strings to specify setup:
  19. - 'linetypes': setup linetypes
  20. - 'styles'; setup text styles
  21. - 'dimstyles[:all|metric|us]': setup dimension styles (us not implemented)
  22. Returns:
  23. """
  24. if not topics: # topics is None, False or ''
  25. return
  26. def get_token(name: str) -> List[str]:
  27. for t in topics:
  28. token = t.split(':')
  29. if token[0] == name:
  30. return token
  31. return []
  32. if topics in ('all', True):
  33. setup_all = True
  34. topics = []
  35. else:
  36. setup_all = False
  37. topics = list(t.lower() for t in topics)
  38. if setup_all or 'linetypes' in topics:
  39. setup_linetypes(dwg)
  40. if setup_all or 'styles' in topics:
  41. setup_styles(dwg)
  42. dimstyles = get_token('dimstyles')
  43. if setup_all or len(dimstyles):
  44. if len(dimstyles) == 2:
  45. domain = dimstyles[1]
  46. else:
  47. domain = 'all'
  48. setup_dimstyles(dwg, domain=domain)
  49. def setup_linetypes(dwg: 'Drawing') -> None:
  50. for name, desc, pattern in linetypes():
  51. if name in dwg.linetypes:
  52. continue
  53. dwg.linetypes.new(name, dxfattribs={
  54. 'description': desc,
  55. 'pattern': pattern,
  56. })
  57. def setup_styles(dwg: 'Drawing') -> None:
  58. dwg.header['$TEXTSTYLE'] = 'OpenSans'
  59. for name, font in styles():
  60. if name in dwg.styles:
  61. continue
  62. dwg.styles.new(name, dxfattribs={
  63. 'font': font,
  64. })
  65. def setup_dimstyles(dwg: 'Drawing', domain: str = 'all') -> None:
  66. setup_styles(dwg)
  67. ezdxf_dimstyle = setup_dimstyle(dwg, name='EZDXF', fmt='EZ_M_100_H25_CM',
  68. style=options.default_dimension_text_style,
  69. blk=ARROWS.architectural_tick)
  70. ezdxf_dimstyle.dxf.dimasz *= .7 # smaller arch ticks
  71. dwg.header['$DIMSTYLE'] = 'EZDXF'
  72. ezdxf_dimstyle.copy_to_header(dwg)
  73. if domain in ('metric', 'all'):
  74. setup_dimstyle(dwg, fmt='EZ_M_100_H25_CM', style=options.default_dimension_text_style)
  75. setup_dimstyle(dwg, fmt='EZ_M_50_H25_CM', style=options.default_dimension_text_style)
  76. setup_dimstyle(dwg, fmt='EZ_M_25_H25_CM', style=options.default_dimension_text_style)
  77. setup_dimstyle(dwg, fmt='EZ_M_20_H25_CM', style=options.default_dimension_text_style)
  78. setup_dimstyle(dwg, fmt='EZ_M_10_H25_CM', style=options.default_dimension_text_style)
  79. setup_dimstyle(dwg, fmt='EZ_M_5_H25_CM', style=options.default_dimension_text_style)
  80. setup_dimstyle(dwg, fmt='EZ_M_1_H25_CM', style=options.default_dimension_text_style)
  81. elif domain in ('us', 'all'):
  82. pass
  83. class DimStyleFmt:
  84. DIMASZ = 2.5 # in mm in paper space
  85. DIMTSZ = 1.25 # x2 in mm in paper space
  86. UNIT_FACTOR = {
  87. 'm': 1, # 1 drawing unit == 1 meter
  88. 'dm': 10, # 1 drawing unit == 1 decimeter
  89. 'cm': 100, # 1 drawing unit == 1 centimeter
  90. 'mm': 1000, # 1 drawing unit == 1 millimeter
  91. }
  92. def __init__(self, fmt: str):
  93. tokens = fmt.lower().split('_')
  94. self.name = fmt
  95. self.drawing_unit = tokens[1] # EZ_<M>_100_H25_CM
  96. self.scale = float(tokens[2]) # EZ_M_<100>_H25_CM
  97. self.height = float(tokens[3][1:]) / 10. # EZ_M_100_H<25>_CM # in mm
  98. self.measurement_unit = tokens[4] # EZ_M_100_H25_<CM>
  99. @property
  100. def unit_factor(self):
  101. return self.UNIT_FACTOR[self.drawing_unit]
  102. @property
  103. def measurement_factor(self):
  104. return self.UNIT_FACTOR[self.measurement_unit]
  105. @property
  106. def text_factor(self):
  107. return self.unit_factor / self.UNIT_FACTOR['mm'] * self.scale
  108. @property
  109. def dimlfac(self):
  110. return self.measurement_factor / self.unit_factor
  111. @property
  112. def dimasz(self):
  113. return self.DIMASZ * self.text_factor
  114. @property
  115. def dimtsz(self):
  116. return self.DIMTSZ * self.text_factor
  117. @property
  118. def dimtxt(self):
  119. return self.height * self.text_factor
  120. @property
  121. def dimexe(self):
  122. return self.dimtxt * 1.5
  123. @property
  124. def dimexo(self):
  125. return self.dimtxt / 2
  126. @property
  127. def dimdle(self):
  128. return .25 * self.unit_factor
  129. def setup_dimstyle(dwg: 'Drawing', fmt: str, style: str = None, blk: str = None, name: str = '') -> 'DimStyle':
  130. """
  131. Easy DimStyle setup, the `fmt` string defines four essential dimension parameters separated by the `_` character.
  132. Tested and works with the metric system, I don't touch the 'english unit' system.
  133. Example: `fmt` = 'EZ_M_100_H25_CM'
  134. 1. '<EZ>_M_100_H25_CM': arbitrary prefix
  135. 2. 'EZ_<M>_100_H25_CM': defines the drawing unit, valid values are 'M', 'DM', 'CM', 'MM'
  136. 3. 'EZ_M_<100>_H25_CM': defines the scale of the drawing, '100' is for 1:100
  137. 4. 'EZ_M_100_<H25>_CM': defines the text height in mm in paper space times 10, 'H25' is 2.5mm
  138. 5. 'EZ_M_100_H25_<CM>': defines the units for the measurement text, valid values are 'M', 'DM', 'CM', 'MM'
  139. Args:
  140. dwg: DXF drawing
  141. fmt: format string
  142. style: text style for measurement
  143. blk: block name for arrow None for oblique stroke
  144. name: dimension style name, if name is '', `fmt` string is used as name
  145. """
  146. style = style or options.default_dimension_text_style
  147. fmt = DimStyleFmt(fmt)
  148. name = name or fmt.name
  149. if dwg.dimstyles.has_entry(name):
  150. logging.debug('DimStyle "{}" already exists.'.format(name))
  151. return cast('DimStyle', dwg.dimstyles.get(name))
  152. dimstyle = cast('DimStyle', dwg.dimstyles.new(name))
  153. dimstyle.dxf.dimtxt = fmt.dimtxt
  154. dimstyle.dxf.dimlfac = fmt.dimlfac # factor for measurement; dwg in m : measurement in cm -> dimlfac=100
  155. dimstyle.dxf.dimgap = fmt.dimtxt * .4 # gap between text and dimension line
  156. dimstyle.dxf.dimtad = 1 # text above dimline
  157. dimstyle.dxf.dimexe = fmt.dimexe
  158. dimstyle.dxf.dimexo = fmt.dimexo
  159. dimstyle.dxf.dimdle = 0 # dimension extension beyond extension lines
  160. dimstyle.dxf.dimtix = 0 # Draws dimension text between the extension lines even if it would ordinarily be placed outside those lines
  161. dimstyle.dxf.dimtih = 0 # Aligns text inside extension lines with dimension line; 1 = Draws text horizontally
  162. dimstyle.dxf.dimtoh = 0 # Aligns text outside of extension lines with dimension line; 1 = Draws text horizontally
  163. dimstyle.dxf.dimzin = 8 # Suppresses trailing zeros in decimal dimensions
  164. dimstyle.dxf.dimsah = 0
  165. if blk is None: # oblique stroke
  166. dimstyle.dxf.dimtsz = fmt.dimtsz # tick size
  167. dimstyle.dxf.dimasz = fmt.dimasz # arrow size
  168. else: # arrow or block
  169. dimstyle.set_arrows(blk=blk)
  170. dimstyle.dxf.dimasz = fmt.dimasz
  171. if dwg.dxfversion > 'AC1009':
  172. # set text style
  173. dimstyle.dxf.dimtmove = 2 # move freely without leader
  174. dimstyle.dxf.dimtxsty = style
  175. dimstyle.dxf.dimupt = 1 # user location override, controls both the text position and the dimension line location, same as DXF12
  176. dimstyle.dxf.dimdsep = ord('.')
  177. dimstyle.dxf.dimdec = 2 # show just 2 decimals
  178. return dimstyle
  179. def linetypes() -> List[Tuple[str, str, Sequence[float]]]:
  180. """ Creates a list of standard line types.
  181. """
  182. # dxf linetype definition
  183. # name, description, elements:
  184. # elements = [total_pattern_length, elem1, elem2, ...]
  185. # total_pattern_length = sum(abs(elem))
  186. # elem > 0 is line, < 0 is gap, 0.0 = dot;
  187. return [("CONTINUOUS", "Solid", [0.0]),
  188. ("CENTER", "Center ____ _ ____ _ ____ _ ____ _ ____ _ ____",
  189. [2.0, 1.25, -0.25, 0.25, -0.25]),
  190. ("CENTERX2", "Center (2x) ________ __ ________ __ ________",
  191. [3.5, 2.5, -0.25, 0.5, -0.25]),
  192. ("CENTER2", "Center (.5x) ____ _ ____ _ ____ _ ____ _ ____",
  193. [1.0, 0.625, -0.125, 0.125, -0.125]),
  194. ("DASHED", "Dashed __ __ __ __ __ __ __ __ __ __ __ __ __ _",
  195. [0.6, 0.5, -0.1]),
  196. ("DASHEDX2", "Dashed (2x) ____ ____ ____ ____ ____ ____",
  197. [1.2, 1.0, -0.2]),
  198. ("DASHED2", "Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _",
  199. [0.3, 0.25, -0.05]),
  200. ("PHANTOM", "Phantom ______ __ __ ______ __ __ ______",
  201. [2.5, 1.25, -0.25, 0.25, -0.25, 0.25, -0.25]),
  202. ("PHANTOMX2", "Phantom (2x)____________ ____ ____ ____________",
  203. [4.25, 2.5, -0.25, 0.5, -0.25, 0.5, -0.25]),
  204. ("PHANTOM2", "Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ ___",
  205. [1.25, 0.625, -0.125, 0.125, -0.125, 0.125, -0.125]),
  206. ("DASHDOT", "Dash dot __ . __ . __ . __ . __ . __ . __ . __",
  207. [1.4, 1.0, -0.2, 0.0, -0.2]),
  208. ("DASHDOTX2", "Dash dot (2x) ____ . ____ . ____ . ____",
  209. [2.4, 2.0, -0.2, 0.0, -0.2]),
  210. ("DASHDOT2", "Dash dot (.5x) _ . _ . _ . _ . _ . _ . _ . _",
  211. [0.7, 0.5, -0.1, 0.0, -0.1]),
  212. ("DOT", "Dot . . . . . . . . . . . . . . . .",
  213. [0.2, 0.0, -0.2]),
  214. ("DOTX2", "Dot (2x) . . . . . . . . ",
  215. [0.4, 0.0, -0.4]),
  216. ("DOT2", "Dot (.5) . . . . . . . . . . . . . . . . . . . ",
  217. [0.1, 0.0, -0.1]),
  218. ("DIVIDE", "Divide __ . . __ . . __ . . __ . . __ . . __",
  219. [1.6, 1.0, -0.2, 0.0, -0.2, 0.0, -0.2]),
  220. ("DIVIDEX2", "Divide (2x) ____ . . ____ . . ____ . . ____",
  221. [2.6, 2.0, -0.2, 0.0, -0.2, 0.0, -0.2]),
  222. ("DIVIDE2", "Divide(.5x) _ . _ . _ . _ . _ . _ . _ . _",
  223. [0.8, 0.5, -0.1, 0.0, -0.1, 0.0, -0.1]),
  224. ]
  225. def styles():
  226. """ Creates a list of standard styles.
  227. """
  228. return [
  229. ('STANDARD', 'txt'),
  230. ('OpenSans-Light', 'OpenSans-Light.ttf'),
  231. ('OpenSans-Light-Italic', 'OpenSans-LightItalic.ttf'),
  232. ('OpenSans', 'OpenSans-Regular.ttf'),
  233. ('OpenSans-Italic', 'OpenSans-Italic.ttf'),
  234. ('OpenSans-SemiBold', 'OpenSans-SemiBold.ttf'),
  235. ('OpenSans-SemiBoldItalic', 'OpenSans-SemiBoldItalic.ttf'),
  236. ('OpenSans-Bold', 'OpenSans-Bold.ttf'),
  237. ('OpenSans-BoldItalic', 'OpenSans-BoldItalic.ttf'),
  238. ('OpenSans-ExtraBold', 'OpenSans-ExtraBold.ttf'),
  239. ('OpenSans-ExtraBoldItalic', 'OpenSans-ExtraBoldItalic.ttf'),
  240. ('OpenSansCondensed-Bold', 'OpenSansCondensed-Bold.ttf'),
  241. ('OpenSansCondensed-Light', 'OpenSansCondensed-Light.ttf'),
  242. ('OpenSansCondensed-Italic', 'OpenSansCondensed-LightItalic.ttf'),
  243. ('LiberationSans', 'LiberationSans-Regular.ttf'),
  244. ('LiberationSans-Bold', 'LiberationSans-Bold.ttf'),
  245. ('LiberationSans-BoldItalic', 'LiberationSans-BoldItalic.ttf'),
  246. ('LiberationSans-Italic', 'LiberationSans-Italic.ttf'),
  247. ('LiberationSerif', 'LiberationSerif-Regular.ttf'),
  248. ('LiberationSerif-Bold', 'LiberationSerif-Bold.ttf'),
  249. ('LiberationSerif-BoldItalic', 'LiberationSerif-BoldItalic.ttf'),
  250. ('LiberationSerif-Italic', 'LiberationSerif-Italic.ttf'),
  251. ('LiberationMono', 'LiberationMono-Regular.ttf'),
  252. ('LiberationMono-Bold', 'LiberationMono-Bold.ttf'),
  253. ('LiberationMono-BoldItalic', 'LiberationMono-BoldItalic.ttf'),
  254. ('LiberationMono-Italic', 'LiberationMono-Italic.ttf'),
  255. ]