Newer
Older
package org.etsi.geodesic;
import java.util.ArrayList;
/**
* @desc
* @see To validate GPS location: http://www.gps-coordinates.net
*/
public class Positioning implements IPositioning {
public static double TWOPI = 2 * Math.PI;
/**
* Unique reference to this object
*/
private static IPositioning Instance;
/**
* Singleton pattern implementation
*/
public static IPositioning getInstance() {
if (Instance == null) {
Instance = new Positioning();
}
return Instance;
}
/**
* Private constructor required for Singleton pattern implementation
*/
private Positioning() {
}
@Override
public boolean isLocationInsideEllipticArea(final WGS84 p_location, final ArrayList<WGS84> p_ellipticArea) {
// TERFactory.getInstance().logDebug(">>> Positioning.isLocationInsideEllipticArea: " + p_location);
// TODO: implement it
// Do not forget aboout passing throw 0 meridian
return false;
}
@Override
public boolean isLocationInsidePolygonalArea(final WGS84 p_location, final ArrayList<WGS84> p_polygonalArea) {
// TERFactory.getInstance().logDebug(">>> Positioning.isLocationInsidePolygonalArea: " + p_location + ", " + p_polygonalArea);
// TODO: Check passing throw 0 meridian and Equador
double angle = 0;
int poleNum = p_polygonalArea.size();
for (int index = 0; index < poleNum; index++) {
WGS84 delta1 = new WGS84(
p_polygonalArea.get(index).getLatitude() - p_location.getLatitude(),
p_polygonalArea.get(index).getLongitude() - p_location.getLongitude(),
0
);
WGS84 delta2 = new WGS84(
p_polygonalArea.get((index + 1) % poleNum).getLatitude() - p_location.getLatitude(),
p_polygonalArea.get((index + 1) % poleNum).getLongitude() - p_location.getLongitude(),
0
);
angle += calcAngle(delta1, delta2);
} // End of 'for' statement
// TERFactory.getInstance().logDebug("<<< Positioning.isLocationInsidePolygonalArea: " + (boolean)((Math.abs(angle) < Math.PI) ? false : true));
return (boolean)((Math.abs(angle) < Math.PI) ? false : true);
}
@Override
public boolean isLocationInsidePolygonalAreas(final WGS84 p_location, final ArrayList< ArrayList<WGS84> > p_polygonalAreas) {
// TERFactory.getInstance().logDebug(">>> Positioning.isLocationInsidePolygonalAreas: " + p_location);
for (int index = 0; index < p_polygonalAreas.size(); index++) {
if (isLocationInsidePolygonalArea(p_location, p_polygonalAreas.get(index))) {
return true;
}
} // End of 'for' statement
return false; // Not found
}
@Override
public boolean isLocationInsideCircularArea(final WGS84 p_location, final WGS84 p_center, final int p_radius) {
// TERFactory.getInstance().logDebug(">>> Positioning.isLocationInsideCircularArea: " + p_location + ", " + p_center + ", " + p_radius);
// TODO: Check passing throw 0 meridian and Equador
double theta = p_center.getLongitude() - p_location.getLongitude();
double distance =
Math.sin(dd2rad(p_center.getLatitude())) * Math.sin(dd2rad(p_location.getLatitude())) +
Math.cos(dd2rad(p_center.getLatitude())) * Math.cos(dd2rad(p_location.getLatitude())) * Math.cos(dd2rad(theta));
distance = rad2dd(Math.acos(distance));
distance *= 60 * 1.1515 * 1.609344 /*Kilometers*/;
// TERFactory.getInstance().logDebug("Positioning.isLocationInsideCircularArea: distance=" + distance);
// TERFactory.getInstance().logDebug("<<< Positioning.isLocationInsideCircularArea: " + (boolean)(distance <= (p_radius / 1000.0)));
return (boolean)(distance <= (p_radius / 1000.0));
}
@Override
public boolean isValidPolygonArea(final ArrayList<WGS84> p_polygonalArea) {
// TERFactory.getInstance().logDebug(">>> Positioning.isValidPolygonArea");
// Check if polygon coordinates are valid
for (int i = 0; i < p_polygonalArea.size(); i++) {
if (!p_polygonalArea.get(i).isValidPosition()) {
return false;
}
}
return true;
}
@Override
public boolean isLocationInsideIdentifiedRegion(final int p_regionDictionary, final int p_regionId, final long p_localRegion, final WGS84 p_location) {
// TERFactory.getInstance().logDebug(">>> Positioning.isLocationInsideIdentifiedRegion: " + p_regionDictionary + ", " + p_regionId + ", " + p_localRegion + ", " + p_location);
return CountriesAreas.getInstance().isLocationInsideIdentifiedRegion(p_regionDictionary, p_regionId, p_localRegion, p_location);
}
@Override
public boolean isPolygonalRegionInside(final ArrayList<WGS84> p_parentArea, final ArrayList<WGS84> p_regionArea) {
// TERFactory.getInstance().logDebug(">>> Positioning.isPolygonalRegionInside: " + p_parentArea + ", " + p_regionArea);
for (int i = 0; i < p_regionArea.size(); i++) {
if (!isLocationInsidePolygonalArea(p_regionArea.get(i), p_parentArea)) {
return false;
}
} // End of 'for' statement
return true;
}
private double calcAngle(final WGS84 p_origin, final WGS84 p_end) {
// TERFactory.getInstance().logDebug(">>> calcAngle: " + p_origin.getLatitude() + " - " + p_origin.getLongitude() + " - " + p_end.getLatitude() + " - " + p_end.getLongitude());
double theta1 = Math.atan2(p_origin.getLatitude(), p_origin.getLongitude());
// TERFactory.getInstance().logDebug("Angle2D: theta1=" + theta1);
double theta2 = Math.atan2(p_end.getLatitude(), p_end.getLongitude());
// TERFactory.getInstance().logDebug("Angle2D: theta2=" + theta2);
double dtheta = theta2 - theta1;
// TERFactory.getInstance().logDebug("calcAngle: dtheta" + dtheta);
while (dtheta > Math.PI) {
dtheta -= TWOPI;
} // End of 'while' statement
while (dtheta < -Math.PI) {
dtheta += TWOPI;
} // End of 'while' statement
// TERFactory.getInstance().logDebug("<<< calcAngle: " + dtheta);
return dtheta;
}
/**
* @desc Convert a decimal degrees value into a decimal radian
* @param p_decimalDegrees The value to convert
* @return The converted value in radians
*/
private double dd2rad(final double p_decimalDegrees) {
return p_decimalDegrees * Math.PI / 180;
}
/**
* @desc Convert a decimal radians value into a decimal degrees
* @param p_decimalRadians The value to convert
* @return The converted value in degrees
*/
private double rad2dd(final double p_decimalRadians) {
return p_decimalRadians * 180.0 / Math.PI;
}
} // End of class Positioning