# AeroSpot AutoReport 项目

AeroSpot AutoReport 是一个用于处理航测数据并生成水质分析报告的工具。项目经过模块化重构，消除了重复定义，提升了可维护性和结构清晰度。各功能模块职责单一，便于扩展和维护。

## 系统要求

- **Python**: >= 3.10 (推荐 3.11)
- **操作系统**: Windows, Linux, macOS
- **内存**: 建议 4GB 以上
- **硬盘**: 建议 1GB 可用空间

### Python版本支持
- ✅ **Python 3.11** (推荐版本)
- ✅ **Python 3.10** (最低版本)
- ✅ **Python 3.12** (最新版本)

## 快速安装

### 用户安装 (推荐)
```bash
# 完整功能安装 (包含水印功能，自动适配平台)
pip install aerospot-autoreport
```

### 开发环境安装
```bash
# 开发环境 (完整功能 + 开发工具)
pip install aerospot-autoreport[dev]
```

### 从源码安装
```bash
git clone https://github.com/1034378361/AutoReportV2.git
cd AutoReportV2
pip install -e .
```

## 安装选项说明

### 两种安装方式
1. **用户安装**: 完整功能 + 智能平台适配
2. **`[dev]`**: 用户功能 + 开发工具(测试、代码质量)

### 智能平台适配
所有安装方式都使用条件依赖，自动根据操作系统安装合适的依赖：

| 平台 | pywin32安装 | Windows目录更新功能 |
|------|-------------|-------------------|
| **Windows** | ✅ 自动安装 | ✅ 完全支持 |
| **Linux** | ❌ 自动跳过 | ❌ 不支持 |
| **macOS** | ❌ 自动跳过 | ❌ 不支持 |

### 功能对比
| 功能 | 用户安装 | [dev] |
|------|----------|-------|
| 报告生成 | ✅ | ✅ |
| 数据处理 | ✅ | ✅ |
| 图表生成 | ✅ | ✅ |
| 水印功能 | ✅ | ✅ |
| Windows目录更新 | 🔄 | 🔄 |
| 开发工具 | ❌ | ✅ |

🔄 = 自动平台适配：Windows支持，Linux/macOS不支持

## 项目结构

项目主要包含以下模块：

```
AeroSpotReportV2/
├── config/               # 配置模块（常量、样式、公司信息等集中管理）
│   ├── __init__.py
│   ├── constants.py      # 常量定义
│   ├── styles.py         # 样式配置
│   ├── company_info.py   # 公司信息配置
│   └── defaults.py       # 默认配置
├── utils/                # 工具模块（通用工具函数，去重整合）
│   ├── __init__.py
│   ├── text.py           # 文本处理工具（如is_chinese、is_numeric等）
│   ├── font.py           # 字体处理工具
│   ├── io.py             # 输入输出工具
│   ├── geo.py            # 地理计算工具
│   └── path.py           # 路径处理工具
├── document/             # 文档生成模块（报告样式、段落、表格、图片、页面等）
│   ├── __init__.py
│   ├── styles.py         # 文档样式
│   ├── paragraphs.py     # 段落生成
│   ├── tables.py         # 表格生成
│   ├── images.py         # 图像处理
│   └── pages.py          # 页面生成
├── processor/            # 数据处理模块
│   ├── data/             # 数据处理子模块
│   │   ├── __init__.py
│   │   ├── processor.py  # 数据处理核心
│   │   ├── standardizer.py # 数据标准化
│   │   ├── analyzer.py   # 数据分析
│   │   ├── matcher.py    # 数据匹配
│   │   └── utils.py      # 数据处理工具
│   ├── config.py         # 配置处理
│   ├── downloader.py     # 数据下载
│   ├── extractor.py      # 数据提取
│   └── maps.py           # 卫星图像与可视化地图生成
├── main.py               # 主程序入口
├── generator.py          # 报告生成器
├── error_handler.py      # 错误处理
├── log_config.py         # 日志配置
└── resource_manager.py   # 资源管理
```

## 主要功能

1. **数据处理**：
   - 从压缩文件中提取航测数据
   - 标准化数据列名和指标名称
   - 计算基本统计信息
   - 数据匹配和分析
   - 卫星图像与指标数据可视化（见processor/maps.py）

2. **报告生成**：
   - 生成专业的Word格式报告
   - 包含统计表格、分布图和分析结果
   - 自定义报告样式和内容

3. **数据可视化**：
   - 生成指标分布图、插值热力图、水质等级分布图
   - 支持卫星底图与自定义地理边界

## 安装使用

1. 克隆项目到本地：
   ```bash
   git clone https://github.com/1034378361/AeroSpotReportV2.git
   cd AeroSpotReportV2
   ```

2. 安装依赖：
   ```bash
   pip install -r requirements.txt
   ```

3. 配置环境变量：
   创建`.env`文件并设置必要的环境变量。

4. 运行程序：
   ```bash
   python main.py
   ```

## 配置说明

项目支持通过配置文件和环境变量进行配置。主要配置项包括：

- 公司信息配置
- 报告样式配置
- 数据处理参数配置
- 输出路径配置

详细配置说明请参考 `config/` 目录下的相关文件。

## 数据处理与可视化模块

- 数据处理模块(`processor/data/`)是项目的核心，负责处理航测数据和实测数据，主要功能包括：
  - 数据标准化：统一列名和指标名称
  - 数据匹配：将航测数据与实测数据进行匹配
  - 数据分析：计算统计信息，分析数据特征
  - 误差分析：分析原始航测数据和重新反演数据与实测数据的误差
- 地图与可视化模块(`processor/maps.py`)支持基于卫星图像和指标数据生成分布图、插值热力图和水质等级分布图。

## KML边界处理 - 差集功能

项目支持使用KML文件定义复杂的地理边界，实现**保留区域与排除区域的差集处理**。

### 功能说明

**BoundaryManager** 类提供以下功能：
- 加载和解析KML文件中的多个多边形区域
- 支持带孔洞的多边形（环形区域）
- 根据Placemark的name标签分类：
  - `name="1"`: 保留区域
  - `name="0"`: 排除区域
- 自动计算差集：`保留区域并集 - 排除区域并集`
- 为网格和点数据应用边界掩膜

### KML文件格式

KML文件需要遵循以下结构：

```xml
<Document>
  <!-- 保留区域 -->
  <Placemark>
    <name>1</name>
    <Polygon>
      <outerBoundaryIs>
        <LinearRing>
          <coordinates>
            lon1,lat1,0 lon2,lat2,0 lon3,lat3,0 ... lon1,lat1,0
          </coordinates>
        </LinearRing>
      </outerBoundaryIs>
      <!-- 可选：内孔（排除的区域） -->
      <innerBoundaryIs>
        <LinearRing>
          <coordinates>
            lon1,lat1,0 lon2,lat2,0 ... lon1,lat1,0
          </coordinates>
        </LinearRing>
      </innerBoundaryIs>
    </Polygon>
  </Placemark>

  <!-- 排除区域 -->
  <Placemark>
    <name>0</name>
    <Polygon>
      <outerBoundaryIs>
        <LinearRing>
          <coordinates>
            lon1,lat1,0 lon2,lat2,0 ... lon1,lat1,0
          </coordinates>
        </LinearRing>
      </outerBoundaryIs>
    </Polygon>
  </Placemark>
</Document>
```

**关键点：**
- 每个区域必须在单独的 `<Placemark>` 中
- `<name>` 标签用于区分：`1` 表示保留，`0` 表示排除
- 支持多个保留区域和排除区域，自动合并
- 坐标格式：`经度,纬度,海拔` (海拔可为0)
- 坐标必须首尾相连（闭合多边形）

### 配置方法

在config.json中添加KML文件URL：

```json
{
  "company_info": {
    "name": "公司名称",
    "kml_boundary_url": "https://example.com/boundary.kml",
    ...
  }
}
```

或使用本地文件路径：

```json
{
  "company_info": {
    "kml_boundary_url": "./path/to/boundary.kml",
    ...
  }
}
```

### 使用示例

