org.matsim.contrib.dvrp.util.chart.ScheduleCharts.java Source code

Java tutorial

Introduction

Here is the source code for org.matsim.contrib.dvrp.util.chart.ScheduleCharts.java

Source

/* *********************************************************************** *
 * project: org.matsim.*
 *                                                                         *
 * *********************************************************************** *
 *                                                                         *
 * copyright       : (C) 2013 by the members listed in the COPYING,        *
 *                   LICENSE and WARRANTY file.                            *
 * email           : info at matsim dot org                                *
 *                                                                         *
 * *********************************************************************** *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *   See also COPYING, LICENSE and WARRANTY file                           *
 *                                                                         *
 * *********************************************************************** */

package org.matsim.contrib.dvrp.util.chart;

import java.awt.Color;
import java.awt.Paint;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.SymbolAxis;
import org.jfree.chart.labels.XYToolTipGenerator;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYBarPainter;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.data.gantt.TaskSeries;
import org.jfree.data.gantt.TaskSeriesCollection;
import org.jfree.data.gantt.XYTaskDataset;
import org.jfree.data.time.SimpleTimePeriod;
import org.jfree.data.time.TimePeriod;
import org.jfree.data.xy.XYDataset;
import org.matsim.contrib.dvrp.data.Vehicle;
import org.matsim.contrib.dvrp.schedule.DriveTask;
import org.matsim.contrib.dvrp.schedule.Schedule;
import org.matsim.contrib.dvrp.schedule.Schedule.ScheduleStatus;
import org.matsim.contrib.dvrp.schedule.StayTask;
import org.matsim.contrib.dvrp.schedule.Task;

public class ScheduleCharts {
    public static JFreeChart chartSchedule(List<? extends Vehicle> vehicles) {
        return chartSchedule(vehicles, BASIC_DESCRIPTION_CREATOR, BASIC_PAINT_SELECTOR);
    }

    public static JFreeChart chartSchedule(Collection<? extends Vehicle> vehicles,
            DescriptionCreator descriptionCreator, PaintSelector paintSelector) {
        // data
        TaskSeriesCollection dataset = createScheduleDataset(vehicles, descriptionCreator);
        XYTaskDataset xyTaskDataset = new XYTaskDataset(dataset);

        // chart
        JFreeChart chart = ChartFactory.createXYBarChart("Schedules", "Time", false, "Vehicles", xyTaskDataset,
                PlotOrientation.HORIZONTAL, false, true, false);
        XYPlot plot = (XYPlot) chart.getPlot();

        // Y axis
        String[] series = new String[vehicles.size()];
        int i = 0;
        for (Vehicle v : vehicles) {
            series[i++] = v.getId().toString();
        }

        SymbolAxis symbolAxis = new SymbolAxis("Vehicles", series);
        symbolAxis.setGridBandsVisible(false);
        plot.setDomainAxis(symbolAxis);

        // X axis
        plot.setRangeAxis(new DateAxis("Time", TimeZone.getTimeZone("GMT"), Locale.getDefault()));

        // Renderer
        XYBarRenderer xyBarRenderer = new ChartTaskRenderer(dataset, paintSelector);
        xyBarRenderer.setUseYInterval(true);
        plot.setRenderer(xyBarRenderer);

        return chart;
    }

    @SuppressWarnings("serial")
    private static class ChartTask extends org.jfree.data.gantt.Task {
        private Task vrpTask;

        private ChartTask(String description, TimePeriod duration, Task vrpTask) {
            super(description, duration);
            this.vrpTask = vrpTask;
        }
    }

    @SuppressWarnings("serial")
    private static class ChartTaskRenderer extends XYBarRenderer {
        private final TaskSeriesCollection tsc;
        private final PaintSelector paintSelector;

        public ChartTaskRenderer(final TaskSeriesCollection tsc, PaintSelector paintSelector) {
            this.tsc = tsc;
            this.paintSelector = paintSelector;

            setBarPainter(new StandardXYBarPainter());
            setShadowVisible(false);
            setDrawBarOutline(true);

            setBaseToolTipGenerator(new XYToolTipGenerator() {
                @Override
                public String generateToolTip(XYDataset dataset, int series, int item) {
                    return getTask(series, item).getDescription();
                }
            });
        }

        @Override
        public Paint getItemPaint(int row, int column) {
            return paintSelector.select(getTask(row, column).vrpTask);
        }

        private ChartTask getTask(int series, int item) {
            ChartTask chartTask = (ChartTask) tsc.getSeries(series).get(item);
            return chartTask;
        }

    }

    public static interface PaintSelector {
        Paint select(Task task);
    }

    private static final Color WAIT_COLOR = new Color(0, 200, 0);
    private static final Color DRIVE_COLOR = new Color(200, 0, 0);

    public static final PaintSelector BASIC_PAINT_SELECTOR = task -> {
        if (task instanceof DriveTask) {
            return DRIVE_COLOR;
        } else if (task instanceof StayTask) {
            return WAIT_COLOR;
        }
        throw new IllegalStateException();
    };

    public static interface DescriptionCreator {
        String create(Task task);
    }

    public static final DescriptionCreator BASIC_DESCRIPTION_CREATOR = task -> {
        if (task instanceof StayTask) {
            return StayTask.class.toString();
        } else if (task instanceof DriveTask) {
            return DriveTask.class.toString();
        }
        throw new RuntimeException("not implemented");
    };

    private static TaskSeriesCollection createScheduleDataset(Collection<? extends Vehicle> vehicles,
            DescriptionCreator descriptionCreator) {
        TaskSeriesCollection collection = new TaskSeriesCollection();

        for (Vehicle v : vehicles) {
            Schedule schedule = v.getSchedule();

            final TaskSeries scheduleTaskSeries = new TaskSeries(v.getId().toString());

            if (schedule.getStatus() == ScheduleStatus.UNPLANNED) {
                collection.add(scheduleTaskSeries);
                continue;
            }

            for (Task t : schedule.getTasks()) {
                String description = descriptionCreator.create(t);

                TimePeriod duration = new SimpleTimePeriod(//
                        new Date((int) Math.floor(t.getBeginTime() * 1000)), //
                        new Date((int) Math.ceil(t.getEndTime() * 1000)));

                scheduleTaskSeries.add(new ChartTask(description, duration, t));
            }

            collection.add(scheduleTaskSeries);
        }

        return collection;
    }
}