You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
7.5 KiB
277 lines
7.5 KiB
define(["dojo", "dojox/math/round"], function(dojo, round){ |
|
|
|
var uidMap = {}; |
|
var start = 0; |
|
//dojox.drawing.util.common = |
|
return { |
|
// summary: |
|
// A collection of common methods used for DojoX Drawing. |
|
// This singleton is accessible in most Drawing classes |
|
// as this.util |
|
|
|
// NOTE: |
|
// A lot of functions use a EventObject |
|
// as an argument. An attempt was made to accept |
|
// either that object or a list of numbers. That wasn't |
|
// finished (it didn't work well in all cases) but is |
|
// likely to happen in the future. |
|
// In cases where you are not sending a Mouse object, |
|
// form your argument like so: |
|
// var obj = { |
|
// start:{ |
|
// x:Number, // start x |
|
// y:Number // start y |
|
// }, |
|
// x: Number, // end x |
|
// y:Number // end y |
|
// } |
|
|
|
|
|
radToDeg: function(/*Number*/n){ |
|
// summary: |
|
// Convert the passed number to degrees. |
|
return (n*180)/Math.PI; // Number |
|
}, |
|
|
|
degToRad: function(/*Number*/n){ |
|
// summary: |
|
// Convert the passed number to radians. |
|
return (n*Math.PI)/180; // Number |
|
}, |
|
|
|
angle: function(/*EventObject*/obj, /*Float?*/snap){ |
|
// summary: |
|
// Return angle based on mouse object |
|
// obj: |
|
// Manager.Mouse event. |
|
// snap: |
|
// Returns nearest angle within snap limits |
|
|
|
//obj = this.argsToObj.apply(this, arguments); |
|
if(snap){ |
|
snap = snap/180; |
|
var radians = this.radians(obj), |
|
seg = Math.PI * snap, |
|
rnd = round(radians/seg), |
|
new_radian = rnd*seg; |
|
return round(this.radToDeg(new_radian)); // Whole Number |
|
|
|
}else{ |
|
return this.radToDeg(this.radians(obj)); // Float |
|
} |
|
}, |
|
|
|
oppAngle: function(/*Angle*/ang){ |
|
(ang+=180) > 360 ? ang = ang - 360 : ang; |
|
return ang; |
|
}, |
|
|
|
radians: function(/*EventObject*/o){ |
|
// summary: |
|
// Return the radians derived from the coordinates |
|
// in the Mouse object. |
|
|
|
//var o = this.argsToObj.apply(this, arguments); |
|
return Math.atan2(o.start.y-o.y,o.x-o.start.x); |
|
}, |
|
|
|
length: function(/*EventObject*/o){ |
|
// summary: |
|
// Return the length derived from the coordinates |
|
// in the Mouse object. |
|
|
|
return Math.sqrt(Math.pow(o.start.x-o.x, 2)+Math.pow(o.start.y-o.y, 2)); |
|
}, |
|
|
|
lineSub: function(/*Number*/x1, /*Number*/y1, /*Number*/x2, /*Number*/y2, /*Number*/amt){ |
|
// summary: |
|
// Subtract an amount from a line |
|
// description: |
|
// x1,y1,x2,y2 represents the Line. 'amt' represents the amount |
|
// to subtract from it. |
|
|
|
var len = this.distance(this.argsToObj.apply(this, arguments)); |
|
len = len < amt ? amt : len; |
|
var pc = (len-amt)/len; |
|
var x = x1 - (x1-x2) * pc; |
|
var y = y1 - (y1-y2) * pc; |
|
return {x:x, y:y}; // Object |
|
}, |
|
|
|
argsToObj: function(){ |
|
// summary: |
|
// Attempts to determine in a Mouse Object |
|
// was passed or indiviual numbers. Returns |
|
// an object. |
|
|
|
var a = arguments; |
|
if(a.length < 4){ return a[0]; } |
|
return { |
|
start:{ |
|
x:a[0], |
|
y:a[1] |
|
}, |
|
x:a[2], |
|
y:a[3]//, |
|
//snap:a[4] |
|
}; // Object |
|
}, |
|
|
|
distance: function(/*EventObject or x1,y1,x2,y2*/){ |
|
// summary: |
|
// Return the length derived from the coordinates |
|
// in the Mouse object. Different from util.length |
|
// in that this always returns an absolute value. |
|
|
|
var o = this.argsToObj.apply(this, arguments); |
|
return Math.abs(Math.sqrt(Math.pow(o.start.x-o.x, 2)+Math.pow(o.start.y-o.y, 2))); // Number |
|
}, |
|
|
|
slope:function(/*Object*/p1, /*Object*/p2){ |
|
// summary: |
|
// Given two poits of a line, returns the slope. |
|
if(!(p1.x-p2.x)){ return 0; } |
|
return ((p1.y-p2.y)/(p1.x-p2.x)); // Number |
|
}, |
|
|
|
pointOnCircle: function(/*Number*/cx, /*Number*/cy, /*Number*/radius, /*Number*/angle){ |
|
// summary: |
|
// A *very* helpful method. If you know the center |
|
// (or starting) point, length and angle, find the |
|
// x,y point at the end of that line. |
|
|
|
var radians = angle * Math.PI / 180.0; |
|
var x = radius * Math.cos(radians); |
|
var y = radius * Math.sin(radians); |
|
return { |
|
x:cx+x, |
|
y:cy-y |
|
}; // Object |
|
}, |
|
|
|
constrainAngle: function(/*EventObject*/obj, /*Number*/min, /*Number*/max){ |
|
// summary: |
|
// Ensures the angle in the Mouse Object is within the |
|
// min and max limits. If not one of those limits is used. |
|
// Returns an x,y point for the angle used. |
|
|
|
var angle = this.angle(obj); |
|
if(angle >= min && angle <= max){ |
|
return obj; // Object |
|
} |
|
var radius = this.length(obj); |
|
var new_angle = angle > max ? max : min - angle < 100 ? min : max; |
|
return this.pointOnCircle(obj.start.x,obj.start.y,radius, new_angle); // Object |
|
}, |
|
|
|
snapAngle: function(/*EventObject*/ obj, /*Float*/ ca){ |
|
// summary: |
|
// Snaps a line to the nearest angle |
|
// obj: Mouse object (see dojox.drawing.Mouse) |
|
// ca: Fractional amount to snap to |
|
// A decimal number fraction of a half circle. |
|
// |
|
// - .5 would snap to 90 degrees |
|
// - .25 would snap to 45 degrees |
|
// - .125 would snap to 22.5 degrees, etc. |
|
|
|
var radians = this.radians(obj), |
|
radius = this.length(obj), |
|
seg = Math.PI * ca, |
|
rnd = Math.round(radians/seg), |
|
new_radian = rnd*seg, |
|
new_angle = this.radToDeg(new_radian), |
|
pt = this.pointOnCircle(obj.start.x,obj.start.y,radius,new_angle); |
|
return pt; // Object |
|
}, |
|
|
|
// helpers |
|
idSetStart: function(num){ |
|
start=num; |
|
}, |
|
|
|
uid: function(/*String?*/ str){ |
|
// summary: |
|
// Creates a unique ID. |
|
// str: String |
|
// If provided, kept in a map, incremented |
|
// and used in the id. Otherwise 'shape' is used. |
|
|
|
str = str || "shape"; |
|
uidMap[str] = uidMap[str]===undefined ? start : uidMap[str] + 1; |
|
return str + uidMap[str]; // String |
|
}, |
|
|
|
abbr: function(type){ |
|
// summary: |
|
// Converts a namespace (typically a tool or a stencil) into |
|
// an abbreviation |
|
return type.substring(type.lastIndexOf(".")+1).charAt(0).toLowerCase() |
|
+ type.substring(type.lastIndexOf(".")+2); |
|
}, |
|
mixin: function(o1, o2){ |
|
// TODO: make faster |
|
//return dojo.mixin(dojo.clone(o1), dojo.clone(o2)); |
|
}, |
|
|
|
objects:{}, //private? |
|
register: function(/*Object*/obj){ |
|
// summary: |
|
// Since util is the only Singleton in Drawing (besides |
|
// keys) it is used to help connect the Drawing object |
|
// the Toolbar. Since multiple drawings can be on one |
|
// page, this function serves a little more use than |
|
// on first apearance. |
|
this.objects[obj.id] = obj; |
|
}, |
|
byId: function(/*String*/id){ |
|
// summary: |
|
// Get an object that was registered with util.register |
|
|
|
return this.objects[id]; |
|
}, |
|
attr: function(/* Object */ elem, /* property */ prop, /* ? value */ value, squelchErrors){ |
|
// summary: |
|
// Helper function to attach attributes to SVG and VML raw nodes. |
|
|
|
|
|
if(!elem){ return false; } |
|
try{ |
|
|
|
// util is a crappy check, but we need to tell the diff |
|
// between a Drawing shape and a GFX shape |
|
if(elem.shape && elem.util){ |
|
elem = elem.shape; |
|
} |
|
|
|
if(!value && prop=="id" && elem.target){ |
|
|
|
var n = elem.target; |
|
while(n && !dojo.attr(n, "id")){ |
|
n = n.parentNode; |
|
} |
|
return n && dojo.attr(n, "id"); |
|
} |
|
|
|
if(elem.rawNode || elem.target){ |
|
var args = Array.prototype.slice.call(arguments); |
|
args[0] = elem.rawNode || elem.target; |
|
return dojo.attr.apply(dojo, args); |
|
} |
|
return dojo.attr(elem, "id"); |
|
|
|
|
|
|
|
}catch(e){ |
|
if(!squelchErrors){ |
|
// For debugging only. These errors actually cause errors in IE's console |
|
//console.error("BAD ATTR: prop:", prop, "el:", elem) |
|
//console.error(e) |
|
//console.trace(); |
|
} |
|
return false; |
|
} |
|
} |
|
}; |
|
|
|
});
|
|
|