All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.celldynamics.quimp.PointsList Maven / Gradle / Ivy

Go to download

QuimP software, a set of plugins for ImageJ to quantify spatio-temporal patterns of fluorescently labeled proteins in the cortex of moving cells.

The newest version!
package com.github.celldynamics.quimp;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.celldynamics.quimp.geom.ExtendedVector2d;

/**
 * Represents node of bidirectional list of points in Cartesian coordinates.
 * 
 * 

This abstract class contains basic properties of points and provides method for moving across * the * list. Points in list are numbered from 1 and list can be looped. There is one special node * called head that indicates beginning of the list (and its end if the list is looped). * PointList is assumed to be infinite long and may not be looped. * * @author p.baniukiewicz * * @param Type of point, currently can be Node or Vert */ public abstract class PointsList> { /** * The Constant LOGGER. */ static final Logger LOGGER = LoggerFactory.getLogger(PointsList.class.getName()); /** * Previous point in list, null if no other point. */ protected transient T prev; /** * Next point in list, null if no other point. */ protected transient T next; /** * x,y co-ordinates of the point. */ protected ExtendedVector2d point; /** * Normal vector. Calculated by * {@link com.github.celldynamics.quimp.PointsList#updateNormale(boolean)} and implicitly by * {@link com.github.celldynamics.quimp.Shape#updateNormals(boolean)} from Shape during * serialization and deserialization and changing the shape of Shape */ protected ExtendedVector2d normal; /** * tangent vector. Calculated by com.github.celldynamics.quimp.PointsList.calcTan(). Implicitly * during calculating normals (see normal) */ protected ExtendedVector2d tan; /** * Indicate if this point is head. */ protected boolean head = false; /** * The clockwise. access clockwise if true. */ private static boolean clockwise = true; /** * ID number of point, unique across list. Given during adding point to list, controlled by * Shape */ protected int tracknumber = 1; /** * Normalized position on list. * *

0 - beginning , 1 - end of the list according to Shape perimeter. Set by * com.github.celldynamics.quimp.Shape.setPositions() and called before and after serialise and on * Shape writing. */ protected double position = -1; /** * flag which is set when the velocity is below the critical velocity. */ private boolean frozen = false; /** * Default constructor, assumes that first point is created on list with ID = 1. */ public PointsList() { point = new ExtendedVector2d(); normal = new ExtendedVector2d(); tan = new ExtendedVector2d(); } /** * Create point with given ID. New point is not linked to any other yet. * *

Caller should care about correct numbering of points * * @param t ID of point */ public PointsList(int t) { this(); setTrackNum(t); } /** * Copy constructor. Make copy of properties of passed point. * *

Previous or next points are not copied * * @param src Source Point */ public PointsList(final PointsList src) { this.point = new ExtendedVector2d(src.point); this.normal = new ExtendedVector2d(src.normal); this.tan = new ExtendedVector2d(src.tan); this.head = src.head; this.tracknumber = src.tracknumber; this.position = src.position; this.frozen = src.frozen; } /** * Creates point with given ID and coordinates. New point is not linked to any other yet. * *

Caller should care about correct numbering of points * * @param xx x coordinate of point * @param yy y coordinate of point * @param t ID of point */ public PointsList(double xx, double yy, int t) { this(t); point = new ExtendedVector2d(xx, yy); } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (frozen ? 1231 : 1237); result = prime * result + (head ? 1231 : 1237); result = prime * result + ((normal == null) ? 0 : normal.hashCode()); result = prime * result + ((point == null) ? 0 : point.hashCode()); long temp; temp = Double.doubleToLongBits(position); result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + ((tan == null) ? 0 : tan.hashCode()); result = prime * result + tracknumber; return result; } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof PointsList)) { return false; } PointsList other = (PointsList) obj; if (frozen != other.frozen) { return false; } if (head != other.head) { return false; } if (normal == null) { if (other.normal != null) { return false; } } else if (!normal.equals(other.normal)) { return false; } if (point == null) { if (other.point != null) { return false; } } else if (!point.equals(other.point)) { return false; } if (Double.doubleToLongBits(position) != Double.doubleToLongBits(other.position)) { return false; } if (tan == null) { if (other.tan != null) { return false; } } else if (!tan.equals(other.tan)) { return false; } if (tracknumber != other.tracknumber) { return false; } return true; } /** * point getter. * * @return X space co-ordinate */ public double getX() { return point.getX(); } /** * point getter. * * @return Y space co-ordinate */ public double getY() { return point.getY(); } /** * Set X space co-ordinate. * * @param x coordinate */ public void setX(double x) { point.setX(x); } /** * Set Y space co-ordinate. * * @param y coordinate */ public void setY(double y) { point.setY(y); } /** * Sets the clockwise. * * @param b the new clockwise */ public static void setClockwise(boolean b) { PointsList.clockwise = b; } /** * Gets the point. * * @return the point */ public ExtendedVector2d getPoint() { return point; } /** * Gets the track num. * * @return the track num */ public int getTrackNum() { return tracknumber; } /** * Gets the normal. * * @return the normal */ public ExtendedVector2d getNormal() { return normal; } /** * Gets the tangent. * * @return the tangent */ public ExtendedVector2d getTangent() { return tan; } /** * Get normalised position of node. * * @return the position */ public double getPosition() { return position; } /** * Set normalised position of node. * * @param position the position to set */ public void setPosition(double position) { this.position = position; } /** * Checks if is head. * * @return true, if is head */ public boolean isHead() { return head; } /** * Sets the normal. * * @param x the x * @param y the y */ public void setNormal(double x, double y) { normal.setX(x); normal.setY(y); } /** * Sets the track num. * * @param b the new track num */ public void setTrackNum(int b) { tracknumber = b; } /** * Set head marker to current node. * *

Warning * *

Only one Node in Snake can be head * * @param t true if current node is head, false otherwise * @see com.github.celldynamics.quimp.Snake#setHead(int) * @see com.github.celldynamics.quimp.Snake */ public void setHead(boolean t) { head = t; } /** * Get previous node in chain (next if not clockwise). * * @return next or previous Node from list */ public T getPrev() { if (clockwise) { return prev; } else { return next; } } /** * Get next node in chain (previous if not clockwise). * * @return previous or next Node from list */ public T getNext() { if (clockwise) { return next; } else { return prev; } } /** * Adds previous (or next if not clockwise) Node to list. * * @param n Node to add */ public void setPrev(T n) { if (clockwise) { prev = n; } else { next = n; } } /** * Adds next (or previous if not clockwise) Node to list. * * @param n Node to add */ public void setNext(T n) { if (clockwise) { next = n; } else { prev = n; } } /** * Updates the normal (must point inwards). * * @param inner inner */ public void updateNormale(boolean inner) { boolean c = clockwise; clockwise = true; // just in case tan = calcTan(); // tangent if (!inner) { // switch around if expanding snake normal.setX(-tan.getY()); normal.setY(tan.getX()); } else { normal.setX(tan.getY()); normal.setY(-tan.getX()); } clockwise = c; } /** * Calculate tangent at current point (i.e. unit vector between neighbours). * *

Calculate a unit vector towards neighbouring nodes and then a unit vector between their * ends. * direction important for normale calculation. Always calculate tan as if clockwise. * * @return Tangent at point */ private ExtendedVector2d calcTan() { ExtendedVector2d unitVecLeft = ExtendedVector2d.unitVector(point, prev.getPoint()); ExtendedVector2d pointLeft = new ExtendedVector2d(); pointLeft.setX(getX()); pointLeft.setY(getY()); pointLeft.addVec(unitVecLeft); ExtendedVector2d unitVecRight = ExtendedVector2d.unitVector(point, next.getPoint()); ExtendedVector2d pointRight = new ExtendedVector2d(); pointRight.setX(getX()); pointRight.setY(getY()); pointRight.addVec(unitVecRight); return ExtendedVector2d.unitVector(pointLeft, pointRight); } /** * Set direction of list. */ public static void randDirection() { if (Math.random() < 0.5) { clockwise = true; } else { clockwise = false; } } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { return "PointsList [point=" + point + ", normal=" + normal + ", tan=" + tan + ", head=" + head + ", tracknumber=" + tracknumber + ", position=" + position + ", frozen=" + frozen + "]"; } /** * Freeze Point. */ public void freeze() { frozen = true; } /** * Unfreeze Point. */ public void unfreeze() { frozen = false; } /** * Getter to frozen field. * * @return frozen */ public boolean isFrozen() { return frozen; } /** * Evaluate local curvature of T related to previous, this and next T. * * @return Local curvature for this node in degrees */ public double getCurvatureLocal() { ExtendedVector2d edge1 = ExtendedVector2d.vecP2P(this.getPoint(), this.getPrev().getPoint()); ExtendedVector2d edge2 = ExtendedVector2d.vecP2P(this.getPoint(), this.getNext().getPoint()); double angle = ExtendedVector2d.angle(edge1, edge2) * (180 / Math.PI); if (angle > 360 || angle < -360) { LOGGER.warn("Warning-angle out of range (Vert l:320)"); } if (angle < 0) { angle = 360 + angle; } double curvatureLocal = 0; if (angle == 180) { curvatureLocal = 0; } else if (angle < 180) { curvatureLocal = -1 * (1 - (angle / 180)); } else { curvatureLocal = (angle - 180) / 180; } return curvatureLocal; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy