强基初中数学&学Python——第一百课 解三角形模块

​'''
解三角形
@作者  码老师
@微信公众号  学思营 IDxuesying
@公司  深圳五行星软件有限公司
@日期  2021-6-1(更新)

@使用方法
from solvingtriangle import Triangle #导入解三角形对象
1、已知三边
  Triangle(12,13,7)
2、已知一边二角
  Triangle(12,A=35,B=67)Triangle(a=12,A=35,B=67)Triangle(a=12,B=35,C=67)
  Triangle(b=12,A=35,B=67)Triangle(b=12,A=35,B=67)Triangle(b=12,B=35,C=67)
  Triangle(c=12,A=35,B=67)Triangle(c=12,A=35,B=67)Triangle(c=12,B=35,C=67)
3、边角边
  Triangle(12,15,C=67)Triangle(a=12,b=15,C=67)
  Triangle(a=12,c=15,B=67)
  Triangle(b=12,c=15,A=67)
4、其它二边一角——不是直角三角形无解
  Triangle(12,12sinB,B=67)Triangle(12sinA,12,A=67)
  Triangle(12,b=12sinB,B=67)Triangle(12sinA,b=12,A=67)
  Triangle(a=12,b=12sinB,B=67)Triangle(a=12sinA,b=12,A=67)
  Triangle(b=12,c=12sinC,C=67)Triangle(b=12sinB,c=12,B=67)
  Triangle(a=12,c=12sinC,C=67)Triangle(a=12sinA,c=12,A=67)
  Triangle(12,c=12sinC,C=67)Triangle(12sinA,c=12,A=67)
5、已解三角形内切圆
    _radius(半径), _distance(里A角距离), _angle(与AB的夹角) = Triangle.createIncircle()
6、已解三角形外接圆
    _radius, _distance, _angle = Triangle.createCircumcircle()

打印结果:
  print(Triangle(12,13,7))
'''
from math import *
zeroNum=0.0001  #判断0
def adjust(val):
    if abs(val)<zeroNum:
        return 0
    elif abs(abs(val)-1)<zeroNum:
        if val>0:
            return 1
        else:
            return -1
    else:
        return val
