awtaylor opened a new issue, #21793:
URL: https://github.com/apache/echarts/issues/21793

   ### What problem does this feature solve?
   
   Smoothed line and area series are easy to misread. With `smooth: true`, the 
constrained Bézier can bow past the samples and invent a peak or a valley that 
is not in the data. `smoothMonotone: 'x'` or `'y'` avoids that overshoot, but 
it does so by making the tangent horizontal or vertical at every sample, so 
each knot looks like a saddle or a plateau. That behavior was an intentional 
tradeoff ([#7158](https://github.com/apache/echarts/issues/7158)). It is still 
surprising on ordinary time series 
([#21532](https://github.com/apache/echarts/issues/21532)): a sensor that rises 
and then levels off is drawn as if it turned over at every measurement.
   
   There is no option today for a curve that passes through the samples, keeps 
a continuous slope, and does not add extrema between samples. That is the usual 
monotone cubic interpolant in scientific tools (MATLAB `pchip`, SciPy 
`PchipInterpolator`, R `splinefun(..., method = "monoH.FC")`). Dashboards and 
monitoring charts are the common case: category or time on one axis, a value on 
the other, including stacked areas.
   
   This could be opt-in. The default smoother, and the existing `'x'`, `'y'`, 
and `'none'` modes, could happily stay as they are.
   
   ### What does the proposed API look like?
   
   Extend `series.line.smoothMonotone` with two values. No new option name, so 
the axis and the algorithm stay in the option that already means "how should 
smoothing respect monotonicity".
   
   ```js
   option = {
       xAxis: {
           type: 'category',
           data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
       },
       yAxis: {},
       series: [{
           type: 'line',
           data: [12, 18, 18, 30, 22, 16, 28],
           smooth: true,
           smoothMonotone: 'monotoneX',
           areaStyle: {}
       }]
   };
   ```
   
   - `monotoneX`: y is a function of x. This is the time-series case in #21532.
   - `monotoneY`: x is a function of y.
   - `'x'`, `'y'`, `'none'`, and the default `null` remain unchanged. In 
particular, `'x'` and `'y'` keep the flat tangents.
   - `smooth: false` still a polyline. In this mode only, `smooth: true` means 
full-strength Hermite tangents. A number is clamped to `(0, 1]` and multiplies 
those tangents, which stays monotone. Numbers above `1` are clamped to `1`. In 
the existing Bézier modes, `smooth: true` would still means tension `0.5`.
   - Stacked areas use the same mode for the baseline. Each series' own 
`smooth` value is the tangent scale for its boundary.
   - Cartesian line series only. On a polar series the value is ignored and the 
current Bézier smooth is used, because the guarantee is about screen x or y and 
would be false after a polar projection.
   - Where the chosen axis is not strictly monotone (a repeated x, or a value 
axis that turns backward), that piece uses the existing non-monotone Bézier. A 
strictly decreasing run is handled, so an inverse axis still works.
   - `connectNulls` keeps its current meaning: nulls break the line, or are 
skipped and the remaining samples are interpolated.
   
   `monotoneX` names the axis. It is not a claim that the curve matches d3 
`curveMonotoneX` (that implementation is Steffen's method). Other names could 
work too e.g., `smoothInterpolation: 'monotone'` if that fits the option style 
better.
   
   ### Method
   
   One cubic Bézier per segment, so the current path, hit testing, and area 
fill stay in place. The knots are the samples. Interior slopes are the 
Fritsch–Butland weighted harmonic mean (1984, 
doi:[10.1137/0905021](https://doi.org/10.1137/0905021), which lies in the 
Fritsch–Carlson monotone region (1980, 
doi:[10.1137/0717021](https://doi.org/10.1137/0717021)). End slopes are the 
one-sided three-point estimate, then clamped into that region ([Moler, 
*Numerical Computing with MATLAB*, 
2004](https://www.mathworks.com/moler/chapters.html)). The code would be 
original, with those citations, and not be a port of SciPy, d3, or Chart.js.
   
   Other monotone or shape-preserving methods were considered and are not 
proposed as extra options. The three local cubic rules below are the same 
feature with different slope formulas; they differ visibly only when 
neighboring secants are very different. Shipping a menu of them would freeze 
that choice in the API. The slope step would be one function, so the formula 
can be swapped in review without an option change.
   
   - [**Steffen (1990)**](https://doi.org/10.4236/apm.2018.81003) is also local 
and monotone. It is d3 `curveMonotoneX` / `curveMonotoneY` and Vega-Lite 
`interpolate: "monotone"`. On equal spacing the slope is held down to the 
smaller neighboring secant, so a sharp turn looks a little tighter than 
Fritsch–Butland. This is the alternative I would switch to if maintainers 
prefer the d3/Vega look.
   - **Arithmetic mean of the secants, then project onto the 1980 disk** is 
what Chart.js uses for `cubicInterpolationMode: 'monotone'`. It is the roundest 
of the three and still monotone. Fritsch–Butland is the direct construction, so 
that projection is only needed at the endpoints.
   - **[Akima (1970)](https://doi.org/10.1145/321607.321609) and modified 
Akima** are local cubics that are not monotone. They can still overshoot.
   - **[Hyman (1983)](https://doi.org/10.1137/0904045) and [Huynh 
(1993)](https://doi.org/10.1137/0730004)** limit the slopes of a global cubic. 
One edited point can move the whole line, which fits shock-capturing better 
than an interactive chart with null breaks and large series. The quintic 
extension is not a cubic Bézier.
   - **[Delbourgo and Gregory's rational 
curves](ttps://bura.brunel.ac.uk/handle/2438/2285), and [Schumaker's 
shape-preserving quadratics](https://www.jstor.org/stable/2157245),** have a 
real tension parameter, and a segment is not one cubic Bézier. ECharts strokes 
with `bezierCurveTo`. Scaling the Fritsch–Butland slopes by `smooth` in `(0, 
1]` is the tension control that stays inside that path model.
   
   The option spelling or the slope formula could be adjusted as the reviewers 
see fit. I would like to implement this and open a pull request that leaves the 
default and the existing `smoothMonotone` values behaviorally unchanged (with 
option docs in `apache/echarts-doc`). I would follow up there once the name is 
settled.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to