c++ - 矩形边界内的旋转线

标签 c++ algorithm drawing linear-algebra trigonometry

我试图实现的是围绕矩形中心旋转一条线,以便它始终保持在接触它们的边界内(或有一些填充)。 现在我有以下例程,如您所见,我使用 tan 计算将我的矩形分成 8 个部分(红线)

它到目前为止有效,但由于某种原因,我使用其他计算半径绘图(绿线)时出现不一致,这些线并不总是按预期匹配,我想知道为什么。

基本上,仅使用 sin/cos 计算并找到直线和矩形边界之间的交叉点就可以实现相同的效果,但由于某种原因我无法让它工作。

    std::pair<Point, Point>
    MathUtils::calculateRotatingLine(Size size, double degrees)
    {
        auto width = size.width;
        auto height = size.height;

        double diagonalAngleTopRight = radiansToDegrees(atan((width / 2) / (height / 2)));
        double diagonalAngleBottomRight = 90 + (90 - diagonalAngleTopRight);
        double diagonalAngleBottomLeft = 180 + diagonalAngleTopRight;
        double diagonalAngleTopLeft = 180 + diagonalAngleBottomRight;
        double x, y;

        /*
         *  *8*1*
         * 7*   *2
         * 6*   *3
         *  *5*4*
         */

        // 1
        if (degrees >= 0 && degrees <= diagonalAngleTopRight) {
            x = width / 2 + height / 2 * tan(degreesToRadians(degrees));
            y = 0;
        }
        // 2
        else if (degrees > diagonalAngleTopRight && degrees <= 90) {
            x = width;
            y = width / 2 * tan(degreesToRadians(degrees - diagonalAngleTopRight));
        }
        // 3
        else if (degrees > 90 && degrees <= diagonalAngleBottomRight) {
            x = width;
            y = height / 2 + width / 2 * tan(degreesToRadians(degrees - 90));
        }
        // 4
        else if (degrees > diagonalAngleBottomRight && degrees <= 180) {
            x = width - height / 2 * tan(degreesToRadians(degrees - diagonalAngleBottomRight));
            y = height;
        }
        // 5
        else if (degrees > 180 && degrees <= diagonalAngleBottomLeft) {
            x = width / 2 - height / 2 * tan(degreesToRadians(degrees - 180));
            y = height;
        }
        // 6
        else if (degrees > diagonalAngleBottomLeft && degrees <= 270) {
            x = 0;
            y = height - width / 2 * tan(degreesToRadians(degrees - diagonalAngleBottomLeft));
        }
        // 7
        else if (degrees > 270 && degrees <= diagonalAngleTopLeft) {
            x = 0;
            y = height / 2 - width / 2 * tan(degreesToRadians(degrees - 270));
        }
        // 8
        else {
            x = height / 2 * tan(degreesToRadians(degrees - diagonalAngleTopLeft));
            y = 0;
        }

        return {Point{width / 2, height / 2}, Point{x, y}};
    }

绿线计算

    Point
    MathUtils::calculateCirclePoint(double radius, double degrees)
    {
        return {radius * cos(degreesToRadians(degrees)), radius * sin(degreesToRadians(degrees))};
    }

enter image description here

编辑

太棒了,多亏了@MBo,它才有效

    Point
    MathUtils::calculateCrossPoint(Size size, double degrees)
    {
        auto x0 = size.width / 2;
        auto y0 = size.height / 2;

        auto vx = cos(degreesToRadians(degrees - 90));
        auto vy = sin(degreesToRadians(degrees - 90));

        //potential border positions
        auto ex = vx > 0 ? size.width : 0;
        auto ey = vy > 0 ? size.height : 0;

        //check for horizontal/vertical directions
        if (vx == 0) {
            return {x0, ey};
        }

        if (vy == 0) {
            return {ex, y0};
        }

        // in general case find times of intersections with horizontal and vertical edge line
        auto tx = (ex - x0) / vx;
        auto ty = (ey - y0) / vy;

        // and get intersection for smaller parameter value
        if (tx <= ty) {
            return {ex, y0 + tx * vy};
        }

        return {x0 + ty * vx, ey};
    }

最佳答案

用于查找从矩形中心(角度 an 以弧度表示)发出的光线与边的交点的伪代码。 (也适用于其他 (x0,y0) 位置)

x0 = width / 2; 
y0 = height / 2; 
vx = cos(an);
vy = sin(an);

//potential border positions    
ex = vx > 0? width: 0
ey = vy > 0? height: 0

 //check for horizontal/vertical directions
if vx = 0 then
   return cx = x0,  cy = ey
if vy = 0 then
    return cx = ex, cy = y0

//in general case find times of intersections with horizontal and vertical edge line
  tx = (ex - x0) / vx
  ty = (ey - y0) / vy

 //and get intersection for smaller parameter value
 if tx <= ty then 
    return cx = ex, cy = y0 + tx * vy
 else
    return cx = x0 + ty * vx,  cy = ey

关于c++ - 矩形边界内的旋转线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53761001/

相关文章:

r - 在 R 中的多列上绘制每行直方图

c++ - std::includes in c++ 算法的复杂性

c++ - 过滤 Eclipse 的 C++ 内容辅助

C++ 无法让 cin 从文件重定向中读取结束行字符

algorithm - 我如何找到时间复杂度 T(n) 并证明它是有界的(Big Theta)?

algorithm - 微语法分析器的递归方法

c# - WPF 中的快速二维图形

wpf - 使用 System.Drawing.Graphics 在 WPF 上绘图?

c++ - 在 pybind11 和 C++ 中添加源时,没有给出目标错误的源代码

c++ - 求二叉搜索树的中位数,C++