0

My problem:Add image along the LineString

My problem has been solved here, but when I add a 32x32 image and I draw between two points, the images in the line don't go straight and there's a slight gap in two or three pictures as shown in the figure. Why can't I draw a straight line between two points with the picture?

Linestring does not draw straight images

The last fiddle: http://jsfiddle.net/w4z3arc9/


I can do this in a nice way with dashed line method, but I can draw lines with a picture I want exactly. While doing so, the breaks at intersection are no longer important. When I draw a line between two points, I want to draw a straight line with the image that I selected without any spaces in the image.

enter image description here

Mathematically, I calculate the angle of a line and calculate how many images will be inserted along that line. Then I calculate the position of each picture. Normally, each new image must be added as a continuation of each other. But when I get closer to the figure, I see that the pictures in the line are not exactly equal to each other and there are some differences between them. What is the reason for this difference?

My mathematical calculation code:

function splitLineString(geometry, minSegmentLength, options) {

        function calculatePointsDistance(coord1, coord2) {
            var dx = coord1[0] - coord2[0];
            var dy = coord1[1] - coord2[1];
            return Math.sqrt(dx * dx + dy * dy);
        };

        function calculateSplitPointCoords(startNode, nextNode, distanceBetweenNodes, distanceToSplitPoint) {
            var d = distanceToSplitPoint / distanceBetweenNodes;
            var x = nextNode[0] + (startNode[0] - nextNode[0]) * d;
            var y = nextNode[1] + (startNode[1] - nextNode[1]) * d;
            return [x, y];
        };

        function calculateAngle(startNode, nextNode, alwaysUp) {

            var x = (nextNode[0] - startNode[0]);
            var y = (nextNode[1] - startNode[1]);
            var angle = Math.atan2(y, x);
            if (!alwaysUp) {
                angle = y < 0 && x < 0 ? angle * -1 : y < 0 && x == 0 ? Math.PI * 2 - angle : y < 0 && x > 0 ? angle * -1 : angle * -1;
            }
            return angle;
        };
        var splitPoints = [];
        var coords = geometry.getCoordinates();
        if (coords.length == 0 ) {
            debugger;
        }
        var coordIndex = 0;
        var startPoint = coords[coordIndex];
        var nextPoint = coords[coordIndex + 1];
        var angle = options.vertices || calculateAngle(startPoint, nextPoint, options.alwaysUp);

        var n = Math.ceil(geometry.getLength() / minSegmentLength);
        var segmentLength = geometry.getLength() / n;
        var midPoints = (options.midPoints && !options.vertices)
        var currentSegmentLength = midPoints ? segmentLength / 2 : segmentLength;

        console.log(n);

        for (var i = 0; i <= n; i++) {

            var distanceBetweenPoints = calculatePointsDistance(startPoint, nextPoint);
            currentSegmentLength += distanceBetweenPoints;

            if (currentSegmentLength < segmentLength) {
                coordIndex++;
                if (coordIndex < coords.length - 1) {
                    startPoint = coords[coordIndex];
                    nextPoint = coords[coordIndex + 1];
                    angle = options.vertices || calculateAngle(startPoint, nextPoint, options.alwaysUp);
                    if (options.vertices && (!options.extent || ol.extent.containsCoordinate(options.extent, startPoint))) {
                        splitPoints.push(startPoint);
                    }
                    i--;
                    continue;
                } else {
                    if (!midPoints) {
                        var splitPointCoords = nextPoint;
                        if (!options.extent || ol.extent.containsCoordinate(options.extent, splitPointCoords)) {
                            if (!options.vertices) { splitPointCoords.push(angle); }
                            splitPoints.push(splitPointCoords);
                        }
                    }
                    break;
                }
            } else {
                var distanceToSplitPoint = currentSegmentLength - segmentLength;
                var splitPointCoords = calculateSplitPointCoords(startPoint, nextPoint, distanceBetweenPoints, distanceToSplitPoint);
                startPoint = splitPointCoords.slice();
                if (!options.extent || ol.extent.containsCoordinate(options.extent, splitPointCoords)) {
                    if (!options.vertices) { splitPointCoords.push(angle); }
                    splitPoints.push(splitPointCoords);
                }
                currentSegmentLength = 0;
            }
        }

        return splitPoints;
    };

var style = function (feature, resolution) {

        var size = 32;
        var styles = [];
        var mapSize = map.getSize();

        var extent = map.getView().calculateExtent([mapSize[0] + (size * 2), mapSize[1] + (size * 2)]);

                    var splitPoints = splitLineString(geom, size * resolution, { alwaysUp: false, midPoints: true, extent: extent });

        splitPoints.forEach(function (point) {

            styles.push(new ol.style.Style({
                geometry: new ol.geom.Point([point[0], point[1]]),
                image: new ol.style.Icon({
                    src: 'https://lh3.googleusercontent.com/-BNhBReluCzc/XCYkBEGVV1I/AAAAAAAAARc/-7j0eR72Ovsaz9NHAgrDhWS0mR3JWi-agCL0BGAYYCw/h32/2018-12-28.png',
                    scale: 1,
                    rotation: point[2]
                })
            }));

        });

        return styles;
    }
4

There has to be a whole number of icons, so if you try to make the split segment lengths the same size as the icon there will always be some overlap (up to 32 pixels spread along the line). It's particularly noticeable with short linestrings, for example 48 pixels would break down to two 24 pixels segments and the 32 pixel icons centered at their midpoints would overlap by 8 pixels.

If you only need a line dash effect there is no need to use icons, the same effect can be produced by a solid stroke overlayed by a dashed darker stroke (these are the color codes picked from the icon you are using)

styles: [
   new ol.style.Style({
       stroke: new ol.style.Stroke({
           width: 4,
           color: '#7af500'
       })
   }),
   new ol.style.Style({
       stroke: new ol.style.Stroke({
           width: 4,
           color: '#55aa00',
           lineDash: [7,9]
       })
   })
],

Icons will cause problems on sharp curves on rail lines, they are straight and don't bend with the track

enter image description here

Dashed stroke is perfect for rail lines and there's no calculation overhead http://mikenunn.16mb.com/demo/glasgow-rail.html But if you need to show trains at regular intervals along the lines then you will need icons!

enter image description here

  • I'm going to use a picture when I draw a line. For example, I will choose a railroad picture and draw a path. I don't understand exactly how to solve it – Onur Ek. Jan 14 at 17:55

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.