[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>&nbsp;Seg : <input type='text' 
id='measureSeg' 
style='border:none;background-color:transparent;width:75px;' /> 
"+this.unitsAbrevations[this.kaMap.getCurrentMap().units]+"<br><br>&nbsp;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