1

特定の座標系で2Dディスプレイのデータを受け取るソフトウェアをプログラミングしています。ここで、(0,0) は左上隅、x 軸は右方向、y 軸は下方向です。

私のグラフ作成ライブラリは、 (0,0) を左下隅と見なすPython ライブラリpygletです。x 軸は右に伸びますが (変換は必要ありません)、y 軸は上に伸びます。したがって、受け取ったデータの座標をグラフ ライブラリに直接渡すことはできません。

y 軸成分をどのように変換できますか?

4

1 に答える 1

0

graphing_heightグラフ ライブラリがビューをサポートしている場合は、をに設定できるはずです-non_graphing_height。ビューの位置が中央にある場合は変更する必要はありません。左下にある場合は、に設定graphic_bottom_leftするnon_graphing_top_left + non_graphing_height必要があります。

C++ で SFML ライブラリを使用すると、次のようになります。

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 の場合、代わりに射影行列に適用できます。

ビューがない場合は、ビュー マトリックスを使用して再作成できるはずです。その後、そのビュー マトリックスをグラフィック ライブラリに渡すことができるはずです。

ビューマトリックスを渡すことができない場合は、それらを非グラフ変換に適用して、グラフ変換を取得します。これを取得すると、グラフィック ライブラリに渡すことができる変換マトリックスが得られます。

グラフィックス ライブラリがそれを渡すことをサポートしていない場合は、変換された行列を変換、回転、およびスケールに分解できます。

非グラフィック ライブラリの 0,0 から 200,200 までのビューでこれを行う、SFML ライブラリを使用しない C++ の関数の例を次に示します。

/// 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();
}

3D では、回転は複数の値またはクォータニオンである可能性があるため、それをサポートする Matrix クラスがあることを確認してください。

上記の例で使用した Vector2 および Matrix クラスの例を次に示します。

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_;
};
于 2020-11-28T16:36:36.617 に答える