// ---------------- Second and Final Iteration of plotting application --------------------- //Plotting from a specific person in your family, will show parents, partner and children public FileContentResult PlotIndividual(int pid) { //Dimensions of the box, all distances should be measured in these unit distances - helps keep consistancy int height = 60; int width = 175; // Collect information on individual and relatives Individual mainIndividual = _treeService.GetIndividual(pid); IList <Relationship> relList = _treeService.GetRelationships(pid); int numberOfChildren = _treeService.GetNumberOfChildren(pid); string mainName = mainIndividual.fullName.ToString(); int bigW = _treeService.GetPlotWidth(pid) * width * 2 + (width / 4); int bigH = height * 6; //Give a border of a height either side around the plot, assi //Used for colour plotting int alpha = 100; int red = 204; int green = 102; int blue = 0; //variables that will contain individual information, used to print values inside node string individualName; string dateBirth; string dateDeath; float titleLocation = (bigW / 2) - ((mainIndividual.fullName.Length * 8) / 2); //A letter in a string takes up approx 8 pixels //Three Rows of boxes, x values for these boxes updated as plotting is done //The y coordinates on these nodes are all constant as they are the three rows and their positions stay constant float xRowOne = width / 4; float yRowOne = height + height / 2; float xRowTwo = width; float yRowTwo = 3 * height; float xRowThree = width / 4; float yRowThree = 5 * height; //If the individual plotted has siblings, these will need to be used, otherwise they won't be used float siblingX = 0; float siblingY = 0; //Plot point for Children float childX = 0; float childY = 0; using (Bitmap bmp = new Bitmap(bigW, 500)) { using (Graphics g = Graphics.FromImage(bmp)) { //Store individual name, first node will be the main individual individualName = mainIndividual.fullName.ToString(); dateBirth = mainIndividual.dateOfBirth.ToString(); dateDeath = mainIndividual.dateOfDeath.ToString(); //Colour the background of the bitmap g.Clear(Color.Bisque); //Title the bitmap with the main individuals name g.DrawString(individualName + "'s Family Tree", new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(titleLocation, 10), new StringFormat()); //Plot Initial Person, g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.DrawRectangle(Pens.Brown, xRowTwo, yRowTwo, width, height); //Fill in the information of the individual within the confised of the rectangle fill g.DrawString(individualName, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowTwo + 5, yRowTwo + 5), new StringFormat()); g.DrawString(dateBirth, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowTwo + 5, yRowTwo + 20), new StringFormat()); g.DrawString(dateDeath, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowTwo + 5, yRowTwo + 35), new StringFormat()); g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, red, green, blue)), xRowTwo, yRowTwo, width, height); //Check if the individual has parents in the database //If there are, prepare the bus to accept two parent boxes, bool Check = relList.Any(p => p.relationshipTypeID == 2); if (Check == true) { g.DrawLine(Pens.Black, xRowTwo + width / 2, yRowTwo, xRowTwo + width / 2, yRowTwo - height); //Draws a T shape above your node, ready for addition of parent nodes g.DrawLine(Pens.Black, xRowTwo + width / 4, yRowTwo - height, xRowTwo + width - width / 4, yRowTwo - height); //Store the location that siblings will need to bus to siblingX = xRowTwo + width / 2; siblingY = yRowTwo - height / 4; } //Update x location xRowTwo = xRowTwo + 2 * width; //Check if the individual has any children, if they do draw a bus for their nodes to attach to and save the x and y coordinates of that location bool kidCheck = relList.Any(c => c.relationshipTypeID == 3); if (kidCheck == true) { g.DrawLine(Pens.Black, xRowTwo - width / 2, (yRowTwo + (height / 2)), xRowTwo - width / 2, (yRowTwo + (height / 2) + height)); } // Assign location for child bus point of connection childX = xRowTwo - width / 2; childY = yRowTwo + height + height / 2; foreach (var relative in relList) { //------------------------------- Check for Marriage Relationship ----------------------------- if (relative.relationshipTypeID == 4) { //Load partners information individualName = _treeService.GetIndividual(relative.relativeID).fullName.ToString(); dateBirth = _treeService.GetIndividual(relative.relativeID).dateOfBirth.ToString(); dateDeath = _treeService.GetIndividual(relative.relativeID).dateOfDeath.ToString(); //Fill the node with their partners information and fill the node with the colour g.DrawString(individualName, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowTwo + 5, yRowTwo + 5), new StringFormat()); g.DrawString(dateBirth, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowTwo + 5, yRowTwo + 20), new StringFormat()); g.DrawString(dateDeath, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowTwo + 5, yRowTwo + 35), new StringFormat()); g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, red, green, blue)), xRowTwo, yRowTwo, width, height); //Draw Line to Partner g.DrawLine(Pens.Black, (xRowTwo), (yRowTwo + (height / 2)), (xRowTwo - width), (yRowTwo + (height / 2))); //Update x coordinates xRowTwo = xRowTwo + 2 * width; } /// ---------------- Check For Parent Relationship ----------------- else if (relative.relationshipTypeID == 2)//relationship type is parent, therefore plot box above you { //Load parents information ready for display individualName = _treeService.GetIndividual(relative.relativeID).fullName.ToString(); dateBirth = _treeService.GetIndividual(relative.relativeID).dateOfBirth.ToString(); dateDeath = _treeService.GetIndividual(relative.relativeID).dateOfDeath.ToString(); //Draw Node for Parent g.DrawString(individualName, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowOne + 5, yRowOne + 5), new StringFormat()); //Writes the Date of Birth g.DrawString(dateBirth, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowOne + 5, yRowOne + 20), new StringFormat()); //Write Date of Death g.DrawString(dateDeath, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowOne + 5, yRowOne + 35), new StringFormat()); g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, red, green, blue)), xRowOne, yRowOne, width, height); // Load parents relationships and check for certain conditions var parCheck = _treeService.GetRelationships(relative.relativeID); bool Checker = parCheck.Any(p => p.relationshipTypeID == 2); //Check if any of the relationships are parents if (Checker == true) //If there are parent relationships, draw a line out of their box { g.DrawLine(Pens.Black, xRowOne + width / 2, yRowOne, xRowOne + width / 2, yRowOne - (height / 2)); //Position the horizontal line, ready for addition of parent nodes, these will not contain information g.DrawString(individualName + "'s Parents", new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowOne + 5, yRowOne - height), new StringFormat()); g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, red, green, blue)), xRowOne, yRowOne - height, width, height / 2); } //Update x location xRowOne = xRowOne + width / 2 + width; } //---------------------- Check for Child Relationship ------------------------ else if (relative.relationshipTypeID == 3)//relationship type is child, therefore plot box below you { individualName = _treeService.GetIndividual(relative.relativeID).fullName.ToString(); dateBirth = _treeService.GetIndividual(relative.relativeID).dateOfBirth.ToString(); dateDeath = _treeService.GetIndividual(relative.relativeID).dateOfDeath.ToString(); //Draw Node for Parent g.DrawString(individualName, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowThree + 5, yRowThree + 5), new StringFormat()); //Writes the Date of Birth g.DrawString(dateBirth, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowThree + 5, yRowThree + 20), new StringFormat()); //Writes Date of Death g.DrawString(dateDeath, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowThree + 5, yRowThree + 35), new StringFormat()); // Fill node with colour g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, red, green, blue)), xRowThree, yRowThree, width, height); // Draw lines up to the bus from the parent g.DrawLine(Pens.Black, xRowThree + width / 2, yRowThree, xRowThree + width / 2, yRowThree - height / 2); g.DrawLine(Pens.Black, xRowThree + width / 2, childY, childX, childY); // Update row three's x Position xRowThree = xRowThree + width + width; var partCheck = _treeService.GetRelationships(relative.relativeID); //Load up childs relationships bool partnerCheck = partCheck.Any(par => par.relationshipTypeID == 4); //Check if any of the relationships match the marriage type if (partnerCheck == true) //If they do, plot the marriage { g.DrawLine(Pens.Black, xRowThree - width, yRowThree + height / 2, xRowThree, yRowThree + height / 2); bool kidChecker = partCheck.Any(c => c.relationshipTypeID == 3); //Check if your children have children, if they do show boxes that can be filled if (kidChecker == true) { //Create busses to the child node, write their names and fill the rectangle g.DrawLine(Pens.Black, xRowThree - width + width / 2, (yRowThree + (height / 2)), xRowThree - width + width / 2, (yRowThree + (height / 2) + height)); g.DrawString(individualName + "'s Children", new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowThree + 5 - width, yRowThree + height + height / 2), new StringFormat()); g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, red, green, blue)), xRowThree - width, yRowThree + height + height / 2, width, height / 2); } foreach (var person in partCheck) { if (person.relationshipTypeID == 4) { individualName = _treeService.GetIndividual(person.relativeID).fullName.ToString(); dateBirth = _treeService.GetIndividual(person.relativeID).dateOfBirth.ToString(); dateDeath = _treeService.GetIndividual(person.relativeID).dateOfDeath.ToString(); g.DrawString(individualName, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowThree + 5, yRowThree + 5), new StringFormat()); //Writes the Date of Birth g.DrawString(dateBirth, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowThree + 5, yRowThree + 20), new StringFormat()); g.DrawString(dateDeath, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowThree + 5, yRowThree + 35), new StringFormat()); g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, red, green, blue)), xRowThree, yRowThree, width, height); xRowThree = xRowThree + width + width; } } } } } //Plot Siblings after all transformations have been made by previous foreach foreach (var relative in relList) { if (relative.relationshipTypeID == 1) { //Load up the individuals name individualName = _treeService.GetIndividual(relative.relativeID).fullName.ToString(); dateBirth = _treeService.GetIndividual(relative.relativeID).dateOfBirth.ToString(); dateDeath = _treeService.GetIndividual(relative.relativeID).dateOfDeath.ToString(); //Writes individual name g.DrawString(individualName, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowTwo + 5, yRowTwo + 5), new StringFormat()); //Writes the Date of Birth g.DrawString(dateBirth, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowTwo + 5, yRowTwo + 20), new StringFormat()); //Writes the Date of Death g.DrawString(dateDeath, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowTwo + 5, yRowTwo + 35), new StringFormat()); g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, red, green, blue)), xRowTwo, yRowTwo, width, height); //Draw lines back to the parent bus g.DrawLine(Pens.Black, xRowTwo + width / 2, yRowTwo, xRowTwo + width / 2, siblingY); g.DrawLine(Pens.Black, xRowTwo + width / 2, siblingY, siblingX, siblingY); //Update x coordinates for next node xRowTwo = xRowTwo + 2 * width; var partCheck = _treeService.GetRelationships(relative.relativeID); //Load up siblings relationships bool partnerCheck = partCheck.Any(par => par.relationshipTypeID == 4); //Check if any of the relationships match the marriage type if (partnerCheck == true) //If they do, plot the marriage { g.DrawLine(Pens.Black, xRowTwo - width, yRowTwo + height / 2, xRowTwo, yRowTwo + height / 2); bool kidChecker = partCheck.Any(c => c.relationshipTypeID == 3); //Check if your sibling has children, if they do show boxes that can be filled if (kidChecker == true) { g.DrawLine(Pens.Black, xRowTwo - width + width / 2, (yRowTwo + (height / 2)), xRowTwo - width + width / 2, (yRowTwo + (height / 2) + height)); g.DrawString(individualName + "'s Children", new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowTwo + 5 - width, yRowTwo + height + height / 2), new StringFormat()); g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, red, green, blue)), xRowTwo - width, yRowTwo + height + height / 2, width, height / 2); } foreach (var person in partCheck) { // Fills the siblings partners node in with information if (person.relationshipTypeID == 4) { individualName = _treeService.GetIndividual(person.relativeID).fullName.ToString(); dateBirth = _treeService.GetIndividual(person.relativeID).dateOfBirth.ToString(); dateDeath = _treeService.GetIndividual(person.relativeID).dateOfDeath.ToString(); g.DrawString(individualName, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowTwo + 5, yRowTwo + 5), new StringFormat()); //Writes the Date of Birth g.DrawString(dateBirth, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowTwo + 5, yRowTwo + 20), new StringFormat()); g.DrawString(dateDeath, new Font("Arial", 10, FontStyle.Bold), SystemBrushes.WindowText, new PointF(xRowTwo + 5, yRowTwo + 35), new StringFormat()); g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, red, green, blue)), xRowTwo, yRowTwo, width, height); xRowTwo = xRowTwo + width + width; } } } } } // Creates a file stream and saves it and outputs the image as a jpeg, accessible in the viwe string filename = Server.MapPath("/") + Guid.NewGuid().ToString("N"); bmp.Save(filename, System.Drawing.Imaging.ImageFormat.Jpeg); byte[] bytes; using (System.IO.FileStream stream = new System.IO.FileStream(filename, System.IO.FileMode.Open)) { bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); } System.IO.File.Delete(filename); return(new FileContentResult(bytes, "image/jpeg")); } } }