Calixte DENIZET [Thu, 19 Sep 2013 15:49:51 +0000 (17:49 +0200)]
Change-Id: I1a44fd7ff3152008e0b626f68c326463afb5d589

index 88db933..e80a09b 100644 (file)
@@ -203,6 +203,8 @@ Scilab Bug Fixes

* Bug #4731 fixed - lqr failed when the time domain of an input was a number.

+* Bug #4743 fixed - Invalid graphics with too big or too small values.
+
* Bug #5073 fixed - New parameter added in strtod function (decimal separator).

* Bug #5205 fixed - permute was slow for large hypermatrices.
index 70c26af..59dcc4b 100644 (file)
@@ -1895,6 +1895,48 @@ public class Axes extends GraphicObject {
}

/**
+     * Get the scale and translate factors corresponding to the displayed bounds
+     * @return the factors as a multidimensional array 2x3
+     */
+    public double[][] getScaleTranslateFactors() {
+        // For an axe scale and translate factors are
+        // such that scale*min+translate=-1 and scale*max+translate=+1
+        // With these factors, double data will be in interval [-1;1]
+
+        Double[] bounds = getMaximalDisplayedBounds();
+        double[][] f = new double[2][];
+
+        // scale factors
+        f[0] = new double[] {2 / (bounds[1] - bounds[0]),
+                             2 / (bounds[3] - bounds[2]),
+                             2 / (bounds[5] - bounds[4])
+                            };
+
+        // translate factors
+        f[1] = new double[] { -(bounds[1] + bounds[0]) / (bounds[1] - bounds[0]), -(bounds[3] + bounds[2]) / (bounds[3] - bounds[2]), -(bounds[5] + bounds[4]) / (bounds[5] - bounds[4])};
+
+        return f;
+    }
+
+    public Double[] getCorrectedBounds() {
+        if (getZoomEnabled()) {
+            Double[] b = getZoomBox();
+            double[][] factors = getScaleTranslateFactors();
+
+            b[0] = b[0] * factors[0][0] + factors[1][0];
+            b[1] = b[1] * factors[0][0] + factors[1][0];
+            b[2] = b[2] * factors[0][1] + factors[1][1];
+            b[3] = b[3] * factors[0][1] + factors[1][1];
+            b[4] = b[4] * factors[0][2] + factors[1][2];
+            b[5] = b[5] * factors[0][2] + factors[1][2];
+
+            return b;
+        } else {
+            return new Double[] { -1., 1., -1., 1., -1., 1.};
+        }
+    }
+
+    /**
* Current displayed bounds getter.
* @return the current visible bounds of this axes.
*/
index 3ec7b96..d3c5179 100644 (file)
@@ -86,7 +86,7 @@ public abstract class Imageplot extends ClippableContouredObject {
}

public Double[] getScale() {
-        return scale;
+        return new Double[] {scale[0], scale[1]};
}

public void setScale(Double[] scale) {
@@ -94,7 +94,7 @@ public abstract class Imageplot extends ClippableContouredObject {
}

public Double[] getTranslate() {
-        return translate;
+        return new Double[] {translate[0], translate[1]};
}

public void setTranslate(Double[] translate) {
index 8499c7c..b043d99 100644 (file)
@@ -16,7 +16,9 @@ import org.scilab.forge.scirenderer.buffers.ElementsBuffer;
import org.scilab.forge.scirenderer.buffers.IndicesBuffer;
import org.scilab.modules.graphic_objects.ObjectRemovedException;
+import org.scilab.modules.graphic_objects.axes.Axes;
import org.scilab.modules.graphic_objects.graphicController.GraphicController;
+import org.scilab.modules.graphic_objects.graphicObject.GraphicObject;
import org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties;
import org.scilab.modules.renderer.JoGLView.util.BufferAllocation;
import org.scilab.modules.renderer.JoGLView.util.OutOfMemoryException;
@@ -32,8 +34,7 @@ import java.util.concurrent.ConcurrentHashMap;

/**
* @author Pierre Lando
- */
-public class DataManager {
+ */public class DataManager {

/**
* Set of properties that affect Fac3d data.
@@ -143,8 +144,7 @@ public class DataManager {
*/
private static final int DEFAULT_LOG_MASK = 0;

-
-    private final Map<String, ElementsBuffer> vertexBufferMap = new HashMap<String, ElementsBuffer>();
+    private final Map<String, TransformedElementsBuffer> vertexBufferMap = new HashMap<String, TransformedElementsBuffer>();
private final Map<String, ElementsBuffer> normalBufferMap = new HashMap<String, ElementsBuffer>();
private final Map<String, ElementsBuffer> colorBufferMap = new ConcurrentHashMap<String, ElementsBuffer>();
private final Map<String, ElementsBuffer> texturesCoordinatesBufferMap = new HashMap<String, ElementsBuffer>();
@@ -168,14 +168,22 @@ public class DataManager {
* @throws ObjectRemovedException if the object is now longer present.
*/
public ElementsBuffer getVertexBuffer(String id) throws ObjectRemovedException, OutOfMemoryException {
+        GraphicObject currentObject = GraphicController.getController().getObjectFromId(id);
+        Axes axes = (Axes) GraphicController.getController().getObjectFromId(currentObject.getParentAxes());
+        double[][] factors = axes.getScaleTranslateFactors();
+
if (vertexBufferMap.containsKey(id)) {
-            return vertexBufferMap.get(id);
-        } else {
-            ElementsBuffer vertexBuffer = canvas.getBuffersManager().createElementsBuffer();
-            fillVertexBuffer(vertexBuffer, id);
-            vertexBufferMap.put(id, vertexBuffer);
-            return vertexBuffer;
+            TransformedElementsBuffer buf = vertexBufferMap.get(id);
+            if (buf.isSameFactors(factors)) {
+                return buf.getBuffer();
+            }
}
+
+        ElementsBuffer vertexBuffer = canvas.getBuffersManager().createElementsBuffer();
+        fillVertexBuffer(vertexBuffer, id, factors[0], factors[1]);
+        vertexBufferMap.put(id, new TransformedElementsBuffer(vertexBuffer, factors));
+
+        return vertexBuffer;
}

/**
@@ -322,9 +330,13 @@ public class DataManager {
* @throws OutOfMemoryException if there was not enough memory.
*/
private void updateChildrenVertexIndex(String id, int coordinateMask) throws ObjectRemovedException, OutOfMemoryException {
-        ElementsBuffer vertexBuffer = vertexBufferMap.get(id);
-        if (vertexBuffer != null) {
+        GraphicObject currentObject = GraphicController.getController().getObjectFromId(id);
+        Axes axes = (Axes) GraphicController.getController().getObjectFromId(currentObject.getParentAxes());
+        double[][] factors = axes.getScaleTranslateFactors();
+
+        TransformedElementsBuffer buf = vertexBufferMap.get(id);
+        if (buf != null) {
+            updateVertexBuffer(buf.getBuffer(), id, coordinateMask, factors[0], factors[1]);
}

ElementsBuffer normalBuffer = normalBufferMap.get(id);
@@ -360,7 +372,7 @@ public class DataManager {
*/
public void dispose(String id) {
if (vertexBufferMap.containsKey(id)) {
-            canvas.getBuffersManager().dispose(vertexBufferMap.get(id));
+            canvas.getBuffersManager().dispose(vertexBufferMap.get(id).getBuffer());
vertexBufferMap.remove(id);
}

@@ -413,9 +425,9 @@ public class DataManager {
* @throws ObjectRemovedException if the object is now longer present.
*/
private void fillBuffers(String id) throws ObjectRemovedException, OutOfMemoryException {
-        ElementsBuffer vertexBuffer = vertexBufferMap.get(id);
-        if (vertexBuffer != null) {
-            fillVertexBuffer(vertexBuffer, id);
+        TransformedElementsBuffer buf = vertexBufferMap.get(id);
+        if (buf != null) {
+            fillVertexBuffer(buf.getBuffer(), id, buf.getScale(), buf.getTranslate());
}

ElementsBuffer colorBuffer = colorBufferMap.get(id);
@@ -439,15 +451,15 @@ public class DataManager {
}
}

-    private void fillVertexBuffer(ElementsBuffer vertexBuffer, String id) throws ObjectRemovedException, OutOfMemoryException {
-        fillVertexBuffer(vertexBuffer, id, 0x01 | 0x02 | 0x04 | 0x08);
+    private void fillVertexBuffer(ElementsBuffer vertexBuffer, String id, double[] scale, double[] translate) throws ObjectRemovedException, OutOfMemoryException {
+        fillVertexBuffer(vertexBuffer, id, 0x01 | 0x02 | 0x04 | 0x08, scale, translate);
}

-    private void fillVertexBuffer(ElementsBuffer vertexBuffer, String id, int coordinateMask) throws ObjectRemovedException, OutOfMemoryException {
+    private void fillVertexBuffer(ElementsBuffer vertexBuffer, String id, int coordinateMask, double[] scale, double[] translate) throws ObjectRemovedException, OutOfMemoryException {
FloatBuffer data = BufferAllocation.newFloatBuffer(length * 4);
vertexBuffer.setData(data, 4);
}

@@ -458,10 +470,10 @@ public class DataManager {
normalBuffer.setData(data, 4);
}

-    private void updateVertexBuffer(ElementsBuffer vertexBuffer, String id, int coordinateMask) throws ObjectRemovedException {
+    private void updateVertexBuffer(ElementsBuffer vertexBuffer, String id, int coordinateMask, double[] scale, double[] translate) throws ObjectRemovedException {
FloatBuffer data = vertexBuffer.getData();
vertexBuffer.setData(data, 4);
}

@@ -516,4 +528,39 @@ public class DataManager {

indexBuffer.setData(data);
}
+
+    private static class TransformedElementsBuffer {
+
+        ElementsBuffer buffer;
+        double[][] factors;
+
+        TransformedElementsBuffer(ElementsBuffer buffer, double[][] factors) {
+            this.buffer = buffer;
+            this.factors = factors;
+        }
+
+        ElementsBuffer getBuffer() {
+            return buffer;
+        }
+
+        double[] getScale() {
+            return factors[0];
+        }
+
+        double[] getTranslate() {
+            return factors[1];
+        }
+
+        boolean isSameFactors(final double[][] factors) {
+            for (int i = 0; i < 2; i++) {
+                for (int j = 0; j < 3; j++) {
+                    if (this.factors[i][j] != factors[i][j]) {
+                        return false;
+                    }
+                }
+            }
+
+            return true;
+        }
+    }
}
index eec408a..6c138be 100755 (executable)
@@ -439,8 +439,16 @@ public class DrawerVisitor implements Visitor, Drawer, GraphicView {
drawingTools.draw(geometry, appearance);
} else {
TransformationStack modelViewStack = drawingTools.getTransformationManager().getModelViewStack();
+                    double[][] factors = currentAxes.getScaleTranslateFactors();
Double[] scale = matplot.getScale();
Double[] translate = matplot.getTranslate();
+
+                    scale[0] *= factors[0][0];
+                    scale[1] *= factors[0][1];
+
+                    translate[0] = translate[0] * factors[0][0] + factors[1][0];
+                    translate[1] = translate[1] * factors[0][1] + factors[1][1];
+
Transformation t = TransformationFactory.getTranslateTransformation(translate[0], translate[1], 0);
Transformation t2 = TransformationFactory.getScaleTransformation(scale[0], scale[1], 1);
modelViewStack.pushRightMultiply(t);
@@ -197,7 +197,7 @@ public class AxesDrawer {

/* 2d view projection, to do: optimize computation */
-        if (axes.getRotationAngles()[0] != 0 || axes.getRotationAngles()[1] != DEFAULT_THETA) {
+        if ((axes.getRotationAngles()[0] != 0 || axes.getRotationAngles()[1] != DEFAULT_THETA)) {
Transformation transformation2dView = computeBoxTransformation(axes, canvasDimension, true);
currentProjection = zoneProjection.rightTimes(transformation2dView);
currentProjection = currentProjection.rightTimes(dataTransformation);
@@ -373,8 +373,6 @@ public class AxesDrawer {
* @throws DegenerateMatrixException if data bounds are not corrects.
*/
private Transformation computeDataTransformation(Axes axes) throws DegenerateMatrixException {
-        Double[] bounds = axes.getDisplayedBounds();
-
// Reverse data if needed.
Transformation transformation = TransformationFactory.getScaleTransformation(
axes.getAxes()[0].getReverse() ? 1 : -1,
@@ -382,22 +380,29 @@ public class AxesDrawer {
axes.getAxes()[2].getReverse() ? 1 : -1
);

-        // Scale data.
-        Transformation scaleTransformation = TransformationFactory.getScaleTransformation(
-                2.0 / (bounds[1] - bounds[0]),
-                2.0 / (bounds[3] - bounds[2]),
-                2.0 / (bounds[5] - bounds[4])
-                                             );
-        transformation = transformation.rightTimes(scaleTransformation);
-
-
-        // Translate data.
-        Transformation translateTransformation = TransformationFactory.getTranslateTransformation(
-                    -(bounds[0] + bounds[1]) / 2.0,
-                    -(bounds[2] + bounds[3]) / 2.0,
-                    -(bounds[4] + bounds[5]) / 2.0
-                );
-        transformation = transformation.rightTimes(translateTransformation);
+        if (axes.getZoomEnabled()) {
+            Double[] bounds = axes.getCorrectedBounds();
+
+            // Scale data.
+            Transformation scaleTransformation = TransformationFactory.getScaleTransformation(
+                    2.0 / (bounds[1] - bounds[0]),
+                    2.0 / (bounds[3] - bounds[2]),
+                    2.0 / (bounds[5] - bounds[4])
+                                                 );
+            transformation = transformation.rightTimes(scaleTransformation);
+
+
+            // Translate data.
+            Transformation translateTransformation = TransformationFactory.getTranslateTransformation(
+                        -(bounds[0] + bounds[1]) / 2.0,
+                        -(bounds[2] + bounds[3]) / 2.0,
+                        -(bounds[4] + bounds[5]) / 2.0
+                    );
+            transformation = transformation.rightTimes(translateTransformation);
+
+            return transformation;
+        }
+
return transformation;
}

@@ -415,7 +420,6 @@ public class AxesDrawer {
*/
private Transformation computeBoxTransformation(Axes axes, Dimension canvasDimension, boolean use2dView) throws DegenerateMatrixException {
Double[] bounds = axes.getDisplayedBounds();
-
double theta;

double tmpX;
@@ -487,7 +491,7 @@ public class AxesDrawer {
* @param axes the given {@see Axes}.
*/
private void computeReversedBounds(Axes axes) {
-        Double[] currentBounds = axes.getDisplayedBounds();
+        Double[] currentBounds = axes.getCorrectedBounds();

/* Reverse */
if (axes.getAxes()[0].getReverse()) {
@@ -739,27 +743,37 @@ public class AxesDrawer {
* @returns the 2d view coordinates (3-element array).
*/
public static double[] compute2dViewCoordinates(Axes axes, double[] coordinates) {
+        // used in geom3d
+
DrawerVisitor currentVisitor = DrawerVisitor.getVisitor(axes.getParentFigure());
AxesDrawer axesDrawer;
Transformation projection;
Transformation projection2d;
-
-        Vector3d point = new Vector3d(coordinates);
+        double[] coords = coordinates;

if (currentVisitor != null) {
Integer[] size = currentVisitor.getFigure().getAxesSize();
Dimension canvasDimension = new Dimension(size[0], size[1]);
+            double[][] factors = axes.getScaleTranslateFactors();

axesDrawer = currentVisitor.getAxesDrawer();
+            coords[0] = coords[0] * factors[0][0] + factors[1][0];
+            coords[1] = coords[1] * factors[0][1] + factors[1][1];
+            coords[2] = coords[2] * factors[0][2] + factors[1][2];

projection = axesDrawer.computeProjection(axes, currentVisitor.getDrawingTools(), canvasDimension, false);
projection2d = axesDrawer.computeProjection(axes, currentVisitor.getDrawingTools(), canvasDimension, true);
-
+            Vector3d point = new Vector3d(coords);
point = projection.project(point);
point = projection2d.unproject(point);
+
+            coords = point.getData();
+            coords[0] = (coords[0] - factors[1][0]) / factors[0][0];
+            coords[1] = (coords[1] - factors[1][1]) / factors[0][1];
+            coords[2] = (coords[2] - factors[1][2]) / factors[0][2];
}

-        return new double[] {point.getX(), point.getY(), point.getZ()};
+        return coords;
}

/**
@@ -771,6 +785,8 @@ public class AxesDrawer {
* @returns the pixel coordinates (2-element array: x, y).
*/
public static double[] computePixelFrom2dViewCoordinates(Axes axes, double[] coordinates) {
+        // used by xchange
+
DrawerVisitor currentVisitor = DrawerVisitor.getVisitor(axes.getParentFigure());
AxesDrawer axesDrawer;
double[] coords2dView = new double[] {0.0, 0.0, 0.0};
@@ -778,22 +794,26 @@ public class AxesDrawer {
if (currentVisitor != null) {
Integer[] size = currentVisitor.getFigure().getAxesSize();
double height = (double) size[1];
+            double[][] factors = axes.getScaleTranslateFactors();

axesDrawer = currentVisitor.getAxesDrawer();
+            coords2dView[0] = coordinates[0] * factors[0][0] + factors[1][0];
+            coords2dView[1] = coordinates[1] * factors[0][1] + factors[1][1];
+            coords2dView[2] = coordinates[2] * factors[0][2] + factors[1][2];

Transformation projection2d = axesDrawer.getProjection2dView(axes.getIdentifier());
-
if (projection2d == null) {
updateAxesTransformation(axes);
projection2d = axesDrawer.getProjection2dView(axes.getIdentifier());
}

-            Vector3d point = new Vector3d(coordinates);
+            Vector3d point = new Vector3d(coords2dView);
point = projection2d.project(point);

/* Convert the window coordinates to pixel coordinates, only y changes due to the differing y-axis convention */
coords2dView[0] = point.getX();
coords2dView[1] = height - point.getY();
+            coords2dView[2] = 0;
}

return coords2dView;
@@ -876,6 +896,8 @@ public class AxesDrawer {
* @return coordinates the 2d view coordinates (3-element array: x, y, z).
*/
public static double[] compute2dViewFromPixelCoordinates(Axes axes, double[] coordinates) {
+        // used by xgetmouse and by xchange
+
DrawerVisitor currentVisitor;
AxesDrawer axesDrawer;

@@ -886,6 +908,7 @@ public class AxesDrawer {
if (currentVisitor != null) {
Integer[] size = currentVisitor.getFigure().getAxesSize();
double height = (double) size[1];
+            double[][] factors = axes.getScaleTranslateFactors();

axesDrawer = currentVisitor.getAxesDrawer();

@@ -900,6 +923,10 @@ public class AxesDrawer {

point = projection2d.unproject(point);
coords2dView = point.getData();
+
+            coords2dView[0] = (coords2dView[0] - factors[1][0]) / factors[0][0];
+            coords2dView[1] = (coords2dView[1] - factors[1][1]) / factors[0][1];
+            coords2dView[2] = (coords2dView[2] - factors[1][2]) / factors[0][2];
}

return coords2dView;
@@ -1008,7 +1035,7 @@ public class AxesDrawer {
* against the Axes box planes.
*/
numPlanes = 6;
-                Double[] bounds = parentAxes.getDisplayedBounds();
+                Double[] bounds = parentAxes.getCorrectedBounds();

for (int i = 0; i < numPlanes; i++) {
clipBounds[i] = bounds[i];
@@ -1031,6 +1058,7 @@ public class AxesDrawer {
clipBounds[2] = clipBox[1] - clipBox[3];
clipBounds[3] = clipBox[1];

+                double[][] factors = parentAxes.getScaleTranslateFactors();
Double[] bounds = parentAxes.getMaximalDisplayedBounds();

/*
@@ -1066,6 +1094,11 @@ public class AxesDrawer {
}
}

+                clipBounds[0] = clipBounds[0] * factors[0][0] + factors[1][0];
+                clipBounds[1] = clipBounds[1] * factors[0][0] + factors[1][0];
+                clipBounds[2] = clipBounds[2] * factors[0][1] + factors[1][1];
+                clipBounds[3] = clipBounds[3] * factors[0][1] + factors[1][1];
+
offsets[0] = CLIPPING_EPSILON * (clipBounds[1] - clipBounds[0]);
offsets[1] = CLIPPING_EPSILON * (clipBounds[3] - clipBounds[2]);
}
@@ -1084,6 +1117,7 @@ public class AxesDrawer {
}

Transformation currentTransformation = drawingTools.getTransformationManager().getTransformation();
+
for (int i = 0 ; i < numPlanes; i++) {
ClippingPlane plane = drawingTools.getClippingManager().getClippingPlane(i);
plane.setTransformation(currentTransformation);
index deaabeb..c27c1ea 100644 (file)
@@ -86,10 +86,15 @@ public class TextManager {

Transformation projection = drawingTools.getTransformationManager().getCanvasProjection();

-        Vector3d textPosition = new Vector3d(text.getPosition());
-
String parentAxesId = text.getParentAxes();
Axes parentAxes = (Axes) GraphicController.getController().getObjectFromId(parentAxesId);
+        double[][] factors = parentAxes.getScaleTranslateFactors();
+        Double[] pos = text.getPosition();
+        pos[0] = pos[0] * factors[0][0] + factors[1][0];
+        pos[1] = pos[1] * factors[0][1] + factors[1][1];
+        pos[2] = pos[2] * factors[0][2] + factors[1][2];
+
+        Vector3d textPosition = new Vector3d(pos);

/* Compute the text box vectors and the text box to texture dimension ratios */
Vector3d[] textBoxVectors =  computeTextBoxVectors(projection, text, texture.getDataProvider().getTextureSize(), parentAxes);
@@ -142,8 +147,14 @@ public class TextManager {

Vector3d[] textBoxVectors = new Vector3d[2];

+        double[][] factors = parentAxes.getScaleTranslateFactors();
+        Double[] pos = text.getPosition();
+        pos[0] = pos[0] * factors[0][0] + factors[1][0];
+        pos[1] = pos[1] * factors[0][1] + factors[1][1];
+        pos[2] = pos[2] * factors[0][2] + factors[1][2];
+
/* The text position vector before logarithmic scaling */
-        Vector3d unscaledTextPosition = new Vector3d(text.getPosition());
+        Vector3d unscaledTextPosition = new Vector3d(pos);

boolean[] logFlags = new boolean[] {parentAxes.getXAxisLogFlag(), parentAxes.getYAxisLogFlag(), parentAxes.getZAxisLogFlag()};

@@ -272,16 +283,20 @@ public class TextManager {
protected Vector3d[] computeTextPosition(Transformation projection, Text text, Vector3d[] textBoxVectors, Dimension spriteDim) throws DegenerateMatrixException {
Vector3d[] cornerPositions = new Vector3d[2];

-        Vector3d textPosition = new Vector3d(text.getPosition());
-
String parentAxesId = text.getParentAxes();
Axes parentAxes = (Axes) GraphicController.getController().getObjectFromId(parentAxesId);
+        double[][] factors = parentAxes.getScaleTranslateFactors();
+        Double[] pos = text.getPosition();
+        pos[0] = pos[0] * factors[0][0] + factors[1][0];
+        pos[1] = pos[1] * factors[0][1] + factors[1][1];
+        pos[2] = pos[2] * factors[0][2] + factors[1][2];
+
+        Vector3d textPosition = new Vector3d(pos);

/* Apply logarithmic scaling */
boolean[] logFlags = new boolean[] {parentAxes.getXAxisLogFlag(), parentAxes.getYAxisLogFlag(), parentAxes.getZAxisLogFlag()};
textPosition = ScaleUtils.applyLogScale(textPosition, logFlags);

-
textPosition = projection.project(textPosition);

cornerPositions[0] = new Vector3d(textPosition);
@@ -620,6 +635,20 @@ public class TextManager {
Vector3d[] corners = currentVisitor.getTextManager().computeCorners(currentProj, projCorners, parentAxes);
Double[] coordinates = currentVisitor.getTextManager().cornersToCoordinateArray(corners);

+            double[][] factors = parentAxes.getScaleTranslateFactors();
+            coordinates[0] = (coordinates[0] - factors[1][0]) / factors[0][0];
+            coordinates[1] = (coordinates[1] - factors[1][1]) / factors[0][1];
+            coordinates[2] = (coordinates[2] - factors[1][2]) / factors[0][2];
+            coordinates[3] = (coordinates[3] - factors[1][0]) / factors[0][0];
+            coordinates[4] = (coordinates[4] - factors[1][1]) / factors[0][1];
+            coordinates[5] = (coordinates[5] - factors[1][2]) / factors[0][2];
+            coordinates[6] = (coordinates[6] - factors[1][0]) / factors[0][0];
+            coordinates[7] = (coordinates[7] - factors[1][1]) / factors[0][1];
+            coordinates[8] = (coordinates[8] - factors[1][2]) / factors[0][2];
+            coordinates[9] = (coordinates[9] - factors[1][0]) / factors[0][0];
+            coordinates[10] = (coordinates[10] - factors[1][1]) / factors[0][1];
+            coordinates[11] = (coordinates[11] - factors[1][2]) / factors[0][2];
+
/* Set the computed coordinates */
text.setCorners(coordinates);