Как нарисовать эллипс с помощью Openlayers3

Я работаю над проектом, в котором мы используем OpenLayers3.

Нам нужно дать пользователям возможность рисовать различные объекты на карте. Вот официальный пример рисования объектов на карте.

Нам нужно нарисовать эллипс на карте, но официально такая функция не предусмотрена. Мне интересно, можно ли настроить геометрию circle таким образом, чтобы мы могли рисовать эллипс на карте.


person muzaffar    schedule 27.07.2015    source источник


Ответы (6)


Для людей, которые будут искать это в будущем, я надеюсь, что это поможет. Рабочий код для создания эллипса в открытом слое V5.3:

// this works for a static image (pixels) but the idea can be on any coordinate system 
addEllipseFeature(center, semiMajor, semiMinor) {
    let coordinates = [] ;
    const radinas = Math.PI / 180 ;
    for (let angle = 1; angle <= 360; angle ++) {
      const px = center[0] + semiMajor * Math.cos(radinas * angle);
      const py = center[0] + semiMinor * Math.sin(radinas * angle);
      coordinates.push([px, py]);
    }
    const geoJson = {
      'type': 'Feature',
      'geometry': {
        'type': 'Polygon',
        'coordinates': []
      }
    };
    const featureId = source.getFeatures().length;
    coordinates = this.convertCoordinates('Polygon', [coordinates]);
    geoJson.geometry.coordinates = coordinates ;
    const polygonFeature = (new GeoJSON()).readFeature(geoJson);
    polygonFeature.setId(featureId );
    const layerStyle = [  new Style({
      stroke: new Stroke({
        color: 'blue',
        width: 3
      }),
      fill: new Fill({
        color: 'rgba(0, 0, 255, 0.1)'
      })
    })];
    polygonFeature.setStyle(layerStyle);
    source.addFeature(polygonFeature);
    return featureId;
}

введите здесь описание изображения

person Ezri Y    schedule 18.03.2019

Во взаимодействии рисования вы можете указать параметр geometryFunction as. Эта функция будет рисовать дополнительную геометрию, когда вы рисуете. В настоящее время это то, что делает взаимодействие рисования в режиме Circle, посмотреть код

Дополнительную информацию см. в API взаимодействия с рисованием.

person oterral    schedule 27.07.2015
comment
Спасибо за вашу помощь, я уже знаю эти моменты, но не знаю, как изменить geometryFunction , чтобы сделать функцию эллипсом. Не могли бы вы помочь в этом отношении? - person muzaffar; 27.07.2015
comment
@muzaffar ты нашел какое-нибудь решение? - person Ezri Y; 13.03.2019
comment
@EzriY извините, я не нашел решения :( - person muzaffar; 13.03.2019
comment
@muzaffar проверьте этот код ниже, если он вам все еще нужен. - person Ezri Y; 18.03.2019

Большинство картографических систем не предоставляют эллиптической геометрии или функции. У меня было такое же требование при работе с картами Google в Android, и я решаю его с помощью многоугольника, вычисляя вершины с помощью параметрического уравнения эллипса.

х = ч + а * соз (т)

у = к + б * грех (т)

Взгляните на эту публикацию, чтобы увидеть пример.

person Arnel    schedule 14.05.2018

Нарисуйте круг, преобразуйте его в круговой многоугольник, а затем масштабируйте направления x и y. Двух щелчков мыши достаточно, чтобы определить центр и радиусы эллипса по осям. Для наклонного эллипса потребуются три щелчка, один для центра и по одному для каждого радиуса, а третий щелчок также задает вращение.

  var raster = new ol.layer.Tile({
    source: new ol.source.OSM()
  });

  var source = new ol.source.Vector({wrapX: false});

  var vector = new ol.layer.Vector({
    source: source,
  });

  var map = new ol.Map({
    layers: [raster, vector],
    target: 'map',
    view: new ol.View({
      center: [-11000000, 4600000],
      zoom: 4
    })
  });

  var typeSelect = document.getElementById('type');

  var draw; // global so we can remove it later
  function addInteraction() {
    var value = typeSelect.value;
    var maxPoints;
    if (value !== 'None') {
      var geometryFunction;
      if (value === 'Square') {
        value = 'Circle';
        geometryFunction = ol.interaction.Draw.createRegularPolygon(4);
      } else if (value === 'Box') {
        value = 'Circle';
        geometryFunction = ol.interaction.Draw.createBox();
      } else if (value === 'Star') {
        value = 'Circle';
        geometryFunction = function(coordinates, geometry) {
          var center = coordinates[0];
          var last = coordinates[1];
          var dx = center[0] - last[0];
          var dy = center[1] - last[1];
          var radius = Math.sqrt(dx * dx + dy * dy);
          var rotation = Math.atan2(dy, dx);
          var newCoordinates = [];
          var numPoints = 12;
          for (var i = 0; i < numPoints; ++i) {
            var angle = rotation + i * 2 * Math.PI / numPoints;
            var fraction = i % 2 === 0 ? 1 : 0.5;
            var offsetX = radius * fraction * Math.cos(angle);
            var offsetY = radius * fraction * Math.sin(angle);
            newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
          }
          newCoordinates.push(newCoordinates[0].slice());
          if (!geometry) {
            geometry = new ol.geom.Polygon([newCoordinates]);
          } else {
            geometry.setCoordinates([newCoordinates]);
          }
          return geometry;
        };
      } else if (value === 'Ellipse') {
        value = 'Circle';
        geometryFunction = function(coordinates, geometry) {
          var center = coordinates[0];
          var last = coordinates[1];
          var dx = center[0] - last[0];
          var dy = center[1] - last[1];
          var radius = Math.sqrt(dx * dx + dy * dy);
          var circle = new ol.geom.Circle(center, radius);
          var polygon = ol.geom.Polygon.fromCircle(circle, 64);
          polygon.scale(dx/radius, dy/radius);
          if (!geometry) {
            geometry = polygon;
          } else {
            geometry.setCoordinates(polygon.getCoordinates());
          }
          return geometry;
        };
      } else if (value === 'Oblique Ellipse') {
        value = 'LineString';
        maxPoints = 3;
        geometryFunction = function(coordinates, geometry) {
          var center = coordinates[0];
          var first = coordinates[1];
          var dx = center[0] - first[0];
          var dy = center[1] - first[1];
          var radius1 = Math.sqrt(dx * dx + dy * dy);
          if (coordinates.length > 2) {
            var last = coordinates[2];
            dx = center[0] - last[0];
            dy = center[1] - last[1];
          }
          var radius2 = Math.sqrt(dx * dx + dy * dy);
          var rotation = Math.atan2(dy, dx);
          var circle = new ol.geom.Circle(center, radius1);
          var polygon = ol.geom.Polygon.fromCircle(circle, 64);
          polygon.scale(radius2/radius1, 1);
          polygon.rotate(rotation, center);
          if (!geometry) {
            geometry = polygon;
          } else {
            geometry.setCoordinates(polygon.getCoordinates());
          }
          return geometry;
        };
      }
      draw = new ol.interaction.Draw({
        source: source,
        type: value,
        maxPoints: maxPoints,
        geometryFunction: geometryFunction
      });
      map.addInteraction(draw);
    }
  }


  /**
   * Handle change event.
   */
  typeSelect.onchange = function() {
    map.removeInteraction(draw);
    addInteraction();
  };

  addInteraction();
html, body {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
}
.map {
    width: 100%;
    height: 90%;
}
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map" class="map"></div>
<form class="form-inline">
  <label>Shape type &nbsp;</label>
  <select id="type">
    <option value="Ellipse">Ellipse</option>
    <option value="Oblique Ellipse">Oblique Ellipse</option>
    <option value="Circle">Circle</option>
    <option value="Square">Square</option>
    <option value="Box">Box</option>
    <option value="Star">Star</option>
    <option value="None">None</option>
  </select>
</form>

person Mike    schedule 31.03.2019

Из кода Майка, работавшего над OL 6.1.1:

const circle = new Circle(
    fromLonLat([longitude, latitude]),
    radius
)

// fromCircle is a function inside Polygon class
const ellipse = fromCircle(circle, 100)
ellipse.scale(1, bigRadius / smallRadius) 

// OL is counterclockwise rotation
ellipse.rotate(-(angleDegree * Math.PI) / 180, circle.getCenter())

this.yourLayer.getSource().addFeature(
    new Feature({
      geometry: ellipse
    })
)

С Уважением

person jekho    schedule 06.02.2020

Благодаря @Ezri Y я сделал рабочий пример и добавил больше функциональности.

посмотрите здесь

person SIE-Coder    schedule 22.06.2021