Pyslvs 開發進度:
- 三角求解器模組
Pyslvs 開發進度
三角求解器模組
寫了一個小模組求解,還未連接使用者界面。
主要功能是傳入一個 list(包含大量題目)並解題。不過 class 裡的函式可以單獨使用。
from math import *
##Directions:
##[{'p1':Point1, 'p2':Point2, 'len1':Line1, ('len2':Line2, 'angle':angle)}, ...]
class solver():
def __init__(self, Directions=list()):
#Cosine Theorem
self.CosineTheoremAngle = lambda a, b, c: acos((b**2+c**2-a**2)/(2*b*c))
self.CosineTheoremSide = lambda alpha, b, c: b**2+c**2-2*b*c*cos(alpha)
self.Directions = Directions
def set(self, Directions): self.Directions = Directions
def answer(self):
answer = self.Iterator() if self.Parser() else None
self.Directions.clear()
return answer
def Parser(self):
for e in self.Directions:
pos = self.Directions.index(e)
if e.get('p1', False) is False: return False
if e.get('p2', False) is False: return False
if e.get('len1', False) is False: return False
if e.get('len2', False) is False and e.get('angle', False) is False: return False
if e.get('len2', False) is False: self.Directions[pos]['Type'] = 'PLAP'
elif e.get('angle', False) is False: self.Directions[pos]['Type'] = 'PLLP'
return True
def Iterator(self):
results = list()
for e in self.Directions:
p1 = results[e['p1']] if type(e['p1'])==int else e['p1']
p2 = results[e['p2']] if type(e['p2'])==int else e['p2']
#Direction of the point
other = e.get('other', False)
##True: angle1-angle2
##False: angle1+angle2
if e['Type']=='PLAP': results.append(self.PLAP(p1, e['len1'], e['angle'], p2, other))
elif e['Type']=='PLLP': results.append(self.PLLP(p1, e['len1'], e['len2'], p2, other))
return results
def PLAP(self, p1, line1, angle, p2, other=False):
x1 = p1[0]
y1 = p1[1]
len1 = float(line1)
angle2 = radians(float(angle))
angle1 = self.m(p1, p2)
if other:
cx = x1+len1*cos(angle1-angle2)
cy = y1+len1*sin(angle1-angle2)
else:
cx = x1+len1*cos(angle1+angle2)
cy = y1+len1*sin(angle1+angle2)
return cx, cy
def PLLP(self, p1, line1, line2, p2, other=False):
x1 = p1[0]
y1 = p1[1]
x2 = p2[0]
y2 = p2[1]
len1 = float(line1)
len2 = float(line2)
d = sqrt((x1-x2)**2+(y2-y1)**2)
angle1 = self.m(p1, p2)
angle2 = self.CosineTheoremAngle(len2, d, len1)
if other:
cx = x1+len1*cos(angle1-angle2)
cy = y1+len1*sin(angle1-angle2)
else:
cx = x1+len1*cos(angle1+angle2)
cy = y1+len1*sin(angle1+angle2)
return cx, cy
def m(self, p1, p2):
x1 = p1[0]
y1 = p1[1]
x2 = p2[0]
y2 = p2[1]
x = x2-x1
y = y2-y1
d = sqrt(x**2+y**2)
return self.CosineTheoremAngle(y, x, d)*(-1 if y<0 else 1)*(-1 if x<0 else 1)
if __name__=='__main__':
#Test
s = solver([
{'p1':(-60, 0), 'p2':(0, 0), 'len1':30, 'angle':50}, #C
{'p1':0, 'p2':(0, 0), 'len1':50, 'len2':60}, #D
{'p1':0, 'p2':1, 'len1':50, 'len2':50}, #E
])
print("C={}\nD={}\nE={}".format(*s.answer()))
##cx= -40.716371709403816 cy= 22.98133329356934
##dx= -6.698073034033397 dy= 59.62495968661744
##ex= -55.44153371488418 ey= 70.76385733649067
解題方向指定 p1、p2、len1、angle 或 len2,Parser 會檢查填入項的完整性;Iterator 會自動判斷輸入內容選擇解題。
而 p1 與 p2 的座標是使用 list 或 tuple 型態給兩個座標軸(取 [0]、[1]),或是引用上一個解(之後會增加順序檢查機制)。其他數據皆為 float 型態。
角度方面使用 degree,不過 Python 的 math 模組是用 radian,途中會進行轉換。
原理都是先求 AB 與水平夾的角度(angle1),最後將 CAB 夾角(angle2)加上 angle1 求 AC 與水平夾的角度,最後求出 C 點座標。
之中為了方便,將餘弦定理做成 lambda 使用。
程式可能還有一些漏洞,接上 Gui 之前會再檢查一遍。
Comments
comments powered by Disqus