1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - Scilab Enterprises - Calixte Denizet
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  */
14 
15 package org.scilab.forge.scirenderer.implementation.g2d.motor;
16 
17 import java.awt.Color;
18 import java.awt.Graphics2D;
19 import java.awt.Shape;
20 import java.awt.Stroke;
21 import java.awt.geom.Path2D;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.List;
25 
26 import org.scilab.forge.scirenderer.tranformations.Vector3d;
27 import org.scilab.forge.scirenderer.tranformations.Vector4d;
28 
29 /**
30  * Segment object (for info, when modify rendering check for PolyLine too).
31  *
32  * @author Calixte DENIZET
33  */
34 public class Segment extends ConvexObject implements Comparable<Segment> {
35 
36     private int hash = -1;
37     protected G2DStroke stroke;
38     protected List<ConvexObject> segmentOn;
39     protected boolean is2D;
40     protected double[] clip = new double[] {Double.NaN, Double.NaN, Double.NaN, Double.NaN};
41 
Segment(Vector3d[] vertices, Color[] colors, G2DStroke stroke, boolean is2D)42     public Segment(Vector3d[] vertices, Color[] colors, G2DStroke stroke, boolean is2D) throws InvalidPolygonException {
43         super(vertices, colors);
44         if (vertices.length != 2) {
45             throw new InvalidPolygonException("Invalid segment: must have 2 vertices.");
46         }
47         this.stroke = stroke;
48         this.is2D = is2D;
49     }
50 
Segment(Vector3d[] vertices, Color[] colors)51     public Segment(Vector3d[] vertices, Color[] colors) throws InvalidPolygonException {
52         this(vertices, colors, null, false);
53     }
54 
setStroke(G2DStroke stroke)55     public void setStroke(G2DStroke stroke) {
56         this.stroke = stroke;
57     }
58 
getLength()59     public double getLength() {
60         return vertices[0].minus(vertices[1]).getNorm();
61     }
62 
getLength(Vector3d[] vertices)63     public static double getLength(Vector3d[] vertices) {
64         return vertices[0].minus(vertices[1]).getNorm();
65     }
66 
addConvexObject(ConvexObject co)67     public void addConvexObject(ConvexObject co) {
68         if (segmentOn == null) {
69             segmentOn = new ArrayList<ConvexObject>(2);
70         }
71         segmentOn.add(co);
72     }
73 
removeConvexObject(ConvexObject co)74     public void removeConvexObject(ConvexObject co) {
75         if (segmentOn != null) {
76             segmentOn.remove(co);
77         }
78     }
79 
replaceSegment(List<Segment> segs)80     public void replaceSegment(List<Segment> segs) {
81         if (segmentOn != null) {
82             for (ConvexObject co : segmentOn) {
83                 Triangle t = (Triangle) co;
84                 t.replaceSegment(this, segs);
85             }
86         }
87     }
88 
isIn2D()89     public boolean isIn2D() {
90         return isNull(vertices[0].getZ()) && isNull(vertices[1].getZ());
91     }
92 
isInFront()93     public boolean isInFront() {
94         return isEqual(vertices[0].getZ(), -0.5) && isEqual(vertices[1].getZ(), -0.5);
95     }
96 
97     @Override
compareTo(Segment o)98     public int compareTo(Segment o) {
99         if (equals(o)) {
100             return 0;
101         }
102 
103         return getPrecedence() - o.getPrecedence();
104     }
105 
106     @Override
equals(Object o)107     public boolean equals(Object o) {
108         if (o instanceof Segment) {
109             Segment s = (Segment) o;
110             return (s.vertices[0].equals(vertices[0]) && s.vertices[1].equals(vertices[1]) && s.getColor(0).equals(getColor(0)) && s.getColor(1).equals(getColor(1))) || (s.vertices[1].equals(vertices[0]) && s.vertices[0].equals(vertices[1]) && s.getColor(1).equals(getColor(0)) && s.getColor(0).equals(getColor(1)));
111         }
112 
113         return false;
114     }
115 
116     @Override
isBehind(ConvexObject o)117     public int isBehind(ConvexObject o) {
118         if (o instanceof Triangle && ((Triangle) o).isSegmentAcross(this)) {
119             return 1;
120         }
121 
122         return super.isBehind(o);
123     }
124 
125     @Override
breakObject(ConvexObject o)126     public List<ConvexObject> breakObject(ConvexObject o) {
127         if (o instanceof Triangle) {
128             return ((Triangle) o).breakObject(this);
129         } else if (o instanceof SpritedRectangle) {
130             return ((SpritedRectangle) o).breakObject(this);
131         }
132 
133         return null;
134     }
135 
136     @Override
breakObject(Vector4d v)137     public List<ConvexObject> breakObject(Vector4d v) {
138         double[] vv = v.getData();
139 
140         if (is2D && vv[2] == 0) {
141             ConvexObject.makeClip(clip, vv);
142         }
143         getNormal();
144         Vector3d np = new Vector3d(vv);
145         boolean a = isBehind(vertices[0], np, vv[3]);
146         boolean b = isBehind(vertices[1], np, vv[3]);
147 
148         if (a && b) {
149             List<ConvexObject> list = new ArrayList<ConvexObject>(1);
150             list.add(this);
151             return list;
152         }
153 
154         if (!a && !b) {
155             return null;
156         }
157 
158         double c = (vv[3] + vertices[1].scalar(np)) / v0.scalar(np);
159         Vector3d p = Vector3d.getBarycenter(vertices[0], vertices[1], c, 1 - c);
160         Color color = getColorsBarycenter(getColor(0), getColor(1), c, 1 - c);
161         Segment s;
162 
163         try {
164             if (a) {
165                 s = new Segment(new Vector3d[] {vertices[0], p}, new Color[] {getColor(0), color}, this.stroke, this.is2D);
166             } else {
167                 s = new Segment(new Vector3d[] {p, vertices[1]}, new Color[] {color, getColor(1)}, this.stroke, this.is2D);
168             }
169 
170             List<ConvexObject> list = new ArrayList<ConvexObject>(1);
171             list.add(s);
172 
173             return list;
174         } catch (InvalidPolygonException e) { }
175 
176         return null;
177     }
178 
breakObject(Vector3d p, Vector3d u, Vector3d n)179     public List<Segment> breakObject(Vector3d p, Vector3d u, Vector3d n) {
180         getNormal();
181         double c = vertices[1].minus(p).scalar(n) / v0.scalar(n);
182         if (c > 0 && !isNull(c) && c < 1 && !isEqual(c, 1)) {
183             List<Segment> list = new ArrayList<Segment>(2);
184             Vector3d q = Vector3d.getBarycenter(vertices[0], vertices[1], c, 1 - c);
185             Color color = getColorsBarycenter(getColor(0), getColor(1), c, 1 - c);
186             try {
187                 list.add(new Segment(new Vector3d[] {vertices[0], q}, new Color[] {getColor(0), color}, stroke, this.is2D));
188                 list.add(new Segment(new Vector3d[] {q, vertices[1]}, new Color[] {color, getColor(1)}, stroke, this.is2D));
189 
190                 return list;
191             } catch (InvalidPolygonException e) { }
192         } else {
193             List<Segment> list = new ArrayList<Segment>(1);
194             try {
195                 list.add(new Segment(new Vector3d[] {vertices[0], vertices[1]}, new Color[] {getColor(0), getColor(1)}, stroke, this.is2D));
196 
197                 return list;
198             } catch (InvalidPolygonException e) { }
199         }
200 
201         return null;
202     }
203 
204     @Override
draw(Graphics2D g2d)205     public void draw(Graphics2D g2d) {
206         if (segmentOn == null || segmentOn.isEmpty()) {
207             Path2D polyline = getProjectedPolyLine();
208             g2d.setColor(getColor(0));
209             Stroke oldStroke = g2d.getStroke();
210             if (oldStroke != stroke) {
211                 g2d.setStroke(stroke);
212             }
213 
214             Shape oldClip = g2d.getClip();
215             Shape newClip = ConvexObject.getClip(clip);
216             if (newClip != null) {
217                 g2d.clip(newClip);
218             }
219 
220             g2d.draw(polyline);
221 
222             if (oldStroke != stroke) {
223                 g2d.setStroke(oldStroke);
224             }
225 
226             if (newClip != null) {
227                 g2d.setClip(oldClip);
228             }
229 
230             drawAreas(g2d);
231         }
232     }
233 
234     @Override
hashCode()235     public int hashCode() {
236         if (hash == -1) {
237             if (colors != null) {
238                 hash = Arrays.hashCode(vertices) + 19 * Arrays.hashCode(colors);
239             } else {
240                 hash = Arrays.hashCode(vertices) + 19 * getColor(0).hashCode();
241             }
242         }
243         return hash;
244     }
245 
246     @Override
toString()247     public String toString() {
248         return "Segment " + vertices[0].toString() + " " + vertices[1].toString() + " Precedence: " + getPrecedence();
249     }
250 }
251