/*----------------------------------------------------------------------------------------------------------------
* CupCarbon: A Smart City & IoT Wireless Sensor Network Simulator
* www.cupcarbon.com
* ----------------------------------------------------------------------------------------------------------------
* Copyright (C) 2013-2017 CupCarbon
* ----------------------------------------------------------------------------------------------------------------
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*----------------------------------------------------------------------------------------------------------------
* CupCarbon U-One is part of the research project PERSEPTEUR supported by the
* French Agence Nationale de la Recherche ANR
* under the reference ANR-14-CE24-0017-01.
* ----------------------------------------------------------------------------------------------------------------
* This Class allows to calculate for a given sensor node a simple visibility based on a 2D environment
**/
package visibility;
import java.util.ArrayList;
import java.util.LinkedList;
import buildings.Building;
import buildings.BuildingList;
import device.SensorNode;
import geo_objects.GeoZone;
import geo_objects.GeoZoneList;
import map.MapLayer;
import math.Angle;
/**
* @author Ahcene Bounceur
* @version 1
*/
public class VisibilityZones2 extends Thread {
//-----------------------------------------------------------------------------------------
// The concerned Sensor Node
//-----------------------------------------------------------------------------------------
private SensorNode sensorNode ;
//-----------------------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------------------
public VisibilityZones2(SensorNode sensorNode) {
this.sensorNode = sensorNode;
}
//-----------------------------------------------------------------------------------------
// Running the process of calculation the visibility region (zone)
//-----------------------------------------------------------------------------------------
@Override
public void run() {
//-----------------------------------------------------------------------------------------
// The list of the points of the final visibility zone
//-----------------------------------------------------------------------------------------
ArrayList<double []> visibilityPointList = new ArrayList<double []>();
//-----------------------------------------------------------------------------------------
// The zone of interest
// We assume that the visibility is not infinite and we take a certain radius around
// the center of the sensor node
// Only the buildings that are around this region will be taken into account
// The other ones will be ignored for the current sensor node
//-----------------------------------------------------------------------------------------
int nPoint = 20;
GeoZone zoneOfInterest = new GeoZone(nPoint);
double step = 2.*Math.PI/nPoint;
double deg = 0.0;
for(int i = 0; i < nPoint; i++) {
zoneOfInterest.set(sensorNode.getLatitude()+0.001*Math.cos(deg), sensorNode.getLongitude()+0.0015*Math.sin(deg), 0, i);
deg += step;
}
//-----------------------------------------------------------------------------------------
// We create a list of building that are inside the zone of interest
// This will make the program and the calculation quick
//-----------------------------------------------------------------------------------------
LinkedList<Building> buildings = new LinkedList<Building>();
for(Building building : BuildingList.buildings) {
if(building.intersect(zoneOfInterest)) {
buildings.add(building);
}
}
//-----------------------------------------------------------------------------------------
// We will test that the edge which is formed by each point of the zoneOfInterest
// and the center of the current sensor node does not intersect
// all the edges of the buildings
//-----------------------------------------------------------------------------------------
for(int k=0; k<nPoint; k++) {
boolean intersection = false;
for(Building building : buildings) {
if(building.intersect(zoneOfInterest)) {
if(building.intersect(sensorNode.getLatitude(), sensorNode.getLongitude(), zoneOfInterest.getXCoord(k), zoneOfInterest.getYCoord(k))) {
intersection = true;
break;
}
}
}
if(!intersection)
visibilityPointList.add(new double[] {zoneOfInterest.getXCoord(k), zoneOfInterest.getYCoord(k)});
}
//-----------------------------------------------------------------------------------------
// We will take each point of a building and test if the edge formed with this point
// and the center of the sensor node don't intersect any edge of the buildings
//-----------------------------------------------------------------------------------------
for(Building building : buildings) {
for(int i=0; i<building.getNPoints(); i++) {
double [] t = new double [2];
t[0] = building.getYCoords(i);
t[1] = building.getXCoords(i);
boolean intersection = false;
for(Building building2 : buildings) {
if(building2.intersect(sensorNode.getLatitude(), sensorNode.getLongitude(), t[0], t[1])) {
intersection = true;
break;
}
}
if(!intersection)
visibilityPointList.add(t);
}
}
//-----------------------------------------------------------------------------------------
// To create the polygon corresponding to the obtained points of the
// visibility zone list, we will sort the obtained points
//-----------------------------------------------------------------------------------------
for(int i=0; i<visibilityPointList.size()-1; i++) {
for(int j=i+1; j<visibilityPointList.size(); j++) {
double a1 = Angle.getAngle(sensorNode.getLongitude()-100, sensorNode.getLatitude(), sensorNode.getLongitude(), sensorNode.getLatitude(), visibilityPointList.get(i)[1], visibilityPointList.get(i)[0]);
double a2 = Angle.getAngle(sensorNode.getLongitude()-100, sensorNode.getLatitude(), sensorNode.getLongitude(), sensorNode.getLatitude(), visibilityPointList.get(j)[1], visibilityPointList.get(j)[0]);
if(a1 > a2) {
double px = visibilityPointList.get(i)[0];
double py = visibilityPointList.get(i)[1];
visibilityPointList.get(i)[0] = visibilityPointList.get(j)[0];
visibilityPointList.get(i)[1] = visibilityPointList.get(j)[1];
visibilityPointList.get(j)[0] = px;
visibilityPointList.get(j)[1] = py;
}
}
}
//-----------------------------------------------------------------------------------------
// Create the zone and,
// assign the center of the obtained polygon which is the center of the considered
// sensor node -> necessary to draw the color of the polygon/zone (degraded)
//-----------------------------------------------------------------------------------------
//GeoZone zone = new GeoZone(visibilityPointList.size());
//zone.setCxCy(sensorNode.getLongitude(), sensorNode.getLatitude());
//-----------------------------------------------------------------------------------------
// Assign the values of the visibility zone that are the same values of the list:
// visibilityPointList
// Assign the zones to the geoZoneList
//-----------------------------------------------------------------------------------------
int n = visibilityPointList.size();
GeoZoneList geoZoneList = new GeoZoneList();
for(int i=0; i<n-1; i++) {
GeoZone zone = new GeoZone(3);
zone.setCxCy(sensorNode.getLongitude(), sensorNode.getLatitude());
zone.set(sensorNode.getLatitude(), sensorNode.getLongitude(), 0, 0);
zone.set(visibilityPointList.get(i)[0], visibilityPointList.get(i)[1], 0, 1);
zone.set(visibilityPointList.get(i+1)[0], visibilityPointList.get(i+1)[1], 0, 2);
geoZoneList.add(zone);
}
GeoZone zone = new GeoZone(3);
zone.setCxCy(sensorNode.getLongitude(), sensorNode.getLatitude());
zone.set(sensorNode.getLatitude(), sensorNode.getLongitude(), 0, 0);
zone.set(visibilityPointList.get(n-1)[0], visibilityPointList.get(n-1)[1], 0, 1);
zone.set(visibilityPointList.get(0)[0], visibilityPointList.get(0)[1], 0, 2);
geoZoneList.add(zone);
//-----------------------------------------------------------------------------------------
// Assign the obtained geoZonList to the sensor node.
//-----------------------------------------------------------------------------------------
sensorNode.setGeoZoneList(geoZoneList);
//-----------------------------------------------------------------------------------------
// Refresh the graphic
//-----------------------------------------------------------------------------------------
MapLayer.repaint();
}
}