OpenLayers – How to Display Segment Lengths with OpenLayers Measure Control?

Measurementsopenlayers-2

I am trying to make a OpenLayers measure tool that displays the length of each segment on top of each segment and the total length of the measurement as shown below:

Measure control with length of each segment

I have used this example http://openlayers.org/dev/examples/measure.html.
I can see in the example that the geometry created is one big LineString.

Therefore my general thought was to get the measure control to create a new line segment (LineString) for each of the user click except the first,
then add an attribute with the segment length and display it with the label parameter in the style.

But I don't know if it will conflict with the current design of the measure control or if this is the correct approach to my problem?

All comments or guidance would be appreciated.

Best Answer

Your suggestions sounds fine. Also every geometry object has a distanceTo() function which can be used like:

geometry.distanceTo(anothergeometry)

EDIT:

After more thought and testing the example, i think it would be easiest for you add new layer for labeling purposes. Possibly a layer of just points which you would set the labelXOffset and labelYOffset to half the distance between each point in your measuring linestring. But i don't think you'll be able to rotate the labels.

Look at how this measure tool is, it's probably the best you'll be able to do: http://chamaps.com/watervliet/

Check out how he does it: http://chamaps.com/watervliet/js/map.js

var lineStyle = new OpenLayers.Style();
lineStyle.addRules([
new OpenLayers.Rule({
    symbolizer: linemeasureStyles
})]);
var linemeasureStyleMap = new OpenLayers.StyleMap({
    "default": lineStyle
});
var length = new OpenLayers.Control.Measure(OpenLayers.Handler.Path, {
    displaySystem: "english",
    geodesic: true,
    persist: true,
    handlerOptions: {
        layerOptions: {
            styleMap: linemeasureStyleMap
        }
    },
    textNodes: null,
    callbacks: {
        create: function () {
            this.textNodes = [];
            layerRuler.removeFeatures(layerRuler.features);
            mouseMovements = 0;
        },
        modify: function (point, line) {
            if (mouseMovements++ < 5) {
                return;
            }
            var len = line.geometry.components.length;
            var from = line.geometry.components[len - 2];
            var to = line.geometry.components[len - 1];
            var ls = new OpenLayers.Geometry.LineString([from, to]);
            var dist = this.getBestLength(ls);
            if (!dist[0]) {
                return;
            }
            var total = this.getBestLength(line.geometry);
            var label = dist[0].toFixed(2) + " " + dist[1];
            var textNode = this.textNodes[len - 2] || null;
            if (textNode && !textNode.layer) {
                this.textNodes.pop();
                textNode = null;
            }
            if (!textNode) {
                var c = ls.getCentroid();
                textNode = new OpenLayers.Feature.Vector(
                new OpenLayers.Geometry.Point(c.x, c.y), {}, {
                    label: '',
                    fontColor: "#FF0000",
                    fontSize: "14px",
                    fontFamily: "Arial",
                    fontWeight: "bold",
                    labelAlign: "cm"
                });
                this.textNodes.push(textNode);
                layerRuler.addFeatures([textNode]);
            }
            textNode.geometry.x = (from.x + to.x) / 2;
            textNode.geometry.y = (from.y + to.y) / 2;
            textNode.style.label = label;
            textNode.layer.drawFeature(textNode);
            this.events.triggerEvent("measuredynamic", {
                measure: dist[0],
                total: total[0],
                units: dist[1],
                order: 1,
                geometry: ls
            });
        }
    }
});
Related Question