Triange Solver

 This code solves a triangle with sides a, b, c and the opposing angles alpha, beta, gamma Download code

import numpy as np

class Triangle:

def __init__( self, s = [-1.0,-1.0,-1.0], a = [-1.0,-1.0,-1.0]):

self.__sideNames__ = ['a', 'b', 'c']

self.__angleNames__ = ['alpha', 'beta', 'gamma']

self.sides = np.array( s)

self.angles = np.array( a)

self.Verbose = False

self.Solve()

return

def Solve( self):

self.__solveAngle__(2,0,1)

self.__solveAngle__(0,1,2)

self.__solveAngle__(1,2,0)

self.__solveSide__(2,0,1)

self.__solveSide__(0,1,2)

self.__solveSide__(1,2,0)

self.__solveAngle__(2,0,1)

self.__solveAngle__(0,1,2)

self.__solveAngle__(1,2,0)

return

def Print( self):

for i in range(3):

print( "{:s} = {:.3f}\t {:s} = {:.3f}".format(

self.__sideNames__[i], self.sides[i], self.__angleNames__[i], self.angles[i]))

return

def SolveInteractive( self):

self.sides = self.__getInput__( "{:s} {:s} {:s}".format(

self.__sideNames__[0], self.__sideNames__[1], self.__sideNames__[2]))

i = self.__CountDefinedSides__()

if i <= 0:

print( "WARNING: At least two angles should be given")

if i < 3:

self.angles = self.__getInput__( "{:s} {:s} {:s}".format(

self.__angleNames__[0], self.__angleNames__[1], self.__angleNames__[2]))

else:

self.angles = -np.ones(3)

if self.Verbose:

print( "Initial Triangle:")

self.Print()

self.Solve()

if self.Verbose:

print( "Solution Triangle:")

self.Print()

return

def __getInput__(self, question):

i = 0

s = str( input( question + " = "))

ss = s.split(" ")

try: a = float( ss[0])

except: a = -1

try: b = float( ss[1])

except: b = -1

try: c = float( ss[2])

except: c = -1

return np.array( [a,b,c])

def __CountDefinedSides__(self):

i = 0

for s in self.sides:

if s > 0: i += 1

return i

def __solveAngle__(self, il, i, ir):

if self.angles[i] > 0: return

if self.angles[il] > 0 and self.angles[ir] > 0:

self.angles[i] = self.__SimpleAngle__(il, i, ir)

return

if self.angles[il] > 0 and self.sides[il] > 0 and self.sides[i] > 0:

self.angles[i] = self.__SineTheoremAngle__(il, i)

return

if self.angles[ir] > 0 and self.sides[ir] > 0 and self.sides[i] > 0:

self.angles[i] = self.__SineTheoremAngle__(ir, i)

return

if self.sides[il] > 0 and self.sides[ir] > 0 and self.sides[i] > 0:

self.angles[i] = self.__CosineTheoremAngle__(il, i, ir)

return

return

def __solveSide__(self, il, i, ir):

if self.sides[i] > 0: return

if self.angles[il] > 0 and self.sides[il] > 0 and self.angles[i] > 0:

self.sides[i] = self.__SineTheoremSide__(il, i)

return

if self.angles[ir] > 0 and self.sides[ir] > 0 and self.angles[i] > 0:

self.sides[i] = self.__SineTheoremSide__(ir, i)

return

if self.sides[il] > 0 and self.sides[ir] > 0 and self.angles[i] > 0:

self.sides[i] = self.__CosineTheoremSide__(il, i, ir)

return

return

def __SimpleAngle__( self, il, i, ir):

if self.Verbose:

print("Using sum of angles for {:s}".format(self.__angleNames__[i]))

return 180 - self.angles[il] - self.angles[ir]

def __SineTheoremAngle__( self, i0, i):

if self.Verbose:

print("Using sine theorem for {:s}".format(self.__angleNames__[i]))

d = self.sides[i] / self.sides[i0]

d *= np.sin( np.pi*self.angles[i0]/180)

if d<0: return -1

return np.arcsin( d)*180/np.pi

def __CosineTheoremAngle__( self, il, i, ir):

if self.Verbose:

print("Using cosine theorem for {:s}".format(self.__angleNames__[i]))

d = self.sides[il] * self.sides[il]

d += self.sides[ir] * self.sides[ir]

d -= self.sides[i] * self.sides[i]

d /= 2 * self.sides[il] * self.sides[ir]

try: a = 180 * np.arccos( d) / np.pi

except: return -1

return a

def __SineTheoremSide__( self, i0, i):

if self.Verbose:

print("Using sine theorem for {:s}".format(self.__sideNames__[i]))

d = np.sin( np.pi*self.angles[i] / 180.0)

d /= np.sin( np.pi*self.angles[i0] / 180.0)

d *= self.sides[i0]

if d<0: return -1

return d

def __CosineTheoremSide__( self, il, i, ir):

if self.Verbose:

print("Using cosine theorem for {:s}".format(self.__sideNames__[i]))

a = np.cos( self.angles[i] * np.pi / 180.0)

d = self.sides[il] * self.sides[il]

d += self.sides[ir] * self.sides[ir]

d -= 2.0 * self.sides[il] * self.sides[ir] * a

if d <= 0: return -1.0

return np.sqrt( d)

##

## Uncomment for testing

##

##print( "Test three sides")

##T = Triangle([10.0,12.0,7.0])

##T.Print()

##

##print( "\nTest two sides and angle in-between")

##T.sides = np.array([10.0,-1.0,7.0])

##T.angles = np.array([-1.0,87.953,-1.0])

##T.Solve()

##T.Print()

##

##print( "\nTest two sides and angle on the side")

##T.sides = np.array([10.0,12.0,-1.0])

##T.angles = np.array([-1.0,87.953,-1.0])

##T.Solve()

##T.Print()

##

##print( "\nTest one side and two angles")

##T.sides = np.array([-1.0,12.0,-1.0])

##T.angles = np.array([56.388,-1.0,35.659])

##T.Solve()

##T.Print()

##

##print( "\nTest incomplete data")

##T.sides = np.array([-1.0,-1.0,-1.0])

##T.angles = np.array([56.388,-1.0,35.659])

##T.Solve()

##T.Print()

##

print( "Triangle calculations.\nSend Control-C to stop.\n")

T = Triangle()

T.Verbose = True

while True:

T.SolveInteractive()

print("")