⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jpgraph_pie.php

📁 极限网络智能办公系统 Office Automation V3.0官方100%源代码.
💻 PHP
📖 第 1 页 / 共 3 页
字号:
          $accsum += $d; 
          $angle2 = $this->startangle+2*M_PI*$accsum/$sum; 
          if( empty($this->explode_radius[$j]) ) 
           $this->explode_radius[$j]=0; 

          $la = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1); 

          $xcm = $xc + $this->explode_radius[$j]*cos($la)*$expscale; 
          $ycm = $yc - $this->explode_radius[$j]*sin($la)*$expscale; 
           
          $xcm += $this->ishadowdrop*$expscale; 
          $ycm += $this->ishadowdrop*$expscale; 

          $img->CakeSlice($xcm,$ycm,$radius,$radius, 
                    $angle1*180/M_PI,$angle2*180/M_PI,$this->ishadowcolor); 
           
      } 
     } 

     $accsum=0; 
     $angle2 = $this->startangle; 
     $img->SetColor($this->color); 
     for($i=0; $sum>0 && $i < $n; ++$i) { 
      $j = $n-$i-1; 
      if( empty($this->explode_radius[$j]) ) 
          $this->explode_radius[$j]=0; 
      $d = $this->data[$i]; 
      $angle1 = $angle2; 
      $accsum += $d; 
      $angle2 = $this->startangle+2*M_PI*$accsum/$sum; 
      $this->la[$i] = 2*M_PI - (abs($angle2-$angle1)/2.0+$angle1); 

      if( $d == 0 ) continue; 

      if( $this->setslicecolors==null ) 
          $slicecolor=$colors[$ta[$i%$numcolors]]; 
      else 
          $slicecolor=$this->setslicecolors[$i%$numcolors]; 

      if( $this->pie_interior_border && $aaoption===0 ) 
          $img->SetColor($this->color); 
      else 
          $img->SetColor($slicecolor); 

      $arccolor = $this->pie_border && $aaoption===0 ? $this->color : ""; 

      $xcm = $xc + $this->explode_radius[$j]*cos($this->la[$i])*$expscale; 
      $ycm = $yc - $this->explode_radius[$j]*sin($this->la[$i])*$expscale; 

      if( $aaoption !== 2 ) { 
          $img->CakeSlice($xcm,$ycm,$radius-1,$radius-1, 
                    $angle1*180/M_PI,$angle2*180/M_PI,$slicecolor,$arccolor); 
      } 

      if( $this->csimtargets && $aaoption !== 1 ) { 
          $this->AddSliceToCSIM($i,$xcm,$ycm,$radius,$angle1,$angle2); 
      } 
     } 

     // Format the titles for each slice 
     if( $aaoption!==2) { 
      for( $i=0; $i < $n; ++$i) { 
          if( $this->labeltype==0 ) { 
           if( $sum != 0 ) 
               $l = 100.0*$this->data[$i]/$sum; 
           else 
               $l = 0.0; 
          } 
          elseif( $this->labeltype==1 ) { 
           $l = $this->data[$i]*1.0; 
          } 
          else { 
           $l = $this->adjusted_data[$i]; 
          } 
          if( isset($this->labels[$i]) && is_string($this->labels[$i]) ) 
           $this->labels[$i]=sprintf($this->labels[$i],$l); 
          else 
           $this->labels[$i]=$l; 
      } 
     } 

     If( $this->value->show && $aaoption !== 1 ) { 
      $this->StrokeAllLabels($img,$xc,$yc,$radius); 
     } 

     // Adjust title position 
     if( $aaoption !== 1 ) { 
      $this->title->Pos($xc, 
                $yc-$this->title->GetFontHeight($img)-$radius-$this->title->margin, 
                "center","bottom"); 
      $this->title->Stroke($img); 
     } 

} 

//--------------- 
// PRIVATE METHODS      

function NormAngle($a) { 
     while( $a < 0 ) $a += 2*M_PI; 
     while( $a > 2*M_PI ) $a -= 2*M_PI; 
     return $a; 
} 

function Quadrant($a) { 
     $a=$this->NormAngle($a); 
     if( $a > 0 && $a <= M_PI/2 ) 
      return 0; 
     if( $a > M_PI/2 && $a <= M_PI ) 
      return 1; 
     if( $a > M_PI && $a <= 1.5*M_PI ) 
      return 2; 
     if( $a > 1.5*M_PI ) 
      return 3; 
} 

function StrokeGuideLabels($img,$xc,$yc,$radius) { 
     $n = count($this->labels); 

     //----------------------------------------------------------------------- 
     // Step 1 of the algorithm is to construct a number of clusters 
     // a cluster is defined as all slices within the same quadrant (almost) 
     // that has an angualr distance less than the treshold 
     //----------------------------------------------------------------------- 
     $tresh_hold=25 * M_PI/180; // 25 degrees difference to be in a cluster 
     $incluster=false;     // flag if we are currently in a cluster or not 
     $clusters = array();     // array of clusters 
     $cidx=-1;          // running cluster index 

     // Go through all the labels and construct a number of clusters 
     for($i=0; $i < $n-1; ++$i) { 
      // Calc the angle distance between two consecutive slices 
      $a1=$this->la[$i]; 
      $a2=$this->la[$i+1]; 
      $q1 = $this->Quadrant($a1); 
      $q2 = $this->Quadrant($a2); 
      $diff = abs($a1-$a2); 
      if( $diff < $tresh_hold ) { 
          if( $incluster ) { 
           $clusters[$cidx][1]++; 
           // Each cluster can only cover one quadrant 
           // Do we cross a quadrant ( and must break the cluster) 
           if( $q1 != $q2 ) { 
               // If we cross a quadrant boundary we normally start a 
               // new cluster. However we need to take the 12'a clock 
               // and 6'a clock positions into a special consideration. 
               // Case 1: WE go from q=1 to q=2 if the last slice on 
               // the cluster for q=1 is close to 12'a clock and the 
               // first slice in q=0 is small we extend the previous 
               // cluster 
               if( $q1 == 1 && $q2 == 0 && $a2 > (90-15)*M_PI/180 ) { 
                if( $i < $n-2 ) { 
                    $a3 = $this->la[$i+2]; 
                    // If there isn't a cluster coming up with the next-next slice 
                    // we extend the previous cluster to cover this slice as well 
                    if( abs($a3-$a2) >= $tresh_hold ) { 
                     $clusters[$cidx][1]++; 
                     $i++; 
                    } 
                } 
               } 
               elseif( $q1 == 3 && $q2 == 2 && $a2 > (270-15)*M_PI/180 ) { 
                if( $i < $n-2 ) { 
                    $a3 = $this->la[$i+2]; 
                    // If there isn't a cluster coming up with the next-next slice 
                    // we extend the previous cluster to cover this slice as well 
                    if( abs($a3-$a2) >= $tresh_hold ) { 
                     $clusters[$cidx][1]++; 
                     $i++; 
                    } 
                } 
               } 

               if( $q1==2 && $q2==1 && $a2 > (180-15)*M_PI/180 ) { 
                $clusters[$cidx][1]++; 
                $i++;                
               } 
                
               $incluster = false; 
           } 
          } 
          elseif( $q1 == $q2) { 
           $incluster = true; 
           // Now we have a special case for quadrant 0. If we previously 
           // have a cluster of one in quadrant 0 we just extend that 
           // cluster. If we don't do this then we risk that the label 
           // for the cluster of one will cross the guide-line 
           if( $q1 == 0 && $cidx > -1 && 
               $clusters[$cidx][1] == 1 && 
               $this->Quadrant($this->la[$clusters[$cidx][0]]) == 0 ) { 
               $clusters[$cidx][1]++; 
           } 
           else { 
               $cidx++; 
               $clusters[$cidx][0] = $i; 
               $clusters[$cidx][1] = 1; 
           } 
          } 
          else { 
           // Create a "cluster" of one since we are just crossing 
           // a quadrant 
           $cidx++; 
           $clusters[$cidx][0] = $i; 
           $clusters[$cidx][1] = 1;      
          } 
      } 
      else { 
          if( $incluster ) { 
           // Add the last slice 
           $clusters[$cidx][1]++; 
           $incluster = false; 
          } 
          else { // Create a "cluster" of one 
           $cidx++; 
           $clusters[$cidx][0] = $i; 
           $clusters[$cidx][1] = 1;      
          } 
      } 
     } 
     // Handle the very last slice 
     if( $incluster ) { 
      $clusters[$cidx][1]++; 
     } 
     else { // Create a "cluster" of one 
      $cidx++; 
      $clusters[$cidx][0] = $i; 
      $clusters[$cidx][1] = 1;      
     } 

     /* 
     if( true ) { 
      // Debug printout in labels 
      for( $i=0; $i <= $cidx; ++$i ) { 
          for( $j=0; $j < $clusters[$i][1]; ++$j ) { 
           $a = $this->la[$clusters[$i][0]+$j]; 
           $aa = round($a*180/M_PI); 
           $q = $this->Quadrant($a); 
           $this->labels[$clusters[$i][0]+$j]="[$q:$aa] $i:$j"; 
          } 
      } 
     } 
     */ 

     //----------------------------------------------------------------------- 
     // Step 2 of the algorithm is use the clusters and draw the labels 
     // and guidelines 
     //----------------------------------------------------------------------- 

     // We use the font height as the base factor for how far we need to 
     // spread the labels in the Y-direction. 
     $img->SetFont($this->value->ff,$this->value->fs,$this->value->fsize); 
     $fh = $img->GetFontHeight(); 
     $origvstep=$fh*$this->iGuideVFactor; 
     $this->value->SetMargin(0); 

     // Number of clusters found 
     $nc = count($clusters); 

     // Walk through all the clusters 
     for($i=0; $i < $nc; ++$i) { 

      // Start angle and number of slices in this cluster 
      $csize = $clusters[$i][1]; 
      $a = $this->la[$clusters[$i][0]]; 
      $q = $this->Quadrant($a); 

      // Now set up the start and end conditions to make sure that 
      // in each cluster we walk through the all the slices starting with the slice 
      // closest to the equator. Since all slices are numbered clockwise from "3'a clock" 
      // we have different conditions depending on in which quadrant the slice lies within. 
      if( $q == 0 ) { 
          $start = $csize-1; $idx = $start; $step = -1; $vstep = -$origvstep; 
      } 
      elseif( $q == 1 ) { 
          $start = 0; $idx = $start; $step = 1; $vstep = -$origvstep; 
      } 
      elseif( $q == 2 ) { 
          $start = $csize-1; $idx = $start; $step = -1; $vstep = $origvstep; 
      } 
      elseif( $q == 3 ) { 
          $start = 0; $idx = $start; $step = 1; $vstep = $origvstep; 
      } 

      // Walk through all slices within this cluster 
      for($j=0; $j < $csize; ++$j) { 
          // Now adjust the position of the labels in each cluster starting 
          // with the slice that is closest to the equator of the pie 
          $a = $this->la[$clusters[$i][0]+$idx]; 
           
          // Guide line start in the center of the arc of the slice 
          $r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)]; 
          $x = round($r*cos($a)+$xc); 
          $y = round($yc-$r*sin($a)); 
           
          // The distance from the arc depends on chosen font and the "R-Factor" 
          $r += $fh*$this->iGuideLineRFactor; 

          // Should the labels be placed curved along the pie or in straight columns 
          // outside the pie? 
          if( $this->iGuideLineCurve ) 
           $xt=round($r*cos($a)+$xc); 

          // If this is the first slice in the cluster we need some first time 
          // proessing 
          if( $idx == $start ) { 
           if( ! $this->iGuideLineCurve ) 
               $xt=round($r*cos($a)+$xc); 
           $yt=round($yc-$r*sin($a)); 

           // Some special consideration in case this cluster starts 
           // in quadrant 1 or 3 very close to the "equator" (< 20 degrees) 
           // and the previous clusters last slice is within the tolerance. 
           // In that case we add a font height to this labels Y-position 
           // so it doesn't collide with 
           // the slice in the previous cluster 
           $prevcluster = ($i + ($nc-1) ) % $nc; 
           $previdx=$clusters[$prevcluster][0]+$clusters[$prevcluster][1]-1; 
           if( $q == 1 && $a > 160*M_PI/180 ) { 
               // Get the angle for the previous clusters last slice 
               $diff = abs($a-$this->la[$previdx]); 
                if( $diff < $tresh_hold ) { 
                $yt -= $fh; 
                } 
           } 
           elseif( $q == 3 && $a > 340*M_PI/180 ) { 
               // We need to subtract 360 to compare angle distance between 
               // q=0 and q=3 
               $diff = abs($a-$this->la[$previdx]-360*M_PI/180); 
               if( $diff < $tresh_hold ) { 
                $yt += $fh; 
               } 
           } 

          } 
          else { 
           // The step is at minimum $vstep but if the slices are relatively large 
           // we make sure that we add at least a step that corresponds to the vertical 
           // distance between the centers at the arc on the slice 
           $prev_a = $this->la[$clusters[$i][0]+($idx-$step)]; 
           $dy = abs($radius*(sin($a)-sin($prev_a))*1.2); 
           if( $vstep > 0 ) 
               $yt += max($vstep,$dy); 
           else 
               $yt += min($vstep,-$dy); 
          } 

          $label = $this->labels[$clusters[$i][0]+$idx]; 

          if( $csize == 1 ) { 
           // A "meta" cluster with only one slice 
           $r = $radius+$this->explode_radius[$n-1-($clusters[$i][0]+$idx)]; 
           $rr = $r+$img->GetFontHeight()/2; 
           $xt=round($rr*cos($a)+$xc); 
           $yt=round($yc-$rr*sin($a)); 
           $this->StrokeLabel($label,$img,$xc,$yc,$a,$r); 
           if( $this->iShowGuideLineForSingle ) 
               $this->guideline->Stroke($img,$x,$y,$xt,$yt); 
          } 
          else { 
           $this->guideline->Stroke($img,$x,$y,$xt,$yt); 
           if( $q==1 || $q==2 ) { 
               // Left side of Pie 
               $this->guideline->Stroke($img,$xt,$yt,$xt-$this->guidelinemargin,$yt); 
               $lbladj = -$this->guidelinemargin-5; 
               $this->value->halign = "right"; 
               $this->value->valign = "center"; 
           } 
           else { 
               // Right side of pie 
               $this->guideline->Stroke($img,$xt,$yt,$xt+$this->guidelinemargin,$yt); 
               $lbladj = $this->guidelinemargin+5; 
               $this->value->halign = "left"; 
               $this->value->valign = "center"; 
           } 
           $this->value->Stroke($img,$label,$xt+$lbladj,$yt); 
          } 

          // Udate idx to point to next slice in the cluster to process 
          $idx += $step; 
      } 
     } 
} 

function StrokeAllLabels($img,$xc,$yc,$radius) { 
     // First normalize all angles for labels 
     $n = count($this->la); 
     for($i=0; $i < $n; ++$i) { 
      $this->la[$i] = $this->NormAngle($this->la[$i]); 
     } 
     if( $this->guideline->iShow ) { 
      $this->StrokeGuideLabels($img,$xc,$yc,$radius); 
     } 
     else { 
      $n = count($this->labels); 
      for($i=0; $i < $n; ++$i) { 
          $this->StrokeLabel($this->labels[$i],$img,$xc,$yc, 
                     $this->la[$i], 
                     $radius + $this->explode_radius[$n-1-$i]); 
      } 
     } 
} 

// Position the labels of each slice 
function StrokeLabel($label,$img,$xc,$yc,$a,$radius) { 

     // Default value 
     if( $this->ilabelposadj === 'auto' ) 
      $this->ilabelposadj = 0.65; 
     $r = $radius; 

     // We position the values diferently depending on if they are inside 
     // or outside the pie 
     if( $this->ilabelposadj < 1.0 ) { 

      $this->value->SetAlign('center','center'); 
      $this->value->margin = 0; 
      
      $xt=round($this->ilabelposadj*$r*cos($a)+$xc); 
      $yt=round($yc-$this->ilabelposadj*$r*sin($a)); 
      
      $this->value->Stroke($img,$label,$xt,$yt); 
     } 
     else { 

      $this->value->halign = "left"; 
      $this->value->valign = "top"; 
      $this->value->margin = 0; 
            
      // Position the axis title. 
      // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text 
      // that intersects with the extension of the corresponding axis. The code looks a little 
      // bit messy but this is really the only way of having a reasonable position of the 
      // axis titles. 
      $img->SetFont($this->value->ff,$this->value->fs,$this->value->fsize); 
      $h=$img->GetTextHeight($label); 
      // For numeric values the format of the display value 
      // must be taken into account 
      if( is_numeric($label) ) { 
          if( $label > 0 ) 
           $w=$img->GetTextWidth(sprintf($this->value->format,$label)); 
          else 
           $w=$img->GetTextWidth(sprintf($this->value->negformat,$label)); 
      } 
      else 
          $w=$img->GetTextWidth($label); 
      if( $this->ilabelposadj > 1.0 && $this->ilabelposadj < 5.0) { 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -