/*********************************************************************************
 Copyright (c) 2003-2006 Armin Burger
 
 Permission is hereby granted, free of charge, to any person obtaining 
 a copy of this software and associated documentation files (the "Software"), 
 to deal in the Software without restriction, including without limitation 
 the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 and/or sell copies of the Software, and to permit persons to whom the Software 
 is furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included 
 in all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 
 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR OR 
 COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
  USES THE JAVASCRIPT LIBRARIES JSGRAPHICS FROM WALTER ZORN
  SEE FILE /JAVASCRIPT/WZ_JSGRAPHICS.JS FOR DETAILS OF COPYRIGHT
  
 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 Modifications for polygon drawing provided by Federico Nieri 
 
**********************************************************************************/

// -------------------------
//  FUNCTIONS FOR MEASURING
// -------------------------

// ADAPT LINE COLOR
var lineColor = '#FF0000';

// ADAPT LINE WIDTH
var lineWidth = 2;

// ADAPT FACTOR FOR DISTANCE/AREA CALCULATION
// eg. 1000 for km, 1 for m
var calcFact = 1;

var numSize;

/** 
 * Return a Point object with geo coordinate instead of px coordinate
 * @param pxPoint: Point object with px coordinate
 */
function toGeoPoint(pxPoint){
	var x_geo = minx_geo + ((pxPoint.x/mapW)  * xdelta_geo);
	var y_geo = maxy_geo - ((pxPoint.y/mapH) * ydelta_geo);
	return new Point(x_geo,y_geo);
}

/** 
 * Return a Polygon object with geo coordinate instead of px coordinate
 * @param pxPolygon: Polygon object with px coordinate
 */
function toGeoPolygon(pxPolygon){
	var pxPoints = pxPolygon.getPoints();
	var geoPolygon = new Polygon();
	for(var i = 0; i < pxPoints.length; i++){
		geoPolygon.addPoint(toGeoPoint(pxPoints[i]));
	}
	return geoPolygon;
}

/**
 * Return a geography measure unit instead of px
 * @param pxLength: length in px
 */
function toGeoLength(pxLength){
	return (pxLength/mapW) * xdelta_geo;
}


var polyline = new Polygon();

/**
 * Main function, draws symbol points between mouseclicks
 * @return void
 */
function measureDrawSymbols(e, clickX, clickY, dblClick) {
    // Polyline points number before to add the current click point
    var nPoints = polyline.getPointsNumber();    
    // Reset everything when last measure ended with double click
    if (nPoints == 0) resetMeasure();        
    // Don't go outside map
    if ((clickX < mapW) && (clickY < mapH)) { 
        
        // SINGLE CLICK
        if (dblClick != 1) { 
	        
	        polyline.addPoint(new Point(clickX,clickY));
	        	        
        	// First point for start click
        	if (nPoints < 1) {
    			
        		drawLineSegment(clickX, clickY, clickX, clickY);         			

    		// Fill distance between clicks with symbol points
    		}else{
                                                              
                // USE wz_jsgraphics.js TO DRAW LINE. lastSegment is of Line type                 
                var lastSegment = polyline.getLastSide();                
                drawLineSegment(lastSegment.getFirstPoint().x, lastSegment.getFirstPoint().y, lastSegment.getSecondPoint().x, lastSegment.getSecondPoint().y);                
                // calls the handler of the side (segment) digitation and pass it the polyline in px coords
                onDigitizedSide(polyline);
                                                
        	}      	        	        	        	                                  
                        	
        // DOUBLE CLICK => CALCULATE AREA
        } else if (dblClick) {
                        	            	    		    	
	    	// Removes the last duplicated point because of the last 2 single click	    	
	    	polyline.delPoint(polyline.getPointsNumber()-1);
	    	// Closing the polyline to have a polygon
	    	polyline.close();	    	
	    	// fix the last side	    	
	    	var lastSegment = polyline.getLastSide();	    		
	    	if(lastSegment != null){    	
	    		drawLineSegment(lastSegment.getFirstPoint().x, lastSegment.getFirstPoint().y, lastSegment.getSecondPoint().x, lastSegment.getSecondPoint().y);           	
	    	}
           	// calls the handler of the polygon digitation before reset the polygon
           	onDigitizedPolygon(polyline);
            // remove all points from the polygon          
    		polyline.reset();
                        
        }                   
    }    
}


/** 
 * Handler of the digitized polygon action. It is called when a double click
 * close tha drawing polygon
 * @param poly: Polygon object passed to the handler
 */
function onDigitizedPolygon(poly){
	
	var polyGEO = toGeoPolygon(poly);
	var perimGEO = polyGEO.getPerimeter()/calcFact;	
	
    var cntPerLen = Math.round(perimGEO).toString().length;
    numSize = Math.max(0, (4 - cntPerLen));
    
    perimGEO = roundN(perimGEO, numSize); 
    
    var areaGEO = Math.abs(roundN (polyGEO.getArea() / (calcFact * calcFact), numSize-1)) ;
                
	// Change input text box to 'Area'
	document.measureForm.sumLen.value = perimGEO;
    document.getElementById("mSegTxt").innerHTML = localeList['Area']; 
    document.measureForm.segLen.value = areaGEO;
    
}

/** 
 * Handler of the digitized line action. It is called when a new click cause draw a new line
 * @param poly: Polygon object passed to the handler
 */
function onDigitizedSide(poly){
	// Polygon in map coordinates
	var polyGEO = toGeoPolygon(poly);
        
    // Segment length in  map coordinates,  write values to input boxes
    var segLenGEO_0 = polyGEO.getSideLength(polyGEO.getSidesNumber()) / calcFact ;
    var perimGEO_0  = polyGEO.getPerimeter() / calcFact ;
    
    var cntSegLen = Math.round(segLenGEO_0).toString().length;
    numSize = Math.max(0, (4 - cntSegLen));
    var segLenGEO = roundN(segLenGEO_0, numSize); 
	var perimGEO  = roundN(perimGEO_0, numSize);     

    document.measureForm.sumLen.value = perimGEO;
    document.measureForm.segLen.value = segLenGEO;
}

/**
 * REDRAW THE LAST AND THE CLOSING SIDE OF THE POLYGON
 */
function redrawAll(currX, currY) {

    if (polyline.getPointsNumber()>0) {    	
        jg.clear();
    	jg.setColor(lineColor); 
    	jg.setStroke(lineWidth); 
	    jg.drawPolyline(polyline.getXList(), polyline.getYList());
      		
	    // Drawing last side	    
	    var lastPoint = polyline.getPoint(polyline.getPointsNumber()-1);
	    jg.drawLine(lastPoint.x, lastPoint.y, currX, currY);
	    
  	    // Drawing closing side  	      	    
	    jg.setStroke(Stroke.DOTTED); 
	    var firstPoint = polyline.getPoint(0);
	    jg.drawLine(firstPoint.x, firstPoint.y, currX, currY);
	    
	    jg.paint();
	}		    

}

/**
 * DRAW LINE USING JSGRAPHICS
 */
function drawLineSegment(xfrom, yfrom, xto, yto) {
    jg.setColor(lineColor); 
    jg.setStroke(lineWidth); 
    jg.drawLine(xfrom, yfrom, xto, yto); 
    jg.paint();
}


/**
 * Remove all measure settings
 */
function resetMeasure() {
    // remove lines
    jg.clear();
    
    // Reset form fields 
    if (document.measureForm) {
        document.measureForm.sumLen.value = '';
        document.measureForm.segLen.value = '';
        document.getElementById("mSegTxt").innerHTML = localeList['Segment']; 
    }    
}


/**
 * Round to a specified decimal
 */
function roundN(numin, rf) {
    return ( Math.round(numin * Math.pow(10, rf)) / Math.pow(10, rf) );
} 

