public void MakeStateMachineTest() { Symbol symbolA = new Symbol('a'); Symbol symbolB = new Symbol('b'); Symbol symbolC = new Symbol('c'); BinaryConcat concat1 = new BinaryConcat(symbolA, symbolB); Iteration iteration1 = new Iteration(concat1, false); ConstIteration constIteration1 = new ConstIteration(iteration1, 0); BinaryConcat concat2 = new BinaryConcat(symbolA, symbolC); Iteration iteration2 = new Iteration(concat2, false); ConstIteration constIteration2 = new ConstIteration(iteration2, 1); BinaryConcat concat3 = new BinaryConcat(symbolB, symbolC); Iteration iteration3 = new Iteration(concat3, false); ConstIteration constIteration3 = new ConstIteration(iteration3, 3); BinaryUnion union1 = new BinaryUnion(constIteration1, constIteration2); BinaryUnion union2 = new BinaryUnion(union1, constIteration3); IList <StateMachinePostReport> reports = new List <StateMachinePostReport>(); FLaGLib.Data.StateMachines.StateMachine stateMachine = union2.MakeStateMachine(d => reports.Add(d)); Assert.Fail("Not Implemented"); }
public static Image DrawDiagram(this FLaGLib.Data.StateMachines.StateMachine stateMachine) { using (Font stateFont = new Font(_FontName, 100f, FontStyle.Italic, GraphicsUnit.Pixel)) { using (Font transitionFont = new Font(_FontName, 70f, FontStyle.Italic, GraphicsUnit.Pixel)) { using (Font subscriptFont = new Font(_FontName, 62f, FontStyle.Italic, GraphicsUnit.Pixel)) { IReadOnlyDictionary <Label, SingleLabel> states = stateMachine.States.Select(s => new KeyValuePair <Label, SingleLabel>(s, s.ExtractSingleLabel())). ToSortedDictionary().AsReadOnly(); SingleLabel initialState = states[stateMachine.InitialState]; IDictionary <SingleLabel, int> stateIndices = stateMachine.States.Select((s, i) => new KeyValuePair <SingleLabel, int>(states[s], i)).ToDictionary(); IReadOnlySet <SingleLabel> finalStates = stateMachine.FinalStates.Select(s => states[s]).ToSortedSet().AsReadOnly(); IDictionary <Tuple <SingleLabel, SingleLabel>, ISet <char> > arrows = new Dictionary <Tuple <SingleLabel, SingleLabel>, ISet <char> >(); foreach (FLaGLib.Data.StateMachines.Transition transition in stateMachine.Transitions) { Tuple <SingleLabel, SingleLabel> stateTransition = new Tuple <SingleLabel, SingleLabel>(states[transition.CurrentState], states[transition.NextState]); ISet <char> arrow; if (arrows.ContainsKey(stateTransition)) { arrow = arrows[stateTransition]; } else { arrow = arrows[stateTransition] = new SortedSet <char>(); } arrow.Add(transition.Symbol); } double radius = GetRadiusByFontAndState(stateFont, subscriptFont, states.Values); double startStateRadius = radius - 10.0; double alpha = 2 * Math.PI / states.Count; double length; if (states.Count > 1) { length = radius / (1 - Math.Cos(alpha)) + 2 * radius; } else { length = 0; } double sideSize = 2 * (length + 4 * radius); Bitmap diagram = new Bitmap((int)sideSize, (int)sideSize); diagram.SetResolution(600, 600); using (Graphics graphics = Graphics.FromImage(diagram)) { graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.SmoothingMode = SmoothingMode.AntiAlias; using (Pen pen = new Pen(Brushes.Black, 5.0f)) { using (Pen boldPen = new Pen(Brushes.Black, 10.0f)) { graphics.TranslateTransform((float)sideSize / 2, (float)sideSize / 2); foreach (SingleLabel state in states.Values) { int index = stateIndices[state]; double left = length * Math.Cos(index * alpha) - radius; double top = length * Math.Sin(index * alpha) - radius; Pen drawPen = finalStates.Contains(state) ? boldPen : pen; RectangleF rect = new RectangleF((float)left, (float)top, (float)(2 * radius), (float)(2 * radius)); graphics.DrawEllipse(drawPen, rect); if (state == initialState) { left = length * Math.Cos(index * alpha) - startStateRadius; top = length * Math.Sin(index * alpha) - startStateRadius; rect = new RectangleF((float)left, (float)top, (float)(2 * startStateRadius), (float)(2 * startStateRadius)); graphics.DrawEllipse(pen, rect); } DrawCenteredStateName(graphics, stateFont, subscriptFont, rect, state); } foreach (KeyValuePair <Tuple <SingleLabel, SingleLabel>, ISet <char> > arrow in arrows) { int currentStateIndex = stateIndices[arrow.Key.Item1]; int nextStateIndex = stateIndices[arrow.Key.Item2]; if (currentStateIndex != nextStateIndex) { double currentStateX = length * Math.Cos(currentStateIndex * alpha); double currentStateY = length * Math.Sin(currentStateIndex * alpha); double nextStateX = length * Math.Cos(nextStateIndex * alpha); double nextStateY = length * Math.Sin(nextStateIndex * alpha); float offset = arrows.ContainsKey(new Tuple <SingleLabel, SingleLabel>(arrow.Key.Item2, arrow.Key.Item1)) ? 15.0f : 0.0f; DrawDirectedLine(graphics, (float)currentStateX, (float)currentStateY, (float)nextStateX, (float)nextStateY, (float)radius, pen, transitionFont, GetArrowText(arrow.Value), offset); } else { Matrix matrix = graphics.Transform; float beta = (float)(currentStateIndex * alpha * 180 / Math.PI + 90); graphics.TranslateTransform((float)(length * Math.Cos(currentStateIndex * alpha)), (float)(length * Math.Sin(currentStateIndex * alpha))); graphics.RotateTransform(beta); double arcTop = -radius * (Math.Sqrt(3) + 1.0); graphics.DrawArc(pen, new RectangleF((float)-radius, (float)arcTop, (float)(2 * radius), (float)(2 * radius)), -225, 270); float gamma = -225 * (float)Math.PI / 180; DrawArrow(graphics, new PointF((float)(radius * Math.Cos(gamma)), (float)(arcTop + radius + radius * Math.Sin(gamma))), gamma + (float)Math.PI / 2.0f); string text = GetArrowText(arrow.Value); SizeF textSize = graphics.MeasureString(text, transitionFont); if (Math.Cos(beta * Math.PI / 180) >= 0.0f) { PointF pointToDraw = new PointF(-textSize.Width / 2.0f, (float)(arcTop - textSize.Height)); graphics.DrawString(text, transitionFont, Brushes.Black, pointToDraw); } else { graphics.RotateTransform(180); PointF pointToDraw = new PointF(-textSize.Width / 2.0f, -(float)(arcTop)); graphics.DrawString(text, transitionFont, Brushes.Black, pointToDraw); } graphics.Transform = matrix; } } } } } return(diagram); } } } }