openlayer中如何根据圆心和半径在一个圆内随机打点?

最近遇到一个需求,需要在一个园内随机打点。使用过openlayer的都知道,这个打点肯定需要知道点的经纬度。怎么去算一个园内点的经纬度呢,这个一开始也愁到我了。目前只有半径和圆心的经纬度,去网上搜也没搜到结果。然后我就换了一种思路去思考。我需要的是在圆内填充点。那我是不是可以能多个同心圆嵌套,每个圆都是虚线的。类似以下的效果 在这里插入图片描述
直接上代码

//根据车站数量获取车站半径
const getRadius = (count) => {
  let radius = 0
  if (count > 0 && count <= 500) {
    //0.5公里
    radius = 0.5
  } else if (count <= 1000) {
    //1公里
    radius = 1
  } else if (count <= 3000) {
    //1.5公里
    radius = 1.5
  } else {
    //2公里
    radius = 2
  }
  return radius * 4
}
  data是圆心点的坐标集合,是个数组。
    const pointFeatures = data.reduce((prev, item) => {
    //圆心点的经纬度
    const coordinate = [Number(item.lon), Number(item.lat)]
    //后端返回的数量
    const count = item.count
    if (count == 0) {
      return
    }
    //这个根据数量,算出每个圆的半径
    const radius1 = getRadius(count)
    //每个圆要嵌套同心圆的个数(层级)
    let features = Array(Math.round(radius / 5) + 1).fill(1)
    
    features = features.map((item, index) => {
    //radius为圆的半径,如果是第一个圆,就默认很小的半径。第一圆就是一个点。后面的都是根据当前的索引算出半径,   		 随着索引半径依次递增。
      const radius =
        index == 0
          ? (0.1 * 250) /
            ol.proj.getPointResolution('EPSG:4326', 1, coordinate, 'm')
          : ((index + 1) * 500) /
            ol.proj.getPointResolution('EPSG:4326', 1, coordinate, 'm')
      const geometry = new ol.Feature({
        geometry: new ol.geom.Circle(coordinate, radius)
      })
      //最后一个圆加上背景
      if (index == features.length - 1) {
        geometry.setStyle(
          new ol.style.Style({
            stroke: new ol.style.Stroke({
              color: 'rgb(54,225,7)',//边框颜色
              width: 5,//这是边框的宽度
              lineDash: [1, 45],//第一个传每个虚线的长度,第二个传每个虚线直接的距离.这个可以控制每个同心圆点的个数.距离越大,圆上点的个数越少.
              lineJoin: 'round',
              lineCap: 'round'
            }),
            //圆的填充颜色
            fill: new ol.style.Fill({
            color: 'rgba(0, 0, 255, 0.1)'
            })
          })
        )
      } else {
        geometry.setStyle(
          new ol.style.Style({
            stroke: new ol.style.Stroke({
              color: 'rgb(54,225,7)',
              width: 5,
              lineDash: [1, 45],
              lineJoin: 'round',
              lineCap: 'round'
            })
          })
        )
      }
      return geometry
    })
    return prev.concat(features)
  }, [])
  //创建地图图层
  let pointsStationLayer = new ol.layer.Vector({
    source: new ol.source.Vector({
      features: features,
      wrapX: true
    })
  })
 map.addLayer(pointsStationLayer)

这样就实现了在地图上创建多个圆,每个圆内均匀的打上点.
好处是这样打的点上,页面不会卡.也不需要算每个圆内点的经纬度.
缺点是这个点在慢慢放大的过程中,这个圆会以一个风扇的形式展开,不太好看.并且这个点也不是随机的.

客户想要的是随机打点的效果,上面这种方案点太均匀了.于是不得不换一种方法.
这次得根据圆心和半径求出园内任意点的坐标.这次难道我了.这个确实不好算.然后我就突然想了个办法,把这个点看作是一个(x,y)的坐标点.
在这里插入图片描述
可以知道这个园内点的坐标主要和角度,圆心点,半径有关.那我们就可以随机0-360的角度,以及0-r的半径.
把这个经度看在y轴上,纬度在x轴上

//r为半径,lon为经度,lat为纬度
const getPointCoordinate = (r, lon, lat) => {
  let angle = Math.floor(Math.random() * 360)
  //半径
  let nd = Math.random(0,1)*r
  //经度
  lon = lon + Math.sin(angle) * nd
  //纬度
  lat = lat + Math.cos(angle) * nd
  return {
    lon,
    lat
  }
}

这种方式打出的点会比较多,建议不用使用矢量图层.我是用的mapV,webgl格式的图层,有几十万个点也不卡.

const addPointStationLayer3 = (data) => {
  const pointFeatures = data.reduce((prev, item) => {
    const coordinate = [Number(item.lon), Number(item.lat)]
    const counts = item.count
    if (counts == 0) {
      return
    }
    const miter = ol.proj.getPointResolution('EPSG:4326', 1, coordinate, 'm')
    //5,10,15,20,0.5公里-500米,1公里-10000米,1.5公里-1500米,2公里-2000米
    const { r, count } = getRadius2(counts,miter)
    let features = Array(count).fill(1)
    features = features.map((item, index) => {
      const coordinates = getPointCoordinate(r, coordinate[0], coordinate[1])
      return {
        geometry: {
          type: 'Point',
          coordinates: [coordinates.lon, coordinates.lat]
        }
      }
    })
    return prev.concat(features)
  }, [])
  let dataset = new mapv.DataSet(pointFeatures)
  let mapvOptions = {
    fillStyle: 'rgb(54,225,7)',
    globalCompositeOperation: 'lighter',
    size: 3,
    context: 'webgl',
    updateImmediate: true,
    draw: 'simple'
  }

  let options = { map: map, dataSet: dataset, mapvOptions: mapvOptions }
  let source = new ol.source.Mapv(options)
  pointsStationLayer = new ol.layer.Image({
    source: source
  })
  map.addLayer(pointsStationLayer)
}
//根据车站数量获取车站半径
const getRadius2 = (count,miter) => {
  let radius = 0
  if (count > 0 && count <= 500) {
    //0.5公里
    radius = 0.5
  } else if (count <= 1000) {
    //1公里
    radius = 1
  } else if (count <= 3000) {
    //1.5公里
    radius = 1.5
  } else {
    //2公里
    radius = 2
  }
  return { r: (radius / miter)*1000, count: radius * 500 }
}

最后实现效果图如下:

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要实现地图上标绘坐标500米半径圆圈内的数据,可以按照以下步骤进行: 1. 获取需要标绘的坐标的经纬度数据。 2. 使用 OpenLayers 创建地图,并将坐标添加到地图上。 3. 创建一个圆形图层,并将其添加到地图上。 4. 遍历坐标数据,计算每个圆心之间的距离,如果距离小于等于500米,则将该添加到圆形图层。 5. 根据需要设置圆形的样式,如颜色、线宽、透明度等。 以下是一个简单的实现示例: ```javascript // 创建地图 var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ center: ol.proj.fromLonLat([120.13, 30.27]), zoom: 12 }) }); // 创建圆形图层 var circleLayer = new ol.layer.Vector({ source: new ol.source.Vector(), style: new ol.style.Style({ fill: new ol.style.Fill({ color: 'rgba(255, 0, 0, 0.2)' }), stroke: new ol.style.Stroke({ color: 'rgba(255, 0, 0, 0.8)', width: 2 }) }) }); map.addLayer(circleLayer); // 坐标数据 var points = [ [120.13, 30.27], [120.14, 30.28], [120.15, 30.29], // ... ]; // 计算圆形半径 var radius = 500; // 圆心坐标 var center = ol.proj.fromLonLat([120.13, 30.27]); // 遍历坐标数据 points.forEach(function(point) { var coordinate = ol.proj.fromLonLat(point); var distance = ol.sphere.getDistance(center, coordinate); if (distance <= radius) { // 将符合条件的添加到圆形图层 circleLayer.getSource().addFeature(new ol.Feature({ geometry: new ol.geom.Point(coordinate) })); } }); ``` 在上述示例,我们首先创建了一个地图,并添加了一个 OpenStreetMap 图层。然后,我们创建了一个圆形图层,设置了其样式,并将其添加到地图上。接着,我们遍历了所有坐标,计算了每个圆心之间的距离,并将距离小于等于500米的添加到圆形图层。最后,我们将圆形图层添加到地图上,即可在地图上显示出符合条件的

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值