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

Last change on this file since 12966 was 12964, checked in by bastiK, 7 years ago

see #15273 - more straightforward way to set up the styles for rendering

  • Property svn:eol-style set to native
File size: 7.6 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.data.osm.Node;
11import org.openstreetmap.josm.data.osm.OsmPrimitive;
12import org.openstreetmap.josm.data.osm.Relation;
13import org.openstreetmap.josm.data.osm.Way;
14import org.openstreetmap.josm.data.osm.visitor.OsmPrimitiveVisitor;
15import org.openstreetmap.josm.data.osm.visitor.paint.StyledMapRenderer.StyleRecord;
16import org.openstreetmap.josm.gui.NavigatableComponent;
17import org.openstreetmap.josm.gui.mappaint.ElemStyles;
18import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
19import org.openstreetmap.josm.gui.mappaint.StyleElementList;
20import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSStyleSource;
21import org.openstreetmap.josm.gui.mappaint.styleelement.AreaElement;
22import org.openstreetmap.josm.gui.mappaint.styleelement.AreaIconElement;
23import org.openstreetmap.josm.gui.mappaint.styleelement.NodeElement;
24import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement;
25import org.openstreetmap.josm.gui.mappaint.styleelement.TextElement;
26import org.openstreetmap.josm.spi.preferences.Config;
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;
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, nc, input, output, directExecutionTaskSize, MapPaintStyles.getStyles());
58 }
59
60 /**
61 * Constructs a new {@code ComputeStyleListWorker}.
62 * @param circum distance on the map in meters that 100 screen pixels represent
63 * @param nc navigatable component
64 * @param input the primitives to process
65 * @param output the list of styles to which styles will be added
66 * @param directExecutionTaskSize the threshold deciding whether to subdivide the tasks
67 * @param styles the {@link ElemStyles} instance used to generate primitive {@link StyleElement}s.
68 * @since 12964
69 */
70 ComputeStyleListWorker(double circum, NavigatableComponent nc,
71 final List<? extends OsmPrimitive> input, List<StyleRecord> output, int directExecutionTaskSize,
72 ElemStyles styles) {
73 this.circum = circum;
74 this.nc = nc;
75 this.input = input;
76 this.output = output;
77 this.directExecutionTaskSize = directExecutionTaskSize;
78 this.styles = styles;
79 this.drawArea = circum <= Config.getPref().getInt("mappaint.fillareas", 10_000_000);
80 this.drawMultipolygon = drawArea && Config.getPref().getBoolean("mappaint.multipolygon", true);
81 this.drawRestriction = Config.getPref().getBoolean("mappaint.restriction", true);
82 this.styles.setDrawMultipolygon(drawMultipolygon);
83 }
84
85 @Override
86 protected List<StyleRecord> compute() {
87 if (input.size() <= directExecutionTaskSize) {
88 return computeDirectly();
89 } else {
90 final Collection<ForkJoinTask<List<StyleRecord>>> tasks = new ArrayList<>();
91 for (int fromIndex = 0; fromIndex < input.size(); fromIndex += directExecutionTaskSize) {
92 final int toIndex = Math.min(fromIndex + directExecutionTaskSize, input.size());
93 tasks.add(new ComputeStyleListWorker(circum, nc, input.subList(fromIndex, toIndex),
94 new ArrayList<>(directExecutionTaskSize), directExecutionTaskSize, styles).fork());
95 }
96 for (ForkJoinTask<List<StyleRecord>> task : tasks) {
97 output.addAll(task.join());
98 }
99 return output;
100 }
101 }
102
103 /**
104 * Compute directly (without using fork/join) the style list. Only called for small input.
105 * @return list of computed style records
106 */
107 public List<StyleRecord> computeDirectly() {
108 MapCSSStyleSource.STYLE_SOURCE_LOCK.readLock().lock();
109 try {
110 for (final OsmPrimitive osm : input) {
111 acceptDrawable(osm);
112 }
113 return output;
114 } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException e) {
115 throw BugReport.intercept(e).put("input-size", input.size()).put("output-size", output.size());
116 } finally {
117 MapCSSStyleSource.STYLE_SOURCE_LOCK.readLock().unlock();
118 }
119 }
120
121 private void acceptDrawable(final OsmPrimitive osm) {
122 try {
123 if (osm.isDrawable()) {
124 osm.accept(this);
125 }
126 } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException e) {
127 throw BugReport.intercept(e).put("osm", osm);
128 }
129 }
130
131 @Override
132 public void visit(Node n) {
133 add(n, StyledMapRenderer.computeFlags(n, false));
134 }
135
136 @Override
137 public void visit(Way w) {
138 add(w, StyledMapRenderer.computeFlags(w, true));
139 }
140
141 @Override
142 public void visit(Relation r) {
143 add(r, StyledMapRenderer.computeFlags(r, true));
144 }
145
146 /**
147 * Add new style records for the given node.
148 * @param osm node
149 * @param flags flags
150 */
151 public void add(Node osm, int flags) {
152 StyleElementList sl = styles.get(osm, circum, nc);
153 for (StyleElement s : sl) {
154 output.add(new StyleRecord(s, osm, flags));
155 }
156 }
157
158 /**
159 * Add new style records for the given way.
160 * @param osm way
161 * @param flags flags
162 */
163 public void add(Way osm, int flags) {
164 StyleElementList sl = styles.get(osm, circum, nc);
165 for (StyleElement s : sl) {
166 if ((drawArea && (flags & StyledMapRenderer.FLAG_DISABLED) == 0) || !(s instanceof AreaElement)) {
167 output.add(new StyleRecord(s, osm, flags));
168 }
169 }
170 }
171
172 /**
173 * Add new style records for the given relation.
174 * @param osm relation
175 * @param flags flags
176 */
177 public void add(Relation osm, int flags) {
178 StyleElementList sl = styles.get(osm, circum, nc);
179 for (StyleElement s : sl) {
180 if (drawAreaElement(flags, s) ||
181 (drawMultipolygon && drawArea && s instanceof TextElement) ||
182 (drawRestriction && s instanceof NodeElement)) {
183 output.add(new StyleRecord(s, osm, flags));
184 }
185 }
186 }
187
188 private boolean drawAreaElement(int flags, StyleElement s) {
189 return drawMultipolygon && drawArea && (s instanceof AreaElement || s instanceof AreaIconElement)
190 && (flags & StyledMapRenderer.FLAG_DISABLED) == 0;
191 }
192}
Note: See TracBrowser for help on using the repository browser.