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

📄 jpgraph_pie3d.php

📁 极限网络智能办公系统 Office Automation V3.0官方100%源代码.
💻 PHP
📖 第 1 页 / 共 2 页
字号:
     for($i=0; $i<count($data); ++$i, ++$idx ) { 
      $da = $data[$i]/$sum * 360; 

      if( empty($this->explode_radius[$i]) ) 
          $this->explode_radius[$i]=0; 

      $expscale=1; 
      if( $aaoption == 1 ) 
          $expscale=2; 

      $la = $a + $da/2; 
      $explode = array( $xc + $this->explode_radius[$i]*cos($la*M_PI/180)*$expscale, 
           $yc - $this->explode_radius[$i]*sin($la*M_PI/180) * ($h/$d) *$expscale ); 
      $adjexplode[$idx] = $explode; 
      $labeldata[$i] = array($la,$explode[0],$explode[1]); 
      $originalangles[$i] = array($a,$a+$da); 

      $ne = $this->NormAngle($a+$da); 
      if( $da <= 180 ) { 
          // If the slice size is <= 90 it can at maximum cut across 
          // one boundary (either 90 or 270) where it needs to be split 
          $split=-1; // no split 
          if( ($da<=90 && ($a <= 90 && $ne > 90)) || 
           (($da <= 180 && $da >90) && (($a < 90 || $a >= 270) && $ne > 90)) ) { 
           $split = 90; 
          } 
          elseif( ($da<=90 && ($a <= 270 && $ne > 270)) || 
           (($da<=180 && $da>90) && ($a >= 90 && $a < 270 && ($a+$da) > 270 )) ) { 
           $split = 270; 
          } 
          if( $split > 0 ) { // split in two 
           $angles[$idx] = array($a,$split); 
           $adjcolors[$idx] = $colors[$i % $numcolors]; 
           $adjexplode[$idx] = $explode; 
           $angles[++$idx] = array($split,$ne); 
           $adjcolors[$idx] = $colors[$i % $numcolors]; 
           $adjexplode[$idx] = $explode; 
          } 
          else { // no split 
           $angles[$idx] = array($a,$ne); 
           $adjcolors[$idx] = $colors[$i % $numcolors]; 
           $adjexplode[$idx] = $explode;      
          } 
      } 
      else { 
          // da>180 
          // Slice may, depending on position, cross one or two 
          // bonudaries 

          if( $a < 90 ) 
           $split = 90; 
          elseif( $a <= 270 ) 
           $split = 270; 
          else 
           $split = 90; 

          $angles[$idx] = array($a,$split); 
          $adjcolors[$idx] = $colors[$i % $numcolors]; 
          $adjexplode[$idx] = $explode; 
          //if( $a+$da > 360-$split ) { 
          // For slices larger than 270 degrees we might cross 
          // another boundary as well. This means that we must 
          // split the slice further. The comparison gets a little 
          // bit complicated since we must take into accound that 
          // a pie might have a startangle >0 and hence a slice might 
          // wrap around the 0 angle. 
          // Three cases: 
          // a) Slice starts before 90 and hence gets a split=90, but 
          // we must also check if we need to split at 270 
          // b) Slice starts after 90 but before 270 and slices 
          // crosses 90 (after a wrap around of 0) 
          // c) If start is > 270 (hence the firstr split is at 90) 
          // and the slice is so large that it goes all the way 
          // around 270. 
          if( ($a < 90 && ($a+$da > 270)) || 
           ($a > 90 && $a<=270 && ($a+$da>360+90) ) || 
           ($a > 270 && $this->NormAngle($a+$da)>270) ) { 
           $angles[++$idx] = array($split,360-$split); 
           $adjcolors[$idx] = $colors[$i % $numcolors]; 
           $adjexplode[$idx] = $explode; 
           $angles[++$idx] = array(360-$split,$ne); 
           $adjcolors[$idx] = $colors[$i % $numcolors]; 
           $adjexplode[$idx] = $explode; 
          }      
          else { 
           // Just a simple split to the previous decided 
           // angle. 
           $angles[++$idx] = array($split,$ne); 
           $adjcolors[$idx] = $colors[$i % $numcolors]; 
           $adjexplode[$idx] = $explode; 
          } 
      } 
      $a += $da; 
      $a = $this->NormAngle($a); 
     } 

     // Total number of slices 
     $n = count($angles); 

     for($i=0; $i<$n; ++$i) { 
      list($dbgs,$dbge) = $angles[$i]; 
     } 

     // 
     // Step 2. Find start index (first pie that starts in upper left quadrant) 
     // 
     $minval = $angles[0][0]; 
     $min = 0; 
     for( $i=0; $i<$n; ++$i ) { 
      if( $angles[$i][0] < $minval ) { 
          $minval = $angles[$i][0]; 
          $min = $i; 
      } 
     } 
     $j = $min; 
     $cnt = 0; 
     while( $angles[$j][1] <= 90 ) { 
      $j++; 
      if( $j>=$n) { 
          $j=0; 
      } 
      if( $cnt > $n ) { 
          JpGraphError::Raise("Pie3D Internal error (#1). Trying to wrap twice when looking for start index"); 
      } 
      ++$cnt; 
     } 
     $start = $j; 

     // 
     // Step 3. Print slices in z-order 
     // 
     $cnt = 0; 
      
     // First stroke all the slices between 90 and 270 (left half circle) 
     // counterclockwise 
      
     while( $angles[$j][0] < 270 && $aaoption !== 2 ) { 

      list($x,$y) = $adjexplode[$j]; 

      $this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1], 
                $z,$adjcolors[$j],$shadow); 
      
      $last = array($x,$y,$j); 

      $j++; 
      if( $j >= $n ) $j=0; 
      if( $cnt > $n ) { 
          JpGraphError::Raise("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking."); 
      } 
      ++$cnt; 
     } 

     $slice_left = $n-$cnt; 
     $j=$start-1; 
     if($j<0) $j=$n-1; 
     $cnt = 0; 
      
     // The stroke all slices from 90 to -90 (right half circle) 
     // clockwise 
     while( $cnt < $slice_left && $aaoption !== 2 ) { 

      list($x,$y) = $adjexplode[$j]; 

      $this->Pie3DSlice($img,$x,$y,$d,$h,$angles[$j][0],$angles[$j][1], 
                $z,$adjcolors[$j],$shadow); 
      $j--; 
      if( $cnt > $n ) { 
          JpGraphError::Raise("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking."); 
      } 
      if($j<0) $j=$n-1; 
      $cnt++; 
     } 
      
     // Now do a special thing. Stroke the last slice on the left 
     // halfcircle one more time. This is needed in the case where 
     // the slice close to 270 have been exploded. In that case the 
     // part of the slice close to the center of the pie might be 
     // slightly nagged. 
     if( $aaoption !== 2 ) 
      $this->Pie3DSlice($img,$last[0],$last[1],$d,$h,$angles[$last[2]][0], 
                $angles[$last[2]][1],$z,$adjcolors[$last[2]],$shadow); 


     if( $aaoption !== 1 ) { 
      // Now print possible labels and add csim 
      $img->SetFont($this->value->ff,$this->value->fs); 
      $margin = $img->GetFontHeight()/2 + $this->value->margin ; 
      for($i=0; $i < count($data); ++$i ) { 
          $la = $labeldata[$i][0]; 
          $x = $labeldata[$i][1] + cos($la*M_PI/180)*($d+$margin); 
          $y = $labeldata[$i][2] - sin($la*M_PI/180)*($h+$margin); 
          if( $la > 180 && $la < 360 ) $y += $z; 
          if( $this->labeltype == 0 ) { 
           if( $sum > 0 ) 
               $l = 100*$data[$i]/$sum; 
           else 
               $l = 0; 
          } 
          elseif( $this->labeltype == 1 ) { 
           $l = $data[$i]; 
          } 
          else { 
           $l = $this->adjusted_data[$i]; 
          } 
          if( isset($this->labels[$i]) && is_string($this->labels[$i]) ) 
           $l=sprintf($this->labels[$i],$l); 

          $this->StrokeLabels($l,$img,$labeldata[$i][0]*M_PI/180,$x,$y,$z); 
      
          $this->AddSliceToCSIM($i,$labeldata[$i][1],$labeldata[$i][2],$h*2,$d*2,$z, 
                     $originalangles[$i][0],$originalangles[$i][1]); 
      }      
     } 

     // 
     // Finally add potential lines in pie 
     // 

     if( $edgecolor=="" || $aaoption !== 0 ) return; 

     $accsum = 0; 
     $a = $startangle; 
     $a = $this->NormAngle($a); 

     $a *= M_PI/180.0; 

     $idx=0; 
     $img->PushColor($edgecolor); 
     $img->SetLineWeight($edgeweight); 
      
     $fulledge = true; 
     for($i=0; $i < count($data) && $fulledge; ++$i ) { 
      if( empty($this->explode_radius[$i]) ) 
          $this->explode_radius[$i]=0; 
      if( $this->explode_radius[$i] > 0 ) { 
          $fulledge = false; 
      } 
     } 
      

     for($i=0; $i < count($data); ++$i, ++$idx ) { 

      $da = $data[$i]/$sum * 2*M_PI; 
      $this->StrokeFullSliceFrame($img,$xc,$yc,$a,$a+$da,$d,$h,$z,$edgecolor, 
                         $this->explode_radius[$i],$fulledge); 
      $a += $da; 
     } 
     $img->PopColor(); 
} 

function StrokeFullSliceFrame($img,$xc,$yc,$sa,$ea,$w,$h,$z,$edgecolor,$exploderadius,$fulledge) { 
     $step = 0.02; 

     if( $exploderadius > 0 ) { 
      $la = ($sa+$ea)/2; 
      $xc += $exploderadius*cos($la); 
      $yc -= $exploderadius*sin($la) * ($h/$w) ; 
      
     } 

     $p = array($xc,$yc,$xc+$w*cos($sa),$yc-$h*sin($sa)); 

     for($a=$sa; $a < $ea; $a += $step ) { 
      $p[] = $xc + $w*cos($a); 
      $p[] = $yc - $h*sin($a); 
     } 

     $p[] = $xc+$w*cos($ea); 
     $p[] = $yc-$h*sin($ea); 
     $p[] = $xc; 
     $p[] = $yc; 

     $img->SetColor($edgecolor); 
     $img->Polygon($p); 

     // Unfortunately we can't really draw the full edge around the whole of 
     // of the slice if any of the slices are exploded. The reason is that 
     // this algorithm is to simply. There are cases where the edges will 
     // "overwrite" other slices when they have been exploded. 
     // Doing the full, proper 3D hidden lines stiff is actually quite 
     // tricky. So for exploded pies we only draw the top edge. Not perfect 
     // but the "real" solution is much more complicated. 
     if( $fulledge && !( $sa > 0 && $sa < M_PI && $ea < M_PI) ) { 

      if($sa < M_PI && $ea > M_PI) 
          $sa = M_PI; 

      if($sa < 2*M_PI && (($ea >= 2*M_PI) || ($ea > 0 && $ea < $sa ) ) ) 
          $ea = 2*M_PI; 

      if( $sa >= M_PI && $ea <= 2*M_PI ) { 
          $p = array($xc + $w*cos($sa),$yc - $h*sin($sa), 
                $xc + $w*cos($sa),$z + $yc - $h*sin($sa)); 
           
          for($a=$sa+$step; $a < $ea; $a += $step ) { 
           $p[] = $xc + $w*cos($a); 
           $p[] = $z + $yc - $h*sin($a); 
          } 
          $p[] = $xc + $w*cos($ea); 
          $p[] = $z + $yc - $h*sin($ea); 
          $p[] = $xc + $w*cos($ea); 
          $p[] = $yc - $h*sin($ea); 
          $img->SetColor($edgecolor); 
          $img->Polygon($p);      
      } 
     } 
} 

