Merge lp:~tapaal-contributor/tapaal/fix-tikz-export-1945642 into lp:tapaal

Proposed by Kristian Morsing Pedersen
Status: Superseded
Proposed branch: lp:~tapaal-contributor/tapaal/fix-tikz-export-1945642
Merge into: lp:tapaal
Diff against target: 403 lines (+224/-47)
1 file modified
src/pipe/gui/TikZExporter.java (+224/-47)
To merge this branch: bzr merge lp:~tapaal-contributor/tapaal/fix-tikz-export-1945642
Reviewer Review Type Date Requested Status
Jiri Srba Pending
Review via email: mp+410240@code.launchpad.net

This proposal supersedes a proposal from 2021-10-10.

This proposal has been superseded by a proposal from 2021-10-14.

Commit message

Improved quality of Tikz export and various fixes

Description of the change

1. Fixed transition rotation
2. Added support for dots (replaces marking #1-5 with dots, like in the GUI)
3. Now correctly shows a place's marking (#1-2) like in the GUI
4. Improved location of place labels
5. Improved location of transition labels
6. Improved location of arc labels
7. Improved scaling so that some nets are no longer 'squished' together
8. Now currecly exports curved arcs

Other comments:
In some nets, labels for places, transitions and arcs are not positioned optimally like in the GUI. It has been difficult to find a solution to this, as some ways works for some of the nets while making other nets looks significantly worse. I'm not sure why this is. I have a suspicion it is due to the X- and Y coordinates of the labels somehow not being correct, or due to some other unintentional sideeffects. I have tried a lot of different ways to place these labels as close as possible, and have settled on the current result.

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

Now correctly show transition rotations for 45 degree angles

1157. By <email address hidden>

merged with trunk

1158. By Kristian Morsing Pedersen <email address hidden>

Changed unit from px to pt

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/pipe/gui/TikZExporter.java'
--- src/pipe/gui/TikZExporter.java 2020-08-04 08:19:44 +0000
+++ src/pipe/gui/TikZExporter.java 2021-10-14 20:24:42 +0000
@@ -27,11 +27,6 @@
27 private final DataLayer net;27 private final DataLayer net;
28 private final String fullpath;28 private final String fullpath;
29 private final TikZOutputOption option;29 private final TikZOutputOption option;
30 private final double scale = 1.0 / 55.0;
31
32 private double RoundCoordinate(double position) {
33 return Math.round(position * scale * 10)/10.0d;
34 }
3530
36 public TikZExporter(DataLayer net, String fullpath, TikZOutputOption option) {31 public TikZExporter(DataLayer net, String fullpath, TikZOutputOption option) {
37 this.net = net;32 this.net = net;
@@ -75,37 +70,44 @@
75 } catch (IOException e) {70 } catch (IOException e) {
7671
77 } finally {72 } finally {
78 if (out != null)73 if (out != null) {
79 out.close();74 out.close();
80 if (outFile != null)75 }
81 try {76 if (outFile != null) {
82 outFile.close();77 try {
83 } catch (IOException e2) {78 outFile.close();
79 } catch (IOException e2) {
8480
85 }81 }
82 }
86 }83 }
87 }84 }
8885
89 private StringBuffer exportArcs(Arc[] arcs) {86 private StringBuffer exportArcs(Arc[] arcs) {
90 StringBuffer out = new StringBuffer();87 StringBuffer out = new StringBuffer();
88
91 for (Arc arc : arcs) {89 for (Arc arc : arcs) {
92 String arcPoints = "";90 String arcPoints = "";
91
93 for (int i = 1; i < arc.getArcPath().getEndIndex(); i++) {92 for (int i = 1; i < arc.getArcPath().getEndIndex(); i++) {
94 ArcPathPoint point = arc.getArcPath().getArcPathPoint(i);93 ArcPathPoint currentPoint = arc.getArcPath().getArcPathPoint(i);
95 arcPoints += "to[bend right=0] (" + RoundCoordinate(point.getX()) + "," + RoundCoordinate(point.getY() * (-1)) + ") ";94
96 }95 if(currentPoint.getPointType() == ArcPathPoint.STRAIGHT) {
9796 arcPoints += "to[bend right=0] (" + (currentPoint.getX()) + "," + (currentPoint.getY() * (-1)) + ") ";
98 String arrowType = "";97 } else if (currentPoint.getPointType() == ArcPathPoint.CURVED) {
99 if (arc instanceof TimedInhibitorArcComponent) {98 double xCtrl1 = Math.round(currentPoint.getControl1().getX());
100 arrowType = "inhibArc";99 double yCtrl1 = Math.round(currentPoint.getControl1().getY() * (-1));
101 } else if (arc instanceof TimedTransportArcComponent) {100 double xCtrl2 = Math.round(currentPoint.getControl2().getX());
102 arrowType = "transportArc";101 double yCtrl2 = Math.round(currentPoint.getControl2().getY() * (-1));
103 } else if (arc instanceof TimedInputArcComponent) {102
104 arrowType = "arc";103 arcPoints += " .. controls(" + xCtrl1 + "," + yCtrl1 + ")";
105 } else {104 arcPoints += " and ";
106 arrowType = "arc";105 arcPoints += "(" + xCtrl2 + "," + yCtrl2 + ") .. ";
107 }106 arcPoints += "(" + currentPoint.getX() + "," + currentPoint.getY() * (-1) + ") ";
108107 }
108 }
109
110 String arrowType = getArcArrowType(arc);
109 String arcLabel = getArcLabels(arc);111 String arcLabel = getArcLabels(arc);
110112
111 out.append("\\draw[");113 out.append("\\draw[");
@@ -115,7 +117,6 @@
115 out.append(") ");117 out.append(") ");
116 out.append(arcPoints);118 out.append(arcPoints);
117 out.append("to[bend right=0]");119 out.append("to[bend right=0]");
118 //out.append(arcLabel);
119 out.append(" (");120 out.append(" (");
120 out.append(arc.getTarget().getId());121 out.append(arc.getTarget().getId());
121 out.append(") {};\n");122 out.append(") {};\n");
@@ -126,9 +127,23 @@
126 return out;127 return out;
127 }128 }
128129
130 private String getArcArrowType(Arc arc) {
131 String arrowType = "";
132 if (arc instanceof TimedInhibitorArcComponent) {
133 arrowType = "inhibArc";
134 } else if (arc instanceof TimedTransportArcComponent) {
135 arrowType = "transportArc";
136 } else if (arc instanceof TimedInputArcComponent) {
137 arrowType = "arc";
138 } else {
139 arrowType = "arc";
140 }
141 return arrowType;
142 }
143
129 protected String getArcLabels(Arc arc) {144 protected String getArcLabels(Arc arc) {
130 String arcLabel = "";145 String arcLabel = "";
131 String arcLabelPositionString = "\\draw (" + RoundCoordinate(arc.getNameLabel().getXPosition())+ "," + (RoundCoordinate(arc.getNameLabel().getYPosition())*(-1)) + ") node {";146 String arcLabelPositionString = "\\draw (" + (arc.getNameLabel().getX()) + "," + (arc.getNameLabel().getY())*(-1) + ") node {";
132147
133 if (arc instanceof TimedInputArcComponent) {148 if (arc instanceof TimedInputArcComponent) {
134 if (!(arc.getSource() instanceof TimedTransitionComponent)) {149 if (!(arc.getSource() instanceof TimedTransitionComponent)) {
@@ -136,10 +151,16 @@
136 if (arc.getWeight().value() > 1) {151 if (arc.getWeight().value() > 1) {
137 arcLabel += "$" + arc.getWeight().value() + "\\times$\\ ";152 arcLabel += "$" + arc.getWeight().value() + "\\times$\\ ";
138 }153 }
139 arcLabel += "$\\mathrm{" + replaceWithMathLatex(getGuardAsStringIfNotHidden((TimedInputArcComponent) arc)) + "}$";154
140 if (arc instanceof TimedTransportArcComponent)155 if(CreateGui.getApp().getCurrentTab().getLens().isTimed()) {
141 arcLabel += ":" + ((TimedTransportArcComponent) arc).getGroupNr();156 arcLabel += "$\\mathrm{" + replaceWithMathLatex(getGuardAsStringIfNotHidden((TimedInputArcComponent) arc)) + "}$";
142 arcLabel += "};\n";157 if (arc instanceof TimedTransportArcComponent)
158 arcLabel += ":" + ((TimedTransportArcComponent) arc).getGroupNr();
159 arcLabel += "};\n";
160 } else {
161 arcLabel += "};\n";
162 }
163
143 } else {164 } else {
144 arcLabel = arcLabelPositionString;165 arcLabel = arcLabelPositionString;
145 if (arc.getWeight().value() > 1) {166 if (arc.getWeight().value() > 1) {
@@ -147,16 +168,17 @@
147 }168 }
148 arcLabel += ":" + ((TimedTransportArcComponent) arc).getGroupNr() + "};\n";169 arcLabel += ":" + ((TimedTransportArcComponent) arc).getGroupNr() + "};\n";
149 }170 }
171
150 } else {172 } else {
151 if (arc.getWeight().value() > 1) {173 if (arc.getWeight().value() > 1) {
152 arcLabel += arcLabelPositionString + "$" + arc.getWeight().value() + "\\times$\\ };\n";174 arcLabel += arcLabelPositionString + "$" + arc.getWeight().value() + "\\times$\\ };\n";
153 }175 }
154 }176 }
155 return arcLabel;177 return arcLabel;
156 }178 }
157179
158 private String getGuardAsStringIfNotHidden(TimedInputArcComponent arc) {180 private String getGuardAsStringIfNotHidden(TimedInputArcComponent arc) {
159 if (!CreateGui.getApp().showZeroToInfinityIntervals() && arc.getGuardAsString().equals("[0,inf)")){181 if (!CreateGui.getApp().showZeroToInfinityIntervals() && arc.getGuardAsString().equals("[0,inf)")){
160 return "";182 return "";
161 } else {183 } else {
162 return arc.getGuardAsString();184 return arc.getGuardAsString();
@@ -168,14 +190,15 @@
168 for (Transition trans : transitions) {190 for (Transition trans : transitions) {
169 String angle = "";191 String angle = "";
170 if (trans.getAngle() != 0)192 if (trans.getAngle() != 0)
171 angle = ",rotate=" + (trans.getAngle() + 90);193 angle = ",rotate=-" + (trans.getAngle());
194
172195
173 out.append("\\node[transition");196 out.append("\\node[transition");
174 out.append(angle); 197 out.append(angle);
175 out.append("] at (");198 out.append("] at (");
176 out.append(RoundCoordinate(trans.getPositionX()));199 out.append((trans.getPositionX()));
177 out.append(',');200 out.append(',');
178 out.append(RoundCoordinate(trans.getPositionY() * (-1)));201 out.append((trans.getPositionY() * (-1)));
179 out.append(") (");202 out.append(") (");
180 out.append(trans.getId());203 out.append(trans.getId());
181 out.append(") {};\n");204 out.append(") {};\n");
@@ -203,9 +226,13 @@
203 out.append(".center) { };\n");226 out.append(".center) { };\n");
204 }227 }
205 if (trans.getAttributesVisible()){228 if (trans.getAttributesVisible()){
229 boolean isLabelAboveTransition = trans.getY() > trans.getNameLabel().getY();
230 boolean isLabelBehindTrans = trans.getX() < trans.getNameLabel().getX();
231 double xOffset = trans.getName().length() > 5 && !isLabelAboveTransition && !isLabelBehindTrans ? trans.getLayerOffset() : 0;
232
206 out.append("%% label for transition " + trans.getName() + "\n");233 out.append("%% label for transition " + trans.getName() + "\n");
207 out.append("\\draw (");234 out.append("\\draw (");
208 out.append(RoundCoordinate(trans.getNameLabel().getXPosition()) + "," + (RoundCoordinate(trans.getNameLabel().getYPosition()) * -1) + ")");235 out.append(trans.getNameLabel().getX() + xOffset + "," + (trans.getNameLabel().getY() * -1) + ")");
209 out.append(" node ");236 out.append(" node ");
210 out.append(" {");237 out.append(" {");
211 out.append(exportMathName(trans.getName()));238 out.append(exportMathName(trans.getName()));
@@ -217,19 +244,21 @@
217244
218 private StringBuffer exportPlacesWithTokens(Place[] places) {245 private StringBuffer exportPlacesWithTokens(Place[] places) {
219 StringBuffer out = new StringBuffer();246 StringBuffer out = new StringBuffer();
247
220 for (Place place : places) {248 for (Place place : places) {
221 String invariant = getPlaceInvariantString(place);249 String invariant = getPlaceInvariantString(place);
222 String tokensInPlace = getTokenListStringFor(place);250 String tokensInPlace = getTokenListStringFor(place);
223251
224 out.append("\\node[place");252 out.append("\\node[place");
225 out.append(tokensInPlace);
226 out.append("] at (");253 out.append("] at (");
227 out.append(RoundCoordinate(place.getPositionX()));254 out.append(place.getPositionX());
228 out.append(',');255 out.append(',');
229 out.append(RoundCoordinate(place.getPositionY() * (-1)));256 out.append(place.getPositionY() * (-1));
230 out.append(") (");257 out.append(") (");
231 out.append(place.getId());258 out.append(place.getId());
232 out.append(") {};\n");259 out.append(") {};\n");
260
261 exportPlaceTokens(place, out, ((TimedPlaceComponent) place).underlyingPlace().tokens().size());
233 262
234 if(((TimedPlaceComponent)place).underlyingPlace().isShared()){263 if(((TimedPlaceComponent)place).underlyingPlace().isShared()){
235 out.append("\\node[sharedplace] at (");264 out.append("\\node[sharedplace] at (");
@@ -237,9 +266,14 @@
237 out.append(".center) { };\n");266 out.append(".center) { };\n");
238 }267 }
239 if (place.getAttributesVisible() || !invariant.equals("")){268 if (place.getAttributesVisible() || !invariant.equals("")){
269 boolean isLabelAbovePlace = place.getY() > place.getNameLabel().getY();
270 boolean isLabelBehindPlace = place.getX() < place.getNameLabel().getX();
271 double xOffset = place.getName().length() > 6 && !isLabelAbovePlace && !isLabelBehindPlace ? place.getLayerOffset() : 0;
272 double yOffset = isLabelAbovePlace ? (place.getNameLabel().getHeight() / 2) : 0;
273
240 out.append("%% label for place " + place.getName() + "\n");274 out.append("%% label for place " + place.getName() + "\n");
241 out.append("\\draw (");275 out.append("\\draw (");
242 out.append(RoundCoordinate(place.getNameLabel().getXPosition()) + "," + (RoundCoordinate(place.getNameLabel().getYPosition()) * -1) + ")");276 out.append((place.getNameLabel().getX() + xOffset) + "," + ((place.getNameLabel().getY() * -1) + yOffset) +")");
243 out.append(" node[align=left] ");277 out.append(" node[align=left] ");
244 out.append("{");278 out.append("{");
245 if(place.getAttributesVisible())279 if(place.getAttributesVisible())
@@ -252,16 +286,159 @@
252 out.append("};\n");286 out.append("};\n");
253 }287 }
254 288
255 } 289 }
256 }290 }
257291
258 return out;292 return out;
259 }293 }
260294
295 private void exportPlaceTokens(Place place, StringBuffer out, int numOfTokens) {
296 // Dot radius
297 final double tRadius = 1;
298
299 // Token dot position offsets
300 final double tLeftX = 7;
301 final double tRightX = 7;
302 final double tTopY = 7;
303 final double tBotY = 7;
304
305 boolean isTimed = CreateGui.getApp().getCurrentTab().getLens().isTimed();
306
307 double placeXpos = (place.getPositionX());
308 double placeYpos = (place.getPositionY() * (-1));
309 double xPos, yPos;
310
311 if(isTimed && numOfTokens > 0) {
312 switch (numOfTokens) {
313 case 2:
314 out.append("\\node at ("); // Top
315 out.append(placeXpos);
316 out.append(",");
317 out.append(placeYpos + 4);
318 out.append(")");
319 out.append("{0,0};\n");
320
321 out.append("\\node at ("); // Bottom
322 out.append(placeXpos);
323 out.append(",");
324 out.append(placeYpos - 5);
325 out.append(")");
326 out.append("{0,0};\n");
327 return;
328 case 1:
329 out.append("\\node at ("); // Top
330 out.append(placeXpos);
331 out.append(",");
332 out.append(placeYpos);
333 out.append(")");
334 out.append("{0,0};\n");
335 return;
336 default:
337 out.append("\\node at (");
338 out.append(placeXpos);
339 out.append(",");
340 out.append(placeYpos);
341 out.append(")");
342 out.append("{$\\mathrm{");
343 out.append("\\#" + numOfTokens + "}$};\n");
344 return;
345 }
346 } else if(numOfTokens > 5 && !isTimed ) {
347 out.append("\\node at (");
348 out.append(placeXpos);
349 out.append(",");
350 out.append(placeYpos);
351 out.append(")");
352 out.append("{$\\mathrm{");
353 out.append("\\#" + numOfTokens + "}$};\n");
354 return;
355 }
356
357 switch (numOfTokens) {
358 case 5: // middle
359 out.append("\\node at (");
360 out.append(placeXpos);
361 out.append(",");
362 out.append(placeYpos);
363 out.append(")");
364 out.append("[circle,fill,inner sep=");
365 out.append(tRadius);
366 out.append("pt]{};\n");
367 /* falls through */
368 case 4: // top left
369 out.append("\\node at (");
370 out.append(placeXpos - tLeftX);
371 out.append(",");
372 out.append(placeYpos + tTopY);
373 out.append(")");
374 out.append("[circle,fill,inner sep=");
375 out.append(tRadius);
376 out.append("pt]{};\n");
377 /* falls through */
378 case 3:
379 if(numOfTokens == 5 || numOfTokens == 4) { // top right
380 xPos = placeXpos + tRightX;
381 yPos = placeYpos + tTopY;
382 } else { // top left
383 xPos = placeXpos - tLeftX;
384 yPos = placeYpos + tTopY;
385 }
386 out.append("\\node at (");
387 out.append(xPos);
388 out.append(",");
389 out.append(yPos);
390 out.append(")");
391 out.append("[circle,fill,inner sep=");
392 out.append(tRadius);
393 out.append("pt]{};\n");
394 /* falls through */
395 case 2:
396 if(numOfTokens == 5 || numOfTokens == 4) { // bottom left
397 xPos = placeXpos - tLeftX;
398 yPos = placeYpos - tBotY;
399 } else if (numOfTokens == 3){ // middle
400 xPos = placeXpos;
401 yPos = placeYpos;
402 } else { // left middle
403 xPos = placeXpos - tLeftX;
404 yPos = placeYpos;
405 }
406 out.append("\\node at (");
407 out.append(xPos);
408 out.append(",");
409 out.append(yPos);
410 out.append(")");
411 out.append("[circle,fill,inner sep=");
412 out.append(tRadius);
413 out.append("pt]{};\n");
414 /* falls through */
415 case 1:
416 if(numOfTokens == 5 || numOfTokens == 4 || numOfTokens == 3) { // bottom right
417 xPos = placeXpos + tRightX;
418 yPos = placeYpos - tBotY;
419 } else if (numOfTokens == 2){ // right middle
420 xPos = placeXpos + tRightX;
421 yPos = placeYpos;
422 } else { // middle
423 xPos = placeXpos;
424 yPos = placeYpos;
425 }
426 out.append("\\node at (");
427 out.append(xPos);
428 out.append(",");
429 out.append(yPos);
430 out.append(")");
431 out.append("[circle,fill,inner sep=");
432 out.append(tRadius);
433 out.append("pt]{};\n");
434 default:
435 break;
436 }
437 }
438
261 protected String getTokenListStringFor(Place place) {439 protected String getTokenListStringFor(Place place) {
262
263 List<TimedToken> tokens = ((TimedPlaceComponent) place).underlyingPlace().tokens();440 List<TimedToken> tokens = ((TimedPlaceComponent) place).underlyingPlace().tokens();
264 441
265 String tokensInPlace = "";442 String tokensInPlace = "";
266 if (tokens.size() > 0) {443 if (tokens.size() > 0) {
267 if (tokens.size() == 1) {444 if (tokens.size() == 1) {
@@ -301,7 +478,7 @@
301 private StringBuffer exportTikZstyle() {478 private StringBuffer exportTikZstyle() {
302 StringBuffer out = new StringBuffer();479 StringBuffer out = new StringBuffer();
303480
304 out.append("\\begin{tikzpicture}[font=\\scriptsize, xscale=1, yscale=1]\n");481 out.append("\\begin{tikzpicture}[font=\\scriptsize, xscale=0.45, yscale=0.45, x=1.33px, y=1.33px]\n");
305 out.append("%% the figure can be scaled by changing xscale and yscale\n");482 out.append("%% the figure can be scaled by changing xscale and yscale\n");
306 out.append("%% positions of place/transition labels that are currently fixed to label=135 degrees\n");483 out.append("%% positions of place/transition labels that are currently fixed to label=135 degrees\n");
307 out.append("%% can be adjusted so that they do not cover arcs\n");484 out.append("%% can be adjusted so that they do not cover arcs\n");

Subscribers

People subscribed via source and target branches