| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 | /** * Class to generate polyline * * @author Dmitry Farafonov */ var ANCHOR_TYPE= {	main: "main",	middle: "middle",	first: "first",	last: "last"};function Anchor(uuid, type, x, y) {	this.uuid = uuid; 	this.x = x	this.y = y	this.type = (type == ANCHOR_TYPE.middle) ? ANCHOR_TYPE.middle : ANCHOR_TYPE.main;};Anchor.prototype = {	uuid: null,	x: 0,	y: 0,	type: ANCHOR_TYPE.main,	isFirst: false,	isLast: false,	ndex: 0,	typeIndex: 0};function Polyline(uuid, points, strokeWidth) {	/* Array on coordinates:	 * points: [{x: 410, y: 110}, 1	 *			{x: 570, y: 110}, 1 2	 *			{x: 620, y: 240},   2 3	 *			{x: 750, y: 270},     3 4	 *			{x: 650, y: 370}];      4	 */	this.points = points;		/*	 * path for graph	 * [["M", x1, y1], ["L", x2, y2], ["C", ax, ay, bx, by, x3, y3], ["L", x3, y3]]	 */	this.path = [];		this.anchors = [];		if (strokeWidth) this.strokeWidth = strokeWidth;		this.closePath = false;		this.init();};Polyline.prototype = {	id: null,	points: [],	path: [],	anchors: [],	strokeWidth: 1,	radius: 15,	showDetails: false,	element: null,	isDefaultConditionAvailable: false,	closePath: false,		init: function(points){		var linesCount = this.getLinesCount();		if (linesCount < 1)			return;					this.normalizeCoordinates();				// create anchors				this.pushAnchor(ANCHOR_TYPE.first, this.getLine(0).x1, this.getLine(0).y1);				for(var i = 1; i < linesCount; i++){			var line1 = this.getLine(i-1),				line2 = this.getLine(i);						//this.pushAnchor(ANCHOR_TYPE.middle, line1.x1 + line1.x2-line1.x1, line1.y1 + line1.y2-line1.y1);			this.pushAnchor(ANCHOR_TYPE.main,  line1.x2, line1.y2);			//this.pushAnchor(ANCHOR_TYPE.middle,  line2.x1 + line2.x2-line2.x1, line2.y1 + line2.y2-line2.y1);		}				this.pushAnchor(ANCHOR_TYPE.last, this.getLine(linesCount-1).x2, this.getLine(linesCount-1).y2);				this.rebuildPath();	},		normalizeCoordinates: function(){		for(var i=0; i < this.points.length; i++){			this.points[i].x = parseFloat(this.points[i].x);			this.points[i].y = parseFloat(this.points[i].y);		}	},		getLinesCount: function(){		return this.points.length-1;	},	_getLine: function(i){		return {x1: this.points[i].x, y1: this.points[i].y, x2: this.points[i+1].x, y2: this.points[i+1].y};	},	getLine: function(i){		var line = this._getLine(i);		line.angle = this.getLineAngle(i) ;		return line;	},	getLineAngle: function(i){		var line = this._getLine(i);		return Math.atan2(line.y2 - line.y1, line.x2 - line.x1);	},	getLineLengthX: function(i){		var line = this.getLine(i);		return (line.x2 - line.x1);	},	getLineLengthY: function(i){		var line = this.getLine(i);		return (line.y2 - line.y1);	},	getLineLength: function(i){		var line = this.getLine(i);		return Math.sqrt(Math.pow(this.getLineLengthX(i), 2) + Math.pow(this.getLineLengthY(i), 2));	},		getAnchors: function(){		// âåðíóòü îòñîðòèðîâàííûé ìàññèâ		// ????		return this.anchors;	},	getAnchorsCount: function(type){		if (!type)			return this.anchors.length;		else {			var count = 0;			for(var i=0; i < this.getAnchorsCount(); i++){				var anchor = this.anchors[i];				if (anchor.getType() == type) {					count++;				}			}			return count;		}	},		pushAnchor: function(type, x, y, index){		if (type == ANCHOR_TYPE.first) {			index = 0;			typeIndex = 0;		} else if (type == ANCHOR_TYPE.last) {			index = this.getAnchorsCount();			typeIndex = 0;		} else if (!index) {			index = this.anchors.length;		} else {			// ïåðåáðàòü anchors, ñäâèíóòü ïîçèöèþ äëÿ êàæäîãî, íà÷èíàÿ ñ index			//var anchor = this.getAnchor()			for(var i=0; i < this.getAnchorsCount(); i++){				var anchor = this.anchors[i];				if (anchor.index > index) {					anchor.index++;					anchor.typeIndex++;				}			}		}				var anchor = new Anchor(this.id, ANCHOR_TYPE.main, x, y, index, typeIndex);				this.anchors.push(anchor);	},		getAnchor: function(position){		return this.anchors[position];	},		getAnchorByType: function(type, position){		if (type == ANCHOR_TYPE.first)			return this.anchors[0];		if (type == ANCHOR_TYPE.last)			return this.anchors[this.getAnchorsCount()-1];				for(var i=0; i < this.getAnchorsCount(); i++){			var anchor = this.anchors[i];			if (anchor.type == type) {				if( position == anchor.position)					return anchor;			}		}		return null;	},		addNewPoint: function(position, x, y){		// 		for(var i = 0; i < this.getLinesCount(); i++){			var line = this.getLine(i);			if (x > line.x1 && x < line.x2 && y > line.y1 && y < line.y2) {				this.points.splice(i+1,0,{x: x, y: y});				break;			}		}				this.rebuildPath();	},		rebuildPath: function(){		var path = [];				for(var i = 0; i < this.getAnchorsCount(); i++){			var anchor = this.getAnchor(i);						var pathType = ""			if (i==0)				pathType = "M";			else 				pathType = "L";			// TODO: save previous points and calculate new path just if points are updated, and then save currents values as previous						var targetX = anchor.x, targetY = anchor.y;			if (i>0 && i < this.getAnchorsCount()-1) {				// get new x,y				var cx = anchor.x, cy = anchor.y;								// pivot point of prev line				var AO = this.getLineLength(i-1);				if (AO < this.radius) {					AO = this.radius;				}								this.isDefaultConditionAvailable = (this.isDefaultConditionAvailable || (i == 1 && AO > 10));				//console.log("isDefaultConditionAvailable", this.isDefaultConditionAvailable);								var ED = this.getLineLengthY(i-1) * this.radius / AO;				var OD = this.getLineLengthX(i-1) * this.radius / AO;					targetX = anchor.x - OD;					targetY = anchor.y - ED;								if (AO < 2*this.radius && i>1) {					targetX = anchor.x - this.getLineLengthX(i-1)/2;					targetY = anchor.y - this.getLineLengthY(i-1)/2;;				}									// pivot point of next line				var AO = this.getLineLength(i);				if (AO < this.radius) {					AO = this.radius;				}				var ED = this.getLineLengthY(i) * this.radius / AO;				var OD = this.getLineLengthX(i) * this.radius / AO;					var nextSrcX = anchor.x + OD;					var nextSrcY = anchor.y + ED;									if (AO < 2*this.radius && i<this.getAnchorsCount()-2) {					nextSrcX = anchor.x + this.getLineLengthX(i)/2;					nextSrcY = anchor.y + this.getLineLengthY(i)/2;;				}													var dx0 = (cx - targetX) / 3,					dy0 = (cy - targetY) / 3,					ax = cx - dx0,					ay = cy - dy0,										dx1 = (cx - nextSrcX) / 3,					dy1 = (cy - nextSrcY) / 3,					bx = cx - dx1,					by = cy - dy1,										zx=nextSrcX, zy=nextSrcY;									if (this.showDetails) {					var c = ProcessDiagramCanvas.g.path("M"+targetX+","+targetY+"L"+ax+","+ay).attr({stroke: Color.get(255, 153, 51), "stroke-dasharray": "- "});					var c = ProcessDiagramCanvas.g.path("M"+nextSrcX+","+nextSrcY+"L"+bx+","+by).attr({stroke: Color.get(255, 153, 51), "stroke-dasharray": "- "});					var c = ProcessDiagramCanvas.g.ellipse(ax, ay, 2, 2).attr({stroke: Color.SlateGrey});					var c = ProcessDiagramCanvas.g.ellipse(bx, by, 2, 2).attr({stroke: Color.SlateGrey});					var c = ProcessDiagramCanvas.g.ellipse(cx, cy, this.radius, this.radius).attr({stroke: Color.Gainsboro});					var c = ProcessDiagramCanvas.g.ellipse(targetX, targetY, 2, 2).attr({fill: Color.red});					var c = ProcessDiagramCanvas.g.ellipse(nextSrcX, nextSrcY, 2, 2).attr({fill: Color.red});				}			} else if (i==1 && this.getAnchorsCount() == 2){				var AO = this.getLineLength(i-1);				if (AO < this.radius) {					AO = this.radius;				}				this.isDefaultConditionAvailable = (this.isDefaultConditionAvailable || (i == 1 && AO > 10));				//console.log("-- isDefaultConditionAvailable", this.isDefaultConditionAvailable);			}			// anti smoothing			if (this.strokeWidth%2 == 1) {				targetX += 0.5;				targetY += 0.5;			}						path.push([pathType, targetX, targetY]);						if (i>0 && i < this.getAnchorsCount()-1) {				path.push(["C", ax, ay, bx, by, zx, zy]);			}		}				if (this.closePath) {			console.log("closePath:", this.closePath);			path.push(["Z"]);		}				this.path = path;	},		transform: function(transformation){		this.element.transform(transformation);	},	attr: function(attrs){		//console.log("attrs: " +attrs, "", this.element);		// TODO: foreach and set each		this.element.attr(attrs);	}};function Polygone(points, strokeWidth) {	/* Array on coordinates:	 * points: [{x: 410, y: 110}, 1	 *			{x: 570, y: 110}, 1 2	 *			{x: 620, y: 240},   2 3	 *			{x: 750, y: 270},     3 4	 *			{x: 650, y: 370}];      4	 */	this.points = points;		/*	 * path for graph	 * [["M", x1, y1], ["L", x2, y2], ["C", ax, ay, bx, by, x3, y3], ["L", x3, y3]]	 */	this.path = [];		this.anchors = [];		if (strokeWidth) this.strokeWidth = strokeWidth;		this.closePath = true;	this.init();};/* * Poligone is inherited from Poliline: draws closedPath of polyline */var Foo = function () { };Foo.prototype = Polyline.prototype;Polygone.prototype = new Foo();Polygone.prototype.rebuildPath = function(){	var path = [];	//console.log("Polygone rebuildPath");	for(var i = 0; i < this.getAnchorsCount(); i++){		var anchor = this.getAnchor(i);				var pathType = ""		if (i==0)			pathType = "M";		else 			pathType = "L";				var targetX = anchor.x, targetY = anchor.y;				// anti smoothing		if (this.strokeWidth%2 == 1) {			targetX += 0.5;			targetY += 0.5;		}				path.push([pathType, targetX, targetY]);		}	if (this.closePath)		path.push(["Z"]);		this.path = path;};/*Polygone.prototype.transform = function(transformation){	this.element.transform(transformation);};*/
 |