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