205 lines
7.8 KiB
Java
205 lines
7.8 KiB
Java
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. <p>
|
|
* k="natural" - v="water" | v="reservoir" | v="wetland" | v="wood"
|
|
*/
|
|
public EOSMNatural natural;
|
|
|
|
/**
|
|
* Tag ten oznacza rzekę lub ciek wodny opisywany liniowo.
|
|
* <p> Wyjątek: waterway=riverbank, który opisuje obszar.
|
|
* <p> 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. <p>
|
|
* k="water" - v="lake" | v="reservoir" | v="river" | v="canal" | v="cove" | v="lagoon" | v="pond"
|
|
*/
|
|
public EOSMWater water;
|
|
|
|
/**
|
|
* Tag oznacza obiekt obszarowy. <p>
|
|
* k="landuse" - v="forest" | v="residential" | v="commercial"
|
|
*/
|
|
public EOSMLanduse landuse;
|
|
|
|
/**
|
|
* Tag oznacza obiekt obszarowy. <p>
|
|
* k="landcover" - v="trees" | v="water" | v="grass"
|
|
*/
|
|
public EOSMLandcover landcover;
|
|
|
|
ArrayList<Way> outerWays = new ArrayList<Way>();
|
|
ArrayList<Way> innerWays = new ArrayList<Way>();
|
|
|
|
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<Way> generatePolygons(ArrayList<Way> wayList) {
|
|
ArrayList<Way> polygons = new ArrayList<Way>();
|
|
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() +
|
|
'}';
|
|
}
|
|
}
|