/** * This file is part of OSM2ShareNav * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * * Copyright (C) 2010 Harald Mueller */ package net.sharenav.osmToShareNav.area; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import net.sharenav.osmToShareNav.model.Bounds; import net.sharenav.osmToShareNav.model.Node; public class Outline { private ArrayList<Vertex> vertexList = new ArrayList<Vertex>(); private long wayId = -1; // private ArrayList<Vertex> ordered; public long getWayId() { return wayId; } public void setWayId(long wayId) { this.wayId = wayId; } public ArrayList<Vertex> getVertexList() { return vertexList; } public boolean isValid() { if (vertexList.size() < 2) { return false; } return true; } public void clean() { vertexList = new ArrayList<Vertex>(); } public void prepend(Vertex v) { vertexList.add(0, v); v.setOutline(this); } public void append(Vertex v) { vertexList.add(v); v.setOutline(this); } public boolean isClosed() { if (vertexList.size() < 1) { return false; } Vertex prev = null; Vertex first = null; first = vertexList.get(0); prev = vertexList.get(vertexList.size() - 1); if (first.equals(prev)) { return true; } return false; } public void connectPartWays(ArrayList<Outline> others) { boolean changed = false; // System.out.println("Entering connectPartWays"); do { changed = false; Iterator<Outline> i = others.iterator(); while (i.hasNext()) { Vertex last = null; Vertex first = null; last = vertexList.get(vertexList.size() - 1); first = vertexList.get(0); Outline o = i.next(); // System.out.println("Iterating, node: " + o.vertexList.get(0).getNode()); if (o == this) { // System.out.println("o == this"); continue; } if (!o.isClosed()) { // System.out.println("not o.isClosed()"); // System.out.println("last.getNode(): " + last.getNode()); // System.out.println("first.getNode(): " + first.getNode()); // System.out.println("vertexlist size: " + vertexList.size()); if (o.vertexList.get(0).getNode().equals(last.getNode())) { // System.out.println("found way connecting to end of outline, so append it"); changed = true; for (Vertex v : o.vertexList) { append(v); } i.remove(); } else if (o.vertexList.get(o.vertexList.size()-1).getNode().equals(last.getNode())) { // System.out.println("found way reverse connecting to end of outline, so append it"); changed = true; for (int loop = o.vertexList.size()-1; loop >= 0; loop--) { Vertex v = o.vertexList.get(loop); append(v); } i.remove(); } else if (o.vertexList.get(0).getNode().equals(first.getNode())) { // System.out.println("found way connecting to start of outline, so prepend it"); changed = true; for (Vertex v : o.vertexList) { prepend(v); } i.remove(); } else if (o.vertexList.get(o.vertexList.size()-1).getNode().equals(first.getNode())) { // System.out.println("found way reverse connecting to start of outline, so prepend it"); changed = true; for (int loop = o.vertexList.size()-1; loop >= 0; loop--) { Vertex v = o.vertexList.get(loop); prepend(v); } i.remove(); } } } } while (changed); } public void calcNextPrev() { if (vertexList == null || vertexList.size() == 0) { return; } Vertex prev = null; Vertex first = null; first = vertexList.get(0); prev = vertexList.get(vertexList.size() - 1); if (first.equals(prev)) { vertexList.remove(vertexList.size() - 1); } if (vertexList.size() < 3) { // this is a degenerated polygon make it empty vertexList.clear(); } for (Vertex v:vertexList) { v.setOutline(this); if (first == null) { first = v; prev = v; } else { v.setPrev(prev); prev.setNext(v); prev = v; } } first.setPrev(prev); prev.setNext(first); } // @SuppressWarnings("unchecked") // public List<Vertex> getLonOrdered() { // ArrayList<Vertex> ordered = (ArrayList<Vertex>) vertexList.clone(); // Collections.sort(ordered, new LonComperator()); // return ordered; // } @SuppressWarnings("unchecked") public Vertex getLonMin() { ArrayList<Vertex> ordered = (ArrayList<Vertex>) vertexList.clone(); return Collections.min(ordered, new LonComperator()); } // @SuppressWarnings("unchecked") // public List<Vertex> getOrdered(int dir) { //// return getLonOrdered(); // ArrayList<Vertex> ordered = (ArrayList<Vertex>) vertexList.clone(); // switch (dir) { // case 0: // Collections.sort(ordered, new DirectionComperator0()); // break; // case 1: // Collections.sort(ordered, new DirectionComperator1()); // break; // case 2: // Collections.sort(ordered, new DirectionComperator2()); // break; // default: // Collections.sort(ordered, new DirectionComperatorX()); // break; // } // return ordered; // } // public Vertex getMin(int dir) { ArrayList<Vertex> ordered = (ArrayList<Vertex>) vertexList.clone(); switch (dir) { case 0: return Collections.min(ordered, new DirectionComperator0()); case 1: return Collections.min(ordered, new DirectionComperator1()); case 2: return Collections.min(ordered, new DirectionComperator2()); default: return Collections.min(ordered, new DirectionComperatorX()); } } // public Vertex findVertexInside(Triangle triangle) { // float leftmost = Float.MAX_VALUE; // Vertex leftmostNode = null; // for (Vertex v:vertexList) { // if (triangle.isVertexInside(v)) { // float lon = v.getX(); // if (lon < leftmost) { // leftmost = lon; // leftmostNode = v; // } // } // } // return leftmostNode; // } public ArrayList<Vertex> findVertexInside(Triangle triangle, ArrayList<Vertex> ret) { for (int i=0; i<vertexList.size(); i++) { Vertex vertex = vertexList.get(i); if (triangle.isVertexInside(vertex)){ if (ret == null) { ret = new ArrayList<Vertex>(); } ret.add(vertex); } } return ret; } public void remove(Vertex v) { v.getPrev().setNext(v.getNext()); v.getNext().setPrev(v.getPrev()); vertexList.remove(v); } public int vertexCount() { return vertexList.size(); } @Override public String toString() { StringBuffer b = new StringBuffer(); for (Vertex n:vertexList) { b.append(n); } return b.toString(); } // public boolean isClockWise() { // boolean cw = isClockWise3(); // if (cw != isClockWise2()){ // System.out.println("2 and 3 not the same"); // } // return cw; // } /** * Check if this outline (polygone) is clockwise. Therfore we get the leftmost vertex and the * booth neighbors. This edge must be convex. * @return */ public boolean isClockWise() { calcNextPrev(); Vertex v = getLonMin(); Vertex vp = v.getPrev(); Vertex vn = v.getNext(); if (((v.getX()-vp.getX())*(vn.getY()-v.getY())-(v.getY()-vp.getY())*(vn.getX()-v.getX())) <0 ) { return true; } else { return false; } } /** * Check if this outline (polygone) is clockwise. Therfore we get the leftmost vertex and the * booth neighbors. This edge must be convex. * @return */ public boolean isClockWiseFast() { //calcNextPrev(); Vertex v = getLonMin(); Vertex vp = v.getPrev(); Vertex vn = v.getNext(); if (((v.getX()-vp.getX())*(vn.getY()-v.getY())-(v.getY()-vp.getY())*(vn.getX()-v.getX())) <0 ) { return true; } else { return false; } } /** * this one is only valid for convex polygon * @return */ public boolean isClockWise2() { float z = 0.0f; for (Vertex i : vertexList) { z += i.cross(i.getNext()); } if (z < 0) { return true; } else { return false; } } public boolean isClockWise1() { Vertex j, k; int count = 0; double z; if (vertexCount() < 3) { throw new IllegalArgumentException("polygone with < then 3 nodes is degenerated"); } for (Vertex i:vertexList){ j=i.getNext(); k=j.getNext(); z = (j.getX() - i.getX()) * (k.getY() - j.getY()) - (j.getY() - i.getY()) * (k.getX() - j.getX()); if (z < 0) { count--; } else if (z > 0) { count++; } } if (count > 0) { return true; } else if (count < 0) { return false; } else { System.err.println("Triangulation Error! this should never happen"); // throw new IllegalArgumentException("this should never happen"); return true; } } public Bounds extendBounds(Bounds b) { for (Vertex i:vertexList){ i.extendBounds(b); } return b; } /** * @param i * @return */ public Node getNode(int i) { return (vertexList.get(i).getNode()); } }