/*GraphUmkreis.java*/

import java.awt.*;

public class GraphUmkreis extends Canvas {
	int breiteX;
	int breiteY;
	double[][] ecke = new double[3][2];
	double[][] seitenMitte = new double[3][2];
	double[][] kreisMittelpunkt = new double[3][2];
	double[] echterUmp = new double[2];
	boolean cavallieriOderNicht = true;
	boolean umpOderNicht = true;
	boolean hilfslinien = false;
	boolean SEITENHALBIERENDE = false;
	boolean MITTELSENKRECHTE = false;
	boolean CAVALIERIHILFE = false;

	Image imageBuffer;
	Graphics graphicsBuffer;

	GraphUmkreis(
		int breiteX,
		int breiteY,
		double a0,
		double a1,
		double b0,
		double b1,
		double c0,
		double c1) {
		this.breiteX = breiteX;
		this.breiteY = breiteY;
		this.ecke[0][0] = a0;
		this.ecke[0][1] = a1;
		this.ecke[1][0] = b0;
		this.ecke[1][1] = b1;
		this.ecke[2][0] = c0;
		this.ecke[2][1] = c1;

		setVisible(true);
	}

	public double abstand(double x0, double x1, double y0, double y1) {
		return (double) Math.sqrt((x0 - y0) * (x0 - y0) + (x1 - y1) * (x1 - y1));
	}

	public double winkel(double x0, double x1, double y0, double y1) {
		double scalarProdukt = x0 * y0 + x1 * y1;
		double betragX = abstand(x0, x1, 0.0, 0.0);
		double betragY = abstand(y0, y1, 0.0, 0.0);
		System.out.println(
			"SP="
				+ scalarProdukt
				+ " SP(norm)="
				+ scalarProdukt / (betragX * betragY)
				+ " BX="
				+ betragX
				+ " BY="
				+ betragY);
		return Math.acos(scalarProdukt / (betragX * betragY));
	}

	double[] kreiseSchnittpunkt(
		double m00,
		double m01,
		double r0,
		double m10,
		double m11,
		double r1) {
		double[] schnittpunkt = new double[2];
		double dist = abstand(m10, m11, m00, m01);
		KoordTrafo kreis = new KoordTrafo(m00, m01, m10 - m00, m11 - m01);
		double linkerRand = dist - r1;
		double rechterRand = r0;
		double x = (linkerRand + rechterRand) / 2;
		double epsilon = 0.001;
		Kreis lk = new Kreis(0, 0, r0);
		Kreis rk = new Kreis(dist, 0, r1);
		KoordTrafo drei =
			new KoordTrafo(
				ecke[1][0],
				ecke[1][1],
				ecke[0][0] - ecke[1][0],
				ecke[0][1] - ecke[1][1]);
		if (drei.trafo(ecke[2][0], ecke[2][1])[1] >= 0) {
			while (Math.abs(lk.mwert(x) - rk.mwert(x))
				> epsilon & Math.abs(linkerRand - rechterRand)
				> epsilon) {
				if (lk.mwert(x) < rk.mwert(x)) {
					linkerRand = x;
					x = (rechterRand + x) / 2;
				} else {
					rechterRand = x;
					x = (linkerRand + x) / 2;
				}
			}
			schnittpunkt[0] = x;
			schnittpunkt[1] = rk.mwert(x);
		} else {
			while (Math.abs(lk.pwert(x) - rk.pwert(x))
				> epsilon & Math.abs(linkerRand - rechterRand)
				> epsilon) {
				if (lk.pwert(x) > rk.pwert(x)) {
					linkerRand = x;
					x = (rechterRand + x) / 2;
				} else {
					rechterRand = x;
					x = (linkerRand + x) / 2;
				}
			}
			schnittpunkt[0] = x;
			schnittpunkt[1] = rk.pwert(x);
		}

		return schnittpunkt;
	}

	double cosGamma(double x0, double x1, double y0, double y1) {
		return (x0 * y0 + x1 * y1)
			/ (Math.sqrt(x0 * x0 + x1 * x1) * Math.sqrt(y0 * y0 + y1 * y1));
	}

	double[] cavallieri() {
		double[] cavallieri = new double[2];
		for (int i = 0; i < 3; i++) {
			if (i != 2) {
				seitenMitte[i][0] = ecke[i][0] + (ecke[i + 1][0] - ecke[i][0]) / 2;
				seitenMitte[i][1] = ecke[i][1] + (ecke[i + 1][1] - ecke[i][1]) / 2;
			} else {
				seitenMitte[i][0] = ecke[i][0] + (ecke[0][0] - ecke[i][0]) / 2;
				seitenMitte[i][1] = ecke[i][1] + (ecke[0][1] - ecke[i][1]) / 2;
			}
		}

		KoordTrafo drei =
			new KoordTrafo(
				ecke[1][0],
				ecke[1][1],
				ecke[0][0] - ecke[1][0],
				ecke[0][1] - ecke[1][1]);
		if (drei.trafo(ecke[2][0], ecke[2][1])[1] >= 0) {
			kreisMittelpunkt[0][0] =
				seitenMitte[0][0] - 0.5773503 * (ecke[1][1] - ecke[0][1]) / 2;
			kreisMittelpunkt[0][1] =
				seitenMitte[0][1] + 0.5773503 * (ecke[1][0] - ecke[0][0]) / 2;
			kreisMittelpunkt[1][0] =
				seitenMitte[1][0] - 0.5773503 * (ecke[2][1] - ecke[1][1]) / 2;
			kreisMittelpunkt[1][1] =
				seitenMitte[1][1] + 0.5773503 * (ecke[2][0] - ecke[1][0]) / 2;
		} else {
			kreisMittelpunkt[0][0] =
				seitenMitte[0][0] + 0.5773503 * (ecke[1][1] - ecke[0][1]) / 2;
			kreisMittelpunkt[0][1] =
				seitenMitte[0][1] - 0.5773503 * (ecke[1][0] - ecke[0][0]) / 2;
			kreisMittelpunkt[1][0] =
				seitenMitte[1][0] + 0.5773503 * (ecke[2][1] - ecke[1][1]) / 2;
			kreisMittelpunkt[1][1] =
				seitenMitte[1][1] - 0.5773503 * (ecke[2][0] - ecke[1][0]) / 2;
		}

		kreisMittelpunkt[2][0] =
			seitenMitte[2][0]
				- Math.tan(30)
					* abstand(ecke[2][0], ecke[2][1], ecke[0][0], ecke[0][1])
					/ 2
					* seitenMitte[2][1];
		kreisMittelpunkt[2][1] =
			seitenMitte[2][1]
				+ Math.tan(30)
					* abstand(ecke[2][0], ecke[2][1], ecke[0][0], ecke[0][1])
					/ 2
					* seitenMitte[2][0];
		double radius1 =
			abstand(
				kreisMittelpunkt[0][0],
				kreisMittelpunkt[0][1],
				ecke[0][0],
				ecke[0][1]);
		double radius2 =
			abstand(
				kreisMittelpunkt[1][0],
				kreisMittelpunkt[1][1],
				ecke[1][0],
				ecke[1][1]);
		KoordTrafo kreis =
			new KoordTrafo(
				kreisMittelpunkt[0][0],
				kreisMittelpunkt[0][1],
				kreisMittelpunkt[1][0] - kreisMittelpunkt[0][0],
				kreisMittelpunkt[1][1] - kreisMittelpunkt[0][1]);
		double[] spAlt = new double[2];
		spAlt[0] =
			kreiseSchnittpunkt(
				kreisMittelpunkt[0][0],
				kreisMittelpunkt[0][1],
				radius1,
				kreisMittelpunkt[1][0],
				kreisMittelpunkt[1][1],
				radius2)[0];
		spAlt[1] =
			kreiseSchnittpunkt(
				kreisMittelpunkt[0][0],
				kreisMittelpunkt[0][1],
				radius1,
				kreisMittelpunkt[1][0],
				kreisMittelpunkt[1][1],
				radius2)[1];
		cavallieri[0] = kreis.ofart(spAlt[0], spAlt[1])[0];
		cavallieri[1] = kreis.ofart(spAlt[0], spAlt[1])[1];

		cavallieriOderNicht = true;
		if (cosGamma(ecke[1][0] - ecke[0][0],
			ecke[1][1] - ecke[0][1],
			ecke[2][0] - ecke[0][0],
			ecke[2][1] - ecke[0][1])
			< -0.5) {
			cavallieri[0] = ecke[0][0];
			cavallieri[1] = ecke[0][1];
			cavallieriOderNicht = false;
		}

		if (cosGamma(ecke[0][0] - ecke[1][0],
			ecke[0][1] - ecke[1][1],
			ecke[2][0] - ecke[1][0],
			ecke[2][1] - ecke[1][1])
			< -0.5) {
			cavallieri[0] = ecke[1][0];
			cavallieri[1] = ecke[1][1];
			cavallieriOderNicht = false;
		}

		if (cosGamma(ecke[0][0] - ecke[2][0],
			ecke[0][1] - ecke[2][1],
			ecke[1][0] - ecke[2][0],
			ecke[1][1] - ecke[2][1])
			< -0.5) {
			cavallieri[0] = ecke[2][0];
			cavallieri[1] = ecke[2][1];
			cavallieriOderNicht = false;
		}

		return cavallieri;
	}

	double[] schwerpunkt() {
		double[] sp = new double[2];
		sp[0] = (ecke[0][0] + ecke[1][0] + ecke[2][0]) / 3;
		sp[1] = (ecke[0][1] + ecke[1][1] + ecke[2][1]) / 3;
		return sp;
	}

	double[] geradenSchnittpunkt(
		double a0,
		double a1,
		double b0,
		double b1,
		double c0,
		double c1,
		double d0,
		double d1) {
		double[] sp = new double[2];
		double lambda = ((c0 - a0) * d1 - (c1 - a1) * d0) / (d1 * b0 - d0 * b1);
		sp[0] = a0 + lambda * b0;
		sp[1] = a1 + lambda * b1;
		return sp;
	}

	double[] umkreismittelpunkt() {
		double[] ump = new double[2];
		ump[0] =
			geradenSchnittpunkt(
				seitenMitte[0][0],
				seitenMitte[0][1],
				-ecke[1][1] + ecke[0][1],
				ecke[1][0] - ecke[0][0],
				seitenMitte[1][0],
				seitenMitte[1][1],
				-ecke[2][1] + ecke[1][1],
				ecke[2][0] - ecke[1][0])[0];
		ump[1] =
			geradenSchnittpunkt(
				seitenMitte[0][0],
				seitenMitte[0][1],
				-ecke[1][1] + ecke[0][1],
				ecke[1][0] - ecke[0][0],
				seitenMitte[1][0],
				seitenMitte[1][1],
				-ecke[2][1] + ecke[1][1],
				ecke[2][0] - ecke[1][0])[1];
		echterUmp[0] = ump[0];
		echterUmp[1] = ump[1];
		umpOderNicht = true;
		if (cosGamma(ecke[1][0] - ecke[0][0],
			ecke[1][1] - ecke[0][1],
			ecke[2][0] - ecke[0][0],
			ecke[2][1] - ecke[0][1])
			< 0) {
			ump[0] = seitenMitte[1][0];
			ump[1] = seitenMitte[1][1];
			umpOderNicht = false;
		}
		if (cosGamma(ecke[2][0] - ecke[1][0],
			ecke[2][1] - ecke[1][1],
			ecke[0][0] - ecke[1][0],
			ecke[0][1] - ecke[1][1])
			< 0) {
			ump[0] = seitenMitte[2][0];
			ump[1] = seitenMitte[2][1];
			umpOderNicht = false;
		}
		if (cosGamma(ecke[0][0] - ecke[2][0],
			ecke[0][1] - ecke[2][1],
			ecke[1][0] - ecke[2][0],
			ecke[1][1] - ecke[2][1])
			< 0) {
			ump[0] = seitenMitte[0][0];
			ump[1] = seitenMitte[0][1];
			umpOderNicht = false;
		}
		return ump;

	}

	void seitenhalbierendeZeichnen() {
		if (SEITENHALBIERENDE) {
			SEITENHALBIERENDE = false;
		} else {
			SEITENHALBIERENDE = true;
		}
	}

	void mittelsenkrechteZeichnen() {
		if (MITTELSENKRECHTE) {
			MITTELSENKRECHTE = false;
		} else {
			MITTELSENKRECHTE = true;
		}
	}

	void cavalierihilfeZeichnen() {
		if (CAVALIERIHILFE) {
			CAVALIERIHILFE = false;
		} else {
			CAVALIERIHILFE = true;
		}
	}

	public void paint(Graphics g) {
		update(g);
	}

	public void update(Graphics g) {
		if (imageBuffer == null) {
			imageBuffer = createImage(breiteX, breiteY);
			graphicsBuffer = imageBuffer.getGraphics();
		}
		double radius;
		graphicsBuffer.setColor(Color.white);
		graphicsBuffer.fillRect(0, 0, breiteX, breiteY);
		graphicsBuffer.setColor(Color.black);
		graphicsBuffer.drawRect(0, 0, breiteX, breiteY);
		double puffer = cavallieri()[0];
		for (int i = 0; i < 3; i++) {
			if (i != 2) {
				graphicsBuffer.fillOval(
					(int) ecke[i][0] - 5,
					(int) ecke[i][1] - 5,
					10,
					10);
				//graphicsBuffer.fillOval((int)kreisMittelpunkt[i][0]-5,(int)kreisMittelpunkt[i][1]-5,10,10);
				//graphicsBuffer.drawLine((int)seitenMitte[i][0],(int)seitenMitte[i][1],
				//	   (int)kreisMittelpunkt[i][0],(int)kreisMittelpunkt[i][1]);
				//graphicsBuffer.setColor(Color.red);
				graphicsBuffer.drawLine(
					(int) ecke[i][0],
					(int) ecke[i][1],
					(int) ecke[i + 1][0],
					(int) ecke[i + 1][1]);
				graphicsBuffer.setColor(Color.black);
				graphicsBuffer.drawString(
					"P" + (i + 1),
					(int) ecke[i][0] - 7,
					(int) ecke[i][1] - 7);
				radius =
					abstand(
						ecke[i][0],
						ecke[i][1],
						kreisMittelpunkt[i][0],
						kreisMittelpunkt[i][1]);
				graphicsBuffer.setColor(Color.red);
				//graphicsBuffer.drawLine((int)ecke[i][0],(int)ecke[i][1],
				//(int)kreisMittelpunkt[i][0],(int)kreisMittelpunkt[i][1]);
				if (hilfslinien) {
					graphicsBuffer.drawOval(
						(int) (kreisMittelpunkt[i][0] - radius),
						(int) (kreisMittelpunkt[i][1] - radius),
						(int) (2 * radius),
						(int) (2 * radius));
					graphicsBuffer.drawLine(10, 15, 30, 15);
					graphicsBuffer.drawString("Hilfskreise für Cavalieri-Pkt.", 40, 20);
				}
				/*graphicsBuffer.fillOval(
					(int) cavallieri()[0] - 5,
					(int) cavallieri()[1] - 5,
					10,
					10);*/
				if (CAVALIERIHILFE) {

					graphicsBuffer.drawLine(
						(int) cavallieri()[0],
						(int) cavallieri()[1],
						(int) ecke[i][0],
						(int) ecke[i][1]);
				}
				/*
				if (cavallieriOderNicht) {
					graphicsBuffer.drawString(
						"Cavalieri",
						(int) cavallieri()[0] - 7,
						(int) cavallieri()[1] - 7);
				}*/
				graphicsBuffer.setColor(Color.black);
			} else {
				graphicsBuffer.fillOval(
					(int) ecke[i][0] - 5,
					(int) ecke[i][1] - 5,
					10,
					10);
				graphicsBuffer.drawLine(
					(int) ecke[i][0],
					(int) ecke[i][1],
					(int) ecke[0][0],
					(int) ecke[0][1]);
				graphicsBuffer.setColor(Color.red);
				/*graphicsBuffer.fillOval(
					(int) cavallieri()[0] - 5,
					(int) cavallieri()[1] - 5,
					10,
					10);*/
				if (CAVALIERIHILFE) {
					graphicsBuffer.drawLine(
						(int) cavallieri()[0],
						(int) cavallieri()[1],
						(int) ecke[i][0],
						(int) ecke[i][1]);
				}
				graphicsBuffer.setColor(Color.blue);
				// graphicsBuffer.drawLine((int)ecke[i][0],(int)ecke[i][1],(int)schwerpunkt()[0],
				// 			   (int)schwerpunkt()[1]);
				graphicsBuffer.setColor(Color.green);
				// graphicsBuffer.drawLine((int)ecke[i][0],(int)ecke[i][1],(int)umkreismittelpunkt()[0],
				// 			   (int)umkreismittelpunkt()[1]);
				graphicsBuffer.setColor(Color.black);
				graphicsBuffer.drawString(
					"P" + (i + 1),
					(int) ecke[i][0] - 7,
					(int) ecke[i][1] - 7);
			}
			graphicsBuffer.setColor(Color.blue);
			/*graphicsBuffer.fillOval(
				(int) schwerpunkt()[0] - 5,
				(int) schwerpunkt()[1] - 5,
				10,
				10);
			graphicsBuffer.drawString(
				"Schwerpunkt",
				(int) schwerpunkt()[0] - 7,
				(int) schwerpunkt()[1] - 7);*/
			graphicsBuffer.setColor(Color.green);
			graphicsBuffer.fillOval(
				(int) umkreismittelpunkt()[0] - 5,
				(int) umkreismittelpunkt()[1] - 5,
				10,
				10);
			if (umpOderNicht) {
				graphicsBuffer.drawString(
					"Umkreismittelpunkt",
					(int) umkreismittelpunkt()[0] - 7,
					(int) umkreismittelpunkt()[1] - 7);
			}
			double umkreisradius =
				abstand(echterUmp[0], echterUmp[1], ecke[0][0], ecke[0][1]);
			if (hilfslinien) {
				graphicsBuffer.drawOval(
					(int) (echterUmp[0] - umkreisradius),
					(int) (echterUmp[1] - umkreisradius),
					(int) (2 * umkreisradius),
					(int) (2 * umkreisradius));
				graphicsBuffer.drawLine(10, 30, 30, 30);
				graphicsBuffer.drawString("Umkreis", 40, 35);
			}
			if (MITTELSENKRECHTE) {
				graphicsBuffer.setColor(Color.green);
				graphicsBuffer.drawLine(
					(int) seitenMitte[0][0],
					(int) seitenMitte[0][1],
					(int) echterUmp[0],
					(int) echterUmp[1]);
				graphicsBuffer.drawLine(
					(int) seitenMitte[1][0],
					(int) seitenMitte[1][1],
					(int) echterUmp[0],
					(int) echterUmp[1]);
				graphicsBuffer.drawLine(
					(int) seitenMitte[2][0],
					(int) seitenMitte[2][1],
					(int) echterUmp[0],
					(int) echterUmp[1]);
				graphicsBuffer.drawOval(
					(int) (echterUmp[0] - umkreisradius),
					(int) (echterUmp[1] - umkreisradius),
					(int) (2 * umkreisradius),
					(int) (2 * umkreisradius));
				graphicsBuffer.drawString("Mittelsenkrechte und Umkreis", 440, 20);
			}
			if (SEITENHALBIERENDE) {
				graphicsBuffer.setColor(Color.blue);
				graphicsBuffer.drawLine(
					(int) seitenMitte[0][0],
					(int) seitenMitte[0][1],
					(int) ecke[2][0],
					(int) ecke[2][1]);
				graphicsBuffer.drawLine(
					(int) seitenMitte[1][0],
					(int) seitenMitte[1][1],
					(int) ecke[0][0],
					(int) ecke[0][1]);
				graphicsBuffer.drawLine(
					(int) seitenMitte[2][0],
					(int) seitenMitte[2][1],
					(int) ecke[1][0],
					(int) ecke[1][1]);
				graphicsBuffer.drawString("Seitenhalbierende für Schwerpunkt", 220, 20);
			}
			if (CAVALIERIHILFE) {
				graphicsBuffer.setColor(Color.red);
				radius =
					abstand(
						ecke[0][0],
						ecke[0][1],
						kreisMittelpunkt[0][0],
						kreisMittelpunkt[0][1]);
				graphicsBuffer.drawOval(
					(int) (kreisMittelpunkt[0][0] - radius),
					(int) (kreisMittelpunkt[0][1] - radius),
					(int) (2 * radius),
					(int) (2 * radius));
				graphicsBuffer.fillOval(
					(int) kreisMittelpunkt[0][0] - 3,
					(int) kreisMittelpunkt[0][1] - 3,
					6,
					6);
				graphicsBuffer.drawLine(
					(int) kreisMittelpunkt[0][0],
					(int) kreisMittelpunkt[0][1],
					(int) seitenMitte[0][0],
					(int) seitenMitte[0][1]);
				graphicsBuffer.drawLine(
					(int) kreisMittelpunkt[0][0],
					(int) kreisMittelpunkt[0][1],
					(int) ecke[0][0],
					(int) ecke[0][1]);
				radius =
					abstand(
						ecke[1][0],
						ecke[1][1],
						kreisMittelpunkt[1][0],
						kreisMittelpunkt[1][1]);
				graphicsBuffer.drawOval(
					(int) (kreisMittelpunkt[1][0] - radius),
					(int) (kreisMittelpunkt[1][1] - radius),
					(int) (2 * radius),
					(int) (2 * radius));
				graphicsBuffer.fillOval(
					(int) kreisMittelpunkt[1][0] - 3,
					(int) kreisMittelpunkt[1][1] - 3,
					6,
					6);
				graphicsBuffer.drawLine(
					(int) kreisMittelpunkt[1][0],
					(int) kreisMittelpunkt[1][1],
					(int) seitenMitte[1][0],
					(int) seitenMitte[1][1]);
				graphicsBuffer.drawLine(
					(int) kreisMittelpunkt[1][0],
					(int) kreisMittelpunkt[1][1],
					(int) ecke[1][0],
					(int) ecke[1][1]);
				graphicsBuffer.drawString("Hilfskreise für Cavalieri-Pkt.", 40, 20);
			}
			graphicsBuffer.setColor(Color.black);
		}
		g.drawImage(imageBuffer, 0, 0, this);
	}
}
