001/*
002 * Copyright 2006 - 2013
003 *     Stefan Balev     <stefan.balev@graphstream-project.org>
004 *     Julien Baudry    <julien.baudry@graphstream-project.org>
005 *     Antoine Dutot    <antoine.dutot@graphstream-project.org>
006 *     Yoann Pigné      <yoann.pigne@graphstream-project.org>
007 *     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
008 * 
009 * This file is part of GraphStream <http://graphstream-project.org>.
010 * 
011 * GraphStream is a library whose purpose is to handle static or dynamic
012 * graph, create them from scratch, file or any source and display them.
013 * 
014 * This program is free software distributed under the terms of two licenses, the
015 * CeCILL-C license that fits European law, and the GNU Lesser General Public
016 * License. You can  use, modify and/ or redistribute the software under the terms
017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
019 * the Free Software Foundation, either version 3 of the License, or (at your
020 * option) any later version.
021 * 
022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
024 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
025 * 
026 * You should have received a copy of the GNU Lesser General Public License
027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
028 * 
029 * The fact that you are presently reading this means that you have had
030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
031 */
032package org.graphstream.ui.swingViewer.util;
033
034import org.graphstream.ui.geom.Point3;
035import org.graphstream.ui.geom.Vector3;
036import org.graphstream.ui.graphicGraph.stylesheet.StyleConstants;
037import org.graphstream.ui.graphicGraph.stylesheet.Value;
038import org.graphstream.ui.graphicGraph.stylesheet.Values;
039import org.graphstream.ui.graphicGraph.stylesheet.StyleConstants.Units;
040
041/**
042 * p Various geometric informations on the graphic graph.
043 * 
044 * <p>
045 * This class extends the GraphMetrics to provide not only metrics on the
046 * graphic graph but also on the rendering canvas, and allow to convert from
047 * graph metrics to canvas metrics and the reverse.
048 * </p>
049 * 
050 * <p>
051 * Here we call the canvas "view port" since this class allows to place a view
052 * port inside the graph in order to zoom and pan the view.
053 * </p>
054 */
055public class GraphMetrics {
056        // Attribute
057
058        /**
059         * Graph lower position (bottom,left,front).
060         */
061        public Point3 lo = new Point3();
062
063        /**
064         * Graph higher position (top,right,back).
065         */
066        public Point3 hi = new Point3();
067
068        /**
069         * The lowest visible point.
070         */
071        public Point3 loVisible = new Point3();
072
073        /**
074         * The highest visible point.
075         */
076        public Point3 hiVisible = new Point3();
077
078        /**
079         * Graph dimension.
080         */
081        public Vector3 size = new Vector3();
082
083        /**
084         * The graph diagonal.
085         */
086        public double diagonal = 1;
087
088        /**
089         * The view port size.
090         */
091        public double viewport[] = new double[4];
092
093        /**
094         * The scaling factor to pass from graph units to pixels.
095         */
096        public double ratioPx2Gu;
097
098        /**
099         * The length for one pixel, according to the current transformation.
100         */
101        public double px1;
102
103        // Construction
104
105        /**
106         * New canvas metrics with default values.
107         */
108        public GraphMetrics() {
109                setDefaults();
110        }
111
112        /**
113         * Set defaults value in the lo, hi and size fields to (-1) and (1)
114         * respectively.
115         */
116        protected void setDefaults() {
117                lo.set(-1, -1, -1);
118                hi.set(1, 1, 1);
119                size.set(2, 2, 2);
120
121                diagonal = 1;
122                ratioPx2Gu = 1;
123                px1 = 1;
124        }
125
126        // Access
127
128        /**
129         * The graph diagonal (the overall width).
130         * 
131         * @return The diagonal.
132         */
133        public double getDiagonal() {
134                return diagonal;
135        }
136
137        /**
138         * The graph bounds.
139         * 
140         * @return The size.
141         */
142        public Vector3 getSize() {
143                return size;
144        }
145
146        /**
147         * The graph lowest (bottom,left,front) point.
148         * 
149         * @return The lowest point.
150         */
151        public Point3 getLowPoint() {
152                return lo;
153        }
154
155        /**
156         * The graph highest (top,right,back) point.
157         * 
158         * @return The highest point.
159         */
160        public Point3 getHighPoint() {
161                return hi;
162        }
163
164        public double graphWidthGU() {
165                return hi.x - lo.x;
166        }
167
168        public double graphHeightGU() {
169                return hi.y - lo.y;
170        }
171
172        public double graphDepthGU() {
173                return hi.z - lo.z;
174        }
175
176        // Access -- Convert values
177
178        /**
179         * Convert a value in given units to graph units.
180         * 
181         * @param value
182         *            The value to convert.
183         * @param units
184         *            The units the value to convert is expressed in.
185         * @return The value converted to GU.
186         */
187        public double lengthToGu(double value, StyleConstants.Units units) {
188                switch (units) {
189                case PX:
190                        //return (value - 0.01f) / ratioPx2Gu;
191                        return value / ratioPx2Gu;
192                case PERCENTS:
193                        return (diagonal * value);
194                case GU:
195                default:
196                        return value;
197                }
198        }
199
200        /**
201         * Convert a value in a given units to graph units.
202         * 
203         * @param value
204         *            The value to convert (it contains its own units).
205         */
206        public double lengthToGu(Value value) {
207                return lengthToGu(value.value, value.units);
208        }
209
210        /**
211         * Convert one of the given values in a given units to graph units.
212         * 
213         * @param values
214         *            The values set containing the value to convert (it contains
215         *            its own units).
216         * @param index
217         *            Index of the value to convert.
218         */
219        public double lengthToGu(Values values, int index) {
220                return lengthToGu(values.get(index), values.units);
221        }
222
223        /**
224         * Convert a value in a given units to pixels.
225         * 
226         * @param value
227         *            The value to convert.
228         * @param units
229         *            The units the value to convert is expressed in.
230         * @return The value converted in pixels.
231         */
232        public double lengthToPx(double value, StyleConstants.Units units) {
233                switch (units) {
234                case GU:
235                        //return (value - 0.01f) * ratioPx2Gu;
236                        return value * ratioPx2Gu;
237                case PERCENTS:
238                        return (diagonal * value) * ratioPx2Gu;
239                case PX:
240                default:
241                        return value;
242                }
243        }
244
245        /**
246         * Convert a value in a given units to pixels.
247         * 
248         * @param value
249         *            The value to convert (it contains its own units).
250         */
251        public double lengthToPx(Value value) {
252                return lengthToPx(value.value, value.units);
253        }
254
255        /**
256         * Convert one of the given values in a given units pixels.
257         * 
258         * @param values
259         *            The values set containing the value to convert (it contains
260         *            its own units).
261         * @param index
262         *            Index of the value to convert.
263         */
264        public double lengthToPx(Values values, int index) {
265                return lengthToPx(values.get(index), values.units);
266        }
267
268        public double positionPixelToGu(int pixels, int index) {
269                double l = lengthToGu(pixels, Units.PX);
270
271                switch (index) {
272                case 0:
273                        l -= graphWidthGU() / 2.0;
274                        l = (hi.x + lo.x) / 2.0 + l;
275                        break;
276                case 1:
277                        l -= graphHeightGU() / 2.0;
278                        l = (hi.y + lo.y) / 2.0 + l;
279                        break;
280                default:
281                        throw new IllegalArgumentException();
282                }
283
284                System.out.printf("%spixel[%d] %d --> %fgu\n", this, index, pixels, l);
285                
286                return l;
287        }
288
289        @Override
290        public String toString() {
291                StringBuilder builder = new StringBuilder(String
292                                .format("Graph Metrics :%n"));
293
294                builder.append(String.format("        lo         = %s%n", lo));
295                builder.append(String.format("        hi         = %s%n", hi));
296                builder.append(String.format("        visible lo = %s%n", loVisible));
297                builder.append(String.format("        visible hi = %s%n", hiVisible));
298                builder.append(String.format("        size       = %s%n", size));
299                builder.append(String.format("        diag       = %f%n", diagonal));
300                builder.append(String.format("        viewport   = %s%n", viewport));
301                builder.append(String.format("        ratio      = %fpx = 1gu%n",
302                                ratioPx2Gu));
303
304                return builder.toString();
305        }
306
307        // Command
308
309        /**
310         * Set the output view port size in pixels.
311         * 
312         * @param viewportWidth
313         *            The width in pixels of the view port.
314         * @param viewportHeight
315         *            The width in pixels of the view port.
316         */
317        public void setViewport(double viewportX, double viewportY, double viewportWidth, double viewportHeight) {
318                viewport[0] = viewportX;
319                viewport[1] = viewportY;
320                viewport[2] = viewportWidth;
321                viewport[3] = viewportHeight;
322        }
323
324        /**
325         * The ratio to pass by multiplication from pixels to graph units. This
326         * ratio must be larger than zero, else nothing is changed.
327         * 
328         * @param ratio
329         *            The ratio.
330         */
331        public void setRatioPx2Gu(double ratio) {
332                if (ratio > 0) {
333                        ratioPx2Gu = ratio;
334                        px1 = 0.95f / ratioPx2Gu;
335                }
336        }
337
338        /**
339         * Set the graphic graph bounds (the lowest and highest points).
340         * 
341         * @param minx
342         *            Lowest abscissa.
343         * @param miny
344         *            Lowest ordinate.
345         * @param minz
346         *            Lowest depth.
347         * @param maxx
348         *            Highest abscissa.
349         * @param maxy
350         *            Highest ordinate.
351         * @param maxz
352         *            Highest depth.
353         */
354        public void setBounds(double minx, double miny, double minz, double maxx,
355                        double maxy, double maxz) {
356                lo.x = minx;
357                lo.y = miny;
358                lo.z = minz;
359                hi.x = maxx;
360                hi.y = maxy;
361                hi.z = maxz;
362
363                size.data[0] = hi.x - lo.x;
364                size.data[1] = hi.y - lo.y;
365                size.data[2] = hi.z - lo.z;
366                diagonal = Math.sqrt(size.data[0] * size.data[0] + size.data[1]
367                                * size.data[1] + size.data[2] * size.data[2]);
368
369                // System.err.printf( "lo=%s hi=%s%n", lo, hi );
370        }
371}