source: josm/trunk/src/org/openstreetmap/josm/data/osm/visitor/paint/ComputeStyleListWorker.java @ 12813

Last change on this file since 12813 was 12813, checked in by bastiK, 6 weeks ago

fix PMD, etc.

  • Property svn:eol-style set to native
File size: 6.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm.visitor.paint;
3
4import java.util.ArrayList;
5import java.util.Collection;
6import java.util.List;
7import java.util.concurrent.ForkJoinTask;
8import java.util.concurrent.RecursiveTask;
9
10import org.openstreetmap.josm.Main;
11import org.openstreetmap.josm.data.osm.Node;
12import org.openstreetmap.josm.data.osm.OsmPrimitive;
13import org.openstreetmap.josm.data.osm.Relation;
14import org.openstreetmap.josm.data.osm.Way;
15import org.openstreetmap.josm.data.osm.visitor.OsmPrimitiveVisitor;
16import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer.StyleRecord;
17import org.openstreetmap.josm.gui.NavigatableComponent;
18import org.openstreetmap.josm.gui.mappaint.ElemStyles;
19import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
20import org.openstreetmap.josm.gui.mappaint.StyleElementList;
21import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
22import org.openstreetmap.josm.gui.mappaint.styleelement.AreaElement;
23import org.openstreetmap.josm.gui.mappaint.styleelement.AreaIconElement;
24import org.openstreetmap.josm.gui.mappaint.styleelement.NodeElement;
25import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement;
26import org.openstreetmap.josm.gui.mappaint.styleelement.TextElement;
27import org.openstreetmap.josm.tools.JosmRuntimeException;
28import org.openstreetmap.josm.tools.bugreport.BugReport;
29
30/**
31 * Helper to compute style list.
32 * @since 11914 (extracted from StyledMapRenderer)
33 */
34public class ComputeStyleListWorker extends RecursiveTask<List<StyleRecord>> implements OsmPrimitiveVisitor {
35    private final transient List<? extends OsmPrimitive> input;
36    private final transient List<StyleRecord> output;
37
38    private final transient ElemStyles styles = MapPaintStyles.getStyles();
39    private final int directExecutionTaskSize;
40    private final double circum;
41    private final NavigatableComponent nc;
42
43    private final boolean drawArea;
44    private final boolean drawMultipolygon;
45    private final boolean drawRestriction;
46
47    /**
48     * Constructs a new {@code ComputeStyleListWorker}.
49     * @param circum distance on the map in meters that 100 screen pixels represent
50     * @param nc navigatable component
51     * @param input the primitives to process
52     * @param output the list of styles to which styles will be added
53     * @param directExecutionTaskSize the threshold deciding whether to subdivide the tasks
54     */
55    ComputeStyleListWorker(double circum, NavigatableComponent nc,
56            final List<? extends OsmPrimitive> input, List<StyleRecord> output, int directExecutionTaskSize) {
57        this.circum = circum;
58        this.nc = nc;
59        this.input = input;
60        this.output = output;
61        this.directExecutionTaskSize = directExecutionTaskSize;
62        this.drawArea = circum <= Main.pref.getInteger("mappaint.fillareas", 10_000_000);
63        this.drawMultipolygon = drawArea && Main.pref.getBoolean("mappaint.multipolygon", true);
64        this.drawRestriction = Main.pref.getBoolean("mappaint.restriction", true);
65        this.styles.setDrawMultipolygon(drawMultipolygon);
66    }
67
68    @Override
69    protected List<StyleRecord> compute() {
70        if (input.size() <= directExecutionTaskSize) {
71            return computeDirectly();
72        } else {
73            final Collection<ForkJoinTask<List<StyleRecord>>> tasks = new ArrayList<>();
74            for (int fromIndex = 0; fromIndex < input.size(); fromIndex += directExecutionTaskSize) {
75                final int toIndex = Math.min(fromIndex + directExecutionTaskSize, input.size());
76                tasks.add(new ComputeStyleListWorker(circum, nc, input.subList(fromIndex, toIndex),
77                        new ArrayList<>(directExecutionTaskSize), directExecutionTaskSize).fork());
78            }
79            for (ForkJoinTask<List<StyleRecord>> task : tasks) {
80                output.addAll(task.join());
81            }
82            return output;
83        }
84    }
85
86    /**
87     * Compute directly (without using fork/join) the style list. Only called for small input.
88     * @return list of computed style records
89     */
90    public List<StyleRecord> computeDirectly() {
91        MapCSSStyleSource.STYLE_SOURCE_LOCK.readLock().lock();
92        try {
93            for (final OsmPrimitive osm : input) {
94                acceptDrawable(osm);
95            }
96            return output;
97        } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException e) {
98            throw BugReport.intercept(e).put("input-size", input.size()).put("output-size", output.size());
99        } finally {
100            MapCSSStyleSource.STYLE_SOURCE_LOCK.readLock().unlock();
101        }
102    }
103
104    private void acceptDrawable(final OsmPrimitive osm) {
105        try {
106            if (osm.isDrawable()) {
107                osm.accept(this);
108            }
109        } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException e) {
110            throw BugReport.intercept(e).put("osm", osm);
111        }
112    }
113
114    @Override
115    public void visit(Node n) {
116        add(n, StyledMapRenderer.computeFlags(n, false));
117    }
118
119    @Override
120    public void visit(Way w) {
121        add(w, StyledMapRenderer.computeFlags(w, true));
122    }
123
124    @Override
125    public void visit(Relation r) {
126        add(r, StyledMapRenderer.computeFlags(r, true));
127    }
128
129    /**
130     * Add new style records for the given node.
131     * @param osm node
132     * @param flags flags
133     */
134    public void add(Node osm, int flags) {
135        StyleElementList sl = styles.get(osm, circum, nc);
136        for (StyleElement s : sl) {
137            output.add(new StyleRecord(s, osm, flags));
138        }
139    }
140
141    /**
142     * Add new style records for the given way.
143     * @param osm way
144     * @param flags flags
145     */
146    public void add(Way osm, int flags) {
147        StyleElementList sl = styles.get(osm, circum, nc);
148        for (StyleElement s : sl) {
149            if ((drawArea && (flags & StyledMapRenderer.FLAG_DISABLED) == 0) || !(s instanceof AreaElement)) {
150                output.add(new StyleRecord(s, osm, flags));
151            }
152        }
153    }
154
155    /**
156     * Add new style records for the given relation.
157     * @param osm relation
158     * @param flags flags
159     */
160    public void add(Relation osm, int flags) {
161        StyleElementList sl = styles.get(osm, circum, nc);
162        for (StyleElement s : sl) {
163            if (drawAreaElement(flags, s) ||
164               (drawMultipolygon && drawArea && s instanceof TextElement) ||
165               (drawRestriction && s instanceof NodeElement)) {
166                output.add(new StyleRecord(s, osm, flags));
167            }
168        }
169    }
170
171    private boolean drawAreaElement(int flags, StyleElement s) {
172        return drawMultipolygon && drawArea && (s instanceof AreaElement || s instanceof AreaIconElement)
173                && (flags & StyledMapRenderer.FLAG_DISABLED) == 0;
174    }
175}
Note: See TracBrowser for help on using the repository browser.