Search code examples
c#bitmapgeometrygdi+system.drawing

Offsetting Rectangle Positions to prevent overlap


I have the following cases where rectangles overlap. enter image description here

I have the coordinates for the intersection rectangle(Blue). How can i offset the starting coordinates(top-left X-Y) of the 2 rectangles to prevent overlapping,provided that i have the coordinates of the intersection rectangle using

rectangle3 = Rectangle.Intersect(rectangle1, rectangle2);

UPDATE:

As per @MBo 's Update i have added the following code

Blue = Rectangle.Intersect(First, Second);
if (Blue != Rectangle.Empty)
{
if (First.Right == Blue.Right)
{

imgpoint.X += (Blue.Right - Blue.Left);
}

if (First.Bottom == Blue.Bottom)
{
imgpoint.Y += (Blue.Bottom - Blue.Top);
}

if (First.Left == Blue.Left)
{
imgpoint.X-= (Blue.Right - Blue.Left);
}
if (First.Top == Blue.Top)
{
imgpoint.Y -= (Blue.Bottom - Blue.Top);
}
}

UPDATE2:

As per @MBo 's Logic i implemented the code above.This works in most cases.But in some images even when the intesection is detected and the offset is added i get overlapping.See the sample image below.

The actual problem i'm trying to solve is linked to these 2 questions Translating a Point(X,Y) for Images of Different Sizes from a Custom PictureBox Control

Performing Overlap Detection of 2 Bitmaps

Please advice.

UPDATE:enter image description here

UPDATE:

As per your update i have translated the Delphi code to C#

Blue = Rectangle.Intersect(First, Second);
if (Blue != Rectangle.Empty)
{
int dcy,dcx;
int dy,dx;
int fl=First.Left,fw=First.Width,fh=First.Height,ft=First.Top,fb=First.Bottom,fr=First.Right;
int sl=Second.Left,sr=Second.Right,st=Second.Top,sb=Second.Bottom,sw=Second.Width,sh=Second.Height;
dcy = (sb + st) - (fb + ft);  //doubled center y-difference
dcx = (sl + sr) - (fl + fr);
if ((int)(dcx) >= (fw + sw) || ((int)(dcy) >= (fh + sh)))
{//no intersection

}
else
{

dx = fw + sw - (int)dcx;  //doubled  needed x-shift absolute value
dy = fh + sh - (int)dcy;

if (dx > dy)
{
if (dcy < 0)
{
dy = - dy/2;
}
else
{
dy = dy/ 2;  //needed y-shift accounting for direction
}
dx = 0;
}
else 
{
if (dcy < 0)
{
dx =  - dx/ 2;
}
else
{
dx =  dx/2;
dy = 0;
}
}
imgpoint.X+=dx;
imgpoint.Y+=dy;
}
} 

While using this code the Second Image gets moved too far in some cases.Please let me know if the code is right.

enter image description here


Solution

  • Edit: Checked all possible cases, had got the next simple code (Delphi code, works).

    //fl, fw, fr, ft, fh, fb: First.Left, Width, Right, Top, Height, Bottom
    //s* - similar parameters for the second rectangle   
    
    
    dcy := (sb + st) - (fb + ft);  //doubled center y-difference
    dcx := (sl + sr) - (fl + fr);
    if (Abs(dcx) >= fw + sw) or ((Abs(dcy) >= fh + sh)) then  //no intersection
      Exit;
    
    dx := fw + sw - Abs(dcx);  //doubled  needed x-shift absolute value
    dy := fh + sh - Abs(dcy);
    
     if dx > dy then begin
       if dcy < 0 then
          dy := - dy div 2
       else
          dy := dy div 2;  //needed y-shift accounting for direction
       dx := 0;
     end else begin
       if dcy < 0 then
          dx :=  - dx div 2
       else
          dx :=  dx div 2;
       dy := 0;
     end;
    
    //Result: dx, dy pair to shift the second rectangle
    

    Full code


    Old answer for temporary reference:

    You need information - what coordinate of the first rectangle coincides with corresponding coordinate of intersection rectangle. For simple intersection cases:

    case
       First.Right = Blue.Right:   
          shift Second.Left by (Blue.Right - Blue.Left)
       First.Bottom = Blue.Bottom:
          shift Second.Top by (Blue.Bottom - Blue.Top)
       First.Left = Blue.Left:
          shift Second.Left by  -(Blue.Right - Blue.Left)
       First.Top = Blue.Top:
          shift Second.Top by -(Blue.Bottom - Blue.Top)
    

    Edit:
    If intersection exists and none of cases above is met, then full inclusion and cross-like intersection takes place. So determine what is the shortest way to avoid overlap:

     dcy = (Second.Bottom + Second.Top) - (First.Bottom + First.Top)   
     if dcy >=0 then
          shift Second.Top by (First.Bottom - Second.Top)   //down
     else
          shift Second.Top by -(Second.Bottom - First.Top)   //up
    
     dcx = (Second.Left + Second.Right) - (First.Left + First.Right)   
     if dcx >=0 then
          shift Second.Left by (First.Right - Second.Left)   //right
     else
          shift Second.Left by -(Second.Right - First.Left)   //left