001/*
002 * Copyright 2010-2015 Institut Pasteur.
003 * 
004 * This file is part of Icy.
005 * 
006 * Icy is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 * 
011 * Icy is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 * 
016 * You should have received a copy of the GNU General Public License
017 * along with Icy. If not, see <http://www.gnu.org/licenses/>.
018 */
019package icy.canvas;
020
021import icy.gui.viewer.Viewer;
022import icy.sequence.DimensionId;
023import icy.type.point.Point3D;
024import icy.type.rectangle.Rectangle3D;
025
026import java.awt.Point;
027
028/**
029 * @author Stephane
030 */
031public abstract class IcyCanvas3D extends IcyCanvas
032{
033    /**
034     * 
035     */
036    private static final long serialVersionUID = 6001100311244609559L;
037
038    /** mouse position (image coordinate space) */
039    protected Point3D.Double mouseImagePos;
040
041    public IcyCanvas3D(Viewer viewer)
042    {
043        super(viewer);
044
045        // default for 3D canvas
046        posX = -1;
047        posY = -1;
048        posZ = -1;
049        posT = 0;
050
051        // initial mouse position
052        mouseImagePos = new Point3D.Double();
053    }
054
055    @Override
056    public void setPositionT(int t)
057    {
058        // position -1 not supported for T dimension on this canvas
059        if (t != -1)
060            super.setPositionT(t);
061    }
062
063    @Override
064    public double getMouseImagePosX()
065    {
066        // can be called before constructor ended
067        if (mouseImagePos == null)
068            return 0d;
069
070        return mouseImagePos.x;
071
072    }
073
074    @Override
075    public double getMouseImagePosY()
076    {
077        // can be called before constructor ended
078        if (mouseImagePos == null)
079            return 0d;
080
081        return mouseImagePos.y;
082    }
083
084    @Override
085    public double getMouseImagePosZ()
086    {
087        // can be called before constructor ended
088        if (mouseImagePos == null)
089            return 0d;
090
091        return mouseImagePos.z;
092    }
093
094    /**
095     * Return mouse image position
096     */
097    public Point3D.Double getMouseImagePos()
098    {
099        return (Point3D.Double) mouseImagePos.clone();
100    }
101
102    public void setMouseImagePos(double x, double y, double z)
103    {
104        if ((mouseImagePos.x != x) || (mouseImagePos.y != y) || (mouseImagePos.z != z))
105        {
106            mouseImagePos.x = x;
107            mouseImagePos.y = y;
108            mouseImagePos.z = z;
109
110            // direct update of mouse canvas position
111            mousePos = imageToCanvas(mouseImagePos);
112            // notify change
113            mouseImagePositionChanged(DimensionId.NULL);
114        }
115    }
116
117    /**
118     * Set mouse image position
119     */
120    public void setMouseImagePos(Point3D.Double point)
121    {
122        setMouseImagePos(point.x, point.y, point.z);
123    }
124
125    @Override
126    public boolean setMousePos(int x, int y)
127    {
128        final boolean result = super.setMousePos(x, y);
129
130        if (result)
131        {
132            if (mouseImagePos == null)
133                mouseImagePos = new Point3D.Double();
134
135            final Point3D newPos = canvasToImage(mousePos);
136            final double newX = newPos.getX();
137            final double newY = newPos.getY();
138            final double newZ = newPos.getZ();
139            boolean changed = false;
140
141            // need to check against NaN is conversion is not supported
142            if (!Double.isNaN(newX) && (newX != mouseImagePos.x))
143            {
144                mouseImagePos.x = newX;
145                changed = true;
146            }
147            // need to check against NaN is conversion is not supported
148            if (!Double.isNaN(newY) && (newY != mouseImagePos.y))
149            {
150                mouseImagePos.y = newY;
151                changed = true;
152            }
153            // need to check against NaN is conversion is not supported
154            if (!Double.isNaN(newZ) && (newZ != mouseImagePos.z))
155            {
156                mouseImagePos.z = newZ;
157                changed = true;
158            }
159
160            // notify change
161            if (changed)
162                mouseImagePositionChanged(DimensionId.NULL);
163        }
164
165        return result;
166    }
167
168    /**
169     * Convert specified image point to canvas point.
170     */
171    @SuppressWarnings("static-method")
172    public Point imageToCanvas(double x, double y, double z)
173    {
174        // default implementation, must be override in IcyCanvas3D implementation
175        return new Point(0, 0);
176    }
177
178    /**
179     * Convert specified image point to canvas point
180     */
181    public Point imageToCanvas(Point3D.Double point)
182    {
183        return imageToCanvas(point.x, point.y, point.z);
184    }
185
186    /**
187     * Convert specified canvas point to image point
188     */
189    @SuppressWarnings("static-method")
190    public Point3D.Double canvasToImage(int x, int y)
191    {
192        // default implementation, must be override in IcyCanvas3D implementation
193        return new Point3D.Double(0d, 0d, 0d);
194    }
195
196    /**
197     * Convert specified canvas point to image point
198     */
199    public Point3D.Double canvasToImage(Point point)
200    {
201        return canvasToImage(point.x, point.y);
202    }
203
204    /**
205     * Adjust view position and possibly scaling factor to ensure the specified region become visible.<br>
206     * It's up to the Canvas implementation to decide how to make the region visible.
207     * 
208     * @param region
209     *        the region we want to see
210     */
211    public void centerOn(Rectangle3D.Integer region)
212    {
213        // override it in Canvas implementation
214    }
215}