<?php
@set_time_limit(3000);
/****************************************************************************
* fanchart.php *
* Original fan plotting code from PhpGedView (GNU/GPL licence) *
* *
* Rewritten and adapted for HuMo-gen by Yossi Beck - October 2009 *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
****************************************************************************/
$kop="fanchart";
include("header.php");
include ("include/language_date.php");
include("include/language_event.php");
include("include/calculate_age_cls.php");
include('include/person_cls.php');
require_once('fanchart/persian_log2vis.php');
include("menu.php");
$gezin_id=1; // *** 1e gezin weergeven als dit bestand rechtstreeks wordt aangeroepen. ***
if (isset($_GET["id"])){ $gezin_id=$_GET["id"]; }
if (isset($_POST["id"])){ $gezin_id=$_POST["id"]; }
$chosengen=5;
if (isset($_GET["chosengen"])){ $chosengen=$_GET["chosengen"]; }
if (isset($_POST["chosengen"])){ $chosengen=$_POST["chosengen"]; }
$fontsize=7;
if (isset($_GET["fontsize"])){ $fontsize=$_GET["fontsize"]; }
if (isset($_POST["fontsize"])){ $fontsize=$_POST["fontsize"]; }
$date_display=2;
if (isset($_GET["date_display"])){ $date_display=$_GET["date_display"]; }
if (isset($_POST["date_display"])){ $date_display=$_POST["date_display"]; }
$printing=1;
if (isset($_GET["printing"])){ $printing=$_GET["printing"]; }
if (isset($_POST["printing"])){ $printing=$_POST["printing"]; }
$treeid = array();
$maxperson = pow(2,$chosengen);
// initialize array
for ($i=0 ; $i < $maxperson; $i++) {
for ($n=0; $n<6; $n++) {
$treeid[$i][$n]="";
}
}
function fillarray ($nr, $famid) {
global $maxperson;
global $treeid;
global $db;
if ($nr >= $maxperson) { return; }
if ($famid) {
$persoonmn=mysql_query("SELECT * FROM ".veilig($_SESSION['tree_prefix'])."person
WHERE pers_gedcomnumber='".$famid."'",$db);
@$persoonmnDb=mysql_fetch_object($persoonmn);
$man_cls = New persoon_cls;
$man_cls->construct($persoonmnDb);
$levendmn=$man_cls->privacy;
$treeid[$nr][0]=$man_cls->naam($persoonmnDb);
$treeid[$nr][1]=$persoonmnDb->pers_birth_date;
$treeid[$nr][4]=$persoonmnDb->pers_death_date;
$pos=strpos($persoonmnDb->pers_fams,";");
if($pos===false) { $treeid[$nr][2]=$persoonmnDb->pers_fams; }
else {$treeid[$nr][2]=substr($persoonmnDb->pers_fams,0,$pos);}
$treeid[$nr][3]=$famid;
$treeid[$nr][5]=$persoonmnDb->pers_sexe;
if ($persoonmnDb->pers_famc){
$query_gezin= "SELECT * FROM ".veilig($_SESSION['tree_prefix'])."family
WHERE fam_gedcomnumber = '".$persoonmnDb->pers_famc."'";
$result_gezin = mysql_query($query_gezin,$db);
@$record_gezin = mysql_fetch_object($result_gezin);
if ($record_gezin->fam_man){
fillarray ($nr*2, $record_gezin->fam_man);
}
if ($record_gezin->fam_woman){
fillarray ($nr*2+1, $record_gezin->fam_woman);
}
}
}
} //END FUNCTION FILLARRAY
fillarray(1, $gezin_id);
/* split and center text by lines
* @param string $data input string
* @param int $maxlen max length of each line
* @return string $text output string
*/
function split_align_text($data, $maxlen, $rtlflag, $nameflag, $gennr) {
$lines = explode("\n", $data);
// more than 1 line : recursive calls
if (count($lines)>1) {
$text = "";
foreach ($lines as $indexval => $line) $text .= split_align_text($line, $maxlen, $rtlflag, $nameflag, $gennr )."\n";
return $text;
}
// process current line word by word
$split = explode(" ", $data);
$text = "";
$line = "";
if($rtlflag==1 AND $nameflag==1) { // rtl name has to be re-positioned
global $fan_style;
if($fan_style==2 AND ($gennr==1 OR $gennr==2)) { $maxlen *= 1.5; } // half-circle has different position for 2nd 3rd generation
else { $maxlen *= 2; }
}
$found = false;
if ($found) $line=$data;
else
foreach ($split as $indexval => $word) {
$len = strlen($line);
$wlen = strlen($word);
// line too long ?
if (($len+$wlen)<$maxlen) {
if (!empty($line)) $line .= " ";
$line .= "$word";
}
else {
$p = max(0,floor(($maxlen-$len)/2));
if (!empty($line)) {
if($rtlflag==1 AND $nameflag==1) { // trl name
$line = "$line".str_repeat(" ", $p); //
}
elseif ($rtlflag==1 AND $nameflag==0) {
$line = str_repeat(" ", $p*1.5) . "$line"; // center alignment using spaces
}
else {
$line = str_repeat(" ", $p) . "$line"; // center alignment using spaces
}
$text .= "$line\n";
}
$line = $word;
}
}
// last line
if (!empty($line)) {
$len = strlen($line);
//.. if (in_array(ord($line{0}),$RTLOrd)) $len/=2;
$p = max(0,floor(($maxlen-$len)/2));
if($rtlflag==1 AND $nameflag==1) {
$line = "$line".str_repeat(" ", $p);
}
elseif ($rtlflag==1 AND $nameflag==0) {
$line = str_repeat(" ", $p*1.5) . "$line"; // center alignment using spaces
}
else {
$line = str_repeat(" ", $p) . "$line"; // center alignment using spaces
}
$text .= "$line";
}
// $text.=$wlen;
return $text;
}
/**
* print ancestors on a fan chart
* @param array $treeid ancestry pid
* @param int $fanw fan width in px (default=840)
* @param int $fandeg fan size in deg (default=270)
*/
function print_fan_chart($treeid, $fanw=840, $fandeg=270) {
global $fontsize, $date_display;
global $fan_style, $gezin_id;
global $printing, $language;
// check for GD 2.x library
if (!defined("IMG_ARC_PIE")) {
print "ERROR: NO GD LIBRARY";
return false;
}
if (!function_exists("ImageTtfBbox")) {
print "ERROR: NO GD LIBRARY";
return false;
}
$fontfile="./fanchart/dejavusans.ttf";
if (intval($fontsize)<2) $fontsize = 7;
$treesize=count($treeid);
if ($treesize<1) return;
// generations count
$gen=log($treesize)/log(2)-1;
$sosa=$treesize-1;
// fan size
if ($fandeg==0) $fandeg=360;
$fandeg=min($fandeg, 360);
$fandeg=max($fandeg, 90);
$cx=$fanw/2-1; // center x
$cy=$cx; // center y
$rx=$fanw-1;
$rw=$fanw/($gen+1);
$fanh=$fanw; // fan height
if ($fandeg==180) $fanh=round($fanh*($gen+1)/($gen*2));
if ($fandeg==270) $fanh=round($fanh*.86);
$scale=$fanw/840;
// image init
$image = ImageCreate($fanw, $fanh);
$black = ImageColorAllocate($image, 0, 0, 0);
$white = ImageColorAllocate($image, 0xFF, 0xFF, 0xFF);
ImageFilledRectangle ($image, 0, 0, $fanw, $fanh, $white);
if($printing==1) {
ImageColorTransparent($image, $white);
}
// *** Border colour ***
$rgb=""; if (empty($rgb)) $rgb = "#6E6E6E";
$grey = ImageColorAllocate($image, hexdec(substr($rgb,1,2)), hexdec(substr($rgb,3,2)), hexdec(substr($rgb,5,2)));
// *** Text colour ***
$rgb=""; if (empty($rgb)) $rgb = "#000000";
$color = ImageColorAllocate($image, hexdec(substr($rgb,1,2)), hexdec(substr($rgb,3,2)), hexdec(substr($rgb,5,2)));
// *** Background colour ***
$rgb=""; if (empty($rgb)) $rgb = "#EEEEEE";
$bgcolor = ImageColorAllocate($image, hexdec(substr($rgb,1,2)), hexdec(substr($rgb,3,2)), hexdec(substr($rgb,5,2)));
// *** Man colour ***
$rgb=""; if (empty($rgb)) $rgb = "#B2DFEE";
$bgcolorM = ImageColorAllocate($image, hexdec(substr($rgb,1,2)), hexdec(substr($rgb,3,2)), hexdec(substr($rgb,5,2)));
// *** wife colour ***
$rgb=""; if (empty($rgb)) $rgb = "#FFE4C4";
$bgcolorF = ImageColorAllocate($image, hexdec(substr($rgb,1,2)), hexdec(substr($rgb,3,2)), hexdec(substr($rgb,5,2)));
// imagemap
$imagemap="<map id=\"fanmap\" name=\"fanmap\">";
// loop to create fan cells
while ($gen>=0) {
// clean current generation area
$deg2=360+($fandeg-180)/2;
$deg1=$deg2-$fandeg;
ImageFilledArc($image, $cx, $cy, $rx, $rx, $deg1, $deg2, $bgcolor, IMG_ARC_PIE);
ImageFilledArc($image, $cx, $cy, $rx, $rx, $deg1, $deg2, $bgcolor, IMG_ARC_EDGED | IMG_ARC_NOFILL);
$rx-=3;
// calculate new angle
$p2=pow(2, $gen);
$angle=$fandeg/$p2;
$deg2=360+($fandeg-180)/2;
$deg1=$deg2-$angle;
// special case for rootid cell
if ($gen==0) {
$deg1=90;
$deg2=360+$deg1;
}
// draw each cell
while ($sosa >= $p2) {
$pid=$treeid[$sosa][0];
$birthyr=$treeid[$sosa][1];
$deathyr=$treeid[$sosa][4];
$fontpx=$fontsize;
if($sosa>=16 AND $fandeg==180) { $fontpx=$fontsize-1; }
if($sosa>=32 AND $fandeg!=180) { $fontpx=$fontsize-1; }
if (!empty($pid)) {
if ($sosa%2) $bg=$bgcolorF;
else $bg=$bgcolorM;
if ($sosa==1) {
if($treeid[$sosa][5]=="F") {
$bg=$bgcolorF;
}
else if ($treeid[$sosa][5]=="M") {
$bg=$bgcolorM;
}
else {
$bg=$bgcolor; // sex unknown
}
}
ImageFilledArc($image, $cx, $cy, $rx, $rx, $deg1, $deg2, $bg, IMG_ARC_PIE);
if($gen!=0) {
ImageFilledArc($image, $cx, $cy, $rx, $rx, $deg1, $deg2, $grey, IMG_ARC_EDGED | IMG_ARC_NOFILL);
}
else {
ImageFilledArc($image, $cx, $cy, $rx, $rx, $deg1, $deg2, $grey, IMG_ARC_NOFILL);
}
$name=$pid;
// check if string is rtl by checking first or second char (second in case first is " or parentheses)
$rtlstr=0;
$tempname=htmlentities($name);
if(substr($tempname,0,1)=="&" OR substr($tempname,1,1)=="&") {
// persian_log2vis($name);
$rtlstr=1;
}
$text = $name; // names
$text2=""; // dates
if($date_display==1) { // don't show dates
}
else if ($date_display==2) { //show years only
// years only chosen but we also do this if no place in outer circles
$text2 .= substr($birthyr,-4)." - ".substr($deathyr,-4);
}
else if ($date_display==3) { //show full dates (but not in narrow outer circles!)
if ($gen >5) {
$text2 .= substr($birthyr,-4)." - ".substr($deathyr,-4);
}
else if ($gen >4 AND $fan_style != 4) {
$text2 .= substr($birthyr,-4)." - ".substr($deathyr,-4);
}
else { // full dates
if($birthyr) { $text2 .= "b.".$birthyr."\n"; }
if($deathyr) { $text2 .= "d.".$deathyr; }
}
}
// split and center text by lines
$wmax = floor($angle*7/$fontpx*$scale);
$wmax = min($wmax,35*$scale); //35
//$wmax = floor((90*$wmax)/100);
if ($gen==0) $wmax = min($wmax, 17*$scale); //17
$text = split_align_text($text, $wmax, $rtlstr, 1, $gen);
$text2 = split_align_text($text2, $wmax, $rtlstr, 0, $gen);
if($rtlstr==1) {
persian_log2vis($text);
}
$text.="\n".$text2;
// text angle
$tangle = 270-($deg1+$angle/2);
if ($gen==0) $tangle=0;
// calculate text position
$bbox=ImageTtfBbox((double)$fontpx, 0, $fontfile, $text);
$textwidth = $bbox[4]; //4
$deg = $deg1+.44;
if ($deg2-$deg1>40) $deg = $deg1+($deg2-$deg1)/11; // 11
if ($deg2-$deg1>80) $deg = $deg1+($deg2-$deg1)/7; // 7
if ($deg2-$deg1>140) $deg = $deg1+($deg2-$deg1)/4; // 4
if ($gen==0) $deg=180;
$rad=deg2rad($deg);
$mr=($rx-$rw/4)/2;
if ($gen>0 and $deg2-$deg1>80) $mr=$rx/2;
$tx=$cx + ($mr) * cos($rad);
$ty=$cy - $mr * -sin($rad);
if ($sosa==1) $ty-=$mr/2;
// print text
ImageTtfText($image, (double)$fontpx, $tangle, $tx, $ty, $color, $fontfile, $text);
$imagemap .= "<area shape=\"poly\" coords=\"";
// plot upper points
$mr=$rx/2;
$deg=$deg1;
while ($deg<=$deg2) {
$rad=deg2rad($deg);
$tx=round($cx + ($mr) * cos($rad));
$ty=round($cy - $mr * -sin($rad));
$imagemap .= "$tx, $ty, ";
$deg+=($deg2-$deg1)/6;
}
// plot lower points
$mr=($rx-$rw)/2;
$deg=$deg2;
while ($deg>=$deg1) {
$rad=deg2rad($deg);
$tx=round($cx + ($mr) * cos($rad));
$ty=round($cy - $mr * -sin($rad));
$imagemap .= "$tx, $ty, ";
$deg-=($deg2-$deg1)/6;
}
// join first point
$mr=$rx/2;
$deg=$deg1;
$rad=deg2rad($deg);
$tx=round($cx + ($mr) * cos($rad));
$ty=round($cy - $mr * -sin($rad));
$imagemap .= "$tx, $ty";
$imagemap .= "\" href=\"gezin.php?id=".$treeid[$sosa][2]."&hoofdpersoon=".$treeid[$sosa][3]."\"";
$imagemap .= " alt=\"".$pid."\" title=\"".$pid."\">";
}
$deg1-=$angle;
$deg2-=$angle;
$sosa--;
}
$rx-=$rw;
$gen--;
}
$imagemap .= "</map>";
echo $imagemap;
// here we cannot send image to browser ('header already sent')
// and we dont want to use a tmp file
// step 1. save image data in a session variable
ob_start();
ImagePng($image);
$image_data = ob_get_contents();
ob_end_clean();
$image_data = serialize($image_data);
unset ($_SESSION['image_data']);
$_SESSION['image_data']=$image_data;
// step 2. call fanimage.php to read this session variable and display image
$image_title=preg_replace("~<.*>~", "", $name) ." - RELOAD FANCHART WITH 'VIEW' BUTTON ON THE LEFT";
echo "<p align=\"center\" >";
echo "<img src=\"fanchart/fanimage.php\" width=\"$fanw\" height=\"$fanh\" border=\"0\" alt=\"$image_title\" title=\"$image_title\" usemap=\"#fanmap\">";
echo "</p>\n";
ImageDestroy($image);
}
$fan_style=3;
$maxgens=7;
$fan_width="auto";
if (isset($_GET["fan_style"])){ $fan_style=$_GET["fan_style"]; }
if (isset($_POST["fan_style"])){ $fan_style=$_POST["fan_style"]; }
if (isset($_GET["fan_width"])){ $fan_width=$_GET["fan_width"]; }
if (isset($_POST["fan_width"])){ $fan_width=$_POST["fan_width"]; }
if ($fan_width >50 AND $fan_width <301){ $tmp_width=$fan_width; }
else { // "auto" or invalid entry - reset to 100%
$tmp_width=100;
}
$realwidth=(840*$tmp_width)/100; // realwidth needed for next line (top text)
// Text on Top: Name of base person and print-help link
echo '<div style="z-index:80; position:absolute; top:25px; left:130px; width:'.$realwidth.'px; height:30px; text-align:center; color:#000000">';
echo '<div style="padding:5px">';
print "<strong>FANCHART - ".$treeid[1][0]."</strong>\n";
//======== HELP POPUP ========================
//echo '<span class="sddm" style="position:absolute;left:500px;top:3px;">';
echo '<div class='.$rtlmarker.'sddm>';
echo '<a href="#"';
echo ' style="display:inline" ';
//echo 'onmouseover="mopen(event,\'hulpmenu\')"';
echo 'onmouseover="mopen(event,\'hulpmenu\',0,0)"';
echo 'onmouseout="mclosetime()">';
echo '<br><strong>'.$language["fan_help"].'</strong>';
echo '</a> ';
//echo '<div style="z-index:40;padding:4px" id="hulpmenu" onmouseover="mcancelclosetime()" onmouseout="mclosetime()">';
echo '<div class="sddm_fixed" style="z-index:40; text-align:'.$alignmarker.'; padding:4px; direction:'.$rtlmarker.'" id="hulpmenu" onmouseover="mcancelclosetime()" onmouseout="mclosetime()">';
echo $language["fan_help1"].'<br>';
echo $language["fan_help2"];
echo '</div>';
echo "</div>\n";
//=================================
echo '</div></div>';
// Semi-transparant MENU BOX on the left
echo '<div class="weergave fanmenu1">';
echo '<div class="weergave fanmenu2">';
echo '<div class="weergave fanmenu3">';
echo '</div>';
echo '<div class=weergave style="position:absolute; left:0; top:0; color: #000000">';
//echo '<div style="border: 2px solid #000077; padding:10px">';
print "<form name=\"people\" method=\"post\" action=\"fanchart.php?id=".$gezin_id."\" style=\"display:inline;\">";
//print "<br>";
print "<input type=\"submit\" value=\"" .$language["fanmenu_view"]. "\">";
// Fan style
print '<br><hr style="width:110px">';
print $language["fanmenu_style"]."<br>";
print '<div style="text-align:'.$alignmarker.';margin-left:15%;margin-right:15%">';
print "<input type=\"radio\" name=\"fan_style\" value=\"2\"";
if ($fan_style==2) print " checked=\"checked\"";
print ">".$language["fanmenu_half"];
print "<br><input type=\"radio\" name=\"fan_style\" value=\"3\"";
if ($fan_style==3) print " checked=\"checked\"";
print "> 3/4";
print "<br><input type=\"radio\" name=\"fan_style\" value=\"4\"";
if ($fan_style==4) print " checked=\"checked\"";
print ">".$language["fanmenu_full"];
print '</div>';
// Nr. of generations
print '<hr style="width:110px">';
print $language["fanmenu_generations"]."<br>";
print "<select name=\"chosengen\">";
for ($i=2; $i<=min(9,$maxgens); $i++) {
print "<option value=\"".$i."\"" ;
if ($i == $chosengen) print "selected=\"selected\" ";
print ">".$i."</option>";
}
print "</select>";
// Fontsize
print '<br><hr style="width:110px">';
print $language["fanmenu_fontsize"]."<br>";
print "<select name=\"fontsize\">";
for ($i=5; $i<=10; $i++) {
print "<option value=\"".$i."\"" ;
if ($i == $fontsize) print "selected=\"selected\" ";
print ">".$i."</option>";
}
print "</select>";
// Date display
print '<br><hr style="width:110px">';
print $language["fanmenu_datedisplay"]."<br>";
print '<div style="text-align:'.$alignmarker.';margin-left:5%;margin-right:5%">';
print "<input type=\"radio\" name=\"date_display\" value=\"1\"";
if ($date_display=="1") print " checked=\"checked\"";
//print '>'.$language["fanmenu_nodates"].'</span>';
print '>'.$language["fanmenu_nodates"];
print "<br><input type=\"radio\" name=\"date_display\" value=\"2\"";
if ($date_display=="2") print " checked=\"checked\"";
print ">".$language["fanmenu_yearsonly"];
print "<br><input type=\"radio\" name=\"date_display\" value=\"3\"";
if ($date_display=="3") print " checked=\"checked\"";
print ">".$language["fanmenu_fulldates"];
print '</div>';
// Fan width in percentages
print '<hr style="width:110px">';
print $language["fanmenu_fanwidth"]."<br>";
print "<input type=\"text\" size=\"3\" name=\"fan_width\" value=\"$fan_width\"> <b>%</b> ";
print '<div style="font-size:10px;">'.$language["fanmenu_auto"].'</div>';
// Background (for printing with IE)
print '<hr style="width:110px">';
print $language["fanmenu_background"]."<br>";
print '<div style="text-align:'.$alignmarker.';margin-left:5%;margin-right:5%">';
print "<input type=\"radio\" name=\"printing\" value=\"1\"";
if ($printing==1) print " checked=\"checked\"";
print "> <span style=\"font-size:10px;\">".$language["fanmenu_transparent"]."</span>";
print "<br><input type=\"radio\" name=\"printing\" value=\"2\"";
if ($printing==2) print " checked=\"checked\"";
print "> <span style=\"font-size:10px;\">".$language["fanmenu_white"]."</span>";
print '</div>';
print "</form>";
print "</div></div></div>";
//YB Code to automatically make chart bigger when 7 generations are chosen
// and the boxes for generations in outer circle(s) become too small
// Same for 6 generations in half circle chart
if($fan_width=="auto") {
if($chosengen==7) {
if($fan_style==2){
$fan_width=220;
}
else if($fan_style==3) {
$fan_width=160;
}
else if($fan_style==4) {
$fan_width=130;
}
else { //YB: you can never get here, but just for paranoia's sake...
$fan_width=100;
}
}
// or 6 generations with half circle...
else if($chosengen==6 AND $fan_style==2){
$fan_width=130;
}
else {
$fan_width=100;
}
}
else if($fan_width >50 AND $fan_width <301) {
} // valid entry - leave it..
else { // invalid entry! reset to 100%
$fan_width=100;
}
// Container for fanchart
echo '<div style="position:absolute; top:60px; left:135px; width:'.$fan_width.'">';
echo '<div style="padding:10px">';
print_fan_chart($treeid, 840*$fan_width/100, $fan_style*90);
echo '</div></div>';
// end container for fanchart
include ("footer.php");
?>