Reputation: 28586
I see that Region.IsVisible(rectangle) is not working as I expect.
So, is me who expect that should not, or is the method that is doing not that it should ??!
I have the following situation:
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
And the following code:
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));
}
Also, a path that is not in the region could be "visible":
Point[] points3 = new Point[] {
new Point(15, 35),
new Point(15, 130),
new Point(60 ,130)
};
EDIT:
Even Intersect does not work for the second L path:
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
Upvotes: 4
Views: 1765
Reputation: 492
Coming in rather late on this! After some experimentation, it makes more sense to check each point in the array individually, rather than check the region. The added advantage is that you can also see whether the whole region is in or not:
Private Function AllWithin(ByVal points() As Point, ByVal r As Region) As Boolean
' Checks whether all the points in an array are within a region
Dim contained As Boolean = True
For a As Integer = 0 To points.Length - 1
If Not r.IsVisible(points(a)) Then
contained = False
Exit For
End If
Next
Return contained
End Function
Private Function SomeWithin(ByVal points() As Point, ByVal r As Region) As Boolean
' Checks whether some of the points in an array are within a region
Dim contained As Boolean = False
For a As Integer = 0 To points.Length - 1
If r.IsVisible(points(a)) Then
contained = True
Exit For
End If
Next
Return contained
End Function
Upvotes: 0
Reputation: 28586
So, a solution for this was to use... Widen() method for paths before checking its visibility:
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));
}
As for the question in the thread title: Yes, actually IsVisible
of Region
is not working as documented in MSDN.
Microsoft should add some precision notes in their documentation.
Upvotes: 2
Reputation: 59675
From the orange L-shaped example I see you are misunderstanding what your code does.
Building a region from a path does not yield a region in the form of the drawn path. Building a region from the L-shaped orange path does not yield a L-shaped one pixel width region. The path gets closed by connecting both ends forming a triangle. The region is then the interior of that triangle and the blue rectangle is obviously partial contained in that region.
For the initial example of the single orange line the resulting region is a degenerated polygon with two corners only - still looking like a line and with zero width in the direction orthogonal to the line(s). Therefore the region has zero area and does not contain anything (except maybe points on the border of the region if a region is a closed set).
What you actually want to do is performing a visibility test of a path against the rectangular region of the blue rectangle. As far as I know there is no build-in support for doing this.
Upvotes: 3
Reputation: 75346
It may be that the Region.IsVisible
method just checks whether any of the endpoints of its component line segments are within the rectangle or not. Thus, the blue and green lines (which each have multiple segment endpoints within the rectangle) are true
, while the orange line (which has 0 endpoints within the rectangle) is false
.
Technically, your code is actually trying to determine whether each irregular Path
contains the blue rectangle (rather than the other way around). An alternative way of doing what you're actually trying to do (but that will probably return the same results) is this:
r1.Intersect(blueRect);
e.Graphics.DrawString("Path blue contained = " +
(!r1.IsEmpty(e.Graphics)).ToString(), Font, Brushes.Black,
new PointF(20, 200));
Upvotes: 1