function Stroke($img,$aaoption=0) { 
     $n = count($this->data); 

     // If user hasn't set the colors use the theme array 
     if( $this->setslicecolors==null ) { 
      $colors = array_keys($img->rgb->rgb_table); 
      sort($colors);      
      $idx_a=$this->themearr[$this->theme];      
      $ca = array(); 
      $m = count($idx_a); 
      for($i=0; $i < $m; ++$i) 
          $ca[$i] = $colors[$idx_a[$i]]; 
      $ca = array_reverse(array_slice($ca,0,$n)); 
     } 
     else { 
      $ca = $this->setslicecolors; 
     } 
      

     if( $this->posx <= 1 && $this->posx > 0 ) 
      $xc = round($this->posx*$img->width); 
     else 
      $xc = $this->posx ; 
      
     if( $this->posy <= 1 && $this->posy > 0 ) 
      $yc = round($this->posy*$img->height); 
     else 
      $yc = $this->posy ; 
                
     if( $this->radius <= 1 ) { 
      $width = floor($this->radius*min($img->width,$img->height)); 
      // Make sure that the pie doesn't overflow the image border 
      // The 0.9 factor is simply an extra margin to leave some space 
      // between the pie an the border of the image. 
      $width = min($width,min($xc*0.9,($yc*90/$this->angle-$width/4)*0.9)); 
     } 
     else { 
      $width = $this->radius * ($aaoption === 1 ? 2 : 1 ) ; 
     } 

     // Add a sanity check for width 
     if( $width < 1 ) { 
      JpGraphError::Raise("Width for 3D Pie is 0. Specify a size > 0"); 
      exit(); 
     } 

     // Establish a thickness. By default the thickness is a fifth of the 
     // pie slice width (=pie radius) but since the perspective depends 
     // on the inclination angle we use some heuristics to make the edge 
     // slightly thicker the less the angle. 
      
     // Has user specified an absolute thickness? In that case use 
     // that instead 

     if( $this->iThickness ) { 
      $thick = $this->iThickness; 
      $thick *= ($aaoption === 1 ? 2 : 1 ); 
     } 
     else 
      $thick = $width/12; 
     $a = $this->angle; 
     if( $a <= 30 ) $thick *= 1.6; 
     elseif( $a <= 40 ) $thick *= 1.4; 
     elseif( $a <= 50 ) $thick *= 1.2; 
     elseif( $a <= 60 ) $thick *= 1.0; 
     elseif( $a <= 70 ) $thick *= 0.8; 
     elseif( $a <= 80 ) $thick *= 0.7; 
     else $thick *= 0.6; 

     $thick = floor($thick); 

     if( $this->explode_all ) 
      for($i=0; $i < $n; ++$i) 
          $this->explode_radius[$i]=$this->explode_r; 

     $this->Pie3D($aaoption,$img,$this->data, $ca, $xc, $yc, $width, $this->angle, 
      $thick, 0.65, $this->startangle, $this->edgecolor, $this->edgeweight); 

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

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

// Position the labels of each slice 
function StrokeLabels($label,$img,$a,$xp,$yp,$z) { 
     $this->value->halign="left"; 
     $this->value->valign="top"; 

     // 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); 
     while( $a > 2*M_PI ) $a -= 2*M_PI; 
     if( $a>=7*M_PI/4 || $a <= M_PI/4 ) $dx=0; 
     if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dx=($a-M_PI/4)*2/M_PI; 
     if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dx=1; 
     if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dx=(1-($a-M_PI*5/4)*2/M_PI); 
           
     if( $a>=7*M_PI/4 ) $dy=(($a-M_PI)-3*M_PI/4)*2/M_PI; 
     if( $a<=M_PI/4 ) $dy=(1-$a*2/M_PI); 
     if( $a>=M_PI/4 && $a <= 3*M_PI/4 ) $dy=1; 
     if( $a>=3*M_PI/4 && $a <= 5*M_PI/4 ) $dy=(1-($a-3*M_PI/4)*2/M_PI); 
     if( $a>=5*M_PI/4 && $a <= 7*M_PI/4 ) $dy=0; 
      
     $x = round($xp-$dx*$w); 
     $y = round($yp-$dy*$h); 

      
// Mark anchor point for debugging 
     /* 
     $img->SetColor('red'); 
     $img->Line($xp-10,$yp,$xp+10,$yp); 
     $img->Line($xp,$yp-10,$xp,$yp+10); 
     */ 
     $oldmargin = $this->value->margin; 
     $this->value->margin=0; 
     $this->value->Stroke($img,$label,$x,$y); 
     $this->value->margin=$oldmargin; 

}      
} // Class 

/* EOF */ 
?> 

⌨️ 快捷键说明

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