private void SeperateCouple(PedigreeCouple pc, PedigreeModel model, double sibMedian, ref List <PedigreeIndividual> kidsPulledToParents) { if (!model.parameters.hideNonBloodRelatives || (pc.mother.bloodRelative && pc.father.bloodRelative)) { if (pc.mother.point.x < pc.father.point.x) { PedigreeUtils.PullTowardX(pc.mother.point.x - 1, pc.mother.point, 0.1, model); PedigreeUtils.PullTowardX(pc.father.point.x + 1, pc.father.point, 0.1, model); } else { PedigreeUtils.PullTowardX(pc.mother.point.x + 1, pc.mother.point, 0.1, model); PedigreeUtils.PullTowardX(pc.father.point.x - 1, pc.father.point, 0.1, model); } } else { double coupleAvg = (pc.mother.point.x + pc.father.point.x) / (2.0); pc.mother.point.x = coupleAvg; pc.father.point.x = coupleAvg; } double target = ((pc.mother.point.x + pc.father.point.x) / 2) - sibMedian; foreach (PedigreeIndividual pi in pc.children) { if (kidsPulledToParents.Contains(pi) == false) { PedigreeUtils.PullTowardX((pc.mother.point.x + pc.father.point.x) / 2, pi.point, 0.075, model); kidsPulledToParents.Add(pi); } //PedigreeUtils.PullTowardX(pi.point.x + target, pi.point, 0.1, model); } foreach (PedigreeCouple nested_pc in model.couples) { if (nested_pc != pc) { if (pc.children.Contains(nested_pc.mother) || pc.children.Contains(nested_pc.father)) { SeperateCouple(nested_pc, model, sibMedian, ref kidsPulledToParents); } } } }
private void ApplyForceToParents(PedigreeIndividualSet iSet, double force) { foreach (PedigreeIndividual individual in iSet) { if (individual.Parents != null) { PedigreeCouple parents = individual.Parents; //only apply the force to the parent which has a parent if (parents.mother.Parents != null) { parents.mother.point.dx += force; } if (parents.father.Parents != null) { parents.father.point.dx += force; } } } }
private static void repelAllCouplePairs(PedigreeModel model) { try { int n = model.couples.Count; //consider the upper triangle (all pairs) for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { PedigreeCouple coupleA = model.couples[i]; PedigreeCouple coupleB = model.couples[j]; if (coupleA.GenerationalLevel == coupleB.GenerationalLevel) { PointWithVelocity a = coupleA.point; PointWithVelocity b = coupleB.point; //separate exactly overlapping points if (b.x - a.x == 0) { a.x += epsilon; } double distance = b.x - a.x; double spread = 200; double forceX = 10 * repulsionStrength * spread / (distance * distance + spread); forceX *= b.x > a.x ? 1 : -1; a.dx -= forceX; b.dx += forceX; } } } } catch (Exception e) { Logger.Instance.WriteToLog(e.ToString()); } }
private static void pullParents(PedigreeModel model, PedigreeCouple couple, bool fatherToLeft) { double halfHSpacing = model.parameters.horizontalSpacing / 2; double reversal = fatherToLeft ? 1 : -1; //position the father to the left { double goalX = couple.point.x - reversal * halfHSpacing; PointWithVelocity point = couple.father.point; double strength = model.parameters.layoutCouplesStrength; PedigreeUtils.PullTowardX(goalX, point, strength, model); } //position the mother to the right { double goalX = couple.point.x + reversal * halfHSpacing; PointWithVelocity point = couple.mother.point; double strength = model.parameters.layoutCouplesStrength; PedigreeUtils.PullTowardX(goalX, point, strength, model); } }
private static void MoveChildren(double dx, PedigreeCouple couple, PedigreeModel model) { foreach (PedigreeIndividual child in couple.children) { child.point.x += dx; child.wasMoved = true; foreach (PedigreeCouple pc in child.spouseCouples) { PedigreeIndividual spouse; if (child.HraPerson.relativeID == pc.mother.HraPerson.relativeID) { spouse = pc.father; } else { spouse = pc.mother; } if (spouse.Parents != null) { PedigreeCouple nestedCouple = GetCoupleFromLR(model, child, spouse); if (nestedCouple != null) { MoveChildren(dx / 2, nestedCouple, model); } } else { spouse.point.x += dx; spouse.wasMoved = true; PedigreeCouple nestedCouple = GetCoupleFromLR(model, child, spouse); if (nestedCouple != null) { MoveChildren(dx / 2, nestedCouple, model); } } } } }
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++; } } } }; }