Adds possibility to color marks in scatter plots
[scilab.git] / scilab / modules / renderer / src / java / org / scilab / modules / renderer / JoGLView / mark / MarkSpriteFactory.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009-2010 - DIGITEO - Pierre Lando
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  */
11
12 package org.scilab.modules.renderer.JoGLView.mark;
13
14 import org.scilab.forge.scirenderer.shapes.appearance.Appearance;
15 import org.scilab.forge.scirenderer.shapes.appearance.Color;
16 import org.scilab.forge.scirenderer.texture.Texture;
17 import org.scilab.forge.scirenderer.texture.TextureDrawer;
18 import org.scilab.forge.scirenderer.texture.TextureDrawingTools;
19 import org.scilab.forge.scirenderer.texture.TextureManager;
20 import org.scilab.modules.graphic_objects.contouredObject.Mark;
21 import org.scilab.modules.graphic_objects.figure.ColorMap;
22 import org.scilab.modules.renderer.JoGLView.util.ColorFactory;
23
24 import java.awt.Dimension;
25
26 /**
27  * @author Pierre Lando
28  */
29 public class MarkSpriteFactory {
30
31     /**
32      * Return a mark sprite corresponding to the given scilab mark.
33      *
34      *
35      * @param spriteManager the current sprite manager.
36      * @param mark the scilab mark.
37      * @param colorMap the scilab color map.
38      * @return a mark sprite corresponding to the given scilab mark.
39      */
40     public static Texture getMarkSprite(TextureManager spriteManager, Mark mark, Integer selectedColor, ColorMap colorMap, Appearance appearance) {
41         int finalSize;
42
43         /**
44          * Compute the sprite pixel size.
45          */
46         if (mark.getMarkSizeUnit() == Mark.MarkSizeUnitType.TABULATED) {
47             // Special case for compatibility with older versions
48             // dot mark with tabulated size of 0 is a single pixel
49             // drawn in pixel size instead of tabulated size
50             if (mark.getStyle() == 0 && mark.getSize() == 0) {
51                 finalSize = 1;
52             } else {
53                 finalSize = (8 + 2 * mark.getSize());
54             }
55         } else {
56             finalSize = mark.getSize();
57         }
58
59         Texture sprite = spriteManager.createTexture();
60         sprite.setDrawer(getSpriteDrawer(mark, selectedColor, finalSize, colorMap, appearance));
61
62         return sprite;
63     }
64
65     /**
66      * Return the sprite drawer corresponding to the given mark.
67      * @param mark the mark to draw.
68      * @param finalSize the final mark size.
69      * @param colorMap the scilab colormap to use.
70      * @return the sprite drawer corresponding to the given mark.
71      */
72     private static TextureDrawer getSpriteDrawer(Mark mark, Integer selectedColor, int finalSize, ColorMap colorMap, Appearance usedAppearance) {
73         final Appearance appearance = new Appearance();
74         Integer markColor = selectedColor == null ? mark.getForeground() : selectedColor;
75         Color backgroundColor;
76         Color foregroundColor;
77
78         if (colorMap != null) {
79             backgroundColor = ColorFactory.createColor(colorMap, mark.getBackground());
80             foregroundColor = ColorFactory.createColor(colorMap, markColor);
81         } else {
82             backgroundColor = new Color(1f, 1f, 1f, 1f);
83             foregroundColor = new Color(0f, 0f, 0f, 1f);
84         }
85
86         if (mark.getBackground() != 0) {
87             appearance.setFillColor(backgroundColor);
88         } else {
89             appearance.setFillColor(new Color(0.0f, 0.0f, 0.0f, 0.0f));
90         }
91         appearance.setLineColor(foregroundColor);
92         if (usedAppearance != null) {
93             appearance.setLineWidth(usedAppearance.getLineWidth());
94         }
95
96         if (finalSize == 0) {
97             // when finalSize is 0 then a dot is drawn so we draw a dot with a PlusSpriteDrawer
98             // which is well exported with size equal to 1 (see bug 13551)
99             finalSize = 1;
100         }
101
102         if (finalSize != 1) {
103             switch (mark.getStyle()) {
104                 case  0:
105                     if (colorMap == null) {
106                         return new DotSpriteDrawer(backgroundColor, finalSize);
107                     } else {
108                         return new DotSpriteDrawer(foregroundColor, finalSize);
109                     }
110                 case  1:
111                     return new PlusSpriteDrawer(appearance, finalSize);
112                 case  2:
113                     return new CrossSpriteDrawer(appearance, finalSize);
114                 case  3:
115                     return new StarSpriteDrawer(appearance, finalSize);
116                 case  4:
117                     if (colorMap == null) {
118                         return new FilledDiamondSpriteDrawer(backgroundColor, finalSize);
119                     } else {
120                         return new FilledDiamondSpriteDrawer(foregroundColor, finalSize);
121                     }
122                 case  5:
123                     return new DiamondSpriteDrawer(appearance, finalSize);
124                 case  6:
125                     return new TriangleUpSpriteDrawer(appearance, finalSize);
126                 case  7:
127                     return new TriangleDownSpriteDrawer(appearance, finalSize);
128                 case  8:
129                     return new DiamondPlusSpriteDrawer(appearance, finalSize);
130                 case  9:
131                     return new CircleSpriteDrawer(appearance, finalSize);
132                 case 10:
133                     return new AsteriskSpriteDrawer(appearance, finalSize);
134                 case 11:
135                     return new SquareSpriteDrawer(appearance, finalSize);
136                 case 12:
137                     return new TriangleRightSpriteDrawer(appearance, finalSize);
138                 case 13:
139                     return new TriangleLeftSpriteDrawer(appearance, finalSize);
140                 case 14:
141                     return new PentagramSpriteDrawer(appearance, finalSize);
142
143                 default:
144                     return new PlusSpriteDrawer(appearance, finalSize);
145             }
146         } else {
147             return new PlusSpriteDrawer(appearance, finalSize);
148         }
149     }
150
151     /**
152      * Abstract class for all scilab mark sprites.
153      */
154     private static abstract class ScilabSpriteDrawer implements TextureDrawer {
155         protected final Appearance appearance;
156         protected final int size;
157
158         public ScilabSpriteDrawer(Appearance appearance, int size) {
159             this.appearance = appearance;
160             this.size = size;
161         }
162
163         @Override
164         public OriginPosition getOriginPosition() {
165             return TextureDrawer.OriginPosition.CENTER;
166         }
167
168         @Override
169         public Dimension getTextureSize() {
170
171             /** Add a margin such that (0, 0) was pixel aligned. */
172             int margin;
173             if (size % 2 == 0) {
174                 margin = 3;
175             } else {
176                 margin = 2;
177             }
178             return new Dimension(size + margin, size + margin);
179         }
180     }
181
182     /**
183      * Dot sprite
184      * Scilab ID = 0
185      */
186     private static class DotSpriteDrawer extends ScilabSpriteDrawer {
187         private final Color color;
188
189         public DotSpriteDrawer(Color color, int size) {
190             super(null, size);
191             this.color = color;
192         }
193
194         @Override
195         public void draw(TextureDrawingTools textureDrawingTools) {
196             textureDrawingTools.fillDisc(0, 0, size, color);
197         }
198     }
199
200     /**
201      * Plus sprite
202      * Scilab ID = 1
203      */
204     private static class PlusSpriteDrawer extends ScilabSpriteDrawer {
205
206         public PlusSpriteDrawer(Appearance appearance, int size) {
207             super(appearance, size);
208         }
209
210         @Override
211         public void draw(TextureDrawingTools textureDrawingTools) {
212             textureDrawingTools.drawPlus(size, appearance);
213         }
214     }
215
216     /**
217      * Cross sprite
218      * Scilab ID = 2
219      */
220     private static class CrossSpriteDrawer extends ScilabSpriteDrawer {
221         private final int[] coordinate1;
222         private final int[] coordinate2;
223
224         public CrossSpriteDrawer(Appearance appearance, int size) {
225             super(appearance, size);
226             int r = (int) (size * Math.sqrt(2.0) / 2.0);
227             coordinate1 = new int[] { -r, -r, r,  r};
228             coordinate2 = new int[] { -r,  r, r, -r};
229         }
230
231         @Override
232         public void draw(TextureDrawingTools textureDrawingTools) {
233             textureDrawingTools.drawPolyline(coordinate1, appearance);
234             textureDrawingTools.drawPolyline(coordinate2, appearance);
235         }
236     }
237
238     /**
239      * Star sprite
240      * Scilab ID = 3
241      */
242     private static class StarSpriteDrawer extends ScilabSpriteDrawer {
243         private final int[] coordinate1;
244         private final int[] coordinate2;
245
246         public StarSpriteDrawer(Appearance appearance, int size) {
247             super(appearance, size);
248             int r = size / 2;
249             coordinate1 = new int[] { -r, 0, r, 0};
250             coordinate2 = new int[] { 0, -r, 0, r};
251         }
252
253         @Override
254         public void draw(TextureDrawingTools textureDrawingTools) {
255             textureDrawingTools.fillDisc(0, 0, size, appearance.getFillColor());
256             textureDrawingTools.drawCircle(0, 0, size, appearance);
257             textureDrawingTools.drawPolyline(coordinate1, appearance);
258             textureDrawingTools.drawPolyline(coordinate2, appearance);
259         }
260     }
261
262     /**
263      * Filled diamond sprite
264      * Scilab ID = 4
265      */
266     private static class FilledDiamondSpriteDrawer extends ScilabSpriteDrawer {
267         private final Appearance appearance;
268         private final int[] coordinates;
269
270         public FilledDiamondSpriteDrawer(Color color, int size) {
271             super(null, size);
272             int r = size / 2;
273
274             appearance = new Appearance();
275             appearance.setFillColor(color);
276             appearance.setLineColor(color);
277
278             coordinates = new int[] { -r, 0, 0, -r, +r, 0, 0, +r};
279         }
280
281         @Override
282         public void draw(TextureDrawingTools textureDrawingTools) {
283             textureDrawingTools.fillPolygon(coordinates, appearance);
284         }
285     }
286
287     /**
288      * Abstract class for all the triangle mark sprites.
289      */
290     private static abstract class TriangleSpriteDrawer extends ScilabSpriteDrawer {
291         protected final int r;
292         protected final int basex;
293         protected final int basey;
294         protected int[] coordinates;
295
296         public TriangleSpriteDrawer(Appearance appearance, int size) {
297             super(appearance, size);
298             double tmpr = (double)(size / 2);
299
300             r = (int) (tmpr);
301
302             basex = (int) (tmpr * 0.5 * Math.sqrt(3));
303             basey = (int) (tmpr * 0.5);
304         }
305
306         @Override
307         public void draw(TextureDrawingTools textureDrawingTools) {
308             textureDrawingTools.fillPolygon(coordinates, appearance);
309         }
310     }
311
312     /**
313      * Diamond sprite
314      * Scilab ID = 5
315      */
316     private static class DiamondSpriteDrawer extends ScilabSpriteDrawer {
317         protected final int[] coordinates;
318
319         public DiamondSpriteDrawer(Appearance appearance, int size) {
320             super(appearance, size);
321             int r = size / 2;
322
323             coordinates = new int[] { -r, 0, 0, -r, r, 0, 0, r};
324         }
325
326         @Override
327         public void draw(TextureDrawingTools textureDrawingTools) {
328             textureDrawingTools.fillPolygon(coordinates, appearance);
329         }
330     }
331
332     /**
333      * Triangle up sprite
334      * Scilab ID = 6
335      */
336     private static class TriangleUpSpriteDrawer extends TriangleSpriteDrawer {
337         public TriangleUpSpriteDrawer(Appearance appearance, int size) {
338             super(appearance, size);
339
340             coordinates = new int[] { -basex, basey, 0, -r, basex, basey};
341         }
342     }
343
344     /**
345      * Triangle down sprite
346      * Scilab ID = 7
347      */
348     private static class TriangleDownSpriteDrawer extends TriangleSpriteDrawer {
349         public TriangleDownSpriteDrawer(Appearance appearance, int size) {
350             super(appearance, size);
351
352             coordinates = new int[] { -basex, -basey, basex, -basey, 0, r};
353         }
354     }
355
356     /**
357      * Diamond plus sprite
358      * Scilab ID = 8
359      */
360     private static class DiamondPlusSpriteDrawer extends DiamondSpriteDrawer {
361         private final int[] coordinate1;
362         private final int[] coordinate2;
363
364         public DiamondPlusSpriteDrawer(Appearance appearance, int size) {
365             super(appearance, size);
366             coordinate1 = new int[] {coordinates[0], coordinates[1], coordinates[4], coordinates[5]};
367             coordinate2 = new int[] {coordinates[2], coordinates[3], coordinates[6], coordinates[7]};
368         }
369
370         @Override
371         public void draw(TextureDrawingTools textureDrawingTools) {
372             super.draw(textureDrawingTools);
373             textureDrawingTools.drawPolyline(coordinate1, appearance);
374             textureDrawingTools.drawPolyline(coordinate2, appearance);
375         }
376     }
377
378     /**
379      * Circle sprite
380      * Scilab ID = 9
381      */
382     private static class CircleSpriteDrawer extends ScilabSpriteDrawer {
383
384         public CircleSpriteDrawer(Appearance appearance, int size) {
385             super(appearance, size);
386         }
387
388         @Override
389         public void draw(TextureDrawingTools textureDrawingTools) {
390             textureDrawingTools.fillDisc(0, 0, size, appearance.getFillColor());
391             textureDrawingTools.drawCircle(0, 0, size, appearance);
392         }
393     }
394
395     /**
396      * Asterisk sprite
397      * Scilab ID = 10
398      */
399     private static class AsteriskSpriteDrawer extends ScilabSpriteDrawer {
400         private final int[] coordinate1;
401         private final int[] coordinate2;
402         private final int[] coordinate3;
403         private final int[] coordinate4;
404
405         public AsteriskSpriteDrawer(Appearance appearance, int size) {
406             super(appearance, size);
407             int r = size / 2;
408             coordinate1 = new int[] { -r, 0, r, 0};
409             coordinate2 = new int[] { 0, -r, 0, r};
410             r = (int) (r * Math.sqrt(2.0) / 2.0);
411             coordinate3 = new int[] { -r, -r, r, r};
412             coordinate4 = new int[] { -r, r, +r, -r};
413         }
414
415         @Override
416         public void draw(TextureDrawingTools textureDrawingTools) {
417             textureDrawingTools.drawPolyline(coordinate1, appearance);
418             textureDrawingTools.drawPolyline(coordinate2, appearance);
419             textureDrawingTools.drawPolyline(coordinate3, appearance);
420             textureDrawingTools.drawPolyline(coordinate4, appearance);
421         }
422     }
423
424     /**
425      * Square sprite
426      * Scilab ID = 11
427      */
428     private static class SquareSpriteDrawer extends ScilabSpriteDrawer {
429         private final int[] coordinate;
430
431         public SquareSpriteDrawer(Appearance appearance, int size) {
432             super(appearance, size);
433             int r = size / 2;
434             coordinate = new int[] { -r, -r, +r, -r, +r, +r, -r, +r};
435         }
436
437         @Override
438         public void draw(TextureDrawingTools textureDrawingTools) {
439             textureDrawingTools.fillPolygon(coordinate, appearance);
440         }
441     }
442
443     /**
444      * Triangle right sprite
445      * Scilab ID = 12
446      */
447     private static class TriangleRightSpriteDrawer extends TriangleSpriteDrawer {
448         public TriangleRightSpriteDrawer(Appearance appearance, int size) {
449             super(appearance, size);
450
451             coordinates = new int[] { -basey, basex, -basey, -basex, r, 0};
452         }
453     }
454
455     /**
456      * Triangle left sprite
457      * Scilab ID = 13
458      */
459     private static class TriangleLeftSpriteDrawer extends TriangleSpriteDrawer {
460         public TriangleLeftSpriteDrawer(Appearance appearance, int size) {
461             super(appearance, size);
462
463             coordinates = new int[] {basey, basex, -r, 0, basey, -basex};
464         }
465     }
466
467     /**
468      * Pentagram sprite (five-pointed star)
469      * Scilab ID = 14
470      */
471     private static class PentagramSpriteDrawer extends ScilabSpriteDrawer {
472         private final int[] coordinates;
473
474         private static final double COS_PI_OVER_10 = Math.cos(Math.PI / 10.0);
475         private static final double SIN_PI_OVER_10 = Math.sin(Math.PI / 10.0);
476         private static final double COS_3_PI_OVER_10 = Math.cos(3.0 * Math.PI / 10.0);
477         private static final double SIN_3_PI_OVER_10 = Math.sin(3.0 * Math.PI / 10.0);
478
479         public PentagramSpriteDrawer(Appearance appearance, int size) {
480             super(appearance, size);
481
482             int r = size / 2;
483
484             double tmpy = SIN_PI_OVER_10 * (double)r;
485
486             int x = (int)(COS_PI_OVER_10 * (double)r);
487             int y = (int)(SIN_PI_OVER_10 * (double)r);
488
489             int x2 = (int)(COS_3_PI_OVER_10 * (double)r);
490             int y2 = (int)(SIN_3_PI_OVER_10 * (double)r);
491
492             double tmpinnr = tmpy / SIN_3_PI_OVER_10;
493
494
495             int xinn = (int)(tmpinnr * COS_3_PI_OVER_10);
496             int yinn = y;
497
498             int xinn2 = (int)(tmpinnr * COS_PI_OVER_10);
499             int yinn2 = (int)(tmpinnr * SIN_PI_OVER_10);
500
501             int innr = (int)tmpinnr;
502
503             coordinates = new int[] { -x2, y2, -xinn2, yinn2, -x, -y, -xinn, -yinn, 0, -r, xinn, -yinn, x, -y, xinn2, yinn2, x2, y2, 0, innr};
504         }
505
506         @Override
507         public void draw(TextureDrawingTools textureDrawingTools) {
508             textureDrawingTools.fillPolygon(coordinates, appearance);
509         }
510     }
511 }