python - 糟糕的数学或糟糕的编程,也许两者兼而有之?

标签 python geometry python-imaging-library

我正在编写一个 Python 程序来生成海因莱因著名小说 The Moon is a Harsh Mistress 中的 Luna Free State 旗帜。 ,作为个人项目。我一直在抄袭网络上的纹章规则和匹配数学公式,但我的 bendsinister 例程显然有问题,因为断言在未注释时失败。险恶弯曲的面积应该是旗帜总面积的 1/3,但事实并非如此。我做过的唯一真正狡猾的事情是猜测梯形高度的公式,但我猜错误可能在任何地方。我已经删除了大部分代码,只留下显示问题所必需的代码。希望数学水平较低的人能够发现错误!

#!/usr/bin/python
'generate bend sinister according to rules of heraldry'
import sys, os, random, math, Image, ImageDraw
FLAG = Image.new('RGB', (900, 600), 'black')
CANVAS = ImageDraw.Draw(FLAG)
DEBUGGING = True

def bendsinister(image = FLAG, draw = CANVAS):
 '''a bend sinister covers 1/3 of the field, sinister chief to dexter base

    (some sources on the web say 1/5 of the field, but we'll use 1/3)
    the "field" in this case being the area of the flag, so we need to
    find a trapezoid which is 1/6 the total area (width * height).

    we need to return only the width of the diagonal, which is double
    the height of the calculated trapezoid
 '''
 x, y = image.size
 b = math.sqrt((x ** 2) + (y ** 2))
 A = float(x * y)
 debug('%d * %d = %d' % (x, y, A))
 H = triangle_height(A / 2, b)  # height of triangular half of flag
 width = trapezoid_height(b, H, A / 6) * 2
 if command == 'bendsinister':
  show_bendsinister(x, y, width, image, draw)
 return width

def show_bendsinister(x, y, width, image = FLAG, draw = CANVAS):
 'for debugging formula'
 dexter_base, sinister_chief = (0, y), (x, 0)
 draw.line((dexter_base, sinister_chief), 'blue', int(width))
 image.show()
 debug(image.getcolors(2))  # should be twice as many black pixels as blue

def triangle_height(a, b):
 'a=bh/2'
 h = float(a) / (float(b) / 2)
 debug('triangle height: %.2f' % h)
 return h

def trapezoid_height(b, H, a):
 '''calculate trapezoid height (h) given the area (a) of the trapezoid and
    base b, the longer base, when it is known that the trapezoid is a section
    of a triangle of height H, such that the top, t, equals b when h=0 and
    t=0 when h=H. h is therefore inversely proportional to t with the formula
    t=(1-(h/H))*b, found simply by looking for what fit the two extremes.
    the area of a trapezoid is simply the height times the average length of
    the two bases, b and t, i.e.: a=h*((b+t)/2). the formula reduces
    then to (2*a)/b=(2*h)+(h**2)/H, which is the quadratic equation
    (1/H)*(h**2)+(2*h)-((2*a)/b)=0; solve for h using the quadratic formula
 '''
 try:
  h = (-2 + math.sqrt(4 - 4 * (1.0 / H) * -((2 * a) / b))) / (2 * (1.0 / H))
  debug('trapezoid height with plus: %.2f' % h)
 except:  # must be imaginary, so try minus instead
  h = (-2 - math.sqrt(4 - 4 * (1.0 / H) * -((2 * a) / b))) / (2 * (1.0 / H))
  debug('trapezoid height with minus: %.2f' % h)
 t = (1 - (float(h) / H)) * b
 debug('t=%d, a=%d, check=%d' % (t, round(a), round(h * ((b + t) / 2))))
 #assert round(a) == round(h * ((b + t) / 2))
 return h

def debug(message):
 if DEBUGGING:
  print >>sys.stderr, message

if __name__ == '__main__':
 command = os.path.splitext(os.path.basename(sys.argv[0]))[0]
 print eval(command)(*sys.argv[1:]) or ''

这是调试输出,显示我离 1/3 区域很远:

jcomeau@intrepid:~/rentacoder/jcomeau/tanstaafl$ ./bendsinister.py 
900 * 600 = 540000
triangle height: 499.23
trapezoid height with plus: 77.23
t=914, a=90000, check=77077
[(154427, (0, 0, 255)), (385573, (0, 0, 0))]
154.462354191

这是输出图像,添加了一些行: bend sinister 红线分出两个三角形,都可以用来计算梯形。我正在使用从左上角开始的那个。绿线就是那个三角形的高,就是程序中的变量H。


对于完成的脚本和标志(使用 Michael Anderson 提供的更正),请参阅 http://unternet.net/tanstaafl/ .感谢大家的帮助!

最佳答案

将矩形分成两个三角形。它们将是相同的。

黑色三角形+蓝色梯形是三角形A。 黑色三角形本身就是三角形 B

三角形 A 和三角形 B 是相似三角形,因此它们的面积与相关比例因子的平方相关。

我们希望蓝色梯形占三角形 A 面积的三分之一。(这样弯曲将占据整个矩形的三分之一)。这意味着三角形 B 必须是三角形 A 的 2/3 面积。因此比例因子必须是 sqrt(2/3)。

然后您应该能够轻松地将其转换为弯曲几何体的坐标。

关于python - 糟糕的数学或糟糕的编程,也许两者兼而有之?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5786573/

相关文章:

python - 无法在 Linux mint 中更改 Python3 中的文件夹

python - Twisted lineReceived 没有被调用

c++ - 光线追踪器 : High FOV distortion

algorithm - 如果旅行推销员乘飞机旅行怎么办?

python - 如何将 numpy 数组保存到 webp 文件?

python - 找出网格中的最大颜色数

python - 在数轴上设置范围的好方法是什么?

math - 围绕一个点旋转 Vector2

python - 使用 Python/PIL 或类似工具来缩小空格

python - 无法正确克隆 cStringIO 对象