fix(study): 강한 압력 즉시 반응 — 3단계 threshold + dynamic range 확장 + thinning 키움
사용자 보고: 빡세게 눌러도 굵기 차이 거의 안 남. 원인 분석: 1. raw pressure 0.1~0.99 만 활용했는데 dynamic range 그대로 → 변동 작음. 2. 속도 기반 변동 폭 0.3~1.0 작음 + dist/25 비율 작음. 3. INTENT alpha 0.25 너무 느림 → 강한 변화도 stroke 내내 못 따라감. 4. thinning 0.4 변동 폭 부족. Fix: - raw pressure 0.1~0.99 → 0.3~1.0 으로 매핑. dynamic range 확장. - 속도 기반 0.25~1.0 + 비율 dist/18. 변동 폭 키움. - 3단계 threshold: · dev < 0.15 (잡음) → alpha 0.03 (fixed 유지) · 0.15 ≤ dev < 0.3 (의도적) → alpha 0.5 (이전 0.25 → 빠르게 따라감) · dev ≥ 0.3 (매우 큼, 빡세게 누름) → 즉시 update (alpha 1.0) - thinning 0.4 → 0.5. 폭 변동 더 명확. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -218,9 +218,8 @@
|
||||
if (!path) {
|
||||
const outline = getStroke(pts, {
|
||||
size,
|
||||
// thinning 0.4 — fixedPressure 가 평소 잡음을 흡수하므로 변동 폭 키워도 안정.
|
||||
// 의도적 큰 압력 변화 시만 굵기 변화 명확히 보임.
|
||||
thinning: 0.4,
|
||||
// thinning 0.5 — 큰 압력 변화 시 굵기 차이 명확. fixedPressure 가 잡음 흡수.
|
||||
thinning: 0.5,
|
||||
smoothing: 0.99,
|
||||
streamline: 0.75,
|
||||
// simulatePressure: false — getStrokePressure 가 raw pressure / 속도 추정 /
|
||||
@@ -350,35 +349,41 @@
|
||||
// 부드러운 곡선 생성 → 보간 점 적게 둘 수록 일정 간격 vertex 패턴 (= 사용자
|
||||
// 보고 "선 사이사이 마디") 안 발생. 단 30px+ gap 은 보간으로 점선 방지.
|
||||
const MAX_GAP_PX = 16;
|
||||
// Smart pressure — fixed 유지 (잡음/평소) + 의도적 큰 변화 시 따라감.
|
||||
// 사용자 시나리오:
|
||||
// - Pencil 정상 + 평소 압력 → fixed 유지 (Notability felt: stroke 내부 균일)
|
||||
// - Pencil 정상 + 의도적 압력 변화 → 따라감 (굵기 변화)
|
||||
// - Pencil 비정상 / mouse → raw pressure 가 0 또는 일정 → 속도 기반 추정.
|
||||
const FIXED_THRESHOLD = 0.15; // 변동 < 15% 잡음, ≥ 15% 의도적
|
||||
// Smart pressure — 3단계 threshold.
|
||||
// 잡음 (dev < 15%) → alpha 0.03 (거의 무시, fixed 유지)
|
||||
// 의도적 (15% ≤ dev < 30%) → alpha 0.5 (빠르게 따라감)
|
||||
// 매우 큼 (dev ≥ 30%) → 즉시 update (사용자 빡세게 누름 같은 큰 변화)
|
||||
const FIXED_THRESHOLD = 0.15;
|
||||
const FIXED_LARGE = 0.3;
|
||||
const FIXED_ALPHA_NOISE = 0.03;
|
||||
const FIXED_ALPHA_INTENT = 0.25;
|
||||
const FIXED_ALPHA_INTENT = 0.5;
|
||||
function getStrokePressure(target: Stroke, x: number, y: number, rawPressure: number): number {
|
||||
// 1. inputP 결정 — raw pressure 정상이면 그것, 비정상이면 속도 기반.
|
||||
// 1. inputP 결정.
|
||||
let inputP: number;
|
||||
if (Number.isFinite(rawPressure) && rawPressure > 0.05 && rawPressure < 0.99) {
|
||||
inputP = rawPressure;
|
||||
if (Number.isFinite(rawPressure) && rawPressure > 0.1 && rawPressure < 0.99) {
|
||||
// raw pressure 활용 — 0.1~0.99 → 0.3~1.0 으로 dynamic range 확장.
|
||||
inputP = 0.3 + ((rawPressure - 0.1) / 0.89) * 0.7;
|
||||
} else {
|
||||
// 속도 기반. 변동 폭 0.25~1.0 (이전 0.3~1.0 보다 넓음).
|
||||
const last = target.points[target.points.length - 1];
|
||||
if (last) {
|
||||
const dist = Math.hypot(x - last[0], y - last[1]);
|
||||
// 빠른 (큰 dist) = 약함, 느린 (작은 dist) = 강함.
|
||||
inputP = Math.max(0.3, Math.min(1.0, 1.5 - dist / 25));
|
||||
inputP = Math.max(0.25, Math.min(1.0, 1.6 - dist / 18));
|
||||
} else {
|
||||
inputP = 0.55;
|
||||
}
|
||||
}
|
||||
// 2. fixed 초기화 (첫 점) 또는 hybrid update.
|
||||
// 2. fixed hybrid.
|
||||
if (target.fixedPressure === undefined) {
|
||||
target.fixedPressure = inputP;
|
||||
return inputP;
|
||||
}
|
||||
const dev = Math.abs(inputP - target.fixedPressure);
|
||||
if (dev >= FIXED_LARGE) {
|
||||
// 매우 큰 변화 — 즉시 update.
|
||||
target.fixedPressure = inputP;
|
||||
return inputP;
|
||||
}
|
||||
const alpha = dev < FIXED_THRESHOLD ? FIXED_ALPHA_NOISE : FIXED_ALPHA_INTENT;
|
||||
target.fixedPressure = target.fixedPressure + (inputP - target.fixedPressure) * alpha;
|
||||
return target.fixedPressure;
|
||||
|
||||
Reference in New Issue
Block a user