tick separated from parter; experimental timeaxis code updated
[PyX/mjg.git] / pyx / bbox.py
blob0e552e6747dac41f6db5fbdad3adef659d7d7932
1 #!/usr/bin/env python
2 # -*- coding: ISO-8859-1 -*-
5 # Copyright (C) 2002-2004 Jörg Lehmann <joergl@users.sourceforge.net>
6 # Copyright (C) 2002-2004 André Wobst <wobsta@users.sourceforge.net>
8 # This file is part of PyX (http://pyx.sourceforge.net/).
10 # PyX is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
15 # PyX is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with PyX; if not, write to the Free Software
22 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 import math
25 import unit
28 # classes representing bounding boxes
31 class _bbox:
33 """class for bounding boxes
35 This variant requires points in the constructor, and is used for internal
36 purposes."""
38 def __init__(self, llx, lly, urx, ury):
39 self.llx = llx
40 self.lly = lly
41 self.urx = urx
42 self.ury = ury
44 def __add__(self, other):
45 """join two bboxes"""
46 return _bbox(min(self.llx, other.llx), min(self.lly, other.lly),
47 max(self.urx, other.urx), max(self.ury, other.ury))
49 def __iadd__(self, other):
50 """join two bboxes inplace"""
51 self.llx = min(self.llx, other.llx)
52 self.lly = min(self.lly, other.lly)
53 self.urx = max(self.urx, other.urx)
54 self.ury = max(self.ury, other.ury)
55 return self
57 def __mul__(self, other):
58 """return intersection of two bboxes"""
59 return _bbox(max(self.llx, other.llx), max(self.lly, other.lly),
60 min(self.urx, other.urx), min(self.ury, other.ury))
62 def __imul__(self, other):
63 """intersect two bboxes in place"""
64 self.llx = max(self.llx, other.llx)
65 self.lly = max(self.lly, other.lly)
66 self.urx = min(self.urx, other.urx)
67 self.ury = min(self.ury, other.ury)
68 return self
70 def __str__(self):
71 return "%s %s %s %s" % (self.llx, self.lly, self.urx, self.ury)
73 def outputPS(self, file):
74 file.write("%%%%BoundingBox: %d %d %d %d\n" %
75 (math.floor(self.llx), math.floor(self.lly),
76 math.ceil(self.urx), math.ceil(self.ury)))
77 file.write("%%%%HiResBoundingBox: %g %g %g %g\n" %
78 (self.llx, self.lly, self.urx, self.ury))
80 def intersects(self, other):
81 """check, if two bboxes intersect eachother"""
82 return not (self.llx > other.urx or
83 self.lly > other.ury or
84 self.urx < other.llx or
85 self.ury < other.lly)
87 def transform(self, trafo):
88 """transform bbox in place by trafo"""
89 # we have to transform all four corner points of the bbox
90 llx, lly = trafo._apply(self.llx, self.lly)
91 lrx, lry = trafo._apply(self.urx, self.lly)
92 urx, ury = trafo._apply(self.urx, self.ury)
93 ulx, uly = trafo._apply(self.llx, self.ury)
95 # Now, by sorting, we obtain the lower left and upper right corner
96 # of the new bounding box.
97 self.llx = min(llx, lrx, urx, ulx)
98 self.lly = min(lly, lry, ury, uly)
99 self.urx = max(llx, lrx, urx, ulx)
100 self.ury = max(lly, lry, ury, uly)
102 def transformed(self, trafo):
103 """return bbox transformed by trafo"""
104 # we have to transform all four corner points of the bbox
105 llx, lly = trafo._apply(self.llx, self.lly)
106 lrx, lry = trafo._apply(self.urx, self.lly)
107 urx, ury = trafo._apply(self.urx, self.ury)
108 ulx, uly = trafo._apply(self.llx, self.ury)
110 # Now, by sorting, we obtain the lower left and upper right corner
111 # of the new bounding box.
112 return _bbox(min(llx, lrx, urx, ulx), min(lly, lry, ury, uly),
113 max(llx, lrx, urx, ulx), max(lly, lry, ury, uly))
115 def enlarged(self, all=0, bottom=None, left=None, top=None, right=None):
116 """enlarge bbox in place
118 all is used, if bottom, left, top and/or right are not given.
121 _bottom = _left = _top = _right = unit.topt(unit.length(all, default_type="v"))
122 if bottom is not None:
123 _bottom = unit.topt(unit.length(bottom, default_type="v"))
124 if left is not None:
125 _left = unit.topt(unit.length(left, default_type="v"))
126 if top is not None:
127 _top = unit.topt(unit.length(top, default_type="v"))
128 if right is not None:
129 _right = unit.topt(unit.length(right, default_type="v"))
130 self.llx -= _left
131 self.lly -= _bottom
132 self.urx += _right
133 self.ury += top
135 def enlarged(self, all=0, bottom=None, left=None, top=None, right=None):
136 """return bbox enlarged
138 all is used, if bottom, left, top and/or right are not given.
141 _bottom = _left = _top = _right = unit.topt(unit.length(all, default_type="v"))
142 if bottom is not None:
143 _bottom = unit.topt(unit.length(bottom, default_type="v"))
144 if left is not None:
145 _left = unit.topt(unit.length(left, default_type="v"))
146 if top is not None:
147 _top = unit.topt(unit.length(top, default_type="v"))
148 if right is not None:
149 _right = unit.topt(unit.length(right, default_type="v"))
150 return _bbox(self.llx-_left, self.lly-_bottom, self.urx+_right, self.ury+_top)
152 def rect(self):
153 """return rectangle corresponding to bbox"""
154 import path
155 return path.rect_pt(self.llx, self.lly, self.urx-self.llx, self.ury-self.lly)
157 path = rect
159 def height(self):
160 """return height of bbox"""
161 return unit.t_pt(self.ury-self.lly)
163 def width(self):
164 """return width of bbox"""
165 return unit.t_pt(self.urx-self.llx)
167 def top(self):
168 """return top coordinate of bbox"""
169 return unit.t_pt(self.ury)
171 def bottom(self):
172 """return bottom coordinate of bbox"""
173 return unit.t_pt(self.lly)
175 def left(self):
176 """return left coordinate of bbox"""
177 return unit.t_pt(self.llx)
179 def right(self):
180 """return right coordinate of bbox"""
181 return unit.t_pt(self.urx)
184 class bbox(_bbox):
186 """class for bounding boxes"""
188 def __init__(self, llx, lly, urx, ury):
189 llx = unit.topt(llx)
190 lly = unit.topt(lly)
191 urx = unit.topt(urx)
192 ury = unit.topt(ury)
193 _bbox.__init__(self, llx, lly, urx, ury)