source: osm/applications/editors/josm/plugins/seachart/src/s57/S57map.java@ 34652

Last change on this file since 34652 was 34652, checked in by donvip, 6 years ago

fix UnnecessaryParentheses warnings

File size: 31.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package s57;
3
4import java.util.ArrayList;
5import java.util.EnumMap;
6import java.util.HashMap;
7import java.util.ListIterator;
8
9import s57.S57att.Att;
10import s57.S57obj.Obj;
11import s57.S57osm.KeyVal;
12import s57.S57val.AttVal;
13
14/**
15 * @author Malcolm Herring
16 */
17public class S57map { // S57/OSM map generation methods
18 // CHECKSTYLE.OFF: LineLength
19
20 public static class MapBounds {
21 public double minlat;
22 public double minlon;
23 public double maxlat;
24 public double maxlon;
25 public MapBounds() {
26 minlat = Math.toRadians(90);
27 minlon = Math.toRadians(180);
28 maxlat = Math.toRadians(-90);
29 maxlon = Math.toRadians(-180);
30 }
31 }
32
33 public enum Nflag {
34 ANON, // Edge inner nodes
35 ISOL, // Node not part of Edge
36 CONN, // Edge first and last nodes
37 TRNK, // Edge truncated polygon nodes
38 DPTH // Sounding nodes
39 }
40
41 public static class Snode { // All coordinates in map
42 public double lat; // Latitude in radians
43 public double lon; // Longitude in radians
44 public Nflag flg; // Role of node
45 public double val; // Optional value
46
47 public Snode() {
48 flg = Nflag.ANON;
49 lat = 0;
50 lon = 0;
51 val = 0;
52 }
53
54 public Snode(double ilat, double ilon) {
55 flg = Nflag.ANON;
56 lat = ilat;
57 lon = ilon;
58 val = 0;
59 }
60
61 public Snode(double ilat, double ilon, Nflag iflg) {
62 lat = ilat;
63 lon = ilon;
64 flg = iflg;
65 val = 0;
66 }
67
68 public Snode(double ilat, double ilon, double ival) {
69 flg = Nflag.DPTH;
70 lat = ilat;
71 lon = ilon;
72 val = ival;
73 }
74 }
75
76 public static class Edge { // A polyline segment
77 public long first; // First CONN node
78 public long last; // Last CONN node
79 public ArrayList<Long> nodes; // Inner ANON nodes
80
81 public Edge() {
82 first = 0;
83 last = 0;
84 nodes = new ArrayList<>();
85 }
86 }
87
88 public enum Rflag {
89 UNKN, MASTER, SLAVE
90 }
91
92 public static class Reln {
93 public long id;
94 public Rflag reln;
95 public Reln(long i, Rflag r) {
96 id = i;
97 reln = r;
98 }
99 }
100
101 public static class RelTab extends ArrayList<Reln> {
102 public RelTab() {
103 super();
104 }
105 }
106
107 public static class ObjTab extends HashMap<Integer, AttMap> {
108 public ObjTab() {
109 super();
110 }
111 }
112
113 public static class ObjMap extends EnumMap<Obj, ObjTab> {
114 public ObjMap() {
115 super(Obj.class);
116 }
117 }
118
119 public static class AttMap extends HashMap<Att, AttVal<?>> {
120 public AttMap() {
121 super();
122 }
123 }
124
125 public static class NodeTab extends HashMap<Long, Snode> {
126 public NodeTab() {
127 super();
128 }
129 }
130
131 public static class EdgeTab extends HashMap<Long, Edge> {
132 public EdgeTab() {
133 super();
134 }
135 }
136
137 public static class FtrMap extends EnumMap<Obj, ArrayList<Feature>> {
138 public FtrMap() {
139 super(Obj.class);
140 }
141 }
142
143 public static class FtrTab extends HashMap<Long, Feature> {
144 public FtrTab() {
145 super();
146 }
147 }
148
149 public static class Prim { // Spatial element
150 public long id; // Snode ID for POINTs, Edge ID for LINEs & AREAs)
151 public boolean forward; // Direction of vector used (LINEs & AREAs)
152 public boolean outer; // Exterior/Interior boundary (AREAs)
153 public boolean trunc; // Cell limit truncation
154 public Prim() {
155 id = 0; forward = true; outer = true; trunc = false;
156 }
157
158 public Prim(long i) {
159 id = i; forward = true; outer = true; trunc = false;
160 }
161
162 public Prim(long i, boolean o) {
163 id = i; forward = true; outer = o; trunc = false;
164 }
165
166 public Prim(long i, boolean f, boolean o) {
167 id = i; forward = f; outer = o; trunc = false;
168 }
169
170 public Prim(long i, boolean f, boolean o, boolean t) {
171 id = i; forward = f; outer = o; trunc = t;
172 }
173 }
174
175 public static class Comp { // Composite spatial element
176 public long ref; // ID of Comp
177 public int size; // Number of Prims in this Comp
178 public Comp(long r, int s) {
179 ref = r;
180 size = s;
181 }
182 }
183
184 public enum Pflag {
185 NOSP, POINT, LINE, AREA
186 }
187
188 public static class Geom { // Geometric structure of feature
189 public Pflag prim; // Geometry type
190 public ArrayList<Prim> elems; // Ordered list of elements
191 public int outers; // Number of outers
192 public int inners; // Number of inners
193 public ArrayList<Comp> comps; // Ordered list of compounds
194 public double area; // Area of feature
195 public double length; // Length of feature
196 public Snode centre; // Centre of feature
197 public Geom(Pflag p) {
198 prim = p;
199 elems = new ArrayList<>();
200 outers = inners = 0;
201 comps = new ArrayList<>();
202 area = 0;
203 length = 0;
204 centre = new Snode();
205 }
206 }
207
208 public static class Feature {
209 public long id; // Ref for this feature
210 public Rflag reln; // Relationship status
211 public Geom geom; // Geometry data
212 public Obj type; // Feature type
213 public AttMap atts; // Feature attributes
214 public RelTab rels; // Related objects
215 public ObjMap objs; // Slave object attributes
216
217 Feature() {
218 id = 0;
219 reln = Rflag.UNKN;
220 geom = new Geom(Pflag.NOSP);
221 type = Obj.UNKOBJ;
222 atts = new AttMap();
223 rels = new RelTab();
224 objs = new ObjMap();
225 }
226 }
227
228 public MapBounds bounds;
229 public NodeTab nodes;
230 public EdgeTab edges;
231 public FtrMap features;
232 public FtrTab index;
233 public long xref;
234
235 private long cref;
236 private Feature feature;
237 private Edge edge;
238 private ArrayList<KeyVal<?>> osm;
239 private boolean sea;
240
241 public S57map(boolean s) {
242 sea = s;
243 nodes = new NodeTab(); // All nodes in map
244 edges = new EdgeTab(); // All edges in map
245 feature = new Feature(); // Current feature being built
246 features = new FtrMap(); // All features in map, grouped by type
247 index = new FtrTab(); // Feature look-up table
248 bounds = new MapBounds();
249 cref = 0x0000ffffffff0000L; // Compound reference generator
250 xref = 0x0fff000000000000L; // Extras reference generator
251 }
252
253 // S57 map building methods
254
255 public void newNode(long id, double lat, double lon, Nflag flag) {
256 nodes.put(id, new Snode(Math.toRadians(lat), Math.toRadians(lon), flag));
257 if (flag == Nflag.ANON) {
258 edge.nodes.add(id);
259 }
260 }
261
262 public void newNode(long id, double lat, double lon, double depth) {
263 nodes.put(id, new Snode(Math.toRadians(lat), Math.toRadians(lon), depth));
264 }
265
266 public void newFeature(long id, Pflag p, long objl) {
267 feature = new Feature();
268 Obj obj = S57obj.decodeType(objl);
269 feature.geom = new Geom(p);
270 feature.type = obj;
271 if (obj != Obj.UNKOBJ) {
272 index.put(id, feature);
273 feature.id = id;
274 }
275 }
276
277 public void refObj(long id, int rind) {
278 Rflag r = Rflag.UNKN;
279 switch (rind) {
280 case 1:
281 r = Rflag.MASTER;
282 break;
283 case 2:
284 r = Rflag.SLAVE;
285 break;
286 case 3:
287 r = Rflag.UNKN;
288 break;
289 }
290 feature.rels.add(new Reln(id, r));
291 }
292
293 public void endFeature() {
294
295 }
296
297 public void newAtt(long attl, String atvl) {
298 Att att = S57att.decodeAttribute(attl);
299 AttVal<?> val = S57val.decodeValue(atvl, att);
300 feature.atts.put(att, val);
301 }
302
303 public void newPrim(long id, long ornt, long usag) {
304 feature.geom.elems.add(new Prim(id, (ornt != 2), (usag != 2)));
305 }
306
307 public void addConn(long id, int topi) {
308 if (topi == 1) {
309 edge.first = id;
310 } else {
311 edge.last = id;
312 }
313 }
314
315 public void newEdge(long id) {
316 edge = new Edge();
317 edges.put(id, edge);
318 }
319
320 public void endFile() {
321 for (long id : index.keySet()) {
322 Feature feature = index.get(id);
323 sortGeom(feature);
324 for (Reln reln : feature.rels) {
325 Feature rel = index.get(reln.id);
326 if (cmpGeoms(feature.geom, rel.geom)) {
327 switch (reln.reln) {
328 case SLAVE:
329 feature.reln = Rflag.MASTER;
330 break;
331 default:
332 feature.reln = Rflag.UNKN;
333 break;
334 }
335 rel.reln = reln.reln;
336 } else {
337 reln.reln = Rflag.UNKN;
338 }
339 }
340 }
341 for (long id : index.keySet()) {
342 Feature feature = index.get(id);
343 if (feature.reln == Rflag.UNKN) {
344 feature.reln = Rflag.MASTER;
345 }
346 if ((feature.type != Obj.UNKOBJ) && (feature.reln == Rflag.MASTER)) {
347 if (features.get(feature.type) == null) {
348 features.put(feature.type, new ArrayList<Feature>());
349 }
350 features.get(feature.type).add(feature);
351 }
352 }
353 for (long id : index.keySet()) {
354 Feature feature = index.get(id);
355 for (Reln reln : feature.rels) {
356 Feature rel = index.get(reln.id);
357 if (rel.reln == Rflag.SLAVE) {
358 if (feature.objs.get(rel.type) == null) {
359 feature.objs.put(rel.type, new ObjTab());
360 }
361 ObjTab tab = feature.objs.get(rel.type);
362 int ix = tab.size();
363 tab.put(ix, rel.atts);
364 }
365 }
366 }
367 }
368
369 // OSM map building methods
370
371 public void addNode(long id, double lat, double lon) {
372 nodes.put(id, new Snode(Math.toRadians(lat), Math.toRadians(lon)));
373 feature = new Feature();
374 feature.id = id;
375 feature.reln = Rflag.UNKN;
376 feature.geom.prim = Pflag.POINT;
377 feature.geom.elems.add(new Prim(id));
378 edge = null;
379 osm = new ArrayList<>();
380 }
381
382 public void addEdge(long id) {
383 feature = new Feature();
384 feature.id = id;
385 feature.reln = Rflag.UNKN;
386 feature.geom.prim = Pflag.LINE;
387 feature.geom.elems.add(new Prim(id));
388 edge = new Edge();
389 osm = new ArrayList<>();
390 }
391
392 public void addToEdge(long node) {
393 if (edge.first == 0) {
394 edge.first = node;
395 nodes.get(node).flg = Nflag.CONN;
396 } else {
397 if (edge.last != 0) {
398 edge.nodes.add(edge.last);
399 }
400 edge.last = node;
401 }
402 }
403
404 public void addArea(long id) {
405 feature = new Feature();
406 feature.id = id;
407 feature.reln = Rflag.UNKN;
408 feature.geom.prim = Pflag.AREA;
409 edge = null;
410 osm = new ArrayList<>();
411 }
412
413 public void addToArea(long id, boolean outer) {
414 feature.geom.elems.add(new Prim(id, outer));
415 }
416
417 public void addTag(String key, String val) {
418 feature.reln = Rflag.MASTER;
419 String[] subkeys = key.split(":");
420 if ((subkeys.length > 1) && subkeys[0].equals("seamark")) {
421 Obj obj = S57obj.enumType(subkeys[1]);
422 if ((subkeys.length > 2) && (obj != Obj.UNKOBJ)) {
423 int idx = 0;
424 Att att = Att.UNKATT;
425 try {
426 idx = Integer.parseInt(subkeys[2]);
427 if (subkeys.length == 4) {
428 att = s57.S57att.enumAttribute(subkeys[3], obj);
429 }
430 } catch (Exception e) {
431 att = S57att.enumAttribute(subkeys[2], obj);
432 }
433 ObjTab objs = feature.objs.get(obj);
434 if (objs == null) {
435 objs = new ObjTab();
436 feature.objs.put(obj, objs);
437 }
438 AttMap atts = objs.get(idx);
439 if (atts == null) {
440 atts = new AttMap();
441 objs.put(idx, atts);
442 }
443 AttVal<?> attval = S57val.convertValue(val, att);
444 if (attval.val != null) {
445 if (att == Att.VALSOU) {
446 Snode node = nodes.get(feature.geom.elems.get(0).id);
447 node.val = (Double) attval.val;
448 }
449 atts.put(att, attval);
450 }
451 } else {
452 if (subkeys[1].equals("type")) {
453 obj = S57obj.enumType(val);
454 feature.type = obj;
455 ObjTab objs = feature.objs.get(obj);
456 if (objs == null) {
457 objs = new ObjTab();
458 feature.objs.put(obj, objs);
459 }
460 AttMap atts = objs.get(0);
461 if (atts == null) {
462 atts = new AttMap();
463 objs.put(0, atts);
464 }
465 if ((obj == Obj.SOUNDG) && (feature.geom.prim == Pflag.POINT)) {
466 Snode node = nodes.get(feature.geom.elems.get(0).id);
467 node.flg = Nflag.DPTH;
468 }
469 } else {
470 if (obj != Obj.UNKOBJ) {
471 if (val.equals("yes")) {
472 ObjTab objs = feature.objs.get(obj);
473 if (objs == null) {
474 objs = new ObjTab();
475 feature.objs.put(obj, objs);
476 }
477 }
478 } else {
479 Att att = S57att.enumAttribute(subkeys[1], Obj.UNKOBJ);
480 if (att != Att.UNKATT) {
481 AttVal<?> attval = S57val.convertValue(val, att);
482 if (attval.val != null)
483 feature.atts.put(att, attval);
484 }
485 }
486 }
487 }
488 } else if (!sea) {
489 S57osm.OSMtag(osm, key, val);
490 }
491 }
492
493 public void tagsDone(long id) {
494 switch (feature.geom.prim) {
495 case POINT:
496 Snode node = nodes.get(id);
497 if ((node.flg != Nflag.CONN) && (node.flg != Nflag.DPTH) && (!feature.objs.isEmpty() || !osm.isEmpty())) {
498 node.flg = Nflag.ISOL;
499 }
500 break;
501 case LINE:
502 edges.put(id, edge);
503 nodes.get(edge.first).flg = Nflag.CONN;
504 nodes.get(edge.last).flg = Nflag.CONN;
505 if (edge.first == edge.last) {
506 feature.geom.prim = Pflag.AREA;
507 }
508 break;
509 case AREA:
510 break;
511 default:
512 break;
513 }
514 if (sortGeom(feature) && !((edge != null) && (edge.last == 0))) {
515 if (feature.type != Obj.UNKOBJ) {
516 index.put(id, feature);
517 if (features.get(feature.type) == null) {
518 features.put(feature.type, new ArrayList<Feature>());
519 }
520 features.get(feature.type).add(feature);
521 }
522 for (KeyVal<?> kvx : osm) {
523 Feature base = new Feature();
524 base.reln = Rflag.MASTER;
525 base.geom = feature.geom;
526 base.type = kvx.obj;
527 ObjTab objs = new ObjTab();
528 base.objs.put(kvx.obj, objs);
529 AttMap atts = new AttMap();
530 objs.put(0, atts);
531 if (kvx.att != Att.UNKATT) {
532 atts.put(kvx.att, new AttVal<>(kvx.conv, kvx.val));
533 }
534 index.put(++xref, base);
535 if (features.get(kvx.obj) == null) {
536 features.put(kvx.obj, new ArrayList<Feature>());
537 }
538 features.get(kvx.obj).add(base);
539 }
540 /* if (!osm.isEmpty()) {
541 if (feature.type == Obj.UNKOBJ) {
542 feature.type = osm.obj;
543 ObjTab objs = feature.objs.get(osm.obj);
544 if (objs == null) {
545 objs = new ObjTab();
546 feature.objs.put(osm.obj, objs);
547 }
548 AttMap atts = objs.get(0);
549 if (atts == null) {
550 atts = new AttMap();
551 objs.put(0, atts);
552 }
553 if (osm.att != Att.UNKATT) {
554 atts.put(osm.att, new AttVal<>(osm.conv, osm.val));
555 }
556 } else {
557 Feature base = new Feature();
558 base.reln = Rflag.MASTER;
559 base.geom = feature.geom;
560 base.type = osm.obj;
561 ObjTab objs = new ObjTab();
562 base.objs.put(osm.obj, objs);
563 AttMap atts = new AttMap();
564 objs.put(0, atts);
565 if (osm.att != Att.UNKATT) {
566 atts.put(osm.att, new AttVal<>(osm.conv, osm.val));
567 }
568 index.put(++xref, base);
569 if (features.get(osm.obj) == null) {
570 features.put(osm.obj, new ArrayList<Feature>());
571 }
572 features.get(osm.obj).add(base);
573 }
574 }*/
575 }
576 }
577
578 public void mapDone() {
579 if (!sea) {
580 S57box.bBox(this);
581 }
582 }
583
584 // Utility methods
585
586 public boolean sortGeom(Feature feature) {
587 try {
588 Geom sort = new Geom(feature.geom.prim);
589 long first = 0;
590 long last = 0;
591 Comp comp = null;
592 boolean next = true;
593 feature.geom.length = 0;
594 feature.geom.area = 0;
595 if (feature.geom.elems.isEmpty()) {
596 return false;
597 }
598 if (feature.geom.prim == Pflag.POINT) {
599 feature.geom.centre = nodes.get(feature.geom.elems.get(0).id);
600 return true;
601 }
602 Geom outer = new Geom(feature.geom.prim);
603 Geom inner = new Geom(feature.geom.prim);
604 for (Prim prim : feature.geom.elems) {
605 if (prim.outer) {
606 outer.elems.add(prim);
607 } else {
608 inner.elems.add(prim);
609 }
610 }
611 boolean outin = true;
612 int sweep = outer.elems.size();
613 if (sweep == 0) {
614 return false;
615 }
616 int prev = sweep;
617 int top = 0;
618 while (!outer.elems.isEmpty()) {
619 Prim prim = outer.elems.remove(0);
620 Edge edge = edges.get(prim.id);
621 if (edge == null) {
622 return false;
623 }
624 if (next == true) {
625 next = false;
626 first = edge.first;
627 last = edge.last;
628 prim.forward = true;
629 sort.elems.add(prim);
630 if (prim.outer) {
631 sort.outers++;
632 } else {
633 sort.inners++;
634 }
635 comp = new Comp(cref++, 1);
636 sort.comps.add(comp);
637 } else {
638 if (edge.first == last) {
639 sort.elems.add(prim);
640 last = edge.last;
641 prim.forward = true;
642 comp.size++;
643 } else if (edge.last == first) {
644 sort.elems.add(top, prim);
645 first = edge.first;
646 prim.forward = true;
647 comp.size++;
648 } else if (edge.last == last) {
649 sort.elems.add(prim);
650 last = edge.first;
651 prim.forward = false;
652 comp.size++;
653 } else if (edge.first == first) {
654 sort.elems.add(top, prim);
655 first = edge.last;
656 prim.forward = false;
657 comp.size++;
658 } else {
659 outer.elems.add(prim);
660 }
661 }
662 if (--sweep == 0) {
663 sweep = outer.elems.size();
664 if ((sweep == 0) || (sweep == prev)) {
665 if ((sort.prim == Pflag.AREA) && (first != last)) {
666 return false;
667 }
668 if (outin) {
669 if (sweep != 0) {
670 return false;
671 }
672 outer = inner;
673 outin = false;
674 sweep = outer.elems.size();
675 }
676 next = true;
677 top = sort.elems.size();
678 }
679 prev = sweep;
680 }
681 }
682 if ((sort.prim == Pflag.LINE) && (sort.outers == 1) && (sort.inners == 0) && (first == last)) {
683 sort.prim = Pflag.AREA;
684 }
685 feature.geom = sort;
686 if (feature.geom.prim == Pflag.AREA) {
687 int ie = 0;
688 int ic = 0;
689 while (ie < feature.geom.elems.size()) {
690 double area = calcArea(feature.geom, ic);
691 if (ie == 0)
692 feature.geom.area = Math.abs(area) * 3444 * 3444;
693 if (((ie == 0) && (area < 0.0)) || ((ie > 0) && (area >= 0.0))) {
694 ArrayList<Prim> tmp = new ArrayList<>();
695 for (int i = 0; i < feature.geom.comps.get(ic).size; i++) {
696 Prim p = feature.geom.elems.remove(ie);
697 p.forward = !p.forward;
698 tmp.add(0, p);
699 }
700 feature.geom.elems.addAll(ie, tmp);
701 }
702 ie += feature.geom.comps.get(ic).size;
703 ic++;
704 }
705 }
706 feature.geom.length = calcLength(feature.geom);
707 feature.geom.centre = calcCentroid(feature);
708 return true;
709 } catch (Exception e) {
710 return false;
711 }
712 }
713
714 public boolean cmpGeoms(Geom g1, Geom g2) {
715 return ((g1.prim == g2.prim) && (g1.outers == g2.outers) && (g1.inners == g2.inners) && (g1.elems.size() == g2.elems.size()));
716 }
717
718 public class EdgeIterator {
719 Edge edge;
720 boolean forward;
721 ListIterator<Long> it;
722
723 public EdgeIterator(Edge e, boolean dir) {
724 edge = e;
725 forward = dir;
726 it = null;
727 }
728
729 public boolean hasNext() {
730 return (edge != null);
731 }
732
733 public long nextRef() {
734 long ref = 0;
735 if (forward) {
736 if (it == null) {
737 ref = edge.first;
738 it = edge.nodes.listIterator();
739 } else {
740 if (it.hasNext()) {
741 ref = it.next();
742 } else {
743 ref = edge.last;
744 edge = null;
745 }
746 }
747 } else {
748 if (it == null) {
749 ref = edge.last;
750 it = edge.nodes.listIterator(edge.nodes.size());
751 } else {
752 if (it.hasPrevious()) {
753 ref = it.previous();
754 } else {
755 ref = edge.first;
756 edge = null;
757 }
758 }
759 }
760 return ref;
761 }
762
763 public Snode next() {
764 return nodes.get(nextRef());
765 }
766 }
767
768 public class GeomIterator {
769 Geom geom;
770 Prim prim;
771 EdgeIterator eit;
772 ListIterator<S57map.Prim> ite;
773 ListIterator<Comp> itc;
774 Comp comp;
775 int ec;
776 long lastref;
777
778 public GeomIterator(Geom g) {
779 geom = g;
780 lastref = 0;
781 ite = geom.elems.listIterator();
782 itc = geom.comps.listIterator();
783 }
784
785 public boolean hasComp() {
786 return (itc.hasNext());
787 }
788
789 public long nextComp() {
790 comp = itc.next();
791 ec = comp.size;
792 lastref = 0;
793 return comp.ref;
794 }
795
796 public boolean hasEdge() {
797 return (ec > 0) && ite.hasNext();
798 }
799
800 public long nextEdge() {
801 prim = ite.next();
802 eit = new EdgeIterator(edges.get(prim.id), prim.forward);
803 ec--;
804 return prim.id;
805 }
806
807 public boolean hasNode() {
808 return (eit.hasNext());
809 }
810
811 public long nextRef(boolean all) {
812 long ref = eit.nextRef();
813 if (!all && (ref == lastref)) {
814 ref = eit.nextRef();
815 }
816 lastref = ref;
817 return ref;
818 }
819
820 public long nextRef() {
821 return nextRef(false);
822 }
823
824 public Snode next() {
825 return nodes.get(nextRef());
826 }
827 }
828
829 double calcArea(Geom geom, int comp) {
830 Snode node;
831 double lat, lon, llon, llat;
832 lat = lon = llon = llat = 0;
833 double sigma = 0;
834 GeomIterator git = new GeomIterator(geom);
835 for (int i = 0; i <= comp; i++) {
836 if (git.hasComp()) {
837 git.nextComp();
838 while (git.hasEdge()) {
839 git.nextEdge();
840 while (git.hasNode()) {
841 node = git.next();
842 if (node == null)
843 continue;
844 llon = lon;
845 llat = lat;
846 lat = node.lat;
847 lon = node.lon;
848 sigma += (lon * Math.sin(llat)) - (llon * Math.sin(lat));
849 }
850 }
851 if (i != comp)
852 sigma = lat = lon = llon = llat = 0;
853 }
854 }
855 return sigma / 2.0;
856 }
857
858 double calcLength(Geom geom) {
859 Snode node;
860 double lat, lon, llon, llat;
861 lat = lon = llon = llat = 0;
862 double sigma = 0;
863 boolean first = true;
864 GeomIterator git = new GeomIterator(geom);
865 while (git.hasComp()) {
866 git.nextComp();
867 while (git.hasEdge()) {
868 git.nextEdge();
869 while (git.hasNode()) {
870 node = git.next();
871 if (first) {
872 first = false;
873 lat = node.lat;
874 lon = node.lon;
875 } else if (node != null) {
876 llat = lat;
877 llon = lon;
878 lat = node.lat;
879 lon = node.lon;
880 sigma += Math.acos(Math.sin(lat) * Math.sin(llat) + Math.cos(lat) * Math.cos(llat) * Math.cos(llon - lon));
881 }
882 }
883 }
884 }
885 return sigma * 3444;
886 }
887
888 Snode calcCentroid(Feature feature) {
889 double lat, lon, slat, slon, llat, llon;
890 llat = llon = lat = lon = slat = slon = 0;
891 double sarc = 0;
892 boolean first = true;
893 switch (feature.geom.prim) {
894 case POINT:
895 return nodes.get(feature.geom.elems.get(0).id);
896 case LINE:
897 GeomIterator git = new GeomIterator(feature.geom);
898 while (git.hasComp()) {
899 git.nextComp();
900 while (git.hasEdge()) {
901 git.nextEdge();
902 while (git.hasNode()) {
903 Snode node = git.next();
904 if (node == null) continue;
905 lat = node.lat;
906 lon = node.lon;
907 if (first) {
908 first = false;
909 } else {
910 sarc += Math.acos(Math.cos(lon - llon) * Math.cos(lat - llat));
911 }
912 llat = lat;
913 llon = lon;
914 }
915 }
916 }
917 double harc = sarc / 2;
918 sarc = 0;
919 first = true;
920 git = new GeomIterator(feature.geom);
921 while (git.hasComp()) {
922 git.nextComp();
923 while (git.hasEdge()) {
924 git.nextEdge();
925 while (git.hasNode()) {
926 Snode node = git.next();
927 if (node == null) continue;
928 lat = node.lat;
929 lon = node.lon;
930 if (first) {
931 first = false;
932 } else {
933 sarc = Math.acos(Math.cos(lon - llon) * Math.cos(lat - llat));
934 if (sarc > harc)
935 break;
936 }
937 harc -= sarc;
938 llat = lat;
939 llon = lon;
940 }
941 }
942 }
943 return new Snode(llat + ((lat - llat) * harc / sarc), llon + ((lon - llon) * harc / sarc));
944 case AREA:
945 git = new GeomIterator(feature.geom);
946 while (git.hasComp()) {
947 git.nextComp();
948 while (git.hasEdge()) {
949 git.nextEdge();
950 while (git.hasNode()) {
951 Snode node = git.next();
952 lat = node.lat;
953 lon = node.lon;
954 if (first) {
955 first = false;
956 } else {
957 double arc = (Math.acos(Math.cos(lon - llon) * Math.cos(lat - llat)));
958 slat += ((lat + llat) / 2 * arc);
959 slon += ((lon + llon) / 2 * arc);
960 sarc += arc;
961 }
962 llon = lon;
963 llat = lat;
964 }
965 }
966 }
967 return new Snode((sarc > 0.0 ? slat / sarc : 0.0), (sarc > 0.0 ? slon / sarc : 0.0));
968 default:
969 }
970 return null;
971 }
972
973}
Note: See TracBrowser for help on using the repository browser.