Circle-Rectangle collision detection (intersection)

前端 未结 24 1389
无人共我
无人共我 2020-11-22 02:55

How can I tell whether a circle and a rectangle intersect in 2D Euclidean space? (i.e. classic 2D geometry)

24条回答
  •  广开言路
    2020-11-22 03:11

    For those have to calculate Circle/Rectangle collision in Geographic Coordinates with SQL,
    this is my implementation in oracle 11 of e.James suggested algorithm.

    In input it requires circle coordinates, circle radius in km and two vertices coordinates of the rectangle:

    CREATE OR REPLACE FUNCTION "DETECT_CIRC_RECT_COLLISION"
    (
        circleCenterLat     IN NUMBER,      -- circle Center Latitude
        circleCenterLon     IN NUMBER,      -- circle Center Longitude
        circleRadius        IN NUMBER,      -- circle Radius in KM
        rectSWLat           IN NUMBER,      -- rectangle South West Latitude
        rectSWLon           IN NUMBER,      -- rectangle South West Longitude
        rectNELat           IN NUMBER,      -- rectangle North Est Latitude
        rectNELon           IN NUMBER       -- rectangle North Est Longitude
    )
    RETURN NUMBER
    AS
        -- converts km to degrees (use 69 if miles)
        kmToDegreeConst     NUMBER := 111.045;
    
        -- Remaining rectangle vertices 
        rectNWLat   NUMBER;
        rectNWLon   NUMBER;
        rectSELat   NUMBER;
        rectSELon   NUMBER;
    
        rectHeight  NUMBER;
        rectWIdth   NUMBER;
    
        circleDistanceLat   NUMBER;
        circleDistanceLon   NUMBER;
        cornerDistanceSQ    NUMBER;
    
    BEGIN
        -- Initialization of remaining rectangle vertices  
        rectNWLat := rectNELat;
        rectNWLon := rectSWLon;
        rectSELat := rectSWLat;
        rectSELon := rectNELon;
    
        -- Rectangle sides length calculation
        rectHeight := calc_distance(rectSWLat, rectSWLon, rectNWLat, rectNWLon);
        rectWidth := calc_distance(rectSWLat, rectSWLon, rectSELat, rectSELon);
    
        circleDistanceLat := abs( (circleCenterLat * kmToDegreeConst) - ((rectSWLat * kmToDegreeConst) + (rectHeight/2)) );
        circleDistanceLon := abs( (circleCenterLon * kmToDegreeConst) - ((rectSWLon * kmToDegreeConst) + (rectWidth/2)) );
    
        IF circleDistanceLon > ((rectWidth/2) + circleRadius) THEN
            RETURN -1;   --  -1 => NO Collision ; 0 => Collision Detected
        END IF;
    
        IF circleDistanceLat > ((rectHeight/2) + circleRadius) THEN
            RETURN -1;   --  -1 => NO Collision ; 0 => Collision Detected
        END IF;
    
        IF circleDistanceLon <= (rectWidth/2) THEN
            RETURN 0;   --  -1 => NO Collision ; 0 => Collision Detected
        END IF;
    
        IF circleDistanceLat <= (rectHeight/2) THEN
            RETURN 0;   --  -1 => NO Collision ; 0 => Collision Detected
        END IF;
    
    
        cornerDistanceSQ := POWER(circleDistanceLon - (rectWidth/2), 2) + POWER(circleDistanceLat - (rectHeight/2), 2);
    
        IF cornerDistanceSQ <=  POWER(circleRadius, 2) THEN
            RETURN 0;  --  -1 => NO Collision ; 0 => Collision Detected
        ELSE
            RETURN -1;  --  -1 => NO Collision ; 0 => Collision Detected
        END IF;
    
        RETURN -1;  --  -1 => NO Collision ; 0 => Collision Detected
    END;    
    

提交回复
热议问题