凸透镜成像

(运行前先下载easyX库,具体看easyX库Dvc++下载)

#include <graphics.h>
#include <conio.h>
#include <cmath>
#include <string>
#include <sstream>
#include <vector>

using namespace std;

// 物理常量定义
const int SCREEN_WIDTH = 1600;      // 窗口宽度
const int SCREEN_HEIGHT = 800;      // 窗口高度
const int CENTER_Y = SCREEN_HEIGHT / 2; // 光轴中心Y坐标
const int LENS_X = 600;             // 透镜中心X坐标
const int FOCAL_LENGTH = 180;       // 焦距(像素)
const int ARROW_HEIGHT = 100;       // 箭头高度
const int ARROW_WIDTH = 30;         // 箭头宽度
const int ARROW_HEAD_SIZE = 20;     // 箭头头部大小

// 颜色定义
const COLORREF CLR_RED = RGB(255, 90, 90);
const COLORREF CLR_GREEN = RGB(90, 255, 90);
const COLORREF CLR_BLUE = RGB(90, 140, 255);
const COLORREF CLR_YELLOW = RGB(255, 255, 120);
const COLORREF CLR_WHITE = RGB(255, 255, 255);
const COLORREF CLR_BLACK = RGB(10, 10, 20);
const COLORREF CLR_GRAY = RGB(160, 160, 160);
const COLORREF CLR_LIGHT_BLUE = RGB(180, 220, 255);
const COLORREF CLR_ORANGE = RGB(255, 180, 90);
const COLORREF CLR_PURPLE = RGB(200, 100, 255);
const COLORREF CLR_DARK_GREEN = RGB(90, 180, 90);
const COLORREF CLR_INFO_BG = RGB(35, 35, 50);
const COLORREF CLR_LENS = RGB(100, 170, 255);
const COLORREF CLR_RAY1 = RGB(255, 220, 100); // 光线1颜色
const COLORREF CLR_RAY2 = RGB(180, 220, 255);  // 光线2颜色
const COLORREF CLR_MENU_BG = RGB(40, 40, 60); // 菜单背景色

// 全局变量
bool isDragging = false;            // 是否正在拖动箭头
int arrowX = LENS_X - 400;          // 箭头初始X坐标
int arrowY = CENTER_Y;              // 箭头Y坐标(可上下移动)
double imageX = 0;                  // 像的X坐标
double imageY = 0;                  // 像的Y坐标
double imageHeight = 0;             // 像的高度
bool isRealImage = true;            // 是否为实像
bool isUpright = false;             // 是否正立
double magnification = 1.0;         // 放大率
bool showMenuWindow = false;        // 是否显示菜单窗口
bool drawAllRays = true;            // 是否绘制所有光线
double lastMouseX = 0, lastMouseY = 0; // 上一次鼠标位置

// 计算像的位置和大小
void calculateImage() {
    double u = LENS_X - arrowX; // 物距
    double f = FOCAL_LENGTH;     // 焦距
    
    // 计算物体到光轴的距离(垂直方向)
    double objectHeightFromAxis = arrowY - CENTER_Y;
    
    // 特殊情况处理
    if (fabs(u - f) < 1.0) {
        // 物体在焦点上,不成像
        imageX = 0;
        imageHeight = 0;
        imageY = CENTER_Y;
        isRealImage = false;
        magnification = 0;
        return;
    }
    
    // 使用透镜公式: 1/f = 1/u + 1/v
    double v = 1.0 / (1.0/f - 1.0/u);
    
    // 计算像的位置
    imageX = LENS_X + v;
    
    // 计算放大率
    magnification = -v / u; // 负号表示倒立
    
    // 计算像的高度(基于箭头实际高度)
    imageHeight = ARROW_HEIGHT * fabs(magnification);
    
    // 计算像的Y坐标(考虑垂直方向位置)
    imageY = CENTER_Y + magnification * objectHeightFromAxis;
    
    // 判断像的性质
    if (v > 0) {
        isRealImage = true;  // 实像(像在透镜另一侧)
        isUpright = (magnification > 0) ? true : false; // 根据放大率正负判断正倒立
    } else {
        isRealImage = false; // 虚像(像在透镜同侧)
        isUpright = (magnification > 0) ? true : false;
        imageHeight = ARROW_HEIGHT * fabs(magnification);
    }
}

