4 # Copyright (C) 2002, 2003 Jörg Lehmann <joergl@users.sourceforge.net>
5 # Copyright (C) 2002, 2003 André Wobst <wobsta@users.sourceforge.net>
7 # This file is part of PyX (http://pyx.sourceforge.net/).
9 # PyX is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
14 # PyX is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with PyX; if not, write to the Free Software
21 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 scale
= { 't':1, 'u':1, 'v':1, 'w':1 }
33 unit_pattern
= re
.compile(r
"""^\s*([+-]?\d*((\d\.?)|(\.?\d))\d*(E[+-]?\d+)?)
35 (\s+(([a-z][a-z]+)|[^t-w]))?\s*$""",
36 re
.IGNORECASE | re
.VERBOSE
)
47 def set(uscale
=None, vscale
=None, wscale
=None, defaultunit
=None):
56 _default_unit
= defaultunit
59 def _convert_to(l
, dest_unit
="m"):
60 if type(l
) in (types
.IntType
, types
.LongType
, types
.FloatType
):
61 return l
*_m
[_default_unit
]*scale
['u']/_m
[dest_unit
]
62 elif not isinstance(l
, length
):
63 l
=length(l
) # convert to length instance if necessary
65 return ( l
.length
['t'] +
66 l
.length
['u']*scale
['u'] +
67 l
.length
['v']*scale
['v'] +
68 l
.length
['w']*scale
['w'] ) / _m
[dest_unit
]
71 return _convert_to(l
, "m")
74 return _convert_to(l
, "cm")
77 return _convert_to(l
, "mm")
80 return _convert_to(l
, "inch")
83 return _convert_to(l
, "pt")
85 ################################################################################
86 # class for generic length
87 ################################################################################
92 Lengths can either be a initialized with a number or a string:
94 - a length specified as a number corresponds to the default values of
95 unit_type and unit_name
96 - a string has to consist of a maximum of three parts:
97 -quantifier: integer/float value
98 -unit_type: "t", "u", "v", or "w".
99 Optional, defaults to "u"
100 -unit_name: "m", "cm", "mm", "inch", "pt".
101 Optional, defaults to _default_unit
103 Internally all length are stored in units of m as a quadruple of the four
108 def __init__(self
, l
=1, default_type
="u", dunit
=None):
109 self
.length
= { 't': 0 , 'u': 0, 'v': 0, 'v':0, 'w':0 }
111 if isinstance(l
, length
):
112 self
.length
= l
.length
113 elif helper
.isstring(l
):
114 unit_match
= re
.match(unit_pattern
, l
)
115 if unit_match
is None:
116 assert 0, "expecting number or string of the form 'number [u|v|w] unit'"
118 self
.prefactor
= float(unit_match
.group(1))
119 self
.unit_type
= unit_match
.group(7) or default_type
120 self
.unit_name
= unit_match
.group(9) or dunit
or _default_unit
122 self
.length
[self
.unit_type
] = self
.prefactor
*_m
[self
.unit_name
]
123 elif helper
.isnumber(l
):
124 self
.length
[default_type
] = l
*_m
[dunit
or _default_unit
]
126 raise ( NotImplementedError,
127 "cannot convert given argument to length type" )
129 def __mul__(self
, factor
):
130 newlength
= self
.__class
__()
131 for unit_type
in newlength
.length
.keys():
132 newlength
.length
[unit_type
] = self
.length
[unit_type
]*factor
137 def __div__(self
, factor
):
138 newlength
= self
.__class
__()
139 for unit_type
in newlength
.length
.keys():
140 newlength
.length
[unit_type
] = self
.length
[unit_type
]/factor
143 def __add__(self
, l
):
144 # convert to length if necessary
146 newlength
= self
.__class
__()
147 for unit_type
in newlength
.length
.keys():
148 newlength
.length
[unit_type
] = self
.length
[unit_type
] + ll
.length
[unit_type
]
153 def __sub__(self
, l
):
154 # convert to length if necessary
156 newlength
= self
.__class
__()
157 for unit_type
in newlength
.length
.keys():
158 newlength
.length
[unit_type
] = self
.length
[unit_type
] - ll
.length
[unit_type
]
161 def __rsub__(self
, l
):
162 # convert to length if necessary
164 newlength
= self
.__class
__()
165 for unit_type
in newlength
.length
.keys():
166 newlength
.length
[unit_type
] = ll
.length
[unit_type
] - self
.length
[unit_type
]
170 newlength
= self
.__class
__()
171 for unit_type
in newlength
.length
.keys():
172 newlength
.length
[unit_type
] = -self
.length
[unit_type
]
176 return "(%(t)f t + %(u)f u + %(v)f v + %(w)f w) m" % self
.length
179 ################################################################################
180 # class for more specialized lengths
181 ################################################################################
183 # lengths with user units as default
186 def __init__(self
, l
=1, default_type
="u"):
187 length
.__init
__(self
, l
, default_type
=default_type
, dunit
="pt")
191 def __init__(self
, l
=1, default_type
="u"):
192 length
.__init
__(self
, l
, default_type
=default_type
, dunit
="m")
196 def __init__(self
, l
=1, default_type
="u"):
197 length
.__init
__(self
, l
, default_type
=default_type
, dunit
="mm")
201 def __init__(self
, l
=1, default_type
="u"):
202 length
.__init
__(self
, l
, default_type
=default_type
, dunit
="cm")
205 class u_inch(length
):
206 def __init__(self
, l
=1, default_type
="u"):
207 length
.__init
__(self
, l
, default_type
=default_type
, dunit
="inch")
209 # without further specification, length are user length. Hence we
210 # define the following aliases
221 def __init__(self
, l
=1):
222 length
.__init
__(self
, l
, default_type
="t", dunit
="pt")
226 def __init__(self
, l
=1):
227 length
.__init
__(self
, l
, default_type
="t", dunit
="m")
231 def __init__(self
, l
=1):
232 length
.__init
__(self
, l
, default_type
="t", dunit
="cm")
236 def __init__(self
, l
=1):
237 length
.__init
__(self
, l
, default_type
="t", dunit
="mm")
240 class t_inch(length
):
241 def __init__(self
, l
=1):
242 length
.__init
__(self
, l
, default_type
="t", dunit
="inch")
247 def __init__(self
, l
=1):
248 length
.__init
__(self
, l
, default_type
="v", dunit
="pt")
252 def __init__(self
, l
=1):
253 length
.__init
__(self
, l
, default_type
="v", dunit
="m")
257 def __init__(self
, l
=1):
258 length
.__init
__(self
, l
, default_type
="v", dunit
="cm")
262 def __init__(self
, l
=1):
263 length
.__init
__(self
, l
, default_type
="v", dunit
="mm")
266 class v_inch(length
):
267 def __init__(self
, l
=1):
268 length
.__init
__(self
, l
, default_type
="v", dunit
="inch")
273 def __init__(self
, l
=1):
274 length
.__init
__(self
, l
, default_type
="w", dunit
="pt")
278 def __init__(self
, l
=1):
279 length
.__init
__(self
, l
, default_type
="w", dunit
="m")
283 def __init__(self
, l
=1):
284 length
.__init
__(self
, l
, default_type
="w", dunit
="cm")
288 def __init__(self
, l
=1):
289 length
.__init
__(self
, l
, default_type
="w", dunit
="mm")
292 class w_inch(length
):
293 def __init__(self
, l
=1):
294 length
.__init
__(self
, l
, default_type
="w", dunit
="inch")