/// <summary> /// Create a new edge. /// </summary> private IEdge CreateEdge(IModule module, string key) { var edge = module.Edges.AddNew(); edge.Description = key; // Determine position var modWidth = PositionedEntities.Max(x => (x.X + x.Width)); var modHeight = PositionedEntities.Max(x => (x.Y + x.Height)); var elements = PositionElements.ToList(); modWidth = Math.Max(modWidth, elements.Max(x => (x.GetIntAttributeValue("x") + 1) * GridSize)); modHeight = Math.Max(modHeight, elements.Max(x => (x.GetIntAttributeValue("y") + 1) * GridSize)); // Find connectors var connectors = Root.Descendants("tk").Where(x => x.GetAttributeValue("type") == "connector"); XElement conn = null; switch (key.Substring(EdgePrefix.Length)) { case "ne": conn = FindBestConnector(connectors, "north", x => int.MaxValue - x.GetIntAttributeValue("y"), x => x.GetIntAttributeValue("x"), false); edge.X = (modWidth / 3) * 1; edge.Y = 0; break; case "nw": conn = FindBestConnector(connectors, "north", x => int.MaxValue - x.GetIntAttributeValue("y"), x => x.GetIntAttributeValue("x"), true); edge.X = (modWidth / 3) * 2; edge.Y = 0; break; case "se": conn = FindBestConnector(connectors, "south", x => x.GetIntAttributeValue("y"), x => x.GetIntAttributeValue("x"), false); edge.X = (modWidth / 3) * 1; edge.Y = modHeight; break; case "sw": conn = FindBestConnector(connectors, "south", x => x.GetIntAttributeValue("y"), x => x.GetIntAttributeValue("x"), true); edge.X = (modWidth / 3) * 2; edge.Y = modHeight; break; case "wn": conn = FindBestConnector(connectors, "east", x => int.MaxValue - x.GetIntAttributeValue("x"), x => x.GetIntAttributeValue("y"), true); edge.X = 0; edge.Y = (modHeight / 3) * 1; break; case "ws": conn = FindBestConnector(connectors, "east", x => int.MaxValue - x.GetIntAttributeValue("x"), x => x.GetIntAttributeValue("y"), false); edge.X = 0; edge.Y = (modHeight / 3) * 2; break; case "en": conn = FindBestConnector(connectors, "west", x => x.GetIntAttributeValue("x"), x => x.GetIntAttributeValue("y"), true); edge.X = modWidth; edge.Y = (modHeight / 3) * 1; break; case "es": conn = FindBestConnector(connectors, "west", x => x.GetIntAttributeValue("x"), x => x.GetIntAttributeValue("y"), false); edge.X = modWidth; edge.Y = (modHeight / 3) * 2; break; default: Message(string.Format("Unknown edge position ({0})", key)); break; } if (conn != null) { var x = conn.GetIntAttributeValue("x"); var y = conn.GetIntAttributeValue("y"); edge.X = x * GridSize + (GridSize - edge.Width) / 2; edge.Y = y * GridSize + (GridSize - edge.Height) / 2; } edges[key] = edge; return(edge); }
/// <summary> /// Import the track image /// </summary> private void ImportTrack(IModule module) { var elements = PositionElements.ToList(); var width = Math.Min(200 * GridSize, Math.Max(module.Width, elements.Max(x => (x.GetIntAttributeValue("x") + 1) * GridSize))); var height = Math.Min(200 * GridSize, Math.Max(module.Height, elements.Max(x => (x.GetIntAttributeValue("y") + 1) * GridSize))); using (var bitmap = new Bitmap(1, 1)) { using (var outerGraphics = Graphics.FromImage(bitmap)) { var refHdc = outerGraphics.GetHdc(); var metaFile = new Metafile(refHdc, new Rectangle(0, 0, width, height), MetafileFrameUnit.Pixel, EmfType.EmfPlusDual); try { const int h = GridSize / 2; using (var g = Graphics.FromImage(metaFile)) { g.SmoothingMode = SmoothingMode.AntiAlias; using (var pen = new Pen(Color.Black, 2)) { foreach (var tk in elements) { var type = tk.GetAttributeValue("type", string.Empty); var x = tk.GetIntAttributeValue("x"); var y = tk.GetIntAttributeValue("y"); var ori = tk.GetAttributeValue("ori"); if ((x < 0) || (y < 0)) { continue; } var ewidth = GridSize; var eheight = GridSize; if ((tk.Name.LocalName == "sw") && ((type == "crossing") || (type == "dcrossing"))) { ewidth = GridSize * 2; } // Transform so we can always draw on 0,0 in 'west' direction var state = g.Save(); switch (ori) { case "south": g.RotateTransform(90); g.TranslateTransform(eheight, 0, MatrixOrder.Append); break; case "north": g.RotateTransform(270); g.TranslateTransform(0, ewidth, MatrixOrder.Append); break; case "east": g.RotateTransform(180); g.TranslateTransform(ewidth, eheight, MatrixOrder.Append); break; } g.TranslateTransform(x * GridSize, y * GridSize, MatrixOrder.Append); if ((tk.Name.LocalName == "fb") && (tk.GetAttributeValue("curve") == "true")) { type = "curve"; } switch (tk.Name.LocalName + "-" + type) { default: case "tk-straight": case "tk-dir": case "tk-dirall": g.DrawLine(pen, 0, h, GridSize, h); break; case "sw-dcrossing": g.DrawLine(pen, 0, h, GridSize * 2, h); break; case "sw-left": g.DrawLine(pen, 0, h, GridSize, h); g.DrawLine(pen, h, GridSize, GridSize, h); break; case "sw-right": g.DrawLine(pen, 0, h, GridSize, h); g.DrawLine(pen, 0, h, h, GridSize); break; case "sw-crossing": g.DrawLine(pen, 0, h, GridSize * 2, h); if (tk.GetAttributeValue("dir") == "true") { g.DrawLine(pen, h, 0, GridSize + h, GridSize); } else { g.DrawLine(pen, h, GridSize, GridSize + h, 0); } break; case "fb-curve": case "tk-curve": g.DrawLine(pen, 0, h, h, GridSize); break; case "tk-connector": g.DrawLine(pen, 0, h, h, h); var r = h / 3; g.DrawArc(pen, h - r / 2, h - r / 2, r, r, 0, 360); break; case "tk-buffer": g.DrawLine(pen, 0, h, h, h); g.DrawLine(pen, h, h / 2, h, h + h / 2); break; } g.Restore(state); } } } } finally { outerGraphics.ReleaseHdc(refHdc); } // Set image var stream = new MemoryStream(); metaFile.SaveAsEmf(stream); stream.Position = 0; module.BackgroundImage = stream; } } }