From 280f9e259d64e7b514c9789f2cc98a4229091a82 Mon Sep 17 00:00:00 2001 From: Stefan Schroeder <4sschroeder@gmail.com> Date: Wed, 28 Aug 2013 18:19:39 +0200 Subject: [PATCH] improve solutionPlotter - add size-label and mark first tourAct --- .../main/java/analysis/SolutionPlotter.java | 74 +++++++++++++++---- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/jsprit-analysis/src/main/java/analysis/SolutionPlotter.java b/jsprit-analysis/src/main/java/analysis/SolutionPlotter.java index 3e7fab1e..b76e51ad 100644 --- a/jsprit-analysis/src/main/java/analysis/SolutionPlotter.java +++ b/jsprit-analysis/src/main/java/analysis/SolutionPlotter.java @@ -20,7 +20,9 @@ ******************************************************************************/ package analysis; +import java.awt.BasicStroke; import java.awt.Color; +import java.awt.geom.Ellipse2D; import java.io.File; import java.io.IOException; import java.util.Collection; @@ -32,10 +34,14 @@ import java.util.Set; import org.apache.log4j.Logger; import org.jfree.chart.ChartUtilities; import org.jfree.chart.JFreeChart; +import org.jfree.chart.annotations.XYShapeAnnotation; import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.labels.XYItemLabelGenerator; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYItemRenderer; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.data.xy.XYDataItem; +import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; @@ -82,13 +88,14 @@ public class SolutionPlotter { public static void plotVrpAsPNG(VehicleRoutingProblem vrp, String pngFile, String title){ log.info("plot routes to " + pngFile); XYSeriesCollection problem; + Map labels = new HashMap(); try { - problem = makeVrpSeries(vrp); + problem = makeVrpSeries(vrp, labels); } catch (NoLocationFoundException e) { log.warn("cannot plot vrp, since coord is missing"); return; } - XYPlot plot = createPlot(problem); + XYPlot plot = createPlot(problem, labels); JFreeChart chart = new JFreeChart(title, plot); save(chart,pngFile); } @@ -105,14 +112,15 @@ public class SolutionPlotter { public static void plotRoutesAsPNG(Collection routes, Locations locations, String pngFile, String title) { log.info("plot routes to " + pngFile); XYSeriesCollection problem; + Map labels = new HashMap(); try { - problem = makeVrpSeries(routes); + problem = makeVrpSeries(routes, labels); } catch (NoLocationFoundException e) { log.warn("cannot plot vrp, since coord is missing"); return; } XYSeriesCollection solutionColl = makeSolutionSeries(routes,locations); - XYPlot plot = createPlot(problem, solutionColl); + XYPlot plot = createPlot(problem, solutionColl, labels); JFreeChart chart = new JFreeChart(title, plot); save(chart,pngFile); } @@ -132,14 +140,15 @@ public class SolutionPlotter { log.info("plot solution to " + pngFile); XYSeriesCollection problem; XYSeriesCollection solutionColl; + Map labels = new HashMap(); try { - problem = makeVrpSeries(vrp); + problem = makeVrpSeries(vrp, labels); solutionColl = makeSolutionSeries(vrp, solution); } catch (NoLocationFoundException e) { log.warn("cannot plot vrp, since coord is missing"); return; } - XYPlot plot = createPlot(problem, solutionColl); + XYPlot plot = createPlot(problem, solutionColl, labels); JFreeChart chart = new JFreeChart(title, plot); save(chart,pngFile); @@ -147,13 +156,23 @@ public class SolutionPlotter { - private static XYPlot createPlot(XYSeriesCollection problem) { + private static XYPlot createPlot(final XYSeriesCollection problem, final Map labels) { XYPlot plot = new XYPlot(); plot.setBackgroundPaint(Color.LIGHT_GRAY); plot.setRangeGridlinePaint(Color.WHITE); plot.setDomainGridlinePaint(Color.WHITE); XYItemRenderer problemRenderer = new XYLineAndShapeRenderer(false, true); // Shapes only + problemRenderer.setBaseItemLabelGenerator(new XYItemLabelGenerator() { + + @Override + public String generateLabel(XYDataset arg0, int arg1, int arg2) { + XYDataItem item = problem.getSeries(arg1).getDataItem(arg2); + return labels.get(item); + } + }); + problemRenderer.setBaseItemLabelsVisible(true); + problemRenderer.setBaseItemLabelPaint(Color.BLACK); NumberAxis xAxis = new NumberAxis(); xAxis.setRangeWithMargins(problem.getDomainBounds(true)); @@ -169,13 +188,24 @@ public class SolutionPlotter { return plot; } - private static XYPlot createPlot(XYSeriesCollection problem, XYSeriesCollection solutionColl) { + private static XYPlot createPlot(final XYSeriesCollection problem, XYSeriesCollection solutionColl, final Map labels) { XYPlot plot = new XYPlot(); plot.setBackgroundPaint(Color.LIGHT_GRAY); plot.setRangeGridlinePaint(Color.WHITE); plot.setDomainGridlinePaint(Color.WHITE); XYItemRenderer problemRenderer = new XYLineAndShapeRenderer(false, true); // Shapes only + problemRenderer.setBaseItemLabelGenerator(new XYItemLabelGenerator() { + + @Override + public String generateLabel(XYDataset arg0, int arg1, int arg2) { + XYDataItem item = problem.getSeries(arg1).getDataItem(arg2); + return labels.get(item); + } + }); + problemRenderer.setBaseItemLabelsVisible(true); + problemRenderer.setBaseItemLabelPaint(Color.BLACK); + NumberAxis xAxis = new NumberAxis(); xAxis.setRangeWithMargins(problem.getDomainBounds(true)); @@ -188,7 +218,13 @@ public class SolutionPlotter { plot.setDomainAxis(0, xAxis); plot.setRangeAxis(0, yAxis); + XYItemRenderer solutionRenderer = new XYLineAndShapeRenderer(true, false); // Lines only + for(int i=0;i vehicles, Collection services) throws NoLocationFoundException{ + private static XYSeriesCollection makeVrpSeries(Collection vehicles, Collection services, Map labels) throws NoLocationFoundException{ XYSeriesCollection coll = new XYSeriesCollection(); XYSeries vehicleSeries = new XYSeries("depot", false, true); for(Vehicle v : vehicles){ @@ -273,17 +309,23 @@ public class SolutionPlotter { if(job instanceof Pickup){ Pickup service = (Pickup)job; Coordinate coord = service.getCoord(); - pickupSeries.add(coord.getX(), coord.getY()); + XYDataItem dataItem = new XYDataItem(coord.getX(), coord.getY()); + pickupSeries.add(dataItem); + labels.put(dataItem, String.valueOf(service.getCapacityDemand())); } else if(job instanceof Delivery){ Delivery service = (Delivery)job; Coordinate coord = service.getCoord(); - deliverySeries.add(coord.getX(), coord.getY()); + XYDataItem dataItem = new XYDataItem(coord.getX(), coord.getY()); + deliverySeries.add(dataItem); + labels.put(dataItem, String.valueOf(service.getCapacityDemand())); } else if(job instanceof Service){ Service service = (Service)job; Coordinate coord = service.getCoord(); - serviceSeries.add(coord.getX(), coord.getY()); + XYDataItem dataItem = new XYDataItem(coord.getX(), coord.getY()); + serviceSeries.add(dataItem); + labels.put(dataItem, String.valueOf(service.getCapacityDemand())); } else{ throw new IllegalStateException("job instanceof " + job.getClass().toString() + ". this is not supported."); @@ -296,18 +338,18 @@ public class SolutionPlotter { return coll; } - private static XYSeriesCollection makeVrpSeries(Collection routes) throws NoLocationFoundException{ + private static XYSeriesCollection makeVrpSeries(Collection routes, Map labels) throws NoLocationFoundException{ Set vehicles = new HashSet(); Set jobs = new HashSet(); for(VehicleRoute route : routes){ vehicles.add(route.getVehicle()); jobs.addAll(route.getTourActivities().getJobs()); } - return makeVrpSeries(vehicles, jobs); + return makeVrpSeries(vehicles, jobs, labels); } - private static XYSeriesCollection makeVrpSeries(VehicleRoutingProblem vrp) throws NoLocationFoundException{ - return makeVrpSeries(vrp.getVehicles(), vrp.getJobs().values()); + private static XYSeriesCollection makeVrpSeries(VehicleRoutingProblem vrp, Map labels) throws NoLocationFoundException{ + return makeVrpSeries(vrp.getVehicles(), vrp.getJobs().values(), labels); } private static Locations retrieveLocations(VehicleRoutingProblem vrp) throws NoLocationFoundException {