Merge remote-tracking branches 'origin/main_laptop_1' and 'origin/sub_laptop_1' into sub_laptop_2
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
· 못 놓으면 다음 꺾임과 합침(같은 쪽으로 돌면 두 접선 교점 · 아니면 다음 IP 를 뺌) → 그래도
|
||||
안 되면 그 곡선을 끔(꺾임만) → 그래도 이탈 한도를 넘으면 실패.
|
||||
· 모두 놓는 길이 없으면 못 놓는 곡선만 그 자리에 두고 나머지는 맞춤(부분 · 「측점 밖 곡선 N개」).
|
||||
그 전에 이웃 곡선과 한 측점을 다투면 덜 꺾인 쪽을 끔 — 꺾임점째 빼거나 꺾임만(364-5).
|
||||
· 그것도 못 하면 None — 부르는 쪽이 원래 선을 씀.
|
||||
|
||||
고른 값은 편집 갈래(`simplify=False` · 곡선 켬 · `radii`)로 다시 짠다 — 화면이 곡선을 교각점
|
||||
@@ -25,7 +26,7 @@ from __future__ import annotations
|
||||
|
||||
import math
|
||||
from collections.abc import Callable, Iterator
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, replace
|
||||
|
||||
import numpy as np
|
||||
import shapely
|
||||
@@ -362,11 +363,63 @@ class _Snapper:
|
||||
kink.flags[k], kink.radii[k] = False, None
|
||||
yield self._kink(state, kink)
|
||||
if self.keep:
|
||||
yield from self._crowded(state)
|
||||
yield from self._kept(state)
|
||||
|
||||
def _kept(self, state: _State) -> Iterator[_State]:
|
||||
"""못 놓는 곡선은 그 자리 그대로(브레인 확정 · 측점 밖 곡선으로 셈)."""
|
||||
def _crowded(self, state: _State) -> Iterator[_State]:
|
||||
"""이웃 곡선과 한 측점을 다툼(꺾임점 사이 20 m 안 · 364-5) — 덜 꺾인 쪽 곡선을 끔.
|
||||
|
||||
끈 꺾임이 원래 선에서 한도 안일 때만. 이 곡선을 끄면 꺾임만 · 뒤 곡선을 끄면 이 곡선을
|
||||
다시 놓아 봄(못 놓으면 그 자리). 앞 곡선은 이미 정해져 이 곡선만 끔.
|
||||
"""
|
||||
plan, k = state.plan, state.k
|
||||
p = plan.points
|
||||
|
||||
def close(i: int) -> bool:
|
||||
return 1 <= i < len(p) - 1 and plan.flags[i] and math.dist(p[i], p[k]) < STATION_M
|
||||
|
||||
pair = [k, k + 1] if close(k + 1) else []
|
||||
# 덜 꺾인 쪽부터 · 그걸 꺼도 못 놓으면 다른 쪽
|
||||
pair.sort(key=lambda i: -_inner_angle_deg(*p[i - 1 : i + 2]))
|
||||
found = _try(state, plan, k, p[k], plan.radii[k] or self.min_radius)
|
||||
# 앞 곡선 MC 측점에서 20 m 안(남는 측점 없음)도 다툼
|
||||
crowded = (
|
||||
found is not None
|
||||
and 0 < state.last_station
|
||||
and (found[1] - state.last_station < STATION_M)
|
||||
)
|
||||
if (close(k - 1) or crowded) and k not in pair:
|
||||
pair.append(k)
|
||||
for small in pair:
|
||||
a, at, b = p[small - 1 : small + 2]
|
||||
chord = [
|
||||
(a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t) for t in (0.25, 0.5, 0.75)
|
||||
]
|
||||
# 꺾임점째 뺌(이웃 곡선 접선 자리가 넓어짐) → 안 되면 꺾임만 남김. 이 꺾임점은 앞
|
||||
# 곡선이 꺾임만일 때만 뺌(앞 곡선 EC 가 이 꺾임점 쪽 직선 위)
|
||||
movable = small > k or not plan.flags[k - 1]
|
||||
if movable and self.reference.gap(chord) <= self.max_gap and not self._steeper(chord):
|
||||
gone = plan.copy()
|
||||
del gone.points[small], gone.flags[small], gone.radii[small]
|
||||
yield replace(state, plan=gone)
|
||||
piece = [
|
||||
((a[0] + at[0]) / 2, (a[1] + at[1]) / 2),
|
||||
at,
|
||||
((at[0] + b[0]) / 2, (at[1] + b[1]) / 2),
|
||||
]
|
||||
if self.reference.gap(piece) > self.max_gap or self._steeper(piece):
|
||||
continue
|
||||
off = plan.copy()
|
||||
off.flags[small], off.radii[small] = False, None
|
||||
if small == k:
|
||||
yield self._kink(state, off)
|
||||
else:
|
||||
yield from self._placements(state, off)
|
||||
yield from self._kept(state, off)
|
||||
|
||||
def _kept(self, state: _State, plan: _Plan | None = None) -> Iterator[_State]:
|
||||
"""못 놓는 곡선은 그 자리 그대로(브레인 확정 · 측점 밖 곡선으로 셈)."""
|
||||
plan, k = plan or state.plan, state.k
|
||||
found = _try(state, plan, k, plan.points[k], plan.radii[k] or self.min_radius)
|
||||
if found is None:
|
||||
return
|
||||
|
||||
@@ -32,7 +32,7 @@ from B05_Profile.B05_Profile_Engine_RouteInitial import (
|
||||
)
|
||||
from common_util.common_util_json import atomic_write_json
|
||||
|
||||
ALGO_VERSION = 3 # 3 = 곡선 MC 일반측점(351-2)
|
||||
ALGO_VERSION = 4 # 3 = 곡선 MC 일반측점(351-2) · 4 = 다투는 곡선 끔(364-5)
|
||||
STORE_DIR = "B05_Profile/route_recommend"
|
||||
# 종류(갈래 · 지형) 마다 남길 벌 수 — 꺼낼 때 수정시각을 새로 해 최근에 쓴 것이 남음
|
||||
KEEP_PER_KIND = 2
|
||||
|
||||
Reference in New Issue
Block a user