package org.geogebra.common.kernel.algos;
import org.geogebra.common.kernel.geos.GeoConic;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoLine;
import org.geogebra.common.kernel.geos.GeoPoint;
import org.geogebra.common.kernel.kernelND.GeoConicND;
import org.geogebra.common.kernel.kernelND.GeoElementND;
import org.geogebra.common.kernel.kernelND.GeoLineND;
import org.geogebra.common.kernel.kernelND.GeoPointND;
import org.geogebra.common.kernel.prover.NoSymbolicParametersException;
import org.geogebra.common.kernel.prover.polynomial.PPolynomial;
import org.geogebra.common.kernel.prover.polynomial.PVariable;
import org.geogebra.common.util.debug.Log;
public class MirrorBotana {
private PPolynomial[] botanaPolynomials;
private PVariable[] botanaVars;
public PPolynomial[] getBotanaPolynomials(GeoElementND geo, GeoElement inGeo,
GeoLineND mirrorLine, GeoPointND mirrorPoint,
GeoConicND mirrorCircle) throws NoSymbolicParametersException {
if (botanaPolynomials != null) {
return botanaPolynomials;
}
if (mirrorLine instanceof GeoLine) {
GeoPoint P;
// if we want to mirror a line to a line
if (inGeo.isGeoLine()) {
/* It's possible that inGeo already has Botana vars. */
PVariable[] inGeoVars = ((GeoLine) inGeo).getBotanaVars(inGeo);
PVariable[] mirrorLineVars = ((GeoLine) mirrorLine)
.getBotanaVars(mirrorLine);
if (inGeoVars != null && mirrorLineVars != null) {
if (botanaVars == null) {
botanaVars = new PVariable[8];
// P' - mirror of P
botanaVars[0] = new PVariable(geo.getKernel());
botanaVars[1] = new PVariable(geo.getKernel());
// Q' - mirror of Q
botanaVars[2] = new PVariable(geo.getKernel());
botanaVars[3] = new PVariable(geo.getKernel());
// V1 - auxiliary point
botanaVars[4] = new PVariable(geo.getKernel());
botanaVars[5] = new PVariable(geo.getKernel());
// V2 - auxiliary point
botanaVars[6] = new PVariable(geo.getKernel());
botanaVars[7] = new PVariable(geo.getKernel());
}
botanaPolynomials = new PPolynomial[8];
// first we want to mirror P to line l
PPolynomial p1 = new PPolynomial(inGeoVars[0]);
PPolynomial p2 = new PPolynomial(inGeoVars[1]);
PPolynomial v1_1 = new PPolynomial(botanaVars[4]);
PPolynomial v1_2 = new PPolynomial(botanaVars[5]);
PPolynomial p_1 = new PPolynomial(botanaVars[0]);
PPolynomial p_2 = new PPolynomial(botanaVars[1]);
// PV1 = V1P'
botanaPolynomials[0] = v1_1.multiply(new PPolynomial(2))
.subtract(p1).subtract(p_1);
botanaPolynomials[1] = v1_2.multiply(new PPolynomial(2))
.subtract(p2).subtract(p_2);
PVariable[] A = new PVariable[2];
// A - start point of mirrorLine
A[0] = mirrorLineVars[0];
A[1] = mirrorLineVars[1];
PVariable[] B = new PVariable[2];
// B - end point of mirrorLine
B[0] = mirrorLineVars[2];
B[1] = mirrorLineVars[3];
// A, V1, B collinear
botanaPolynomials[2] = PPolynomial.collinear(A[0], A[1],
botanaVars[4], botanaVars[5], B[0], B[1]);
// PV1 orthogonal AB
botanaPolynomials[3] = PPolynomial.perpendicular(
inGeoVars[0], inGeoVars[1], botanaVars[4],
botanaVars[5], A[0], A[1], B[0], B[1]);
// second we want to mirror Q to the mirrorLine
PPolynomial q1 = new PPolynomial(inGeoVars[2]);
PPolynomial q2 = new PPolynomial(inGeoVars[3]);
PPolynomial v2_1 = new PPolynomial(botanaVars[6]);
PPolynomial v2_2 = new PPolynomial(botanaVars[7]);
PPolynomial q_1 = new PPolynomial(botanaVars[2]);
PPolynomial q_2 = new PPolynomial(botanaVars[3]);
// QV2 = V2Q'
botanaPolynomials[4] = v2_1.multiply(new PPolynomial(2))
.subtract(q1).subtract(q_1);
botanaPolynomials[5] = v2_2.multiply(new PPolynomial(2))
.subtract(q2).subtract(q_2);
// A, V2, B collinear
botanaPolynomials[6] = PPolynomial.collinear(A[0], A[1],
botanaVars[6], botanaVars[7], B[0], B[1]);
// QV2 orthogonal AB
botanaPolynomials[7] = PPolynomial.perpendicular(
inGeoVars[2], inGeoVars[3], botanaVars[6],
botanaVars[7], A[0], A[1], B[0], B[1]);
return botanaPolynomials;
}
throw new NoSymbolicParametersException();
}
// we want to mirror a point to a line
else if (inGeo.isGeoPoint()) {
P = (GeoPoint) inGeo;
GeoLine l = (GeoLine) mirrorLine;
PVariable[] vP = P.getBotanaVars(P);
PVariable[] vL = l.getBotanaVars(l);
if (botanaVars == null) {
botanaVars = new PVariable[6];
// C'
botanaVars[0] = new PVariable(geo.getKernel());
botanaVars[1] = new PVariable(geo.getKernel());
// V
botanaVars[2] = new PVariable(geo.getKernel());
botanaVars[3] = new PVariable(geo.getKernel());
// N
botanaVars[4] = new PVariable(geo.getKernel());
botanaVars[5] = new PVariable(geo.getKernel());
}
botanaPolynomials = new PPolynomial[6];
PPolynomial v1 = new PPolynomial(botanaVars[2]);
PPolynomial v2 = new PPolynomial(botanaVars[3]);
PPolynomial c1 = new PPolynomial(vP[0]);
PPolynomial c2 = new PPolynomial(vP[1]);
PPolynomial c_1 = new PPolynomial(botanaVars[0]);
PPolynomial c_2 = new PPolynomial(botanaVars[1]);
// CV = VC'
botanaPolynomials[0] = v1.multiply(new PPolynomial(2))
.subtract(c_1).subtract(c1);
botanaPolynomials[1] = v2.multiply(new PPolynomial(2))
.subtract(c_2).subtract(c2);
// points of mirrorLine
PVariable[] A = new PVariable[2];
A[0] = vL[0];
A[1] = vL[1];
PVariable[] B = new PVariable[2];
B[0] = vL[2];
B[1] = vL[3];
// A,V,B collinear
botanaPolynomials[2] = PPolynomial.collinear(A[0], A[1],
B[0], B[1], botanaVars[2], botanaVars[3]);
PPolynomial a1 = new PPolynomial(A[0]);
PPolynomial a2 = new PPolynomial(A[1]);
PPolynomial b1 = new PPolynomial(B[0]);
PPolynomial b2 = new PPolynomial(B[1]);
PPolynomial n1 = new PPolynomial(botanaVars[4]);
PPolynomial n2 = new PPolynomial(botanaVars[5]);
// CV orthogonal AB
botanaPolynomials[3] = b1.subtract(a1).add(c2).subtract(n2);
botanaPolynomials[4] = c1.subtract(b2).add(a2).subtract(n1);
// C',N,V collinear
botanaPolynomials[5] = PPolynomial.collinear(botanaVars[0],
botanaVars[1], botanaVars[2], botanaVars[3],
botanaVars[4], botanaVars[5]);
return botanaPolynomials;
}
// mirror circle to line
else if (inGeo.isGeoConic() && ((GeoConic) inGeo).isCircle()) {
GeoConic circle = (GeoConic) inGeo;
GeoLine l = (GeoLine) mirrorLine;
PVariable[] vCircle = circle.getBotanaVars(circle);
PVariable[] vl = l.getBotanaVars(l);
if (botanaVars == null) {
botanaVars = new PVariable[12];
// A' - mirror of center
botanaVars[0] = new PVariable(geo.getKernel());
botanaVars[1] = new PVariable(geo.getKernel());
// B' - mirror of point on circle
botanaVars[2] = new PVariable(geo.getKernel());
botanaVars[3] = new PVariable(geo.getKernel());
// V - midpoint of center and mirror of center
botanaVars[4] = new PVariable(geo.getKernel());
botanaVars[5] = new PVariable(geo.getKernel());
// T - midpoint of point on circle and mirror of point
// on circle
botanaVars[6] = new PVariable(geo.getKernel());
botanaVars[7] = new PVariable(geo.getKernel());
// N1 - AN1 orthogonal CD
botanaVars[8] = new PVariable(geo.getKernel());
botanaVars[9] = new PVariable(geo.getKernel());
// N2 - BN2 orthogonal CD
botanaVars[10] = new PVariable(geo.getKernel());
botanaVars[11] = new PVariable(geo.getKernel());
}
botanaPolynomials = new PPolynomial[12];
PPolynomial v1 = new PPolynomial(botanaVars[4]);
PPolynomial v2 = new PPolynomial(botanaVars[5]);
PPolynomial a1 = new PPolynomial(vCircle[0]);
PPolynomial a2 = new PPolynomial(vCircle[1]);
PPolynomial a_1 = new PPolynomial(botanaVars[0]);
PPolynomial a_2 = new PPolynomial(botanaVars[1]);
// AV = VA'
botanaPolynomials[0] = v1.multiply(new PPolynomial(2))
.subtract(a_1).subtract(a1);
botanaPolynomials[1] = v2.multiply(new PPolynomial(2))
.subtract(a_2).subtract(a2);
// C, V, D collinear
botanaPolynomials[2] = PPolynomial.collinear(vl[0], vl[1],
botanaVars[4], botanaVars[5], vl[2], vl[3]);
PPolynomial c1 = new PPolynomial(vl[0]);
PPolynomial c2 = new PPolynomial(vl[1]);
PPolynomial d1 = new PPolynomial(vl[2]);
PPolynomial d2 = new PPolynomial(vl[3]);
PPolynomial n1_1 = new PPolynomial(botanaVars[8]);
PPolynomial n1_2 = new PPolynomial(botanaVars[9]);
// AV orthogonal CD
botanaPolynomials[3] = d1.subtract(c1).add(a2)
.subtract(n1_2);
botanaPolynomials[4] = a1.subtract(d2).add(c2)
.subtract(n1_1);
// A', V, N1 collinear
botanaPolynomials[5] = PPolynomial.collinear(botanaVars[0],
botanaVars[1], botanaVars[4], botanaVars[5],
botanaVars[8], botanaVars[9]);
PPolynomial t1 = new PPolynomial(botanaVars[6]);
PPolynomial t2 = new PPolynomial(botanaVars[7]);
PPolynomial b1 = new PPolynomial(vCircle[2]);
PPolynomial b2 = new PPolynomial(vCircle[3]);
PPolynomial b_1 = new PPolynomial(botanaVars[2]);
PPolynomial b_2 = new PPolynomial(botanaVars[3]);
// BT = TB'
botanaPolynomials[6] = t1.multiply(new PPolynomial(2))
.subtract(b_1).subtract(b1);
botanaPolynomials[7] = t2.multiply(new PPolynomial(2))
.subtract(b_2).subtract(b2);
// C, T, D collinear
botanaPolynomials[8] = PPolynomial.collinear(vl[0], vl[1],
botanaVars[6], botanaVars[7], vl[2], vl[3]);
PPolynomial n2_1 = new PPolynomial(botanaVars[10]);
PPolynomial n2_2 = new PPolynomial(botanaVars[11]);
// BT orthogonal CD
botanaPolynomials[9] = d1.subtract(c1).add(b2)
.subtract(n2_2);
botanaPolynomials[10] = b1.subtract(d2).add(c2)
.subtract(n2_1);
// B', T, N2 collinear
botanaPolynomials[11] = PPolynomial.collinear(botanaVars[1],
botanaVars[2], botanaVars[6], botanaVars[7],
botanaVars[10], botanaVars[11]);
return botanaPolynomials;
}
// mirror parabola about line
else if (inGeo.isGeoConic() && ((GeoConic) inGeo).isParabola()) {
GeoConic parabola = (GeoConic) inGeo;
GeoLine l = (GeoLine) mirrorLine;
PVariable[] vparabola = parabola.getBotanaVars(parabola);
PVariable[] vl = l.getBotanaVars(l);
if (botanaVars == null) {
botanaVars = new PVariable[22];
// P' - point at parabola
botanaVars[0] = new PVariable(geo.getKernel());
botanaVars[1] = new PVariable(geo.getKernel());
// T' - projection of P' at directirx
botanaVars[2] = new PVariable(geo.getKernel());
botanaVars[3] = new PVariable(geo.getKernel());
// A' - mirror of star point of directrix
botanaVars[4] = new PVariable(geo.getKernel());
botanaVars[5] = new PVariable(geo.getKernel());
// B' - mirror of end point of directrix
botanaVars[6] = new PVariable(geo.getKernel());
botanaVars[7] = new PVariable(geo.getKernel());
// F' - mirror of focus point
botanaVars[8] = new PVariable(geo.getKernel());
botanaVars[9] = new PVariable(geo.getKernel());
// V1 - midpoint of AA'
botanaVars[10] = new PVariable(geo.getKernel());
botanaVars[11] = new PVariable(geo.getKernel());
// V2 - midpoint of BB'
botanaVars[12] = new PVariable(geo.getKernel());
botanaVars[13] = new PVariable(geo.getKernel());
// V3 - midpoint of CC'
botanaVars[14] = new PVariable(geo.getKernel());
botanaVars[15] = new PVariable(geo.getKernel());
// N1 - AN1 orthogonal M1M2 (mirror line)
botanaVars[16] = new PVariable(geo.getKernel());
botanaVars[17] = new PVariable(geo.getKernel());
// N2 - BN2 orthogonal M1M2
botanaVars[18] = new PVariable(geo.getKernel());
botanaVars[19] = new PVariable(geo.getKernel());
// N3 - CN3 orthogonal M1M2
botanaVars[20] = new PVariable(geo.getKernel());
botanaVars[21] = new PVariable(geo.getKernel());
}
botanaPolynomials = new PPolynomial[21];
PPolynomial a1 = new PPolynomial(vparabola[4]);
PPolynomial a2 = new PPolynomial(vparabola[5]);
PPolynomial v1_1 = new PPolynomial(botanaVars[10]);
PPolynomial v1_2 = new PPolynomial(botanaVars[11]);
PPolynomial a_1 = new PPolynomial(botanaVars[4]);
PPolynomial a_2 = new PPolynomial(botanaVars[5]);
PPolynomial n1_1 = new PPolynomial(botanaVars[16]);
PPolynomial n1_2 = new PPolynomial(botanaVars[17]);
PPolynomial m1_1 = new PPolynomial(vl[0]);
PPolynomial m1_2 = new PPolynomial(vl[1]);
PPolynomial m2_1 = new PPolynomial(vl[2]);
PPolynomial m2_2 = new PPolynomial(vl[3]);
// 6 equations to define A'
// AV1 = V1A'
botanaPolynomials[0] = new PPolynomial(2).multiply(v1_1)
.subtract(a1).subtract(a_1);
botanaPolynomials[1] = new PPolynomial(2).multiply(v1_2)
.subtract(a2).subtract(a_2);
// A', V1, N1 collinear
botanaPolynomials[2] = PPolynomial.collinear(botanaVars[4],
botanaVars[5], botanaVars[10], botanaVars[11],
botanaVars[16], botanaVars[17]);
// M1, V1, M2 collinear
botanaPolynomials[3] = PPolynomial.collinear(vl[0], vl[1],
botanaVars[10], botanaVars[11], vl[2], vl[3]);
// AN1 orthogonal M1M2
botanaPolynomials[4] = m2_1.subtract(m1_1).add(a2)
.subtract(n1_2);
botanaPolynomials[5] = a1.subtract(m2_2).add(m1_2)
.subtract(n1_1);
PPolynomial b1 = new PPolynomial(vparabola[6]);
PPolynomial b2 = new PPolynomial(vparabola[7]);
PPolynomial v2_1 = new PPolynomial(botanaVars[12]);
PPolynomial v2_2 = new PPolynomial(botanaVars[13]);
PPolynomial b_1 = new PPolynomial(botanaVars[6]);
PPolynomial b_2 = new PPolynomial(botanaVars[7]);
PPolynomial n2_1 = new PPolynomial(botanaVars[18]);
PPolynomial n2_2 = new PPolynomial(botanaVars[19]);
// 6 equations to deifne B'
// BV2 = V2B'
botanaPolynomials[6] = new PPolynomial(2).multiply(v2_1)
.subtract(b1).subtract(b_1);
botanaPolynomials[7] = new PPolynomial(2).multiply(v2_2)
.subtract(b2).subtract(b_2);
// B', V2, N2 collinear
botanaPolynomials[8] = PPolynomial.collinear(botanaVars[6],
botanaVars[7], botanaVars[12], botanaVars[13],
botanaVars[18], botanaVars[19]);
// M1, V2, M2 collinear
botanaPolynomials[9] = PPolynomial.collinear(vl[0], vl[1],
botanaVars[12], botanaVars[13], vl[2], vl[3]);
// BN2 orthogonal M1M2
botanaPolynomials[10] = m2_1.subtract(m1_1).add(b2)
.subtract(n2_2);
botanaPolynomials[11] = b1.subtract(m2_2).add(m1_2)
.subtract(n2_1);
PPolynomial f1 = new PPolynomial(vparabola[8]);
PPolynomial f2 = new PPolynomial(vparabola[9]);
PPolynomial v3_1 = new PPolynomial(botanaVars[14]);
PPolynomial v3_2 = new PPolynomial(botanaVars[15]);
PPolynomial f_1 = new PPolynomial(botanaVars[8]);
PPolynomial f_2 = new PPolynomial(botanaVars[9]);
PPolynomial n3_1 = new PPolynomial(botanaVars[20]);
PPolynomial n3_2 = new PPolynomial(botanaVars[21]);
// 6 equations to define F'
// FV3 = V3F'
botanaPolynomials[12] = new PPolynomial(2).multiply(v3_1)
.subtract(f1).subtract(f_1);
botanaPolynomials[13] = new PPolynomial(2).multiply(v3_2)
.subtract(f2).subtract(f_2);
// F', V3, N3 collinear
botanaPolynomials[14] = PPolynomial.collinear(botanaVars[8],
botanaVars[9], botanaVars[14], botanaVars[15],
botanaVars[20], botanaVars[21]);
// M1, V3, M2 collinear
botanaPolynomials[15] = PPolynomial.collinear(vl[0], vl[1],
botanaVars[14], botanaVars[15], vl[2], vl[3]);
// FN3 orthogonal M1M2
botanaPolynomials[16] = m2_1.subtract(m1_1).add(f2)
.subtract(n3_2);
botanaPolynomials[17] = f1.subtract(m2_2).add(m1_2)
.subtract(n3_1);
// 3 equations to define parabola
// |F'P'| = |P'T'|
botanaPolynomials[18] = PPolynomial.equidistant(
botanaVars[8], botanaVars[9], botanaVars[0],
botanaVars[1], botanaVars[2], botanaVars[3]);
// A', T', B' collinear
botanaPolynomials[19] = PPolynomial.collinear(botanaVars[4],
botanaVars[5], botanaVars[2], botanaVars[3],
botanaVars[6], botanaVars[7]);
// P'T' orthogonal A'B'
botanaPolynomials[20] = PPolynomial.perpendicular(
botanaVars[0], botanaVars[1], botanaVars[2],
botanaVars[3], botanaVars[4], botanaVars[5],
botanaVars[6], botanaVars[7]);
// 2 more equation for F' and T'
// |FP|^2 = |F'P'|^2
// botanaPolynomials[21] = Polynomial.sqrDistance(
// vparabola[8], vparabola[9], vparabola[0],
// vparabola[1]).subtract(
// Polynomial
// .sqrDistance(botanaVars[8], botanaVars[9],
// botanaVars[0], botanaVars[1]));
// |PT|^2 = |P'T'|^2
// botanaPolynomials[22] = Polynomial.sqrDistance(
// vparabola[0], vparabola[1], vparabola[2],
// vparabola[3]).subtract(
// Polynomial
// .sqrDistance(botanaVars[0], botanaVars[1],
// botanaVars[2], botanaVars[3]));
return botanaPolynomials;
}
// invalid object to reflect about line
throw new NoSymbolicParametersException();
}
// case mirroring GeoElement about point
else if (mirrorPoint instanceof GeoPoint) {
// mirror point about point
if (inGeo.isGeoPoint()) {
GeoPoint P1 = (GeoPoint) inGeo;
GeoPoint P2 = (GeoPoint) mirrorPoint;
PVariable[] vP1 = P1.getBotanaVars(P1);
PVariable[] vP2 = P2.getBotanaVars(P2);
if (botanaVars == null) {
botanaVars = new PVariable[2];
// A' - mirror of point
botanaVars[0] = new PVariable(geo.getKernel());
botanaVars[1] = new PVariable(geo.getKernel());
}
botanaPolynomials = new PPolynomial[2];
PPolynomial a1 = new PPolynomial(vP1[0]);
PPolynomial a2 = new PPolynomial(vP1[1]);
PPolynomial b1 = new PPolynomial(vP2[0]);
PPolynomial b2 = new PPolynomial(vP2[1]);
PPolynomial a_1 = new PPolynomial(botanaVars[0]);
PPolynomial a_2 = new PPolynomial(botanaVars[1]);
// AB vector = BA' vector
botanaPolynomials[0] = b1.multiply(new PPolynomial(2))
.subtract(a1).subtract(a_1);
botanaPolynomials[1] = b2.multiply(new PPolynomial(2))
.subtract(a2).subtract(a_2);
return botanaPolynomials;
}
// mirror line about point
else if (inGeo.isGeoLine()) {
GeoLine l = (GeoLine) inGeo;
GeoPoint P = (GeoPoint) mirrorPoint;
PVariable[] vl = l.getBotanaVars(l);
PVariable[] vP = P.getBotanaVars(P);
if (botanaVars == null) {
botanaVars = new PVariable[4];
// A' - mirror of start point
botanaVars[0] = new PVariable(geo.getKernel());
botanaVars[1] = new PVariable(geo.getKernel());
// B' - mirror of end point
botanaVars[2] = new PVariable(geo.getKernel());
botanaVars[3] = new PVariable(geo.getKernel());
}
botanaPolynomials = new PPolynomial[4];
PPolynomial p1 = new PPolynomial(vP[0]);
PPolynomial p2 = new PPolynomial(vP[1]);
PPolynomial a1 = new PPolynomial(vl[0]);
PPolynomial a2 = new PPolynomial(vl[1]);
PPolynomial a_1 = new PPolynomial(botanaVars[0]);
PPolynomial a_2 = new PPolynomial(botanaVars[1]);
PPolynomial b1 = new PPolynomial(vl[2]);
PPolynomial b2 = new PPolynomial(vl[3]);
PPolynomial b_1 = new PPolynomial(botanaVars[2]);
PPolynomial b_2 = new PPolynomial(botanaVars[3]);
// AP vector = PA' vector
botanaPolynomials[0] = p1.subtract(a1)
.subtract(a_1.subtract(p1));
botanaPolynomials[1] = p2.subtract(a2)
.subtract(a_2.subtract(p2));
// BP vector = PB' vector
botanaPolynomials[2] = p1.subtract(b1)
.subtract(b_1.subtract(p1));
botanaPolynomials[3] = p2.subtract(b2)
.subtract(b_2.subtract(p2));
return botanaPolynomials;
}
// mirror circle about point
else if (inGeo.isGeoConic() && ((GeoConic) inGeo).isCircle()) {
GeoConic circle = (GeoConic) inGeo;
GeoPoint P = (GeoPoint) mirrorPoint;
PVariable[] vCircle = circle.getBotanaVars(circle);
PVariable[] vP = P.getBotanaVars(P);
if (botanaVars == null) {
botanaVars = new PVariable[4];
// A' - mirror of center
botanaVars[0] = new PVariable(geo.getKernel());
botanaVars[1] = new PVariable(geo.getKernel());
// B' - mirror of point on the circle
botanaVars[2] = new PVariable(geo.getKernel());
botanaVars[3] = new PVariable(geo.getKernel());
}
botanaPolynomials = new PPolynomial[4];
PPolynomial p1 = new PPolynomial(vP[0]);
PPolynomial p2 = new PPolynomial(vP[1]);
PPolynomial a1 = new PPolynomial(vCircle[0]);
PPolynomial a2 = new PPolynomial(vCircle[1]);
PPolynomial a_1 = new PPolynomial(botanaVars[0]);
PPolynomial a_2 = new PPolynomial(botanaVars[1]);
PPolynomial b1 = new PPolynomial(vCircle[2]);
PPolynomial b2 = new PPolynomial(vCircle[3]);
PPolynomial b_1 = new PPolynomial(botanaVars[2]);
PPolynomial b_2 = new PPolynomial(botanaVars[3]);
// AP vector = PA' vector
botanaPolynomials[0] = p1.subtract(a1)
.subtract(a_1.subtract(p1));
botanaPolynomials[1] = p2.subtract(a2)
.subtract(a_2.subtract(p2));
// BP vector = PB' vector
botanaPolynomials[2] = p1.subtract(b1)
.subtract(b_1.subtract(p1));
botanaPolynomials[3] = p2.subtract(b2)
.subtract(b_2.subtract(p2));
return botanaPolynomials;
}
// mirror parabola about point
else if (inGeo.isGeoConic() && ((GeoConic) inGeo).isParabola()) {
GeoConic parabola = (GeoConic) inGeo;
GeoPoint P = (GeoPoint) mirrorPoint;
PVariable[] vparabola = parabola.getBotanaVars(parabola);
PVariable[] vP = P.getBotanaVars(P);
if (botanaVars == null) {
botanaVars = new PVariable[10];
// P' - mirror of point on parabola
botanaVars[0] = new PVariable(geo.getKernel());
botanaVars[1] = new PVariable(geo.getKernel());
// T' - mirror of projection point of P' at A'B'
botanaVars[2] = new PVariable(geo.getKernel());
botanaVars[3] = new PVariable(geo.getKernel());
// A' - mirror of start point of directrix
botanaVars[4] = new PVariable(geo.getKernel());
botanaVars[5] = new PVariable(geo.getKernel());
// B' - mirror of end point of directrix
botanaVars[6] = new PVariable(geo.getKernel());
botanaVars[7] = new PVariable(geo.getKernel());
// F' - mirror of focus point
botanaVars[8] = new PVariable(geo.getKernel());
botanaVars[9] = new PVariable(geo.getKernel());
}
botanaPolynomials = new PPolynomial[13];
PPolynomial p1 = new PPolynomial(vparabola[0]);
PPolynomial p2 = new PPolynomial(vparabola[1]);
PPolynomial t1 = new PPolynomial(vparabola[2]);
PPolynomial t2 = new PPolynomial(vparabola[3]);
PPolynomial a1 = new PPolynomial(vparabola[4]);
PPolynomial a2 = new PPolynomial(vparabola[5]);
PPolynomial b1 = new PPolynomial(vparabola[6]);
PPolynomial b2 = new PPolynomial(vparabola[7]);
PPolynomial f1 = new PPolynomial(vparabola[8]);
PPolynomial f2 = new PPolynomial(vparabola[9]);
PPolynomial p_1 = new PPolynomial(botanaVars[0]);
PPolynomial p_2 = new PPolynomial(botanaVars[1]);
PPolynomial t_1 = new PPolynomial(botanaVars[2]);
PPolynomial t_2 = new PPolynomial(botanaVars[3]);
PPolynomial a_1 = new PPolynomial(botanaVars[4]);
PPolynomial a_2 = new PPolynomial(botanaVars[5]);
PPolynomial b_1 = new PPolynomial(botanaVars[6]);
PPolynomial b_2 = new PPolynomial(botanaVars[7]);
PPolynomial f_1 = new PPolynomial(botanaVars[8]);
PPolynomial f_2 = new PPolynomial(botanaVars[9]);
PPolynomial m1 = new PPolynomial(vP[0]);
PPolynomial m2 = new PPolynomial(vP[1]);
// 10 equations for coordinates of mirrored points
// PM vector = MP' vector
botanaPolynomials[0] = new PPolynomial(2).multiply(m1)
.subtract(p1).subtract(p_1);
botanaPolynomials[1] = new PPolynomial(2).multiply(m2)
.subtract(p2).subtract(p_2);
// TM vector = MT' vector
botanaPolynomials[2] = new PPolynomial(2).multiply(m1)
.subtract(t1).subtract(t_1);
botanaPolynomials[3] = new PPolynomial(2).multiply(m2)
.subtract(t2).subtract(t_2);
// AM vector = MA' vector
botanaPolynomials[4] = new PPolynomial(2).multiply(m1)
.subtract(a1).subtract(a_1);
botanaPolynomials[5] = new PPolynomial(2).multiply(m2)
.subtract(a2).subtract(a_2);
// BM vector = MB' vector
botanaPolynomials[6] = new PPolynomial(2).multiply(m1)
.subtract(b1).subtract(b_1);
botanaPolynomials[7] = new PPolynomial(2).multiply(m2)
.subtract(b2).subtract(b_2);
// FM vector = MF' vector
botanaPolynomials[8] = new PPolynomial(2).multiply(m1)
.subtract(f1).subtract(f_1);
botanaPolynomials[9] = new PPolynomial(2).multiply(m2)
.subtract(f2).subtract(f_2);
// 3 equations as definition of mirrored parabola
// |F'P'| = |P'T'|
botanaPolynomials[10] = PPolynomial.equidistant(
botanaVars[8], botanaVars[9], botanaVars[0],
botanaVars[1], botanaVars[2], botanaVars[3]);
// A',T',B' collinear
botanaPolynomials[11] = PPolynomial.collinear(botanaVars[4],
botanaVars[5], botanaVars[2], botanaVars[3],
botanaVars[6], botanaVars[7]);
// P'T' orthogonal A'B'
botanaPolynomials[12] = PPolynomial.perpendicular(
botanaVars[0], botanaVars[1], botanaVars[2],
botanaVars[3], botanaVars[4], botanaVars[5],
botanaVars[6], botanaVars[7]);
return botanaPolynomials;
}
// mirror ellipse about point
else if (inGeo.isGeoConic() && ((GeoConic) inGeo).isEllipse()) {
GeoConic ellipse = (GeoConic) inGeo;
GeoPoint P = (GeoPoint) mirrorPoint;
PVariable[] vellipse = ellipse.getBotanaVars(ellipse);
PVariable[] vP = P.getBotanaVars(P);
// the two focus points are the same
if (vellipse[6] == vellipse[8]
&& vellipse[7] == vellipse[9]) {
// handle ellipse as circle
if (botanaVars == null) {
botanaVars = new PVariable[4];
// A' - mirror of the center point
botanaVars[0] = new PVariable(geo.getKernel());
botanaVars[1] = new PVariable(geo.getKernel());
// C' - mirror of the point at circle
botanaVars[2] = new PVariable(geo.getKernel());
botanaVars[3] = new PVariable(geo.getKernel());
}
botanaPolynomials = new PPolynomial[4];
PPolynomial a1 = new PPolynomial(vellipse[0]);
PPolynomial a2 = new PPolynomial(vellipse[1]);
PPolynomial c1 = new PPolynomial(vellipse[2]);
PPolynomial c2 = new PPolynomial(vellipse[3]);
PPolynomial p1 = new PPolynomial(vP[0]);
PPolynomial p2 = new PPolynomial(vP[1]);
PPolynomial a_1 = new PPolynomial(botanaVars[0]);
PPolynomial a_2 = new PPolynomial(botanaVars[1]);
PPolynomial c_1 = new PPolynomial(botanaVars[2]);
PPolynomial c_2 = new PPolynomial(botanaVars[3]);
// AP vector = PA' vector
botanaPolynomials[0] = new PPolynomial(2).multiply(p1)
.subtract(a1).subtract(a_1);
botanaPolynomials[1] = new PPolynomial(2).multiply(p2)
.subtract(a2).subtract(a_2);
// CP vector = PC' vector
botanaPolynomials[2] = new PPolynomial(2).multiply(p1)
.subtract(c1).subtract(c_1);
botanaPolynomials[3] = new PPolynomial(2).multiply(p2)
.subtract(c2).subtract(c_2);
} else {
if (botanaVars == null) {
botanaVars = new PVariable[12];
// P' - mirror of second point on ellipse
botanaVars[0] = new PVariable(geo.getKernel());
botanaVars[1] = new PVariable(geo.getKernel());
// auxiliary variables
botanaVars[2] = new PVariable(geo.getKernel());
botanaVars[3] = new PVariable(geo.getKernel());
botanaVars[4] = new PVariable(geo.getKernel());
botanaVars[5] = new PVariable(geo.getKernel());
// A' - mirror of first focus point
botanaVars[6] = new PVariable(geo.getKernel());
botanaVars[7] = new PVariable(geo.getKernel());
// B' - mirror of second focus point
botanaVars[8] = new PVariable(geo.getKernel());
botanaVars[9] = new PVariable(geo.getKernel());
// C' - mirror of point on ellipse
botanaVars[10] = new PVariable(geo.getKernel());
botanaVars[11] = new PVariable(geo.getKernel());
}
botanaPolynomials = new PPolynomial[13];
PPolynomial p1 = new PPolynomial(vellipse[0]);
PPolynomial p2 = new PPolynomial(vellipse[1]);
PPolynomial a1 = new PPolynomial(vellipse[6]);
PPolynomial a2 = new PPolynomial(vellipse[7]);
PPolynomial b1 = new PPolynomial(vellipse[8]);
PPolynomial b2 = new PPolynomial(vellipse[9]);
PPolynomial c1 = new PPolynomial(vellipse[10]);
PPolynomial c2 = new PPolynomial(vellipse[11]);
PPolynomial m1 = new PPolynomial(vP[0]);
PPolynomial m2 = new PPolynomial(vP[1]);
PPolynomial p_1 = new PPolynomial(botanaVars[0]);
PPolynomial p_2 = new PPolynomial(botanaVars[1]);
PPolynomial a_1 = new PPolynomial(botanaVars[6]);
PPolynomial a_2 = new PPolynomial(botanaVars[7]);
PPolynomial b_1 = new PPolynomial(botanaVars[8]);
PPolynomial b_2 = new PPolynomial(botanaVars[9]);
PPolynomial c_1 = new PPolynomial(botanaVars[10]);
PPolynomial c_2 = new PPolynomial(botanaVars[11]);
PPolynomial d1 = new PPolynomial(botanaVars[2]);
PPolynomial d2 = new PPolynomial(botanaVars[3]);
PPolynomial e1 = new PPolynomial(botanaVars[4]);
PPolynomial e2 = new PPolynomial(botanaVars[5]);
// 8 equations for coordinates of mirrored points
// PM vector = MP' vector
botanaPolynomials[0] = new PPolynomial(2).multiply(m1)
.subtract(p1).subtract(p_1);
botanaPolynomials[1] = new PPolynomial(2).multiply(m2)
.subtract(p2).subtract(p_2);
// AM vector = MA' vector
botanaPolynomials[2] = new PPolynomial(2).multiply(m1)
.subtract(a1).subtract(a_1);
botanaPolynomials[3] = new PPolynomial(2).multiply(m2)
.subtract(a2).subtract(a_2);
// BM vector = MB' vector
botanaPolynomials[4] = new PPolynomial(2).multiply(m1)
.subtract(b1).subtract(b_1);
botanaPolynomials[5] = new PPolynomial(2).multiply(m2)
.subtract(b2).subtract(b_2);
// CM vector = MC' vector
botanaPolynomials[6] = new PPolynomial(2).multiply(m1)
.subtract(c1).subtract(c_1);
botanaPolynomials[7] = new PPolynomial(2).multiply(m2)
.subtract(c2).subtract(c_2);
// 5 equations as definition of ellipse
// d1+d2 = e1+e2
botanaPolynomials[8] = d1.add(d2).subtract(e1)
.subtract(e2);
// d1^2=Polynomial.sqrDistance(a_1,a_2,c_1,c_2)
botanaPolynomials[9] = PPolynomial
.sqrDistance(botanaVars[6], botanaVars[7],
botanaVars[8], botanaVars[9])
.subtract(d1.multiply(d1));
// d2^2=Polynomial.sqrDistance(b_1,b_2,c_1,c_2)
botanaPolynomials[10] = PPolynomial
.sqrDistance(botanaVars[6], botanaVars[7],
botanaVars[8], botanaVars[9])
.subtract(d2.multiply(d2));
// e1^2=Polynomial.sqrDistance(a_1,a_2,p_1,p_2)
botanaPolynomials[11] = PPolynomial
.sqrDistance(botanaVars[6], botanaVars[7],
botanaVars[0], botanaVars[1])
.subtract(e1.multiply(e1));
// e2^2=Polynomial.sqrDistance(b_1,b_2,p_1,p_2)
botanaPolynomials[12] = PPolynomial
.sqrDistance(botanaVars[8], botanaVars[9],
botanaVars[0], botanaVars[1])
.subtract(e2.multiply(e2));
}
return botanaPolynomials;
}
// mirror hyperbola about point
else if (inGeo.isGeoConic() && ((GeoConic) inGeo).isHyperbola()) {
GeoConic hyperbola = (GeoConic) inGeo;
GeoPoint P = (GeoPoint) mirrorPoint;
PVariable[] vhyperbola = hyperbola.getBotanaVars(hyperbola);
PVariable[] vP = P.getBotanaVars(P);
if (botanaVars == null) {
botanaVars = new PVariable[12];
// P' - mirror of second point at hyperbola
botanaVars[0] = new PVariable(geo.getKernel());
botanaVars[1] = new PVariable(geo.getKernel());
// auxiliary variables
botanaVars[2] = new PVariable(geo.getKernel());
botanaVars[3] = new PVariable(geo.getKernel());
botanaVars[4] = new PVariable(geo.getKernel());
botanaVars[5] = new PVariable(geo.getKernel());
// A' - mirror of first focus point
botanaVars[6] = new PVariable(geo.getKernel());
botanaVars[7] = new PVariable(geo.getKernel());
// B' - mirror of second focus point
botanaVars[8] = new PVariable(geo.getKernel());
botanaVars[9] = new PVariable(geo.getKernel());
// C' - mirror of second point at hyperbola
botanaVars[10] = new PVariable(geo.getKernel());
botanaVars[11] = new PVariable(geo.getKernel());
}
botanaPolynomials = new PPolynomial[13];
PPolynomial p1 = new PPolynomial(vhyperbola[0]);
PPolynomial p2 = new PPolynomial(vhyperbola[1]);
PPolynomial a1 = new PPolynomial(vhyperbola[6]);
PPolynomial a2 = new PPolynomial(vhyperbola[7]);
PPolynomial b1 = new PPolynomial(vhyperbola[8]);
PPolynomial b2 = new PPolynomial(vhyperbola[9]);
PPolynomial c1 = new PPolynomial(vhyperbola[10]);
PPolynomial c2 = new PPolynomial(vhyperbola[11]);
PPolynomial m1 = new PPolynomial(vP[0]);
PPolynomial m2 = new PPolynomial(vP[1]);
PPolynomial p_1 = new PPolynomial(botanaVars[0]);
PPolynomial p_2 = new PPolynomial(botanaVars[1]);
PPolynomial a_1 = new PPolynomial(botanaVars[6]);
PPolynomial a_2 = new PPolynomial(botanaVars[7]);
PPolynomial b_1 = new PPolynomial(botanaVars[8]);
PPolynomial b_2 = new PPolynomial(botanaVars[9]);
PPolynomial c_1 = new PPolynomial(botanaVars[10]);
PPolynomial c_2 = new PPolynomial(botanaVars[11]);
PPolynomial d1 = new PPolynomial(botanaVars[2]);
PPolynomial d2 = new PPolynomial(botanaVars[3]);
PPolynomial e1 = new PPolynomial(botanaVars[4]);
PPolynomial e2 = new PPolynomial(botanaVars[5]);
// 8 equations for mirrored points
// PM vector = MP' vector
botanaPolynomials[0] = new PPolynomial(2).multiply(m1)
.subtract(p1).subtract(p_1);
botanaPolynomials[1] = new PPolynomial(2).multiply(m2)
.subtract(p2).subtract(p_2);
// AM vector = MA' vector
botanaPolynomials[2] = new PPolynomial(2).multiply(m1)
.subtract(a1).subtract(a_1);
botanaPolynomials[3] = new PPolynomial(2).multiply(m2)
.subtract(a2).subtract(a_2);
// BM vector = MB' vector
botanaPolynomials[4] = new PPolynomial(2).multiply(m1)
.subtract(b1).subtract(b_1);
botanaPolynomials[5] = new PPolynomial(2).multiply(m2)
.subtract(b2).subtract(b_2);
// CM vector = MC' vector
botanaPolynomials[6] = new PPolynomial(2).multiply(m1)
.subtract(c1).subtract(c_1);
botanaPolynomials[7] = new PPolynomial(2).multiply(m2)
.subtract(c2).subtract(c_2);
// 5 equations as definition of hyperbola
// d1-d2 = e1-e2
botanaPolynomials[8] = d1.subtract(d2).subtract(e1).add(e2);
// d1^2=Polynomial.sqrDistance(a_1,a_2,c_1,c_2)
botanaPolynomials[9] = PPolynomial
.sqrDistance(botanaVars[6], botanaVars[7],
botanaVars[10], botanaVars[11])
.subtract(d1.multiply(d1));
// d2^2=Polynomial.sqrDistance(b_1,b_2,c_1,c_2)
botanaPolynomials[10] = PPolynomial
.sqrDistance(botanaVars[8], botanaVars[9],
botanaVars[10], botanaVars[11])
.subtract(d2.multiply(d2));
// e1^2=Polynomial.sqrDistance(a_1,a_2,p_1,p_2)
botanaPolynomials[3] = PPolynomial
.sqrDistance(botanaVars[6], botanaVars[7],
botanaVars[0], botanaVars[1])
.subtract(e1.multiply(e1));
// e2^2=Polynomial.sqrDistance(b_1,b_2,p_1,p_2)
botanaPolynomials[4] = PPolynomial
.sqrDistance(botanaVars[8], botanaVars[9],
botanaVars[0], botanaVars[1])
.subtract(e2.multiply(e2));
return botanaPolynomials;
}
// invalid object to reflect about point
throw new NoSymbolicParametersException();
} else if (mirrorCircle instanceof GeoConic) {
// mirror point about circle
if (inGeo.isGeoPoint()) {
GeoPoint P = (GeoPoint) inGeo;
GeoConic c = (GeoConic) mirrorCircle;
PVariable[] vP = P.getBotanaVars(P);
PVariable[] vc = c.getBotanaVars(c);
if (botanaVars == null) {
botanaVars = new PVariable[8];
// B' - mirror of point
botanaVars[0] = new PVariable(geo.getKernel());
botanaVars[1] = new PVariable(geo.getKernel());
// B - point to mirror
botanaVars[2] = vP[0];
botanaVars[3] = vP[1];
// O - center of circle
botanaVars[4] = vc[0];
botanaVars[5] = vc[1];
// A - point on circle
botanaVars[6] = vc[2];
botanaVars[7] = vc[3];
}
botanaPolynomials = new PPolynomial[2];
PPolynomial o1 = new PPolynomial(vc[0]);
PPolynomial o2 = new PPolynomial(vc[1]);
PPolynomial a1 = new PPolynomial(vc[2]);
PPolynomial a2 = new PPolynomial(vc[3]);
PPolynomial b1 = new PPolynomial(vP[0]);
PPolynomial b2 = new PPolynomial(vP[1]);
PPolynomial b_1 = new PPolynomial(botanaVars[0]);
PPolynomial b_2 = new PPolynomial(botanaVars[1]);
// r^2
PPolynomial oa = (a1.subtract(o1)).multiply(a1.subtract(o1))
.add((a2.subtract(o2)).multiply(a2.subtract(o2)));
// (x-x_0)^2 + (y-y_0)^2
PPolynomial denominator = (b1.subtract(o1))
.multiply(b1.subtract(o1))
.add((b2.subtract(o2)).multiply(b2.subtract(o2)));
// formula for the coordinates of inverse point
// from: http://mathworld.wolfram.com/Inversion.html
botanaPolynomials[0] = oa.multiply(b1.subtract(o1))
.add((o1.subtract(b_1)).multiply(denominator));
botanaPolynomials[1] = oa.multiply(b2.subtract(o2))
.add((o2.subtract(b_2)).multiply(denominator));
return botanaPolynomials;
}
// mirror line about circle
else if (inGeo.isGeoLine()) {
Log.debug("mirroring line about circle not implemented");
throw new NoSymbolicParametersException();
}
// mirror circle about circle
else if (inGeo.isGeoConic() && ((GeoConic) inGeo).isCircle()) {
GeoConic circle = (GeoConic) inGeo;
GeoConic mirrorcircle = (GeoConic) mirrorCircle;
PVariable[] vcircle = circle.getBotanaVars(circle);
PVariable[] vmirrorcircle = mirrorcircle
.getBotanaVars(mirrorcircle);
if (botanaVars == null) {
botanaVars = new PVariable[4];
// A' - center of mirrored circle
botanaVars[0] = new PVariable(geo.getKernel());
botanaVars[1] = new PVariable(geo.getKernel());
// B' - mirror of point of circle (B)
botanaVars[2] = new PVariable(geo.getKernel());
botanaVars[3] = new PVariable(geo.getKernel());
}
botanaPolynomials = new PPolynomial[4];
// (A,B) - circle to mirror
PPolynomial a1 = new PPolynomial(vcircle[0]);
PPolynomial a2 = new PPolynomial(vcircle[1]);
PPolynomial b1 = new PPolynomial(vcircle[2]);
PPolynomial b2 = new PPolynomial(vcircle[3]);
// (O,C) - circle to mirror about
PPolynomial o1 = new PPolynomial(vmirrorcircle[0]);
PPolynomial o2 = new PPolynomial(vmirrorcircle[1]);
PPolynomial c1 = new PPolynomial(vmirrorcircle[2]);
PPolynomial c2 = new PPolynomial(vmirrorcircle[3]);
// (A',B') - mirrored circle
PPolynomial a_1 = new PPolynomial(botanaVars[0]);
PPolynomial a_2 = new PPolynomial(botanaVars[1]);
PPolynomial b_1 = new PPolynomial(botanaVars[2]);
PPolynomial b_2 = new PPolynomial(botanaVars[3]);
// k^2 - circle power of (O,C) circle
PPolynomial oc = (c1.subtract(o1)).multiply(c1.subtract(o1))
.add((c2.subtract(o2)).multiply(c2.subtract(o2)));
// a^2 - circle power of (A,B) circle
PPolynomial ab = (b1.subtract(a1)).multiply(b1.subtract(a1))
.add((b2.subtract(a2)).multiply(b2.subtract(a2)));
// (x-x_0)^2 + (y-y_0)^2 - a^2
PPolynomial denominator1 = (a1.subtract(o1))
.multiply(a1.subtract(o1))
.add((a2.subtract(o2)).multiply(a2.subtract(o2)))
.subtract(ab);
// formula for the coordinates of the center of inverse
// circle
// from: http://mathworld.wolfram.com/Inversion.html
botanaPolynomials[0] = oc.multiply(a1.subtract(o1))
.add((o1.subtract(a_1)).multiply(denominator1));
botanaPolynomials[1] = oc.multiply(a2.subtract(o2))
.add((o2.subtract(a_2)).multiply(denominator1));
PPolynomial denominator2 = (b1.subtract(o1))
.multiply(b1.subtract(o1))
.add((b2.subtract(o2)).multiply(b2.subtract(o2)));
// formula for the coordinates of inverse point
// from: http://mathworld.wolfram.com/Inversion.html
botanaPolynomials[2] = oc.multiply(b1.subtract(o1))
.add((o1.subtract(b_1)).multiply(denominator2));
botanaPolynomials[3] = oc.multiply(b2.subtract(o2))
.add((o2.subtract(b_2)).multiply(denominator2));
return botanaPolynomials;
} else {
// invalid object to mirror about circle
throw new NoSymbolicParametersException();
}
} else {
// invalid object to mirror about
throw new NoSymbolicParametersException();
}
}
public PVariable[] getBotanaVars() {
return botanaVars;
}
}