⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 polygonfigure.java

📁 JHotDraw学习过程中对数组的测试程序haha 学习过程中对数组的测试程序
💻 JAVA
字号:
/* * Fri Feb 28 07:47:05 1997  Doug Lea  (dl at gee) * Based on PolyLineFigure */package CH.ifa.draw.contrib;import java.awt.*;import java.util.*;import java.io.IOException;import CH.ifa.draw.framework.*;import CH.ifa.draw.util.*;import CH.ifa.draw.standard.*;import CH.ifa.draw.figures.*;/** * A scalable, rotatable polygon with an arbitrary number of points */public  class PolygonFigure extends AttributeFigure {  /**   * Distance threshold for smoothing away or locating points   **/  static final int TOO_CLOSE = 2;  /*   * Serialization support.   */  private static final long serialVersionUID = 6254089689239215026L;  private int polygonFigureSerializedDataVersion = 1;  protected Polygon fPoly = new Polygon();  public PolygonFigure() {    super();  }  public PolygonFigure(int x, int y) {    fPoly.addPoint(x, y);  }  public PolygonFigure(Polygon p) {    fPoly = new Polygon(p.xpoints, p.ypoints, p.npoints);  }  public Rectangle displayBox() {    return bounds(fPoly);  }  public boolean isEmpty() {    return (fPoly.npoints < 3 ||            (size().width < TOO_CLOSE) && (size().height < TOO_CLOSE));  }  public Vector handles() {    Vector handles = new Vector(fPoly.npoints);    for (int i = 0; i < fPoly.npoints; i++)      handles.addElement(new PolygonHandle(this, locator(i), i));    handles.addElement(new PolygonScaleHandle(this));    //handles.addElement(new PolygonPointAddHandle(this));    return handles;  }  public void basicDisplayBox(Point origin, Point corner) {    Rectangle r = displayBox();    int dx = origin.x - r.x;    int dy = origin.y - r.y;    fPoly.translate(dx, dy);    r = displayBox();    Point oldCorner = new Point(r.x + r.width, r.y + r.height);    Polygon p = getPolygon();    scaleRotate(oldCorner, p, corner);  }  /**   * return a copy of the raw polygon   **/  public Polygon getPolygon() {    return new Polygon(fPoly.xpoints, fPoly.ypoints, fPoly.npoints);  }  public Point center() {    return center(fPoly);  }  public Enumeration points() {    Vector pts = new Vector(fPoly.npoints);    for (int i = 0; i < fPoly.npoints; ++i)      pts.addElement(new Point(fPoly.xpoints[i], fPoly.ypoints[i]));    return pts.elements();  }  public int pointCount() {    return fPoly.npoints;  }  public void basicMoveBy(int dx, int dy) {    fPoly.translate(dx, dy);  }  public void drawBackground(Graphics g) {      g.fillPolygon(fPoly);  }  public void drawFrame(Graphics g) {      g.drawPolygon(fPoly);  }  public boolean containsPoint(int x, int y) {    return fPoly.contains(x, y);  }  public Connector connectorAt(int x, int y) {    return new ChopPolygonConnector(this);  }  /**   * Adds a node to the list of points.   */  public  void addPoint(int x, int y) {    fPoly.addPoint(x, y);    changed();  }  /**   * Changes the position of a node.   */  public  void setPointAt(Point p, int i) {    willChange();    fPoly.xpoints[i] = p.x;    fPoly.ypoints[i] = p.y;    changed();  }  /**   * Insert a node at the given point.   */  public  void insertPointAt(Point p, int i) {    willChange();    int n = fPoly.npoints + 1;    int[] xs = new int[n];    int[] ys = new int[n];    for (int j = 0; j < i; ++j) {      xs[j] = fPoly.xpoints[j];      ys[j] = fPoly.ypoints[j];    }    xs[i] = p.x;    ys[i] = p.y;    for (int j = i; j < fPoly.npoints; ++j) {      xs[j+1] = fPoly.xpoints[j];      ys[j+1] = fPoly.ypoints[j];    }    fPoly = new Polygon(xs, ys, n);    changed();  }  public  void removePointAt(int i) {    willChange();    int n = fPoly.npoints - 1;    int[] xs = new int[n];    int[] ys = new int[n];    for (int j = 0; j < i; ++j) {      xs[j] = fPoly.xpoints[j];      ys[j] = fPoly.ypoints[j];    }    for (int j = i; j < n; ++j) {      xs[j] = fPoly.xpoints[j+1];      ys[j] = fPoly.ypoints[j+1];    }    fPoly = new Polygon(xs, ys, n);    changed();  }  /**   * Scale and rotate relative to anchor   **/  public  void scaleRotate(Point anchor, Polygon originalPolygon, Point p) {    willChange();    // use center to determine relative angles and lengths    Point ctr = center(originalPolygon);    double anchorLen = Geom.length(ctr.x, ctr.y, anchor.x, anchor.y);    if (anchorLen > 0.0) {      double newLen = Geom.length(ctr.x, ctr.y, p.x, p.y);      double ratio = newLen / anchorLen;      double anchorAngle = Math.atan2(anchor.y - ctr.y, anchor.x - ctr.x);      double newAngle = Math.atan2(p.y - ctr.y, p.x - ctr.x);      double rotation = newAngle - anchorAngle;      int n = originalPolygon.npoints;      int[] xs = new int[n];      int[] ys = new int[n];      for (int i = 0; i < n; ++i) {        int x = originalPolygon.xpoints[i];        int y = originalPolygon.ypoints[i];        double l = Geom.length(ctr.x, ctr.y, x, y) * ratio;        double a = Math.atan2(y - ctr.y, x - ctr.x) + rotation;        xs[i] = (int)(ctr.x + l * Math.cos(a) + 0.5);        ys[i] = (int)(ctr.y + l * Math.sin(a) + 0.5);      }      fPoly =  new Polygon(xs, ys, n);    }    changed();  }  /**   * Remove points that are nearly colinear with others   **/  public void smoothPoints() {    willChange();    boolean removed = false;    int n = fPoly.npoints;    do {      removed = false;      int i = 0;      while (i < n && n >= 3) {        int nxt = (i + 1) % n;        int prv = (i - 1 + n) % n;        if ((distanceFromLine(fPoly.xpoints[prv], fPoly.ypoints[prv],                              fPoly.xpoints[nxt], fPoly.ypoints[nxt],                              fPoly.xpoints[i], fPoly.ypoints[i]) < TOO_CLOSE)) {          removed = true;          --n;          for (int j = i; j < n; ++j) {            fPoly.xpoints[j] = fPoly.xpoints[j+1];            fPoly.ypoints[j] = fPoly.ypoints[j+1];          }        }        else          ++i;      }    } while(removed);    if (n != fPoly.npoints)      fPoly =  new Polygon(fPoly.xpoints, fPoly.ypoints, n);    changed();  }  /**   * Splits the segment at the given point if a segment was hit.   * @return the index of the segment or -1 if no segment was hit.   */  public int splitSegment(int x, int y) {    int i = findSegment(x, y);    if (i != -1) {      insertPointAt(new Point(x, y), i+1);      return i + 1;    }    else      return -1;  }  public Point pointAt(int i) {    return new Point(fPoly.xpoints[i], fPoly.ypoints[i]);  }  /**   * Return the point on the polygon that is furthest from the center   **/  public Point outermostPoint() {    Point ctr = center();    int outer = 0;    long dist = 0;    for (int i = 0; i < fPoly.npoints; ++i) {      long d = Geom.length2(ctr.x, ctr.y, fPoly.xpoints[i], fPoly.ypoints[i]);      if (d > dist) {        dist = d;        outer = i;      }    }    return new Point(fPoly.xpoints[outer], fPoly.ypoints[outer]);  }  /**   * Gets the segment that is hit by the given point.   * @return the index of the segment or -1 if no segment was hit.   */  public int findSegment(int x, int y) {    double dist = TOO_CLOSE;    int best = -1;    for (int i = 0; i < fPoly.npoints; i++) {      int n = (i + 1) % fPoly.npoints;      double d =  distanceFromLine(fPoly.xpoints[i], fPoly.ypoints[i],                                   fPoly.xpoints[n], fPoly.ypoints[n],                                   x, y);      if (d < dist) {        dist = d;        best = i;      }    }    return best;  }  public Point chop(Point p) {    return chop(fPoly, p);  }  public void write(StorableOutput dw) {    super.write(dw);    dw.writeInt(fPoly.npoints);    for (int i = 0; i < fPoly.npoints; ++i) {      dw.writeInt(fPoly.xpoints[i]);      dw.writeInt(fPoly.ypoints[i]);    }  }  public void read(StorableInput dr) throws IOException {    super.read(dr);    int size = dr.readInt();    int[] xs = new int[size];    int[] ys = new int[size];    for (int i = 0; i < size; i++) {      xs[i] = dr.readInt();      ys[i] = dr.readInt();    }    fPoly = new Polygon(xs, ys, size);  }  /**   * Creates a locator for the point with the given index.   */  public static Locator locator(final int pointIndex) {    return new AbstractLocator() {      public Point locate(Figure owner) {        PolygonFigure plf = (PolygonFigure)owner;        // guard against changing PolygonFigures -> temporary hack        if (pointIndex < plf.pointCount())          return ((PolygonFigure)owner).pointAt(pointIndex);        return new Point(-1, -1);      }    };  }  /**   * compute distance of point from line segment, or   * Double.MAX_VALUE if perpendicular projection is outside segment; or   * If pts on line are same, return distance from point   **/  public static double distanceFromLine(int xa, int ya,                                        int xb, int yb,                                        int xc, int yc) {    // source:http://vision.dai.ed.ac.uk/andrewfg/c-g-a-faq.html#q7    //Let the point be C (XC,YC) and the line be AB (XA,YA) to (XB,YB).    //The length of the    //      line segment AB is L:    //    //                    ___________________    //                   |        2         2    //              L = \| (XB-XA) + (YB-YA)    //and    //    //                  (YA-YC)(YA-YB)-(XA-XC)(XB-XA)    //              r = -----------------------------    //                              L**2    //    //                  (YA-YC)(XB-XA)-(XA-XC)(YB-YA)    //              s = -----------------------------    //                              L**2    //    //      Let I be the point of perpendicular projection of C onto AB, the    //    //              XI=XA+r(XB-XA)    //              YI=YA+r(YB-YA)    //    //      Distance from A to I = r*L    //      Distance from C to I = s*L    //    //      If r < 0 I is on backward extension of AB    //      If r>1 I is on ahead extension of AB    //      If 0<=r<=1 I is on AB    //    //      If s < 0 C is left of AB (you can just check the numerator)    //      If s>0 C is right of AB    //      If s=0 C is on AB    int xdiff = xb - xa;    int ydiff = yb - ya;    long l2 = xdiff*xdiff + ydiff*ydiff;    if (l2 == 0) return Geom.length(xa, ya, xc, yc);    double rnum =  (ya-yc) * (ya-yb) - (xa-xc) * (xb-xa);    double r = rnum / l2;    if (r < 0.0 || r > 1.0) return Double.MAX_VALUE;    double xi = xa + r * xdiff;    double yi = ya + r * ydiff;    double xd = xc - xi;    double yd = yc - yi;    return Math.sqrt(xd * xd + yd * yd);    /*      for directional version, instead use      double snum =  (ya-yc) * (xb-xa) - (xa-xc) * (yb-ya);      double s = snum / l2;      double l = Math.sqrt((double)l2);      return = s * l;      */  }  /**   * replacement for builtin Polygon.getBounds that doesn't always update?   */  public static Rectangle bounds(Polygon p) {	int minx = Integer.MAX_VALUE;	int miny = Integer.MAX_VALUE;	int maxx = Integer.MIN_VALUE;	int maxy = Integer.MIN_VALUE;	int n = p.npoints;	for (int i = 0; i < n; i++) {      int x = p.xpoints[i];      int y = p.ypoints[i];      if (x > maxx) maxx = x;      if (x < minx) minx = x;      if (y > maxy) maxy = y;      if (y < miny) miny = y;    }	return new Rectangle(minx, miny, maxx-minx, maxy-miny);  }  public static Point center(Polygon p) {    long sx = 0;    long sy = 0;    int n = p.npoints;	for (int i = 0; i < n; i++) {      sx += p.xpoints[i];      sy += p.ypoints[i];    }	return new Point((int)(sx/n), (int)(sy/n));  }  public static Point chop(Polygon poly, Point p) {    Point ctr = center(poly);    int cx = -1;    int cy = -1;    long len = Long.MAX_VALUE;    // Try for points along edge    for (int i = 0; i < poly.npoints; ++i) {      int nxt = (i + 1) % poly.npoints;      Point chop = Geom.intersect(poly.xpoints[i],                             poly.ypoints[i],                             poly.xpoints[nxt],                             poly.ypoints[nxt],                             p.x,                             p.y,                             ctr.x,                             ctr.y);      if (chop != null) {        long cl = Geom.length2(chop.x, chop.y, p.x, p.y);        if (cl < len) {          len = cl;          cx = chop.x;          cy = chop.y;        }      }    }    // if none found, pick closest vertex    //if (len ==  Long.MAX_VALUE) {    { // try anyway      for (int i = 0; i < poly.npoints; ++i) {        long l = Geom.length2(poly.xpoints[i], poly.ypoints[i], p.x, p.y);        if (l < len) {          len = l;          cx = poly.xpoints[i];          cy = poly.ypoints[i];        }      }    }    return new Point(cx, cy);  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -