private void AddRelativeToMoveList(PedigreeIndividual rightIndividual, List <PedigreeIndividual> toMove) { if (toMove.Contains(rightIndividual) == false) { toMove.Add(rightIndividual); } //if (rightIndividual.motherID > 0) // AddRelativeToMoveList(rightIndividual.Mother, toMove); //if (rightIndividual.fatherID > 0) // AddRelativeToMoveList(rightIndividual.Father, toMove); //foreach (PedigreeCouple pc in rightIndividual.spouseCouples) //{ // foreach (PedigreeIndividual pi in pc.children) // { // if (pi != rightIndividual) // if (pi.point.x >= rightIndividual.point.x) // AddRelativeToMoveList(pi, toMove); // } //} //rightIndividual.point.x += (h - interSetDistance); //if (rightIndividual.motherID > 0) //if (rightIndividual.fatherID > 0) // if (toMove.Contains(rightIndividual.Father) == false) // toMove.Add(rightIndividual.Father); }
private PedigreeIndividual GetLeftmostIndividualOfSet(PedigreeIndividualSet individualSet, PedigreeIndividualSet exclusionSet) { PedigreeIndividual retval = null; foreach (PedigreeIndividual individual in individualSet) { if (exclusionSet.Contains(individual) == false) { if (retval == null) { retval = individual; } else { if (individual.point.x < retval.point.x) { retval = individual; } } } } return(retval); //PedigreeIndividual leftmostIndividual = individualSet[0]; //double minX = leftmostIndividual.point.x; //foreach (PedigreeIndividual individual in individualSet) //{ // if (individual.point.x < minX) // { // minX = individual.point.x; // leftmostIndividual = individual; // } // foreach (PedigreeCouple pc in individual.spouseCouples) // { // if (pc.mother != null && pc.father != null) // { // PedigreeIndividual spouse; // if (individual.HraPerson.relativeID == pc.mother.HraPerson.relativeID) // spouse = pc.father; // else // spouse = pc.mother; // if (exclusionSet.Contains(spouse) == false) // { // if (spouse.point.x < minX) // { // minX = spouse.point.x; // leftmostIndividual = spouse; // } // } // } // } //} //return leftmostIndividual; }
private void SetNorms(PedigreeIndividual pi) { if (pi.HraPerson.x_norm == int.MinValue) { pi.HraPerson.x_norm = (int)(pi.point.x - (pedigreeControl1.model.displayXMax / 2)); } if (pi.HraPerson.y_norm == int.MinValue) { pi.HraPerson.y_norm = (int)(pi.point.y - (pedigreeControl1.model.displayYMax / 2)); } }
private PointWithVelocity GetPointUnderCursor(PedigreeModel model, double x, double y) { PedigreeIndividual individual = PedigreeUtils.GetIndividualUnderPoint(model, x, y); if (individual != null) { return(individual.point); } else { return(null); } }
private PedigreeIndividual GetLeftmostIndividualOfSet(PedigreeIndividualSet individualSet) { PedigreeIndividual leftmostIndividual = individualSet[0]; double minX = leftmostIndividual.point.x; foreach (PedigreeIndividual individual in individualSet) { if (individual.point.x < minX) { minX = individual.point.x; leftmostIndividual = individual; } } return(leftmostIndividual); }
private static PedigreeCouple GetCoupleFromLR(PedigreeModel model, PedigreeIndividual left, PedigreeIndividual right) { CoupleID coupleId = left.HraPerson.gender == PedigreeIndividual.GENDER_MALE ? new CoupleID(left.HraPerson.relativeID, right.HraPerson.relativeID) : new CoupleID(right.HraPerson.relativeID, left.HraPerson.relativeID); if (model.couplesDictionary.ContainsKey(coupleId)) { return(model.couplesDictionary[coupleId]); } else { return(null); } }
private PedigreeIndividual GetRightmostIndividualOfSet(PedigreeIndividualSet individualSet) { PedigreeIndividual rightmostIndividual = individualSet[0]; double maxX = rightmostIndividual.point.x; foreach (PedigreeIndividual individual in individualSet) { if (individual.point.x > maxX) { maxX = individual.point.x; rightmostIndividual = individual; } } return(rightmostIndividual); ; }
public PedigreeModel(List<SimpleIndividual> simpleIndividuals) { // initialize (with random coordinates) and index all individuals foreach (SimpleIndividual simpleIndividual in simpleIndividuals) { PedigreeIndividual pedigreeIndividual = new PedigreeIndividual(simpleIndividual, RandomPoint()); individuals.Add(pedigreeIndividual); individualsMap.Add(simpleIndividual.id, pedigreeIndividual); } // derive and index all couples foreach (PedigreeIndividual child in individuals) { PedigreeIndividual mother = null; if (individualsMap.ContainsKey(child.simpleIndividual.motherId)) mother = individualsMap[child.simpleIndividual.motherId]; PedigreeIndividual father = null; if (individualsMap.ContainsKey(child.simpleIndividual.fatherId)) father = individualsMap[child.simpleIndividual.fatherId]; if (mother != null && father != null) { PedigreeCouple parents = null; if (couplesMap.ContainsKey(mother.simpleIndividual.id)) parents = couplesMap[mother.simpleIndividual.id]; else { parents = new PedigreeCouple(mother, father, RandomPoint()); couples.Add(parents); couplesMap.Add(mother.simpleIndividual.id, parents); couplesMap.Add(father.simpleIndividual.id, parents); } parents.children.Add(child); child.parents = parents; } } }
/*************************************************************************************/ private double GetRightEdge(PedigreeIndividual pi, double current, PedigreeModel model) { double retval = current; if (pi.point.x > current) { retval = pi.point.x; } foreach (PedigreeCouple pc in model.couples) { if (pc.mother.HraPerson.relativeID == pi.HraPerson.relativeID || pc.father.HraPerson.relativeID == pi.HraPerson.relativeID) { foreach (PedigreeIndividual kid in pc.children) { retval = GetRightEdge(kid, retval, model); } } } return(retval); }
/*************************************************************************************/ /// <summary> /// Gets the effective position of an individual in a sibship, used /// for horizontal sorting. If an individual has a spouse, then the /// x position of that couple is used as the "effective position" /// of the individual. /// </summary> private double EffectivePosition(PedigreeIndividual child) { foreach (PedigreeCouple pc in child.spouseCouples) { if (pc.mother != null && pc.father != null) { PedigreeIndividual spouse; if (child.HraPerson.relativeID == pc.mother.HraPerson.relativeID) { spouse = pc.father; } else { spouse = pc.mother; } //if the spouse's parents are to the right of //this child's parents, if (spouse.Parents != null) { if (spouse.Parents.point.x > child.Parents.point.x) { //place the child at the rightmost position //in the sibship return(99999); } else { //otherwise to the leftmost return(-99999); } } } } return(child.point.x); /*************************************************************************************/ }
private static EventHandler GenerateAddSiblingListener(PedigreeControl pedigreeControl, PedigreeIndividual individual) { return(new EventHandler(delegate(object sender, EventArgs e) { if (pedigreeControl.model.Selected.Count == 0) { //pedigreeControl.SetPedigreeModel(PedigreeModelUtils.AddBrother(individual, pedigreeControl.model)); } else { foreach (PedigreeIndividual pi in pedigreeControl.model.Selected) { //pedigreeControl.SetPedigreeModel(PedigreeModelUtils.AddBrother(pi, pedigreeControl.model)); } } //ToolStripItem tsi = (ToolStripItem)sender; //pedigreeControl.SetPedigreeModel(PedigreeModelUtils.AddBrother(individual, pedigreeControl.model)); })); }
private static EventHandler GenerateAddChildListener(PedigreeControl pedigreeControl, PedigreeIndividual individual) { return(new EventHandler(delegate(object sender, EventArgs e) { if (pedigreeControl.model.Selected.Count == 0) { //pedigreeControl.SetPedigreeModel(PedigreeModelUtils.AddSon(individual, pedigreeControl.model)); } else { foreach (PedigreeIndividual pi in pedigreeControl.model.Selected) { //pedigreeControl.SetPedigreeModel(PedigreeModelUtils.AddSon(pi, pedigreeControl.model)); } } //pedigreeControl.SetPedigreeModel(PedigreeModelUtils.AddSon(individual, pedigreeControl.model)); })); }
private static EventHandler GenerateLinkToParentListener(PedigreeControl pedigreeControl, PedigreeIndividual individual) { return(new EventHandler(delegate(object sender, EventArgs e) { //pedigreeControl.SetPedigreeModel(PedigreeModelUtils.SetIndividualParents(individual, pedigreeControl.model)); })); }
private static EventHandler GenerateAddParentsListener(PedigreeControl pedigreeControl, PedigreeIndividual individual) { return(new EventHandler(delegate(object sender, EventArgs e) { //if (pedigreeControl.model.Selected.Count == 0) //{ // pedigreeControl.SetPedigreeModel(PedigreeModelUtils.AddParents(individual, pedigreeControl.model)); //} //else //{ // foreach (PedigreeIndividual pi in pedigreeControl.model.Selected) // { // pedigreeControl.SetPedigreeModel(PedigreeModelUtils.AddParents(pi, pedigreeControl.model)); // } //} })); }
internal static ContextMenuStrip GenerateMenu(PedigreeControl pedigreeControl, PedigreeIndividual individual) { ContextMenuStrip menu = new ContextMenuStrip(); ToolStripMenuItem addBrotherToolStripMenuItem = new ToolStripMenuItem(); addBrotherToolStripMenuItem.Click += GenerateAddSiblingListener(pedigreeControl, individual); addBrotherToolStripMenuItem.Text = "Add Brother"; menu.Items.Add(addBrotherToolStripMenuItem); ToolStripMenuItem addSonX1ToolStripMenuItem = new ToolStripMenuItem("Add Son"); addSonX1ToolStripMenuItem.Click += GenerateAddChildListener(pedigreeControl, individual); addSonX1ToolStripMenuItem.Text = "Add Son"; menu.Items.Add(addSonX1ToolStripMenuItem); ToolStripMenuItem addParentsToolStripMenuItem = new ToolStripMenuItem("Add Parents"); addParentsToolStripMenuItem.Click += GenerateAddParentsListener(pedigreeControl, individual); addParentsToolStripMenuItem.Text = "Add Parents"; menu.Items.Add(addParentsToolStripMenuItem); menu.Items.Add("-"); ToolStripMenuItem LinkToParentToolStripMenuItem = new ToolStripMenuItem("Link To Parent"); LinkToParentToolStripMenuItem.Click += GenerateLinkToParentListener(pedigreeControl, individual); LinkToParentToolStripMenuItem.Text = "Link To Parent"; menu.Items.Add(LinkToParentToolStripMenuItem); return(menu); }
public StaticLayout(PedigreeModel model, PedigreeController layoutEngine) { transitionToStaticLayout = delegate() { if (model.cycles > 1000 || (model.cycles > 800 && model.couplesGraphIsPlanar && model.layoutIsValid == false))// && model.forcesHaveConverged) { //switch modes from self organizing to static if (layoutEngine.GetMode() == PedigreeController.SELF_ORGANIZING) { model.TargetPositions.Clear(); foreach (PedigreeIndividual pi in model.individuals) { PointWithVelocity pos = new PointWithVelocity(); pos.x = pi.point.x; pos.y = pi.point.y; model.TargetPositions.Add(pi.HraPerson.relativeID, pos); } layoutEngine.SetMode(PedigreeController.STATIC_LAYOUT); generations = new List <List <PedigreeIndividual> >(); //initialize the per-level ordering lists for each generation for (int generation = 0; generation <= model.maxGenerationalLevel + 1; generation++) { generations.Add(PedigreeUtils.GetIndividualsInGeneration(model, generation)); } readyToRunStaticLayout = true; } } }; step = delegate() { if (runOnce && readyToRunStaticLayout) { failedAttempts++; readyToRunStaticLayout = false; double spacing = model.parameters.verticalSpacing; double centerY = (model.displayYMin + model.displayYMax) / 2; double offset = centerY - (model.maxGenerationalLevel + 1) * spacing / 2; double initialX = 30; double initialY = centerY; //for each generation, bottom to top... for (int g = generations.Count - 1; g >= 0; g--) //for(int i = 0;i<generations.Count;i++) { List <PedigreeIndividual> generation = generations[g]; //compute the y positions foreach (PedigreeIndividual individual in generation) { individual.point.y = g * spacing + offset; } //for the bottom level, just position with even spaces if (g == generations.Count - 1) { double x = initialX; foreach (PedigreeIndividual individual in generation) { individual.point.x = x += model.parameters.horizontalSpacing; individual.wasMoved = true; } } //for all the other levels... else { //First compute locations of parents centered around their children //and place the parent couples exactly at those centers: //for each individual in the current generation... for (int j = 0; j < generation.Count; j++) { PedigreeIndividual individual = generation[j]; //if the current individual has a spouse... foreach (PedigreeCouple pc in individual.spouseCouples) { //so we compute the center of this couple's sibship, double sibshipCenterX = pc.GetSibshipCenterX(model); //and position the couple such that its center is the same as the sibship center if (pc.father.point.x < pc.mother.point.x) { pc.father.point.x = sibshipCenterX - model.parameters.horizontalSpacing / 2; pc.mother.point.x = sibshipCenterX + model.parameters.horizontalSpacing / 2; } else { pc.mother.point.x = sibshipCenterX - model.parameters.horizontalSpacing / 2; pc.father.point.x = sibshipCenterX + model.parameters.horizontalSpacing / 2; } pc.mother.wasMoved = pc.father.wasMoved = true; } } /**/ //Second, position the outer children: //find the leftmost individual that was placed for (int inc = 1; inc >= -1; inc -= 2) { for (int j = inc == 1 ? 0 : generation.Count - 1; inc == 1 ? j < generation.Count : j >= 0; j += inc) { if (generation[j].wasMoved) { for (int i = j - inc; inc == 1 ? i >= 0 : i < generation.Count; i -= inc) { generation[i].point.x = generation[i + inc].point.x - inc * model.parameters.horizontalSpacing; generation[i].wasMoved = true; } break; } } } //Third, detect "too close"ness and move individuals to be perfectly spaced, //propagating left to right and downward through children for (int j = 0; j < generation.Count - 1; j++) { PedigreeIndividual left = generation[j]; PedigreeIndividual right = generation[j + 1]; //if folks are too close... if (right.point.x - left.point.x < model.parameters.horizontalSpacing) { //move the individual on the right such that spacing is perfect, //based on the current position of the individual on the left double dx = left.point.x + model.parameters.horizontalSpacing - right.point.x; right.point.x += dx; right.wasMoved = true; for (int z = j + 2; z < generation.Count - 1; z++) { PedigreeIndividual farRight = generation[z]; farRight.point.x += dx; farRight.wasMoved = true; } //and through their children foreach (PedigreeCouple pc in left.spouseCouples) { PedigreeIndividual spouse; if (left.HraPerson.relativeID == pc.mother.HraPerson.relativeID) { spouse = pc.father; } else { spouse = pc.mother; } if (right.HraPerson.relativeID == spouse.HraPerson.relativeID) { //PedigreeCouple couple = GetCoupleFromLR(model, left, right); //if (couple != null) MoveChildren(dx, pc, model); } } } } } } for (int g = 0; g < generations.Count - 1; g++) { List <PedigreeIndividual> generation = generations[g]; //for (int j = 0; j < 1; j++) for (int j = generation.Count - 1; j >= 0; j--) { PedigreeIndividual left = generation[j]; if (left.HasSpouse()) { //PedigreeCouple couple = GetCoupleFromLR(model, left, right); foreach (PedigreeCouple pc in model.couples) { double parentsX = (pc.mother.point.x + pc.father.point.x) / 2; if (pc.mother == left || pc.father == left) { double kidsX = 0; foreach (PedigreeIndividual kid in pc.children) { kidsX += kid.point.x; } kidsX = kidsX / ((double)(pc.children.Count)); foreach (PedigreeIndividual kid in pc.children) { kid.point.x += (parentsX - kidsX); foreach (PedigreeCouple kidsPC in kid.spouseCouples) { PedigreeIndividual spouse; if (left.HraPerson.relativeID == pc.mother.HraPerson.relativeID) { spouse = pc.father; } else { spouse = pc.mother; } spouse.point.x += (parentsX - kidsX); spouse.wasMoved = true; } } } } } } } //after positioning everyone, center the pedigree on the screen: double minX = double.MaxValue; double maxX = -minX; foreach (PointWithVelocity point in model.points) { if (point.x < minX) { minX = point.x; } else if (point.x > maxX) { maxX = point.x; } } double centerX = (minX + maxX) / 2; double idealCenterX = (model.displayXMin + model.displayYMax) / 2; double off = idealCenterX - centerX; foreach (PointWithVelocity point in model.points) { point.x = point.x + off; } } //if (LayoutIsValid(model)) if (true) { //model.parameters.repelIndividualSetsStrength = 1; layoutEngine.SetMode(PedigreeController.MANUAL); } //else //{ //layoutEngine.SetMode(PedigreeController.SELF_ORGANIZING); //if (failedAttempts < 5) //{ //model.parameters.repelIndividualSetsStrength += 0.5; //} //else if (failedAttempts < 10) //{ // model.parameters.repelIndividualSetsStrength = 1; // foreach (PointWithVelocity p in model.points) // { // double newX = autoRand.NextDouble() * (model.displayXMax - 1); // double newY = autoRand.NextDouble() * (model.displayYMax - 1); // p.x = newX; // p.dx = 0; // p.y = newY; // p.dy = 0; // } //} //else //{ // layoutEngine.SetMode(PedigreeController.MANUAL); //} /**/ //} }; }
public LayoutSibships(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) { return; } //if (model.cycles > 150) // return; //for each couple, layout their children foreach (PedigreeCouple parents in model.couples) { PedigreeCouple otherCouple = null; foreach (PedigreeCouple otherparents in model.couples) { if (parents != otherparents && (parents.mother == otherparents.mother || parents.father == otherparents.father)) { if (otherparents.alreadyHandledHalfSibship == false) { otherCouple = otherparents; parents.alreadyHandledHalfSibship = true; double oneleft = double.MaxValue; double oneright = double.MinValue; double twoleft = double.MaxValue; double tworight = double.MinValue; foreach (PedigreeIndividual one in parents.children) { if (one.point.x < oneleft) { oneleft = one.point.x; } if (one.point.x > oneright) { oneright = one.point.x; } } foreach (PedigreeIndividual two in otherparents.children) { if (two.point.x < twoleft) { twoleft = two.point.x; } if (two.point.x > tworight) { tworight = two.point.x; } } foreach (PedigreeIndividual two in otherparents.children) { if (two.point.x < oneright && two.point.x > oneleft) { if (parents.point.x < otherparents.point.x) { PedigreeUtils.PullTowardX(tworight, two.point, 5, model); } else { PedigreeUtils.PullTowardX(oneleft, two.point, 5, model); } } } } } } //Pull children toward their computed ideal locations as follows: //Step 1 of 2: Sort sibship by x position parents.children.Sort(delegate(PedigreeIndividual a, PedigreeIndividual b) { double ax = EffectivePosition(a); double bx = EffectivePosition(b); return(ax.CompareTo(bx)); }); //Step 2 of 2: Pull sibship members toward their ideal positions, //spaced ideally and centered around thir parent couple, leaving //open spaces for spouses (as they will be positioned by the //layout step addressing couples). double spacing; //Compute the offset from the couple center for positioning individuals double offset = 0; int numIndividualsInSibshipSpan = 0; //compute the center for the couple's sibship double sibshipMinX = double.MaxValue; double sibshipMaxX = -double.MaxValue; for (int j = 0; j < parents.children.Count; j++) { PedigreeIndividual child = parents.children[j]; if (child.point.x < sibshipMinX) { sibshipMinX = (int)child.point.x; } if (child.point.x > sibshipMaxX) { sibshipMaxX = (int)child.point.x; } //double leftEdge = GetLeftEdge(child, double.MaxValue, model); //double rightEdge = GetRightEdge(child, double.MinValue, model); //if (leftEdge < sibshipMinX) // sibshipMinX = (int)leftEdge; //if (rightEdge > sibshipMaxX) // sibshipMaxX = (int)rightEdge; //count the child numIndividualsInSibshipSpan++; foreach (PedigreeCouple pc in child.spouseCouples) { //overlap += pc.childOverlap; if (pc.mother != null && pc.father != null) { PedigreeIndividual spouse; if (child.HraPerson.relativeID == pc.mother.HraPerson.relativeID) { spouse = pc.father; } else { spouse = pc.mother; } bool thisSpouseCounts = true; bool spouseIsToRight = spouse.point.x > child.point.x; //don't count the spouse to the right of //the sibship's rightmost child if (j == parents.children.Count - 1 && spouseIsToRight) { thisSpouseCounts = false; } //don't count the spouse to the left of //the sibship's leftmost child if (j == 0 && !spouseIsToRight) { thisSpouseCounts = false; } if (model.parameters.hideNonBloodRelatives && !spouse.bloodRelative) { thisSpouseCounts = false; } if (thisSpouseCounts) { numIndividualsInSibshipSpan++; } } } } double sibshipSpanSize = (sibshipMaxX - sibshipMinX) * model.parameters.sibshipShrinkingFacor; if (numIndividualsInSibshipSpan == 1) { spacing = 0; } else { spacing = (sibshipSpanSize / (numIndividualsInSibshipSpan - 1)); } if (spacing < model.parameters.horizontalSpacing) { spacing = model.parameters.horizontalSpacing; sibshipSpanSize = ((numIndividualsInSibshipSpan - 1) * spacing); } offset = parents.point.x - sibshipSpanSize / 2; //position individuals ideally by applying a force to them int i = 0; foreach (PedigreeIndividual child in parents.children) { //position the individuals vertically based on the //positions of the parents: { double goalY = parents.point.y + model.parameters.verticalSpacing; double strength = model.parameters.verticalPositioningForceStrength; PedigreeUtils.PullTowardY(goalY, child.point, strength, model); } //position the individuals horizontally based on //computation of their ideal horizontal positions { double goalX = offset; //if the child has no spouse if (child.spouseCouples.Count == 0) { //compute the position directly //without incrementing i goalX += i * spacing; } //if the child has a spouse, insert appropriate spacing foreach (PedigreeCouple pc in child.spouseCouples) { if (pc.mother != null && pc.father != null) { PedigreeIndividual spouse; if (child.HraPerson.relativeID == pc.mother.HraPerson.relativeID) { spouse = pc.father; } else { spouse = pc.mother; } if (!model.parameters.hideNonBloodRelatives || spouse.bloodRelative) { bool spouseIsToRight = spouse.point.x > child.point.x; int index = parents.children.IndexOf(child); //if the spouse is to the right... if (spouseIsToRight) { //...but not for the rightmost child if (index != parents.children.Count - 1) { //leave a space to the right. goalX = offset + (i++) * spacing; } else { goalX = offset + i * spacing; } } else//if the spouse is to the left... //...but not for the leftmost child if (index != 0) { //leave a space to the left. goalX = offset + (++i) * spacing; } } else { goalX += i * (spacing); } } } double strength = model.parameters.layoutSibshipsStrength; PedigreeUtils.PullTowardX(goalX, child.point, strength, model); //increment i to account for enumeration this child i++; } } } }; }
private bool LayoutIsValid(PedigreeModel model) { for (int generation = 0; generation < model.maxGenerationalLevel + 1; generation++) { //test for crossed edges foreach (PedigreeCouple coupleA in model.couples) { if (coupleA.GenerationalLevel == generation) { foreach (PedigreeIndividual childA in coupleA.children) { foreach (PedigreeCouple coupleB in model.couples) { if (coupleB.GenerationalLevel == generation) { foreach (PedigreeIndividual childB in coupleB.children) { if (coupleA != coupleB && childA != childB) { double x1 = coupleA.point.x; double y1 = coupleA.point.y; double x2 = childA.point.x; double y2 = childA.point.y; double x3 = coupleB.point.x; double y3 = coupleB.point.y; double x4 = childB.point.x; double y4 = childB.point.y; //does the edge from coupleA to childA //cross the edge from coupleB to childB? if (PedigreeUtils.LinesIntersect(x1, y1, x2, y2, x3, y3, x4, y4)) { //if yes then the layout is not valid return(false); } } } } } } } } //test for individuals inbetween fathers and mothers: //put all individuals in the current generation in a list PedigreeUtils.GetIndividualsInGeneration(model, generation, temp); if (model.couplesGraphIsPlanar) { for (int i = 0; i < temp.Count; i++) { for (int j = 0; j < temp.Count; j++) { if (i != j) { if (Math.Abs(temp[i].point.x - temp[j].point.x) < (model.parameters.horizontalSpacing / 2)) { //if (model.couplesGraphIsPlanar && model.layoutIsValid == false) //{ //if (model.parameters.repelIndividualSetsStrength < 10) //{ // model.parameters.repelIndividualSetsStrength += 0.5; //} //if (model.parameters.couplesAttractionStrength > 0.1) //{ // model.parameters.couplesAttractionStrength -= 0.1; //} //if (model.parameters.layoutCouplesStrength > 0.01) //{ // model.parameters.layoutCouplesStrength -= 0.01; //} //if (model.parameters.centeringForceStrength > 0.01) //{ // model.parameters.centeringForceStrength -= 0.01; //} //if (model.parameters.sibshipShrinkingFacor > 0.01) //{ // model.parameters.sibshipShrinkingFacor -= 0.01; //} //} return(false); } } } } } //for each person who has a spouse, make sure the spouse is next to that person, //otherwise report an invalid layout for (int i = 0; i < temp.Count; i++) { PedigreeIndividual individual = temp[i]; foreach (PedigreeCouple pc in individual.spouseCouples) { if (!model.parameters.hideNonBloodRelatives || (pc.mother.bloodRelative && pc.father.bloodRelative)) { PedigreeIndividual spouse; if (individual.HraPerson.relativeID == pc.mother.HraPerson.relativeID) { spouse = pc.father; } else { spouse = pc.mother; } bool coupleIsSplit = true; if (i > 0) { if (temp[i - 1].HraPerson.relativeID == spouse.HraPerson.relativeID) { coupleIsSplit = false; } } if (i < temp.Count - 1) { if (temp[i + 1].HraPerson.relativeID == spouse.HraPerson.relativeID) { coupleIsSplit = false; } } if (coupleIsSplit) { return(false); } } } //if (individual.spouseCouples.Count == 1) //{ // PedigreeIndividual spouse = individual.Spouse; // bool coupleIsSplit = true; // if (i > 0) // if (temp[i - 1].relativeID == spouse.relativeID) // coupleIsSplit = false; // if (i < temp.Count - 1) // if (temp[i + 1].relativeID == spouse.relativeID) // coupleIsSplit = false; // if (coupleIsSplit) // return false; //} } } return(true); }
public DrawLayoutSteps(PedigreeModel model) { step = delegate(Graphics g) { if (model.parameters.drawVisualDebugging && model.couplesGraphIsPlanar) { //draw the center line //double idealCenterX = (model.displayXMin + model.displayYMax) / 2; int avgVerticalOffset = (int)( (model.parameters.verticalSpacing - model.parameters.individualSize) / 4); foreach (PedigreeCouple couple in model.couples) { //draw lines showing the averages between couples int motherX = (int)couple.mother.point.x; int motherY = (int)couple.mother.point.y + model.parameters.individualSize / 2; int fatherX = (int)couple.father.point.x; int fatherY = (int)couple.father.point.y + model.parameters.individualSize / 2; int coupleCenterX = (motherX + fatherX) / 2; int coupleCenterY = (motherY + fatherY) / 2 + avgVerticalOffset; Pen pen = Pens.Green; g.DrawLine(pen, motherX, motherY, motherX, coupleCenterY); g.DrawLine(pen, motherX, coupleCenterY, coupleCenterX, coupleCenterY); g.DrawLine(pen, fatherX, fatherY, fatherX, coupleCenterY); g.DrawLine(pen, fatherX, coupleCenterY, coupleCenterX, coupleCenterY); //draw lines showing the averages between sibships if (couple.children.Count > 0) { int sibshipMinX = int.MaxValue; int sibshipMaxX = -int.MaxValue; foreach (PedigreeIndividual child in couple.children) { if (child.point.x < sibshipMinX) { sibshipMinX = (int)child.point.x; } if (child.point.x > sibshipMaxX) { sibshipMaxX = (int)child.point.x; } } int sibshipY = (int)couple.point.y + model.parameters.verticalSpacing - model.parameters.individualSize / 2; int sibshipCenterX = (sibshipMinX + sibshipMaxX) / 2; int sibshipCenterY = sibshipY - avgVerticalOffset; g.DrawLine(pen, sibshipMinX, sibshipY, sibshipMinX, sibshipCenterY); g.DrawLine(pen, sibshipMinX, sibshipCenterY, sibshipCenterX, sibshipCenterY); g.DrawLine(pen, sibshipMaxX, sibshipY, sibshipMaxX, sibshipCenterY); g.DrawLine(pen, sibshipMaxX, sibshipCenterY, sibshipCenterX, sibshipCenterY); //draw the line showing the average of the two centers g.DrawLine(pen, sibshipCenterX, sibshipCenterY, coupleCenterX, coupleCenterY); int middleX = (sibshipCenterX + coupleCenterX) / 2; int middleY = (sibshipCenterY + coupleCenterY) / 2; int midRadius = 5; int side = midRadius * 2; g.FillEllipse(Brushes.Green, middleX - midRadius, middleY - midRadius, side, side); //draw the ideal positions of the couple bool fatherToTheLeft = fatherX < motherX; int f = fatherToTheLeft ? 1 : -1; int idealFatherX = middleX - f * model.parameters.horizontalSpacing / 2; int idealMotherX = middleX + f * model.parameters.horizontalSpacing / 2; pen = Pens.Red; g.DrawLine(pen, idealFatherX, fatherY, middleX, middleY); g.DrawLine(pen, idealMotherX, motherY, middleX, middleY); DrawIndividual(idealFatherX, couple.father.point.y, couple.father.HraPerson.gender, model, g, pen); DrawIndividual(idealMotherX, couple.mother.point.y, couple.mother.HraPerson.gender, model, g, pen); //draw the ideal sibship positions //Step 2 of 2: Pull sibship members toward their ideal positions, //spaced ideally and centered around thir parent couple, leaving //open spaces for spouses (as they will be positioned by the //layout step addressing couples). { double spacing = model.parameters.horizontalSpacing; //Compute the offset from the couple center for positioning individuals double offset = 0; { int numIndividualsInSibshipSpan = 0; // foreach (PedigreeIndividual child in couple.children) for (int j = 0; j < couple.children.Count; j++) { PedigreeIndividual child = couple.children[j]; //count the child numIndividualsInSibshipSpan++; //count the spouse ... sometimes //if (child.spouseCouples.Count == 1) //{ // bool thisSpouseCounts = true; // bool spouseIsToRight = child.Spouse.point.x > child.point.x; // //don't count the spouse to the right of // //the sibship's rightmost child // if (j == couple.children.Count - 1 && spouseIsToRight) // thisSpouseCounts = false; // //don't count the spouse to the left of // //the sibship's leftmost child // if (j == 0 && !spouseIsToRight) // thisSpouseCounts = false; // if (thisSpouseCounts) // numIndividualsInSibshipSpan++; //} //else if (couple.children[j].spouseCouples.Count == 2) // throw new Exception("Half siblings not yet supported"); } double sibshipSpanSize = (numIndividualsInSibshipSpan - 1) * spacing; offset = middleX - sibshipSpanSize / 2; } //position individuals ideally by applying a force to them int i = 0; foreach (PedigreeIndividual child in couple.children) { //position the individuals horizontally based on //computation of their ideal horizontal positions { double goalX = offset; //if the child has no spouse if (child.spouseCouples.Count == 0) { //compute the position directly //without incrementing i goalX += i * spacing; } //if the child has a spouse, insert appropriate spacing else if (child.spouseCouples.Count == 1) { //where the space goes depends on whether the spouse is //to the left or right of the child, so find out //if the spouse is to the right or left of the child: // bool spouseIsToRight = child.Spouse.point.x > child.point.x; // //if the spouse is to the right... // if (spouseIsToRight) // //...but not for the rightmost child // if (i != couple.children.Count - 1) // //leave a space to the right. // goalX = offset + (i++) * spacing; // else // goalX = offset + i * spacing; // else//if the spouse is to the left... // //...but not for the leftmost child // if (i != 0) // //leave a space to the left. // goalX = offset + (++i) * spacing; //} //else if (child.spouseCouples.Count == 2) // throw new Exception("Half siblings not yet supported"); } g.DrawLine(pen, (float)middleX, (float)middleY, (float)goalX, (float)sibshipY); DrawIndividual(goalX, child.point.y, child.HraPerson.gender, model, g, pen); //increment i to account for enumeration this child i++; } } } } } } }; }
private bool LayoutIsValid(PedigreeModel model) { List <PedigreeIndividual> temp = new List <PedigreeIndividual>(); for (int generation = 0; generation <= model.maxGenerationalLevel + 1; generation++) { //test for crossed edges foreach (PedigreeCouple coupleA in model.couples) { if (coupleA.GenerationalLevel == generation) { foreach (PedigreeIndividual childA in coupleA.children) { foreach (PedigreeCouple coupleB in model.couples) { if (coupleB.GenerationalLevel == generation) { foreach (PedigreeIndividual childB in coupleB.children) { if (coupleA != coupleB && childA != childB) { double x1 = coupleA.point.x; double y1 = coupleA.point.y; double x2 = childA.point.x; double y2 = childA.point.y; double x3 = coupleB.point.x; double y3 = coupleB.point.y; double x4 = childB.point.x; double y4 = childB.point.y; //does the edge from coupleA to childA //cross the edge from coupleB to childB? if (PedigreeUtils.LinesIntersect(x1, y1, x2, y2, x3, y3, x4, y4)) { //if yes then the layout is not valid return(false); } } } } } } } } //test for individuals inbetween fathers and mothers: //put all individuals in the current generation in a list PedigreeUtils.GetIndividualsInGeneration(model, generation, temp); for (int i = 0; i < temp.Count; i++) { for (int j = 0; j < temp.Count; j++) { if (i != j) { if (Math.Abs(temp[i].point.x - temp[j].point.x) < (model.parameters.horizontalSpacing / 2)) { return(false); } } } } //for each person who has a spouse, make sure the spouse is next to that person, //otherwise report an invalid layout for (int i = 0; i < temp.Count; i++) { PedigreeIndividual individual = temp[i]; foreach (PedigreeCouple pc in individual.spouseCouples) { PedigreeIndividual spouse; if (individual.HraPerson.relativeID == pc.mother.HraPerson.relativeID) { spouse = pc.father; } else { spouse = pc.mother; } bool coupleIsSplit = true; if (i > 0) { if (temp[i - 1].HraPerson.relativeID == spouse.HraPerson.relativeID) { coupleIsSplit = false; } } if (i < temp.Count - 1) { if (temp[i + 1].HraPerson.relativeID == spouse.HraPerson.relativeID) { coupleIsSplit = false; } } if (coupleIsSplit) { return(false); } } } } return(true); }
public RepelIndividualSets(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) { return; } //foreach (PedigreeCouple pc in model.couples) //{ // pc.childOverlap = 0; //} int setId = 0; //for each generation, for (int generationalLevel = 0; generationalLevel < model.individualSets.Count; generationalLevel++) { //sort the individual sets of the current generation if (model.individualSets.ContainsKey(generationalLevel)) { List <PedigreeIndividualSet> levelIndividualSets = model.individualSets[generationalLevel]; levelIndividualSets.Sort(delegate(PedigreeIndividualSet a, PedigreeIndividualSet b) { double ax = a.associatedCouple.point.x; double bx = b.associatedCouple.point.x; return(ax.CompareTo(bx)); }); //then repel adjacent individual sets if necessary for (int i = 0; i < levelIndividualSets.Count - 1; i++) { setId++; PedigreeIndividualSet leftSet = levelIndividualSets[i]; PedigreeIndividualSet rightSet = levelIndividualSets[i + 1]; PedigreeIndividual rightmostOfLeftSet = GetRightmostIndividualOfSet(leftSet, rightSet); PedigreeIndividual leftmostOfRightSet = GetLeftmostIndividualOfSet(rightSet, leftSet); PedigreeIndividual rightmostOfRightSet = GetRightmostIndividualOfSet(rightSet, leftSet); PedigreeIndividual leftmostOfLefttSet = GetLeftmostIndividualOfSet(leftSet, rightSet); if (rightmostOfLeftSet != null && leftmostOfRightSet != null && rightmostOfRightSet != null && leftmostOfLefttSet != null) { //double interSetDistance = Math.Abs(leftmostOfRightSet.point.x - rightmostOfLeftSet.point.x); double interSetDistance = leftmostOfRightSet.point.x - rightmostOfLeftSet.point.x; double h = model.parameters.horizontalSpacing; //if (leftmostOfRightSet.point.x < leftmostOfLefttSet.point.x && rightmostOfRightSet.point.x > rightmostOfLeftSet.point.x) //{ // interSetDistance = 0; //} double x = -1 * (interSetDistance - h); //double x = (interSetDistance - h); //double force = 1 / (1 + Math.Pow(2, x)); double force = Math.Pow(2, x); if (force > 5) { force = 5; } force *= model.parameters.repelIndividualSetsStrength; foreach (PedigreeIndividual leftIndividual in leftSet) { leftIndividual.point.dx -= force; } foreach (PedigreeIndividual rightIndividual in rightSet) { rightIndividual.point.dx += force; } ApplyForceToParents(leftSet, -force, x); ApplyForceToParents(rightSet, force, x); } } } } }; }
public PedigreeCouple(PedigreeIndividual mother, PedigreeIndividual father, PointWithVelocity point) { this.mother = mother; this.father = father; this.point = point; }
public void Repel(PedigreeIndividual pi, int delta, PedigreeModel model) { PedigreeUtils.PullTowardX(pi.point.x + delta, pi.point, model.parameters.repelIndividualSetsStrength, model); }