代码之家  ›  专栏  ›  技术社区  ›  Tolgahan Albayrak

关于:矩形旋转和拟合

  •  3
  • Tolgahan Albayrak  · 技术社区  · 16 年前

    经过一番艰苦的工作,我的大脑出了问题。。(土耳其时间是晚上11:40)

    我在做轮换工作

    变量:

    _cx = horizontal center of rect
    _cy = vertical center of rect
    _cos = cos value of current angle
    _sin = sin value of current angle
    
    to rotating any point in this rect :
    
    function getx(x, y)
    {
          return _cx + _cos * (x - _cx) - _sin * (y - _cy);
    }
    function gety(x, y)
    {
          return _cy + _sin * (x - _cx) + _cos * (y - _cy);
    }
    

    我试图在旋转过程之前调整给定矩形的大小,使其达到符合原始边界的最大大小。。我怎么办?

    谢谢你的帮助

    编辑:Igor Krivokon的解决方案

    这个问题由Igor Krivokon解决,下面是该解决方案的修改版本,它适用于每个角度值

    var h1:Number, h2:Number, hh:Number, ww:Number,
        degt:Number, d2r:Number, r2d:Number, deg:Number,
        sint:Number, cost:Number;
    //@angle = given angle in radians
    //@r is source/target rectangle
    //@d2r is static PI / 180 constant for degree -> radian conversation
    //@r2d is static 180 / PI constant for radian -> degree conversation
    d2r = 0.017453292519943295769236907683141;
    r2d = 57.295779513082320876798154814105;
    deg = Math.abs(angle * r2d) % 360;
    if(deg < 91)
    {
        degt = angle;
    }else if(deg < 181){
        degt = (180 - deg) * d2r;
    }else if(deg < 271){
        degt = (deg - 180) * d2r;
    }else{
        degt = (360 - deg) * d2r;
    }
    
    sint = Math.sin(degt);
    cost = Math.cos(degt);
    
    h1 = r.height * r.height / (r.width * sint + r.height * cost);
    h2 = r.height * r.width / (r.width * cost + r.height * sint);
    hh = Math.min(h1, h2);
    ww = hh * r.width / r.height;
    r.x = (r.width - ww) * .5;
    r.y = (r.height - hh) * .5;
    r.height = hh;
    r.width = ww;
    

    谢谢

    4 回复  |  直到 9 年前
        1
  •  5
  •   Igor Krivokon    16 年前

    如果您的原始尺寸为h和w,且旋转角度为φ,请尝试计算新高度

    h1 = h*h / (w*sin(phi) + h*cos(phi))
    

    h2 = h*w / (w*cos(phi) + h*sin(phi))
    

    并选择劈高h'作为h1和h2中的最小值。

    然后,很明显,新的宽度 w' = h' * w / h .

    请试一试——我没有时间考数学:)

        2
  •  0
  •   ryansstack    16 年前

    将矩形划分为4个较小的矩形。沿对角线将其切成两半(在旋转之前,从一个角到一个中心点),您将有8个三角形。你只需要4个。旋转后,这些三角形的斜边将伸出原始边界框。

    确定斜边的公式(原始角度为45,-45,135,-135,起点为mx+b),变换这些线(通过添加旋转修改其坡度),使这些线与边界墙相交(y=0,y=w,x=0,x=h,距离公式,无限情况下的测试)&找出哪个斜边最短(从中心到墙,在拐角处)。由于所有斜边的起始长度相同,只需将所有斜边的大小调整为这个新值,就有了新的矩形。

        3
  •  0
  •   krubo    16 年前
    function resize_factor()
    {
        /* Find how far the upper-left corner sticks up beyond the top */
        overtop = gety(0, 0);
        /* Compute a vertical resize factor that would put that point at the top */
        /* (be sure to use floating point arithmetic) */
        vertical_resize = _cy / (_cy - overtop);
    
        /* Do the same for the lower-left corner sticking out beyond the left */
        /* (using 2*_cy for the height of the rectangle) */
        overleft = getx(0, 2*_cy);    
        horizontal_resize = _cx / (_cx - overleft);
    
        /* Return whichever resize constraint is stricter */
        return min(vertical_resize, horizontal_resize);
    }
    
    function resize_x(x)
    {
        /* To get location of a point, after resize, before rotation... */
        /* ...multiply its resize factor by its distance from the center. */
        return resize_factor()*(x - _cx) + _cx;
    }
    
    function resize_y(y)
    {
        return resize_factor()*(y - _cy) + _cy;
    }
    
    /* These resized coordinates can be used inside any other code you want: */
    function getx_after_resize_and_rotate(x, y)
    {
        return getx( resized_x(x), resized_y(y) );
    }
    

    注意:此代码假设角度顺时针旋转小于90度(因为这是图片显示的角度)。如果您的角度是其他角度,您可能需要检查所有4个角,并确定哪一个角是最远的超高和超高。

        4
  •  0
  •   bajie    14 年前
        fitRect: function( rw,rh,radians ){
                var x1 = -rw/2,
                    x2 = rw/2,
                    x3 = rw/2,
                    x4 = -rw/2,
                    y1 = rh/2,
                    y2 = rh/2,
                    y3 = -rh/2,
                    y4 = -rh/2;
    
                var x11 = x1 * Math.cos(radians) + y1 * Math.sin(radians),
                    y11 = -x1 * Math.sin(radians) + y1 * Math.cos(radians),
                    x21 = x2 * Math.cos(radians) + y2 * Math.sin(radians),
                    y21 = -x2 * Math.sin(radians) + y2 * Math.cos(radians), 
                    x31 = x3 * Math.cos(radians) + y3 * Math.sin(radians),
                    y31 = -x3 * Math.sin(radians) + y3 * Math.cos(radians),
                    x41 = x4 * Math.cos(radians) + y4 * Math.sin(radians),
                    y41 = -x4 * Math.sin(radians) + y4 * Math.cos(radians);
    
                var x_min = Math.min(x11,x21,x31,x41),
                    x_max = Math.max(x11,x21,x31,x41);
    
                var y_min = Math.min(y11,y21,y31,y41);
                    y_max = Math.max(y11,y21,y31,y41);
    
                return [x_max-x_min,y_max-y_min];
            }