Archive

Archive for the ‘WorldWind’ Category

More about the project

September 22, 2009 Comments off

Most of what I’ll be doing in the next 6 hr increment (whenever I get 6 hrs) will be to do some of the things found on this and this post by Sean.  Not in GE of course, but in WWJ.  I’ll use this for the horizon LOS calculations.

Interestingly, one of the GCCS-J folks suggested WWJ to Sean.

Advertisements
Categories: WorldWind

Java API for KML – the 24 hour project

September 22, 2009 1 comment

I haven’t done any fun projects for almost 2 years (WorldWind .net and WiiMote) at home.  There are several TODOs on my list ranging from building a FITR based multitouch surface to writing an iPhone game to fixing bugs in WW.NET and revamping how icons work there.

Instead I’ve been doing a lot of coding with WorldWind Java (WWJ) at work and coming home a bit late in the evenings.  It’s nice coding again for work and I find I need to do that every couple years and take a break from technical management.  The side effect is I don’t have to code on the side to keep my hand in.

But Java API for KML came out recently and while it isn’t necessary for our work project I would like to play with it a bit and see if it can replace some of our custom KML code.  I’ve also had a long running itch to scratch in terms of getting the Worldwide SAM Site Overview data into WorldWind.

So a 24 hour project to do that.  That’s a little TOO simple so here are the overall requirements:

  • Import the SSO kmz file into java using JAK
  • Display the SSO data on WWJ
  • Automatically generate range circles based on the SAM type
  • Export the range circle and extra data back into KML

Extra credit:

  • Import CIA World Factbook data and display that as well
  • Use raycasting to limit the range cicles based on terrain
  • Provide ranges limits based on target altitude as a function of terrain and curvature of the earth

I started this weekend (12 hours worth) and things went quickly until they bogged down from gold plating:

  • I got JAK to import the SSO data (easy).
  • I got WWJ to show an icon (not the one that is used in the SSO kml but a generic one)
  • I parsed the site name to get the SAM type (S300-P, Patriot, Hawk, etc)

That took maybe 4 hours.  Then I went into la-la land.  I started looking at HSQL and H2 for an embedded DB.  I started wandering down the H2 spatial path.  I stated defining fairly complex data tables that this program would never need.  Then I ran out of weekend without being in a demoable state. 🙂

The project, alas, will have to go through my work to release but I can talk about JAK here.  Other than an a lack of documentation (common for open source) it was easy to figure out.  But since I couldn’t find an unmarshall example anywhere on the net here’s a simple example based on the SSO kml (I extracted it from the KMZ file first):


package edu.jhuapl.ssov.core;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import de.micromata.opengis.kml.v_2_2_0.Document;
import de.micromata.opengis.kml.v_2_2_0.Feature;
import de.micromata.opengis.kml.v_2_2_0.Folder;
import de.micromata.opengis.kml.v_2_2_0.Kml;
import de.micromata.opengis.kml.v_2_2_0.Placemark;

