Visualizing LINQ Sequences with GDI+ | CodeGuru

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 […]

Written By
CodeGuru Staff
CodeGuru Staff
Feb 4, 2008
2 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

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 / _
         numberOfHorizontalSegments - padding
      Dim newHeight As Integer = height / _
         numberOfVerticalSegments - padding

      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 / _
         numberOfHorizontalSegments - padding
      Dim newHeight As Single = height / _
         numberOfVerticalSegments - padding

      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, _
         numberOfVerticalSegments, padding)

   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, _
         numberOfVerticalSegments, padding)

   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
CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.