Quantcast
Channel: VBForums
Viewing all articles
Browse latest Browse all 15431

Cylinder projection to 2D globe

$
0
0
This belongs in Games and Graphics but it seems that posting rates are so low nobody goes there. But a mod could always move this too.


I was curious as a non-graphics programmer how people do things like spin a globe without carrying around pretty massive amounts of image data (individual frames).

I noticed that flat rectangular "cylindrical projection" images are often used, but I wasn't sure how.

Here is a hack that came to me:

Code:

Option Explicit

'Obviously for a real program you'd replace these VB6 drawing methods with the underlying
'GDI calls, e.g. StretchBlt() and friends.  But this is just a test of concept.  I was
'trying out an idea to see how close it got me to the desired result.
'
'Basic concept here:
'
'  StretchBlt lines pole to pole, narrowing toward each pole of the sphere.

Private OrigSourceWidthPixels As Single
Private SourceCopyWidth As Single
Private OnePixel As Single
Private Center As Single
Private Radius As Single
Private OffsetPixels As Long

Private Sub PaintGlobe()
    Dim Offset As Single
    Dim ScanLine As Single
    Dim Distance As Single
    Dim Chord As Single

    If OffsetPixels > OrigSourceWidthPixels Then
        OffsetPixels = OffsetPixels - OrigSourceWidthPixels
    End If
    With picDest
        Offset = .ScaleX(OffsetPixels, vbPixels)
        For ScanLine = 0 To .ScaleHeight - OnePixel Step OnePixel
            Distance = Abs(Center - ScanLine)
            Chord = 2 * Sqr(Radius * Radius - Distance * Distance)
            picDest.PaintPicture picSource.Picture, _
                                (.ScaleWidth - Chord) / 2, _
                                ScanLine, _
                                Chord, _
                                OnePixel, _
                                Offset, _
                                ScanLine, _
                                SourceCopyWidth, _
                                OnePixel
        Next
    End With
End Sub

Private Sub Form_Load()
    Dim OrigSourceWidth As Single
   
    'Enlarge by half, copying the left "half" to the new "third" of the image.  We use
    'this to "wrap around" the globe:
    With picSource
        OrigSourceWidth = .ScaleWidth
        .Width = ScaleX(OrigSourceWidth * 1.5, .ScaleMode)
        .AutoRedraw = True
        .PaintPicture .Picture, _
                      OrigSourceWidth, _
                      0, _
                      OrigSourceWidth / 2, _
                      .ScaleHeight, _
                      0, _
                      0, _
                      OrigSourceWidth / 2
        .AutoRedraw = False
        Set .Picture = .Image
    End With
    With picDest
        OrigSourceWidthPixels = .ScaleX(OrigSourceWidth, picSource.ScaleMode, vbPixels)
        SourceCopyWidth = .ScaleX(OrigSourceWidth / 2, picSource.ScaleMode)
        OnePixel = .ScaleX(1, vbPixels)
        Center = (.ScaleHeight - OnePixel) / 2
        Radius = .ScaleHeight / 2
    End With
    PaintGlobe
    Timer1.Enabled = True
End Sub

Private Sub Timer1_Timer()
    OffsetPixels = OffsetPixels + 2
    PaintGlobe
End Sub

This uses a ton of CPU and it probably isn't "correct" because the compression as we approach each pole probably shouldn't be linear across each scanline. But is this sort of technique considered "good enough" for most non-cartographic purposes?

Is there a better, maybe even more obvious technique without using 3D graphics libraries?

Or if "good enough" is there a better approach (coordinate transforms?) that isn't as expensive as painting line by line?

Name:  sshot.png
Views: 53
Size:  9.0 KB
Attached Images
 
Attached Files

Viewing all articles
Browse latest Browse all 15431

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>