diff options
Diffstat (limited to 'library/WT/Controller/Pedigree.php')
| -rw-r--r-- | library/WT/Controller/Pedigree.php | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/library/WT/Controller/Pedigree.php b/library/WT/Controller/Pedigree.php new file mode 100644 index 0000000000..8f12fee31c --- /dev/null +++ b/library/WT/Controller/Pedigree.php @@ -0,0 +1,317 @@ +<?php +// webtrees: Web based Family History software +// Copyright (C) 2010 webtrees development team. +// +// Derived from PhpGedView +// Copyright (C) 2002 to 2009 PGV Development Team. All rights reserved. +// +// 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// @version $Id$ + +if (!defined('WT_WEBTREES')) { + header('HTTP/1.0 403 Forbidden'); + exit; +} + +define('WT_PEDIGREE_CTRL_PHP', ''); + +require_once WT_ROOT.'includes/functions/functions_charts.php'; + +class WT_Controller_Pedigree extends WT_Controller_Base { + var $log2; + var $rootid; + var $name; + var $addname; + var $rootPerson; + var $show_full; + var $talloffset; + var $PEDIGREE_GENERATIONS; + var $pbwidth; + var $pbheight; + var $treeid; + var $treesize; + var $curgen; + var $yoffset; + var $xoffset; + var $prevyoffset; + var $offsetarray; + var $minyoffset; + + /** + * Initialization function + */ + function init() { + global $PEDIGREE_FULL_DETAILS, $PEDIGREE_LAYOUT, $MAX_PEDIGREE_GENERATIONS; + global $DEFAULT_PEDIGREE_GENERATIONS, $SHOW_EMPTY_BOXES; + global $bwidth, $bheight, $baseyoffset, $basexoffset, $byspacing, $bxspacing; + global $TEXT_DIRECTION, $BROWSER_TYPE, $show_full, $talloffset; + + $this->log2 = log(2); + + $this->rootid =safe_GET_xref('rootid'); + $this->show_full =safe_GET('show_full', array('0', '1'), $PEDIGREE_FULL_DETAILS); + $this->talloffset=safe_GET('talloffset', array('0', '1', '2', '3'), $PEDIGREE_LAYOUT); + $this->PEDIGREE_GENERATIONS=safe_GET_integer('PEDIGREE_GENERATIONS', 2, $MAX_PEDIGREE_GENERATIONS, $DEFAULT_PEDIGREE_GENERATIONS); + + if ($this->talloffset==1) $this->talloffset=1; // Make SURE this is an integer + if ($this->talloffset>1 && $this->PEDIGREE_GENERATIONS>8) $this->PEDIGREE_GENERATIONS=8; + + // TODO: some library functions expect this as a global. + // Passing a function parameter would be much better. + global $PEDIGREE_GENERATIONS; + $PEDIGREE_GENERATIONS=$this->PEDIGREE_GENERATIONS; + + // This is passed as a global. A parameter would be better... + $this->show_full = ($this->show_full) ? 1 : 0; // Make SURE this is an integer + if ($this->talloffset>3) { + $this->talloffset=3; + } elseif ($this->talloffset<0) { + $this->talloffset=0; + } + $show_full = $this->show_full; + $talloffset = $this->talloffset; + + // Validate parameters + $this->rootid=check_rootid($this->rootid); + + $this->rootPerson = WT_Person::getInstance($this->rootid); + if (is_null($this->rootPerson)) $this->rootPerson = new WT_Person(''); + $this->name = $this->rootPerson->getFullName(); + $this->addname = $this->rootPerson->getAddName(); + + //-- adjustments for hide details + if ($this->show_full==false) { + $bheight=30; + if ($this->talloffset < 2) { + $bwidth-=30; + } + else { + $bwidth-=50; + } + } + //-- adjustments for portrait mode + if ($this->talloffset==0) { + $bxspacing+=12; + $bwidth+=20; + $baseyoffset -= 20*($this->PEDIGREE_GENERATIONS-1); + } + + $this->pbwidth = $bwidth+6; + $this->pbheight = $bheight+5; + + $this->treeid = ancestry_array($this->rootid); + $this->treesize = pow(2, (int)($this->PEDIGREE_GENERATIONS))-1; + + //-- ancestry_array puts everyone at $i+1 + for ($i=0; $i<$this->treesize; $i++) { + $this->treeid[$i] = $this->treeid[$i+1]; + } + + if (!$this->show_full) { + if ($this->talloffset==0) { + $baseyoffset = 160+$bheight*2; + } elseif ($this->talloffset==1) { + $baseyoffset = 180+$bheight*2; + } elseif ($this->talloffset>1) { + if ($this->PEDIGREE_GENERATIONS==3) { + $baseyoffset = 30; + } else { + $baseyoffset = -85; + } + } + } else { + if ($this->talloffset==0) { + $baseyoffset = 100+$bheight/2; + } elseif ($this->talloffset==1) { + $baseyoffset = 160+$bheight/2; + } elseif ($this->talloffset>1) { + if ($this->PEDIGREE_GENERATIONS==3) { + $baseyoffset = 30; + } else { + $baseyoffset = -85; + } + } + } + // -- this next section will create and position the DIV layers for the pedigree tree + $this->curgen = 1; // -- variable to track which generation the algorithm is currently working on + $this->yoffset=0; // -- used to offset the position of each box as it is generated + $this->xoffset=0; + $this->prevyoffset=0; // -- used to track the y position of the previous box + $this->offsetarray = array(); + $this->minyoffset = 0; + if ($this->treesize<3) $this->treesize=3; + // -- loop through all of id's in the array starting at the last and working to the first + //-- calculation the box positions + for ($i=($this->treesize-1); $i>=0; $i--) { + // -- check to see if we have moved to the next generation + if ($i < floor($this->treesize / (pow(2, $this->curgen)))) { + $this->curgen++; + } + //-- box position in current generation + $boxpos = $i-pow(2, $this->PEDIGREE_GENERATIONS-$this->curgen); + //-- offset multiple for current generation + if ($this->talloffset < 2) { + $genoffset = pow(2, $this->curgen-$this->talloffset); + $boxspacing = $this->pbheight+$byspacing; + } + else { + $genoffset = pow(2, $this->curgen-1); + $boxspacing = $this->pbwidth+$byspacing; + } + // -- calculate the yoffset Position in the generation Spacing between boxes put child between parents + $this->yoffset = $baseyoffset+($boxpos * ($boxspacing * $genoffset))+(($boxspacing/2)*$genoffset)+($boxspacing * $genoffset); + // -- calculate the xoffset + if ($this->talloffset==0) { + if ($this->PEDIGREE_GENERATIONS<6) { + $addxoffset = $basexoffset+(10+60*(5-$this->PEDIGREE_GENERATIONS)); + $this->xoffset = ($this->PEDIGREE_GENERATIONS - $this->curgen) * (($this->pbwidth+$bxspacing) / 2)+$addxoffset; + } + else { + $addxoffset = $basexoffset+10; + $this->xoffset = ($this->PEDIGREE_GENERATIONS - $this->curgen) * (($this->pbwidth+$bxspacing) / 2)+$addxoffset; + } + //-- compact the tree + if ($this->curgen<$this->PEDIGREE_GENERATIONS) { + $parent = floor(($i-1)/2); + if ($i%2 == 0) $this->yoffset=$this->yoffset - (($boxspacing/2) * ($this->curgen-1)); + else $this->yoffset=$this->yoffset + (($boxspacing/2) * ($this->curgen-1)); + $pgen = $this->curgen; + while ($parent>0) { + if ($parent%2 == 0) $this->yoffset=$this->yoffset - (($boxspacing/2) * $pgen); + else $this->yoffset=$this->yoffset + (($boxspacing/2) * $pgen); + $pgen++; + if ($pgen>3) { + $temp=0; + for ($j=1; $j<($pgen-2); $j++) $temp += (pow(2, $j)-1); + if ($parent%2 == 0) $this->yoffset=$this->yoffset - (($boxspacing/2) * $temp); + else $this->yoffset=$this->yoffset + (($boxspacing/2) * $temp); + } + $parent = floor(($parent-1)/2); + } + if ($this->curgen>3) { + $temp=0; + for ($j=1; $j<($this->curgen-2); $j++) $temp += (pow(2, $j)-1); + if ($i%2 == 0) $this->yoffset=$this->yoffset - (($boxspacing/2) * $temp); + else $this->yoffset=$this->yoffset + (($boxspacing/2) * $temp); + } + + } + $this->yoffset-=(($boxspacing/2)*pow(2,($this->PEDIGREE_GENERATIONS-2))-($boxspacing/2)); + } + else if ($this->talloffset==1) { + $this->xoffset = 10 + $basexoffset + (($this->PEDIGREE_GENERATIONS - $this->curgen) * ($this->pbwidth+$bxspacing)); + if ($this->curgen == $this->PEDIGREE_GENERATIONS) $this->xoffset += 10; + if ($this->PEDIGREE_GENERATIONS<4) $this->xoffset += 60; + } + else if ($this->talloffset==2) { + if ($this->show_full) $this->xoffset = ($this->curgen) * (($this->pbwidth+$bxspacing) / 2)+($this->curgen)*10+136.5; + else $this->xoffset = ($this->curgen) * (($this->pbwidth+$bxspacing) / 4)+($this->curgen)*10+215.75; + } + else { + if ($this->show_full) $this->xoffset = ($this->PEDIGREE_GENERATIONS - $this->curgen) * (($this->pbwidth+$bxspacing) / 2)+260; + else $this->xoffset = ($this->PEDIGREE_GENERATIONS - $this->curgen) * (($this->pbwidth+$bxspacing) / 4)+270; + } + if ($this->curgen == 1 && $this->talloffset==1) $this->xoffset += 10; + $this->offsetarray[$i]["x"]=$this->xoffset; + $this->offsetarray[$i]["y"]=$this->yoffset; + } + + //-- collapse the tree if boxes are missing + if (!$SHOW_EMPTY_BOXES) { + if ($this->PEDIGREE_GENERATIONS>1) $this->collapse_tree(0, 1, 0); + } + + //-- calculate the smallest yoffset and adjust the tree to that offset + $minyoffset = 0; + for ($i=0; $i<count($this->treeid); $i++) { + if ($SHOW_EMPTY_BOXES || !empty($treeid[$i])) { + if (!empty($offsetarray[$i])) { + if (($minyoffset==0)||($minyoffset>$this->offsetarray[$i]["y"])) $minyoffset = $this->offsetarray[$i]["y"]; + } + } + } + + $ydiff = $baseyoffset+35-$minyoffset; + $this->adjust_subtree(0, $ydiff); + } + + /** + * return the title of this page + * @return string the title of the page to go in the <title> tags + */ + function getPageTitle() { + return $this->getPersonName()." ".i18n::translate('Pedigree Tree'); + } + + function getPersonName() { + if (is_null($this->rootPerson)) { + return i18n::translate('unknown'); + } else { + return $this->rootPerson->getFullName(); + } + } + + function adjust_subtree($index, $diff) { + global $offsetarray, $treeid, $log2, $talloffset,$boxspacing, $mdiff, $SHOW_EMPTY_BOXES; + $f = ($index*2)+1; //-- father index + $m = $f+1; //-- mother index + + if (!$SHOW_EMPTY_BOXES && empty($treeid[$index])) return; + if (empty($offsetarray[$index])) return; + $offsetarray[$index]["y"] += $diff; + if ($f<count($treeid)) adjust_subtree($f, $diff); + if ($m<count($treeid)) adjust_subtree($m, $diff); + } + + function collapse_tree($index, $curgen, $diff) { + global $offsetarray, $treeid, $log2, $talloffset,$boxspacing, $mdiff, $minyoffset; + + //print "$index:$curgen:$diff<br />\n"; + $f = ($index*2)+1; //-- father index + $m = $f+1; //-- mother index + if (empty($treeid[$index])) { + $pgen=$curgen; + $genoffset=0; + while ($pgen<=$this->PEDIGREE_GENERATIONS) { + $genoffset += pow(2, ($this->PEDIGREE_GENERATIONS-$pgen)); + $pgen++; + } + if ($talloffset==1) $diff+=.5*$genoffset; + else $diff+=$genoffset; + if (isset($offsetarray[$index]["y"])) $offsetarray[$index]["y"]-=($boxspacing*$diff)/2; + return $diff; + } + if ($curgen==$this->PEDIGREE_GENERATIONS) { + $offsetarray[$index]["y"] -= $boxspacing*$diff; + //print "UP $index BY $diff<br />\n"; + return $diff; + } + $odiff=$diff; + $fdiff = collapse_tree($f, $curgen+1, $diff); + if (($curgen<($this->PEDIGREE_GENERATIONS-1))||($index%2==1)) $diff=$fdiff; + if (isset($offsetarray[$index]["y"])) $offsetarray[$index]["y"] -= $boxspacing*$diff; + //print "UP $index BY $diff<br />\n"; + $mdiff = collapse_tree($m, $curgen+1, $diff); + $zdiff = $mdiff - $fdiff; + if (($zdiff>0)&&($curgen<$this->PEDIGREE_GENERATIONS-2)) { + $offsetarray[$index]["y"] -= $boxspacing*$zdiff/2; + //print "UP $index BY ".($zdiff/2)."<br />\n"; + if ((empty($treeid[$m]))&&(!empty($treeid[$f]))) adjust_subtree($f, -1*($boxspacing*$zdiff/4)); + $diff+=($zdiff/2); + } + return $diff; + } +} |
