13 OpenLayers学习笔记-绘制指定半径的圆

504 阅读6分钟

需求

用户在地图上任意位置点击,然后选择一个距离范围(1公里、2公里……),显示以点击的位置为中心,用户选择的距离为半径的圆形范围内的点位数据。

错误的实现过程

起初的方案是以用户点击的位置为中心,以用户选择的距离范围为半径。使用new ol.geom.Circle(center, radius)方法绘制一个圆。然后请求点位数据,调用circleGeometry().intersectsCoordinate(coodes)方法,判断点位是否在圆范围内,在范围内的,渲染到地图上,不在园内的,丢弃。后来发现这个方案会丢数据,明明一个点位在用户选择的距离范围内,但却不在绘制的圆的范围内。经百度、谷歌、GPT,发现原因是new ol.geom.Circle(center, radius)radius指☞的是投影平面上的距离,并不是实际地球球面上的距离,没有考虑球面的曲率。半径设置为1000,通过圆的外切正方形或者圆上的点到圆心的距离,使用ol.sphere.getDistance(center, p2)计算实际距离,得出的结果是800,也就是radius设置为1000,在平面投影上绘制了一个半径为1000米圆,但是把这个圆贴到实际的地球球面上,半径就变为800了。所以就导致new ol.geom.Circle(center, radius)绘制的1000米为半径的圆,只能覆盖ol.sphere.getDistance(center, p2)方法计算出来的800米范围内的数据。丢失了800-1000米内的点位数据。

给AI提问:在EPSG:3857坐标系下,绘制一个半径为1000米圆。再将其反投影回地球球面上,半径是变大了还是变小了?

AI的回答是:在EPSG:3857坐标系下绘制一个半径为1000米的圆,并将其反投影回地球球面上时,半径会变小。这是因为Web Mercator投影在高纬度地区的变形使得平面距离拉伸,而反投影回球面时,这种拉伸效应使得实际球面距离变小。

正确的实现过程

  • 方案1 根据圆心经纬度,计算出2个点,一个经度方向上的点,一个纬度方向上的点,这两个点距离圆心的距离是1000米,这个1000米是通过ol.sphere.getDistance(p1, p2)计算出来的实际距离。找到这两个点后,再计算出这两个点在投影平面的距离(比1000米大),取较大的距离,以这个距离为半径,使用new ol.geom.Circle(center, radius)绘制圆。这样绘制出来的圆,在地球的球面上的半径是1000米,能包含使用ol.sphere.getDistance(center, p2)计算出来的1000米范围内的点位。
  • 方案2 使用ol.geom.Polygon.circular(center, radius, n, sphereRadius)方法绘制一个近似的圆,这个方法绘制的圆是考虑到地球球面的。此方案是出现问题后找到的首选方案,但是苦于一直没有实现,调用方法后一直无法绘制出图形而放弃。实际业务中就暂时采用了方案1。在整理openlayers学习笔记时,看到了这篇文章openlayers 根据中心点和半径得到实际距离的圆(平面),才正确绘制出了图形。

知识点

  • ol.sphere.getDistance(p1, p2)计算的是经纬度之间的实际距离,其中p1,p2WGS84 EPSG:4326坐标系下的坐标。

  • new ol.geom.Circle(center, radius)方法的radius参数指的是在投影平面上的距离,不是地球球面上的距离。

  • EPSG:4326坐标系下,已知一个点的坐标是[lon, lat],距离这个点1000米垂直方向上方的点的坐标为[lon, lat + (1000 / R) * (180 / Math.PI)]。距离这个点1000米水平方向右侧的点的坐标为[lon + (1000 / (R * Math.cos(Math.PI * lat / 180))) * (180 / Math.PI), lat]。其中R为地球半径6371000。

  • EPSG:3857坐标系下的坐标的单位是米。

  • 设两个点A、B以及坐标分别为A(x1, y1),B(x2, y2) ,则A和B两点之间的距离为(x2x1)2+(y2y1)2\sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}

  • EPSG:3857坐标系下,坐标单位是米,计算距离一个点多少米距离的经纬度可以直接加减。点A的坐标为[lon, lat],在A点水平方向右侧距离为1000米的点的坐标是[lon + 1000, lat],在A点垂直方向上方距离为1000米的点的坐标是[lon, lat + 1000]

  • AI提供了一个已知一个点的经纬度,计算距离这个点 一定距离,一定角度的另一个点的经纬度的方法。参数和返回值都是EPSG:4326坐标系下的坐标。

    function toRadians(degrees) {
      return degrees * Math.PI / 180;
    }
    function toDegrees(radians) {
      return radians * 180 / Math.PI;
    }
    function calculateDestination(coord1, distance, bearing) {
      const R = 6371000; // 地球半径,单位为米
      const lat1 = toRadians(coord1[1]);
      const lon1 = toRadians(coord1[0]);
      const theta = toRadians(bearing);
      const dR = distance / R;
      const lat2 = Math.asin(Math.sin(lat1) * Math.cos(dR) +
          Math.cos(lat1) * Math.sin(dR) * Math.cos(theta));
      const lon2 = lon1 + Math.atan2(Math.sin(theta) * Math.sin(dR) * Math.cos(lat1),
          Math.cos(dR) - Math.sin(lat1) * Math.sin(lat2));
      return [toDegrees(lon2), toDegrees(lat2)];
    }
    
  • ol.geom.Polygon.circular(center, radius, n, sphereRadius)方法的center的参数是EPSG:4326坐标系下的坐标,得到的gemo的数据也是EPSG:4326坐标系下的,可通过gemo.flatCoordinates查看geomn个点的坐标数据。要想将其放在EPSG:3857的地图上,需要手动转换为地图设置的坐标系,调用gemo.clone().transform('EPSG:4326', 'EPSG:3857')将其转换为EPSG:3857坐标系的gemo

  • 获取new ol.geom.Circle(center, radius)绘制的圆上的一点,可以使用circleGemo.getLastCoordinate()方法。

  • Math.sqrt(num)求一个数字的平方根。

代码HTML+CSS+JS

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/openlayers/9.2.4/ol.min.css" integrity="sha512-bc9nJM5uKHN+wK7rtqMnzlGicwJBWR11SIDFJlYBe5fVOwjHGtXX8KMyYZ4sMgSL0CoUjo4GYgIBucOtqX/RUQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    <title>绘制指定半径的圆</title>
    <style>
        * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    html,
    body,
    #app {
      height: 100%;
      display: flex;
      flex-wrap: wrap;
      overflow: hidden;
    }
    #map1, #map2, #map3, #map4 {
        width: 50vw;
        height: 50vh;
        position: relative;
        border: 1px solid deeppink;
    }
    #map1, #map3 {
        border-right: none;
    }
    #map1, #map2 {
        border-bottom: none;
    }
    .map {
        height: 100%;
        width: 100%;
    }
    button {
      font-size: 18px;
      border: none;
      padding: 12px 20px;
      border-radius: 4px;
      color: #fff;
      background-color: #409eff;
      border-color: #409eff;
      cursor: pointer;
      border: 1px solid #dcdfe6;
      margin-bottom: 5px;
      position: absolute;
      top: 0;
      right: 0;
    }
    .text {
        position: absolute;
        right: 5px;
        bottom: 5px;
        border-radius: 4px;
        border: 1px solid #ebeef5;
        background-color: #fff;
        overflow: hidden;
        color: #303133;
        width: 225px;
        height: 80px;
        padding: 10px;
        box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
        font-size: 13px;
    }
    .no {
        position: absolute;
        left: 5px;
        top: 5px;
        width: 40px;
        height: 40px;
        background-color: deeppink;
        font-size: 22px;
        border-radius: 50%;
        text-align: center;
        line-height: 40px;
    }
    [v-cloak] {
        display: none;
    }
  </style>
