所以我需要将TRectF装入另一个TRectF并获得比例因子,但所有都存储在Single变量中。 问题是我失去了精度,所以我如何得到最接近的值可以存储在单个?
中示例:
LToFit := TRectF.Create( 0, 0, 320, 480 );
LRect := TRectF.Create( 0, 0, 841, 613 );
LRatio := Min(
LRect.Width / LToFit.FWidth,
LRect.Height / LToFit.FHeight
);
// The value of LRatio is 1.27708327770233
// Now i want that result is Pixel aligned so
LAdd.X := Floor( LToFit.FWidth * LRatio ) mod 2;
LAdd.Y := Floor( LToFit.FHeight * LRatio ) mod 2;
if LRect.Width > LRect.Height then
LRatio := ( Floor( LToFit.FWidth * LRatio ) + LAdd.X ) / FViewer.FView.FWidth
else
LRatio := ( Floor( LToFit.FHeight * LRatio ) + LAdd.Y ) / FViewer.FView.FHeight;
// The value of LRatio is 1.27499997615814
Ecc ......结果是可以接受的。但是现在假设LRect在高度上有-3,所以:
LToFit := TRectF.Create( 0, 0, 320, 480 );
LRect := TRectF.Create( 0, 0, 841, 610 );
LRatio := Min(
LRect.Width / LToFit.FWidth,
LRect.Height / LToFit.FHeight
);
// The value of LRatio is 1.27083337306976
// Now i want that result is Pixel aligned so
LAdd.X := Floor( LToFit.FWidth * LRatio ) mod 2;
LAdd.Y := Floor( LToFit.FHeight * LRatio ) mod 2;
if LRect.Width > LRect.Height then
LRatio := ( Floor( LToFit.FWidth * LRatio ) + LAdd.X ) / FViewer.FView.FWidth
else
LRatio := ( Floor( LToFit.FHeight * LRatio ) + LAdd.Y ) / FViewer.FView.FHeight;
// The value of LRatio is 1.26874995231628
Ecc ...所以在第一种情况下,LRatio为674高度为1.27499997615814,在第二种情况下,对于610 Heigh,LRatio为1.26874995231628。
其他测试:
LRatio Height
A 1.27499997615814 611
B 1.26874995231628 610< - not accettable
C 1.26874995231628 609< - not accettable
D 1.26874995231628 608< - not accettable
E 1.26250004768372 607
问题是如何将B和C的LRatio限制为A和D进入E? 还有其他公式?
所有这一切都是为了设置使用单一类型变量的Matrix Scaling。
感谢。
更新:
我尝试这个:
S1 := 0;
S2 := 1 / Power( 2, 23 );
while S1 < LRatio do
begin
S1 := S1 + 0.0625 + S2;
end;
LRatio := S1 - S2;
似乎工作但我不知道为什么!计算也比较贵:(
更新2:
好的,不使用LAdd我计算从605到619的LRect高度。你怎么看我只需要黄色值。但我不能喜欢这个公式:
(目的地高度):(比例)(ToFit Scaled Height(Rounded))(圆角结果H:W)
解决方案? :
我找不到更多“数学”的东西,我会满足于这个我认为符合我需要的功能。 我仍然会对建议表示感谢。
function GetRoundedScale( const ARect, AIntoRect: TRectF ): Single;
var
LScaled: TPointF;
LOffSet: Integer;
begin
Result := Min(
AIntoRect.Width / ARect.Width,
AIntoRect.Height / ARect.Height
);
LScaled := TPointF.Create( ARect.Width * Result, ARect.Height * Result );
LOffSet := 0;
while Odd( Round( LScaled.X ) ) or Odd( Round( LScaled.Y ) ) do
begin
Inc( LOffSet );
Result := Min(
( AIntoRect.Width + LOffSet ) / ARect.Width,
( AIntoRect.Height + LOffSet ) / ARect.Height
);
LScaled := TPointF.Create( ARect.Width * Result, ARect.Height * Result );
end;
end;