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

Subscribers

People subscribed via source and target branches