fix(459 노선 바뀜): [저장] 구조물 초안을 서버 따라감 위에 · 추가 측점 초안 동안 좌표 따라감 · 옮긴 시설 측점 427 꼭짓점 세움 · 관 따라감 선 = points
- 구조물: 노선 저장 뒤 rebaseStructureDraft(관 rebasePipeDraft 짝) — 따라가기만 한 것 = 서버 자리 · 사용자가 옮긴 것 = 초안 - 추가 측점: follow 단계가 좌표로 옮긴 정수 m 를 patch.plusStations 로(FOLLOW_KEYS · stations 단계 입력값) · followPlusDraft(가게 쓰기 · 초안 버림 되돌림 · page 부름은 sub7) · follow 만 쓴 초안은 [저장]이 PUT 안 함 - 427: 초안 planline · 서버 _carry_profile 이 바뀐 구간 관 · 구조물 측점(+ 초안 중 사용자가 옮긴 것)에 seatBornNodes 로 다시 세움(route_moved_stations · seat_route_moved 짝) - 서버 관 따라감 = 구조물과 같은 points(사용 범위 자름) · 좌표 없는 옛 관은 옛 노선 자리로 먼저 · 따라감 실패 = follow_failed 알림 - 시험 test_459_route_seat_mirror(거울 · 임시 storage · _place_pipes) · 헬퍼 400 · 449 · design_store_save 가짜 창구 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,8 @@
|
||||
* 아니면 누가거리의 노선 위 자리 · 410) · 거울 시험 = resources/tester/test_410_follow_xy.py.
|
||||
* - `placeOnLine` 의 좌표 없는 관 · `rebasePipeDraft` 는 TS 만 — 좌표 없는 세션 관 초안(정본 PUT 꼴)을 따라가기
|
||||
* 전 자리로 · 노선을 저장한 [저장]이 서버가 따라 옮긴 관 위에 초안을 얹음(349-0u).
|
||||
* - `rebaseStructureDraft` 도 TS 만 — 구조물 초안을 서버가 따라 옮긴 정본 위에(459 · 관 짝).
|
||||
* - `followPlusStations` ↔ 파이썬 `B05_Profile_Plus_Stations.follow_plus_stations`(459 · 노선 초안 동안).
|
||||
* 거울 시험 = resources/tester/test_344_2_route_pairs.py.
|
||||
* ========================================================================== */
|
||||
|
||||
@@ -142,6 +144,66 @@ export function rebasePipeDraft<P extends FollowingPoint & { id?: string | null
|
||||
return [...kept, ...added].sort((a, b) => a.chainage_m - b.chainage_m);
|
||||
}
|
||||
|
||||
type StructureLike = FollowingStructure & { structure_id?: string | null };
|
||||
|
||||
/** 자리 셋(기준 · 구간 끝)이 같은가 — `shift` 만큼 민 자리로 견줌(구간 길이 = 시설 치수). */
|
||||
const samePositions = (a: FollowingStructure, b: FollowingStructure, shift = 0): boolean =>
|
||||
(["chainage_m", "start_m", "end_m"] as const).every(
|
||||
(key) =>
|
||||
(a[key] == null) === (b[key] == null) &&
|
||||
Math.abs((a[key] ?? 0) + shift - (b[key] ?? 0)) <= SAME_STATION_M,
|
||||
);
|
||||
|
||||
/** 노선을 저장한 [저장] — 세션 구조물 초안을 서버가 따라 옮긴 정본(`after`) 위에 얹은 목록(459 · 관
|
||||
* `rebasePipeDraft` 짝). 따라가기만 한 것(자리 = 노선 저장 전 정본 `before` 그대로 · 또는 땅 위 자리가 같고
|
||||
* 기준 누가거리가 서버 따라감과 같음)은 서버 자리(기준 · 구간 끝 · 좌표) · 사용자가 옮긴 것(마커 · 폼 =
|
||||
* 누가거리만 옮겨 좌표 낡음 포함) · 새로 놓은 것은 초안 그대로 · 옵션 · 메모는 늘 초안 · 짝은 `structure_id`. */
|
||||
export function rebaseStructureDraft<S extends StructureLike>(
|
||||
draft: ReadonlyArray<S>,
|
||||
before: ReadonlyArray<StructureLike>,
|
||||
after: ReadonlyArray<StructureLike>,
|
||||
): S[] {
|
||||
const old = new Map(before.map((item) => [item.structure_id, item]));
|
||||
const moved = new Map(after.map((item) => [item.structure_id, item]));
|
||||
return draft.map((item) => {
|
||||
const was = item.structure_id ? old.get(item.structure_id) : undefined;
|
||||
const now = item.structure_id ? moved.get(item.structure_id) : undefined;
|
||||
if (!was || !now) return item;
|
||||
const followed =
|
||||
item.x != null &&
|
||||
item.y != null &&
|
||||
was.x != null &&
|
||||
was.y != null &&
|
||||
Math.hypot(item.x - was.x, item.y - was.y) <= FOLLOW_SAME_XY_M &&
|
||||
samePositions(was, item, (item.chainage_m ?? 0) - (was.chainage_m ?? 0)) &&
|
||||
Math.abs((item.chainage_m ?? 0) - (now.chainage_m ?? 0)) <= SAME_STATION_M;
|
||||
if (!followed && !samePositions(item, was)) return item;
|
||||
return {
|
||||
...item,
|
||||
chainage_m: now.chainage_m ?? item.chainage_m,
|
||||
start_m: now.start_m ?? null,
|
||||
end_m: now.end_m ?? null,
|
||||
x: now.x ?? item.x,
|
||||
y: now.y ?? item.y,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/** 추가 측점이 노선을 따라감(459) — 옛 선(`from`) 위 누가거리의 땅 위 자리를 새 선(`to`)에 투영한 정수 m
|
||||
* (같은 m 하나 · 오름차순). 파이썬 `follow_plus_stations` 짝(`follow_structures` 같은 셈). */
|
||||
export function followPlusStations(
|
||||
list: ReadonlyArray<number>,
|
||||
from: ReadonlyArray<XY>,
|
||||
to: ReadonlyArray<XY>,
|
||||
): number[] {
|
||||
const placed = placeOnLine(
|
||||
list.map((chainage_m) => ({ chainage_m })),
|
||||
from,
|
||||
);
|
||||
const moved = followStructures(placed, to).map(({ item }) => item.chainage_m!);
|
||||
return [...new Set(moved)].sort((a, b) => a - b);
|
||||
}
|
||||
|
||||
/** 따라가기만 한 관 = 정본과 같은 땅 위 자리(m) — 서버 좌표가 mm 3자리라 그 반올림 폭. */
|
||||
const FOLLOW_SAME_XY_M = 0.001;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user