Start with two rectangles:
aOrigin = np.array([
[2.1],
[5.1],
[5.3],
[2.3],
])
bOrigin = np.array([
[2.3],
[4.3],
[4.4],
[2.4]])# Center point position
aPosOrigin = np.array([3.5.2])
bPosOrigin = np.array([3.3.5])
Half the length of x and y
ahOrigin = np.array([1.5.1])
bhOrigin = np.array([1.0.5])
Copy the code
Add rotation:
rotateA = np.array([
[math.cos(math.pi / 180 * 40), math.sin(math.pi / 180 * 40) * -1],
[math.sin(math.pi / 180 * 40), math.cos(math.pi / 180 * 40)]
])
rotateB = np.array([
[math.cos(math.pi / 180 * 50), math.sin(math.pi / 180 * 50) * -1],
[math.sin(math.pi / 180 * 50), math.cos(math.pi / 180 * 50)]
])
iRotateA = np.linalg.inv(rotateA) The inverse of A, useful later
a = np.array([rotateA.dot(item) for item in aOrigin])
b = np.array([rotateB.dot(item) for item in bOrigin])
aPos = rotateA.dot(aPosOrigin)
bPos = rotateB.dot(bPosOrigin)
Copy the code
Now we have two rotated rectangles, and let’s see if they overlap
First, we transform the coordinate system to the coordinate system based on the rotation of rectangle A, which can make rectangle A horizontal, flat and vertical for the convenience of subsequent calculation
aBase = np.array([iRotateA.dot(item) for item in a])
iAPos = iRotateA.dot(aPos)
Copy the code
And now I’m going to transform rectangle B into rectangle A’s coordinate system
bBase = np.array([iRotateA.dot(item) for item in b])
iBPos = iRotateA.dot(bPos)
Copy the code
The x and y distance between the center points can be obtained by subtracting the center point vectors of the two rectangles
posTotal = abs(iBPos - iAPos) # array ([1.15334536, 1.96777167])
Copy the code
The difference between x axis and Y axis of central point is 1.15334536 and 1.96777167
When creating the rectangle, we know that the length of x and half of y of horizontal and vertical rectangle A is the variable ahOrigin. If we calculate the maximum length of x and half of y of rectangle B at this time (the green line in the following figure, assuming bh),
So the posTotal -BH-ahorigin vector if x and y are both negative then the two rectangles overlap
Bh can be solved by traversing four points of rectangle B. Here we introduce a method that does not require traversal:
We know that the largest x of the horizontal, horizontal and vertical rectangle B, and half of the y is bhOrigin, has undergone two rotateB and iRotateA rotateB transformations
Merge two transformations first:
rotateC = iRotateA.dot(rotateB)
Copy the code
Take the absolute value of rotateC and dot it with bhOrigin to get bh
bh = np.array([ abs(item) for item in rotateC ]).dot(bhOrigin)
posTotal - bh - ahOrigin Array ([-1.41828648, 0.30171961]) x,y
Copy the code
The following introduces the principle of the method of BH (personal understanding, please comment) :
According to the matrix multiplication formula, the X-axis value of the dot product of rotateC and a point is (the same as the Y-axis) :
cos * x - sin * y
Copy the code
The cosine of theta and the sine of theta in the quadrants of the coordinate system are plus and minus
[+ +] [-, +] [-, -] [+, -]Copy the code
We now take the center of rectangle B as the point [0, 0]
The f vector is bhOrigin
Assuming the rotation is now 30 degrees (first quadrant), then cosine and sine are both positive and the coordinates of the four points of the rectangle are:
cos * -1 - sin * 0.5
cos * 1 - sin * 0.5
cos * 1 + sin * 0.5
cos * -1 + sin * 0.5
Copy the code
The maximum X-axis value is cosine * 1 + sine * 0.5
Assuming the rotation is now 100 degrees (second quadrant), then cosine is negative, sine is positive, and the coordinates of the four points of the rectangle are:
cos * 1 - sin * 0.5
-cos * 1 - sin * 0.5
-cos * 1 + sin * 0.5
cos * 1 + sin * 0.5
Copy the code
The maximum X-axis value is cosine * 1 + sine * 0.5
And so on, whatever the Angle of rotation is, the maximum X-axis value is cosine * 1 + sine * 0.5
So you just take the absolute value of each term of the transformation matrix and dot it with bhOrigin to get the desired bh
Box2d-lite source code reading notes