Baldráni
Baldráni

Reputation: 5640

Determine intersection with an Ovale shape

I'm working with Java and I am trying to detect the intersection of an ovale with a rectangle.

I tough at first using Intersect would be sufficient :

Shape rect = new Rectangle2D.Double(ant.getPosX(), ant.getPosY(), 5, 5);
for (Shape obstacle : obstaclesShape) {
    if(obstacle.intersects(rect.getBounds())){
        System.out.println("Boom");
    }
}

obstaclesShape is an ArrayList of oval shape.

Shape oval = new Ellipse2D.Double(getRandomX(), getRandomY(), obstacle.getRandomWidth(), obstacle.
this.obstaclesShape.add(oval);

But using this method is not reliable enough. The event seems to be triggered almost randomly.

So I was asking myself wouldn't it be better to use mathematic and determine the position of the border of my ellipsis? Something which would be determine by the angle and height / width I guess.

enter image description here

The thing is how to determine it precisely? What is the formula for it? Or is there a better way?

Upvotes: 1

Views: 570

Answers (1)

MBo
MBo

Reputation: 80187

Yes, it is worth to apply some math and find whether your ellipse intersects rectangle.

Let rectangle has corners (x0,y0) and (x1,y1) and ellipse has center (cx, cy), horizontal semi-axis a, vertical sem-axis b.

At first we can make affine transformation to simplify calculations - we transform ellipse into origin-centered circle with radius 1. Rectangle will transform too, and intersection fact does not change.

With such transform  we apply shift by (-cx,-cy), scaling by `1/a` in OX direction and scaling by `1/b` in 0Y direction. After that rectangle will have coordinates

 xxx0 = (x0-cx) / a
 yyy0 = (y0-cy) / b
 xxx1 = (x1-cx) / a
 yyy1 = (y1-cy) / b

Now we can apply described here approach to find a distance between origin (circle center) and rectangle. If it less than 1, objects do intersect.

Slightly modified function (Delphi)

function RectDistanceToZeroLessThan1(RR: TRect): Boolean;
var
  wh, hh, dx, dy, t, SquaredDist: Double;
begin
  SquaredDist := 0;

  //width and height
  wh := RR.Right - RR.Left;
  hh := RR.Bottom - RR.Top;

  //doubled rectangle center coordinates
  dx :=  - (RR.Left + RR.Right);
  dy :=  - (RR.Top + RR.Bottom);

  //rectangle sides divide plane to 9 parts,
  t := dx + wh;
  if t < 0 then
    SquaredDist := t * t
  else begin
    t := dx - wh;
    if t > 0 then
      SquaredDist := t * t
  end;
  t := dy + hh;
  if t < 0 then
    SquaredDist := SquaredDist + t * t
  else begin
    t := dy - hh;
    if t > 0 then
      SquaredDist := SquaredDist + t * t
  end;

  Result = SquaredDist <= 4 // due to removed 0.5 coefficients
end;

Upvotes: 1

Related Questions