package com.esri.geoevent.solutions.processor.ll2mgrs;
import java.util.ArrayList;
import java.util.List;
import com.esri.core.geometry.Geometry;
import com.esri.core.geometry.GeometryEngine;
import com.esri.core.geometry.MapGeometry;
import com.esri.core.geometry.Point;
import com.esri.core.geometry.Polygon;
import com.esri.core.geometry.SpatialReference;
import com.esri.ges.core.ConfigurationException;
import com.esri.ges.core.component.ComponentException;
import com.esri.ges.core.geoevent.DefaultFieldDefinition;
import com.esri.ges.core.geoevent.FieldDefinition;
import com.esri.ges.core.geoevent.FieldType;
import com.esri.ges.core.geoevent.GeoEvent;
import com.esri.ges.core.geoevent.GeoEventDefinition;
import com.esri.ges.core.geoevent.GeoEventPropertyName;
import com.esri.ges.manager.geoeventdefinition.GeoEventDefinitionManager;
import com.esri.ges.messaging.GeoEventCreator;
import com.esri.ges.messaging.Messaging;
import com.esri.ges.processor.GeoEventProcessorBase;
import com.esri.ges.processor.GeoEventProcessorDefinition;
import com.esri.sde.sdk.pe.factory.PeFactory;
import com.esri.sde.sdk.pe.engine.PeAngunit;
import com.esri.sde.sdk.pe.engine.PeGeogcs;
import com.esri.sde.sdk.pe.engine.PeNotationMgrs;
import com.esri.sde.sdk.pe.engine.PeNotationUtm;
import com.esri.sde.sdk.pe.engine.PePrimem;
public class LatLongProcessor extends GeoEventProcessorBase {
private GeoEventDefinitionManager manager;
public Messaging messaging;
private Integer accuracy;
private String newdef;
private String geofld;
private String mgrs;
private Boolean returnBB;
private Boolean overwrite;
private List<FieldDefinition> fds;
public LatLongProcessor(GeoEventProcessorDefinition definition)
throws ComponentException {
super(definition);
geoEventMutator = true;
}
public void setManager(GeoEventDefinitionManager manager) {
this.manager = manager;
}
public void setMessaging(Messaging messaging) {
this.messaging = messaging;
}
@Override
public void afterPropertiesSet() {
mgrs = properties.get("mgrs").getValueAsString();
overwrite = (Boolean) properties.get("overwrite").getValue();
returnBB = (Boolean) properties.get("returnbb").getValue();
if (overwrite)
geofld = "GEOMETRY";
else {
geofld = properties.get("geofld").getValueAsString();
try {
FieldDefinition fd = new DefaultFieldDefinition(geofld,
FieldType.Geometry);
fds = new ArrayList<FieldDefinition>();
fds.add(fd);
} catch (ConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
newdef = properties.get("eventdef").getValueAsString();
//accuracy = (Integer) properties.get("accuracy").getValue();
}
@Override
public boolean isGeoEventMutator() {
return true;
}
@Override
public GeoEvent process(GeoEvent evt) throws Exception {
String mgrsval = (String) evt.getField(mgrs);
mgrsval.replace(" ", ""); //remove spaces
String[] mgrsvals = { mgrsval };
PeGeogcs peGeoCS = PeFactory.geogcs(4326);
// PeNotationMgrs mgrs = new PeNotationMgrs();
double[] pts = new double[2];
PeNotationMgrs.mgrs_to_geog(peGeoCS, 1, mgrsvals, pts);
Point pt = new Point(pts[0], pts[1]);
MapGeometry mapGeo = null;
if(returnBB)
{
int accuracy = FindAccuracy(mgrsval);
Geometry geo = findBoundingBox(mgrsval, accuracy, pt);
mapGeo = new MapGeometry(geo, SpatialReference.create(4326));
}
else
{
mapGeo = new MapGeometry(pt, SpatialReference.create(4326));
}
GeoEvent geOut = null;
if (!overwrite) {
GeoEventDefinition edOut;
GeoEventDefinition geoDef = evt.getGeoEventDefinition();
if ((edOut = manager.searchGeoEventDefinition(newdef, getId())) == null) {
edOut = geoDef.augment(fds);
edOut.setOwner(getId());
edOut.setName(newdef);
manager.addGeoEventDefinition(edOut);
}
GeoEventCreator geoEventCreator = messaging.createGeoEventCreator();
geOut = geoEventCreator.create(edOut.getGuid(),
new Object[] { evt.getAllFields(), mapGeo });
geOut.setProperty(GeoEventPropertyName.TYPE, "message");
geOut.setProperty(GeoEventPropertyName.OWNER_ID, getId());
geOut.setProperty(GeoEventPropertyName.OWNER_ID,
definition.getUri());
geOut.setField(geofld, mapGeo);
} else {
geOut = evt;
geOut.setGeometry(mapGeo);
}
return geOut;
}
private int FindAccuracy(String mgrs)
{
char[] charArray = mgrs.toCharArray();
int accuracy = 0;
boolean startSearching = false;
int index = 0;
for(int i = 0; i < charArray.length; ++i)
{
char c = charArray[i];
if (Character.isLetter(c))
{
index = i;
break;
}
}
String dropZone = mgrs.substring(index);
accuracy = dropZone.length()-3;
return accuracy/2;
}
private Geometry findBoundingBox(String mgrs, int accuracy, Point mgrsPt)
{
String mgrsZone = mgrs.substring(0, 1);
int wkid = 0;
String utm = null;
if(mgrsZone.equals("A") || mgrsZone.equals("B") )
{
wkid = 32761;
}
else if(mgrsZone.equals("Y") || mgrsZone.equals("Z"))
{
wkid = 32661;
}
else
{
PeGeogcs peGeoCS = PeFactory.geogcs(4326);
double[] coordArray = {mgrsPt.getX(), mgrsPt.getY()};
String[] utmArray = new String[1];
PeNotationUtm.geog_to_utm(peGeoCS, 1, coordArray, PeNotationUtm.PE_UTM_OPTS_NS, utmArray);
utm=utmArray[0];
wkid=GetWkidFromUTM(utm);
}
SpatialReference pcs = SpatialReference.create(wkid);
SpatialReference gcs = SpatialReference.create(4326);
Geometry projGeo = GeometryEngine.project(mgrsPt, gcs, pcs);//projec local
Point projPt = (Point)projGeo;
double dist = getDistFromAccuracy(accuracy);
double xmin, ymin, xmax, ymax;
xmin=projPt.getX();
ymin=projPt.getY();
xmax = xmin + dist;
ymax = ymin + dist;
Polygon pbb = new Polygon();
pbb.startPath(xmin, ymin);
pbb.lineTo(xmax, ymin);
pbb.lineTo(xmax, ymax);
pbb.lineTo(xmin, ymax);
pbb.lineTo(xmin, ymin);
pbb.closeAllPaths();
Geometry bb = GeometryEngine.project(pbb, pcs, gcs);//project back to wgs84
return bb;
}
private double getDistFromAccuracy(int accuracy)
{
double dist = 0;
if (accuracy == 0)
dist = 100000;
else if (accuracy == 1)
dist = 10000;
else if (accuracy == 2)
dist = 1000;
else if (accuracy == 3)
dist = 100;
else if (accuracy == 4)
dist = 10;
else if (accuracy == 5)
dist = 1;
else if (accuracy == 6)
dist = 0.1;
else if (accuracy == 7)
dist = 0.01;
else if (accuracy == 8)
dist = 0.001;
return dist;
}
private int GetWkidFromUTM(String utm)
{
int wkid = 0;
int nbase = 32600;
int sbase = 32700;
int base=0;
char[] cArray = utm.toCharArray();
int len = cArray.length;
int index = 0;
for(int i = 0; i < len; ++i)
{
char c = cArray[i];
if(Character.isLetter(c))
{
index = i;
break;
}
}
if(utm.substring(index, index+1).equals("N"))
{
base = nbase;//north
}
else
{
base = sbase;//south
}
String zone = utm.substring(0,index);
Integer zoneNum = Integer.parseInt(zone);
wkid = base + zoneNum;
return wkid;
}
}