
    var MNTH = ["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"];
    var pcpCesiumToolsState = null;
    	/** преобразование целого числа к строке заданного формата
            		s - число (25)
            		count - размер строки (4)
            		результат - строка (0025)
        */
        function STRTOFORMAT(s, count)
        {
        	var s2 = String(s);
        	var len = s2.length;
        	if (len < count)
        	{
        		for (iSTRTOFORMAT=0; iSTRTOFORMAT<count-len; iSTRTOFORMAT++)
        			s2 = "0"+s2;
        	}
                return s2;
        }


        function localDateFromJulianDate(julianDate)
        {
            return Cesium.JulianDate.toDate(julianDate);
        }

        function localTimeZoneLabel()
        {
            try {
                var parts = new Intl.DateTimeFormat('ru-RU', {timeZoneName: 'short'}).formatToParts(new Date());
                var part = parts.find(function (item) { return item.type === 'timeZoneName'; });
                return part && part.value ? part.value : 'лок.';
            } catch (error) {
                return 'лок.';
            }
        }

        /** получение строки времени в часовом поясе браузера
        */
        var TDMT = function GetLocalTime(e,t)
        {
            var date = localDateFromJulianDate(e);
            if (Math.abs(t._clockViewModel.multiplier)<1)
                s = STRTOFORMAT(date.getHours(),2) + ':' + STRTOFORMAT(date.getMinutes(),2) + ':' + STRTOFORMAT(date.getSeconds(),2)+'.'+STRTOFORMAT(date.getMilliseconds(),3)
            else
                s = STRTOFORMAT(date.getHours(),2) + ':' + STRTOFORMAT(date.getMinutes(),2) + ':' + STRTOFORMAT(date.getSeconds(),2)+' '+localTimeZoneLabel();

            return s;
        }

        /**  получение строки даты в часовом поясе браузера
        */
        var TDMD = function GetLocalDate(e)
        {
            var date = localDateFromJulianDate(e);

            s = STRTOFORMAT(date.getDate(),2)+ ' ' + MNTH[date.getMonth()] + ' ' + STRTOFORMAT(date.getFullYear(),4);

            return s;
        }

        /**  получение строки даты и времени в часовом поясе браузера
        */
        var TDMDT = function GetLocalDateTime(e)
        {
            s = "";
            var date = localDateFromJulianDate(e);
            s = date.getDate()+" "+ MNTH[date.getMonth()]+" "+date.getFullYear()+" "+STRTOFORMAT(date.getHours(),2)+":"+STRTOFORMAT(date.getMinutes(),2)+":"+STRTOFORMAT(date.getSeconds(),2)+" "+localTimeZoneLabel();
            return s;
        }



        function formatDistanceMeters(distanceMeters) {
            if (!Cesium.defined(distanceMeters) || !isFinite(distanceMeters)) {
                return "-";
            }

            if (distanceMeters < 1000) {
                return distanceMeters.toFixed(1) + " м";
            }

            return (distanceMeters / 1000).toFixed(3) + " км";
        }

        function getMapCartesianPosition(viewer, screenPosition) {
            if (!viewer || !screenPosition) {
                return null;
            }

            var scene = viewer.scene;
            var ray = viewer.camera.getPickRay(screenPosition);
            if (ray) {
                var globePoint = scene.globe.pick(ray, scene);
                if (Cesium.defined(globePoint)) {
                    return globePoint;
                }
            }

            var ellipsoidPoint = viewer.camera.pickEllipsoid(screenPosition, scene.globe.ellipsoid);
            return Cesium.defined(ellipsoidPoint) ? ellipsoidPoint : null;
        }

        function computeSurfaceDistanceMeters(viewer, pointA, pointB) {
            if (!viewer || !Cesium.defined(pointA) || !Cesium.defined(pointB)) {
                return 0;
            }

            var ellipsoid = viewer.scene.globe.ellipsoid;
            var cartographicA = ellipsoid.cartesianToCartographic(pointA);
            var cartographicB = ellipsoid.cartesianToCartographic(pointB);
            if (!Cesium.defined(cartographicA) || !Cesium.defined(cartographicB)) {
                return 0;
            }

            var geodesic = new Cesium.EllipsoidGeodesic(cartographicA, cartographicB);
            return geodesic.surfaceDistance || 0;
        }

        function getMidpoint(pointA, pointB) {
            if (!Cesium.defined(pointA) || !Cesium.defined(pointB)) {
                return Cesium.Cartesian3.ZERO;
            }

            return Cesium.Cartesian3.midpoint(pointA, pointB, new Cesium.Cartesian3());
        }

        function formatDegree(value, positiveSuffix, negativeSuffix) {
            if (!isFinite(value)) {
                return '-';
            }

            var suffix = value >= 0 ? positiveSuffix : negativeSuffix;
            return Math.abs(value).toFixed(6) + '° ' + suffix;
        }

        function formatCursorCoordinates(viewer, cartesian) {
            if (!viewer || !Cesium.defined(cartesian)) {
                return 'Координаты: -';
            }

            var ellipsoid = viewer.scene.globe.ellipsoid;
            var cartographic = ellipsoid.cartesianToCartographic(cartesian);
            if (!Cesium.defined(cartographic)) {
                return 'Координаты: -';
            }

            var lon = Cesium.Math.toDegrees(cartographic.longitude);
            var lat = Cesium.Math.toDegrees(cartographic.latitude);
            return 'Lon: ' + formatDegree(lon, 'E', 'W') + ' | Lat: ' + formatDegree(lat, 'N', 'S');
        }

        function setRulerInfoText(text) {
            return;
        }

        function getRulerDisplayPositions(ruler) {
            var positions = [];
            if (!ruler || !ruler.points) {
                return positions;
            }

            for (var i = 0; i < ruler.points.length; i++) {
                positions.push(ruler.points[i]);
            }

            if (ruler.points.length > 0 && ruler.tempPoint) {
                var lastFixed = ruler.points[ruler.points.length - 1];
                if (!Cesium.Cartesian3.equalsEpsilon(lastFixed, ruler.tempPoint, Cesium.Math.EPSILON7, Cesium.Math.EPSILON7)) {
                    positions.push(ruler.tempPoint);
                }
            }

            return positions;
        }

        function computePolylineDistanceMeters(viewer, positions) {
            if (!viewer || !positions || positions.length < 2) {
                return 0;
            }

            var total = 0;
            for (var i = 1; i < positions.length; i++) {
                total += computeSurfaceDistanceMeters(viewer, positions[i - 1], positions[i]);
            }
            return total;
        }

        function addRulerVertexMarker(viewer, position, isFirstPoint) {
            return viewer.entities.add({
                name: 'pcp-ruler-vertex',
                position: position,
                point: {
                    pixelSize: 8,
                    color: isFirstPoint ? Cesium.Color.LIME : Cesium.Color.RED,
                    outlineColor: Cesium.Color.WHITE,
                    outlineWidth: 2,
                    disableDepthTestDistance: Number.POSITIVE_INFINITY
                }
            });
        }

        function updateCursorCoordinatesText(viewer, screenPosition) {
            if (!pcpCesiumToolsState || !pcpCesiumToolsState.cursorCoordsPanel) {
                return;
            }

            if (!pcpCesiumToolsState.cursorCoordsEnabled) {
                pcpCesiumToolsState.cursorCoordsPanel.style.display = 'none';
                return;
            }

            var point = getMapCartesianPosition(viewer, screenPosition);
            pcpCesiumToolsState.cursorCoordsPanel.textContent = formatCursorCoordinates(viewer, point);
        }

        function updateButtonActiveState(button, active) {
            if (!button) {
                return;
            }

            if (active) {
                button.classList.add('active');
                button.style.background = '#0d6efd';
                button.style.borderColor = '#0d6efd';
                button.style.color = '#ffffff';
            } else {
                button.classList.remove('active');
                button.style.background = '';
                button.style.borderColor = '';
                button.style.color = '';
            }
        }

        function clearRulerMeasurement(viewer) {
            if (!pcpCesiumToolsState || !pcpCesiumToolsState.ruler) {
                return;
            }

            var ruler = pcpCesiumToolsState.ruler;
            if (ruler.lineEntity) {
                viewer.entities.remove(ruler.lineEntity);
                ruler.lineEntity = null;
            }
            if (ruler.labelEntity) {
                viewer.entities.remove(ruler.labelEntity);
                ruler.labelEntity = null;
            }
            if (ruler.pointEntities && ruler.pointEntities.length) {
                for (var i = 0; i < ruler.pointEntities.length; i++) {
                    viewer.entities.remove(ruler.pointEntities[i]);
                }
            }

            ruler.pointEntities = [];
            ruler.points = [];
            ruler.tempPoint = null;
            ruler.completed = false;
        }

        function ensureRulerEntities(viewer) {
            var ruler = pcpCesiumToolsState.ruler;
            if (ruler.lineEntity) {
                return;
            }

            ruler.lineEntity = viewer.entities.add({
                name: 'pcp-ruler-line',
                polyline: {
                    positions: new Cesium.CallbackProperty(function () {
                        return getRulerDisplayPositions(ruler);
                    }, false),
                    width: 3,
                    material: Cesium.Color.CYAN
                }
            });

            ruler.labelEntity = viewer.entities.add({
                name: 'pcp-ruler-label',
                position: new Cesium.CallbackProperty(function () {
                    var positions = getRulerDisplayPositions(ruler);
                    if (!positions.length) {
                        return Cesium.Cartesian3.ZERO;
                    }
                    return positions[positions.length - 1];
                }, false),
                label: {
                    text: new Cesium.CallbackProperty(function () {
                        var positions = getRulerDisplayPositions(ruler);
                        if (positions.length < 2) {
                            return '';
                        }
                        var distance = computePolylineDistanceMeters(viewer, positions);
                        return 'Σ ' + formatDistanceMeters(distance);
                    }, false),
                    showBackground: true,
                    backgroundColor: Cesium.Color.BLACK.withAlpha(0.75),
                    fillColor: Cesium.Color.WHITE,
                    font: '14px sans-serif',
                    pixelOffset: new Cesium.Cartesian2(10, -10),
                    horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
                    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                    disableDepthTestDistance: Number.POSITIVE_INFINITY
                }
            });
        }

        function updateRulerDistanceInfo(viewer) {
            return;
        }

        function startRulerMeasurement(viewer, point) {
            var ruler = pcpCesiumToolsState.ruler;

            clearRulerMeasurement(viewer);
            ensureRulerEntities(viewer);

            ruler.points = [Cesium.Cartesian3.clone(point)];
            ruler.tempPoint = Cesium.Cartesian3.clone(point);
            ruler.completed = false;
            ruler.pointEntities = [addRulerVertexMarker(viewer, ruler.points[0], true)];

            updateRulerDistanceInfo(viewer);
        }

        function completeRulerMeasurement(viewer, point) {
            var ruler = pcpCesiumToolsState.ruler;

            var fixedPoint = Cesium.Cartesian3.clone(point);
            ruler.points.push(fixedPoint);
            ruler.tempPoint = Cesium.Cartesian3.clone(point);
            ruler.completed = false;
            if (!ruler.pointEntities) {
                ruler.pointEntities = [];
            }
            ruler.pointEntities.push(addRulerVertexMarker(viewer, fixedPoint, false));

            updateRulerDistanceInfo(viewer);
        }

        function disableRuler(viewer) {
            if (!pcpCesiumToolsState || !pcpCesiumToolsState.ruler) {
                return;
            }

            var ruler = pcpCesiumToolsState.ruler;
            ruler.enabled = false;

            if (ruler.handler) {
                ruler.handler.destroy();
                ruler.handler = null;
            }

            clearRulerMeasurement(viewer);
            updateButtonActiveState(pcpCesiumToolsState.rulerButton, false);
            viewer.container.style.cursor = '';
            viewer.scene.requestRender();
        }

        function enableRuler(viewer) {
            if (!pcpCesiumToolsState || !pcpCesiumToolsState.ruler) {
                return;
            }

            var ruler = pcpCesiumToolsState.ruler;
            if (ruler.enabled) {
                return;
            }

            ruler.enabled = true;
            clearRulerMeasurement(viewer);

            ruler.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
            ruler.handler.setInputAction(function (movement) {
                var point = getMapCartesianPosition(viewer, movement.position);
                if (!point) {
                    return;
                }

                if (!ruler.points || ruler.points.length === 0) {
                    startRulerMeasurement(viewer, point);
                    return;
                }

                completeRulerMeasurement(viewer, point);
            }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

            ruler.handler.setInputAction(function (movement) {
                if (!ruler.points || ruler.points.length === 0) {
                    return;
                }

                var point = getMapCartesianPosition(viewer, movement.endPosition);
                if (!point) {
                    return;
                }

                ruler.tempPoint = Cesium.Cartesian3.clone(point);
                updateRulerDistanceInfo(viewer);
                viewer.scene.requestRender();
            }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

            ruler.handler.setInputAction(function () {
                clearRulerMeasurement(viewer);
                updateRulerDistanceInfo(viewer);
                viewer.scene.requestRender();
            }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

            updateButtonActiveState(pcpCesiumToolsState.rulerButton, true);
            viewer.container.style.cursor = 'crosshair';
            viewer.scene.requestRender();
        }

        function toggleRuler(viewer) {
            if (!pcpCesiumToolsState || !pcpCesiumToolsState.ruler) {
                return;
            }

            if (pcpCesiumToolsState.ruler.enabled) {
                disableRuler(viewer);
            } else {
                enableRuler(viewer);
            }
        }

        function setSunLightingEnabled(viewer, enabled) {
            if (!pcpCesiumToolsState) {
                return;
            }

            pcpCesiumToolsState.sunLightingEnabled = enabled;
            viewer.scene.globe.enableLighting = enabled;
            viewer.scene.globe.dynamicAtmosphereLighting = enabled;
            viewer.scene.globe.dynamicAtmosphereLightingFromSun = enabled;

            updateButtonActiveState(pcpCesiumToolsState.sunButton, enabled);
            if (pcpCesiumToolsState.sunButton) {
                pcpCesiumToolsState.sunButton.title = enabled
                    ? 'Освещенность Солнцем: включена'
                    : 'Освещенность Солнцем: выключена';
            }

            viewer.scene.requestRender();
        }

        function toggleSunLighting(viewer) {
            if (!pcpCesiumToolsState) {
                return;
            }

            setSunLightingEnabled(viewer, !pcpCesiumToolsState.sunLightingEnabled);
        }

        function setCursorCoordinatesEnabled(viewer, enabled) {
            if (!pcpCesiumToolsState) {
                return;
            }

            pcpCesiumToolsState.cursorCoordsEnabled = enabled;
            updateButtonActiveState(pcpCesiumToolsState.cursorCoordsButton, enabled);

            if (pcpCesiumToolsState.cursorCoordsPanel) {
                pcpCesiumToolsState.cursorCoordsPanel.style.display = enabled ? 'block' : 'none';
                pcpCesiumToolsState.cursorCoordsPanel.textContent = enabled
                    ? 'Координаты: наведите курсор на карту'
                    : '';
            }

            viewer.scene.requestRender();
        }

        function toggleCursorCoordinates(viewer) {
            if (!pcpCesiumToolsState) {
                return;
            }

            setCursorCoordinatesEnabled(viewer, !pcpCesiumToolsState.cursorCoordsEnabled);
        }

        function createCesiumToolsWidget(viewer) {
            if (pcpCesiumToolsState && pcpCesiumToolsState.toolbarEl) {
                return;
            }

            var viewerToolbar = viewer.container.querySelector('.cesium-viewer-toolbar');
            if (!viewerToolbar) {
                return;
            }

            var rulerButton = document.createElement('button');
            rulerButton.type = 'button';
            rulerButton.className = 'cesium-button cesium-toolbar-button';
            rulerButton.title = 'Включить/выключить линейку';
            rulerButton.style.marginLeft = '4px';
            rulerButton.style.width = '32px';
            rulerButton.style.height = '32px';
            rulerButton.style.display = 'inline-flex';
            rulerButton.style.alignItems = 'center';
            rulerButton.style.justifyContent = 'center';
            rulerButton.innerHTML = '<i class="bi bi-rulers"></i>';

            var coordsButton = document.createElement('button');
            coordsButton.type = 'button';
            coordsButton.className = 'cesium-button cesium-toolbar-button';
            coordsButton.title = 'Включить/выключить отображение координат под курсором';
            coordsButton.style.marginLeft = '4px';
            coordsButton.style.width = '32px';
            coordsButton.style.height = '32px';
            coordsButton.style.display = 'inline-flex';
            coordsButton.style.alignItems = 'center';
            coordsButton.style.justifyContent = 'center';
            coordsButton.innerHTML = '<img alt="Координаты" ' +
                'src="data:image/svg+xml;utf8,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 fill=%27none%27 stroke=%27%23ffffff%27 stroke-width=%272%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27%3E%3Ccircle cx=%2712%27 cy=%2712%27 r=%274%27/%3E%3Cpath d=%27M12 2v4M12 18v4M2 12h4M18 12h4%27/%3E%3C/svg%3E" ' +
                'style="width:16px;height:16px;display:block;">';

            var sunButton = document.createElement('button');
            sunButton.type = 'button';
            sunButton.className = 'cesium-button cesium-toolbar-button';
            sunButton.title = 'Включить/выключить освещенность Солнцем';
            sunButton.style.marginLeft = '4px';
            sunButton.style.width = '32px';
            sunButton.style.height = '32px';
            sunButton.style.display = 'inline-flex';
            sunButton.style.alignItems = 'center';
            sunButton.style.justifyContent = 'center';
            sunButton.innerHTML = '<i class="bi bi-sun"></i>';

            var cursorCoordsPanel = document.createElement('div');
            cursorCoordsPanel.className = 'pcp-cursor-coords-panel';
            cursorCoordsPanel.style.position = 'absolute';
            cursorCoordsPanel.style.top = '50px';
            cursorCoordsPanel.style.right = '10px';
            cursorCoordsPanel.style.zIndex = '1000';
            cursorCoordsPanel.style.maxWidth = '520px';
            cursorCoordsPanel.style.padding = '6px 10px';
            cursorCoordsPanel.style.background = 'rgba(0, 0, 0, 0.75)';
            cursorCoordsPanel.style.color = '#ffffff';
            cursorCoordsPanel.style.borderRadius = '4px';
            cursorCoordsPanel.style.fontSize = '12px';
            cursorCoordsPanel.style.lineHeight = '1.3';
            cursorCoordsPanel.style.display = 'none';
            cursorCoordsPanel.style.pointerEvents = 'none';
            cursorCoordsPanel.textContent = '';

            viewerToolbar.appendChild(rulerButton);
            viewerToolbar.appendChild(coordsButton);
            viewerToolbar.appendChild(sunButton);
            viewer.cesiumWidget.container.appendChild(cursorCoordsPanel);

            pcpCesiumToolsState = {
                toolbarEl: viewerToolbar,
                rulerButton: rulerButton,
                cursorCoordsButton: coordsButton,
                cursorCoordsPanel: cursorCoordsPanel,
                sunButton: sunButton,
                cursorCoordsEnabled: false,
                sunLightingEnabled: false,
                ruler: {
                    enabled: false,
                    handler: null,
                    points: [],
                    tempPoint: null,
                    completed: false,
                    lineEntity: null,
                    labelEntity: null,
                    pointEntities: []
                }
            };

            rulerButton.addEventListener('click', function () {
                toggleRuler(viewer);
            });

            coordsButton.addEventListener('click', function () {
                toggleCursorCoordinates(viewer);
            });

            sunButton.addEventListener('click', function () {
                toggleSunLighting(viewer);
            });

            viewer.scene.canvas.addEventListener('mousemove', function (event) {
                if (!pcpCesiumToolsState || !pcpCesiumToolsState.cursorCoordsEnabled) {
                    return;
                }

                var rect = viewer.scene.canvas.getBoundingClientRect();
                var screenPosition = new Cesium.Cartesian2(
                    event.clientX - rect.left,
                    event.clientY - rect.top
                );
                updateCursorCoordinatesText(viewer, screenPosition);
            });

            viewer.scene.canvas.addEventListener('mouseleave', function () {
                if (!pcpCesiumToolsState || !pcpCesiumToolsState.cursorCoordsEnabled || !pcpCesiumToolsState.cursorCoordsPanel) {
                    return;
                }
                pcpCesiumToolsState.cursorCoordsPanel.textContent = 'Координаты: курсор вне карты';
            });
        }

        function initializeCesium() {
            // Задаем область по умолчанию
            var ext = Cesium.Rectangle.fromDegrees(351, 72.6, 76.3, 31.4);
            Cesium.Camera.DEFAULT_VIEW_RECTANGLE = ext;
            var imageryProviderViewModels = Cesium.createDefaultImageryProviderViewModels();
            var arcGisWorldImagery = imageryProviderViewModels.find(function (viewModel) {
                return viewModel && viewModel.name && viewModel.name.indexOf('ArcGIS World Imagery') !== -1;
            }) || imageryProviderViewModels[0];

            // Создаем viewer
            var viewer = new Cesium.Viewer('cesiumContainer', {
                baseLayerPicker: true,
                imageryProviderViewModels: imageryProviderViewModels,
                selectedImageryProviderViewModel: arcGisWorldImagery,
                geocoder: false,
                infoBox: true,
                navigationHelpButton: false,
                sceneMode: Cesium.SceneMode.SCENE2D,
                // Оптимизация для полного заполнения контейнера
                useDefaultRenderLoop: true,
                orderIndependentTranslucency: false,
                contextOptions: {
                    webgl: {
                        alpha: false,
                        antialias: true,
                        preserveDrawingBuffer: true,
                        failIfMajorPerformanceCaveat: false
                    }
                }
            });

            var scene = viewer.scene;


            // Настройка форматирования времени
            if (viewer.animation && viewer.animation.viewModel) {
                viewer.animation.viewModel.timeFormatter = TDMT;
                viewer.animation.viewModel.dateFormatter = TDMD;
            }

            if (viewer.timeline) {
                viewer.timeline.makeLabel = TDMDT;
            }

            // Обработчик изменения размера окна
            window.addEventListener('resize', function() {
                viewer.resize();
            });

            // Принудительно вызываем resize после создания viewer
            setTimeout(function() {
                viewer.resize();
            }, 100);

            createCesiumToolsWidget(viewer);
            setSunLightingEnabled(viewer, false);

            // Сохраняем viewer в глобальной области видимости для доступа из других функций
            window.viewer = viewer;
            window.heatmapLayer = null; // Здесь будет храниться слой тепловой карты
        }
