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