# Dividing a range into major and minor divisions

I'm drawing a graph, and need to annotate the x axis. The x axis is dimensioned in days -- eg, 11/25, 11/26, 11/27... The number of of days on the x axis may range from about 10 to perhaps 100 or more, depending on circumstances. This is all displayed on a smartphone in portrait orientation, so the x axis is fairly short.

To annotate the x axis I'd like to draw "major tick marks" (short vertical lines) at intervals and label them with, eg, "11/26" (for today, Nov 26). There is room along the x axis, with a given font size, to fit in up to 7 date labels.

Between the "major tick marks" I'd like to insert multiple (though possibly zero) "minor tick marks". (These are even shorter vertical with no label.) Obviously, there should be an integral number of "minor tick marks" between the "major" ones, and each minor mark should denote some integral multiple of days. Along the axis there is room for about 50 "minor tick marks" before they start getting too crowded.

So how do I calculate, given a number of days to be covered, the greatest number of major and minor tick marks (ie, smallest space between) that will satisfy the criteria? Eg, when I applied the two criteria separately for one set of dates I came up with 13 days between major marks and 3 days between minor ones, and that doesn't really work. The closest reasonable numbers would appear to be 15 and 5, but how do I create an algorithm that arrives at that, without having to repeatedly calculate prime factors or some such?

(Note that absolute optimality (if that can even be defined) is not required here -- just a good, stable approximation that can be reliably implemented with simple (testable) code.)

-

Here's a thought.

1. precalculate a list which contains the various numbers of minor tick marks you'll allow, and the corresponding numbers of major tick marks. Then you could just list all the multiples of $4, 5, 6$ and $7$ which are between $25$ and $50$, with the largest number in the set {4, 5, 6, 7} which divides them. For definiteness lets say that you want to have between 25 and 50 minor tick marks and between $4$ and $7$ major ones, giving the list

$(25, 5), (28, 7), (30, 6), (32, 4), (35, 7), (36, 6), (40, 5), (42, 7), (44, 4), (45, 5), (48, 6), (49, 7), (50, 5)$

This says, for example, that if you have 40 minor tick marks you will have 5 major tick marks.

1. Let the number of days between the earliest and latest dates in your data set be $n$. You probably don't want data all the way up to the edge of the screen, so say that you want the length of the $x$ axis to be between perhaps $N_1 = 1.1n$ and $N_2 = 1.2n$. (The parameters $1.1$ and $1.2$ are arbitrary, but if you make them too close together this won't work.)

2. for a given value of $n$, look in the intervals $[N_1, N_2], [N_1/2, N_2/2], [N_1/3, N_2/3], ...$ for an allowable number of minor tick marks. The corresponding number of major tick marks then comes from the list in 1; the distance between minor tick marks is the denominator that you used.

For example, say $n = 100$. Then we want the length of the x-axis to be between 110 and 120. The intervals $[110/1, 120/1]$ and $[110/2, 120/2] = [55, 60]$ don't contain any allowable numbers of minor tick marks. But $[110/3, 120/3] = [36.66\ldots, 40]$ does (see the list above); in particular you want to have 40 minor tick marks and 5 major tick marks, and the spacing between minor tick marks is 3.

For another example, say $n = 365$. Then we have to work our way down to $[365 \times 1.1/9, 365 \times 1.2/9] = [44.61, 48.67]$ to get into the allowable range; you'll either have 45 minor (5 major) tick marks or 48 minor (6 major) tick marks, with spacing 9.

Finally, you could just precompute all the results - just have stored in a table that if $n = 100$ you'll have 40 minor tick marks at spacing 3 and 5 major tick marks, and similarly for each $n$ you expect to see.

-
I'll have to think about this one. I like the idea that, since everything is precomputed, it's inherently stable and testable. – Daniel R Hicks Nov 27 '12 at 4:12
I tried the scheme on for size and it works pretty well, thanks. It hadn't occurred to me that the number of variations was small enough to practically enumerate, and with this scheme certain "unpleasing" combos can be eliminated if desired, just by altering the table. – Daniel R Hicks Nov 27 '12 at 18:05
You're welcome! Glad to hear it works - I was pretty much just thinking out loud and didn't do any testing, so I could have said something stupid. – Michael Lugo Nov 27 '12 at 20:45