# CoordinateConverter 使用指南

## 文件位置

`src/Utils/CoordinateConverter.cs`

## 用途

负责 2D 地图坐标与 3D 世界坐标之间的转换，用于导航地图和路径规划可视化。

## 核心概念

- **地图坐标（MapPoint2D）**：2D 像素坐标，原点在左上角，Y轴向下
- **世界坐标（Point3D）**：3D 模型坐标，单位与文档单位一致
- **通道边界（ChannelBounds）**：定义了有效转换的区域范围

## 构造函数

```csharp
// 使用通道边界和地图尺寸创建转换器
var converter = new CoordinateConverter(
    channelBounds: bounds,      // ChannelBounds 对象
    mapWidth: 800,              // 地图窗口宽度（像素）
    mapHeight: 600              // 地图窗口高度（像素）
);
```

## 核心方法

### 坐标转换

```csharp
// 2D地图坐标 → 3D世界坐标
MapPoint2D mapPoint = new MapPoint2D(400, 300);
Point3D worldPoint = converter.MapToWorld(mapPoint);

// 3D世界坐标 → 2D地图坐标
Point3D worldPoint = new Point3D(x, y, z);
MapPoint2D mapPoint = converter.WorldToMap(worldPoint);

// 批量转换
var worldPoints = converter.MapToWorldBatch(mapPoints);
var mapPoints = converter.WorldToMapBatch(worldPoints);
```

### 有效性检查

```csharp
// 检查地图坐标是否在有效范围内
bool isValid = converter.IsValidMapPoint(mapPoint);

// 检查世界坐标是否在通道范围内
bool isValid = converter.IsValidWorldPoint(worldPoint);
```

### 距离计算

```csharp
// 计算两个地图点之间的像素距离
double pixelDistance = converter.CalculateMapDistance(point1, point2);

// 计算两个世界坐标点之间的距离（模型单位）
double worldDistance = converter.CalculateWorldDistance(point1, point2);
```

### 视图操作

```csharp
// 放大视图
converter.ZoomIn(factor: 1.5, centerPoint: mapCenter);

// 缩小视图
converter.ZoomOut(factor: 1.5, centerPoint: mapCenter);

// 平移视图
converter.Pan(deltaX: 100, deltaY: -50);

// 重置视图到最佳适应
converter.ResetView();

// 计算最佳适应视图
converter.CalculateBestFitView();
```

### 尺寸更新

```csharp
// 更新地图尺寸（窗口大小变化时）
converter.UpdateMapSize(newWidth: 1024, newHeight: 768);

// 更新通道边界
converter.UpdateChannelBounds(newChannelBounds);
```

### 辅助方法

```csharp
// 获取地图中心点的世界坐标
Point3D center = converter.GetMapCenterInWorld();

// 调整高程
Point3D adjusted = converter.AdjustElevation(worldPoint, elevationOffset: 0.5);

// 获取地图缩放比例
converter.GetMapScale(out double scaleX, out double scaleY);

// 获取转换器信息摘要
string info = converter.ToString();
```

## 属性

```csharp
// 地图尺寸
converter.MapWidth = 800;
converter.MapHeight = 600;

// 通道边界
converter.ChannelBounds = newChannelBounds;

// 默认高程（Z坐标）
converter.DefaultElevation = 10.0;

// 缩放因子（限制范围 0.1 - 50.0）
converter.ZoomFactor = 2.0;

// 偏移量
converter.OffsetX = 100;
converter.OffsetY = 50;
```

## 使用示例

### 示例1：基本的坐标转换

```csharp
// 创建转换器
var bounds = new ChannelBounds(minPoint, maxPoint);
var converter = new CoordinateConverter(bounds, 800, 600);

// 用户在地图上点击的位置
var clickPoint = new MapPoint2D(400, 300);

// 转换为世界坐标进行路径规划
Point3D worldPoint = converter.MapToWorld(clickPoint);
LogManager.Info($"点击位置对应世界坐标: ({worldPoint.X:F2}, {worldPoint.Y:F2}, {worldPoint.Z:F2})");
```

### 示例2：路径点批量转换

```csharp
// 将规划好的路径点转换为地图坐标显示
var pathWorldPoints = pathRoute.Points.Select(p => p.Position);
var pathMapPoints = converter.WorldToMapBatch(pathWorldPoints);

// 在地图上绘制路径
foreach (var mapPoint in pathMapPoints)
{
    DrawPointOnMap(mapPoint.X, mapPoint.Y);
}
```

### 示例3：响应窗口大小变化

```csharp
// 地图控件大小变化时更新转换器
void OnMapSizeChanged(double newWidth, double newHeight)
{
    converter.UpdateMapSize(newWidth, newHeight);
    converter.CalculateBestFitView();
    
    // 重绘地图...
}
```

## 注意事项

1. **Y轴翻转**：地图坐标系 Y 轴向下（屏幕坐标），世界坐标系 Y 轴向上，转换时自动处理
2. **边距设置**：从配置读取 `MarginRatio`，默认 10%，确保内容不会贴边显示
3. **Z坐标处理**：`MapToWorld` 返回的 Z 坐标使用 `DefaultElevation`，可通过 `AdjustElevation` 调整
4. **缩放限制**：缩放因子限制在 0.1 - 50.0 范围内，防止过度缩放
5. **线程安全**：此类的实例方法不是线程安全的，需要在单线程中使用或使用外部锁
