geometry: make `BoxedArray` a subclass of `Array`
[nit.git] / lib / geometry / boxes.nit
index 61af367..dc87cb5 100644 (file)
@@ -74,6 +74,17 @@ interface Boxed[N: Numeric]
                return self.left <= other.right and other.left <= self.right and
                        self.top >= other.bottom and other.top >= self.bottom
        end
+
+       # Create a bounding box that encloses the actual bounding box.
+       # `dist` is the distance between the inner boundaries and the outer boundaries.
+       # ~~~
+       # var p = new Point[Int](5,10)
+       # var b = p.padded(3)
+       # assert b.left == 2 and b.right == 8 and b.top == 13 and b.bottom == 7
+       # ~~~
+       fun padded(dist: N): Box[N] do return new Box[N].lrtb(left - dist, right + dist, top + dist, bottom - dist)
+
+       redef fun to_s do return "<{class_name} left: {left}, right: {right}, top: {top}, bottom: {bottom}>"
 end
 
 # A 2d bounded object and an implementation of `Boxed`
@@ -111,51 +122,32 @@ class Box[N: Numeric]
 
                assert left != null and right != null and top != null and bottom != null
 
-               self.left = left
-               self.right = right
-               self.top = top
-               self.bottom = bottom
+               init(left, right, top, bottom)
        end
 
        # Create a `Box` using left, right, bottom and top
        init lrbt(left, right, bottom, top: N)
        do
-               self.left = left
-               self.right = right
-               self.top = top
-               self.bottom = bottom
+               init(left, right, top, bottom)
        end
 
        # Create a `Box` using left, right, top and bottom
        init lrtb(left, right, top, bottom: N)
        do
-               self.left = left
-               self.right = right
-               self.top = top
-               self.bottom = bottom
+               init(left, right, top, bottom)
        end
 
        # Create a `Box` using left, bottom, width and height
        init lbwh(left, bottom, width, height: N)
        do
-               self.left = left
-               self.bottom = bottom
-
-               self.right = left + width
-               self.top = bottom + height
+               init(left, left + width, bottom + height, bottom)
        end
 
        # Create a `Box` using left, top, width and height
        init ltwh(left, top, width, height: N)
        do
-               self.left = left
-               self.top = top
-
-               self.right = left + width
-               self.bottom = top - height
+               init(left, left+width, top, top - height)
        end
-
-       redef fun to_s do return "<left: {left}, right: {right}, top: {top}, bottom: {bottom}>"
 end
 
 # An 3d abstract bounded object
@@ -201,6 +193,10 @@ interface Boxed3d[N: Numeric]
                return super and (not other isa Boxed3d[N] or
                        (self.back <= other.front and other.back <= self.front))
        end
+
+       redef fun padded(dist): Box3d[N] do return new Box3d[N].lrtbfb(left - dist, right + dist, top + dist, bottom - dist, front + dist, back - dist)
+
+       redef fun to_s do return "<{class_name} left: {left}, right: {right}, top: {top}, bottom: {bottom}, front: {front}, back: {back}>"
 end
 
 # A 3d bounded object and an implementation of Boxed
@@ -221,6 +217,8 @@ class Box3d[N: Numeric]
        #     assert box.right == 4 and box.top == 4
        init around(boxed: Boxed3d[N]...)
        do
+               super
+
                assert not boxed.is_empty
 
                var left: nullable N = null
@@ -282,8 +280,6 @@ class Box3d[N: Numeric]
                self.front = front
                self.back = front - depth
        end
-
-       redef fun to_s do return "<left: {left}, right: {right}, top: {top}, bottom: {bottom}, front: {front}, back: {back}"
 end
 
 redef class IPoint[N]
@@ -307,8 +303,8 @@ redef class ILine[N]
 
        redef fun left do return point_left.x
        redef fun right do return point_right.x
-       redef fun top do return point_left.y.min(point_right.y)
-       redef fun bottom do return point_left.y.max(point_right.y)
+       redef fun top do return point_left.y.max(point_right.y)
+       redef fun bottom do return point_left.y.min(point_right.y)
 end
 
 redef class ILine3d[N]
@@ -317,3 +313,28 @@ redef class ILine3d[N]
        redef fun front do return point_left.z.min(point_right.z)
        redef fun back do return point_left.z.max(point_right.z)
 end
+
+# Base for all data structures containing multiple Boxed Objects
+interface BoxedCollection[E: Boxed[Numeric]]
+       super SimpleCollection[E]
+
+       # returns all the items overlapping with `region`
+       fun items_overlapping(region :Boxed[Numeric]): SimpleCollection[E] is abstract
+end
+
+# `BoxedCollection` implemented by an array
+#
+# Linear performances for searching, but really fast creation and filling.
+class BoxedArray[E: Boxed[Numeric]]
+       super BoxedCollection[E]
+       super Array[E]
+
+       redef fun items_overlapping(item)
+       do
+               var arr = new Array[E]
+               for i in self do
+                       if i.intersects(item) then arr.add(i)
+               end
+               return arr
+       end
+end