问题
I need a way to align tick marks on two separate axis, while being able to control the "step" value (value between tick marks), where both axis start at mark 0 and end on a different maximum value.
Why this problem:
Flot, the JS charting package has an option to align tick marks, but when I do, I cannot control the step value. I can however control the step value directly, but then I lose the ability to align tick marks. I can however revert to defining my own max and step values, to get what I need (aligned tick marks while maintaining desired step value), but I need some help. yielding this question (read on for details).
Example
Let a be maximum value on axis A and b, be maximum value on axis B.
In this example, let a = 30, and b = 82. Let's say I want 6 tick marks (not counting the extra tick mark at end of axis). In reality I guessed at 6 after trying out a few.
Once I have a desired number of tick marks, I can do something like this:
- 30 / 6 = 5 (I just go the needed step value for axis A)
- Now need to figure out tick alignment for axis B
- 82 / 6 = 13.67 (not a good value, I prefer something more rounded)
- move max value of B to 90 , where 90 / 6 = 15 (good - I just got the needed step value for axis B)
End Result
Input:
- a_max = 30, b_max = 82
- (in reality a_max could be 28.5, 29.42, b_max could be 84, 85.345, etc)
Output:
- a_adjusted_max = 30, b_adjusted_max = 90,
- a_step = 5, b_step = 15
- number of ticks = 6 (+1 if count the end)
Visual:
|---------|---------|---------|---------|---------|---------> A
0 5 10 15 20 25 30
|---------|---------|---------|---------|---------|---------> B
0 15 30 45 60 75 90
Summary of "Demands"
- Need
step value
for each axis to be one of 1, 2, 5, 10, 15, 20, 25, 50, 100 (in example was 5 for A, 15 for B) - Need
adjusted max value
for each axis (in example was 30 for A, 90 for B) - Need number of ticks to
match
for both axis - (optional) Number of ticks is flexible but should be anywhere between 4 and 12 as a sweet spot
- adjusted max value is at or greater than original max value, and is located at a "rounded number" (i.e. 90 is prefered over 82 as in my above example)
Problems (Question)
- I need to remove most of the guessing and automate tick mark generation.
- i.e. at first, I Need better way to get number of tick marks because I guessed at number of tick marks I wanted above, because I wanted a good "step" value, which can be something like 1, 2, 5, 10, 15, 20, 25, 50, 100. Max values start at 4, and can go up to 100. In rarer cases go up to 500. In most cases the max values stay between 30-90.
How can I do so?
回答1:
Here's a procedure I came up with. I'm assuming you only want integers.
- choose a number of ticks from 4 to 12
- calculate the number of steps needed for the A and B axes using this number of ticks
- find how much we would have to extend axis A and axis B using these step values; add these numbers together and remember the result
- repeat from the start for the next tick value
- we choose the number of ticks that gives the minimal score; if there is a tie we choose the smaller number of ticks
Here are some example results:
a=30, b=82
gives 4 ticks
0 10 20 30
0 28 56 84
a=8, b=5
gives 6 ticks
0 2 4 6 8 10
0 1 2 3 4 5
Here's the pseudocode:
a = range of A axis
b = range of B axis
tickList[] = {4,5,6,7,8,9,10,11,12}
// calculate the scores for each number of ticks
for i from 0 to length(tickList)-1
ticks = tickList[i]
// find the number of steps we would use for this number of ticks
Astep = ceiling(a/(ticks-1))
Bstep = ceiling(b/(ticks-1))
// how much we would need to extend the A axis
if (a%Astep != 0)
Aextend[i] = Astep - a%Astep
else
Aextend[i] = 0
end
// how much we would need to extend the B axis
if (b%Bstep != 0)
Bextend[i] = Bstep - b%Bstep
else
Bextend[i] = 0
end
// the score is the total extending we would need to do
score[i] = Aextend[i] + Bextend[i]
end
// find the number of ticks that minimizes the score
bestIdx = 0
bestScore = 1000;
for i from 0 to length(tickList);
if (score[i] < bestScore)
bestIdx = i
bestScore = score[i]
end
end
bestTick = tickList[bestIdx]
bestAstep = ceiling(a/(bestTick-1))
bestBstep = ceiling(b/(bestTick-1))
A axis goes from 0
by bestAstep
to bestAstep*bestTick
B axis goes from 0
by bestBstep
to bestBstep*bestTick
来源:https://stackoverflow.com/questions/28285412/how-to-define-matching-axis-notches-from-existing-step-list