6cbfe8b87467ea45c25dd6944f14805666b04ff6
[scilab.git] / scilab / modules / renderer / src / java / org / scilab / modules / renderer / JoGLView / axes / ruler / AxesRulerDrawer.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009-2010 - DIGITEO - Pierre Lando
4  * Copyright (C) 2011 - DIGITEO - Manuel Juliachs
5  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  */
12
13 package org.scilab.modules.renderer.JoGLView.axes.ruler;
14
15 import org.scilab.forge.scirenderer.Canvas;
16 import org.scilab.forge.scirenderer.DrawingTools;
17 import org.scilab.forge.scirenderer.SciRendererException;
18 import org.scilab.forge.scirenderer.buffers.ElementsBuffer;
19 import org.scilab.forge.scirenderer.ruler.DefaultRulerModel;
20 import org.scilab.forge.scirenderer.ruler.RulerDrawer;
21 import org.scilab.forge.scirenderer.ruler.RulerDrawingResult;
22 import org.scilab.forge.scirenderer.ruler.RulerModel;
23 import org.scilab.forge.scirenderer.shapes.appearance.Appearance;
24 import org.scilab.forge.scirenderer.shapes.geometry.DefaultGeometry;
25 import org.scilab.forge.scirenderer.shapes.geometry.Geometry;
26 import org.scilab.forge.scirenderer.tranformations.DegenerateMatrixException;
27 import org.scilab.forge.scirenderer.tranformations.Transformation;
28 import org.scilab.forge.scirenderer.tranformations.TransformationFactory;
29 import org.scilab.forge.scirenderer.tranformations.Vector3d;
30 import org.scilab.modules.graphic_objects.axes.Axes;
31 import org.scilab.modules.graphic_objects.axes.AxisProperty;
32 import org.scilab.modules.graphic_objects.axes.Camera;
33 import org.scilab.modules.graphic_objects.figure.ColorMap;
34 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
35 import org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties;
36 import org.scilab.modules.renderer.JoGLView.axes.AxesDrawer;
37 import org.scilab.modules.renderer.JoGLView.label.AxisLabelPositioner;
38 import org.scilab.modules.renderer.JoGLView.util.ColorFactory;
39
40 import java.awt.Color;
41 import java.nio.FloatBuffer;
42 import java.text.DecimalFormat;
43 import java.util.Arrays;
44
45 /**
46  * @author Pierre Lando
47  */
48 public class AxesRulerDrawer {
49
50     /**
51      * Grid pattern.
52      */
53     private static final short GRID_LINE_PATTERN = (short) 0xF0F0;
54
55     private static final double LINEAR_MINIMAL_SUB_TICKS_DISTANCE = 8;
56     private static final double LOG_MINIMAL_SUB_TICKS_DISTANCE = 2;
57
58     /** Ticks length in pixels. */
59     private static final int TICKS_LENGTH = 6;
60
61     /** Sub-ticks length in pixels. */
62     private static final int SUB_TICKS_LENGTH = 3;
63
64     /**Ticks sprites distance in pixels. */
65     private static final int SPRITE_DISTANCE = 12;
66
67
68     private final RulerDrawerManager rulerDrawerManager;
69
70     public AxesRulerDrawer(Canvas canvas) {
71         this.rulerDrawerManager = new RulerDrawerManager(canvas.getTextureManager());
72     }
73
74     /**
75      * Draw the ruler.
76      * @param axes the current {@see Axes}
77      * @param axesDrawer the drawer used to draw the current {@see Axes}
78      * @param colorMap current {@see ColorMap}
79      * @param drawingTools the used {@see DrawingTools}
80      * @throws org.scilab.forge.scirenderer.SciRendererException if draw fail.
81      */
82     public void drawRuler(Axes axes, AxesDrawer axesDrawer, ColorMap colorMap, DrawingTools drawingTools) throws SciRendererException {
83         Double[] bounds = axes.getDisplayedBounds();
84         double[] matrix = drawingTools.getTransformationManager().getModelViewStack().peek().getMatrix();
85
86         RulerDrawingResult rulerDrawingResult;
87         double[] values;
88
89         RulerDrawer[] rulerDrawers = rulerDrawerManager.get(axes);
90         DefaultRulerModel rulerModel = new DefaultRulerModel();
91         rulerModel.setTicksLength(TICKS_LENGTH);
92         rulerModel.setSubTicksLength(SUB_TICKS_LENGTH);
93         rulerModel.setLineWidth(axes.getLineThickness());
94         rulerModel.setSpriteDistance(SPRITE_DISTANCE);
95         rulerModel.setColor(ColorFactory.createColor(colorMap, axes.getLineColor()));
96
97         Transformation canvasProjection = drawingTools.getTransformationManager().getCanvasProjection();
98
99         Vector3d xAxisPosition = computeXAxisPosition(matrix, bounds, axes.getXAxis().getAxisLocation());
100         Vector3d yAxisPosition = computeYAxisPosition(matrix, bounds, axes.getYAxis().getAxisLocation());
101
102         Vector3d px = canvasProjection.projectDirection(new Vector3d(1, 0, 0)).setZ(0);
103         Vector3d py = canvasProjection.projectDirection(new Vector3d(0, 1, 0)).setZ(0);
104         Vector3d pz = canvasProjection.projectDirection(new Vector3d(0, 0, 1)).setZ(0);
105
106         Vector3d xTicksDirection, yTicksDirection;
107         if (py.getNorm2() > pz.getNorm2()) {
108             xTicksDirection = new Vector3d(0, getNonZeroSignum(xAxisPosition.getY()), 0);
109         } else {
110             xTicksDirection = new Vector3d(0, 0, getNonZeroSignum(xAxisPosition.getZ()));
111         }
112
113         if (px.getNorm2() > pz.getNorm2()) {
114             yTicksDirection = new Vector3d(getNonZeroSignum(yAxisPosition.getX()), 0, 0);
115         } else {
116             yTicksDirection = new Vector3d(0, 0, getNonZeroSignum(yAxisPosition.getZ()));
117         }
118
119         int gridPosition;
120         if (axes.getGridPositionAsEnum().equals(Axes.GridPosition.FOREGROUND)) {
121             gridPosition = 1;
122         } else {
123             gridPosition = -1;
124         }
125
126         // Draw X ruler
127
128         ElementsBuffer vertexBuffer = drawingTools.getCanvas().getBuffersManager().createElementsBuffer();
129
130         Appearance gridAppearance = new Appearance();
131         gridAppearance.setLinePattern(GRID_LINE_PATTERN);
132         gridAppearance.setLineWidth(axes.getLineThickness().floatValue());
133
134         rulerModel.setTicksDirection(xTicksDirection);
135         rulerModel.setFirstPoint(xAxisPosition.setX(-1));
136         rulerModel.setSecondPoint(xAxisPosition.setX(1));
137
138         setRulerBounds(axes.getXAxis(), rulerModel, bounds[0], bounds[1]);
139
140         rulerModel.setLogarithmic(axes.getXAxis().getLogFlag());
141         rulerModel.setMinimalSubTicksDistance(axes.getXAxis().getLogFlag() ? LOG_MINIMAL_SUB_TICKS_DISTANCE : LINEAR_MINIMAL_SUB_TICKS_DISTANCE);
142
143         if (!axes.getXAxis().getAutoTicks()) {
144             rulerModel.setUserGraduation(new UserDefineGraduation(axes.getXAxis(), bounds[0], bounds[1]));
145             rulerModel.setAutoTicks(false);
146         } else {
147             rulerModel.setAutoTicks(true);
148         }
149
150         double distanceRatio;
151         AxisLabelPositioner xAxisLabelPositioner = axesDrawer.getXAxisLabelPositioner();
152         xAxisLabelPositioner.setLabelPosition(xAxisPosition);
153
154         if (axes.getXAxisVisible()) {
155             rulerDrawingResult = rulerDrawers[0].draw(drawingTools, rulerModel);
156             values = rulerDrawingResult.getTicksValues();
157             if (axes.getXAxisAutoTicks()) {
158                 Arrays.sort(values);
159                 GraphicController.getController().setProperty(axes.getIdentifier(), GraphicObjectProperties.__GO_X_AXIS_TICKS_LOCATIONS__, toDoubleArray(values));
160                 GraphicController.getController().setProperty(axes.getIdentifier(), GraphicObjectProperties.__GO_X_AXIS_TICKS_LABELS__, toStringArray(values, rulerDrawingResult.getFormat()));
161                 GraphicController.getController().setProperty(axes.getIdentifier(), GraphicObjectProperties.__GO_X_AXIS_SUBTICKS__, rulerDrawingResult.getSubTicksDensity() - 1);
162             }
163
164             distanceRatio  = rulerDrawingResult.getMaxDistToTicksDirNorm();
165
166             xAxisLabelPositioner.setTicksDirection(xTicksDirection);
167             xAxisLabelPositioner.setDistanceRatio(distanceRatio);
168             xAxisLabelPositioner.setProjectedTicksDirection(rulerDrawingResult.getNormalizedTicksDirection().setZ(0));
169
170             if (axes.getXAxisGridColor() != -1) {
171                 FloatBuffer vertexData;
172                 if (axes.getXAxisLogFlag()) {
173                     vertexData = getXGridData(rulerDrawingResult.getSubTicksValues(), rulerModel);
174                 } else {
175                     vertexData = getXGridData(values, rulerModel);
176                 }
177                 vertexBuffer.setData(vertexData, 4);
178
179                 Transformation mirror;
180                 try {
181                     mirror = TransformationFactory.getScaleTransformation(
182                                  1,
183                                  matrix[6] < 0 ? gridPosition : -gridPosition,
184                                  matrix[10] < 0 ? gridPosition : -gridPosition
185                              );
186                 } catch (DegenerateMatrixException ignored) {
187                     // Should never happens as long as gridPosition the value 1 or -1
188                     mirror = TransformationFactory.getIdentity();
189                 }
190
191                 gridAppearance.setLineColor(ColorFactory.createColor(colorMap, axes.getXAxisGridColor()));
192                 drawingTools.getTransformationManager().getModelViewStack().pushRightMultiply(mirror);
193                 DefaultGeometry gridGeometry = new DefaultGeometry();
194                 gridGeometry.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
195                 gridGeometry.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
196                 gridGeometry.setVertices(vertexBuffer);
197                 drawingTools.draw(gridGeometry, gridAppearance);
198                 drawingTools.getTransformationManager().getModelViewStack().pop();
199             }
200
201         } else {
202             /*
203              * x-axis not visible: the projected ticks direction must be computed, as well as
204              * the distance ratio using the default ticks length as numerator.
205              */
206             xAxisLabelPositioner.setTicksDirection(xTicksDirection);
207             Vector3d projTicksDir = canvasProjection.projectDirection(xTicksDirection);
208             xAxisLabelPositioner.setDistanceRatio((double) TICKS_LENGTH / projTicksDir.getNorm());
209             xAxisLabelPositioner.setProjectedTicksDirection(projTicksDir.getNormalized().setZ(0));
210         }
211
212         // Draw Y ruler
213         rulerModel.setTicksDirection(yTicksDirection);
214         rulerModel.setFirstPoint(yAxisPosition.setY(-1));
215         rulerModel.setSecondPoint(yAxisPosition.setY(1));
216
217         setRulerBounds(axes.getYAxis(), rulerModel, bounds[2], bounds[3]);
218         rulerModel.setLogarithmic(axes.getYAxis().getLogFlag());
219         rulerModel.setMinimalSubTicksDistance(axes.getYAxis().getLogFlag() ? LOG_MINIMAL_SUB_TICKS_DISTANCE : LINEAR_MINIMAL_SUB_TICKS_DISTANCE);
220
221         if (!axes.getYAxis().getAutoTicks()) {
222             rulerModel.setUserGraduation(new UserDefineGraduation(axes.getYAxis(), bounds[2], bounds[3]));
223             rulerModel.setAutoTicks(false);
224         } else {
225             rulerModel.setAutoTicks(true);
226         }
227
228         AxisLabelPositioner yAxisLabelPositioner = axesDrawer.getYAxisLabelPositioner();
229         yAxisLabelPositioner.setLabelPosition(yAxisPosition);
230
231         if (axes.getYAxisVisible()) {
232             rulerDrawingResult = rulerDrawers[1].draw(drawingTools, rulerModel);
233             values = rulerDrawingResult.getTicksValues();
234             if (axes.getYAxisAutoTicks()) {
235                 Arrays.sort(values);
236                 GraphicController.getController().setProperty(axes.getIdentifier(), GraphicObjectProperties.__GO_Y_AXIS_TICKS_LOCATIONS__, toDoubleArray(values));
237                 GraphicController.getController().setProperty(axes.getIdentifier(), GraphicObjectProperties.__GO_Y_AXIS_TICKS_LABELS__, toStringArray(values, rulerDrawingResult.getFormat()));
238                 GraphicController.getController().setProperty(axes.getIdentifier(), GraphicObjectProperties.__GO_Y_AXIS_SUBTICKS__, rulerDrawingResult.getSubTicksDensity() - 1);
239             }
240
241             distanceRatio = rulerDrawingResult.getMaxDistToTicksDirNorm();
242
243             yAxisLabelPositioner.setTicksDirection(yTicksDirection);
244             yAxisLabelPositioner.setDistanceRatio(distanceRatio);
245             yAxisLabelPositioner.setProjectedTicksDirection(rulerDrawingResult.getNormalizedTicksDirection().setZ(0));
246
247             if (axes.getYAxisGridColor() != -1) {
248                 FloatBuffer vertexData;
249                 if (axes.getYAxisLogFlag()) {
250                     vertexData = getYGridData(rulerDrawingResult.getSubTicksValues(), rulerModel);
251                 } else {
252                     vertexData = getYGridData(values, rulerModel);
253                 }
254                 vertexBuffer.setData(vertexData, 4);
255
256                 Transformation mirror;
257                 try {
258                     mirror = TransformationFactory.getScaleTransformation(
259                                  matrix[2] < 0 ? gridPosition : -gridPosition,
260                                  1,
261                                  matrix[10] < 0 ? gridPosition : -gridPosition
262                              );
263                 } catch (DegenerateMatrixException ignored) {
264                     // Should never happens as long as gridPosition the value 1 or -1
265                     mirror = TransformationFactory.getIdentity();
266                 }
267
268                 gridAppearance.setLineColor(ColorFactory.createColor(colorMap, axes.getYAxisGridColor()));
269                 drawingTools.getTransformationManager().getModelViewStack().pushRightMultiply(mirror);
270                 DefaultGeometry gridGeometry = new DefaultGeometry();
271                 gridGeometry.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
272                 gridGeometry.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
273                 gridGeometry.setVertices(vertexBuffer);
274                 drawingTools.draw(gridGeometry, gridAppearance);
275                 drawingTools.getTransformationManager().getModelViewStack().pop();
276             }
277         } else {
278             /* y-axis not visible: compute the projected ticks direction and distance ratio (see the x-axis case). */
279             yAxisLabelPositioner.setTicksDirection(yTicksDirection);
280             Vector3d projTicksDir = canvasProjection.projectDirection(yTicksDirection);
281             yAxisLabelPositioner.setDistanceRatio((double) TICKS_LENGTH / projTicksDir.getNorm());
282             yAxisLabelPositioner.setProjectedTicksDirection(projTicksDir.getNormalized().setZ(0));
283         }
284
285         // Draw Z ruler
286         if (axes.getViewAsEnum() == Camera.ViewType.VIEW_3D && axes.getRotationAngles()[1] != 90.0) {
287             double txs, tys, xs, ys;
288
289             if (Math.abs(matrix[2]) < Math.abs(matrix[6])) {
290                 xs = Math.signum(matrix[2]);
291                 ys = -Math.signum(matrix[6]);
292                 txs = xs;
293                 tys = 0;
294             } else {
295                 xs = -Math.signum(matrix[2]);
296                 ys = Math.signum(matrix[6]);
297                 txs = 0;
298                 tys = ys;
299             }
300
301             rulerModel.setFirstPoint(new Vector3d(xs, ys, -1));
302             rulerModel.setSecondPoint(new Vector3d(xs, ys, 1));
303             rulerModel.setTicksDirection(new Vector3d(txs, tys, 0));
304
305
306             setRulerBounds(axes.getZAxis(), rulerModel, bounds[4], bounds[5]);
307             rulerModel.setLogarithmic(axes.getZAxis().getLogFlag());
308             rulerModel.setMinimalSubTicksDistance(axes.getZAxis().getLogFlag() ? LOG_MINIMAL_SUB_TICKS_DISTANCE : LINEAR_MINIMAL_SUB_TICKS_DISTANCE);
309
310             if (!axes.getZAxis().getAutoTicks()) {
311                 rulerModel.setUserGraduation(new UserDefineGraduation(axes.getZAxis(), bounds[4], bounds[5]));
312                 rulerModel.setAutoTicks(false);
313             } else {
314                 rulerModel.setAutoTicks(true);
315             }
316
317             AxisLabelPositioner zAxisLabelPositioner = axesDrawer.getZAxisLabelPositioner();
318             zAxisLabelPositioner.setLabelPosition(new Vector3d(xs, ys, 0));
319
320             if (axes.getZAxisVisible()) {
321                 rulerDrawingResult = rulerDrawers[2].draw(drawingTools, rulerModel);
322                 values = rulerDrawingResult.getTicksValues();
323                 if (axes.getZAxisAutoTicks()) {
324                     Arrays.sort(values);
325                     GraphicController.getController().setProperty(axes.getIdentifier(), GraphicObjectProperties.__GO_Z_AXIS_TICKS_LOCATIONS__, toDoubleArray(values));
326                     GraphicController.getController().setProperty(axes.getIdentifier(), GraphicObjectProperties.__GO_Z_AXIS_TICKS_LABELS__, toStringArray(values, rulerDrawingResult.getFormat()));
327                     GraphicController.getController().setProperty(axes.getIdentifier(), GraphicObjectProperties.__GO_Z_AXIS_SUBTICKS__, rulerDrawingResult.getSubTicksDensity() - 1);
328                 }
329
330                 distanceRatio = rulerDrawingResult.getMaxDistToTicksDirNorm();
331
332                 zAxisLabelPositioner.setTicksDirection(new Vector3d(txs, tys, 0.0));
333                 zAxisLabelPositioner.setDistanceRatio(distanceRatio);
334                 zAxisLabelPositioner.setProjectedTicksDirection(rulerDrawingResult.getNormalizedTicksDirection().setZ(0));
335
336                 if (axes.getZAxisGridColor() != -1 || !axes.getZAxisVisible()) {
337                     FloatBuffer vertexData;
338                     if (axes.getZAxisLogFlag()) {
339                         vertexData = getZGridData(rulerDrawingResult.getSubTicksValues(), rulerModel);
340                     } else {
341                         vertexData = getZGridData(values, rulerModel);
342                     }
343                     vertexBuffer.setData(vertexData, 4);
344
345                     Transformation mirror;
346                     try {
347                         mirror = TransformationFactory.getScaleTransformation(
348                                      matrix[2] < 0 ? gridPosition : -gridPosition,
349                                      matrix[6] < 0 ? gridPosition : -gridPosition,
350                                      1
351                                  );
352                     } catch (DegenerateMatrixException ignored) {
353                         // Should never happens as long as gridPosition the value 1 or -1
354                         mirror = TransformationFactory.getIdentity();
355                     }
356
357                     gridAppearance.setLineColor(ColorFactory.createColor(colorMap, axes.getZAxisGridColor()));
358                     drawingTools.getTransformationManager().getModelViewStack().pushRightMultiply(mirror);
359                     DefaultGeometry gridGeometry = new DefaultGeometry();
360                     gridGeometry.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
361                     gridGeometry.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
362                     gridGeometry.setVertices(vertexBuffer);
363                     drawingTools.draw(gridGeometry, gridAppearance);
364                     drawingTools.getTransformationManager().getModelViewStack().pop();
365                 }
366             } else {
367                 /* z-axis not visible: compute the projected ticks direction and distance ratio (see the x-axis case). */
368                 Vector3d zTicksDirection = new Vector3d(txs, tys, 0);
369
370                 zAxisLabelPositioner.setTicksDirection(zTicksDirection);
371                 Vector3d projTicksDir = canvasProjection.projectDirection(zTicksDirection);
372                 zAxisLabelPositioner.setDistanceRatio((double) TICKS_LENGTH / projTicksDir.getNorm());
373                 zAxisLabelPositioner.setProjectedTicksDirection(projTicksDir.getNormalized().setZ(0));
374             }
375         }
376
377         drawingTools.getCanvas().getBuffersManager().dispose(vertexBuffer);
378     }
379
380     private double getNonZeroSignum(double value) {
381         if (value < 0) {
382             return -1;
383         } else {
384             return 1;
385         }
386     }
387
388     private void setRulerBounds(AxisProperty axis, DefaultRulerModel rulerModel, double axisMin, double axisMax) {
389         double min, max;
390         if (axis.getReverse()) {
391             min = axisMin;
392             max = axisMax;
393         } else {
394             min = axisMax;
395             max = axisMin;
396         }
397
398         if (axis.getLogFlag()) {
399             min = Math.pow(10, min);
400             max = Math.pow(10, max);
401         }
402         rulerModel.setValues(min, max);
403     }
404
405     private Vector3d computeXAxisPosition(double[] projectionMatrix, Double[] bounds, AxisProperty.AxisLocation axisLocation) {
406         double y, z;
407         switch (axisLocation) {
408             default:
409             case BOTTOM:
410                 z = -Math.signum(projectionMatrix[9]);  // First : switch Z such that Y was minimal.
411                 y = -Math.signum(projectionMatrix[6]) * z * Math.signum(projectionMatrix[10]);
412                 if (y == 0) {
413                     y = +1;
414                 }
415                 break;
416             case MIDDLE:
417                 z = Math.signum(projectionMatrix[9]);  // First : switch Z such that Y was maximal.
418                 y = 0;
419                 break;
420             case TOP:
421                 z = Math.signum(projectionMatrix[9]);  // First : switch Z such that Y was maximal.
422                 y = -Math.signum(projectionMatrix[6]) * z * Math.signum(projectionMatrix[10]);
423                 if (y == 0) {
424                     y = -1;
425                 }
426                 break;
427             case ORIGIN:
428                 z = Math.signum(projectionMatrix[9]);  // First : switch Z such that Y was maximal.
429                 y = (bounds[3] + bounds[2]) / (bounds[3] - bounds[2]);
430                 if (Math.abs(y) > 1) {
431                     y = Math.signum(y);
432                 }
433                 break;
434         }
435         return new Vector3d(0, y, z);
436     }
437
438     private Vector3d computeYAxisPosition(double[] matrix, Double[] bounds, AxisProperty.AxisLocation axisLocation) {
439         double x, z;
440         switch (axisLocation) {
441             default:
442             case LEFT:
443                 z = -Math.signum(matrix[9]);  // First : switch Z such that Y was minimal.
444                 x = -Math.signum(matrix[2]) * z * Math.signum(matrix[10]);
445                 if (x == 0) {
446                     x = +1;
447                 }
448                 break;
449             case MIDDLE:
450                 z = Math.signum(matrix[9]);  // First : switch Z such that Y was minimal.
451                 x = 0;
452                 break;
453             case RIGHT:
454                 z = Math.signum(matrix[9]);  // First : switch Z such that Y was minimal.
455                 x = -Math.signum(matrix[2]) * z * Math.signum(matrix[10]); // Then switch X such that Z max but not in the middle.
456                 if (x == 0) {
457                     x = -1;
458                 }
459                 break;
460             case ORIGIN:
461                 z = Math.signum(matrix[9]);  // First : switch Z such that Y was minimal.
462                 x = (bounds[1] + bounds[0]) / (bounds[1] - bounds[0]);
463                 if (Math.abs(x) > 1) {
464                     x = Math.signum(x);
465                 }
466                 break;
467         }
468         return new Vector3d(x, 0, z);
469     }
470
471     private String[] toStringArray(double[] values, DecimalFormat format) {
472         AxesRulerSpriteFactory.setScilabStyle(format);
473         String[] r = new String[values.length];
474         for (int i = 0; i < values.length; i++) {
475             r[i] = format.format(values[i]);
476         }
477         return r;
478     }
479
480     private Double[] toDoubleArray(double[] values) {
481         Double[] r = new Double[values.length];
482         for (int i = 0; i < values.length; i++) {
483             r[i] = values[i];
484         }
485         return r;
486     }
487
488     /**
489      * Build X grid data.
490      * @param values X values where grid is drawn.
491      * @param rulerModel used rulerModel to compute grid world position.
492      * @return X grid data.
493      */
494     private FloatBuffer getXGridData(double[] values, RulerModel rulerModel) {
495         FloatBuffer vertexData = FloatBuffer.allocate(values.length * 16);
496         for (double value : values) {
497             float p = (float) rulerModel.getPosition(value).getX();
498             vertexData.put(p);
499             vertexData.put(+1);
500             vertexData.put(+1);
501             vertexData.put(1);
502             vertexData.put(p);
503             vertexData.put(-1);
504             vertexData.put(+1);
505             vertexData.put(1);
506             vertexData.put(p);
507             vertexData.put(+1);
508             vertexData.put(+1);
509             vertexData.put(1);
510             vertexData.put(p);
511             vertexData.put(+1);
512             vertexData.put(-1);
513             vertexData.put(1);
514         }
515         vertexData.rewind();
516         return vertexData;
517     }
518
519     /**
520      * Build Y grid data.
521      * @param values Y values where grid is drawn.
522      * @param rulerModel used rulerModel to compute grid world position.
523      * @return Y grid data.
524      */
525     private FloatBuffer getYGridData(double[] values, RulerModel rulerModel) {
526         FloatBuffer vertexData = FloatBuffer.allocate(values.length * 16);
527         for (double value : values) {
528             float p = (float) rulerModel.getPosition(value).getY();
529             vertexData.put(+1);
530             vertexData.put(p);
531             vertexData.put(+1);
532             vertexData.put(1);
533             vertexData.put(-1);
534             vertexData.put(p);
535             vertexData.put(+1);
536             vertexData.put(1);
537             vertexData.put(+1);
538             vertexData.put(p);
539             vertexData.put(+1);
540             vertexData.put(1);
541             vertexData.put(+1);
542             vertexData.put(p);
543             vertexData.put(-1);
544             vertexData.put(1);
545         }
546         vertexData.rewind();
547         return vertexData;
548     }
549
550     /**
551      * Build Z grid data.
552      * @param values Z values where grid is drawn.
553      * @param rulerModel used rulerModel to compute grid world position.
554      * @return Z grid data.
555      */
556     private FloatBuffer getZGridData(double[] values, RulerModel rulerModel) {
557         FloatBuffer vertexData = FloatBuffer.allocate(values.length * 16);
558         int limit = 0;
559         for (double value : values) {
560             float p = (float) rulerModel.getPosition(value).getZ();
561             vertexData.put(+1);
562             vertexData.put(+1);
563             vertexData.put(p);
564             vertexData.put(1);
565             vertexData.put(-1);
566             vertexData.put(+1);
567             vertexData.put(p);
568             vertexData.put(1);
569             vertexData.put(+1);
570             vertexData.put(+1);
571             vertexData.put(p);
572             vertexData.put(1);
573             vertexData.put(+1);
574             vertexData.put(-1);
575             vertexData.put(p);
576             vertexData.put(1);
577             limit += 16;
578         }
579         vertexData.limit(limit);
580         return vertexData;
581     }
582
583     public void disposeAll() {
584         this.rulerDrawerManager.disposeAll();
585     }
586
587     public void update(String id, int property) {
588         this.rulerDrawerManager.update(id, property);
589     }
590
591     public void dispose(String id) {
592         this.rulerDrawerManager.dispose(id);
593     }
594 }