util.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. var min = Math.min;
  2. var max = Math.max;
  3. var abs = Math.abs;
  4. var floor = Math.floor;
  5. var ceil = Math.ceil;
  6. var sin = Math.sin;
  7. var cos = Math.cos;
  8. var tan = Math.tan;
  9. var asin = Math.asin;
  10. var acos = Math.acos;
  11. var atan = Math.atan;
  12. var atan2 = Math.atan2;
  13. var PI = Math.PI;
  14. var PI2 = Math.PI * 2;
  15. var PI3_2 = (3*Math.PI) / 2;
  16. var PI_2 = Math.PI / 2;
  17. var PI_4 = Math.PI / 4;
  18. function rand(min, max) {
  19. return Math.floor(Math.random() * (max - min + 1)) + min;
  20. }
  21. function pt(x,y) {
  22. return {x: x, y: y};
  23. }
  24. function ptc(p) {
  25. return {x: p.x, y: p.y};
  26. }
  27. function rect(top, bottom, left, right) {
  28. return {t: top, b: bottom, l: left, r: right};
  29. }
  30. function rectc(r) {
  31. return {t: r.t, b: r.b, l: r.l, r: r.r};
  32. }
  33. function translateRect(r, p) {
  34. return {
  35. t: r.t + p.y,
  36. b: r.b + p.y,
  37. l: r.l + p.x,
  38. r: r.r + p.x
  39. }
  40. }
  41. function intersectRect(a,b) {
  42. var q = a.l > b.r,
  43. w = a.r < b.l,
  44. e = a.t < b.b,
  45. r = a.b > b.t;
  46. return !(q || w || e || r);
  47. }
  48. function vecLen(x,y) {
  49. return Math.sqrt(x*x + y*y);
  50. }
  51. function norm(x,y) {
  52. var l = 1 / Math.sqrt(x*x + y*y);
  53. return {
  54. x:x * l,
  55. y:y * l
  56. }
  57. }
  58. function ptNorm(pt) {
  59. var l = 1 / Math.sqrt(pt.x*pt.x + pt.y*pt.y);
  60. return {
  61. x:pt.x * l,
  62. y:pt.y * l
  63. }
  64. }
  65. function vDist(a,b) {
  66. var x = a.x - b.x;
  67. var y = a.y - b.y;
  68. return Math.sqrt(x*x + y*y);
  69. }
  70. function circleIntersect(a, ar, b, br) {
  71. var x = a.x - b.x;
  72. var y = a.y - b.y;
  73. return x*x + y*y <= (ar+br) * (ar+br);
  74. }
  75. function exec(fn) { return fn() };
  76. function inverse(obj) {
  77. var inv = {};
  78. for(var k in obj) {
  79. if(obj.hasOwnProperty(k)) {
  80. inv[obj[k]] = k;
  81. }
  82. }
  83. return inv;
  84. }
  85. var fsm = function(initial) {
  86. this.table = {};
  87. this.state = initial;
  88. this.enter = {};
  89. this.leave = {};
  90. }
  91. fsm.prototype.addState = function(s) {
  92. this.table[s] = {};
  93. this.enter[s] = [];
  94. this.leave[s] = [];
  95. }
  96. fsm.prototype.addEdge = function(from, to, on) {
  97. this.table[from][on] = to;
  98. }
  99. fsm.prototype.send = function(action) {
  100. var t = this.table[this.state];
  101. if(!t) return false;
  102. var to = t[action];
  103. if(!t) return false;
  104. this.enter[to].map(exec);
  105. this.leave[this.state].map(exec);
  106. this.state = to;
  107. return true;
  108. }
  109. fsm.prototype.enter = function(state, fn) {
  110. this.enter[state].push(fn);
  111. }
  112. fsm.prototype.leave = function(state, fn) {
  113. this.leave[state].push(fn);
  114. }
  115. var hfsm = function(initial) {
  116. this.table = {};
  117. this.membership = {};
  118. this.state = initial;
  119. this.enter = {};
  120. this.leave = {};
  121. }
  122. hfsm.prototype.addState = function(s, ss) {
  123. this.table[s] = {};
  124. this.enter[s] = [];
  125. this.leave[s] = [];
  126. this.membership[s] = ss || null;
  127. }
  128. hfsm.prototype.addSuperState = function(ss) {
  129. this.membership[ss] = {};
  130. this.enter[ss] = [];
  131. this.leave[ss] = [];
  132. }
  133. hfsm.prototype.addEdge = function(from, to, on) {
  134. this.table[from][on] = to;
  135. }
  136. hfsm.prototype.send = function(action) {
  137. var t = this.table[this.state];
  138. if(!t) return false;
  139. var to = t[action];
  140. if(!t) return false;
  141. this.leave[this.state].map(exec);
  142. this.enter[to].map(exec);
  143. var nss = this.getSS(to);
  144. var oss = this.getSS(this.state);
  145. if(nss != oss) { // need to check null == null logic here
  146. this.leave[oss].map(exec);
  147. this.enter[nss].map(exec);
  148. }
  149. this.state = to;
  150. return true;
  151. }
  152. hfsm.prototype.getSS = function(state) {
  153. return this.membership[state];
  154. }
  155. hfsm.prototype.enter = function(state, fn) {
  156. this.enter[state].push(fn);
  157. }
  158. hfsm.prototype.leave = function(state, fn) {
  159. this.leave[state].push(fn);
  160. }