Layered Pictureboxes
Layered Pictureboxes
Layered Pictureboxes
Layered Pictureboxes
Layered Pictureboxes
Layered Pictureboxes Layered Pictureboxes Layered Pictureboxes Layered Pictureboxes Layered Pictureboxes Layered Pictureboxes Layered Pictureboxes Layered Pictureboxes
Layered Pictureboxes Layered Pictureboxes
Layered Pictureboxes
Go Back  Xtreme Visual Basic Talk > > > Layered Pictureboxes


Reply
 
Thread Tools Display Modes
  #21  
Old 07-24-2013, 09:19 AM
passel's Avatar
passelLayered Pictureboxes passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 8,026
Default


I was holding off responding until I could look at things in detail, but because I'm pretty busy I guess I'll just post some observations of things that jump out at me.
First, you're passing variable "tdy" to trig functions, but tdy is defined as an Integer.
I can think of no reason for ever passing an Integer to a trig function.
Trig functions, at least those which expect angles, e.g. Sin and Cos, expect the angle to be passed in units of Radian.

Then looking up where tdy is calculated I see:
tdy = (360 / 365.25) * (dat.DayOfYear + dat.Hour) / 24

It doesn't seem likely that you would want to divide the DayOfYear by 24.
(360/265.25) would give you degrees per day over the period of one year.
So you would want to mutiply that value by Days to get degrees.
So Days would be DayOfYear + HourOfDay/HoursPerDay, so the equation should be
tdy = (360/365.25) * (dat.DayOfYear + dat.Hour/24)

And then on the same line, or the next (all above assuming you made tdy a Single or Double) you would convert the tdy value from degrees to Radians before using it in the remaining lines, i.e.
tdy *= (Math.PI / 180) 'for instance

Back in the VB6 version you posted I noticed a couple of things, one which is an error, the other just useless code.
First, the useless code (which is in two places, at least).
Code:
'
        .ScaleLeft = X1
        .ScaleTop = X1
        .ScaleWidth = dia * 2
        .ScaleHeight = dia * 2
        Picture1.Scale (X1, dia)-(dia, X1)
The Picture1.Scale function sets the values for .ScaleLeft, .ScaleTop, .ScaleWidth and .ScaleHeight, so the four lines that set those values before calling the Scale function are pointless as the Scale function replaces them.

Second, observe the following code from Sub positionMarker.
Code:
'
    If Val(Latitude) > 0 Then
        Marker.Top = (Yscale * 90) - HalfMarkerWidth - (Val(Latitude) * Yscale)
    Else
        Marker.Top = (Yscale * 90) - HalfMarkerWidth + (-Val(Latitude) * Yscale)
    End If
"- (Val(Latitude) * Yscale)" and "+ (-Val(Latitude) * Yscale)" will give you the same value.
minus a postive, or plus a negative.
All the locators would end up in the +,+ quandrant, eg. a locator in Syracuse would end up around India.
That's it for now.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 07-24-2013 at 10:14 AM.
Reply With Quote
  #22  
Old 07-26-2013, 11:30 PM
n2amg n2amg is offline
Junior Contributor
 
Join Date: Aug 2001
Posts: 279
Default

The formula I am using there was from a website I had found for computing the declination of the sun. The VB6 application I did not write. That was written by another member of the team that is no longer on the team. I have taken over his spot.

Looking at the way the terminator is drawn it looks pretty close to correct. But I do have some tweeking to do.

I have never been a graphics person so this is why I am a bit laxed in this area. But the part that is gotten me bugged is taking this part of the code.
Code:
       For i = -180 To 180
            yy = computeLat(i, dec)
            yy1 = computeLat(i + 1, dec)
            g.DrawLine(shadepen, xL + X + i, y0 - yy, xL + X + i + 1, y0 - yy1)
            g.DrawLine(shadepen, xL + X + i, y0 - yy, xL + X + i, y0 + F * PictureBox1.Height - 2)  
        Next
and converting it to scale to the size of the picturebox. right now if the image is 360x180 the size and such if perfect. But if you resize the picturebox then things get out of whack.

