Фильтрация объектов для WMS в GeoServer

Mapserver, GeoServer, MapGuide, Google и другое ПО для веб-картографии
Tink
Участник
Сообщения: 50
Зарегистрирован: 20 июл 2012, 15:49
Репутация: 4

Фильтрация объектов для WMS в GeoServer

Сообщение Tink »

Здравствуйте!
Можно показать WMS ограниченное прямоугольной областью - bbox.
А можно ли сказать серверу что бы он вернул (отрисовал) только объекты попадающие в область заданную полигоном?

Для WFS фильтры хотя и не ограничивающие отрисовываемую область, но хотя бы отбирающие объекты находящиеся под заданным полигоном. А тут есть хотя бы такое, если первое не возможно?
Последний раз редактировалось Tink 04 фев 2013, 08:22, всего редактировалось 3 раза.
Petruxin
Гуру
Сообщения: 1695
Зарегистрирован: 14 июн 2011, 16:47
Репутация: 133
Ваше звание: Завсегдатай
Откуда: Череповец

Re: Фильтрация объектов в WMS в GeoServer

Сообщение Petruxin »

wms как бы растр... так что Ваша задача не решается(вроде)

[ Сообщение с мобильного устройства ]
Tink
Участник
Сообщения: 50
Зарегистрирован: 20 июл 2012, 15:49
Репутация: 4

Re: Фильтрация объектов в WMS в GeoServer

Сообщение Tink »

Я понимаю что растр... Но GeoServer то вроде бы должен его генерировать по вектору, если исходная карта векторная...

Можно же в GeoServer задавать стили отрисовки объектов даже для WMS...
Может и фильтры есть, или какие ещё инструменты ?
Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

Re: Фильтрация объектов в WMS в GeoServer

Сообщение Denis Rykov »

Конечно можно, на гислабе даже есть статья по этому вопросу. В двух словах: передаёте WMS-серверу SLD-документ, содержащий необходимые фильтры и он рисует то, что нужно.
Spatial is now, more than ever, just another column- The Geometry Column.
Tink
Участник
Сообщения: 50
Зарегистрирован: 20 июл 2012, 15:49
Репутация: 4

Re: Фильтрация объектов в WMS в GeoServer

Сообщение Tink »

Я правильно понял, что будут работать все OpenLayers.​Filter.​Spatial при описанном в статье подходе ?

То есть используя OpenLayers.Filter.Spatial.INTERSECTS я получу объекты под полигоном ?..
А обрезать так же как по BBOX, только полигоном, можно ?
Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

Re: Фильтрация объектов в WMS в GeoServer

Сообщение Denis Rykov »

Не совсем понятно, что вы хотите получить.
Spatial is now, more than ever, just another column- The Geometry Column.
Tink
Участник
Сообщения: 50
Зарегистрирован: 20 июл 2012, 15:49
Репутация: 4

Re: Фильтрация объектов в WMS в GeoServer

Сообщение Tink »

Примерно то же что и в вопросе "Можно от GeoServer получить полигоны пересекаемые линией ?" но применительно к WMS слою... :oops:

Хочу увидеть только объекты которые попадают целиком в векторный полигон.
Нужно именно WMS потому что объектов на слое очень много и OpenLayers практически ложится при их отрисовки. :(
Tink
Участник
Сообщения: 50
Зарегистрирован: 20 июл 2012, 15:49
Репутация: 4

Re: Фильтрация объектов в WMS в GeoServer геометрией

Сообщение Tink »

Пробовал сделать следующим образом (на основе примеров Multiple SLD Rules for PolygonSymbolizer on a Single Layer):

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

var oFilter= new OpenLayers.Filter.FeatureId({
fids: ["Feature.193","Feature.193764","Feature.193765","Feature.193766","Feature.193767"]
});
var oRule = new OpenLayers.Rule({
symbolizer: {"Polygon": {
fillColor: "#0000FF",
fillOpacity: "0.5",
strokeColor: "#00FFFF",
strokeWidth: "1",
strokeOpacity: "1"
}},
filter: oFilter
});
var oColorStyle = new OpenLayers.Style("MyStyle", {
rules: [oRule]
});
var strSld = new OpenLayers.Format.SLD().write({
namedLayers: [{
name: SpaceName + ':' + LayerNmae,
userStyles: [oColorStyle]
}]
});
layerWMS = new OpenLayers.Layer.WMS.Post(
"Polygons", "http://localhost:8081/geoserver/wms",
{
layers: SpaceName + ':' + LayerNmae,
transparent: true,
format: "image/png",
sld_body: strSld
}
);

Но не заработало - ругается
TypeError: undefined is not a function
Оказалось что

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

OpenLayers.Layer.WMS.Post

устарел (класс вынесен в deprecated.js), но удалось это обойти (на основе описания класса и совета) следующим образом:

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

layerWMS = new OpenLayers.Layer.WMS(
"Polygons", "http://localhost:8081/geoserver/wms",
{
layers: SpaceName + ':' + LayerNmae,
transparent: true,
format: "image/png",
sld_body: strSld
}, {
tileOptions: {maxGetUrlLength: 0}
}
);

Оказалось, что если длина строки GET запроса получается больше maxGetUrlLength, то запрос шлется уже POST и если задать 0, то все запросы у экземпляра класса пойдут POST, что собственно логично.

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

var oFilter = new OpenLayers.Filter.Spatial({
type: OpenLayers.Filter.Spatial.INTERSECTS,
property: "the_geom", // не обязательно, повторяет значение по умолчанию
value: geometry,
projection: "EPSG:4326"
});

Где geometry может быль полигоном, линией или точкой. По крайней мере у меня с ними работало корректно.

Надеюсь это кому-нибудь пригодится :wink:
Последний раз редактировалось Tink 23 янв 2013, 09:56, всего редактировалось 1 раз.
Tink
Участник
Сообщения: 50
Зарегистрирован: 20 июл 2012, 15:49
Репутация: 4

Re: Фильтрация объектов в WMS в GeoServer

Сообщение Tink »

Осталось решить все пару появившихся проблем:
  • Если создаю, приведенным образом, фильтр для так 4000 тысяч (для каждой тысячи свой стиль) по FEATUREID (или fid - не особо важно) то POST-запрос оказывается длиннее 200000 байт и вываливается ошибка вида:
    javascript.lang.IllegalStateException: From to LargeXXXX > 200000
    Обходить её не вижу смысла - мало ли в каком браузере обход не будет работать (и после какого обновления браузера). Поэтому нужно как-то уменьшить размер получаемой XML при условии что фильтр по ID полей таки нужен для их большого числа.
    Возможно ли посылать кроме GET и POST например PUT запросы? Слышал что GeoServer PUT поддерживает, вопрос поддерживает ли он PUT для WMS и как его послать из OpenLayers?
  • Как составить фильтр, если нужно получить в итого объекты находящиеся в области пересечения двух полигонов (как получить объекты под или в одном/-им полигоном все понятно - пример в предыдущем посте).
Tink
Участник
Сообщения: 50
Зарегистрирован: 20 июл 2012, 15:49
Репутация: 4

Re: Фильтрация объектов в WMS в GeoServer геометрией

Сообщение Tink »

Пока пришел к выводу, что использовать PUT в данном случае нельзя...


Сейчас у меня фильтр строится по следующей схеме

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

var oFilter= new OpenLayers.Filter.FeatureId({
fids: ["Feature.193","Feature.193764","Feature.193765","Feature.193766","Feature.193767"]
});
var oRule = new OpenLayers.Rule({
symbolizer: {"Polygon": {
fillColor: "#0000FF",
fillOpacity: "0.5",
strokeColor: "#00FFFF",
strokeWidth: "1",
strokeOpacity: "1"
}},
filter: oFilter
});
var oColorStyle = new OpenLayers.Style("MyStyle", {
rules: [oRule]
});
var strSld = new OpenLayers.Format.SLD().write({
namedLayers: [{
name: SpaceName + ':' + LayerNmae,
userStyles: [oColorStyle]
}]
});

А можно ли просто выбрать нужные объекты без смены заданного для слоя стиля ?

Скажем рисовались у меня страны какими-то цветами по умолчанию... ну и пусть так же и красятся, но только по некоторому условию... такое возможно ?
Tink
Участник
Сообщения: 50
Зарегистрирован: 20 июл 2012, 15:49
Репутация: 4

Re: Фильтрация объектов в WMS в GeoServer

Сообщение Tink »

Denis Rykov писал(а):Конечно можно, на гислабе даже есть статья по этому вопросу. В двух словах: передаёте WMS-серверу SLD-документ, содержащий необходимые фильтры и он рисует то, что нужно.
Как в OpenLayers получить XML такого же вида как в приведенной статье ?

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

<sld:StyledLayerDescriptor version="1.1.0">
<sld:NamedLayer>
<se:Name>mylayer</se:Name>

<!-- фильтр слоя -->
<sld:LayerFeatureConstraints>
<sld:FeatureTypeConstraint>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>country</ogc:PropertyName>
<ogc:Literal>UKRAINE</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
</sld:FeatureTypeConstraint>
</sld:LayerFeatureConstraints>

<sld:UserStyle>
<!-- описание стилей (rules) -->
</sld:UserStyle>

</sld:NamedLayer>
</sld:StyledLayerDescriptor>

Приведенный выше код создает XML вида:

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

<sld:StyledLayerDescriptor xmlns:sld="http://www.opengis.net/sld" version="1.0.0" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/St ... riptor.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml">
<sld:NamedLayer>
<sld:Name>SpaceName:LayerNmae</sld:Name>
<sld:UserStyle>
<sld:FeatureTypeStyle>
<sld:Rule>
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
<ogc:And>
<ogc:Or>
<ogc:FeatureId fid="Feature.193"/>
<ogc:FeatureId fid="Feature.193764"/>
<ogc:FeatureId fid="Feature.193765"/>
<ogc:FeatureId fid="Feature.193766"/>
<ogc:FeatureId fid="Feature.193767"/>
</ogc:Or>
</ogc:And>
</ogc:Filter>
<sld:PolygonSymbolizer>
<sld:Fill>
<sld:CssParameter name="fill">#0000FF</sld:CssParameter>
<sld:CssParameter name="fill-opacity">0.5</sld:CssParameter>
</sld:Fill>
<sld:Stroke>
<sld:CssParameter name="stroke">#00FFFF</sld:CssParameter>
<sld:CssParameter name="stroke-opacity">1</sld:CssParameter>
<sld:CssParameter name="stroke-width">1</sld:CssParameter>
</sld:Stroke>
</sld:PolygonSymbolizer>
</sld:Rule>
</sld:FeatureTypeStyle>
</sld:UserStyle>
</sld:NamedLayer>
</sld:StyledLayerDescriptor>

А как я понимаю, нужна секция LayerFeatureConstraints, а не NamedLayer...


Как в OpenLayers сформировать правило фильтрации, что бы появилась секция LayerFeatureConstraints, а не NamedLayer ?
Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

Re: Фильтрация объектов в WMS в GeoServer

Сообщение Denis Rykov »

В статье оговаривается этот момент:
Преобразование стиля в формат SLD (LayerFeatureConstraints не поддерживается)
Spatial is now, more than ever, just another column- The Geometry Column.
Tink
Участник
Сообщения: 50
Зарегистрирован: 20 июл 2012, 15:49
Репутация: 4

Re: Фильтрация объектов в WMS в GeoServer

Сообщение Tink »

Да я видел... и в статье и в исходниках OL...
Пытаюсь допились этот момент сам, но пока не особо успешно - GeoServer отвергает все мои попытки...
И, похоже, что мне его даже удалось повесить пару раз...

Пока написал следующее:

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

OpenLayers.Format.SLD.v1_0_0c = OpenLayers.Class(
OpenLayers.Format.SLD.v1_0_0, {
VERSION: "1.0.0c",
writers: OpenLayers.Util.applyDefaults({
"sld": OpenLayers.Util.applyDefaults({
"NamedLayer": function (layer) {
var node = this.createElementNSPlus("sld:NamedLayer");
this.writeNode("Name", layer.name, node);

// optional sld:LayerFeatureConstraints
if(layer.layerFeatureConstraints) {
for(var i = 0, len = layer.layerFeatureConstraints.length; i < len; ++i) {
this.writeNode(
"LayerFeatureConstraints",
layer.layerFeatureConstraints,
node
);
}
}

if(layer.namedStyles) {
for(var i = 0, len = layer.namedStyles.length; i < len; ++i) {
this.writeNode(
"NamedStyle",
layer.namedStyles,
node
);
}
}

if(layer.userStyles) {
for(var i = 0, len = layer.userStyles.length; i < len; ++i) {
this.writeNode(
"UserStyle",
layer.userStyles,
node
);
}
}

return node;
},
"LayerFeatureConstraints": function (constraint) {
var node = this.createElementNSPlus("sld:LayerFeatureConstraints");
this.writeNode("FeatureTypeConstraint", constraint, node);
return node;
},
"FeatureTypeName": function (name) {
return this.createElementNSPlus(
"sld:FeatureTypeName", {value: name}
);
},
"FeatureTypeConstraint": function (constraint) {
var node = this.createElementNSPlus("sld:FeatureTypeConstraint");

if (constraint.name) {
this.writeNode("FeatureTypeName", constraint.name, node);
}

if (constraint.filter) {
this.writeNode("ogc:Filter", constraint.filter, node);
}

return node;
}
}, OpenLayers.Format.SLD.v1_0_0.prototype.writers["sld"])
}, OpenLayers.Format.SLD.v1_0_0.prototype.writers),

CLASS_NAME: "OpenLayers.Format.SLD.v1_0_0c"
});

Использую это расширение так:

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

var theFilter = new OpenLayers.Filter.Comparison({
type: OpenLayers.Filter.Comparison.EQUAL_TO,
property: 'FUTUREID',
value: '19'
});
var strSld = new OpenLayers.Format.SLD({defaultVersion: "1.0.0c"}).write({
namedLayers: [{
name: layer.params ? layer.params.LAYERS : layer.protocol.params.typeName,
layerFeatureConstraints: [{filter: theFilter}]
}]
});

Но сервер отказывается мне что либо отдавать, не смотря на то что XML у меня получается следующий:

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

<sld:StyledLayerDescriptor xmlns:sld="http://www.opengis.net/sld" version="1.0.0c" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/St ... riptor.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml">
<sld:NamedLayer>
<sld:Name>SpaceName:LayerName</sld:Name>
<sld:LayerFeatureConstraints>
<sld:FeatureTypeConstraint>
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>FUTUREID</ogc:PropertyName>
<ogc:Literal>19</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
</sld:FeatureTypeConstraint>
</sld:LayerFeatureConstraints>
</sld:NamedLayer>
</sld:StyledLayerDescriptor>

Может каких параметров ещё не хватает ?

Или, может быть, GeoServer не поддерживает вообще LayerFeatureConstraints ?

Мне нужно то не много... Всего лишь показать отобранные по условию объекты со стилем установленным для слоя на сервера, то есть не передавать его при запросе... поэтому в этом контексте UserStyle мне не подходит - так как там обязательно должен быть задан стиль, который мне не нужно переопределять...

Может я вообще не тем путем иду, и нужно использовать не SLD, а что-то другое для решения подобных задач?
Tink
Участник
Сообщения: 50
Зарегистрирован: 20 июл 2012, 15:49
Репутация: 4

Re: Фильтрация объектов для WMS в GeoServer

Сообщение Tink »

Действительно - шел не той дорогой...
Пришлось из-за этого долго гуглить и пробовать то что мне к этой задаче не нужно оказалось...
Что же, для общего развития пойдет :wink: Жаль что ни кто не сказал что иду не тем путём... :(


Удалось решить задача следующим образом:

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

layer.params.cql_filter = "INTERSECTS(the_geom, " + vectorFeature.geometry.toString() + ")";

В результате чего получается следующий запрос:

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

INTERSECTS(the_geom, POLYGON((-90 40, -90 45, -60 45, -60 40, -90 40)))
Аналогично и с другими фильтрами. Как-то упростить составление запросов через OpenLayers пока не пробовал.


Подробнее про CQL и ECQL можно прочесть тут (CQL and ECQL) и тут (ECQL Reference), если кому интересно.
К сожалению у меня пока не получается заставить работать меж слоевые запросы (Developer corner: cross layer filtering coming down to GeoServer) :( А жаль - штука нужная... особенно если геометрия не одна, да ещё и сложная... На практике, POST запросы часто могут получаться больше 200 000 байт... :(


Если по подобным запросам кто поможет информацией, примерами или пинком в их сторону - буду признателен. :)
Аватара пользователя
Denis Rykov
Гуру
Сообщения: 3376
Зарегистрирован: 11 апр 2008, 21:09
Репутация: 529
Ваше звание: Author
Контактная информация:

Re: Фильтрация объектов для WMS в GeoServer

Сообщение Denis Rykov »

Отлично, что разобрались. У меня к сожалению нет опыта работы с GeoServer, а CQL - это насколько мне известно его вендор фича.
Spatial is now, more than ever, just another column- The Geometry Column.
Ответить

Вернуться в «Веб-картография»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 3 гостя