C# 计算TranslateTransform后的最大可用面积

C# 计算TranslateTransform后的最大可用面积,c#,.net,winforms,drawing,rectangles,C#,.net,Winforms,Drawing,Rectangles,假设我想在windows窗体内绘制一个有角度的矩形 我可以用它来做这件事 private void Form1_Paint(object sender, PaintEventArgs e) { e.Graphics.RotateTransform(20); e.Graphics.DrawRectangle(Pens.Black, 0, 0, e.ClipRectangle.Width, e.ClipRectangle.Height); }

假设我想在windows窗体内绘制一个有角度的矩形

我可以用它来做这件事

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.RotateTransform(20);
        e.Graphics.DrawRectangle(Pens.Black, 0, 0, e.ClipRectangle.Width, e.ClipRectangle.Height);
    }
但这只会旋转矩形,因此缺少左侧和底部部分

但我真正想做的是,我想画一个最大的矩形,在我的形状内有一个特定的角度,像这样


做这件事最好的方法是什么?

我画了一些草图来解决这个问题。这个问题更多的是关于数学而不是编程,但这是我的想法。我画过,但试着遵循:

旋转矩形时,需要为其计算
newWidth
newHeight
。使用这些尺寸创建一个新矩形,并将其放置在左上角,就像当前矩形一样。alpha
α
表示要旋转的度数。旋转后,需要将此新矩形向右移动,
X
。然后,将最大的矩形完美地放置在绘图区域中

下面是代码的一些想法。我还没有测试过:

private void Form1_Paint(object sender, PaintEventArgs e)
    {
        double angle = 20;

        double width = Convert.ToDouble(e.ClipRectangle.Width),
               height = Convert.ToDouble(e.ClipRectangle.Height),
               h = Math.Sqrt((width*width) + (height*height)),
               y = (width/h);

        int newHeight = Convert.ToInt32(height*y),
            newWidth = Convert.ToInt32(width*y),
            x = Convert.ToInt32((Math.Sin(angle) * height);

        e.Graphics.RotateTransform(angle);
        e.Graphics.DrawRectangle(Pens.Black, x, 0, newWidth, newHeight);
    }

我们可以找到θ角的矩形,它接触所有四条边。如果我们让W,H为我们窗户的宽度和高度,以弧度表示的角度,这些都是事先知道的。现在,让a,b为矩形的宽度和高度,我们尝试将其放入框中,这是我们希望找到的两个值。设x0,y0为窗口中心点的坐标x0=W/2,y0=H/2。矩形的一个角将是

x1 = x0 - 0.5 * a * sin(th) + 0.5 * b * cos(th)
y1 = y0 + 0.5 * a * cos(th) + 0.5 * b * sin(th)
另一点是相似的,但符号不同。一点三角学就能说明这一点

使矩形接触到我们想要的边

a * sin(th) + b cos(th) = W
a * cos(th) + b sin(th) = H
这给了我们一对联立方程,我们可以求解。第一个乘以sin(th),第二个乘以cos(th)

减去

a ( sin(th) sin(th) - cos(th) cos(th) ) = W sin(th) - H cos(th)
除以(sin(th)sin(th)-cos(th)cos(th))得到

类似的过程也会产生类似的结果

b = (H sin(th) - W cos(th)) / ( sin(th) sin(th) - cos(th) cos(th) )
一旦我们有了a和b,我们就可以计算矩形的角并绘制它

我把代码放在一个JSFIDLE中,代码是

// canvas and mousedown related variables
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var scrollX = $canvas.scrollLeft();
var scrollY = $canvas.scrollTop();
// save canvas size to vars b/ they're used often
var W = canvas.width;
var H = canvas.height;

 var spinner = $( "#startAng" ).spinner({ 
  spin: function( event, ui ) {
    if ( ui.value > 180 ) {
      $( this ).spinner( "value", ui.value - 360 );
        draw();
      return false;
    } else if ( ui.value < -180 ) {
      $( this ).spinner( "value", ui.value + 360 );
        draw();
      return false;
    }
    draw();
  }
});


var angle = 10.0;

function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
angle = $("#startAng").spinner("value");
var th = Math.PI*angle/180.0;
var S = Math.sin(th);
var C = Math.cos(th);
var S2 = S*S - C*C;
var a = (W*S-H*C)/S2;
var b = (H*S-W*C)/S2;
var x0 = W/2;
var y0 = H/2;
//alert("angle "+angle+"S "+S+" "+C+" "+a+" "+b);
var x1 = x0 - 0.5 * a * Math.sin(th) + 0.5 * b * Math.cos(th);
var y1 = y0 + 0.5 * a * Math.cos(th) + 0.5 * b * Math.sin(th);

var x2 = x0 - 0.5 * a * Math.sin(th) - 0.5 * b * Math.cos(th);
var y2 = y0 + 0.5 * a * Math.cos(th) - 0.5 * b * Math.sin(th);

var x3 = x0 + 0.5 * a * Math.sin(th) + 0.5 * b * Math.cos(th);
var y3 = y0 - 0.5 * a * Math.cos(th) + 0.5 * b * Math.sin(th);

var x4 = x0 + 0.5 * a * Math.sin(th) - 0.5 * b * Math.cos(th);
var y4 = y0 - 0.5 * a * Math.cos(th) - 0.5 * b * Math.sin(th);

ctx.beginPath();
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.lineTo(x4,y4);
ctx.lineTo(x3,y3);
ctx.lineTo(x1,y1);
ctx.closePath();
ctx.stroke();
}

