code: package wprover;
  
  import java.util.Vector;
  import java.io.DataOutputStream;
  import java.io.IOException;
  import java.io.DataInputStream;
  import java.io.FileOutputStream;
  import java.awt.*;
  
  /**
   * Created by IntelliJ IDEA.
   * User: ${Yezheng}
   * Date: 2004-12-9
   * Time: 12:29:48
   * To change this template use File | Settings | File Templates.
   */
  public class Circle extends CClass {
      public static int PCircle = 0;
      public static int RCircle = 1;
      public static int SCircle = 2;
  
      int type = PCircle;
  
      CPoint o = new CPoint();
      Vector points = new Vector();
      Vector cons = new Vector();
  
      public int psize() {
          return points.size();
      }
  
      public CPoint getP(int i) {
          return (CPoint) points.get(i);
      }
  
      public boolean p_on_circle(CPoint p) {
          for (int i = 0; i < points.size(); i++)
              if (p == points.get(i))
                  return true;
          return false;
      }
  
      public void draw(Graphics2D g2, boolean selected) {
          if (!isdraw()) return;
          if (selected) {
              g2.setColor(CMisc.SelectObjectColor);
              g2.setStroke(CMisc.SelectObjectStroke);
          } else
              super.setDraw(g2);
  
          double x1, y1, r;
          x1 = o.x1.value;
          y1 = o.y1.value;
          r = getRadius();
          if (r < CMisc.MAX_DRAW_LEN)
              g2.drawOval((int) (x1 - r), (int) (y1 - r), 2 * (int) r, 2 * (int) r);
          else {
              if (points.size() < 2) return;
              CPoint p1, p2;
              p1 = p2 = null;
              double len = 0.00;
              for (int i = 0; i < points.size(); i++) {
                  CPoint tp1 = (CPoint) points.get(i);
                  for (int j = 1; j < points.size(); j++) {
  
                      CPoint tp2 = (CPoint) points.get(j);
                      if (tp1 == tp2) continue;
                      double tlen = Math.pow(tp1.getx() - tp2.getx(), 2) + Math.pow(tp1.gety() - tp2.gety(), 2);
                      if (tlen > len) {
                          len = tlen;
                          p1 = tp1;
                          p2 = tp2;
                      }
                  }
              }
              if (p1 == null || p2 == null) return;
              double dx = p2.getx() - p1.getx();
              double dy = p2.gety() - p1.gety();
              double sl = Math.sqrt(dx * dx + dy * dy);
              x1 = p1.getx() - dx * 2000 / sl;
              y1 = p1.gety() - dy * 2000 / sl;
              double x2 = p1.getx() + dx * 2000 / sl;
              double y2 = p1.gety() + dy * 2000 / sl;
              g2.drawLine((int) x1, (int) y1, (int) x2, (int) y2);
  
  
          }
  
  
      }
  
      public void draw(Graphics2D g2) {
          this.draw(g2, false);
      }
  
      public String TypeString() {
          if (m_name == null) return Language.getLs(50, "circle ");
          return Language.getLs(50, "circle ") + m_name;
      }
  
      public String getDescription() {
          String st =  Language.getLs(50, "circle ");
  
          if (type == PCircle)
              return st + "(" + o.m_name + "," + o.m_name + this.getSidePoint().getname() + ")";
          else if (type == SCircle) {
              CPoint p1, p2, p3;
              p1 = p2 = p3 = null;
              if (points.size() < 3) return st;
  
              p1 = (CPoint) points.get(0);
              p2 = (CPoint) points.get(1);
              p3 = (CPoint) points.get(2);
              return st + "(" + o.getname() + "," + p1.getname() + p2.getname() + p3.getname() + ")";
          } else if (type == RCircle) {
              constraint cs = (constraint) cons.get(0);
              if (cs.GetConstraintType() == constraint.RCIRCLE) {
                  CClass p1 = (CClass) cs.getelement(0);
                  CClass p2 = (CClass) cs.getelement(1);
                  return st + "(" + o.m_name + "," + p1.getname() + p2.getname() + ")";
              }
          }
          return this.TypeString();
      }
  
      public boolean select(double x, double y) {
          if (!visible) return false;
          double ox, oy;
          ox = o.getx();
          oy = o.gety();
  
          double r = this.getRadius();
          double len = Math.sqrt(Math.pow(x - ox, 2) + Math.pow(y - oy, 2));
          if (Math.abs(r - len) < CMisc.PIXEPS)
              return true;
          return false;
  
      }
  
      public void setType(int type) {
          this.type = type;
      }
  
      public String getAllPointName() {
          String s = new String();
          for (int i = 0; i < points.size(); i++) {
              CPoint p = (CPoint) points.get(i);
              if (i == 0)
                  s += p.m_name;
              else
                  s += ", " + p.m_name;
          }
          return s;
      }
  
  
      public CPoint getSidePoint() // point that with least number
      {
          CPoint pt = null;
  
          for (int i = 0; i < points.size(); i++) {
              CPoint p = (CPoint) points.get(i);
              if (p == null)
                  continue;
              if (pt == null)
                  pt = p;
              else if (pt.x1.xindex > p.x1.xindex)
                  pt = p;
  
          }
          return pt;
      }
  
      public double getCenterOX() {
          return o.getx();
      }
  
      public double getCenterOY() {
          return o.gety();
      }
  
      public double getRadius() {
          if (type == RCircle) {
              //constraint cs = null;
              for (int i = 0; i < cons.size(); i++) {
                  constraint c = (constraint) cons.get(i);
                  if (c.GetConstraintType() == constraint.RCIRCLE) {
                      CPoint p1 = (CPoint) c.getelement(0);
                      CPoint p2 = (CPoint) c.getelement(1);
                      return Math.sqrt(Math.pow(p1.getx() - p2.getx(), 2) + Math.pow(p1.gety() - p2.gety(), 2));
                  }
              }
              return -1;
          } else {
              CPoint p = getSidePoint();
              return Math.sqrt(Math.pow(p.getx() - o.getx(), 2) + Math.pow(p.gety() - o.gety(), 2));
          }
      }
  
      public CPoint[] getRadiusPoint() {
          CPoint[] pl = new CPoint[2];
          if (type == Circle.RCircle) {
              for (int i = 0; i < cons.size(); i++) {
                  constraint cs = (constraint) cons.get(i);
                  if (cs.GetConstraintType() == constraint.RCIRCLE) {
                      pl[0] = (CPoint) cs.getelement(0);
                      pl[1] = (CPoint) cs.getelement(1);
                      return pl;
                  }
              }
  
          } else if (type == Circle.PCircle | type == Circle.SCircle) {
              pl[0] = o;
              pl[1] = this.getSidePoint();
          }
          return pl;
  
      }
  
      public Circle() {
          super(CClass.CIRCLE);
      }
  
      public Circle(CPoint O, CPoint A, CPoint B, CPoint C) {
          super(CClass.CIRCLE);
          type = SCircle;
          this.o = O;
          points.add(A);
          points.add(B);
          points.add(C);
      }
  
      public Circle(CPoint O, CPoint A, CPoint B) {
          super(CClass.CIRCLE);
          this.o = O;
          points.add(A);
          points.add(B);
      }
  
      public Circle(CPoint O, CPoint A) {
          super(CClass.CIRCLE);
          this.o = O;
          points.add(A);
      }
  
      public Circle(int type, CPoint O) {
          super(CClass.CIRCLE);
          this.o = O;
          this.type = type;
      }
  
      public void addConstraint(constraint cs) {
          cons.add(cs);
      }
  
      public boolean hasPoint(CPoint p) {
          for (int i = 0; i < points.size(); i++) {
              if (p.isEqual((CPoint) points.get(i))) return true;
          }
          return false;
      }
  
      public void addPoint(CPoint p) {
          if (!points.contains(p))
              points.add(p);
      }
  
      public void pointStickToCircle(CPoint p) {
          double x = p.getx();
          double y = p.gety();
  
          double xo = o.x1.value;
          double yo = o.y1.value;
          double R = this.getRadius();
          double R1 = Math.sqrt((xo - x) * (xo - x) + (yo - y) * (yo - y));
  
          double y1 = yo + (y - yo) * R / R1;
          double x1 = xo + (x - xo) * R / R1;
          p.setXY(x1, y1);
  
      }
  
      public boolean on_circle(double x, double y) {
          return this.select(x, y);
      }
  
      public boolean nearcircle(double x, double y, double eps) {
          double ox, oy;
          ox = o.getx();
          oy = o.gety();
  
          double r = getRadius();
          double len = Math.sqrt(Math.pow(x - ox, 2) + Math.pow(y - oy, 2));
          if (Math.abs(r - len) < eps)
              return true;
          return false;
      }
  
      public void SmartPonc(CPoint p) {
          //    CPoint pt = (CPoint) points.get(0);
          double ox, oy, x, y;
          ox = o.getx();
          oy = o.gety();
          x = p.getx();
          y = p.gety();
  
          double r = this.getRadius();//Math.sqrt(Math.pow(pt.getx() - ox, 2) + Math.pow(pt.gety() - oy, 2));
          double len = Math.sqrt(Math.pow(p.getx() - ox, 2) + Math.pow(p.gety() - oy, 2));
  
  
          if (Math.abs(x - o.getx()) < 0.001) {
              if (y > oy)
                  p.setXY(ox, oy + r);
              else
                  p.setXY(ox, oy - r);
          } else {
              double k = r / len;
              p.setXY(ox + k * (x - ox), oy + k * (y - oy));
          }
      }
  
      public static Vector CommonPoints(Circle c1, Circle c2) {
          Vector vlist = new Vector();
          for (int i = 0; i < c1.points.size(); i++) {
              Object obj = c1.points.get(i);
              if (c2.points.contains(obj)) {
                  if (!vlist.contains(obj))
                      vlist.add(obj);
              }
          }
          return vlist;
      }
  
      public boolean Tangent(Object obj) {
          if (obj instanceof CLine) {
              return true;
          } else if (obj instanceof Circle) {
              Circle c2 = (Circle) obj;
              CPoint p1 = this.getSidePoint();
              CPoint p2 = c2.getSidePoint();
              double r1 = Math.sqrt(Math.pow(this.o.getx() - p1.getx(), 2) + Math.pow(this.o.gety() - p1.gety(), 2));
              double r2 = Math.sqrt(Math.pow(c2.o.getx() - p2.getx(), 2) + Math.pow(c2.o.gety() - p2.gety(), 2));
              double d = Math.sqrt(Math.pow(this.o.getx() - c2.o.getx(), 2) + Math.pow(this.o.gety() - c2.o.gety(), 2));
              if (Math.abs(r1 + r2 - d) < CMisc.PIXEPS)
                  return true;
              else
                  return false;
          } else
              return false;
      }
  
      public void SavePS(FileOutputStream fp, int stype) throws IOException {
          if (!visible) return;
  
          float r = (float) (((int) (getRadius() * 100)) / 100.0);
          String s = "newpath " + o.m_name + " " +
                  new Float(r).toString() + " circle";
          fp.write(s.getBytes());
          this.saveSuper(fp);
      }
  
      public void Save(DataOutputStream out) throws IOException {
          super.Save(out);
  
          out.writeInt(type);
          out.writeInt(o.m_id);
          out.writeInt(points.size());
          for (int i = 0; i < points.size(); i++) {
              CPoint p = (CPoint) points.get(i);
              out.writeInt(p.m_id);
          }
          out.writeInt(cons.size());
          for (int i = 0; i < cons.size(); i++) {
              constraint cs = (constraint) cons.get(i);
              out.writeInt(cs.id);
          }
  
  
      }
  
      public void Load(DataInputStream in, drawProcess dp) throws IOException {
          if (CMisc.version_load_now < 0.010) {
              m_id = in.readInt();
  
              drawType drawt = new drawType();
              drawt.Load(in);
              m_color = drawt.color_index;
              {
                  if (m_color == 1)
                      m_color = 3;
                  else if (m_color == 2)
                      m_color = 5;
                  else if (m_color == 3)
                      m_color = 11;
                  else if (m_color == 7)
                      m_color = 8;
              }
              m_dash = drawt.dash;
              m_width = drawt.width;
  
  
              type = in.readInt();
              int size = in.readInt();
              m_name = new String();
              for (int i = 0; i < size; i++)
                  m_name += in.readChar();
              int d = in.readInt();
              o = dp.getPointById(d);
  
              size = in.readInt();
              for (int i = 0; i < size; i++) {
                  int dx = in.readInt();
                  points.add(dp.getPointById(dx));
              }
              size = in.readInt();
              for (int i = 0; i < size; i++) {
                  int dx = in.readInt();
                  cons.add(dp.getConstraintByid(dx));
              }
          } else {
              super.Load(in, dp);
  
              type = in.readInt();
  
              int d = in.readInt();
              o = dp.getPointById(d);
  
              int size = in.readInt();
              for (int i = 0; i < size; i++) {
                  int dx = in.readInt();
                  points.add(dp.getPointById(dx));
              }
              size = in.readInt();
              for (int i = 0; i < size; i++) {
                  int dx = in.readInt();
                  cons.add(dp.getConstraintByid(dx));
              }
  
          }
  
  
      }
  
  
  }
  