You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

左手坐标系极坐标转屏幕笛卡尔坐标:适配90度旋转问题

问题描述

设备生成左手坐标系下的极坐标(角度、幅值),需要转换为以屏幕中心为原点的笛卡尔坐标并绘制线段。采用C++在WT32-SC01屏幕上实现,该屏幕的tft.drawLine函数以左上角(0,0)为像素原点。现有部分代码,但需完成左手坐标系与屏幕坐标系的转换,同时处理平面90度旋转的适配。

现有代码片段:

....
int screen_height = tft.height();
int screen_width = tft.width();
// Device can read to 12m and reports in mm
float zoom_factor = (screen_width / 2.0) / 12000.0;
int originY = (int)(screen_height / 2);
int originX = (int)(screen_width / 2);
// Offset is for screen scrolling. No screen offset to start
int offsetX = 0;
int offsetY = 0;
...
// ld06 holds the reported angles and distances.
Coord coord = polarToCartesian(ld06.angles[i], ld06.distances[i]);
drawVector(coord, WHITE);

Coord polarToCartesian(float theta, float r) {
  // cos() and sin() take radians
  float rad = theta * 0.017453292519;
  Coord converted = {
    (int)(r * cos(rad)),
    (int)(r * sin(rad))
  };
  return converted;
}

void drawVector(Coord coord, int color) {
  // Cartesian relative the center of the screen factoring zoom and pan
  int destX = (int)(zoom_factor * coord.x) + originX + offsetX;
  int destY = originY - (int)(zoom_factor * coord.y) + offsetY;
  // From the middle of the screen (origin X, origin Y) to destination x,y
  tft.drawLine( originX, originY, destX, destY, color);
}
解决方案

1. 明确坐标系映射关系

先理清三个核心坐标系的差异:

  • 设备左手极坐标系:原点为设备中心,0度指向正上方,角度顺时针递增,幅值为距离(单位mm)。
  • 屏幕中心笛卡尔坐标系:原点为屏幕中心,X轴向右为正,Y轴向下为正。
  • 屏幕像素坐标系:原点为左上角(0,0),X轴向右为正,Y轴向下为正。

2. 修改极坐标转笛卡尔坐标函数

调整polarToCartesian函数,适配左手系角度方向和90度旋转需求:

Coord polarToCartesian(float theta, float r) {
  // 将角度转换为弧度
  float rad = theta * 0.017453292519;
  // 左手系顺时针角度转换为屏幕中心坐标系的坐标:
  // - X方向:对应角度的sin值(顺时针90度为X正方向)
  // - Y方向:取角度cos值的负数(设备0度向上对应屏幕Y轴负方向)
  Coord converted = {
    (int)(r * sin(rad)),
    (int)(-r * cos(rad))
  };
  return converted;
}

3. 修正屏幕像素坐标计算

调整drawVector函数中的坐标转换逻辑,因上述步骤已处理Y轴方向,无需再对Y值取反:

void drawVector(Coord coord, int color) {
  // 计算目标像素坐标:屏幕中心原点 + 缩放后的坐标 + 偏移量
  int destX = originX + offsetX + (int)(zoom_factor * coord.x);
  int destY = originY + offsetY + (int)(zoom_factor * coord.y);
  // 从屏幕中心绘制到目标点
  tft.drawLine(originX, originY, destX, destY, color);
}

4. 微调适配(按需)

如果绘制的向量方向仍有偏差,可根据实际设备的角度定义调整:

  • 若设备0度指向正右而非正上,可在弧度计算时添加偏移:rad = (theta - 90.0f) * 0.017453292519;
  • 若角度递增方向为逆时针,可将sin(rad)改为sin(-rad),cos(rad)改为cos(-rad)

内容的提问来源于stack exchange,提问作者CarbonMan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 23:33:30