public void ExtractSingleLabelTest_Ok() { SingleLabel actualSingleLabel = new Label(new SingleLabel('b')).ExtractSingleLabel(); SingleLabel expectedSingleLabel = new SingleLabel('b'); Assert.AreEqual(expectedSingleLabel, actualSingleLabel); }
public void CCtorTest_Simple_Ok() { SingleLabel singleLabel = new SingleLabel('b'); IEnumerable <SingleLabel> expectedLabels = EnumerateHelper.Sequence( singleLabel ); Label label = new Label(singleLabel); CollectionAssert.AreEquivalent(expectedLabels, label.Sublabels); Assert.AreEqual(LabelType.Simple, label.LabelType); }
public static SizeF GetStateLabelSize(Graphics g, Font stateFont, Font subscriptFont, SingleLabel state) { SizeF textSize = g.MeasureString(state.Sign.ToString(), stateFont); if (state.SignIndex != null) { int value = state.SignIndex.Value; SizeF indexSize = g.MeasureString(value.ToString(), subscriptFont); float xSize = textSize.Width + 2 + indexSize.Width; float ySize = Math.Max(textSize.Height, 0.6f * textSize.Height + indexSize.Height); textSize = new SizeF(xSize, ySize); } return(textSize); }
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); } } } }
public static void DrawCenteredStateName(Graphics g, Font stateFont, Font subscriptFont, RectangleF rect, SingleLabel state) { SizeF labelSize = GetStateLabelSize(g, stateFont, subscriptFont, state); float centerX = (rect.Left + rect.Right) / 2; float centerY = (rect.Top + rect.Bottom) / 2; float leftX = centerX - labelSize.Width / 2; float topY = centerY - labelSize.Height / 2; string sign = state.Sign.ToString(); g.DrawString(sign, stateFont, Brushes.Black, new PointF(leftX, topY)); SizeF letterSize = g.MeasureString(sign, stateFont); if (state.SignIndex != null) { int v = state.SignIndex.Value; leftX += letterSize.Width + 2; topY += 0.6f * letterSize.Height; g.DrawString(v.ToString(), subscriptFont, Brushes.Black, new PointF(leftX, topY)); } }
public StateMachine ConvertToDeterministicIfNot() { if (IsDeterministic()) { return(this); } SortedSet <Transition> newTransitions = new SortedSet <Transition>(); SortedSet <Label> visitedNewStates = new SortedSet <Label>(); Label newInitialState = InitialState.ConvertToComplex(); visitedNewStates.Add(newInitialState); Queue <Label> queue = new Queue <Label>(); queue.Enqueue(newInitialState); do { Label currentState = queue.Dequeue(); Dictionary <char, HashSet <SingleLabel> > symbolSingleLabelsDictionary = new Dictionary <char, HashSet <SingleLabel> >(); foreach (Transition transition in Transitions) { SingleLabel currentStateSingleLabel = transition.CurrentState.ExtractSingleLabel(); if (currentState.Sublabels.Contains(currentStateSingleLabel)) { HashSet <SingleLabel> singleLabels; if (symbolSingleLabelsDictionary.ContainsKey(transition.Symbol)) { singleLabels = symbolSingleLabelsDictionary[transition.Symbol]; } else { symbolSingleLabelsDictionary[transition.Symbol] = singleLabels = new HashSet <SingleLabel>(); } SingleLabel nextStateSingleLabel = transition.NextState.ExtractSingleLabel(); singleLabels.Add(nextStateSingleLabel); } } foreach (KeyValuePair <char, HashSet <SingleLabel> > entry in symbolSingleLabelsDictionary) { Label nextState = new Label(entry.Value); newTransitions.Add(new Transition(currentState, entry.Key, nextState)); if (visitedNewStates.Add(nextState)) { queue.Enqueue(nextState); } } } while (queue.Count > 0); HashSet <Label> newFinalStates = new HashSet <Label>(); foreach (Label state in ExtractStates(newTransitions)) { bool atLeastOneFromFinalStates = false; foreach (Label finalState in FinalStates) { if (state.Sublabels.Contains(finalState.ExtractSingleLabel())) { atLeastOneFromFinalStates = true; break; } } if (atLeastOneFromFinalStates) { newFinalStates.Add(state); } } return(new StateMachine(newInitialState, newFinalStates, newTransitions)); }
public static void Write(CsvWriter csvWriter, SingleLabel singleLabel) { csvWriter.WriteField(singleLabel.Value); }