Wersja działająca. Release.

This commit is contained in:
2026-02-06 20:16:40 +01:00
parent b8cfa7301a
commit fb7a210501
51 changed files with 1674 additions and 1783 deletions

View File

@@ -0,0 +1,204 @@
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() +
'}';
}
}