class Triangle():
    #是否已经初始化
    __initOk=False
    def isInit(self):
        return self.__initOk
    #
    __a=None
    def geta(self):
        return self.__a
    __b=None
    def getb(self):
        return self.__b    
    __c=None
    def getc(self):
        return self.__c
    #
    __A=None
    def getA(self):
        return self.__A
    __B=None
    def getB(self):
        return self.__B    
    __C=None
    def getC(self):
        return self.__C
        
    #解决钝角三角形问题
    def __solvObtuseAngle(self):
        if abs(self.__A+self.__B+self.__C-pi)>=zeroNum:
            if self.__a>max(self.__b,self.__c):
                self.__A=pi-self.__A
            elif self.__b>max(self.__a,self.__c):
                self.__B=pi-self.__B
            else:
                self.__C=pi-self.__C
    #三边初始化——解三角形
    def __initE3(self, a, b, c, A, B, C):
        if a<=0 or b<=0 or c<=0:
            return False
        if a+b<=c or a+c<=b or b+c<=a:           
            return True
        #用秦九韶公式计算三角形的2倍面积
        _2S=(a**2*b**2-((a**2+b**2-c**2)/2)**2)**.5
        #_2S=a*c*sin(B)
        self.__A=asin(adjust(_2S/(b*c)))
        self.__B=asin(adjust(_2S/(a*c)))
        self.__C=asin(adjust(_2S/(a*b)))
        self.__a=a
        self.__b=b
        self.__c=c
        #解决钝角三角形问题
        self.__solvObtuseAngle()
        self.__initOk=True
        return True

    #31边初始化——解三角形
    def __initE1A3(self, a, b, c):
        #absin∠C=acsin∠B=bcsin∠A
        if a>0:
            self.__a=a
            self.__b=a*sin(self.__B)/sin(self.__A)
            self.__c=a*sin(self.__C)/sin(self.__A)
        elif b>0:
            self.__b=b
            self.__a=b*sin(self.__A)/sin(self.__B)
            self.__c=b*sin(self.__C)/sin(self.__B)
        elif c>0:
            self.__c=c
            self.__a=c*sin(self.__A)/sin(self.__C)
            self.__b=c*sin(self.__B)/sin(self.__C)
    #21边初始化——解三角形
    def __initE1A2(self, a, b, c, A, B, C):        
        if a<=0:
            if (b<=0) ^ (c<=0):
                pass
            else:
                return False
        else:
            if b<=0 and c<=0:
                pass
            else:
                return False
        if A<=0:
            if B<=0 or C<=0 or B+C>=180:
                print("三角∠A=%s∠B=%s∠C=%s不能构成三角形!" % (str(A), str(B), str(C)))
                return True
            self.__B=B*pi/180
            self.__C=C*pi/180
            self.__A=pi-self.__B-self.__C
            #初始化边
            self.__initE1A3( a, b, c)
        elif B<=0:
            if A<=0 or C<=0 or A+C>=180:
                print("三角∠A=%s∠B=%s∠C=%s不能构成三角形!" % (str(A), str(B), str(C)))
                return True
            self.__A=A*pi/180
            self.__C=C*pi/180
            self.__B=pi-self.__A-self.__C
            #初始化边
            self.__initE1A3( a, b, c)
        elif C<=0:
            if A<=0 or B<=0 or A+B>=180:
                print("三角∠A=%s∠B=%s∠C=%s不能构成三角形!" % (str(A), str(B), str(C)))
                return True
            self.__A=A*pi/180
            self.__B=B*pi/180
            self.__C=pi-self.__A-self.__B
            #初始化边
            self.__initE1A3( a, b, c)
        else:
            if A+B+C!=180:
                print("三角∠A=%s∠B=%s∠C=%s不能构成三角形!" % (str(A), str(B), str(C)))
                return True
            self.__A=A*pi/180
            self.__B=B*pi/180
            self.__C=C*pi/180
            #初始化边
            self.__initE1A3( a, b, c)            
        self.__initOk=True
        return True

    #21角初始化——解三角形
    def __initE2A1(self, a, b, c, A, B, C):
        #边角边       
        if a>0 and b>0 and c<=0:
            if C>0 and C<180: #a,bC
                self.__a=a
                self.__b=b
                self.__C=C*pi/180
                #a边上的高
                _h=b*sin(self.__C)
                _x=b*cos(self.__C)
                self.__c=((a-_x)**2+_h**2)**.5
                self.__B=asin(adjust(_h/self.__c))
                self.__A=asin(adjust(a*sin(self.__C)/self.__c))
                #解决钝角三角形问题
                self.__solvObtuseAngle()
            else: #直角三角形才有解
                if A>0 and A<90 and b>a and abs(a-b*sin(A*pi/180))<zeroNum:  #∠B必然是90°
                    self.__a=a
                    self.__b=b
                    self.__c=(b**2-a**2)**.5
                    self.__A=A*pi/180
                    self.__C=pi/2-self.__A
                    self.__B=pi/2
                elif B>0 and B<90 and a>b and abs(b-a*sin(B*pi/180))<zeroNum:  #∠A必然是90°
                    self.__a=a
                    self.__b=b
                    self.__c=(a**2-b**2)**.5
                    self.__B=B*pi/180
                    self.__C=pi/2-self.__B
                    self.__A=pi/2
                else:
                    return True               
        elif a>0 and b<=0 and c>0:
            if B>0 and B<180: #a,cB
                self.__a=a
                self.__c=c
                self.__B=B*pi/180
                #a边上的高
                _h=c*sin(self.__B)
                _x=c*cos(self.__B)
                self.__b=((a-_x)**2+_h**2)**.5
                self.__C=asin(adjust(_h/self.__b))
                self.__A=asin(adjust(a*sin(self.__B)/self.__b))
                #解决钝角三角形问题
                self.__solvObtuseAngle()
            else:
                if A>0 and A<90  and c>a and abs(a-c*sin(A*pi/180))<zeroNum: #∠C为直角
                    self.__a=a
                    self.__b=(c**2-a**2)**.5
                    self.__c=c
                    self.__A=A*pi/180
                    self.__B=pi/2-self.__A
                    self.__C=pi/2
                elif C>0 and C<90 and a>c and abs(c-a*sin(C*pi/180))<zeroNum:  #∠A为直角
                    self.__a=a
                    self.__b=(a**2-c**2)**.5
                    self.__c=c
                    self.__C=C*pi/180
                    self.__B=pi/2-self.__C
                    self.__A=pi/2
                else:
                    return True
        elif a<=0 and b>0 and c>0:
            if A>0 and A<180: #b,cA
                self.__b=b
                self.__c=c
                self.__A=A*pi/180
                #b边上的高
                _h=c*sin(self.__A)
                _x=c*cos(self.__A)
                self.__a=((b-_x)**2+_h**2)**.5
                self.__C=asin(adjust(_h/self.__a))
                self.__B=asin(adjust(b*sin(self.__A)/self.__a))
                #解决钝角三角形问题
                self.__solvObtuseAngle()
            else:
                if B>0 and B<90 and c>b and (b-c*sin(B*pi/180)) < zeroNum: #C直角
                    self.__B=B*pi/180
                    self.__a=c*cos(self.__B)
                    self.__b=b
                    self.__c=c
                    self.__A=pi/2-self.__B
                    self.__C=pi/2
                elif C>0 and C<90 and b>c and (c-b*sin(C*pi/180)) < zeroNum: #B为直角
                    self.__C=C*pi/180
                    self.__a=b*cos(self.__C)
                    self.__b=b
                    self.__c=c
                    self.__A=pi/2-self.__C
                    self.__B=pi/2   
                else:
                    return True                
        else:
            return None
        self.__initOk=True
        return True
    #内切圆和外接圆,使用元组(radiusdistanceangle
    #class Circle():
    #    radius=None  #半径
    #    distance=None #A距离
    #    angle=None #AB边(即c)的夹角
    #创建内切圆
    def createIncircle(self):
        #角平分线交点
        _radius=self.__b*self.__c*sin(self.__A)/(self.__a+self.__b+self.__c)
        _distance=_radius/sin(self.__A/2)
        _angle=self.__A/2
        return _radius, _distance, _angle
    #创建外接圆
    def createCircumcircle(self):
        #中垂线交点
        _radius=self.__a/(2*sin(self.__A))
        _distance=_radius
        if self.__C<pi/2:
            _angle=pi/2-self.__C
        else:
           _angle=pi/2-self.__C
        return  _radius, _distance, _angle       

    def __str__(self):
        if self.__initOk:
            return "三角形边长a=%s,b=%s,c=%s\n∠A=%s,∠B=%s,∠C=%s" % (str(self.__a),str(self.__b),str(self.__c),str(self.__A*180/pi),str(self.__B*180/pi),str(self.__C*180/pi))
        else:
            return "输入的参数未能构成唯一的三角形"
    #初始化
    def __init__(self, a=-1 , b=-1, c=-1, A=-1, B=-1, C=-1):
        if self.__initE3(a, b, c, A, B, C):  #3
            pass
        elif self.__initE1A2(a, b, c, A, B, C): #21
            pass
        elif self.__initE2A1( a, b, c, A, B, C): #21
            pass
        else:
            print("输入的参数未能构成唯一的三角形")
                    
            
if __name__ == "__main__":
    print("1、已知三边")
    print(Triangle(12,13,7))
    print("2、已知一边二角")
    print(Triangle(12,A=35,B=67))
    print(Triangle(a=12,A=35,B=67))
    print(Triangle(a=12,B=35,C=67))
    print(Triangle(b=12,A=35,B=67))
    print(Triangle(b=12,A=35,B=67))
    print(Triangle(b=12,B=35,C=67))
    print(Triangle(c=12,A=35,B=67))
    print(Triangle(c=12,A=35,B=67))
    print(Triangle(c=12,B=35,C=67))
    print("3、边角边")
    print(Triangle(12,15,C=67))
    print(Triangle(a=12,b=15,C=67))
    print(Triangle(a=12,c=15,B=67))
    print(Triangle(b=12,c=15,A=67))
    print("4、其它二边一角——不是直角三角形无解")
    print(Triangle(12,12*sin(67*pi/180),B=67))
    print(Triangle(12*sin(67*pi/180),12,A=67))
    print(Triangle(12,b=12*sin(67*pi/180),B=67))
    print(Triangle(a=12,b=12*sin(67*pi/180),B=67))
    print(Triangle(a=12*sin(67*pi/180),b=12,A=67))
    print(Triangle(b=12,c=12*sin(67*pi/180),C=67))
    print(Triangle(b=12*sin(67*pi/180),c=12,B=67))
    print(Triangle(a=12,c=12*sin(67*pi/180),C=67))
    print(Triangle(a=12*sin(67*pi/180),c=12,A=67))
    print(Triangle(12,c=12*sin(67*pi/180),C=67))
    print(Triangle(12*sin(67*pi/180),c=12,A=67))
    _t=7*3**.5
    _tr=Triangle(14,7,_t)
    _radius, _distance, _angle = _tr.createIncircle()
    print("radius=",_radius," distance=",_distance," angle=",_angle*180/pi)
    _radius, _distance, _angle = _tr.createCircumcircle()
    print("radius=",_radius," distance=",_distance," angle=",_angle*180/pi)