偏移矩形位置以防止重叠
Offsetting Rectangle Positions to prevent overlap
我有以下矩形重叠的情况。
我有相交矩形(蓝色)的坐标。
我如何偏移 2 个矩形的起始坐标(左上角 X-Y)以防止重叠,前提是我有使用
的交叉矩形的坐标
rectangle3 = Rectangle.Intersect(rectangle1, rectangle2);
更新:
根据@MBo 的更新,我添加了以下代码
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);
}
}
更新2:
根据@MBo 的逻辑,我实现了代码 above.This 在某些图像中大多数 cases.But 有效,即使检测到相交并添加了偏移,我得到 overlapping.See下面的示例图片。
我试图解决的实际问题与这两个问题有关
Performing Overlap Detection of 2 Bitmaps
请指教。
更新:
更新:
根据您的更新,我已将 Delphi 代码翻译成 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;
}
}
使用此代码时,第二张图片在某些地方移动得太远 cases.Please 让我知道代码是否正确。
编辑: 检查了所有可能的情况,得到了下一个简单代码(Delphi 代码,有效)。
//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
旧答案临时参考:
您需要信息 - 第一个矩形的坐标与相交矩形的相应坐标重合。对于简单的交集情况:
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)
编辑:
如果存在交集并且满足上述 none 种情况,则发生完全包含和十字交集。所以确定避免重叠的最短方法是什么:
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
您需要检查 r2(rectangle2) 是否介于 r2.X 和 r2.X+r2.Height 之间或介于 r2.Y 和 r2.Y + r2.Y+r2.Width 或不在我们之间进行更改
我写了一个示例代码
private int GetNewX(Rectangle r1, Rectangle r2)
{
if (r2.X < r1.X)
{
return r1.X - r2.Width;
}
else
{
return r1.X + r1.Width;
}
}
private int GetNewY(Rectangle r1, Rectangle r2)
{
if (r2.Y < r1.Y)
{
return r1.Y - r2.Height;
}
else
{
return r1.Y + r1.Height;
}
}
Pen pen = new Pen(Color.Black);
Rectangle r1 = new Rectangle(60, 10, 200, 200);
Rectangle r2 = new Rectangle(40, 25, 200, 160);
//If overlapped change X,Y of the r2 rectangle
Rectangle overlapRect = Rectangle.Intersect(r1, r2);
if (overlapRect.Width > 0 || overlapRect.Height > 0)
{
bool betweenX = overlapRect.X >= r1.X && overlapRect.X <= (r1.X + r1.Height);
bool betweenY = overlapRect.Y >= r1.Y && overlapRect.Y <= (r1.Y + r1.Width);
if (betweenX)
{
r2.X = GetNewX(r1,r2);
}
else if (betweenY)
{
r2.Y = GetNewY(r1, r2);
}
else
{
if (overlapRect.Width <= overlapRect.Height)
{
r2.X = GetNewX(r1, r2);
}
else
{
r2.Y = GetNewY(r1, r2);
}
}
}
Graphics g = this.CreateGraphics();
g.DrawRectangle(pen, r1);
g.DrawRectangle(pen, r2);
我有以下矩形重叠的情况。
我有相交矩形(蓝色)的坐标。 我如何偏移 2 个矩形的起始坐标(左上角 X-Y)以防止重叠,前提是我有使用
的交叉矩形的坐标rectangle3 = Rectangle.Intersect(rectangle1, rectangle2);
更新:
根据@MBo 的更新,我添加了以下代码
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);
}
}
更新2:
根据@MBo 的逻辑,我实现了代码 above.This 在某些图像中大多数 cases.But 有效,即使检测到相交并添加了偏移,我得到 overlapping.See下面的示例图片。
我试图解决的实际问题与这两个问题有关
Performing Overlap Detection of 2 Bitmaps
请指教。
更新:
更新:
根据您的更新,我已将 Delphi 代码翻译成 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;
}
}
使用此代码时,第二张图片在某些地方移动得太远 cases.Please 让我知道代码是否正确。
编辑: 检查了所有可能的情况,得到了下一个简单代码(Delphi 代码,有效)。
//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
旧答案临时参考:
您需要信息 - 第一个矩形的坐标与相交矩形的相应坐标重合。对于简单的交集情况:
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)
编辑:
如果存在交集并且满足上述 none 种情况,则发生完全包含和十字交集。所以确定避免重叠的最短方法是什么:
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
您需要检查 r2(rectangle2) 是否介于 r2.X 和 r2.X+r2.Height 之间或介于 r2.Y 和 r2.Y + r2.Y+r2.Width 或不在我们之间进行更改 我写了一个示例代码
private int GetNewX(Rectangle r1, Rectangle r2)
{
if (r2.X < r1.X)
{
return r1.X - r2.Width;
}
else
{
return r1.X + r1.Width;
}
}
private int GetNewY(Rectangle r1, Rectangle r2)
{
if (r2.Y < r1.Y)
{
return r1.Y - r2.Height;
}
else
{
return r1.Y + r1.Height;
}
}
Pen pen = new Pen(Color.Black);
Rectangle r1 = new Rectangle(60, 10, 200, 200);
Rectangle r2 = new Rectangle(40, 25, 200, 160);
//If overlapped change X,Y of the r2 rectangle
Rectangle overlapRect = Rectangle.Intersect(r1, r2);
if (overlapRect.Width > 0 || overlapRect.Height > 0)
{
bool betweenX = overlapRect.X >= r1.X && overlapRect.X <= (r1.X + r1.Height);
bool betweenY = overlapRect.Y >= r1.Y && overlapRect.Y <= (r1.Y + r1.Width);
if (betweenX)
{
r2.X = GetNewX(r1,r2);
}
else if (betweenY)
{
r2.Y = GetNewY(r1, r2);
}
else
{
if (overlapRect.Width <= overlapRect.Height)
{
r2.X = GetNewX(r1, r2);
}
else
{
r2.Y = GetNewY(r1, r2);
}
}
}
Graphics g = this.CreateGraphics();
g.DrawRectangle(pen, r1);
g.DrawRectangle(pen, r2);