[ka-Map-users] Ruler tool
Stéphane RIFF
stephane.riff at cerene.fr
Wed Sep 13 11:16:34 EDT 2006
Hello,
I have developped a Ruler tool based on the kaTool prototype.
I don't know it's perfect (maybe not) but it's enough for my needs.
If someone is interested I send the code
Thanks,
Steff
/**********************************************************************
*
*
* purpose: a simple tool for measuring distance
*
* author: RIFF Stéphane
*
*
**********************************************************************
*
* Copyright (c) 2005, DM Solutions Group Inc.
*
* 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 AUTHORS OR COPYRIGHT HOLDERS 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.
*
**********************************************************************
*
* To use this tool:
*
* 1) add a script tag to your page
*
* <script type="text/javascript" src="myKaRuler.js"></script>
*
* 2) create a new instance of myKaRuler
*
* myKaRuler = new myKaRuler( myKaMap);
*
* 3) provide some way of activating it. This example would allow switching
* between querying and navigating.
*
* <input type="button" name="navigate" value="Navigate"
* onclick="myKaNavigator.activate()">
* <input type="button" name="query" value="Query"
* onclick="myKaQuery.activate()">
* <input type="button" name="ruler" value="Measuring"
* onclick="myKaRuler.activate()">
*
*
*
*****************************************************************************/
/**
* myKaRuler constructor
*
* construct a new myKaRuler object of a given type for a given kaMap
instance
*
* oKaMap - a kaMap instance
*
*/
function myKaRuler( oKaMap ) {
kaTool.apply( this, [oKaMap] );
this.name = 'myKaRuler';
this.cursor = 'default';
this.canvas = null;
// the units abrevations (if map units is DD, the distance is in
kilometers)
this.unitsAbrevations = new Array("ft","in","km","m","mi","km");
//this is the HTML element that is visible
this.domObj = document.createElement( 'div' );
this.domObj.id = 'measureResult';
this.domObj.style.position = 'absolute';
this.domObj.style.top = '-300px';
this.domObj.style.left = '-300px';
this.domObj.style.width = '150px';
this.domObj.style.height = '65px';
this.domObj.style.zIndex = 300;
this.domObj.style.visibility = 'hidden';
this.domObj.style.backgroundColor = 'white';
this.domObj.style.border = '1px solid #999999';
this.domObj.style.fontFamily = 'Verdana, Arial';
this.domObj.style.fontSize = '10px';
document.body.appendChild( this.domObj );
// the jsgraphic object
this.jg = null;
// store the user clicks coordinates
this.startx = null;
this.starty = null;
this.endx = null;
this.endy = null;
// the total polyline length
this.total = 0.0;
this.input = getRawObject('coords');
for (var p in kaTool.prototype) {
if (!myKaRuler.prototype[p])
myKaRuler.prototype[p]= kaTool.prototype[p];
}
};
/**
* activate this tool. Activating the tool causes any existing tools to be
* deactivated.
*/
myKaRuler.prototype.activate = function() {
this.kaMap.activateTool( this );
document.kaCurrentTool = this;
this.domObj.innerHTML = "<h3> Seg : <input type='text'
id='measureSeg'
style='border:none;background-color:transparent;width:75px;' />
"+this.unitsAbrevations[this.kaMap.getCurrentMap().units]+"<br><br> Tot
: <input type='text' id='measureTot'
style='border:none;background-color:transparent;width:75px;' />
"+this.unitsAbrevations[this.kaMap.getCurrentMap().units];
if(this.canvas == null){
this.canvas = this.kaMap.createDrawingCanvas( 300 );
this.canvas.id = "measureCanvas";
}
if(this.jg == null){
this.jg = new jsGraphics("measureCanvas");
this.jg.setColor("#ff0000");
this.jg.setStroke(3);
}
this.domObj.style.visibility='visible';
};
/**
* deactivate this tool.
*/
myKaRuler.prototype.deactivate = function() {
this.kaMap.deactivateTool( this );
document.kaCurrentTool = null;
this.jg.clear();
this.jg=null;
this.kaMap.removeDrawingCanvas(this.canvas);
this.canvas=null;
this.domObj.style.visibility='hidden';
};
/*
* draw line representing the measure.
*
*/
myKaRuler.prototype.drawLine = function() {
this.jg.drawLine((this.startx-this.kaMap.xOrigin),
(this.starty-this.kaMap.yOrigin),
(this.endx-this.kaMap.xOrigin),
(this.endy-this.kaMap.yOrigin)); // co-ordinates related to "myCanvas"
this.jg.paint();
this.startx = this.endx;
this.starty = this.endy;
};
/**
* myKaRuler.onmouseout( e )
*
* called when the mouse leaves theInsideLayer. hide the result box
*
* e - object, the event object or null (in ie)
*/
myKaRuler.prototype.onmouseout = function(e) {
e = (e)?e:((event)?event:null);
if (!e.target) e.target = e.srcElement;
this.domObj.style.visibility='hidden';
};
/**
* myKaRuler.onmouseout( e )
*
* called when the mouse leaves theInsideLayer. show the result box
*
* e - object, the event object or null (in ie)
*/
myKaRuler.prototype.onmouseover = function(e) {
e = (e)?e:((event)?event:null);
if (!e.target) e.target = e.srcElement;
this.domObj.style.visibility='visible';
};
/**
* myKaRuler.onmousemove( e )
*
* called when the mouse moves over theInsideLayer.
*
* e - object, the event object or null (in ie)
*/
myKaRuler.prototype.onmousemove = function(e) {
e = (e)?e:((event)?event:null);
//show coordinate
var x = e.pageX || (e.clientX +
(document.documentElement.scrollLeft ||
document.body.scrollLeft));
var y = e.pageY || (e.clientY +
(document.documentElement.scrollTop || document.body.scrollTop));
var aPixPos = this.adjustPixPosition( x,y );
var geoCoo= this.kaMap.pixToGeo(aPixPos[0],aPixPos[1]);
var gX = geoCoo[0];
var gY = geoCoo[1];
var gX= (parseInt(gX*10000))/10000;
var gY= (parseInt(gY*10000))/10000;
if(this.input)
{
if(this.kaMap.getCurrentMap().units == 5)
this.input.value = "Lon.: "+gX+" Lat.: "+gY;
else
this.input.value = "X: "+gX+" Y: "+gY;
}
//**//
this.domObj.style.left = (e.clientX+5)+"px";
this.domObj.style.top = (e.clientY+5)+"px";
if(this.startx !== null)
{
this.endx=-aPixPos[0];
this.endy=-aPixPos[1];
if(this.kaMap.getCurrentMap().units == 5) {
document.getElementById("measureSeg").value =
this.measureSphericalDistance2Points(this.startx,this.starty,this.endx,this.endy);
}else{
document.getElementById("measureSeg").value =
this.measure2points(this.startx,this.starty,this.endx,this.endy);
}
}
return false;
}
;
/**
* myKaRuler.onmousedown( e )
*
* called when a mouse button is pressed over theInsideLayer.
*
* e - object, the event object or null (in ie)
*/
myKaRuler.prototype.onmousedown = function(e) {
e = (e)?e:((event)?event:null);
if (e.button==2) {
this.jg.clear();
this.startx=this.starty=this.endx=this.endy=null;
document.getElementById("measureSeg").value="0.0";
document.getElementById("measureTot").value="0.0";
this.total = 0.0;
return this.cancelEvent(e);
} else {
if (this.kaMap.isIE4) document.onkeydown =
kaTool_redirect_onkeypress;
document.onkeypress = kaTool_redirect_onkeypress;
var x = e.pageX || (e.clientX +
(document.documentElement.scrollLeft ||
document.body.scrollLeft));
var y = e.pageY || (e.clientY +
(document.documentElement.scrollTop ||
document.body.scrollTop));
var aPixPos = this.adjustPixPosition( x,y );
if(this.endx == null)
{
this.startx=this.endx=-aPixPos[0];
this.starty=this.endy=-aPixPos[1];
}
else
{
this.endx=-aPixPos[0];
this.endy=-aPixPos[1];
}
if(this.kaMap.getCurrentMap().units == 5) {
this.total +=
this.measureSphericalDistance2Points(this.startx,this.starty,this.endx,this.endy);
}else{
this.total +=
this.measure2points(this.startx,this.starty,this.endx,this.endy);
}
this.total = parseInt(this.total*100)/100;
document.getElementById("measureTot").value = this.total;
this.drawLine();
e.cancelBubble = true;
e.returnValue = false;
if (e.stopPropogation) e.stopPropogation();
if (e.preventDefault) e.preventDefault();
return false;
}
};
/**
* myKaRuler.onmouseup( e )
*
* called when a mouse button is clicked over theInsideLayer.
*
* e - object, the event object or null (in ie)
*/
myKaRuler.prototype.onmouseup = function(e) {
e = (e)?e:((event)?event:null);
return false;
};
/**
* myKaRuler.measureSphericalDistance2Points
*
* pix1,piy1 - pixel coordinates of the first point
* pix2,piy2 - pixel coordinates of the second point
*
* This function is used to calculate the distance between two points in
decimel degree unit.
* It assume that the earth is a perfect sphere, so the calculation isn't
accurate.
* In fact the further you are from the equator the least accurate the
calulation is.
*/
myKaRuler.prototype.measureSphericalDistance2Points =
function(pix1,piy1,pix2,piy2)
{
var pt1 = this.kaMap.pixToGeo(pix1,piy1);
var pt2 = this.kaMap.pixToGeo(pix2,piy2);
/* Convert all the degrees to radians */
var la1 = pt1[0] * Math.PI/180.0;
var lo1 = pt1[1] * Math.PI/180.0;
var la2 = pt2[0] * Math.PI/180.0;
var lo2 = pt2[1] * Math.PI/180.0;
/* Find the Great Circle distance */
var EARTH_RADIUS = 6378;//kilometers //3956;//miles
var distance =
Math.acos(Math.sin(la1)*Math.sin(la2)+Math.cos(la1)*Math.cos(la2)*Math.cos(lo2-lo1))
* EARTH_RADIUS ;
return distance ;
};
/**
* myKaRuler.measureSphericalDistance2Points
*
* p1X,p1Y - pixel coordinates of the first point
* p2X,p2Y - pixel coordinates of the second point
*
* This function is used to calculate the distance between two points in
planar projection.
* I use the Pythagor algorythm. The result unit is the same as the
projection unit and is round
* at two decimals.
*/
myKaRuler.prototype.measure2points = function(p1X,p1Y,p2X,p2Y)
{
// Diff X/Y between current new and previous click
var x_delta = p1X - p2X;
var y_delta = p1Y - p2Y;
// Segment length in Pixel
var segLenPix = Math.sqrt((Math.pow(x_delta, 2)) +
(Math.pow(y_delta, 2)));
// Segment length in map coordinates, write values to input boxes
var extent = this.kaMap.getGeoExtents();
var xdelta_geo = extent[2]-extent[0];
var segLenGEO = parseInt( ((segLenPix/this.kaMap.viewportWidth ) *
xdelta_geo)*100 )/100;
return segLenGEO;
};
More information about the ka-Map-users
mailing list