Geographic chart for java

Can someone recommend a Java component that allows you to create a nice image of a world map, highlighting certain countries (based on some statistics). Something similar to this image:

World map with highlighted countries

Something similar to Google Geo Charts (but for Java): https://developers.google.com/chart/interactive/docs/gallery/geochart but works on the server side, without an Internet connection. Ideally, I would like to attach weight to several countries that will cover them proportionally.

Both open source and advertising (if this is not ridiculously priced).

+7
java graph maps geo
source share
6 answers

I could not find a java library to do what you were looking for, so I studied SVG and changed its style and converted it to an image. At first, this problem occurred to me: Apache Batik.

I decided to use the open svg cards open source available on wikimedia (similar to the answer of Gregor Ofis), because it doesn’t do it so you don’t care about licensing, it is also ready for simple CSS modifications by country. (For instructions, see SVG comments). There is one hitch, some of these images on wikimedia were created by a python script , which also puts CSS style into the elements. If you want to use one of these SVG files, you will have to process this.

To my happy surprise, there was an almost perfect example in a batik wiki that needed just a few tweaks. I was able to create a modified image (png) with one small syntax change (their outfile is named .jpg, but its use is png transcoder) and a small change to load svg from project resources instead of disk. Below is an example code with my minor changes:

public class MapMaker { private final static String MAP_FLAT = "BlankMap-World6-Equirectangular.svg"; private final static String MAP_ROUND = "WorldMap.svg"; public static void main(String... args) { try { // make a Document with the base map String parser = XMLResourceDescriptor.getXMLParserClassName(); SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser); Document doc = f.createDocument("http://example.com/stuff", MapMaker.class.getClassLoader().getResourceAsStream(MAP_ROUND)); // prepare to modify and transcode the document SVGDocument sdoc = (SVGDocument) doc; Element svgRoot = sdoc.getDocumentElement(); PNGTranscoder t = new PNGTranscoder(); TranscoderInput input = new TranscoderInput(doc); // find the existing stylesheet in the document NodeList stylesList = doc.getElementsByTagName("style"); Node styleNode = stylesList.item(0); // append another stylesheet after the existing one SVGStyleElement style = (SVGStyleElement) doc.createElementNS(SVG_NAMESPACE_URI, "style"); style.setAttributeNS(null, "type", "text/css"); style.appendChild(doc.createCDATASection(".us {fill: blue;}")); styleNode.getParentNode().appendChild(style); // transcode the map OutputStream ostream = new FileOutputStream("outblue.jpg"); TranscoderOutput output = new TranscoderOutput(ostream); t.transcode(input, output); ostream.close(); // replace the appended stylesheet with another SVGStyleElement oldStyle = style; style = (SVGStyleElement) doc.createElementNS(SVG_NAMESPACE_URI, "style"); style.setAttributeNS(null, "type", "text/css"); style.appendChild(doc.createCDATASection(".us {fill: green;}")); styleNode.getParentNode().replaceChild(style, oldStyle); // transcode the revised map File outFile = new File(System.getProperty("java.io.tmpdir"), "outgreen.png"); ostream = new FileOutputStream(outFile); output = new TranscoderOutput(ostream); t.transcode(input, output); ostream.close(); System.out.println("Out File: " + outFile); } catch (Exception ex) { ex.printStackTrace(); } } } 

As I mentioned, the way this works is to add CSS to the SVG before converting it to the bitmap you need. The secret sauce is SVGStyleElement , here you can see that the United States has turned green. For any other country, you simply use your 2-letter digraph and choose the color you want to fill. Of course, since this is CSS, you can also do things like changing the colors of borders or using a background image instead of color, so you have more flexibility.

I had to play a little with dependencies, so for you to overcome this obstacle, I will include my maven dependencies:

 <dependencies> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-parser</artifactId> <version>1.7</version> </dependency> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-css</artifactId> <version>1.7</version> </dependency> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-svg-dom</artifactId> <version>1.7</version> </dependency> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-transcoder</artifactId> <version>1.7</version> </dependency> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-rasterizer</artifactId> <version>1.7</version> </dependency> <dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>batik-codec</artifactId> <version>1.7</version> </dependency> </dependencies> 

If you use a different layout manager, let me know and I can reset the transitive dependency tree.

+4
source share

Take a look at GeoTools , it may have what you need.

+2
source share

I haven't used it and I'm not sure if it fits your needs, but you can take a look at Nasa WorldWind . It has an SDK, and it seems that there is offline mode.

Check:

+2
source share

Well, you can make a GWT application for this. GWT (Google Web ToolKit) is a Java-based application that creates a form. It provides the same visualization APIs as the javascript Google Charts API, but in java code. Check out this link for the Java API diagrams and a live example of a geogram in the Java code http://gwt-charts.appspot.com/#geochart . Hope this helps :)

+1
source share

In the beginning, you can easily collapse the component, or rather the same function, using an SVG world map (like this ). Save the java.util.Map country names for the path elements as indicated in the SVG source. Your function will take a set of country names and essentially return svg for the map as a string. If the path identifier matches the one in the set, you must add the fill attribute with the desired color ...

Here is the code. You will need to download this and use it as world.svg in the same folder. Then go to the countries that you want to highlight as arguments. The program will write the out.svg file, which you can open in the browser (I used Firefox). Hope this is a trick. I was just trying to launch it from an eclipse ...

 package com.examples.firstbundle; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.FileSystems; import java.nio.file.Files; import java.text.MessageFormat; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; public class SVGMap { private static String prefix = ""; private static String postfix = ""; private static Map<String, String> worldMap = new TreeMap<String, String>(); private final static String pathFormat = "<path id=\"{0}\" d=\"{1}\" fill=\"{2}\" />"; static { try { List<String> lines = Files.readAllLines(FileSystems.getDefault().getPath("world.svg"), StandardCharsets.UTF_8); boolean pathstarted = false; for(String line : lines) { if(isPath(line)) { pathstarted = true; worldMap.put(getCountry(line), getPath(line)); } else { if(!pathstarted) { prefix += line; } else { postfix += line; } } } } catch (IOException e) { e.printStackTrace(); } } /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { Set<String> countries = new TreeSet<String>(); for(String country : args) { countries.add(country); } FileOutputStream fileOutputStream = new FileOutputStream("out.svg"); OutputStreamWriter out = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8); out.append(prefix); for(String country : worldMap.keySet()) { out.append(MessageFormat.format(pathFormat, country, worldMap.get(country), countries.contains(country) ? "tomato" : "grey")); } out.append(postfix); out.flush(); out.close(); } private static String getPath(String line) { String part = line.split("=")[2]; String path = part.split("\"")[1]; return path; } private static String getCountry(String line) { String part = line.split("=")[1]; String country = part.split("\"")[1]; return country; } private static boolean isPath(String line) { return line.startsWith("<path"); } } 
+1
source share

I think the best for you:

gvSIG is known for having a convenient interface that can access the most common formats, both vector and raster. It offers a wide range of tools for working with geographic information (query tools, layout creation, geoprocessing, networks, etc.)

source: gvSIG Wikipedia

0
source share

All Articles