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 Needs Fixing
Kenneth Yrke Jørgensen code Pending
Review via email: mp+415854@code.launchpad.net

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

This proposal has been superseded by a proposal from 2022-03-06.

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
Merged with cpn-gui-dev

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.
Revision history for this message
Kenneth Yrke Jørgensen (yrke) : Posted in a previous version of this proposal
review: Approve (code)
Revision history for this message
Jiri Srba (srba) wrote : Posted in a previous version of this proposal

It would be nice if instead of (in referendum colored timed):

1′v[1, 2]Voters1 → [1, 4]

one would print:

1′v
[1, 2]
Voters1 → [1, 4]

(on three sepratate lines).

review: Needs Fixing
Revision history for this message
Jiri Srba (srba) wrote :

Please, set the default position for arc lables to pos=0.5

review: Needs Fixing
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-02-21 19:46:59 +0000
3+++ src/net/tapaal/export/TikZExporter.java 2022-03-06 10:50:31 +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.5] (");
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,align=left]");
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.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.getAppGui().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: