Merge lp:~tapaal-contributor/tapaal/cpn-gui-TikZ-support into lp:~tapaal-contributor/tapaal/cpn-gui-dev

Proposed by Kristian Morsing Pedersen
Status: Superseded
Proposed branch: lp:~tapaal-contributor/tapaal/cpn-gui-TikZ-support
Merge into: lp:~tapaal-contributor/tapaal/cpn-gui-dev
Diff against target: 461 lines (+199/-136)
1 file modified
src/net/tapaal/export/TikZExporter.java (+199/-136)
To merge this branch: bzr merge lp:~tapaal-contributor/tapaal/cpn-gui-TikZ-support
Reviewer Review Type Date Requested Status
Jiri Srba Pending
Review via email: mp+415746@code.launchpad.net

This proposal supersedes a proposal from 2022-02-09.

This proposal has been superseded by a proposal from 2022-02-17.

Commit message

Added TikZ support for colored nets.
Added a framed box to the Tikz output for global variables/constants/color types.
Removed subscripiting from transition- and place names
Changed \mathrm to \mathit
Added more adjustment options for transitions, places and arcs

Description of the change

The TikZ export now shows all of the new features associated with colored nets.
Also added a framed box that contains all the global variables, constants and/or color types for a given net.
Subscripting from transition- and place names have been removed, so it looks more like the GUI.
\mathrm has also been replaces with \mathit.

To post a comment you must log in.
1574. By Kristian Morsing Pedersen <email address hidden>

Merged with cpn-gui-dev

1575. By Kristian Morsing Pedersen <email address hidden>

Labels with multiple lines on arcs now displays correctly

1576. By Kristian Morsing Pedersen <email address hidden>

Changed default pos of arc labels to 0.5

1577. By Kristian Morsing Pedersen <email address hidden>

Resolved merge conflicts

1578. By Kristian Morsing Pedersen <email address hidden>

Removed redundant \\ and changed 0,0 -> 0.0 for age of tokens in initial markings

1579. By Kristian Morsing Pedersen <email address hidden>

Changed x -> \times in inhibitor arcs

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/net/tapaal/export/TikZExporter.java'
2--- src/net/tapaal/export/TikZExporter.java 2022-01-07 17:05:54 +0000
3+++ src/net/tapaal/export/TikZExporter.java 2022-02-17 17:11:33 +0000
4@@ -3,16 +3,17 @@
5 import java.io.FileWriter;
6 import java.io.IOException;
7 import java.io.PrintWriter;
8-import java.util.List;
9+import java.util.*;
10
11+import dk.aau.cs.model.CPN.ColorType;
12+import dk.aau.cs.model.CPN.Variable;
13+import dk.aau.cs.model.tapn.Constant;
14 import dk.aau.cs.model.tapn.TimedToken;
15
16+import net.tapaal.gui.petrinet.Context;
17 import pipe.gui.petrinet.dataLayer.DataLayer;
18 import pipe.gui.TAPAALGUI;
19-import pipe.gui.petrinet.graphicElements.Arc;
20-import pipe.gui.petrinet.graphicElements.ArcPathPoint;
21-import pipe.gui.petrinet.graphicElements.Place;
22-import pipe.gui.petrinet.graphicElements.Transition;
23+import pipe.gui.petrinet.graphicElements.*;
24 import pipe.gui.petrinet.graphicElements.tapn.TimedInhibitorArcComponent;
25 import pipe.gui.petrinet.graphicElements.tapn.TimedInputArcComponent;
26 import pipe.gui.petrinet.graphicElements.tapn.TimedPlaceComponent;
27@@ -45,7 +46,7 @@
28 if (option == TikZOutputOption.FULL_LATEX) {
29 out.println("\\documentclass[a4paper]{article}");
30 out.println("\\usepackage{tikz}");
31- out.println("\\usetikzlibrary{petri,arrows}");
32+ out.println("\\usetikzlibrary{petri,arrows,positioning}");
33 out.println("\\usepackage{amstext}");
34 out.println();
35 out.println("\\begin{document}");
36@@ -62,6 +63,8 @@
37 out.print(exportTransitions(net.getTransitions()));
38 out.print(exportArcs(net.getArcs()));
39
40+ out.println(exportGlobalVariables());
41+
42 out.println("\\end{tikzpicture}");
43 if (option == TikZOutputOption.FULL_LATEX) {
44 out.println("\\end{document}");
45@@ -94,7 +97,7 @@
46 ArcPathPoint currentPoint = arc.getArcPath().getArcPathPoint(i);
47
48 if(currentPoint.getPointType() == ArcPathPoint.STRAIGHT) {
49- arcPoints += "to[bend right=0] (" + (currentPoint.getX()) + "," + (currentPoint.getY() * (-1)) + ") ";
50+ arcPoints += "to [bend right=0] (" + (currentPoint.getX()) + "," + (currentPoint.getY() * (-1)) + ") ";
51 } else if (currentPoint.getPointType() == ArcPathPoint.CURVED) {
52 double xCtrl1 = Math.round(currentPoint.getControl1().getX());
53 double yCtrl1 = Math.round(currentPoint.getControl1().getY() * (-1));
54@@ -109,21 +112,19 @@
55 }
56
57 String arrowType = getArcArrowType(arc);
58- String arcLabel = getArcLabels(arc);
59
60+ out.append("% Arc between " + arc.getSource().getName() + " and " + arc.getTarget().getName() + "\n");
61 out.append("\\draw[");
62 out.append(arrowType);
63- out.append("] (");
64+ out.append(",pos=0] (");
65 out.append(arc.getSource().getId());
66 out.append(") ");
67 out.append(arcPoints);
68- out.append("to[bend right=0]");
69- out.append(" (");
70- out.append(arc.getTarget().getId());
71- out.append(") {};\n");
72- if(!arcLabel.equals(""))
73- out.append("%% Label for arc between " + arc.getSource().getName() + " and " + arc.getTarget().getName() + "\n");
74- out.append(arcLabel);
75+ out.append("to node[bend right=0,auto]");
76+ out.append(" {");
77+ out.append(handleNameLabel(arc.getNameLabel().getText()));
78+ out.append("} ");
79+ out.append("(" + arc.getTarget().getId() + ");\n");
80 }
81 return out;
82 }
83@@ -142,50 +143,6 @@
84 return arrowType;
85 }
86
87- protected String getArcLabels(Arc arc) {
88- String arcLabel = "";
89- String arcLabelPositionString = "\\draw (" + (arc.getNameLabel().getX()) + "," + (arc.getNameLabel().getY())*(-1) + ") node {";
90-
91- if (arc instanceof TimedInputArcComponent) {
92- if (!(arc.getSource() instanceof TimedTransitionComponent)) {
93- arcLabel = arcLabelPositionString;
94- if (arc.getWeight().value() > 1) {
95- arcLabel += "$" + arc.getWeight().value() + "\\times$\\ ";
96- }
97-
98- if(TAPAALGUI.getApp().getCurrentTab().getLens().isTimed()) {
99- arcLabel += "$\\mathrm{" + replaceWithMathLatex(getGuardAsStringIfNotHidden((TimedInputArcComponent) arc)) + "}$";
100- if (arc instanceof TimedTransportArcComponent)
101- arcLabel += ":" + ((TimedTransportArcComponent) arc).getGroupNr();
102- arcLabel += "};\n";
103- } else {
104- arcLabel += "};\n";
105- }
106-
107- } else {
108- arcLabel = arcLabelPositionString;
109- if (arc.getWeight().value() > 1) {
110- arcLabel += "$" + arc.getWeight().value() + "\\times$\\ ";
111- }
112- arcLabel += ":" + ((TimedTransportArcComponent) arc).getGroupNr() + "};\n";
113- }
114-
115- } else {
116- if (arc.getWeight().value() > 1) {
117- arcLabel += arcLabelPositionString + "$" + arc.getWeight().value() + "\\times$\\ };\n";
118- }
119- }
120- return arcLabel;
121- }
122-
123- private String getGuardAsStringIfNotHidden(TimedInputArcComponent arc) {
124- if (!TAPAALGUI.getApp().showZeroToInfinityIntervals() && arc.getGuardAsString().equals("[0,inf)")){
125- return "";
126- } else {
127- return arc.getGuardAsString();
128- }
129- }
130-
131 private StringBuffer exportTransitions(Transition[] transitions) {
132 StringBuffer out = new StringBuffer();
133 for (Transition trans : transitions) {
134@@ -195,7 +152,8 @@
135
136
137 out.append("\\node[transition");
138- out.append(angle);
139+ out.append(angle);
140+ out.append(handlePlaceAndTransitionLabel(trans.getNameLabel().getText(), trans.getName(), trans.getAttributesVisible()));
141 out.append("] at (");
142 out.append((trans.getPositionX()));
143 out.append(',');
144@@ -226,31 +184,30 @@
145 out.append(trans.getId());
146 out.append(".center) { };\n");
147 }
148- if (trans.getAttributesVisible()){
149- boolean isLabelAboveTransition = trans.getY() > trans.getNameLabel().getY();
150- boolean isLabelBehindTrans = trans.getX() < trans.getNameLabel().getX();
151- double xOffset = trans.getName().length() > 5 && !isLabelAboveTransition && !isLabelBehindTrans ? trans.getLayerOffset() : 0;
152-
153- out.append("%% label for transition " + trans.getName() + "\n");
154- out.append("\\draw (");
155- out.append(trans.getNameLabel().getX() + xOffset + "," + (trans.getNameLabel().getY() * -1) + ")");
156- out.append(" node ");
157- out.append(" {");
158- out.append(exportMathName(trans.getName()));
159- out.append("};\n");
160- }
161 }
162 return out;
163 }
164
165+ private String handlePlaceAndTransitionLabel(String nameLabelText, String name, boolean isVisible) {
166+ if(!isVisible)
167+ return "";
168+
169+ String result = ", label={[align=left,label distance=0cm]90:";
170+ result += "$\\mathrm{" + (name.replace("_","\\_")) + "}$";
171+ result += handleNameLabel(nameLabelText);
172+ result += "}";
173+ return result;
174+ }
175+
176 private StringBuffer exportPlacesWithTokens(Place[] places) {
177 StringBuffer out = new StringBuffer();
178
179 for (Place place : places) {
180- String invariant = getPlaceInvariantString(place);
181+ String invariant = "$" + getPlaceInvariantString(place) + "$";
182 String tokensInPlace = getTokenListStringFor(place);
183
184 out.append("\\node[place");
185+ out.append(handlePlaceAndTransitionLabel(place.getNameLabel().getText(), place.getName(), place.getAttributesVisible()));
186 out.append("] at (");
187 out.append(place.getPositionX());
188 out.append(',');
189@@ -262,37 +219,38 @@
190 exportPlaceTokens(place, out, ((TimedPlaceComponent) place).underlyingPlace().tokens().size());
191
192 if(((TimedPlaceComponent)place).underlyingPlace().isShared()){
193- out.append("\\node[sharedplace] at (");
194+ out.append("\\node[sharedplace ");
195+ out.append("] at (");
196 out.append(place.getId());
197 out.append(".center) { };\n");
198 }
199- if (place.getAttributesVisible() || !invariant.equals("")){
200- boolean isLabelAbovePlace = place.getY() > place.getNameLabel().getY();
201- boolean isLabelBehindPlace = place.getX() < place.getNameLabel().getX();
202- double xOffset = place.getName().length() > 6 && !isLabelAbovePlace && !isLabelBehindPlace ? place.getLayerOffset() : 0;
203- double yOffset = isLabelAbovePlace ? (place.getNameLabel().getHeight() / 2) : 0;
204-
205- out.append("%% label for place " + place.getName() + "\n");
206- out.append("\\draw (");
207- out.append((place.getNameLabel().getX() + xOffset) + "," + ((place.getNameLabel().getY() * -1) + yOffset) +")");
208- out.append(" node[align=left] ");
209- out.append("{");
210- if(place.getAttributesVisible())
211- out.append(exportMathName(place.getName()));
212- if(!invariant.equals("")) {
213- if((place.getAttributesVisible()))
214- out.append("\\\\");
215- out.append(invariant);
216- }else {
217- out.append("};\n");
218- }
219-
220- }
221 }
222-
223 return out;
224 }
225
226+ private String handleNameLabel(String nameLabel) {
227+ String nameLabelsString = "";
228+ String[] labelsInName = nameLabel.split("\n");
229+ for(int i = 0; i < labelsInName.length; i++) {
230+
231+ if(labelsInName[i].contains("[")) {
232+ nameLabelsString += escapeSpacesInAndOrNot(replaceWithMathLatex(labelsInName[i]));
233+ nameLabelsString += "\\\\";
234+ }
235+ else if(!labelsInName[i].isEmpty()){
236+ nameLabelsString += escapeSpacesInAndOrNot(replaceWithMathLatex(labelsInName[i]));
237+ nameLabelsString += "\\\\";
238+ } else {
239+ nameLabelsString += "\\\\";
240+ }
241+ }
242+ return nameLabelsString;
243+ }
244+
245+ private String escapeSpacesInAndOrNot(String str) {
246+ return str.replace(" and ", "\\ and\\ ").replace(" or", "\\ or\\ ").replace(" not", "\\ not\\ ");
247+ }
248+
249 private void exportPlaceTokens(Place place, StringBuffer out, int numOfTokens) {
250 // Dot radius
251 final double tRadius = 1;
252@@ -437,6 +395,124 @@
253 }
254 }
255
256+ private StringBuffer exportGlobalVariables() {
257+ StringBuffer out = new StringBuffer();
258+
259+ Context context = new Context(TAPAALGUI.getCurrentTab());
260+ List<ColorType> listColorTypes = context.network().colorTypes();
261+ List<Constant> constantsList = new ArrayList<>(context.network().constants());
262+ List<Variable> variableList = context.network().variables();
263+
264+ if(!context.network().isColored()) {
265+ if(constantsList.isEmpty()) {
266+ return out;
267+ }
268+ out.append("%%Global box which contains global color types, variables and/or constants.\n");
269+ out.append("\\node [globalBox] (globalBox) at (current bounding box.north west) [anchor=south west] {");
270+ exportConstants(constantsList, out);
271+ out.append("};");
272+ return out;
273+ }
274+
275+ if((listColorTypes.isEmpty() && constantsList.isEmpty() && variableList.isEmpty()))
276+ return out;
277+
278+ out.append("%%Global box which contains global color types, variables and/or constants.\n");
279+ out.append("\\node [globalBox] (globalBox) at (current bounding box.north west) [anchor=south west] {");
280+
281+ exportColorTypes(listColorTypes, out);
282+
283+ if(listColorTypes.size() > 0 && (variableList.size() > 0 || constantsList.size() > 0)) {
284+ out.append("\\\\");
285+ }
286+
287+ exportVariables(variableList, out);
288+
289+ if(variableList.size() > 0 && !constantsList.isEmpty()) {
290+ out.append("\\\\");
291+ }
292+
293+ exportConstants(constantsList, out);
294+
295+ out.append("};");
296+
297+ return out;
298+ }
299+
300+ private void exportColorTypes(List<ColorType> listColorTypes, StringBuffer out) {
301+ String stringColorList = "";
302+ for(int i = 0; i < listColorTypes.size(); i++) {
303+ if(i == 0) {
304+ out.append("Color Types:\\\\");
305+ }
306+ out.append("$\\mathit{" + listColorTypes.get(i).getName() + "}$ \\textbf{is} ");
307+
308+ if(listColorTypes.get(i).isProductColorType()) {
309+ out.append("$\\mathit{<");
310+ for(int x = 0; x < listColorTypes.get(i).getProductColorTypes().size(); x++) {
311+ stringColorList += listColorTypes.get(i).getProductColorTypes().get(x).getName().replace("_", "\\_");
312+
313+ if(x != listColorTypes.get(i).getProductColorTypes().size() - 1){
314+ stringColorList += ", ";
315+ }
316+ }
317+ out.append(stringColorList + ">}$\\\\");
318+ stringColorList = "";
319+
320+ } else if(listColorTypes.get(i).isIntegerRange()) {
321+ out.append("$\\mathit{");
322+ if(listColorTypes.get(i).size() > 1) {
323+ int listSize = listColorTypes.get(i).size();
324+ out.append("[" + listColorTypes.get(i).getColors().get(0).getColorName().replace("_","\\_") + ".." + listColorTypes.get(i).getColors().get(listSize - 1).getColorName().replace("_","\\_") + "]");
325+ } else {
326+ out.append("[" + listColorTypes.get(i).getFirstColor().getColorName().replace("_","\\_") + "]");
327+ }
328+ out.append("}$\\\\");
329+
330+ } else {
331+ out.append("$\\mathit{[");
332+ for(int x = 0; x < listColorTypes.get(i).getColors().size(); x++) {
333+ stringColorList += listColorTypes.get(i).getColors().get(x).getName().replace("_","\\_");
334+
335+ if(x != listColorTypes.get(i).getColors().size() - 1){
336+ stringColorList += ", ";
337+ }
338+ }
339+ out.append(stringColorList + "]}$\\\\");
340+ stringColorList = "";
341+ }
342+ }
343+ }
344+
345+ private void exportVariables(List<Variable> variableList, StringBuffer out) {
346+ String result = "";
347+ for(int i = 0; i < variableList.size(); i++) {
348+ if (i == 0) {
349+ result += "Variables:\\\\ ";
350+ }
351+ result += "$\\mathit{" + variableList.get(i).getName().replace("_","\\_") + " \\textbf{ in } " + variableList.get(i).getColorType().getName().replace("_","\\_") + "}$";
352+ if(i != variableList.size() - 1) {
353+ result += "\\\\";
354+ }
355+ }
356+ out.append(result);
357+ }
358+
359+ private void exportConstants(List<Constant> constantsList, StringBuffer out) {
360+ String result = "";
361+
362+ for(int i = 0; i < constantsList.size(); i++) {
363+ if(i == 0) {
364+ result += "Constants:\\\\";
365+ }
366+ result += "$\\mathit{" + constantsList.get(i).toString().replace("_","\\_") + "}$";
367+ if(i != constantsList.size() - 1) {
368+ result += "\\\\";
369+ }
370+ }
371+ out.append(result);
372+ }
373+
374 protected String getTokenListStringFor(Place place) {
375 List<TimedToken> tokens = ((TimedPlaceComponent) place).underlyingPlace().tokens();
376
377@@ -455,7 +531,7 @@
378 String invariant = "";
379
380 if (!((TimedPlaceComponent) place).getInvariantAsString().contains("inf"))
381- invariant = "$\\mathrm{" + replaceWithMathLatex(((TimedPlaceComponent) place).getInvariantAsString()) + "}$};\n";
382+ invariant = replaceWithMathLatex(((TimedPlaceComponent) place).getInvariantAsString()) + "};\n";
383 return invariant;
384 }
385
386@@ -480,12 +556,14 @@
387 StringBuffer out = new StringBuffer();
388
389 out.append("\\begin{tikzpicture}[font=\\scriptsize, xscale=0.45, yscale=0.45, x=1.33pt, y=1.33pt]\n");
390- out.append("%% the figure can be scaled by changing xscale and yscale\n");
391+ out.append("%% the figure can be scaled by changing xscale and yscale or the size of the x- and y-coordinates\n");
392 out.append("%% positions of place/transition labels that are currently fixed to label=135 degrees\n");
393- out.append("%% can be adjusted so that they do not cover arcs\n");
394- out.append("%% similarly the curving of arcs can be done by adjusting bend left/right=XX\n");
395- out.append("%% labels may be slightly skewed compared to the tapaal drawing due to rounding.\n");
396- out.append("%% This can be adjusted by tuning the coordinates of the label\n");
397+ out.append("%% these can be adjusted by adjusting either the coordinates, the label distance or the label degree\n");
398+ out.append("%% that is placed right after the 'label-distance'. 90: is above (default), 180 is left, 270 is below etc.\n");
399+ out.append("%% The curving of arcs can be done by adjusting bend left/right=XX\n");
400+ out.append("%% labels may be slightly skewed compared to the Tapaal drawing due to rounding.\n");
401+ out.append("%% This can be adjusted by tuning the coordinates of the label, or the degree (see above)\n");
402+ out.append("%% The box containing global variables can also be moved by adjusting the anchor points / bounding box in the [globalBox] node at the end of the Tikz document\n");
403 out.append("\\tikzstyle{arc}=[->,>=stealth,thick]\n");
404
405 out.append("\\tikzstyle{transportArc}=[->,>=diamond,thick]\n");
406@@ -496,39 +574,24 @@
407 out.append("\\tikzstyle{every token}=[fill=white,text=black]\n");
408 out.append("\\tikzstyle{sharedplace}=[place,minimum size=7.5mm,dashed,thin]\n");
409 out.append("\\tikzstyle{sharedtransition}=[transition, fill opacity=0, minimum width=3.5mm, minimum height=6.5mm,dashed]\n");
410- out.append("\\tikzstyle{urgenttransition}=[place,fill=white,minimum size=2.0mm,thin]");
411- out.append("\\tikzstyle{uncontrollabletransition}=[transition,fill=white,draw=black,very thick]");
412+ out.append("\\tikzstyle{urgenttransition}=[place,fill=white,minimum size=2.0mm,thin]\n");
413+ out.append("\\tikzstyle{uncontrollabletransition}=[transition,fill=white,draw=black,very thick]\n");
414+ out.append("\\tikzstyle{globalBox} = [draw,thick,align=left]");
415 return out;
416 }
417
418 protected String replaceWithMathLatex(String text) {
419- return text.replace("inf", "\\infty").replace("<=", "\\leq ").replace("*", "\\cdot ");
420- }
421-
422- private String exportMathName(String name) {
423- StringBuilder out = new StringBuilder("$\\mathrm{");
424- int subscripts = 0;
425- for (int i = 0; i < name.length() - 1; i++) {
426- char c = name.charAt(i);
427- if (c == '_') {
428- out.append("_{");
429- subscripts++;
430- } else {
431- out.append(c);
432- }
433- }
434-
435- char last = name.charAt(name.length() - 1);
436- if (last == '_') {
437- out.append("\\_");
438- } else
439- out.append(last);
440-
441- for (int i = 0; i < subscripts; i++) {
442- out.append('}');
443- }
444- out.append("}$");
445- return out.toString();
446- }
447-
448+ String[] stringList = text.split(" ");
449+ String result = "";
450+
451+ for(int i = 0; i < stringList.length; i++) {
452+ result += "$\\mathit{" + replaceSpecialSymbols(stringList[i]) + "}$ ";
453+ }
454+ return result;
455+ }
456+
457+ protected String replaceSpecialSymbols(String text) {
458+ return text.replace("inf", "\\infty").replace("<=", "\\leq").replace("*", "\\cdot")
459+ .replace("\u2192", "\\rightarrow").replace("\u221E", "\\infty");
460+ }
461 }

Subscribers

People subscribed via source and target branches

to all changes: