Shapes.vb
- ''
- '' This code is part of Document Solutions for PDF demos.
- '' Copyright (c) MESCIUS inc. All rights reserved.
- ''
- Imports System.IO
- Imports System.Drawing
- Imports System.Numerics
- Imports System.Linq
- Imports GrapeCity.Documents.Pdf
- Imports GrapeCity.Documents.Text
- Imports GrapeCity.Documents.Drawing
- Imports GCTEXT = GrapeCity.Documents.Text
- Imports GCDRAW = GrapeCity.Documents.Drawing
-
- '' Demonstrates how various shapes can be drawn in DsPdf.
- '' Shows how simple shapes can be combined to produce more complex shapes.
- '' Simple graphics transformations are used to draw some shapes.
- Public Class Shapes
-
- '' Helper method to draw a polygon and a caption beneath it.
- '' Can also be used to just calculate the points without actual drawing.
- '' startAngle is for the first point, clockwise from (1,0).
- Private Function DrawPolygon(
- ByVal g As GcGraphics,
- ByVal center As PointF,
- ByVal r As Single,
- ByVal n As Integer,
- ByVal startAngle As Single,
- ByVal pn As GCDRAW.Pen,
- Optional ByVal caption As String = Nothing) As PointF()
- Dim pts(n - 1) As PointF
- For i = 0 To n - 1
- pts(i) = New PointF(center.X + (r * Math.Cos(startAngle + 2 * Math.PI * i / n)), center.Y + (r * Math.Sin(startAngle + 2 * Math.PI * i / n)))
- Next
-
- If pn IsNot Nothing Then
- g.DrawPolygon(pts, pn)
- End If
- If Not String.IsNullOrEmpty(caption) Then
- DrawCaption(g, center, r, caption)
- End If
- Return pts
- End Function
-
- '' Helper method to draw a caption beneath a shape:
- Private Sub DrawCaption(ByVal g As GcGraphics, ByVal center As PointF, ByVal r As Single, ByVal caption As String)
- g.DrawString(
- caption,
- New TextFormat() With {.Font = StandardFonts.Times, .FontSize = 10},
- New RectangleF(center.X - r, center.Y + r, r * 2, 24),
- TextAlignment.Center, ParagraphAlignment.Center, False)
- End Sub
-
- '' Main entry point.
- Function CreatePDF(ByVal stream As Stream) As Integer
- Dim doc = New GcPdfDocument()
- Dim page = doc.Pages.Add()
- Dim g = page.Graphics
- '' Document header:
- g.DrawString("Shapes",
- New TextFormat() With {.Font = StandardFonts.TimesBold, .FontSize = 14, .Underline = True},
- New RectangleF(PointF.Empty, New SizeF(page.Size.Width, 44)),
- TextAlignment.Center, ParagraphAlignment.Far)
- '' Pen used to draw shapes:
- Dim pen = New GCDRAW.Pen(Color.Orange, 1)
- pen.LineJoin = PenLineJoin.Round
- Dim fill = 100 '' Surfaces fill alpha
-
- '' Set up the helper layout grid:
- Dim grid = New With {
- .Cols = 3,
- .Rows = 5,
- .MarginX = 72,
- .MarginY = 36,
- .Radius = 36,
- .StepX = (page.Size.Width - 144) / 3,
- .StepY = (page.Size.Height - 72) / 5
- }
-
- '' Insertion point of the next figure's center:
- Dim startIp = New PointF(grid.MarginX + grid.StepX / 2, grid.MarginY + grid.StepY / 2 + 10)
- Dim ip = startIp
- #If False Then
- '' Debug code to show the layout grid:
- Dim ipp = ip
- For i = 1 To grid.Cols
- ipp.Y = ip.Y
- For j = 1 To grid.Rows
- g.DrawRectangle(New RectangleF(ipp.X - grid.Radius, ipp.Y - grid.Radius, grid.Radius * 2, grid.Radius * 2), Color.LightGreen, 0.5F)
- ipp.Y += grid.StepY
- Next
- ipp.X += grid.StepX
- Next
- #End If
- '' Circle:
- g.DrawEllipse(New RectangleF(ip.X - grid.Radius, ip.Y - grid.Radius, grid.Radius * 2, grid.Radius * 2), pen)
- DrawCaption(g, ip, grid.Radius, "Circle")
- ip.X += grid.StepX
-
- '' Ellipse:
- g.DrawEllipse(New RectangleF(ip.X - grid.Radius * 1.4F, ip.Y - grid.Radius / 2, grid.Radius * 2 * 1.4F, grid.Radius), pen)
- DrawCaption(g, ip, grid.Radius, "Ellipse")
- ip.X += grid.StepX
-
- '' Cylinder:
- Dim radX = grid.Radius / 1.4F
- Dim radY = grid.Radius / 6
- Dim height = grid.Radius * 1.8F
- g.DrawEllipse(New RectangleF(ip.X - radX, ip.Y - height / 2, radX * 2, radY * 2), pen)
- g.FillEllipse(New RectangleF(ip.X - radX, ip.Y + height / 2 - radY * 2, radX * 2, radY * 2), Color.FromArgb(fill, pen.Color))
- g.DrawEllipse(New RectangleF(ip.X - radX, ip.Y + height / 2 - radY * 2, radX * 2, radY * 2), pen)
- g.DrawLine(New PointF(ip.X - radX, ip.Y - height / 2 + radY), New PointF(ip.X - radX, ip.Y + height / 2 - radY), pen)
- g.DrawLine(New PointF(ip.X + radX, ip.Y - height / 2 + radY), New PointF(ip.X + radX, ip.Y + height / 2 - radY), pen)
- DrawCaption(g, ip, grid.Radius, "Cylinder")
- ip.X = startIp.X
- ip.Y += grid.StepY
- pen.Color = Color.Indigo
-
- '' Square:
- DrawPolygon(g, ip, grid.Radius, 4, -Math.PI / 4, pen, "Square")
- ip.X += grid.StepX
-
- '' Rectangle:
- Dim rectQx = 1.4F
- Dim rectQy = 0.6F
- Dim rect = New RectangleF(ip.X - grid.Radius * rectQx, ip.Y - grid.Radius * rectQy, grid.Radius * 2 * rectQx, grid.Radius * 2 * rectQy)
- g.DrawRectangle(rect, pen)
- DrawCaption(g, ip, grid.Radius, "Rectangle")
- ip.X += grid.StepX
-
- '' Cube:
- Dim cubex = 6
- Dim cubePtsFar = DrawPolygon(g, New PointF(ip.X - cubex, ip.Y - cubex), grid.Radius, 4, -Math.PI / 4, pen)
- Dim cubePtsNear = DrawPolygon(g, New PointF(ip.X + cubex, ip.Y + cubex), grid.Radius, 4, -Math.PI / 4, pen)
- g.DrawLine(cubePtsFar(0), cubePtsNear(0), pen)
- g.DrawLine(cubePtsFar(1), cubePtsNear(1), pen)
- g.DrawLine(cubePtsFar(2), cubePtsNear(2), pen)
- g.DrawLine(cubePtsFar(3), cubePtsNear(3), pen)
- g.FillPolygon(New PointF() {cubePtsFar(1), cubePtsFar(2), cubePtsNear(2), cubePtsNear(1)}, Color.FromArgb(fill, pen.Color))
- DrawCaption(g, ip, grid.Radius, "Cube")
- ip.X = startIp.X
- ip.Y += grid.StepY
- pen.Color = Color.DarkGreen
-
- '' Pentagon:
- DrawPolygon(g, ip, grid.Radius, 5, -Math.PI / 2, pen, "Pentagon")
- ip.X += grid.StepX
-
- '' Hexagon:
- '' For sample sake, we apply a transform to make the hexagon wider and shorter:
- g.Transform = Matrix3x2.CreateScale(1.4F, 0.8F) * Matrix3x2.CreateTranslation(ip.X, ip.Y)
- DrawPolygon(g, PointF.Empty, grid.Radius, 6, 0, pen, Nothing)
- g.Transform = Matrix3x2.Identity
- DrawCaption(g, ip, grid.Radius, "Hexagon")
- ip.X += grid.StepX
-
- '' Octagon:
- DrawPolygon(g, ip, grid.Radius, 8, -Math.PI / 8, pen, "Octagon")
- ip.X = startIp.X
- ip.Y += grid.StepY
- pen.Color = Color.DarkRed
-
- '' Triangle:
- DrawPolygon(g, ip, grid.Radius, 3, -Math.PI / 2, pen, "Triangle")
- ip.X += grid.StepX
-
- '' Filled pentagram:
- Dim pts = DrawPolygon(g, ip, grid.Radius, 5, -Math.PI / 2, pen, "Pentagram")
- pts = New PointF() {pts(0), pts(2), pts(4), pts(1), pts(3)}
- g.FillPolygon(pts, Color.FromArgb(fill, pen.Color))
- g.DrawPolygon(pts, pen)
- ip.X += grid.StepX
-
- '' Set up a simple kind of oblique projection to draw a pyramid:
- Dim angle = Math.PI / 6
- Dim s = Math.Sin(angle)
- Dim c = Math.Cos(angle)
-
- Dim project As Func(Of Single, Single, Single, PointF) =
- Function(ByVal x_, ByVal y_, ByVal z_)
- Return New PointF(x_ - c * y_ * 0.5F, -(z_ - s * y_ * 0.5F))
- End Function
-
- Dim p3d As Func(Of Vector3, PointF) =
- Function(ByVal v_)
- Return project(v_.X, v_.Y, v_.Z)
- End Function
-
- Dim hedge = grid.Radius '' 1/2 edge
- '' Debug - draw the 3 axis:
- '' g.DrawLine(project(0, 0, 0), project(100, 0, 0), Color.Red)
- '' g.DrawLine(project(0, 0, 0), project(0, 100, 0), Color.Green)
- '' g.DrawLine(project(0, 0, 0), project(0, 0, 100), Color.Blue)
-
- '' 3d points forming a square pyramid:
- Dim pts3d As Vector3() =
- {
- New Vector3(-hedge, -hedge, 0),
- New Vector3(hedge, -hedge, 0),
- New Vector3(hedge, hedge, 0),
- New Vector3(-hedge, hedge, 0),
- New Vector3(0, 0, hedge * 2)
- }
- '' Project the points to draw the pyramid:
- pts = pts3d.Select(Function(v_) p3d(v_)).ToArray()
- g.Transform = Matrix3x2.CreateTranslation(ip.X, ip.Y + hedge * 0.7F)
- '' Visible edges:
- g.DrawPolygon(New PointF() {pts(4), pts(1), pts(2), pts(3), pts(4), pts(2)}, pen)
- '' Invisible edges:
- pen.Width /= 2
- pen.Color = Color.FromArgb(fill, pen.Color)
- g.DrawLine(pts(0), pts(4), pen)
- g.DrawLine(pts(0), pts(1), pen)
- g.DrawLine(pts(0), pts(3), pen)
- g.FillPolygon(pts.Take(4).ToArray(), pen.Color)
- ''
- g.Transform = Matrix3x2.Identity
- DrawCaption(g, ip, grid.Radius, "Pyramid")
- ip.X = startIp.X
- ip.Y += grid.StepY
- pen.Width *= 2
- pen.Color = Color.Green
-
- '' Cone:
- Dim baseh = grid.Radius * 0.3F
- pts = DrawPolygon(g, ip, grid.Radius, 3, -Math.PI / 2, Nothing, "Cone")
- g.DrawLines(New PointF() {pts(2), pts(0), pts(1)}, pen)
- rect = New RectangleF(pts(2).X, pts(2).Y - baseh / 2, pts(1).X - pts(2).X, baseh)
- g.FillEllipse(rect, Color.FromArgb(fill, pen.Color))
- g.DrawEllipse(rect, pen)
- ip.X += grid.StepX
-
- '' Parallelogram (use graphics.Transform on a rectangle):
- rect = New RectangleF(-grid.Radius * rectQx, -grid.Radius * rectQy, grid.Radius * 2 * rectQx, grid.Radius * 2 * rectQy)
- g.Transform = Matrix3x2.CreateSkew(Math.PI / 6, 0) * Matrix3x2.CreateTranslation(ip.X, ip.Y)
- g.DrawRectangle(rect, pen)
- g.Transform = Matrix3x2.Identity
- DrawCaption(g, ip, grid.Radius, "Parallelogram")
- ip.X += grid.StepX
-
- '' Trapezoid (use DrawPolygon to just get the points of the square):
- Dim dx = 10
- pts = DrawPolygon(g, ip, grid.Radius, 4, -Math.PI / 4, Nothing, "Trapezoid")
- pts(0).X -= dx
- pts(1).X += dx
- pts(2).X -= dx
- pts(3).X += dx
- g.DrawPolygon(pts, pen)
- ''
- '' Done:
- doc.Save(stream)
- Return doc.Pages.Count
- End Function
- End Class
-