当前位置: 首页 > 知识库问答 >
问题:

有效地在圆扇形内找到点

督德明
2023-03-14

我有一组随机分布的二维点。我需要对这些点的一个小子集执行时间密集操作,但我需要首先找出我需要对哪些点执行这个时间密集操作。为了确定我需要什么点,它们必须通过一系列几何准则。

有没有一个有效的算法来找到什么2D点在一个圆扇区?

需要注意的是,我们的特定系统在浮点数学和三角学方面都很慢,所以一个解决方案涉及的较少,需要大量的浮点数学和三角学是更好的解决方案。

共有1个答案

欧阳智志
2023-03-14

只要用整数算术和加、减、乘的基本运算,就可以检查一个点是否在扇区内。

要使一个点位于圆形扇区内,它必须满足以下测试

>

  • 必须从扇区的起始“臂”逆时针方向定位。
  • 必须从扇区的端臂顺时针定位。
  • 它必须比扇形半径更靠近圆心。

    如果投影是正数,那么v2就逆时针定位到V1。否则,v2是顺时针方向到V1。

    这些步骤可以组合在一起:

    function areClockwise(v1, v2) {
      return -v1.x*v2.y + v1.y*v2.x > 0;
    }
    

    半径测试很简单。只要检查点到圆心的距离是否小于期望的半径。为了避免计算平方根,我们可以将距离的平方与半径的平方进行比较。

    function isWithinRadius(v, radiusSquared) {
      return v.x*v.x + v.y*v.y <= radiusSquared;
    }
    
    function isInsideSector(point, center, sectorStart, sectorEnd, radiusSquared) {
      var relPoint = {
        x: point.x - center.x,
        y: point.y - center.y
      };
    
      return !areClockwise(sectorStart, relPoint) &&
             areClockwise(sectorEnd, relPoint) &&
             isWithinRadius(relPoint, radiusSquared);
    }
    

    https://imgs.xnip.cn/cj/n/21/62114dbc-dd7d-4992-8eb4-f0d665346606.png" width="100%" height="100%" />

    <!DOCTYPE html>
    <html>
      <head>
        <script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
        <style>
          .canvas {
            position: absolute;
            background: #f4f4f4;
            border: 8px solid #f4f4f4;
            width: 400px;
            height: 400px;
          }
    
          .dot {
            position: absolute;
            font: 16px Arial;
          }
          .out { color: #ddd; }
          .in { color: #00dd44; }
        </style>
        <script>
          function isInsideSector(point, center, sectorStart, sectorEnd, radiusSquared) {
            var relPoint = {
              x: point.x - center.x,
              y: point.y - center.y
            };
    
            return !areClockwise(sectorStart, relPoint) &&
                   areClockwise(sectorEnd, relPoint) &&
                   isWithinRadius(relPoint, radiusSquared);
          }
    
          function areClockwise(v1, v2) {
            return -v1.x*v2.y + v1.y*v2.x > 0;
          }
    
          function isWithinRadius(v, radiusSquared) {
            return v.x*v.x + v.y*v.y <= radiusSquared;
          }
    
          $(function() {
            var $canvas = $("#canvas");
            var canvasSize = 400;
            var count = 4000;
    
            // define the sector
            var center = { x: canvasSize / 2, y: canvasSize / 2 };
            var sectorStart = { x: 4, y: 1 };
            var sectorEnd = { x: 1, y: 4 };
            var radiusSquared = canvasSize * canvasSize / 4;
    
            // create, draw and test a number of random points
            for (var i = 0; i < count; ++i) {
    
              // generate a random point
              var point = {
                x: Math.random() * canvasSize,
                y: Math.random() * canvasSize
              };
    
              // test if the point is inside the sector
              var isInside = isInsideSector(point, center, sectorStart, sectorEnd, radiusSquared);
    
              // draw the point
              var $point = $("<div class='dot'></div>")
                  .css({
                    left: point.x - 3,
                    top:  canvasSize - point.y - 8 })
                  .html("&#8226;")
                  .addClass(isInside ? "in" : "out")
                  .appendTo($canvas);
            }
          });
        </script>
      </head>
      <body>
        <div id="canvas" class="canvas"></div>
      </body>
    </html>
    

    此外,代码假定您知道扇区的边界向量中哪一个是“开始”,哪一个是“结束”。如果没有,可以对它们运行Areclockwise()以找出答案。

    请注意,虽然所有这些都可以用整数算法来完成,但半径和顺时针测试都使用了更大的数字范围,这是因为x和y的平方和相乘。确保使用足够位的整数来保存结果。

  •  类似资料:
    • 我正在尝试解决简单的任务,但我没有找到任何优雅的解决方案。 我基本上解决了两个圆形扇区的交集。每个扇区由(-pi, pi]范围内的2个角度(从atan2 func)给出。每个选择器占用的最大角度为179.999。所以每两个角度就可以知道圆形扇区的位置。 返回值应根据以下内容描述互交:

    • 我应该自己写方法吗?尽管我害怕不能解释一些事情,因为我的数学已经生疏了。或者我能为Java找到一个现成的实现吗?我有谷歌地图sdk在我的项目,但我找不到任何有用的东西。

    • 我需要画一个有4个扇区的圆。我试着画一个扇区,像这样:

    • 我在location _ table(point _ location geometry)中存储了位置,现在我在谷歌地图上绘制了一个多边形,并将该多边形(几何)传递给后端,我想找到该多边形内的所有位置。 当我将多边形从谷歌地图传递到后端时,这给了我随机的结果。它没有给我多边形内的所有点。它给了我甚至在多边形之外的点。 在 postgis 中准确查找多边形内所有点的正确方法是什么(也包括边界情况)

    • 绘制自定义形状-扇形 感谢群友 墨明棋妙 309764601@qq.com 提供功能思路和源码 目前cesium的entity里面是没有直接绘制扇形的形状的,当时在网上搜索的时候,在官方的google group里面有人明确说明是没有的,然后需要自己重载Geometry,再重新打包。。。 这,略麻烦,然后墨明棋妙兄弟就自己写了一个函数来进行绘制,最终提供了源码,感谢感谢 思路比较简单,如下: 1.

    • 问题内容: 我对块数据存储有特殊需要。我的数据是大小为4096的格式化数据块。为了提高效率,我想直接在硬盘扇区上操作该块,并且不想将数据块视为文件。我认为一种方法是将设备视为/ dev / sda1之类的文件,并使用lseek()read()和write()读取和写入数据。但是我不知道文件的头是否是硬盘的第一个扇区。我也怀疑这种方法的效率。 我正在使用Linux OS和C编程语言。 处理硬盘扇区的