// License: GPL. For details, see LICENSE file. package jrender; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import javax.imageio.ImageIO; import render.ChartContext; import render.Renderer; import s57.S57map; import s57.S57map.Feature; import s57.S57map.Snode; import s57.S57osm; /** * @author Malcolm Herring */ public final class Jrender { private Jrender() { // Hide default constructor for utilities classes } static String srcdir; static String dstdir; static int xtile; static int ytile; static int zoom; static ArrayList<String> send; static HashMap<String, Boolean> deletes; static Context context; static S57map map; static int empty; static class Context implements ChartContext { static double top; static double mile; Context() { top = (1.0 - Math.log(Math.tan(map.bounds.maxlat) + 1.0 / Math.cos(map.bounds.maxlat)) / Math.PI) / 2.0 * 256.0 * 4096.0 * Math.pow(2, (zoom - 12)); mile = (2 * ((zoom < 12) ? (256 / (int) (Math.pow(2, (11 - zoom)))) : 256) + 256) / ((Math.toDegrees(map.bounds.maxlat) - Math.toDegrees(map.bounds.minlat)) * 60); } @Override public Point2D getPoint(Snode coord) { double x = (Math.toDegrees(coord.lon) - Math.toDegrees(map.bounds.minlon)) * 256.0 * 2048.0 * Math.pow(2, (zoom - 12)) / 180.0; double y = ((1.0 - Math.log(Math.tan(coord.lat) + 1.0 / Math.cos(coord.lat)) / Math.PI) / 2.0 * 256.0 * 4096.0 * Math.pow(2, (zoom - 12))) - top; return new Point2D.Double(x, y); } @Override public double mile(Feature feature) { return mile; } @Override public boolean clip() { return false; } @Override public Color background(S57map map) { return new Color(0, true); } @Override public RuleSet ruleset() { return RuleSet.SEAMARK; } } static void tile(int z, int s, int xn, int yn) throws IOException { int border = (z < 12) ? (256 / (int) (Math.pow(2, (11 - zoom)))) : 256; int scale = (int) Math.pow(2, z - 12); int xdir = (scale > 0) ? (scale * xtile) + xn : xtile; int ynam = (scale > 0) ? (scale * ytile) + yn : ytile; BufferedImage img = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); g2.scale(s, s); g2.translate(-(border + (xn * 256 / s)), -(border + (yn * 256 / s))); Renderer.reRender(g2, new Rectangle(256, 256), z, 1.0 * Math.pow(2, (zoom - 12)), map, context); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ImageIO.write(img, "png", bos); if (bos.size() > empty) { String dstnam = dstdir + z + "/" + xdir + "/" + ynam + ".png"; deletes.remove(dstnam); send.add("put " + dstnam + " tiles/" + z + "/" + xdir + "/" + ynam + ".png"); File ofile = new File(dstdir + "/" + z + "/" + xdir + "/"); ofile.mkdirs(); FileOutputStream fos = new FileOutputStream(dstdir + "/" + z + "/" + xdir + "/" + ynam + ".png"); bos.writeTo(fos); fos.close(); if (send.size() > 20) { PrintWriter writer = new PrintWriter(srcdir + z + "-" + xdir + "-" + ynam + ".send", "UTF-8"); for (String str : send) { writer.println(str); } writer.close(); send = new ArrayList<>(); } } if ((z >= 12) && (z < 18) && ((z < 16) || (bos.size() > empty))) { for (int x = 0; x < 2; x++) { for (int y = 0; y < 2; y++) { tile((z + 1), (s * 2), (xn * 2 + x), (yn * 2 + y)); } } } } static void clean(int z, int xn, int yn) throws Exception { int scale = (int) Math.pow(2, z - 12); int xdir = (scale * xtile) + xn; int ynam = (scale * ytile) + yn; String delnam = dstdir + z + "/" + xdir + "/" + ynam + ".png"; File delfile = new File(delnam); if (delfile.exists()) { deletes.put(delnam, true); delfile.delete(); } if ((z < 18)) { for (int x = 0; x < 2; x++) { for (int y = 0; y < 2; y++) { clean((z + 1), (xn * 2 + x), (yn * 2 + y)); } } } } public static void main(String[] args) throws Exception { if (args.length < 5) { System.err.println("Usage: java -jar jrender.jar <osm source directory> <tile directory> <zoom> <xtile> <ytile>"); System.exit(-1); } srcdir = args[0]; dstdir = args[1]; zoom = Integer.parseInt(args[2]); xtile = Integer.parseInt(args[3]); ytile = Integer.parseInt(args[4]); send = new ArrayList<>(); deletes = new HashMap<>(); BufferedReader in = new BufferedReader(new FileReader(srcdir + xtile + "-" + ytile + "-" + zoom + ".osm")); map = new S57map(true); S57osm.OSMmap(in, map, false); in.close(); context = new Context(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ImageIO.write(new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB), "png", bos); empty = bos.size(); if (zoom == 12) { clean(12, 0, 0); } tile(zoom, 1, 0, 0); if (send.size() > 0) { PrintWriter writer = new PrintWriter(srcdir + zoom + "-" + xtile + "-" + ytile + ".send", "UTF-8"); for (String str : send) { writer.println(str); } writer.close(); } if (deletes.size() > 0) { PrintWriter writer = new PrintWriter(srcdir + zoom + "-" + xtile + "-" + ytile + ".delete", "UTF-8"); for (String del : deletes.keySet()) { writer.println("rm " + del); } writer.close(); } System.exit(0); } }