Java API for KML - Advanced Example2

The concept

This series of more sophisticated JAK examples is trying to show the capabilities what is possible with KML in Java. They show the usage of JAK for generating some nice-looking KML files, which can be viewed with Google Earth.

Important!
JAK only works if all dependencies are resolved! That are mainly JAK and JAXB! For further instructions check out the FAQ.

Import data from World Borders Dataset and change it.

The second example creates a KML file with random colors and heights for each country.

Figure 1: 2D country polygons with random color and random height in Google Earth

Figure 2: 3D country polygons with random color and random height in Google Earth

With the World Borders Dataset of Bjorn Sandvik (special thanks to him) it's possible to create 2D and 3D polygons with the borders of each country. It's a nice alternative to bar charts.
The data is saved as a shape file. For an easier handling (and for not to parse the shape file) we 'import' the data with JAK's unmarshal-method from one of Bjorn's KML files. This dataset contains the World Borders Dataset (polygons with the coordinates of the borders of each country).

The Code

Listing 1 reads the world borders from a KML file and creates two radio folder. The first folder show all countries with a color overlay (2D) and random colors (see Figure 1).
The second folder show a polygon (3D) with random color and random height for each country. To create a 3D polygon, the object structure must be traverse until the Coordinate objects (see Figure 2).

Load world borders KML and create folders
int minPolyHeight = 308000; //set a minimum height used by the 3D shapes
int maxPolyHeight = 2692000; // real max = 3000000 - 308000 = 2692000

Kml worldBorders = Kml.unmarshal(new File("src/main/resources/exampledata/worldBorders.kml"));

Document document = (Document) worldBorders.getFeature().withName("JAK Example 2");
Folder rootFolder = document.createAndAddFolder().withName("choose").withStyleUrl("radioFolder");
// set radiofolder: only one folder can be activated
Style radioStyle = document.createAndAddStyle().withId("radioFolder");
radioStyle.createAndSetListStyle().withListItemType(ListItemType.RADIO_FOLDER);

// put the original folder into the rootFolder and use for 3D shapes
Folder folder2D = (Folder) document.getFeature().get(0).withName("2D borders");
document.getFeature().remove(0);
rootFolder.addToFeature(folder2D);

// set a random color to each placemark
for (int i = 0; i < folder2D.getFeature().size(); i++) {
  Placemark placemaek2D = (Placemark) folder2D.getFeature().get(i);
  placemaek2D.withDescription(placemaek2D.getName());

  List<StyleSelector> styleSelector = placemaek2D.getStyleSelector();
  Iterator<StyleSelector> iterator = styleSelector.iterator();
  Style style = null;
  while (iterator.hasNext()) {
    StyleSelector tmp = iterator.next();
    if (tmp instanceof Style) {
      style = (Style) tmp;
      style.getPolyStyle().withColor("FFFFFFFF").withColorMode(ColorMode.RANDOM);
      style.createAndSetLineStyle().withWidth(1).withColor("FF000000").withColorMode(ColorMode.NORMAL);
    }
  }
}

// clone the 2d folder
Folder folder3D = folder2D.clone();
folder3D.setName("3D borders");
rootFolder.addToFeature(folder3D);

// loop over all countries / Placemarks and set a random height to each country
for (int i = 0; i < folder3D.getFeature().size(); i++) {
  Placemark placemark3D = (Placemark) folder3D.getFeature().get(i);
  placemark3D.withDescription(placemark3D.getName());

  // use random color for the polygon and a black (default color) stroke with 1 width
  MultiGeometry multigeometry3D = (MultiGeometry) placemark3D.getGeometry();
  Random rand = new Random(System.nanoTime());
  // use minimal polygon height to prevent the "polygon hole problem"
  double x = rand.nextInt(maxPolyHeight) + minPolyHeight;

  for (int j = 0; j < multigeometry3D.getGeometry().size(); j++) {
    Polygon polygon3D = (Polygon) multigeometry3D.getGeometry().get(j);
    polygon3D.setAltitudeMode(AltitudeMode.RELATIVE_TO_GROUND); // altitude can only be set in this mode
    polygon3D.setExtrude(Boolean.TRUE);
    Boundary outerBoundaryIs = polygon3D.getOuterBoundaryIs();
    LinearRing linearRing = outerBoundaryIs.getLinearRing();
    List<Coordinate> coordinates = linearRing.getCoordinates();
    // set the altitude of all vertices (height of the polygon)
    for (Coordinate c : coordinates) {
      c.setAltitude(x);
    }

    // check enclaves or polygons like it
    if (!polygon3D.getInnerBoundaryIs().isEmpty()) {
      for (int k = 0; k < polygon3D.getInnerBoundaryIs().size(); k++) {
        Boundary innerBoundaryIs = polygon3D.getInnerBoundaryIs().get(k);
        LinearRing linearRingInner = innerBoundaryIs.getLinearRing();
        List<Coordinate> coordinatesInner = linearRingInner.getCoordinates();
        // set the altitude of all vertices (height of the polygon)
        for (Coordinate c : coordinatesInner) {
          c.setAltitude(x);
        }
      }
    }
  }
}
worldBorders.marshal(new File("advancedexample2.kml"));

The full example is contained in JAK's sources (/JavaAPIforKML/src/test/java/de/micromata/jak/examples/Example2.java).

Searching JAK

Java API for KML | @Google

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.




PageRank verified www.micromata.de/