/*----------------------------------------------------------------------------------------------------------------
* 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 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 VisibilityZones extends Thread {
// -----------------------------------------------------------------------------------------
// The concerned Sensor Node
// -----------------------------------------------------------------------------------------
private SensorNode sensorNode;
// -----------------------------------------------------------------------------------------
// Constructor
// -----------------------------------------------------------------------------------------
public VisibilityZones(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
// -----------------------------------------------------------------------------------------
ArrayList<Building> buildings = new ArrayList<Building>();
for (Building building : BuildingList.buildings) {
if(sensorNode.getElevation()<building.getHeight())
if (building.intersect(zoneOfInterest)) {
buildings.add(building);
}
}
// -----------------------------------------------------------------------------------------
// 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) {
double z = building.getHeight();
for (int i = 0; i < building.getNPoints(); i++) {
double[] t = new double[2];
t[0] = building.getYCoords(i);
t[1] = building.getXCoords(i);
if(sensorNode.distance(t[1], t[0])<(sensorNode.getCurrentRadioRangeRadius())) {
boolean intersection = false;
if(sensorNode.getElevation()<z)
for (Building building2 : buildings) {
if (building2.intersect(sensorNode.getLatitude(), sensorNode.getLongitude(), t[0], t[1])) {
intersection = true;
break;
}
}
if (!intersection)
visibilityPointList.add(t);
}
}
}
// -----------------------------------------------------------------------------------------
// 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) });
}
// -----------------------------------------------------------------------------------------
// 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 visibliity zone that are the same values of
// the list:
// visibilityPointList
// -----------------------------------------------------------------------------------------
int k = 0;
for (double[] v : visibilityPointList) {
zone.set(v[0], v[1], 0, k++);
}
// -----------------------------------------------------------------------------------------
// Assign the zone to the geoZoneList (in this case only 1 zone exists)
// -----------------------------------------------------------------------------------------
GeoZoneList geoZoneList = new GeoZoneList();
geoZoneList.add(zone);
// -----------------------------------------------------------------------------------------
// Assign the obtained geoZonList to the sensor node.
// -----------------------------------------------------------------------------------------
sensorNode.setGeoZoneList(geoZoneList);
// -----------------------------------------------------------------------------------------
// Refresh the graphic
// -----------------------------------------------------------------------------------------
MapLayer.repaint();
}
}