def point(self, eh, ev=Edge.MinX): """ Get a ``Point`` at a given compass direction, chosen from * C * W * NW * N * NE * E * SE * S * SW """ ev = txt_to_edge(ev) pc = Edge.PairFromCompass(eh) if pc: return self.point(*pc) else: px = self.x py = self.y if eh == Edge.MaxX: px = self.x + self.w elif eh == Edge.CenterX: px = self.x + self.w / 2 if ev == Edge.MaxY: py = self.y + self.h if ev == Edge.CenterY: py = self.y + self.h / 2 return Point((px, py))
def subtract(self, amount, edge): """ The opposite of ``take``, this will remove and not return a piece of the given amount from the given edge. Let's say you have a 100px-wide square and you want to drop 10px from the right-hand side, you would do: ``Rect(100, 100).subtract(10, Edge.MaxX)``, which leaves you with ``Rect([0, 0, 90, 100])`` """ edge = txt_to_edge(edge) return Rect(subtract(self.rect(), amount, edge))
def align(b, rect, x=Edge.CenterX, y=Edge.CenterY): x = txt_to_edge(x) y = txt_to_edge(y) xoff = 0 if x != None: if x == Edge.CenterX: xoff = -b.x + rect.x + rect.w / 2 - b.w / 2 elif x == Edge.MinX: xoff = -(b.x - rect.x) elif x == Edge.MaxX: xoff = -b.x + rect.x + rect.w - b.w yoff = 0 if y != None: if y == Edge.CenterY: yoff = -b.y + rect.y + rect.h / 2 - b.h / 2 elif y == Edge.MaxY: yoff = (rect.y + rect.h) - (b.h + b.y) elif y == Edge.MinY: yoff = -(b.y - rect.y) #diff = rect.w - b.w return (xoff, yoff)
def expand(self, amount, edge): edges = None if edge == "NW": edges = ["mxy", "mnx"] elif edge == "NE": edges = ["mxy", "mxx"] elif edge == "SE": edges = ["mny", "mxx"] elif edge == "SW": edges = ["mny", "mnx"] if edges: return self.expand(amount, edges[0]).expand(amount, edges[1]) edge = txt_to_edge(edge) return Rect(expand(self.rect(), amount, edge))
def subdivide_with_leadings(self, count, leadings, edge, forcePixel=True): """ Same as `subdivide_with_leadings`, but inserts leading between each subdivision, indexing the size of the leading from a list of leadings """ edge = txt_to_edge(edge) leadings = leadings + [0] full = self.w if edge == Edge.MinX or edge == Edge.MaxX else self.h unit = (full - sum(leadings)) / count amounts = [ val for pair in zip([unit] * count, leadings) for val in pair ][:-1] return [ Rect(x) for x in subdivide( self.rect(), amounts, edge, forcePixel=forcePixel) ][::2]
def maxima(self, n, edge): e = txt_to_edge(edge) if e == Edge.MinX: return self.setmnx(n) elif e == Edge.MaxX: return self.setmxx(n) elif e == Edge.CenterX: return self.setmdx(n) elif e == Edge.MinY: return self.setmny(n) elif e == Edge.MaxY: return self.setmxy(n) elif e == Edge.CenterY: return self.setmdy(n) else: raise Exception("HELLO")
def subdivide(self, amount, edge): """ Like ``divide``, but here you specify the number of equal pieces you want (like columns or rows), and then what edge to start at, i.e. .. code:: python r = Rect(0, 0, 500, 100) r.subdivide(5, "mxx") => [Rect([400.0, 0, 100.0, 100]), Rect([300.0, 0, 100.0, 100]), Rect([200.0, 0, 100.0, 100]), Rect([100.0, 0, 100.0, 100]), Rect([0, 0, 100.0, 100])] will get you five 100-px wide rectangles, right-to-left (N.B. Does not support center edges, as that makes no sense) """ edge = txt_to_edge(edge) return [Rect(x) for x in subdivide(self.rect(), amount, edge)]
def divide(self, amount, edge, forcePixel=False): """ **Dividing** Derived from the behavior of the classic Cocoa function CGRectDivide, which takes a rectangle and breaks it into two pieces, based on a pixel amount and an edge. A quick example: assume you have a rectangle, ``r``, defined as such: ``r = Rect(0, 0, 300, 100)`` If you want to break that into a left-hand rectangle that’s 100 pixels wide and a right-hand rectangle that’s 200 pixels wide, you could either say: ``left, right = r.divide(100, "mnx")`` `or you could say` ``right, left = r.divide(200, "mxx")`` where ``mxx`` is the rightmost edge, and ``mnx`` is the leftmost edge. **Centering** A special use-case is if you want to break a rectangle into `three` rectangles, based on the center "edge", you can do something like this: ``left, center, right = r.divide(200, "mdx")`` This will result in three rectangles, always left-to-right, where left is 50px wide, then center is 200px wide, then right is also 50px wide — anything not in the center will be evenly distributed between left and right, or top-and-bottom in the case of a Y edge. """ edge = txt_to_edge(edge) if edge == Edge.CenterX or edge == Edge.CenterY: a, b, c = divide(self.rect(), amount, edge, forcePixel=forcePixel) return Rect(a), Rect(b), Rect(c) else: a, b = divide(self.rect(), amount, edge, forcePixel=forcePixel) return Rect(a), Rect(b)
def edge(self, edge): edge = txt_to_edge(edge) return Line(*edgepoints(self.rect(), edge))
def pieces(self, amount, edge): edge = txt_to_edge(edge) return [Rect(x) for x in pieces(self.rect(), amount, edge)]
def takeOpposite(self, amount, edge, forcePixel=False): edge = txt_to_edge(edge) return self.divide(amount, edge, forcePixel=forcePixel)[1]
def take(self, amount, edge, forcePixel=False): """ Like `divide`, but here it just returns the "first" rect from a divide call, not all the resulting pieces, i.e. you can "take" 200px from the center of a rectangle by doing this ``Rect(0, 0, 300, 100).take(200, "mdx")`` which will result in ``Rect([50, 0, 200, 100])`` """ edge = txt_to_edge(edge) return Rect(take(self.rect(), amount, edge, forcePixel=forcePixel))