2 USING: accessors arrays combinators combinators.short-circuit
3 fry kernel locals math math.intervals math.vectors multi-methods
5 FROM: multi-methods => GENERIC: ;
8 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10 ! Two dimensional world protocol
12 GENERIC: x ( obj -- x )
13 GENERIC: y ( obj -- y )
15 GENERIC: (x!) ( x obj -- )
16 GENERIC: (y!) ( y obj -- )
18 : x! ( obj x -- obj ) over (x!) ;
19 : y! ( obj y -- obj ) over (y!) ;
21 GENERIC: width ( obj -- width )
22 GENERIC: height ( obj -- height )
24 GENERIC: (width!) ( width obj -- )
25 GENERIC: (height!) ( height obj -- )
27 : width! ( obj width -- obj ) over (width!) ;
28 : height! ( obj height -- obj ) over (width!) ;
30 ! Predicates on relative placement
32 GENERIC: to-the-left-of? ( obj obj -- ? )
33 GENERIC: to-the-right-of? ( obj obj -- ? )
35 GENERIC: below? ( obj obj -- ? )
36 GENERIC: above? ( obj obj -- ? )
38 GENERIC: in-between-horizontally? ( obj obj -- ? )
40 GENERIC: horizontal-interval ( obj -- interval )
42 GENERIC: move-to ( obj obj -- )
44 GENERIC: move-by ( obj delta -- )
46 GENERIC: move-left-by ( obj obj -- )
47 GENERIC: move-right-by ( obj obj -- )
49 GENERIC: left ( obj -- left )
50 GENERIC: right ( obj -- right )
51 GENERIC: bottom ( obj -- bottom )
52 GENERIC: top ( obj -- top )
54 GENERIC: distance ( a b -- c )
56 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
58 ! Some of the above methods work on two element sequences.
59 ! A two element sequence may represent a point in space or describe
62 METHOD: x { sequence } first ;
63 METHOD: y { sequence } second ;
65 METHOD: (x!) { number sequence } set-first ;
66 METHOD: (y!) { number sequence } set-second ;
68 METHOD: width { sequence } first ;
69 METHOD: height { sequence } second ;
71 : changed-x ( seq quot -- ) over [ [ x ] dip call ] dip (x!) ; inline
72 : changed-y ( seq quot -- ) over [ [ y ] dip call ] dip (y!) ; inline
74 METHOD: move-to { sequence sequence } [ x x! ] [ y y! ] bi drop ;
75 METHOD: move-by { sequence sequence } dupd v+ [ x x! ] [ y y! ] bi drop ;
77 METHOD: move-left-by { sequence number } '[ _ - ] changed-x ;
78 METHOD: move-right-by { sequence number } '[ _ + ] changed-x ;
80 ! METHOD: move-left-by { sequence number } neg 0 2array move-by ;
81 ! METHOD: move-right-by { sequence number } 0 2array move-by ;
83 ! METHOD:: move-left-by { SEQ:sequence X:number -- )
84 ! SEQ { X 0 } { -1 0 } v* move-by ;
86 METHOD: distance { sequence sequence } v- norm ;
88 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
90 ! A class for objects with a position
94 METHOD: x { <pos> } pos>> first ;
95 METHOD: y { <pos> } pos>> second ;
97 METHOD: (x!) { number <pos> } pos>> set-first ;
98 METHOD: (y!) { number <pos> } pos>> set-second ;
100 METHOD: to-the-left-of? { <pos> number } [ x ] dip < ;
101 METHOD: to-the-right-of? { <pos> number } [ x ] dip > ;
103 METHOD: move-left-by { <pos> number } [ pos>> ] dip move-left-by ;
104 METHOD: move-right-by { <pos> number } [ pos>> ] dip move-right-by ;
106 METHOD: above? { <pos> number } [ y ] dip > ;
107 METHOD: below? { <pos> number } [ y ] dip < ;
109 METHOD: move-by { <pos> sequence } '[ _ v+ ] change-pos drop ;
111 METHOD: distance { <pos> <pos> } [ pos>> ] bi@ distance ;
113 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
115 ! A class for objects with velocity. It inherits from <pos>. Hey, if
116 ! it's moving it has a position right? Unless it's some alternate universe...
118 TUPLE: <vel> < <pos> vel ;
120 : moving-up? ( obj -- ? ) vel>> y 0 > ;
121 : moving-down? ( obj -- ? ) vel>> y 0 < ;
123 : step-size ( vel time -- dist ) [ vel>> ] dip v*n ;
124 : move-for ( vel time -- ) dupd step-size move-by ;
126 : reverse-horizontal-velocity ( vel -- ) vel>> [ x neg ] [ ] bi (x!) ;
128 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
130 ! The 'pos' slot indicates the lower left hand corner of the
131 ! rectangle. The 'dim' is holds the width and height.
133 TUPLE: <rectangle> < <pos> dim ;
135 METHOD: width { <rectangle> } dim>> first ;
136 METHOD: height { <rectangle> } dim>> second ;
138 METHOD: left { <rectangle> } x ;
139 METHOD: right { <rectangle> } [ x ] [ width ] bi + ;
140 METHOD: bottom { <rectangle> } y ;
141 METHOD: top { <rectangle> } [ y ] [ height ] bi + ;
143 : bottom-left ( rectangle -- pos ) pos>> ;
145 : center-x ( rectangle -- x ) [ left ] [ width 2 / ] bi + ;
146 : center-y ( rectangle -- y ) [ bottom ] [ height 2 / ] bi + ;
148 : center ( rectangle -- seq ) [ center-x ] [ center-y ] bi 2array ;
150 METHOD: to-the-left-of? { <pos> <rectangle> } [ x ] [ left ] bi* < ;
151 METHOD: to-the-right-of? { <pos> <rectangle> } [ x ] [ right ] bi* > ;
153 METHOD: below? { <pos> <rectangle> } [ y ] [ bottom ] bi* < ;
154 METHOD: above? { <pos> <rectangle> } [ y ] [ top ] bi* > ;
156 METHOD: horizontal-interval { <rectangle> }
157 [ left ] [ right ] bi [a,b] ;
159 METHOD: in-between-horizontally? { <pos> <rectangle> }
160 [ x ] [ horizontal-interval ] bi* interval-contains? ;
162 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
164 TUPLE: <extent> left right bottom top ;
166 METHOD: left { <extent> } left>> ;
167 METHOD: right { <extent> } right>> ;
168 METHOD: bottom { <extent> } bottom>> ;
169 METHOD: top { <extent> } top>> ;
171 METHOD: width { <extent> } [ right>> ] [ left>> ] bi - ;
172 METHOD: height { <extent> } [ top>> ] [ bottom>> ] bi - ;
174 ! METHOD: to-extent ( <rectangle> -- <extent> )
175 ! { [ left>> ] [ right>> ] [ bottom>> ] [ top>> ] } cleave <extent> boa ;
177 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
179 METHOD: to-the-left-of? { sequence <rectangle> } [ x ] [ left ] bi* < ;
180 METHOD: to-the-right-of? { sequence <rectangle> } [ x ] [ right ] bi* > ;
182 METHOD: below? { sequence <rectangle> } [ y ] [ bottom ] bi* < ;
183 METHOD: above? { sequence <rectangle> } [ y ] [ top ] bi* > ;
185 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
187 ! Some support for the' 'rect' class from math.geometry.rect'
189 ! METHOD: width ( rect -- width ) dim>> first ;
190 ! METHOD: height ( rect -- height ) dim>> second ;
192 ! METHOD: left ( rect -- left ) loc>> x
193 ! METHOD: right ( rect -- right ) [ loc>> x ] [ width ] bi + ;
195 ! METHOD: to-the-left-of? ( sequence rect -- ? ) [ x ] [ loc>> x ] bi* < ;
196 ! METHOD: to-the-right-of? ( sequence rect -- ? ) [ x ] [ loc>> x ] bi* > ;
198 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
200 :: wrap ( POINT RECT -- POINT )
202 { [ POINT RECT to-the-left-of? ] [ RECT right ] }
203 { [ POINT RECT to-the-right-of? ] [ RECT left ] }
204 { [ t ] [ POINT x ] }
209 { [ POINT RECT below? ] [ RECT top ] }
210 { [ POINT RECT above? ] [ RECT bottom ] }
211 { [ t ] [ POINT y ] }
217 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
219 GENERIC: within? ( a b -- ? )
221 METHOD: within? { <pos> <rectangle> }
223 [ left to-the-right-of? ]
224 [ right to-the-left-of? ]