Subversion Repositories splitter

Rev

Rev 529 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Copyright (C) 2014, Gerd Petermann
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 or
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

package uk.me.parabola.splitter.solver;

import java.awt.Rectangle;
import java.util.BitSet;

import uk.me.parabola.splitter.Area;
import uk.me.parabola.splitter.Utils;

/**
 * Contains info that is needed by the {@link Tile} class. For a given
 * DensityMap we calculate some extra info to allow faster access to row sums
 * and column sums.
 *
 * @author GerdP
 *
 */

public class EnhancedDensityMap {
        private final DensityMap densityMap;
        private int[][] xyMap;
        private int[][] yxMap;
        private BitSet xyInPolygon;
        private double[] aspectRatioFactor;
        private int minAspectRatioFactorPos;
        private int maxNodesInDensityMapGridElement = Integer.MIN_VALUE;
        private int maxNodesInDensityMapGridElementInPoly = Integer.MIN_VALUE;
        private java.awt.geom.Area polygonArea;

        public EnhancedDensityMap(DensityMap densities, java.awt.geom.Area polygonArea) {
                this.densityMap = densities;
                this.polygonArea = polygonArea;
                prepare();
        }

       
        /**
         * If a polygon is given, filter the density data Compute once complex
         * trigonometric results for needed for proper aspect ratio calculations.
         *
         */

        private void prepare(){
                // performance: calculate only once the needed complex math results
                aspectRatioFactor = new double[densityMap.getHeight()+1];
                int minLat = densityMap.getBounds().getMinLat();
                int maxLat = densityMap.getBounds().getMaxLat();
                int lat = 0;
                double maxAspectRatioFactor = Double.MIN_VALUE;
                int minPos = Integer.MAX_VALUE;
                for (int i = 0; i < aspectRatioFactor.length; i++ ){
                        lat = minLat + i * (1 << densityMap.getShift());
                        assert lat <= maxLat;
                        aspectRatioFactor[i] = Math.cos(Math.toRadians(Utils.toDegrees(lat))) ;
                        if (maxAspectRatioFactor < aspectRatioFactor[i]){
                                maxAspectRatioFactor = aspectRatioFactor[i];
                                minPos = i;
                        }
                }
                minAspectRatioFactorPos = minPos;
                assert lat == maxLat;
               
                // filter the density map and populate xyMap  
                int width = densityMap.getWidth();
                int height = densityMap.getHeight();
                xyMap = new int [width][height];
                if (polygonArea != null)
                        xyInPolygon = new BitSet(width * height);
                int shift = densityMap.getShift();
                for (int x = 0; x < width; x++){
                        int polyXPos = densityMap.getBounds().getMinLong() +  (x << shift);
                        int[] xCol = xyMap[x];
                        for(int y = 0; y < height; y++){
                                int count = densityMap.getNodeCount(x, y);
                                if (polygonArea != null){
                                        int polyYPos = densityMap.getBounds().getMinLat() + (y << shift);
                                        if (polygonArea.intersects(polyXPos, polyYPos, 1<<shift, 1<<shift)){
                                                xyInPolygon.set(x * height + y);
                                                if (count > maxNodesInDensityMapGridElementInPoly){
                                                        maxNodesInDensityMapGridElementInPoly = count;
                                                }
                                        }
                                }
                                if (count > 0){
                                        if (count > maxNodesInDensityMapGridElement)
                                                maxNodesInDensityMapGridElement = count;

                                        xCol[y] = count;
                                }
                        }
                }
                // create and populate yxMap, this helps to speed up row access
                yxMap = new int [height][width];
                for(int y = 0; y < height; y++){
                        int[] yRow = yxMap[y];
                        for (int x = 0; x < width; x++){
                                yRow[x] = xyMap[x][y];
                        }
                }
        }

        public boolean isGridElemInPolygon (int x, int y){
                if (polygonArea == null)
                        return true;
                return xyInPolygon.get(x* densityMap.getHeight() + y);
        }
       
        // calculate aspect ratio of a tile which is a view on the densityMap
        public double getAspectRatio(Rectangle r) {
                double ratio;
                double maxWidth ;
                if (r.y < minAspectRatioFactorPos && r.y+r.height > minAspectRatioFactorPos){
                        maxWidth = r.width; // tile crosses equator
                }else {
                        double width1 = r.width * aspectRatioFactor[r.y];
                        double width2 = r.width * aspectRatioFactor[r.y + r.height];
                        maxWidth = Math.max(width1, width2);           
                }
                ratio = maxWidth/r.height;
                return ratio;
        }
       
        public Area getBounds() {
                return densityMap.getBounds();
        }
        public DensityMap getDensityMap() {
                return densityMap;
        }
       
        public long getNodeCount(){
                return densityMap.getNodeCount();
        }
        public int[] getMapRow(int mapRow) {
                return yxMap[mapRow];
        }
        public int[] getMapCol(int mapCol) {
                return xyMap[mapCol];
        }
        public double[] getAspectRatioFactor() {
                return aspectRatioFactor;
        }
        public int getMinAspectRatioFactorPos() {
                return minAspectRatioFactorPos;
        }

        public int getMaxNodesInDensityMapGridElement() {
                return maxNodesInDensityMapGridElement;
        }

        public int getMaxNodesInDensityMapGridElementInPoly() {
                return maxNodesInDensityMapGridElementInPoly;
        }

        public java.awt.geom.Area getPolygonArea() {
                return polygonArea;
        }
       
}