394 lines
12 KiB
JavaScript
394 lines
12 KiB
JavaScript
/**
|
|
* @namespace shape
|
|
*/
|
|
ovm.shape = ovm.shape || {};
|
|
|
|
/**
|
|
* Definition of shape Lines
|
|
*/
|
|
ovm.shape.ruler = function(xPixelSpacing,yPixelSpacing,measure_Unit) {
|
|
var handle = 5;
|
|
var lines = [];
|
|
var curr_line=null;
|
|
|
|
var xPxlSpcing = xPixelSpacing;
|
|
var yPxlSpcing = yPixelSpacing;
|
|
var measureUnit = measure_Unit;
|
|
var isCurrentDrawingLine = false;
|
|
|
|
this.createNewLine = function(x1,y1,x2,y2) {
|
|
if(curr_line!=undefined) {
|
|
curr_line.setCoords(x1,y1,x2,y2,false);
|
|
if(parseInt(curr_line.len)>0) {
|
|
lines.push(curr_line);
|
|
curr_line = undefined;
|
|
}
|
|
}
|
|
};
|
|
|
|
this.initNewLine = function() {
|
|
curr_line = new ovm.line(xPxlSpcing, yPxlSpcing,measureUnit, 0, 0, 0, 0, 0);
|
|
};
|
|
|
|
this.draw = function(graphic,ctx) {
|
|
ctx.strokeStyle=ctx.fillStyle='orange';
|
|
ctx.beginPath();
|
|
ctx.moveTo(graphic.x1,graphic.y1);
|
|
ctx.lineTo(graphic.x2,graphic.y2);
|
|
ctx.stroke();
|
|
ctx.closePath();
|
|
// Handles
|
|
ctx.strokeStyle = ctx.fillStyle = graphic.active? 'red' : 'white';
|
|
ctx.strokeRect(graphic.x1-handle,graphic.y1-handle,handle*2,handle*2);
|
|
ctx.strokeRect(graphic.x2-handle,graphic.y2-handle,handle*2,handle*2);
|
|
// Text
|
|
ctx.fillStyle = graphic.txtActive? "blue" : "maroon";
|
|
ctx.globalAlpha = 0.7;
|
|
ctx.font = "14px Arial";
|
|
var text = ctx.measureText(graphic.len + " " + measureUnit);
|
|
ctx.fillRect(graphic.textX,graphic.textY,Math.ceil(text.width)+5,20);
|
|
ctx.globalAlpha = 0.9;
|
|
ctx.fillStyle = "white";
|
|
//ctx.fillText(graphic.len+" " + measureUnit,graphic.textX+2,graphic.textY+14);
|
|
|
|
if(state.hflip && !state.vflip && !state.rotate!=0 && !this.isCurrentDrawingLine){
|
|
ctx.save();
|
|
ctx.translate(drawCanvas.width,0);
|
|
ctx.scale(-1,1);
|
|
ctx.fillText(graphic.len+ " " + measureUnit,(drawCanvas.width - graphic.textX)-60,graphic.textY+14);
|
|
ctx.restore();
|
|
}
|
|
|
|
if(state.vflip && !state.hflip && !state.rotate!=0 && !this.isCurrentDrawingLine){
|
|
ctx.save();
|
|
ctx.translate(0,drawCanvas.height);
|
|
ctx.scale(1,-1);
|
|
ctx.fillText(graphic.len+ " " + measureUnit, graphic.textX,(drawCanvas.height -graphic.textY));
|
|
ctx.restore();
|
|
}
|
|
|
|
if(!state.vflip && state.hflip && (state.rotate===90 || state.rotate===180 || state.rotate===270) && !this.isCurrentDrawingLine){
|
|
if(state.rotate===90|| state.rotate===180 || state.rotate===270) {
|
|
ctx.save();
|
|
ctx.translate(0,drawCanvas.height);
|
|
ctx.scale(1,-1);
|
|
ctx.fillText(graphic.len+ " " + measureUnit, graphic.textX,(drawCanvas.height -graphic.textY));
|
|
ctx.restore();
|
|
}
|
|
}
|
|
|
|
if(state.vflip && !state.hflip && (state.rotate===90 || state.rotate===180 || state.rotate===270) && !this.isCurrentDrawingLine){
|
|
if(state.rotate===90 || state.rotate===180 || state.rotate===270) {
|
|
ctx.save();
|
|
ctx.translate(drawCanvas.width,0);
|
|
ctx.scale(-1,1);
|
|
ctx.fillText(graphic.len+ " " + measureUnit,(drawCanvas.width - graphic.textX)-60,graphic.textY+14);
|
|
ctx.restore();
|
|
}
|
|
}
|
|
|
|
if(state.rotate!=0 && !state.vflip && !state.hflip && !this.isCurrentDrawingLine) {
|
|
if(state.rotate===180) {
|
|
ctx.save();
|
|
ctx.translate(drawCanvas.width/2,drawCanvas.height/2);
|
|
ctx.rotate(Math.PI);
|
|
ctx.translate(-drawCanvas.width/2,-drawCanvas.height/2);
|
|
ctx.fillText(graphic.len+ " " + measureUnit, (drawCanvas.width -graphic.textX)-60,(drawCanvas.height -graphic.textY));
|
|
ctx.restore();
|
|
}
|
|
else {
|
|
ctx.fillText(graphic.len+ " " + measureUnit,graphic.textX+2,graphic.textY+14);
|
|
}
|
|
}
|
|
|
|
if((state.rotate===0 || state.rotate===90 || state.rotate===180 || state.rotate===270) && state.vflip && state.hflip && !this.isCurrentDrawingLine) {
|
|
if(state.rotate===0) {
|
|
ctx.save();
|
|
ctx.translate(drawCanvas.width,drawCanvas.height);
|
|
ctx.scale(-1,-1);
|
|
ctx.fillText(graphic.len+ " " + measureUnit, (drawCanvas.width -graphic.textX)-60,(drawCanvas.height -graphic.textY));
|
|
ctx.restore();
|
|
} else {
|
|
ctx.fillText(graphic.len+ " " + measureUnit,graphic.textX+2,graphic.textY+14);
|
|
}
|
|
}
|
|
|
|
if(!state.hflip && !state.vflip && !state.rotate!=0) {
|
|
ctx.fillText(graphic.len+ " " + measureUnit,graphic.textX+2,graphic.textY+14);
|
|
}
|
|
|
|
if(this.isCurrentDrawingLine) {
|
|
ctx.fillText(graphic.len+ " " + measureUnit, graphic.textX+2,graphic.textY+14);
|
|
}
|
|
|
|
|
|
// Reference lines
|
|
if(graphic.x1!=graphic.textX) {
|
|
ctx.save();
|
|
ctx.beginPath();
|
|
ctx.globalAlpha = 0.5;
|
|
ctx.strokeStyle = "yellow";
|
|
ctx.setLineDash([10,7]);
|
|
var closestPt = this.getClosestAnchor([{x:graphic.textX,y:graphic.textY},{x:graphic.textX+Math.ceil(text.width+5),y:graphic.textY},{x:graphic.textX,y:graphic.textY+20},{x:graphic.textX+Math.ceil(text.width+5),y:graphic.textY+20}],{x:graphic.refX,y:graphic.refY});
|
|
ctx.moveTo(closestPt.x, closestPt.y);
|
|
ctx.lineTo(graphic.refX,graphic.refY);
|
|
ctx.stroke();
|
|
ctx.closePath();
|
|
ctx.restore();
|
|
}
|
|
};
|
|
|
|
this.drawData = function(ctx) {
|
|
ctx.save();
|
|
ctx.lineWidth='2';
|
|
|
|
for(var i=0;i<lines.length;i++) {
|
|
this.draw(this.viewPortGraphic(lines[i]),ctx);
|
|
}
|
|
ctx.restore();
|
|
};
|
|
|
|
this.drawRuler = function(canvasCtx,x1,y1,x2,y2) {
|
|
curr_line.setCoords(x1,y1,x2,y2,true);
|
|
this.isCurrentDrawingLine = true;
|
|
canvasCtx.save();
|
|
canvasCtx.lineWidth='2';
|
|
this.draw(this.viewPortGraphic(curr_line),canvasCtx);
|
|
this.isCurrentDrawingLine = false;
|
|
canvasCtx.restore();
|
|
};
|
|
|
|
this.getActiveLine = function(canvasCtx,x,y) {
|
|
for(var i=0;i<lines.length;i++) {
|
|
var line = lines[i];
|
|
if(line.isActiveShape(canvasCtx,x,y)) {
|
|
return line;
|
|
}
|
|
}
|
|
return null;
|
|
};
|
|
|
|
this.viewPortGraphic = function(shape) {
|
|
return {
|
|
x1:shape.x1*state.scale+state.translationX,
|
|
y1:shape.y1*state.scale+state.translationY,
|
|
x2:shape.x2*state.scale+state.translationX,
|
|
y2:shape.y2*state.scale+state.translationY,
|
|
textX:shape.textX*state.scale+state.translationX,
|
|
textY:shape.textY*state.scale+state.translationY,
|
|
refX:shape.refX*state.scale+state.translationX,
|
|
refY:shape.refY*state.scale+state.translationY,
|
|
active:shape.active,
|
|
len:shape.len,
|
|
txtActive:shape.txtActive
|
|
};
|
|
};
|
|
|
|
this.canvasToImgCoordinates = function(point) {
|
|
return {x:(point.x-state.translationX)/state.scale,y:(point.y-state.translationY)/state.scale};
|
|
};
|
|
|
|
this.removeShape = function(shape) {
|
|
lines.splice(lines.indexOf(shape), 1);
|
|
};
|
|
|
|
this.clearAll = function() {
|
|
lines = [];
|
|
};
|
|
|
|
this.getClosestAnchor = function(points,refPt) {
|
|
var dist1 = Math.round(Math.sqrt(Math.pow(points[0].x-refPt.x,2) + Math.pow(points[0].y-refPt.y,2)));
|
|
var dist2 = Math.round(Math.sqrt(Math.pow(points[1].x-refPt.x,2) + Math.pow(points[1].y-refPt.y,2)));
|
|
var dist3 = Math.round(Math.sqrt(Math.pow(points[2].x-refPt.x,2) + Math.pow(points[2].y-refPt.y,2)));
|
|
var dist4 = Math.round(Math.sqrt(Math.pow(points[3].x-refPt.x,2) + Math.pow(points[3].y-refPt.y,2)));
|
|
var min = Math.min(dist1,dist2,dist3,dist4);
|
|
|
|
switch(min) {
|
|
case dist1:
|
|
return points[0];
|
|
case dist2:
|
|
return points[1];
|
|
case dist3:
|
|
return points[2];
|
|
case dist4:
|
|
return points[3];
|
|
default:
|
|
return points[0];
|
|
}
|
|
};
|
|
};
|
|
|
|
/**
|
|
* @namespace line
|
|
*/
|
|
|
|
ovm.line = function(xPixelSpacing,yPixelSpacing,measure_Unit,a,b,c,d,e) {
|
|
// Variables
|
|
var handle = 5;
|
|
this.xPxlSpcing = xPixelSpacing;
|
|
this.yPxlSpcing = yPixelSpacing;
|
|
this.measureUnit = measure_Unit;
|
|
this.x1=a;
|
|
this.y1=b;
|
|
this.x2=c;
|
|
this.y2=d;
|
|
this.active = false;
|
|
this.len = e;
|
|
|
|
// Text
|
|
this.textX = a;
|
|
this.textY = b-25;
|
|
this.txtActive = false;
|
|
this.refX = 0;
|
|
this.refY = 0;
|
|
|
|
// Functions
|
|
this.setCoords = function(a,b,c,d,active) {
|
|
this.x1=(a-state.translationX)/state.scale;
|
|
this.y1=(b-state.translationY)/state.scale;
|
|
this.x2=(c-state.translationX)/state.scale;
|
|
this.y2=(d-state.translationY)/state.scale;
|
|
this.active = active;
|
|
this.len = this.calculateLength(this.x2-this.x1, this.y2-this.y1).toFixed(3);
|
|
this.textX = this.x1;
|
|
this.textY = this.y1-(25/state.scale);
|
|
this.findClosestPointOnLine();
|
|
};
|
|
|
|
this.getType = function() {
|
|
return "ruler";
|
|
};
|
|
|
|
this.isActiveShape = function(canvasCtx,x,y) {
|
|
var start = this.ImgTocanvascoordinates({x:this.x1,y:this.y1});
|
|
var end = this.ImgTocanvascoordinates({x:this.x2,y:this.y2});
|
|
var a = Math.round(Math.sqrt(Math.pow((end.x+handle)-(start.x+handle),2) + Math.pow((end.y+handle)-(start.y+handle),2)));
|
|
var b = Math.round(Math.sqrt(Math.pow(x-(start.x+handle),2) + Math.pow(y-(start.y+handle),2)));
|
|
var c = Math.round(Math.sqrt(Math.pow((end.x+handle)-x,2) + Math.pow((end.y+handle)-y,2)));
|
|
this.active = (a==b+c);
|
|
return this.active || this.isTextSelection(canvasCtx,x,y);
|
|
};
|
|
|
|
this.detectHandle = function(x,y,target) {
|
|
var start = this.ImgTocanvascoordinates({x:this.x1,y:this.y1});
|
|
var end = this.ImgTocanvascoordinates({x:this.x2,y:this.y2});
|
|
|
|
if(x>=start.x-handle && x<=start.x+handle && y>=start.y-handle && y<=start.y+handle) {
|
|
target.style.cursor = "pointer";
|
|
return 0;
|
|
} else if(x>=end.x-handle && x<=end.x+handle && y>=end.y-handle && y<=end.y+handle) {
|
|
target.style.cursor = "pointer";
|
|
return 1;
|
|
} else {
|
|
return -1;
|
|
}
|
|
};
|
|
|
|
this.moveShape = function(deltaX,deltaY) {
|
|
if(this.active) {
|
|
this.x1+=deltaX;
|
|
this.y1+=deltaY;
|
|
this.x2+=deltaX;
|
|
this.y2+=deltaY;
|
|
}
|
|
this.textX+=deltaX;
|
|
this.textY+=deltaY;
|
|
this.findClosestPointOnLine();
|
|
};
|
|
|
|
this.resizeShape = function(deltaX,deltaY,handle) {
|
|
switch(handle) {
|
|
case 0:
|
|
this.x1+=deltaX;
|
|
this.y1+=deltaY;
|
|
this.len= this.calculateLength(this.x2-this.x1, this.y2-this.y1).toFixed(3);
|
|
break;
|
|
case 1:
|
|
this.x2+=deltaX;
|
|
this.y2+=deltaY;
|
|
this.len = this.calculateLength(this.x2-this.x1, this.y2-this.y1).toFixed(3);
|
|
break;
|
|
}
|
|
this.findClosestPointOnLine();
|
|
};
|
|
|
|
this.calculateLength = function(xDiff,yDiff) {
|
|
var mult = Math.max(this.getFloatShift(this.xPxlSpcing),this.getFloatShift(this.yPxlSpcing));
|
|
var xDist = mult * this.xPxlSpcing * xDiff;
|
|
var yDist = mult * this.yPxlSpcing * yDiff;
|
|
|
|
return ((Math.sqrt((Math.pow(xDist,2)+Math.pow(yDist,2))/Math.pow(mult,2))))/10;
|
|
};
|
|
|
|
this.getFloatShift = function(floatNum) {
|
|
var decimalLen = 0;
|
|
var floatElements = floatNum.toString().split('\.');
|
|
if(floatElements.length==2) {
|
|
decimalLen = floatElements[1].length;
|
|
}
|
|
mult = Math.pow(10,decimalLen);
|
|
return mult;
|
|
};
|
|
|
|
this.canvasToImgcoordinates = function(point) {
|
|
return {x:((point.x-state.translationX)/state.scale),y:((point.y-state.translationY)/state.scale)};
|
|
};
|
|
|
|
this.ImgTocanvascoordinates = function(point) {
|
|
return {x:point.x*state.scale+state.translationX,y:point.y*state.scale+state.translationY};
|
|
};
|
|
|
|
this.isTextSelection = function(canvasCtx,mouseX,mouseY) {
|
|
var x = (mouseX-state.translationX)/state.scale;
|
|
var y = (mouseY-state.translationY)/state.scale;
|
|
|
|
var textWid = Math.ceil(canvasCtx.measureText(this.len + " " + this.measureUnit).width)+5;
|
|
this.txtActive = (x>=this.textX && x<=this.textX+(textWid/state.scale) && y>=this.textY && y<=(this.textY+(20/state.scale)));
|
|
return this.txtActive;
|
|
};
|
|
|
|
this.findClosestPointOnLine = function() {
|
|
var ptWithinLine = true;
|
|
|
|
var dotproduct = (this.textX - this.x1) * (this.x2 - this.x1) + (this.textY - this.y1)*(this.y2 - this.y1);
|
|
if(dotproduct<0) {
|
|
ptWithinLine = false;
|
|
}
|
|
|
|
var squaredlengthBA = (this.x2 - this.x1)*(this.x2 - this.x1) + (this.y2 - this.y1)*(this.y2 - this.y1);
|
|
|
|
if(dotproduct > squaredlengthBA) {
|
|
ptWithinLine = false;
|
|
}
|
|
|
|
if(ptWithinLine) {
|
|
var a_to_p = [this.textX - this.x1 , this.textY - this.y1]; // Vector A to P
|
|
var a_to_b = [this.x2 - this.x1 , this.y2 - this.y1]; // Vector A to B
|
|
|
|
// Find squared magnitude of a_to_b
|
|
var atb2 = Math.pow(a_to_b[0],2) + Math.pow(a_to_b[1],2);
|
|
|
|
// Find dot product of a_to_p and a_to_b
|
|
var atp_dot_atb = a_to_p[0] * a_to_b[0] + a_to_p[1] * a_to_b[1];
|
|
|
|
// Normalized distance from a to closest point
|
|
var t = atp_dot_atb / atb2;
|
|
|
|
// Add the distance to A, moving towards B
|
|
this.refX = this.x1 + a_to_b[0] * t;
|
|
this.refY = this.y1 + a_to_b[1] * t;
|
|
} else {
|
|
var p_to_a = Math.sqrt(Math.pow(this.textX-this.x1,2) + Math.pow(this.textY-this.y1,2)); // Distance from Point to A
|
|
var p_to_b = Math.sqrt(Math.pow(this.textX-this.x2,2) + Math.pow(this.textY-this.y2,2)); // Distance from Point to B
|
|
|
|
if(p_to_b>p_to_a) {
|
|
this.refX = this.x1;
|
|
this.refY = this.y1;
|
|
} else {
|
|
this.refX = this.x2;
|
|
this.refY = this.y2;
|
|
}
|
|
}
|
|
};
|
|
};
|