/** Constructor for child hull (has parent) */
  public ConvexHull(List<OrganismNode> nodes, String hullName, ConvexHull parent) {
    this.level = parent == null ? 1 : parent.getLevel() + 1;
    this.nodes = nodes;

    // Construct points as well as any children hull that exist
    this.points = new LinkedList<Point>();
    Map<String, List<OrganismNode>> childrenGroups = new HashMap<String, List<OrganismNode>>();
    for (OrganismNode o : nodes) {
      this.points.add(o.getCenter());
      if (o.getTypes().containsKey(level + 1)) {
        if (childrenGroups.containsKey(o.getTypes().get(level + 1)))
          childrenGroups.get(o.getTypes().get(level + 1)).add(o);
        else {
          List<OrganismNode> temp = new LinkedList<OrganismNode>();
          temp.add(o);
          childrenGroups.put(o.getTypes().get(level + 1), temp);
        }
      }
    }

    this.hullName = hullName;
    this.parent = parent;
    hull = new ArrayList<Point>();
    hullShape = new Polygon();
    if (points.size() < 3) {
      hull.addAll(points);
      for (Point p : hull) hullShape.addPoint(p.x, p.y);
    } else GrahamScan();

    children = new LinkedList<ConvexHull>();
    if (childrenGroups.size() > 0) {
      for (Map.Entry<String, List<OrganismNode>> e : childrenGroups.entrySet())
        children.add(new ConvexHull(e.getValue(), e.getKey(), this));
    }
    childCollisions = TBSUtils.hullCollisions(level, children);
  }
 /** Returns true for a point on the line, as determined algebraically */
 public boolean contains(int x, int y) {
   double dist = Math.abs(TBSUtils.getConnectionBounds(from, to).ptSegDist(new Point(x, y)));
   return dist < 1.5;
 }