// 绘制凸透镜 - 优化版
void drawLens() {
    // 绘制光轴
    setlinecolor(CLR_GRAY);
    setlinestyle(PS_SOLID, 1);
    line(80, CENTER_Y, SCREEN_WIDTH - 80, CENTER_Y);
    
    // 绘制透镜支架
    setlinecolor(RGB(180, 180, 200));
    setlinestyle(PS_SOLID, 3);
    line(LENS_X, CENTER_Y - 140, LENS_X, CENTER_Y + 140);
    
    // 绘制透镜底座
    setfillcolor(RGB(80, 80, 100));
    fillrectangle(LENS_X - 15, CENTER_Y - 140, LENS_X + 15, CENTER_Y - 120);
    fillrectangle(LENS_X - 15, CENTER_Y + 120, LENS_X + 15, CENTER_Y + 140);
    
    // 绘制凸透镜 - 使用渐变效果
    int lensHeight = 120;
    
    // 绘制透镜边缘
    setlinecolor(CLR_LENS);
    setlinestyle(PS_SOLID, 6);
    
    // 绘制透镜左弧
    ellipse(LENS_X - 80, CENTER_Y - lensHeight, 
            LENS_X + 80, CENTER_Y + lensHeight);
    
    // 填充透镜
    setfillcolor(RGB(100, 170, 255));
    solidellipse(LENS_X - 70, CENTER_Y - lensHeight + 10, 
                 LENS_X + 70, CENTER_Y + lensHeight - 10);
    
    // 标记透镜中心
    setfillcolor(CLR_ORANGE);
    solidcircle(LENS_X, CENTER_Y, 8);
    
    // 绘制光心标记
    setlinecolor(CLR_ORANGE);
    setlinestyle(PS_SOLID, 2);
    line(LENS_X - 15, CENTER_Y, LENS_X + 15, CENTER_Y);
    line(LENS_X, CENTER_Y - 15, LENS_X, CENTER_Y + 15);
    
    // 标注透镜
    settextcolor(CLR_LENS);
    settextstyle(24, 0, _T("微软雅黑"));
    setbkmode(TRANSPARENT);
    outtextxy(LENS_X - 40, CENTER_Y - 160, _T("凸透镜"));
    
    // 标注光心
    settextcolor(CLR_ORANGE);
    settextstyle(20, 0, _T("微软雅黑"));
    outtextxy(LENS_X - 10, CENTER_Y - 50, _T("O"));
}

// 绘制焦点和2F点 - 优化版
void drawFocalPoints() {
    // 绘制左侧焦点F
    int leftF = LENS_X - FOCAL_LENGTH;
    setlinecolor(CLR_RED);
    setlinestyle(PS_DASH, 2);
    line(leftF, CENTER_Y - 50, leftF, CENTER_Y + 50);
    
    // 绘制焦点标记
    setfillcolor(CLR_RED);
    solidcircle(leftF, CENTER_Y, 8);
    
    // 焦点内圆
    setfillcolor(CLR_WHITE);
    solidcircle(leftF, CENTER_Y, 4);
    
    settextcolor(CLR_RED);
    settextstyle(22, 0, _T("微软雅黑"));
    outtextxy(leftF - 15, CENTER_Y - 80, _T("F"));
    
    // 绘制左侧2F点
    int left2F = LENS_X - 2 * FOCAL_LENGTH;
    setlinecolor(CLR_GREEN);
    setlinestyle(PS_DASH, 2);
    line(left2F, CENTER_Y - 50, left2F, CENTER_Y + 50);
    
    setfillcolor(CLR_GREEN);
    solidcircle(left2F, CENTER_Y, 8);
    
    setfillcolor(CLR_WHITE);
    solidcircle(left2F, CENTER_Y, 4);
    
    settextcolor(CLR_GREEN);
    outtextxy(left2F - 20, CENTER_Y - 80, _T("2F"));
    
    // 绘制右侧焦点F'
    int rightF = LENS_X + FOCAL_LENGTH;
    setlinecolor(CLR_RED);
    setlinestyle(PS_DASH, 2);
    line(rightF, CENTER_Y - 50, rightF, CENTER_Y + 50);
    
    setfillcolor(CLR_RED);
    solidcircle(rightF, CENTER_Y, 8);
    
    setfillcolor(CLR_WHITE);
    solidcircle(rightF, CENTER_Y, 4);
    
    settextcolor(CLR_RED);
    outtextxy(rightF - 15, CENTER_Y - 80, _T("F'"));
    
    // 绘制右侧2F点
    int right2F = LENS_X + 2 * FOCAL_LENGTH;
    setlinecolor(CLR_GREEN);
    setlinestyle(PS_DASH, 2);
    line(right2F, CENTER_Y - 50, right2F, CENTER_Y + 50);
    
    setfillcolor(CLR_GREEN);
    solidcircle(right2F, CENTER_Y, 8);
    
    setfillcolor(CLR_WHITE);
    solidcircle(right2F, CENTER_Y, 4);
    
    settextcolor(CLR_GREEN);
    outtextxy(right2F - 20, CENTER_Y - 80, _T("2F'"));
}

// 绘制箭头
void drawArrow(int x, int y, bool isRealObject = true, double scale = 1.0, bool isUpright = true, bool isImage = false) {
    // 计算缩放后的尺寸
    int scaledHeight = static_cast<int>(ARROW_HEIGHT * scale);
    int scaledWidth = static_cast<int>(ARROW_WIDTH * scale);
    int scaledHeadSize = static_cast<int>(ARROW_HEAD_SIZE * scale);
    
    // 设置颜色
    COLORREF arrowColor;
    if (isRealObject) {
        arrowColor = CLR_YELLOW;  // 物体箭头用黄色
    } else if (isRealImage) {
        arrowColor = CLR_RED;     // 实像箭头用红色
    } else {
        arrowColor = CLR_PURPLE;  // 虚像箭头用紫色
    }
    
    setlinecolor(arrowColor);
    setlinestyle(PS_SOLID, 2);
    
    // 计算箭头的顶部和底部位置
    int arrowTopY, arrowBottomY;
    if (isUpright) {
        arrowTopY = y - scaledHeight/2;
        arrowBottomY = y + scaledHeight/2;
    } else {
        arrowTopY = y + scaledHeight/2;
        arrowBottomY = y - scaledHeight/2;
    }
    
    // 绘制箭头主体
    line(x, arrowBottomY, x, arrowTopY);
    
    // 绘制箭头头部
    if (isUpright) {
        // 箭头向上
        line(x, arrowTopY, x - scaledHeadSize/2, arrowTopY + scaledHeadSize);
        line(x, arrowTopY, x + scaledHeadSize/2, arrowTopY + scaledHeadSize);
    } else {
        // 箭头向下
        line(x, arrowTopY, x - scaledHeadSize/2, arrowTopY - scaledHeadSize);
        line(x, arrowTopY, x + scaledHeadSize/2, arrowTopY - scaledHeadSize);
    }
    
    // 如果是虚像,用虚线绘制
    if (!isRealObject && !isRealImage) {
        setlinestyle(PS_DASH, 2);
        // 重新绘制虚线箭头
        line(x, arrowBottomY, x, arrowTopY);
        if (isUpright) {
            line(x, arrowTopY, x - scaledHeadSize/2, arrowTopY + scaledHeadSize);
            line(x, arrowTopY, x + scaledHeadSize/2, arrowTopY + scaledHeadSize);
        } else {
            line(x, arrowTopY, x - scaledHeadSize/2, arrowTopY - scaledHeadSize);
            line(x, arrowTopY, x + scaledHeadSize/2, arrowTopY - scaledHeadSize);
        }
        setlinestyle(PS_SOLID, 1); // 恢复线型
    }
    
    // 绘制箭头底座(小横线)
    setlinestyle(PS_SOLID, 2);
    line(x - scaledWidth/2, arrowBottomY, x + scaledWidth/2, arrowBottomY);
    
    // 标注
    settextcolor(arrowColor);
    settextstyle(18, 0, _T("微软雅黑"));
    
    if (isRealObject) {
        outtextxy(x - 25, arrowTopY - 40, _T("物体"));
    } else {
        string label = isImage ? "像" : "";
        outtextxy(x - 10, (isUpright ? arrowTopY - 40 : arrowTopY + 20), label.c_str());
    }
}

// 绘制像 - 使用箭头样式
void drawImageArrow() {
    if (imageX == 0) return; // 不成像
    
    // 绘制像箭头
    drawArrow(static_cast<int>(imageX), static_cast<int>(imageY), 
              false, fabs(magnification), isUpright, true);
    
    // 标注像的性质
    settextcolor(isRealImage ? CLR_RED : CLR_PURPLE);
    settextstyle(18, 0, _T("微软雅黑"));
    
    string imageType = isRealImage ? "实像" : "虚像";
    string orientation = isUpright ? "正立" : "倒立";
    string sizeType;
    
    if (fabs(magnification) > 1.05) sizeType = "放大";
    else if (fabs(magnification) < 0.95) sizeType = "缩小";
    else sizeType = "等大";
    
    stringstream label;
    label << imageType << " " << orientation << " " << sizeType;
    
    int labelY = (isUpright && imageY < CENTER_Y) ? imageY - ARROW_HEIGHT * fabs(magnification)/2 - 60 : 
                (!isUpright && imageY > CENTER_Y) ? imageY + ARROW_HEIGHT * fabs(magnification)/2 + 20 :
                imageY - 40;
    
    outtextxy(static_cast<int>(imageX) - 40, static_cast<int>(labelY), label.str().c_str());
}

// 绘制光线路径 - 修正版
void drawRays() {
    if (!drawAllRays) return;
    
    // 物体箭头顶部坐标
    int objectTopX = arrowX;
    int objectTopY = arrowY - ARROW_HEIGHT/2; // 箭头顶部
    
    // 物体箭头底部坐标
    int objectBottomX = arrowX;
    int objectBottomY = arrowY + ARROW_HEIGHT/2; // 箭头底部
    
    // 像箭头顶部坐标
    double imageTopY = imageY + (isUpright ? -imageHeight/2 : imageHeight/2);
    
    // 绘制三条主要光线
    
    // 光线1: 平行于主光轴的光线,经过透镜后通过焦点
    setlinecolor(CLR_RAY1);
    setlinestyle(PS_SOLID, 2);
    
    // 从物体顶部到透镜(平行于光轴)
    line(objectTopX, objectTopY, LENS_X, objectTopY);
    
    if (isRealImage && imageX != 0) {
        // 实像情况:光线通过透镜后经过焦点并到达像点
        int rightF = LENS_X + FOCAL_LENGTH;
        line(LENS_X, objectTopY, rightF, CENTER_Y);
        line(rightF, CENTER_Y, static_cast<int>(imageX), static_cast<int>(imageTopY));
    } else if (!isRealImage && imageX != 0) {
        // 虚像情况:反向延长线经过同侧焦点
        setlinestyle(PS_DASH, 2); // 反向延长线用虚线
        int leftF = LENS_X - FOCAL_LENGTH;
        line(LENS_X, objectTopY, leftF, CENTER_Y);
        
        // 从反向延长线的交点继续延伸到像点
        line(leftF, CENTER_Y, static_cast<int>(imageX), static_cast<int>(imageTopY));
        
        // 实际光线继续直线传播(实线)
        setlinestyle(PS_SOLID, 2);
        line(LENS_X, objectTopY, LENS_X + 100, objectTopY);
    }
    
    // 光线2: 通过光心的光线,方向不变
    setlinecolor(CLR_RAY2);
    setlinestyle(PS_SOLID, 2);
    line(objectTopX, objectTopY, LENS_X, CENTER_Y);
    
    if (isRealImage && imageX != 0) {
        // 实像情况:继续直线传播到像点
        line(LENS_X, CENTER_Y, static_cast<int>(imageX), static_cast<int>(imageTopY));
    } else if (!isRealImage && imageX != 0) {
        // 虚像情况:反向延长线
        setlinestyle(PS_DASH, 2);
        line(LENS_X, CENTER_Y, static_cast<int>(imageX), static_cast<int>(imageTopY));
    }
    
    
    
    // 恢复线型
    setlinestyle(PS_SOLID, 1);
}

// 绘制连接线 - 从物体到像点
void drawConnectionLines() {
    if (imageX == 0) return;
    
    // 物体箭头顶部坐标
    int objectTopX = arrowX;
    int objectTopY = arrowY - ARROW_HEIGHT/2;
    
    // 物体箭头底部坐标
    int objectBottomX = arrowX;
    int objectBottomY = arrowY + ARROW_HEIGHT/2;
    
    // 像箭头顶部坐标
    double imageTopY = imageY + (isUpright ? -imageHeight/2 : imageHeight/2);
    
    // 绘制从物体顶部到像点的辅助线(虚线)
    setlinecolor(RGB(150, 150, 200));
    setlinestyle(PS_DASH, 1);
    
    // 连接物体顶部和像点顶部
    line(objectTopX, objectTopY, static_cast<int>(imageX), static_cast<int>(imageTopY));
    
    // 连接物体底部和像点底部(如果像有足够高度)
    if (imageHeight > 10) {
        double imageBottomY = imageY + (isUpright ? imageHeight/2 : -imageHeight/2);
        line(objectBottomX, objectBottomY, static_cast<int>(imageX), static_cast<int>(imageBottomY));
    }
    
    // 恢复线型
    setlinestyle(PS_SOLID, 1);
}

// 绘制位置标记线
void drawPositionMarkers() {
    setlinecolor(RGB(120, 120, 140));
    setlinestyle(PS_DOT, 1);
    
    // 从箭头到底部画垂直线
    line(arrowX, arrowY - ARROW_HEIGHT/2 - 30, arrowX, arrowY + ARROW_HEIGHT/2 + 30);
    
    // 从像到底部画垂直线
    if (imageX != 0) {
        line(static_cast<int>(imageX), static_cast<int>(imageY) - static_cast<int>(imageHeight)/2 - 30, 
             static_cast<int>(imageX), static_cast<int>(imageY) + static_cast<int>(imageHeight)/2 + 30);
    }
}

// 创建渐变背景
void createGradientBackground() {
    // 创建深色渐变背景
    for (int i = 0; i < SCREEN_HEIGHT; i++) {
        float t = (float)i / SCREEN_HEIGHT;
        int r = 15 + static_cast<int>(t * 30);
        int g = 15 + static_cast<int>(t * 30);
        int b = 25 + static_cast<int>(t * 40);
        setlinecolor(RGB(r, g, b));
        line(0, i, SCREEN_WIDTH, i);
    }
}

// 显示成像信息 - 优化版
void showInfo() {
    double u = LENS_X - arrowX; // 物距
    double f = FOCAL_LENGTH;     // 焦距
    double v = (imageX == 0) ? 0 : imageX - LENS_X; // 像距
    
    // 在屏幕右侧创建信息面板
    setfillcolor(CLR_INFO_BG);
    solidrectangle(SCREEN_WIDTH - 350, 30, SCREEN_WIDTH - 30, SCREEN_HEIGHT - 30);
    
    // 绘制面板边框
    setlinecolor(RGB(100, 150, 255));
    setlinestyle(PS_SOLID, 3);
    rectangle(SCREEN_WIDTH - 350, 30, SCREEN_WIDTH - 30, SCREEN_HEIGHT - 30);
    
    settextcolor(CLR_YELLOW);
    settextstyle(26, 0, _T("微软雅黑"));
    outtextxy(SCREEN_WIDTH - 320, 50, _T("凸透镜成像规律"));
    
    // 创建信息字符串
    stringstream info;
    info.precision(2);
    info << fixed;
    
    info << "\n物距 u = " << fabs(u)/10 << " cm";
    info << "\n焦距 f = " << f/10 << " cm";
    
    if (imageX != 0) {
        info << "\n像距 v = " << fabs(v)/10 << " cm";
        info << "\n放大率 m = " << fabs(magnification);
        
        if (fabs(magnification) > 1.05) {
            info << " (放大)";
        } else if (fabs(magnification) < 0.95) {
            info << " (缩小)";
        } else {
            info << " (等大)";
        }
        
        info << "\n像的性质: ";
        if (isRealImage) {
            info << "实像";
        } else {
            info << "虚像";
        }
        
        info << ", ";
        if (isUpright) {
            info << "正立";
        } else {
            info << "倒立";
        }
    } else {
        info << "\n像距 v = ∞ (不成像)";
        info << "\n放大率 m = ∞";
        info << "\n像的性质: 无像(平行光)";
    }
    
    // 显示成像情况说明
    string situation;
    if (u > 2*f) {
        situation = "物体在二倍焦距外\n→ 倒立、缩小的实像";
    } else if (fabs(u - 2*f) < 1.0) {
        situation = "物体在二倍焦距上\n→ 倒立、等大的实像";
    } else if (u > f && u < 2*f) {
        situation = "物体在一二倍焦距之间\n→ 倒立、放大的实像";
    } else if (fabs(u - f) < 1.0) {
        situation = "物体在焦点上\n→ 不成像(平行光)";
    } else if (u < f && u > 0) {
        situation = "物体在焦点内\n→ 正立、放大的虚像";
    } else if (u < 0) {
        situation = "物体在透镜右侧\n→ 特殊情况";
    }
    
    // 在信息面板中显示信息
    settextcolor(CLR_WHITE);
    settextstyle(18, 0, _T("微软雅黑"));
    
    // 分割信息字符串并逐行显示
    string infoStr = info.str();
    size_t pos = 0;
    size_t prev = 0;
    int lineY = 100;
    while ((pos = infoStr.find('\n', prev)) != string::npos) {
        string line = infoStr.substr(prev, pos - prev);
        outtextxy(SCREEN_WIDTH - 320, lineY, line.c_str());
        prev = pos + 1;
        lineY += 35;
    }
    // 显示最后一行
    string lastLine = infoStr.substr(prev);
    outtextxy(SCREEN_WIDTH - 320, lineY, lastLine.c_str());
    
    // 显示成像情况
    settextcolor(CLR_GREEN);
    lineY += 50;
    
    // 分割多行文本
    pos = 0;
    prev = 0;
    while ((pos = situation.find('\n', prev)) != string::npos) {
        string line = situation.substr(prev, pos - prev);
        outtextxy(SCREEN_WIDTH - 320, lineY, line.c_str());
        prev = pos + 1;
        lineY += 35;
    }
    string lastSituation = situation.substr(prev);
    outtextxy(SCREEN_WIDTH - 320, lineY, lastSituation.c_str());
    
    // 显示操作提示
    settextcolor(CLR_GRAY);
    settextstyle(16, 0, _T("微软雅黑"));
    outtextxy(SCREEN_WIDTH - 320, SCREEN_HEIGHT - 150, _T("操作说明:"));
    outtextxy(SCREEN_WIDTH - 320, SCREEN_HEIGHT - 125, _T("1. 拖动箭头左右/上下移动"));
    outtextxy(SCREEN_WIDTH - 320, SCREEN_HEIGHT - 100, _T("2. 空格键: 特殊位置对齐"));
    outtextxy(SCREEN_WIDTH - 320, SCREEN_HEIGHT - 75, _T("3. R键: 重置"));
    outtextxy(SCREEN_WIDTH - 320, SCREEN_HEIGHT - 50, _T("4. G键: 切换光线显示"));
    outtextxy(SCREEN_WIDTH - 320, SCREEN_HEIGHT - 25, _T("5. ESC键: 退出"));
}

// 显示菜单窗口
void drawMenuWindow() {
    // 绘制菜单背景
    setfillcolor(CLR_MENU_BG);
    solidrectangle(SCREEN_WIDTH/2 - 220, SCREEN_HEIGHT/2 - 180, 
                  SCREEN_WIDTH/2 + 220, SCREEN_HEIGHT/2 + 180);
    
    // 绘制菜单边框
    setlinecolor(CLR_YELLOW);
    setlinestyle(PS_SOLID, 4);
    rectangle(SCREEN_WIDTH/2 - 220, SCREEN_HEIGHT/2 - 180, 
              SCREEN_WIDTH/2 + 220, SCREEN_HEIGHT/2 + 180);
    
    // 绘制标题
    settextcolor(CLR_YELLOW);
    settextstyle(28, 0, _T("微软雅黑"));
    outtextxy(SCREEN_WIDTH/2 - 120, SCREEN_HEIGHT/2 - 160, _T("选择对齐位置"));
    
    settextstyle(22, 0, _T("微软雅黑"));
    
    // 菜单选项
    outtextxy(SCREEN_WIDTH/2 - 180, SCREEN_HEIGHT/2 - 100, _T("1. 2F点 (二倍焦距)"));
    outtextxy(SCREEN_WIDTH/2 - 180, SCREEN_HEIGHT/2 - 60, _T("2. F点 (焦点)"));
    outtextxy(SCREEN_WIDTH/2 - 180, SCREEN_HEIGHT/2 - 20, _T("3. 焦点内 (F/2)"));
    outtextxy(SCREEN_WIDTH/2 - 180, SCREEN_HEIGHT/2 + 20, _T("4. 2F点外 (3F)"));
    outtextxy(SCREEN_WIDTH/2 - 180, SCREEN_HEIGHT/2 + 60, _T("5. 默认位置"));
    outtextxy(SCREEN_WIDTH/2 - 180, SCREEN_HEIGHT/2 + 100, _T("6. 无限远 (10F)"));
    
    settextcolor(CLR_GRAY);
    outtextxy(SCREEN_WIDTH/2 - 180, SCREEN_HEIGHT/2 + 140, _T("按对应数字键选择,ESC取消"));
}

// 将箭头对齐到特殊位置
void alignToSpecialPoint(int pointType) {
    switch(pointType) {
        case 1: // 2F点
            arrowX = LENS_X - 2 * FOCAL_LENGTH;
            arrowY = CENTER_Y; // 重置到光轴
            break;
        case 2: // F点
            arrowX = LENS_X - FOCAL_LENGTH;
            arrowY = CENTER_Y;
            break;
        case 3: // 焦点内
            arrowX = LENS_X - FOCAL_LENGTH / 2;
            arrowY = CENTER_Y;
            break;
        case 4: // 2F点外
            arrowX = LENS_X - 3 * FOCAL_LENGTH;
            arrowY = CENTER_Y;
            break;
        case 5: // 默认位置
            arrowX = LENS_X - 400;
            arrowY = CENTER_Y;
            break;
        case 6: // 无限远
            arrowX = LENS_X - 10 * FOCAL_LENGTH;
            arrowY = CENTER_Y;
            break;
        default:
            arrowX = LENS_X - 400;
            arrowY = CENTER_Y;
    }
    calculateImage();
}

