''
'' This code is part of Document Solutions for Imaging demos.
'' Copyright (c) MESCIUS inc. All rights reserved.
''
Imports System
Imports System.IO
Imports System.Drawing
Imports System.Collections.Generic
Imports System.Linq
Imports System.Numerics
Imports GrapeCity.Documents.Drawing
Imports GrapeCity.Documents.Text
Imports GrapeCity.Documents.Imaging
Imports GrapeCity.Documents.Svg
Imports GCTEXT = GrapeCity.Documents.Text
Imports GCDRAW = GrapeCity.Documents.Drawing
'' This example shows how to use GcSvgGraphics for common graphics
'' operations. It draws some geometric shapes on GcSvgGraphics,
'' then converts that graphics to GcSvgDocument, which is saved
'' to an SVG stream that is shown by this sample.
'' Note that the code drawing shapes on GcSvgGraphics is identical
'' to the code drawing shapes on GcBitmapGraphics in the Shapes sample.
'' Compare this to the SvgShapes sample which creates SVG elements
'' representing shapes, and draws them on the resulting raster GcBitmap.
Public Class SvgGraphicsShapes
Public ReadOnly Property DefaultMime As String
Get
Return Util.MimeTypes.SVG
End Get
End Property
'' 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(g As GcGraphics, center As PointF, r As Single, n As Integer, startAngle As Single, pen As GCDRAW.Pen, Optional caption As String = Nothing) As PointF()
Dim pts(n - 1) As PointF
For i = 0 To n - 1
pts(i) = New PointF(center.X + CSng(r * Math.Cos(startAngle + 2 * Math.PI * i / n)), center.Y + CSng(r * Math.Sin(startAngle + 2 * Math.PI * i / n)))
Next
If pen IsNot Nothing Then
g.DrawPolygon(pts, pen)
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(g As GcGraphics, center As PointF, r As Single, caption As String)
g.DrawString(caption,
New TextFormat() With {
.Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "FreeSerif.ttf")),
.FontSize = 12
},
New RectangleF(center.X - r, center.Y + r, r * 2, 24),
TextAlignment.Center, ParagraphAlignment.Center, False)
End Sub
'' Main entry point.
Public Function GenerateImageStream(targetMime As String, pixelSize As Size, dpi As Single, opaque As Boolean, Optional sampleParams As String() = Nothing) As Stream
If targetMime <> Util.MimeTypes.SVG Then
Throw New Exception("This sample only supports SVG output format.")
End If
Dim Inch = dpi
Dim ms = New MemoryStream()
Using g As New GcSvgGraphics(pixelSize.Width, pixelSize.Height)
If opaque Then
g.FillRectangle(New RectangleF(0, 0, g.Width, g.Height), Color.White)
End If
'' Document header:
g.DrawString("Shapes",
New TextFormat() With {
.Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "FreeSerifBold.ttf")),
.FontBold = True,
.FontSize = 14,
.Underline = True
},
New RectangleF(PointF.Empty, New SizeF(g.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 As Integer = 100 '' Surfaces fill alpha
'' Set up the helper layout grid:
Dim grid = New With {
.Cols = 3,
.Rows = 5,
.MarginX = Inch / 4,
.MarginY = Inch / 3,
.Radius = Inch * 0.7F,
.StepX = (g.Width - Inch / 2) / 3,
.StepY = (g.Height - Inch / 4) / 5.5F
}
Dim startIp As New PointF(grid.MarginX + grid.StepX / 2, grid.MarginY + grid.StepY / 2 + 10)
Dim ip As PointF = startIp
'' 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, CSng(-Math.PI / 4), pen, "Square")
ip.X += grid.StepX
'' Rectangle:
Dim rectQx As Single = 1.4F
Dim rectQy As Single = 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 As Single = 6
Dim cubePtsFar = DrawPolygon(g, New PointF(ip.X - cubex, ip.Y - cubex), grid.Radius, 4, CSng(-Math.PI / 4), pen)
Dim cubePtsNear = DrawPolygon(g, New PointF(ip.X + cubex, ip.Y + cubex), grid.Radius, 4, CSng(-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, CSng(-Math.PI / 2), pen, "Pentagon")
ip.X += grid.StepX
'' Hexagon with transform:
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, CSng(-Math.PI / 8), pen, "Octagon")
ip.X = startIp.X
ip.Y += grid.StepY
pen.Color = Color.DarkRed
'' Triangle:
DrawPolygon(g, ip, grid.Radius, 3, CSng(-Math.PI / 2), pen, "Triangle")
ip.X += grid.StepX
'' Filled pentagram:
Dim pts = DrawPolygon(g, ip, grid.Radius, 5, CSng(-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
'' Pyramid (oblique projection):
Dim angle = Math.PI / 6
Dim s = CSng(Math.Sin(angle))
Dim c = CSng(Math.Cos(angle))
Dim project As Func(Of Single, Single, Single, PointF) = Function(x_, y_, z_) New PointF(x_ - c * y_ * 0.5F, -(z_ - s * y_ * 0.5F))
Dim p3d As Func(Of Vector3, PointF) = Function(v_) project(v_.X, v_.Y, v_.Z)
Dim hedge = grid.Radius
Dim pts3d = {
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)
}
pts = pts3d.Select(Function(v_) p3d(v_)).ToArray()
g.Transform = Matrix3x2.CreateTranslation(ip.X, ip.Y + hedge * 0.7F)
g.DrawPolygon(New PointF() {pts(4), pts(1), pts(2), pts(3), pts(4), pts(2)}, pen)
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, CSng(-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 skew 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(CSng(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 (adjust points of a square):
Dim dx As Single = 10
pts = DrawPolygon(g, ip, grid.Radius, 4, CSng(-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:
Dim svg = g.ToSvgDocument()
svg.Save(ms)
ms.Seek(0, SeekOrigin.Begin)
Return ms
End Using
End Function
End Class