2 # -*- coding: ISO-8859-1 -*-
5 # Copyright (C) 2002-2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
28 # classes representing bounding boxes
33 """class for bounding boxes
35 This variant requires points in the constructor, and is used for internal
38 def __init__(self
, llx_pt
, lly_pt
, urx_pt
, ury_pt
):
44 def __add__(self
, other
):
46 return bbox_pt(min(self
.llx_pt
, other
.llx_pt
), min(self
.lly_pt
, other
.lly_pt
),
47 max(self
.urx_pt
, other
.urx_pt
), max(self
.ury_pt
, other
.ury_pt
))
49 def __iadd__(self
, other
):
50 """join two bboxes inplace"""
51 self
.llx_pt
= min(self
.llx_pt
, other
.llx_pt
)
52 self
.lly_pt
= min(self
.lly_pt
, other
.lly_pt
)
53 self
.urx_pt
= max(self
.urx_pt
, other
.urx_pt
)
54 self
.ury_pt
= max(self
.ury_pt
, other
.ury_pt
)
57 def __mul__(self
, other
):
58 """return intersection of two bboxes"""
59 return bbox_pt(max(self
.llx_pt
, other
.llx_pt
), max(self
.lly_pt
, other
.lly_pt
),
60 min(self
.urx_pt
, other
.urx_pt
), min(self
.ury_pt
, other
.ury_pt
))
62 def __imul__(self
, other
):
63 """intersect two bboxes in place"""
64 self
.llx_pt
= max(self
.llx_pt
, other
.llx_pt
)
65 self
.lly_pt
= max(self
.lly_pt
, other
.lly_pt
)
66 self
.urx_pt
= min(self
.urx_pt
, other
.urx_pt
)
67 self
.ury_pt
= min(self
.ury_pt
, other
.ury_pt
)
71 return bbox_pt(self
.llx_pt
, self
.lly_pt
, self
.urx_pt
, self
.ury_pt
)
73 def lowrestuple_pt(self
):
74 return (math
.floor(self
.llx_pt
), math
.floor(self
.lly_pt
),
75 math
.ceil(self
.urx_pt
), math
.ceil(self
.ury_pt
))
77 def highrestuple_pt(self
):
78 return (self
.llx_pt
, self
.lly_pt
, self
.urx_pt
, self
.ury_pt
)
80 def intersects(self
, other
):
81 """check, if two bboxes intersect eachother"""
82 return not (self
.llx_pt
> other
.urx_pt
or
83 self
.lly_pt
> other
.ury_pt
or
84 self
.urx_pt
< other
.llx_pt
or
85 self
.ury_pt
< other
.lly_pt
)
87 def includepoint_pt(self
, x_pt
, y_pt
):
88 self
.llx_pt
= min(self
.llx_pt
, x_pt
)
89 self
.lly_pt
= min(self
.lly_pt
, y_pt
)
90 self
.urx_pt
= max(self
.urx_pt
, x_pt
)
91 self
.ury_pt
= max(self
.ury_pt
, y_pt
)
93 def transform(self
, trafo
):
94 """transform bbox in place by trafo"""
95 # we have to transform all four corner points of the bbox
96 llx_pt
, lly_pt
= trafo
.apply_pt(self
.llx_pt
, self
.lly_pt
)
97 lrx_pt
, lry_pt
= trafo
.apply_pt(self
.urx_pt
, self
.lly_pt
)
98 urx_pt
, ury_pt
= trafo
.apply_pt(self
.urx_pt
, self
.ury_pt
)
99 ulx_pt
, uly_pt
= trafo
.apply_pt(self
.llx_pt
, self
.ury_pt
)
101 # Now, by sorting, we obtain the lower left and upper right corner
102 # of the new bounding box.
103 self
.llx_pt
= min(llx_pt
, lrx_pt
, urx_pt
, ulx_pt
)
104 self
.lly_pt
= min(lly_pt
, lry_pt
, ury_pt
, uly_pt
)
105 self
.urx_pt
= max(llx_pt
, lrx_pt
, urx_pt
, ulx_pt
)
106 self
.ury_pt
= max(lly_pt
, lry_pt
, ury_pt
, uly_pt
)
108 def transformed(self
, trafo
):
109 """return bbox transformed by trafo"""
110 # we have to transform all four corner points of the bbox
111 llx_pt
, lly_pt
= trafo
.apply_pt(self
.llx_pt
, self
.lly_pt
)
112 lrx_pt
, lry_pt
= trafo
.apply_pt(self
.urx_pt
, self
.lly_pt
)
113 urx_pt
, ury_pt
= trafo
.apply_pt(self
.urx_pt
, self
.ury_pt
)
114 ulx_pt
, uly_pt
= trafo
.apply_pt(self
.llx_pt
, self
.ury_pt
)
116 # Now, by sorting, we obtain the lower left and upper right corner
117 # of the new bounding box.
118 return bbox_pt(min(llx_pt
, lrx_pt
, urx_pt
, ulx_pt
), min(lly_pt
, lry_pt
, ury_pt
, uly_pt
),
119 max(llx_pt
, lrx_pt
, urx_pt
, ulx_pt
), max(lly_pt
, lry_pt
, ury_pt
, uly_pt
))
121 def enlarge_pt(self
, all_pt
=0, bottom_pt
=None, left_pt
=None, top_pt
=None, right_pt
=None):
122 """enlarge bbox in place by the given amounts in pts
124 all is used, if bottom, left, top and/or right are not given.
127 if bottom_pt
is None:
135 self
.llx_pt
-= left_pt
136 self
.lly_pt
-= bottom_pt
137 self
.urx_pt
+= right_pt
138 self
.ury_pt
+= top_pt
140 def enlarged_pt(self
, all_pt
=0, bottom_pt
=None, left_pt
=None, top_pt
=None, right_pt
=None):
141 """return bbox enlarged by the given amounts in pts
143 all is used, if bottom, left, top and/or right are not given.
146 if bottom_pt
is None:
154 return bbox_pt(self
.llx_pt
-left_pt
, self
.lly_pt
-bottom_pt
, self
.urx_pt
+right_pt
, self
.ury_pt
+top_pt
)
156 def enlarge(self
, all
=0, bottom
=None, left
=None, top
=None, right
=None):
157 """enlarge bbox in place
159 all is used, if bottom, left, top and/or right are not given.
162 bottom_pt
= left_pt
= top_pt
= right_pt
= unit
.topt(all
)
163 if bottom
is not None:
164 bottom_pt
= unit
.topt(bottom
)
166 left_pt
= unit
.topt(left
)
168 top_pt
= unit
.topt(top
)
169 if right
is not None:
170 right_pt
= unit
.topt(right
)
171 self
.llx_pt
-= left_pt
172 self
.lly_pt
-= bottom_pt
173 self
.urx_pt
+= right_pt
174 self
.ury_pt
+= top_pt
176 def enlarged(self
, all
=0, bottom
=None, left
=None, top
=None, right
=None):
177 """return bbox enlarged
179 all is used, if bottom, left, top and/or right are not given.
182 bottom_pt
= left_pt
= top_pt
= right_pt
= unit
.topt(all
)
183 if bottom
is not None:
184 bottom_pt
= unit
.topt(bottom
)
186 left_pt
= unit
.topt(left
)
188 top_pt
= unit
.topt(top
)
189 if right
is not None:
190 right_pt
= unit
.topt(right
)
191 return bbox_pt(self
.llx_pt
-left_pt
, self
.lly_pt
-bottom_pt
, self
.urx_pt
+right_pt
, self
.ury_pt
+top_pt
)
194 """return rectangle corresponding to bbox"""
196 return path
.rect_pt(self
.llx_pt
, self
.lly_pt
, self
.urx_pt
-self
.llx_pt
, self
.ury_pt
-self
.lly_pt
)
201 """return height of bbox in pts"""
202 return self
.ury_pt
-self
.lly_pt
205 """return width of bbox in pts"""
206 return self
.urx_pt
-self
.llx_pt
209 """return top coordinate of bbox in pts"""
213 """return bottom coordinate of bbox in pts"""
217 """return left coordinate of bbox in pts"""
221 """return right coordinate of bbox in pts"""
225 """return coordinates of the center of the bbox in pts"""
226 return 0.5 * (self
.llx_pt
+self
.urx_pt
), 0.5 * (self
.lly_pt
+self
.ury_pt
)
229 """return height of bbox"""
230 return self
.height_pt() * unit
.t_pt
233 """return width of bbox"""
234 return self
.width_pt() * unit
.t_pt
237 """return top coordinate of bbox"""
238 return self
.ury_pt
* unit
.t_pt
241 """return bottom coordinate of bbox"""
242 return self
.lly_pt
* unit
.t_pt
245 """return left coordinate of bbox"""
246 return self
.llx_pt
* unit
.t_pt
249 """return right coordinate of bbox"""
250 return self
.urx_pt
* unit
.t_pt
253 """return coordinates of the center of the bbox"""
254 centerx_pt
, centery_pt
= self
.center_pt()
255 return centerx_pt
* unit
.t_pt
, centery_pt
* unit
.t_pt
260 """class for bounding boxes"""
262 def __init__(self
, llx_pt
, lly_pt
, urx_pt
, ury_pt
):
263 llx_pt
= unit
.topt(llx_pt
)
264 lly_pt
= unit
.topt(lly_pt
)
265 urx_pt
= unit
.topt(urx_pt
)
266 ury_pt
= unit
.topt(ury_pt
)
267 bbox_pt
.__init
__(self
, llx_pt
, lly_pt
, urx_pt
, ury_pt
)