Holen Sie sich die Schnittpunkte von 2 Rechtecken

Holen Sie sich die Schnittpunkte von 2 Rechtecken

Wenn die Eingaberechtecke normalisiert sind, d.h. Sie wissen bereits, dass x1 < x2 , y1 < y2 (und dasselbe für das zweite Rechteck), dann müssen Sie nur noch rechnen

int x5 = max(x1, x3);
int y5 = max(y1, y3);
int x6 = min(x2, x4);
int y6 = min(y2, y4);

und es wird Ihnen Ihren Schnittpunkt als Rechteck (x5, y5)-(x6, y6) geben . Wenn sich die ursprünglichen Rechtecke nicht schneiden, ist das Ergebnis ein "entartetes" Rechteck (mit x5 >= x6 und/oder y5 >= y6 ), die Sie leicht überprüfen können.

P.S. Wie üblich hängen kleine Details davon ab, ob Sie Anfassen in Betracht ziehen müssen Rechtecke als überschneidend.


Um nach einem Schnittpunkt zu suchen, müssen Sie die Punkte einfach vergleichen:

Wie wir also aus dem Bild sehen können, wenn x3, y3 größer oder gleich x1, y1 und kleiner oder gleich x2, y2 ist, dann befindet es sich innerhalb des ersten Rechtecks, ebenso müssen Sie prüfen, ob x4, y4 innerhalb des Rechtecks ​​liegt Bereich von x1,y1 bis x2,y2.

Wenn sich beide Bedingungen als wahr erweisen, können Sie sicher sein, dass das zweite Rechteck vollständig vom ersten umfasst ist.

Umgekehrt müssen Sie auch nachsehen, was für Sie wichtig ist.

Außerdem müssen die Rechtecke achsenausgerichtet sein, sonst funktioniert das nicht zuverlässig.

Lassen Sie es mich wissen, wenn Sie mehr Details benötigen, obwohl ich denke, dass eine schnelle Google-Suche sehr leicht viel mehr Details für Sie aufdecken wird, aber lassen Sie es mich wissen und ich kann ein Rechteck-Kollisions-Tutorial erstellen, wenn Sie möchten.

Im Detail:

Um herauszufinden, ob die Rechtecke Schnittpunkte haben, können Sie die Koordinaten ihrer definierenden Punkte überprüfen. Für unsere Zwecke verwenden wir die Koordinaten der oberen linken und unteren rechten Ecke. Wir können eine Klasse verwenden, um uns dies zu erleichtern und die zu maximieren Verwendbarkeit des Codes können wir einen 2d-Vektor und einen 2d-Punkt verwenden:2dVectorPoint.h

#include <cmath>

class Vector2D
{
    public:
        float   x;
        float   y;

        Vector2D() {}    
        Vector2D(float inX, float inY)
        {
            x = inX;
            y = inY;
        }

        Vector2D& Set(float inX, float inY)
        {
            x = inX;
            y = inY;
            return (*this);
        }

        float& operator [](long k)        {            return ((&x)[k]);        }

        const float& operator [](long k) const        {            return ((&x)[k]);        }

        Vector2D& operator +=(const Vector2D& v)
        {
            x += v.x;
            y += v.y;
            return (*this);
        }

        Vector2D& operator -=(const Vector2D& v)
        {
            x -= v.x;
            y -= v.y;
            return (*this);
        }

        Vector2D& operator *=(float t)
        {
            x *= t;
            y *= t;
            return (*this);
        }

        Vector2D& operator /=(float t)
        {
            float f = 1.0F / t;
            x *= f;
            y *= f;
            return (*this);
        }

        Vector2D& operator &=(const Vector2D& v)
        {
            x *= v.x;
            y *= v.y;
            return (*this);
        }

        Vector2D operator -(void) const        {            return (Vector2D(-x, -y));        }

        Vector2D operator +(const Vector2D& v) const        {            return (Vector2D(x + v.x, y + v.y));        }

        Vector2D operator -(const Vector2D& v) const        {  return (Vector2D(x - v.x, y - v.y));        }

        Vector2D operator *(float t) const        {            return (Vector2D(x * t, y * t));        }

        Vector2D operator /(float t) const        {     float f = 1.0F / t; return (Vector2D(x * , y * f));        }

        float operator *(const Vector2D& v) const        {            return (x * v.x + y * v.y);        }

        Vector2D operator &(const Vector2D& v) const     {            return (Vector2D(x * v.x, y * v.y));        }

        bool operator ==(const Vector2D& v) const        {            return ((x == v.x) && (y == v.y));        }

        bool operator !=(const Vector2D& v) const        {            return ((x != v.x) || (y != v.y));        }

        Vector2D& Normalize(void)                        {            return (*this /= sqrtf(x * x + y * y));        }

        Vector2D& Rotate(float angle);
};


class Point2D : public Vector2D
{
    public:

        Point2D() {}

        Point2D(float r, float s) : Vector2D(r, s) {}

