从一个二维坐标系转换为另一个具有不同(0,0)的二维坐标系



我正在编程一个软件,在该软件中,我接收给定坐标系中2D显示的数据,其中(0,0(是左上角,x轴向右增长,y轴向下增长。

我的图形库是Python库pyglet,它认为(0,0(是左下角。x轴向右增长(不需要转换(,但y轴向上增长。因此,我无法将接收到的数据中的坐标直接传递到绘图库。

我可以用哪种方式转换y轴分量?

如果图形库支持视图,那么您应该能够将graphing_height设置为-non_graphing_height。如果视图的位置是中心,则不需要更改;如果是左下角,则应将graphic_bottom_left设置为non_graphing_top_left + non_graphing_height

这在带有SFML库的C++中可能是这样的:

const auto& current_view = window.getView();
const auto& current_view_size = current_view.getSize();
window.setView(sf::View(current_view.getCenter(), { current_view_size.x, -current_view_size.y }));

如果是在3D中,则可以将其应用于投影矩阵。

如果没有视图,您应该能够使用视图矩阵重新创建它们。然后,您应该能够将该视图矩阵传递到图形库中。

如果不能传入视图矩阵,则将其应用于非图形变换以获得图形变换。一旦你有了,你将有一个变换矩阵,你可以传递到你的图形库。

如果图形库不支持传入,也可以将转换后的矩阵分解为平移、旋转和缩放。

以下是C++中一个没有SFML库的函数的示例,该函数将在非图形库中使用从0,0到200200的视图来执行此操作:

/// transform the passed in position, rotation and scale
/// param rotation radians
void transform(Vector2& position, float& rotation, Vector2& scale) {
// create a transformation matrix from the position, rotation and scale
const Matrix transform_matrix{ position, rotation, scale };
// create a upside down view matrix at origin of size 200x200
const Vector2 view_position{
0.f,
0.f
};
const Vector2 view_size{
200.f,
200.f
};
const Matrix view_matrix =
Matrix::translation({ -view_position.x, -(view_position.y + view_size.y) }) *
Matrix::scale({ 1.f / view_size.x, -1.f / view_size.y });
// multiply the transformation matrix with the view matrix
const auto multiplied = transform_matrix * view_matrix;
// update the passed in values
position = multiplied.getTranslation();
rotation = multiplied.getAngle();
scale = multiplied.getScale();
}

请注意,在三维中,旋转可能是多个值或一个四元数,因此请确保您有一个支持这一点的"矩阵"类。

以下是Vector2和Matrix类I的示例,用于上面的示例:

struct Vector2 {
float x;
float y;
};
class Matrix {
public:
/// creates a matrix using passed in matrix
Matrix(const std::vector<std::vector<float>>& matrix) :
matrix_{ matrix }
{}
/// creates 2d transformation matrix
/// param angle radians
Matrix(const Vector2& translation, const float angle, const Vector2& scale) :
Matrix({
{ scale.x * cos(angle), scale.y * sin(angle), 0.f },
{ -scale.x * sin(angle), scale.x * cos(angle), 0.f },
{ translation.x, translation.y, 1.f }
})
{}
/// create 2d translation matrix
static Matrix translation(const Vector2& translation) {
return Matrix({
{ 1.f, 0.f, 0.f },
{ 0.f, 1.f, 0.f },
{ translation.x, translation.y, 1.f }
});
}
/// create 2d scale matrix
static Matrix scale(const Vector2& scale) {
return Matrix({
{ scale.x, 0.f, 0.f },
{ 0.f, scale.y, 0.f },
{ 0.f, 0.f, 1.f }
});
}
/// multiplies two matrices together
Matrix operator*(const Matrix& rhs) const {
// get number of rows, columns and elements
const auto rows = matrix_.size();
const auto columns = rhs.matrix_[0].size();
const auto elements = rhs.matrix_.size();
// create a new matrix of the correct size, filled with zeroes
Matrix new_matrix(
std::vector<std::vector<float>>(
rows, std::vector<float>(columns, 0.f)
)
);
// go through each row of the new matrix
for (size_t row = 0; row < rows; ++row) {
// go through each column of the new matrix
for (size_t column = 0; column < columns; ++column) {
// set element in the new matrix to the dot product of this matrix's row and the rhs matrix's column
for (size_t element = 0; element < elements; ++element) {
new_matrix.matrix_[row][column] +=
matrix_[row][element] * rhs.matrix_[element][column];
}
}
}
return new_matrix;
}
/// gets the translation from the matrix
Vector2 getTranslation() const {
return { matrix_[2][0], matrix_[2][1] };
}
/// gets the positive scale from the matrix
Vector2 getScale() const {
Vector2 scale{
sqrt(pow(matrix_[0][0], 2) + pow(matrix_[0][1], 2)),
sqrt(pow(matrix_[1][0], 2) + pow(matrix_[1][1], 2))
};
if (matrix_[0][0] < 0) {
scale.x = -scale.x;
}
if (matrix_[1][1] < 0) {
scale.y = -scale.y;
}
return scale;
}
/// gets the angle from the matrix
/// returns radians
float getAngle() const {
return atan2(matrix_[0][1], std::abs(matrix_[1][1]));
}
private:
std::vector<std::vector<float>> matrix_;
};

相关内容

  • 没有找到相关文章

最新更新