How can I determine whether a 2D Point is within a Polygon?

前端 未结 30 2070
醉梦人生
醉梦人生 2020-11-21 05:06

I\'m trying to create a fast 2D point inside polygon algorithm, for use in hit-testing (e.g. Polygon.contains(p:Point)). Suggestions for effective tech

30条回答
  •  北海茫月
    2020-11-21 05:58

    I realize this is old, but here is a ray casting algorithm implemented in Cocoa, in case anyone is interested. Not sure it is the most efficient way to do things, but it may help someone out.

    - (BOOL)shape:(NSBezierPath *)path containsPoint:(NSPoint)point
    {
        NSBezierPath *currentPath = [path bezierPathByFlatteningPath];
        BOOL result;
        float aggregateX = 0; //I use these to calculate the centroid of the shape
        float aggregateY = 0;
        NSPoint firstPoint[1];
        [currentPath elementAtIndex:0 associatedPoints:firstPoint];
        float olderX = firstPoint[0].x;
        float olderY = firstPoint[0].y;
        NSPoint interPoint;
        int noOfIntersections = 0;
    
        for (int n = 0; n < [currentPath elementCount]; n++) {
            NSPoint points[1];
            [currentPath elementAtIndex:n associatedPoints:points];
            aggregateX += points[0].x;
            aggregateY += points[0].y;
        }
    
        for (int n = 0; n < [currentPath elementCount]; n++) {
            NSPoint points[1];
    
            [currentPath elementAtIndex:n associatedPoints:points];
            //line equations in Ax + By = C form
            float _A_FOO = (aggregateY/[currentPath elementCount]) - point.y;  
            float _B_FOO = point.x - (aggregateX/[currentPath elementCount]);
            float _C_FOO = (_A_FOO * point.x) + (_B_FOO * point.y);
    
            float _A_BAR = olderY - points[0].y;
            float _B_BAR = points[0].x - olderX;
            float _C_BAR = (_A_BAR * olderX) + (_B_BAR * olderY);
    
            float det = (_A_FOO * _B_BAR) - (_A_BAR * _B_FOO);
            if (det != 0) {
                //intersection points with the edges
                float xIntersectionPoint = ((_B_BAR * _C_FOO) - (_B_FOO * _C_BAR)) / det;
                float yIntersectionPoint = ((_A_FOO * _C_BAR) - (_A_BAR * _C_FOO)) / det;
                interPoint = NSMakePoint(xIntersectionPoint, yIntersectionPoint);
                if (olderX <= points[0].x) {
                    //doesn't matter in which direction the ray goes, so I send it right-ward.
                    if ((interPoint.x >= olderX && interPoint.x <= points[0].x) && (interPoint.x > point.x)) {  
                        noOfIntersections++;
                    }
                } else {
                    if ((interPoint.x >= points[0].x && interPoint.x <= olderX) && (interPoint.x > point.x)) {
                         noOfIntersections++;
                    } 
                }
            }
            olderX = points[0].x;
            olderY = points[0].y;
        }
        if (noOfIntersections % 2 == 0) {
            result = FALSE;
        } else {
            result = TRUE;
        }
        return result;
    }
    

提交回复
热议问题