-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CartesianAxis: Improve interval option 'equidistantPreserveStart' (#3768
) <!--- Provide a general summary of your changes in the Title above --> ## Description This PR overhauls the existing interval option `equidistantPreserveStart` In this variant, we always show the first tick, and starting from the first, we find the smallest N, for which all n-th ticks can be shown without collision. A collision is defined as two overlapping ticks, taking into account custom tick formatting, a unit, the fontsize, the angle, et cetera (in alignment with the other existing methods). An overlap is identified if the end of the previous tick overlaps with the start of the next one. Downside of this method: - When the first tick is very long, hardly any other ticks will be shown. - Performance: Instead of iterating over the ticks once, as all other methods do, this method iterates at most M times, M being the total amount of available ticks (i.e. for 1000 datapoints, 1000 times). All other methods are thus more performant. This is a good candidate to discuss in review or to iterate upon. <!--- Describe your changes in detail --> ## Related Issue #3305 <!--- This project only accepts pull requests related to open issues --> <!--- If suggesting a new feature or change, please discuss it in an issue first --> <!--- If fixing a bug, there should be an issue describing it with steps to reproduce --> <!--- Please link to the issue here: --> ## How Has This Been Tested? <!--- Please describe in detail how you tested your changes. --> <!--- Include details of your testing environment, and the tests you ran to --> <!--- see how your change affects other areas of the code, etc. --> ## Screenshots (if appropriate): ## Types of changes <!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: --> - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) ## Checklist: <!--- Go over all the following points, and put an `x` in all the boxes that apply. --> <!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> - [ ] My code follows the code style of this project. - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [ ] I have added tests to cover my changes. - [ ] I have added a storybook story or extended an existing story to show my changes - [ ] All new and existing tests passed. --------- Co-authored-by: “Nikolas <“nikolas@rieble.com“>
- Loading branch information
Nikolas Rieble
and
“Nikolas
committed
Sep 22, 2023
1 parent
9f91761
commit 1a70268
Showing
8 changed files
with
110 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { isVisible } from '../util/TickUtils'; | ||
import { CartesianTickItem } from '../util/types'; | ||
import { getEveryNthWithCondition } from '../util/getEveryNthWithCondition'; | ||
import { Sign } from './getTicks'; | ||
|
||
export function getEquidistantTicks( | ||
sign: Sign, | ||
boundaries: { start: number; end: number }, | ||
getTickSize: (tick: CartesianTickItem, index: number) => number, | ||
ticks: CartesianTickItem[], | ||
minTickGap: number, | ||
): CartesianTickItem[] { | ||
const result = (ticks || []).slice(); | ||
|
||
const { start: initialStart, end } = boundaries; | ||
let index = 0; | ||
// Premature optimisation idea 1: Estimate a lower bound, and start from there. | ||
// For now, start from every tick | ||
let stepsize = 1; | ||
let start = initialStart; | ||
|
||
while (stepsize <= result.length) { | ||
// Given stepsize, evaluate whether every stepsize-th tick can be shown. | ||
// If it can not, then increase the stepsize by 1, and try again. | ||
|
||
const entry = ticks?.[index]; | ||
|
||
// Break condition - If we have evaluate all the ticks, then we are done. | ||
if (entry === undefined) { | ||
return getEveryNthWithCondition(ticks, stepsize); | ||
} | ||
|
||
// Check if the element collides with the next element | ||
const size = getTickSize(entry, index); | ||
|
||
const tickCoord = entry.coordinate; | ||
// We will always show the first tick. | ||
const isShow = index === 0 || isVisible(sign, tickCoord, size, start, end); | ||
|
||
if (!isShow) { | ||
// Start all over with a larger stepsize | ||
index = 0; | ||
start = initialStart; | ||
stepsize += 1; | ||
} | ||
|
||
if (isShow) { | ||
// If it can be shown, update the start | ||
start = tickCoord + sign * (size / 2 + minTickGap); | ||
index += stepsize; | ||
} | ||
} | ||
|
||
return []; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// unit test for getEquidisantTicks | ||
|
||
import { getEquidistantTicks } from '../../src/cartesian/getEquidistantTicks'; | ||
import { CartesianTickItem } from '../../src/util/types'; | ||
|
||
describe('getEquidistantTicks', () => { | ||
// We mock getting the tick width by simply using the value of the tick. | ||
// This makes testing rather easy and intuitive. | ||
const getTickSize = (tick: CartesianTickItem) => { | ||
return tick.value; | ||
}; | ||
|
||
it('should return empty array if no ticks are passed', () => { | ||
const result = getEquidistantTicks(1, { start: 0, end: 100 }, getTickSize, [], 0); | ||
expect(result).toEqual([]); | ||
}); | ||
|
||
test.each([ | ||
// If all ticks fit, we show all ticks | ||
{ ticksThatFit: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], resultingTicks: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] }, | ||
{ ticksThatFit: [0, 1, 2, 3, 4, 5, 6, 7, 8], resultingTicks: [0, 2, 4, 6, 8] }, | ||
{ ticksThatFit: [0, 1, 2, 3, 4, 5, 6, 7], resultingTicks: [0, 5] }, | ||
{ ticksThatFit: [0, 1, 2, 3, 4, 5, 6], resultingTicks: [0, 5] }, | ||
{ ticksThatFit: [0, 1, 2, 3, 4, 5], resultingTicks: [0, 5] }, | ||
{ ticksThatFit: [0, 1, 2, 3, 4], resultingTicks: [0] }, | ||
{ ticksThatFit: [0, 1, 2, 3], resultingTicks: [0] }, | ||
{ ticksThatFit: [0, 1, 2], resultingTicks: [0] }, | ||
{ ticksThatFit: [0, 1], resultingTicks: [0] }, | ||
{ ticksThatFit: [0], resultingTicks: [0] }, | ||
// We always show the first tick, even if it does not fit | ||
{ ticksThatFit: [1, 2, 3, 4, 5, 6, 7, 8, 9], resultingTicks: [0] }, | ||
])('Show only every n-th tick that fits, but always show the first.', ({ ticksThatFit, resultingTicks }) => { | ||
const ticks = [] as CartesianTickItem[]; | ||
for (let index = 0; index < 10; index++) { | ||
ticks.push({ value: ticksThatFit.includes(index) ? 10 : 1000, coordinate: index * 50 }); | ||
} | ||
const result = getEquidistantTicks(1, { start: 0, end: 10 * 50 }, getTickSize, ticks, 0); | ||
expect(result).toEqual(resultingTicks.map(index => ticks[index])); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -234,7 +234,6 @@ describe('getTicks', () => { | |
[ | ||
{ | ||
coordinate: 50, | ||
tickCoord: 50, | ||
value: '10', | ||
}, | ||
], | ||
|
This file was deleted.
Oops, something went wrong.