1 /* 2 * Copyright (c) 2016 Helmut Neemann 3 * Use of this source code is governed by the GPL v3 license 4 * that can be found in the LICENSE file. 5 */ 6 package de.neemann.digital.draw.graphics.linemerger; 7 8 import de.neemann.digital.draw.graphics.*; 9 10 import java.util.ArrayList; 11 import java.util.HashMap; 12 import java.util.Iterator; 13 14 /** 15 * Merges all single lines which are drawn to polygons. 16 * Needed to create a nicer svg export because of the creation of longer strokes 17 * instead of single lines. 18 */ 19 public class GraphicLineCollector extends Graphic { 20 private final HashMap<Style, PolygonSet> polys; 21 22 /** 23 * Creates a new instance 24 */ GraphicLineCollector()25 public GraphicLineCollector() { 26 this.polys = new HashMap<>(); 27 } 28 29 @Override drawLine(VectorInterface p1, VectorInterface p2, Style style)30 public void drawLine(VectorInterface p1, VectorInterface p2, Style style) { 31 PolygonSet polyList = polys.get(style); 32 if (polyList == null) { 33 polyList = new PolygonSet(style); 34 polys.put(style, polyList); 35 } 36 polyList.add(p1, p2); 37 } 38 39 @Override drawPolygon(Polygon p, Style style)40 public void drawPolygon(Polygon p, Style style) { 41 } 42 43 @Override drawCircle(VectorInterface p1, VectorInterface p2, Style style)44 public void drawCircle(VectorInterface p1, VectorInterface p2, Style style) { 45 } 46 47 @Override drawText(VectorInterface p1, VectorInterface p2, VectorInterface p3, String text, Orientation orientation, Style style)48 public void drawText(VectorInterface p1, VectorInterface p2, VectorInterface p3, String text, Orientation orientation, Style style) { 49 } 50 51 private static final class PolygonSet implements Iterable<Polygon> { 52 private final ArrayList<Polygon> polyList; 53 private final Style style; 54 PolygonSet(Style style)55 private PolygonSet(Style style) { 56 this.style = style; 57 this.polyList = new ArrayList<>(); 58 } 59 add(VectorInterface p1, VectorInterface p2)60 private void add(VectorInterface p1, VectorInterface p2) { 61 for (Polygon p : polyList) { 62 if (p.addLine(p1, p2)) { 63 tryMerge(p); 64 return; 65 } 66 } 67 Polygon p = new Polygon(false).add(p1).add(p2); 68 polyList.add(p); 69 } 70 71 @Override iterator()72 public Iterator<Polygon> iterator() { 73 return polyList.iterator(); 74 } 75 tryMerge(Polygon p1)76 private void tryMerge(Polygon p1) { 77 for (Polygon p2 : polyList) 78 if (p1 != p2 && !p1.isClosed() && !p2.isClosed()) { 79 if (p1.getLast().equals(p2.getFirst())) { 80 p1.append(p2); 81 polyList.remove(p2); 82 return; 83 } else if (p2.getLast().equals(p1.getFirst())) { 84 p2.append(p1); 85 polyList.remove(p1); 86 return; 87 } else if (p1.getLast().equals(p2.getLast())) { 88 p1.append(p2.reverse()); 89 polyList.remove(p2); 90 return; 91 } else if (p1.getFirst().equals(p2.getFirst())) { 92 polyList.remove(p1); 93 polyList.remove(p2); 94 polyList.add(p1.reverse().append(p2)); 95 return; 96 } 97 } 98 } 99 drawTo(Graphic gr)100 public void drawTo(Graphic gr) { 101 for (Polygon p : polyList) 102 gr.drawPolygon(p, style); 103 } 104 } 105 106 /** 107 * Draws the polygons to the given {@link Graphic} instance 108 * 109 * @param gr the {@link Graphic} instace to use 110 */ drawTo(Graphic gr)111 public void drawTo(Graphic gr) { 112 for (PolygonSet p : polys.values()) 113 p.drawTo(gr); 114 } 115 } 116