// used by tests protected void forceTreeSplit(int depth) { if (depth <= treeRoot.maxNodeDepth && this.depth < depth) { split(); for (AbstractQuadTreeNode<E> child : children) { child.forceTreeSplit(depth); } } }
/** * Ajoute tous les éléments contenus dans cette node et ses enfants dans <code>collection</code> * * @param collection */ protected void getAllElements(Collection<E> collection) { collection.addAll(elements); if (children != null) { for (AbstractQuadTreeNode<E> child : children) { child.getAllElements(collection); } } }
/** * Ajoute cette node et toutes les sous-nodes dans <code>collection</code> * * @param collection */ protected void getAllNodes(Collection<QuadTreeNodeInterface<E>> collection) { collection.add(this); if (children != null) { for (AbstractQuadTreeNode<E> child : children) { child.getAllNodes(collection); } } }
/** * Renvoie dans <code>collection</code> toutes les nodes à la profondeur indiquée * * @param collection la collection dans laquelleajouter les nodes * @param depth */ protected void getAllNodesAtDepth(Collection<QuadTreeNodeInterface<E>> collection, int depth) { if (this.depth == depth) { collection.add(this); } else if (this.depth < depth) { if (children != null) { for (AbstractQuadTreeNode<E> child : children) { child.getAllNodesAtDepth(collection, depth); } } } }
// retourne le noeud voisin d'un noeud (algorithme générique) private QuadTreeNodeInterface<E> sibling( AbstractQuadTreeNode<E> node, int[] ancestortype, int[] reverter) { int[] path = new int[treeRoot.maxNodeDepth + 1]; int pathlength = 0; // recherche du plus proche ancetre commun AbstractQuadTreeNode<E> ancestor = node; while (true) { if (ancestor.getPositionInParentNode() == ROOT) { return null; // no common ancestor -> exit } path[pathlength] = ancestor.getPositionInParentNode(); pathlength++; if (ancestor.getPositionInParentNode() == ancestortype[0]) { ancestor = ancestor.getParent(); break; } if (ancestor.getPositionInParentNode() == ancestortype[1]) { ancestor = ancestor.getParent(); break; } ancestor = ancestor.getParent(); } // parcours de l'arbre en utilisant le chemin symetrique AbstractQuadTreeNode<E> cursor = ancestor, next = null; for (int i = pathlength - 1; i >= 0; i--) { if (cursor.children == null) break; next = cursor.children.get(reverter[path[i]]); if (next == null) break; cursor = next; } return cursor; }
/** @return le chemin pour accéder à cette node sous une forme du type (ROOT)123012 etc. */ public String getCompactPath() { if (parent == this) { return ""; } else { return parent.getCompactPath() + positionInParentNode; } }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((parent == null) ? 0 : parent.hashCode()); result = prime * result + ((splitPoint == null) ? 0 : splitPoint.hashCode()); return result; }
/** * Supprime une instance de <code>e</code> de cette node. Utilise le QuadTree pour localiser * l'objet à supprimer. Effectue un clear() sur le parent si il s'agissait du dernier élément * contenu dans la node parent * * @param e L'objet à supprimer * @return <code>true</code> si l'élément a été supprimé */ public boolean remove(E e) { if (e == null) { return false; } AbstractQuadTreeNode<E> node = (AbstractQuadTreeNode<E>) getElementNode(e); if (node == null) { return false; } else { boolean ret = node.elements.remove(e); // vérification : est ce que cet élément était le dernier élément contenu dans la node parent. // Si oui : effacer les enfants dans le parent. if (parent.isEmpty()) { parent.clear(); } return ret; } }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; @SuppressWarnings("unchecked") AbstractQuadTreeNode<E> other = (AbstractQuadTreeNode<E>) obj; if (parent == null) { if (other.parent != null) return false; } else if (!parent.equals(other.parent)) return false; if (splitPoint == null) { if (other.splitPoint != null) return false; } else if (!splitPoint.equals(other.splitPoint)) return false; return true; }
public AbstractQuadTreeNode(AbstractQuadTreeNode<E> parent, int positionInParentNode) { this.parent = parent; this.depth = parent.getDepth() + 1; this.treeRoot = parent.getTreeRoot(); this.positionInParentNode = positionInParentNode; this.elements = new ArrayList<E>(treeRoot.maxElementsPerNode); switch (positionInParentNode) { case NW: maxX = parent.getSplitPoint().x; maxY = parent.getMaxY(); minX = parent.getMinX(); minY = parent.getSplitPoint().y; break; case NE: maxX = parent.getMaxX(); maxY = parent.getMaxY(); minX = parent.getSplitPoint().x; minY = parent.getSplitPoint().y; break; case SW: maxX = parent.getSplitPoint().x; maxY = parent.getSplitPoint().y; minX = parent.getMinX(); minY = parent.getMinY(); break; case SE: maxX = parent.getMaxX(); maxY = parent.getSplitPoint().y; minX = parent.getSplitPoint().x; minY = parent.getMinY(); break; } this.splitPoint = new Point2D.Double((maxX + minX) / 2, (maxY + minY) / 2); }