Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

OpenLayers has a OpenLayers.Control.Measure class to implement a measure tool.

There is a measure and measure-partial event, both which are passed a variable containing the total distance. Is it possible to get the last segment length?

Thanks,

CLARIFY: When I say last segment length ... you see how you can draw 2 or 3 lines in one go and it will give you the total distance drawn across all lines? That's great. What I'm after is the length of the last line the user drew only.

share|improve this question
add comment

5 Answers

see the exemple on openlayers website and have a glance to the source code, adapting it you will be able to get the length of last segment

I would quickly adapt the code like that (not tested) :

function handleMeasurements(event) {
        var geometry = event.geometry;
        var units = event.units;
        var order = event.order;
        var measure = event.measure;
        var element = document.getElementById('output');

        var out = "";
        if(order == 1) {
            out += measure.toFixed(3);
        } else {
            out += measure.toFixed(3);
        }
        alert("Latest segment length : " + (element.value - out))
        element.innerHTML = out;
}
share|improve this answer
    
That is in fact the sample I worked off. I can't see anything in there about segment length, only total length. Could you point me to it? –  James Feb 22 '11 at 15:21
    
See my edited first post for a minimalist and not tested adaptation –  simo Feb 22 '11 at 15:53
    
This is the approach I am now trying, but you forgot to account for what happens when the user finishes one measurement and starts another. You have to set the counter back to zero in those cases. Am already working on code to do this .... –  James Feb 22 '11 at 16:03
add comment

event.geometry is an OpenLayers.Geometry.LineString (or Polygon); it will have a .components array attached to it, which is a list of points. That list of points will be coordinates projected in the projection of your map.

To get the distance between any given set of the coordinates, you can reproject the geometry to LonLat:

var geometry = geometry.clone().transform(
    new OpenLayers.Projection("yourprojection"), 
    new OpenLayers.Projection("EPSG:4326"))` 

Then you can use the Vincenty distance calculation to get the length of the last section:

      p1 = geometry.components[geometry.components.length-1];
      p2 = geometry.components[geometry.components.length-2];
      length = OpenLayers.Util.distVincenty(
            {lon: p1.x, lat: p1.y}, {lon: p2.x, lat: p2.y}
      );
share|improve this answer
add comment

How to calculate the length of each segment:

var vertices = event.geometry.getVertices();
var units = event.units;
var out = "Total distance: " + event.measure.toFixed(3) + " " + units + "<br/>";

var projection = new OpenLayers.Projection(map.projection);
for (var i = 0; i <= vertices.length - 2; i++) {
    out += "Segment " + (i + 1) + " :<br/>";
    var point1 = new OpenLayers.Geometry.Point(vertices[i].x, vertices[i].y);
    var point2 = new OpenLayers.Geometry.Point(vertices[i + 1].x, vertices[i + 1].y);
    var segment = new OpenLayers.Geometry.LineString([point1, point2]);
    var dist = segment.getGeodesicLength(projection);
    out += "Distance: " + dist.toFixed(3) + " " + units + "<br/>";
}

$("#output").html(function() { return out; });
share|improve this answer
add comment

http://openlayers.org/dev/examples/measure.html

handles use of geodesic measures & use of immediate measures

        function handleMeasurements(event) {
        var geometry = event.geometry;
        var units = event.units;
        var order = event.order;
        var measure = event.measure;
        var element = document.getElementById('output');
        var out = "";
        if(order == 1) {
            out += "measure: " + measure.toFixed(3) + " " + units;
        } else {
            out += "measure: " + measure.toFixed(3) + " " + units + "<sup>2</" + "sup>";
        }
        element.innerHTML = out;
share|improve this answer
    
That's total length not segment length. –  James Feb 22 '11 at 15:23
    
event.measure is collecting segment lengths and this is accumulated to obtain the total length. So you just need to collect the segments in an array. –  Mapperz Feb 22 '11 at 15:37
add comment
up vote 0 down vote accepted

Here's how I did it with 3 separate event handlers ...

var lastMeasure = 0.0;

function measurementToolActivated() {
    lastMeasure = 0.0;
}

function handleFinalMeasurement(event) {
    var units = event.units;
    var measure = event.measure;
    var out = "measure: " + measure.toFixed(3) + " " + units;
    if (lastMeasure > 0) {
        out += "    last segment: " + (measure-lastMeasure).toFixed(3) + " " + units;
    }
    lastMeasure = 0.0;  
    $('#Message').html(out);
}

function handlePartialMeasurement(event) {
    var units = event.units;
    var measure = event.measure;
    var out = "measure: " + measure.toFixed(3) + " " + units;
    if (lastMeasure > 0) {
        out += "    last segment: " + (measure-lastMeasure).toFixed(3) + " " + units;
    }
    lastMeasure = measure;
    $('#Message').html(out);
}

So set up the event handlers

mapMeasureControl.events.on({
        "measure": handleFinalMeasurement,
        "measurepartial": handlePartialMeasurement,
        "activate": measurementToolActivated
    });
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.