Страница 1 из 1

min/max масштаб слоя

Добавлено: 16 ноя 2010, 16:37
Mavka
Например, при увеличении карты должен включаться более детальный слой. Ниже дается 3 варианта, все абсолютно независимые. Не нужно копировать код со всех подряд и мешать в кучу.

Вариант #1

OpenLayers

Для этого предусмотрены пары атрибутов minResolution/maxResolution и minScale/maxScale. Первый используется при работе с разрешениями (resolutions), второй - масштабами (scales). Про их соотношение см. ниже.

Scales

Для начала рассмотрим работу с масштабами.

Код: Выделить всё

var t1_wms = new OpenLayers.Layer.WMS(
    "Tatarstan bounds",
    "http://localhost:8080/geoserver/wms", 
    {layers: 'Tatarstan:tatar_region'},
    {isBaseLayer: false, maxScale: 200000, minScale: 2000000}
);
 
Слой будет виден только если масштаб карты находится в интервале 1:200К - 1:2М.
Атрибуты можно использовать отдельно, только верхнюю или только нижнюю границу.

Если будете ориентироваться на показания контроллера OpenLayers.Control.Scale, то можете столкнуться с несоответствием. Контроллер показывает масштаб при котором слой должен быть отключен, а он тем не менее включён. Дело в том, что этот контроллер рассчитан на географические СК (epsg:4326 и иже с ним). Масштаб вычисляется через длину дуги на элипсе.

Следовательно, заданные min- и maxScale работают правильно. А контроллер для проекций использовать нельзя (или переопределить функцию расчетов в нем).

Resolutions
Термин "разрешения" употребляется не в значении "кому что можно и нельзя", а как понятие аналогичное разрешению принтера или сканера (300-600 dpi).

Сперва потребуется пересчитать масштаб в разрешение. Формула для метров имеет вид (подробнее):

Код: Выделить всё

resolution = scale / 39.3701 / 72
Для масштаба 1:2'000'000 (1:2M):

Код: Выделить всё

resolution = 2000000 / 39.3701 / 72 = 705.5551745558
Далее в определение слоя добавляем minResolution или maxResolution.

Границы разрешений и масштабов имеют обратные названия. Для интервала 1:500-1:1М аналогии будут:
  • maxScale ~ minResolution (1:500)
  • minScale ~ maxResolution (1:1000000)
Например:

Код: Выделить всё

var t1_wms = new OpenLayers.Layer.WMS(
    "Tatarstan bounds",
    "http://localhost:8080/geoserver/wms", 
    {layers: 'Tatarstan:tatar_region'},
    {isBaseLayer: false, visibility: false, minResolution: 705.5551745558}
);
 
Здесь использован minResolution - значит при масштабе 1:4М он будет показан, а при 1:1М - нет.

Re: min/max масштаб слоя

Добавлено: 16 ноя 2010, 17:58
Bzzzuka
а если еще использовать СвичЛэер? например была подложка гугловская wms и свои генштабовские слои по масштабам.. они должны включаться как один слой.. и менятся только от масштаба.. как этого добится?

Re: min/max масштаб слоя

Добавлено: 16 ноя 2010, 18:11
Mavka
Одним слоем они не могут быть. У них разные источники. Сделай стопочку слоев:

Код: Выделить всё

lay_goo = new OpenLayers.Layer.Google("Google Streets", {
    numZoomLevels: 20,
    sphericalMercator: true
}); // он будет нижним и всегда включен

lay_1 = new OpenLayers.Layer.WMS('Генштаб 1:200000'
    {layers: 'genshtab_200k'},
    {maxScale: 100001, minScale: 200000}
);

lay_2 = new OpenLayers.Layer.WMS('Генштаб 1:100000'
    {layers: 'genshtab_100k'},
    {maxScale: 50001, minScale: 100000}
);

lay_3 = new OpenLayers.Layer.WMS('Генштаб 1:50000'
    {layers: 'genshtab_50k'},
    {minScale: 50000}
); 
Изначально все слои включены (visibility: true). В процессе приближения мелкие слои будут автоматически выключаться, а более подробные - включаться.

В свитчлеере создаем видимость как будто слой один. А сами оперативно вкл/выкл все три слоя.

Re: min/max масштаб слоя

Добавлено: 16 ноя 2010, 18:12
Mavka
Или нужен один генштаб-слой и все организовать на сервере? В UMN MapServer я знаю как такое сделать через группы слоев. Но в GeoServer так сразу и не скажешь, нужно экспериментировать.

Re: min/max масштаб слоя

Добавлено: 18 ноя 2010, 14:19
Bzzzuka
Если добавить эти функции в слои которые потом должны отображаться в OL свичлеере, то они получаются не рабочими.. OL их пишет другим цветом, и запрещает ими манипулировать..

Re: min/max масштаб слоя

Добавлено: 18 ноя 2010, 14:37
Mavka
Но при увеличении они сами включаются?

Re: min/max масштаб слоя

