- Code\rebar_pipeline, review_pipeline, pier-program을 정션에서 실제 폴더로 전환 - Code\rhino_mcp 및 CLAUDE_rhino배경.md 추가, .mcp.json은 PYTHONPATH로 새 위치 사용 - pier-program 내부 .git 제거(이력은 backup\pier-program_20261028.bundle에 보관) - worktree 가이드 반영(CLAUDE.local.md, HANDOFF.md) - D:\Rhino-MCP 경로 참조를 새 위치로 치환 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
76 lines
2.9 KiB
Python
76 lines
2.9 KiB
Python
"""월드 좌표와 코핑 로컬 좌표를 바꾸는 모듈.
|
|
|
|
Rhino 없이 실행됩니다. 단위는 mm, 각도는 라디안입니다.
|
|
|
|
월드 좌표 (x, y, z) <-> 로컬 좌표 (s, t, z)
|
|
s = 길이방향 (코핑 축 방향), t = 폭방향 (s를 반시계로 90도 돌린 방향)
|
|
z = 월드 높이를 그대로 사용
|
|
|
|
원점(origin_x, origin_y)과 각도(angle)는 값으로 받으므로 언제든 바꿀 수 있습니다.
|
|
기존 프로젝트 rebar_pipeline/rhino/07_ctc_extract.py 의 OX, OY, ANG 방식과 같습니다.
|
|
"""
|
|
import math
|
|
|
|
|
|
class Frame(object):
|
|
"""코핑 로컬 좌표계. 원점(월드 x, y)과 s축 각도(월드 +X 기준, 반시계)로 정해집니다."""
|
|
|
|
def __init__(self, origin_x, origin_y, angle):
|
|
self.origin_x = float(origin_x)
|
|
self.origin_y = float(origin_y)
|
|
self.angle = float(angle)
|
|
self._cos = math.cos(self.angle)
|
|
self._sin = math.sin(self.angle)
|
|
|
|
def to_local(self, x, y, z):
|
|
"""월드 점 (x, y, z) -> 로컬 점 (s, t, z)."""
|
|
dx = x - self.origin_x
|
|
dy = y - self.origin_y
|
|
return (dx * self._cos + dy * self._sin,
|
|
-dx * self._sin + dy * self._cos,
|
|
z)
|
|
|
|
def to_world(self, s, t, z):
|
|
"""로컬 점 (s, t, z) -> 월드 점 (x, y, z)."""
|
|
return (self.origin_x + s * self._cos - t * self._sin,
|
|
self.origin_y + s * self._sin + t * self._cos,
|
|
z)
|
|
|
|
def direction_to_local(self, dx, dy, dz):
|
|
"""월드 방향 벡터 -> 로컬 방향 벡터 (원점 이동 없이 회전만)."""
|
|
return (dx * self._cos + dy * self._sin,
|
|
-dx * self._sin + dy * self._cos,
|
|
dz)
|
|
|
|
def direction_to_world(self, ds, dt, dz):
|
|
"""로컬 방향 벡터 -> 월드 방향 벡터 (원점 이동 없이 회전만)."""
|
|
return (ds * self._cos - dt * self._sin,
|
|
ds * self._sin + dt * self._cos,
|
|
dz)
|
|
|
|
def to_local_many(self, points):
|
|
"""월드 점 목록 -> 로컬 점 목록."""
|
|
return [self.to_local(x, y, z) for (x, y, z) in points]
|
|
|
|
def to_world_many(self, points):
|
|
"""로컬 점 목록 -> 월드 점 목록."""
|
|
return [self.to_world(s, t, z) for (s, t, z) in points]
|
|
|
|
|
|
def from_two_points(a, b):
|
|
"""두 점 a, b (월드 (x, y))로 프레임을 만듭니다.
|
|
|
|
원점 = 두 점의 가운데, s축 = a에서 b로 향하는 방향.
|
|
(예: 2주식 교각의 두 기둥 중심)
|
|
"""
|
|
dx = b[0] - a[0]
|
|
dy = b[1] - a[1]
|
|
if dx == 0 and dy == 0:
|
|
raise ValueError("두 점이 같아서 방향을 정할 수 없습니다: %r" % (a,))
|
|
return Frame((a[0] + b[0]) / 2.0, (a[1] + b[1]) / 2.0, math.atan2(dy, dx))
|
|
|
|
|
|
def convert(point, src, dst):
|
|
"""src 프레임의 로컬 점을 dst 프레임의 로컬 점으로 바꿉니다 (월드를 거쳐서)."""
|
|
return dst.to_local(*src.to_world(*point))
|