Region.IsVisible () не работает как задокументировано (?) [GDI +] - PullRequest
4 голосов
/ 28 июня 2010

Я вижу, что Region.IsVisible (прямоугольник) работает не так, как я ожидаю.
Итак, - это я , ожидающий, что не должен, или метод , которыйделаю не то что должно ??!

у меня следующая ситуация:

alt text http://lh4.ggpht.com/_1TPOP7DzY1E/TCmxn6Tzn2I/AAAAAAAADRc/GJhbStCvabQ/s800/Capture3.gif alt text http://lh5.ggpht.com/_1TPOP7DzY1E/TCmuVyrgpTI/AAAAAAAADRU/yLNn-jZQDNA/s800/Capture2.gif

И следующий код:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    Point[] points1 = new Point[] {
        new Point(50, 30),
        new Point(70, 30),
        new Point(40, 40),
        new Point(60, 70),
        new Point(30, 50)
    };

    Point[] points2 = new Point[] {
        new Point(70, 150),
        new Point(50, 110 ),
        new Point(60, 80),
        new Point(90, 80),
        new Point(140, 60)                
    };

    Point[] points3 = new Point[] {
        new Point(100, 10),
        new Point(130, 40)
    };

    GraphicsPath path1 = new GraphicsPath();
    GraphicsPath path2 = new GraphicsPath();
    GraphicsPath path3 = new GraphicsPath();

    path1.AddLines(points1);
    path2.AddLines(points2);
    path3.AddLines(points3);

    e.Graphics.DrawPath(Pens.DarkBlue, path1);
    e.Graphics.DrawPath(Pens.DarkGreen, path2);
    e.Graphics.DrawPath(Pens.DarkOrange, path3);

    Region r1 = new Region(path1);
    Region r2 = new Region(path2);
    Region r3 = new Region(path3);

    // Create the first rectangle and draw it to the screen in blue.
    Rectangle blueRect = new Rectangle(20, 20, 100, 100);
    e.Graphics.DrawRectangle(Pens.Blue, blueRect);

    bool contained;

    // Display the result.                        
    ControlPaint.DrawGrid(e.Graphics, this.ClientRectangle,
        new Size(10, 10), Color.Red);

    contained = r1.IsVisible(blueRect);
    e.Graphics.DrawString("Path blue contained = " + contained.ToString(),
        Font, myBrush, new PointF(20, 160));

    contained = r2.IsVisible(blueRect);
    e.Graphics.DrawString("Path green contained = " + contained.ToString(),
        Font, Brushes.Black, new PointF(20, 180));

    contained = r3.IsVisible(blueRect);
    e.Graphics.DrawString("Path orange contained = " + contained.ToString(),
        Font, Brushes.Black, new PointF(20, 200));
}

Кроме того, путь, который не находится в области, может быть «видимым»:

Point[] points3 = new Point[] {
  new Point(15, 35),
  new Point(15, 130),
  new Point(60 ,130)
};

РЕДАКТИРОВАТЬ:
Даже пересечение не работает для второго пути L:

Point[] points3 = new Point[] {
    new Point(10, 40),
    new Point(10, 130),
    new Point(50 ,130)
};

r3.Intersect(blueRect);
bool contained = !(r1.IsEmpty(e.Graphics)); 
e.Graphics.DrawString("Path orange contained = " + contained.ToString(),
    Font, Brushes.Black, new PointF(20, 200)); // TRUE! instead of desired FALSE

Ответы [ 3 ]

3 голосов
/ 29 июня 2010

Из оранжевого L-образного примера я вижу, что вы неправильно понимаете, что делает ваш код.

Построение области из пути не дает регион в форме нарисованного пути. Построение области из L-образного оранжевого пути не дает L-образную область шириной в один пиксель. Путь замыкается, соединяя оба конца, образуя треугольник. В этом случае область является внутренней частью этого треугольника, и синий прямоугольник явно частично содержится в этой области.

Для начального примера одиночной оранжевой линии результирующая область представляет собой вырожденный многоугольник только с двумя углами - все еще выглядит как линия и с нулевой шириной в направлении, ортогональном линии (ям). Поэтому область имеет нулевую область и не содержит ничего (за исключением, возможно, точек на границе области, если область является замкнутым множеством).

