예제 #1
0
 private static Shape makeLine(Vector2D base, Vector2D disp) {
   double x1 = base.getX();
   double y1 = base.getY();
   double x2 = x1 + disp.getX();
   double y2 = y1 + disp.getY();
   return new Line2D.Double(x1, y1, x2, y2);
 }
예제 #2
0
  /**
   * Get the bounding rectangle
   *
   * @return minimum bounding rectangle
   */
  public BoundingRectangle2D getBounds() {
    if (boundsChanged == true) {
      boolean first = true;
      double minX = 0;
      double maxX = 0;
      double minY = 0;
      double maxY = 0;

      for (Enumeration e = vertices.elements(); e.hasMoreElements(); ) {
        Vector2D vertex = (Vector2D) e.nextElement();
        if (first) {
          minX = vertex.getX();
          maxX = vertex.getX();
          minY = vertex.getY();
          maxY = vertex.getY();
          first = false;
        } else {
          minX = Math.min(minX, vertex.getX());
          maxX = Math.max(maxX, vertex.getX());
          minY = Math.min(minY, vertex.getY());
          maxY = Math.max(maxY, vertex.getY());
        }
      }

      bounds.set(minX, minY, Math.abs(maxX - minX), Math.abs(maxY - minY));

      boundsChanged = false;
    }

    return bounds;
  }
예제 #3
0
  /**
   * Rotate the polygon clockwise about a point by an arbritray angle.
   *
   * @param x X ordinate of point to rotate about
   * @param y Y ordinate of point to rotate about
   * @param angle Angle in radians
   */
  public void rotate(double x, double y, double angle) {
    double theta = -angle;

    for (Enumeration e = vertices(); e.hasMoreElements(); ) {
      Vector2D vertex = (Vector2D) e.nextElement();

      // translate to origin
      double tmpX = vertex.getX() - x;
      double tmpY = vertex.getY() - y;

      // rotate
      double sin = Math.sin(theta);
      double cos = Math.cos(theta);

      double newX = tmpX * cos - tmpY * sin;
      double newY = tmpX * sin + tmpY * cos;

      // translate back to old location
      newX += x;
      newY += y;

      // set teh point to be where we calculated it should be
      vertex.setXY(newX, newY);
    }

    flagModified();
  }
예제 #4
0
  /** Generate the edges of this polygon */
  private void generateEdges() {
    if (haveEdgesChanged == true) {
      edges.removeAllElements();
      Vector2D first = null;
      Vector2D lastChecked = null;
      double x = 0;
      double y = 0;

      for (Enumeration e = vertices.elements(); e.hasMoreElements(); ) {
        Vector2D vertex = (Vector2D) e.nextElement();
        x += vertex.getX();
        y += vertex.getY();

        if (lastChecked == null) {
          first = vertex;
          lastChecked = first;
        } else {
          edges.addElement(new Line2D(lastChecked, vertex));
          lastChecked = vertex;
        }
      }
      if (first != null) {
        edges.addElement(new Line2D(lastChecked, first));
      }
    }

    haveEdgesChanged = false;
  }
예제 #5
0
  /**
   * Check if a point is contained within this polygon
   *
   * @param point
   * @return true if contained, false otherwise
   */
  public boolean contains(Vector2D point) {

    if (!getBounds().contains(point)) {
      System.out.println("AAA: " + point);
      return false;
    }

    Line2D verticalRay = new Line2D(point, new Vector2D(point.getX(), Double.POSITIVE_INFINITY));
    int intersectionCount = 0;
    boolean contains = false;

    generateEdges();

    for (Enumeration e = edges.elements(); e.hasMoreElements(); ) {
      Line2D testLine = (Line2D) e.nextElement();
      double minY = Math.min(testLine.getStart().getY(), testLine.getEnd().getY());
      double maxY = Math.max(testLine.getStart().getY(), testLine.getEnd().getY());

      if (testLine.getGradient() == Double.POSITIVE_INFINITY) {
        if (point.getX() == testLine.getStart().getX()
            && point.getY() >= minY
            && point.getY() <= maxY) {
          contains = true;
        }
      } else {
        if (verticalRay.intersects(testLine)) {
          intersectionCount++;
        }
      }
    }

    return (contains || (intersectionCount % 2 == 1));
  }
예제 #6
0
  /**
   * Translate the polygon by a vector offset
   *
   * @param offset
   */
  public void translate(Vector2D offset) {
    Enumeration e = vertices();
    while (e.hasMoreElements()) {
      Vector2D v = (Vector2D) e.nextElement();
      v.add(offset);
    }

    flagModified();
  }
예제 #7
0
  /**
   * Compute the (inward) normal of each node by taking a weighted average of the (inward) surface
   * normals of the edges connected to it. Longer edges are given more weight.
   */
  private void computeWeightedNormals() {
    for (int i = 0, n = nodeList.size(); i < n; i++) {
      Node prevNode = nodeList.get(i);
      Node curNode = nodeList.get((i + 1) % n);
      Node nextNode = nodeList.get((i + 2) % n);

      Vector2D prevVector = curNode.getPosition().subtract(prevNode.getPosition()).rotate270();
      Vector2D nextVector = nextNode.getPosition().subtract(curNode.getPosition()).rotate270();

      normals.put(curNode, prevVector.add(nextVector).normalize());
    }
  }
예제 #8
0
 private final void computeArea() {
   // The area of a quadrilateral is 0.5*p*q*sin(theta)
   // Where p and q are the length of the 2 diagonals and theta is the angle between them
   // If we rotate P in the right direction, then area = 0.5*p*q*cos(theta) where theta is
   // the angle between Q and the rotated P, but this is simply 0.5 * dot product of P' and Q
   // Note, it is possible because of the cos to get a negative area, when this happens, it means
   // that the quadrilateral has flipped and that the normally inward pointing normals are
   // now pointing outward, so if we get a negative area, we should flip the force vectors...
   Vector2D P = tv.getPosition().subtract(d.getPosition());
   Vector2D Q = dt.getPosition().subtract(v.getPosition());
   area = 0.5 * P.rotate90().dot(Q);
   if (Math.signum(area) != Math.signum(desiredArea) && desiredArea != 0) {
     System.err.println(
         "Compartment:" + this.toString() + " has flipped inside out. Area:" + area);
   }
 }
예제 #9
0
  /**
   * Compute the (inward) normal at each node by averaging the unit direction vectors of the two
   * edges connected to it.
   */
  private void computeNormals() {
    for (int i = 0, n = nodeList.size(); i < n; i++) {
      Node prevNode = nodeList.get(i);
      Node curNode = nodeList.get((i + 1) % n);
      Node nextNode = nodeList.get((i + 2) % n);

      Vector2D prevEdge = curNode.getPosition().subtract(prevNode.getPosition());
      Vector2D nextEdge = nextNode.getPosition().subtract(curNode.getPosition());

      double crossProd = prevEdge.crossMag(nextEdge);
      Vector2D normal =
          prevEdge.normalize().subtract(nextEdge.normalize()).scaleTo(Math.signum(crossProd));

      normals.put(curNode, normal);
    }
  }
예제 #10
0
    public void update() {
      // See Compute Area for reason of the absolute value and signum of area...
      double pressureForce =
          Constants.get().getPressure() * (Math.abs(area) - Math.abs(desiredArea));
      pressureForce =
          Math.signum(area) * Math.signum(pressureForce) * Math.sqrt(Math.abs(pressureForce));

      // The pressure is applied on every segment proportionally to its area.
      for (int i = 0, n = nodeList.size(); i < n; i++) {
        Node prevNode = nodeList.get(i);
        Node curNode = nodeList.get((i + 1) % n);
        Node nextNode = nodeList.get((i + 2) % n);

        Vector2D prevVector = curNode.getPosition().subtract(prevNode.getPosition()).rotate270();
        Vector2D nextVector = nextNode.getPosition().subtract(curNode.getPosition()).rotate270();
        forces.put(curNode, prevVector.scale(pressureForce).add(nextVector.scale(pressureForce)));
      }
    }
예제 #11
0
  /**
   * Get the midpoint of this polygon
   *
   * @return Midpoint
   */
  public Vector2D midPoint() {
    if (isMidPointChanged == true) {
      double x = 0;
      double y = 0;

      for (Enumeration e = vertices.elements(); e.hasMoreElements(); ) {
        Vector2D vertex = (Vector2D) e.nextElement();
        x += vertex.getX();
        y += vertex.getY();
      }

      midPoint = new Vector2D(x / vertices.size(), y / vertices.size());
      isMidPointChanged = false;

      return midPoint;
    } else {
      return midPoint;
    }
  }
예제 #12
0
    public void update() {
      Vector2D prevVector = main.getPosition().subtract(previous.getPosition());
      Vector2D nextVector = next.getPosition().subtract(main.getPosition());

      double angleRad =
          Math.acos(prevVector.dot(nextVector) / (prevVector.norm() * nextVector.norm()));
      double angle = Math.toDegrees(angleRad);
      if (prevVector.crossMag(nextVector) > 0) {
        angle = 360.0 - angle;
      }

      double forceMag = ANGLE_CONSTANT * (angle - 90.0);

      forces.put(previous, prevVector.rotate270().scaleTo(NEIGHBOR_ANGLE_SCALE * forceMag));
      forces.put(main, normals.get(main).scaleTo(forceMag));
      forces.put(next, nextVector.rotate270().scaleTo(NEIGHBOR_ANGLE_SCALE * forceMag));
    }
예제 #13
0
 /**
  * Rotate the polygon clockwise about a point by an arbritray angle.
  *
  * @param v Point vector to rotate about
  * @param angle Angle in radians
  */
 public void rotate(Vector2D v, double angle) {
   rotate(v.getX(), v.getY(), angle);
 }