dcsimg
August 14, 2018
Hot Topics:

Visualizing LINQ Sequences with GDI+

  • February 4, 2008
  • By Paul Kimmel
  • Send Email »
  • More Articles »

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




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.

By submitting your information, you agree that developer.com may send you developer offers via email, phone and text message, as well as email offers about other products and services that developer believes may be of interest to you. developer will process your information in accordance with the Quinstreet Privacy Policy.

Sitemap

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