Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions resources/BaseComponents/SwiftValueAxis.qml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,46 @@ ValueAxis {
labelsColor: Constants.commonChart.labelsColor
titleFont: Constants.commonChart.axisTitleFont
labelsFont: Constants.commonChart.axisLabelsFont

// A function that returns the best tick interval for the
// plot to have ticks that land on round numbers
// --
// adapted from
// https://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks
function getGoodTickInterval(): real {
const ticksRange = (max - min) / (tickCount - 1);
const exponent = Math.floor(Math.log10(ticksRange));
const fraction = ticksRange / Math.pow(10, exponent);
var niceFraction = 10;
if (fraction < 1.5) {
niceFraction = 1;
} else if (fraction < 3) {
niceFraction = 2;
} else if (fraction < 7) {
niceFraction = 5;
}
return niceFraction * Math.pow(10, exponent);
}

// A function that can be used to get that good tick spacing.
// --
// WARNING! if the tickType is dynamic, and you drastically change
// the size of the plot via zooming or plotting a new series, it is
// NOT ENOUGH to have the getGoodTicks function on the onRangeChanged
// slot of the ValueAxis to avoid your plot trying to render thousands
// of tick lines. I think there may be a way around that, but instead
// what I chose to do is manually call the freezeTicks function below before
// the big change in range, and then calling the setGoodTicks() function
// after.
function setGoodTicks(tickSpacing: real) {
tickAnchor = Math.ceil(min / tickSpacing) * tickSpacing;
tickInterval = tickSpacing;
tickType = ValueAxis.TicksDynamic;
}

// Kind of a throwaway function, but it is used whenever you
// need to make sure you won't render too many ticks.
function freezeTicks() {
tickType = ValueAxis.TicksFixed;
}
}
59 changes: 52 additions & 7 deletions resources/SolutionTabComponents/SolutionPositionTab.qml
Original file line number Diff line number Diff line change
Expand Up @@ -191,29 +191,67 @@ Item {
ChartView {
id: solutionPositionChart

function freezeTicks() {
// fix the interval so tick number will not be too large.
solutionPositionXAxis.freezeTicks();
solutionPositionYAxis.freezeTicks();
}

// This function make the ticks on the x & y axes have the
// same interval, and have them land on evenish numbers.
// It also ensures the ranges of the two axes are the same.
function setTicks() {
const x_tick_interval = solutionPositionXAxis.getGoodTickInterval();
const y_tick_interval = solutionPositionYAxis.getGoodTickInterval();
const max_tick_interval = Math.max(x_tick_interval, y_tick_interval);
const x_range = Math.abs(solutionPositionXAxis.max - solutionPositionXAxis.min);
const y_range = Math.abs(solutionPositionYAxis.max - solutionPositionYAxis.min);
const range_diff = Math.abs(x_range - y_range);
if (x_range < y_range) {
solutionPositionXAxis.min -= range_diff / 2;
solutionPositionXAxis.max += range_diff / 2;
} else {
solutionPositionYAxis.min -= range_diff / 2;
solutionPositionYAxis.max += range_diff / 2;
}
solutionPositionXAxis.setGoodTicks(max_tick_interval);
solutionPositionYAxis.setGoodTicks(max_tick_interval);
}

function resetChartZoom() {
solutionPositionChart.freezeTicks();
// update the chart lims
solutionPositionChart.zoomReset();
solutionPositionXAxis.max = orig_lon_max;
solutionPositionXAxis.min = orig_lon_min;
solutionPositionYAxis.max = orig_lat_max;
solutionPositionYAxis.min = orig_lat_min;
// update ticks
solutionPositionChart.setTicks();
}

function centerToSolution() {
solutionPositionChart.freezeTicks();
// update chart lims
solutionPositionChart.zoomReset();
if (cur_scatters.length) {
solutionPositionXAxis.max = cur_solution.x + x_axis_half;
solutionPositionXAxis.min = cur_solution.x - x_axis_half;
solutionPositionYAxis.max = cur_solution.y + y_axis_half;
solutionPositionYAxis.min = cur_solution.y - y_axis_half;
}
// update ticks
solutionPositionChart.setTicks();
}

function chartZoomByDirection(delta) {
if (delta > 0)
solutionPositionChart.freezeTicks();
if (delta > 0) {
solutionPositionChart.zoom(Constants.commonChart.zoomInMult);
else
} else {
solutionPositionChart.zoom(Constants.commonChart.zoomOutMult);
}
solutionPositionChart.setTicks();
}

function stopZoomFeatures() {
Expand Down Expand Up @@ -293,12 +331,14 @@ Item {
id: solutionPositionXAxis

titleText: Constants.solutionPosition.xAxisTitleText + " (" + available_units[solutionPositionSelectedUnit.currentIndex] + ")"
tickType: ValueAxis.TicksDynamic
}

SwiftValueAxis {
id: solutionPositionYAxis

titleText: Constants.solutionPosition.yAxisTitleText + " (" + available_units[solutionPositionSelectedUnit.currentIndex] + ")"
tickType: ValueAxis.TicksDynamic
}

MouseArea {
Expand Down Expand Up @@ -357,15 +397,19 @@ Item {
running: true
repeat: true
onTriggered: {
if (!solutionPositionTab.visible)
if (!solutionPositionTab.visible) {
return;
}
solution_position_model.fill_console_points(solutionPositionPoints);
if (!solutionPositionPoints.points.length)
if (!solutionPositionPoints.points.length) {
return;
if (available_units != solutionPositionPoints.available_units)
}
if (available_units != solutionPositionPoints.available_units) {
available_units = solutionPositionPoints.available_units;
if (!line || !scatters.length || !cur_scatters.length)
}
if (!line || !scatters.length || !cur_scatters.length) {
[scatters, cur_scatters, line] = SolutionPlotLoop.setupScatterSeries(solutionPositionChart, Constants, Globals, solutionPositionXAxis, solutionPositionYAxis, Constants.solutionPosition.legendLabels, Constants.solutionPosition.colors, false, true);
}
var combined = [line, scatters, cur_scatters];
solutionPositionPoints.fill_series(combined);
let point = SolutionPlotLoop.getCurSolution(solutionPositionPoints.cur_points);
Expand Down Expand Up @@ -405,8 +449,9 @@ Item {
orig_lat_max = new_lat_max;
orig_lon_min = new_lon_min;
orig_lon_max = new_lon_max;
if (zoom_all)
if (zoom_all) {
solutionPositionChart.resetChartZoom();
}
}
}
}
Expand Down