Skip to content

fix(line): keep step corners when adjacent points are visually close#21616

Open
JamesGoslings wants to merge 1 commit into
apache:masterfrom
JamesGoslings:fix/21614-line-step-tiny-segment
Open

fix(line): keep step corners when adjacent points are visually close#21616
JamesGoslings wants to merge 1 commit into
apache:masterfrom
JamesGoslings:fix/21614-line-step-tiny-segment

Conversation

@JamesGoslings
Copy link
Copy Markdown

Brief Information

This pull request is in the type of:

  • bug fixing
  • new feature
  • others

What does this PR do?

Stop the line renderer from collapsing step (stair-case) lines into diagonal slopes when adjacent data points are very close on the base axis.

Fixed issues

Details

Before: What was the problem?

drawSegment in src/chart/line/poly.ts drops any segment whose squared pixel distance is < 0.5 as a render-time optimization:

// Ignore tiny segment.
if ((dx * dx + dy * dy) < 0.5) {
    idx += dir;
    continue;
}

For plain polylines this is harmless. For step lines, however, turnPointsIntoStep expands each data segment into an L-shape by inserting an auxiliary corner point. Those corner points encode the stair-case and must all be visited.

When two consecutive data points are very close on the base axis (e.g. [08:59:30, 1] and [09:00:00, 1] reported in #21614), both the corner and one or more intermediate auxiliary points fall under the < 0.5 threshold. They all get skipped, so the renderer goes straight from the previous point to the next far point, drawing a diagonal slope instead of a vertical step.

Reproduction from the issue (CodeSandbox): https://codesandbox.io/p/sandbox/pdh82y?file=%2Findex.js

The reporter also already pinpointed the offending line: src/chart/line/poly.ts:83.

After: How does it behave after the fixing?

A step flag is propagated from LineView through ECPolyline/ECPolygon shapes into drawSegment. In step mode the function now only drops strictly duplicate points (dx === 0 && dy === 0) and keeps every other corner intact:

// Ignore tiny segment.
// In step mode, keep every corner; only drop strict duplicates. See #21614.
if (step) {
    if (dx === 0 && dy === 0) {
        idx += dir;
        continue;
    }
}
else if ((dx * dx + dy * dy) < 0.5) {
    idx += dir;
    continue;
}

Non-step rendering is byte-for-byte identical.

Added a unit test test/ut/spec/series/line-step-poly.test.ts that records the path commands emitted for a step-expanded point set matching the #21614 reproduction and asserts:

  1. Step mode visits the corner before the tail (regression for [Bug] Line chart tiny segments skipped, becoming a slope #21614).
  2. Step mode still collapses strictly duplicated points so the path stays clean.
  3. Non-step mode still applies the < 0.5 tiny-segment optimization.

Verification:

  • Without the fix, the corner-visit assertion fails with the exact bug behavior (corner is missing, only the tail lineTo is emitted).
  • With the fix, the new tests pass.
  • Full unit test suite: Test Suites: 25 passed, 25 total; Tests: 188 passed, 188 total.
  • npm run lint and tsc --noEmit both pass (also enforced by the project's pre-commit hook).

Document Info

One of the following should be checked.

  • This PR doesn't relate to document changes
  • The document should be updated later
  • The document changes have been made in apache/echarts-doc#xxx

Misc

Security Checking

  • This PR uses security-sensitive Web APIs.

ZRender Changes

  • This PR depends on ZRender changes (ecomfe/zrender#xxx).

Related test cases or examples to use the new APIs

N.A.

Merging options

  • Please squash the commits into a single one when merging.

Other information

…lose apache#21614

The drawSegment helper in line/poly.ts drops segments whose squared
pixel distance is below 0.5 as a render-time optimization. For regular
polylines this is harmless, but step lines (produced by
turnPointsIntoStep) rely on every emitted point to define the corners
of the stair-case. When two consecutive data points are very close on
the base axis, the auxiliary corner points fall under the threshold
and get skipped, collapsing the L-shape into a diagonal slope.

Propagate a `step` flag from LineView through ECPolyline/ECPolygon
shapes into drawSegment, and in step mode only drop strictly duplicate
points (dx === 0 && dy === 0). Non-step rendering is unchanged.

Adds a unit test that records the path commands emitted for a step
configuration matching the reproduction in apache#21614 and asserts that the
corner is visited before the tail.
@echarts-bot
Copy link
Copy Markdown

echarts-bot Bot commented May 15, 2026

Thanks for your contribution!
The community will review it ASAP. In the meanwhile, please checkout the coding standard and Wiki about How to make a pull request.

Please DO NOT commit the files in dist, i18n, and ssr/client/dist folders in a non-release pull request. These folders are for release use only.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant