/*----------------------------------------------------------------------+
|	Title:	PointElement.java					|
|		Java Class extends Element				|
|									|
|	Author:	David E. Joyce						|
|		Department of Mathematics and Computer Science   	|
|		Clark University					|
|		Worcester, MA 01610-1477				|
|		U.S.A.							|
|									|
|		http://aleph0.clarku.edu/~djoyce/home.html		|
|		djoyce@clarku.edu					|
|									|
|	Date:	February, 1996.  					|
+----------------------------------------------------------------------*/

import java.awt.*;

public class PointElement extends Element {

  double x,y;

  public String toString() {
    return "[" + name + "=(" +x+ "," +y+ ")]";
  }

  double distance (PointElement B) {		// how far to point B?
    return Math.sqrt((B.x-x)*(B.x-x) + (B.y-y)*(B.y-y));
  }

  double distance (double Bx, double By) {
    return Math.sqrt((Bx-x)*(Bx-x) + (By-y)*(By-y));
  }

  double distance2 (PointElement B) {
    return (B.x-x)*(B.x-x) + (B.y-y)*(B.y-y);
  }

  double distance2 (double Bx, double By) {
    return (Bx-x)*(Bx-x) + (By-y)*(By-y);
  }

  double angle (PointElement B, PointElement C) {
    // find the angle BAC in radians, ranging from -pi to +pi
    double u = B.x - x,		v = B.y - y;
    double s = C.x - x,		t = C.y - y;
    return Math.atan2 (u*t - v*s, u*s + v*t);
  }

  void toIntersection (PointElement A, PointElement B,
		       PointElement C, PointElement D) {
    // move this point to  where two lines AB and CD meet
    double d0 = A.x*B.y - A.y*B.x;
    double d1 = C.x*D.y - C.y*D.x;
    double den = (B.y-A.y)*(C.x-D.x) - (A.x-B.x)*(D.y-C.y);
    x = (d0*(C.x-D.x) - d1*(A.x-B.x)) / den;
    y = (d1*(B.y-A.y) - d0*(D.y-C.y)) / den;
  }

  void toFoot (PointElement A, PointElement B, PointElement C) {
    // move this point to the foot of the perpendicular from A to line BC
    double fmd = B.y - C.y;
    double emc = B.x - C.x;
    double d0 = C.x*fmd - C.y *emc;
    double d1 = A.x*emc + A.y*fmd;
    double den = fmd*fmd + emc*emc;
    x = (d0*fmd + d1*emc) / den;
    y = (d1*fmd - d0*emc) /den;
  }

  void toCircumcenter (PointElement A, PointElement B, PointElement C) {
    // move this point to the center of the circle passing through A,B,C
    double u = ((A.x-B.x)*(A.x+B.x) + (A.y-B.y)*(A.y+B.y)) / 2.0;
    double v = ((B.x-C.x)*(B.x+C.x) + (B.y-C.y)*(B.y+C.y)) / 2.0;
    double den = (A.x-B.x)*(B.y-C.y) - (B.x-C.x)*(A.y-B.y);
    x = (u * (B.y-C.y) - v*(A.y-B.y)) / den;
    y = (v * (A.x-B.x) - u*(B.x-C.x)) / den;
  }

  void toCircle (PointElement A, CircleElement C) {
    // move this point to the intersection of the circle C with the line
    // from its center to A
    double factor = C.radius() / A.distance(C.Center);
    x = C.Center.x + factor*(A.x - C.Center.x);
    y = C.Center.y + factor*(A.y - C.Center.y);
  }

  void toEllipse (PointElement A, EllipseElement E) {
    // move this point to the intersection of the elllipse E with the line
    // from its center to A
    double vr2 = (E.A.y - E.C.y)*(E.A.y - E.C.y);
    double hr2 = (E.B.x - E.C.x)*(E.B.x - E.C.x);
    double den = vr2*(A.x-E.C.x)*(A.x-E.C.x) + hr2*(A.y-E.C.y)*(A.y-E.C.y);
    double factor = Math.sqrt(vr2*hr2/den);
    x = E.C.x + factor*(A.x - E.C.x);
    y = E.C.y + factor*(A.y - E.C.y);
  }

  void toInvertPoint (PointElement A, CircleElement C) {
    // move this point to the inversion of the point A in the circle C
    double factor = C.radius2() / A.distance2(C.Center);
    x = C.Center.x + factor*(A.x - C.Center.x);
    y = C.Center.y + factor*(A.y - C.Center.y);
  }

  void toSimilar (PointElement A, PointElement B, PointElement D,
	PointElement E, PointElement F) {
    // move this point to the location C so that triangle ABC is similar
    // to triangle DEF.
    double theta = D.angle(E,F);
    x = B.x; y = B.y;
    rotate(A,Math.cos(theta),Math.sin(theta));
    double factor = D.distance(F) / D.distance(E);
    x = A.x + factor*(x - A.x);
    y = A.y + factor*(y - A.y);
  }

  protected void translate (double dx, double dy) {
    x += dx;
    y += dy;
  }

  protected void rotate (PointElement pivot, double ac, double as) {
    double dx = x - pivot.x;
    double dy = y - pivot.y;
    x = pivot.x + ac*dx - as*dy;
    y = pivot.y + as*dx + ac*dy;
  }

  protected boolean defined() {
    return !Double.isNaN(x) && !Double.isNaN(y);
  }

  protected void drawName (Graphics g, Dimension d) {
    if (nameColor!=null && name!=null && defined()) {
      g.setColor(nameColor);
      drawString(name, (int)Math.round(x),(int)Math.round(y), g,d);
  } }

  protected void drawVertex (Graphics g) {
    if (vertexColor != null && defined()) {
      g.setColor(vertexColor);
      g.fillOval ((int)Math.round(x) - 2, (int)Math.round(y) - 2, 4, 4);
} } }



