import L from "leaflet";
import { map } from "$utils/map";
import { findDistance, middle_latlng } from "../js/common";
let poly = null;
export const km_marks = L.layerGroup();
// const updateOverlays = () => updateMarks({ map, poly, km_marks });
const getRouteArray = poly => poly.toGeoJSON().geometry.coordinates;
export const writeReduxData = ({ e, updatePolyCoords }) => {
const route = getRouteArray(poly);
const latlngs = route.map(([lng, lat]) => ({lat, lng}));
updatePolyCoords({ latlngs });
};
const endMarker = ({ end_latlng, length }) => L.marker(
[end_latlng[1], end_latlng[0]],
{
icon: L.divIcon(
{
html: `${length} км`,
className: 'end_mark'
}
)
}
);
const startMarker = ({ start_latlng, map }) => L.marker(
[start_latlng[1], start_latlng[0]],
{
icon: L.divIcon({
html: `
`,
className: 'arr_mark'
})
}
);
export const updateMarks = () => {
km_marks.clearLayers();
const route = getRouteArray(poly);
const latlngs = poly.getLatLngs();
let start_latlng;
let end_latlng;
let i;
let rotation;
let middle;
let distance;
if (route.length > 0) {
start_latlng = route[0];
end_latlng = route[route.length - 1];
km_marks.addLayer(startMarker({ start_latlng, map }));
if (route.length > 1) {
const segs = L.GeometryUtil.accumulatedLengths(poly);
const length = Math.round(segs[segs.length - 1] / 1000);
// end mark
km_marks.addLayer(endMarker({ end_latlng, length }));
//and also length to panel:
// $('#text_route_length').text(length + 'км');
for (i = 1; i < latlngs.length; i += 1) {
rotation = L.GeometryUtil.bearing(latlngs[i - 1], latlngs[i]);
middle = middle_latlng(latlngs[i], latlngs[i - 1]);
distance = findDistance(latlngs[i - 1].lat, latlngs[i - 1].lng, latlngs[i].lat, latlngs[i].lng);
if (distance > 1) {
km_marks.addLayer(L.marker([middle.lat, middle.lng], { icon: L.divIcon({ html: '
', className: 'arr_mark' }) }));
}
}
} else {
// $('#text_route_length').text('0 км');
}
}
// updatePolyCoords({ latlngs: route });
// local_store_data();
};
const clearKmMarks = () => km_marks.clearLayers();
const insertVertex = ({ e, updatePolyCoords }) => {
// Добавляет редактирующую ручку по щелчку
// если щелчок по кривой, а не по ручке И если ломаная в режиме редактирования. Иначе - перейти к редактированию
if (e.originalEvent.target.tagName === 'path' && poly.editor._enabled) {
// если щелкнуть по кривой во время редактирования, editable не должно рисовать новую точку
if (e.type === 'editable:drawing:click') e.cancel();
let latlngs = poly.getLatLngs(); // набор точек ломанной
let best = 10000;
let pos = []; // переменные для определения принадлежности точки отрезку на ломанной
for(let i=0; ix1 && xx2 && (xx2))
||
(x1 === x2 && Math.abs(x-x1)>0.001)
) && (
(y1y1 && yy2 && (yy2))
||
(y1 === y2 && Math.abs(y-y1)>0.001)
)
) {
// если да, то проверяем, далеко ли точка от самого отрезка между двумя точками
let dx1 = x2 - x1;
let dy1 = y2 - y1;
let dx = x - x1;
let dy = y - y1;
let result = Math.abs((dx1 * dy) - (dx * dy1));
if (result < best) {
// это - не очень-то точная функция. Но по клику она определяет, по какому отрезку мы кликнули
best = result;
pos = [i, i+1];
}
}
}
// если точка найдена, добавляем её в отрезок
if (pos.length>1) {
// poly.editor.disable();
latlngs.splice(pos[1],0,e.latlng);
poly.setLatLngs(latlngs);
poly.editor.initVertexMarkers();
poly.editor.enable();
poly.editor.continueForward();
writeReduxData({ e, updatePolyCoords });
}
} else {
// Рисование! Очистим буфер отмен :-)
// redoBuffer = [];
// если ломаная не в режиме редактирования или если мы, всё-таки, кликнули по ручке, просто активируем редактор
// route_state('active');
}
};
export const bindPolyEvents = ({ updatePolyCoords }) => {
// Если на карте что-то меняется, пересчитать километражи
map.editTools.addEventListener('editable:drawing:mouseup', updateMarks);
map.editTools.addEventListener('editable:vertex:dragend', updateMarks);
map.editTools.addEventListener('editable:vertex:dragend', e => writeReduxData({ e, updatePolyCoords }));
map.editTools.addEventListener('editable:vertex:new', e => writeReduxData({ e, updatePolyCoords }));
map.editTools.addEventListener('editable:vertex:deleted', e => writeReduxData({ e, updatePolyCoords }));
// Продолжить рисование после удаления точки
map.editTools.addEventListener('editable:vertex:deleted', e => {
poly.editor.continueForward();
updateMarks();
});
// Добавлять точек в полилинию по щелчку
map.editTools.addEventListener('editable:drawing:click', e => insertVertex({ e, updatePolyCoords }));
map.editTools.addEventListener('editable:drawing:clicked', () => updateMarks({ updatePolyCoords }));
// Это для точек. При перетаскивании конца указателя тащим точку
// map.editTools.addEventListener('editable:vertex:drag', on_vertex_drag);
// при перетаскивании ручек убирать все отметки километров
map.editTools.addEventListener('editable:vertex:dragstart', clearKmMarks);
};
export const updatePoly = (latlngs) => {
// const route = latlngs.map(([lat, lng]) => new L.latLng(lat, lng));
if (!latlngs || latlngs.length < 2) return;
poly.setLatLngs(createLatLngs(latlngs));
poly.addTo(map);
poly.setStyle({ color: '#ff3333', weight: '5' });
poly.editor.options.skipMiddleMarkers = true;
poly.editor.disable().enable();
poly.editor.continueForward();
//
};
export const createLatLngs = latlngs => latlngs.map(({ lat, lng }) => new L.LatLng(lat, lng));
const createPoly = () => {
const result = map.editTools.startPolyline();
result.editor.enable();
return result;
};
const restorePoly = latlngs => {
const result = L.polyline(createLatLngs(latlngs), { color: 'red' }).addTo(map);
result.enableEdit().continueForward();
result.editor.options.skipMiddleMarkers = true;
result.editor.reset();
return result;
};
export const preparePoly = ({ updatePolyCoords, latlngs }) => {
map.addLayer(km_marks);
poly = (latlngs && latlngs.length)
? restorePoly(latlngs)
: createPoly();
updateMarks();
poly.setStyle({ color: '#ff3333', weight: '5' });
bindPolyEvents({ updatePolyCoords });
return poly;
};