请注意,必须有整数个正方形来填充宽度和高度。因此,纵横比必须是一个有理数。
输入:width
(float或int),height
算法:
aspectRatio = RationalNumber(width/height).lowestTerms #must be rational number
# it must be the case that our return values
# numHorizontalSqaures/numVerticalSquares = aspectRatio
return {
numHorizontalSquares = aspectRatio.numerator,
numVerticalSquares = aspectRatio.denominator,
squareLength = width/aspectRatio.numerator
}
如果宽度/高度是一个有理数,那么你的答案只是纵横比的任意倍数!(例如,如果你的纵横比是4/3,你可以用4x3个长width/4
=height/3
的正方形来填充,或者用8x6个一半大小的正方形,或者用12x9个三分之一大小的正方形…)如果它不是有理数,你的任务就不可能完成。
通过对分子和分母进行因子分解,并删除所有重复的因子对,可以将分数转换为最低项;这相当于只使用最大公约数算法GCD(numer,denom)
,并将分子和分母都除以它。
以下是python3中的一个示例实现:
from fractions import Fraction
def largestSquareTiling(width, height, maxVerticalSquares=10**6):
"""
Returns the minimum number (corresponding to largest size) of square
which will perfectly tile a widthxheight rectangle.
Return format:
(numHorizontalTiles, numVerticalTiles), tileLength
"""
if isinstance(width,int) and isinstance(height,int):
aspectRatio = Fraction(width, height)
else:
aspectRatio = Fraction.from_float(width/height)
aspectRatio2 = aspectRatio.limit_denominator(max_denominator=maxVerticalSquares)
if aspectRatio != aspectRatio2:
raise Exception( too many squares ) #optional
aspectRatio = aspectRatio2
squareLength = width/aspectRatio.numerator
return (aspectRatio.numerator, aspectRatio.denominator), squareLength
例如。
>>> largestSquareTiling(2.25, 11.75)
((9, 47), 0.25)
You can tune the optional parameter maxVerticalSquares
to give yourself more robustness versus floating-point imprecision (but the downside is the operation may fail), or to avoid a larger number of vertical squares (例如。 if this is architecture code and you are tiling a floor); depending on the range of numbers you are working with, a default value of maxVerticalSquares=500
might be reasonable or something (possibly not even including the exception code).
一旦你有了这个,以及一个所需的平方长度范围(minLength,maxLength)
,你只需要乘以:
# inputs
desiredTileSizeRange = (0.9, 0.13)
(minHTiles, minVTiles), maxTileSize = largestSquareTiling(2.25, 11.75)
# calculate integral shrinkFactor
shrinkFactorMin = maxTileSize/desiredTileSizeRange[0]
shrinkFactorMax = maxTileSize/desiredTileSizeRange[1]
shrinkFactor = int(scaleFactorMax)
if shrinkFactor<shrinkFactorMin:
raise Exception( desired tile size range too restrictive; no tiling found )
例如,如果shrinkFactor
现在为2
,则示例中的新输出值将为((9*2,47*2),0.25/2)
。