Mercurial > mxd2map
view src/java/de/intevation/mxd/writer/SymbolWriter.java @ 314:cd3cb1a7f35a
Workaround a bug in ArcGIS causing FieldNames of shape files that
are 11 Characters long to be postfixed with their Type Identifier.
author | Andre Heinecke <aheinecke@intevation.de> |
---|---|
date | Mon, 17 Sep 2012 17:02:15 +0200 |
parents | 2cb2f26d0d54 |
children |
line wrap: on
line source
/* * Copyright (c) 2011 by Intevation GmbH, Germany <info@intevation.de> * * This file is part of MXD2map. * * This program is free software under the LGPL (>=v2.1) * Read the file LICENCE.txt coming with the software for details * or visit http://www.gnu.org/licenses/ if it does not exist. * * MXD2map has been developed on behalf of the * Bundesamt fuer Seeschifffahrt und Hydrographie (BSH) in Hamburg * by Intevation GmbH. * * Authors: * Raimund Renkert <raimund.renkert@intevation.de> * Bjoern Schilberg <bjoern.schilberg@intevation.de> * Stephan Holl <stephan.holl@intevation.de> */ package de.intevation.mxd.writer; import org.apache.log4j.Logger; import org.w3c.dom.Element; import edu.umn.gis.mapscript.mapObj; import edu.umn.gis.mapscript.classObj; import edu.umn.gis.mapscript.symbolObj; import edu.umn.gis.mapscript.symbolSetObj; import edu.umn.gis.mapscript.lineObj; import edu.umn.gis.mapscript.pointObj; import edu.umn.gis.mapscript.fontSetObj; import edu.umn.gis.mapscript.hashTableObj; import edu.umn.gis.mapscript.MS_SYMBOL_TYPE; import java.io.File; import java.awt.Image; import java.awt.image.BufferedImage; import java.awt.image.FilteredImageSource; import java.awt.image.ImageFilter; import java.awt.image.ImageProducer; import java.awt.image.RGBImageFilter; import java.awt.Toolkit; import java.awt.Color; import java.awt.Graphics2D; import javax.imageio.ImageIO; import java.io.ByteArrayInputStream; import org.apache.commons.codec.binary.Base64; /** * The interface to the mapfile writer. * * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a> */ public class SymbolWriter { /** * The Logger. */ private static final Logger logger = Logger.getLogger(SymbolWriter.class); /** * Private member. */ private mapObj map; private classObj cl; /** * Contructor with map object and class object. * * @param map The map object. * @param cl The class object containing the style. */ public SymbolWriter (mapObj map, classObj cl) { this.map = map; this.cl = cl; } /** * Write the content. * * @param symbolElement DOM element containg the style and symbol * attributes. */ public boolean write(Element symbolElement) { logger.debug("write(Element)"); symbolSetObj symbolSet = map.getSymbolset(); String symType = symbolElement.getAttribute("style"); String type = symbolElement.getAttribute("type"); if(symType.equals("point")) { String name = symbolElement.getAttribute("name"); symbolObj sym = symbolSet.getSymbolByName(name); writeSimple(sym); } else if (symType.equals("arrow")) { String name = symbolElement.getAttribute("name"); symbolObj sym = symbolSet.getSymbolByName(name); writeArrow(sym, symbolElement); } else if (symType.equals("char")) { String name = symbolElement.getAttribute("name"); symbolObj sym = symbolSet.getSymbolByName(name); int exists = symbolExists(symbolElement); if(exists == -1) { String old = symbolElement.getAttribute("name"); symbolElement.setAttribute( "name", old + symbolSet.getNumsymbols() + 1); writeCharacter(sym, symbolElement); } else { symbolElement.setAttribute( "name", symbolSet.getSymbol(exists).getName()); } } else if (type.equals("line") && !symType.equals("picture")) { String name = symbolElement.getAttribute("name"); symbolObj sym = symbolSet.getSymbolByName(name); writeHatch(sym); } else if(symType.equals("picture")) { // Create the path to the picture. int exists = symbolExists(symbolElement); String n = symbolElement.getAttribute("name"); symbolElement.setAttribute( "name", n + symbolSet.getNumsymbols() + 1); String path = this.map.getMappath(); if (path.endsWith(".map")) { path = path.substring(0, path.lastIndexOf(File.separator) + 1); path += symbolElement.getAttribute("name") + ".png"; } else { path += symbolElement.getAttribute("name") + ".png"; } // Create a new symbol using the path as symbol name. // This is a workarround to set the IMAGE attribute to the path // since this attribute is immutable via mapscript. symbolObj sym = symbolSet.getSymbolByName(path); writePicture(sym, symbolElement, path); } else { return false; } try { saveSymbolSet(symbolSet); } catch(Exception e) { logger.error("Error saving symbol set."); return false; } return true; } /** * Create a simple point symbol. * * @param symbol The symbol object. */ private void writeSimple(symbolObj symbol) { logger.debug("writeSimple(symbolObj)"); lineObj points = new lineObj(); points.add(new pointObj(1,1,0)); symbol.setType(MS_SYMBOL_TYPE.MS_SYMBOL_ELLIPSE.swigValue()); symbol.setPoints(points); symbol.setFilled(1); } /** * Create an arrow symbol. * * @param symbol The symbol object. * @param symbolElement DOM element containing symbol attributes. */ private void writeArrow(symbolObj symbol, Element symbolElement) { logger.debug("writeArrow(symbolObj, Element)"); double len = 0; double width = 1; try { len = Double.parseDouble(symbolElement.getAttribute("length")); width = Double.parseDouble(symbolElement.getAttribute("width")); } catch(NumberFormatException nfe) { logger.warn ("Error setting arrow symbol."); return; } double ratio = len/width; lineObj points = new lineObj(); points.add(new pointObj(0, 0, 0)); points.add(new pointObj((1*ratio), 0.5, 0)); points.add(new pointObj(0, 1, 0)); points.add(new pointObj(0, 0, 0)); symbol.setType(MS_SYMBOL_TYPE.MS_SYMBOL_VECTOR.swigValue()); symbol.setPoints(points); symbol.setFilled(1); } /** * Create a character marker symbol. * * @param symbol The symbol object. * @param symbolElement DOM element containing symbol attributes. */ private void writeCharacter(symbolObj symbol, Element symbolElement) { logger.debug("writeCharacter(symbolObj, Element)"); String font = symbolElement.getAttribute("font"); //Remove all blank character to match the mapserver fonts.txt. font = font.replaceAll(" ", ""); fontSetObj fso = this.map.getFontset(); hashTableObj fonts = fso.getFonts(); String mapFont = fonts.get(font,""); if (mapFont == null || mapFont.equals("")) { logger.warn( "Could not find font " + font + " in font set. " + "Setting FreeSans as symbol font." + "Please add " + font + " to fonts.txt and replace the alias " + "in symbol \"" + symbolElement.getAttribute("name") + "\"."); font = "FreeSans"; } symbol.setName(symbolElement.getAttribute("name")); symbol.setFont(font); symbol.setType(MS_SYMBOL_TYPE.MS_SYMBOL_TRUETYPE.swigValue()); symbol.setAntialias(1); symbol.setCharacter("&#" + symbolElement.getAttribute("char") + ";"); } /** * Create the image and a pixmap symbol. * * @param sym The symbol object. * @param symElem The DOM element containing symbol informations. */ private void writePicture(symbolObj sym, Element symElem, String path) { logger.debug("writePicture(symbolObj, Element)"); try { // Create the image as png. if(symElem.hasAttribute("picture")) { Base64 decoder = new Base64(); // Decode the base64 string. byte[] ba = decoder.decode(symElem.getAttribute("picture")); ByteArrayInputStream ins = new ByteArrayInputStream(ba); // Create temporary image from byte array. BufferedImage bi = ImageIO.read(ins); Color c = Color.decode( symElem.getAttribute("transparent_color")); // Make a color transparent. Image im = colorToTransparent(bi, c); // Save image as png. BufferedImage dest = new BufferedImage( bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = dest.createGraphics(); g2.drawImage(im, 0, 0, null); g2.dispose(); File f = new File(path); ImageIO.write(dest, "PNG", f); } // Set symbol attributes. // Overwrite the symbol name conating the path to the image // with the real name. This is part of the workarround(line 137). sym.setName(symElem.getAttribute("name")); sym.setType(MS_SYMBOL_TYPE.MS_SYMBOL_PIXMAP.swigValue()); } catch(Exception e) { logger.warn("Could not save image for pixmap symbol."); } } /** * Create a hatch symbol for polygon fill. * * @param symbol The symbol object. */ private void writeHatch(symbolObj symbol) { logger.debug("writeHatch(symbolObj)"); symbol.setType(MS_SYMBOL_TYPE.MS_SYMBOL_HATCH.swigValue()); } /** * Determine whether this writer can create the symbol. * * @param type The symbol type. */ public boolean canWrite(String type) { if (type.equals("point") || type.equals("arrow") || type.equals("char") || type.equals("line") || type.equals("picture")) { return true; } else { return false; } } /** * Save the symbol set. * * @param symbols The symbol set object. */ public void saveSymbolSet(symbolSetObj symbols) throws Exception { String path = this.map.getMappath(); String filename = path.substring(path.lastIndexOf(File.separator) + 1, path.lastIndexOf(".")); String symbolPath = filename + "-symbols.sym"; if(path.equals("")) { return; } if (path.endsWith(".map")) { path = path.substring(0, path.lastIndexOf(File.separator) + 1); path += symbolPath; } else { path += symbolPath; } path = path.replaceAll("\\\\", "/"); symbols.save(path); this.map.setSymbolSet(path); } /** * Determine whether the symbol exists. * * @param elem DOM element containing the symbol attributes. * * @return Returns the symbol index if the symbol exists, else returns -1. */ private int symbolExists (Element elem) { symbolSetObj symbolSet = map.getSymbolset(); for (int i = 0; i < symbolSet.getNumsymbols(); i++) { symbolObj sym = symbolSet.getSymbol(i); int stype = sym.getType(); String etype = elem.getAttribute("style"); if(stype == MS_SYMBOL_TYPE.MS_SYMBOL_ELLIPSE.swigValue () && etype.equals("point")) { return i; } else if(stype == MS_SYMBOL_TYPE.MS_SYMBOL_VECTOR.swigValue () && etype.equals("arrow")) { return i; } else if(stype == MS_SYMBOL_TYPE.MS_SYMBOL_TRUETYPE.swigValue () && etype.equals("char")) { String font = elem.getAttribute("font"); font = font.replaceAll(" ", ""); String c = elem.getAttribute("char"); c = "&#" + c + ";"; if (font.equals(sym.getFont()) && c.equals(sym.getCharacter())) { return i; } } else if(stype == MS_SYMBOL_TYPE.MS_SYMBOL_HATCH.swigValue () && etype.equals("hatch")) { return i; } else if(stype == MS_SYMBOL_TYPE.MS_SYMBOL_PIXMAP.swigValue() && etype.equals("picture")) { return i; } } return -1; } /** * Transform a color to transparency. * * @param bi The image. * @param col the color. * * @return The image with transparent color. */ private Image colorToTransparent(BufferedImage bi, Color col) { final int markerRGB = col.getRGB() | 0xFF000000; ImageFilter filter = new RGBImageFilter() { public final int filterRGB(int x, int y, int rgb) { if ((rgb | 0xFF000000) == markerRGB) { // Mark the alpha bits as zero - transparent return 0x00FFFFFF & rgb; } else { // nothing to do return rgb; } } }; ImageProducer ip = new FilteredImageSource(bi.getSource(), filter); return Toolkit.getDefaultToolkit().createImage(ip); } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :