Changeset 10487 for branches/HeuristicLab.ReingoldTilfordTreeLayout/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.cs
- Timestamp:
- 02/20/14 15:25:28 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.ReingoldTilfordTreeLayout/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.cs
r10471 r10487 266 266 267 267 #region methods for painting the symbolic expression tree 268 269 private void DrawFunctionTree(ISymbolicExpressionTree tree, Graphics graphics, int preferredWidth, int preferredHeight, int minHDistance, int minVDistance) { 270 var layoutNodes = layoutAdapter.Convert(tree).ToList(); 268 private void DrawFunctionTree(ISymbolicExpressionTree symbolicExpressionTree, Graphics graphics, int preferredWidth, int preferredHeight, int minHDistance, int minVDistance) { 269 var layoutNodes = layoutAdapter.Convert(symbolicExpressionTree).ToList(); 271 270 layoutEngine.Reset(); 272 271 layoutEngine.Root = layoutNodes[0]; 273 272 layoutEngine.AddNodes(layoutNodes); 274 layoutEngine.MinHorizontalSpacing = (preferred NodeWidth + minHDistance);275 layoutEngine.MinVerticalSpacing = (preferred NodeHeight + minVDistance);273 layoutEngine.MinHorizontalSpacing = (preferredWidth + minHDistance); 274 layoutEngine.MinVerticalSpacing = (preferredHeight + minVDistance); 276 275 layoutEngine.CalculateLayout(); 277 276 var bounds = layoutEngine.Bounds(); 278 double sx = this.Width / (bounds.Width + preferredWidth); 279 if (sx > 1) sx = 1; 280 double sy = this.Height / (bounds.Height + preferredHeight); 281 if (sy > 1) sy = 1; 282 double dx = (this.Width - bounds.Width + preferredWidth) / 2; 283 if (dx < 0) dx = 0; 284 double dy = (this.Height - bounds.Height + preferredHeight) / 2; 285 if (dy < 0) dy = 0; 286 287 var levels = layoutNodes.GroupBy(n => n.Level, n => n); 288 289 foreach (var level in levels) { 290 var nodes = level.ToList(); 291 double min = 0; 292 for (int i = 0; i < nodes.Count - 1; ++i) { 293 var w = (nodes[i + 1].X - nodes[i].X) * sx - preferredWidth; 294 if (w < min) min = w; 295 } 296 if (min > 0) min = 0; 297 298 foreach (var layoutNode in level) { 277 278 double verticalScalingFactor = 1.0; 279 double layoutHeight = (bounds.Height + preferredHeight); 280 if (this.Height < layoutHeight) 281 verticalScalingFactor = this.Height / layoutHeight; 282 283 double horizontalScalingFactor = 1.0; 284 double layoutWidth = (bounds.Width + preferredWidth); 285 if (this.Width < layoutWidth) 286 horizontalScalingFactor = this.Width / layoutWidth; 287 288 double horizontalOffset; 289 if (this.Width > layoutWidth) 290 horizontalOffset = (this.Width - layoutWidth) / 2.0; 291 else 292 horizontalOffset = preferredWidth / 2.0; 293 294 var levels = layoutNodes.GroupBy(n => n.Level, n => n).ToList(); 295 for (int i = levels.Count - 1; i >= 0; --i) { 296 var nodes = levels[i].ToList(); 297 298 double minSpacing = double.MaxValue; 299 if (nodes.Count > 1) { 300 for (int j = 1; j < nodes.Count() - 1; ++j) { 301 var distance = nodes[j].X - nodes[j - 1].X; // guaranteed to be > 0 302 if (minSpacing > distance) minSpacing = distance; 303 } 304 } 305 minSpacing *= horizontalScalingFactor; 306 307 int minWidth = (int)Math.Round(preferredWidth * horizontalScalingFactor); 308 int width = (int)Math.Min(minSpacing, preferredWidth) - 2; // leave some pixels so that node margins don't overlap 309 310 foreach (var layoutNode in nodes) { 299 311 var visualNode = visualTreeNodes[layoutNode.Content]; 300 visualNode.Width = (int)Math.Round(preferredWidth + min) - 2; // -2 to allow enough padding (1px on each side) for the node contour to be drawn301 visualNode.Height = (int)Math.Round(preferredHeight * sy);302 visualNode.X = (int) (Math.Round(layoutNode.X * sx + dx));303 visualNode.Y = (int) (Math.Round(layoutNode.Y * sy + dy));312 visualNode.Width = width; 313 visualNode.Height = (int)Math.Round(preferredHeight * verticalScalingFactor); 314 visualNode.X = (int)Math.Round((layoutNode.X + horizontalOffset) * horizontalScalingFactor + (minWidth - width) / 2.0); 315 visualNode.Y = (int)Math.Round(layoutNode.Y * verticalScalingFactor); 304 316 DrawTreeNode(graphics, visualNode); 305 317 } 306 318 } 307 308 graphics.ResetClip(); // reset clip region309 319 // draw node connections 310 320 foreach (var visualNode in visualTreeNodes.Values) { … … 315 325 var origin = new Point(visualNode.X + visualNode.Width / 2, visualNode.Y + visualNode.Height); 316 326 var target = new Point(visualSubtree.X + visualSubtree.Width / 2, visualSubtree.Y); 327 graphics.Clip = new Region(new Rectangle(Math.Min(origin.X, target.X), origin.Y, Math.Max(origin.X, target.X), target.Y)); 317 328 using (var linePen = new Pen(visualLine.LineColor)) { 318 329 linePen.DashStyle = visualLine.DashStyle; … … 366 377 Image image = new Bitmap(Width, Height); 367 378 using (Graphics g = Graphics.FromImage(image)) { 368 int height = this.Height / tree.Depth; 369 DrawFunctionTree(tree, g, 0, 0, Width, height); 379 DrawFunctionTree(tree, g, preferredNodeWidth, preferredNodeHeight, minHorizontalDistance, minVerticalDistance); 370 380 } 371 381 image.Save(filename); … … 377 387 using (Metafile file = new Metafile(filename, g.GetHdc())) { 378 388 using (Graphics emfFile = Graphics.FromImage(file)) { 379 int height = this.Height / tree.Depth; 380 DrawFunctionTree(tree, emfFile, 0, 0, Width, height); 389 DrawFunctionTree(tree, emfFile, preferredNodeWidth, preferredNodeHeight, minHorizontalDistance, minVerticalDistance); 381 390 } 382 391 }
Note: See TracChangeset
for help on using the changeset viewer.