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: 402 lines (+223/-47)
1 file modified
src/pipe/gui/TikZExporter.java (+223/-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+409960@code.launchpad.net

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

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.
1151. By Kristian Morsing Pedersen <email address hidden>

Removed commented code

1152. By Kristian Morsing Pedersen <email address hidden>

Now exports curved arcs correctly

1153. By Kristian Morsing Pedersen <email address hidden>

Removes unused imports

1154. By Kristian Morsing Pedersen <email address hidden>

Removes unused imports

1155. By Kristian Morsing Pedersen <email address hidden>

Fixed imports

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 19:16:28 +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,14 @@
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());
172194
173 out.append("\\node[transition");195 out.append("\\node[transition");
174 out.append(angle); 196 out.append(angle);
175 out.append("] at (");197 out.append("] at (");
176 out.append(RoundCoordinate(trans.getPositionX()));198 out.append((trans.getPositionX()));
177 out.append(',');199 out.append(',');
178 out.append(RoundCoordinate(trans.getPositionY() * (-1)));200 out.append((trans.getPositionY() * (-1)));
179 out.append(") (");201 out.append(") (");
180 out.append(trans.getId());202 out.append(trans.getId());
181 out.append(") {};\n");203 out.append(") {};\n");
@@ -203,9 +225,13 @@
203 out.append(".center) { };\n");225 out.append(".center) { };\n");
204 }226 }
205 if (trans.getAttributesVisible()){227 if (trans.getAttributesVisible()){
228 boolean isLabelAboveTransition = trans.getY() > trans.getNameLabel().getY();
229 boolean isLabelBehindTrans = trans.getX() < trans.getNameLabel().getX();
230 double xOffset = trans.getName().length() > 5 && !isLabelAboveTransition && !isLabelBehindTrans ? trans.getLayerOffset() : 0;
231
206 out.append("%% label for transition " + trans.getName() + "\n");232 out.append("%% label for transition " + trans.getName() + "\n");
207 out.append("\\draw (");233 out.append("\\draw (");
208 out.append(RoundCoordinate(trans.getNameLabel().getXPosition()) + "," + (RoundCoordinate(trans.getNameLabel().getYPosition()) * -1) + ")");234 out.append(trans.getNameLabel().getX() + xOffset + "," + (trans.getNameLabel().getY() * -1) + ")");
209 out.append(" node ");235 out.append(" node ");
210 out.append(" {");236 out.append(" {");
211 out.append(exportMathName(trans.getName()));237 out.append(exportMathName(trans.getName()));
@@ -217,19 +243,21 @@
217243
218 private StringBuffer exportPlacesWithTokens(Place[] places) {244 private StringBuffer exportPlacesWithTokens(Place[] places) {
219 StringBuffer out = new StringBuffer();245 StringBuffer out = new StringBuffer();
246
220 for (Place place : places) {247 for (Place place : places) {
221 String invariant = getPlaceInvariantString(place);248 String invariant = getPlaceInvariantString(place);
222 String tokensInPlace = getTokenListStringFor(place);249 String tokensInPlace = getTokenListStringFor(place);
223250
224 out.append("\\node[place");251 out.append("\\node[place");
225 out.append(tokensInPlace);
226 out.append("] at (");252 out.append("] at (");
227 out.append(RoundCoordinate(place.getPositionX()));253 out.append(place.getPositionX());
228 out.append(',');254 out.append(',');
229 out.append(RoundCoordinate(place.getPositionY() * (-1)));255 out.append(place.getPositionY() * (-1));
230 out.append(") (");256 out.append(") (");
231 out.append(place.getId());257 out.append(place.getId());
232 out.append(") {};\n");258 out.append(") {};\n");
259
260 exportPlaceTokens(place, out, ((TimedPlaceComponent) place).underlyingPlace().tokens().size());
233 261
234 if(((TimedPlaceComponent)place).underlyingPlace().isShared()){262 if(((TimedPlaceComponent)place).underlyingPlace().isShared()){
235 out.append("\\node[sharedplace] at (");263 out.append("\\node[sharedplace] at (");
@@ -237,9 +265,14 @@
237 out.append(".center) { };\n");265 out.append(".center) { };\n");
238 }266 }
239 if (place.getAttributesVisible() || !invariant.equals("")){267 if (place.getAttributesVisible() || !invariant.equals("")){
268 boolean isLabelAbovePlace = place.getY() > place.getNameLabel().getY();
269 boolean isLabelBehindPlace = place.getX() < place.getNameLabel().getX();
270 double xOffset = place.getName().length() > 6 && !isLabelAbovePlace && !isLabelBehindPlace ? place.getLayerOffset() : 0;
271 double yOffset = isLabelAbovePlace ? (place.getNameLabel().getHeight() / 2) : 0;
272
240 out.append("%% label for place " + place.getName() + "\n");273 out.append("%% label for place " + place.getName() + "\n");
241 out.append("\\draw (");274 out.append("\\draw (");
242 out.append(RoundCoordinate(place.getNameLabel().getXPosition()) + "," + (RoundCoordinate(place.getNameLabel().getYPosition()) * -1) + ")");275 out.append((place.getNameLabel().getX() + xOffset) + "," + ((place.getNameLabel().getY() * -1) + yOffset) +")");
243 out.append(" node[align=left] ");276 out.append(" node[align=left] ");
244 out.append("{");277 out.append("{");
245 if(place.getAttributesVisible())278 if(place.getAttributesVisible())
@@ -252,16 +285,159 @@
252 out.append("};\n");285 out.append("};\n");
253 }286 }
254 287
255 } 288 }
256 }289 }
257290
258 return out;291 return out;
259 }292 }
260293
294 private void exportPlaceTokens(Place place, StringBuffer out, int numOfTokens) {
295 // Dot radius
296 final double tRadius = 1;
297
298 // Token dot position offsets
299 final double tLeftX = 7;
300 final double tRightX = 7;
301 final double tTopY = 7;
302 final double tBotY = 7;
303
304 boolean isTimed = CreateGui.getApp().getCurrentTab().getLens().isTimed();
305
306 double placeXpos = (place.getPositionX());
307 double placeYpos = (place.getPositionY() * (-1));
308 double xPos, yPos;
309
310 if(isTimed && numOfTokens > 0) {
311 switch (numOfTokens) {
312 case 2:
313 out.append("\\node at ("); // Top
314 out.append(placeXpos);
315 out.append(",");
316 out.append(placeYpos + 4);
317 out.append(")");
318 out.append("{0,0};\n");
319
320 out.append("\\node at ("); // Bottom
321 out.append(placeXpos);
322 out.append(",");
323 out.append(placeYpos - 5);
324 out.append(")");
325 out.append("{0,0};\n");
326 return;
327 case 1:
328 out.append("\\node at ("); // Top
329 out.append(placeXpos);
330 out.append(",");
331 out.append(placeYpos);
332 out.append(")");
333 out.append("{0,0};\n");
334 return;
335 default:
336 out.append("\\node at (");
337 out.append(placeXpos);
338 out.append(",");
339 out.append(placeYpos);
340 out.append(")");
341 out.append("{$\\mathrm{");
342 out.append("\\#" + numOfTokens + "}$};\n");
343 return;
344 }
345 } else if(numOfTokens > 5 && !isTimed ) {
346 out.append("\\node at (");
347 out.append(placeXpos);
348 out.append(",");
349 out.append(placeYpos);
350 out.append(")");
351 out.append("{$\\mathrm{");
352 out.append("\\#" + numOfTokens + "}$};\n");
353 return;
354 }
355
356 switch (numOfTokens) {
357 case 5: // middle
358 out.append("\\node at (");
359 out.append(placeXpos);
360 out.append(",");
361 out.append(placeYpos);
362 out.append(")");
363 out.append("[circle,fill,inner sep=");
364 out.append(tRadius);
365 out.append("pt]{};\n");
366 /* falls through */
367 case 4: // top left
368 out.append("\\node at (");
369 out.append(placeXpos - tLeftX);
370 out.append(",");
371 out.append(placeYpos + tTopY);
372 out.append(")");
373 out.append("[circle,fill,inner sep=");
374 out.append(tRadius);
375 out.append("pt]{};\n");
376 /* falls through */
377 case 3:
378 if(numOfTokens == 5 || numOfTokens == 4) { // top right
379 xPos = placeXpos + tRightX;
380 yPos = placeYpos + tTopY;
381 } else { // top left
382 xPos = placeXpos - tLeftX;
383 yPos = placeYpos + tTopY;
384 }
385 out.append("\\node at (");
386 out.append(xPos);
387 out.append(",");
388 out.append(yPos);
389 out.append(")");
390 out.append("[circle,fill,inner sep=");
391 out.append(tRadius);
392 out.append("pt]{};\n");
393 /* falls through */
394 case 2:
395 if(numOfTokens == 5 || numOfTokens == 4) { // bottom left
396 xPos = placeXpos - tLeftX;
397 yPos = placeYpos - tBotY;
398 } else if (numOfTokens == 3){ // middle
399 xPos = placeXpos;
400 yPos = placeYpos;
401 } else { // left middle
402 xPos = placeXpos - tLeftX;
403 yPos = placeYpos;
404 }
405 out.append("\\node at (");
406 out.append(xPos);
407 out.append(",");
408 out.append(yPos);
409 out.append(")");
410 out.append("[circle,fill,inner sep=");
411 out.append(tRadius);
412 out.append("pt]{};\n");
413 /* falls through */
414 case 1:
415 if(numOfTokens == 5 || numOfTokens == 4 || numOfTokens == 3) { // bottom right
416 xPos = placeXpos + tRightX;
417 yPos = placeYpos - tBotY;
418 } else if (numOfTokens == 2){ // right middle
419 xPos = placeXpos + tRightX;
420 yPos = placeYpos;
421 } else { // middle
422 xPos = placeXpos;
423 yPos = placeYpos;
424 }
425 out.append("\\node at (");
426 out.append(xPos);
427 out.append(",");
428 out.append(yPos);
429 out.append(")");
430 out.append("[circle,fill,inner sep=");
431 out.append(tRadius);
432 out.append("pt]{};\n");
433 default:
434 break;
435 }
436 }
437
261 protected String getTokenListStringFor(Place place) {438 protected String getTokenListStringFor(Place place) {
262
263 List<TimedToken> tokens = ((TimedPlaceComponent) place).underlyingPlace().tokens();439 List<TimedToken> tokens = ((TimedPlaceComponent) place).underlyingPlace().tokens();
264 440
265 String tokensInPlace = "";441 String tokensInPlace = "";
266 if (tokens.size() > 0) {442 if (tokens.size() > 0) {
267 if (tokens.size() == 1) {443 if (tokens.size() == 1) {
@@ -301,7 +477,7 @@
301 private StringBuffer exportTikZstyle() {477 private StringBuffer exportTikZstyle() {
302 StringBuffer out = new StringBuffer();478 StringBuffer out = new StringBuffer();
303479
304 out.append("\\begin{tikzpicture}[font=\\scriptsize, xscale=1, yscale=1]\n");480 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");481 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");482 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");483 out.append("%% can be adjusted so that they do not cover arcs\n");

Subscribers

People subscribed via source and target branches