Bug 13150 fixed: Vectorial export used too much memory for grayplot 31/13631/2
Calixte DENIZET [Fri, 31 Jan 2014 16:21:49 +0000 (17:21 +0100)]
Change-Id: I9fc010bfca402eb8906eebb60519930ac2f82f23

14 files changed:
scilab/CHANGES_5.5.X
scilab/modules/graphic_export/tests/nonreg_tests/bug_13150.dia.ref [new file with mode: 0644]
scilab/modules/graphic_export/tests/nonreg_tests/bug_13150.tst [new file with mode: 0644]
scilab/modules/scirenderer/src/org/scilab/forge/scirenderer/implementation/g2d/motor/AbstractDrawable3DObject.java
scilab/modules/scirenderer/src/org/scilab/forge/scirenderer/implementation/g2d/motor/BoundingBox.java
scilab/modules/scirenderer/src/org/scilab/forge/scirenderer/implementation/g2d/motor/ConvexObject.java
scilab/modules/scirenderer/src/org/scilab/forge/scirenderer/implementation/g2d/motor/DrawTools.java
scilab/modules/scirenderer/src/org/scilab/forge/scirenderer/implementation/g2d/motor/Motor3D.java
scilab/modules/scirenderer/src/org/scilab/forge/scirenderer/implementation/g2d/motor/PolyLine.java
scilab/modules/scirenderer/src/org/scilab/forge/scirenderer/implementation/g2d/motor/Scene.java
scilab/modules/scirenderer/src/org/scilab/forge/scirenderer/implementation/g2d/motor/Segment.java
scilab/modules/scirenderer/src/org/scilab/forge/scirenderer/implementation/g2d/motor/Triangle.java
scilab/modules/scirenderer/src/org/scilab/forge/scirenderer/implementation/g2d/texture/G2DTextureDrawingTools.java
scilab/modules/scirenderer/src/org/scilab/forge/scirenderer/tranformations/Vector3d.java

index 8806656..49e88a1 100644 (file)
@@ -439,6 +439,8 @@ Scilab Bug Fixes
 
 * Bug #13146 fixed - profile failed when a comment was on the same line as a function declaration.
 
+* Bug #13150 fixed - Vectorial export used too much memory for grayplot.
+
 * Bug #13152 fixed - Typo fixed in syslin french help page.
 
 * Bug #13174 fixed - Scilab crashed after XML element removal.
diff --git a/scilab/modules/graphic_export/tests/nonreg_tests/bug_13150.dia.ref b/scilab/modules/graphic_export/tests/nonreg_tests/bug_13150.dia.ref
new file mode 100644 (file)
index 0000000..baa7b3b
--- /dev/null
@@ -0,0 +1,22 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2014 - Scilab Enterprises - Calixte DENIZET
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- Non-regression test for bug 13150 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/13150
+//
+// <-- Short Description -->
+// Vectorial export used too much memory for grayplot
+driver("png")
+ ans  =
+ Rec   
+xinit(TMPDIR+"/plop.png")
+m = rand(500,500);
+grayplot(1:500, 1:500, m);
+xend();
diff --git a/scilab/modules/graphic_export/tests/nonreg_tests/bug_13150.tst b/scilab/modules/graphic_export/tests/nonreg_tests/bug_13150.tst
new file mode 100644 (file)
index 0000000..4e030e0
--- /dev/null
@@ -0,0 +1,21 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2014 - Scilab Enterprises - Calixte DENIZET
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- Non-regression test for bug 13150 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/13150
+//
+// <-- Short Description -->
+// Vectorial export used too much memory for grayplot
+
+
+driver("png")
+xinit(TMPDIR+"/plop.png")
+m = rand(500,500);
+grayplot(1:500, 1:500, m);
+xend();
\ No newline at end of file
index a503c07..47117fe 100644 (file)
@@ -31,21 +31,16 @@ public abstract class AbstractDrawable3DObject {
     private static int defaultPrecedence = 0;
 
     protected final Vector3d[] vertices;
-
     protected final Color[] colors;
+    protected final Color color;
+
     protected int precedence;
-    protected Boolean is2d;
-    protected Double zindex;
     protected Vector3d v0;
     protected Vector3d v1;
     protected Vector3d v0v1;
     protected double nv0v1;
     protected Vector3d normal;
     protected BoundingBox bbox;
-    protected boolean marked;
-    protected boolean marked2;
-    protected Boolean degenerated;
-    protected double[] clip = new double[] {Double.NaN, Double.NaN, Double.NaN, Double.NaN};
 
     /**
      * Default constructor
@@ -56,7 +51,13 @@ public abstract class AbstractDrawable3DObject {
             throw new InvalidPolygonException("Invalid 3D Object: no vertices was given");
         }
         this.vertices = vertices;
-        this.colors = colors;
+        if (colors != null && AbstractDrawable3DObject.isMonochromatic(colors)) {
+            this.color = colors[0];
+            this.colors = null;
+        } else {
+            this.colors = colors;
+            this.color = null;
+        }
         if (isDegenerate()) {
             throw new InvalidPolygonException("Invalid 3D Object: two vertices are the same");
         }
@@ -64,47 +65,18 @@ public abstract class AbstractDrawable3DObject {
             throw new InvalidPolygonException("Invalid 3D Object: contains NaN or Inf coordinates");
         }
         setPrecedence(defaultPrecedence++);
-        getNormal();
     }
 
-    /**
-     * Create a clip rect for 2D view according to clipping planes passed as arguments
-     * @param v the clipping plane equation
-     */
-    void makeClip(double[] v) {
-        if (v[1] == 0) {
-            double x = -v[3] / v[0];
-            if (Double.isNaN(clip[0])) {
-                clip[0] = x;
-            } else if (clip[0] > x) {
-                clip[1] = clip[0];
-                clip[0] = x;
-            } else {
-                clip[1] = x;
-            }
-        } else {
-            double y = -v[3] / v[1];
-            if (Double.isNaN(clip[2])) {
-                clip[2] = y;
-            } else if (clip[2] > y) {
-                clip[3] = clip[2];
-                clip[2] = y;
-            } else {
-                clip[3] = y;
-            }
+    final Color getColor(final int i) {
+        if (colors != null) {
+            return colors[i];
         }
-    }
 
-    /**
-     * Get the clipping shape (for 2D view)
-     * @return the clipping shape
-     */
-    Shape getClip() {
-        if (!Double.isNaN(clip[0]) && !Double.isNaN(clip[1]) && !Double.isNaN(clip[2]) && !Double.isNaN(clip[3])) {
-            return new Rectangle2D.Double(clip[0], clip[2], clip[1] - clip[0], clip[3] - clip[2]);
-        }
+        return color;
+    }
 
-        return null;
+    final boolean isMonochromatic() {
+        return color != null;
     }
 
     /**
@@ -168,24 +140,6 @@ public abstract class AbstractDrawable3DObject {
     }
 
     /**
-     * Determinates if this object is 2D in looking at the z coordinates
-     * (when all the drawn objects are 2D, we can avoid the projection)
-     */
-    public boolean is2D() {
-        if (is2d == null) {
-            for (Vector3d v : vertices) {
-                if (v.getZ() != 0) {
-                    is2d = Boolean.FALSE;
-                    return is2d;
-                }
-            }
-            is2d = Boolean.TRUE;
-        }
-
-        return is2d;
-    }
-
-    /**
      * Get the normal vector.
      * If no normal vector has been set then it is calculated in using the cross product of the first two vectors.
      * @return the normal vector.
@@ -396,16 +350,12 @@ public abstract class AbstractDrawable3DObject {
      * @return true if there are two vertices which are indentical
      */
     protected boolean isDegenerate() {
-        if (degenerated == null) {
-            Set<Vector3d> set = new HashSet<Vector3d>();
-            for (Vector3d v : vertices) {
-                set.add(v);
-            }
-
-            degenerated = set.size() != vertices.length;
+        Set<Vector3d> set = new HashSet<Vector3d>();
+        for (Vector3d v : vertices) {
+            set.add(v);
         }
 
-        return degenerated;
+        return set.size() != vertices.length;
     }
 
     protected boolean isNanOrInf() {
@@ -433,4 +383,44 @@ public abstract class AbstractDrawable3DObject {
         }
         return false;
     }
+
+    /**
+     * Create a clip rect for 2D view according to clipping planes passed as arguments
+     * @param v the clipping plane equation
+     */
+    public final static void makeClip(final double[] clip, final double[] v) {
+        if (v[1] == 0) {
+            double x = -v[3] / v[0];
+            if (Double.isNaN(clip[0])) {
+                clip[0] = x;
+            } else if (clip[0] > x) {
+                clip[1] = clip[0];
+                clip[0] = x;
+            } else {
+                clip[1] = x;
+            }
+        } else {
+            double y = -v[3] / v[1];
+            if (Double.isNaN(clip[2])) {
+                clip[2] = y;
+            } else if (clip[2] > y) {
+                clip[3] = clip[2];
+                clip[2] = y;
+            } else {
+                clip[3] = y;
+            }
+        }
+    }
+
+    /**
+     * Get the clipping shape (for 2D view)
+     * @return the clipping shape
+     */
+    public final static Shape getClip(final double[] clip) {
+        if (!Double.isNaN(clip[0]) && !Double.isNaN(clip[1]) && !Double.isNaN(clip[2]) && !Double.isNaN(clip[3])) {
+            return new Rectangle2D.Double(clip[0], clip[2], clip[1] - clip[0], clip[3] - clip[2]);
+        }
+
+        return null;
+    }
 }
index b434acc..a101e17 100644 (file)
@@ -107,6 +107,13 @@ public class BoundingBox {
     }
 
     /**
+     * @return true if the bbox are non-intersecting and no z-overlapping
+     */
+    public boolean isNonZOverlapping(BoundingBox box) {
+        return (box.maxX < minX || maxX < box.minX || box.maxY < minY || maxY < box.minY) || ((box.maxZ < minZ || maxZ < box.minZ) && (maxX == box.minX || box.maxX == minX || box.minY == maxY || minY == box.maxY));
+    }
+
+    /**
      * @param box a BoundingBox
      * @return true if this BoundingBox and the box have a strict intersection
      */
index 60b6f1d..c0c473f 100644 (file)
@@ -78,7 +78,7 @@ public abstract class ConvexObject extends AbstractDrawable3DObject implements C
      */
     public boolean areCoplanar(ConvexObject o) {
         if (!(this instanceof Segment)) {
-            double sc = vertices[0].scalar(v0v1);
+            double sc = vertices[0].scalar(getNormal());
             if (o instanceof Segment) {
                 return isEqual(sc, o.vertices[0].scalar(v0v1)) && isEqual(sc, o.vertices[1].scalar(v0v1));
             }
@@ -93,6 +93,8 @@ public abstract class ConvexObject extends AbstractDrawable3DObject implements C
             return true;
         }
 
+        getNormal();
+        o.getNormal();
         Vector3d v = Vector3d.product(v0, o.v0);
         return isNull(v.scalar(vertices[0].minus(o.vertices[0])));
     }
@@ -106,10 +108,8 @@ public abstract class ConvexObject extends AbstractDrawable3DObject implements C
         BoundingBox bbox = getBBox();
         BoundingBox obbox = o.getBBox();
         // Quick test in using bounding boxes
-        if (!bbox.isIntersecting(obbox)) {
-            if (bbox.xCompare(obbox) != 0 || bbox.yCompare(obbox) != 0) {
-                return 0;
-            }
+        if (bbox.isNonZOverlapping(obbox)) {
+            return 0;
         }
 
         // Check if the two objects intersect in projection plane or not
index c3dc2b1..925751d 100644 (file)
@@ -60,18 +60,18 @@ public final class DrawTools {
         area.add(new Area(stroke.createStrokedShape(contour)));
 
 
-        g2d.setColor(t.colors[0]);
+        g2d.setColor(t.getColor(0));
         g2d.fill(area);
 
 
-        float[] col = t.colors[1].getComponents(null);
-        GradientPaint gp = new GradientPaint((float) v1[0], (float) v1[1], t.colors[1], (float) pv1[0], (float) pv1[1], new Color(col[0], col[1], col[2], 0.0f));
+        float[] col = t.getColor(1).getComponents(null);
+        GradientPaint gp = new GradientPaint((float) v1[0], (float) v1[1], t.getColor(1), (float) pv1[0], (float) pv1[1], new Color(col[0], col[1], col[2], 0.0f));
         g2d.setPaint(gp);
         g2d.fill(area);
 
 
-        col = t.colors[2].getComponents(null);
-        gp = new GradientPaint((float) v2[0], (float) v2[1], t.colors[2], (float) pv2[0], (float) pv2[1], new Color(col[0], col[1], col[2], 0.0f));
+        col = t.getColor(2).getComponents(null);
+        gp = new GradientPaint((float) v2[0], (float) v2[1], t.getColor(2), (float) pv2[0], (float) pv2[1], new Color(col[0], col[1], col[2], 0.0f));
         g2d.setPaint(gp);
         g2d.fill(area);
 
index 46127f6..9b6be63 100644 (file)
@@ -242,14 +242,19 @@ public class Motor3D {
      * @param tri the triangle to add
      */
     private void add(Triangle tri) {
-        Vector3d normal = tri.getNormal();
-        if (normal != null) {
-            //normal = transf.projectDirection(normal);
-            if ((mode == FaceCullingMode.CW && normal.getZ() > 0) || (mode == FaceCullingMode.CCW && normal.getZ() < 0) || mode == FaceCullingMode.BOTH) {
-                Scene.addToRoot(is2DView(), tri);
-            }
+        final boolean is2d = is2DView();
+        if (is2d) {
+            Scene.addToRoot(is2d, tri);
         } else {
-            Scene.addToRoot(is2DView(), tri);
+            Vector3d normal = tri.getNormal();
+            if (normal != null) {
+                //normal = transf.projectDirection(normal);
+                if ((mode == FaceCullingMode.CW && normal.getZ() > 0) || (mode == FaceCullingMode.CCW && normal.getZ() < 0) || mode == FaceCullingMode.BOTH) {
+                    Scene.addToRoot(is2d, tri);
+                }
+            } else {
+                Scene.addToRoot(is2d, tri);
+            }
         }
     }
 
index 7faeb08..095e65b 100644 (file)
@@ -36,6 +36,7 @@ public class PolyLine extends ConvexObject {
 
     private boolean monochromatic;
     private G2DStroke stroke;
+    protected double[] clip = new double[] {Double.NaN, Double.NaN, Double.NaN, Double.NaN};
 
     /**
      * Default constructor
@@ -105,7 +106,7 @@ public class PolyLine extends ConvexObject {
         // Since PolyLine are only used in 2D it is useless to check when z != 0
         if (vv[2] == 0) {
             final Vector3d np = new Vector3d(vv);
-            makeClip(vv);
+            ConvexObject.makeClip(clip, vv);
 
             int pos = 0;
             boolean prev = false;
@@ -196,16 +197,16 @@ public class PolyLine extends ConvexObject {
 
             for (int i = 1; i < len - 1; i++) {
                 newVertices[i] = vertices[first + i - 1];
-                newColors[i] = colors[first + i - 1];
+                newColors[i] = getColor(first + i - 1);
             }
 
             double c = (C + vertices[first].scalar(np)) / vertices[first].minus(vertices[first - 1]).scalar(np);
             newVertices[0] = Vector3d.getBarycenter(vertices[first - 1], vertices[first], c, 1 - c);
-            newColors[0] = getColorsBarycenter(colors[first - 1], colors[first], c, 1 - c);
+            newColors[0] = getColorsBarycenter(getColor(first - 1), getColor(first), c, 1 - c);
 
             c = (C + vertices[second].scalar(np)) / vertices[second].minus(vertices[second - 1]).scalar(np);
             newVertices[len - 1] = Vector3d.getBarycenter(vertices[second - 1], vertices[second], c, 1 - c);
-            newColors[len - 1] = getColorsBarycenter(colors[second - 1], colors[second], c, 1 - c);
+            newColors[len - 1] = getColorsBarycenter(getColor(second - 1), getColor(second), c, 1 - c);
 
             return new PolyLine(newVertices, newColors, this.stroke);
         }
@@ -219,11 +220,11 @@ public class PolyLine extends ConvexObject {
 
             for (int i = 1; i < len; i++) {
                 newVertices[i] = vertices[first + i - 1];
-                newColors[i] = colors[first + i - 1];
+                newColors[i] = getColor(first + i - 1);
             }
 
             newVertices[0] = Vector3d.getBarycenter(vertices[first - 1], vertices[first], c, 1 - c);
-            newColors[0] = getColorsBarycenter(colors[first - 1], colors[first], c, 1 - c);
+            newColors[0] = getColorsBarycenter(getColor(first - 1), getColor(first), c, 1 - c);
 
             return new PolyLine(newVertices, newColors, this.stroke);
         } else {
@@ -235,11 +236,11 @@ public class PolyLine extends ConvexObject {
 
             for (int i = 0; i < len - 1; i++) {
                 newVertices[i] = vertices[first + i];
-                newColors[i] = colors[first + i];
+                newColors[i] = getColor(first + i);
             }
 
             newVertices[len - 1] = Vector3d.getBarycenter(vertices[second - 1], vertices[second], c, 1 - c);
-            newColors[len - 1] = getColorsBarycenter(colors[second - 1], colors[second], c, 1 - c);
+            newColors[len - 1] = getColorsBarycenter(getColor(second - 1), getColor(second), c, 1 - c);
             return new PolyLine(newVertices, newColors, this.stroke);
         }
     }
@@ -249,20 +250,20 @@ public class PolyLine extends ConvexObject {
         Stroke oldStroke = g2d.getStroke();
         Shape oldClip = g2d.getClip();
 
-        Shape newClip = getClip();
+        Shape newClip = ConvexObject.getClip(clip);
         if (newClip != null) {
             g2d.clip(newClip);
         }
 
         if (monochromatic) {
-            g2d.setColor(colors[0]);
+            g2d.setColor(getColor(0));
             g2d.setStroke(stroke);
             g2d.draw(getProjectedPolyLine());
         } else {
             // on peut surement faire mieux ici
             // avec un LinearGradientPaint
             Vector3d start = vertices[0];
-            Color color = colors[0];
+            Color color = getColor(0);
             double cumLen = 0;
             float[] dashArray = stroke.getDashArray();
             float lwidth = stroke.getLineWidth();
index 3bafa08..06d429b 100644 (file)
@@ -158,7 +158,7 @@ final class Scene {
                 }
                 if (toAdd != null) {
                     for (ConvexObject co : toAdd) {
-                        add(is2D, co);
+                        add(false, co);
                     }
                 }
             }
index ec0c6a2..4c924a0 100644 (file)
@@ -30,10 +30,11 @@ import org.scilab.forge.scirenderer.tranformations.Vector4d;
  */
 public class Segment extends ConvexObject implements Comparable<Segment> {
 
-    private Integer hash;
+    private int hash = -1;
     protected G2DStroke stroke;
     protected List<ConvexObject> segmentOn;
     protected boolean is2D;
+    protected double[] clip = new double[] {Double.NaN, Double.NaN, Double.NaN, Double.NaN};
 
     public Segment(Vector3d[] vertices, Color[] colors, G2DStroke stroke, boolean is2D) throws InvalidPolygonException {
         super(vertices, colors);
@@ -103,7 +104,7 @@ public class Segment extends ConvexObject implements Comparable<Segment> {
     public boolean equals(Object o) {
         if (o instanceof Segment) {
             Segment s = (Segment) o;
-            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]));
+            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)));
         }
 
         return false;
@@ -134,9 +135,9 @@ public class Segment extends ConvexObject implements Comparable<Segment> {
         double[] vv = v.getData();
 
         if (is2D && vv[2] == 0) {
-            makeClip(vv);
+            ConvexObject.makeClip(clip, vv);
         }
-
+        getNormal();
         Vector3d np = new Vector3d(vv);
         boolean a = isBehind(vertices[0], np, vv[3]);
         boolean b = isBehind(vertices[1], np, vv[3]);
@@ -153,14 +154,14 @@ public class Segment extends ConvexObject implements Comparable<Segment> {
 
         double c = (vv[3] + vertices[1].scalar(np)) / v0.scalar(np);
         Vector3d p = Vector3d.getBarycenter(vertices[0], vertices[1], c, 1 - c);
-        Color color = getColorsBarycenter(colors[0], colors[1], c, 1 - c);
+        Color color = getColorsBarycenter(getColor(0), getColor(1), c, 1 - c);
         Segment s;
 
         try {
             if (a) {
-                s = new Segment(new Vector3d[] {vertices[0], p}, new Color[] {colors[0], color}, this.stroke, this.is2D);
+                s = new Segment(new Vector3d[] {vertices[0], p}, new Color[] {getColor(0), color}, this.stroke, this.is2D);
             } else {
-                s = new Segment(new Vector3d[] {p, vertices[1]}, new Color[] {color, colors[1]}, this.stroke, this.is2D);
+                s = new Segment(new Vector3d[] {p, vertices[1]}, new Color[] {color, getColor(1)}, this.stroke, this.is2D);
             }
 
             List<ConvexObject> list = new ArrayList<ConvexObject>(1);
@@ -173,21 +174,22 @@ public class Segment extends ConvexObject implements Comparable<Segment> {
     }
 
     public List<Segment> breakObject(Vector3d p, Vector3d u, Vector3d n) {
+        getNormal();
         double c = vertices[1].minus(p).scalar(n) / v0.scalar(n);
         if (c > 0 && !isNull(c) && c < 1 && !isEqual(c, 1)) {
             List<Segment> list = new ArrayList<Segment>(2);
             Vector3d q = Vector3d.getBarycenter(vertices[0], vertices[1], c, 1 - c);
-            Color color = getColorsBarycenter(colors[0], colors[1], c, 1 - c);
+            Color color = getColorsBarycenter(getColor(0), getColor(1), c, 1 - c);
             try {
-                list.add(new Segment(new Vector3d[] {vertices[0], q}, new Color[] {colors[0], color}, stroke, this.is2D));
-                list.add(new Segment(new Vector3d[] {q, vertices[1]}, new Color[] {color, colors[1]}, stroke, this.is2D));
+                list.add(new Segment(new Vector3d[] {vertices[0], q}, new Color[] {getColor(0), color}, stroke, this.is2D));
+                list.add(new Segment(new Vector3d[] {q, vertices[1]}, new Color[] {color, getColor(1)}, stroke, this.is2D));
 
                 return list;
             } catch (InvalidPolygonException e) { }
         } else {
             List<Segment> list = new ArrayList<Segment>(1);
             try {
-                list.add(new Segment(new Vector3d[] {vertices[0], vertices[1]}, new Color[] {colors[0], colors[1]}, stroke, this.is2D));
+                list.add(new Segment(new Vector3d[] {vertices[0], vertices[1]}, new Color[] {getColor(0), getColor(1)}, stroke, this.is2D));
 
                 return list;
             } catch (InvalidPolygonException e) { }
@@ -200,14 +202,14 @@ public class Segment extends ConvexObject implements Comparable<Segment> {
     public void draw(Graphics2D g2d) {
         if (segmentOn == null || segmentOn.isEmpty()) {
             Path2D polyline = getProjectedPolyLine();
-            g2d.setColor(colors[0]);
+            g2d.setColor(getColor(0));
             Stroke oldStroke = g2d.getStroke();
             if (oldStroke != stroke) {
                 g2d.setStroke(stroke);
             }
 
             Shape oldClip = g2d.getClip();
-            Shape newClip = getClip();
+            Shape newClip = ConvexObject.getClip(clip);
             if (newClip != null) {
                 g2d.clip(newClip);
             }
@@ -228,8 +230,12 @@ public class Segment extends ConvexObject implements Comparable<Segment> {
 
     @Override
     public int hashCode() {
-        if (hash == null) {
-            hash = Arrays.hashCode(vertices) + 19 * Arrays.hashCode(colors);
+        if (hash == -1) {
+            if (colors != null) {
+                hash = Arrays.hashCode(vertices) + 19 * Arrays.hashCode(colors);
+            } else {
+                hash = Arrays.hashCode(vertices) + 19 * getColor(0).hashCode();
+            }
         }
         return hash;
     }
index fd370fa..8463b7c 100644 (file)
@@ -130,7 +130,7 @@ public class Triangle extends ConvexObject {
     }
 
     public List<ConvexObject> breakObject(Triangle o) {
-        Vector3d n = Vector3d.product(this.v0v1, o.v0v1);
+        Vector3d n = Vector3d.product(getNormal(), o.getNormal());
         n = n.times(1 / n.getNorm2());
         Vector3d u = Vector3d.product(o.v0v1, n);
         Vector3d v = Vector3d.product(n, this.v0v1);
@@ -152,14 +152,14 @@ public class Triangle extends ConvexObject {
 
         List<ConvexObject> list = new ArrayList<ConvexObject>(5);
         Vector3d p = Vector3d.getBarycenter(o.vertices[0], o.vertices[1], c, 1 - c);
-        Color cc = getColorsBarycenter(o.colors[0], o.colors[1], c, 1 - c);
+        Color cc = getColorsBarycenter(o.getColor(0), o.getColor(1), c, 1 - c);
 
         try {
-            list.add(new Segment(new Vector3d[] {o.vertices[0], p}, new Color[] {o.colors[0], cc}, o.stroke, o.is2D));
-            list.add(new Segment(new Vector3d[] {p, o.vertices[1]}, new Color[] {cc, o.colors[1]}, o.stroke, o.is2D));
+            list.add(new Segment(new Vector3d[] {o.vertices[0], p}, new Color[] {o.getColor(0), cc}, o.stroke, o.is2D));
+            list.add(new Segment(new Vector3d[] {p, o.vertices[1]}, new Color[] {cc, o.getColor(1)}, o.stroke, o.is2D));
         } catch (InvalidPolygonException e) { }
 
-        List<ConvexObject> list1 = breakTriangleOnLine(this, p, Vector3d.product(v0v1, vertices[0].minus(p)));
+        List<ConvexObject> list1 = breakTriangleOnLine(this, p, Vector3d.product(getNormal(), vertices[0].minus(p)));
         list.addAll(list1);
 
         return list;
@@ -180,25 +180,28 @@ public class Triangle extends ConvexObject {
             Path2D contour = getProjectedContour();
             Area area = new Area(contour);
             // Trick to paint the triangle and its outline
-            area.add(new Area(stroke.createStrokedShape(contour)));
+            //area.add(new Area(stroke.createStrokedShape(contour)));
             g2d.clip(area);//getProjectedContour());
             sprite.draw(g2d);
             g2d.setClip(oldClip);
         } else if (image != null) {
             Object key = filter == Texture.Filter.LINEAR ? RenderingHints.VALUE_INTERPOLATION_BILINEAR : RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
             DrawTools.drawTriangleTexture(g2d, image, new double[] {textureCoords[0].getX(), textureCoords[1].getX(), textureCoords[2].getX()}, new double[] {textureCoords[0].getY(), textureCoords[1].getY(), textureCoords[2].getY()}, new double[] {vertices[0].getX(), vertices[1].getX(), vertices[2].getX()}, new double[] {vertices[0].getY(), vertices[1].getY(), vertices[2].getY()}, key);
-        } else if (colors[0].equals(colors[1]) && colors[1].equals(colors[2])) {
+        } else if (isMonochromatic()) {
             Path2D contour = getProjectedContour();
-            Area area = new Area(contour);
+            //Area area = new Area(contour);
             // Trick to paint the triangle and its outline
             // TODO: the newly created Area contains in fact two areas
             // it should be better to have one area where its border
             // is the external outline of the contour...
             // (it would reduce eps/ps/pdf/svg file size)
-            area.add(new Area(stroke.createStrokedShape(contour)));
-            g2d.setStroke(EMPTYSTROKE);
-            g2d.setColor(colors[0]);
-            g2d.fill(area);
+            // fill(area) is very very slow... (for a grayplot 500x500, fill(area) is 10 times slower than fill(contour))...
+            //area.add(new Area(stroke.createStrokedShape(contour)));
+            if (g2d.getStroke() != EMPTYSTROKE) {
+                g2d.setStroke(EMPTYSTROKE);
+            }
+            g2d.setColor(getColor(0));
+            g2d.fill(contour);
         } else {
             DrawTools.fillGouraud(g2d, this);
         }
@@ -226,7 +229,7 @@ public class Triangle extends ConvexObject {
             return null;
         }
 
-        Vector3d n = Vector3d.product(this.v0v1, np);
+        Vector3d n = Vector3d.product(getNormal(), np);
         n = n.times(1 / n.getNorm2());
         Vector3d u = Vector3d.product(np, n);
         Vector3d w = Vector3d.product(n, this.v0v1);
@@ -249,6 +252,7 @@ public class Triangle extends ConvexObject {
 
     protected boolean isPointInside(final Vector3d v, final boolean checkCoplanarity) {
         Vector3d v2 = v.minus(vertices[0]);
+        getNormal();
         if (checkCoplanarity && !isNull(v2.scalar(v0v1))) {
             return false;
         }
@@ -268,12 +272,12 @@ public class Triangle extends ConvexObject {
     }
 
     protected boolean isCoplanar(final Segment s) {
-        double sc = vertices[0].scalar(v0v1);
+        double sc = vertices[0].scalar(getNormal());
         return isEqual(sc, s.vertices[0].scalar(v0v1)) && isEqual(sc, s.vertices[1].scalar(v0v1));
     }
 
     protected boolean isCoplanar(final Triangle t) {
-        double sc = vertices[0].scalar(v0v1);
+        double sc = vertices[0].scalar(getNormal());
         return isEqual(sc, t.vertices[0].scalar(v0v1)) && isEqual(sc, t.vertices[1].scalar(v0v1)) && isEqual(sc, t.vertices[2].scalar(v0v1));
     }
 
@@ -304,7 +308,7 @@ public class Triangle extends ConvexObject {
     protected boolean isSegmentIntersects(final Segment s) {
         Vector3d v3 = s.vertices[0].minus(vertices[0]);
         Vector3d v4 = s.vertices[1].minus(vertices[0]);
-        double c = v3.scalar(v0v1);
+        double c = v3.scalar(getNormal());
 
         if (Math.signum(c) == Math.signum(v4.scalar(v0v1))) {
             return false;
@@ -322,7 +326,7 @@ public class Triangle extends ConvexObject {
 
     protected double getSegmentIntersection(final Segment s) {
         Vector3d v = s.vertices[1].minus(vertices[0]);
-        double c = v.scalar(v0v1) / s.v0.scalar(v0v1);
+        double c = v.scalar(getNormal()) / s.v0.scalar(getNormal());
 
         if (isNegativeOrNull(c) || isGreaterOrEqual(c, 1)) {
             return Double.NaN;
@@ -344,11 +348,11 @@ public class Triangle extends ConvexObject {
 
         List<ConvexObject> list = new ArrayList<ConvexObject>(2);
         Vector3d p = Vector3d.getBarycenter(s.vertices[0], s.vertices[1], c, 1 - c);
-        Color cc = getColorsBarycenter(s.colors[0], s.colors[1], c, 1 - c);
+        Color cc = getColorsBarycenter(s.getColor(0), s.getColor(1), c, 1 - c);
 
         try {
-            list.add(new Segment(new Vector3d[] {s.vertices[0], p}, new Color[] {s.colors[0], cc}, s.stroke, s.is2D));
-            list.add(new Segment(new Vector3d[] {p, s.vertices[1]}, new Color[] {cc, s.colors[1]}, s.stroke, s.is2D));
+            list.add(new Segment(new Vector3d[] {s.vertices[0], p}, new Color[] {s.getColor(0), cc}, s.stroke, s.is2D));
+            list.add(new Segment(new Vector3d[] {p, s.vertices[1]}, new Color[] {cc, s.getColor(1)}, s.stroke, s.is2D));
         } catch (InvalidPolygonException e) { }
 
 
@@ -364,6 +368,7 @@ public class Triangle extends ConvexObject {
      * @return a list of triangles
      */
     protected static List<ConvexObject> breakTriangleOnLine(Triangle t, Vector3d p, Vector3d n) {
+        t.getNormal();
         // aP0+(1-a)P1
         double a = t.vertices[1].minus(p).scalar(n) / t.v0.scalar(n);
         // bP0+(1-b)P2
@@ -415,11 +420,11 @@ public class Triangle extends ConvexObject {
             if (weight >= 0 && weight <= 1) {
                 // We break into two triangles
                 Vector3d vb = Vector3d.getBarycenter(t.vertices[j], t.vertices[k], weight, 1 - weight);
-                Color cb = getColorsBarycenter(t.colors[j], t.colors[k], weight, 1 - weight);
+                Color cb = getColorsBarycenter(t.getColor(j), t.getColor(k), weight, 1 - weight);
                 Vector3d[] vertices1 = new Vector3d[] {t.vertices[i], t.vertices[j], vb};
                 Vector3d[] vertices2 = new Vector3d[] {t.vertices[i], vb, t.vertices[k]};
-                Color[] colors1 = new Color[] {t.colors[i], t.colors[j], cb};
-                Color[] colors2 = new Color[] {t.colors[i], cb, t.colors[k]};
+                Color[] colors1 = new Color[] {t.getColor(i), t.getColor(j), cb};
+                Color[] colors2 = new Color[] {t.getColor(i), cb, t.getColor(k)};
 
                 Vector3d[] tvertices1 = null;
                 Vector3d[] tvertices2 = null;
@@ -463,8 +468,8 @@ public class Triangle extends ConvexObject {
             k = 1;
             u = Vector3d.getBarycenter(t.vertices[1], t.vertices[2], c, 1 - c);
             v = Vector3d.getBarycenter(t.vertices[0], t.vertices[2], b, 1 - b);
-            cu = getColorsBarycenter(t.colors[1], t.colors[2], c, 1 - c);
-            cv = getColorsBarycenter(t.colors[0], t.colors[2], b, 1 - b);
+            cu = getColorsBarycenter(t.getColor(1), t.getColor(2), c, 1 - c);
+            cv = getColorsBarycenter(t.getColor(0), t.getColor(2), b, 1 - b);
             if (t.textureCoords != null) {
                 tu = Vector3d.getBarycenter(t.textureCoords[1], t.textureCoords[2], c, 1 - c);
                 tv = Vector3d.getBarycenter(t.textureCoords[0], t.textureCoords[2], b, 1 - b);
@@ -475,8 +480,8 @@ public class Triangle extends ConvexObject {
             k = 0;
             u = Vector3d.getBarycenter(t.vertices[0], t.vertices[1], a, 1 - a);
             v = Vector3d.getBarycenter(t.vertices[1], t.vertices[2], c, 1 - c);
-            cu = getColorsBarycenter(t.colors[0], t.colors[1], a, 1 - a);
-            cv = getColorsBarycenter(t.colors[1], t.colors[2], c, 1 - c);
+            cu = getColorsBarycenter(t.getColor(0), t.getColor(1), a, 1 - a);
+            cv = getColorsBarycenter(t.getColor(1), t.getColor(2), c, 1 - c);
             if (t.textureCoords != null) {
                 tu = Vector3d.getBarycenter(t.textureCoords[0], t.textureCoords[1], a, 1 - a);
                 tv = Vector3d.getBarycenter(t.textureCoords[1], t.textureCoords[2], c, 1 - c);
@@ -487,8 +492,8 @@ public class Triangle extends ConvexObject {
             k = 2;
             u = Vector3d.getBarycenter(t.vertices[0], t.vertices[2], b, 1 - b);
             v = Vector3d.getBarycenter(t.vertices[0], t.vertices[1], a, 1 - a);
-            cu = getColorsBarycenter(t.colors[0], t.colors[2], b, 1 - b);
-            cv = getColorsBarycenter(t.colors[0], t.colors[1], a, 1 - a);
+            cu = getColorsBarycenter(t.getColor(0), t.getColor(2), b, 1 - b);
+            cv = getColorsBarycenter(t.getColor(0), t.getColor(1), a, 1 - a);
             if (t.textureCoords != null) {
                 tu = Vector3d.getBarycenter(t.textureCoords[0], t.textureCoords[2], b, 1 - b);
                 tv = Vector3d.getBarycenter(t.textureCoords[0], t.textureCoords[1], a, 1 - a);
@@ -496,11 +501,11 @@ public class Triangle extends ConvexObject {
         }
 
         Vector3d[] vertices1 = new Vector3d[] {u, t.vertices[i], v};
-        Color[] colors1 = new Color[] {cu, t.colors[i], cv};
+        Color[] colors1 = new Color[] {cu, t.getColor(i), cv};
         Vector3d[] vertices2 = new Vector3d[] {u, v, t.vertices[j]};
-        Color[] colors2 = new Color[] {cu, cv, t.colors[j]};
+        Color[] colors2 = new Color[] {cu, cv, t.getColor(j)};
         Vector3d[] vertices3 = new Vector3d[] {u, t.vertices[j], t.vertices[k]};
-        Color[] colors3 = new Color[] {cu, t.colors[j], t.colors[k]};
+        Color[] colors3 = new Color[] {cu, t.getColor(j), t.getColor(k)};
 
         Vector3d[] tvertices1 = null;
         Vector3d[] tvertices2 = null;
@@ -564,7 +569,7 @@ public class Triangle extends ConvexObject {
      * @return an array of length 2 containing the resulting triangles for t1 and t2.
      */
     protected static List<ConvexObject> breakIntersectingTriangles(Triangle t1, Triangle t2) {
-        Vector3d n = Vector3d.product(t1.v0v1, t2.v0v1);
+        Vector3d n = Vector3d.product(t1.getNormal(), t2.getNormal());
         n = n.times(1 / n.getNorm2());
         Vector3d u = Vector3d.product(t2.v0v1, n);
         Vector3d v = Vector3d.product(n, t1.v0v1);
@@ -578,6 +583,6 @@ public class Triangle extends ConvexObject {
     }
 
     public String toString() {
-        return "Triangle: " + vertices[0].toString() + " " + vertices[1].toString() + " " + vertices[2].toString() + "\nColor: " + colors[0] + "\nPrecedence: " + precedence;
+        return "Triangle: " + vertices[0].toString() + " " + vertices[1].toString() + " " + vertices[2].toString() + "\nColor: " + getColor(0) + "\nPrecedence: " + precedence;
     }
 }
index f1a187a..3ae9a6a 100644 (file)
@@ -190,7 +190,7 @@ public class G2DTextureDrawingTools implements TextureDrawingTools {
             TextLayout textLayout = new TextLayout(textEntity.getText(), textEntity.getFont(), g2d.getFontRenderContext());
             Rectangle2D bounds = textLayout.getBounds();
             g2d.setFont(textEntity.getFont());
-            g2d.drawString(textEntity.getText(), (float) (x - bounds.getX()), (float) (y + textLayout.getAscent()));
+            g2d.drawString(textEntity.getText(), (float) (x - bounds.getX()), y + textLayout.getAscent());
         }
     }
 
index a834ca3..5feccb2 100644 (file)
@@ -21,7 +21,7 @@ public class Vector3d {
     private final double x;
     private final double y;
     private final double z;
-    private Integer hash;
+    private int hash = -1;
 
     public Vector3d(Vector3d v) {
         this.x = v.x;
@@ -198,7 +198,7 @@ public class Vector3d {
 
     @Override
     public int hashCode() {
-        if (hash == null) {
+        if (hash == -1) {
             hash = Arrays.hashCode(new double[] {x, y, z});
         }
         return hash;