3
3
from enum import IntEnum
4
4
from math import pi
5
5
from cmath import phase , rect
6
- from types import GeneratorType
7
6
from typing import Callable
8
7
from .metric import format_metric_unit
8
+ import re
9
9
10
10
Cbox = namedtuple ('Cbox' , 'p1 p2 type id' )
11
11
BOMData = namedtuple ('BOMData' , 'type id data' )
@@ -69,7 +69,7 @@ def merge_colinear(points: list[tuple[complex, complex]]) -> list[tuple[complex,
69
69
return out
70
70
71
71
72
- def iterate_line (p1 : complex , p2 : complex , step : float = 1. ) -> GeneratorType :
72
+ def iterate_line (p1 : complex , p2 : complex , step : float = 1. ):
73
73
"Yields complex points along a line."
74
74
vec = p2 - p1
75
75
point = p1
@@ -96,19 +96,33 @@ def deep_transform(data, origin: complex, theta: float):
96
96
"bad type to deep_transform(): " + type (data ).__name__ ) from err
97
97
98
98
99
+ def fix_number (n : float ) -> str :
100
+ """If n is an integer, remove the trailing ".0".
101
+ Otherwise round it to 2 digits."""
102
+ if n .is_integer ():
103
+ return str (int (n ))
104
+ return str (round (n , 4 ))
105
+
106
+
99
107
class XMLClass :
100
108
def __getattr__ (self , tag ) -> Callable :
101
109
def mk_tag (* contents , ** attrs ) -> str :
102
110
out = f'<{ tag } '
103
111
for k , v in attrs .items ():
104
- if v is not False :
105
- out += f'{ k .removesuffix ("_" ).replace ("__" , "-" )} ="{ v } " '
112
+ if v is False :
113
+ continue
114
+ if isinstance (v , float ):
115
+ v = fix_number (v )
116
+ elif isinstance (v , str ):
117
+ v = re .sub (r"\d+(\.\d+)" , lambda m : fix_number (float (m .group ())), v )
118
+ out += f'{ k .removesuffix ("_" ).replace ("__" , "-" )} ="{ v } " '
106
119
out = out .rstrip () + '>' + '' .join (contents )
107
120
return out + f'</{ tag } >'
108
121
return mk_tag
109
122
110
123
111
124
XML = XMLClass ()
125
+ del XMLClass
112
126
113
127
114
128
def polylinegon (points : list [complex ], is_polygon : bool = False , ** options ):
@@ -224,6 +238,16 @@ def make_plus(
224
238
class_ = "plus" )
225
239
226
240
241
+ def arrow_points (p1 : complex , p2 : complex ) -> list [tuple [complex , complex ]]:
242
+ "Return points to make an arrow from p1 pointing to p2."
243
+ angle = phase (p2 - p1 )
244
+ tick_len = min (0.25 , abs (p2 - p1 ))
245
+ return [
246
+ (p2 , p1 ),
247
+ (p2 , p2 - rect (tick_len , angle + pi / 5 )),
248
+ (p2 , p2 - rect (tick_len , angle - pi / 5 ))]
249
+
250
+
227
251
def make_variable (
228
252
center : complex ,
229
253
theta : float ,
@@ -232,28 +256,33 @@ def make_variable(
232
256
"Draw a 'variable' arrow across the component."
233
257
if not is_variable :
234
258
return ""
235
- theta = theta % pi
236
- return bunch_o_lines (deep_transform ([
237
- (- .6 + .5j , .75 - .5j ),
238
- (.75 - .5j , .5 - .55j ),
239
- (.75 - .5j , .7 - .25j ),
240
- ], center , theta ), ** options )
241
-
242
-
243
- # def arrows(
244
- # center: complex,
245
- # theta: float,
246
- # out: bool,
247
- # **options):
248
- # """Draw arrows towards or away from the component
249
- # (i.e.light-emitting or light-dependent)."""
250
- # theta = theta % pi
251
- # if out:
252
- # return bunch_o_lines(deep_transform([
253
- # (-.5-.6j, .5-1.2j),
254
- # (.375-1.2j, .5-1.2j),
255
- # (.5-1.)
256
- # ], center, theta), **options)
259
+ return bunch_o_lines (
260
+ deep_transform (
261
+ arrow_points (- 1 , 1 ),
262
+ center ,
263
+ (theta % pi ) + pi / 4 ),
264
+ ** options )
265
+
266
+
267
+ def light_arrows (
268
+ center : complex ,
269
+ theta : float ,
270
+ out : bool ,
271
+ ** options ):
272
+ """Draw arrows towards or away from the component
273
+ (i.e. light-emitting or light-dependent)."""
274
+ a , b = 1j , .3 + .3j
275
+ if out :
276
+ a , b = b , a
277
+ return bunch_o_lines (
278
+ deep_transform (
279
+ arrow_points (a , b ),
280
+ center , theta - pi / 2 ),
281
+ ** options ) + bunch_o_lines (
282
+ deep_transform (
283
+ arrow_points (a - .5 , b - .5 ),
284
+ center , theta - pi / 2 ),
285
+ ** options )
257
286
258
287
259
288
def sort_counterclockwise (terminals : list [Terminal ]) -> list [Terminal ]:
0 commit comments