Page 1 of 1

TrigonMaster

Posted: Sat Sep 17, 2011 7:10 pm
by BasicallyPure
TrigonMaster is a utility program that will solve triangle parameters for you.
You must know three parameters about your triangle and TrigonMaster will solve the rest.
You must know the length of at least one side.

This is a screen capture of the Linux version.
Image

This code will run on Windows and Linux
I have tested TrigonMaster with Windows XP, Windows 7, and Linux (Ubuntu).

Code: Select all

;Trigon Master by BasicallyPure
#VERSION = 107
#WHEN = "10/26/2011"
;PureBasic 4.51
;Tested on Linux - Ubuntu 10.04
;Tested on Windows XP and 7

EnableExplicit

;enumerations
;{ gadgets
Enumeration
   #imgGad_Tri
   #Spin_Aa
   #Spin_Ab
   #Spin_Ac
   #Spin_Sa
   #Spin_Sb
   #Spin_Sc
   #CheckBox_Reverse
   #ChkBox_Lock_Aa
   #ChkBox_Lock_Ab
   #ChkBox_Lock_Ac
   #ChkBox_LocK_Sa
   #ChkBox_LocK_Sb
   #ChkBox_LocK_Sc
   #Checkbox_AutoScale
   #Text_Title
   #Editor_Note
   #Editor_Analysis
   #Btn_Right
   #Btn_Equal
   #Btn_Perimeter
   #Btn_Area
   #Str_Value
EndEnumeration
;}
;{ Images
Enumeration
   #Image_Triangle
EndEnumeration
;}
;{ Fonts
Enumeration
   #Font_10BoldHQ
   #Font_12BoldHQ
   #Font_Courier_10HQ
EndEnumeration
;}
;{ menu items
Enumeration
   #exit
   #about
   #Enter_Key
EndEnumeration
;}

;{ procedure declarations
Declare.d AdjustTriangle (part.l, value.d)
Declare.d SpinStep(part, updn)
;}

;{ constant declarations
#Angle_A = %000001
#Angle_B = %000010
#Angle_C = %000100
#Side_a  = %001000
#Side_b  = %010000
#Side_c  = %100000
#C_Red   = $0000FF
#C_Green = $00FF00
#C_Blue  = $FF0000
#C_White = $FFFFFF
#C_Black = $000000
;}

;{ Variable definitions
Define.d Sa = 1, Sb = 1, Sc = 1
Define.d Aa = Radian(60), Ab = Radian(60), Ac = Radian(60)
Define.l part, lock, gadget, flags, bigEvent, key, upDn, side, angle
Define.d value, newValue, perimeter, area
Define.s text
;}

