// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.namemanager.utils; import java.awt.Component; import java.awt.Window; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.openstreetmap.gui.jmapviewer.Coordinate; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.Way; import org.openstreetmap.josm.plugins.namemanager.NameManagerPlugin; import org.openstreetmap.josm.plugins.namemanager.countryData.Country; import org.openstreetmap.josm.plugins.namemanager.countryData.CountryDataMemory; import org.openstreetmap.josm.tools.Pair; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public final class NameManagerUtils { private NameManagerUtils() { // Hide default constructor for utilities classes } /** * @return the top {@link Window} of the JOSM application. */ public static Window getTopWindow() { Component component = Main.parent; if (component != null) { while (component.getParent() != null) { component = component.getParent(); } if (component instanceof Window) return (Window) component; } return null; } public static List<Way> getWaysInsideSelectedArea(Way areaBorder) { List<Way> waysInsideSelectedArea = new ArrayList<>(); if (areaBorder != null) { Coordinate topLeftCorner = getTopLeftCorener(areaBorder); List<Pair<Node, Node>> areaBorderLines = areaBorder.getNodePairs(true); Collection<Way> ways = Main.getLayerManager().getEditDataSet().getWays(); ways: for (Way way : ways) { if (areaBorder == way) { continue ways; } pairs: for (Pair<Node, Node> pair : way.getNodePairs(false)) { double x1Pair = pair.a.getCoor().getX(); double y1Pair = pair.a.getCoor().getY(); double x2Pair = pair.b.getCoor().getX(); double y2Pair = pair.b.getCoor().getY(); double aPair = 0.0; double bPair = 0.0; double cPair = 0.0; boolean pairPerpendicular = false; if (x2Pair == x1Pair || y2Pair == y1Pair) { pairPerpendicular = true; } else { aPair = 1 / (x2Pair - x1Pair); bPair = -1 / (y2Pair - y1Pair); cPair = y1Pair / (y2Pair - y1Pair) - x1Pair / (x2Pair - x1Pair); } int crossCount = 0; areaLine: for (Pair<Node, Node> areaLine : areaBorderLines) { double x1Line = areaLine.a.getCoor().getX(); double y1Line = areaLine.a.getCoor().getY(); double x2Line = areaLine.b.getCoor().getX(); double y2Line = areaLine.b.getCoor().getY(); boolean areaLinePerpendicular = false; double aLine = 0.0; double bLine = 0.0; double cLine = 0.0; if (x2Line == x1Line || y2Line == y1Line) { areaLinePerpendicular = true; } else { aLine = 1 / (x2Line - x1Line); bLine = -1 / (y2Line - y1Line); cLine = y1Line / (y2Line - y1Line) - x1Line / (x2Line - x1Line); } if (pairPerpendicular && areaLinePerpendicular) { if (x1Pair == x2Pair) { if (x1Line == x2Line) { if (x1Pair == x1Line) { if ((y1Pair - y1Line) * (y1Pair - y2Line) < 0.0 || (y2Pair - y1Line) * (y2Pair - y2Line) < 0.0 || (y1Line - y1Pair) * (y1Line - y2Pair) < 0.0 || (y2Line - y1Pair) * (y2Line - y2Pair) < 0.0) { waysInsideSelectedArea.add(way); continue ways; } } } else if (y1Line == y2Line) { if ((x1Pair - x1Line) * (x1Pair - x2Line) < 0.0 && (y1Line - y1Pair) * (y1Line - y2Pair) < 0.0) { waysInsideSelectedArea.add(way); continue ways; } } } else if (y1Pair == y2Pair) { if (x1Line == x2Line) { if ((y1Pair - y1Line) * (y1Pair - y2Line) < 0.0 && (x1Line - x1Pair) * (x1Line - x2Pair) < 0.0) { waysInsideSelectedArea.add(way); continue ways; } } else if (y1Line == y2Line) { if (y1Pair == y1Line) { if ((x1Pair - x1Line) * (x1Pair - x2Line) < 0.0 || (x2Pair - x1Line) * (x2Pair - x2Line) < 0.0 || (x1Line - x1Pair) * (x1Line - x2Pair) < 0.0 || (x2Line - x1Pair) * (x2Line - x2Pair) < 0.0) { waysInsideSelectedArea.add(way); continue ways; } } } } } else if (pairPerpendicular) { if (((aLine * x1Pair + bLine * y1Pair + cLine) * (aLine * x2Pair + bLine * y2Pair + cLine)) < 0.0) { if (x1Pair == x2Pair) { if ((x1Pair - x1Line) * (x1Pair - x2Line) < 0.0) { waysInsideSelectedArea.add(way); continue ways; } } else if (y1Pair == y2Pair) { if ((y1Pair - y1Line) * (y1Pair - y2Line) < 0.0) { waysInsideSelectedArea.add(way); continue ways; } } } } else if (areaLinePerpendicular) { if (((aPair * x1Line + bPair * y1Line + cPair) * (aPair * x2Line + bPair * y2Line + cPair)) < 0.0) { if (x1Line == x2Line) { if ((x1Line - x1Pair) * (x1Line - x2Pair) < 0.0) { waysInsideSelectedArea.add(way); continue ways; } } else if (y1Line == y2Line) { if ((y1Line - y1Pair) * (y1Line - y2Pair) < 0.0) { waysInsideSelectedArea.add(way); continue ways; } } } } else if (((aLine * x1Pair + bLine * y1Pair + cLine) * (aLine * x2Pair + bLine * y2Pair + cLine)) < 0.0 && ((aPair * x1Line + bPair * y1Line + cPair) * (aPair * x2Line + bPair * y2Line + cPair)) < 0.0) { waysInsideSelectedArea.add(way); continue ways; } Node raySource = null; double tlcX = topLeftCorner.getLon(); double tlcY = topLeftCorner.getLat(); if (x1Pair != tlcX && y1Pair != tlcY) { raySource = pair.a; } else if (x2Pair != tlcX && y2Pair != tlcY) { raySource = pair.b; } else { continue pairs; } if (raySource != null) { double rsX = raySource.getCoor().getX(); double rsY = raySource.getCoor().getY(); if (areaLinePerpendicular) { if (x1Line == x2Line) { if ((x1Line - rsX) * (x1Line - tlcX) > 0.0) { continue areaLine; } } else if (y1Line == y2Line) { if ((y1Line - rsY) * (y1Line - tlcY) > 0.0) { continue areaLine; } } } else if (((aLine * rsX + bLine * rsY + cLine) * (aLine * tlcX + bLine * tlcY + cLine)) > 0.0) { continue areaLine; } double aRay = 1 / (tlcX - rsX); double bRay = -1 / (tlcY - rsY); double cRay = rsY / (tlcY - rsY) - rsX / (tlcX - rsX); if (((aRay * x1Line + bRay * y1Line + cRay) * (aRay * x2Line + bRay * y2Line + cRay)) < 0.0) { crossCount++; } } } if (crossCount % 2 == 1) { waysInsideSelectedArea.add(way); continue ways; } } } } return waysInsideSelectedArea; } private static Coordinate getTopLeftCorener(Way way) { double x = Double.POSITIVE_INFINITY; double y = Double.NEGATIVE_INFINITY; List<Node> nodes = way.getNodes(); for (Node node : nodes) { if (node.getCoor().getX() < x) { x = node.getCoor().getX(); } if (node.getCoor().getY() > y) { y = node.getCoor().getY(); } } x--; y++; return new Coordinate(y, x); } public static Document parseCountries() { Document doc = null; DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db; try { db = dbf.newDocumentBuilder(); InputStream xml = NameManagerPlugin.class .getResourceAsStream("/resources/administrative-levels.xml"); doc = db.parse(xml); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return doc; } public static void prepareCountryDataMemoryCache(Document doc) { CountryDataMemory.instantiateCountryCache(); if (!CountryDataMemory.isEmpty()) { CountryDataMemory.clearCache(); } NodeList nodeList = doc.getElementsByTagName("country"); for (int i = 0; i < nodeList.getLength(); i++) { Element countryNode = (Element) nodeList.item(i); String countryName = countryNode.getAttributes().item(0).getNodeValue(); NodeList level1List = countryNode.getElementsByTagName("level1"); String level1 = "n/a"; if (level1List.getLength() == 1) { level1 = level1List.item(0).getTextContent(); } NodeList level2List = countryNode.getElementsByTagName("level2"); String level2 = "n/a"; if (level2List.getLength() == 1) { level2 = level2List.item(0).getTextContent(); } NodeList level3List = countryNode.getElementsByTagName("level3"); String level3 = "n/a"; if (level3List.getLength() == 1) { level3 = level3List.item(0).getTextContent(); } NodeList level4List = countryNode.getElementsByTagName("level4"); String level4 = "n/a"; if (level4List.getLength() == 1) { level4 = level4List.item(0).getTextContent(); } NodeList level5List = countryNode.getElementsByTagName("level5"); String level5 = "n/a"; if (level5List.getLength() == 1) { level5 = level5List.item(0).getTextContent(); } NodeList level6List = countryNode.getElementsByTagName("level6"); String level6 = "n/a"; if (level6List.getLength() == 1) { level6 = level6List.item(0).getTextContent(); } CountryDataMemory.addCountry(new Country(countryName, level1, level2, level3, level4, level5, level6)); } } }