2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2010 - DIGITEO - Pierre Lando
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-en.txt
12 package org.scilab.modules.renderer.JoGLView;
14 import org.scilab.forge.scirenderer.Canvas;
15 import org.scilab.forge.scirenderer.Drawer;
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.implementation.jogl.JoGLCanvas;
20 import org.scilab.forge.scirenderer.shapes.appearance.Appearance;
21 import org.scilab.forge.scirenderer.shapes.geometry.DefaultGeometry;
22 import org.scilab.forge.scirenderer.shapes.geometry.Geometry;
23 import org.scilab.forge.scirenderer.texture.AnchorPosition;
24 import org.scilab.forge.scirenderer.texture.AbstractTextureDataProvider;
25 import org.scilab.forge.scirenderer.texture.Texture;
26 import org.scilab.forge.scirenderer.tranformations.Transformation;
27 import org.scilab.forge.scirenderer.tranformations.TransformationFactory;
28 import org.scilab.forge.scirenderer.tranformations.TransformationStack;
29 import org.scilab.forge.scirenderer.utils.shapes.geometry.CubeFactory;
30 import org.scilab.modules.graphic_objects.ObjectRemovedException;
31 import org.scilab.modules.graphic_objects.arc.Arc;
32 import org.scilab.modules.graphic_objects.axes.Axes;
33 import org.scilab.modules.graphic_objects.axes.Camera.ViewType;
34 import org.scilab.modules.graphic_objects.axis.Axis;
35 import org.scilab.modules.graphic_objects.compound.Compound;
36 import org.scilab.modules.graphic_objects.fec.Fec;
37 import org.scilab.modules.graphic_objects.figure.ColorMap;
38 import org.scilab.modules.graphic_objects.figure.Figure;
39 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
40 import org.scilab.modules.graphic_objects.graphicObject.GraphicObject;
41 import org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties;
42 import org.scilab.modules.graphic_objects.graphicObject.Visitor;
43 import org.scilab.modules.graphic_objects.graphicView.GraphicView;
44 import org.scilab.modules.graphic_objects.imageplot.Grayplot;
45 import org.scilab.modules.graphic_objects.imageplot.Matplot;
46 import org.scilab.modules.graphic_objects.label.Label;
47 import org.scilab.modules.graphic_objects.legend.Legend;
48 import org.scilab.modules.graphic_objects.polyline.Polyline;
49 import org.scilab.modules.graphic_objects.rectangle.Rectangle;
50 import org.scilab.modules.graphic_objects.surface.Fac3d;
51 import org.scilab.modules.graphic_objects.surface.Plot3d;
52 import org.scilab.modules.graphic_objects.textObject.Text;
53 import org.scilab.modules.graphic_objects.vectfield.Arrow;
54 import org.scilab.modules.graphic_objects.vectfield.Champ;
55 import org.scilab.modules.graphic_objects.vectfield.Segs;
56 import org.scilab.modules.renderer.JoGLView.arrowDrawing.ArrowDrawer;
57 import org.scilab.modules.renderer.JoGLView.axes.AxesDrawer;
58 import org.scilab.modules.renderer.JoGLView.contouredObject.ContouredObjectDrawer;
59 import org.scilab.modules.renderer.JoGLView.interaction.InteractionManager;
60 import org.scilab.modules.renderer.JoGLView.label.LabelManager;
61 import org.scilab.modules.renderer.JoGLView.legend.LegendDrawer;
62 import org.scilab.modules.renderer.JoGLView.mark.MarkSpriteManager;
63 import org.scilab.modules.renderer.JoGLView.postRendering.PostRendered;
64 import org.scilab.modules.renderer.JoGLView.text.TextManager;
65 import org.scilab.modules.renderer.JoGLView.util.ColorFactory;
66 import org.scilab.modules.renderer.JoGLView.util.OutOfMemoryException;
67 import org.scilab.modules.renderer.utils.textRendering.FontManager;
69 import java.awt.Component;
70 import java.awt.Dimension;
71 import java.nio.ByteBuffer;
72 import java.util.Arrays;
73 import java.util.HashMap;
74 import java.util.HashSet;
75 import java.util.LinkedList;
76 import java.util.List;
80 import javax.swing.SwingUtilities;
83 * @author Pierre Lando
85 public class DrawerVisitor implements Visitor, Drawer, GraphicView {
87 /** Set of properties changed during a draw if auto-ticks is on for X axis. */
88 private static final Set<Integer> X_AXIS_TICKS_PROPERTIES = new HashSet<Integer>(Arrays.asList(
89 GraphicObjectProperties.__GO_X_AXIS_TICKS_LOCATIONS__,
90 GraphicObjectProperties.__GO_X_AXIS_TICKS_LABELS__,
91 GraphicObjectProperties.__GO_X_AXIS_SUBTICKS__
94 /** Set of properties changed during a draw if auto-ticks is on for Y axis. */
95 private static final Set<Integer> Y_AXIS_TICKS_PROPERTIES = new HashSet<Integer>(Arrays.asList(
96 GraphicObjectProperties.__GO_Y_AXIS_TICKS_LOCATIONS__,
97 GraphicObjectProperties.__GO_Y_AXIS_TICKS_LABELS__,
98 GraphicObjectProperties.__GO_Y_AXIS_SUBTICKS__
101 /** Set of properties changed during a draw if auto-ticks is on for Z axis. */
102 private static final Set<Integer> Z_AXIS_TICKS_PROPERTIES = new HashSet<Integer>(Arrays.asList(
103 GraphicObjectProperties.__GO_Z_AXIS_TICKS_LOCATIONS__,
104 GraphicObjectProperties.__GO_Z_AXIS_TICKS_LABELS__,
105 GraphicObjectProperties.__GO_Z_AXIS_SUBTICKS__
108 /** Set of figure properties for witch a change doesn't lead to a redraw */
109 private static final Set<Integer> SILENT_FIGURE_PROPERTIES = new HashSet<Integer>(Arrays.asList(
110 GraphicObjectProperties.__GO_ROTATION_TYPE__,
111 GraphicObjectProperties.__GO_INFO_MESSAGE__,
112 GraphicObjectProperties.__GO_FIGURE_NAME__,
113 GraphicObjectProperties.__GO_AUTORESIZE__,
114 GraphicObjectProperties.__GO_POSITION__,
115 GraphicObjectProperties.__GO_SIZE__,
116 GraphicObjectProperties.__GO_ID__
119 private static final boolean DEBUG_MODE = false;
121 private final Component component;
122 private final Canvas canvas;
123 private final Figure figure;
124 private final InteractionManager interactionManager;
126 private final ColorMapTextureDataProvider colorMapTextureDataProvider;
128 private final ScilabTextureManager textureManager;
129 private final MarkSpriteManager markManager;
130 private final LabelManager labelManager;
131 private final DataManager dataManager;
132 private final TextManager textManager;
134 private final ContouredObjectDrawer contouredObjectDrawer;
135 private final LegendDrawer legendDrawer;
136 private final AxesDrawer axesDrawer;
137 private final AxisDrawer axisDrawer;
138 private final ArrowDrawer arrowDrawer;
139 private final FecDrawer fecDrawer;
141 private DrawingTools drawingTools;
142 private Texture colorMapTexture;
143 private ColorMap colorMap;
145 private Axes currentAxes;
148 * The map between the existing Figures' identifiers and their corresponding Visitor.
149 * Used to get access to the DrawerVisitor corresponding to a given Figure when the
150 * renderer module is accessed from another thread than the AWT's.
152 private final static Map<String, DrawerVisitor> visitorMap = new HashMap<String, DrawerVisitor>();
153 private final List<PostRendered> postRenderedList = new LinkedList<PostRendered>();
155 public DrawerVisitor(Component component, Canvas canvas, Figure figure) {
156 GraphicController.getController().register(this);
158 this.component = component;
159 this.canvas = canvas;
160 this.figure = figure;
162 this.interactionManager = new InteractionManager(this);
163 this.dataManager = new DataManager(canvas);
164 this.textureManager = new ScilabTextureManager(this);
165 this.markManager = new MarkSpriteManager(canvas.getTextureManager());
166 this.textManager = new TextManager(canvas.getTextureManager());
167 this.labelManager = new LabelManager(canvas.getTextureManager());
168 this.axesDrawer = new AxesDrawer(this);
169 this.axisDrawer = new AxisDrawer(this);
170 this.arrowDrawer = new ArrowDrawer(this);
171 this.contouredObjectDrawer = new ContouredObjectDrawer(this, this.dataManager, this.markManager);
172 this.legendDrawer = new LegendDrawer(this);
173 this.fecDrawer = new FecDrawer(this);
174 this.colorMapTextureDataProvider = new ColorMapTextureDataProvider();
177 * Forces font loading from the main thread. This is done because
178 * if getSciFontManager (thus, font loading) is concurrently accessed from
179 * 2 different threads (the AWT's and the main one), freezing may occur.
181 FontManager.getSciFontManager();
183 visitorMap.put(figure.getIdentifier(), this);
186 public static void changeVisitor(Figure figure, DrawerVisitor visitor) {
187 if (visitor == null) {
188 visitorMap.remove(figure.getIdentifier());
190 visitorMap.put(figure.getIdentifier(), visitor);
194 public void setDrawingTools(DrawingTools drawingTools) {
195 this.drawingTools = drawingTools;
198 public DrawingTools getDrawingTools() {
202 public Canvas getCanvas() {
207 * @return the DataManager
209 public DataManager getDataManager() {
214 * @return the TextManager
216 public TextManager getTextManager() {
221 * Mark manager getter.
222 * @return the mark manager.
224 public MarkSpriteManager getMarkManager() {
229 * @return the AxesDrawer
231 public AxesDrawer getAxesDrawer() {
236 * @return the ArrowDrawer
238 public ArrowDrawer getArrowDrawer() {
242 public ColorMap getColorMap() {
248 * Returns the visitor corresponding to the Figure identifier.
249 * @param figureId the figure identifier.
250 * @return the visitor.
252 public static DrawerVisitor getVisitor(String figureId) {
253 return visitorMap.get(figureId);
256 public void addPostRendering(PostRendered postRendered) {
257 if (postRendered != null) {
258 postRenderedList.add(postRendered);
262 public void removePostRendering(PostRendered postRendered) {
263 postRenderedList.remove(postRendered);
267 public void draw(DrawingTools drawingTools) {
268 this.drawingTools = drawingTools;
271 for (PostRendered postRendered : postRenderedList) {
273 postRendered.draw(drawingTools);
274 } catch (SciRendererException e) {
275 System.err.println("A 'PostRendered' is not drawable because: '" + e.getMessage() + "'");
278 drawingTools.getTransformationManager().useSceneCoordinate();
282 * Ask the given object to accept visitor.
283 * @param childrenId array of object identifier.
285 public void askAcceptVisitor(String[] childrenId) {
286 if (childrenId != null) {
288 for (int i = childrenId.length - 1; i >= 0; --i) {
289 GraphicObject child = GraphicController.getController().getObjectFromId(childrenId[i]);
293 } catch (ObjectRemovedException e) {
295 System.err.println("[DEBUG] Try to draw an already removed object");
296 System.err.println("[DEBUG] " + e);
297 System.err.println("[DEBUG] Skipped...");
306 * @return true if it is a 2D view
308 public boolean is2DView() {
309 return currentAxes.getViewAsEnum() == ViewType.VIEW_2D;
313 public void visit(Axes axes) {
314 synchronized (axes) {
315 if (axes.isValid() && axes.getVisible()) {
318 axesDrawer.draw(axes);
319 } catch (SciRendererException e) {
327 public void visit(Arc arc) {
328 if (arc.isValid() && arc.getVisible()) {
329 axesDrawer.enableClipping(currentAxes, arc.getClipProperty());
331 contouredObjectDrawer.draw(arc, currentAxes.getViewAsEnum() == ViewType.VIEW_2D);
332 } catch (OutOfMemoryException e) {
334 } catch (SciRendererException e) {
336 } catch (ObjectRemovedException e) {
339 axesDrawer.disableClipping(arc.getClipProperty());
344 public void visit(Axis axis) {
345 if (axis.getVisible()) {
346 axesDrawer.enableClipping(currentAxes, axis.getClipProperty());
347 axisDrawer.draw(axis);
348 axesDrawer.disableClipping(axis.getClipProperty());
353 public void visit(Compound compound) {
354 if (compound.getVisible()) {
355 askAcceptVisitor(compound.getChildren());
360 public void visit(Fec fec) throws ObjectRemovedException {
361 if (fec.isValid() && fec.getVisible()) {
362 axesDrawer.enableClipping(currentAxes, fec.getClipProperty());
365 } catch (OutOfMemoryException e) {
368 axesDrawer.disableClipping(fec.getClipProperty());
373 public void visit(Figure figure) {
374 synchronized (figure) {
375 /** Set the current {@see ColorMap}. */
376 colorMap = figure.getColorMap();
377 drawingTools.clear(ColorFactory.createColor(colorMap, figure.getBackground()));
378 drawingTools.clearDepthBuffer();
379 if (figure.getVisible() && figure.getImmediateDrawing()) {
380 askAcceptVisitor(figure.getChildren());
386 public void visit(final Grayplot grayplot) {
387 if (grayplot.isValid() && grayplot.getVisible()) {
388 axesDrawer.enableClipping(currentAxes, grayplot.getClipProperty());
390 DefaultGeometry triangles = new DefaultGeometry();
391 triangles.setFillDrawingMode(Geometry.FillDrawingMode.TRIANGLES);
392 triangles.setVertices(dataManager.getVertexBuffer(grayplot.getIdentifier()));
393 triangles.setColors(dataManager.getColorBuffer(grayplot.getIdentifier()));
394 triangles.setIndices(dataManager.getIndexBuffer(grayplot.getIdentifier()));
395 triangles.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
396 Appearance trianglesAppearance = new Appearance();
397 drawingTools.draw(triangles, trianglesAppearance);
398 } catch (ObjectRemovedException e) {
399 invalidate(grayplot, e);
400 } catch (SciRendererException e) {
401 invalidate(grayplot, e);
402 } catch (OutOfMemoryException e) {
403 invalidate(grayplot, e);
405 axesDrawer.disableClipping(grayplot.getClipProperty());
410 public void visit(final Matplot matplot) {
411 if (matplot.isValid() && matplot.getVisible()) {
412 axesDrawer.enableClipping(currentAxes, matplot.getClipProperty());
414 if ((currentAxes != null) && (currentAxes.getXAxisLogFlag() || currentAxes.getYAxisLogFlag())) {
415 DefaultGeometry geometry = new DefaultGeometry();
416 geometry.setFillDrawingMode(Geometry.FillDrawingMode.TRIANGLES);
417 geometry.setVertices(dataManager.getVertexBuffer(matplot.getIdentifier()));
418 geometry.setColors(dataManager.getColorBuffer(matplot.getIdentifier()));
419 geometry.setIndices(dataManager.getIndexBuffer(matplot.getIdentifier()));
420 geometry.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
421 Appearance appearance = new Appearance();
422 drawingTools.draw(geometry, appearance);
424 TransformationStack modelViewStack = drawingTools.getTransformationManager().getModelViewStack();
425 Double[] scale = matplot.getScale();
426 Double[] translate = matplot.getTranslate();
427 Transformation t = TransformationFactory.getTranslateTransformation(translate[0], translate[1], 0);
428 Transformation t2 = TransformationFactory.getScaleTransformation(scale[0], scale[1], 1);
429 modelViewStack.pushRightMultiply(t);
430 modelViewStack.pushRightMultiply(t2);
431 drawingTools.draw(textureManager.getTexture(matplot.getIdentifier()));
432 modelViewStack.pop();
433 modelViewStack.pop();
435 } catch (ObjectRemovedException e) {
436 invalidate(matplot, e);
437 } catch (SciRendererException e) {
438 invalidate(matplot, e);
439 } catch (OutOfMemoryException e) {
440 invalidate(matplot, e);
442 axesDrawer.disableClipping(matplot.getClipProperty());
447 public void visit(Label label) {
448 if (label.isValid() && label.getVisible()) {
450 labelManager.draw(drawingTools, colorMap, label, axesDrawer);
451 } catch (SciRendererException e) {
452 invalidate(label, e);
458 public void visit(Legend legend) {
459 if (legend.isValid() && legend.getVisible()) {
461 legendDrawer.draw(legend);
462 } catch (SciRendererException e) {
463 invalidate(legend, e);
469 public void visit(final Polyline polyline) {
470 synchronized (polyline) {
471 if (polyline.isValid() && polyline.getVisible()) {
472 axesDrawer.enableClipping(currentAxes, polyline.getClipProperty());
474 DefaultGeometry geometry = new DefaultGeometry();
476 geometry.setVertices(dataManager.getVertexBuffer(polyline.getIdentifier()));
477 geometry.setIndices(dataManager.getIndexBuffer(polyline.getIdentifier()));
478 geometry.setWireIndices(dataManager.getWireIndexBuffer(polyline.getIdentifier()));
480 final int style = polyline.getPolylineStyle();
481 if (style == 1 || style == 2 || style == 4 || style == 5) {
482 geometry.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS_STRIP);
484 geometry.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
487 geometry.setFillDrawingMode(Geometry.FillDrawingMode.TRIANGLES);
488 geometry.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
490 geometry.setPolygonOffsetMode(currentAxes.getCamera().getView() == ViewType.VIEW_3D);
492 /* Interpolated color rendering is used only for basic polylines for now. */
493 Appearance appearance = new Appearance();
495 if (polyline.getInterpColorMode() && style == 1) {
496 geometry.setTextureCoordinates(dataManager.getTextureCoordinatesBuffer(polyline.getIdentifier()));
497 appearance.setTexture(getColorMapTexture());
499 geometry.setColors(null);
502 appearance.setLineColor(ColorFactory.createColor(colorMap, polyline.getLineColor()));
503 appearance.setLineWidth(polyline.getLineThickness().floatValue());
504 appearance.setLinePattern(polyline.getLineStyleAsEnum().asPattern());
506 if (!polyline.getInterpColorMode() || style != 1) {
510 * The line color is used as fill color for the filled patch polyline style
511 * whereas the background color is used for all the other styles.
514 fillColor = polyline.getLineColor();
516 fillColor = polyline.getBackground();
519 appearance.setFillColor(ColorFactory.createColor(colorMap, fillColor));
522 drawingTools.draw(geometry, appearance);
525 arrowDrawer.drawArrows(polyline.getParentAxes(), polyline.getIdentifier(), polyline.getArrowSizeFactor(),
526 polyline.getLineThickness(), false, false, polyline.getLineColor(), true);
529 if (polyline.getMarkMode()) {
530 Texture sprite = markManager.getMarkSprite(polyline, colorMap);
531 ElementsBuffer positions = dataManager.getVertexBuffer(polyline.getIdentifier());
532 drawingTools.draw(sprite, AnchorPosition.CENTER, positions);
534 } catch (ObjectRemovedException e) {
535 invalidate(polyline, e);
536 } catch (OutOfMemoryException e) {
537 invalidate(polyline, e);
538 } catch (SciRendererException e) {
539 invalidate(polyline, e);
541 axesDrawer.disableClipping(polyline.getClipProperty());
547 public void visit(Rectangle rectangle) {
548 if (rectangle.isValid() && rectangle.getVisible()) {
549 axesDrawer.enableClipping(currentAxes, rectangle.getClipProperty());
551 contouredObjectDrawer.draw(rectangle, currentAxes.getCamera().getView() == ViewType.VIEW_2D);
552 } catch (ObjectRemovedException e) {
553 invalidate(rectangle, e);
554 } catch (OutOfMemoryException e) {
555 invalidate(rectangle, e);
556 } catch (SciRendererException e) {
557 invalidate(rectangle, e);
559 axesDrawer.disableClipping(rectangle.getClipProperty());
565 * -use common code for both the Fac3d and Plot3d visit methods
566 * as they are mostly similar.
569 public void visit(final Fac3d fac3d) {
570 if (fac3d.isValid() && fac3d.getVisible()) {
571 axesDrawer.enableClipping(currentAxes, fac3d.getClipProperty());
573 if (fac3d.getSurfaceMode()) {
574 DefaultGeometry geometry = new DefaultGeometry();
575 geometry.setVertices(dataManager.getVertexBuffer(fac3d.getIdentifier()));
576 geometry.setIndices(dataManager.getIndexBuffer(fac3d.getIdentifier()));
578 geometry.setPolygonOffsetMode(true);
580 /* Front-facing triangles */
581 Appearance appearance = new Appearance();
583 if (fac3d.getColorMode() != 0) {
584 geometry.setFillDrawingMode(Geometry.FillDrawingMode.TRIANGLES);
585 /* Back-facing triangles */
586 if (fac3d.getHiddenColor() > 0) {
587 geometry.setFaceCullingMode(axesDrawer.getBackFaceCullingMode());
588 Appearance backTrianglesAppearance = new Appearance();
589 backTrianglesAppearance.setFillColor(ColorFactory.createColor(colorMap, fac3d.getHiddenColor()));
590 drawingTools.draw(geometry, backTrianglesAppearance);
592 // Now we will draw front face.
593 geometry.setFaceCullingMode(axesDrawer.getFrontFaceCullingMode());
595 geometry.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
598 if (fac3d.getColorFlag() == 0) {
599 appearance.setFillColor(ColorFactory.createColor(colorMap, Math.abs(fac3d.getColorMode())));
600 } else if (fac3d.getColorFlag() > 0) {
601 geometry.setTextureCoordinates(dataManager.getTextureCoordinatesBuffer(fac3d.getIdentifier()));
602 appearance.setTexture(getColorMapTexture());
604 geometry.setColors(null);
607 geometry.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
610 if ((fac3d.getColorMode() >= 0) && (fac3d.getLineThickness() > 0.0)) {
611 geometry.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
612 geometry.setWireIndices(dataManager.getWireIndexBuffer(fac3d.getIdentifier()));
614 appearance.setLineColor(ColorFactory.createColor(colorMap, fac3d.getLineColor()));
615 appearance.setLineWidth(fac3d.getLineThickness().floatValue());
618 drawingTools.draw(geometry, appearance);
621 if (fac3d.getMarkMode()) {
622 Texture texture = markManager.getMarkSprite(fac3d, colorMap);
623 ElementsBuffer positions = dataManager.getVertexBuffer(fac3d.getIdentifier());
624 drawingTools.draw(texture, AnchorPosition.CENTER, positions);
626 } catch (ObjectRemovedException e) {
627 invalidate(fac3d, e);
628 } catch (OutOfMemoryException e) {
629 invalidate(fac3d, e);
630 } catch (SciRendererException e) {
631 invalidate(fac3d, e);
633 axesDrawer.disableClipping(fac3d.getClipProperty());
639 public void visit(final Plot3d plot3d) {
640 if (plot3d.isValid() && plot3d.getVisible()) {
641 axesDrawer.enableClipping(currentAxes, plot3d.getClipProperty());
643 if (plot3d.getSurfaceMode()) {
644 DefaultGeometry geometry = new DefaultGeometry();
645 if (plot3d.getColorMode() != 0) {
646 geometry.setFillDrawingMode(Geometry.FillDrawingMode.TRIANGLES);
648 geometry.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
651 geometry.setPolygonOffsetMode(true);
653 geometry.setVertices(dataManager.getVertexBuffer(plot3d.getIdentifier()));
654 geometry.setIndices(dataManager.getIndexBuffer(plot3d.getIdentifier()));
655 /* Back-facing triangles */
656 if (plot3d.getHiddenColor() > 0) {
657 geometry.setFaceCullingMode(axesDrawer.getBackFaceCullingMode());
658 Appearance backTrianglesAppearance = new Appearance();
659 backTrianglesAppearance.setFillColor(ColorFactory.createColor(colorMap, plot3d.getHiddenColor()));
660 drawingTools.draw(geometry, backTrianglesAppearance);
663 /* Front-facing triangles */
664 Appearance appearance = new Appearance();
667 if (plot3d.getColorFlag() == 1) {
668 geometry.setColors(dataManager.getColorBuffer(plot3d.getIdentifier()));
670 geometry.setColors(null);
673 if (plot3d.getHiddenColor() > 0) {
674 geometry.setFaceCullingMode(axesDrawer.getFrontFaceCullingMode());
676 geometry.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
679 if (plot3d.getColorFlag() == 0) {
680 appearance.setFillColor(ColorFactory.createColor(colorMap, Math.abs(plot3d.getColorMode())));
683 if ((plot3d.getColorMode() >= 0) && (plot3d.getLineThickness() > 0.0)) {
684 geometry.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
685 geometry.setWireIndices(dataManager.getWireIndexBuffer(plot3d.getIdentifier()));
687 appearance.setLinePattern(plot3d.getLineStyleAsEnum().asPattern());
688 appearance.setLineColor(ColorFactory.createColor(colorMap, plot3d.getLineColor()));
689 appearance.setLineWidth(plot3d.getLineThickness().floatValue());
692 drawingTools.draw(geometry, appearance);
695 if (plot3d.getMarkMode()) {
696 Texture texture = markManager.getMarkSprite(plot3d, colorMap);
697 ElementsBuffer positions = dataManager.getVertexBuffer(plot3d.getIdentifier());
698 drawingTools.draw(texture, AnchorPosition.CENTER, positions);
700 } catch (ObjectRemovedException e) {
701 invalidate(plot3d, e);
702 } catch (OutOfMemoryException e) {
703 invalidate(plot3d, e);
704 } catch (SciRendererException e) {
705 invalidate(plot3d, e);
707 axesDrawer.disableClipping(plot3d.getClipProperty());
713 public void visit(Text text) {
714 if (text.isValid() && text.getVisible()) {
715 axesDrawer.enableClipping(currentAxes, text.getClipProperty());
717 textManager.draw(drawingTools, colorMap, text);
718 } catch (SciRendererException e) {
721 axesDrawer.disableClipping(text.getClipProperty());
726 public void visit(Arrow arrow) {
728 System.out.println("How can I draw an arrow ?");
732 public void visit(final Champ champ) {
733 if (champ.isValid() && champ.getVisible()) {
734 axesDrawer.enableClipping(currentAxes, champ.getClipProperty());
736 DefaultGeometry segments = new DefaultGeometry();
737 segments.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
738 segments.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
739 segments.setVertices(dataManager.getVertexBuffer(champ.getIdentifier()));
740 segments.setWireIndices(dataManager.getWireIndexBuffer(champ.getIdentifier()));
741 segments.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
742 if (champ.getColored()) {
743 segments.setColors(dataManager.getColorBuffer(champ.getIdentifier()));
745 segments.setColors(null);
748 if (champ.getLineMode()) {
749 Appearance segmentAppearance = new Appearance();
751 /* If not colored, all segments have the same color. */
752 if (champ.getColored()) {
753 segmentAppearance.setLineColor(null);
755 segmentAppearance.setLineColor(ColorFactory.createColor(colorMap, champ.getLineColor()));
758 segmentAppearance.setLineWidth(champ.getLineThickness().floatValue());
759 segmentAppearance.setLinePattern(champ.getLineStyleAsEnum().asPattern());
760 drawingTools.draw(segments, segmentAppearance);
763 /* Draw the arrows */
764 if (champ.getArrowSize() != 0.0) {
765 arrowDrawer.drawArrows(champ.getParentAxes(), champ.getIdentifier(), champ.getArrowSize(), champ.getLineThickness(), false,
766 champ.getColored(), champ.getLineColor(), false);
768 } catch (OutOfMemoryException e) {
769 invalidate(champ, e);
770 } catch (ObjectRemovedException e) {
771 invalidate(champ, e);
772 } catch (SciRendererException e) {
773 invalidate(champ, e);
775 axesDrawer.disableClipping(champ.getClipProperty());
780 public void visit(final Segs segs) {
781 if (segs.isValid() && segs.getVisible() && segs.getArrows().size() != 0) {
782 axesDrawer.enableClipping(currentAxes, segs.getClipProperty());
784 DefaultGeometry segments = new DefaultGeometry();
785 segments.setFillDrawingMode(Geometry.FillDrawingMode.NONE);
786 segments.setLineDrawingMode(Geometry.LineDrawingMode.SEGMENTS);
787 segments.setVertices(dataManager.getVertexBuffer(segs.getIdentifier()));
788 segments.setColors(dataManager.getColorBuffer(segs.getIdentifier()));
789 segments.setWireIndices(dataManager.getWireIndexBuffer(segs.getIdentifier()));
790 segments.setFaceCullingMode(Geometry.FaceCullingMode.BOTH);
792 if (segs.getLineMode()) {
793 Appearance segmentAppearance = new Appearance();
794 segmentAppearance.setLineColor(null);
795 segmentAppearance.setLineWidth(segs.getLineThickness().floatValue());
796 segmentAppearance.setLinePattern(segs.getLineStyleAsEnum().asPattern());
797 drawingTools.draw(segments, segmentAppearance);
801 * Segs does not derive from ContouredObject but Arrow does, hence we have to get the former's first Arrow
802 * in order to obtain the latter's Mark (all arrows are supposed to have the same contour properties for now).
804 if (segs.getMarkMode()) {
805 Texture texture = markManager.getMarkSprite(segs.getIdentifier(), segs.getArrows().get(0).getMark(), colorMap);
806 ElementsBuffer positions = dataManager.getVertexBuffer(segs.getIdentifier());
807 drawingTools.draw(texture, AnchorPosition.CENTER, positions);
810 /* Draw the arrows */
811 if (segs.getArrowSize() != 0.0) {
812 arrowDrawer.drawArrows(segs.getParentAxes(), segs.getIdentifier(), segs.getArrowSize(), segs.getLineThickness(), true,
813 true, segs.getLineColor(), false);
815 } catch (OutOfMemoryException e) {
817 } catch (ObjectRemovedException e) {
819 } catch (SciRendererException e) {
822 axesDrawer.disableClipping(segs.getClipProperty());
827 public void updateObject(String id, int property) {
829 if (needUpdate(id, property)) {
830 GraphicController.getController().setProperty(id, GraphicObjectProperties.__GO_VALID__, true);
831 if (GraphicObjectProperties.__GO_COLORMAP__ == property && figure.getIdentifier().equals(id)) {
832 labelManager.disposeAll();
833 dataManager.disposeAllColorBuffers();
834 dataManager.disposeAllTextureCoordinatesBuffers();
835 markManager.disposeAll();
836 textManager.disposeAll();
837 axesDrawer.disposeAll();
838 fecDrawer.updateAll();
839 colorMapTextureDataProvider.update();
840 textureManager.disposeAll();
842 labelManager.update(id, property);
843 dataManager.update(id, property);
844 markManager.update(id, property);
845 textManager.update(id, property);
846 axesDrawer.update(id, property);
847 legendDrawer.update(id, property);
848 fecDrawer.update(id, property);
851 if (GraphicObjectProperties.__GO_ANTIALIASING__ == property) {
852 canvas.setAntiAliasingLevel(figure.getAntialiasing());
855 if (isImmediateDrawing(id)) {
856 if (GraphicObjectProperties.__GO_IMMEDIATE_DRAWING__ == property) {
857 canvas.redrawAndWait();
864 if (GraphicObjectProperties.__GO_IMMEDIATE_DRAWING__ == property && !isImmediateDrawing(id)) {
868 } catch (OutOfMemoryException e) {
869 invalidate(GraphicController.getController().getObjectFromId(id), e);
870 } catch (ObjectRemovedException e) {
871 // Object has been removed before draw : do nothing.
876 * Check if the given changed property make the figure out of date.
877 * @param id the object updated
878 * @param property the changed property.
879 * @return true id the given changed property make the figure out of date.
881 private boolean needUpdate(String id, int property) {
882 GraphicObject object = GraphicController.getController().getObjectFromId(id);
883 int objectType = (Integer) GraphicController.getController().getProperty(id, GraphicObjectProperties.__GO_TYPE__);
884 if ((object != null) && isFigureChild(id)
885 && objectType != GraphicObjectProperties.__GO_UICONTROL__
886 && objectType !=GraphicObjectProperties.__GO_UIMENU__) {
888 if (GraphicObjectProperties.__GO_VALID__ == property) {
892 if (object instanceof Axes) {
893 Axes axes = (Axes) object;
894 if (axes.getXAxisAutoTicks() && X_AXIS_TICKS_PROPERTIES.contains(property)) {
898 if (axes.getYAxisAutoTicks() && Y_AXIS_TICKS_PROPERTIES.contains(property)) {
902 if (axes.getZAxisAutoTicks() && Z_AXIS_TICKS_PROPERTIES.contains(property)) {
907 if (object instanceof Figure) {
908 if (SILENT_FIGURE_PROPERTIES.contains(property)) {
919 private boolean isImmediateDrawing(String id) {
920 String parentId = (String) GraphicController.getController().getProperty(id, GraphicObjectProperties.__GO_PARENT_FIGURE__);
921 if (parentId == null) {
924 Boolean b = (Boolean) GraphicController.getController().getProperty(parentId, GraphicObjectProperties.__GO_IMMEDIATE_DRAWING__);
925 return (b == null) ? false : b;
930 public void createObject(String id) {
934 public void deleteObject(String id) {
935 dataManager.dispose(id);
936 markManager.dispose(id);
937 textManager.dispose(id);
938 labelManager.dispose(id);
939 axesDrawer.dispose(id);
940 legendDrawer.dispose(id);
941 fecDrawer.dispose(id);
942 textureManager.dispose(id);
944 GraphicObject object = GraphicController.getController().getObjectFromId(id);
945 if (object instanceof Figure && visitorMap.containsKey(id)) {
946 visitorMap.remove(id);
947 GraphicController.getController().unregister(this);
948 if (SwingUtilities.isEventDispatchThread()) {
952 SwingUtilities.invokeAndWait(new Runnable() {
957 } catch (Exception e) { }
960 if (isImmediateDrawing(id)) {
967 * Check if the given id correspond to a child of the current {@see Figure}.
968 * @param id the given id.
969 * @return true if the given id correspond to a child of the current {@see Figure}.
971 private boolean isFigureChild(String id) {
972 String parentFigureID = (String) GraphicController.getController().getProperty(id, GraphicObjectProperties.__GO_PARENT_FIGURE__);
973 return figure.getIdentifier().equals(parentFigureID);
977 * Invalidate the given graphic object and inform the user.
978 * @param graphicObject the graphic object to invalidate
979 * @param exception the cause of invalidation.
981 public void invalidate(GraphicObject graphicObject, Exception exception) {
983 System.err.println("The " + graphicObject.getType() + " \"" + graphicObject.getIdentifier()
984 + "\" has been invalidated: " + exception.getMessage());
985 exception.printStackTrace();
987 GraphicController.getController().setProperty(graphicObject.getIdentifier(), GraphicObjectProperties.__GO_VALID__, false);
990 public LabelManager getLabelManager() {
994 public Texture getColorMapTexture() {
995 if (colorMapTexture == null) {
996 colorMapTexture = canvas.getTextureManager().createTexture();
997 colorMapTexture.setMagnificationFilter(Texture.Filter.NEAREST);
998 colorMapTexture.setMinifyingFilter(Texture.Filter.NEAREST);
999 colorMapTexture.setSWrappingMode(Texture.Wrap.CLAMP);
1000 colorMapTexture.setTWrappingMode(Texture.Wrap.CLAMP);
1001 colorMapTexture.setDataProvider(colorMapTextureDataProvider);
1003 return colorMapTexture;
1008 * @return the figure this visitor draw.
1010 public Figure getFigure() {
1014 private Geometry cube;
1015 public Geometry getCube() {
1017 cube = CubeFactory.createCube(canvas);
1024 * @return return the attached component.
1026 public Component getComponent() {
1031 * Interaction manager getter
1032 * @return the interaction manager.
1034 public InteractionManager getInteractionManager() {
1035 return interactionManager;
1038 private class ColorMapTextureDataProvider extends AbstractTextureDataProvider {
1039 byte[] whiteColor = {(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
1040 byte[] blackColor = {0x00, 0x00, 0x00, (byte) 0xFF};
1043 public Dimension getTextureSize() {
1044 return new Dimension(colorMap.getSize() + 2, 1);
1048 public ByteBuffer getData() {
1049 Double[] data = colorMap.getData();
1050 ByteBuffer buffer = ByteBuffer.allocate(4 * ((data.length / 3) + 2));
1052 /* White and black are written in the first and second positions */
1053 buffer.put(whiteColor);
1054 buffer.put(blackColor);
1056 for (int i = 0 ; i < data.length / 3 ; i++) {
1057 buffer.put(toByte(data[i]));
1058 buffer.put(toByte(data[i + colorMap.getSize()].floatValue()));
1059 buffer.put(toByte(data[i + 2 * colorMap.getSize()].floatValue()));
1060 buffer.put(toByte(1));
1067 public ByteBuffer getSubData(int x, int y, int width, int height) {
1069 * For the moment, we presuppose that x and y are 0 and that
1070 * width is equal to the colormap's total size (with height == 1).
1071 * To be correctly implemented.
1077 public boolean isValid() {
1081 public void update() {