[ka-Map-users] Area measurement tool
Jordi Cerdà
jordieumoll at gmail.com
Mon Jan 28 07:09:57 EST 2008
Hello,
We have developped an Area measurement tool based on the kaTool prototype.
It's not perfect but it's enough for our needs.
If someone is interested I send the code
Thanks,
Jordi
/**********************************************************************
*
*
* purpose: a simple tool for measuring area
*
*
*
**********************************************************************
*
* To use this tool:
*
* 1) add a script tag to your page
*
* <script type="text/javascript" src="myKaArea.js"></script>
*
* 2) create a new instance of myKaRuler
*
* myKaArea = new myKaArea( myKaMap);
*
* 3) provide some way of activating it.
*
* <img id="toolArea" onclick="switchMode(this.id)" title="Area"
alt="mesurar area" src="images/a_pixel.gif" >
*
*
*
*****************************************************************************/
/**
* myKaArea constructor
*
* construct a new myKaArea object of a given type for a given kaMap
instance
*
* oKaMap - a kaMap instance
*
*/
function myKaArea( oKaMap ) {
kaTool.apply( this, [oKaMap] );
this.name = 'myKaArea';
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;
this.arrayX = new Array();
this.arrayY = new Array();
this.nPunts = 0;
// the total polyline length
this.total = 0.0;
this.input = getRawObject('coords');
for (var p in kaTool.prototype) {
if (!myKaArea.prototype[p])
myKaArea.prototype[p]= kaTool.prototype[p];
}
};
/**
* activate this tool. Activating the tool causes any existing tools to be
* deactivated.
*/
myKaArea.prototype.activate = function() {
this.kaMap.activateTool( this );
document.kaCurrentTool = this;
this.domObj.innerHTML = "<h3> Àrea: <input
type='text' id='measureTot'
style='border:none;background-color:transparent;width:75px;' />" +
this.unitsAbrevations[this.kaMap.getCurrentMap().units] +"2";
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.
*/
myKaArea.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.
*
*/
myKaArea.prototype.drawPolygon = function() {
var i = 0;
this.jg.clear();
for (i=1;i<this.nPunts;i++)
{
this.jg.drawLine(
(this.arrayX[i-1]-this.kaMap.xOrigin), (this.arrayY[i-1]-this.kaMap.yOrigin),
(this.arrayX[i]-this.kaMap.xOrigin),
(this.arrayY[i]-this.kaMap.yOrigin)); // co-ordinates related to
"myCanvas"
}
this.jg.drawLine((this.arrayX[0]-this.kaMap.xOrigin),
(this.arrayY[0]-this.kaMap.yOrigin),
(this.arrayX[this.nPunts-1]-this.kaMap.xOrigin),
(this.arrayY[this.nPunts-1]-this.kaMap.yOrigin)); // co-ordinates
related to "myCanvas"
this.jg.paint();
this.measurePolygonArea();
this.startx = this.endx;
this.starty = this.endy;
};
/**
* myKaArea.onmouseout( e )
*
* called when the mouse leaves theInsideLayer. hide the result box
*
* e - object, the event object or null (in ie)
*/
myKaArea.prototype.onmouseout = function(e) {
e = (e)?e:((event)?event:null);
if (!e.target) e.target = e.srcElement;
this.domObj.style.visibility='hidden';
};
/**
* myKaArea.onmouseout( e )
*
* called when the mouse leaves theInsideLayer. show the result box
*
* e - object, the event object or null (in ie)
*/
myKaArea.prototype.onmouseover = function(e) {
e = (e)?e:((event)?event:null);
if (!e.target) e.target = e.srcElement;
this.domObj.style.visibility='visible';
};
/**
* myKaArea.onmousemove( e )
*
* called when the mouse moves over theInsideLayer.
*
* e - object, the event object or null (in ie)
*/
myKaArea.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);
// document.getElementById("measureSeg").value =
parseFloat(this.measurePolygonArea());
}
*/
}
return false;
}
;
/**
* myKaArea.onmousedown( e )
*
* called when a mouse button is pressed over theInsideLayer.
*
* e - object, the event object or null (in ie)
*/
myKaArea.prototype.onmousedown = function(e) {
e = (e)?e:((event)?event:null);
if (e.button==2) {
this.jg.clear();
this.jg.clear();
this.startx=this.starty=this.endx=this.endy=null;
//document.getElementById("measureSeg").value="0.0";
document.getElementById("measureTot").value="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.arrayX[0]=this.startx=this.endx=-aPixPos[0];
this.arrayY[0]=this.starty=this.endy=-aPixPos[1];
this.nPunts=1;
}
else
{
this.arrayX[this.nPunts]=this.endx=-aPixPos[0];
this.arrayY[this.nPunts]=this.endy=-aPixPos[1];
this.nPunts++;
}
/* 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.drawPolygon();
this.total = this.measurePolygonArea();
document.getElementById("measureTot").value = parseInt(this.total*100)/100;
e.cancelBubble = true;
e.returnValue = false;
if (e.stopPropogation) e.stopPropogation();
if (e.preventDefault) e.preventDefault();
return false;
}
};
/**
* myKaArea.onmouseup( e )
*
* called when a mouse button is clicked over theInsideLayer.
*
* e - object, the event object or null (in ie)
*/
myKaArea.prototype.onmouseup = function(e) {
e = (e)?e:((event)?event:null);
return false;
};
/**
* myKaArea.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.
*/
myKaArea.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 ;
};
// Implementació del càlcul de l'àrea basada en
http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/
// Funciona amb polígons simples (sense encreuaments), tant convexos com còncavs
myKaArea.prototype.measurePolygonArea = function()
{
if (this.nPunts<3)
return 0.0;
else
{
var totalArea = 0;
var i,j;
var pi,pj;
for (i=0;i<this.nPunts;i++) {
j = (i + 1) % this.nPunts;
pi = this.kaMap.pixToGeo(this.arrayX[i],this.arrayY[i]);
pj = this.kaMap.pixToGeo(this.arrayX[j],this.arrayY[j]);
totalArea += Math.abs(pi[0]) * Math.abs(pj[1]);
totalArea -= Math.abs(pi[1]) * Math.abs(pj[0]);
}
totalArea /= 2;
return Math.abs(totalArea);
}
};
/*
// Implementació del càlcul de l'àrea basada en triangles, però que
només funciona amb polígons convexos
myKaArea.prototype.measurePolygonArea = function()
{
if (this.nPunts<3)
return 0.0;
else
{
var i;
var p0,p1,p2;
var totalArea=0.0,area2=0.0;
p0 = this.kaMap.pixToGeo(this.arrayX[0],this.arrayY[0]);
for (i=1;i<this.nPunts-1;i++)
{
p1 = this.kaMap.pixToGeo(this.arrayX[i],this.arrayY[i]);
p2 = this.kaMap.pixToGeo(this.arrayX[i+1],this.arrayY[i+1]);
//window.alert("p0="+p0[0]+";"+p0[1] +"\np1="+p1[0]+";"+p1[1]
+"\np2="+p2[0]+";"+p2[1]);
var triangleArea = Math.abs(
Math.abs(p0[0]*p2[1])-Math.abs(p0[0]*p1[1])+Math.abs(p1[0]*p0[1])-Math.abs(p1[0]*p2[1])+Math.abs(p2[0]*p1[1])-Math.abs(p2[0]*p0[1])
);
triangleArea *= 0.5;
//window.alert("Area triangle="+triangleArea);
totalArea += triangleArea;
}
area2=this.measurePolygonArea2();
window.alert("Area total 1 = "+totalArea + ". Area total 2 = "+area2);
return totalArea;
}
};
*/
/**
* myKaArea.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.
*/
myKaArea.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