common.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // wrapped by build app
  2. define("dojox/drawing/util/common", ["dijit","dojo","dojox","dojo/require!dojox/math/round"], function(dijit,dojo,dojox){
  3. dojo.provide("dojox.drawing.util.common");
  4. dojo.require("dojox.math.round");
  5. (function(){
  6. var uidMap = {};
  7. var start = 0;
  8. dojox.drawing.util.common = {
  9. // summary:
  10. // A collection of common methods used for DojoX Drawing.
  11. // This singleton is accessible in most Drawing classes
  12. // as this.util
  13. //
  14. // NOTE:
  15. // A lot of functions use a EventObject
  16. // as an argument. An attempt was made to accept
  17. // either that object or a list of numbers. That wasn't
  18. // finished (it didn't work well in all cases) but is
  19. // likely to happen in the future.
  20. // In cases where you are not sending a Mouse object,
  21. // form your argument like so:
  22. // var obj = {
  23. // start:{
  24. // x:Number, // start x
  25. // y:Number // start y
  26. // },
  27. // x: Number, // end x
  28. // y:Number // end y
  29. // }
  30. //
  31. //
  32. radToDeg: function(/*Numer*/n){
  33. // summary:
  34. // Convert the passed number to degrees.
  35. return (n*180)/Math.PI; // Number
  36. },
  37. degToRad: function(/*Numer*/n){
  38. // summary:
  39. // Convert the passed number to radians.
  40. return (n*Math.PI)/180; // Number
  41. },
  42. angle: function(/*EventObject*/obj, /* ? Float */snap){
  43. // summary:
  44. // Return angle based on mouse object
  45. // arguments:
  46. // obj: EventObject
  47. // Manager.Mouse event.
  48. // snap: Float
  49. // Returns nearest angle within snap limits
  50. //
  51. //obj = this.argsToObj.apply(this, arguments);
  52. if(snap){
  53. snap = snap/180;
  54. var radians = this.radians(obj),
  55. seg = Math.PI * snap,
  56. rnd = dojox.math.round(radians/seg),
  57. new_radian = rnd*seg;
  58. return dojox.math.round(this.radToDeg(new_radian)); // Whole Number
  59. }else{
  60. return this.radToDeg(this.radians(obj)); // Float
  61. }
  62. },
  63. oppAngle: function(/*Angle*/ang){
  64. (ang+=180) > 360 ? ang = ang - 360 : ang;
  65. return ang;
  66. },
  67. radians: function(/*EventObject*/o){
  68. // summary:
  69. // Return the radians derived from the coordinates
  70. // in the Mouse object.
  71. //
  72. //var o = this.argsToObj.apply(this, arguments);
  73. return Math.atan2(o.start.y-o.y,o.x-o.start.x);
  74. },
  75. length: function(/*EventObject*/o){
  76. // summary:
  77. // Return the length derived from the coordinates
  78. // in the Mouse object.
  79. //
  80. return Math.sqrt(Math.pow(o.start.x-o.x, 2)+Math.pow(o.start.y-o.y, 2));
  81. },
  82. lineSub: function(/*Number*/x1, /*Number*/y1, /*Number*/x2, /*Number*/y2, /*Number*/amt){
  83. // summary:
  84. // Subtract an amount from a line
  85. // description:
  86. // x1,y1,x2,y2 represents the Line. 'amt' represents the amount
  87. // to subtract from it.
  88. //
  89. var len = this.distance(this.argsToObj.apply(this, arguments));
  90. len = len < amt ? amt : len;
  91. var pc = (len-amt)/len;
  92. var x = x1 - (x1-x2) * pc;
  93. var y = y1 - (y1-y2) * pc;
  94. return {x:x, y:y}; // Object
  95. },
  96. argsToObj: function(){
  97. // summary:
  98. // Attempts to determine in a Mouse Object
  99. // was passed or indiviual numbers. Returns
  100. // an object.
  101. //
  102. var a = arguments;
  103. if(a.length < 4){ return a[0]; }
  104. return {
  105. start:{
  106. x:a[0],
  107. y:a[1]
  108. },
  109. x:a[2],
  110. y:a[3]//,
  111. //snap:a[4]
  112. }; // Object
  113. },
  114. distance: function(/*EventObject or x1,y1,x2,y2*/){
  115. // summary:
  116. // Return the length derived from the coordinates
  117. // in the Mouse object. Different from util.length
  118. // in that this always returns an absolute value.
  119. //
  120. var o = this.argsToObj.apply(this, arguments);
  121. return Math.abs(Math.sqrt(Math.pow(o.start.x-o.x, 2)+Math.pow(o.start.y-o.y, 2))); // Number
  122. },
  123. slope:function(/*Object*/p1, /*Object*/p2){
  124. // summary:
  125. // Given two poits of a line, returns the slope.
  126. if(!(p1.x-p2.x)){ return 0; }
  127. return ((p1.y-p2.y)/(p1.x-p2.x)); // Number
  128. },
  129. pointOnCircle: function(/*Number*/cx, /*Number*/cy, /*Number*/radius, /*Number*/angle){
  130. // summary:
  131. // A *very* helpful method. If you know the center
  132. // (or starting) point, length and angle, find the
  133. // x,y point at the end of that line.
  134. //
  135. var radians = angle * Math.PI / 180.0;
  136. var x = radius * Math.cos(radians);
  137. var y = radius * Math.sin(radians);
  138. return {
  139. x:cx+x,
  140. y:cy-y
  141. }; // Object
  142. },
  143. constrainAngle: function(/*EventObject*/obj, /*Number*/min, /*Number*/max){
  144. // summary:
  145. // Ensures the angle in the Mouse Object is within the
  146. // min and max limits. If not one of those limits is used.
  147. // Returns an x,y point for the angle used.
  148. //
  149. var angle = this.angle(obj);
  150. if(angle >= min && angle <= max){
  151. return obj; // Object
  152. }
  153. var radius = this.length(obj);
  154. var new_angle = angle > max ? max : min - angle < 100 ? min : max;
  155. return this.pointOnCircle(obj.start.x,obj.start.y,radius, new_angle); // Object
  156. },
  157. snapAngle: function(/*EventObject*/obj, /*Float*/ca){
  158. // summary:
  159. // Snaps a line to the nearest angle
  160. // obj: Mouse object (see dojox.drawing.Mouse)
  161. // ca: Fractional amount to snap to
  162. // A decimal number fraction of a half circle
  163. // .5 would snap to 90 degrees
  164. // .25 would snap to 45 degrees
  165. // .125 would snap to 22.5 degrees, etc.
  166. //
  167. var radians = this.radians(obj),
  168. radius = this.length(obj),
  169. seg = Math.PI * ca,
  170. rnd = Math.round(radians/seg),
  171. new_radian = rnd*seg,
  172. new_angle = this.radToDeg(new_radian),
  173. pt = this.pointOnCircle(obj.start.x,obj.start.y,radius,new_angle);
  174. return pt; // Object
  175. },
  176. // helpers
  177. idSetStart: function(num){
  178. start=num;
  179. },
  180. uid: function(/* ? String */str){
  181. // summary:
  182. // Creates a unique ID.
  183. // arguments:
  184. // str: String
  185. // If provided, kept in a map, incremented
  186. // and used in the id. Otherwise 'shape' is used.
  187. //
  188. str = str || "shape";
  189. uidMap[str] = uidMap[str]===undefined ? start : uidMap[str] + 1;
  190. return str + uidMap[str]; // String
  191. },
  192. abbr: function(type){
  193. // summary:
  194. // Converts a namespace (typically a tool or a stencil) into
  195. // an abbreviation
  196. return type.substring(type.lastIndexOf(".")+1).charAt(0).toLowerCase()
  197. + type.substring(type.lastIndexOf(".")+2);
  198. },
  199. mixin: function(o1, o2){
  200. // TODO: make faster
  201. //return dojo.mixin(dojo.clone(o1), dojo.clone(o2));
  202. },
  203. objects:{}, //private?
  204. register: function(/*Object*/obj){
  205. // summary:
  206. // Since util is the only Singleton in Drawing (besides
  207. // keys) it is used to help connect the Drawing object
  208. // the Toolbar. Since multiple drawings can be on one
  209. // page, this function serves a little more use than
  210. // on first apearance.
  211. this.objects[obj.id] = obj;
  212. },
  213. byId: function(/*String*/id){
  214. // summary:
  215. // Get an object that was registered with util.register
  216. //
  217. return this.objects[id];
  218. },
  219. attr: function(/* Object */ elem, /* property */ prop, /* ? value */ value, squelchErrors){
  220. // summary:
  221. // Helper function to attach attributes to SVG and VML raw nodes.
  222. //
  223. if(!elem){ return false; }
  224. try{
  225. // util is a crappy check, but we need to tell the diff
  226. // between a Drawing shape and a GFX shape
  227. if(elem.shape && elem.util){
  228. elem = elem.shape;
  229. }
  230. if(!value && prop=="id" && elem.target){
  231. var n = elem.target;
  232. while(!dojo.attr(n, "id")){
  233. n = n.parentNode;
  234. }
  235. return dojo.attr(n, "id");
  236. }
  237. if(elem.rawNode || elem.target){
  238. var args = Array.prototype.slice.call(arguments);
  239. args[0] = elem.rawNode || elem.target;
  240. return dojo.attr.apply(dojo, args);
  241. }
  242. return dojo.attr(elem, "id");
  243. }catch(e){
  244. if(!squelchErrors){
  245. // For debugging only. These errors actually cause errors in IE's console
  246. //console.error("BAD ATTR: prop:", prop, "el:", elem)
  247. //console.error(e)
  248. //console.trace();
  249. }
  250. return false;
  251. }
  252. }
  253. };
  254. })();
  255. });