【问题标题】:Offsetting Rectangle Positions to prevent overlap偏移矩形位置以防止重叠
【发布时间】:2017-10-16 13:54:58
【问题描述】:

我有以下矩形重叠的情况。

我有相交矩形(蓝色)的坐标。 我如何偏移 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 的逻辑,我实现了上面的代码。这在大多数情况下都有效。但在某些图像中,即使检测到相交并添加偏移量,我也会重叠。请参见下面的示例图像。

我要解决的实际问题与这两个问题有关 Translating a Point(X,Y) for Images of Different Sizes from a Custom PictureBox Control

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;
}
} 

使用此代码时,在某些情况下,第二张图片会移动得太远。请告诉我代码是否正确。

【问题讨论】:

  • 您在两个需要绝对值的地方使用(int)(dcx) 和 dcy(类似于math.abs
  • @MBo 谢谢。会检查并回复。
  • @MBo 非常感谢 :) 使用 Math.Abs 后,您的第二次更新效果很好。非常感谢您的努力。

标签: c# bitmap geometry gdi+ system.drawing


【解决方案1】:

编辑:检查了所有可能的情况,得到了下一个简单的代码(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

Full code


临时参考的旧答案:

您需要信息 - 第一个矩形的坐标与相交矩形的相应坐标重合。对于简单的交集情况:

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)

编辑:
如果存在交集且以上情况均不满足,则发生完全包含和十字交叉。所以确定避免重叠的最短方法是什么:

 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

【讨论】:

  • 谢谢.. 但是如果Blue 有两个交叉边怎么办..?
  • 这适用于角角情况(两种情况)。关于更复杂的案例(交叉等)-您写了“我有以下案例”。此处向左移动带有减号`-(Blue.Right - Blue.Left)`
  • 我的坏..错过了减号...如果可能的话..你能看看这个问题吗,我问这个问题来解决这个问题stackoverflow.com/questions/44018201/…
  • 我已经在我的代码中实现了你的逻辑,它运行得很好。请检查我的更新,看看是否有问题。
  • 看起来不错。 (如果你不需要完全包含和交叉状相交的情况)
【解决方案2】:

您需要检查 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);

【讨论】:

  • 欢迎您@techno。如果你有任何问题,请回来。请注意我在表单上使用了我的代码
  • 会做的。谢谢:)。你的意思是你已经测试了表单上的代码...
  • 好的..谢谢...将测试我的用例并返回..我实际上试图用这个问题解决的是这个问题stackoverflow.com/questions/44018201/…
  • @techno 如果您有 2 个位图坐标及其宽度和高度,您可以使用相同的技术。如果你不能解决,请给我写信。如果可以的话我会帮你的
  • @techno 我在表格上为您创建了一个样本,它接受 2 张图像并且不重叠。见答案stackoverflow.com/questions/44018201/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多