views:

163

answers:

2

hello

i am creating a timeline where i want to paint the ticks at a certain timestep.

so depending on the available width i want to paint as much ticks as possible. but they should not be too close together. they should stay at least a certain number of pixels apart.

so when you zoom in the ticks obviously move apart, but at a certain threshold there will be appearing new ticks between the old ones as soon as the limit allows for new ones to paint.

so how can i find the space between the ticks depending on zoom and width?

thanks!

+1  A: 

This is a bit messy, but it's simple and it works well:

First decide what intervals should be allowed between ticks. Because of the craziness of the time system (base 10? base 60? how long is a month?) there is no particulatly good algorithm to generate this list - just pick natural intervals that people are familiar with and hardcode it into your program:

...etc...
every 0.1 second
every 1 second
every 5 seconds
every 15 seconds
every 1 minute
every 5 minutes
every 15 minutes
every 1 hours
every 2 hours
every 4 hours
every 8 hours
every day, midnight
every 7 days, midnight
every month start
every quarter start
every year start
every 10 years
...etc...

Then given a specific axis width, and a specific time interval to display, simply iterate over your list calculating how many ticks it would produce and how close the ticks would be in pixels would be if you used that scale. This calculation be done using simple division. Choose the scale with the largest number of ticks with the condition that the ticks don't get too close. This naive algorithm should give perfectly adequate performance, but you could use a binary search rather than iterating over the whole list if you wish to optimize it (probably not worth the effort though).

It's a bit annoying, but I don't know of a better way unless you can find some library that will do this for you. I don't know of any library that offers this function, but there must be tons of open source projects that do something similar that you could grab code from if you don't want to write this yourself.

Mark Byers
thanks for your answer! well the time is abstract, not related to seconds, minutes, etc. so the base should be 10.
clamp
Then you can just start with 1 time unit, and see how many ticks you get (numberOfTicks = total time / 1) and how close they are (distanceBetweenTicks = pixelsOnXAxis / numberOfTicks). If distanceBetweenTicks < threshold, timeunit *=10. If distanceBetweenTicks > threshold, timeunit /=10. Until you get the closest you can to threshold, then stop.
Mark Byers
Sorry about the formatting. Was my answer unclear?
Mark Byers
thanks for the effort of your answer! i believe it would work, but to be honest i dont like the naive approach by just looking for a fitting stepsize by just iterating over the options. i was expecting there would be some kind of formula like stepsize = fucntion(width, zoom)
clamp
+2  A: 

After my first answer your clarified your specifications and the problem turned out to be simpler than I expected. You also wanted a simpler solution than the general solution I provided earlier. Rather than editing my original comment, I'd rather create a new comment because this is a completely different approach.

First define the interesting variables:

minimumPixelsBetweenTicks = 5
axisWidthPixels = 400
axisRangeTime = 1000.0         # = axisMaximumTime - axisMinimumTime
tickSeparationTime = 10 ** e   # e is an unknown integer that we must find

Then you can calculate e directly using the following formula (you didn't specify language, so I'm using Python):

e = int(math.ceil(math.log(minimumPixelsBetweenTicks * axisRange / axisWidthPixels, 10)))
Mark Byers