jflowmap.views.map.PGeoMap.java Source code

Java tutorial

Introduction

Here is the source code for jflowmap.views.map.PGeoMap.java

Source

/*
 * This file is part of JFlowMap.
 *
 * Copyright 2009 Ilya Boyandin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package jflowmap.views.map;

import java.awt.geom.Rectangle2D;
import java.awt.geom.Rectangle2D.Double;
import java.util.Collections;
import java.util.List;

import jflowmap.geo.MapProjection;
import jflowmap.geom.GeomUtils;
import jflowmap.models.map.GeoMap;
import jflowmap.models.map.MapArea;
import jflowmap.util.piccolo.PNodes;
import jflowmap.views.ColorCodes;
import jflowmap.views.flowmap.ColorSchemeAware;
import prefuse.data.Node;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

import edu.umd.cs.piccolo.PNode;

/**
 * @author Ilya Boyandin
 */
public class PGeoMap extends PNode {

    private static final long serialVersionUID = 1L;
    private final ColorSchemeAware colorSchemaAware;
    private final GeoMap mapModel;
    private final MapProjection mapProjection;
    private Rectangle2D boundingBox;

    public PGeoMap(PGeoMap toCopy) {
        this(toCopy.getColorSchemaAware(), toCopy.mapModel, toCopy.mapProjection);
    }

    public PGeoMap(ColorSchemeAware cs, GeoMap mapModel, MapProjection proj) {
        this.mapModel = mapModel;
        this.colorSchemaAware = cs;
        this.mapProjection = proj;
        for (MapArea area : mapModel.getAreas()) {
            if (!area.isEmpty()) {
                addArea(area);
            }
        }
        setPaint(getColorSchemaAware().getColor(ColorCodes.BACKGROUND));
    }

    public Rectangle2D getBoundingBox() {
        if (boundingBox == null) {
            Rectangle2D b = null;
            for (PGeoMapArea va : PNodes.childrenOfType(this, PGeoMapArea.class)) {
                if (b == null) {
                    b = va.getBoundingBox();
                } else {
                    b.add(va.getBoundingBox());
                }
            }
            boundingBox = b;
        }
        return (Rectangle2D) boundingBox.clone();
    }

    public PGeoMapArea addArea(MapArea area) {
        return addArea(area, mapProjection);
    }

    public PGeoMapArea addArea(MapArea area, MapProjection proj) {
        PGeoMapArea visualArea = createVisualArea(area, proj);
        addChild(visualArea);
        boundingBox = null;
        return visualArea;
    }

    private PGeoMapArea createVisualArea(MapArea area, MapProjection proj) {
        return new PGeoMapArea(this, area, proj);
    }

    public MapProjection getMapProjection() {
        return mapProjection;
    }

    public ColorSchemeAware getColorSchemaAware() {
        return colorSchemaAware;
    }

    public void updateColors() {
        for (PGeoMapArea va : PNodes.childrenOfType(this, PGeoMapArea.class)) {
            va.updateColors();
        }
    }

    public PGeoMapArea getVisualAreaBy(String id) {
        for (PGeoMapArea va : PNodes.childrenOfType(this, PGeoMapArea.class)) {
            String vaid = va.getArea().getId();
            if (vaid != null && id.equals(vaid))
                return va;
        }
        return null;
    }

    public List<Rectangle2D> createAreasForNodesWithoutCoords(Iterable<Node> nodesWithoutCoords) {
        int num = Iterables.size(nodesWithoutCoords);
        if (num <= 0) {
            return Collections.emptyList();
        }

        List<Rectangle2D> rects = Lists.newArrayList();

        int maxPerRow = 4;
        int numPerRow = Math.min(maxPerRow, num);
        int r = num % numPerRow;

        Rectangle2D bounds = getBoundingBox();
        double rwidth = bounds.getWidth() * 0.7 / (maxPerRow - 1);
        double rheight = (bounds.getHeight() / 10);
        double topMargin = bounds.getHeight() / 5;

        for (int i = 0; i < num; i++) {
            final int numInThisRow = (i >= (num - r) ? r : numPerRow);
            double hcentering = (bounds.getWidth() - (numInThisRow - 1) * rwidth) / 2;

            double x = hcentering + bounds.getMinX() + (i % numPerRow) * rwidth;
            double y = bounds.getMaxY() + topMargin + Math.floor(i / numPerRow) * rheight;

            Rectangle2D rect = new Double(x - rwidth / 2, y - rheight / 3, rwidth, rheight);
            rect = GeomUtils.growRectByRelativeSize(rect, -0.05, -0.1, -0.05, -0.1);

            rects.add(rect);
        }

        assert (rects.size() == num);

        return rects;
    }
}