;{ Macro definitions
Macro unlockAll ;used in 'Right' and 'Equal' button events
   lock = 0
   SetGadgetState(#ChkBox_Lock_Aa,0) : SetGadgetState(#ChkBox_Lock_Ab,0)
   SetGadgetState(#ChkBox_Lock_Ac,0) : SetGadgetState(#ChkBox_LocK_Sa,0)
   SetGadgetState(#ChkBox_LocK_Sb,0) : SetGadgetState(#ChkBox_LocK_Sc,0)
EndMacro

Macro sideStep(S1, S2, S3) ;used in SpinStep() procedure
   value = S3
   Select updn
      Case 1 ;up
         value + (S1 + S2 - S3) * 0.02
      Case -1 ;down
         value + (Abs(S1 - S2) - S3) * 0.02
   EndSelect
EndMacro

Macro angleStep(angle) ;used in SpinStep() procedure
   value = Degree(angle)
   Select updn
      Case 1 ;up
         value + Degree((#PI - angle) * 0.02)
      Case -1 ;down
         value + Degree((0 - angle) * 0.02)
   EndSelect
EndMacro

Macro CosLaw(S1,S2,S3,A1) ;cosine law for sides
   S1 = Sqr(S2*S2 + S3*S3 - 2*S2*S3*Cos(A1))
EndMacro

Macro ArcCosLaw(A1,S1,S2,S3) ;ArcCosine law for angles
   A1 = ACos((S1*S1 - S2*S2 - S3*S3) / (-2*S2*s3))
EndMacro

Macro SinLaw(S1,S2,A1,A2) ;sine law for sides
   S1 = (S2 * Sin(A1)) / Sin(A2)
EndMacro

Macro ArcSinLaw(A1,S1,A2,S2) ;ArcSine law for angles
   A1 = ASin(S1*Sin(A2) / S2)
EndMacro

Macro ASub(A1,A2,A3) ;angle by subtraction
   A1 = #PI - A2 - A3
EndMacro

Macro LowLimit(S1,S2,A) ;enforce low limit for side
   If S1 < S2 * Sin(A) : S1 = S2 * Sin(A) : EndIf
   If S1 < S2 And A > #PI / 2 : S1 = S2 : EndIf
EndMacro

Macro HighLimit(S1,S2,A) ;enforce high limit for side
   If S1 > S2 / Sin(A) : S1 = S2 / Sin(A) : EndIf
   If S1 > S2 And A > #PI / 2 : S1 = S2 : EndIf
EndMacro

;}

;{ Open window and add gadgets
text = "Trigon Master"
flags = #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered
If OpenWindow(0, 0, 0, 800, 450, text, flags)
   
   If CreateMenu(0, WindowID(0))
      MenuTitle("File")
      MenuItem(#exit, "Exit")
      MenuTitle("Help")
      MenuItem(#about, "About Trigon Master")
   EndIf
   
   AddKeyboardShortcut(0,#PB_Shortcut_Return, #Enter_Key)
   
   LoadFont(#Font_12BoldHQ, "Microsoft Sans Serif", 12, #PB_Font_Bold|#PB_Font_HighQuality)
   LoadFont(#Font_Courier_10HQ, "Courier New", 10, #PB_Font_HighQuality)
   
   CreateImage(#Image_Triangle,300,300)
   ImageGadget(#imgGad_Tri, 10, 45, 300, 300, ImageID(#Image_Triangle), #PB_Image_Border)
   
   TextGadget(#Text_Title, 35, 10, 250, 23, "Solve Triangle Parameters", #PB_Text_Center)
      SetGadgetFont(#Text_Title, FontID(#Font_12BoldHQ))
   ;
   EditorGadget(#Editor_Note, 325, 10, 355,40, #PB_Editor_ReadOnly)
      text = "To scale a triangle:  Unlock all sides. Lock any angle," + #CRLF$
      text + "then change the side opposite the locked angle."
      SetGadgetText(#Editor_Note,text)
   ;
   EditorGadget(#Editor_Analysis, 530, 60, 255, 275, #PB_Editor_ReadOnly)
      SetGadgetFont(#Editor_Analysis, FontID(#Font_Courier_10HQ))
   ;
   ; ****************** Angle controls **********************
   Frame3DGadget(#PB_Any, 325,55, 195, 125, "Angle adjust")
      ; Angle A
      SpinGadget(#Spin_Aa, 330, 75,122,25,-1,1)
         SetGadgetColor(#Spin_Aa, #PB_Gadget_BackColor, #C_Red)
         SetGadgetColor(#Spin_Aa, #PB_Gadget_FrontColor, #C_White)
         SetGadgetState(#Spin_Aa,0)
      CheckBoxGadget(#ChkBox_Lock_Aa, 460, 078, 55, 20, "Lock")
      ; Angle B
      SpinGadget(#Spin_Ab, 330, 110, 122, 25, -1, 1)
         SetGadgetColor(#Spin_Ab, #PB_Gadget_BackColor, #C_Green)
         SetGadgetColor(#Spin_Ab, #PB_Gadget_FrontColor, #C_Black)
         SetGadgetState(#Spin_Ab,0)
      CheckBoxGadget(#ChkBox_Lock_Ab, 460, 113, 55, 20, "Lock")
      ; Angle C
      SpinGadget(#Spin_Ac, 330, 145, 122, 25, -1, 1)
         SetGadgetColor(#Spin_Ac, #PB_Gadget_BackColor, #C_Blue)
         SetGadgetColor(#Spin_Ac, #PB_Gadget_FrontColor, #C_White)
         SetGadgetState(#Spin_Ac,0)
      CheckBoxGadget(#ChkBox_Lock_Ac, 460, 148, 55, 20, "Lock")
   ;
   ; ******************* Side controls ***********************
   Frame3DGadget(#PB_Any, 325,210, 195, 125, "Side adjust")
      ; Side a
      SpinGadget(#Spin_Sa, 330, 230, 122, 25, -1, 1)
         SetGadgetColor(#Spin_Sa, #PB_Gadget_BackColor, #C_Red)
         SetGadgetColor(#Spin_Sa, #PB_Gadget_FrontColor, #C_White)
         SetGadgetState(#Spin_Sa,0)
      CheckBoxGadget(#ChkBox_LocK_Sa, 460, 233, 55, 20, "Lock")
      ; Side b
      SpinGadget(#Spin_Sb, 330, 265, 122, 25, -1, 1)
         SetGadgetColor(#Spin_Sb, #PB_Gadget_BackColor, #C_Green)
         SetGadgetColor(#Spin_Sb, #PB_Gadget_FrontColor, #C_Black)
         SetGadgetState(#Spin_Sb,0)
      CheckBoxGadget(#ChkBox_LocK_Sb, 460, 268, 55, 20, "Lock")
      ; Side c
      SpinGadget(#Spin_Sc, 330, 300, 122, 25, -1, 1)
         SetGadgetColor(#Spin_Sc, #PB_Gadget_BackColor, #C_Blue)
         SetGadgetColor(#Spin_Sc, #PB_Gadget_FrontColor, #C_White)
         SetGadgetState(#Spin_Sc,0)
      CheckBoxGadget(#ChkBox_LocK_Sc, 460, 303, 55, 20, "Lock")
   ;
   ; **************** Image controls **************************
   Frame3DGadget(#PB_Any, 15,360, 200, 38, "Image controls")
      CheckBoxGadget(#CheckBox_Reverse, 25, 375,80, 20, "Reverse")
      CheckBoxGadget(#Checkbox_AutoScale, 115, 375,95, 20, "auto scale")
         SetGadgetState(#Checkbox_AutoScale,#PB_Checkbox_Checked)
   ;
   ; *************** Force Angles controls ********************
   Frame3DGadget(#PB_Any, 325,350, 170, 60, "Force Angles")
      ButtonGadget(#Btn_Right, 335, 370, 65, 25, "Right")
      ButtonGadget(#Btn_Equal, 420, 370, 65, 25, "Equal")
   ;
   ; *************** Force Size controls **********************
   Frame3DGadget(#PB_Any, 530,340, 255, 70, "Force Size")
      ButtonGadget(#Btn_Perimeter, 680, 352, 80, 25, "Perimeter")
      SetGadgetState(#Btn_Perimeter,1)     
      ButtonGadget(#Btn_Area, 680, 382, 80, 25, "Area")     
      StringGadget(#Str_Value, 540, 365, 120, 25, "")     
   ;
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      LoadFont(#Font_10BoldHQ, "Microsoft Sans Serif", 10, #PB_Font_Bold|#PB_Font_HighQuality)
      For gadget = #Spin_Aa To #Spin_Sc
         SetGadgetFont(gadget,FontID(#Font_10BoldHQ))
      Next gadget
   CompilerEndIf
   
Else
   MessageRequester("Error", "Can't open window 'Trigon Master'!", 0)
   End
EndIf
;}

;{ initial operations
AdjustTriangle(#False,value) ;draw the default triangle
;}
         
;{  >>>>> Event loop <<<<<
Repeat
   bigEvent = WaitWindowEvent()
   
   If bigEvent = #PB_Event_Menu
      Select EventMenu()
         Case #Enter_Key
            If GetActiveGadget() <> #Str_Value
               AdjustTriangle(part, value)
            EndIf
         Case #exit
            flags = #PB_MessageRequester_YesNo
            If MessageRequester("","Quit Trigon Master?",flags) = #PB_MessageRequester_Yes
               End
            EndIf
         Case #about
            text = "Trigon Master - version " + StrF(#VERSION / 100.0,2)
            text + #CRLF$ + "Copyright " + Chr(169) + " BasicallyPure"
            text + #CRLF$ + #WHEN
            text + #CRLF$ + "License: free"
            MessageRequester("", text, 0)
      EndSelect
   EndIf
   
   If bigEvent = #PB_Event_Gadget
      gadget = EventGadget()
      Select gadget
         Case #Spin_Aa To #Spin_Sc
            part = Pow(2,gadget - #Spin_Aa)
            value = ValD(GetGadgetText(gadget))
            Select EventType()
               Case -1,0,1
                  upDn = GetGadgetState(gadget) : SetGadgetState(gadget,0)
                  AdjustTriangle(part, SpinStep(part, upDn))
            EndSelect
         Case #ChkBox_Lock_Aa To #ChkBox_LocK_Sc
            part = Pow(2,gadget - #ChkBox_Lock_Aa)
            lock ! part ;toggle side or angle lock
            If gadget > #ChkBox_Lock_Ac ;a side lock was toggled
               lock & (%000111 + part) ;unlock other sides
               For side = #ChkBox_LocK_Sa To #ChkBox_LocK_Sc ;uncheck other boxes
                  If side <> gadget : SetGadgetState(side,0) : EndIf
               Next side
            Else ;an angle lock was toggled
               lock & (%111000 + part) ;unlock other angles
               For angle = #ChkBox_Lock_Aa To #ChkBox_Lock_Ac ;unlock other boxes
                  If angle <> gadget : SetGadgetState(angle,0) : EndIf
               Next angle
            EndIf
         Case #CheckBox_Reverse, #Checkbox_AutoScale
            AdjustTriangle(#False, value)
         Case #Btn_Equal
            unlockAll ; macro
            value = perimeter / 3
            AdjustTriangle(#Side_a,value)
            AdjustTriangle(#Side_b,value)
            AdjustTriangle(#Side_c,value)
         Case #Btn_Right
            unlockAll ; macro
            value = perimeter / (2 + Sqr(2))
            If ValD(GetGadgetText(#Spin_Aa)) = 90
               AdjustTriangle(#Angle_B, 90)
               SetGadgetState(#ChkBox_Lock_Ab,1) : lock | #Angle_B
               AdjustTriangle(#Side_a,value)
               AdjustTriangle(#Side_c, value)
            ElseIf ValD(GetGadgetText(#Spin_Ac)) = 90
               AdjustTriangle(#Angle_A, 90)
               SetGadgetState(#ChkBox_Lock_Aa,1) : lock | #Angle_A
               AdjustTriangle(#Side_b,value)
               AdjustTriangle(#Side_c, value)
            Else
               AdjustTriangle(#Angle_C, 90)
               SetGadgetState(#ChkBox_Lock_Ac,1) : lock | #Angle_C
               AdjustTriangle(#Side_a,value)
               AdjustTriangle(#Side_b, value)
            EndIf
         Case #Btn_Area, #Btn_Perimeter
            newValue = ValD(GetGadgetText(#Str_Value))
            If newValue > 0
               part = lock ;remember lock states
               lock = #Angle_A ;lock only angle A
               value = Sa
               If gadget = #Btn_Perimeter
                  ;set the perimeter to a specified value
                  value / perimeter * newValue
               ElseIf gadget = #Btn_Area
                  ;set the area to a specified value
                  value * Sqr(newValue / area)
               EndIf
               AdjustTriangle(#Side_a, value)
               lock = part ;restore the lock states
            EndIf
      EndSelect
   EndIf
Until bigEvent = #PB_Event_CloseWindow
;} end event loop

End

Procedure.d AdjustTriangle(part.l, value.d)
   ;recalculate and redraw the triangle using the new part and value
   ;part specifies one of the 3 sides or 3 angles to modify
   ;value specifies the magnitude of the part
   ;part = #false draws triangle without value adjustments
   
   ;{ variables used in this procedure
   Static.d scale = 1
   Static.l SideX, SideY, SideZ
   Static.l AngleX, AngleY, AngleZ
   Static.l GadgetString
   Static.d Sx, Sy, Sz, Ax, Ay, Az
   Protected.l x, y, a, b, c
   Protected.d n, width, height, oldAngle
   Protected.s text
   Shared Sa, Sb, Sc ;triangle sides
   Shared Aa, Ab, Ac ;triangle angles
   Shared lock, perimeter, area
   ;}
   
   Select part
         ;{ assign the generic adjustment variables
      Case #Side_a, #Angle_A
         If part = #Angle_A : GadgetString = #Spin_Aa
            Else : GadgetString = #Spin_Sa : EndIf
         SideX = #Side_a : SideY = #Side_b : SideZ = #Side_c
         AngleX = #Angle_A : AngleY = #Angle_B : AngleZ = #Angle_C
         Sx = Sa : Sy = Sb : Sz = Sc : Ax = Aa : Ay = Ab : Az = Ac
      Case #Side_b, #Angle_B
         If part = #Angle_B : GadgetString = #Spin_Ab
            Else : GadgetString = #Spin_Sb : EndIf
         SideX = #Side_b : SideY = #Side_c : SideZ = #Side_a
         AngleX = #Angle_B : AngleY = #Angle_C : AngleZ = #Angle_A
         Sx = Sb : Sy = Sc : Sz = Sa : Ax = Ab : Ay = Ac : Az = Aa
      Case #Side_c, #Angle_C
         If part = #Angle_C : GadgetString = #Spin_Ac
            Else : GadgetString = #Spin_Sc : EndIf
         SideX = #Side_c : SideY = #Side_a : SideZ = #Side_b
         AngleX = #Angle_C : AngleY = #Angle_A : AngleZ = #Angle_B
         Sx = Sc : Sy = Sa : Sz = Sb : Ax = Ac : Ay = Aa : Az = Ab
         ;}
   EndSelect
   
   Select part ;perform the generic adjustments
      Case #Side_a, #Side_b, #Side_c
         ;{ generic side adjustment (sideX)
         If SideX & lock
            SetGadgetText(GadgetString,Left(StrD(Sx,11),12))
            ProcedureReturn
         EndIf
         If value < 1E-10 : value = 1E-10 : EndIf
         Sx = value
         If AngleX & lock
            If SideY & lock ;adjust Angle Y, Z and side z
               LowLimit(Sx,Sy,Ax) ;enforce lower limit
               ArcSinLaw(Ay,Sy,Ax,Sx) : ASub(Az,Ax,Ay) : CosLaw(Sz,Sx,Sy,Az)
            ElseIf SideZ & lock ;adjust Angle Z, Y and side y
               LowLimit(Sx,Sz,Ax) ;enforce lower limit
               ArcSinLaw(Az,Sz,Ax,Sx) : ASub(Ay,Ax,Az) : CosLaw(Sy,Sx,Sz,Ay)
            Else ;adjust sides z, y
               SinLaw(Sz,Sx,Az,Ax) : CosLaw(Sy,Sx,Sz,Ay)
            EndIf
         ElseIf AngleY & lock
            If SideY & lock ;adjust Angle X, Z and side z
               HighLimit(Sx,Sy,Ay) ;enforce upper limit
               ArcSinLaw(Ax,Sx,Ay,Sy) : ASub(Az,Ax,Ay) : CosLaw(Sz,Sx,Sy,Az)
            Else ;adjust side y and Ang X, Z
               CosLaw(Sy,Sx,Sz,Ay) : ArcCosLaw(Ax,Sx,Sy,Sz) : ArcCosLaw(Az,Sz,Sx,Sy)
            EndIf
         ElseIf AngleZ & lock
            If SideZ & lock ;adjust Angle X, Y and side y
               HighLimit(Sx,Sz,Az) ;enforce upper limit
               ArcSinLaw(Ax,Sx,Az,Sz) : ASub(Ay,Ax,Az) : CosLaw(Sy,Sx,Sz,Ay)
            Else ;adjust side z and Angle X, Y
               CosLaw(Sz,Sx,Sy,Az) : ArcCosLaw(Ax,Sx,Sy,Sz) : ArcCosLaw(Ay,Sy,Sz,Sx)
            EndIf
         Else ;adjust all angles
            If Sx >= Sy + Sz : Sx = Sy + Sz - 1E-10 : EndIf
            If Sx + Sy <= Sz : Sx = Sz - Sy + 1E-10 : EndIf
            If Sx + Sz <= Sy : Sx = Sy - Sz + 1E-10 : EndIf
            ArcCosLaw(Ax,Sx,Sy,Sz) : ArcCosLaw(Ay,Sy,Sz,Sx) : ArcCosLaw(Az,Sz,Sx,Sy)
         EndIf
         ;}
      Case #Angle_A, #Angle_B, #Angle_C
         ;{ generic angle adjustment (AngleX)
         If AngleX & lock
            SetGadgetText(GadgetString,Left(StrD(Degree(Ax),11),12))
            ProcedureReturn
         EndIf
         If value >= 180 : value = 180 - 1E-6 : EndIf
         If value < 1E-6 : value = 1E-6 : EndIf
         oldAngle = Ax : Ax = Radian(value)
         If AngleY & lock ;adjust angle Z
            If Ax + Ay >= #PI : Ax = #PI - Ay - 1E-10 : EndIf
            ASub(Az,Ax,Ay)
            If SideX & lock ;adjust sides y, z
               SinLaw(Sy,Sx,Ay,Ax) : CosLaw(Sz,Sx,Sy,Az)
            ElseIf SideZ & lock ;adjust sides x, y
               SinLaw(Sx,Sz,Ax,Az) : CosLaw(Sy,Sx,Sz,Ay)
            Else ;adjust sides x, z
               SinLaw(Sx,Sy,Ax,Ay) : CosLaw(Sz,Sx,Sy,Az)
            EndIf
         ElseIf AngleZ & lock ;adjust angle Y
            If Ax + Az >= #PI : Ax = #PI - Az - 1E-10 : EndIf
            ASub(Ay,Ax,Az)
            If SideX & lock ; adjust sides y, z
               SinLaw(Sy,Sx,Ay,Ax) : CosLaw(Sz,Sx,Sy,Az)
            ElseIf SideY & lock ;adjust sides x, z
               SinLaw(Sx,Sy,Ax,Ay) : CosLaw(Sz,Sx,Sy,Az)
            Else ;adjust sides x, y
               SinLaw(Sx,Sz,Ax,Az) : CosLaw(Sy,Sx,Sz,Ay)
            EndIf
         ElseIf SideX & lock ;adjust Angle Y, Z and sides y, z
            Ay + (oldAngle - Ax) / 2
            ASub(Az,Ax,Ay) : SinLaw(Sy,Sx,Ay,Ax) : CosLaw(Sz,Sx,Sy,Az)
         ElseIf SideY & lock ;adjust Angle Y and sides x, z
            ASub(Ay,Ax,Az) : SinLaw(Sx,Sy,Ax,Ay) : CosLaw(Sz,Sx,Sy,Az)
         ElseIf SideZ & lock ;adjust Angle Z and sides x, y
            ASub(Az,Ax,Ay) : SinLaw(Sx,Sz,Ax,Az) : CosLaw(Sy,Sx,Sz,Ay)
         Else ;nothing locked, adjust side x and Angle Y, Z
            CosLaw(Sx,Sy,Sz,Ax) : ArcCosLaw(Ay,Sy,Sz,Sx) : ArcCosLaw(Az,Sz,Sx,Sy)
         EndIf
         ;}
   EndSelect
   
   Select part
         ;{ update side & angle variables from generic adjustment variables
      Case #Side_a, #Angle_A
         Sa = Sx : Sb = Sy : Sc = Sz : Aa = Ax : Ab = Ay : Ac = Az
      Case #Side_b, #Angle_B
         Sb = Sx : Sc = Sy : Sa = Sz : Ab = Ax : Ac = Ay : Aa = Az
      Case #Side_c, #Angle_C
         Sc = Sx : Sa = Sy : Sb = Sz : Ac = Ax : Aa = Ay : Ab = Az
         ;}
   EndSelect
   
   ;{ display the results
   n = Sb * Cos(Ac)
   width = Sa
   If n < 0
      width - n
   ElseIf n > Sa
      width + n - Sa
   EndIf
   height = Sb * Sin(Ac)
   If GetGadgetState(#Checkbox_AutoScale) = #PB_Checkbox_Checked
      If IsNAN(width) Or IsNAN(height)
         text = "Result was 'Not A Number'." + #CRLF$
         text + "All paramaters will be reset."
         MessageRequester("Error!",text)
         Sa = 1 : Sb = 1 : Sc = 1
         Aa = Radian(60) : Ab = Radian(60) : Ac = Radian(60)
         width = 1 : scale = 250 : height = Sin(Ac) : n = Sb * Cos(Ac)
         unlockAll
      Else
         If width > height
            scale = 250 / width
         Else
            scale = 250 / height
         EndIf
      EndIf
   EndIf
   x = (300 - width * scale) / 2
   If n < 0 :  x - n * scale : EndIf
   y = 300 - (300 - height * scale) / 2
   a = Sa * scale : b = Sb * scale : c = Sc * scale
   
   If GetGadgetState(#CheckBox_Reverse) = #PB_Checkbox_Checked
      x = 300 - x : y = 300 - y : a * -1 : b * -1: c * -1
   EndIf
   
   StartDrawing(ImageOutput(#Image_Triangle))
   ;erase
   Box(0, 0, 300, 300, #C_Black)
   
   ; draw vertices
   Circle(x + a, y, 3, #C_Green)
   Circle(x, y, 3, #C_Blue)
   Circle(x + b*Cos(Ac), y - b*Sin(Ac), 3, #C_Red)
   
   ;draw side a
   LineXY(x, y, x + a, y , #C_Red)
   
   ;draw side b
   LineXY(x, y, x + b*Cos(Ac), y - b*Sin(Ac) , #C_Green)
   
   ;draw side c
   LineXY(x + a, y, x + a - c * Cos(Ab), y - c * Sin(Ab) , #C_Blue)
   
   StopDrawing()
   SetGadgetState(#imgGad_Tri,ImageID(#Image_Triangle))
   
   SetGadgetText(#Spin_Aa,Left(StrD(Degree(Aa),11),12))
   SetGadgetText(#Spin_Ab,Left(StrD(Degree(Ab),11),12))
   SetGadgetText(#Spin_Ac,Left(StrD(Degree(Ac),11),12))
   SetGadgetText(#Spin_Sa,Left(StrD(Sa,11),12))
   SetGadgetText(#Spin_Sb,Left(StrD(Sb,11),12))
   SetGadgetText(#Spin_Sc,Left(StrD(Sc,11),12))
   
   text = " Triangle analysis:" + #CRLF$ + #CRLF$
   x = 1E4 : a = Aa*x : b = Ab*x : c = Ac*x
   y = #PI/2 * x ;use for right angle comparison
   ;angle classification
   If a = y Or b = y Or c = y
      text + " a 'right' triangle" + #CRLF$
   ElseIf a < y And b < y And c < y
      text + " an 'acute' triangle" + #CRLF$
   Else
      text + " an 'obtuse' triangle" + #CRLF$
   EndIf
   ;side classification
   a = Round(Sa*x, 2) : b = Round(Sb*x, 2) : c = Round(Sc*x, 2)
   If a = b And b = c
      text + " an 'equilateral' triangle" + #CRLF$
   ElseIf a = b Or a = c Or b = c
      text + " an 'isosceles' triangle" + #CRLF$
   Else
      text + " a 'scalene' triangle" + #CRLF$
   EndIf
   perimeter = Sa + Sb + Sc
   area = (Sa * Sb * Sin(Ac)) / 2
   text + #CRLF$
   text + " red length   = " + Left(StrD(Sa,11),12) + #CRLF$
   text + " green length = " + Left(StrD(Sb,11),12) + #CRLF$
   text + " blue length  = " + Left(StrD(Sc,11),12) + #CRLF$ + #CRLF$
   text + " red angle   = " + Left(StrD(Degree(Aa),11),12) + #CRLF$
   text + " green angle = " + Left(StrD(Degree(Ab),11),12) + #CRLF$
   text + " blue angle  = " + Left(StrD(Degree(Ac),11),12) + #CRLF$
   text + #CRLF$ + " perimeter = " + StrD(perimeter) + #CRLF$
   text + #CRLF$ + " area = " + StrD(area)
   SetGadgetText(#Editor_Analysis,text)
   ;}
EndProcedure

Procedure.d SpinStep(part, updn)
   ;calculate increment and return new value for triangle spingadgets
   Shared Sa, Sb, Sc, Aa, Ab, Ac
   Protected value.d
   
   Select part
      Case #Side_a
         sideStep(Sb, Sc, Sa) ; macro
      Case #Side_b
         sideStep(Sa, Sc, Sb) ; macro
      Case #Side_c
         sideStep(Sa, Sb, Sc) ; macro
      Case #Angle_A
         angleStep(Aa) ; macro
      Case #Angle_B
         angleStep(Ab) ; macro
      Case #Angle_C
         angleStep(Ac) ; macro
   EndSelect
   ProcedureReturn value
EndProcedure

Re: TrigonMaster

Posted: Sat Sep 17, 2011 7:13 pm
by Polo
Looks cool, the code can't compile on MacOS as you're using #Red an so on which are not defined in PB Mac (why is it not, btw?)

Re: TrigonMaster

Posted: Sat Sep 17, 2011 7:44 pm
by BasicallyPure
@Polo
I have edited the code and removed all of the color constants and replaced with literals.
You may try to compile on the MacOS again if you wish.

Re: TrigonMaster

Posted: Sat Sep 17, 2011 7:51 pm
by Polo
Thanks, it works nice, some adjustments would have to be made to the gadget widths but other than that, perfect!

Image

Re: TrigonMaster

Posted: Sat Oct 29, 2011 6:37 pm
by BasicallyPure
I have modified the code to run on Linux as well as Windows. (see the first post)

I have cleaned up the code and made it more compact.
Some of that was by using 'macros' which I have just learned to use.
Error handling has been improved.
The GUI was redesigned for the 'Force Size' functions.

For Linux compatibility, the string gadgets were resized to accommodate the larger default font.

I struggled with the spin gadgets under Linux because they do not operate the same as under Windows.
I developed a work-around and now everything is fine, but there is one difference.
With Windows, the spin gadget will auto-repeat if the mouse button is held down and Linux does not.
I don't have a fix for this but it is not really a problem.

TrigonMaster can be a handy tool for solving real world problems.
I hope some of you find it useful.