/************************************************************************************ * Copyright (C) 2008 by Politehnica University of Bucharest and Rutgers University * All rights reserved. * Refer to LICENSE for terms and conditions of use. ***********************************************************************************/ package vnsim.vehicular.routePlan.selfRouted; import java.util.ArrayList; import java.io.Serializable; import vnsim.map.object.Cross; import vnsim.map.object.Globals; import vnsim.map.object.Point; import vnsim.map.object.Road; import vnsim.map.utils.GPSutil; public class RoadAreaUtils implements Serializable { /** serialVersionUID */ private static final long serialVersionUID = -5883719321862303634L; public ArrayList mainRoads; // indicii drumurilor principale // din Globals.map.roads public ArrayList distinctAreas; public RoadAreaUtils() { mainRoads = new ArrayList(); distinctAreas = new ArrayList(); } public void splitRoads() { int i, j, k; Road r; Point p; for (i = 0; i < Globals.map.roads.size(); i++) { r = Globals.map.roads.get(i); //if (((r.getRoadinfo())[1] == 49) || ((r.getRoadinfo())[1] == 50)) { // if (((r.getRoadinfo())[1] >= 49) || ((r.getRoadinfo())[1] <= 51)) { if (((r.getRoadinfo())[1] == 49)) { mainRoads.add(new Integer(i)); } } int dim = mainRoads.size(); System.out.println("I have: " + dim + " primary roads"); if (dim > 0) { for (i = 0; i < Globals.map.roads.size(); i++) { r = Globals.map.roads.get(i); for (j = 0; j < r.points.size(); j++) { p = r.points.get(j); p.areaCode = new AreaCode(dim); for (k = 0; k < dim; k++) { p.areaCode.code[k] = -1; } } } for (i = 0; i < mainRoads.size(); i++) { r = Globals.map.roads.get(mainRoads.get(i).intValue()); for (j = 0; j < r.points.size(); j++) { p = r.points.get(j); p.areaCode.code[i] = 2; } } } } public boolean inDirection(float xM1, float yM1, float xM2, float yM2, float xm1, float ym1, float xm2, float ym2) { float cosM, cosm, sinM, sinm; float dxM, dxm, dyM, dym; double angleM = 0.0, anglem = 0.0; dxM = xM2 - xM1; dxm = xm2 - xm1; dyM = yM2 - yM1; dym = ym2 - ym1; cosM = (dxM / ((float) (Math.sqrt((double) (dxM * dxM + dyM * dyM))))); cosm = (dxm / ((float) (Math.sqrt((double) (dxm * dxm + dym * dym))))); sinM = (dyM / ((float) (Math.sqrt((double) (dxM * dxM + dyM * dyM))))); sinm = (dym / ((float) (Math.sqrt((double) (dxm * dxm + dym * dym))))); // System.out.println(" "+(Math.sqrt((double) (xM1 * xM2 + yM1 * yM2)))+ // "..."+(Math.sqrt((double) (xm1 * xm2 + ym1 * ym2)))); if (cosM > 1.0f) { cosM = 1.0f; } if (cosm > 1.0f) { cosm = 1.0f; } if (cosM < -1.0f) { cosM = -1.0f; } if (cosm < -1.0f) { cosm = -1.0f; } if (sinM > 1.0f) { sinM = 1.0f; } if (sinm > 1.0f) { sinm = 1.0f; } if (sinM < -1.0f) { sinM = -1.0f; } if (sinm < -1.0f) { sinm = -1.0f; } // //First angle if (sinM == 0) { if (cosM > 0) { angleM = 0; } else { angleM = Math.PI; } } if (cosM == 0) { if (sinM > 0) { angleM = Math.PI / 2; } else { angleM = 0 - Math.PI / 2; } } if (sinM > 0 && cosM > 0) { angleM = Math.acos(cosM); } if (sinM < 0 && cosM < 0) { angleM = Math.acos(cosM); angleM = (Math.PI - angleM) + Math.PI; } if (sinM < 0 && cosM > 0) { angleM = Math.acos(cosM); angleM = Math.PI + Math.PI - angleM; } if (sinM > 0 && cosM < 0) { angleM = Math.acos(cosM); } // Second angle if (sinm == 0) { if (cosm > 0) { anglem = 0; } else { anglem = Math.PI; } } if (cosm == 0) { if (sinm > 0) { anglem = Math.PI / 2; } else { anglem = 0 - Math.PI / 2; } } if (sinm > 0 && cosm > 0) { anglem = Math.acos(cosm); } if (sinm < 0 && cosm < 0) { anglem = Math.acos(cosm); anglem = (Math.PI - anglem) + Math.PI; } if (sinm < 0 && cosm > 0) { anglem = Math.acos(cosm); anglem = Math.PI + Math.PI - anglem; } if (sinm > 0 && cosm < 0) { anglem = Math.acos(cosm); } // System.out.println("Unghi MARE=" + angleM + " si in grade" // + ((angleM * 180) / Math.PI)); // System.out.println("Unghi mic=" + anglem + " si in grade" // + ((anglem * 180) / Math.PI)); if (Math.abs(angleM - anglem) >= Math.PI) { if (anglem > angleM) { // on the left side return false; } else { // on the right side return true; } } else { if (anglem > angleM) { // on the right side return true; } else { // on the left side return false; } } } ArrayList currentMarks ; ArrayList nextMarks ; public void splitMap() { splitRoads(); currentMarks = new ArrayList(); nextMarks = new ArrayList(); int i, ii, j, k, l, mainRoadIdx; Road r, crossedRoad; Point p, cp; Cross c; java.awt.geom.Point2D.Float main1, main2, second1, second2; int idxM1, idxM2, idxS1, idxS2; Mark m; for (ii = 0; ii < mainRoads.size(); ii++) { mainRoadIdx = mainRoads.get(ii).intValue(); r = Globals.map.roads.get(mainRoadIdx); for (j = 0; j < r.crosses.size(); j++) { c = r.crosses.get(j); crossedRoad = Globals.map.roads.get(c.getCrossRoadIndex()); main1 = new java.awt.geom.Point2D.Float(); main2 = new java.awt.geom.Point2D.Float(); second1 = new java.awt.geom.Point2D.Float(); second2 = new java.awt.geom.Point2D.Float(); if (c.getPointIndex() == 0) { idxM1 = 0; idxM2 = 1; } else { if (c.getPointIndex() == r.points.size() - 1) { idxM1 = r.points.size() - 2; idxM2 = r.points.size() - 1; } else { idxM1 = c.getPointIndex() - 1; idxM2 = c.getPointIndex() + 1; } } if (c.getCrossPointIndex() == 0) { idxS1 = 0; idxS2 = 1; } else { if (c.getCrossPointIndex() == crossedRoad.points.size() - 1) { idxS1 = crossedRoad.points.size() - 2; idxS2 = crossedRoad.points.size() - 1; } else { idxS1 = c.getCrossPointIndex() - 1; idxS2 = c.getCrossPointIndex() + 1; } } main1.y = (float) GPSutil.getMetersLatitude( Globals.map.minPoint, r.points.get(idxM1)); main1.x = (float) GPSutil.getMetersLongitude( Globals.map.minPoint, r.points.get(idxM1)); main2.y = (float) GPSutil.getMetersLatitude( Globals.map.minPoint, r.points.get(idxM2)); main2.x = (float) GPSutil.getMetersLongitude( Globals.map.minPoint, r.points.get(idxM2)); second1.y = (float) GPSutil.getMetersLatitude( Globals.map.minPoint, crossedRoad.points.get(idxS1)); second1.x = (float) GPSutil.getMetersLongitude( Globals.map.minPoint, crossedRoad.points.get(idxS1)); second2.y = (float) GPSutil.getMetersLatitude( Globals.map.minPoint, crossedRoad.points.get(idxS2)); second2.x = (float) GPSutil.getMetersLongitude( Globals.map.minPoint, crossedRoad.points.get(idxS2)); crossedRoad.points.get(c.getCrossPointIndex()).areaCode.code[ii] = 2; if (inDirection(main1.x, main1.y, main2.x, main2.y, second1.x, second1.y, second2.x, second2.y)) { nextMarks .add(new Mark(ii, 0, c.getCrossRoadIndex(), idxS1)); nextMarks .add(new Mark(ii, 1, c.getCrossRoadIndex(), idxS2)); } else { nextMarks .add(new Mark(ii, 1, c.getCrossRoadIndex(), idxS1)); nextMarks .add(new Mark(ii, 0, c.getCrossRoadIndex(), idxS2)); } } // /////////////////////////////////////////////////////////////////////////// while (nextMarks.size() != 0) { currentMarks = nextMarks; nextMarks = new ArrayList(); for (i = 0; i < currentMarks.size(); i++) { m = currentMarks.get(i); if (m.pos >= mainRoads.size()) { System.out .println("Incorect position for area code!To many major roads!"); continue; } if (m.pos < 0) { System.out .println("Incorect position for area code!Negative value!"); continue; } r = Globals.map.roads.get(m.roadId); p = r.points.get(m.pointId); if (p.areaCode.code[m.pos] != -1) { continue; } else { p.areaCode.code[m.pos] = (byte) m.val; if (m.pointId == 0) { nextMarks.add(new Mark(m.pos, m.val, m.roadId, 1)); } else { if (m.pointId == r.points.size() - 1) { nextMarks.add(new Mark(m.pos, m.val, m.roadId, m.pointId - 1)); } else { nextMarks.add(new Mark(m.pos, m.val, m.roadId, m.pointId - 1)); nextMarks.add(new Mark(m.pos, m.val, m.roadId, m.pointId + 1)); } } for (j = 0; j < r.crosses.size(); j++) { c = r.crosses.get(j); cp = Globals.map.roads.get(c.getCrossRoadIndex()).points .get(c.getCrossPointIndex()); if (cp.equals(p)) { nextMarks.add(new Mark(m.pos, m.val, c .getCrossRoadIndex(), c .getCrossPointIndex())); } } } } } // /////////////////////////////////////////////////////////////////////////// } } public void selectDistinctRoadAreas() { int i, j, k; Road r; Point p; boolean found = false; for (i = 0; i < Globals.map.roads.size(); i++) { r = Globals.map.roads.get(i); for (j = 0; j < r.points.size(); j++) { p = r.points.get(j); // if(p.areaCode.code==null){ // continue; // } if (distinctAreas.size() != 0) { // if (!isOnBorder(p.areaCode.code)) { found = false; for (k = 0; k < distinctAreas.size(); k++) { if (distinctAreas.get(k).areaCodeString .equals(p.areaCode.areaCodeToString())) { found = true; p.areaCode.belongingTo = distinctAreas.get(k); p.areaCode.code = null; break; } } if (found == false) { p.areaCode.belongingTo = new MajorRoadArea(p.areaCode); p.areaCode.code = null; distinctAreas.add(p.areaCode.belongingTo); } // } } else { // if (!isOnBorder(p.areaCode.code)) { p.areaCode.belongingTo = new MajorRoadArea(p.areaCode); p.areaCode.code = null; distinctAreas.add(p.areaCode.belongingTo); // } } } } for (i = 0; i < distinctAreas.size(); i++) { distinctAreas.get(i).constructArea(); } } public void mergeAreas() { int i, j, k, u, v; Road r; Point p1, p2; ArrayList changed = new ArrayList(); ArrayList changedWith = new ArrayList(); ArrayList changedIdx = new ArrayList(); Cross c; for (i = 0; i < Globals.map.roads.size(); i++) { r = Globals.map.roads.get(i); if (i == 5360) { System.out.println("STACK"); } for (j = 0; j < r.points.size() - 1; j++) { p1 = r.points.get(j); p2 = r.points.get(j + 1); if (!p1.areaCode.belongingTo.areaCodeString .equals(p2.areaCode.belongingTo.areaCodeString)) { if ((!isOnBorder(p1.areaCode.belongingTo.areaCodeByte)) && (!isOnBorder(p2.areaCode.belongingTo.areaCodeByte))) { changed.add(new MajorRoadArea(p2.areaCode.belongingTo)); changedWith.add(new MajorRoadArea( p1.areaCode.belongingTo)); changedIdx.add(new Integer(this.distinctAreas .indexOf(p2.areaCode.belongingTo))); for (v = 0; v < changedWith.size() - 1; v++) { if (changedWith.get(v).areaCodeString .equals(p2.areaCode.belongingTo.areaCodeString)) { this.distinctAreas.get( changedIdx.get(v).intValue()).move( p1.areaCode.belongingTo); changedWith.get(v) .move(p1.areaCode.belongingTo); } } p2.areaCode.belongingTo.move(p1.areaCode.belongingTo); } } } for (j = 0; j < r.crosses.size(); j++) { c = r.crosses.get(j); p1 = r.points.get(c.getPointIndex()); p2 = Globals.map.roads.get(c.getCrossRoadIndex()).points.get(c .getCrossPointIndex()); if (!p1.areaCode.belongingTo.areaCodeString .equals(p2.areaCode.belongingTo.areaCodeString)) { if ((!isOnBorder(p1.areaCode.belongingTo.areaCodeByte)) && (!isOnBorder(p2.areaCode.belongingTo.areaCodeByte))) { changed.add(new MajorRoadArea(p2.areaCode.belongingTo)); changedWith.add(new MajorRoadArea( p1.areaCode.belongingTo)); changedIdx.add(new Integer(this.distinctAreas .indexOf(p2.areaCode.belongingTo))); for (v = 0; v < changedWith.size() - 1; v++) { if (changedWith.get(v).areaCodeString .equals(p2.areaCode.belongingTo.areaCodeString)) { this.distinctAreas.get( changedIdx.get(v).intValue()).move( p1.areaCode.belongingTo); changedWith.get(v) .move(p1.areaCode.belongingTo); } } p2.areaCode.belongingTo.move(p1.areaCode.belongingTo); } } } } // for (i = 0; i < changed.size(); i++) { // System.out.println(" **** " + changed.get(i).areaCodeString // + " cu " + changedWith.get(i).areaCodeString); // // } ArrayList borders; for (i = 0; i < mainRoads.size(); i++) { r = Globals.map.roads.get(mainRoads.get(i).intValue()); for (j = 0; j < r.points.size() - 1; j++) { p1 = r.points.get(j); p2 = r.points.get(j + 1); if (!p1.areaCode.belongingTo.areaCodeString .equals(p2.areaCode.belongingTo.areaCodeString)) { for (u = 0; u < changed.size(); u++) { k = -1; k = isOnBorderOf(p1.areaCode.belongingTo.areaCodeByte, changed.get(u).areaCodeByte); if (k > -1) { borders = getBordersOf(p1.areaCode.belongingTo.areaCodeByte); p1.areaCode.belongingTo.move(changedWith.get(u)); p1.areaCode.belongingTo.areaCodeByte[k] = 2; for (k = 0; k < borders.size(); k++) { p1.areaCode.belongingTo.areaCodeByte[borders .get(k).intValue()] = 2; } p1.areaCode.belongingTo.setStringValue(); } k = -1; k = isOnBorderOf(p2.areaCode.belongingTo.areaCodeByte, changed.get(u).areaCodeByte); if (k > -1) { borders = getBordersOf(p2.areaCode.belongingTo.areaCodeByte); p2.areaCode.belongingTo.move(changedWith.get(u)); for (k = 0; k < borders.size(); k++) { p2.areaCode.belongingTo.areaCodeByte[borders .get(k).intValue()] = 2; } p2.areaCode.belongingTo.setStringValue(); } } } } } } public boolean isOnBorder(byte[] area) { int i; for (i = 0; i < area.length; i++) { if (area[i] == 2) { return true; } } return false; } // /area1Code is the border of area2 public int isOnBorderOf(byte[] area1, byte[] area2) { int i; int j = -1; for (i = 0; i < area1.length; i++) { if (area1[i] != area2[i]) { if (area1[i] != 2) { return -1; } else { continue; } } } return 0; } public ArrayList getBordersOf(byte[] area1) { int i; ArrayList rez = new ArrayList(); int j = -1; for (i = 0; i < area1.length; i++) { if (area1[i] == 2) { rez.add(new Integer(i)); } } return rez; } public boolean inSameArea(byte[] area1, byte[] area2) { int i; if (area1.length != area2.length) { return false; } else { for (i = 0; i < area1.length; i++) { if (area1[i] != area2[i]) { if ((area1[i] != 2) && (area2[i] != 2)) { return false; } } } return true; } } public int getAreaFor(Point p) { int i; for (i = 0; i < distinctAreas.size(); i++) { if (distinctAreas.get(i).areaCodeString .equals(p.areaCode.belongingTo.areaCodeString)) { return i; } } return -1; } }