Movement2DWithinShapeObserver.java 9.67 KiB
package pikelake.environment;
import fr.cemagref.observation.gui.Configurable;
import fr.cemagref.observation.gui.Drawable;
import fr.cemagref.observation.kernel.ObservablesHandler;
import fr.cemagref.observation.kernel.ObserverListener;
import fr.cemagref.ohoui.annotations.Description;
import fr.cemagref.ohoui.filters.NoTransientField;
import fr.cemagref.ohoui.swing.OhOUI;
import fr.cemagref.ohoui.swing.OhOUIDialog;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JComponent;
import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.MultiPolygon;
import pikelake.pikes.Pike;
import pikelake.pikes.PikesGroup;
public class Movement2DWithinShapeObserver extends ObserverListener implements Configurable, Drawable {
    private transient JComponent display;
    private transient GeneralPath generalPath;
    private transient List<PikesGroup> groups;
    private String title;
    // TODO supress transient when list will be supported by AutOUI
    @Description (name="Groups colors",tooltip="Colors af aquanisms groups")
    private transient List<Color> groupsColors;
    @Description (name="Background color",tooltip="Background color")
    private Color bgColor;
    @Description (name="Pikes color",tooltip="Pikes color")
    private Color pikeColor;
    @Description (name="River color",tooltip="River color")
    private Color shapeColor;
    private int margin;
//    private int sizeOfDisplayedIndividuals;
    // use for determine if generalPath must be rescaled
    private transient int displayWidthBak,displayHeightBak;
    // used for coordinates rescaling
    private transient double repositioningTranslateX,repositioningTranslateY;
    private transient double shapeOriginalWidth, shapeOriginalHeight;
    private transient double shapeAspectRatio;
    @SuppressWarnings("unused")
	private transient double rescaleFactorWithOriginal;
    public Movement2DWithinShapeObserver(int margin) {
        this(margin,Color.BLACK,Color.BLUE);
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
public Movement2DWithinShapeObserver() { this(Color.BLACK,Color.BLUE); } public Movement2DWithinShapeObserver(Color bgColor,Color shapeColor) { this(0,bgColor,shapeColor); } public Movement2DWithinShapeObserver(int margin,Color bgColor,Color shapeColor) { this.margin = margin; this.bgColor = bgColor; this.shapeColor = shapeColor; } public String getTitle() { return title; } public JComponent getDisplay() { return display; } public void init() { //System.out.println("Init Shape"); display = new DisplayComponent(); display.setVisible(false); display.setDoubleBuffered(true); displayWidthBak = 0; displayHeightBak = 0; File file = new File("data/input/shape/513_5.shp"); FileDataStore store; try { store = FileDataStoreFinder.getDataStore(file); SimpleFeatureSource featureSource = store.getFeatureSource(); SimpleFeatureIterator iterator = featureSource.getFeatures().features(); MultiPolygon p = (MultiPolygon) iterator.next().getDefaultGeometry(); iterator.close(); Path2D.Double shape = new Path2D.Double(); shape.moveTo(p.getCoordinates()[0].x, p.getCoordinates()[0].y); for (int i = 1; i < p.getCoordinates().length; i++) { Coordinate coord = p.getCoordinates()[i]; shape.lineTo(coord.x, coord.y); } this.generalPath = new GeneralPath(shape); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // original dimension storage this.shapeOriginalWidth = this.generalPath.getBounds().getWidth(); this.shapeOriginalHeight = this.generalPath.getBounds().getHeight(); this.shapeAspectRatio = shapeOriginalWidth / shapeOriginalHeight; // repositionning the shape to (0,0) this.repositioningTranslateX = - this.generalPath.getBounds().getX(); this.repositioningTranslateY = - this.generalPath.getBounds().getY(); this.generalPath.transform(AffineTransform.getTranslateInstance(this.margin+repositioningTranslateX,this.margin+repositioningTranslateY)); // vertical flip this.generalPath.transform(AffineTransform.getScaleInstance(1,-1)); this.generalPath.transform(AffineTransform.getTranslateInstance(0,shapeOriginalHeight)); this.groups = new ArrayList<PikesGroup>(); groupsColors = new ArrayList<Color>();
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
groupsColors.add(Color.RED); groupsColors.add(Color.GREEN); groupsColors.add(Color.YELLOW); groupsColors.add(Color.CYAN); groupsColors.add(Color.GRAY); display.repaint(); display.setVisible(true); //System.out.println("Fin IS"); } public void disable() { display.setVisible(false); } @Override public void addObservable(ObservablesHandler classObservable) { // nothing to do } public void valueChanged(ObservablesHandler clObservable, Object instance, long t) { if (groups == null && instance != null) { groups.add((PikesGroup) instance); } System.out.println(groups.isEmpty()); display.repaint(); display.setVisible(true); } public static interface AsShapeConvertible { public Shape getShape(); } public void configure() { OhOUIDialog dialog = OhOUI.getDialog(null,this,new NoTransientField()); dialog.setSize(new Dimension(480, 200)); dialog.setVisible(true); display.repaint(); } public void addObservable(ObserverListener classObservable) { // nothing to do } public void close() { // nothing to do } private class DisplayComponent extends JComponent { /** * */ private static final long serialVersionUID = 1L; protected synchronized void paintComponent(Graphics g) { super.paintComponents(g); Graphics2D g2d = (Graphics2D)g; // determine if generalPath must be rescaled if ( (this.getWidth() != displayWidthBak) || (this.getHeight() != displayHeightBak) ) { // backup for comparaison in the next loop displayWidthBak = this.getWidth(); displayHeightBak = this.getHeight(); // compute the rescale factor with keeping the aspect ratio double rescaleFactor; // TODO calcul faux quand margin > 0 if ( ((double)displayWidthBak/displayHeightBak) < shapeAspectRatio ) { rescaleFactor = displayWidthBak / (generalPath.getBounds().getWidth()); rescaleFactorWithOriginal = displayWidthBak / shapeOriginalWidth; } else {