I am currently working on how to read in ESRI shapefiles, parse/edit layers and then export out to SVG (Scalable Vector Graphic) file type. I have been using GeoTools primarily for reading/loading shapefiles. I am also displaying them using an JMapFrame GUI.
My issue currently is how to export a shapefile, after reading it in, to an SVG file. There is a great example by OpenJUMP which does exactly as I need, however, while looking at the code used to implement this feature, I am unable to figure out how to do it myself. I want to avoid using OpenJUMP's program as export to SVG using java code (so I can do other things before exporting).
Note: I have 2 files - ShapefileExporter.java (main class) and ExportShapefile.java (export to svg code)
Here is some of my code reading in shapefiles:
public class ShapefileExporter {
final static ExportShapefile exportSHP = new ExportShapefile();
final JFileChooser jfc = new JFileChooser();
JToolBar jtb;
MapContent map;
JPopupMenu rcMenu = new JPopupMenu("Popup");
private JMapFrame jframe;
private File shapeFile;
// Main, start program
public static void main(String[] args) throws Exception {
ShapefileExporter exporter = new ShapefileExporter();
if (args.length == 0 || !args[0].toLowerCase().endsWith(".shp")) {
System.out.println("Any provided shapefile.prl or .sld will be used");
} else {
String pathname = args[0];
URL shape = acquireURL(pathname);
if (shape == null) {
System.err.println("Could not find shapefile");
System.exit(1);
}
exporter.loadFile(shape);
}
}
// Load Shapefile into JMapFrame
protected void loadFile(URL shape) throws IOException {
FileDataStore store = FileDataStoreFinder.getDataStore(shape);
SimpleFeatureSource featureSource = store.getFeatureSource();
Style style = SLD.createSimpleStyle( featureSource.getSchema() );
FeatureLayer layer = new FeatureLayer(featureSource, style);
ShapefileDataStore ds = new ShapefileDataStore(shape);
FeatureSource<SimpleFeatureType, SimpleFeature> fs = ds.getFeatureSource();
map = new MapContent();
map.addLayer(layer);
jframe.setMapContent(map);
}
// Constructor, create/display JMapFrame GUI
public ShapefileExporter() {
File default_dir = new File(System.getProperty("user.home") + System.getProperty("file.separator") + "NetBeansProjects/Working On");
jfc.setCurrentDirectory(default_dir);
jframe = new JMapFrame();
jframe.setSize(1000, 800);
jframe.enableStatusBar(true);
jframe.enableToolBar(true);
jframe.enableLayerTable(true);
JMenuBar menuBar = new JMenuBar();
jframe.setJMenuBar(menuBar);
JMenu menubar = new JMenu("File");
menuBar.add(menubar);
menubar.add(new SafeAction("Load file") {
@Override
public void action(ActionEvent e) throws Throwable {
setJFCFilter("Shapefiles", "shp");
int returnVal = jfc.showOpenDialog(jframe);
if (returnVal == JFileChooser.APPROVE_OPTION) {
String pathname = jfc.getSelectedFile().getAbsolutePath();
URL shape = acquireURL(pathname);
if (shape == null) {
JOptionPane.showMessageDialog(jframe, "could not find file \"" + pathname + "\"", "Could not find file",
JOptionPane.ERROR_MESSAGE);
}
try {
shapeFile = new File(pathname);
loadFile(shape);
} catch (IOException ex) {
System.err.println("File exception for file: " + shape);
}
}
}
});
menubar.add(new SafeAction("Export Shapefile") {
@Override
public void action(ActionEvent e) throws Throwable {
File svgFile = changeFileExt(shapeFile, ".svg");
jfc.setSelectedFile(svgFile);
setJFCFilter("Scaleable Vector Graphics", "svg");
int returnVal = jfc.showSaveDialog(jframe);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File selFile = jfc.getSelectedFile();
//File svgfile = changeFileExt(shpfile, ".svg");
//URL svg = acquireURL(shpfile);
Path path = Paths.get(selFile.getPath());
if (Files.notExists(path, LinkOption.NOFOLLOW_LINKS)) {
FileOutputStream out = new FileOutputStream(new File(path.toString()));
out.close();
}
if (selFile == null) {
JOptionPane.showMessageDialog(jframe, "could not find file \"" + selFile + "\"", "Could not find file",
JOptionPane.ERROR_MESSAGE);
}
try {
System.out.println("SvG File: " + selFile);
System.out.println();
if (Files.exists(path, LinkOption.NOFOLLOW_LINKS)) {
exportSHP.exportToSVG(new File(selFile.getPath()), jframe, map);
}
} catch (Exception ex) {
System.err.println("File exception for file: " + selFile + "\n" + ex);
}
}
}
});
jframe.setVisible(true);
} // End constructor
} // End class
Export to SVG Code
public class ExportShapefile {
public void exportToSVG(File file, JMapFrame jframe, MapContent map)
throws ParserConfigurationException {
Dimension canvasSize = new Dimension(jframe.getMapPane().getSize());
Document doc;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db;
db = dbf.newDocumentBuilder();
// Create an instance of org.w3c.dom.Document
doc = db.getDOMImplementation().createDocument(null, "svg", null);
// Set up the map
SVGGeneratorContext ctx1 = SVGGeneratorContext.createDefault(doc);
SVGGeneratorContext ctx = ctx1;
ctx.setComment("Generated by GeoTools with Batik SVG Generator");
SVGGraphics2D g2d = new SVGGraphics2D(ctx, true);
g2d.setSVGCanvasSize(canvasSize);
Rectangle outputArea = new Rectangle(g2d.getSVGCanvasSize());
ReferencedEnvelope dataArea = map.getViewport().getBounds();
jframe.getMapPane().getRenderer().paint(g2d, outputArea, dataArea);
OutputStreamWriter osw = null;
try {
OutputStream out = new FileOutputStream(file);
osw = null;
osw = new OutputStreamWriter(out, "UTF-8");
g2d.stream(osw);
} catch (FileNotFoundException | UnsupportedEncodingException |
SVGGraphics2DIOException ex) {
System.err.println("IOException found: " + ex);
} finally {
if (osw != null) {
try {
osw.close();
} catch (IOException ex) {
System.err.println("IOException found: " + ex);
}
}
}
}
}
pom.xml file (maven version)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- =========================================================== -->
<!-- Project Description -->
<!-- =========================================================== -->
<groupId>com.mycompany</groupId>
<artifactId>ShpExportMaven</artifactId>
<version>14-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ShpExportMaven</name>
<url>http://maven.apache.org</url>
<properties>
<oracle>false</oracle>
<allow.test.skip>true</allow.test.skip>
<allow.test.failure.ignore>false</allow.test.failure.ignore>
<extensive.tests>false</extensive.tests>
<skip.image.tests>false</skip.image.tests>
<interactive.tests>false</interactive.tests>
<interactive.image>false</interactive.image>
<online.skip.pattern>**/*OnlineTest.java</online.skip.pattern>
<stress.skip.pattern>**/*StressTest.java</stress.skip.pattern>
<test.exclude.pattern>disabled</test.exclude.pattern>
<test.maxHeapSize>256M</test.maxHeapSize>
<javadoc.maxHeapSize>1536M</javadoc.maxHeapSize>
<test.forkMode>once</test.forkMode>
<src.output>${basedir}/target</src.output>
<imageio.ext.version>1.1.12</imageio.ext.version>
<jaiext.version>1.0.3</jaiext.version>
<netcdf.version>4.5.5</netcdf.version>
<jt.version>1.3.1</jt.version>
<jvm.opts></jvm.opts>
<maven.build.timestamp.format>dd-MMM-yyyy HH:mm</maven.build.timestamp.format>
<build.timestamp>${maven.build.timestamp}</build.timestamp>
<fork.javac>true</fork.javac>
<javac.maxHeapSize>256M</javac.maxHeapSize>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<postgresql.jdbc.version>9.4-1201-jdbc41</postgresql.jdbc.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.java.dev.jsr-275</groupId>
<artifactId>jsr-275</artifactId>
<version>1.0-beta-2</version>
</dependency>
<!-- Mathematic, geometries, SVG... -->
<dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts</artifactId>
<version>1.13</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-svggen</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-awt-util</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-dom</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-util</artifactId>
<version>1.6.1</version>
</dependency>
<!-- Java Advabnced Imaging (JAI) -->
<dependency>
<groupId>javax.media</groupId>
<artifactId>jai_core</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>javax.media</groupId>
<artifactId>jai_imageio</artifactId>
<version>1.1</version>
</dependency>
<!-- ImageIO-Ext -->
<dependency>
<groupId>it.geosolutions.imageio-ext</groupId>
<artifactId>imageio-ext-tiff</artifactId>
<version>${imageio.ext.version}</version>
</dependency>
<dependency>
<groupId>it.geosolutions.imageio-ext</groupId>
<artifactId>imageio-ext-utilities</artifactId>
<version>${imageio.ext.version}</version>
</dependency>
<!-- XML -->
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom</artifactId>
<version>1.1.3</version>
</dependency>
<!-- Apache -->
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.2</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- Databases -->
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- Inherited by all modules -->
<dependencies>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-api</artifactId>
<version>14.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-main</artifactId>
<version>14.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>14.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-render</artifactId>
<version>14.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-swing</artifactId>
<version>14.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-awt-util</artifactId>
<version>1.6-1</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-dom</artifactId>
<version>1.6-1</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik-svggen</artifactId>
<version>1.6-1</version>
</dependency>
<dependency>
<groupId>batik</groupId>
<artifactId>batik</artifactId>
<version>1.5</version>
</dependency>
</dependencies>
<!-- =========================================================== -->
<!-- Build Configuration -->
<!-- =========================================================== -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<archive>
<manifest>
<mainClass>com.mycompany.shapefileexporter.mvn.ShapefileExporter</mainClass>
</manifest>
</archive>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<!-- ================================================================== -->
<!-- Repositories. This is where Maven looks for dependencies. The -->
<!-- Maven repository is implicit and doesn't need to be specified. -->
<!-- ================================================================== -->
<repositories>
<repository>
<id>central.maven.org</id>
<name>Central Maven repository</name>
<url>http://central.maven.org/maven2</url>
</repository>
<repository>
<id>java.net-Public</id>
<name>Maven Java Net Snapshots and Releases</name>
<url>https://maven.java.net/content/groups/public/</url>
</repository>
<repository>
<id>geosolutions</id>
<name>geosolutions repository</name>
<url>http://maven.geo-solutions.it/</url>
</repository>
<repository>
<id>osgeo</id>
<name>Open Source Geospatial Foundation Repository</name>
<url>http://download.osgeo.org/webdav/geotools/</url>
</repository>
<repository>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>boundless</id>
<name>Boundless Maven Repository</name>
<url>http://repo.boundlessgeo.com/main</url>
</repository>
</repositories>
<!-- =========================================================== -->
<!-- Plugin repositories. -->
<!-- This is where Maven looks for plugin dependencies. -->
<!-- =========================================================== -->
<pluginRepositories>
<pluginRepository>
<id>osgeo</id>
<name>Open Source Geospatial Foundation Maven 2 Repository</name>
<url>http://download.osgeo.org/webdav/geotools/</url>
<releases>
<enabled>true</enabled>
</releases>
</pluginRepository>
<pluginRepository>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>boundless</id>
<name>Boundless Maven Repository</name>
<url>http://repo.boundlessgeo.com/main</url>
</pluginRepository>
<pluginRepository>
<id>sonatype-snapshots</id>
<name>sonatype-snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
Note: 'file' 'jframe' and 'map' are being declared and pointed to from another file.
Example of JMapFrame display:
Update: I got the code working, there were some issues with the pom.xml and versions of libraries I had.