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: 411 lines (+204/-98)
1 file modified
src/net/tapaal/export/TikZExporter.java (+204/-98)
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+415332@code.launchpad.net

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

Commit message

Added TikZ support for colored nets.
Added a framed box to the Tikz output for global variables/constants/color types.

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.

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

Removed subscripting from place- and transition names, and changed \mathrm to \mathit

1573. By Kristian Morsing Pedersen <email address hidden>

Added new adjustment options for labels on arcs, places and transitions

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
=== modified file 'src/net/tapaal/export/TikZExporter.java'
--- src/net/tapaal/export/TikZExporter.java 2022-01-07 17:05:54 +0000
+++ src/net/tapaal/export/TikZExporter.java 2022-02-09 20:32:33 +0000
@@ -3,22 +3,27 @@
3import java.io.FileWriter;3import java.io.FileWriter;
4import java.io.IOException;4import java.io.IOException;
5import java.io.PrintWriter;5import java.io.PrintWriter;
6import java.util.List;6import java.util.*;
7import java.util.stream.Collectors;
78
9import dk.aau.cs.model.CPN.Color;
10import dk.aau.cs.model.CPN.ColorType;
11import dk.aau.cs.model.CPN.Variable;
12import dk.aau.cs.model.tapn.Constant;
8import dk.aau.cs.model.tapn.TimedToken;13import dk.aau.cs.model.tapn.TimedToken;
914
15import net.tapaal.gui.petrinet.Context;
10import pipe.gui.petrinet.dataLayer.DataLayer;16import pipe.gui.petrinet.dataLayer.DataLayer;
11import pipe.gui.TAPAALGUI;17import pipe.gui.TAPAALGUI;
12import pipe.gui.petrinet.graphicElements.Arc;18import pipe.gui.petrinet.graphicElements.*;
13import pipe.gui.petrinet.graphicElements.ArcPathPoint;
14import pipe.gui.petrinet.graphicElements.Place;
15import pipe.gui.petrinet.graphicElements.Transition;
16import pipe.gui.petrinet.graphicElements.tapn.TimedInhibitorArcComponent;19import pipe.gui.petrinet.graphicElements.tapn.TimedInhibitorArcComponent;
17import pipe.gui.petrinet.graphicElements.tapn.TimedInputArcComponent;20import pipe.gui.petrinet.graphicElements.tapn.TimedInputArcComponent;
18import pipe.gui.petrinet.graphicElements.tapn.TimedPlaceComponent;21import pipe.gui.petrinet.graphicElements.tapn.TimedPlaceComponent;
19import pipe.gui.petrinet.graphicElements.tapn.TimedTransitionComponent;22import pipe.gui.petrinet.graphicElements.tapn.TimedTransitionComponent;
20import pipe.gui.petrinet.graphicElements.tapn.TimedTransportArcComponent;23import pipe.gui.petrinet.graphicElements.tapn.TimedTransportArcComponent;
2124
25import static java.util.stream.Collectors.toList;
26
22public class TikZExporter {27public class TikZExporter {
2328
24 public enum TikZOutputOption {29 public enum TikZOutputOption {
@@ -45,7 +50,7 @@
45 if (option == TikZOutputOption.FULL_LATEX) {50 if (option == TikZOutputOption.FULL_LATEX) {
46 out.println("\\documentclass[a4paper]{article}");51 out.println("\\documentclass[a4paper]{article}");
47 out.println("\\usepackage{tikz}");52 out.println("\\usepackage{tikz}");
48 out.println("\\usetikzlibrary{petri,arrows}");53 out.println("\\usetikzlibrary{petri,arrows,positioning}");
49 out.println("\\usepackage{amstext}");54 out.println("\\usepackage{amstext}");
50 out.println();55 out.println();
51 out.println("\\begin{document}");56 out.println("\\begin{document}");
@@ -62,6 +67,8 @@
62 out.print(exportTransitions(net.getTransitions()));67 out.print(exportTransitions(net.getTransitions()));
63 out.print(exportArcs(net.getArcs()));68 out.print(exportArcs(net.getArcs()));
6469
70 out.println(exportGlobalVariables());
71
65 out.println("\\end{tikzpicture}");72 out.println("\\end{tikzpicture}");
66 if (option == TikZOutputOption.FULL_LATEX) {73 if (option == TikZOutputOption.FULL_LATEX) {
67 out.println("\\end{document}");74 out.println("\\end{document}");
@@ -144,48 +151,22 @@
144151
145 protected String getArcLabels(Arc arc) {152 protected String getArcLabels(Arc arc) {
146 String arcLabel = "";153 String arcLabel = "";
147 String arcLabelPositionString = "\\draw (" + (arc.getNameLabel().getX()) + "," + (arc.getNameLabel().getY())*(-1) + ") node {";154 String arcLabelPositionString = "\\draw (" + (arc.getArcPath().midPoint.getX()) + "," + (arc.getNameLabel().getY())*(-1) + ") node[align=left,xshift=0pt,yshift=0pt] {";
148155
149 if (arc instanceof TimedInputArcComponent) {156 if(!arc.getNameLabel().getText().isEmpty()) {
150 if (!(arc.getSource() instanceof TimedTransitionComponent)) {157 arcLabel += arcLabelPositionString;
151 arcLabel = arcLabelPositionString;158 arcLabel += "\\\\" + handleNameLabel(arc.getNameLabel().getText()) + "";
152 if (arc.getWeight().value() > 1) {159 }
153 arcLabel += "$" + arc.getWeight().value() + "\\times$\\ ";160
154 }161 if(!arcLabel.isEmpty()) {
155162 arcLabel += "};\n";
156 if(TAPAALGUI.getApp().getCurrentTab().getLens().isTimed()) {163 } else {
157 arcLabel += "$\\mathrm{" + replaceWithMathLatex(getGuardAsStringIfNotHidden((TimedInputArcComponent) arc)) + "}$";164 arcLabel += "{};\n";
158 if (arc instanceof TimedTransportArcComponent)165 }
159 arcLabel += ":" + ((TimedTransportArcComponent) arc).getGroupNr();166
160 arcLabel += "};\n";
161 } else {
162 arcLabel += "};\n";
163 }
164
165 } else {
166 arcLabel = arcLabelPositionString;
167 if (arc.getWeight().value() > 1) {
168 arcLabel += "$" + arc.getWeight().value() + "\\times$\\ ";
169 }
170 arcLabel += ":" + ((TimedTransportArcComponent) arc).getGroupNr() + "};\n";
171 }
172
173 } else {
174 if (arc.getWeight().value() > 1) {
175 arcLabel += arcLabelPositionString + "$" + arc.getWeight().value() + "\\times$\\ };\n";
176 }
177 }
178 return arcLabel;167 return arcLabel;
179 }168 }
180169
181 private String getGuardAsStringIfNotHidden(TimedInputArcComponent arc) {
182 if (!TAPAALGUI.getApp().showZeroToInfinityIntervals() && arc.getGuardAsString().equals("[0,inf)")){
183 return "";
184 } else {
185 return arc.getGuardAsString();
186 }
187 }
188
189 private StringBuffer exportTransitions(Transition[] transitions) {170 private StringBuffer exportTransitions(Transition[] transitions) {
190 StringBuffer out = new StringBuffer();171 StringBuffer out = new StringBuffer();
191 for (Transition trans : transitions) {172 for (Transition trans : transitions) {
@@ -234,9 +215,10 @@
234 out.append("%% label for transition " + trans.getName() + "\n");215 out.append("%% label for transition " + trans.getName() + "\n");
235 out.append("\\draw (");216 out.append("\\draw (");
236 out.append(trans.getNameLabel().getX() + xOffset + "," + (trans.getNameLabel().getY() * -1) + ")");217 out.append(trans.getNameLabel().getX() + xOffset + "," + (trans.getNameLabel().getY() * -1) + ")");
237 out.append(" node ");218 out.append(" node[align=left,xshift=0pt,yshift=0pt]");
238 out.append(" {");219 out.append(" {");
239 out.append(exportMathName(trans.getName()));220 out.append("$\\mathit{" + (trans.getName().replace("_","\\_")) + "}$");
221 out.append(handleNameLabel(trans.getNameLabel().getText()));
240 out.append("};\n");222 out.append("};\n");
241 } 223 }
242 }224 }
@@ -247,7 +229,7 @@
247 StringBuffer out = new StringBuffer();229 StringBuffer out = new StringBuffer();
248230
249 for (Place place : places) {231 for (Place place : places) {
250 String invariant = getPlaceInvariantString(place);232 String invariant = "$" + getPlaceInvariantString(place) + "$";
251 String tokensInPlace = getTokenListStringFor(place);233 String tokensInPlace = getTokenListStringFor(place);
252234
253 out.append("\\node[place");235 out.append("\\node[place");
@@ -269,30 +251,58 @@
269 if (place.getAttributesVisible() || !invariant.equals("")){251 if (place.getAttributesVisible() || !invariant.equals("")){
270 boolean isLabelAbovePlace = place.getY() > place.getNameLabel().getY();252 boolean isLabelAbovePlace = place.getY() > place.getNameLabel().getY();
271 boolean isLabelBehindPlace = place.getX() < place.getNameLabel().getX();253 boolean isLabelBehindPlace = place.getX() < place.getNameLabel().getX();
272 double xOffset = place.getName().length() > 6 && !isLabelAbovePlace && !isLabelBehindPlace ? place.getLayerOffset() : 0;254 int longestString = 0;
273 double yOffset = isLabelAbovePlace ? (place.getNameLabel().getHeight() / 2) : 0;255 List<String> listStringNameLabel = place.getNameLabel().getText().lines().collect(toList());
256 for(int i = 0; i < listStringNameLabel.size(); i++) {
257 if(listStringNameLabel.get(i).length() > longestString) {
258 longestString = listStringNameLabel.get(i).length();
259 }
260 }
261 double xOffset = longestString > 8 && !isLabelAbovePlace && !isLabelBehindPlace ? place.getLayerOffset() : 0;
262 double yOffset = place.getNameLabel().getText().lines().count() * 5;
263
264 String nameLabel = place.getNameLabel().getText();
274265
275 out.append("%% label for place " + place.getName() + "\n");266 out.append("%% label for place " + place.getName() + "\n");
276 out.append("\\draw (");267 out.append("\\draw (");
277 out.append((place.getNameLabel().getX() + xOffset) + "," + ((place.getNameLabel().getY() * -1) + yOffset) +")");268 out.append((place.getNameLabel().getX() + xOffset) + "," + ((place.getNameLabel().getY() + yOffset) * -1) +")");
278 out.append(" node[align=left] ");269 out.append(" node[align=left,xshift=0pt,yshift=0pt] ");
279 out.append("{");270 out.append("{");
280 if(place.getAttributesVisible())271 if(place.getAttributesVisible()) {
281 out.append(exportMathName(place.getName())); 272 out.append("$\\mathit{" + (place.getName().replace("_","\\_")) + "}$");
282 if(!invariant.equals("")) {273 if (!place.getNameLabel().getText().isEmpty()) {
283 if((place.getAttributesVisible()))274 out.append(handleNameLabel(nameLabel));
284 out.append("\\\\");275 }
285 out.append(invariant);276 }
286 }else {277 out.append("};\n");
287 out.append("};\n");
288 }
289
290 }278 }
291 }279 }
292
293 return out;280 return out;
294 }281 }
295282
283 private String handleNameLabel(String nameLabel) {
284 String nameLabelsString = "";
285 String[] labelsInName = nameLabel.split("\n");
286 for(int i = 0; i < labelsInName.length; i++) {
287
288 if(labelsInName[i].contains("[")) {
289 nameLabelsString += escapeSpacesInAndOrNot(replaceWithMathLatex(labelsInName[i]));
290 nameLabelsString += "\\\\";
291 }
292 else if(!labelsInName[i].isEmpty()){
293 nameLabelsString += escapeSpacesInAndOrNot(replaceWithMathLatex(labelsInName[i]));
294 nameLabelsString += "\\\\";
295 } else {
296 nameLabelsString += "\\\\";
297 }
298 }
299 return nameLabelsString;
300 }
301
302 private String escapeSpacesInAndOrNot(String str) {
303 return str.replace(" and ", "\\ and\\ ").replace(" or", "\\ or\\ ").replace(" not", "\\ not\\ ");
304 }
305
296 private void exportPlaceTokens(Place place, StringBuffer out, int numOfTokens) {306 private void exportPlaceTokens(Place place, StringBuffer out, int numOfTokens) {
297 // Dot radius307 // Dot radius
298 final double tRadius = 1;308 final double tRadius = 1;
@@ -437,6 +447,116 @@
437 }447 }
438 }448 }
439449
450 private StringBuffer exportGlobalVariables() {
451 StringBuffer out = new StringBuffer();
452
453 Context context = new Context(TAPAALGUI.getCurrentTab());
454 List<ColorType> listColorTypes = context.network().colorTypes();
455 List<Constant> constantsList = new ArrayList<>(context.network().constants());
456 List<Variable> variableList = context.network().variables();
457
458 if(!context.network().isColored() || (listColorTypes.isEmpty() && constantsList.isEmpty() && variableList.isEmpty())) {
459 out.append("\\node [globalBox] (globalBox) at (current bounding box.north west) [anchor=south west] {");
460 exportConstants(constantsList, out);
461 out.append("};");
462 return out;
463 }
464
465 out.append("\\node [globalBox] (globalBox) at (current bounding box.north west) [anchor=south west] {");
466
467 exportColorTypes(listColorTypes, out);
468
469 if(listColorTypes.size() > 0 && (variableList.size() > 0 || constantsList.size() > 0)) {
470 out.append("\\\\");
471 }
472
473 exportVariables(variableList, out);
474
475 if(variableList.size() > 0 && !constantsList.isEmpty()) {
476 out.append("\\\\");
477 }
478
479 exportConstants(constantsList, out);
480
481 out.append("};");
482
483 return out;
484 }
485
486 private void exportColorTypes(List<ColorType> listColorTypes, StringBuffer out) {
487 String stringColorList = "";
488 for(int i = 0; i < listColorTypes.size(); i++) {
489 if(i == 0) {
490 out.append("Color Types:\\\\");
491 }
492 out.append("$\\mathit{" + listColorTypes.get(i).getName() + "}$ \\textbf{is} ");
493
494 if(listColorTypes.get(i).isProductColorType()) {
495 out.append("$\\mathit{<");
496 for(int x = 0; x < listColorTypes.get(i).getProductColorTypes().size(); x++) {
497 stringColorList += listColorTypes.get(i).getProductColorTypes().get(x).getName().replace("_", "\\_");
498
499 if(x != listColorTypes.get(i).getProductColorTypes().size() - 1){
500 stringColorList += ", ";
501 }
502 }
503 out.append(stringColorList + ">}$\\\\");
504 stringColorList = "";
505
506 } else if(listColorTypes.get(i).isIntegerRange()) {
507 out.append("$\\mathit{");
508 if(listColorTypes.get(i).size() > 1) {
509 int listSize = listColorTypes.get(i).size();
510 out.append("[" + listColorTypes.get(i).getColors().get(0).getColorName().replace("_","\\_") + ".." + listColorTypes.get(i).getColors().get(listSize - 1).getColorName().replace("_","\\_") + "]");
511 } else {
512 out.append("[" + listColorTypes.get(i).getFirstColor().getColorName().replace("_","\\_") + "]");
513 }
514 out.append("}$\\\\");
515
516 } else {
517 out.append("$\\mathit{[");
518 for(int x = 0; x < listColorTypes.get(i).getColors().size(); x++) {
519 stringColorList += listColorTypes.get(i).getColors().get(x).getName().replace("_","\\_");
520
521 if(x != listColorTypes.get(i).getColors().size() - 1){
522 stringColorList += ", ";
523 }
524 }
525 out.append(stringColorList + "]}$\\\\");
526 stringColorList = "";
527 }
528 }
529 }
530
531 private void exportVariables(List<Variable> variableList, StringBuffer out) {
532 String result = "";
533 for(int i = 0; i < variableList.size(); i++) {
534 if (i == 0) {
535 result += "Variables:\\\\ ";
536 }
537 result += "$\\mathit{" + variableList.get(i).getName().replace("_","\\_") + " \\textbf{ in } " + variableList.get(i).getColorType().getName().replace("_","\\_") + "}$";
538 if(i != variableList.size() - 1) {
539 result += "\\\\";
540 }
541 }
542 out.append(result);
543 }
544
545 private void exportConstants(List<Constant> constantsList, StringBuffer out) {
546 String result = "";
547
548 for(int i = 0; i < constantsList.size(); i++) {
549 if(i == 0) {
550 result += "Constants:\\\\";
551 }
552 result += "$\\mathit{" + constantsList.get(i).toString().replace("_","\\_") + "}$";
553 if(i != constantsList.size() - 1) {
554 result += "\\\\";
555 }
556 }
557 out.append(result);
558 }
559
440 protected String getTokenListStringFor(Place place) {560 protected String getTokenListStringFor(Place place) {
441 List<TimedToken> tokens = ((TimedPlaceComponent) place).underlyingPlace().tokens();561 List<TimedToken> tokens = ((TimedPlaceComponent) place).underlyingPlace().tokens();
442562
@@ -455,7 +575,7 @@
455 String invariant = "";575 String invariant = "";
456576
457 if (!((TimedPlaceComponent) place).getInvariantAsString().contains("inf"))577 if (!((TimedPlaceComponent) place).getInvariantAsString().contains("inf"))
458 invariant = "$\\mathrm{" + replaceWithMathLatex(((TimedPlaceComponent) place).getInvariantAsString()) + "}$};\n";578 invariant = replaceWithMathLatex(((TimedPlaceComponent) place).getInvariantAsString()) + "};\n";
459 return invariant;579 return invariant;
460 }580 }
461581
@@ -480,12 +600,13 @@
480 StringBuffer out = new StringBuffer();600 StringBuffer out = new StringBuffer();
481601
482 out.append("\\begin{tikzpicture}[font=\\scriptsize, xscale=0.45, yscale=0.45, x=1.33pt, y=1.33pt]\n");602 out.append("\\begin{tikzpicture}[font=\\scriptsize, xscale=0.45, yscale=0.45, x=1.33pt, y=1.33pt]\n");
483 out.append("%% the figure can be scaled by changing xscale and yscale\n");603 out.append("%% the figure can be scaled by changing xscale and yscale or the size of the x- and y-coordinates\n");
484 out.append("%% positions of place/transition labels that are currently fixed to label=135 degrees\n");604 out.append("%% positions of place/transition labels that are currently fixed to label=135 degrees\n");
485 out.append("%% can be adjusted so that they do not cover arcs\n");605 out.append("%% can be adjusted so that they do not cover arcs\n");
486 out.append("%% similarly the curving of arcs can be done by adjusting bend left/right=XX\n");606 out.append("%% similarly the curving of arcs can be done by adjusting bend left/right=XX\n");
487 out.append("%% labels may be slightly skewed compared to the tapaal drawing due to rounding.\n");607 out.append("%% labels may be slightly skewed compared to the Tapaal drawing due to rounding.\n");
488 out.append("%% This can be adjusted by tuning the coordinates of the label\n");608 out.append("%% This can be adjusted by tuning the coordinates of the label or adjusting the x- and y-shift for the label\n");
609 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");
489 out.append("\\tikzstyle{arc}=[->,>=stealth,thick]\n");610 out.append("\\tikzstyle{arc}=[->,>=stealth,thick]\n");
490611
491 out.append("\\tikzstyle{transportArc}=[->,>=diamond,thick]\n");612 out.append("\\tikzstyle{transportArc}=[->,>=diamond,thick]\n");
@@ -496,39 +617,24 @@
496 out.append("\\tikzstyle{every token}=[fill=white,text=black]\n");617 out.append("\\tikzstyle{every token}=[fill=white,text=black]\n");
497 out.append("\\tikzstyle{sharedplace}=[place,minimum size=7.5mm,dashed,thin]\n");618 out.append("\\tikzstyle{sharedplace}=[place,minimum size=7.5mm,dashed,thin]\n");
498 out.append("\\tikzstyle{sharedtransition}=[transition, fill opacity=0, minimum width=3.5mm, minimum height=6.5mm,dashed]\n");619 out.append("\\tikzstyle{sharedtransition}=[transition, fill opacity=0, minimum width=3.5mm, minimum height=6.5mm,dashed]\n");
499 out.append("\\tikzstyle{urgenttransition}=[place,fill=white,minimum size=2.0mm,thin]");620 out.append("\\tikzstyle{urgenttransition}=[place,fill=white,minimum size=2.0mm,thin]\n");
500 out.append("\\tikzstyle{uncontrollabletransition}=[transition,fill=white,draw=black,very thick]");621 out.append("\\tikzstyle{uncontrollabletransition}=[transition,fill=white,draw=black,very thick]\n");
622 out.append("\\tikzstyle{globalBox} = [draw,thick,align=left]");
501 return out;623 return out;
502 }624 }
503625
504 protected String replaceWithMathLatex(String text) {626 protected String replaceWithMathLatex(String text) {
505 return text.replace("inf", "\\infty").replace("<=", "\\leq ").replace("*", "\\cdot ");627 String[] stringList = text.split(" ");
506 }628 String result = "";
507629
508 private String exportMathName(String name) {630 for(int i = 0; i < stringList.length; i++) {
509 StringBuilder out = new StringBuilder("$\\mathrm{");631 result += "$\\mathit{" + replaceSpecialSymbols(stringList[i]) + "}$ ";
510 int subscripts = 0;632 }
511 for (int i = 0; i < name.length() - 1; i++) {633 return result;
512 char c = name.charAt(i);634 }
513 if (c == '_') {635
514 out.append("_{");636 protected String replaceSpecialSymbols(String text) {
515 subscripts++;637 return text.replace("inf", "\\infty").replace("<=", "\\leq").replace("*", "\\cdot")
516 } else {638 .replace("\u2192", "\\rightarrow").replace("\u221E", "\\infty");
517 out.append(c);639 }
518 }
519 }
520
521 char last = name.charAt(name.length() - 1);
522 if (last == '_') {
523 out.append("\\_");
524 } else
525 out.append(last);
526
527 for (int i = 0; i < subscripts; i++) {
528 out.append('}');
529 }
530 out.append("}$");
531 return out.toString();
532 }
533
534}640}

Subscribers

People subscribed via source and target branches

to all changes: