July 26, 2017
Hot Topics:

# Visualizing LINQ Sequences with GDI+

### Introduction

It's all rectangles. Draw a rectangle and you need a rectangle control. Draw an ellipse and you need the bounding rectangle. Drawing controls, graphics, positioning forms—these all require rectangles.

My upcoming book, LINQ Unleashed for C# from Sams, talks about Language INtegrated Query. LINQ produces sequences. I wanted to visualize those sequences for the books—I got tired of creating them by hand in MS-Paint—so I thought I'd write a utility to generate the LINQ visualizations for me. Guess what? Rectangles are needed to lay out each item in the sequence.

In this article, a general utility for laying out rectangles and sub-rectangles in a line is provided. The utility also will lay out multiple rows of rectangles and sub-rectangles. Finally, the utility is used to display the results of LINQ queries. Enjoy.

### Defining the Rectangle Utility

The basic objective is to define a simple utility that will lay out rectangles and sub-rectangles. The utility includes the ability to center a rectangle; this can be used to lay out text within the rectangle.

The solution chosen is a shared class that defines a couple of functions to return a rectangle and some number and position of smaller rectangles within the outer rectangle. The solution supports inserting padding between rectangles for a uniform, evenly spaced layout. Finally, some of the methods are overloaded to support rectangles with integer coordinates and those with floating point coordinates. Listing 1 contains the solution.

Listing 1: A general rectangle utility.

```Imports System.Drawing

Public Class Rectangles

' example: a rectangle divided four across and three down
' get h=2 and v = 2 the x shows the sub-rect we would get
' -----------------
' |   |   |   |   |
' -----------------
' |   | x |   |   |
' -----------------
' |   |   |   |   |
' -----------------

' Given a rectangle return a sub-rectangle based on horizontal
' and vertical sub-divsions
Public Shared Function GetSubRect(ByVal x As Integer, _
ByVal y As Integer, _
ByVal width As Integer, ByVal height As Integer, _
ByVal horizontalSegment As Integer, _
ByVal verticalSegment As Integer, _
ByVal numberOfHorizontalSegments As Integer, _
ByVal numberOfVerticalSegments As Integer) As Rectangle

Return GetSubRect(x, y, width, height, horizontalSegment, _
verticalSegment, numberOfHorizontalSegments, _
numberOfVerticalSegments, 0)
End Function

' Given a rectangle return a sub-rectangle based on horizontal
' and vertical sub-divsions
Public Shared Function GetSubRectF(ByVal x As Integer, _
ByVal y As Integer, _
ByVal width As Single, ByVal height As Single, _
ByVal horizontalSegment As Single, _
ByVal verticalSegment As Single, _
ByVal numberOfHorizontalSegments As Integer, _
ByVal numberOfVerticalSegments As Integer) As RectangleF

Return GetSubRect(x, y, width, height, horizontalSegment, _
verticalSegment, numberOfHorizontalSegments, _
numberOfVerticalSegments, 0)

End Function

' Given a rectangle with padding in between
' return a sub-rectangle based on horizontal and vertical
' sub-divsions
Public Shared Function GetSubRect(ByVal x As Integer, _
ByVal y As Integer, _
ByVal width As Integer, ByVal height As Integer, _
ByVal horizontalSegment As Integer, _
ByVal verticalSegment As Integer, _
ByVal numberOfHorizontalSegments As Integer, _
ByVal numberOfVerticalSegments As Integer, _
ByVal padding As Integer) As Rectangle

Dim newWidth As Integer = width / _
Dim newHeight As Integer = height / _

Return New Rectangle(x + (newWidth + padding) * _
horizontalSegment, _ y + (newHeight + padding) *
verticalSegment, _
newWidth, newHeight)

End Function

' Given a rectangle with padding in between
' return a sub-rectangle based on horizontal and vertical
' sub-divsions
Public Shared Function GetSubRectF(ByVal x As Integer,
ByVal y As Integer, _
ByVal width As Single, ByVal height As Single, _
ByVal horizontalSegment As Single, _
ByVal verticalSegment As Single, _
ByVal numberOfHorizontalSegments As Integer, _
ByVal numberOfVerticalSegments As Integer, _
ByVal padding As Single) As RectangleF

Dim newWidth As Single = width / _
Dim newHeight As Single = height / _

Return New Rectangle(x + (newWidth + padding) * _
horizontalSegment, y + (newHeight + padding) * _
verticalSegment, _
newWidth, newHeight)

End Function

' Given a rectangle return a sub-rectangle based on horizontal _
' and vertical sub-divsions
Public Shared Function GetSubRect(ByVal boundingRect _
As Rectangle, _
ByVal horizontalSegment As Integer, _
ByVal verticalSegment As Integer, _
ByVal numberOfHorizontalSegments As Integer, _
ByVal numberOfVerticalSegments As Integer) As Rectangle

Return GetSubRect(boundingRect.X, boundingRect.Y, _
boundingRect.Width, _
boundingRect.Height, horizontalSegment, _
verticalSegment, numberOfHorizontalSegments, _
numberOfVerticalSegments)

End Function

' Given a rectangle return a sub-rectangle based on horizontal
' and vertical sub-divsions
Public Shared Function GetSubRectF(ByVal boundingRect _
As RectangleF, _
ByVal horizontalSegment As Single, _
ByVal verticalSegment As Single, _
ByVal numberOfHorizontalSegments As Integer, _
ByVal numberOfVerticalSegments As Integer) As RectangleF

Return GetSubRectF(boundingRect.X, boundingRect.Y, _
boundingRect.Width, _
boundingRect.Height, horizontalSegment, _
verticalSegment, numberOfHorizontalSegments, _
numberOfVerticalSegments)

End Function

' Given a rectangle with padding in between
' return a sub-rectangle based on horizontal and vertical
' sub-divsions
Public Shared Function GetSubRect(ByVal boundingRect _
As Rectangle, _
ByVal horizontalSegment As Integer, _
ByVal verticalSegment As Integer, _
ByVal numberOfHorizontalSegments As Integer, _
ByVal numberOfVerticalSegments As Integer, _
ByVal padding As Integer) As Rectangle

Return GetSubRect(boundingRect.X, boundingRect.Y, _
boundingRect.Width, _
boundingRect.Height, horizontalSegment, _
verticalSegment, numberOfHorizontalSegments, _

End Function

' Given a rectangle with padding in between
' return a sub-rectangle based on horizontal and vertical
' sub-divsions
Public Shared Function GetSubRectF(ByVal boundingRect _
As RectangleF, _
ByVal horizontalSegment As Single, _
ByVal verticalSegment As Single, _
ByVal numberOfHorizontalSegments As Integer, _
ByVal numberOfVerticalSegments As Integer, _
ByVal padding As Single) As RectangleF

Return GetSubRectF(boundingRect.X, boundingRect.Y, _
boundingRect.Width, _
boundingRect.Height, horizontalSegment, _
verticalSegment, numberOfHorizontalSegments, _

End Function

' Given the size of something get a centered horizontally
' and vertically centered rectangle
Public Shared Function CenterRect(ByVal size As SizeF, _
ByVal boundingRectangle As Rectangle)

Return New Rectangle(boundingRectangle.X + _
(boundingRectangle.Width - size.Width) / 2, _
boundingRectangle.Y + (boundingRectangle.Height - _
size.Height) / 2, _
boundingRectangle.Width, _
boundingRectangle.Height)

End Function

End Class
```

Page 1 of 3

Comment and Contribute

(Maximum characters: 1200). You have characters left.

## Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

## Most Popular Developer Stories

Thanks for your registration, follow us on our social networks to keep up-to-date