Exemple #1
0
 public List<Vector2D> getShapeForDrawing() {
   List<Vector2D> theList = new ArrayList<Vector2D>();
   theList.add(d.getPosition());
   for (Node n : Arrays.asList(dt, tv, v)) {
     theList.add(n.getPosition());
   }
   return theList;
 }
Exemple #2
0
 public Shape getShape() {
   GeneralPath gp = new GeneralPath();
   gp.moveTo((float) d.getPosition().getX(), (float) d.getPosition().getY());
   for (Node n : Arrays.asList(dt, tv, v)) {
     gp.lineTo((float) n.getPosition().getX(), (float) n.getPosition().getY());
   }
   gp.closePath();
   return gp;
 }
Exemple #3
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);
   }
 }
Exemple #4
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));
    }
  /** used for cut and paste. */
  public void addObjectFromClipboard(String a_value) throws CircularIncludeException {
    Reader reader = new StringReader(a_value);
    Document document = null;
    try {
      document = UJAXP.getDocument(reader);
    } catch (Exception e) {
      e.printStackTrace();
      return;
    } // try-catch

    Element root = document.getDocumentElement();
    if (!root.getNodeName().equals("clipboard")) {
      return;
    } // if

    Node child;
    for (child = root.getFirstChild(); child != null; child = child.getNextSibling()) {
      if (!(child instanceof Element)) {
        continue;
      } // if
      Element element = (Element) child;

      IGlyphFactory factory = GlyphFactory.getFactory();

      if (XModule.isMatch(element)) {
        EModuleInvoke module = (EModuleInvoke) factory.createXModule(element);
        addModule(module);
        continue;
      } // if

      if (XContour.isMatch(element)) {
        EContour contour = (EContour) factory.createXContour(element);
        addContour(contour);
        continue;
      } // if

      if (XInclude.isMatch(element)) {
        EIncludeInvoke include = (EIncludeInvoke) factory.createXInclude(element);
        addInclude(include);
        continue;
      } // if
    } // while
  }
Exemple #6
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());
    }
  }
    @Override
    public SVGDocument toSVG(ConcreteDiagram cd) {
      /*
       * Use a Plain drawer to generate an SVG Document, then
       * "post-process" any SVG circles in the document to convert them
       * into "sketches".
       */
      SVGDocument document = (new PlainCircleSVGDrawer()).toSVG(cd);
      // return document;

      // find each circle in the document and turn it into a sketch. We
      // need to keep track of the circles and their eventual replacements
      // as each circle is replaced by 10's of smaller circles, thus the
      // DOM updates and we get the 10's of circles in our NodeList circles.
      NodeList circles = document.getElementsByTagName("circle");
      List<Node> replaceable = nodeListToList(circles);
      for (Node n : replaceable) {
        Node circleAsSketch = circleToSketch(document, (SVGCircleElement) n);
        n.getParentNode().replaceChild(circleAsSketch, n);
      }

      return document;
    }
Exemple #8
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);
    }
  }
Exemple #9
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)));
      }
    }
Exemple #10
0
  /**
   * Constructs a new compartment from four nodes
   *
   * @param d Dorsal node
   * @param dt Dorsal transversal Node
   * @param tv Ventral transversal node
   * @param v Ventral node
   */
  public Compartment(Node d, Node dt, Node tv, Node v) {
    this.d = d;
    this.dt = dt;
    this.tv = tv;
    this.v = v;
    nodeList = Arrays.asList(d, dt, tv, v);

    // Internal pressures
    pressure = new PressureInfluence();
    for (Node n : nodeList) {
      n.addInfluence(pressure);
    }

    // Muscles
    dorsal =
        new LongitudinalMuscleInfluence(d, dt, dt.getPosition().subtract(tv.getPosition()).norm());
    d.addInfluence(dorsal);
    dt.addInfluence(dorsal);
    transversal =
        new TransversalMuscleInfluence(dt, tv, dt.getPosition().subtract(d.getPosition()).norm());
    dt.addInfluence(transversal);
    tv.addInfluence(transversal);
    ventral =
        new LongitudinalMuscleInfluence(tv, v, dt.getPosition().subtract(tv.getPosition()).norm());
    tv.addInfluence(ventral);
    v.addInfluence(ventral);

    // Friction
    dorsalFriction = new AxialFrictionInfluence(dt, d);
    dt.addInfluence(dorsalFriction);
    ventralFriction = new AxialFrictionInfluence(tv, v);
    tv.addInfluence(ventralFriction);

    normals = new HashMap<Node, Vector2D>();

    pressureShapes = new ArrayList<Polygon>();

    computeArea();
    desiredArea = area;
  }