```python
from autoreport.core.boundary_manager import BoundaryManager

# 方法1：初始化时指定KML文件
boundary_manager = BoundaryManager("path/to/boundary.kml")

# 检查是否成功启用
if boundary_manager.is_enabled:
    print("边界管理器已启用")
    # 获取统计信息
    stats = boundary_manager.get_statistics()
    print(f"边界类型: {stats['geometry_type']}")
    print(f"边界面积: {stats['area']}")

# 方法2：过滤数据点
import pandas as pd

df = pd.DataFrame({
    'Longitude': [104.0, 104.1, 104.2],
    'Latitude': [30.0, 30.1, 30.2],
    'value': [10, 20, 30]
})

filtered_df, mask = boundary_manager.filter_dataframe(df)
print(f"保留数据点: {len(filtered_df)}/{len(df)}")

# 方法3：检查单个点
is_inside = boundary_manager.contains_point(lon=104.05, lat=30.05)
print(f"点在边界内: {is_inside}")

# 方法4：生成网格掩膜（用于插值）
import numpy as np

grid_lon = np.linspace(104.0, 104.5, 100)
grid_lat = np.linspace(30.0, 30.5, 100)
grid_lon, grid_lat = np.meshgrid(grid_lon, grid_lat)

mask = boundary_manager.get_grid_mask(grid_lon, grid_lat)
print(f"网格内的点数: {np.sum(mask)}/{mask.size}")
```

### 工作流程

系统在报告生成过程中自动应用KML边界：

1. **加载配置**: 读取config.json中的`kml_boundary_url`
2. **初始化边界管理器**: 在`download_resources()`后创建BoundaryManager实例
3. **数据过滤**: 在`process_data()`中对UAV数据和测量数据应用边界过滤
4. **地图生成**: 在`generate_indicator_maps()`中使用边界掩膜生成精确的插值热力图

### 功能特性

- **零依赖额外配置**: 如不提供KML文件，系统会自动使用Alpha Shape自适应边界检测
- **自动降级**: 如果KML文件无效，系统自动回退到Alpha Shape算法
- **性能优化**: 使用Shapely库的矢量化操作，支持大规模数据高效处理
- **灵活边界**: 支持凸边界、凹边界、有孔洞的复杂多边形

### 故障排查

| 问题 | 原因 | 解决方案 |
|------|------|--------|
| KML文件未加载 | 文件路径错误或文件不存在 | 检查`kml_boundary_url`路径，确保文件存在 |
| 边界掩膜为全0 | name="1"的保留区域不存在 | 检查KML文件中是否有name="1"的Placemark |
| 数据点全部被过滤 | 数据点不在保留区域内 | 检查坐标系统是否匹配，确认数据范围 |
| 内存溢出 | KML文件过大或坐标过多 | 简化KML多边形复杂度，减少顶点数量 |

## 模块化重构说明

- 本项目已完成配置、工具函数、文档生成等模块的结构化重构，消除了重复定义，提升了可维护性。
- 主程序（如`main.py`、`generator.py`）的导入路径更新与全局适配正在规划中。
- 详细重构计划见 `refactoring_plan.md`。

## 安全设计说明

### 加密密钥管理

本项目使用**硬编码加密密钥**来保护水质模型系数。这是有意的架构设计，而非安全漏洞。

#### 为什么采用硬编码密钥？

项目使用 **Nuitka 编译为 .so 二进制文件** 分发给用户：

1. **二进制保护**
   - 加密密钥被编译进二进制，不存在于源代码文件中
   - 密钥与二进制合并，难以单独提取

2. **配置文件安全**
   - 避免了在 `.env` 或配置文件中暴露敏感密钥
   - 配置文件泄露不会导致密钥泄露

3. **部署简化**
   - 用户只需接收和运行二进制文件
   - 无需单独配置和管理密钥

4. **逆向工程防护**
   - 从编译的二进制中提取密钥需要复杂的逆向工程
   - 二进制混淆和编译可进一步增强防护

#### 密钥更换流程

如需更换加密密钥：

1. 修改源代码中的密钥值（见 `src/autoreport/main.py::save_model_func()` 第 1826 行）
2. 重新编译项目为二进制
3. 将新二进制分发给用户

#### 代码审查要求

开发人员和审查者必须确保：

- ✅ 密钥**绝不输出**到日志（`logger.error()`, `logger.info()` 等）
- ✅ 密钥**绝不包含**在异常消息中
- ✅ 密钥**绝不使用** `print()` 或 `repr()` 输出
- ✅ 密钥**绝不在** f-string 中泄露
- ✅ 代码注释不包含实际的密钥值

详见 `CODE_REVIEW_CHECKLIST.md` 中的"密钥安全审查"部分。

## 注意事项

- 项目需要Python 3.10或更高版本
- 部分功能需要授权才能使用
- 请确保输入数据格式符合要求