001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.demos.irc; 031 032import java.util.HashMap; 033import java.util.List; 034import java.util.Map; 035 036import org.openimaj.content.animation.animator.LinearTimeBasedFloatValueAnimator; 037import org.openimaj.content.animation.animator.ValueAnimator; 038import org.openimaj.image.MBFImage; 039import org.openimaj.image.colour.ColourSpace; 040import org.openimaj.image.colour.RGBColour; 041import org.openimaj.math.geometry.point.Point2d; 042import org.openimaj.math.geometry.shape.Shape; 043import org.openimaj.math.geometry.transforms.TransformUtilities; 044import org.openimaj.text.geo.WorldPlace; 045import org.openimaj.text.geo.WorldPolygons; 046import org.openimaj.video.AnimatedVideo; 047 048import Jama.Matrix; 049 050public class WorldVis extends AnimatedVideo<MBFImage>{ 051 class LabColourAnimator implements ValueAnimator<Float[]>{ 052 private final LinearTimeBasedFloatValueAnimator l; 053 private final LinearTimeBasedFloatValueAnimator a; 054 private final LinearTimeBasedFloatValueAnimator b; 055 private final MBFImage buffer; 056 057 ColourSpace space = ColourSpace.RGB; 058 public LabColourAnimator(final Float[] start, final Float[] end, final long duration) { 059 final MBFImage startImg = new MBFImage(1,1,3); 060 startImg.setPixel(0, 0, start); 061 final MBFImage endImg = new MBFImage(1,1,3); 062 this.buffer = new MBFImage(1,1,3); 063 endImg.setPixel(0, 0, end); 064 final Float[] labstart = this.space.convertFromRGB(startImg).getPixel(0, 0); 065 final Float[] labend = this.space.convertFromRGB(endImg).getPixel(0, 0); 066 this.l = new LinearTimeBasedFloatValueAnimator(labstart[0], labend[0], duration); 067 this.a = new LinearTimeBasedFloatValueAnimator(labstart[1], labend[1], duration); 068 this.b = new LinearTimeBasedFloatValueAnimator(labstart[2], labend[2], duration); 069 } 070 @Override 071 public Float[] nextValue() { 072 this.buffer.setPixel(0, 0, new Float[]{this.l.nextValue(),this.a.nextValue(),this.b.nextValue()}); 073 final Float[] retPix = this.space.convertToRGB(this.buffer).getPixel(0, 0); 074 return retPix; 075 } 076 077 @Override 078 public boolean hasFinished() { 079 return this.l.hasFinished(); 080 } 081 082 @Override 083 public void reset() { 084 this.l.reset(); 085 this.a.reset(); 086 this.b.reset(); 087 } 088 089 } 090 private static final Float[] SEA_COLOUR = new Float[]{135f/255f,206f/255f,250f/255f}; 091 private static final Float[] LAND_COLOUR = new Float[]{238f/255f,232f/255f,170f/255f}; 092 private final int w; 093 private final int h; 094 private final WorldPolygons worldPolys; 095 private final float scale; 096 private final Map<String,LabColourAnimator> activeCountries = new HashMap<String, LabColourAnimator>(); 097 private final MBFImage img; 098 099 /** 100 * @param w 101 * @param h 102 */ 103 public WorldVis(final int w, final int h) { 104 super(new MBFImage(w,h,3)); 105 this.w = w; 106 this.h = h; 107 this.worldPolys = new WorldPolygons(); 108 this.scale = h/this.worldPolys.getBounds().height; 109 this.img = new MBFImage(w, h, 3); 110 } 111 112 private MBFImage create(){ 113 this.img.fill(WorldVis.SEA_COLOUR); 114 final Point2d mid = this.img.getBounds().calculateCentroid(); 115 Matrix trans = Matrix.identity(3, 3); 116 trans = trans.times( 117 TransformUtilities.scaleMatrixAboutPoint( 118 this.scale, this.scale, mid 119 ) 120 ); 121 trans = trans.times( 122 TransformUtilities.rotationMatrixAboutPoint(Math.PI, mid.getX(), mid.getY()) 123 ); 124 trans = trans.times( 125 TransformUtilities.translateMatrix(mid.getX(), mid.getY()) 126 ); 127 for (final WorldPlace wp : this.worldPolys.getShapes()) { 128 129 final List<Shape> shapes = wp.getShapes(); 130 for (Shape s : shapes) { 131 s = s.clone(); 132 133 s = s.transform(trans); 134 this.img.drawShape(s,3, RGBColour.RED); 135 if(this.activeCountries.containsKey(wp.getISOA2())) 136 { 137 this.img.drawShapeFilled(s, this.activeCountries.get(wp.getISOA2()).nextValue()); 138 if(this.activeCountries.get(wp.getISOA2()).hasFinished()) 139 { 140 this.activeCountries.remove(wp.getISOA2()); 141 } 142 }else{ 143 this.img.drawShapeFilled(s, WorldVis.LAND_COLOUR); 144 } 145 } 146 } 147 return this.img.flipX(); 148 } 149 150 @Override 151 protected void updateNextFrame(final MBFImage frame) { 152 frame.internalAssign(this.create()); 153 154 } 155 156 public void activate(final FreeGeoIPLocation geoip) { 157 this.activeCountries.put( 158 geoip.country_code.toLowerCase(), 159 new LabColourAnimator(RGBColour.RED, WorldVis.LAND_COLOUR, 1000) 160 ); 161 } 162 163}