import MilCon import typing import math class _HPos: x: str y: str z: str class RelativePos: def __init__(self, x: str | int | float = "~", y: str | int | float = "~", z: str | int | float = "~"): self.x: str = str(x) if isinstance(x, (int, float)) else x self.y: str = str(y) if isinstance(y, (int, float)) else y self.z: str = str(z) if isinstance(z, (int, float)) else z def __str__(self): return f"{self.x} {self.y} {self.z}" @classmethod def FromString(cls, s: str): parts = s.split() if len(parts) != 3 or not all(p.startswith('~') for p in parts): raise ValueError("Catch A Error As RelativePos ~x ~y ~z") return cls(*parts) def ToAbsolute(self, reference: _HPos=None): def ParseCoord(coord: str, ref): if coord.startswith('~'): return ref + (float(coord[1:]) if len(coord) > 1 else 0.0) else: return float(coord) ref_x = reference.x if reference and reference.x.startswith('~') else 0.0 ref_y = reference.y if reference and reference.y.startswith('~') else 0.0 ref_z = reference.z if reference and reference.z.startswith('~') else 0.0 abs_x = ParseCoord(self.x, ref_x) abs_y = ParseCoord(self.y, ref_y) abs_z = ParseCoord(self.z, ref_z) return RelativePos(abs_x, abs_y, abs_z) class LocalCoordinatesPos: def __init__(self, x: str | int | float = "^", y: str | int | float = "^", z: str | int | float = "^"): self.x: str = str(x) if isinstance(x, (int, float)) else x self.y: str = str(y) if isinstance(y, (int, float)) else y self.z: str = str(z) if isinstance(z, (int, float)) else z def __str__(self): return f"{self.x} {self.y} {self.z}" @classmethod def FromString(cls, s: str): parts = s.split() if len(parts) != 3 or not all(p.startswith('^') for p in parts): raise ValueError("Catch A Error As LocalCoordinatesPos ^x ^y ^z") return cls(*parts) def ToAbsolute(self, reference: _HPos=None): def ParseCoord(coord: str, ref): if coord.startswith('^'): return ref + (float(coord[1:]) if len(coord) > 1 else 0.0) else: return float(coord) ref_x = reference.x if reference and reference.x.startswith('^') else 0.0 ref_y = reference.y if reference and reference.y.startswith('^') else 0.0 ref_z = reference.z if reference and reference.z.startswith('^') else 0.0 abs_x = ParseCoord(self.x, ref_x) abs_y = ParseCoord(self.y, ref_y) abs_z = ParseCoord(self.z, ref_z) return LocalCoordinatesPos(abs_x, abs_y, abs_z) class Delta: def __init__(self, x: int = 0, y: int = 0, z: int = 0): self.x, self.y, self.z = x, y, z def __str__(self): return f"{self.x} {self.y} {self.z}" class Command(): def __init__(self, command): self.command = command def __str__(self): return self.command class ExecuteSubCommandRule(typing.TypedDict): mode: MilCon._execute_sub_commands text: Command def _Bool2Str(self, value: bool): return "true" if value else "false" def _WithValue(self, value: str | int): return f" {value}" if value else "" def _Pos1ToPos2(pos1: RelativePos, pos2: RelativePos, radios: int): abs_pos1 = pos1.ToAbsolute() abs_pos2 = pos2.ToAbsolute() x1, y1, z1 = abs_pos1.x, abs_pos1.y, abs_pos1.z x2, y2, z2 = abs_pos2.x, abs_pos2.y, abs_pos2.z delta_x = (x2 - x1) / (radios + 1) delta_y = (y2 - y1) / (radios + 1) delta_z = (z2 - z1) / (radios + 1) points = [] for i in range(1, radios + 1): x = x1 + delta_x * i y = y1 + delta_y * i z = z1 + delta_z * i points.append(RelativePos(x, y, z)) return points def _Pos1ToPos2WithPoints(radios: int, radian: int, pos1: RelativePos, pos2: RelativePos, *poses: RelativePos): # 参数验证 if radios <= len(poses) + 2: raise ValueError("radios must be greater than len(poses) + 2") if radian < 0: raise ValueError("radian must be non-negative") # 转换为绝对坐标 abs_pos1 = pos1.ToAbsolute() abs_poses = [p.ToAbsolute() for p in poses] abs_pos2 = pos2.ToAbsolute() # 所有点按顺序排列 all_points = [abs_pos1] + abs_poses + [abs_pos2] num_segments = len(all_points) - 1 # 计算每段的点数 points_per_segment = (radios - num_segments + 1) // num_segments remainder = (radios - num_segments + 1) % num_segments # 生成点 points = [] for i in range(num_segments): start = all_points[i] end = all_points[i + 1] # 当前段的点数 current_points = points_per_segment + (1 if i < remainder else 0) # 计算增量 delta_x = (float(end.x) - float(start.x)) / (current_points + 1) delta_y = (float(end.y) - float(start.y)) / (current_points + 1) delta_z = (float(end.z) - float(start.z)) / (current_points + 1) # 生成当前段的点 for j in range(1, current_points + 1): x = float(start.x) + delta_x * j y = float(start.y) + delta_y * j z = float(start.z) + delta_z * j # 如果 radian 不为 0 且 poses 存在,则在中间点附近向外偏移 if radian != 0 and len(poses) > 0 and i < len(poses): # 计算当前点与中间点的距离比例 t = j / (current_points + 1) # 使用正弦函数生成弧形偏移 offset = radian * math.sin(t * math.pi) # 计算垂直于路径的方向(简单实现,可以改进为真正的 3D 垂直) # 这里假设偏移方向为 (1, 1, 1) 的某个分量,实际应根据路径方向计算 x += offset * 0.577 # 0.577 ≈ 1 / sqrt(3) y += offset * 0.577 z += offset * 0.577 points.append(RelativePos(x, y, z)) return points '''def _Pos1ToPos2WithPoints(radios: int, pos1: RelativePos, pos2: RelativePos, *poses: RelativePos): if radios <= len(poses) + 2: raise ValueError("radios must be greater than len(poses) + 2") abs_pos1 = pos1.ToAbsolute() abs_poses = [p.ToAbsolute() for p in poses] abs_pos2 = pos2.ToAbsolute() all_points = [abs_pos1] + abs_poses + [abs_pos2] num_segments = len(all_points) - 1 points_per_segment = (radios - num_segments + 1) // num_segments remainder = (radios - num_segments + 1) % num_segments points = [] for i in range(num_segments): start = all_points[i] end = all_points[i + 1] current_points = points_per_segment + (1 if i < remainder else 0) delta_x = (float(end.x) - float(start.x)) / (current_points + 1) delta_y = (float(end.y) - float(start.y)) / (current_points + 1) delta_z = (float(end.z) - float(start.z)) / (current_points + 1) for j in range(1, current_points + 1): x = float(start.x) + delta_x * j y = float(start.y) + delta_y * j z = float(start.z) + delta_z * j points.append(RelativePos(x, y, z)) return points'''