source: osm/applications/editors/josm/plugins/smed2/src/seamap/Renderer.java@ 29826

Last change on this file since 29826 was 29826, checked in by malcolmh, 11 years ago

save

File size: 9.7 KB
Line 
1/* Copyright 2013 Malcolm Herring
2 *
3 * This is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License.
6 *
7 * For a copy of the GNU General Public License, see <http://www.gnu.org/licenses/>.
8 */
9
10package seamap;
11
12import java.awt.*;
13import java.awt.font.*;
14import java.awt.geom.*;
15import java.util.*;
16
17import s57.S57att.*;
18import s57.S57obj.*;
19import s57.S57val.*;
20import s57.S57val;
21import seamap.SeaMap;
22import seamap.SeaMap.*;
23import seamap.SeaMap.Area;
24import symbols.Symbols;
25import symbols.Symbols.*;
26
27public class Renderer {
28
29 static MapHelper helper;
30 static SeaMap map;
31 static double sScale;
32 static double tScale;
33 static Graphics2D g2;
34 static int zoom;
35
36 public static void reRender(Graphics2D g, int z, double factor, SeaMap m, MapHelper h) {
37 g2 = g;
38 zoom = z;
39 helper = h;
40 map = m;
41 sScale = Symbols.symbolScale[zoom] * factor;
42 tScale = Symbols.textScale[zoom] * factor;
43 if (map != null) {
44 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
45 g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);
46 Rules.rules(map, zoom);
47 }
48 }
49
50 public static AttMap getAtts(Feature feature, Obj obj, int idx) {
51 HashMap<Integer, AttMap> objs = feature.objs.get(obj);
52 if (objs == null)
53 return null;
54 else
55 return objs.get(idx);
56 }
57
58 public static Object getAttVal(Feature feature, Obj obj, int idx, Att att) {
59 AttMap atts = getAtts(feature, obj, idx);
60 if (atts == null)
61 return S57val.nullVal(att);
62 else {
63 AttItem item = atts.get(att);
64 if (item == null)
65 return S57val.nullVal(att);
66 return item.val;
67 }
68 }
69
70 public static void symbol(Feature feature, Symbol symbol, Obj obj, Delta delta) {
71 Point2D point = helper.getPoint(feature.centre);
72 if (obj == null) {
73 Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), delta, null);
74 } else {
75 ArrayList<ColCOL> colours = (ArrayList<ColCOL>) getAttVal(feature, obj, 0, Att.COLOUR);
76 ArrayList<ColPAT> pattern = (ArrayList<ColPAT>) getAttVal(feature, obj, 0, Att.COLPAT);
77 Symbols.drawSymbol(g2, symbol, sScale, point.getX(), point.getY(), delta, new Scheme(pattern, colours));
78 }
79 }
80
81 private static Rectangle symbolSize(Symbol symbol) {
82 Symbol ssymb = symbol;
83 while (ssymb != null) {
84 for (Instr item : symbol) {
85 if (item.type == Prim.BBOX) {
86 return (Rectangle) item.params;
87 }
88 if (item.type == Prim.SYMB) {
89 ssymb = ((SubSymbol) item.params).instr;
90 break;
91 }
92 }
93 if (ssymb == symbol)
94 break;
95 }
96 return null;
97 }
98
99 private double mile(Feature feature) {
100 return Math.pow(2, zoom) * 256 / (21600 * Math.abs(Math.cos(feature.centre.lat)));
101 }
102
103 public static void lineSymbols(Feature feature, Symbol prisymb, double space, Symbol secsymb, int ratio) {
104 Area area;
105 switch (feature.flag) {
106 case LINE:
107 Edge edge = map.edges.get(feature.refs);
108 area = map.new Area();
109 area.add(map.new Bound(map.new Side(edge, true), true));
110 break;
111 case AREA:
112 area = map.areas.get(feature.refs);
113 break;
114 default:
115 return;
116 }
117 Rectangle prect = symbolSize(prisymb);
118 Rectangle srect = symbolSize(secsymb);
119 if (srect == null)
120 ratio = 0;
121 if (prect != null) {
122 double psize = Math.abs(prect.getY()) * sScale;
123 double ssize = (srect != null) ? Math.abs(srect.getY()) * sScale : 0;
124 Point2D prev = new Point2D.Double();
125 Point2D next = new Point2D.Double();
126 Point2D curr = new Point2D.Double();
127 Point2D succ = new Point2D.Double();
128 boolean gap = true;
129 boolean piv = false;
130 double len = 0;
131 double angle = 0;
132 int scount = ratio;
133 Symbol symbol = prisymb;
134 for (Bound bound : area) {
135 BoundIterator bit = map.new BoundIterator(bound);
136 boolean first = true;
137 while (bit.hasNext()) {
138 prev = next;
139 next = helper.getPoint(bit.next());
140 angle = Math.atan2(next.getY() - prev.getY(), next.getX() - prev.getX());
141 piv = true;
142 if (first) {
143 curr = succ = next;
144 gap = (space > 0);
145 scount = ratio;
146 symbol = prisymb;
147 len = gap ? psize * space * 0.5 : psize;
148 first = false;
149 } else {
150 while (curr.distance(next) >= len) {
151 if (piv) {
152 double rem = len;
153 double s = prev.distance(next);
154 double p = curr.distance(prev);
155 if ((s > 0) && (p > 0)) {
156 double n = curr.distance(next);
157 double theta = Math.acos((s * s + p * p - n * n) / 2 / s / p);
158 double phi = Math.asin(p / len * Math.sin(theta));
159 rem = len * Math.sin(Math.PI - theta - phi) / Math.sin(theta);
160 }
161 succ = new Point2D.Double(prev.getX() + (rem * Math.cos(angle)), prev.getY() + (rem * Math.sin(angle)));
162 piv = false;
163 } else {
164 succ = new Point2D.Double(curr.getX() + (len * Math.cos(angle)), curr.getY() + (len * Math.sin(angle)));
165 }
166 if (!gap) {
167 Symbols.drawSymbol(g2, symbol, sScale, curr.getX(), curr.getY(), new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.atan2((succ.getY() - curr.getY()), (succ.getX() - curr.getX())) + Math.toRadians(90))), null);
168 }
169 if (space > 0)
170 gap = !gap;
171 curr = succ;
172 len = gap ? (psize * space) : (--scount == 0) ? ssize : psize;
173 if (scount == 0) {
174 symbol = secsymb;
175 scount = ratio;
176 } else {
177 symbol = prisymb;
178 }
179 }
180 }
181 }
182 }
183 }
184 }
185
186 public static void lineVector(Feature feature, LineStyle style) {
187 Path2D.Double p = new Path2D.Double();
188 p.setWindingRule(GeneralPath.WIND_EVEN_ODD);
189 Point2D point;
190 switch (feature.flag) {
191 case LINE:
192 EdgeIterator eit = map.new EdgeIterator(map.edges.get(feature.refs), true);
193 point = helper.getPoint(eit.next());
194 p.moveTo(point.getX(), point.getY());
195 while (eit.hasNext()) {
196 point = helper.getPoint(eit.next());
197 p.lineTo(point.getX(), point.getY());
198 }
199 break;
200 case AREA:
201 for (Bound bound : map.areas.get(feature.refs)) {
202 BoundIterator bit = map.new BoundIterator(bound);
203 point = helper.getPoint(bit.next());
204 p.moveTo(point.getX(), point.getY());
205 while (bit.hasNext()) {
206 point = helper.getPoint(bit.next());
207 p.lineTo(point.getX(), point.getY());
208 }
209 }
210 break;
211 }
212 if (style.line != null) {
213 if (style.dash != null) {
214 float[] dash = new float[style.dash.length];
215 System.arraycopy(style.dash, 0, dash, 0, style.dash.length);
216 for (int i = 0; i < style.dash.length; i++) {
217 dash[i] *= (float) sScale;
218 }
219 g2.setStroke(new BasicStroke((float) (style.width * sScale), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1, dash, 0));
220 } else {
221 g2.setStroke(new BasicStroke((float) (style.width * sScale), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND));
222 }
223 g2.setPaint(style.line);
224 g2.draw(p);
225 }
226 if (style.fill != null) {
227 g2.setPaint(style.fill);
228 g2.fill(p);
229 }
230 }
231
232 public static void labelText(Feature feature, String str, Font font, Color colour, Delta delta) {
233 Symbol label = new Symbol();
234 label.add(new Instr(Prim.TEXT, new Caption(str, font, colour, (delta == null) ? new Delta(Handle.CC, null) : delta)));
235 Point2D point = helper.getPoint(feature.centre);
236 Symbols.drawSymbol(g2, label, tScale, point.getX(), point.getY(), null, null);
237 }
238
239 public static void lineText(Feature feature, String str, Font font, Color colour, double offset, double dy) {
240 Area area;
241 switch (feature.flag) {
242 case LINE:
243 Edge edge = map.edges.get(feature.refs);
244 area = map.new Area();
245 area.add(map.new Bound(map.new Side(edge, true), true));
246 break;
247 case AREA:
248 area = map.areas.get(feature.refs);
249 break;
250 default:
251 return;
252 }
253// Rectangle prect = symbolSize(prisymb);
254 if (!str.isEmpty()) {
255 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
256 FontRenderContext frc = g2.getFontRenderContext();
257 GlyphVector gv = font.deriveFont((float)(font.getSize()*tScale)).createGlyphVector(frc, str);
258// double psize = Math.abs(prect.getX());
259 Point2D prev = new Point2D.Double();
260 Point2D next = new Point2D.Double();
261 Point2D curr = new Point2D.Double();
262 Point2D succ = new Point2D.Double();
263 boolean gap = true;
264 boolean piv = false;
265 double len = 0;
266 double angle = 0;
267 for (Bound bound : area) {
268 BoundIterator bit = map.new BoundIterator(bound);
269 boolean first = true;
270 while (bit.hasNext()) {
271 prev = next;
272 next = helper.getPoint(bit.next());
273 angle = Math.atan2(next.getY() - prev.getY(), next.getX() - prev.getX());
274 piv = true;
275 if (first) {
276 curr = succ = next;
277// gap = (space > 0);
278// len = gap ? psize * space * 0.5 : psize;
279 first = false;
280 } else {
281 while (curr.distance(next) >= len) {
282 if (piv) {
283 double rem = len;
284 double s = prev.distance(next);
285 double p = curr.distance(prev);
286 if ((s > 0) && (p > 0)) {
287 double n = curr.distance(next);
288 double theta = Math.acos((s * s + p * p - n * n) / 2 / s / p);
289 double phi = Math.asin(p / len * Math.sin(theta));
290 rem = len * Math.sin(Math.PI - theta - phi) / Math.sin(theta);
291 }
292 succ = new Point2D.Double(prev.getX() + (rem * Math.cos(angle)), prev.getY() + (rem * Math.sin(angle)));
293 piv = false;
294 } else {
295 succ = new Point2D.Double(curr.getX() + (len * Math.cos(angle)), curr.getY() + (len * Math.sin(angle)));
296 }
297 if (!gap) {
298// Symbols.drawSymbol(g2, symbol, sScale, curr.getX(), curr.getY(), new Delta(Handle.BC, AffineTransform.getRotateInstance(Math.atan2((succ.getY() - curr.getY()), (succ.getX() - curr.getX())) + Math.toRadians(90))), null);
299 }
300 gap = false;
301 curr = succ;
302// len = psize;
303 }
304 }
305 }
306 }
307 }
308 }
309}
Note: See TracBrowser for help on using the repository browser.