</head>

<body>
    <div id="app" v-cloak>
        <div id="map1">
            <div class="map"></div>
            <button @click='drawCircle1' type="button">绘制圆</button>
            <div class="no">1</div>
            <div class="text" v-show='map1.radius > 0'>
                通过外切正方形和ol.sphere.getDistance计算圆的实际半径是{{map1.radius.toFixed(2)}}米
            </div>
        </div>
        <div id="map2">
            <div class="map"></div>
            <button @click='drawCircle2' type="button">绘制圆</button>
            <div class="no">2</div>
            <div class="text" v-show='map2.radius > 0'>
                通过外切正方形和ol.sphere.getDistance计算圆的实际半径是{{map2.radius.toFixed(2)}}米
            </div>
        </div>
        <div id="map3">
            <div class="map"></div>
            <button @click='drawCircle3' type="button">绘制圆</button>
            <div class="no">3</div>
            <div class="text" v-show='map3.radius > 0'>
                通过外切正方形和ol.sphere.getDistance计算圆的实际半径是{{map3.radius.toFixed(2)}}米
            </div>
        </div>
        <div id="map4">
            <div class="map"></div>
            <button @click='drawCircle4' type="button">绘制圆</button>
            <div class="no">4</div>
            <div class="text" v-show='map4.radius > 0'>
                通过外切正方形和ol.sphere.getDistance计算圆的实际半径是{{map4.radius.toFixed(2)}}米
            </div>
        </div>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/openlayers/9.2.4/dist/ol.min.js" integrity="sha512-xXS2hdEzrUC2BFO0fIJ+d/bwScOLgN+W7psE4XXq6xULXjKFCskUNe8QOVVUsB7vtYRI5ZS0Ie4EgS4VzJQBkQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.14/vue.global.prod.min.js" integrity="sha512-huEQFMCpBzGkSDSPVAeQFMfvWuQJWs09DslYxQ1xHeaCGQlBiky9KKZuXX7zfb0ytmgvfpTIKKAmlCZT94TAlQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script>
    const attributions = '<a href="https://ditu.amap.com/" target="_blank">&copy; 地图版权归高德地图所有</a>';
    const opt = {
        attribution: true, // 地图版权信息工具
        attributionOptions: {
            collapsed: false, // 默认折叠
            collapsible: false // 是否可折叠,显示折叠按钮
        }
    };
    const controls1 = ol.control.defaults.defaults(opt);
    const controls2 = ol.control.defaults.defaults(opt);
    const controls3 = ol.control.defaults.defaults(opt);
    const controls4 = ol.control.defaults.defaults(opt);
    const { createApp } = Vue;
    const points = [
        [106.03856529698734, 36.715601452531985],
        [106.04511871358466, 36.715249157323015],
        [106.0441664739892, 36.70309480469023],
        [106.05334789377213, 36.71736392034397],
        [106.04823045590192, 36.71700300656149],
        [106.03627851728827, 36.71912529157915],
        [106.05360531616198, 36.71198113636472],
        [106.05428014137092, 36.70364632178643],
        [106.05272219344934, 36.70405878147777],
        [106.04031644749523, 36.70131469639507],
        [106.04992475700587, 36.704465013438984],
        [106.0362851004705, 36.71631725725335],
        [106.04396444398678, 36.70170854267481],
        [106.03967129518713, 36.70465966283948],
        [106.04947973195947, 36.701027023961714],
        [106.05009739335343, 36.70103654486449],
        [106.04874323314455, 36.719335085953205],
        [106.03881457149267, 36.71469589863913],
        [106.04058181311, 36.717262154552685],
        [106.04119879278763, 36.719316603943696],
        [106.03312059096076, 36.701078249021116],
        [106.05204167785408, 36.70374086782358],
        [106.04870676748037, 36.70673950708234],
        [106.04015754145077, 36.71136658608413],
        [106.04881304819146, 36.71524252121091],
        [106.04589747892628, 36.71780435952241],
        [106.03434325338866, 36.71512495802869],
        [106.03603721844492, 36.70043548429202],
        [106.05045407137399, 36.710360982261406],
        [106.05160293938468, 36.71942325734422],
        [106.03969629297869, 36.7007645924199],
        [106.03586403120973, 36.717155982993525],
        [106.05337985500408, 36.70532711839829],
        [106.05599125714248, 36.71901791698683],
        [106.04675383821021, 36.71482007750959],
        [106.03565090215798, 36.71469680322872],
        [106.04896501175787, 36.71522708924307],
        [106.05514087275122, 36.715668531817215],
        [106.03677123895822, 36.70575434597479],
        [106.03527682817865, 36.71762155005134],
        [106.04671251850077, 36.708161558697505],
        [106.04166918273323, 36.718122766010765],
        [106.05686689596588, 36.71394013441751],
        [106.03510618101379, 36.705853577302385],
        [106.04987963777226, 36.71386476864049],
        [106.0437309103353, 36.71220071146156],
        [106.04388189720399, 36.71861748064869],
        [106.04747078253119, 36.71102457046147],
        [106.05245261048138, 36.71612487521888],
        [106.03906672145371, 36.71052904513593],
        [106.04770239170306, 36.71315125362329],
        [106.03835651355784, 36.707662446481805],
        [106.05179120177168, 36.71061592502026],
        [106.05631990450053, 36.709793483982914],
        [106.05505846219096, 36.7174717150576],
        [106.04948935552717, 36.70733869708594],
        [106.04913128708446, 36.71028657292116],
        [106.04082586277384, 36.70689167033498],
        [106.03878921926291, 36.712295856026316],
        [106.05597166455875, 36.718934346109855],
        [106.04458594406023, 36.712325321362606],
        [106.04553023288403, 36.718573076115305],
        [106.0377139625627, 36.70295490849309],
        [106.04507362315279, 36.701823477487295],
        [106.055910473036, 36.705235302254756],
        [106.03304137950572, 36.70596343837254],
        [106.04530861573848, 36.704210753641526],
        [106.04818217445073, 36.71724676661675],
        [106.04524631796305, 36.71345092172417],
        [106.05197425082197, 36.70876385934474],
        [106.05133232074328, 36.71253001408609],
        [106.05643889483093, 36.70245359947348],
        [106.05138093624726, 36.708667227263646],
        [106.05492091952475, 36.70522334930395],
        [106.04021222576561, 36.71303203877023],
        [106.04646254141682, 36.71066997999058],
        [106.05688047872697, 36.70340829434909],
        [106.04679357921378, 36.70350713868674],
        [106.04615639552989, 36.715637849843354],
        [106.04932134645253, 36.70916228366454],
        [106.04116669506682, 36.70695548745731],
        [106.05582832600577, 36.71656187147019],
        [106.03622355969662, 36.70204903093024],
        [106.03857970493063, 36.709859467933775],
        [106.03789778267465, 36.719485447001446],
        [106.04378213238229, 36.71270104328229],
        [106.05406414843756, 36.70477052639887],
        [106.05088835231388, 36.71592477339423],
        [106.03287966476613, 36.70070398927898],
        [106.04875533711666, 36.7087945623416],
        [106.05383547728064, 36.70817889692501],
        [106.04477844325737, 36.71036975386329],
        [106.05126518373585, 36.703257320496576],
        [106.04034907247515, 36.71372075225273],
        [106.053697991376, 36.70691196769714],
        [106.04650440971503, 36.70536709225446],
        [106.04868999368568, 36.71087850589237],
        [106.04894327456397, 36.7011707708129],
        [106.0394126654202, 36.71635780232134],
        [106.0388381325141, 36.716585730506516],
        [106.0326448555328, 36.702610527189165],
        [106.04201897570853, 36.718077319886376],
        [106.0378001062355, 36.717158370716554],
        [106.04888133264807, 36.70200187799761],
        [106.04021804839164, 36.700540435616126],
        [106.03784170223852, 36.71327590603148],
        [106.05393633775599, 36.701378827646224],
        [106.04451593745588, 36.70258972594541],
        [106.04939628338197, 36.71132554060028],
        [106.04103796987322, 36.71781284710831],
        [106.05177065376328, 36.71906135452441],
        [106.04921013441802, 36.70394190294814],
        [106.0403178873249, 36.711696186898735],
        [106.03407637806852, 36.71562338269049],
        [106.05644150310924, 36.71758133757321],
        [106.05683737377416, 36.713101267097414],
        [106.05534798197625, 36.70922744499401],
        [106.0357939454618, 36.70471399438291],
        [106.05433154590376, 36.70290803026316],
        [106.03264085328779, 36.714549813420675],
        [106.04428732464854, 36.70820716843422],
        [106.05469080591362, 36.716377184570185],
        [106.04780035322352, 36.7040761232565],
        [106.04548038423829, 36.709776264730806],
        [106.05119827677512, 36.70817721466057],
        [106.05290523857231, 36.712519436472185],
        [106.0504020471747, 36.70039422022602],
        [106.04620637835825, 36.7173258855394],
        [106.05227834599178, 36.70458765214443],
        [106.03825798206574, 36.70722796140763],
        [106.05217242677695, 36.70772520894793],
        [106.03380008375886, 36.70294806341726],
        [106.0518410377322, 36.70354835106634],
        [106.033890176223, 36.71189378230229],
        [106.04639018191502, 36.71205887554912],
        [106.03775394951647, 36.70446218961782],
        [106.0487829996151, 36.70649306362228],
        [106.04003456058831, 36.70209972419181],
        [106.05039205184828, 36.713702030164434],
        [106.04911798300643, 36.700665812564765],
        [106.04310673452018, 36.71826056574923],
        [106.04533512785106, 36.70489164269526],
        [106.04601777224514, 36.71085347625881],
        [106.04614716311029, 36.708608749380566],
        [106.04628691786874, 36.703539900728614],
        [106.05286500650338, 36.707216529886914],
        [106.05183506333333, 36.69995690172742],
        [106.04675392818517, 36.70604546151936],
        [106.04576551604372, 36.71541249703902],
        [106.04438841236691, 36.70122891745222],
        [106.04232133868294, 36.71278495342945],
        [106.050502151664, 36.709216657364706],
        [106.04572508426592, 36.71375157340604],
        [106.03479197187006, 36.71169673905095],
        [106.0554333966306, 36.710725503536956],
        [106.03966051160171, 36.718046132028434],
        [106.05456768673989, 36.702155441652366],
        [106.03707017826035, 36.70527654128902],
        [106.03947902773584, 36.71350623566335],
        [106.04043697680892, 36.710805824387144],
        [106.04904035599918, 36.71333631650749],
        [106.04733798431874, 36.710704170698676],
        [106.05296019785051, 36.70783313840637],
        [106.0391263591018, 36.707461325955215],
        [106.05325279662762, 36.70536322216468],
        [106.0506900602622, 36.705920294077174],
        [106.03833260407428, 36.70313549234984],
        [106.0355718325746, 36.70095966465655],
        [106.03737877849426, 36.700006600639966],
        [106.04987463584925, 36.702938236981765],
        [106.0416836880834, 36.71976144285817],
        [106.03239951008095, 36.70385559818152],
        [106.04987359225544, 36.7048785013871],
        [106.04284993637684, 36.71304289422518],
        [106.05315320131669, 36.70013062762211],
        [106.04636803132085, 36.70140687433069],
        [106.03222326157571, 36.7164493838061],
        [106.05529200080794, 36.7029578705509],
        [106.04593000325151, 36.70239718695554],
        [106.05072083163437, 36.706991719399525],
        [106.04640673049332, 36.70964026865297],
        [106.03855990160424, 36.70540768761446],
        [106.05332296126807, 36.70160185637431],
        [106.0466812758447, 36.71985433012892],
        [106.05340274994487, 36.71490014557847],
        [106.03383512464055, 36.71786203096421],
        [106.03390133804677, 36.71200045570234],
        [106.04932079848855, 36.70115984183022],
        [106.04783041940833, 36.709823937702375],
        [106.05678771546434, 36.70549771686619],
        [106.03822944714464, 36.71063563192302],
        [106.03461814019026, 36.702663860491086],
        [106.05638072919696, 36.701745969556136],
        [106.0557453493057, 36.70676485391145],
        [106.03616985546736, 36.716395082863656],
        [106.03767891436716, 36.716791922477555],
        [106.04549999280567, 36.70381460640143],
        [106.05433773130724, 36.708383990284034],
        [106.045837908683, 36.71340038892937],
        [106.03272402745576, 36.69995799280429],
        [106.04587463242001, 36.71535230550449],
        [106.0557474779694, 36.70528718715958],
        [106.04447641040765, 36.71419615423086],
        [106.04810714060854, 36.712995577010325],
        [106.03684734490014, 36.70634076517822],
        [106.03863406228542, 36.70766656378712],
        [106.04816729975687, 36.71686251319633],
        [106.04448795390216, 36.71214238711057],
        [106.03480072117743, 36.70374993822852],
        [106.04407178124542, 36.716899495000135],
        [106.05532557902093, 36.71632472042606],
        [106.05507706902513, 36.71279191815255],
        [106.04417594278276, 36.70525482292016],
        [106.04930651529567, 36.71527476742723],
        [106.05187862568722, 36.7140425950128],
        [106.04047262041387, 36.70299286776074],
        [106.05431935556251, 36.70720669360498],
        [106.04457033469778, 36.70054935324986],
        [106.04303126730774, 36.719559601533696],
        [106.05569969919843, 36.70251762453498],
        [106.04831903707762, 36.70367855404402],
        [106.03381762680844, 36.70394286642498],
        [106.05527763278069, 36.70358945310848],
        [106.03542558865388, 36.70667530355766],
        [106.03694671947558, 36.70311918704647],
        [106.04044424613987, 36.70556714660077],
        [106.03467597729748, 36.718709456475075],
        [106.03398256001896, 36.718224102940205],
        [106.04668524712888, 36.71211523043252],
        [106.04551157664821, 36.719403129398486],
        [106.03779648679831, 36.71406555335596],
        [106.03616053115213, 36.704877663042886],
        [106.03808087838968, 36.70824217583612],
        [106.05602736857116, 36.71085103668903],
        [106.0485743664788, 36.71872452537744],
        [106.0345013412136, 36.70621265352114],
        [106.04194771643465, 36.70097355869823],
        [106.0380406636863, 36.70326342362782],
        [106.05470356468179, 36.70150431181921],
        [106.05154927580638, 36.70388325632227],
        [106.03213826105276, 36.70066568242373],
        [106.04707022733638, 36.71229443195848],
        [106.04185773685298, 36.70747652186279],
        [106.04315171328125, 36.70900700766254],
        [106.04892832052079, 36.719779538379875],
        [106.03568689238371, 36.70553899199747],
        [106.04838588099524, 36.713752885006286],
        [106.04711086938697, 36.71277596929717],
        [106.05550266903327, 36.719089041840945],
        [106.04337826204709, 36.71819988828975],
        [106.04569853740217, 36.70549390390651],
        [106.03728096061772, 36.703264360106566],
        [106.03914262699271, 36.70184285196452],
        [106.04097821448354, 36.70842703479423],
        [106.03583469129666, 36.70333173298524],
        [106.04535387203276, 36.70708978562918],
        [106.04223924510708, 36.7134509292004],
        [106.05145917480039, 36.719403935468044],
        [106.04044938279979, 36.71810882814595],
        [106.0553455225815, 36.71949355029116],
        [106.04314755523593, 36.71645122305788],
        [106.04481036578464, 36.71885508326397],
        [106.05565599762916, 36.71874865147025],
        [106.05389516820489, 36.71289215641193],
        [106.03304167486988, 36.716813858042926],
        [106.0409460962699, 36.70219734005007],
        [106.04124507036776, 36.70248301066145],
        [106.04688510709857, 36.70271494472224],
        [106.0449768279204, 36.717040399641554],
        [106.05387632457463, 36.718269503142515],
        [106.05120699887344, 36.70984564045039],
        [106.04496249189789, 36.70321863863696],
        [106.03896504917707, 36.70419546319513],
        [106.04320647626743, 36.70306118164444],
        [106.04137045661689, 36.71019131343606],
        [106.05191973143974, 36.71068311003903],
        [106.05430272252461, 36.70075443784451],
        [106.03447204582379, 36.70052254899382],
        [106.0468355859208, 36.708394693663664],
        [106.05617645721657, 36.716272887953245],
        [106.04944706451056, 36.70461379059886],
        [106.04045229847124, 36.70073377644245],
        [106.05116040683545, 36.71052790723829],
        [106.05615470222952, 36.71123339245161],
        [106.04003861226059, 36.702555065412184],
        [106.04891944112643, 36.71490037368554],
        [106.04965603345349, 36.700760813901475],
        [106.0358665234692, 36.715695274273386],
        [106.03774219896556, 36.70506106407363],
        [106.0524323097498, 36.70056077167771],
        [106.05035219600221, 36.711291243033585],
        [106.04894433456562, 36.70100562776742],
        [106.03462832374007, 36.70950550944486],
        [106.05681465080569, 36.70957628850537],
        [106.05564186457724, 36.708083463811164],
        [106.03711288965172, 36.70025229922964],
        [106.04029187732093, 36.70113567426903],
        [106.0503300514655, 36.711929477579325],
        [106.05169202268291, 36.707030798025464],
        [106.03282607786207, 36.711643420465776],
        [106.04471033755955, 36.70547049444256],
        [106.03260043460058, 36.71637755917025],
        [106.03761757632347, 36.71740216295046],
        [106.04847316530716, 36.719385977044595],
        [106.04449218437765, 36.719181188059025],
        [106.05076099246332, 36.70311856637862],
        [106.04830551231728, 36.70587082061162],
        [106.05534302194665, 36.70541445870636],
        [106.05382604585122, 36.714389841044564],
        [106.04271260030971, 36.71616260141933],
        [106.0444473672652, 36.717790677194195],
        [106.04621899530942, 36.701668896607856],
        [106.05426167611076, 36.71547373741108],
        [106.04876748388521, 36.70217670408399],
        [106.03704079985748, 36.70076831071585],
        [106.03709049506224, 36.7035296010181],
        [106.05485737116972, 36.70473447848138],
        [106.04563751763521, 36.70216531719663],
        [106.03286585839643, 36.70475513338537],
        [106.04496365116194, 36.71041003090177],
        [106.04575850704198, 36.7134273444236],
        [106.04774475622483, 36.70951744712853],
        [106.04730844967102, 36.71029452079092],
        [106.04070505769285, 36.71291339683349],
        [106.03426515345926, 36.71154806489388],
        [106.05458716874529, 36.70887443891013],
        [106.05299157125887, 36.7034236603848],
        [106.0492116091035, 36.70634811666345],
        [106.04779355115062, 36.71555301725728],
        [106.0358426214764, 36.71266104446128],
        [106.05071214140189, 36.71213907946835],
        [106.05452587564318, 36.703035987091496],
        [106.04691920942791, 36.71113831137103],
        [106.054101183946, 36.7072236383197],
        [106.03290103459432, 36.71352192273852],
        [106.05349157216071, 36.71659247637842],
        [106.05464742827013, 36.716695523304814],
        [106.04176786545918, 36.718381216509606],
        [106.0434851534801, 36.708744703193425],
        [106.03280578860841, 36.71187955274604],
        [106.05621330962762, 36.71632533428255],
        [106.03216939451838, 36.70297378682236],
        [106.03330944124103, 36.70582228978953],
        [106.0360416439692, 36.70558043432113],
        [106.03939556154845, 36.70523021802937],
        [106.03577381544757, 36.70925729812435],
        [106.03561724584505, 36.71528141091663],
        [106.0451311366277, 36.71579605390048],
        [106.05156625872931, 36.70828804935262],
        [106.04070706101032, 36.70628475919599],
        [106.04194889168618, 36.71433701430015],
        [106.0525208085825, 36.71480627492417],
        [106.0452582678306, 36.7074783774109],
        [106.03289515322506, 36.70802695801666],
        [106.03799044143197, 36.71784851708591],
        [106.03390319172952, 36.701566305149555],
        [106.04183945777444, 36.71537415600202],
        [106.0447963558994, 36.706974557275345],
        [106.04032050367881, 36.70112888580936],
        [106.04764850478733, 36.703566850258824],
        [106.04540367042308, 36.71668205659898],
        [106.04935925305546, 36.71014368406572],
        [106.05141487596453, 36.71307490903447],
        [106.03379649025938, 36.71005442589269],
        [106.04982755245594, 36.70597826650642],
        [106.0559137246373, 36.70326779802888],
        [106.05598394739748, 36.71029440571298],
        [106.04051637300584, 36.706046204747686],
        [106.03334897626561, 36.71714118549034],
        [106.0483331047027, 36.7133279405543],
        [106.05625166283839, 36.7151401020501],
        [106.03908226393187, 36.71353046966022],
        [106.03204632348513, 36.704959476384026],
        [106.04004555365728, 36.71182792622598],
        [106.04413869185454, 36.716371543214805],
        [106.03803755440441, 36.71792929596167],
        [106.04155380768336, 36.70384909312614],
        [106.04733291007393, 36.71557440664517],
        [106.0368392221992, 36.716208053130245],
        [106.0376311214515, 36.718276209445996],
        [106.0502353426452, 36.71603257104893],
        [106.04198653560763, 36.71416216196465],
        [106.05365850887728, 36.703179804727995],
        [106.0335108099139, 36.71336091891637],
        [106.05546475962966, 36.71778824689305],
        [106.04931564677848, 36.711743006798294],
        [106.0501829693853, 36.7082338088767],
        [106.03703319901514, 36.71718748244755],
        [106.04703650620726, 36.700701532490264],
        [106.05015363441433, 36.70200294835435],
        [106.0536002688133, 36.716507973853304],
        [106.05403787168486, 36.70333545045256],
        [106.055748560005, 36.70836650611977],
        [106.03364962987283, 36.71070330842656],
        [106.05264999723273, 36.70271761948378],
        [106.04678757968013, 36.70549302535579],
        [106.04261613860061, 36.706574223031154],
        [106.04450856912118, 36.70340150619908],
        [106.04807717868269, 36.71857319503142],
        [106.05064891627359, 36.70027703990959],
        [106.03270791070948, 36.704892949344035],
        [106.03221664922037, 36.715716235092295],
        [106.03599813947318, 36.7031368792047],
        [106.04276425120963, 36.70117328686747],
        [106.0473037985282, 36.70405212779703],
        [106.03810220835216, 36.702867519579456],
        [106.0483290137876, 36.71671822232172],
        [106.04904719315728, 36.711206496719974],
        [106.04753011288827, 36.71251543642333],
        [106.04905583372617, 36.70020584793258],
        [106.05224310052633, 36.70110336106104],
        [106.04947680488715, 36.71798527321728],
        [106.03830208565758, 36.714630000842206],
        [106.0325071220447, 36.71518002823173],
        [106.03999568460011, 36.70650950533316],
        [106.04403241767253, 36.700288334710926],
        [106.04926477743953, 36.71492156079252],
        [106.05139136586614, 36.70487400314485],
        [106.03481269980115, 36.70901647759997],
        [106.03394831294484, 36.71175310110714],
        [106.05248216101539, 36.718571982208644],
        [106.05359101692488, 36.71479285070182],
        [106.051980633667, 36.70483828285411],
        [106.05464032305628, 36.70479723151598],
        [106.04148059975869, 36.712495647107325],
        [106.04810110051436, 36.71796515883503],
        [106.03507030268236, 36.71553986578019],
        [106.04258501488121, 36.70556956669319],
        [106.04726097931741, 36.700995609965126],
        [106.04904012773262, 36.71045371167133],
        [106.04574541145624, 36.709079263857],
        [106.03706525135219, 36.71599330507114],
        [106.03468264276357, 36.709695269629],
        [106.03400927300177, 36.718212868399014],
        [106.04866441053859, 36.71624791925375],
        [106.0430022011958, 36.70140537121249],
        [106.04551948586212, 36.70078199377391],
        [106.03833316220913, 36.70252854638897],
        [106.04547320281306, 36.71945889312365],
        [106.04954978424122, 36.70726341987572],
        [106.04109970713621, 36.71643155689624],
        [106.03634515899242, 36.715743501780544],
        [106.05520257477436, 36.70627528436206],
        [106.0334791849541, 36.71204111906343],
        [106.03642755366457, 36.718822131694594],
        [106.05570540920304, 36.71739174700097],
        [106.05497917607805, 36.707227458855556],
        [106.03432145841626, 36.71351626285991],
        [106.03537679206863, 36.70326066144831],
        [106.05245174330476, 36.71133890442973],
        [106.03410744411066, 36.7111663472046],
        [106.04131772047506, 36.71741185159578],
        [106.03683030450382, 36.71131625899536],
        [106.04578179234655, 36.70064281321336],
        [106.05290198971426, 36.71742527212465],
        [106.04278604129415, 36.71139616913906],
        [106.04950822351584, 36.71084541452434],
        [106.03915575153927, 36.70928046913254],
        [106.05175594452174, 36.69987503925852],
        [106.0492571667899, 36.703980740219826],
        [106.03877990359152, 36.715453434198096],
        [106.04210436097638, 36.71793215607503],
        [106.0450396630497, 36.71488787325943],
        [106.0362129377385, 36.70869032059021],
        [106.03616241613977, 36.704520030911226],
        [106.036661948216, 36.71666549749765],
        [106.0329563273556, 36.7057664993579],
        [106.05175848979977, 36.717470427670754],
        [106.05160619807715, 36.71821257348684],
        [106.04985305983249, 36.70981592918541],
        [106.03717425500905, 36.70395989504171],
        [106.0431519223249, 36.70969982963854],
        [106.04791933202296, 36.71166776985325],
        [106.04537992214972, 36.703042468910475],
        [106.03838271793984, 36.70969081491188],
        [106.05150120069915, 36.70479171925673],
        [106.03964719607897, 36.708501806202065],
        [106.04988172882067, 36.70238413561519],
        [106.0515486626882, 36.719679345986265],
        [106.0555674897898, 36.704266013255825],
        [106.05328606775883, 36.7069827019421],
        [106.04348697993494, 36.71906304950808],
        [106.0566659338933, 36.703587088929815],
        [106.05155902690595, 36.70213212761456],
        [106.05556402574092, 36.70805818768446],
        [106.04093978164462, 36.71224978155864],
        [106.04423836322405, 36.713804700344205],
        [106.05567341653659, 36.70929223671041],
        [106.04311596451332, 36.71665852437281],
        [106.05554487892157, 36.705036419359686],
        [106.03866064193534, 36.71467711999602],
        [106.04996103564122, 36.7111101601153],
        [106.0496870916733, 36.70099960674403],
        [106.03364757016008, 36.71325092085002],
        [106.03564848477943, 36.71123063217433],
        [106.05168459026355, 36.70367452460956],
        [106.03626557305711, 36.71827554297811],
        [106.04458924959508, 36.71161496382338],
        [106.03998119515909, 36.71721163978081],
        [106.0372755957419, 36.70871757428361],
        [106.0350172218906, 36.71777573175365],
        [106.0468968687522, 36.718858317745664],
        [106.03401798990103, 36.71840316096129],
        [106.05035178201196, 36.70838852198183],
        [106.05015846355417, 36.71588497322889],
        [106.03534804178162, 36.71395492206424],
        [106.03291149086361, 36.71353972923258],
        [106.04242574808862, 36.71805946198379],
        [106.04857685280867, 36.710510006810985],
        [106.05040795288119, 36.70455880045482],
        [106.0537428465665, 36.70653594136755],
        [106.05260419457004, 36.71626289476245],
        [106.04631877682618, 36.71804829509059],
        [106.05576379897457, 36.70259282865169],
        [106.04171261840376, 36.714052932880776],
        [106.04921110116398, 36.70850769925966],
        [106.04299107825874, 36.70663292145527],
        [106.04209691348417, 36.71395833875756],
        [106.04039654359438, 36.7005617359808],
        [106.04164288667022, 36.700395795511774],
        [106.04118297177719, 36.71924705829585],
        [106.03672620151532, 36.71631032990466],
        [106.03387707308877, 36.717487780195896],
        [106.0392897842217, 36.71452401819241],
        [106.03614359601163, 36.71323245152329],
        [106.03462292844712, 36.71403587352088],
        [106.04191597714244, 36.713942988276315],
        [106.05429571014103, 36.70330806671734],
        [106.03760562358613, 36.705780374389064],
        [106.0504368833694, 36.70540604388448],
        [106.05265016366403, 36.71137792395548],
        [106.04574429147176, 36.70363717690035],
        [106.04816012248729, 36.71397943103718],
        [106.05035693498421, 36.715794242076534],
        [106.04559268886602, 36.71398018823342],
        [106.04802227995116, 36.71396534337241],
        [106.04217912451941, 36.71496095795798],
        [106.04870991522488, 36.7086808770516],
        [106.03731488879549, 36.7162007598518],
        [106.05086246945935, 36.71719539725983],
        [106.05592257048683, 36.71789346567711],
        [106.03598422842744, 36.712141163237625],
        [106.04294856395072, 36.70887482419375],
        [106.03424210075087, 36.70216268521245],
        [106.03616506969709, 36.718533481738554],
        [106.0344162297561, 36.70893260042332],
        [106.04461980866861, 36.71047871350797],
        [106.05333040130357, 36.71335078544918],
        [106.05668635292338, 36.71837147921423],
        [106.05316597998787, 36.71101682456235],
        [106.04536252848428, 36.71376799752717],
        [106.03545638837527, 36.71683738643369],
        [106.05496287652628, 36.711903234311606],
        [106.0352032482723, 36.70399920927027],
        [106.05149090527806, 36.701268454295715],
        [106.05378038146443, 36.703687560826054],
        [106.04746786310935, 36.7120744348901],
        [106.04799814908839, 36.714896300328384],
        [106.03246974586685, 36.717496315563274],
        [106.04800005975162, 36.701007472136666],
        [106.03255710363348, 36.71013784982679],
        [106.05410423491749, 36.70423749627373],
        [106.0351963727064, 36.714878423534294],
        [106.05124266382217, 36.717697791092824],
        [106.04420248013527, 36.71451424790791],
        [106.0449279394075, 36.71061415553897],
        [106.03308228705512, 36.70518586897944],
        [106.04253959623362, 36.71084501815781],
        [106.05639596927357, 36.712998631562364],
        [106.03343970746432, 36.707920341059776],
        [106.05381818816598, 36.7020736331998],
        [106.0396064440584, 36.71963003062546],
        [106.0464325041783, 36.71430268277222],
        [106.0422377575763, 36.7077254929263],
        [106.05186278111104, 36.71124066630282],
        [106.04978995594801, 36.70896060867328],
        [106.04534540967332, 36.71234291090418],
        [106.0465711670962, 36.71087665577389],
        [106.05028762408061, 36.71169237101467],
        [106.04917061621866, 36.70780568270031],
        [106.03386465913144, 36.70149718153289],
        [106.05031138094164, 36.71186829801462],
        [106.03853587812273, 36.71715039868047],
        [106.04804491283406, 36.69990523806046],
        [106.05010794166067, 36.706924122837016],
        [106.05233542684257, 36.718950993928814],
        [106.03790444019563, 36.7152190689625],
        [106.04165507645716, 36.719550589047685],
        [106.03581948075197, 36.71512528836285],
        [106.05632243145658, 36.71416432566731],
        [106.041038193138, 36.71739590178611],
        [106.04371097217168, 36.71868761277389],
        [106.05442176125383, 36.701819600108145],
        [106.0379648669348, 36.70908788011148],
        [106.03641122700984, 36.71402771461132],
        [106.05657884490662, 36.70842904901045],
        [106.04389854634292, 36.709827804640625],
        [106.0438270194108, 36.71105599428718],
        [106.0457040575846, 36.70404425757913],
        [106.0568274375135, 36.70915911176283]
    ];

    function toRadians(degrees) {
        return degrees * Math.PI / 180;
    }

    function toDegrees(radians) {
        return radians * 180 / Math.PI;
    }

    function calculateDestination(coord1, distance, bearing) {
        const R = 6371000; // 地球半径,单位为米
        const lat1 = toRadians(coord1[1]);
        const lon1 = toRadians(coord1[0]);
        const theta = toRadians(bearing);
        const dR = distance / R;
        const lat2 = Math.asin(Math.sin(lat1) * Math.cos(dR) +
            Math.cos(lat1) * Math.sin(dR) * Math.cos(theta));
        const lon2 = lon1 + Math.atan2(Math.sin(theta) * Math.sin(dR) * Math.cos(lat1),
            Math.cos(dR) - Math.sin(lat1) * Math.sin(lat2));
        return [toDegrees(lon2), toDegrees(lat2)];
    }
    const center4326 = [106.04453415000009, 36.70986324334069];
    const center3857 = ol.proj.transform(center4326, 'EPSG:4326', 'EPSG:3857');
    const radius = 1000;
    const R = 6371000; // 地球半径
    const circleStyle = new ol.style.Style({
        stroke: new ol.style.Stroke({
            color: '#20b1aa',
            width: 4
        }),
        zIndex: 2
    })
    const vm = createApp({
        data() {
            return {
                map1: {
                    map: {},
                    radius: 0,
                    layer: {}
                },
                map2: {
                    map: {},
                    radius: 0,
                    layer: {}
                },
                map3: {
                    map: {},
                    radius: 0,
                    layer: {}
                },
                map4: {
                    map: {},
                    radius: 0,
                    layer: {}
                }
            }
        },
        methods: {
            // 初始化地图
            initMap() {
                // 高德地图瓦片地址
                const source = new ol.source.XYZ({
                    url: 'http://wprd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}',
                    attributions: attributions
                });
                const viewOpt = {
                    center: center3857,
                    zoom: 14
                };
                this.map1.map = new ol.Map({
                    target: document.querySelector('#map1 .map'),
                    layers: [new ol.layer.Tile({
                        source
                    })],
                    controls: controls1,
                    view: new ol.View({
                        ...viewOpt
                    })
                });
                this.map2.map = new ol.Map({
                    target: document.querySelector('#map2 .map'),
                    layers: [new ol.layer.Tile({
                        source
                    })],
                    controls: controls2,
                    view: new ol.View({
                        ...viewOpt
                    })
                });
                this.map3.map = new ol.Map({
                    target: document.querySelector('#map3 .map'),
                    layers: [new ol.layer.Tile({
                        source
                    })],
                    controls: controls3,
                    view: new ol.View({
                        ...viewOpt
                    })
                });
                this.map4.map = new ol.Map({
                    target: document.querySelector('#map4 .map'),
                    layers: [new ol.layer.Tile({
                        source
                    })],
                    controls: controls4,
                    view: new ol.View({
                        ...viewOpt
                    })
                });
                // // 渲染点位
                this.renderPoints(1);
                this.renderPoints(2);
                this.renderPoints(3);
                this.renderPoints(4);
            },
            // 使用ol.geom.Circle直接绘制半径为1000米的圆
            drawCircle1() {
                const geom = new ol.geom.Circle(center3857, radius);
                const feature = new ol.Feature(geom);
                feature.setStyle(circleStyle);
                this.map1.layer.getSource().addFeature(feature);
                // 绘制辅助正方形,验证圆的半径
                this.drawRect(feature.getGeometry(), this.map1);
                console.log('通过ol.geom.Circle方法,以1000为半径绘制的圆,使用外切正方形计算的半径是', this.map1.radius);
                // 圆上的点到圆心的距离验证圆的实际半径
                const pointOnCircle = [center3857[0], center3857[1] + radius];
                const pointOnCircle4326 = ol.proj.transform(pointOnCircle, 'EPSG:3857', 'EPSG:4326')
                this.drawPoint(pointOnCircle4326, this.map1.layer);
                const distanceRadius = ol.sphere.getDistance(pointOnCircle4326, center4326);
                console.log('通过ol.geom.Circle方法,以1000为半径绘制的圆,使用圆上的一点,通过ol.sphere.getDistance计算点到圆心的距离', distanceRadius);
                // 圆上的点到圆心的距离验证圆的实际半径
                const lastCoord = geom.getLastCoordinate();
                const lastCoord4326 = ol.proj.transform(lastCoord, 'EPSG:3857', 'EPSG:4326')
                this.drawPoint(lastCoord4326, this.map1.layer, 'black');
                const distanceRadius1 = ol.sphere.getDistance(lastCoord4326, center4326);
                console.log('通过ol.geom.Circle方法,以1000为半径绘制的圆,使用圆上的一点,通过ol.sphere.getDistance计算点到圆心的距离', distanceRadius1);
                // 用ol.sphere.getDistance计算点位距离圆心的距离是否在1000米之内,在的,变为红色
                this.calcDistanceAndSetStyle(this.map1);
            },
            // 以圆心为基准,经度方向和纬度方向上,计算出距离这个圆心1000米的点位的经纬度,
            // 再计算两个点位距离圆心的平面距离,以两个距离中较大的作为圆心,绘制圆
            drawCircle2() {
                // 计算出经度方向上距离圆心1000米的点的坐标
                const lat1 = center4326[1] + (radius / R) * (180 / Math.PI);
                const top4236 = [center4326[0], lat1];
                const top3857 = ol.proj.transform(top4236, 'EPSG:4326', 'EPSG:3857');
                this.drawPoint(top4236, this.map2.layer);
                const topDistance = ol.sphere.getDistance(center4326, top4236);
                console.log('计算出来的经度方向的点', top4236)
                console.log('通过ol.sphere.getDistance验证计算出来的经度方向的点和中心点的实际距离', topDistance);
                // 计算出纬度方向上距离圆心1000米的点的坐标
                const lon1 = center4326[0] + (1000 / (R * Math.cos(Math.PI * center4326[1] / 180))) * (180 / Math.PI);
                const right4236 = [lon1, center4326[1]];
                const right3857 = ol.proj.transform(right4236, 'EPSG:4326', 'EPSG:3857');
                this.drawPoint(right4236, this.map2.layer);
                const rightDistance = ol.sphere.getDistance(center4326, right4236);
                console.log('计算出来的纬度方向的点', right4236);
                console.log('通过ol.sphere.getDistance验证计算出来的纬度方向的点和中心点的实际距离', rightDistance);
                // 计算经度方向上的点和圆心的平面距离
                const dx = top3857[0] - center3857[0];
                const dy = top3857[1] - center3857[1];
                const verticalDistance = Math.sqrt(dx * dx + dy * dy);
                console.log('垂直方向上平面距离', verticalDistance);
                // 计算纬度方向上的点和圆心的平面距离
                const dxR = right3857[0] - center3857[0];
                const dyR = right3857[1] - center3857[1];
                const horizontalDistance = Math.sqrt(dxR * dxR + dyR * dyR);
                console.log('水平方向上平面距离', horizontalDistance);
                // 两个距离选择最大的作为圆的半径
                const bigRadius = Math.max(verticalDistance, horizontalDistance);
                console.log(`以 ${bigRadius} 为半径绘制圆,此圆的平面半径是${bigRadius},在地球的椭圆上的半径是${radius}`);
                const feature = new ol.Feature(new ol.geom.Circle(center3857, bigRadius));
                feature.setStyle(circleStyle);
                this.map2.layer.getSource().addFeature(feature);
                // 用ol.sphere.getDistance计算点位距离圆心的距离是否在1000米之内,在的,变为红色
                this.calcDistanceAndSetStyle(this.map2);
                // 绘制圆的外切正方形,通过正方形变长验证绘制的圆的半径
                this.drawRect(feature.getGeometry(), this.map2);
                console.log('通过ol.geom.Circle方法,以' + bigRadius + '为半径绘制的圆,使用外切正方形计算的半径是', this.map2.radius);
                // 通过圆上的一点,ol.sphere.getDistance计算点到圆心的距离
                const pointOnCircle = [center3857[0] - bigRadius, center3857[1]];
                const distanceRadius = ol.sphere.getDistance(ol.proj.transform(pointOnCircle, 'EPSG:3857', 'EPSG:4326'), center4326);
                console.log('通过ol.geom.Circle方法,以' + bigRadius + '为半径绘制的圆,使用圆上的一点,通过ol.sphere.getDistance计算点到圆心的距离', distanceRadius);
            },
            // 通过ol.geom.Polygon.circular绘制
            drawCircle3() {
                const geom4326 = ol.geom.Polygon.circular(center4326, 1000, 64, 6371000);
                const geom3857 = geom4326.clone().transform('EPSG:4326', 'EPSG:3857');
                const feature = new ol.Feature(geom3857);
                feature.setStyle(circleStyle);
                this.map3.layer.getSource().addFeature(feature);
                // 绘制辅助正方形,验证圆的直径
                this.drawRect(feature.getGeometry(), this.map3);
                this.calcDistanceAndSetStyle(this.map3);
                console.log('通过ol.geom.Polygon.circular方法,以1000为半径绘制的近似圆,使用外切正方形计算的半径是', this.map3.radius);
                // 通过圆上的一点,ol.sphere.getDistance计算点到圆心的距离
                const pointOnCircle = [geom4326.flatCoordinates[0], geom4326.flatCoordinates[1]];
                this.drawPoint(pointOnCircle, this.map3.layer);
                const distanceRadius = ol.sphere.getDistance(pointOnCircle, center4326);
                console.log('通过ol.geom.Polygon.circular方法,以1000为半径绘制的近似圆,使用圆上的一点,通过ol.sphere.getDistance计算点到圆心的距离', distanceRadius);
            },
            // 与 drawCircle2 思路相同,只不过计算点使用calculateDestination函数
            drawCircle4() {
                const top4236 = calculateDestination(center4326, radius, 0);
                const top3857 = ol.proj.transform(top4236, 'EPSG:4326', 'EPSG:3857');
                this.drawPoint(top4236, this.map4.layer);
                const topDistance = ol.sphere.getDistance(center4326, top4236);
                console.log('计算出来的经度方向的点', top4236);
                console.log('通过ol.sphere.getDistance验证计算出来的经度方向的点和中心点的实际距离', topDistance);
                const right4236 = calculateDestination(center4326, radius, 90);
                const right3857 = ol.proj.transform(right4236, 'EPSG:4326', 'EPSG:3857');
                this.drawPoint(right4236, this.map4.layer);
                const rightDistance = ol.sphere.getDistance(center4326, right4236);
                console.log('计算出来的纬度方向的点', right4236);
                console.log('通过ol.sphere.getDistance验证计算出来的纬度方向的点和中心点的实际距离', rightDistance);
                // 计算经度方向上的点和圆心的平面距离
                const dx = top3857[0] - center3857[0];
                const dy = top3857[1] - center3857[1];
                const verticalDistance = Math.sqrt(dx * dx + dy * dy);
                console.log('垂直方向上平面距离', verticalDistance);
                // 计算纬度方向上的点和圆心的平面距离
                const dxR = right3857[0] - center3857[0];
                const dyR = right3857[1] - center3857[1];
                const horizontalDistance = Math.sqrt(dxR * dxR + dyR * dyR);
                console.log('水平方向上平面距离', horizontalDistance);
                // 两个距离选择最大的作为圆的半径
                const bigRadius = Math.max(verticalDistance, horizontalDistance);
                console.log(`以 ${bigRadius} 为半径绘制圆,此圆的平面半径是${bigRadius},在地球的椭圆上的半径是${radius}`);
                const feature = new ol.Feature(new ol.geom.Circle(center3857, bigRadius));
                feature.setStyle(circleStyle);
                this.map4.layer.getSource().addFeature(feature);
                // 用ol.sphere.getDistance计算点位距离圆心的距离是否在1000米之内,在的,变为红色
                this.calcDistanceAndSetStyle(this.map4);
                // 绘制圆的外切正方形,通过正方形变长验证绘制的圆的半径
                this.drawRect(feature.getGeometry(), this.map4);
                console.log('通过ol.geom.Circle方法,以' + bigRadius + '为半径绘制的圆,使用外切正方形计算的半径是', this.map4.radius);
                // 通过圆上的一点,ol.sphere.getDistance计算点到圆心的距离
                const pointOnCircle = [center3857[0] - bigRadius, center3857[1]];
                const distanceRadius = ol.sphere.getDistance(ol.proj.transform(pointOnCircle, 'EPSG:3857', 'EPSG:4326'), center4326);
                console.log('通过ol.geom.Circle方法,以' + bigRadius + '为半径绘制的圆,使用圆上的一点,通过ol.sphere.getDistance计算点到圆心的距离', distanceRadius);
            },
            // 绘制辅助的矩形
            drawRect(circleGeom, map) {
                const rect = circleGeom.getExtent();
                const coordinates = [
                    [rect[2], rect[3]],
                    [rect[2], rect[1]],
                    [rect[0], rect[1]],
                    [rect[0], rect[3]],
                    [rect[2], rect[3]]
                ]
                // 辅助正方形
                const polygon = new ol.geom.Polygon([coordinates]);
                // 创建多边形的样式
                const style = new ol.style.Style({
                    fill: new ol.style.Fill({
                        color: 'rgba(255 ,255 ,255 , 0.5)'
                    }),
                    stroke: new ol.style.Stroke({
                        color: '#192336',
                        width: 2
                    })
                });
                const feature = new ol.Feature({
                    geometry: polygon
                });
                feature.setStyle(style);
                map.layer.getSource().addFeature(feature);
                const p1 = ol.proj.transform([rect[2], rect[3]], 'EPSG:3857', 'EPSG:4326');
                const p2 = ol.proj.transform([rect[2], rect[1]], 'EPSG:3857', 'EPSG:4326');
                map.radius = (ol.sphere.getDistance(p1, p2) / 2);
            },
            // 计算距离并修改样式
            calcDistanceAndSetStyle(mapN) {
                const goodPoints = [];
                for (let i = 0; i < points.length; i++) {
                    const distance = ol.sphere.getDistance(center4326, points[i]);
                    if (distance <= 1000) {
                        goodPoints.push(String(points[i][0]).replace('.', '_') + '-' + String(points[i][1]).replace('.', '_'))
                    }
                }
                const features = mapN.layer.getSource().getFeatures();
                for (let i = 0; i < features.length; i++) {
                    const cid = features[i].get('cid');
                    if (goodPoints.indexOf(cid) > -1) {
                        features[i].setStyle(new ol.style.Style({
                            image: new ol.style.Circle({
                                radius: 5,
                                fill: new ol.style.Fill({ color: '#ff0000' })
                            })
                        }))
                    }
                }
            },
            // 渲染经纬度点位
            renderPoints(lid) {
                const vectorSource = new ol.source.Vector({
                    features: points.map(e => {
                        const feature = new ol.Feature({
                            geometry: new ol.geom.Point(ol.proj.fromLonLat(e)),
                            cid: String(e[0]).replace('.', '_') + '-' + String(e[1]).replace('.', '_')
                        });
                        feature.setStyle(new ol.style.Style({
                            image: new ol.style.Circle({
                                radius: 5,
                                fill: new ol.style.Fill({ color: 'orange' })
                            })
                        }))
                        return feature;
                    })
                });
                // 创建图层
                const pointLayer = new ol.layer.Vector({
                    source: vectorSource,
                    lid: 'pointLayer'
                });
                // 将矢量图层添加到地图上
                this['map' + lid].map.addLayer(pointLayer);
                // 存储图层
                this['map' + lid].layer = pointLayer;
            },
            // 画点
            drawPoint(lonlat, layer, color = 'rgba(7, 193, 93, 0.8)') {
                const point = new ol.Feature({
                    geometry: new ol.geom.Point(ol.proj.fromLonLat(lonlat)) // 设置点的坐标
                });
                point.setStyle(new ol.style.Style({
                    image: new ol.style.Circle({
                        radius: 10,
                        fill: new ol.style.Fill({ color }),
                        stroke: new ol.style.Stroke({
                            color,
                            width: 2
                        })
                    })
                }));
                layer.getSource().addFeature(point);
            }
        },
        mounted() {
            this.initMap();
        }
    }).mount('#app');
    </script>
</body>

</html>

备注

代码内初始化了四个地图,第一个地图是错误的实现过程的示例,直接调用ol.geom.Circle,半径参数传1000。第二个地图是采用计算距离圆心实际距离是1000米的点,再计算投影距离为半径来绘制圆的示例。第三个地图是采用ol.geom.Polygon.circular(center, radius, n, sphereRadius)绘制近似圆的示例。第四个地图和第二个地图的思路是一样的,只不过在如何计算出两个点的方法上有所区别,第四个地图采用了通用函数来计算出垂直方向和水平方向点的经纬度坐标。绘制完图形变红的点位是根据ol.sphere.getDistance(p1, p2)计算出来距离圆心在1000米之内的点位。可以看出第一个地图有的点位没有被圆覆盖到。

由于不是专业的测绘人员,也不是GIS开发人员,涉及的GIS名词全凭个人理解。

参考文章

geometry.getExtent

ol.geom.Circle官网文档

地理空间参考数据和工具网站

ol.sphere.getDistance官网文档

ol.geom.Polygon.circular官网文档

openlayers 根据中心点和半径得到实际距离的圆(平面)