// 主函数
int main() {
    // 初始化图形窗口
    initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);
    
    // 使用setaspectratio设置高精度渲染
    // 注意:这里设置坐标轴比例为1:1,确保图形不变形
    setaspectratio(1, 1);
    
    // 设置背景色
    setbkcolor(CLR_BLACK);
    cleardevice();
    
    // 创建背景
    createGradientBackground();
    
    // 计算初始像的位置
    calculateImage();
    
    // 主循环
    while (true) {
        // 清屏
        //cleardevice();
        BeginBatchDraw();
        // 重新绘制背景
        createGradientBackground();
        
        // 绘制所有元素
        if (drawAllRays) {
            drawRays();
        }
        drawConnectionLines();
        drawPositionMarkers();
        drawLens();
        drawFocalPoints();
        drawArrow(arrowX, arrowY, true, 1.0, true, false); // 绘制物体箭头
        drawImageArrow();
        showInfo();
        
        // 如果显示菜单窗口,绘制菜单
        if (showMenuWindow) {
            drawMenuWindow();
        }
        
        // 处理鼠标事件
        if (MouseHit()) {
            MOUSEMSG msg = GetMouseMsg();
            
            // 检查是否点击了箭头
            if (msg.uMsg == WM_LBUTTONDOWN) {
                if (!showMenuWindow && 
                    msg.x >= arrowX - ARROW_WIDTH - 15 && 
                    msg.x <= arrowX + ARROW_WIDTH + 15 &&
                    msg.y >= arrowY - ARROW_HEIGHT/2 - 15 && 
                    msg.y <= arrowY + ARROW_HEIGHT/2 + 15) {
                    isDragging = true;
                    lastMouseX = msg.x;
                    lastMouseY = msg.y;
                }
            }
            
            // 处理拖动
            if (msg.uMsg == WM_MOUSEMOVE && isDragging) {
                // 计算鼠标移动距离
                int deltaX = msg.x - static_cast<int>(lastMouseX);
                int deltaY = msg.y - static_cast<int>(lastMouseY);
                
                // 更新箭头位置
                int newX = arrowX + deltaX;
                int newY = arrowY + deltaY;
                
                // 限制边界
                if (newX < 80) newX = 80; // 左边界
                if (newX > LENS_X - 15) newX = LENS_X - 15; // 不能超过透镜
                if (newY < 100) newY = 100; // 上边界
                if (newY > SCREEN_HEIGHT - 100) newY = SCREEN_HEIGHT - 100; // 下边界
                
                arrowX = newX;
                arrowY = newY;
                
                lastMouseX = msg.x;
                lastMouseY = msg.y;
                calculateImage(); // 重新计算像的位置
            }
            
            // 停止拖动
            if (msg.uMsg == WM_LBUTTONUP) {
                isDragging = false;
            }
        }
        
        // 检查键盘输入
        if (_kbhit()) {
            char key = _getch();
            if (key == 27) { // ESC键
                if (showMenuWindow) {
                    showMenuWindow = false;
                } else {
                    break;
                }
            }
            
            // 空格键显示/隐藏菜单窗口
            if (key == ' ') {
                showMenuWindow = !showMenuWindow;
            }
            
            // G键切换光线显示
            if (key == 'g' || key == 'G') {
                drawAllRays = !drawAllRays;
            }
            
            // 如果在菜单窗口模式下,处理数字键选择
            if (showMenuWindow) {
                switch(key) {
                    case '1': alignToSpecialPoint(1); showMenuWindow = false; break;
                    case '2': alignToSpecialPoint(2); showMenuWindow = false; break;
                    case '3': alignToSpecialPoint(3); showMenuWindow = false; break;
                    case '4': alignToSpecialPoint(4); showMenuWindow = false; break;
                    case '5': alignToSpecialPoint(5); showMenuWindow = false; break;
                    case '6': alignToSpecialPoint(6); showMenuWindow = false; break;
                }
            }
            
            // R键重置
            if (key == 'r' || key == 'R') {
                arrowX = LENS_X - 400;
                arrowY = CENTER_Y;
                calculateImage();
                showMenuWindow = false;
            }
        }
        FlushBatchDraw();
        // 短暂延迟,减少CPU占用
       // Sleep(1);
    }
    EndBatchDraw();
    // 关闭图形窗口
    closegraph();
    return 0;
}