Что вы на самом деле хотите сделать, так это выполнить тест видимости пути к прямоугольной области синего прямоугольника. Насколько я знаю, для этого нет встроенной поддержки.

2 голосов
/ 01 июля 2010

Итак, решением для этого было использование ... метода Widen () для путей перед проверкой его видимости:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    Point[] points1 = new Point[] {
                new Point(50, 30),
                new Point(70, 30),
                new Point(40, 40),
                new Point(60, 70),
                new Point(30, 50)
            };

    Point[] points2 = new Point[] {
                new Point(70, 150),
                new Point(50, 110 ),
                new Point(60, 80),
                new Point(90, 80),
                new Point(140, 60)
            };

    Point[] points4 = new Point[] {
        new Point(50, 50),
        new Point(90, 90)
      };

    Point[] points3 = new Point[] {
                new Point(15, 35),
                new Point(15, 130),
                new Point(60 ,130)
            };

    GraphicsPath path1 = new GraphicsPath();
    GraphicsPath path2 = new GraphicsPath();
    GraphicsPath path3 = new GraphicsPath();
    GraphicsPath path4 = new GraphicsPath();

    path1.AddLines(points1);
    path2.AddLines(points2);
    path3.AddLines(points3);
    path4.AddLines(points4);

    e.Graphics.DrawPath(Pens.DarkBlue, path1);
    e.Graphics.DrawPath(Pens.DarkGreen, path2);
    e.Graphics.DrawPath(Pens.DarkRed, path3);
    e.Graphics.DrawPath(Pens.DarkGoldenrod, path4);

    // <<<< HERE >>>>>
    path3.Widen(Pens.DarkRed);
    path4.Widen(Pens.DarkGoldenrod);

    Region r1 = new Region(path1);
    Region r2 = new Region(path2);
    Region r3 = new Region(path3);
    Region r4 = new Region(path4);

    // Create the first rectangle and draw it to the screen in blue.
    Rectangle blueRect = new Rectangle(20, 20, 100, 100);
    e.Graphics.DrawRectangle(Pens.Blue, blueRect);

    bool contained;

    // Display the result.            
    ControlPaint.DrawGrid(e.Graphics, this.ClientRectangle,
         new Size(10, 10), Color.Red);

    contained = r1.IsVisible(blueRect);
    e.Graphics.DrawString("Path blue contained = " + contained.ToString(),
         Font, Brushes.Black, new PointF(20, 160));

    contained = r2.IsVisible(blueRect);
    e.Graphics.DrawString("Path green contained = " + contained.ToString(),
         Font, Brushes.Black, new PointF(20, 180));

    contained = r3.IsVisible(blueRect);
    e.Graphics.DrawString("Path orange contained = " + contained.ToString(),
         Font, Brushes.Black, new PointF(20, 200));

    contained = r4.IsVisible(blueRect);
    e.Graphics.DrawString("Path DarkGoldenrod contained = " + contained.ToString(),
         Font, Brushes.Black, new PointF(20, 220));
}

Что касается вопроса в заголовке темы: Да , на самом деле IsVisible из Region не работает, как описано в MSDN.

Microsoft должна добавить некоторые точные заметки в свою документацию.

1 голос
/ 28 июня 2010

Может случиться так, что метод Region.IsVisible просто проверяет, находятся ли какие-либо из конечных точек его компонентных сегментов в прямоугольнике или нет.Таким образом, синие и зеленые линии (каждая из которых имеет несколько конечных точек сегмента в прямоугольнике) равны true, а оранжевая линия (которая имеет 0 конечных точек в прямоугольнике) - false.

Технически, вашНа самом деле код пытается определить, содержит ли каждый неправильный Path синий прямоугольник (а не наоборот).Альтернативный способ сделать то, что вы на самом деле пытаетесь сделать (но это, вероятно, даст те же результаты), это:

r1.Intersect(blueRect);
e.Graphics.DrawString("Path blue contained = " + 
    (!r1.IsEmpty(e.Graphics)).ToString(), Font, Brushes.Black, 
    new PointF(20, 200));   
...