Rick
Reply With Quote
  #23  
Old 07-28-2013, 08:15 PM
n2amg n2amg is offline
Junior Contributor
 
Join Date: Aug 2001
Posts: 279
Default

Ok I finally have the scale issues worked out. Don't know why I have such a problem when it was actually fairly easy.

One last question..
In the image that is attached see the shaded part. What would be the best way to draw it so that there are no lines?

Right now I use:
Code:
Dim shadePen As New Pen(Color.FromArgb(70, 180, 180, 180), 1)
then to draw the terminator:
Code:
 g.DrawLine(terminatorpen, x0 + CInt(CDbl(i) * xscale), y1, x0 + CInt(CDbl(i + 1) * xscale), y2)
And then this to do the shading:
Code:
g.DrawLine(shadePen, x0 + CInt(CDbl(i) * xscale), y1, x0 + CInt(CDbl(i + 1) * xscale), PictureBox1.Height)
Is there something different I can do??

TIA Rick
Attached Images
File Type: jpg Clipboard07.jpg (43.8 KB, 14 views)
Reply With Quote
  #24  
Old 07-28-2013, 10:08 PM
passel's Avatar
passelLayered Pictureboxes passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 8,026
Default

You don't show how xscale is calculated or what "i" is indexing through, but I'll assume that xscale is a factor representing pixels per degree and i is indexing through degrees.
So, as you expand your scale, you get gaps between the lines since you have more than 1 degree per pixel.
Since you are using a pen with reduced alpha, widening the pen so that lines overlap to fill the gap won't be easy to accomplish because the overlap will be a different color (the sum of the two alphas will make the overlap darker than the non-overlap areas) so you'll end up with a different type of line artifacts in the drawing.
Ideally, instead of looping by degree, you would want to loop by pixel so that you fill each adjacent vertical line of pixels.
So, reverse your scale factor to be degrees per pixel, and start with pixel 0 to the width of your screen, stepping by one, calculate the terminator spot (convert the pixel to degrees), and draw your vertical line.

I wish I had more time to play around with this. If I were doing it I think I would take a different approach.
The shape of the terminator on any given day is not going to change significantly.
I would use the size of your map as the base size of a bitmap that I would create to draw the terminator in. So, in your case you have a 667x667 pixel map and I would create a corresponding bitmap of 667x667 pixels and calculate the terminator at noon Greenwich and draw it in the bitmap. I would also draw the Sun on that bitmap, Longitude would be 0, Latitude would be base on the declination. I would then create a texturebrush from that bitmap.
Now when you needed to draw the terminator on the map, all you would need to do is use the texturebrush to fill the rectangle (667x667) of your map.
But, before you filled the rectangle, you would offset the brush (TranslateTransform) by the Sun's Longitude. You wouldn't have to worry about offsetting by declination since you already took that into consideration when you created the bitmap and the declination isn't going to change over the period of a day to move the terminator vertically or change its shape enough to be seen on the image.
But since I haven't the time at the moment, I don't expect you to try to tackle that on your own. It probably doesn't seem like it from the description, but using a texturebrush for this particular application can actually make things much easier, and definitely quicker.

But, go ahead and try the first option, which is to change your loop to loop through all the pixels horizontally and draw the vertical lines based on the calculated degree offset, rather than the other way around.

p.s. While I don't have the time to create a specific example that implements drawing a terminator, It only takes a few minutes to modify my previous example to show the texturebrush in action.
I added a declaration for a texturebrush, named tb.
I changed the left button drawing to also do the drawing (lessened alpha pen with a width of 10) that the right button used to do.
When the leftbutton is released, the texturebrush, tb, is modified to use the overlay bitmap as its texture.
If you drag back and forth using the right mouse button, then the texturebrush is offset in the direction you move the mouse so it appears to scroll back and forth.
I suggest you trace the grayline with the left button, then drag back and forth with the right. You should see the other advantage to using a texture brush for this particular application. It will automatically wrap the image, which is what you need in this case. You only need to calculate the terminator once, and in a fixed position to make the calculation simpler, i.e. at 0 longitude, and then over the course of the day you only need to calculate the sun's current longitude and not care about the latitude.
Very quick and simple.


