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 / Segment.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.Color;
15 import java.awt.Graphics2D;
16 import java.awt.Stroke;
17 import java.awt.geom.Path2D;
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.List;
21 import java.util.HashSet;
22 import java.util.Set;
23
24 import org.scilab.forge.scirenderer.tranformations.Vector3d;
25 import org.scilab.forge.scirenderer.tranformations.Vector4d;
26
27 /**
28  * Segment object (for info, when modify rendering check for PolyLine too).
29  *
30  * @author Calixte DENIZET
31  */
32 public class Segment extends ConvexObject implements Comparable<Segment> {
33
34     private Integer hash;
35     protected G2DStroke stroke;
36     protected List<ConvexObject> segmentOn;
37
38     public Segment(Vector3d[] vertices, Color[] colors, G2DStroke stroke) throws InvalidPolygonException {
39         super(vertices, colors);
40         if (vertices.length != 2) {
41             throw new InvalidPolygonException("Invalid segment: must have 2 vertices.");
42         }
43         this.stroke = stroke;
44     }
45
46     public Segment(Vector3d[] vertices, Color[] colors) throws InvalidPolygonException {
47         this(vertices, colors, null);
48     }
49
50     public void setStroke(G2DStroke stroke) {
51         this.stroke = stroke;
52     }
53
54     public double getLength() {
55         return vertices[0].minus(vertices[1]).getNorm();
56     }
57
58     public static double getLength(Vector3d[] vertices) {
59         return vertices[0].minus(vertices[1]).getNorm();
60     }
61
62     public void addConvexObject(ConvexObject co) {
63         if (segmentOn == null) {
64             segmentOn = new ArrayList<ConvexObject>(2);
65         }
66         segmentOn.add(co);
67     }
68
69     public void removeConvexObject(ConvexObject co) {
70         if (segmentOn != null) {
71             segmentOn.remove(co);
72         }
73     }
74
75     public void replaceSegment(List<Segment> segs) {
76         if (segmentOn != null) {
77             for (ConvexObject co : segmentOn) {
78                 Triangle t = (Triangle) co;
79                 t.replaceSegment(this, segs);
80             }
81         }
82     }
83
84     public boolean isIn2D() {
85         return isNull(vertices[0].getZ()) && isNull(vertices[1].getZ());
86     }
87
88     public boolean isInFront() {
89         return isEqual(vertices[0].getZ(), -0.5) && isEqual(vertices[1].getZ(), -0.5);
90     }
91
92     @Override
93     public int compareTo(Segment o) {
94         if (equals(o)) {
95             return 0;
96         }
97
98         return getPrecedence() - o.getPrecedence();
99     }
100
101     @Override
102     public boolean equals(Object o) {
103         if (o instanceof Segment) {
104             Segment s = (Segment) o;
105             return (s.vertices[0].equals(vertices[0]) && s.vertices[1].equals(vertices[1]) && s.colors[0].equals(colors[0]) && s.colors[1].equals(colors[1])) || (s.vertices[1].equals(vertices[0]) && s.vertices[0].equals(vertices[1]) && s.colors[1].equals(colors[0]) && s.colors[0].equals(colors[1]));
106         }
107
108         return false;
109     }
110
111     @Override
112     public int isBehind(ConvexObject o) {
113         if (o instanceof Triangle && ((Triangle) o).isSegmentAcross(this)) {
114             return 1;
115         }
116
117         return super.isBehind(o);
118     }
119
120     @Override
121     public List<ConvexObject> breakObject(ConvexObject o) {
122         if (o instanceof Triangle) {
123             return ((Triangle) o).breakObject(this);
124         } else if (o instanceof SpritedRectangle) {
125             return ((SpritedRectangle) o).breakObject(this);
126         }
127
128         return null;
129     }
130
131     @Override
132     public List<ConvexObject> breakObject(Vector4d v) {
133         double[] vv = v.getData();
134         Vector3d np = new Vector3d(vv);
135         boolean a = isBehind(vertices[0], np, vv[3]);
136         boolean b = isBehind(vertices[1], np, vv[3]);
137
138         if (a && b) {
139             List<ConvexObject> list = new ArrayList<ConvexObject>(1);
140             list.add(this);
141             return list;
142         }
143
144         if (!a && !b) {
145             return null;
146         }
147
148         double c = (vv[3] + vertices[1].scalar(np)) / v0.scalar(np);
149         Vector3d p = Vector3d.getBarycenter(vertices[0], vertices[1], c, 1 - c);
150         Color color = getColorsBarycenter(colors[0], colors[1], c, 1 - c);
151         Segment s;
152
153         try {
154             if (a) {
155                 s = new Segment(new Vector3d[] {vertices[0], p}, new Color[] {colors[0], color}, this.stroke);
156             } else {
157                 s = new Segment(new Vector3d[] {p, vertices[1]}, new Color[] {color, colors[1]}, this.stroke);
158             }
159
160             List<ConvexObject> list = new ArrayList<ConvexObject>(1);
161             list.add(s);
162
163             return list;
164         } catch (InvalidPolygonException e) { }
165
166         return null;
167     }
168
169     public List<Segment> breakObject(Vector3d p, Vector3d u, Vector3d n) {
170         double c = vertices[1].minus(p).scalar(n) / v0.scalar(n);
171         if (c > 0 && !isNull(c) && c < 1 && !isEqual(c, 1)) {
172             List<Segment> list = new ArrayList<Segment>(2);
173             Vector3d q = Vector3d.getBarycenter(vertices[0], vertices[1], c, 1 - c);
174             Color color = getColorsBarycenter(colors[0], colors[1], c, 1 - c);
175             try {
176                 list.add(new Segment(new Vector3d[] {vertices[0], q}, new Color[] {colors[0], color}, stroke));
177                 list.add(new Segment(new Vector3d[] {q, vertices[1]}, new Color[] {color, colors[1]}, stroke));
178
179                 return list;
180             } catch (InvalidPolygonException e) { }
181         } else {
182             List<Segment> list = new ArrayList<Segment>(1);
183             try {
184                 list.add(new Segment(new Vector3d[] {vertices[0], vertices[1]}, new Color[] {colors[0], colors[1]}, stroke));
185
186                 return list;
187             } catch (InvalidPolygonException e) { }
188         }
189
190         return null;
191     }
192
193     @Override
194     public void draw(Graphics2D g2d) {
195         if (segmentOn == null || segmentOn.isEmpty()) {
196             Path2D polyline = getProjectedPolyLine();
197             g2d.setColor(colors[0]);
198             Stroke oldStroke = g2d.getStroke();
199             if (oldStroke != stroke) {
200                 g2d.setStroke(stroke);
201             }
202
203             g2d.draw(polyline);
204
205             if (oldStroke != stroke) {
206                 g2d.setStroke(oldStroke);
207             }
208
209             drawAreas(g2d);
210         }
211     }
212
213     @Override
214     public int hashCode() {
215         if (hash == null) {
216             hash = Arrays.hashCode(vertices) + 19 * Arrays.hashCode(colors);
217         }
218         return hash;
219     }
220
221     @Override
222     public String toString() {
223         return "Segment " + vertices[0].toString() + " " + vertices[1].toString() + " Precedence: " + getPrecedence();
224     }
225 }