I'm looking for some function which can create a circle on map. I'm using Gmap library in VB.Net. Exist some function which can create a circle around of point on map, for examle with 500 meters radius ?
I found a code, but it isn't what I'm exactly looking for :
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports GMap.NET
Imports GMap.NET.WindowsForms
Namespace Map
Public Class GMapMarkerCircle
Inherits GMapMarker
Private m_Radius As Integer
'In Meters
Public m_OutlinePen As Pen
Public m_FillBrush As Brush
Public m_Fill As Boolean
Public Sub New(p As PointLatLng, Radius As Integer, OutlinePen As Pen, FillBrush As Brush, Fill As Boolean)
MyBase.New(p)
m_OutlinePen = OutlinePen
m_FillBrush = FillBrush
m_Radius = Radius
m_Fill = Fill
End Sub
Public Overrides Sub OnRender(g As Graphics)
g.SmoothingMode = SmoothingMode.AntiAlias
Dim R As Integer = CInt((m_Radius) / Overlay.Control.MapProvider.Projection.GetGroundResolution(Overlay.Control.Zoom, Position.Lat)) * 2
If m_Fill = True Then
g.FillEllipse(m_FillBrush, New System.Drawing.Rectangle(LocalPosition.X - R \ 2, LocalPosition.Y - R \ 2, R, R))
End If
g.DrawEllipse(m_OutlinePen, New System.Drawing.Rectangle(LocalPosition.X - R \ 2, LocalPosition.Y - R \ 2, R, R))
End Sub
End Class
End Namespace
And in app:
Dim CircleMarker As New GMapMarkerCircle(New GMap.NET.PointLatLng(ZemSirka, ZemDlzka), 660, New Pen(Color.Azure, 1), Brushes.LightSeaGreen, True)
Dim Overlay As New GMapOverlay("Circle")
Overlay.Markers.Add(CircleMarker)
GMapControl1.Overlays.Add(Overlay)
But when I zoom in/out the map circle disappears.
I have one beginners question: is any possibility to do Brushes semitransparent ?
Finally I create code which works fine for short distances for examle: 200,300,500 meters.
Public Function toRad(ByVal deegres As Double)
Return deegres * (Math.PI / 180)
End Function
Public Function toDeg(ByVal radians As Double)
Return radians * (180 / Math.PI)
End Function
Private Function pivotRadius(ByVal Dlzka As Double, ByVal Sirka As Double, ByVal dist As Double)
Dim distance = (dist / earthRadius) / 1000
Dim lat As Double = toRad(Sirka)
Dim lng As Double = toRad(Dlzka)
Dim points As IList(Of PointLatLng) = New List(Of PointLatLng)()
Dim x As Integer = 0
While x < 360
Dim brng As Double = toRad(x)
Dim latRadians As Double = Math.Asin(Math.Sin(lat) * Math.Cos(distance) + Math.Cos(lat) * Math.Sin(distance) * Math.Cos(brng))
Dim lngRadians As Double = lng + (Math.Atan2(Math.Sin(brng) * Math.Sin(distance) * Math.Cos(lat), Math.Cos(distance) - Math.Sin(lat) * Math.Sin(latRadians)) / 1.6)
points.Add(New PointLatLng(toDeg(lngRadians), toDeg(latRadians)))
latRadians = 0
lngRadians = 0
x += 10
End While
Dim polyOverlay As New GMapOverlay("polygons")
Dim polygon As New GMapPolygon(points, "mypolygon")
polygon.Fill = New SolidBrush(Color.FromArgb(30, Color.Aqua))
polygon.Stroke = New Pen(Color.Blue, 1)
GMapControl1.Overlays.Clear()
GMapControl1.Overlays.Add(polyOverlay)
polyOverlay.Polygons.Add(polygon)
Return 0
End Function
Related
how can I Show only three significant digits for the data volume, i.e. 0,xxx; x,xx; xx,x; xxx; x’xxx etc.
this is my code
Option Strict On
Imports System.Globalization
Module Module1
Public Function BytesToMegabytes(Bytes As Long) As String
'This function gives an estimate to two decimal
'places. For a more precise answer, format to
'more decimal places or just return dblAns
Dim dblAns As Double = (Bytes / 1024) / 1024
Dim ci = New CultureInfo("en-GB")
ci.NumberFormat.NumberDecimalSeparator = "'"
Return dblAns.ToString("###,###,##0.00", ci)
End Function
Sub Main()
Console.WriteLine(BytesToMegabytes(9225936896))
Console.ReadLine()
End Sub
End Module
Outputs:
currently I score 8,798'54 MB.
to be 8'798 MB, how can I get it?
thank you all for your help
Following on from your previous question...
To use significant figures instead of decimal places:
Public Function BytesToMegabytes(bytes As Long) As String
Dim dblAns As Double = (bytes / 1024) / 1024
If dblAns = 0 Then
Return "0"
End If
Dim significantFigures = 3
Dim magnitude = Math.Floor(Math.Log10(dblAns))
Dim v As Double = 10 ^ (magnitude - significantFigures + 1)
dblAns = Math.Floor(dblAns / v) * v
Dim ci = New CultureInfo("")
ci.NumberFormat.NumberDecimalSeparator = ","
ci.NumberFormat.NumberGroupSeparator = "'"
Return dblAns.ToString("#,##0.###", ci)
End Function
For example, Console.WriteLine(BytesToMegabytes(9225936896)) outputs
8'790
If you change the line Dim significantFigures = 3 to Dim significantFigures = 4, it outputs
8'798
Depending on the rounding you want, you may want to use dblAns = Math.Round(dblAns / v, MidpointRounding.AwayFromZero) * v instead, or perhaps Math.Ceiling instead of Math.Floor.
I'm designing a hexagon grid and I need to be able to name each hexagon, so I can refer to them later. Below is my class, it generates the hexagon grid, and I've labeled the code throughout so you can understand what's happening.
I've been searching for a while now reading a lot about Graphics, but I can't get a working design with the answers I've seen offered. Perhaps, I'm going about this wrong by using Graphics, but my plan is to be able to click on each hexagon and do something with it.
Note: If you see a way to improve my code let me know. It's appreciated!
' Generate Hexagon Grid
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
' Hexagon Grid Parameters
Dim HexagonRadius As Integer = 20 ' Fix "Position Hexagon Grid Columns" Before Changing Hexagon Radius
Dim GridSize As Integer = 10
' Generate Hexagon Grid
Dim HexagonX As Integer = HexagonRadius
Dim HexagonY As Integer = HexagonRadius
For i As Integer = 1 To GridSize
For j As Integer = 1 To GridSize
' Hexagon Vertex Coordinates
Dim point1 As New Point((HexagonX - HexagonRadius), (HexagonY))
Dim point2 As New Point((HexagonX - (HexagonRadius / 2)), (HexagonY + ((HexagonRadius / 2) * Math.Sqrt(3))))
Dim point3 As New Point((HexagonX + (HexagonRadius / 2)), (HexagonY + ((HexagonRadius / 2) * Math.Sqrt(3))))
Dim point4 As New Point((HexagonX + HexagonRadius), (HexagonY))
Dim point5 As New Point((HexagonX + (HexagonRadius / 2)), (HexagonY - ((HexagonRadius / 2) * Math.Sqrt(3))))
Dim point6 As New Point((HexagonX - (HexagonRadius / 2)), (HexagonY - ((HexagonRadius / 2) * Math.Sqrt(3))))
Dim hexagonPoints As Point() = {point1, point2, point3, point4, point5, point6}
' Create Hexagon
e.Graphics.FillPolygon(Brushes.Green, hexagonPoints)
' Hexagon Outline
e.Graphics.DrawLine(Pens.Black, point1, point2)
e.Graphics.DrawLine(Pens.Black, point2, point3)
e.Graphics.DrawLine(Pens.Black, point3, point4)
e.Graphics.DrawLine(Pens.Black, point4, point5)
e.Graphics.DrawLine(Pens.Black, point5, point6)
e.Graphics.DrawLine(Pens.Black, point6, point1)
' Position Hexagon Grid Columns
HexagonY += 34 ' Specific to Hexagon Radius: 20
Next
If i Mod 2 > 0 Then
HexagonY = 36.75 ' Specific to Hexagon Radius: 20
Else
HexagonY = 20 ' Specific to Hexagon Radius: 20
End If
HexagonX += 30 ' Specific to Hexagon Radius: 20
Next
End Sub
You'll need to create some Hexagon class with it's coordinates and (maybe name, if really needed). And save them to some suitable collection (2-dimensional array maybe?)
This should happen somewhere outside your Paint event and might be recalculated on grid SizeChanged event.
Inside your Paint event you'll just iterate throught existing collection and render according to pre-computed coordinates.
OnClick event will loop throught the same collection to find specific Hexagon for updating (changing background color for example) and forcing form to repaint to take effect.
For large rendering you should consider rendering to bitmap first and drawing that final bitmap to e.Graphics for faster work. Your bitmap could be cached as well to speed up even more.
EDIT: Code sample added
Turn Option Strict On in your project properties to avoid many problems in your code that you're not aware of.
Public Class frmTest
Private Const HexagonRadius As Integer = 20
Private Const GridSize As Integer = 10
Private fHexagons As New List(Of Hexagon)
Private fCache As Bitmap
Private fGraphics As Graphics
Private Sub ResetHexagons() 'Call when some parameter changes (Radius/GridSize)
fHexagons.Clear()
Invalidate()
End Sub
Private Function EnsureHexagons() As List(Of Hexagon)
Dim X, Y As Single, xi, yi As Integer
If fHexagons.Count = 0 Then
X = HexagonRadius : Y = HexagonRadius
For xi = 1 To GridSize
For yi = 1 To GridSize
fHexagons.Add(New Hexagon(HexagonRadius, X, Y))
Y += 34
Next
'Do your math to get theese values from HexagonRadius value
If xi Mod 2 > 0 Then
Y = 36.75
Else
Y = 20
End If
X += 30
Next
fCache?.Dispose()
fGraphics?.Dispose()
fCache = New Bitmap(GridSize * HexagonRadius * 2, GridSize * HexagonRadius * 2)
fGraphics = Graphics.FromImage(fCache)
For Each H As Hexagon In fHexagons
H.Render(fGraphics)
Next
End If
Return fHexagons
End Function
Private Sub frmTest_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
EnsureHexagons()
e.Graphics.DrawImageUnscaled(fCache, Point.Empty)
End Sub
Private Sub frmTest_MouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
Dim H As Hexagon = EnsureHexagons.FirstOrDefault(Function(X) X.Contains(e.Location))
If H IsNot Nothing Then
H.Checked = Not H.Checked
H.Render(fGraphics) 'Update cache without repainting all
Invalidate()
End If
End Sub
End Class
Public Class Hexagon
Public ReadOnly Radius, X, Y As Single
Public ReadOnly Points() As PointF
Public Property Checked As Boolean
Public Sub New(Radius As Single, X As Single, Y As Single)
Me.Radius = Radius : Me.X = X : Me.Y = Y
Points = {New PointF((X - Radius), (Y)),
New PointF((X - (Radius / 2)), CSng(Y + ((Radius / 2) * Math.Sqrt(3)))),
New PointF((X + (Radius / 2)), CSng(Y + ((Radius / 2) * Math.Sqrt(3)))),
New PointF((X + Radius), (Y)),
New PointF((X + (Radius / 2)), CSng(Y - ((Radius / 2) * Math.Sqrt(3)))),
New PointF((X - (Radius / 2)), CSng(Y - ((Radius / 2) * Math.Sqrt(3.0!))))}
End Sub
Public Sub Render(G As Graphics)
' Create Hexagon
G.FillPolygon(If(Checked, Brushes.Blue, Brushes.Green), Points)
' Hexagon Outline
For i As Integer = 0 To Points.Length - 1
G.DrawLine(Pens.Black, Points(i), Points((i + 1) Mod Points.Length))
Next
End Sub
Public Function Contains(P As Point) As Boolean
'Do your math here, this is just simplified estimation
Return X - Radius <= P.X AndAlso P.X <= X + Radius AndAlso Y - Radius <= P.Y AndAlso P.Y <= Y + Radius
End Function
End Class
I am making a lunar lander game, and want the spaceship to rotate when the left and right arrow keys are pressed.
I know how to move an image using a picture box and the keydown event, but there isn't anyway to directly rotate a picture box. Do i need to use the image a different way to be able to achieve what I want? Any help is much appreciated.
Make a new class inheriting from picturebox. Use that. You can edit the designer.vb to change the type.
This is pseudocode, untested, so it certainly won't run.
class RotateablePictureBox
inherits picturebox
public property RotationAngle as single
overrides onpaint(e as ...)
e.graphics.rotatetransform(rotationangle)
mybase.onpaint(e)
That's the idea that Hans Passant is talking about (might have to do the DrawImage yourself too and skip the mybase.onpaint - it's done like e.graphics.onpaint(TheImage,dimensions etc...))
This is my first time posting code so let me know how I can improve it for the group. I developed this class using code from http://www.devasp.net/net/articles/display/391.htmlenter code here
I hope this helps. This is the button code
Private Sub btnRotateLeft_Click(sender As Object, e As EventArgs) Handles btnRotateLeft.Click
' IMAGE IS THE NEW OBJECT FROM THE CLASS. PASS THE PICTUREBOX CONTROL(pbItems)
image.RotateLeft(pbItems)
End Sub
This is the class
Imports System.Math
Public Class clsImage
Private wid As Single
Private hgt As Single
Public Function RotateLeft(ByVal picSource As PictureBox) As PictureBox
'ROTATES THE IMAGE LEFT
Dim bm_in = New Bitmap(picSource.Image)
wid = bm_in.Width
hgt = bm_in.Height
Dim corners As Point() = {New Point(0, 0), New Point(wid, 0), New Point(0, hgt), New Point(wid, hgt)}
Dim cx As Single = wid / 2
Dim cy As Single = hgt / 2
Dim i As Long
'ROTATES LEFT
For i = 0 To 3
corners(i).X -= cx
corners(i).Y -= cy
Next i
'THE ROTATION ANGLE IS HARD CODED HERE BUT COULD BE PASS TO THE CLASS
Dim theta As Single = Single.Parse(90) * PI / 180.0
Dim sin_theta As Single = Sin(theta)
Dim cos_theta As Single = Cos(theta)
Dim X As Single
Dim Y As Single
For i = 0 To 3
X = corners(i).X
Y = corners(i).Y
corners(i).X = X * cos_theta + Y * sin_theta
corners(i).Y = -X * sin_theta + Y * cos_theta
Next i
Dim xmin As Single = corners(0).X
Dim ymin As Single = corners(0).Y
For i = 1 To 3
If xmin > corners(i).X Then xmin = corners(i).X
If ymin > corners(i).Y Then ymin = corners(i).Y
Next i
For i = 0 To 3
corners(i).X -= xmin
corners(i).Y -= ymin
Next i
Dim bm_out As New Bitmap(CInt(-2 * xmin), CInt(-2 * ymin))
Dim gr_out As Graphics = Graphics.FromImage(bm_out)
ReDim Preserve corners(2)
gr_out.DrawImage(bm_in, corners)
picSource.Image = bm_out
Return picSource
End Function
Public Function RotateRight(ByVal picSource As PictureBox) As PictureBox
'ROTATES THE IMAGE RIGHT
Dim bm_in = New Bitmap(picSource.Image)
wid = bm_in.Width
hgt = bm_in.Height
Dim corners As Point() = {New Point(0, 0), New Point(wid, 0), New Point(0, hgt), New Point(wid, hgt)}
Dim cx As Single = wid / 2
Dim cy As Single = hgt / 2
Dim i As Long
'ROTATES RIGHT
For i = 0 To 3
corners(i).X -= cx
corners(i).Y -= cy
Next i
'THE ROTATION ANGLE IS HARD CODED HERE BUT COULD BE PASS TO THE CLASS
Dim theta As Single = Single.Parse(-90) * PI / 180.0
Dim sin_theta As Single = Sin(theta)
Dim cos_theta As Single = Cos(theta)
Dim X As Single
Dim Y As Single
For i = 0 To 3
X = corners(i).X
Y = corners(i).Y
corners(i).X = X * cos_theta + Y * sin_theta
corners(i).Y = -X * sin_theta + Y * cos_theta
Next i
Dim xmin As Single = corners(0).X
Dim ymin As Single = corners(0).Y
For i = 1 To 3
If xmin > corners(i).X Then xmin = corners(i).X
If ymin > corners(i).Y Then ymin = corners(i).Y
Next i
For i = 0 To 3
corners(i).X -= xmin
corners(i).Y -= ymin
Next i
Dim bm_out As New Bitmap(CInt(-2 * xmin), CInt(-2 * ymin))
Dim gr_out As Graphics = Graphics.FromImage(bm_out)
ReDim Preserve corners(2)
gr_out.DrawImage(bm_in, corners)
picSource.Image = bm_out
Return picSource
End Function
End Class
Here is my code.
Module Module1
Dim a, x, y As Integer
Public Delegate Sub Areas()
Sub Main()
Dim Square As Areas
Dim Rectangle As Areas
Dim Add As Areas
Dim Area As [Delegate]
Square = New Areas(AddressOf areasquare)
Rectangle = New Areas(AddressOf arearect)
Add = New Areas(AddressOf addition)
Area = [Delegate].Combine(Square, Rectangle, Add)
Area.DynamicInvoke()
Console.WriteLine("the combined areas are equal to " & x * y + a * a)
Console.ReadKey()
End Sub
Class SqareArea
Public Function mult(ByVal a As Integer)
Return a * a
End Function
End Class
Class RectangleArea
Public Function mult(ByVal x As Integer, ByVal y As Integer)
Return x * y
End Function
End Class
Public Sub areasquare()
Dim a As Integer
Dim objSqareArea As New SqareArea()
Console.WriteLine("What is the measurement of one side of the square?")
a = Int32.Parse(Console.ReadLine)
Console.WriteLine("The area of the square is " & objSqareArea.mult(a))
End Sub
Sub arearect()
Dim x, y As Integer
Dim objRectangleArea As New RectangleArea()
Console.WriteLine("What is the length of the rectangle?")
x = Int32.Parse(Console.ReadLine)
Console.WriteLine("What is the width of the rectangle?")
y = Int32.Parse(Console.ReadLine)
Console.WriteLine("The area of the rectangle is " & objRectangleArea.mult(x, y))
End Sub
Public Sub addition()
Console.WriteLine("the combined areas are equal to " & x * y + a * a)
End Sub
End Module
I am multiplying two sets of numbers using variables from the user.
Then I want to take the products of both operations and add them together.
So I want to use the variables from other subs. How would I do that?
Take out
Dim a As Integer
in Public Sub areaSquare()
AND
Dim x, y As Integer
in Sub areaRect().
Module Module1
Dim a, x, y As Integer
Public Delegate Sub Areas()
Sub Main()
Dim Square As Areas
Dim Rectangle As Areas
Dim Add As Areas
Dim Area As [Delegate]
Square = New Areas(AddressOf areasquare)
Rectangle = New Areas(AddressOf arearect)
Add = New Areas(AddressOf addition)
Area = [Delegate].Combine(Square, Rectangle, Add)
Area.DynamicInvoke()
Console.WriteLine("the combined areas are equal to " & x * y + a * a)
Console.ReadKey()
End Sub
Class SqareArea
Public Function mult(ByVal a As Integer)
Return a * a
End Function
End Class
Class RectangleArea
Public Function mult(ByVal x As Integer, ByVal y As Integer)
Return x * y
End Function
End Class
Public Sub areasquare()
Dim objSqareArea As New SqareArea()
Console.WriteLine("What is the measurement of one side of the square?")
a = Int32.Parse(Console.ReadLine)
Console.WriteLine("The area of the square is " & objSqareArea.mult(a))
End Sub
Sub arearect()
Dim objRectangleArea As New RectangleArea()
Console.WriteLine("What is the length of the rectangle?")
x = Int32.Parse(Console.ReadLine)
Console.WriteLine("What is the width of the rectangle?")
y = Int32.Parse(Console.ReadLine)
Console.WriteLine("The area of the rectangle is " & objRectangleArea.mult(x, y))
End Sub
Public Sub addition()
Console.WriteLine("the combined areas are equal to " & x * y + a * a)
End Sub
End Module
You're declaring class level variables, but then diminishing their value during run-time.
My inputs:
Side of square: 5
Length of rectangle: 10
Width of rectangle: 4
Results:
Area of the square is 25
Area of the rectangle is 40
The combined areas are equal to 65
The combined areas are equal to 65
I have a bitmap image in VB.net that I want to print to a Zebra printer, hopefully using the ZPLII code. I have seen the example here: Working with bitmaps to a ZPL label printer with no luck. Can anyone help with this? I have hit my head against the wall for days on this. Thanks in advance!
You can use font downloader utility to store the image in the the printer and then recall it using ZPL:
^XA
^FT60,1750^A0B,42,40^XGE:[image_name].GRF^FS
^PQ1,0,1,Y^XZ
i have a solution
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Text
Class CONVERTBITMAP
''' <summary>
''' Return codeZPL of an bitmap
''' </summary>
''' <param name="BMP2">BITMAP</param>
''' <returns></returns>
Public Shared Function CreateGRF(BMP2 As Bitmap) As String
'Dim bmp2 As Bitmap = Nothing
Dim bmp As Bitmap = Nothing
Dim imgData As BitmapData = Nothing
Dim pixels As Byte()
Dim x As Integer, y As Integer, width As Integer
Dim sb As StringBuilder
Dim ptr As IntPtr
Try
bmp = CONVERTBITMAP.CopyToBpp(BMP2, 1)
imgData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.[ReadOnly], PixelFormat.Format1bppIndexed)
width = Math.Abs(imgData.Stride)
pixels = New Byte(width - 1) {}
sb = New StringBuilder(width * bmp.Height * 2)
ptr = imgData.Scan0
Dim PREVNUM As Integer = 0
For y = 0 To bmp.Height - 1
Marshal.Copy(ptr, pixels, 0, width)
For x = 0 To width - 1
If (x + 1) * 8 > bmp.Width Then
Dim DIF As Integer = ((x + 1) * 8) - bmp.Width
Dim NUM As Integer = (2 ^ (DIF - PREVNUM)) - 1
Dim BYTENOT As Byte = Not (CByte(NUM))
PREVNUM = DIF
If NUM < 255 Then
Dim NOTPX As Byte = Not (pixels(x))
Dim CBYTE2 As Byte = CByte(NUM)
Dim STR As Byte = Format("{0:X2}", NOTPX - CBYTE2)
sb.AppendFormat("{0:X2}", CByte(STR))
Else
sb.AppendFormat("{0:X2}", CByte(0))
End If
Else
sb.AppendFormat("{0:X2}", CByte(Not pixels(x)))
End If
Next
PREVNUM = 0
ptr = ptr.ToInt64 + imgData.Stride 'DirectCast(ptr.ToInt64() + imgData.Stride), IntPtr)
Next
Finally
If bmp IsNot Nothing Then
If imgData IsNot Nothing Then
bmp.UnlockBits(imgData)
End If
bmp.Dispose()
End If
End Try
Return [String].Format("^GFA,{0},{0},{1},", width * y, width) + sb.ToString()
End Function
End Class
then, for use
public function Create_ZPLImage(my_Image As Image) as string
return CONVERTBITMAP.CreateGRF(_Image)
End Sub
work for me