$( ".ui-spinner-input" ).on( "spinchange", draw );
$( ".ui-spinner-input" ).on( "spinstop", draw );
$( "#baseRad" ).on( "spin", draw );

draw();
//画布和鼠标向下相关变量
var canvas=document.getElementById(“canvas”);
var ctx=canvas.getContext(“2d”);
var$canvas=$(“#canvas”);
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var scrollX=$canvas.scrollLeft();
var scrollY=$canvas.scrollTop();
//将画布大小保存到vars b/它们经常使用
var W=画布宽度;
var H=画布高度;
变量微调器=$(“#startAng”)。微调器({
自旋:函数(事件、ui){
如果(ui.value>180){
$(this.spinner(“value”,ui.value-360);
draw();
返回false;
}否则如果(ui.value<-180){
$(this.spinner(“value”,ui.value+360);
draw();
返回false;
}
draw();
}
});
var角=10.0;
函数绘图(){
clearRect(0,0,canvas.width,canvas.height);
角度=$(“#startAng”)。微调器(“值”);
var th=数学PI*角度/180.0;
var S=数学sin(th);
var C=数学cos(th);
var S2=S*S-C*C;
var a=(W*S-H*C)/S2;
VarB=(H*S-W*C)/S2;
var x0=W/2;
var y0=H/2;
//警报(“角度”+角度+“S”+S+“”+C+“”+a+“”+b);
var x1=x0-0.5*a*Math.sin(th)+0.5*b*Math.cos(th);
变量y1=y0+0.5*a*Math.cos(th)+0.5*b*Math.sin(th);
var x2=x0-0.5*a*Math.sin(th)-0.5*b*Math.cos(th);
变量y2=y0+0.5*a*Math.cos(th)-0.5*b*Math.sin(th);
var x3=x0+0.5*a*Math.sin(th)+0.5*b*Math.cos(th);
变量y3=y0-0.5*a*Math.cos(th)+0.5*b*Math.sin(th);
var x4=x0+0.5*a*数学正弦(th)-0.5*b*数学正弦(th);
变量y4=y0-0.5*a*Math.cos(th)-0.5*b*Math.sin(th);
ctx.beginPath();
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.lineTo(x4,y4);
ctx.lineTo(x3,y3);
ctx.lineTo(x1,y1);
ctx.closePath();
ctx.stroke();
}
$(.ui微调器输入”)。打开(“微调更改”,绘制);
$(.ui微调器输入”)。打开(“旋转停止”,绘制);
美元(“#baseRad”)。在(“旋转”,绘制);
draw();
注意,这不一定给出最大的矩形,因为可能有较大的矩形接触两侧,并且可能的角度也有一些限制

b = (H sin(th) - W cos(th)) / ( sin(th) sin(th) - cos(th) cos(th) )
// canvas and mousedown related variables
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var scrollX = $canvas.scrollLeft();
var scrollY = $canvas.scrollTop();
// save canvas size to vars b/ they're used often
var W = canvas.width;
var H = canvas.height;

 var spinner = $( "#startAng" ).spinner({ 
  spin: function( event, ui ) {
    if ( ui.value > 180 ) {
      $( this ).spinner( "value", ui.value - 360 );
        draw();
      return false;
    } else if ( ui.value < -180 ) {
      $( this ).spinner( "value", ui.value + 360 );
        draw();
      return false;
    }
    draw();
  }
});


var angle = 10.0;

function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
angle = $("#startAng").spinner("value");
var th = Math.PI*angle/180.0;
var S = Math.sin(th);
var C = Math.cos(th);
var S2 = S*S - C*C;
var a = (W*S-H*C)/S2;
var b = (H*S-W*C)/S2;
var x0 = W/2;
var y0 = H/2;
//alert("angle "+angle+"S "+S+" "+C+" "+a+" "+b);
var x1 = x0 - 0.5 * a * Math.sin(th) + 0.5 * b * Math.cos(th);
var y1 = y0 + 0.5 * a * Math.cos(th) + 0.5 * b * Math.sin(th);

var x2 = x0 - 0.5 * a * Math.sin(th) - 0.5 * b * Math.cos(th);
var y2 = y0 + 0.5 * a * Math.cos(th) - 0.5 * b * Math.sin(th);

var x3 = x0 + 0.5 * a * Math.sin(th) + 0.5 * b * Math.cos(th);
var y3 = y0 - 0.5 * a * Math.cos(th) + 0.5 * b * Math.sin(th);

var x4 = x0 + 0.5 * a * Math.sin(th) - 0.5 * b * Math.cos(th);
var y4 = y0 - 0.5 * a * Math.cos(th) - 0.5 * b * Math.sin(th);

ctx.beginPath();
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.lineTo(x4,y4);
ctx.lineTo(x3,y3);
ctx.lineTo(x1,y1);
ctx.closePath();
ctx.stroke();
}

$( ".ui-spinner-input" ).on( "spinchange", draw );
$( ".ui-spinner-input" ).on( "spinstop", draw );
$( "#baseRad" ).on( "spin", draw );

draw();