p.p.s. The above reminds me, in your current program, assuming it still looks like it did, for the most part, last week, could use another change to do things more along the way they should be done in .Net.
I would change the paintTerm subroutine to except a graphics object as a parameter, like so:
Code:
'
  Public Sub paintTerm(ByVal g As Graphics)
    ' PictureBox1.Refresh()
    ' Dim g = PictureBox1.CreateGraphics
    Dim datestr As Integer
    Dim x0 As Integer = PictureBox1.Width / 2 '180
   '....
This you would add code to the PictureBox1_Paint sub (a Paint event handler) to call your paintTerm sub like so:
Code:
'
  Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
    paintTerm(e.Graphics)
  End Sub
Then everywhere else where you call paintTerm directly, you would replace with PictureBox1.Invalidate().
e.g. in the Form1_ResizeEnd event handler:
Code:
  Private Sub Form1_ResizeEnd(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ResizeEnd
    ' DrawHomeCoords(homeLat, homeLon)
    PlotSpots()
    ComputeSun()
    PictureBox1.Invalidate()  ' paintTerm()
  End Sub
That will clear up some of the other anomalies you mentioned with when the drawing appeared. You should almost always do your drawing as part of the paint event of a control, rather than use <control>.CreateGraphics to draw on the screen area of the control outside of the paint event.
The picturebox in particular is designed by default to be double buffered so if you do your drawing in the Paint event all the drawing will be done in a back buffer and the final result displayed on the screen in one update (no flashing).
If you use .CreateGraphics to draw outside the paint event, you loose that double buffering and see flashing as the picturebox image is Refreshed (because you called it), and then your drawing is drawn "on top" and visible to the user as you draw.
Attached Files
File Type: zip AutoStretchExample2.zip (157.3 KB, 4 views)
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 07-28-2013 at 11:06 PM. Reason: Add TextureBrush example
Reply With Quote
  #25  
Old 07-30-2013, 07:14 PM
passel's Avatar
passelLayered Pictureboxes passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 8,026
Default

Don't like to double post, but I did play with the .Net version of your code about 9 days ago. I went back to that version and went ahead and added the loop from 0 to Width instead of -180 to 180, which I mentioned in the last post as a least effort fix for the existing code.
After that was put in, when the form was resized, it was quite obvious that the grayline was quite jagged. You used integers for a lot of the values, such as Sunlat and SunLon and your computeLat function also return Integer degrees, and you used Math.Round a lot of places to round to Integers. If you want to scale smoothly, you need to use floating point values for your various coordinates and angles so that you can plot in less than 1 degree increments.
So, I made those changes as well, and since I won't be on this machine later, I might as well attach the resulting project here, otherwise it will just sit around in the Virtual machine I did the changes in. This was done earlier on, so the refreshing is done a bit differently than I described in the earlier post. In this case, I had moved the drawing code out of the paintTerm sub and put it in the Paint event sub. Then the paintTerm sub just became the single call to PictureBox1.Refresh(), which was already in there.
But, I really prefer doing it the other way. Keeping the drawing code in its own sub and having the Paint event call that sub passing the graphics object to the drawing routine. That way, it is easy to call the same routine to draw the output to any graphics object, such as a printer, or a bitmap, or another control, etc.
Attached Files
File Type: zip vbnetGrayline.zip (738.5 KB, 4 views)
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
Layered Pictureboxes
Layered Pictureboxes
Layered Pictureboxes Layered Pictureboxes
Layered Pictureboxes
Layered Pictureboxes
Layered Pictureboxes Layered Pictureboxes Layered Pictureboxes Layered Pictureboxes Layered Pictureboxes Layered Pictureboxes Layered Pictureboxes
Layered Pictureboxes
Layered Pictureboxes
 
Layered Pictureboxes
Layered Pictureboxes
 
-->