/// <summary> /// Adds a new tree to the list of trees to draw. /// </summary> /// <param name="tree">the tree to add</param> public void AddTree(ContourTree tree) { if (tree.maxValue > this.maxValue || this.trees.Count == 0) { this.maxValue = tree.maxValue; } if (tree.minValue < this.minValue || this.trees.Count == 0) { this.minValue = tree.minValue; } this.trees.Add(tree); this.DrawTrees(); }
/// <summary> /// Mutator for the contour tree that this view displays information about. /// </summary> /// <param name="tree">the tree to be displayed</param> public void SetTree(ContourTree tree) { this.tree = tree; if (tree != null) { this.maxValue = tree.GetMaxValue(); this.minValue = tree.GetMinValue(); } else { this.maxValue = 0; this.minValue = 0; } }
/// <summary> /// Figures out what kind of data the file contains and passes it to parser. /// </summary> /// <param name="myStream">the file to parse</param> private void readFileData(Stream myStream) { // Make a new StreamReader to read the text input file. StreamReader reader = new StreamReader(myStream); // Check the first line of the file for its file type identifier. string fileType = reader.ReadLine().Trim(); // The new file data object will be stored here if successful. FileDataAbstract fileData; // Try to read the file data. if (fileType == "I0") { // TODO: Finish other data file types. fileData = new FileDataI0(reader.ReadToEnd(), this.currentTimeStep); } // Throw an exception if the format is not recognized. else { throw new Exception("The file format was not recognized; only files in 'I0' format work at this time."); } // If there are already other data files, make sure they are compatible. if (this.fileDataList.Count > 0) { FileDataAbstract tempData = this.fileDataList[0]; if (tempData.Xdim != fileData.Xdim || tempData.Ydim != fileData.Ydim || tempData.Zdim != fileData.Zdim) { throw new Exception("The file you are attempting to add has different dimensions than the previously added file(s). " + "If you would like to start over with new data, please clear the current data first."); } } // If we've gotten this far without Exception, we can // assume the file data will be added successfully. this.currentTimeStep++; this.fileDataList.Add(fileData); // Take the file data and turn it into a list of grid points. List<GridPoint> pointsList = fileData.GetSortedGridPointList(); // If there are already other file(s) in the program, clear out // the current trees and add their data to the points list. if (this.fileDataList.Count > 1) { // Clear the trees. this.joinTreeView.ClearTrees(); this.splitTreeView.ClearTrees(); this.contourTreeView.ClearTrees(); // Add the data. foreach (FileDataAbstract data in this.fileDataList) { pointsList = pointsList.Union(data.GetSortedGridPointList()).ToList(); pointsList.Sort(new Comparison<GridPoint>(GridPoint.Compare)); } } // Create the join tree and split tree from the file data. JoinTree joinTree = new JoinTree(pointsList[0].value, pointsList.Last().value, pointsList); SplitTree splitTree = new SplitTree(pointsList[0].value, pointsList.Last().value, pointsList); // Simplify the trees, except for the others' critical points. joinTree.SimplifyExceptFor(splitTree.GetCritical()); splitTree.SimplifyExceptFor( joinTree.GetCritical()); // Make the contour tree. ContourTree contourTree = new ContourTree(joinTree, splitTree); this.contourTreeView.AddTree(contourTree); this.topology.SetTree(contourTree); this.topology.AddTimeStep(); // Simplify trees the rest of the way. joinTree.Simplify(); splitTree.Simplify(); // Add trees to their views. this.joinTreeView.AddTree(joinTree); this.splitTreeView.AddTree(splitTree); // Dispose of unneeded resources. reader.Dispose(); myStream.Close(); }
/// <summary> /// Add a new data file with formatting like the data file from Nathaniel. /// </summary> /// <param name="uselessParam1">required by C#</param> /// <param name="uselessParam2">required by C#</param> private void addNewNathanielDataFile(object uselessParam1, EventArgs uselessParam2) { // If opened properly, the file data will be stored here. Stream myStream = null; // This is a popup window that lets you pick a file to open. OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.InitialDirectory = "C:\\"; openFileDialog.Filter = "txt files (*.txt)|*.txt"; // Only look at text files. // If the file doesn't get opened / read / added properly, display an error message. if (openFileDialog.ShowDialog() == DialogResult.OK) { try { if ((myStream = openFileDialog.OpenFile()) != null) { // Make a new StreamReader to read the text input file. StreamReader reader = new StreamReader(myStream); // The new file data object will be stored here if successful. FileDataAbstract fileData; fileData = new FileDataNathaniel(reader.ReadToEnd(), this.currentTimeStep); // If there are already other data files, make sure they are compatible. if (this.fileDataList.Count > 0) { FileDataAbstract tempData = this.fileDataList[0]; if (tempData.Xdim != fileData.Xdim || tempData.Ydim != fileData.Ydim || tempData.Zdim != fileData.Zdim) { throw new Exception("The file you are attempting to add has different dimensions than the previously added file(s). " + "If you would like to start over with new data, please clear the current data first."); } } // If we've gotten this far without Exception, we can // assume the file data will be added successfully. this.currentTimeStep++; this.fileDataList.Add(fileData); // Take the file data and turn it into a list of grid points. List<GridPoint> pointsList = fileData.GetSortedGridPointList(); // If there are already other file(s) in the program, clear out // the current trees and add their data to the points list. if (this.fileDataList.Count > 1) { // Clear the trees. this.joinTreeView.ClearTrees(); this.splitTreeView.ClearTrees(); this.contourTreeView.ClearTrees(); // Add the data. foreach (FileDataAbstract data in this.fileDataList) { pointsList = pointsList.Union(data.GetSortedGridPointList()).ToList(); pointsList.Sort(new Comparison<GridPoint>(GridPoint.Compare)); } } // Create the join tree and split tree from the file data. JoinTree joinTree = new JoinTree(pointsList[0].value, pointsList.Last().value, pointsList); SplitTree splitTree = new SplitTree(pointsList[0].value, pointsList.Last().value, pointsList); // Simplify the trees, except for the others' critical points. joinTree.SimplifyExceptFor(splitTree.GetCritical()); splitTree.SimplifyExceptFor(joinTree.GetCritical()); // Make the contour tree. ContourTree contourTree = new ContourTree(joinTree, splitTree); this.contourTreeView.AddTree(contourTree); this.topology.SetTree(contourTree); this.topology.AddTimeStep(); // Simplify trees the rest of the way. joinTree.Simplify(); splitTree.Simplify(); // Add trees to their views. this.joinTreeView.AddTree(joinTree); this.splitTreeView.AddTree(splitTree); // Dispose of unneeded resources. reader.Dispose(); myStream.Close(); } } catch (Exception ex) { MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message); } } }
//===================================================================// // Actions // //===================================================================// /// <summary> /// Draw a particular contour tree. /// </summary> /// <param name="tree">the tree to draw</param> /// <param name="graphics">allows things to be drawn</param> /// <param name="pen">for drawing lines</param> /// <param name="nodeFill">for drawing nodes</param> private void drawTree(ContourTree tree, Graphics graphics, Pen pen, Brush nodeFill) { int nrSlotsNeeded = tree.GetNumSlotsNeeded(); float pixelsPerSlot = this.GetPixelsPerSlot(nrSlotsNeeded); float screenCenterX = this.Width / 2.0f; float half_Diameter = AbstractTreeView.NODE_DIAMETER / 2.0f; int topLeSlotsUsed = 0; int topRiSlotsUsed = 0; int botLeSlotsUsed = 0; int botRiSlotsUsed = 0; // Draw root, top, and bottom nodes. // TODO: Make the root node normal-colored again. graphics.FillEllipse(new SolidBrush(Color.Blue), screenCenterX - half_Diameter, this.ValueToYCoordinate(tree.GetRoot().value) - half_Diameter, AbstractTreeView.NODE_DIAMETER, AbstractTreeView.NODE_DIAMETER); graphics.FillEllipse(nodeFill, screenCenterX - half_Diameter, this.ValueToYCoordinate(tree.maxValue) - half_Diameter, AbstractTreeView.NODE_DIAMETER, AbstractTreeView.NODE_DIAMETER); graphics.FillEllipse(nodeFill, screenCenterX - half_Diameter, this.ValueToYCoordinate(tree.minValue) - half_Diameter, AbstractTreeView.NODE_DIAMETER, AbstractTreeView.NODE_DIAMETER); ContourNode currentTopMainPathNode = tree.GetTopMostLeaf(); ContourNode currentBotMainPathNode = tree.GetBotMostLeaf(); int currentTopDir = -1; int currentBotDir = 1; while (currentTopMainPathNode.GetTrunk() != tree.GetRoot() || currentBotMainPathNode.GetTrunk() != tree.GetRoot()) { // Top half of tree: if (currentTopMainPathNode.GetTrunk() != tree.GetRoot()) { // Look ahead at next "main path" node. ContourNode nextTopMainPathNode = currentTopMainPathNode.GetTrunk(); // Draw the next node. graphics.FillEllipse(nodeFill, screenCenterX - half_Diameter, this.ValueToYCoordinate(nextTopMainPathNode.value) - half_Diameter, AbstractTreeView.NODE_DIAMETER, AbstractTreeView.NODE_DIAMETER); // Draw the path to next node. graphics.DrawLine(pen, screenCenterX, this.ValueToYCoordinate(currentTopMainPathNode.value), screenCenterX, this.ValueToYCoordinate( nextTopMainPathNode.value)); // Make a list of branches from the next node. List<ContourNode> branches = new List<ContourNode>(nextTopMainPathNode.GetBranches()); // Remove the current node from the list of branches. branches.Remove(currentTopMainPathNode); // Draw all the branches. foreach (ContourNode branch in branches) { drawBranch(branch, graphics, pen, nodeFill, currentTopDir, currentTopDir == -1 ? topLeSlotsUsed : topRiSlotsUsed, pixelsPerSlot, screenCenterX); if (currentTopDir == -1) { topLeSlotsUsed += branch.GetNumLeaves(); } else { topRiSlotsUsed += branch.GetNumLeaves(); } } // Toggle the direction of adding. currentTopDir *= -1; // Point at next node. currentTopMainPathNode = nextTopMainPathNode; } // Bottom half of tree: if (currentBotMainPathNode.GetTrunk() != tree.GetRoot()) { // Look ahead at next "main path" node. ContourNode nextBotMainPathNode = currentBotMainPathNode.GetTrunk(); // Draw the next node. graphics.FillEllipse(nodeFill, screenCenterX - half_Diameter, this.ValueToYCoordinate(nextBotMainPathNode.value) - half_Diameter, AbstractTreeView.NODE_DIAMETER, AbstractTreeView.NODE_DIAMETER); // Draw the path to next node. graphics.DrawLine(pen, screenCenterX, this.ValueToYCoordinate(currentBotMainPathNode.value), screenCenterX, this.ValueToYCoordinate( nextBotMainPathNode.value)); // Make a list of branches from the next node. List<ContourNode> branches = new List<ContourNode>(nextBotMainPathNode.GetBranches()); // Remove the current node from the list of branches. branches.Remove(currentBotMainPathNode); // Draw all the branches. foreach (ContourNode branch in branches) { drawBranch(branch, graphics, pen, nodeFill, currentBotDir, currentBotDir == -1 ? botLeSlotsUsed : botRiSlotsUsed, pixelsPerSlot, screenCenterX); if (currentBotDir == -1) { botLeSlotsUsed += branch.GetNumLeaves(); } else { botRiSlotsUsed += branch.GetNumLeaves(); } } // Toggle the direction of adding. currentBotDir *= -1; // Point at next node. currentBotMainPathNode = nextBotMainPathNode; } } // Draw paths from currentTopMainPathNode and currentBotMainPathNode to root. graphics.DrawLine(pen, screenCenterX, this.ValueToYCoordinate(currentTopMainPathNode.value), screenCenterX, this.ValueToYCoordinate(currentBotMainPathNode.value)); // Leftover branches from the root: foreach (ContourNode branch in tree.GetRoot().GetBranches()) { if (branch != currentTopMainPathNode && branch != currentBotMainPathNode) { if (branch.value > tree.GetRoot().value) { drawBranch(branch, graphics, pen, nodeFill, currentTopDir, currentTopDir == -1 ? topLeSlotsUsed : topRiSlotsUsed, pixelsPerSlot, screenCenterX); if (currentTopDir == -1) { topLeSlotsUsed += branch.GetNumLeaves(); } else { topRiSlotsUsed += branch.GetNumLeaves(); } currentTopDir *= -1; } else { drawBranch(branch, graphics, pen, nodeFill, currentBotDir, currentBotDir == -1 ? botLeSlotsUsed : botRiSlotsUsed, pixelsPerSlot, screenCenterX); if (currentBotDir == -1) { botLeSlotsUsed += branch.GetNumLeaves(); } else { botRiSlotsUsed += branch.GetNumLeaves(); } currentBotDir *= -1; } } } }