1

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?

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.

2

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;
}
3
  • 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
2

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; });
1

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}
      );
0

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;
2
  • 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
0

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
    });

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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