Добавлено: 18 ноя 2010, 14:38
Bzzzuka
Все теперь понятно.. они включаются только при нужном мастшабе.. теперь другой вопрос как несколько слоев в layerswitcher'e прописать как один?

Re: min/max масштаб слоя

Добавлено: 18 ноя 2010, 16:49
Mavka
В стандартный - никак.
Может сделать все на стороне GeoServer?

Re: min/max масштаб слоя

Добавлено: 18 ноя 2010, 18:08
Mavka
Если их грузить сразу все.. то это будет очень долго.
if Zoomleverl=1 грузится 1й слой
if Zoomleverl=2 грузится 2й слой а 1й стирается.
Если слой выключен (находится вне заданных масштабов), то и грузиться он не будит.
Предложенный вариант с подменой слоев при каждом зуме реализовать можно, но это будет сложный код, концептуально не соответствующий логике OpenLayers.
Суть такая: нужно зарегистрировать обработчик события "увеличили/уменьшили". В обработчике у нужного слоя поменять 'url' или 'layers' на новое значение.

Re: min/max масштаб слоя

Добавлено: 18 ноя 2010, 18:27
Mavka
Вариант #2

GeoServer

Имеем растровый слой. Берем стандартный стиль "raster".

Код: Выделить всё

<Rule>
    <RasterSymbolizer>
        <Opacity>1.0</Opacity>
    </RasterSymbolizer>
</Rule> 
Добавляем в правило масштаб:

Код: Выделить всё

<Rule>
    <sld:MinScaleDenominator>50001</sld:MinScaleDenominator>
    <sld:MaxScaleDenominator>100000</sld:MaxScaleDenominator>
    <RasterSymbolizer>
        <Opacity>1.0</Opacity>
    </RasterSymbolizer>
</Rule> 
Создаем несколько таких стилей и приписываем их соответствующим слоям. Потом слои собираем в группу. Если смотреть на группу, то в каждом интервале масштаба будет видно только один из под-слоев.

Re: min/max масштаб слоя

Добавлено: 21 ноя 2010, 16:06
Mavka
Вариант #3

Соня
Вот вариант для OpenLayers по методу "if Zoomleverl=1 грузится 1й слой, if Zoomleverl=2 грузится 2й слой а 1й стирается." Пусть на сервере WMS есть два слоя "genshtab_200k" (1:200'000) и "genshtab_100k" (1:100'000).
Как обычно создаем слой и добавляем его на карту:

Код: Выделить всё

var topo = new OpenLayers.Layer.WMS('Топокарта',
    'http://localhost:8080/geoserver/wms', 
    {layers: 'genshtab_200k'}
);
...
map.AddLayer(topo); 
Теперь перехватим событие "увеличили/уменьшили карту" - zoomend.

Код: Выделить всё

map.events.register('zoomend', topo, myZoom); 
в параметрах передаем ссылку на слой topo (понадобится позднее) и функцию myZoom, которая получит управление. Отдельно пишем myZoom:

Код: Выделить всё

function myZoom() {
    if (this.map.zoom > 7) {
        this.mergeNewParams({layers: 'genshtab_100k'});
    } else {
        this.mergeNewParams({layers: 'genshtab_200k'});
    }
} 
Окружение this мы указали ренее как ссылку на слой topo, поэтому работаем через него. С помощью mergeNewParams подменяем слой на сервере.

Ссылку на карту можно получить через this.map. Но в ней есть только текущий zoom и resolution. Если понадобиться именно масштаб, то его придется высчитывать через разрешение.

Re: min/max масштаб слоя

Добавлено: 23 ноя 2010, 15:19
Mavka
Соня
Префикс sld лучше убрать, в GeoServer использованы обрезанные стили и в них нет ссылки на этот namespace.

Re: min/max масштаб слоя

Добавлено: 23 ноя 2010, 15:33
Bzzzuka
Первый вариант прошел на ура.. а вот на втором, консоль ошибок выдает какой то невменяемый error причем не в моем файле а в библиотеке.
Ошибка: [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXMLHttpRequest.statusText]" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" location: "JS frame :: file:///C:/Program%20Files/Mozilla%20Firefox/components/nsBlocklistService.js :: anonymous :: line 469" data: no]
Источник: file:///C:/Program%20Files/Mozilla%20Firefox/components/nsBlocklistService.js
Строка: 469

Код: Выделить всё

var statusText = request.statusText;
    // When status is 0 we don't have a valid channel.
    if (status == 0)
      statusText = "nsIXMLHttpRequest channel unavailable";
    LOG("Blocklist:onError: There was an error loading the blocklist file\r\n" +
        statusText);
  },

Re: min/max масштаб слоя

Добавлено: 23 ноя 2010, 16:59
Mavka
Второй вариант - это с GeoServer? Проверь слой в qgis.

Ошибку вероятнее всего следует понимать так: из OpenLayers сделан запрос на сервере, но ответ не пришел и по тайм-ауту генерируется ошибка; в программе без проверки кода ответа делается попытка чтения данных. Причину такого поведения не представляю.