/**
==============================================================================================
класс objIsolines.js
изолиниии марширующих квадратов
==============================================================================================
используется два метода, один плагин d3.geom.contour.js
плагин https://github.com/d3/d3-plugins/tree/master/geom/contour
пример http://bl.ocks.org/mbostock/4241134
==============================================================================================
второй, закоментированный -- кустарный
функции класса: 
makeIsolines() - сборка всех функций для построения изолиний
getnumberisolines() - получить число изолиний
nlattice1Init(), nlattice2Init() - получить размерности скалярного поля плотностей Lattice
pointsInit() - формирование массива точек Points
latticeInit() - заполнения массива Lattice
isolineInit() - уровни изолиний Isolines
generateisolines() - создание самих изолиний через плагин d3.geom.contour.js
==============================================================================================
(c) Mychko Eduard, 2015, Moscow, Russia, eduard.mychko@gmail.com
==============================================================================================
*/

var objIsolines = {
	/*--------------------------------------------------------------сборка--------------------------------------------------------------*/
	makeIsolines: function(){
		objD3.remove(objAnalys.svg,".isoline"); /* очищаем канву от изолиний*/ 
		objD3.remove(objAnalys.svg,".legendlabels"); /* очищаем канву от наименований легенды*/ 
		objD3.remove(objAnalys.svg,".legenda"); /* очищаем канву от легенды*/ 
		this.getnumberisolines();
		this.nlattice1Init();
		this.nlattice2Init();
		this.pointsInit();
		this.latticeInit();
		this.isolineInit();
 		//this.isolineArr(objAnalys.svg);
		//console.log(IsolinesArr2);
		this.generateisolines(objAnalys.svg);
		return false;
	},
	
	/*--------------------------------------------------------------основные переменные--------------------------------------------------------------*/
 	'dataset' : false,
	'MinX' : 0, /* минимальное значение X */
	'MinY' : 0.5, /* минимальное значение Y */
	'MaxX' : 0.7, /* максимальной значение X */
	'MaxY' : 5, /* максимальной значение Y */
	'stepX' : 0.01, /* наг по X */
	'stepY' : 0.01, /* шаг по Y */
	'radius' : 0.08, /*радиус окружности для поиска соседей */
	'nlines' : 3, /*количество изолиний */
	'n' : 100, /* количество точек на карте, по умолчанию */
	'MinDens' : 10000,  
	'MaxDens' : 0, 
	'Points' : [], /* поле размерностей */
	'Lattice' : [], /* поле плотностей точек*/
	'Isolines' : [], /* изолинии */
	'Isocolors' : [], /* цвета изолиний */ 
	'IsolinesArr' : [], /* весь набор координат изолиний */ 
	'nlattice1' : 0, /*размерности массива Lattice*/ 
	'nlattice2' : 0, /*размерности массива Lattice*/ 
	'sFadeStartColor' : "#F8F4A7", /* начальный цвет изолиний */   
	'sFadeFinishColor': "#E08415", /* конечный цвет изолиний */   
 
	/*--------------------------------------------------------------получаем количество изолиний--------------------------------------------------------------*/
	getnumberisolines: function(){
		this.nlines =  $("#rangeisoline").val();
		return false;
	},
 
	nlattice1Init: function(){
		this.nlattice1 = Math.round((this.MaxX - this.MinX) / this.stepX); 
		return false;
	},
	
	nlattice2Init: function(){
		this.nlattice2 = Math.round((this.MaxY - this.MinY) / this.stepY);
		return false;
	},
  
	/*--------------------------------------------------------------формирование массива точек--------------------------------------------------------------*/
	pointsInit: function(){
		var Points = [];
		Points[0] = [];
		Points[1] = [];
		for(var count = 0; count < this.dataset.length; count++){
			Points[0][count] = this.dataset[count][2];
			Points[1][count] = this.dataset[count][1];
		}
		this.n = count; /*определяем количество точек исходя из массива*/
		this.Points = Points;
		return false;
	},

	/*--------------------------------------------------------------формирование массива поля плотностей точек--------------------------------------------------------------*/
	latticeInit: function(){
		var Lattice = []; /* объявляем массив */
  		for (var count = 0; count <= this.nlattice1; count++){
			Lattice[count] = new Array(); 
 			for (var count2 = 0; count2 <= this.nlattice2; count2++){
 				Lattice[count][count2] = 0; /* собираем матрицу плотностей точек*/
 				for (var i = 0; i <= this.n-1; i++){
					var currentDist = this.distFunc(this.MinX + count * this.stepX, this.MinY + count2 * this.stepY, this.Points[0][i], this.Points[1][i]);
					if (currentDist < this.radius)   Lattice[count][count2] = Lattice[count][count2]+ 1 - (currentDist / this.radius); 	  
					if (Lattice[count][count2] < this.MinDens)   this.MinDens = Lattice[count][count2];	 
					if (Lattice[count][count2] > this.MaxDens)   this.MaxDens = Lattice[count][count2];
					//вывод переменных console.log(i + ' -- ' + currentDist + ' -- '+ (currentDist / this.radius) + ' -- ' + Lattice[count][count2]);					
				}
			}
		} 
		if ((this.MaxDens - this.MinDens) < this.nlines)  this.nlines = (this.MaxDens - this.MinDens); 
		this.Lattice = Lattice;
		/*console.log(Lattice);*/
		return false;
	},

	/*--------------------------------------------------------------определяем расстояние по координатам--------------------------------------------------------------*/
	distFunc: function(X1, y1, X2, y2){
		return Math.sqrt((X1 - X2) * (X1 - X2) + 0.0625 * (y1 - y2) * (y1 - y2));
	},
	
	/*--------------------------------------------------------------заполнение массивов Isolines и Isocolors--------------------------------------------------------------*/
	isolineInit: function(){
		for (var i=0; i <= this.nlines-1; i++){
			this.Isolines[i] = Math.round((this.MaxDens - this.MinDens - 1) * i / (this.nlines - 1 ) + this.MinDens + 1);
 			this.Isocolors[i] = 200 - i * 200 / (this.nlines - 1);
		}
		return false;
	},
		
	/*--------------------------------------------------------------рисуем изолинии и легенду--------------------------------------------------------------*/
	generateisolines: function(svg){

		
		
		var x = d3.scale.linear()
			.range([0, objAnalys.boxWidth-50]);

		var y = d3.scale.linear()
			.range([ 0, objAnalys.boxHeight]);
 
		/* параметры для создания массива цветов*/
		var arrparam = {
			'source' : this.Isolines,
			'startcolor' : this.sFadeStartColor,
			'finishcolor' : this.sFadeFinishColor,
		};
		
		var arr_color = objD3.makearrgradientcolors(arrparam); /*создаем массив цветов*/
   
		/* -------------легенда----------- */
		if($('#content-analyses-fillisolines').prop("checked")) {
			var width_legend = (objAnalys.boxWidth/5); /* общая ширина легенды */
			var width_legend_part = width_legend/this.Isolines.length; /* ширина участка легенды */
			var width_legend_x = ((objAnalys.boxWidth-width_legend)-width_legend_part)-40; /* самый левый X легенды */
			for (var i = 0; i<this.Isolines.length; i++){
				width_legend_x = width_legend_x + width_legend_part;
				svg.append("rect")
						.attr("x", width_legend_x-(width_legend_part/3))
						.attr("y", 0)
						.attr("width", width_legend_part)
						.attr("height", 40)
						.attr("class","legenda") 
						.style('fill',arr_color[i]);
				
				svg.append("text")
						.attr("x", width_legend_x)
						.attr("y", -3)			
						.text( this.Isolines[i])
						.attr("class","legendlabels"); 
			}
		}

		/* создание самих изолиний  */
		/* цветовой массив и порядок изолиний  */
		var color = d3.scale.linear()
			.domain(this.Isolines)
			.range(arr_color);
		
		var heatmap =  this.Lattice; 

		var lineFunction_cardinal = d3.svg.line()
							.x(function(d) { return d[0]; })
							.y(function(d) { return d[1]; })
							.interpolate("basis-closed");	 
							
		/* перебор массива скалярного поля Lattice и построение изолиний*/	
		for (var i=0; i<=heatmap.length; i++) {
	  
			var dx = heatmap[0].length,
				dy = heatmap.length;

				x.domain([0, dx]);
				y.domain([0, dy]);

			/* если стоит условие закрашивать изолинии */ 
			if($('#content-analyses-fillisolines').prop("checked")) var fill = function(d, i) { return color.range()[i]; };
			else var fill = "none";
	
			
			
			svg.selectAll(".isoline")
				  .data(color.domain().map(isoline))
				  .enter().append("path")
				  .datum(function(d) {  return d3.geom.contour(d).map(transform); })
				  .attr("class", "isoline")
				  .attr("d", lineFunction_cardinal)
				  .style("fill", fill);
		  
			function isoline(min) {
				return function(x, y) {
				  return x >= 0 && y >= 0 && x < dx && y < dy && heatmap[y][x] >= min;
				};
			}

			function transform(point) {
				return [point[1] * (objAnalys.boxWidth) / dy, point[0] * (objAnalys.boxHeight-50) / dx];
			}
			
			if (i==heatmap.length) objHelpers.complectOperation();  /* когда изолинии отрисованы удаляем окощко ожидания */
		};	
		return false;
	},	
	
	/** ---------------------------------------------------------------------------- **/
	/** ------------ ЭТО СТАРЫЙ АЛГОРИТМ ДЛЯ РИСОВАНИЯ ИЗОЛИНИЙ  ------------------- **/
	/** ---------------------------------------------------------------------------- **/
	/* получаем массив точек каждой изолинии */
	isolineArr: function(svg){
	var IsolinesArr =  [];
	for (var isocount = 0; isocount <= this.nlines; isocount++){ 
		//Legend.CurrentX = 20
		//Legend.CurrentY = Legend.CurrentY + 50
		//Legend.ForeColor = RGB(Isocolors(isocount), Isocolors(isocount), Isocolors(isocount))
		//PicGraph.ForeColor = RGB(Isocolors(isocount), Isocolors(isocount), Isocolors(isocount))
		//Legend.Print ("Ecieeiey o?iaiy  " & FormatNumber(Isolines(isocount), 0))
		//console.log(this.nlines);
		//this.Isolines[isocount] = this.Isolines[isocount] - 0.1;
		IsolinesArr[isocount] = new Array();	
			for (var count2 = 0; count2 < this.nlattice2-1; count2++){
				for (var count = 0; count < this.nlattice1-1; count++){
				
					var xleft = this.MinX + count *  this.stepX;
					var xcenter = xleft + 0.5 *  this.stepX;
					var xright = xleft +  this.stepX;
					var yTop =  this.MinY + count2 *  this.stepY;
					var ycenter = yTop + 0.5 *  this.stepY;
					var ybottom = yTop +  this.stepY;

					/* проверка console.log(isocount+ " count2 - " + count2 + " count - " + count+  " latt - " + this.Lattice[count][count2] + " - xleft: " + xleft + " - xcenter: " + xcenter	+ " - xright: " + xright	+ " - yTop: " + yTop + " - ycenter: " + ycenter+ " - ybottom: " + ybottom);*/
					var L00 = this.Lattice[count][count2];
					var L10 = this.Lattice[count + 1][count2];
					var L01 = this.Lattice[count][count2 + 1];
					var L11 = this.Lattice[count + 1][count2 + 1]
					var iso = this.Isolines[isocount];
					var iarr = IsolinesArr[isocount];
					
					/*---------------------свой кустарный метод рисования------------------------------*/
					// '0 0			// '0 1
					if ((L00 <= iso) && (L10 <= iso) && (L01 <= iso) && (L11 > iso)) this.dl(svg,xcenter,ybottom,xright,ycenter);
					// '0 0	// '1 0
					if ((L00 <= iso) && (L10 <= iso) && (L01 > iso) && (L11 <= iso)) this.dl(svg,xleft,ycenter,xcenter,ybottom);
					// '0 0		// '1 1
					if ((L00 <= iso) && (L10 <= iso) && (L01 > iso) && (L11 > iso)) this.dl(svg,xleft,ycenter,xright,ycenter);
					// '0 1		// '0 0
					if ((L00 <= iso) && (L10 > iso) && (L01<= iso) && (L11 <= iso))	this.dl(svg,xcenter, yTop,xright, ycenter);
					// '0 1			// '0 1
					if ((L00 <= iso) && (L10 > iso) && (L01<= iso) && (L11 > iso))	this.dl(svg,xcenter, yTop,xcenter, ybottom);
					//'0 1	//'1 0
					if ((L00 <= iso) && (L10 > iso) && (L01 > iso) && (iso) && (L11 <= iso)){
						var foo = 0;
						for (var i = 0; i < this.n-1; i++){
							var currentDist = this.distFunc(xcenter, ycenter, this.Points[0][i], this.Points[1][i]);
							if (currentDist < this.radius)	foo = foo + 1 - (currentDist / this.radius);
						}
						if (foo > iso) { this.dl(svg,xleft, ycenter,xcenter, yTop); this.dl(svg,xcenter, ybottom,xright, ycenter);
						}else{	this.dl(svg,xleft, ycenter,xcenter, ybottom);	this.dl(svg,xcenter, yTop,xright, ycenter);
						}
					}
					//'0 1	//'1 1
					if ((L00 <= iso) && (L10 > iso) && (L01 > iso) && (L11> iso)) this.dl(svg,xleft, ycenter,xcenter, yTop);
					// '1 0	// '0 0
					if ((L00 > iso) && (L10 <= iso) && (L01 <= iso) && (L11<= iso))		this.dl(svg,xleft, ycenter,xcenter, yTop);
					// '1 0	// '0 1
					if ((L00 > iso) && (L10 <= iso) && (L01 <= iso) && (L11> iso)){
						var foo = 0;
						for (var i = 0; i < this.n-1; i++){
							var currentDist = this.distFunc(xcenter, ycenter, this.Points[0][i], this.Points[1][i]);
							if (currentDist < this.radius)	foo = foo + 1 - (currentDist / this.radius);
						}
							if (foo > iso){	this.dl(svg,xcenter, yTop,xright, ycenter);	this.dl(svg,xleft, ycenter,xcenter, ybottom);
						}else{	this.dl(svg,xleft, ycenter,xcenter, yTop); this.dl(svg,xcenter, ybottom,xright, ycenter);	}
					}
					//'1 0	//'1 0
					if ((L00 > iso) && (L10 <= iso) && (L01 > iso) && (L11 <= iso) ) this.dl(svg,xcenter, yTop,xcenter, ybottom);
					//'1 0		//'1 1
					if ((L00 > iso) && (L10 <= iso) && (L01 > iso) && (L11 > iso) ) this.dl(svg,xcenter, yTop,xright, ycenter);
					//'1 1				//'0 0
					if ((L00 > iso) && (L10 > iso) && (L01 <= iso) && (L11 <= iso) ) this.dl(svg,xleft, ycenter,xright, ycenter);
					//'1 1	//'0 1
					if ((L00 > iso) && (L10 > iso) && (L01 < iso) && (L11 > iso)) 	this.dl(svg,xleft,ycenter,xcenter,ybottom);
					//'1 1			//'1 0
					if ((L00 > iso) && (L10 > iso) && (L01 > iso) && (L11 <= iso))	this.dl(svg,xcenter,ybottom,xright,ycenter);
					
					
				}
			}
		}
	return IsolinesArr;

	},
	
	// нарисовать линию - для моего кустарного метода
	dl: function(svg,x,y, x2,y2){
			var yScale = d3.scale.linear()
						.domain([0.5, 5])
						.range([0, objAnalys.boxHeight-50]);

			var xScale = d3.scale.linear()
					.domain([0, 0.7])
					.range([0, objAnalys.boxWidth]);	
		
		//	svg.append("line")
        //                .attr("x1", xScale(x))
        //                .attr("y1", yScale(y))
        //                .attr("x2", xScale(x2))
        //                .attr("y2", yScale(y2))
		//				.attr("stroke-width", 1)
        //                .attr("stroke", "black");
	},
	
	/** ---------------------------------------------------------------------------- **/
	/** ----------------------------------END--------------------------------------- **/
	/** ---------------------------------------------------------------------------- **/
	
	

};















