Advertisement
CheeseKeg

A simple triangle solver - programmed with Monkey Demo

Apr 3rd, 2011
466
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Strict
  2.  
  3. Import mojo.app
  4. Import mojo.graphics
  5. Import mojo.input
  6. Import mojo.audio
  7.  
  8. Class Vector3
  9.     Field a:Float, b:Float, c:Float
  10.    
  11.     Method New(_a:Float = 0, _b:Float = 0, _c:Float = 0)
  12.         a = _a
  13.         b = _b
  14.         c = _c
  15.     End
  16.    
  17.     Method propagate:Void(variable:String)
  18.         If variable = "a"
  19.             b = a
  20.             c = a
  21.         Else If variable = "b"
  22.             a = b
  23.             c = b
  24.         Else If variable = "c"
  25.             a = c
  26.             b = c
  27.         End
  28.     End
  29. End
  30.  
  31. Class Triangle
  32.     Field angles:Vector3, sides:Vector3
  33.    
  34.     Method New(angleA:Float = 0, angleB:Float = 0, angleC:Float = 0, sideA:Float = 0, sideB:Float = 0, sideC:Float = 0)
  35.         angles = New Vector3(angleA, angleB, angleC)
  36.         sides = New Vector3(sideA, sideB, sideC)
  37.     End
  38.    
  39.     Method PrintValues:Void()
  40.         Print("Angle A: " + String(angles.a))
  41.         Print("Angle B: " + String(angles.b))
  42.         Print("Angle C: " + String(angles.c))
  43.         Print("Side A: " + String(sides.a))
  44.         Print("Side B: " + String(sides.b))
  45.         Print("Side C: " + String(sides.c))
  46.     End
  47. End
  48.  
  49. Class TriangleMath
  50.     ' Basement functionality
  51.     Method LoC:Float(angleA:Float, sideB:Float, sideC:Float) ' Law of Cosines - Solve for side
  52.         Return Sqrt(Pow(sideB, 2) + Pow(sideC, 2) - 2.0*sideB*sideC*Cos(angleA))
  53.     End
  54.    
  55.     Method iLoC:Float(sideA:Float, sideB:Float, sideC:Float) ' Inverse Law of Cosines - Solve for angle
  56.         Return ACos((Pow(sideB, 2) + Pow(sideC, 2) - Pow(sideA, 2)) / (2.0*sideB*sideC))
  57.     End
  58.    
  59.     Method LoS:Float(angleA:Float, angleB:Float, sideB:Float) ' Law of Sines - Solve for side
  60.         Return Sin(angleA)*(sideB/Sin(angleB))
  61.     End
  62.    
  63.     Method iLoS:Float(angleB:Float, sideA:Float, sideB:Float) ' Inverse Law of Sines - Solve for angle
  64.         Return ASin(sideA/(sideB/Sin(angleB)))
  65.     End
  66.    
  67.     Method TST:Float(angleB:Float, angleC:Float) ' Triangle Sum Theory - Solve for angle
  68.         Return 180.0 - (angleB + angleC)
  69.     End
  70.    
  71.     Method HF:Float(sideA:Float, sideB:Float, sideC:Float) ' Heron's Formula - Solve for area
  72.         Local s:Float = (sideA + sideB + sideC)/2.0
  73.         Return Sqrt(s*(s - sideA)*(s - sideB)*(s - sideC))
  74.     End
  75.    
  76.     ' Lobby functionality
  77.     Method SSS:Triangle(sideA:Float, sideB:Float, sideC:Float) ' Side-Side-Side
  78.         Local angleA:Float = iLoC(sideA, sideB, sideC)
  79.         Local angleB:Float = iLoC(sideB, sideA, sideC)
  80.         Local angleC:Float = TST(angleA, angleB)
  81.         Local result:Triangle = New Triangle(angleA, angleB, angleC, sideA, sideB, sideC)
  82.         Return result
  83.     End
  84.    
  85.     Method SAS:Triangle(sideC:Float, angleA:Float, sideB:Float, variation:Int = 0) ' Side-Angle-Side - Three variations: 0-sCaAsB, 1-sAaBsC, 2-sBaCsA
  86.         Local sideA:Float = LoC(angleA, sideB, sideC)
  87.         Local angleB:Float = iLoC(sideB, sideA, sideC)
  88.         Local angleC:Float = iLoC(sideC, sideB, sideA)
  89.         Local result:Triangle
  90.         If (variation = 1) ' Inputs assumed to be sAaBsC
  91.             result = New Triangle(angleC, angleA, angleB, sideC, sideA, sideB)
  92.         Else If (variation = 2) ' Inputs assumed to be sBaCsA
  93.             result = New Triangle(angleB, angleC, angleA, sideB, sideC, sideA)
  94.         Else ' Inputs assumed to be sCaAsB
  95.             result = New Triangle(angleA, angleB, angleC, sideA, sideB, sideC)
  96.         End
  97.         Return result
  98.     End
  99.    
  100.     Method ASA:Triangle(angleB:Float, sideC:Float, angleA:Float, variation:Int = 0) ' Angle-Side-Angle - Three variations: 0-aBsCaA, 1-aCsAaB, 2-aAsBaC
  101.         Local angleC:Float = TST(angleA, angleB)
  102.         Local sideB:Float = LoS(angleB, angleC, sideC)
  103.         Local sideA:Float = LoC(angleA, sideB, sideC)
  104.         Local result:Triangle
  105.         If (variation = 1) ' Inputs assumed to be aBsCaA
  106.             result = New Triangle(angleC, angleA, angleB, sideC, sideA, sideB)
  107.         Else If (variation = 2) ' Inputs assumed to be aCsAaB
  108.             result = New Triangle(angleB, angleC, angleA, sideB, sideC, sideA)
  109.         Else ' Inputs assumed to be aAsBaC
  110.             result = New Triangle(angleA, angleB, angleC, sideA, sideB, sideC)
  111.         End
  112.         Return result
  113.     End
  114. End
  115.  
  116. Class Widget Abstract
  117.     Field x:Float, y:Float, width:Float, height:Float
  118.    
  119.     Method New(_x:Float, _y:Float, _width:Float, _height:Float)
  120.         x = _x
  121.         y = _y
  122.         width = _width
  123.         height = _height
  124.     End
  125.    
  126.     Method Update:Void() Abstract
  127.    
  128.     Method Render:Void() Abstract
  129. End
  130.  
  131. Class LabelInput Extends Widget
  132.     Field label:String, input:String
  133.     Field labelColor:Vector3
  134.     Field keyCode:Int
  135.     Field rollOver:Bool
  136.    
  137.     Method New(_x:Float = 0, _y:Float = 0, _label:String = "Derp", _keyCode:Int = KEY_ESCAPE, _labelColor:Vector3 = New Vector3(255, 255, 255))
  138.         Super.New(_x, _y, 0, 0)
  139.         label = _label
  140.         input = ""
  141.         labelColor = _labelColor
  142.         keyCode = _keyCode
  143.         rollOver = False
  144.     End
  145.    
  146.     Method Update:Void()
  147.         If (widgetFocus = keyCode)
  148.             Local character:Int = GetChar()
  149.             If ((character >= 48 And character <= 57) Or character = 46)
  150.                 If (((character = 46 And Not input.Contains(".")) Or character <> 46) And input.Length < 14)
  151.                     ChannelSound(typeSound)
  152.                     input += String.FromChar(character)
  153.                 Else
  154.                     ChannelSound(selectSound)
  155.                 End
  156.             Else If (character = CHAR_BACKSPACE Or character = CHAR_DELETE)
  157.                 If (input.Length > 0)
  158.                     input = input[0..input.Length-1]
  159.                     ChannelSound(typeSound)
  160.                 Else
  161.                     ChannelSound(selectSound)
  162.                 End
  163.             End
  164.             If (KeyHit(KEY_R))
  165.                 ChannelSound(typeSound)
  166.                 input = ""
  167.             End
  168.         End
  169.         If (MouseY() > y - 3 And MouseY() < y + 15)
  170.             rollOver = True
  171.             If (MouseHit(MOUSE_LEFT))
  172.                 ChannelSound(selectSound)
  173.                 widgetFocus = keyCode
  174.             End
  175.         Else
  176.             rollOver = False
  177.         End
  178.         If (KeyHit(keyCode))
  179.             ChannelSound(selectSound)
  180.             widgetFocus = keyCode
  181.         End
  182.     End
  183.    
  184.     Method Render:Void()
  185.         If (widgetFocus = keyCode)
  186.             SetColor 255, 0, 0
  187.             DrawCircle(x - 5, y + 5, 5)
  188.         Else If (rollOver)
  189.             SetColor 0, 255, 0
  190.             DrawCircle(x - 5, y + 5, 5)
  191.         End
  192.         If (input = "" And widgetFocus <> keyCode)
  193.             DrawText(label + " = Undefined", x, y)
  194.         Else
  195.             DrawText(label + " = " + input, x, y)
  196.         End
  197.     End
  198. End
  199.  
  200. Global solution:Int = 0
  201. Global widgetFocus:Int
  202. Global typeSound:Sound, selectSound:Sound, backSound:Sound
  203. Global soundChannel:Int = 0
  204. Global playSound:Bool
  205.  
  206. Function ChannelSound:Void(snd:Sound)
  207.     If (playSound)
  208.         If (soundChannel < 10)
  209.             soundChannel += 1
  210.         Else
  211.             soundChannel = 0
  212.         End
  213.         StopChannel(soundChannel)
  214.         PlaySound(snd)
  215.     End
  216. End
  217.  
  218. Class KegSolver Extends App
  219.     Field tMath:TriangleMath
  220.     Field solved:Triangle, solvedArea:Float
  221.     Field inputs:LabelInput[6]
  222.     Field mode:Int
  223.    
  224.     Method OnCreate:Void()
  225.         SetUpdateRate 60
  226.         tMath = New TriangleMath()
  227.         solved = New Triangle(0, 0, 0, 0, 0, 0)
  228.         typeSound = LoadSound("type.wav")
  229.         selectSound = LoadSound("tick.wav")
  230.         inputs[0] = New LabelInput(50, 50, "A) Angle A", KEY_A)
  231.         inputs[1] = New LabelInput(50, 70, "S) Angle B", KEY_S)
  232.         inputs[2] = New LabelInput(50, 90, "D) Angle C", KEY_D)
  233.         inputs[3] = New LabelInput(50, 130, "Z) Side A", KEY_Z)
  234.         inputs[4] = New LabelInput(50, 150, "X) Side B", KEY_X)
  235.         inputs[5] = New LabelInput(50, 170, "C) Side C", KEY_C)
  236.         mode = 0
  237.         playSound = True
  238.     End
  239.    
  240.     Method OnUpdate:Void()
  241.         For Local input:LabelInput = Eachin inputs
  242.             input.Update()
  243.         End
  244.         If (KeyHit(KEY_ENTER))
  245.             ChannelSound(selectSound)
  246.             Local fInputs:Float[6]
  247.             For Local i:Int = 0 To 5
  248.                 If (inputs[i].input = "")
  249.                     fInputs[i] = 0
  250.                 Else
  251.                     Local inputValue:Float = Float(inputs[i].input)
  252.                     If (i < 3)
  253.                         fInputs[i] = convertInput(inputValue)
  254.                     Else
  255.                         fInputs[i] = inputValue
  256.                     End
  257.                 End
  258.             Next
  259.             Local unsolved:Triangle = New Triangle(fInputs[0], fInputs[1], fInputs[2], fInputs[3], fInputs[4], fInputs[5])
  260.             solved = Solve(unsolved)
  261.             solvedArea = tMath.HF(solved.sides.a, solved.sides.b, solved.sides.c)
  262.         End
  263.         If (KeyHit(KEY_M))
  264.             ChannelSound(selectSound)
  265.             If (mode = 0)
  266.                 mode = 1
  267.                 inputs[0].input = floatToString(toRadians(Float(inputs[0].input)))
  268.                 inputs[1].input = floatToString(toRadians(Float(inputs[1].input)))
  269.                 inputs[2].input = floatToString(toRadians(Float(inputs[2].input)))
  270.             Else
  271.                 mode = 0
  272.                 inputs[0].input = floatToString(toDegrees(Float(inputs[0].input)))
  273.                 inputs[1].input = floatToString(toDegrees(Float(inputs[1].input)))
  274.                 inputs[2].input = floatToString(toDegrees(Float(inputs[2].input)))
  275.             End
  276.         End
  277.         If (KeyHit(KEY_T))
  278.             If (playSound)
  279.                 playSound = False
  280.             Else
  281.                 playSound = True
  282.                 ChannelSound(selectSound)
  283.             End
  284.         End
  285.     End
  286.    
  287.     Method OnRender:Void()
  288.         Cls 0, 0, 0
  289.         For Local input:LabelInput = Eachin inputs
  290.             input.Render()
  291.         End
  292.         DrawText "Input three values and press Enter (press R to reset a field):", 50, 20
  293.         Local modeText:String
  294.         If (mode = 0)
  295.             modeText = "Degrees"
  296.         Else If (mode = 1)
  297.             modeText = "Radians"
  298.         End
  299.         DrawText "Angle units: " + modeText, DeviceWidth() - 320, DeviceHeight() - 30
  300.         Local soundText:String
  301.         If (playSound)
  302.             soundText = "Enabled"
  303.         Else
  304.             soundText = "Disabled"
  305.         End
  306.         DrawText "Sound: " + soundText, DeviceWidth() - 140, DeviceHeight() - 30
  307.         If (solution = 0)
  308.             DrawText "Triangle Solver 1.1 by Brandon DeRosier, 2011.", 50, 230
  309.             DrawText "Navigation:", 50, 260
  310.             DrawText "- Press A, S, D, Z, X, or C to focus on corresponding angle/side inputs.", 60, 280
  311.             DrawText "- Press R to reset the focused input field.", 60, 300
  312.             DrawText "- Press M to toggle between degrees and radians for angle measurements.", 60, 320
  313.             DrawText "- Press T to toggle sound.", 60, 340
  314.             DrawText "- Press Enter to solve the triangle based on the inputs given.", 60, 360
  315.         Else If (solution = 1)
  316.             DrawText "Impossible to solve..", 50, 230
  317.             DrawText "Guidelines:", 50, 260
  318.             DrawText "- Three value inputs are needed.", 60, 280
  319.             DrawText "- At least one of the inputs should be a side length.", 60, 300
  320.         Else If (solution > 1)
  321.             If (solution = 2)
  322.                 DrawText "Solved using SSS (Side-Side-Side)", 50, 230
  323.             Else If (solution = 3)
  324.                 DrawText "Solved using SAS (Side-Angle-Side) [First variation]", 50, 230
  325.             Else If (solution = 4)
  326.                 DrawText "Solved using SAS (Side-Angle-Side) [Second variation]", 50, 230
  327.             Else If (solution = 5)
  328.                 DrawText "Solved using SAS (Side-Angle-Side) [Third variation]", 50, 230
  329.             Else If (solution = 6)
  330.                 DrawText "Solved using ASA (Angle-Side-Angle) [First variation]", 50, 230
  331.             Else If (solution = 7)
  332.                 DrawText "Solved using ASA (Angle-Side-Angle) [Second variation]", 50, 230
  333.             Else If (solution = 8)
  334.                 DrawText "Solved using ASA (Angle-Side-Angle) [Third variation]", 50, 230
  335.             End
  336.             DrawText "Angle A = " + convertValue(solved.angles.a), 50, 260
  337.             DrawText "Angle B = " + convertValue(solved.angles.b), 50, 280
  338.             DrawText "Angle C = " + convertValue(solved.angles.c), 50, 300
  339.             DrawText "Side A = " + solved.sides.a, 50, 340
  340.             DrawText "Side B = " + solved.sides.b, 50, 360
  341.             DrawText "Side C = " + solved.sides.c, 50, 380
  342.             DrawText "Area = " + solvedArea, 50, 420
  343.         End
  344.     End
  345.    
  346.     ' Attic functionality
  347.     Method toRadians:Float(degrees:Float)
  348.         If (String(degrees) = "NaN")
  349.             degrees = 0
  350.         End
  351.         Return (degrees*PI)/180.0
  352.     End
  353.    
  354.     Method toDegrees:Float(radians:Float)
  355.         If (String(radians) = "NaN")
  356.             radians = 0
  357.         End
  358.         Return (radians*180.0)/PI
  359.     End
  360.    
  361.     Method convertValue:Float(number:Float)
  362.         If (mode = 1)
  363.             Return toRadians(number)
  364.         End
  365.         Return number
  366.     End
  367.    
  368.     Method convertInput:Float(number:Float)
  369.         If (mode = 1)
  370.             Return toDegrees(number)
  371.         End
  372.         Return number
  373.     End
  374.    
  375.     Method floatToString:String(number:Float)
  376.         If (number = 0)
  377.             Return ""
  378.         End
  379.         Return String(number)
  380.     End
  381.    
  382.     Method Solve:Triangle(tri:Triangle)
  383.         Local result:Triangle
  384.         solution = 0
  385.         If (tri.angles.a > 0 And tri.angles.b > 0 And tri.angles.c = 0)
  386.             tri.angles.c = tMath.TST(tri.angles.a, tri.angles.b)
  387.         Else If (tri.angles.c > 0 And tri.angles.a > 0 And tri.angles.b = 0)
  388.             tri.angles.b = tMath.TST(tri.angles.a, tri.angles.c)
  389.         Else If (tri.angles.b > 0 And tri.angles.c > 0 And tri.angles.a = 0)
  390.             tri.angles.a = tMath.TST(tri.angles.b, tri.angles.c)
  391.         End
  392.         If (tri.sides.a > 0 And tri.sides.b > 0 And tri.sides.c > 0) ' SSS
  393.             result = tMath.SSS(tri.sides.a, tri.sides.b, tri.sides.c)
  394.             solution = 2
  395.         Else If (tri.sides.c > 0 And tri.angles.a > 0 And tri.sides.b > 0) ' SAS original
  396.             result = tMath.SAS(tri.sides.c, tri.angles.a, tri.sides.b, 0)
  397.             solution = 3
  398.         Else If (tri.sides.a > 0 And tri.angles.b > 0 And tri.sides.c > 0) ' SAS morph 1
  399.             result = tMath.SAS(tri.sides.a, tri.angles.b, tri.sides.c, 1)
  400.             solution = 4
  401.         Else If (tri.sides.b > 0 And tri.angles.c > 0 And tri.sides.a > 0) ' SAS morph 2
  402.             result = tMath.SAS(tri.sides.b, tri.angles.c, tri.sides.a, 2)
  403.             solution = 5
  404.         End
  405.         If (solution = 0)
  406.             If (tri.angles.b > 0 And tri.sides.c > 0 And tri.sides.b > 0 And tri.angles.c = 0)
  407.                 tri.angles.c = tMath.iLoS(tri.angles.b, tri.sides.c, tri.sides.b)
  408.                 tri.angles.a = tMath.TST(tri.angles.b, tri.angles.c)
  409.             Else If (tri.angles.c > 0 And tri.sides.a > 0 And tri.sides.c > 0 And tri.angles.a = 0)
  410.                 tri.angles.a = tMath.iLoS(tri.angles.c, tri.sides.a, tri.sides.c)
  411.                 tri.angles.b = tMath.TST(tri.angles.a, tri.angles.c)
  412.             Else If (tri.angles.a > 0 And tri.sides.b > 0 And tri.sides.a > 0 And tri.angles.b = 0)
  413.                 tri.angles.b = tMath.iLoS(tri.angles.a, tri.sides.b, tri.sides.a)
  414.                 tri.angles.c = tMath.TST(tri.angles.a, tri.angles.b)
  415.             Else If (tri.angles.c > 0 And tri.sides.b > 0 And tri.sides.c > 0 And tri.angles.b = 0)
  416.                 tri.angles.b = tMath.iLoS(tri.angles.c, tri.sides.b, tri.sides.c)
  417.                 tri.angles.a = tMath.TST(tri.angles.b, tri.angles.c)
  418.             Else If (tri.angles.a > 0 And tri.sides.c > 0 And tri.sides.a > 0 And tri.angles.c = 0)
  419.                 tri.angles.c = tMath.iLoS(tri.angles.a, tri.sides.c, tri.sides.a)
  420.                 tri.angles.b = tMath.TST(tri.angles.a, tri.angles.c)
  421.             Else If (tri.angles.b > 0 And tri.sides.a > 0 And tri.sides.b > 0 And tri.angles.a = 0)
  422.                 tri.angles.a = tMath.iLoS(tri.angles.b, tri.sides.a, tri.sides.b)
  423.                 tri.angles.c = tMath.TST(tri.angles.a, tri.angles.b)
  424.             End
  425.             If (tri.angles.b > 0 And tri.sides.c > 0 And tri.angles.a > 0) ' ASA original
  426.                 result = tMath.ASA(tri.angles.b, tri.sides.c, tri.angles.a, 0)
  427.                 solution = 6
  428.             Else If (tri.angles.c > 0 And tri.sides.a > 0 And tri.angles.b > 0) ' ASA morph 1
  429.                 result = tMath.ASA(tri.angles.c, tri.sides.a, tri.angles.b, 1)
  430.                 solution = 7
  431.             Else If (tri.angles.a > 0 And tri.sides.b > 0 And tri.angles.c > 0) ' ASA morph 2
  432.                 result = tMath.ASA(tri.angles.a, tri.sides.b, tri.angles.c, 2)
  433.                 solution = 8
  434.             Else ' Can't solve
  435.                 result = New Triangle(0, 0, 0, 0, 0, 0)
  436.                 solution = 1
  437.             End
  438.         End
  439.         Return result
  440.     End
  441. End
  442.  
  443. Function Main:Int()
  444.     New KegSolver
  445.     Return 0
  446. End
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement