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; }
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; }
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); }
/** * 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()); } }
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); } }
/** * 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); } }
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)); }
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))); } }
/** * 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}; }
@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); }
/** * 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; }
/** * 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()); }