Revert "Bug 12212 fixed: Export a polyline in 2D broke it into several segments"
[scilab.git] / scilab / modules / scirenderer / src / org / scilab / forge / scirenderer / implementation / g2d / motor / Scene.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - Scilab Enterprises - Calixte Denizet
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.forge.scirenderer.implementation.g2d.motor;
13
14 import java.awt.Graphics2D;
15 import java.util.ArrayList;
16 import java.util.Comparator;
17 import java.util.HashSet;
18 import java.util.List;
19 import java.util.Set;
20 import java.util.Stack;
21 import java.util.TreeSet;
22
23 import org.scilab.forge.scirenderer.clipping.ClippingPlane;
24
25 final class Scene {
26
27     private static Set<Scene> faces2d = new TreeSet<Scene>(new Comparator<Scene>() {
28         public int compare(Scene o1, Scene o2) {
29             if (o1.object.vertices[0].getZ() == o2.object.vertices[0].getZ()) {
30                 return o1.object.getPrecedence() - o2.object.getPrecedence();
31             }
32
33             return (int) Math.signum(o2.object.vertices[0].getZ() - o1.object.vertices[0].getZ());
34         }
35
36         public boolean equals(Object obj) {
37             return this == obj;
38         }
39     });
40
41     private static List<Scene> faces = new ArrayList<Scene>();
42     private static List<Scene> disabledFaces = new ArrayList<Scene>();
43     private static List<ClippingPlane> clippingPlanes;
44     private static Stack<Scene> stack = new Stack<Scene>();;
45
46     private List<Scene> behind;
47     private List<Scene> onfront;
48     private ConvexObject object;
49     private boolean drawn;
50
51     private Scene(final ConvexObject object) {
52         this.object = object;
53     }
54
55     public static final void setClippingPlanes(final List<ClippingPlane> clippingPlanes) {
56         Scene.clippingPlanes = clippingPlanes;
57     }
58
59     private static final List<ConvexObject> breakOnClippingPlane(ConvexObject o) {
60         List<ConvexObject> list = new ArrayList<ConvexObject>();
61         List<ConvexObject> tmp = new ArrayList<ConvexObject>();
62         list.add(o);
63         if (clippingPlanes != null) {
64             for (ClippingPlane clip : clippingPlanes) {
65                 if (clip.isEnable()) {
66                     tmp.clear();
67                     for (ConvexObject co : list) {
68                         List<ConvexObject> l = co.breakObject(clip.getEquation());
69                         if (l != null) {
70                             tmp.addAll(l);
71                         }
72                     }
73                     list.clear();
74                     list.addAll(tmp);
75                     if (list.isEmpty()) {
76                         break;
77                     }
78                 }
79             }
80         }
81         return list;
82     }
83
84     static final void addToRoot(final boolean is2D, final ConvexObject co) {
85         List<ConvexObject> broken = breakOnClippingPlane(co);
86         for (ConvexObject object : broken) {
87             add(is2D, object);
88         }
89     }
90
91     private static final void add(final boolean is2D, final ConvexObject object) {
92         synchronized (faces) {
93             Scene st = new Scene(object);
94             if (is2D) {
95                 faces2d.add(st);
96             } else {
97                 Set<Scene> toRemove = new HashSet<Scene>();
98                 List<ConvexObject> toAdd = null;
99
100                 for (Scene face : faces) {
101                     if (face.object instanceof Triangle && object instanceof Segment) {
102                         if (((Triangle) face.object).addSegment((Segment) object)) {
103                             if (st != null) {
104                                 toRemove.add(st);
105                                 st = null;
106                             }
107                         }
108                     } else if (object instanceof Triangle && face.object instanceof Segment) {
109                         if (((Triangle) object).addSegment((Segment) face.object)) {
110                             toRemove.add(face);
111                         }
112                     }
113
114                     if (st != null) {
115                         int r = face.object.isBehind(st.object);
116
117                         if (r == 1) {
118                             // object is behind face.object
119                             addBehind(face, st);
120                             addOnFront(st, face);
121                         } else if (r == -1) {
122                             // face.object is behind object
123                             addBehind(st, face);
124                             addOnFront(face, st);
125                         } else if (r == 2) {
126                             // collision
127                             toAdd = face.object.breakObject(st.object);
128                             if (toAdd != null && !toAdd.isEmpty()) {
129                                 toRemove.add(face);
130                                 toRemove.add(st);
131                                 st = null;
132                                 break;
133                             }
134                         }
135                     }
136                 }
137
138                 if (st != null) {
139                     faces.add(st);
140                 }
141
142                 for (Scene s : toRemove) {
143                     faces.remove(s);
144                     if (s.onfront != null) {
145                         for (Scene ss : s.onfront) {
146                             ss.behind.remove(s);
147                         }
148                     }
149                 }
150                 if (toAdd != null) {
151                     for (ConvexObject co : toAdd) {
152                         add(is2D, co);
153                     }
154                 }
155             }
156         }
157     }
158
159
160     static final void clearDepth() {
161         disabledFaces.addAll(faces);
162         disabledFaces.addAll(faces2d);
163         faces.clear();
164         faces2d.clear();
165     }
166
167     static final void drawRoot(final Graphics2D g2d) {
168         synchronized (faces) {
169             for (Scene face : disabledFaces) {
170                 face.draw(g2d);
171             }
172
173             for (Scene face : disabledFaces) {
174                 face.drawn = false;
175             }
176
177             for (Scene face : faces) {
178                 face.draw(g2d);
179             }
180
181             for (Scene face : faces2d) {
182                 face.draw(g2d);
183             }
184
185             // code to help debug
186             /*for (Scene face : faces) {
187               face.drawn = false;
188               }
189
190               for (Scene face : faces) {
191               if (face.object.marked) {
192               face.object.draw(g2d);
193               }
194               }*/
195         }
196     }
197
198     static final void clear() {
199         disabledFaces.clear();
200         faces.clear();
201         faces2d.clear();
202         stack.clear();
203     }
204
205     static final void clearAll() {
206         clear();
207         clippingPlanes.clear();
208     }
209
210     private final void draw(final Graphics2D g2d) {
211         if (stack.contains(this)) {
212             this.object.addArea(stack.peek().object);
213             return;
214         }
215         if (!drawn) {
216             stack.push(this);
217             drawn = true;
218             if (behind != null && !behind.isEmpty()) {
219                 for (Scene face : behind) {
220                     face.draw(g2d);
221                 }
222             }
223             object.draw(g2d);
224             stack.pop();
225         }
226     }
227
228     private static final void addBehind(Scene face, Scene s) {
229         if (face.behind == null) {
230             face.behind = new ArrayList<Scene>();
231         }
232         face.behind.add(s);
233     }
234
235     private static final void addOnFront(Scene face, Scene s) {
236         if (face.onfront == null) {
237             face.onfront = new ArrayList<Scene>();
238         }
239         face.onfront.add(s);
240     }
241 }