package edu.byu.cs.roots.opg.chart.presetvertical; import java.awt.Color; import java.util.ArrayList; import java.util.HashMap; import edu.byu.cs.roots.opg.chart.cmds.DrawCmdMoveTo; import edu.byu.cs.roots.opg.chart.cmds.DrawCmdRelLineTo; import edu.byu.cs.roots.opg.model.Individual; public class AncesTree { public AncesBox root = null; public ArrayList<Generation> generations; //all duplicate ancestors on the current chart are stored in here by id private HashMap<String, Integer> duplicateMap; private int duplicateCounter; private TreeFormat format; public AncesTree(Individual rootIndi) { duplicateMap = new HashMap<String, Integer>(); duplicateCounter = 1; root = new AncesBox(rootIndi); generations = new ArrayList<Generation>(); Generation gen = new Generation(0); gen.add(root); buildTree(gen); } public AncesTree(Individual father, Individual mother) { duplicateMap = new HashMap<String, Integer>(); duplicateCounter = 1; root = createFakeChildBox(father, mother); generations = new ArrayList<Generation>(); Generation gen = new Generation(-1); gen.add(root); buildTree(gen); } private AncesBox createFakeChildBox(Individual father, Individual mother) { Individual fake = new Individual(); fake.father = father; fake.mother = mother; AncesBox fakeChild = new FakeAncesBox(fake); return fakeChild; } public void DrawTree(ChartMargins chart, VerticalChartOptions options, double x, double y) { //root.drawSubTreeConnectors(chart, options, x, y); root.drawSubTree(chart, options, x, y); if(root instanceof FakeAncesBox || (options.getDescGens() == 0 && options.isIncludeSpouses())) { //System.out.println(root.father); drawSpouseConnector(chart, x + root.father.getWidth()/3.0, y + root.fatherVOffset - root.father.getHeight()/2, -root.fatherVOffset + root.motherVOffset + root.mother.getHeight()); } } private void drawSpouseConnector(ChartMargins chart, double x, double y, double offset) { chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x), chart.yOffset(y))); chart.addDrawCommand(new DrawCmdRelLineTo(0.0,offset,root.father.getLineWidth(), Color.BLACK)); } private void setDuplicateNumbers() { for(Generation g : generations) { for(Box b : g.getBoxes()){ if(duplicateMap.containsKey(b.indi.id)) b.setDuplicateIndex(duplicateMap.get(b.indi.id)); } } } public void setFormat(TreeFormat treeFormat) { int i = (root != null && root instanceof FakeAncesBox)? 1 : 0; if (i == 1) { generations.get(0).setFormat(treeFormat.get(0)); generations.get(0).setWidth(treeFormat.getIntrusion(0)); } int k = 0; for(; i < generations.size(); i++) { generations.get(i).setFormat(treeFormat.get(k)); generations.get(i).setWidth(treeFormat.getIntrusion(k++)); } } private void buildTree(Generation g) { Generation gen = g; while(!gen.isEmpty()) { generations.add(gen); gen = createNextGeneration(gen); } setDuplicateNumbers(); } private Generation createNextGeneration(Generation gen) { Generation nextGen = new Generation(gen.getGenNum()+1); for(Box b : gen.getBoxes()) { AncesBox ab = (AncesBox)b; if(ab.expand) { ab.setFather(addIndividualToGen(ab.indi.father,nextGen)); ab.setMother(addIndividualToGen(ab.indi.mother,nextGen)); } } return nextGen; } /** * Adds Individual to the specified generation. * If individual is null or is a parent of a duplicate it is not added * The duplicate map is populated (0 = non-dup, non-zero = dup) * @param indi individual to add to the generation * @param gen generation to add individual to * @return Box of the individual added, null if not added */ private AncesBox addIndividualToGen(Individual indi, Generation gen) { AncesBox newBox = null; if(indi != null) { if(!duplicateMap.containsKey(indi.id)) { newBox = new AncesBox(indi); duplicateMap.put(indi.id,0); gen.add(newBox); } else { if(duplicateMap.get(indi.id) == 0){ newBox = new AncesBox(indi); newBox.expand = false; gen.add(newBox); duplicateMap.put(indi.id,duplicateCounter); duplicateCounter++; } } } return newBox; } public int getGenerationSize(int gen) { return generations.get(gen).getCount(); } public Generation getGeneration(int gen) { return generations.get(gen); } public int getGenerationCount() { return generations.size(); } public double getHeight() { return root.upperSubTreeOffset - root.lowerSubTreeOffset; } public double getWidth(int maxGen) { double result = 0; for(int i=0; i <= maxGen ; i++) result += generations.get(i).getFormat().getWidth(); return result; } public double getRootOffset() { return root.upperSubTreeOffset + root.lowerSubTreeOffset; } public void setTreeFormat(TreeFormat format) { this.format = format; } public TreeFormat getTreeFormat() { return format; } }