        Point2D& operator =(const Vector2D& v)
        {
            x = v.x;
            y = v.y;
            return (*this);
        }

        Point2D& operator *=(float t)
        {
            x *= t;
            y *= t;
            return (*this);
        }

        Point2D& operator /=(float t)
        {
            float f = 1.0F / t;
            x *= f;
            y *= f;
            return (*this);
        }

        Point2D operator -(void) const{            return (Point2D(-x, -y));        }

        Point2D operator +(const Vector2D& v) const        {            return (Point2D(x + v.x, y + v.y));        }

        Point2D operator -(const Vector2D& v) const        {            return (Point2D(x - v.x, y - v.y));        }

        Vector2D operator -(const Point2D& p) const        {            return (Vector2D(x - p.x, y - p.y));        }

        Point2D operator *(float t) const        {            return (Point2D(x * t, y * t));        }

        Point2D operator /(float t) const
        {
            float f = 1.0F / t;
            return (Point2D(x * f, y * f));
        }
};


inline Vector2D operator *(float t, const Vector2D& v){    return (Vector2D(t * v.x, t * v.y));}

inline Point2D operator *(float t, const Point2D& p){    return (Point2D(t * p.x, t * p.y));}

inline float Dot(const Vector2D& v1, const Vector2D& v2){    return (v1 * v2);}

inline float Magnitude(const Vector2D& v){    return (sqrtf(v.x * v.x + v.y * v.y));}

inline float InverseMag(const Vector2D& v){    return (1.0F / sqrtf(v.x * v.x + v.y * v.y));}

inline float SquaredMag(const Vector2D& v){    return (v.x * v.x + v.y * v.y);}

struct Origin2D_
{
    const Point2D& operator +(const Vector2D& v)    {        return (static_cast<const Point2D&>(v));    }

    Point2D operator -(const Vector2D& v)    {        return (Point2D(-v.x, -v.y));    }
};

2dVectorPoint.cpp

#include "2dVectorPoint.h"

Origin2D_ Origin2D;

Vector2D& Vector2D::Rotate(float angle)
{
    float s = sinf(angle);
    float c = cosf(angle);

    float nx = c * x - s * y;
    float ny = s * x + c * y;

    x = nx;
    y = ny;

    return (*this);
}
extern Origin2D_ Origin2D;

Der verwendete Code wird von hier angepasst, um meine Finger zu schonen.

Dann können wir dies für einen einfachen Vergleich verwenden:Wir können Rechteck 1 so definieren, dass es P1 und P2 als seine Grenzen hat, und Rechteck 2, als hätte es P3 und P4 als seine Grenzen, was uns den folgenden Vergleich gibt:

if ( P2.y <= P3.y && P1.y >= P4.y && P2.x>= P3.x && P1.x <= P4.x )
{
    return true;
}

Dies gibt einen wahren Wert für jeden Schnittpunkt oder für Rechteck 1, das Rechteck 2 vollständig umschließt, zurück.

Um nur nach Schnittpunkten zu suchen, entfernen Sie einfach die Gleichheitsprüfung (nehmen Sie alle = aus der obigen Gleichung), und Sie werden nur nach Schnittpunkten suchen. Wenn Sie einen Schnittpunkt haben, können Sie die genauen Koordinaten mithilfe der linearen Algebra berechnen.


Nehmen wir an, dass eine Box einen Radius X und einen Radius Y hat (ich weiß, dass das nicht der Fall ist, aber dieser Begriff ist hier nützlich).

Sie haben:

rect1_x_radius = (x2-x1)/2
rect1_y_radius = (y2-y1)/2

und

rect2_x_radius = (x4-x3)/2
rect2_y_radius = (y4-y3)/2

Wenn nun gerade Mittelpunkte weiter entfernt sind als die Summe ihrer Radien in der entsprechenden Richtung - sie kollidieren nicht. Andernfalls tun sie es - dieser Hinweis sollte genügen.

Sie sollten Ihre Aufgabe jetzt abschließen können.

AKTUALISIERUNG:

OK - lösen wir es für 1D - später lösen Sie es für 2D auf. Schau dir dieses Kunstwerk an;-)

Sie sehen 2 Segmente - jetzt einige Berechnungen:

rA = (maxA-minA) / 2
rB = (maxB-minB) / 2

midA = minA + rA
midB = minB + rB

mid_dist = |midA - midB|

Wie kann man nun überprüfen, ob eine Kollision auftritt? Wie gesagt, wenn die Summe der 'Radien' kleiner ist als der Abstand der Segmente, gibt es keine Kollision:

if ( mid_dist > fabs(rA+rB) )
{
    // no intersection
}
else
{
    // segments intersect
}

Jetzt ist es Ihre Aufgabe, den Schnittpunkt / den gemeinsamen Teil in 1D und 2D zu berechnen. Es liegt jetzt an Ihnen (oder Sie können Andreys Antwort lesen).

Hier ist die gleiche Situation, aber in 2D - zwei 1D-Situationen: