/************************************************************************************
* 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;
}
}