【问题标题】:Determine if point is within bounding box确定点是否在边界框内
【发布时间】:2013-08-20 04:31:55
【问题描述】:

您如何确定给定点是否在边界框内?

我的观点是 48.847172 , 2.386597。

边界框:

    "48.7998602295",
    "48.8198640442",
    "2.46138595581",
    "2.48138619423"

【问题讨论】:

    标签: javascript ios google-maps google-maps-api-3 maps


    【解决方案1】:

    照常做:

    if( bb.ix <= p.x && p.x <= bb.ax && bb.iy <= p.y && p.y <= bb.ay ) {
        // Point is in bounding box
    }
    

    bb 是边界框,(ix,iy) 是它的左上角坐标,(ax,ay) 是它的右下角坐标。 p 是点,(x,y) 是它的坐标。

    【讨论】:

    • 这仅适用于轴对齐的边界框!
    • @mrueg 没有进一步的限定,边界框被理解为轴对齐。参见例如 mathopenref.com/coordbounds.html。此外,OP 仅使用 4 个数字描述了示例框。对于通用框,至少需要 5 个。他显然指的是轴对齐的。
    • this answer 还涵盖左下角位于正经度范围 (0
    【解决方案2】:

    此解决方案还考虑了 UI 发送一个跨经度 180/-180 的框的情况(以低缩放级别映射视图,您可以看到整个世界,允许无限循环水平滚动,因此可以例如,一个盒子的 bottomLeft.lng=170 而 topRight.lng=-170(=190) 以及包括 20 度的范围。

    def inBoundingBox(bl/*bottom left*/: Coordinates, tr/*top right*/: Coordinates, p: Coordinates): Boolean = {
        // in case longitude 180 is inside the box
        val isLongInRange =
          if (tr.long < bl.long) {
            p.long >= bl.long || p.long <= tr.long
          } else
            p.long >= bl.long && p.long <= tr.long
    
        p.lat >= bl.lat  &&  p.lat <= tr.lat  &&  isLongInRange
    }
    

    【讨论】:

      【解决方案3】:

      如果您使用的是传单,您可以创建一个新的LatLngBounds 并使用它的contains() 操作:

      var bounds = new L.LatLngBounds(
       new L.LatLng(gc.bbox['_northEast'].lat, gc.bbox['_northEast'].lng),
       new L.LatLng(gc.bbox['_southWest'].lat, gc.bbox['_southWest'].lng));
      
      return bounds.contains(new L.LatLng(pos.latitude, pos.longitude))
      

      【讨论】:

        【解决方案4】:

        这应该更快。

        function doesPointCollide(p,box) {
            return !(p.x < box.left || p.x > box.right || p.y > box.bottom || p.y < box.top)
        }
        

        如果该点在我们知道它不在边界框中的任何维度之外,否则它在边界框中,因此我们可以更快地忽略否定的情况。

        【讨论】:

        • 任何半体面的编译器都会生成完全相同的代码,因为它是一个微不足道的逻辑转换。即使没有(也许我们正在谈论没有按需编译的解释器),差异也会如此之小,以至于每个人都应该更喜欢最可维护(即可读)的版本。
        • 一般来说我会同意你的观点。然而,想象一个场景,这个函数以 DOM 创建 mousemove 事件的速率触发,每个事件循环一次,每秒可能数百或数千次;在这种情况下,此处的优化会有所帮助。
        • "p.y > box.bottom || p.y box.top"
        【解决方案5】:

        此答案与kumetix's answer above 相同;然而,就我的一生而言,我不明白那里发生了什么,因为它被浓缩了很多。这是带有详细解释的相同答案。另请注意,答案是在 Kotlin 中,而不是原始帖子要求的 JavaScript,但它具有足够的可读性,因此转换为您的语言应该不会太糟糕。

        首先定义 Coordinate2D 和 BoundingBox 类:

        data class Coordinate2D (val latitude: Double, val longitude: Double)
        
        data class BoundingBox (val north: Double, val east: Double, val south: Double, val west: Double)
        

        这里是判断一个点是否在任意边界框内的函数

        fun isPointInBoundingBox(point: Coordinate2D, boundingBox: BoundingBox): Boolean {
            //given the bounding box is an imaginary rectangle in a coordinate system
            //bounding box has 4 sides - northLine, eastLine, southLine and westLine
            //initially assume the point is not in our bounding box of interest as such:
            var isPointEastOfWestLine = false
            var isPointWestOfEastLine = false
            var isPointSouthOfNorthLine = false
            var isPointNorthOfSouthLine = false
        
            if (boundingBox.east < boundingBox.west) {
                //if west coordinate has a bigger value than the east, 
                //the bounding box must be crossing the dateline
                //in other words, longitude 180 is inside the box
                //let's see what's happening with the point
                if (point.longitude >= boundingBox.west) {
                    //imagine a bounding box where westernmost longitude is +170 and easternmost longitude is -170
                    //if the point in question has a latitude of +171 as in the case expressed in the if
                    //statement, then we can conclude that point lies east of the west line
                    isPointEastOfWestLine = true
        
                    //we can also infer that the point must lie west of east line because the point's longitude is positive
                    //therefore, the point's position must be to the west of the easternmost longitude of the bounding box
                    isPointWestOfEastLine = true
                }
        
                if (point.longitude <= boundingBox.east) {
                    //imagine a bounding box where westernmost longitude is +170 and easternmost longitude is -170
                    //if the point in question has a latitude of -171 as in the case expressed in the if
                    //statement, then we can conclude that point lies west of the east line
                    isPointWestOfEastLine = true
        
                    //we can also infer that the point must lie east of the west line because the point's longitude is negative
                    //therefore, the point's position must be to the east of the westernmost longitude of the bounding box
                    isPointEastOfWestLine = true
                }
            } else {
                //in the else case, bounding box does not cross the dateline, so comparisons are more straightforward
                //longitudes range from -180 to +180; therefore, western side of a bounding box will always
                //have lower value than eastern side
                if (point.longitude >= boundingBox.west) {
                    //in this case, point's longitude has a higher value than the west side of the bounding box
                    //we can conclude that point lies to the east of the west line of the bounding box
                    isPointEastOfWestLine = true
                }
                if (point.longitude <= boundingBox.east) {
                    //in this case, point's longitude has a lower value than the east side of the bounding box
                    //we can conclude that point lies to the east of the west line of the bounding box
                    isPointWestOfEastLine = true
                }
            }
        
            //comparing latitudes are little bit easier. latitude values range from -90 to +90 where
            //-90 is the southern pole and +90 is the northern pole. The more north you go, higher the values.
            if (point.latitude >= boundingBox.south) {
                //point's latitude is higher, therefore, point must lie to the north of the south line
                isPointNorthOfSouthLine = true
            }
        
            if (point.latitude <= boundingBox.north) {
                //point's latitude is higher, therefore, point must lie to the north of the south line
                isPointSouthOfNorthLine = true
            }
        
            return isPointEastOfWestLine &&
                    isPointWestOfEastLine &&
                    isPointNorthOfSouthLine &&
                    isPointSouthOfNorthLine
        }
        

        【讨论】:

          【解决方案6】:

          对于 CGRect 和 CGPoint 有相当不错的实用方法(假设您不介意它们使用 CGFloat 来存储坐标 - 并且查看您的值,您不会 :-))。

          你可以这样做:

          // Create bounding box
          CGRect area = CGRectMake(x, y, width, height);
          
          // Define point
          CGPoint point = CGPointMake(pX, pY);
          
          /Check
          BOOL isInside = CGRectContainsPoint(area, point);
          

          【讨论】:

            【解决方案7】:

            对c plus plus使用这个函数来检查一个点是否存在于一个矩形内

            struct Box{
            
            Vec2 corner1;
            Vec2 corner2;
            Vec2 corner3;
            Vec2 corner4;
            
            };
            
            bool boxContainsPoint(Vec2 point, Box box){
            
            //Calculate distances from corner to corner
            float abL = box.corner1.getDistance(box.corner2);////////////////////
            float bcL = box.corner2.getDistance(box.corner3);////////////////////
            float cdL = box.corner3.getDistance(box.corner4);////////////////////
            float daL = box.corner4.getDistance(box.corner1);////////////////////
            
            //Calculate corner touch distance//////////////////////////////////
            float apL = box.corner1.getDistance(point);/////////////////////////
            float bpL = box.corner2.getDistance(point);/////////////////////////
            float cpL = box.corner3.getDistance(point);/////////////////////////
            float dpL = box.corner4.getDistance(point);/////////////////////////
            
            //Here we calculate the touch area
            //Heron's Formula
            ///////////////////////////////////////////////////////////////////
            float area1 = (abL + apL + bpL) / 2;///////////////////////////////
            float area2 = (bcL + bpL + cpL) / 2;///////////////////////////////
            float area3 = (cdL + cpL + dpL) / 2;///////////////////////////////
            float area4 = (daL + dpL + apL) / 2;///////////////////////////////
            float a1 = sqrtf(area1 * (area1 - abL)*(area1 - apL)*(area1 - bpL));
            float a2 = sqrtf(area2 * (area2 - bcL)*(area2 - bpL)*(area2 - cpL));
            float a3 = sqrtf(area3 * (area3 - cdL)*(area3 - cpL)*(area3 - dpL));
            float a4 = sqrtf(area4 * (area4 - daL)*(area4 - dpL)*(area4 - apL));
            
            //Calculate the rectangle area
            float A = roundf(abL*bcL);
            
            //Check to see if the point contains the polygon rect
            if(A ==roundf(a1 + a2 + a3 + a4)) return true;
            return false;
            
            }
            

            【讨论】:

              猜你喜欢
              • 2020-09-25
              • 1970-01-01
              • 1970-01-01
              • 2014-11-08
              • 1970-01-01
              • 1970-01-01
              • 2012-05-19
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多