public class SsoParser {
HashMap<String, List > samTable = new HashMap<String, List >();
ArrayList samType = new ArrayList();

public void parseKML(String filename)
{
Kml kml = Kml.unmarshal(new File(filename));

initSamType();

if (kml != null)
{

Feature feature = kml.getFeature();
processFeature(null, feature);
}

System.out.println(samTable.size() + " SAM types.");

List unknown = samTable.get("UNKNOWN");
if (unknown != null)
{
System.out.println(unknown.size() + " unknown installations.");

for (Placemark placemark : unknown)
{
System.out.println("UNKNOWN: " + placemark.getName());

}
}

List genericSAM = samTable.get("SAM");
if (genericSAM != null)
{
System.out.println(genericSAM.size() + " generic SAM installations.");

for (Placemark placemark : genericSAM)
{
System.out.println("SAM: " + placemark.getName());

}
}

List genericEW= samTable.get("EW");
if (genericSAM != null)
{
System.out.println(genericEW.size() + " generic EW installations.");

for (Placemark placemark : genericEW)
{
System.out.println("EW: " + placemark.getName());

}
}
}

public void processFeature(Feature parentFeature, Feature feature)
{
if (feature instanceof Document)
{
processDocument(parentFeature, (Document) feature);
}
else if (feature instanceof Folder)
{
processFolder(parentFeature, (Folder) feature);
}
else if (feature instanceof Placemark)
{
processPlacemark(parentFeature, (Placemark) feature);
}
else
{
System.out.println("Feature " + feature.getName() + " : " + feature);
}
}

public void processDocument(Feature parentFeature, Document doc)
{
List features = doc.getFeature();

// System.out.println("Document " + doc.getName());

for (Feature docFeature : features)
{
processFeature(doc, docFeature);
}
}

public void processFolder(Feature parentFeature, Folder folder)
{
List features = folder.getFeature();

// System.out.println("Folder " + folder.getName());

for (Feature folderFeature : features)
{
processFeature(folder, folderFeature);
}
}

public void processPlacemark(Feature parentFeature, Placemark placemark)
{
String samType = processPlacemarkName (placemark.getName());
List placemarks = samTable.get(samType);

if (placemarks == null)
{
// System.out.println("SAM Type " + samType +" found: " + placemark.getName());

placemarks = new ArrayList();
samTable.put(samType, placemarks);
}

placemarks.add(placemark);
}

public String processPlacemarkName(String name)
{
boolean emptyFlag = false;

for (String samName : samType)
{
emptyFlag = false;
if (name.toLowerCase().contains("Empty"))
{
emptyFlag = true;
}

if (name.toLowerCase().contains(samName.toLowerCase()))
{
if (emptyFlag)
return "Empty " + samName;
else
return samName;
}
}
return "UNKNOWN";
}

private void initSamType()
{
samType.add("SA-11");
samType.add("SA-15");
samType.add("SA-20");
samType.add("SA-1");
samType.add("SA-2");
samType.add("SA-3");
samType.add("SA-4");
samType.add("SA-5");
samType.add("SA-6");
samType.add("SA-8");
samType.add("Buk-M1-2");
samType.add("HAWK");
samType.add("FM-90");
samType.add("KS-1A");
samType.add("HQ-2");
samType.add("HQ-6");
samType.add("HQ-9");
samType.add("S-300PS/PMU");
samType.add("S-300PMU-1");
samType.add("S-300PMU");
samType.add("S-300PT");
samType.add("S-300P");
samType.add("S-300V");
samType.add("Chu-SAM");
samType.add("NIKE HERCULES");
samType.add("NIKE-HERCULES");
samType.add("PATRIOT");
samType.add("Arrow II");
samType.add("SL-AMRAAM");
samType.add("Rapier");
samType.add("Crotale");
samType.add("Skyguard");
samType.add("Shahine");
samType.add("TACSAM");
samType.add("Bloodhound");
samType.add("NASAMS");

samType.add("36D6");
samType.add("64N6");
samType.add("96L6");
samType.add("9S18M1");
samType.add("TK-II");
samType.add("HT-233");
samType.add("5V11 Dal");
samType.add("OTH-R");
samType.add("OTH-T");
samType.add("OTH");
samType.add("LPAR");
samType.add("7010 ABM RADAR");
samType.add("AN/FPS-108 COBRA DANE");
samType.add("AN/TPS-71 Receiver");
samType.add("AN/TPS-71 Transmitter");

samType.add("SAM Garrison");
samType.add("SAM Training Facility");
samType.add("SAM Training Range");
samType.add("SAM Test Range");
samType.add("SAM");

samType.add("BMEW");
samType.add("ABM");
samType.add("RADAR");
samType.add("EW");
samType.add("TEST");
}
}

Yes, my java conventions are kinda funny. I’m mostly a C/C++/C# developer. 🙂 Also, some things are stubbed in there (like SAM types) that will come from the embedded database (Yes, this is where I went off track).

So I went from 4 hours to 12 hours very quickly. On the other hand I have some hibernate hbm files and a semi-working database (HSQL because I have code samples for that and I only have 12 hours left).

Categories: WorldWind