package pl.wat.ms4ds.terrain.osm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; /** * Bazowa klasa dla obiektów OpenStreetMap. */ public class Relation { private static final Logger logger = LoggerFactory.getLogger(Relation.class); public String id; /** * Tag oznacza obiekt obszarowy.

* k="natural" - v="water" | v="reservoir" | v="wetland" | v="wood" */ public EOSMNatural natural; /** * Tag ten oznacza rzekę lub ciek wodny opisywany liniowo. *

Wyjątek: waterway=riverbank, który opisuje obszar. *

k="waterway" - v="river" | v="riverbank" | v="stream" | v="canal" | v="drain" | v="ditch" */ public EOSMWaterway waterway; /** * Tag stosowany w połączeniu z tagiem obszarowym: natural=water.

* k="water" - v="lake" | v="reservoir" | v="river" | v="canal" | v="cove" | v="lagoon" | v="pond" */ public EOSMWater water; /** * Tag oznacza obiekt obszarowy.

* k="landuse" - v="forest" | v="residential" | v="commercial" */ public EOSMLanduse landuse; /** * Tag oznacza obiekt obszarowy.

* k="landcover" - v="trees" | v="water" | v="grass" */ public EOSMLandcover landcover; ArrayList outerWays = new ArrayList(); ArrayList innerWays = new ArrayList(); public Relation(String id) { this.id = id; } public Relation(Relation oryg) { this.id = oryg.id; } public void copyTags(Relation oryg) { this.id = oryg.id; this.natural = oryg.natural; this.waterway = oryg.waterway; this.water = oryg.water; this.landuse = oryg.landuse; this.landcover = oryg.landcover; } ArrayList generatePolygons(ArrayList wayList) { ArrayList polygons = new ArrayList(); Way newPolygon = new Way((String)null); int prevLast = -1; for (int iWay = 0; iWay < wayList.size(); iWay++) { Way testWay = wayList.get(iWay); if (testWay.nodes.size() < 2) { continue; } int currLast = testWay.nodes.size() - 1; Node currFirstNode = testWay.nodes.get(0); Node currLastNode = testWay.nodes.get(currLast); if (prevLast < 0) { // biezacy wielokat jeszcze nie zawiera wezlow // newPolygon = new Way((String)null); newPolygon.nodes = testWay.nodes; newPolygon.copyTags(testWay); if (currFirstNode == currLastNode) { // lamana jest wielokatem polygons.add(newPolygon); prevLast = -1; newPolygon = new Way((String)null); } else { prevLast = newPolygon.nodes.size() - 1; } } else { if (currFirstNode == currLastNode) { // !! Blad w danych - brak ciaglosci lamanych: poprzedni wielokat sie nie zamknal // lamana jest wielokatem, // newPolygon = new Way((String)null); newPolygon.nodes = testWay.nodes; newPolygon.copyTags(testWay); polygons.add(newPolygon); prevLast = -1; newPolygon = new Way((String)null); } else { // biezacy wielokat zawiera juz wezly Node prevFirstNode = newPolygon.nodes.get(0); Node prevLastNode = newPolygon.nodes.get(prevLast); if (currFirstNode == prevLastNode) { for (int jNode = 1; jNode < testWay.nodes.size(); jNode++) { newPolygon.nodes.add(testWay.nodes.get(jNode)); } if (currLastNode == prevFirstNode) { // lamana zamyka wielokat polygons.add(newPolygon); prevLast = -1; newPolygon = new Way((String)null); } else { // lamana nie zamyka jeszcze wielokata prevLast = newPolygon.nodes.size() - 1; } } else if (currLastNode == prevFirstNode) { // odwracam kolejnosc dodawanych wezlow z biezacej lamanej for (int jNode = 1; jNode < newPolygon.nodes.size(); jNode++) { testWay.nodes.add(newPolygon.nodes.get(jNode)); } newPolygon.nodes = testWay.nodes; // for (int jNode = currLast - 1; jNode >= 0; jNode--) { // newPolygon.nodes.add(testWay.nodes.get(jNode)); // } if (currFirstNode == prevLastNode) { // lamana zamyka wielokat polygons.add(newPolygon); prevLast = -1; newPolygon = new Way((String)null); } else { // lamana nie zamyka jeszcze wielokata prevLast = newPolygon.nodes.size() - 1; } } else { // !! Blad w danych - brak ciaglosci lamanych: poprzedni wielokat sie nie zamknal // lamana nowego obszaru // newPolygon = new Way((String)null); newPolygon.nodes = testWay.nodes; newPolygon.copyTags(testWay); prevLast = newPolygon.nodes.size() - 1; } } } } return polygons; } void writeAreaFeatureIntoSquares(EAreaFeature type) { for (Way way : outerWays) { // wpisanie w kwadraty danej cechy dla wielokatow opisujacych zewnetrzna powloke obszaru way.writeAreaFeatureIntoSquares(type, false); } for (Way way : innerWays) { // wykreslenie z kwadratow danej cechy dla wielokatow opisujacych wewnetrzne podobszary way.writeAreaFeatureIntoSquares(type, true); } } void removeSimilarNodes() { for (Way way : outerWays) { // wpisanie w kwadraty danej cechy dla wielokatow opisujacych zewnetrzna powloke obszaru way.removeSimilarNodes(); } for (Way way : innerWays) { // wykreslenie z kwadratow danej cechy dla wielokatow opisujacych wewnetrzne podobszary way.removeSimilarNodes(); } } void removeCollinearNodes(boolean isPolygon) { for (Way way : outerWays) { // wpisanie w kwadraty danej cechy dla wielokatow opisujacych zewnetrzna powloke obszaru way.removeCollinearNodes(isPolygon); } for (Way way : innerWays) { // wykreslenie z kwadratow danej cechy dla wielokatow opisujacych wewnetrzne podobszary way.removeCollinearNodes(isPolygon); } } void removeLastNodes() { for (Way way : outerWays) { // usunięcie powtórzenia węzła z wielokata definiującego obszar if (way.nodes.size() > 1) { way.nodes.remove(way.nodes.size() - 1); } } for (Way way : innerWays) { // usunięcie powtórzenia węzła z wielokata definiującego obszar if (way.nodes.size() > 1) { way.nodes.remove(way.nodes.size() - 1); } } } @Override public String toString() { return "Relation{id=" + id + ", outerWays.len=" + outerWays.size() + ", innerWays.len=" + innerWays.size() + '}'; } }