package com.bbn.openmap.layer.vpf; import java.awt.geom.Rectangle2D; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import com.bbn.openmap.dataAccess.shape.DbfTableModel; import com.bbn.openmap.dataAccess.shape.EsriGraphic; import com.bbn.openmap.dataAccess.shape.EsriGraphicList; import com.bbn.openmap.io.FormatException; import com.bbn.openmap.proj.ProjMath; import com.bbn.openmap.util.FileUtils; import com.bbn.openmap.util.PropUtils; public class VpfCoverageTrimmer { // <editor-fold defaultstate="collapsed" desc="Logger Code"> /** * Holder for this class's Logger. This allows for lazy initialization of * the logger. */ private static final class LoggerHolder { /** * The logger for this class */ private static final Logger LOGGER = Logger.getLogger(VpfCoverageTrimmer.class.getName()); /** * Prevent instantiation */ private LoggerHolder() { throw new AssertionError("The LoggerHolder should never be instantiated"); } } /** * Get the logger for this class. * * @return logger for this class */ private static Logger getLogger() { return LoggerHolder.LOGGER; } // </editor-fold> private String sourceVpfLibLoc; private LibrarySelectionTable lst; private File outputLocation; private List<Rectangle2D> filters; private VpfCoverageTrimmer(Builder builder) { this.sourceVpfLibLoc = builder.vpfPath; this.lst = builder.lst; this.outputLocation = builder.outputLocation; this.filters = builder.filters; } public void go() throws IOException { for (Rectangle2D filter : filters) { trim(filter); } copyFilesNotDirectories(new File(sourceVpfLibLoc)); } protected void copyTileDirectories(File sourceLoc) throws IOException { if (sourceLoc.isDirectory()) { for (File currentFile : sourceLoc.listFiles()) { String localPath = currentFile.getAbsolutePath().substring(sourceVpfLibLoc.length() + 1); String destFilePath = outputLocation.getAbsolutePath() + "/" + localPath; if (currentFile.isDirectory()) { File subDir = new File(destFilePath); subDir.mkdirs(); copyTileDirectories(subDir); } else { File destFile = new File(destFilePath); if (destFile.exists()) { continue; } destFile.getParentFile().mkdirs(); FileUtils.copy(currentFile, destFile, 1028); } } } } protected void copyFilesNotDirectories(File sourceLoc) throws IOException { if (sourceLoc.isDirectory()) { for (File currentFile : sourceLoc.listFiles()) { String localPath = currentFile.getAbsolutePath().substring(sourceVpfLibLoc.length() + 1); String destFilePath = outputLocation.getAbsolutePath() + "/" + localPath; if (currentFile.isDirectory()) { File subDir = new File(destFilePath); if (subDir.exists()) { copyFilesNotDirectories(currentFile); } } else { File destFile = new File(destFilePath); if (destFile.exists()) { continue; } destFile.getParentFile().mkdirs(); FileUtils.copy(currentFile, destFile, 1028); } } } } protected void trim(Rectangle2D filter) throws IOException { double ulx = filter.getX(); double uly = filter.getY(); double lrx = ulx + filter.getWidth(); double lry = uly - filter.getHeight(); uly = Math.toDegrees(ProjMath.normalizeLatitude(Math.toRadians(uly), Math.toRadians(10.0))); lry = Math.toDegrees(ProjMath.normalizeLatitude(Math.toRadians(lry), Math.toRadians(10.0))); ulx = Math.toDegrees(ProjMath.wrapLongitude(Math.toRadians(ulx))); lrx = Math.toDegrees(ProjMath.wrapLongitude(Math.toRadians(lrx))); if (getLogger().isLoggable(Level.FINE)) { getLogger().fine("filtering on: " + uly + ", " + lry + ", " + lrx + ", " + ulx); } try { for (String libName : lst.getLibraryNames()) { CoverageAttributeTable cat = lst.getCAT(libName); List<TileDirectory> td = cat.tilesInRegion((float) uly, (float) lry, (float) lrx, (float) ulx); if (td != null) { for (TileDirectory t : td) { for (String covName : cat.getCoverageNames()) { copyTileDirectories(new File(sourceVpfLibLoc, libName + "/" + covName + "/" + t.getPath())); } copyTileDirectories(new File(sourceVpfLibLoc, libName + "/tileref")); copyTileDirectories(new File(sourceVpfLibLoc, libName + "/libref")); } } } } catch (FormatException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static class Builder { private String vpfPath; private LibrarySelectionTable lst; private File outputLocation; private List<Rectangle2D> filters = new ArrayList<Rectangle2D>(); public Builder(String vpfPath) throws FormatException { this.lst = new LibrarySelectionTable(vpfPath); this.vpfPath = vpfPath; } /** * rect defined in decimal degrees, x, y is upper left corner. * * @param rect * @return Builder */ public Builder addFilterRect(Rectangle2D rect) { filters.add(rect); return (Builder) this; } public Builder addFilterRect(String shpFile, String column, String attribute) throws MalformedURLException, FormatException { URL shpURL = PropUtils.getResourceOrFileOrURL(shpFile); if (shpURL != null) { EsriGraphicList graphicList = EsriGraphicList.getEsriGraphicList(shpURL, null, null); DbfTableModel dbf = graphicList.getTable(); int colIndex = dbf.findColumn(column); if (colIndex != -1) { int recordCount = 0; for (List<Object> record : dbf) { if (record.get(colIndex).equals(attribute)) { EsriGraphic eg = (EsriGraphic) graphicList.get(recordCount); // miny, minx, maxy, maxx double[] extents = eg.getExtents(); Rectangle2D rect = new Rectangle2D.Double(extents[1], extents[2], extents[3] - extents[1], extents[2] - extents[0]); addFilterRect(rect); getLogger().fine("Adding rect for " + attribute + " :" + rect); } recordCount++; } } else { throw new FormatException("Column " + column + " not found"); } } return (Builder) this; } public VpfCoverageTrimmer create(String outputLocationDirectory) { File vpfPathDir = new File(vpfPath); outputLocation = new File(outputLocationDirectory, vpfPathDir.getName()); if (filters.isEmpty()) { // If no filters have been added, do whole world filters.add(new Rectangle2D.Double(-180.0, 90.0, 360.0, 180.0)); } return new VpfCoverageTrimmer(this); } } public static void main(String[] args) { String vpfPath = "/Volumes/data/vpf/dnc/dnc01"; try { new VpfCoverageTrimmer.Builder(vpfPath).addFilterRect("/Volumes/data/shape/world/cntry02/cntry02.shp", "CNTRY_NAME", "Gabon").create("/Users/dietrick/Desktop").go(); } catch (FormatException fe) { System.out.println(fe.getMessage()); } catch (IOException ioe) { System.out.println(ioe.getMessage()); } } }