package org.geogebra.common.kernel.algos;
import org.geogebra.common.geogebra3D.kernel3D.geos.GeoVec4D;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.Kernel;
import org.geogebra.common.kernel.arithmetic.NumberValue;
import org.geogebra.common.kernel.arithmetic.VectorNDValue;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoPoint;
import org.geogebra.common.kernel.geos.GeoVec3D;
import org.geogebra.common.kernel.geos.GeoVector;
import org.geogebra.common.kernel.kernelND.GeoPointND;
import org.geogebra.common.kernel.kernelND.GeoVectorND;
import org.geogebra.common.plugin.GeoClass;
import org.geogebra.common.plugin.Operation;
import org.geogebra.common.util.debug.Log;
/**
* Helper for Sum/Product when points or vectors are involved
*/
public class PointNDFold implements FoldComputer {
private GeoElement result;
private double x, y, z;
@Override
public GeoElement getTemplate(Construction cons, GeoClass listElement) {
return this.result = doGetTemplate(cons, listElement);
}
private static GeoElement doGetTemplate(Construction cons,
GeoClass listElement) {
switch (listElement) {
case POINT:
return new GeoPoint(cons);
case POINT3D:
return (GeoElement) cons.getKernel().getGeoFactory().newPoint(3,
cons);
case VECTOR:
return new GeoVector(cons);
case VECTOR3D:
return (GeoElement) cons.getKernel().getGeoFactory().newPoint(3,
cons);
}
return new GeoPoint(cons);
}
@Override
public void add(GeoElement p, Operation op) {
if (op == Operation.MULTIPLY) {
double x0 = x;
if (p instanceof GeoPoint) {
((GeoPoint) p).updateCoords();
x = x0 * ((GeoPoint) p).getInhomX()
- y * ((GeoPoint) p).getInhomY();
y = y * ((GeoPoint) p).getInhomX()
+ x0 * ((GeoPoint) p).getInhomY();
Log.debug(x + "," + y);
} else if (p instanceof GeoVector) {
double[] coords = ((GeoVectorND) p).getInhomCoords();
x = x0 * coords[0] - y * coords[1];
y = y * coords[0] + x0 * coords[1];
} else {
x = Double.NaN;
}
return;
}
if (p instanceof GeoPoint) {
x += ((GeoPoint) p).getInhomX();
y += ((GeoPoint) p).getInhomY();
} else if (p instanceof GeoPointND) { // 3D
double[] coords = new double[3];
((GeoPointND) p).getInhomCoords(coords);
x += coords[0];
y += coords[1];
z += coords[2];
} else if (p.isGeoVector()) {
double[] coords = ((GeoVectorND) p).getInhomCoords();
x += coords[0];
y += coords[1];
if (coords.length == 3) {
z += coords[2];
}
} else if (p instanceof NumberValue) {
// changed from GeoGebra 4.2 so that Sum[{(1,2),3}] gives (4,5)
// not (4,2)
// to be consistent with the CAS View
double val = ((NumberValue) p).getDouble();
x += val;
y += val;
z += val;
} else {
result.setUndefined();
return;
}
}
@Override
public void setFrom(GeoElement geoElement, Kernel kernel) {
x = 0;
y = 0;
z = 0;
add(geoElement, Operation.PLUS);
}
@Override
public boolean check(GeoElement geoElement) {
return geoElement instanceof VectorNDValue;
}
@Override
public void finish() {
if (result instanceof GeoVec3D) {
// 2D Point / Vector
((GeoVec3D) result).setCoords(x, y, 1.0);
} else if (result instanceof GeoVec4D) {
// 3D Point / Vector
((GeoVec4D) result).setCoords(x, y, z, 1.0);
}
}
}