1::<HTML>
2::<HEAD><TITLE>TA </TITLE>
3::<TITLE>
4::php Triangle Graphing Program -- Andy Carter
5::</TITLE>
6::</HEAD>
7::
8::<BODY>
9::<?php
10::// works with calls from tangle028.htm <br>
11::// ta_1 org from 2008
12::// t1.010 off prohosting
13::// ta.011
14::// ta.012 strip out all .011 stuff and start over parsting error
15::// ta.013 law of sines working
16::// ta.015 put in comparison stuff into triangle class (not used yet) got dump of sides to work
17::// ta.016 sorts, but needs cleaning up need to move where sorted and note sorted length index
18::// also not getting toBool function to find falses
19::// ta.017 working on items of .016
20::// ta.018 working on list of .016 getting usort to work
21::// ta.019 still on .016 list cleaning up
22::// ta.020 ... ta.022 cleaned up from .016 list on to graphing
23::// ta.023 counts file entries and forms name
24::// ta.024 last and web page before making as an image
25::// mistake to try to make an image
26::// .027 back from .024 or .025
27::// .028 built long GET list to make image files
28::// .029 still working on making long GET list
29::// ,031 getting close on GET string
30::// .032
31::// .033 incorporated call to grphTri.php
32::// .035 is graphing but messy
33::// .036 building table to show results
34::// .037 my_Echo works
35::// .038
36::// .039
37::// .040 problems with line 386 $failureMsg
38::// .041
39::// .042 putting givens and calc values into left cell
40::// .043 better message when called with 0's in values fields
41::// .044 saved to "A" directory
42::// .045 saved for "B" dir added support for passed in $Title and T1sl[] and T2sl[]
43::// .046 saved for "B" dir
44:: $solnCnt = 0;
45::
46::    $showInfo = true;
47::
48::function my_Echo($input)
49::   {
50::   global $temp_outPut;
51::   $temp_outPut .= $input;
52::   if(true) // set to false to turn off echo
53::      echo $input;
54::   }
55::
56::// my_Echo("TEST MY ECHO \$showInfo = $showInfo TEST MY ECHO ");
57::
58::
59::$leftCell = ""; // text content on page assigned to left cell of table
60::$failureMsg = ""; // message why doesn't graph
61::
62::function Bool2Str($strIn)
63::   {
64::   if( substr( strtoupper($strIn),0,1) == "T")
65::     return TRUE;
66::   return FALSE;
67::   }
68::
69::
70::function dataI($item,$sCnt,$type,$Givens)
71::   {
72::   return $dex =($sCnt-1)*6+ ($type-1)*3+$item+($Givens-1)*12;
73::   }
74::function bldItemName($item,$sCnt,$type)
75::   {
76::   $name= "P_Val_";
77::   if($type == 1)
78::       $name= $name."S";
79::   else
80::       $name= $name."A";
81::   $name= $name.$item."_".$sCnt;
82::   return $name;
83::   }
84::function str2Bool($Input)
85::   {
86::// var $retVal;
87::   $firstChar = "";
88::   $retVal = false;
89::    $firstChar = Substr($Input,0,1);
90::     switch($firstChar)
91::        {
92::        case "T":
93::        case "t":
94::           $retVal = true;
95::           break;
96::        case "F":
97::        case "f":
98::        default:
99::           $retVal = false;
100::           break;
101::        }
102::   return $retVal;
103::   }
104::
105::
106::class side
107::   {
108::   var $length;
109::   var $given;
110::   var $sideNum;
111::   var $sideLabel;
112::   function setLength($value)
113::      {
114::      $this->length = $value;
115::      }
116::   function getLength()
117::      {
118::      return $this->length;
119::      }
120::   function setGiven($value)
121::     {
122::     $this->given = $value;
123::     }
124::   function getGiven()
125::     {
126::     return $this->given;
127::     }
128::   function setSideNum($value)
129::     {
130::     $this->sideNum = $value;
131::     }
132::   function getSideNum()
133::     {
134::     return $this->sideNum;
135::     }
136::   function setsideLabel($value)
137::     {
138::     $this->sideLabel = $value;
139::     }
140::   function getsideLabel()
141::     {
142::     return $this->sideLabel;
143::     }
144::   }
145::
146::class angle
147::   {
148::   var $angle;
149::   var $given;
150::   function setAngle($value)
151::      {
152::      $this->angle = $value;
153::      }
154::   function getAngle()
155::      {
156::      return $this->angle;
157::      }
158::   function setGiven($value)
159::     {
160::     $this->given = $value;
161::     }
162::   function getGiven()
163::     {
164::     return $this->given;
165::     }
166::   }
167::
168::// see http://stackoverflow.com/questions/4282413/php-sort-array-of-objects-by-object-fields
169::// for using usort
170::
171::   function revCompSidesLengths($a,$b)
172::      {
173::       // $a,$b being side objects in array sides of this triangle object
174::       // compares the lengths field
175::       // used by usort function for arrays
176::       // see http://stackoverflow.com/questions/4282413/php-sort-array-of-objects-by-object-fields
177::       if($a->length < $b->length)
178::          return 1;
179::       if($b->length < $a->length)
180::          return -1;
181::       return 0;
182::       }
183::
184::   function compSidesSideNum($a,$b)
185::      {
186::       // $a,$b being side objects in array sides of this triangle object
187::       // compares the sideNums field
188::       // used by usort function for arrays
189::       // see http://stackoverflow.com/questions/4282413/php-sort-array-of-objects-by-object-fields
190::       if($a->sideNum > $b->sideNum)
191::          return 1;
192::       if($b->sideNum > $a->sideNum)
193::          return -1;
194::       return 0;
195::       }
196::
197::
198::
199::
200::class tAngle
201::   {
202::   var $sides;
203::   var $angles;
204::   var $long2Short;
205::   var $setsOK = true;
206::   var $devMsg = "";
207::   // **** following for graphing
208::   var $IWidth; // wdth of image Make 400 in constructor
209::   var $IHMargin; // horizontal margin Make 15 in constuctor
210::   var $IVMargin; // vertical margin Set the same in construction
211::   var $IMinHeight; // NOt sure set in constructor
212::   var $IHeight ; // Greater of $IMinHeight or 2 * $IVMargin + height of graphed triangle
213::   var $iName;
214::   var $Title;
215::   function tAngle()
216::      {
217::      $this->sides = array ( new side(), new side(), new side() );
218::      $this->angles = array ( new angle(), new angle(), new angle() );
219::      $this->long2Short = array (0,1,2); // Dummy Data will give indices for $sides from longest to shortest
220::      $this->devMsg = "";
221::
222::      $this->IWidth = 400;
223::      $this->IHMargin = 15;
224::      $this->IVMargin = $this->IHMargin;
225::      $this->IMinHeight = 200; // arbitrary determine later
226::      $this->iName = "" ; // set later
227::
228::      $Title;
229::      }
230::
231::   function YtoGCoord($y)
232::      {
233::      if( ($retval = $this->IHeight-$y) < 0)
234::           {
235::           $retval = 0;
236::           }
237::      return $retval;
238::      }
239::   function prepareGraph()
240::      {
241::      $retVal = "";
242::      // graphics coordinates are from upper left with to right and down being positive
243::      // these calculations will be done using lower right as 0,0 and a transformation will be done
244::     
245::      // Graph will have longest side (a) being a horizontal line at bottom
246::      // shortest side (c) will be at left side
247::      // Vertices are labeled opposite across the triangle from the side number
248::      // so A is the peak, B is left and C is right
249::
250::      // Determine a scaling factor margins on either side of longest side
251::      $this->dumpArrays();
252::      $longSideNum = $this->long2Short[0];
253::      $longSideLen = $this->sides[($longSideNum-1)]->getLength();
254::      $scaleFactor = ($this->IWidth - 2.0 * $this->IHMargin) / $longSideLen;
255::
256::                        
257::      // Since the shortest side is at the left, the angle for the opposite the mid
258::      // length side is at the left
259::      $midAngRad = $this->angles[($this->long2Short[1]-1)]->getAngle() * pi()/180;
260::      $shortSideLen = $this->sides[($this->long2Short[2]-1)]->getLength();
261::
262::
263::      // using short side as hypotenuse and angle opposite mid length side
264::      // determine height to peak and offset of peak from left
265::      $height = sin( $midAngRad )*$shortSideLen;
266::      $offset = cos( $midAngRad )*$shortSideLen;
267::     
268::      $scaleHeight = round($height* $scaleFactor);
269::      $scaleOffset = round($offset* $scaleFactor);
270::
271::      if( ($this->IHeight = $this->IVMargin*2+$scaleHeight ) <$this->IMinHeight )
272::           $this->IHeight = $this->IMinHeight;
273::
274::      $this->IHeight = 400;
275::
276::      $S1= round($this->sides[0]->getLength(),1);
277::      $S2= round($this->sides[1]->getLength(),1);
278::      $S3= round($this->sides[2]->getLength(),1);
279::      $Title= $this->iName;
280::      if(strlen($tempStr=$this->sides[0]->getsideLabel()) >0)
281::         $S1 = $tempStr;
282::      if(strlen($tempStr=$this->sides[1]->getsideLabel()) >0)
283::         $S2 = $tempStr;
284::      if(strlen($tempStr=$this->sides[2]->getsideLabel()) >0)
285::         $S3 = $tempStr;
286::      if(strlen($tempStr=$this->Title) >0)
287::         $Title = $tempStr;
288::
289::     $retVal = "width=$this->IWidth&".
290::               "height=$this->IHeight&".
291::               "Ybase=".$this->YtoGCoord($this->IVMargin)."&".
292::               "Ypeak=".$this->YtoGCoord($this->IVMargin+$scaleHeight)."&".
293::               "Xleft=$this->IHMargin&".
294::               "Xpeak=".($this->IHMargin+ $scaleOffset)."&".
295::               "Xright=".($this->IWidth-$this->IHMargin)."&".
296::                "Aside=".$this->long2Short[0]."&".
297::                "Bside=".$this->long2Short[1]."&".
298::                "Cside=".$this->long2Short[2]."&".
299::                "S1=$S1&".
300::                "S2=$S2&".
301::                "S3=$S3&".
302::                "A1=".round($this->angles[0]->getAngle(),1)."&".
303::                "A2=".round($this->angles[1]->getAngle(),1)."&".
304::                "A3=".round($this->angles[2]->getAngle(),1)."&".
305::                "iName=".$this->iName."&".
306::                 "Title=$Title";
307::
308::
309::     return $retVal;
310::     }
311::   function setSideAng($V,$S,$Sg,$A,$Ag,$Side)
312::     {
313::     $this->sides[$V]->setLength($S);
314::     $this->sides[$V]->setGiven($Sg);
315::     $this->sides[$V]->setSideNum($Side);
316::     $this->angles[$V]->setAngle($A);
317::     $this->angles[$V]->setGiven($Ag);
318::     if( ($S <=0) OR ($A <=0) )
319::        $this->setsOK = false;
320::     }
321::   function dumpSideInfoAng($V)
322::     {
323::     $retVal = "Side:".$this->sides[$V]->getSideNum()." Length:". $this->sides[$V]->getLength($S).
324::        "Side is Given:".$this->sides[$V]->getGiven()." Opposite Angle:".$this->angles[$V]->getAngle().
325::        "Angle is Given:".$this->angles[$V]->getGiven();
326::     return $retVal;
327::     }
328::   function dumpArrays()
329::     {
330::     $retVal = $this->dumpSideInfoAng(0)."<br>\n".$this->dumpSideInfoAng(1)."<br>\n".
331::              $this->dumpSideInfoAng(2)."<br>\n";
332::     return $retVal;
333::     }
334::    
335::   function findLong2Short()
336::     {
337::// for info on usort see
338::// http://stackoverflow.com/questions/4282413/php-sort-array-of-objects-by-object-fields
339::
340::
341::    usort($this->sides,"revCompSidesLengths");
342::    // note order of sides sorted by length
343::     for($cnt=0; $cnt < 3; $cnt++)
344::        $this->long2Short[$cnt] = $this->sides[$cnt]->getSideNum();
345::
346::
347::     usort($this->sides,"compSidesSideNum");
348::     }
349::
350::
351::   function checkLawOfSines()
352::      {
353::      $ave = 0;
354::      $maxDev = 0;
355::      $tempDev = 0;
356::      $length = 0;
357::      $angR = 0;
358::      $this->devMsg = "";
359::      for($cnt = 0; $cnt<3;$cnt++)
360::         {
361::         $angR = $this->angles[$cnt]->getAngle()*pi()/180.0;
362::         $length = $this->sides[$cnt]->getLength();
363::         if($length <=0)
364::            return false; // can't divide by 0
365::         else
366::            {
367::            $ave += sin($angR)/($length*3); // save dividing by 3 later
368::            }
369::         }
370::      for($cnt = 0; $cnt<3;$cnt++)
371::         {
372::         $angR = $this->angles[$cnt]->getAngle()*pi()/180.0;
373::         $length = $this->sides[$cnt]->getLength();
374::         if( ($tempDev = ( abs( ( sin($angR)/$length - $ave )/$ave) ) )> $maxDev)
375::             $maxDev = $tempDev;
376::         }
377::      if($maxDev > 0.005)
378::         $this->devMsg = "\$maxDev = $maxDev ";
379::      if($maxDev > 0.02) // 2%
380::          return false;
381::      return true;
382::      }
383::   }
384::
385::
386::
387::$TriAngle = array (new tAngle(), new tAngle());
388::
389::if(isset($Title))
390::     {
391::     $TriAngle[0]->Title = $Title;
392::     $TriAngle[1]->Title = $Title;
393::     }
394::
395::for($cnt = 0; $cnt <3; $cnt++)
396::   {
397::   if(isset($T1S))
398::      $TriAngle[0]-> setSideAng($cnt,($T1S[$cnt]*1),str2Bool($T1Sg[$cnt]),($T1A[$cnt]*1),str2Bool($T1Ag[$cnt]),($cnt+1));
399::   else
400::      $failureMsg .= 'program was called without variable "T1S" (and presumably others) not set <br>\n';
401::   if(isset($T1Sl))
402::      {
403::      $TriAngle[0]->sides[$cnt]->setsideLabel($T1Sl[$cnt]);
404::// $TriAngle[0]->$sides[$cnt]->setsideLabel("");
405::      }
406::   else
407::      $TriAngle[0]->sides[$cnt]->setsideLabel("");
408::   if(isset($T2S))
409::       $TriAngle[1]-> setSideAng($cnt,($T2S[$cnt]*1),str2Bool($T2Sg[$cnt]),($T2A[$cnt]*1),str2Bool($T2Ag[$cnt]),($cnt+1));
410::   if(isset($T2Sl))
411::      {
412::      $TriAngle[1]->sides[$cnt]->setsideLabel($T2Sl[$cnt]);
413::// $TriAngle[1]->$sides[$cnt]->setsideLabel("");
414::      }
415::   else
416::      $TriAngle[1]->sides[$cnt]->setsideLabel("");
417::   }
418::if(!($TriAngle[0]->setsOK))
419::   $failureMsg .= 'one or more angle or side values is 0 or less -- most likely triangle not solved on calling page '."<br>\n";
420::
421::   if(isset($T1S))
422::      if($TriAngle[0]->checkLawOfSines())
423::         {
424::         $solnCnt++;
425::         $TriAngle[0]->findLong2Short();
426::         if(isset($T2S))
427::            if($TriAngle[1]->checkLawOfSines())
428::               {
429::               $solnCnt++;
430::               $TriAngle[1]->findLong2Short();
431::               }
432::            else
433::                $failureMsg .= 'Inconsistancies found in data for solution 2 :: specificly ratios of sines of angles to opposite sides not constant <br>';
434::
435::         }
436::      else
437::          $failureMsg .= 'Inconsistancies found in data:: specificly ratios of sines of angles to opposite sides not constant <br>';
438::
439::
440::
441::$imgCntFile = "./cntPicts.txt";
442::if(file_exists($imgCntFile))
443::   {
444::   $fp = fopen($imgCntFile,"r");
445::   $imgCnt= (int) fread($fp,20);
446::   fclose($fp);
447::   }
448::else
449::   $imgCnt= 515; // arbitrary #'s
450::
451::if( $imgCnt > 32000)
452::   $imgCnt= 103; // arbitrary #'s
453::
454::
455::   $fp = fopen($imgCntFile,"w");
456::   fwrite($fp,($imgCnt+$solnCnt));
457::   fclose($fp);
458::
459::  
460::   // $this->long2Short = array (0,1,2); // Dummy Data will give indices for $sides from longest to shortest
461::   $solnSubSt = ""; // adds solution count if more than a
462::   $imgHTML_Str = array("","");
463::   for($cnt=0; $cnt<$solnCnt; $cnt++)
464::      {
465::      if($solnCnt>1)
466::         {
467::         $solnSubSt=" Solution: ".($cnt+1);
468::         if( strlen($tempStr = $TriAngle[0]->$Title)>0)
469::             $TriAngle[$cnt]->$Title = "$tempStr $solnSubSt";
470::         }
471::      $tempName="000000".($imgCnt+$cnt);
472::      $tempLen = strlen($tempName);
473::      $tempName = Substr($tempName,$tempLen-5,5);
474::   // should have used sprintf in 3 preceeding lines
475::      $TriAngle[$cnt]->iName = $tempName.$solnSubSt;
476::      $argStr= 'grphTri.php?'.$TriAngle[$cnt]->prepareGraph();
477::      $imgHTML_Str[$cnt] = "<img src=\"$argStr\" align=\"right\" alt=\"$argStr\" width=\"400\" height=\"400\">\n";
478::      }
479::///// *************************
480::  echo '<br clear="all">';
481::if($solnCnt > 0)
482::   {
483::   $leftCell .= "Given Values:<ul>\n";
484::   for($cnt=0; $cnt<3; $cnt++)
485::      if($TriAngle[0]->sides[$cnt]->getGiven())
486::          $leftCell .= "<li> Side ".($cnt+1)." = ".$TriAngle[0]->sides[$cnt]->getLength()."\n";
487::   for($cnt=0; $cnt<3; $cnt++)
488::      if($TriAngle[0]->angles[$cnt]->getGiven())
489::          $leftCell .= "<li> Angle ".($cnt+1)." = ".$TriAngle[0]->angles[$cnt]->getAngle()."\n";
490::   $leftCell .= "</ul>\n";
491::
492::   $MoreSoln = "";
493::   for($cnt2 = 0; $cnt2 <$solnCnt; $cnt2++)
494::      {
495::      if($solnCnt > 1)
496::        $MoreSoln = "Solution ".($cnt2+1)." ";
497::      $leftCell .= "$MoreSoln Calculated Values:<ul>\n";
498::      for($cnt=0; $cnt<3; $cnt++)
499::         if(!($TriAngle[$cnt2]->sides[$cnt]->getGiven()))
500::             $leftCell .= "<li> Side ".($cnt+1)." = ".$TriAngle[$cnt2]->sides[$cnt]->getLength()."\n";
501::      for($cnt=0; $cnt<3; $cnt++)
502::         if(!($TriAngle[$cnt2]->angles[$cnt]->getGiven()))
503::             $leftCell .= "<li> Angle ".($cnt+1)." = ".$TriAngle[$cnt2]->angles[$cnt]->getAngle()."\n";
504::      $leftCell .= "</ul>\n";
505::      }
506::
507::
508::
509::   echo '<table border="0">';
510::   echo '<tr><td ';
511::   if($solnCnt > 1)
512::       echo ' rowspan="2" ';
513::   echo "> \n $leftCell \n</td>\n <td> \n". $imgHTML_Str[0]."</td></tr>\n";
514::   if($solnCnt > 1)
515::     {
516::     echo '<tr><td> '.$imgHTML_Str[1]."\n</td></tr>\n";
517::     }
518::   echo "</table>\n";
519::   }
520::else
521::   echo $failureMsg;
522::
523::
524::
525::////////////////////////
526::// REMAINING STUFF IS VARIABLE DUMPING CODE TURNED OFF BY NEXT IF(FALSE)
527::////////////////////////
528::
529::if(false) {
530::echo "<hr>";;
531::// echo 'var_dump($_POST)<br>';
532::var_dump($_POST);
533::echo "<hr>";
534::// phpinfo();
535::echo "Passed Variables:<br>\n";
536::if (is_array($_POST) && count($_POST) > 1)
537::   {
538::   if(isset($_POST["hGSoln"]))
539::      echo "<br> found set <br>".$_POST["hGSoln"]." ".Bool2Str($_POST["hGSoln"])."<br>";
540::// $message = '';
541::   foreach ($_POST as $passedVar)
542::      echo " $passedVar isarray".is_array($passedVar)." isInt".is_int($passedVar)." <br>\n";
543::   }
544::echo "<br><br><hr><br><br>\n";
545::
546::
547::if (is_array($_POST) && count($_POST) > 1)
548::   {
549::// $message = '';
550::   foreach ($_POST as $passedVar)
551::      echo " $passedVar isarray".is_array($passedVar)." isInt".is_int($passedVar)." <br>\n";
552::   }
553::echo "<br><br><br><br>\n";
554::}
555::?>
556::
557::</BODY>
558::</HTML>