<commit_before>L.GeomUtils = (function() {
    var self;
    return self = {

        // Calculate if a point p is between a and b
        isBetween: function(x, a, b, epsilon) {
            epsilon = epsilon || 0.5;
            var d = x.distanceTo(a) + x.distanceTo(b) - a.distanceTo(b);
            return d < epsilon;
        },

        // Use LatLng
        getPercentageDistanceFromPolyline: function(ll, polyline) {
            // Will test every point, considering a point is in a segment with an error of 2 meters
            return self.getPercentageDistance(ll, polyline.getLatLngs(), 5 /* in meters */, true);
        },

        // May be used for performance issue but you will loose precision
        getPercentageDistanceFromPolylineAsPoints: function(point, polyline) {
            return self.getPercentageDistance(point, polyline._parts[0], 5, true);
        },

        // You may pass latlng or point to this function
        getPercentageDistance: function(x, xs, epsilon, only_first) {
            var xs_len = 0.0
              , distance_found = false
              , closest_idx = null
              , distance = Number.MAX_VALUE;

            for (var i = 0; i < xs.length - 1; i++) {
                var x1 = xs[i], x2 = xs[i+1];

                // We iterate on each segment of the path
                if (!distance_found || !only_first) {
                    if (self.isBetween(x, x1, x2, epsilon)) {
                        distance_found = true;
                        xdistance = xs_len + x.distanceTo(x1);

                        if (only_first || xdistance < distance) {
                            distance = xdistance;
                            closest_idx = i;
                        }
                    }
                }

                xs_len += x1.distanceTo(x2);
            }
            
            if (!distance_found) {
                console.warn('Could not find ' + x + ' in ' + xs);
                return null;
            }
            var percent = Math.round((distance / xs_len)*100)/100;
            return { 'distance': percent, 'closest': closest_idx };
        },

        getLatLngFromPos: function(map, polyline, pos_list, equal_delta) {
            equal_delta === equal_delta === undefined ? 2 /*in meters*/ : equal_delta;

            // Safety check : should be ordered and 0.0 <= X <=1.0!
            $.each(pos_list, function(i, pos) {
                var prev_pos = pos[i - 1];
                var sorted = prev_pos === undefined ? true : pos > prev_pos;
                if (! (pos >= 0 && pos <= 1 && sorted)) {
                    throw 'Wrong value: ' + pos_list;
                }
            });

            // Polyline related
            var polyline_lls = polyline.getLatLngs();
            var d_len = self.getDistances(polyline_lls)
              , polyline_len = d_len.length
              , polyline_distances = d_len.distances;

            // Simple situation... simple solution.
            if (pos_list.length == 1) {
                 if (pos_list[0] == 0.0) return [self.cloneLatLng(polyline_lls[0])];
                 if (pos_list[0] == 1.0) return [self.cloneLatLng(polyline_lls[polyline_lls.length-1])];
            }

            var ds = $.map(pos_list, function(pos) { return polyline_len * pos; });

            var res = [];
            var i;

            var current_distance = ds.shift()
              , current_geom = [];

            // If pos is 0.0, take first latlng
            if (current_distance == 0.0) {
                res.push(self.cloneLatLng(polyline_distances[0].x1));
                current_distance = ds.shift()
            }

            for (i = 0; i < polyline_distances.length; i++) {
                var dist = polyline_distances[i];
                var new_acc = dist.acc + dist.distance;

                var delta = Math.abs(current_distance - new_acc)
                var distance_equal = delta < equal_delta;

                if (distance_equal || current_distance < new_acc) {
                    if (distance_equal) {
                        // Same point
                        res.push(self.cloneLatLng(dist.x2));
                    } else { 
                        // current_distance < new_acc
                        // New point

                        var dist_from_point = current_distance - dist.acc;
                        var ratio_dist = dist_from_point / dist.distance;
                        var ll = self.getPointOnLine(map, ratio_dist, dist.x1, dist.x2);

                        res.push(ll);
                    }

                    if (ds.length == 0) break;
                    current_distance = ds.shift()
                }
            }

            if (res.length < 1) console.warn("Could not get LatLng from position " + pos_list);
            if (window.DEBUG) {
                console.log("Invert getLatLngFromPos("+ pos_list[0] + ") : " +
                            JSON.stringify(self.getPercentageDistanceFromPolyline(res[0], polyline)));
            }
            return res;
        },

        cloneLatLng: function(latlng) {
            return new L.LatLng(latlng.lat, latlng.lng);
        },

        getPointOnLine: function(map, ratio_dist, ll1, ll2) {
            if (ratio_dist == 0.0) return ll1;
            if (ratio_dist == 1.0) return ll2;
            var zoom = map.getMaxZoom()
              , p1 = map.project(ll1, zoom)
              , p2 = map.project(ll2, zoom)
              , d = p1.distanceTo(p2);

            var x_new = p1.x + (p2.x - p1.x) * ratio_dist
              , y_new = p1.y + (p2.y - p1.y) * ratio_dist
              , ll_new = map.unproject(new L.Point(x_new, y_new), zoom);
            console.assert(!ll_new.equals(ll1) && !ll_new.equals(ll2), ratio_dist + ' got extremity (margin is ' + L.LatLng.MAX_MARGIN + ')');
            return ll_new;
        },

        getGradient: function(x1, y1, x2, y2) {
            var a = (y2 - y1) / (x2 - x1);
            var b = y1 - (a * x1);
            return {'a': a, 'b': b};
        },

        getDistances: function(xs) {
            var xs_len = 0.0, d, distances = [];

            for (var i = 0; i < xs.length - 1; i++) {
                var x1 = xs[i], x2 = xs[i+1];
                d = x1.distanceTo(x2);

                // acc: so far (without distance)
                distances.push({
                    'i1': i, 'i2': i+1,
                    'x1': x1, 'x2': x2,
                    'acc': xs_len, 'distance': d
                });

                xs_len += d
            }
            return {'length': xs_len, 'distances': distances};
        },

        // Calculate length (works for either points or latlngs)
        length: function(xs) {
            var xs_len = 0;
            for (var i = 0; i < xs.length - 1; i++) {
                xs_len += xs[i].distanceTo(xs[i+1]);
            }
            return xs_len;
        },

        distance: function (map, latlng1, latlng2) {
            return map.latLngToLayerPoint(latlng1).distanceTo(map.latLngToLayerPoint(latlng2));
        },

        distanceSegment: function (map, latlng, latlngA, latlngB) {
            var p = map.latLngToLayerPoint(latlng),
               p1 = map.latLngToLayerPoint(latlngA),
               p2 = map.latLngToLayerPoint(latlngB);
            return L.LineUtil.pointToSegmentDistance(p, p1, p2);
        },

        latlngOnSegment: function (map, latlng, latlngA, latlngB) {
            var p = map.latLngToLayerPoint(latlng),
               p1 = map.latLngToLayerPoint(latlngA),
               p2 = map.latLngToLayerPoint(latlngB);
               closest = L.LineUtil.closestPointOnSegment(p, p1, p2);
            return map.layerPointToLatLng(closest);
        },

        closestOnLine: function (map, latlng, linestring) {
            return self.closestOnLatLngs(map, latlng, linestring.getLatLngs());
        },

        closestOnLatLngs: function (map, latlng, lls) {
            // Iterate on line segments
            var segmentmindist = Number.MAX_VALUE,
                ll = null;
            // Keep the closest point of all segments
            for (var j = 0; j < lls.length - 1; j++) {
                var p1 = lls[j],
                    p2 = lls[j+1],
                    d = self.distanceSegment(map, latlng, p1, p2);
                if (d < segmentmindist) {
                    segmentmindist = d;
                    ll = self.latlngOnSegment(map, latlng, p1, p2);
                }
            }
            return ll;
        },

        closest: function (map, marker, snaplist, snap_distance) {
            var mindist = Number.MAX_VALUE,
                 chosen = null,
                 point = null;
            var n = snaplist.length;
            // /!\ Careful with size of this list, iterated at every marker move!<commit_msg>Fix snap at loading with low zoom<commit_after>L.GeomUtils = (function() {
    var self;
    return self = {

        // Calculate if a point p is between a and b
        isBetween: function(x, a, b, epsilon) {
            epsilon = epsilon || 0.5;
            var d = x.distanceTo(a) + x.distanceTo(b) - a.distanceTo(b);
            return d < epsilon;
        },

        // Use LatLng
        getPercentageDistanceFromPolyline: function(ll, polyline) {
            // Will test every point, considering a point is in a segment with an error of 2 meters
            return self.getPercentageDistance(ll, polyline.getLatLngs(), 5 /* in meters */, true);
        },

        // May be used for performance issue but you will loose precision
        getPercentageDistanceFromPolylineAsPoints: function(point, polyline) {
            return self.getPercentageDistance(point, polyline._parts[0], 5, true);
        },

        // You may pass latlng or point to this function
        getPercentageDistance: function(x, xs, epsilon, only_first) {
            var xs_len = 0.0
              , distance_found = false
              , closest_idx = null
              , distance = Number.MAX_VALUE;

            for (var i = 0; i < xs.length - 1; i++) {
                var x1 = xs[i], x2 = xs[i+1];

                // We iterate on each segment of the path
                if (!distance_found || !only_first) {
                    if (self.isBetween(x, x1, x2, epsilon)) {
                        distance_found = true;
                        xdistance = xs_len + x.distanceTo(x1);

                        if (only_first || xdistance < distance) {
                            distance = xdistance;
                            closest_idx = i;
                        }
                    }
                }

                xs_len += x1.distanceTo(x2);
            }
            
            if (!distance_found) {
                console.warn('Could not find ' + x + ' in ' + xs);
                // Try with closest point.
                var seg = L.GeomUtils.closestSegment(x, xs)
                  , p = L.LineUtil.closestPointOnSegment(x, seg[0], seg[1]);
                return L.GeomUtils.getPercentageDistance(p, xs, epsilon, only_first);
            }
            var percent = Math.round((distance / xs_len)*10000)/10000;
            return { 'distance': percent, 'closest': closest_idx };
        },

        getLatLngFromPos: function(map, polyline, pos_list, equal_delta) {
            equal_delta === equal_delta === undefined ? 2 /*in meters*/ : equal_delta;

            // Safety check : should be ordered and 0.0 <= X <=1.0!
            $.each(pos_list, function(i, pos) {
                var prev_pos = pos[i - 1];
                var sorted = prev_pos === undefined ? true : pos > prev_pos;
                if (! (pos >= 0 && pos <= 1 && sorted)) {
                    throw 'Wrong value: ' + pos_list;
                }
            });

            // Polyline related
            var polyline_lls = polyline.getLatLngs();
            var d_len = self.getDistances(polyline_lls)
              , polyline_len = d_len.length
              , polyline_distances = d_len.distances;

            // Simple situation... simple solution.
            if (pos_list.length == 1) {
                 if (pos_list[0] == 0.0) return [self.cloneLatLng(polyline_lls[0])];
                 if (pos_list[0] == 1.0) return [self.cloneLatLng(polyline_lls[polyline_lls.length-1])];
            }

            var ds = $.map(pos_list, function(pos) { return polyline_len * pos; });

            var res = [];
            var i;

            var current_distance = ds.shift()
              , current_geom = [];

            // If pos is 0.0, take first latlng
            if (current_distance == 0.0) {
                res.push(self.cloneLatLng(polyline_distances[0].x1));
                current_distance = ds.shift()
            }

            for (i = 0; i < polyline_distances.length; i++) {
                var dist = polyline_distances[i];
                var new_acc = dist.acc + dist.distance;

                var delta = Math.abs(current_distance - new_acc)
                var distance_equal = delta < equal_delta;

                if (distance_equal || current_distance < new_acc) {
                    if (distance_equal) {
                        // Same point
                        res.push(self.cloneLatLng(dist.x2));
                    } else { 
                        // current_distance < new_acc
                        // New point

                        var dist_from_point = current_distance - dist.acc;
                        var ratio_dist = dist_from_point / dist.distance;
                        var ll = self.getPointOnLine(map, ratio_dist, dist.x1, dist.x2);

                        res.push(ll);
                    }

                    if (ds.length == 0) break;
                    current_distance = ds.shift()
                }
            }

            if (res.length < 1) console.warn("Could not get LatLng from position " + pos_list);
            if (window.DEBUG) {
                console.log("Invert getLatLngFromPos("+ pos_list[0] + ") : " +
                            JSON.stringify(self.getPercentageDistanceFromPolyline(res[0], polyline)));
            }
            return res;
        },

        cloneLatLng: function(latlng) {
            return new L.LatLng(latlng.lat, latlng.lng);
        },

        getPointOnLine: function(map, ratio_dist, ll1, ll2) {
            if (ratio_dist == 0.0) return ll1;
            if (ratio_dist == 1.0) return ll2;
            var zoom = map.getMaxZoom()
              , p1 = map.project(ll1, zoom)
              , p2 = map.project(ll2, zoom)
              , d = p1.distanceTo(p2);

            var x_new = p1.x + (p2.x - p1.x) * ratio_dist
              , y_new = p1.y + (p2.y - p1.y) * ratio_dist
              , ll_new = map.unproject(new L.Point(x_new, y_new), zoom);
            console.assert(!ll_new.equals(ll1) && !ll_new.equals(ll2), ratio_dist + ' got extremity (margin is ' + L.LatLng.MAX_MARGIN + ')');
            return ll_new;
        },

        getGradient: function(x1, y1, x2, y2) {
            var a = (y2 - y1) / (x2 - x1);
            var b = y1 - (a * x1);
            return {'a': a, 'b': b};
        },

        getDistances: function(xs) {
            var xs_len = 0.0, d, distances = [];

            for (var i = 0; i < xs.length - 1; i++) {
                var x1 = xs[i], x2 = xs[i+1];
                d = x1.distanceTo(x2);

                // acc: so far (without distance)
                distances.push({
                    'i1': i, 'i2': i+1,
                    'x1': x1, 'x2': x2,
                    'acc': xs_len, 'distance': d
                });

                xs_len += d
            }
            return {'length': xs_len, 'distances': distances};
        },

        // Calculate length (works for either points or latlngs)
        length: function(xs) {
            var xs_len = 0;
            for (var i = 0; i < xs.length - 1; i++) {
                xs_len += xs[i].distanceTo(xs[i+1]);
            }
            return xs_len;
        },

        distance: function (map, latlng1, latlng2) {
            return map.latLngToLayerPoint(latlng1).distanceTo(map.latLngToLayerPoint(latlng2));
        },

        distanceSegment: function (map, latlng, latlngA, latlngB) {
            var p = map.latLngToLayerPoint(latlng),
               p1 = map.latLngToLayerPoint(latlngA),
               p2 = map.latLngToLayerPoint(latlngB);
            return L.LineUtil.pointToSegmentDistance(p, p1, p2);
        },

        latlngOnSegment: function (map, latlng, latlngA, latlngB) {
            var p = map.latLngToLayerPoint(latlng),
               p1 = map.latLngToLayerPoint(latlngA),
               p2 = map.latLngToLayerPoint(latlngB);
               closest = L.LineUtil.closestPointOnSegment(p, p1, p2);
            return map.layerPointToLatLng(closest);
        },

        closestSegment: function (p, points) {
            var mindist = Number.MAX_VALUE
              , idx = 0;
            for (var i=0; i<points.length-1; i++) {
                var x = points[i]
                  , d = p.distanceTo(x);
                if (d < mindist) {
                    idx = i;
                }
            }
            return [points[idx], points[idx+1]];
        },

        closestOnLine: function (map, latlng, linestring) {
            return self.closestOnLatLngs(map, latlng, linestring.getLatLngs());
        },

        closestOnLatLngs: function (map, latlng, lls) {
            // Iterate on line segments
            var segmentmindist = Number.MAX_VALUE,
                ll = null;
            // Keep the closest point of all segments
            for (var j = 0; j < lls.length - 1; j++) {
                var p1 = lls[j],
                    p2 = lls[j+1],
                    d = self.distanceSegment(map, latlng, p1, p2);
                if (d < segmentmindist) {
                    segmentmindist = d;
                    ll = self.latlngOnSegment(map, latlng, p1, p2);
                }
            }
            return ll;
        },

        closest: function (map, marker, snaplist, snap_distance) {
            var mindist = Number.MAX_VALUE,
                 chosen = null,
                 point = null;
            var n = snaplist.length;
            // /!\ Careful with size of this list, iterated at every marker move!
{'fraction_non_alphanumeric': 0.11250682687056253, 'fraction_numerical': 0.014527580557072638, 'mean_word_length': 1.3758920461917736, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3010207', 'n_tokens_mistral': 5659, 'n_tokens_neox': 5338, 'n_words': 1295}