public IncrementControllerVariables(PedigreeModel model, PedigreeController layoutEngine) { step = delegate() { model.parameters.ControllerMode = layoutEngine.GetMode(); }; }
public LayoutHoldingPen(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) return; //pull everything gently toward the center horizontally int minX = int.MaxValue; int maxX = -minX; foreach (PedigreeIndividual pi in model.individuals) { if (model.HoldingPen.ContainsKey(pi.HraPerson.relativeID) == false) { if (pi.point.x < minX) minX = (int)pi.point.x; } } model.parameters.HoldingPenOrigin.X = minX; int count = 0; foreach (PedigreeIndividual pi in model.HoldingPen.Values) { pi.point.x = model.parameters.HoldingPenOrigin.X + (model.parameters.horizontalSpacing * count); pi.point.y = model.parameters.HoldingPenOrigin.Y + (model.parameters.verticalSpacing / 2); count++; } }; }
public AutoSave(PedigreeModel model, PedigreeController layoutEngine) { step = delegate() { layoutEngine.Finished(); }; }
public LayoutHoldingPen(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) { return; } //pull everything gently toward the center horizontally int minX = int.MaxValue; int maxX = -minX; foreach (PedigreeIndividual pi in model.individuals) { if (model.HoldingPen.ContainsKey(pi.HraPerson.relativeID) == false) { if (pi.point.x < minX) { minX = (int)pi.point.x; } } } model.parameters.HoldingPenOrigin.X = minX; int count = 0; foreach (PedigreeIndividual pi in model.HoldingPen.Values) { pi.point.x = model.parameters.HoldingPenOrigin.X + (model.parameters.horizontalSpacing * count); pi.point.y = model.parameters.HoldingPenOrigin.Y + (model.parameters.verticalSpacing / 2); count++; } }; }
public LevelRestrictedForceDirectedLayout(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) { return; } if (!model.couplesGraphIsPlanar) { attractAdjacentCouplePairs(model); repelAllCouplePairs(model); //int n = model.coupleEdges.Count; //for (int i = 0; i < n; i++) // for (int j = i + 1; j < n; j++) // if (model.edgesCross(model.coupleEdges[i], model.coupleEdges[j])) // { // ShrinkEdge(model.coupleEdges[i]); // ShrinkEdge(model.coupleEdges[j]); // } } }; }
/// <summary> /// Adds a layout step to this layout engine. /// </summary> public void AddLayoutStep(String mode, LayoutStep layoutStep) { if (!layoutSteps.ContainsKey(mode)) { layoutSteps.Add(mode, new List <LayoutStep>()); } layoutSteps[mode].Add(layoutStep); }
public SwapSibs(PedigreeModel model) { step = delegate() { foreach (PedigreeCouple pc1 in model.couples) { pc1.point.x = (pc1.mother.point.x + pc1.father.point.x) / 2; pc1.point.y = (pc1.mother.point.y + pc1.father.point.y) / 2; foreach (PedigreeCouple pc2 in model.couples) { pc2.point.x = (pc2.mother.point.x + pc2.father.point.x) / 2; pc2.point.y = (pc2.mother.point.y + pc2.father.point.y) / 2; if (pc1 != pc2) { if (Math.Abs(pc1.point.y - pc2.point.y) < (model.parameters.verticalSpacing / 2)) { bool FirstIsLeft = false; if (pc1.point.x < pc2.point.x) { FirstIsLeft = true; } foreach (PedigreeIndividual pi1 in pc1.children) { foreach (PedigreeIndividual pi2 in pc2.children) { if (FirstIsLeft) { if (pi2.point.x < pi1.point.x) { double temp = pi2.point.x; pi2.point.x = pi1.point.x; pi1.point.x = temp; return; } } else { if (pi1.point.x < pi2.point.x) { double temp = pi2.point.x; pi2.point.x = pi1.point.x; pi1.point.x = temp; return; } } } } } } } } }; }
public DetectPlanarity(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) return; model.couplesGraphIsPlanar = CouplesGraphIsPlanar(model); }; }
public DetectValidLayout(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) return; model.layoutIsValid = LayoutIsValid(model); }; }
public PullToTargetPositions(PedigreeModel model) { step = delegate() { foreach (PedigreeIndividual pi in model.individuals) { PedigreeUtils.PullTowardX(model.TargetPositions[pi.HraPerson.relativeID].x, pi.point, 0.1, model); PedigreeUtils.PullTowardY(model.TargetPositions[pi.HraPerson.relativeID].y, pi.point, 0.1, model); } }; }
public ComputeCenters(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) { return; } if (model.couplesGraphIsPlanar) { foreach (PedigreeCouple couple in model.couples) { if (!model.pointsBeingDragged.Contains(couple.point)) { //compute the center for the couple if (couple.mother != null && couple.father != null) { double motherX = couple.mother.point.x; double motherY = couple.mother.point.y + model.parameters.individualSize / 2; double fatherX = couple.father.point.x; double fatherY = couple.father.point.y + model.parameters.individualSize / 2; double coupleCenterX = (motherX + fatherX) / 2; //compute the center for the couple's sibship double sibshipMinX = double.MaxValue; double sibshipMaxX = -double.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; } } double sibshipY = couple.point.y + model.parameters.verticalSpacing - model.parameters.individualSize / 2; double sibshipCenterX = (sibshipMinX + sibshipMaxX) / 2; //this is the middle point between parents and children from which //ideal positions of both are derived double middleX = (sibshipCenterX + coupleCenterX) / 2; couple.point.x = middleX; } } } } }; }
public IncrementIOVariables(PedigreeModel model) { step = delegate() { model.io.mousePressed = !model.io.pMouseDown && model.io.mouseDown; model.io.mouseReleased = model.io.pMouseDown && !model.io.mouseDown; model.io.pMouseDown = model.io.mouseDown; model.io.pMouseX = model.io.mouseX; model.io.pMouseY = model.io.mouseY; }; }
public DetectValidLayout(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) { return; } model.layoutIsValid = LayoutIsValid(model); }; }
public DetectPlanarity(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) { return; } model.couplesGraphIsPlanar = CouplesGraphIsPlanar(model); }; }
/*************************************************************************************/ public LayoutSipshipsTwo(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) { parents.children.Sort(delegate(PedigreeIndividual a, PedigreeIndividual b) { double ax = EffectivePosition(a); double bx = EffectivePosition(b); return(ax.CompareTo(bx)); }); double sibWidth = 0; double leftEdge = 0; double rightEdge = 0;; foreach (PedigreeIndividual child in parents.children) { leftEdge = GetLeftEdge(child, double.MaxValue, model); rightEdge = GetRightEdge(child, double.MinValue, model); sibWidth += (rightEdge - leftEdge); } double spacing = sibWidth / ((double)(parents.children.Count)); double 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); double goalX = leftEdge + (spacing * i); PedigreeUtils.PullTowardX(goalX, child.point, strength, model); i++; } } }; }
/*************************************************************************************/ public LayoutSipshipsTwo(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) { parents.children.Sort(delegate(PedigreeIndividual a, PedigreeIndividual b) { double ax = EffectivePosition(a); double bx = EffectivePosition(b); return ax.CompareTo(bx); }); double sibWidth = 0; double leftEdge = 0; double rightEdge = 0; ; foreach (PedigreeIndividual child in parents.children) { leftEdge = GetLeftEdge(child, double.MaxValue, model); rightEdge = GetRightEdge(child, double.MinValue, model); sibWidth += (rightEdge - leftEdge); } double spacing = sibWidth / ((double)(parents.children.Count)); double 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); double goalX = leftEdge + (spacing * i); PedigreeUtils.PullTowardX(goalX, child.point, strength, model); i++; } } }; }
public DragPoints(PedigreeModel model, PedigreeController layoutEngine) { step = delegate() { //if the mouse was pressed and there were no couples being dragged, //drag the one under the mouse point. if (model.io.mousePressed) { double x = model.io.mouseX; // -model.parameters.hOffset; double y = model.io.mouseY; // -model.parameters.vOffset; PointWithVelocity pointUnderCursor = GetPointUnderCursor(model, x, y); if (model.Selected.Count < 2) { if (pointUnderCursor != null) { model.pointsBeingDragged.Add(pointUnderCursor); } } else { bool found = false; foreach (PedigreeIndividual pi in model.Selected) { model.pointsBeingDragged.Add(pi.point); if (pi.point == pointUnderCursor) { found = true; } } if (found == false) { model.pointsBeingDragged.Clear(); } } } if (model.io.mouseReleased) { model.pointsBeingDragged.Clear(); } foreach (PointWithVelocity point in model.pointsBeingDragged) { point.x += ((model.io.mouseX - model.io.pMouseX) / model.parameters.scale); point.y += ((model.io.mouseY - model.io.pMouseY) / model.parameters.scale); } }; }
public ComputeCenters(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) return; if (model.couplesGraphIsPlanar) { foreach (PedigreeCouple couple in model.couples) { if (!model.pointsBeingDragged.Contains(couple.point)) { //compute the center for the couple if (couple.mother != null && couple.father != null) { double motherX = couple.mother.point.x; double motherY = couple.mother.point.y + model.parameters.individualSize / 2; double fatherX = couple.father.point.x; double fatherY = couple.father.point.y + model.parameters.individualSize / 2; double coupleCenterX = (motherX + fatherX) / 2; //compute the center for the couple's sibship double sibshipMinX = double.MaxValue; double sibshipMaxX = -double.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; } double sibshipY = couple.point.y + model.parameters.verticalSpacing - model.parameters.individualSize / 2; double sibshipCenterX = (sibshipMinX + sibshipMaxX) / 2; //this is the middle point between parents and children from which //ideal positions of both are derived double middleX = (sibshipCenterX + coupleCenterX) / 2; couple.point.x = middleX; } } } } }; }
public DragPoints(PedigreeModel model, PedigreeController layoutEngine) { step = delegate() { //if the mouse was pressed and there were no couples being dragged, //drag the one under the mouse point. if (model.io.mousePressed) { double x = model.io.mouseX;// -model.parameters.hOffset; double y = model.io.mouseY;// -model.parameters.vOffset; PointWithVelocity pointUnderCursor = GetPointUnderCursor(model, x, y); if (model.Selected.Count < 2) { if (pointUnderCursor != null) model.pointsBeingDragged.Add(pointUnderCursor); } else { bool found = false; foreach (PedigreeIndividual pi in model.Selected) { model.pointsBeingDragged.Add(pi.point); if (pi.point == pointUnderCursor) { found = true; } } if (found == false) { model.pointsBeingDragged.Clear(); } } } if (model.io.mouseReleased) { model.pointsBeingDragged.Clear(); } foreach (PointWithVelocity point in model.pointsBeingDragged) { point.x += ((model.io.mouseX - model.io.pMouseX) / model.parameters.scale); point.y += ((model.io.mouseY - model.io.pMouseY) / model.parameters.scale); } }; }
public PullTowardCenterHorizontally(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) { return; } //pull everything gently toward the center horizontally //foreach (PointWithVelocity point in model.points) //{ // double goalX = (model.displayXMin + model.displayXMax) / 2; // double strength = model.parameters.centeringForceStrength; // //strength = 0.06; // PedigreeUtils.PullTowardX(goalX, point,strength); //} //pull everything gently toward the center horizontally 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.displayXMax) / 2; double offset = idealCenterX - centerX; foreach (PointWithVelocity point in model.points) { double goalX = point.x + offset; double strength = model.parameters.centeringForceStrength; PedigreeUtils.PullTowardX(goalX, point, strength, model); } }; }
public IncrementVelocities(PedigreeModel model) { step = delegate() { foreach (PointWithVelocity point in model.points) { if (!model.pointsBeingDragged.Contains(point)) { point.x += point.dx; point.y += point.dy; point.dx *= model.parameters.dampeningFactor; point.dy *= model.parameters.dampeningFactor; } else point.dx = point.dy = 0; } }; }
public PlaceIndividualsOverCouples(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) return; if(!model.couplesGraphIsPlanar) foreach (PedigreeCouple couple in model.couples) { couple.mother.point.Set(couple.point); couple.father.point.Set(couple.point); foreach(PedigreeIndividual child in couple.children) child.point.Set(couple.point); } }; }
public EllapsedTimeCheck(PedigreeModel model) { step = delegate() { model.cycles++; if (model.cycles % 200 == 0 && model.cycles <= 800 && model.layoutIsValid == false) { 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; } } }; }
public IncrementVelocities(PedigreeModel model) { step = delegate() { foreach (PointWithVelocity point in model.points) { if (!model.pointsBeingDragged.Contains(point)) { point.x += point.dx; point.y += point.dy; point.dx *= model.parameters.dampeningFactor; point.dy *= model.parameters.dampeningFactor; } else { point.dx = point.dy = 0; } } }; }
public SnapToGrid(PedigreeModel model, PedigreeController layoutEngine) { step = delegate() { if (model.io.mousePressed == false) { foreach (PedigreeIndividual pi in model.individuals) { if (model.pointsBeingDragged.Contains(pi.point) == false) { double deltaX = pi.point.x % model.parameters.gridWidth; if (deltaX > 0.0) { if (deltaX >= (model.parameters.gridWidth / 2.0)) { pi.point.x += (model.parameters.gridWidth - deltaX); } else { pi.point.x -= (deltaX); } } double deltaY = pi.point.y % model.parameters.gridHeight; if (deltaY > 0.0) { if (deltaY >= (model.parameters.gridHeight / 2.0)) { pi.point.y += (model.parameters.gridHeight - deltaY); } else { pi.point.y -= (deltaY); } } } } } }; }
public PlaceIndividualsOverCouples(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) { return; } if (!model.couplesGraphIsPlanar) { foreach (PedigreeCouple couple in model.couples) { couple.mother.point.Set(couple.point); couple.father.point.Set(couple.point); foreach (PedigreeIndividual child in couple.children) { child.point.Set(couple.point); } } } }; }
public PullTowardCenterHorizontally(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) return; //pull everything gently toward the center horizontally //foreach (PointWithVelocity point in model.points) //{ // double goalX = (model.displayXMin + model.displayXMax) / 2; // double strength = model.parameters.centeringForceStrength; // //strength = 0.06; // PedigreeUtils.PullTowardX(goalX, point,strength); //} //pull everything gently toward the center horizontally 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.displayXMax) / 2; double offset = idealCenterX - centerX; foreach (PointWithVelocity point in model.points) { double goalX = point.x + offset; double strength = model.parameters.centeringForceStrength; PedigreeUtils.PullTowardX(goalX, point, strength, model); } }; }
public LevelRestrictedForceDirectedLayout(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) return; if (!model.couplesGraphIsPlanar) { attractAdjacentCouplePairs(model); repelAllCouplePairs(model); //int n = model.coupleEdges.Count; //for (int i = 0; i < n; i++) // for (int j = i + 1; j < n; j++) // if (model.edgesCross(model.coupleEdges[i], model.coupleEdges[j])) // { // ShrinkEdge(model.coupleEdges[i]); // ShrinkEdge(model.coupleEdges[j]); // } } }; }
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++; } } } }; }
public PullTowardIdealVerticalPositions(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) { return; } double spacing = model.parameters.verticalSpacing; double centerY = (model.displayYMin + model.displayYMax) / 2; double offset = centerY - (model.maxGenerationalLevel + 1) * spacing / 2; foreach (PedigreeCouple couple in model.couples) { //pull the couples toward their optimal positions //based on their generational level int level = couple.GenerationalLevel; if (level >= 0) { double goalY = level * spacing + offset; double strength = model.parameters.verticalPositioningForceStrength; PedigreeUtils.PullTowardY(goalY, couple.point, strength, model); //position the individuals vertically based on the //positions of the couples: goalY = couple.point.y; strength = model.parameters.verticalPositioningForceStrength; if (couple.mother != null) { if (model.pointsBeingDragged.Contains(couple.mother.point) == false) { PedigreeUtils.PullTowardY(goalY, couple.mother.point, strength, model); //foreach (PedigreeCouple pc in couple.mother.spouseCouples) //{ // PedigreeUtils.PullTowardY(goalY, pc.father.point, strength, model); //} } } if (couple.father != null) { if (model.pointsBeingDragged.Contains(couple.father.point) == false) { PedigreeUtils.PullTowardY(goalY, couple.father.point, strength, model); //foreach (PedigreeCouple pc in couple.father.spouseCouples) //{ // PedigreeUtils.PullTowardY(goalY, pc.mother.point, strength, model); //} } } foreach (PedigreeIndividual pi in couple.children) { if (model.pointsBeingDragged.Contains(pi.point) == false) { if ((couple.mother != null) && (couple.father != null)) { double target = ((couple.mother.point.y + couple.father.point.y) / 2) + (model.parameters.verticalSpacing); pi.point.y = target; PedigreeUtils.PullTowardY(target, pi.point, model.parameters.verticalPositioningForceStrength, model); } } } } } }; }
/// <summary> /// Adds a layout step to this layout engine. /// </summary> public void AddLayoutStep(String mode,LayoutStep layoutStep) { if (!layoutSteps.ContainsKey(mode)) layoutSteps.Add(mode, new List<LayoutStep>()); layoutSteps[mode].Add(layoutStep); }
public PullTowardIdealVerticalPositions(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) return; double spacing = model.parameters.verticalSpacing; double centerY = (model.displayYMin + model.displayYMax) / 2; double offset = centerY - (model.maxGenerationalLevel + 1) * spacing / 2; foreach (PedigreeCouple couple in model.couples) { //pull the couples toward their optimal positions //based on their generational level int level = couple.GenerationalLevel; if (level >= 0) { double goalY = level * spacing + offset; double strength = model.parameters.verticalPositioningForceStrength; PedigreeUtils.PullTowardY(goalY, couple.point, strength, model); //position the individuals vertically based on the //positions of the couples: goalY = couple.point.y; strength = model.parameters.verticalPositioningForceStrength; if (couple.mother != null) if (model.pointsBeingDragged.Contains(couple.mother.point) == false) { PedigreeUtils.PullTowardY(goalY, couple.mother.point, strength, model); //foreach (PedigreeCouple pc in couple.mother.spouseCouples) //{ // PedigreeUtils.PullTowardY(goalY, pc.father.point, strength, model); //} } if (couple.father != null) if (model.pointsBeingDragged.Contains(couple.father.point) == false) { PedigreeUtils.PullTowardY(goalY, couple.father.point, strength, model); //foreach (PedigreeCouple pc in couple.father.spouseCouples) //{ // PedigreeUtils.PullTowardY(goalY, pc.mother.point, strength, model); //} } foreach (PedigreeIndividual pi in couple.children) { if (model.pointsBeingDragged.Contains(pi.point) == false) { if ((couple.mother != null) && (couple.father != null)) { double target = ((couple.mother.point.y + couple.father.point.y) / 2) + (model.parameters.verticalSpacing); pi.point.y = target; PedigreeUtils.PullTowardY(target, pi.point, model.parameters.verticalPositioningForceStrength, model); } } } } } }; }
public AttractCouples(PedigreeModel model) { step = delegate() { foreach (PedigreeCouple pc in model.couples) { if ((pc.mother != null) && (pc.father != null)) { if (pc.mother.Mother != null && pc.mother.Father != null && pc.father.Mother != null && pc.father.Father != null) { double motherAvgX = (pc.mother.Mother.point.x + pc.mother.Father.point.x) / 2; double fatherAvgX = (pc.father.Mother.point.x + pc.father.Father.point.x) / 2; if (pc.mother.point.x > pc.father.point.x && motherAvgX < fatherAvgX) { double temp = pc.mother.point.x; pc.mother.point.x = pc.father.point.x; pc.father.point.x = temp; } else if (pc.father.point.x > pc.mother.point.x && fatherAvgX < motherAvgX) { double temp = pc.mother.point.x; pc.mother.point.x = pc.father.point.x; pc.father.point.x = temp; } } if (pc.children.Count > 0) { double xAcc = 0; double yAcc = 0; double sibMin = double.MaxValue; double sibMax = double.MinValue; foreach (PedigreeIndividual kid in pc.children) { xAcc += kid.point.x; yAcc += kid.point.y; if (sibMin > kid.point.x) sibMin = kid.point.x; if (sibMax < kid.point.x) sibMax = kid.point.x; } xAcc = (sibMin + sibMax) / 2; yAcc /= (double)pc.children.Count; double distance = Math.Abs(pc.mother.point.x - pc.father.point.x); double coupleAvg = (pc.mother.point.x + pc.father.point.x) / (2.0); if (!model.parameters.hideNonBloodRelatives || (pc.mother.bloodRelative && pc.father.bloodRelative)) { if (pc.mother.point.x < pc.father.point.x) { PedigreeUtils.PullTowardX(xAcc - (distance / 2), pc.mother.point, 0.1, model); PedigreeUtils.PullTowardX(xAcc + (distance / 2), pc.father.point, 0.1, model); } else { PedigreeUtils.PullTowardX(xAcc + (distance / 2), pc.mother.point, 0.1, model); PedigreeUtils.PullTowardX(xAcc - (distance / 2), pc.father.point, 0.1, model); } List<PedigreeIndividual> kidsPulledToParents = new List<PedigreeIndividual>(); if (Math.Abs(pc.mother.point.x - pc.father.point.x) < (0.90 * model.parameters.horizontalSpacing)) { SeperateCouple(pc, model, xAcc, ref kidsPulledToParents); } } else { if (model.parameters.hideNonBloodRelatives) { if (pc.mother.bloodRelative && !pc.father.bloodRelative) { PedigreeUtils.PullTowardX(pc.mother.point.x, pc.father.point, 0.1, model); } else if (!pc.mother.bloodRelative && pc.father.bloodRelative) { PedigreeUtils.PullTowardX(pc.father.point.x, pc.mother.point, 0.1, model); } } pc.mother.point.x = coupleAvg; pc.father.point.x = coupleAvg; } } } } }; }
public CenterParents(PedigreeModel model) { step = delegate() { ////initialize the per-level ordering lists for each generation //for (int generationIndex = 0; generationIndex <= model.maxGenerationalLevel + 1; generationIndex++) //{ // List<PedigreeIndividual> generation = PedigreeUtils.GetIndividualsInGeneration(model, generationIndex); // for (int i = 0; i < generation.Count; i++) // { // } //} }; //if (model.couplesGraphIsPlanar) //{ // foreach (PedigreeCouple couple in model.couples) // { // if (!model.pointsBeingDragged.Contains(couple.point)) // { // //compute the center for the couple // double motherX = couple.mother.point.x; // double motherY = couple.mother.point.y + model.parameters.individualSize / 2; // double fatherX = couple.father.point.x; // double fatherY = couple.father.point.y + model.parameters.individualSize / 2; // double coupleCenterX = (motherX + fatherX) / 2; // //compute the center for the couple's sibship // double sibshipMinX = double.MaxValue; // double sibshipMaxX = -double.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; // } // double sibshipY = couple.point.y + // model.parameters.verticalSpacing - model.parameters.individualSize / 2; // double sibshipCenterX = (sibshipMinX + sibshipMaxX) / 2; // //this is the middle point between parents and children from which // //ideal positions of both are derived // //double middleX = (sibshipCenterX + coupleCenterX) / 2; // if (couple.mother.point.x < couple.father.point.x) // { // PedigreeUtils.PullTowardX(sibshipCenterX + (model.parameters.horizontalSpacing / 2), couple.mother.point, 2, model); // PedigreeUtils.PullTowardX(sibshipCenterX - (model.parameters.horizontalSpacing / 2), couple.father.point, 2, model); // } // else // { // PedigreeUtils.PullTowardX(sibshipCenterX + (model.parameters.horizontalSpacing / 2), couple.mother.point, 2, model); // PedigreeUtils.PullTowardX(sibshipCenterX - (model.parameters.horizontalSpacing / 2), couple.father.point, 2, model); // } // /**/ // } // //if (Math.Abs(couple.mother.point.x - couple.father.point.x) > 120) // //{ // // if (couple.mother.point.x < couple.father.point.x) // // { // // PedigreeUtils.PullTowardX(couple.father.point.x + 60, couple.mother.point, 0.25, model); // // PedigreeUtils.PullTowardX(couple.mother.point.x - 60, couple.father.point, 0.25, model); // // } // // else // // { // // PedigreeUtils.PullTowardX(couple.father.point.x - 60, couple.mother.point, 0.25, model); // // PedigreeUtils.PullTowardX(couple.mother.point.x + 60, couple.father.point, 0.25, model); // // } // //} // } //} /* */ /* * //initialize the per-level ordering lists for each generation * for (int generationIndex = 0; generationIndex <= model.maxGenerationalLevel + 1; generationIndex++) * { * * List<PedigreeIndividual> generation = PedigreeUtils.GetIndividualsInGeneration(model, generationIndex); * for (int i = 0; i < generation.Count; i++) * { * for (int j = i; j < generation.Count; j++) * { * PedigreeIndividual one = generation[i]; * PedigreeIndividual two = generation[j]; * double delta = Math.Abs(one.point.x - two.point.x); * if ( delta < (model.parameters.horizontalSpacing)) * { * if (one.Parents.point.x < two.Parents.point.x) * { * PedigreeUtils.PullTowardX(one.point.x - (model.parameters.horizontalSpacing - delta), one.point, 1, model); * PedigreeUtils.PullTowardX(two.point.x + (model.parameters.horizontalSpacing - delta), two.point, 1, model); * } * else * { * PedigreeUtils.PullTowardX(one.point.x + (model.parameters.horizontalSpacing - delta), one.point, 1, model); * PedigreeUtils.PullTowardX(two.point.x - (model.parameters.horizontalSpacing - delta), two.point, 1, model); * } * } * * } * } * } * * if (model.couplesGraphIsPlanar) * { * foreach (PedigreeCouple couple in model.couples) * { * * if (!model.pointsBeingDragged.Contains(couple.point)) * { * if (Math.Abs(couple.mother.point.x - couple.father.point.x) > (2 * model.parameters.horizontalSpacing)) * { * * //compute the center for the couple * double motherX = couple.mother.point.x; * double motherY = couple.mother.point.y + model.parameters.individualSize / 2; * double fatherX = couple.father.point.x; * double fatherY = couple.father.point.y + model.parameters.individualSize / 2; * double coupleCenterX = (motherX + fatherX) / 2; * * if (couple.mother.point.x < couple.father.point.x) * { * PedigreeUtils.PullTowardX(coupleCenterX + model.parameters.horizontalSpacing, couple.mother.point, 1, model); * PedigreeUtils.PullTowardX(coupleCenterX - model.parameters.horizontalSpacing, couple.father.point, 1, model); * } * else * { * PedigreeUtils.PullTowardX(coupleCenterX - model.parameters.horizontalSpacing, couple.mother.point, 1, model); * PedigreeUtils.PullTowardX(coupleCenterX + model.parameters.horizontalSpacing, couple.father.point, 1, 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++; } } } }; }
public RepelIndividuals(PedigreeModel model) { step = delegate() { foreach (PedigreeIndividual pi in model.individuals) { foreach (PedigreeIndividual neighbor in model.individuals) { if (pi != neighbor) { if (Math.Abs(neighbor.point.y - pi.point.y) < (model.parameters.verticalSpacing / 2)) { if (Math.Abs(neighbor.point.x - pi.point.x) < model.parameters.horizontalSpacing) { if (!model.parameters.hideNonBloodRelatives || (neighbor.bloodRelative && pi.bloodRelative)) { if (pi.Group == null || pi.Group.Contains(neighbor)==false) { if (neighbor.point.x < pi.point.x) { PedigreeUtils.PullTowardX(neighbor.point.x + model.parameters.horizontalSpacing, pi.point, model.parameters.repelIndividualSetsStrength, model); } else { PedigreeUtils.PullTowardX(neighbor.point.x - model.parameters.horizontalSpacing, pi.point, model.parameters.repelIndividualSetsStrength, model); } } } } //check for neighnor placed between person and spouse if (neighbor.HraPerson.motherID == pi.HraPerson.motherID || neighbor.HraPerson.fatherID == pi.HraPerson.fatherID) { foreach (PedigreeCouple pc in pi.spouseCouples) { PedigreeIndividual spouse; if (pc.mother == pi) spouse = pc.father; else spouse = pc.mother; if (spouse != null) { if (neighbor.point.x > Math.Min(pi.point.x, spouse.point.x) && neighbor.point.x < Math.Max(pi.point.x, spouse.point.x)) { double x = neighbor.point.x; neighbor.point.x = pi.point.x; pi.point.x = x; } } } } } } } } }; }
public LayoutCouples(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) { return; } double hSpacing = model.parameters.horizontalSpacing; double halfHSpacing = hSpacing / 2; //for each couple, layout the mothers and fathers with no parents foreach (PedigreeCouple couple in model.couples) { if (model.parameters.hideNonBloodRelatives && couple.mother.bloodRelative && !couple.father.bloodRelative) { couple.father.point.x = couple.mother.point.x; couple.point.x = couple.mother.point.x; } else if (model.parameters.hideNonBloodRelatives && couple.father.bloodRelative && !couple.mother.bloodRelative) { couple.mother.point.x = couple.father.point.x; couple.point.x = couple.father.point.x; } else { if (couple.mother != null && couple.father != null) { bool motherHasParents = couple.mother.Parents != null; bool fatherHasParents = couple.father.Parents != null; //if mother and father both have parents, if (motherHasParents && fatherHasParents) { bool fatherToLeft = couple.father.Parents.point.x < couple.mother.Parents.point.x; pullParents(model, couple, fatherToLeft); } //if the mother has parents but the father doesn't, else if (motherHasParents && !fatherHasParents) { //then the mother will be pulled into position by //the layout step for her sibship, so position the //father depending on where the mother is: //pull the father to the left of the mother double goalX = couple.mother.point.x - hSpacing; PointWithVelocity point = couple.father.point; double strength = model.parameters.layoutCouplesStrength; PedigreeUtils.PullTowardX(goalX, point, strength, model); } //if the father has parents but the mother diesn't, else if (!motherHasParents && fatherHasParents) { //then the father will be pulled into position by //the layout step for his sibship, so position the //mother depending on where the father is: //pull the mother to the right of the father double goalX = couple.father.point.x + hSpacing; PointWithVelocity point = couple.mother.point; double strength = model.parameters.layoutCouplesStrength; PedigreeUtils.PullTowardX(goalX, point, strength, model); } //if neither the father nor the mother has parents, else if (!motherHasParents && !fatherHasParents) { //then position them according to their spouse position, //placing the father on the left: { //handle the case of half siblings: bool coupleIsReversed = false; if (couple.mother.spouseCouples.Count == 2) { PedigreeCouple oppositeCouple; if (couple.mother.spouseCouples[0].Equals(couple)) { oppositeCouple = couple.mother.spouseCouples[1]; } else { oppositeCouple = couple.mother.spouseCouples[0]; } double oppositeX = oppositeCouple.point.x; double motherX = couple.point.x; bool oppositeCoupleIsLeftOfMother = oppositeX < motherX; coupleIsReversed = oppositeCoupleIsLeftOfMother; } bool fatherToLeft = !coupleIsReversed; pullParents(model, couple, fatherToLeft); } } } } } }; }
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 void addLayoutStep(LayoutStep layoutStep) { this.steps.Add(layoutStep); }
public RepelIndividuals(PedigreeModel model) { step = delegate() { foreach (PedigreeIndividual pi in model.individuals) { foreach (PedigreeIndividual neighbor in model.individuals) { if (pi != neighbor) { if (Math.Abs(neighbor.point.y - pi.point.y) < (model.parameters.verticalSpacing / 2)) { if (Math.Abs(neighbor.point.x - pi.point.x) < model.parameters.horizontalSpacing) { if (!model.parameters.hideNonBloodRelatives || (neighbor.bloodRelative && pi.bloodRelative)) { if (pi.Group == null || pi.Group.Contains(neighbor) == false) { if (neighbor.point.x < pi.point.x) { PedigreeUtils.PullTowardX(neighbor.point.x + model.parameters.horizontalSpacing, pi.point, model.parameters.repelIndividualSetsStrength, model); } else { PedigreeUtils.PullTowardX(neighbor.point.x - model.parameters.horizontalSpacing, pi.point, model.parameters.repelIndividualSetsStrength, model); } } } } //check for neighnor placed between person and spouse if (neighbor.HraPerson.motherID == pi.HraPerson.motherID || neighbor.HraPerson.fatherID == pi.HraPerson.fatherID) { foreach (PedigreeCouple pc in pi.spouseCouples) { PedigreeIndividual spouse; if (pc.mother == pi) { spouse = pc.father; } else { spouse = pc.mother; } if (spouse != null) { if (neighbor.point.x > Math.Min(pi.point.x, spouse.point.x) && neighbor.point.x < Math.Max(pi.point.x, spouse.point.x)) { double x = neighbor.point.x; neighbor.point.x = pi.point.x; pi.point.x = x; } } } } } } } } }; }
public LayoutCouples(PedigreeModel model) { step = delegate() { if (model.individuals.Count < 2) return; double hSpacing = model.parameters.horizontalSpacing; double halfHSpacing = hSpacing / 2; //for each couple, layout the mothers and fathers with no parents foreach (PedigreeCouple couple in model.couples) { if (model.parameters.hideNonBloodRelatives && couple.mother.bloodRelative && !couple.father.bloodRelative) { couple.father.point.x = couple.mother.point.x; couple.point.x = couple.mother.point.x; } else if (model.parameters.hideNonBloodRelatives && couple.father.bloodRelative && !couple.mother.bloodRelative) { couple.mother.point.x = couple.father.point.x; couple.point.x = couple.father.point.x; } else { if (couple.mother != null && couple.father != null) { bool motherHasParents = couple.mother.Parents != null; bool fatherHasParents = couple.father.Parents != null; //if mother and father both have parents, if (motherHasParents && fatherHasParents) { bool fatherToLeft = couple.father.Parents.point.x < couple.mother.Parents.point.x; pullParents(model, couple, fatherToLeft); } //if the mother has parents but the father doesn't, else if (motherHasParents && !fatherHasParents) { //then the mother will be pulled into position by //the layout step for her sibship, so position the //father depending on where the mother is: //pull the father to the left of the mother double goalX = couple.mother.point.x - hSpacing; PointWithVelocity point = couple.father.point; double strength = model.parameters.layoutCouplesStrength; PedigreeUtils.PullTowardX(goalX, point, strength, model); } //if the father has parents but the mother diesn't, else if (!motherHasParents && fatherHasParents) { //then the father will be pulled into position by //the layout step for his sibship, so position the //mother depending on where the father is: //pull the mother to the right of the father double goalX = couple.father.point.x + hSpacing; PointWithVelocity point = couple.mother.point; double strength = model.parameters.layoutCouplesStrength; PedigreeUtils.PullTowardX(goalX, point, strength, model); } //if neither the father nor the mother has parents, else if (!motherHasParents && !fatherHasParents) { //then position them according to their spouse position, //placing the father on the left: { //handle the case of half siblings: bool coupleIsReversed = false; if (couple.mother.spouseCouples.Count == 2) { PedigreeCouple oppositeCouple; if (couple.mother.spouseCouples[0].Equals(couple)) oppositeCouple = couple.mother.spouseCouples[1]; else oppositeCouple = couple.mother.spouseCouples[0]; double oppositeX = oppositeCouple.point.x; double motherX = couple.point.x; bool oppositeCoupleIsLeftOfMother = oppositeX < motherX; coupleIsReversed = oppositeCoupleIsLeftOfMother; } bool fatherToLeft = !coupleIsReversed; pullParents(model, couple, fatherToLeft); } } } } } }; }
public CenterParents(PedigreeModel model) { step = delegate() { ////initialize the per-level ordering lists for each generation //for (int generationIndex = 0; generationIndex <= model.maxGenerationalLevel + 1; generationIndex++) //{ // List<PedigreeIndividual> generation = PedigreeUtils.GetIndividualsInGeneration(model, generationIndex); // for (int i = 0; i < generation.Count; i++) // { // } //} }; //if (model.couplesGraphIsPlanar) //{ // foreach (PedigreeCouple couple in model.couples) // { // if (!model.pointsBeingDragged.Contains(couple.point)) // { // //compute the center for the couple // double motherX = couple.mother.point.x; // double motherY = couple.mother.point.y + model.parameters.individualSize / 2; // double fatherX = couple.father.point.x; // double fatherY = couple.father.point.y + model.parameters.individualSize / 2; // double coupleCenterX = (motherX + fatherX) / 2; // //compute the center for the couple's sibship // double sibshipMinX = double.MaxValue; // double sibshipMaxX = -double.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; // } // double sibshipY = couple.point.y + // model.parameters.verticalSpacing - model.parameters.individualSize / 2; // double sibshipCenterX = (sibshipMinX + sibshipMaxX) / 2; // //this is the middle point between parents and children from which // //ideal positions of both are derived // //double middleX = (sibshipCenterX + coupleCenterX) / 2; // if (couple.mother.point.x < couple.father.point.x) // { // PedigreeUtils.PullTowardX(sibshipCenterX + (model.parameters.horizontalSpacing / 2), couple.mother.point, 2, model); // PedigreeUtils.PullTowardX(sibshipCenterX - (model.parameters.horizontalSpacing / 2), couple.father.point, 2, model); // } // else // { // PedigreeUtils.PullTowardX(sibshipCenterX + (model.parameters.horizontalSpacing / 2), couple.mother.point, 2, model); // PedigreeUtils.PullTowardX(sibshipCenterX - (model.parameters.horizontalSpacing / 2), couple.father.point, 2, model); // } // /**/ // } // //if (Math.Abs(couple.mother.point.x - couple.father.point.x) > 120) // //{ // // if (couple.mother.point.x < couple.father.point.x) // // { // // PedigreeUtils.PullTowardX(couple.father.point.x + 60, couple.mother.point, 0.25, model); // // PedigreeUtils.PullTowardX(couple.mother.point.x - 60, couple.father.point, 0.25, model); // // } // // else // // { // // PedigreeUtils.PullTowardX(couple.father.point.x - 60, couple.mother.point, 0.25, model); // // PedigreeUtils.PullTowardX(couple.mother.point.x + 60, couple.father.point, 0.25, model); // // } // //} // } //} /* */ /* //initialize the per-level ordering lists for each generation for (int generationIndex = 0; generationIndex <= model.maxGenerationalLevel + 1; generationIndex++) { List<PedigreeIndividual> generation = PedigreeUtils.GetIndividualsInGeneration(model, generationIndex); for (int i = 0; i < generation.Count; i++) { for (int j = i; j < generation.Count; j++) { PedigreeIndividual one = generation[i]; PedigreeIndividual two = generation[j]; double delta = Math.Abs(one.point.x - two.point.x); if ( delta < (model.parameters.horizontalSpacing)) { if (one.Parents.point.x < two.Parents.point.x) { PedigreeUtils.PullTowardX(one.point.x - (model.parameters.horizontalSpacing - delta), one.point, 1, model); PedigreeUtils.PullTowardX(two.point.x + (model.parameters.horizontalSpacing - delta), two.point, 1, model); } else { PedigreeUtils.PullTowardX(one.point.x + (model.parameters.horizontalSpacing - delta), one.point, 1, model); PedigreeUtils.PullTowardX(two.point.x - (model.parameters.horizontalSpacing - delta), two.point, 1, model); } } } } } if (model.couplesGraphIsPlanar) { foreach (PedigreeCouple couple in model.couples) { if (!model.pointsBeingDragged.Contains(couple.point)) { if (Math.Abs(couple.mother.point.x - couple.father.point.x) > (2 * model.parameters.horizontalSpacing)) { //compute the center for the couple double motherX = couple.mother.point.x; double motherY = couple.mother.point.y + model.parameters.individualSize / 2; double fatherX = couple.father.point.x; double fatherY = couple.father.point.y + model.parameters.individualSize / 2; double coupleCenterX = (motherX + fatherX) / 2; if (couple.mother.point.x < couple.father.point.x) { PedigreeUtils.PullTowardX(coupleCenterX + model.parameters.horizontalSpacing, couple.mother.point, 1, model); PedigreeUtils.PullTowardX(coupleCenterX - model.parameters.horizontalSpacing, couple.father.point, 1, model); } else { PedigreeUtils.PullTowardX(coupleCenterX - model.parameters.horizontalSpacing, couple.mother.point, 1, model); PedigreeUtils.PullTowardX(coupleCenterX + model.parameters.horizontalSpacing, couple.father.point, 1, model); } } } } } */ }
public Pan(PedigreeModel model) { step = delegate() { //if the mouse was pressed and there were no couples being dragged, //drag the one under the mouse point. if (model.io.mousePressed) { double x = model.io.mouseX; double y = model.io.mouseY; PointWithVelocity pointUnderCursor = GetPointUnderCursor(model, x, y); if (pointUnderCursor == null) { x1 = x; y1 = y; hOffset1 = model.parameters.hOffset; vOffset1 = model.parameters.vOffset; panInProgress = true; //model.parameters.multiSelect = true; } } else if (model.io.mouseReleased) { if (model.SelectionLasso.Count > 3) { model.Selected.Clear(); Polygon p = new Polygon(model.SelectionLasso.ToArray()); foreach (PedigreeIndividual pi in model.individuals) { System.Drawing.Point scaled = new System.Drawing.Point((int)pi.point.x, (int)pi.point.y); scaled.X += model.parameters.hOffset; scaled.Y += model.parameters.vOffset; scaled.X = (int)(model.parameters.scale * (double)scaled.X); scaled.Y = (int)(model.parameters.scale * (double)scaled.Y); pi.Selected = false; if (p.Contains(scaled)) { pi.Selected = true; if(model.Selected.Contains(pi) == false) model.Selected.Add(pi); } } } else { //PedigreeIndividual s = PedigreeUtils.GetIndividualUnderPoint(model, x1, y1); //if (s != null) //{ // s.Selected = true; // if(model.Selected.Contains(s) == false) // model.Selected.Add(s); //} } model.parameters.multiSelect = false; panInProgress = false; model.SelectionLasso.Clear(); } else if (panInProgress) { double x2 = model.io.mouseX; double y2 = model.io.mouseY; if (model.parameters.multiSelect) { model.SelectionLasso.Add(new System.Drawing.Point((int)x2, (int)y2)); } else { model.parameters.hOffset = (int)(hOffset1 + x2 - x1); model.parameters.vOffset = (int)(vOffset1 + y2 - y1); } } }; }
public DetectForceConvergence(PedigreeModel model, PedigreeController layoutEngine) { step = delegate() { if (model.individuals.Count < 2) { layoutEngine.SetMode(PedigreeController.MANUAL); return; } if (model.io.mouseDown == false) { double delta = 0; //bool moving = false; foreach (PedigreeIndividual pi in model.individuals) { double meanX = 0; double meanY = 0; if (model.PositionHistoryX.ContainsKey(pi.HraPerson.relativeID)) { model.PositionHistoryX[pi.HraPerson.relativeID].Add(pi.point.x); if (model.PositionHistoryX[pi.HraPerson.relativeID].Count > model.parameters.PositionHistoryDepth) { model.PositionHistoryX[pi.HraPerson.relativeID].RemoveAt(0); } } else { List <double> past = new List <double>(); past.Add(pi.point.x); model.PositionHistoryX.Add(pi.HraPerson.relativeID, past); } foreach (double cur in model.PositionHistoryX[pi.HraPerson.relativeID]) { meanX += cur; } meanX = meanX / ((double)(model.PositionHistoryX[pi.HraPerson.relativeID].Count)); if (model.PositionHistoryY.ContainsKey(pi.HraPerson.relativeID)) { model.PositionHistoryY[pi.HraPerson.relativeID].Add(pi.point.y); if (model.PositionHistoryY[pi.HraPerson.relativeID].Count > model.parameters.PositionHistoryDepth) { model.PositionHistoryY[pi.HraPerson.relativeID].RemoveAt(0); } } else { List <double> past = new List <double>(); past.Add(pi.point.y); model.PositionHistoryY.Add(pi.HraPerson.relativeID, past); } foreach (double cur in model.PositionHistoryY[pi.HraPerson.relativeID]) { meanY += cur; } meanY = meanY / ((double)(model.PositionHistoryY[pi.HraPerson.relativeID].Count)); if (model.TargetPositions.ContainsKey(pi.HraPerson.relativeID)) { delta += Math.Abs((model.TargetPositions[pi.HraPerson.relativeID].x - meanX)); delta += Math.Abs((model.TargetPositions[pi.HraPerson.relativeID].y - meanY)); model.TargetPositions[pi.HraPerson.relativeID].x = meanX; model.TargetPositions[pi.HraPerson.relativeID].y = meanY; } else { PointWithVelocity pos = new PointWithVelocity(); pos.x = meanX; pos.y = meanY; model.TargetPositions.Add(pi.HraPerson.relativeID, pos); delta += Math.Abs(meanX); delta += Math.Abs(meanY); } } if (delta / model.individuals.Count < 0.05) { if (model.converged == false) { if (layoutEngine.ModelConvergedCallback != null) { layoutEngine.ModelConvergedCallback.Invoke(); } } model.converged = true; } else { model.converged = false; } } }; }
public Pan(PedigreeModel model) { step = delegate() { //if the mouse was pressed and there were no couples being dragged, //drag the one under the mouse point. if (model.io.mousePressed) { double x = model.io.mouseX; double y = model.io.mouseY; PointWithVelocity pointUnderCursor = GetPointUnderCursor(model, x, y); if (pointUnderCursor == null) { x1 = x; y1 = y; hOffset1 = model.parameters.hOffset; vOffset1 = model.parameters.vOffset; panInProgress = true; //model.parameters.multiSelect = true; } } else if (model.io.mouseReleased) { if (model.SelectionLasso.Count > 3) { model.Selected.Clear(); Polygon p = new Polygon(model.SelectionLasso.ToArray()); foreach (PedigreeIndividual pi in model.individuals) { System.Drawing.Point scaled = new System.Drawing.Point((int)pi.point.x, (int)pi.point.y); scaled.X += model.parameters.hOffset; scaled.Y += model.parameters.vOffset; scaled.X = (int)(model.parameters.scale * (double)scaled.X); scaled.Y = (int)(model.parameters.scale * (double)scaled.Y); pi.Selected = false; if (p.Contains(scaled)) { pi.Selected = true; if (model.Selected.Contains(pi) == false) { model.Selected.Add(pi); } } } } else { //PedigreeIndividual s = PedigreeUtils.GetIndividualUnderPoint(model, x1, y1); //if (s != null) //{ // s.Selected = true; // if(model.Selected.Contains(s) == false) // model.Selected.Add(s); //} } model.parameters.multiSelect = false; panInProgress = false; model.SelectionLasso.Clear(); } else if (panInProgress) { double x2 = model.io.mouseX; double y2 = model.io.mouseY; if (model.parameters.multiSelect) { model.SelectionLasso.Add(new System.Drawing.Point((int)x2, (int)y2)); } else { model.parameters.hOffset = (int)(hOffset1 + x2 - x1); model.parameters.vOffset = (int)(vOffset1 + y2 - y1); } } }; }
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 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 AttractCouples(PedigreeModel model) { step = delegate() { foreach (PedigreeCouple pc in model.couples) { if ((pc.mother != null) && (pc.father != null)) { if (pc.mother.Mother != null && pc.mother.Father != null && pc.father.Mother != null && pc.father.Father != null) { double motherAvgX = (pc.mother.Mother.point.x + pc.mother.Father.point.x) / 2; double fatherAvgX = (pc.father.Mother.point.x + pc.father.Father.point.x) / 2; if (pc.mother.point.x > pc.father.point.x && motherAvgX < fatherAvgX) { double temp = pc.mother.point.x; pc.mother.point.x = pc.father.point.x; pc.father.point.x = temp; } else if (pc.father.point.x > pc.mother.point.x && fatherAvgX < motherAvgX) { double temp = pc.mother.point.x; pc.mother.point.x = pc.father.point.x; pc.father.point.x = temp; } } if (pc.children.Count > 0) { double xAcc = 0; double yAcc = 0; double sibMin = double.MaxValue; double sibMax = double.MinValue; foreach (PedigreeIndividual kid in pc.children) { xAcc += kid.point.x; yAcc += kid.point.y; if (sibMin > kid.point.x) { sibMin = kid.point.x; } if (sibMax < kid.point.x) { sibMax = kid.point.x; } } xAcc = (sibMin + sibMax) / 2; yAcc /= (double)pc.children.Count; double distance = Math.Abs(pc.mother.point.x - pc.father.point.x); double coupleAvg = (pc.mother.point.x + pc.father.point.x) / (2.0); if (!model.parameters.hideNonBloodRelatives || (pc.mother.bloodRelative && pc.father.bloodRelative)) { if (pc.mother.point.x < pc.father.point.x) { PedigreeUtils.PullTowardX(xAcc - (distance / 2), pc.mother.point, 0.1, model); PedigreeUtils.PullTowardX(xAcc + (distance / 2), pc.father.point, 0.1, model); } else { PedigreeUtils.PullTowardX(xAcc + (distance / 2), pc.mother.point, 0.1, model); PedigreeUtils.PullTowardX(xAcc - (distance / 2), pc.father.point, 0.1, model); } List <PedigreeIndividual> kidsPulledToParents = new List <PedigreeIndividual>(); if (Math.Abs(pc.mother.point.x - pc.father.point.x) < (0.90 * model.parameters.horizontalSpacing)) { SeperateCouple(pc, model, xAcc, ref kidsPulledToParents); } } else { if (model.parameters.hideNonBloodRelatives) { if (pc.mother.bloodRelative && !pc.father.bloodRelative) { PedigreeUtils.PullTowardX(pc.mother.point.x, pc.father.point, 0.1, model); } else if (!pc.mother.bloodRelative && pc.father.bloodRelative) { PedigreeUtils.PullTowardX(pc.father.point.x, pc.mother.point, 0.1, model); } } pc.mother.point.x = coupleAvg; pc.father.point.x = coupleAvg; } } } } }; }
public DetectForceConvergence(PedigreeModel model, PedigreeController layoutEngine) { step = delegate() { if (model.individuals.Count < 2) { layoutEngine.SetMode(PedigreeController.MANUAL); return; } if (model.io.mouseDown == false) { double delta = 0; //bool moving = false; foreach (PedigreeIndividual pi in model.individuals) { double meanX = 0; double meanY = 0; if (model.PositionHistoryX.ContainsKey(pi.HraPerson.relativeID)) { model.PositionHistoryX[pi.HraPerson.relativeID].Add(pi.point.x); if (model.PositionHistoryX[pi.HraPerson.relativeID].Count > model.parameters.PositionHistoryDepth) model.PositionHistoryX[pi.HraPerson.relativeID].RemoveAt(0); } else { List<double> past = new List<double>(); past.Add(pi.point.x); model.PositionHistoryX.Add(pi.HraPerson.relativeID, past); } foreach (double cur in model.PositionHistoryX[pi.HraPerson.relativeID]) { meanX += cur; } meanX = meanX / ((double)(model.PositionHistoryX[pi.HraPerson.relativeID].Count)); if (model.PositionHistoryY.ContainsKey(pi.HraPerson.relativeID)) { model.PositionHistoryY[pi.HraPerson.relativeID].Add(pi.point.y); if (model.PositionHistoryY[pi.HraPerson.relativeID].Count > model.parameters.PositionHistoryDepth) model.PositionHistoryY[pi.HraPerson.relativeID].RemoveAt(0); } else { List<double> past = new List<double>(); past.Add(pi.point.y); model.PositionHistoryY.Add(pi.HraPerson.relativeID, past); } foreach (double cur in model.PositionHistoryY[pi.HraPerson.relativeID]) { meanY += cur; } meanY = meanY / ((double)(model.PositionHistoryY[pi.HraPerson.relativeID].Count)); if (model.TargetPositions.ContainsKey(pi.HraPerson.relativeID)) { delta += Math.Abs((model.TargetPositions[pi.HraPerson.relativeID].x - meanX)); delta += Math.Abs((model.TargetPositions[pi.HraPerson.relativeID].y - meanY)); model.TargetPositions[pi.HraPerson.relativeID].x = meanX; model.TargetPositions[pi.HraPerson.relativeID].y = meanY; } else { PointWithVelocity pos = new PointWithVelocity(); pos.x = meanX; pos.y = meanY; model.TargetPositions.Add(pi.HraPerson.relativeID, pos); delta += Math.Abs(meanX); delta += Math.Abs(meanY); } } if (delta / model.individuals.Count < 0.05) { if (model.converged == false) { if (layoutEngine.ModelConvergedCallback != null) layoutEngine.ModelConvergedCallback.Invoke(); } model.converged = true; } else { model.converged = false; } } }; }
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); //} /**/ //} }; }