Страницы

Поиск по вопросам

Показаны сообщения с ярлыком openlayers. Показать все сообщения
Показаны сообщения с ярлыком openlayers. Показать все сообщения

понедельник, 13 апреля 2020 г.

Правила и фильтры OpenLayers (отбор по свойствам объектов)

#c_sharp #json #javascript #openlayers #geojson

                    
Есть GeoJSON вида:

{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-108.04,44.68]},"properties":{"course":184.7,"vid":1}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-111.04,45.68]},"properties":{"course":44.1,"vid":2}}]}


Являющийся источником слоя vectors (см. "Как послать JSON в теле HTTP-ответа?").
Нужен фильтр показывающий только точки с vid входящим массив, вида:  

var pointShow = [1,3];


Вроде бы для этого нужно использовать правила (Rule), но я с OpenLayers не особо
знаком, да и в интернете найти что-то по теме кроме описания FeatureId на сайте "OpenLayers"
не получилось.  

Пробовал сделать так:

var myStyle = new OpenLayers.Style();
var defRule = new OpenLayers.Rule({
    filter: new OpenLayers.Filter.FeatureId({fids: ["2242"]}),
    symbolizer: {
        externalGraphic: "OpenLayersRotationExample_files/marker-red.png",
        graphicWidth: 21,
        graphicHeight: 25,
        graphicXOffset: -10,
        graphicYOffset: -12
    }
});
myStyle.addRules([defRule]);

...

vectors = new OpenLayers.Layer.Vector(
   "Simple Geometry",
   {
      protocol: new OpenLayers.Protocol.Script({
        url: "http://localhost:8181/view",
        callbackKey: "format_options",
        callbackPrefix: "callback:",
        filterToParams: function(filter, params) {
          if (filter.type === OpenLayers.Filter.Spatial.BBOX) {
            params.bbox = filter.value.toArray();
            if (filter.projection) {
              params.bbox.push(filter.projection.getCode());
            }
          }
          return params;
        }
      }),
      strategies: [
        new OpenLayers.Strategy.Refresh({force: true, interval:10000}),
        new OpenLayers.Strategy.BBOX({resFactor:2})
      ],
      styleMap: new OpenLayers.StyleMap({
        "default": myStyle
      })
   }
);


Но в итоге я ничего не вижу.  

В связи с этим вопрос - как правильно писать правила и фильтры OpenLayers?
Буду признателен за полезные ссылки на примеры и примеры использования разных фиьтров,
в частности FeatureId (желательно более понятных чем тут "Filtering a WFS Layer").  

PS: Пока решил так:

var myStyle = new OpenLayers.Style();
var defRule = new OpenLayers.Rule({
  symbolizer: {
    externalGraphic: "OpenLayersRotationExample_files/marker.png",
    graphicWidth: 14,
    graphicHeight: 17,
    graphicXOffset: -7,
    graphicYOffset: -8,
    graphicOpacity: 0.9,
    rotation: "${course}",
    display: "none"
  }
});
myStyle.addRules([defRule]);
for (keyVar in arr) {
  myStyle.addRules([
    new OpenLayers.Rule({
      filters: [new OpenLayers.Filter.Comparison({
        type: OpenLayers.Filter.Comparison.EQUAL_TO,
        property: "vid",
        value: arr[keyVar]
      }),
      symbolizer: {
        externalGraphic: "OpenLayersRotationExample_files/marker-red.png",
        display: ""
      }
    })
  ])
}

//arr - список id объектов которые нужно показать
//vid, course - поля свойств объектов (properties)


Возможно не очень красиво и медленно, но работает. Кто знает как разобраться с FeatureId,
прошу подскажите - все таки, я думаю, он быстрее отработает чем куча фильтров.
    


Ответы

Ответ 1



У вас JSON не полный. У каждой feature должен быть некоторый "id", по которому фильтровать фильтром FeatureId.

четверг, 19 марта 2020 г.

Как послать JSON в теле HTTP-ответа?

#c_sharp #openlayers #json #http #ajax


Отдается JSON так:

HttpListener listener = new HttpListener();
listener.Prefixes.Add(new Uri("http://localhost:8181"));
listener.Start();
while (isListening) {
  HttpListenerContext context = listener.GetContext();
  HttpListenerRequest request = context.Request;
  HttpListenerResponse response = context.Response;
  //...
  MemoryStream ms = (GeoJsonDeserialize.SerializeGeoJson(ObjToJson) as MemoryStream);
  byte[] buffer = ms.ToArray();
  response.StatusCode = (int)HttpStatusCode.OK;
  response.KeepAlive = false;
  response.ContentType = "application/json";
  response.ContentEncoding = System.Text.UTF8Encoding.UTF8;
  response.ContentLength64 = buffer.Length;
  response.AddHeader("Cache-Control", "private, max-age=0");
  Stream output = response.OutputStream;
  output.Write(buffer, 0, buffer.Length);
  ms = new MemoryStream();
  ms.Write(buffer, 0, buffer.Length);
  buffer = ms.ToArray();
  output.Close();
}

В другой проге на C# я запрашиваю так:

WebRequest webRequest = WebRequest.Create("http://localhost:8181");
WebResponse webResponse = webRequest.GetResponse();
StreamReader sr = new StreamReader(webResponse.GetResponseStream());
String str = sr.ReadToEnd();

и вижу переданный текст (JSON).
Но вот беда - ни Ajax не видит тело ответа (выдает ошибку), ни OpenLayers который
по GeoJSON должен показать точки на карте.

OpenLayers запрашивает данные (за основу взят пример OpenLayersRotationExample):
vectors = new OpenLayers.Layer.Vector( "Simple Geometry", {
  protocol: new OpenLayers.Protocol.HTTP({
    url: "http://localhost:8181",   format: new OpenLayers.Format.GeoJSON()
  }),
  strategies: [new OpenLayers.Strategy.Fixed()]
});
map.addLayers([vectors]);

Объект в JSON (GeoJSON) выглядит так:

{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-108.04,44.68]},"properties":{"course":184.7}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-111.04,45.68]},"properties":{"course":44.1}}]}

Специально пробовал текст передаваемого JSON загрузить в OL непосредственно в JavaScript:

var featurecollection = {"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-111.04,45.68]},"properties":{"course":42.9}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-111.04,45.68]},"properties":{"course":157.5}}]};
var geojson_format = new OpenLayers.Format.GeoJSON();
var vector_layer = new OpenLayers.Layer.Vector("Simple 1", {
styleMap: new OpenLayers.StyleMap({
  "default": {
     externalGraphic: "OpenLayersRotationExample_files/marker-gold.png",
         //graphicWidth: 17,
         graphicHeight: 20,
         graphicYOffset: -19,
         rotation: "${course}",
     },
     "select": {
        cursor: "crosshair",
        externalGraphic: "OpenLayersRotationExample_files/marker.png"
     }
  })
}); 
map.addLayer(vector_layer);
vector_layer.addFeatures(geojson_format.read(featurecollection));

И все работает - точки отображаются.
Вывод - я неправильно отдаю JSON.
Подскажите как в ответ на запрос отдать JSON что бы JavaScript его смог принять?    


Ответы

Ответ 1



Поскольку провайдер точек и страница отображающая карту находится в разных доменах, действует Same Orign Policy. В OpenLayers есть OpenLayers.Protocol.Script который использует JSONP для получения данных. По умолчанию callback называется OpenLayers.Protocol.Script.registry.c1. Вам необходимо переделать провайдер соответствующим образом, чтобы он оборачивал результирующий JSON в эту функцию.

суббота, 6 июля 2019 г.

Правила и фильтры OpenLayers (отбор по свойствам объектов)

Есть GeoJSON вида:
{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-108.04,44.68]},"properties":{"course":184.7,"vid":1}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-111.04,45.68]},"properties":{"course":44.1,"vid":2}}]}
Являющийся источником слоя vectors (см. "Как послать JSON в теле HTTP-ответа?"). Нужен фильтр показывающий только точки с vid входящим массив, вида:
var pointShow = [1,3];
Вроде бы для этого нужно использовать правила (Rule), но я с OpenLayers не особо знаком, да и в интернете найти что-то по теме кроме описания FeatureId на сайте "OpenLayers" не получилось.
Пробовал сделать так:
var myStyle = new OpenLayers.Style(); var defRule = new OpenLayers.Rule({ filter: new OpenLayers.Filter.FeatureId({fids: ["2242"]}), symbolizer: { externalGraphic: "OpenLayersRotationExample_files/marker-red.png", graphicWidth: 21, graphicHeight: 25, graphicXOffset: -10, graphicYOffset: -12 } }); myStyle.addRules([defRule]);
...
vectors = new OpenLayers.Layer.Vector( "Simple Geometry", { protocol: new OpenLayers.Protocol.Script({ url: "http://localhost:8181/view", callbackKey: "format_options", callbackPrefix: "callback:", filterToParams: function(filter, params) { if (filter.type === OpenLayers.Filter.Spatial.BBOX) { params.bbox = filter.value.toArray(); if (filter.projection) { params.bbox.push(filter.projection.getCode()); } } return params; } }), strategies: [ new OpenLayers.Strategy.Refresh({force: true, interval:10000}), new OpenLayers.Strategy.BBOX({resFactor:2}) ], styleMap: new OpenLayers.StyleMap({ "default": myStyle }) } );
Но в итоге я ничего не вижу.
В связи с этим вопрос - как правильно писать правила и фильтры OpenLayers? Буду признателен за полезные ссылки на примеры и примеры использования разных фиьтров, в частности FeatureId (желательно более понятных чем тут "Filtering a WFS Layer").
PS: Пока решил так:
var myStyle = new OpenLayers.Style(); var defRule = new OpenLayers.Rule({ symbolizer: { externalGraphic: "OpenLayersRotationExample_files/marker.png", graphicWidth: 14, graphicHeight: 17, graphicXOffset: -7, graphicYOffset: -8, graphicOpacity: 0.9, rotation: "${course}", display: "none" } }); myStyle.addRules([defRule]); for (keyVar in arr) { myStyle.addRules([ new OpenLayers.Rule({ filters: [new OpenLayers.Filter.Comparison({ type: OpenLayers.Filter.Comparison.EQUAL_TO, property: "vid", value: arr[keyVar] }), symbolizer: { externalGraphic: "OpenLayersRotationExample_files/marker-red.png", display: "" } }) ]) }
//arr - список id объектов которые нужно показать //vid, course - поля свойств объектов (properties)
Возможно не очень красиво и медленно, но работает. Кто знает как разобраться с FeatureId, прошу подскажите - все таки, я думаю, он быстрее отработает чем куча фильтров.


Ответ

У вас JSON не полный. У каждой feature должен быть некоторый "id", по которому фильтровать фильтром FeatureId.

четверг, 6 июня 2019 г.

Как послать JSON в теле HTTP-ответа?

Отдается JSON так: HttpListener listener = new HttpListener(); listener.Prefixes.Add(new Uri("http://localhost:8181")); listener.Start(); while (isListening) { HttpListenerContext context = listener.GetContext(); HttpListenerRequest request = context.Request; HttpListenerResponse response = context.Response; //... MemoryStream ms = (GeoJsonDeserialize.SerializeGeoJson(ObjToJson) as MemoryStream); byte[] buffer = ms.ToArray(); response.StatusCode = (int)HttpStatusCode.OK; response.KeepAlive = false; response.ContentType = "application/json"; response.ContentEncoding = System.Text.UTF8Encoding.UTF8; response.ContentLength64 = buffer.Length; response.AddHeader("Cache-Control", "private, max-age=0"); Stream output = response.OutputStream; output.Write(buffer, 0, buffer.Length); ms = new MemoryStream(); ms.Write(buffer, 0, buffer.Length); buffer = ms.ToArray(); output.Close(); } В другой проге на C# я запрашиваю так: WebRequest webRequest = WebRequest.Create("http://localhost:8181"); WebResponse webResponse = webRequest.GetResponse(); StreamReader sr = new StreamReader(webResponse.GetResponseStream()); String str = sr.ReadToEnd(); и вижу переданный текст (JSON). Но вот беда - ни Ajax не видит тело ответа (выдает ошибку), ни OpenLayers который по GeoJSON должен показать точки на карте. OpenLayers запрашивает данные (за основу взят пример OpenLayersRotationExample): vectors = new OpenLayers.Layer.Vector( "Simple Geometry", { protocol: new OpenLayers.Protocol.HTTP({ url: "http://localhost:8181", format: new OpenLayers.Format.GeoJSON() }), strategies: [new OpenLayers.Strategy.Fixed()] }); map.addLayers([vectors]); Объект в JSON (GeoJSON) выглядит так: {"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-108.04,44.68]},"properties":{"course":184.7}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-111.04,45.68]},"properties":{"course":44.1}}]} Специально пробовал текст передаваемого JSON загрузить в OL непосредственно в JavaScript: var featurecollection = {"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-111.04,45.68]},"properties":{"course":42.9}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-111.04,45.68]},"properties":{"course":157.5}}]}; var geojson_format = new OpenLayers.Format.GeoJSON(); var vector_layer = new OpenLayers.Layer.Vector("Simple 1", { styleMap: new OpenLayers.StyleMap({ "default": { externalGraphic: "OpenLayersRotationExample_files/marker-gold.png", //graphicWidth: 17, graphicHeight: 20, graphicYOffset: -19, rotation: "${course}", }, "select": { cursor: "crosshair", externalGraphic: "OpenLayersRotationExample_files/marker.png" } }) }); map.addLayer(vector_layer); vector_layer.addFeatures(geojson_format.read(featurecollection)); И все работает - точки отображаются. Вывод - я неправильно отдаю JSON. Подскажите как в ответ на запрос отдать JSON что бы JavaScript его смог принять?


Ответ

Поскольку провайдер точек и страница отображающая карту находится в разных доменах, действует Same Orign Policy В OpenLayers есть OpenLayers.Protocol.Script который использует JSONP для получения данных. По умолчанию callback называется OpenLayers.Protocol.Script.registry.c1. Вам необходимо переделать провайдер соответствующим образом, чтобы он оборачивал результирующий JSON в эту функцию.