Ошибка отсечения рисования .Net

Функция GDI + DrawLines имеет ошибку отсечения, которая может быть воспроизведена с помощью следующего кода на c #. При выполнении кода появляются два пути строки, которые должны быть идентичны, поскольку оба они находятся внутри области отсечения. Но когда задан регион отсечения, один из отрезков линии не рисуется.

protected override void OnPaint(PaintEventArgs e)
{
   PointF[] points = new PointF[] { new PointF(73.36f, 196), 
             new PointF(75.44f, 32), 
             new PointF(77.52f, 32), 
             new PointF(79.6f, 196), 
             new PointF(85.84f, 196) };

   Rectangle b = new Rectangle(70, 32, 20, 164);         
   e.Graphics.SetClip(b);
   e.Graphics.DrawLines(Pens.Red, points); // clipped incorrectly
   e.Graphics.TranslateTransform(80, 0);
   e.Graphics.ResetClip();
   e.Graphics.DrawLines(Pens.Red, points);
 }

Установка режима antials на графическом объекте решает эту проблему. Но это не настоящее решение.

Кто-нибудь знает об обходном пути?

19.08.2008 01:11:28
3 ОТВЕТА

В чем дело с кодом?

Хорошо, вопрос должен быть ... что должен делать код, а он этого не делает.

Когда я запускаю код, я вижу 2 красных «шипа».

Похоже, вы рисуете первый всплеск в области ограниченного прямоугольника, проверенный путем добавления следующего после объявления Rectangle:

e.Graphics.FillRectangle( new SolidBrush( Color.Black ), b );

Затем вы выполняете перевод, сбрасываете клип, так что в этот момент я предполагаю, что clientRectangle используется в качестве соответствующей области клипа, а затем пытаюсь повторить преобразованный скачок. Где ошибка?!?

0
19.08.2008 08:32:56

Ошибка состоит в том, что оба отрезка линии должны быть нарисованы одинаково, но это не так, потому что пик, который рисуется в области отсечения, полностью находится в области отсечения и не должен быть каким-либо образом вырезан, но это так. Это очень раздражает, но это приводит к тому, что любое программное обеспечение, которое сильно использует Drawlines + отсечение, выглядит непрофессионально из-за пробелов, которые могут появиться в полигонах.

0
19.08.2008 09:17:37

Похоже, это известная ошибка ...

Следующий код работает так, как вы просили:

protected override void OnPaint(PaintEventArgs e)
    {
        PointF[] points = new PointF[] { new PointF(73.36f, 196), 
         new PointF(75.44f, 32), 
         new PointF(77.52f, 32), 
         new PointF(79.6f, 196), 
         new PointF(85.84f, 196) };

        e.Graphics.SmoothingMode =  System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        Rectangle b = new Rectangle(70, 32, 20, 165);
        e.Graphics.SetClip(b);
        e.Graphics.DrawLines(Pens.Red, points); // clipped incorrectly
        e.Graphics.TranslateTransform(80, 0);
        e.Graphics.ResetClip();           
        e.Graphics.DrawLines(Pens.Red, points);
    }

Примечание: я AntiAlias'ed линии и расширил ваш регион отсечения на 1

похоже, что могут помочь следующие обходные пути (хотя и не проверенные):

  • Перо толщиной более одного пикселя
  • Линия идеально горизонтальная или вертикальная
  • Отсечение идет по границам окна, а не по прямоугольнику клипа.

Ниже приведен список статей, которые могут / или затем могут не помочь:

http://www.tech-archive.net/pdf/Archive/Development/microsoft.public.win32.programmer.gdi/2004-08/0350.pdf http://www.tech-archive.net/Archive/Development /microsoft.public.win32.programmer.gdi/2004-08/0368.html

ИЛИ...

возможно также следующее:

protected override void OnPaint ( PaintEventArgs e )
    {
        PointF[] points = new PointF[] { new PointF(73.36f, 196), 
         new PointF(75.44f, 32), 
         new PointF(77.52f, 32), 
         new PointF(79.6f, 196), 
         new PointF(85.84f, 196) };

        Rectangle b = new Rectangle( 70, 32, 20, 164 );
        Region reg = new Region( b );
        e.Graphics.SetClip( reg, System.Drawing.Drawing2D.CombineMode.Union);
        e.Graphics.DrawLines( Pens.Red, points ); // clipped incorrectly
        e.Graphics.TranslateTransform( 80, 0 );
        e.Graphics.ResetClip();
        e.Graphics.DrawLines( Pens.Red, points );
    }

Это эффективно обрезает, используя область, объединенную / объединенную (я думаю) с ClientRectangle canvas / Control. Поскольку область отличается от прямоугольника, результаты должны соответствовать ожидаемым. Этот код может быть доказан для работы, добавив

e.Graphics.FillRectangle( new SolidBrush( Color.Black ), b );

после вызова setClip (). Это ясно показывает, что черный прямоугольник появляется только в обрезанной области.

Это может быть допустимым обходным решением, если сглаживание линии не является вариантом.

Надеюсь это поможет

3
23.09.2008 12:39:47