Documentation / @finchart/core / M4Decimation
Class: M4Decimation<T>
Defined in: packages/core/src/data/decimation.ts:235
픽셀 컬럼마다 first·last·min·max 넷을 고른다.
기본 전략이다. 버킷당 한 점만 남기는 전략(격자·LTTB)은 같은 버킷 안에 위아래 스파이크가 함께 있으면 하나를 반드시 잃는다. M4는 넷을 고르므로 그런 손실이 없다 — 원 논문은 컬럼당 이 넷이면 원본과 픽셀 단위로 같은 선이 나온다는 것을 증명한다 (Jugel et al., VLDB 2014).
그래서 threshold의 4분의 1만큼 버킷을 만든다. 폭 w인 차트에서 컬럼 하나가 버킷 하나가 되려면 threshold가 4w여야 한다 — pointsPerPixel 기본값이 4인 이유다.
버킷은 인덱스가 아니라 화면 위의 자리로 나눈다. 컬럼은 화면 위의 자리이지 배열 위의 자리가 아니다. 점이 한쪽에 몰린 데이터에서 인덱스로 나누면 성긴 쪽이 한 버킷에 뭉쳐 뭉개진다. 화면 위의 자리는 보통 x지만, 봉 번호 좌표계에서는 screenXScan이 되찾아 준다 (D2).
Type Parameters
T
T extends BaseDataPoint = BaseDataPoint
Implements
Constructors
Constructor
new M4Decimation<
T>(coordinates?):M4Decimation<T>
Defined in: packages/core/src/data/decimation.ts:243
기본값은 형제와 같은 {x, y} 접근자다 — 없으면 타입 없는 소비자의 new M4Decimation()이 첫 decimate에서 내부 이름을 누설하는 생 TypeError로 터진다.
Parameters
coordinates?
CoordinateAccessor<T> = ...
Returns
M4Decimation<T>
Methods
decimate()
decimate(
data,range,threshold,screenXScan?,gapFree?):T[]
Defined in: packages/core/src/data/decimation.ts:247
data 전체가 아니라 [range.start, range.end) 창만 솎는다.
창을 배열이 아니라 구간으로 받는 이유: 호출부가 보이는 구간을 slice로 복사하면 큰 데이터에서 매 프레임 큰 배열을 만들어 일부만 쓰고 버린다. 구간이 필수인 이유: 선택이면 구간을 모르는 전략이 전체를 솎아도 타입이 못 잡는다.
screenXScan은 화면 자리 조회의 판을 여는 공장이다(→ Viewport. screenXScan). x로 버킷을 나누는 전략(M4·LTTB)이 화면과 다른 공간에서 맞으려면 그 공간에서 나눠야 한다. 훑기 한 번마다 한 판을 연다 — 커서가 그 판의 것이라 전략끼리·프레임끼리 간섭할 수 없다. 없으면 x가 곧 화면 자리다(연속 좌표계, 기본).
gapFree는 부르는 쪽이 아는 사실이다 — 참이면 이 데이터에 구멍이 없음이 보장되므로 구멍 경계를 찾는 창 스캔을 건너뛴다. 구멍의 유무는 창이 아니라 배열의 성질이라 뷰포트 캐시로는 못 아끼는 값이라, 변경을 소유한 쪽만 증분으로 유지할 수 있다.
gapless와 합치지는 않는다 — 그쪽은 접근자의 정적 사실이고 이것은 배열의 런타임 상태다.
거짓은 "구멍이 있다"가 아니라 "모른다"를 포함한다 — 안전한 쪽이 거짓이다. 참을 잘못 주면 구멍이 삼켜져 선이 없는 값을 가로질러 이어진다.
Parameters
data
T[]
range
threshold
number
screenXScan?
() => (x) => number
gapFree?
boolean
Returns
T[]