Пример #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;
 }
Пример #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;
 }
Пример #3
0
  private float getAngle(Node node1, Node node2) {
    PVector pos1 = node1.getPosition();
    PVector pos2 = node2.getPosition();

    float diffX = (pos2.x - pos1.x);
    float diffY = (pos2.y - pos1.y);

    if (diffX == 0) diffX = 0.001f;
    if (diffY == 0) diffY = 0.001f;

    return (float) Math.atan2(diffY, diffX);
  }
Пример #4
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());
    }
  }
Пример #5
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);
   }
 }
Пример #6
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);
    }
  }
Пример #7
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));
    }
Пример #8
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)));
      }
    }
Пример #9
0
  /**
   * Converts the node coordinates into display coordinates on the screen. If this problem uses
   * geographical weights, then the latitude/longitude coordinates are projected on the screen using
   * the Mercator projection.
   *
   * @param node the node whose display coordinates are calculated
   * @param isGeographical {@code true} if the coordinates are geographical; {@code false} otherwise
   * @return the node coordinates into display coordinates on the screen
   */
  private double[] toDisplayCoordinates(Node node, boolean isGeographical) {
    double[] position = node.getPosition();
    double x = position[1];
    double y = position[0];

    if (isGeographical) {
      x = GeographicalDistance.toGeographical(x);
      y = GeographicalDistance.toGeographical(y);
      x = 0.5 * Math.log((1.0 + Math.sin(x)) / (1.0 - Math.sin(x)));
    }

    return new double[] {x, y};
  }
Пример #10
0
  @Override
  public ZemObject eval(Interpreter interpreter) {
    boolean test =
        testCondition.eval(interpreter).toBoolean(testCondition.getPosition()).booleanValue();

    if (test) {
      return thenBlock.eval(interpreter);
    } else if (elseBlock != null) {
      return elseBlock.eval(interpreter);
    }

    return ZemBoolean.FALSE;
  }
  boolean adjustMinMax(long[] rangeMin, long[] rangeMax) {
    calcLimits(rangeMin, rangeMax);

    if (next >= this.maskUpper) {
      // we already fully traversed this node
      return false;
    }

    if (next < this.maskLower) {
      if (isHC) {
        currentOffsetKey = node.getBitPosIndex();
        next = START;
      } else if (isNI) {
        if (!useNiHcIncrementer) {
          niIterator.adjustMinMax(maskLower, maskUpper);
        } else {
          next = START;
        }
      } else {
        // LHC
        if (this.next + PhTree11.LHC_BINARY_SEARCH_THRESHOLD < this.maskLower) {
          int pin = node.getPosition(maskLower, dims);
          // If we don't find it we use the next following entry, i.e. -(pin+1)
          pin = pin >= 0 ? pin : -(pin + 1);
          currentOffsetKey = node.pinToOffsBitsLHC(pin, node.getBitPosIndex(), dims);
          nFound = pin;
        }
        // just set it to START, it is not used and will be set during the next iteration
        next = START;
      }
      return true;
    }

    if ((useHcIncrementer || useNiHcIncrementer) && !checkHcPos(next)) {
      // Adjust pos in HCI mode such that it works for the next inc()
      // At this point, next is >= maskLower
      long pos = next - 1;
      // After the following, pos==START or pos==(a valid entry such that inc(pos) is
      // the next valid entry after the original `next`)
      while (!checkHcPos(pos) && pos > START) {
        // normal iteration to ensure we to get a valid POS for HCI-inc()
        pos--;
      }
      next = pos;
    }
    return true;
  }
 private Node replaceNormalNode(
     Node normalNode, GKInstance diseaseEntity, Boolean needDashedBorder) {
   Node diseaseNode = normalToDiseaseNode.get(normalNode);
   if (diseaseNode != null) return diseaseNode;
   try {
     // If a node exists already, it should use
     for (Renderable r : diseaseComps) {
       if (diseaseEntity.getDBID().equals(r.getReactomeId()) && r instanceof Node) {
         // This is rather arbitrary: if two nodes are very close,
         // use the existing one.
         int dx = Math.abs(r.getPosition().x - normalNode.getPosition().x);
         int dy = Math.abs(r.getPosition().y - normalNode.getPosition().y);
         if (dx < 10 && dy < 10) {
           // We don't need to create a new Node if it exists already
           normalToDiseaseNode.put(normalNode, (Node) r);
           overlaidObjects.add(r); // Add it to overlaid object to cover edges
           return (Node) r;
         }
       }
     }
     diseaseNode = normalNode.getClass().newInstance();
     RenderUtility.copyRenderInfo(normalNode, diseaseNode);
     // The following should NOT be called since NodeAttachment is
     // related to disease entity only.
     // TODO: Need to support this. Currently it is not supported!!! See example
     // in PI3/AKT cancer pathway.
     // diseaseNode.setNodeAttachmentsLocally(node.getNodeAttachments());
     diseaseNode.setDisplayName(diseaseEntity.getDisplayName());
     diseaseNode.setReactomeId(diseaseEntity.getDBID());
     diseaseNode.invalidateBounds();
     diseaseNode.setRenderer(normalNode.getRenderer());
     diseaseNode.setLineColor(DefaultRenderConstants.DEFAULT_DISEASE_BACKGROUND);
     diseaseNode.setNeedDashedBorder(needDashedBorder);
     RenderUtility.hideCompartmentInNodeName(diseaseNode);
     overlaidObjects.add(diseaseNode);
     displayedObject.addComponent(diseaseNode);
     normalToDiseaseNode.put(normalNode, diseaseNode);
     return diseaseNode;
   } catch (Exception e) {
     e.printStackTrace();
   }
   return null;
 }
  private boolean getNextHCI(PhEntry<T> result) {
    // Ideally we would switch between b-serch-HCI and incr-search depending on the expected
    // distance to the next value.
    long currentPos = next;
    do {
      if (currentPos == START) {
        // starting position
        currentPos = maskLower;
      } else {
        currentPos = PhTree11.inc(currentPos, maskLower, maskUpper);
        if (currentPos <= maskLower) {
          return false;
        }
      }

      int pin = node.getPosition(currentPos, dims);
      if (pin >= 0 && readValue(pin, currentPos, result)) {
        next = currentPos;
        return true;
      }
    } while (true);
  }
Пример #14
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;
  }
Пример #15
0
  /**
   * Calculates the distance between two nodes. Uses position which is specified in the Node class.
   *
   * @return the distance between two nodes.
   */
  public float getDistance() {

    return node1.getPosition().dist(node2.getPosition());
  }