⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtree.java 1.3

📁 R-Tree Java implementations 结构清晰
💻 3
📖 第 1 页 / 共 3 页
字号:
          } else if (newNodeIncrease < nIncrease) {
            nextGroup = 1;
          } else if (n.mbr.area() < newNode.mbr.area()) {
            nextGroup = 0;
          } else if (newNode.mbr.area() < n.mbr.area()) {
            nextGroup = 1;
          } else if (newNode.entryCount < maxNodeEntries / 2) {
            nextGroup = 0;
          } else {
            nextGroup = 1;
          }
          maxDifference = difference; 
        }
        if (log.isDebugEnabled()) {
          log.debug("Entry " + i + " group0 increase = " + nIncrease + ", group1 increase = " + newNodeIncrease +
                    ", diff = " + difference + ", MaxDiff = " + maxDifference + " (entry " + next + ")");
        }
      }
    }
    
    entryStatus[next] = ENTRY_STATUS_ASSIGNED;
    
    if (visualization) {
      int s = (nextGroup == 0 ? VisualizeNodeSplit.STATUS_ASSIGNED_TO_GROUP0 :
                                VisualizeNodeSplit.STATUS_ASSIGNED_TO_GROUP1);
      vns.setRectangleStatus(n.entries[next], n.isLeaf(), n.ids[next], s);
      vns.redraw();
    }
      
    if (nextGroup == 0) {
      n.mbr.add(n.entries[next]);
      n.entryCount++;
    } else {
      // move to new node.
      newNode.addEntryNoCopy(n.entries[next], n.ids[next]);
      n.entries[next] = null;
    }
    
    if (visualization) {
      vns.setRectangleStatus(n.mbr, false, n.nodeId, VisualizeNodeSplit.STATUS_MBR_GROUP0);
      vns.setRectangleStatus(newNode.mbr, false, newNode.nodeId, VisualizeNodeSplit.STATUS_MBR_GROUP1);      
      vns.redraw();
    }
    
    return next; 
  }

  /**
   * Recursively searches the tree for the nearest entry. Other queries
   * call execute() on an IntProcedure when a matching entry is found; 
   * however nearest() must store the entry Ids as it searches the tree,
   * in case a nearer entry is found.
   * Uses the member variable nearestIds to store the nearest
   * entry IDs.
   * 
   * [x] TODO rewrite this to be non-recursive?
   */
  private void nearest(Point p, Node n, float nearestDistance) {
    for (int i = 0; i < n.entryCount; i++) {
      float tempDistance = n.entries[i].distance(p);  
      if (n.isLeaf()) { // for leaves, the distance is an actual nearest distance 
        if (tempDistance <= nearestDistance) {
          nearestIds.add(n.ids[i]);
          nearestDistance = tempDistance;
        }     
      } else { // for index nodes, only go into them if they potentially could have
               // a rectangle nearer than actualNearest
         if (tempDistance < nearestDistance) {
           // search the child node
           nearest(p, getNode(n.ids[i]), nearestDistance);
         }
      }
    }
  }
  
  /** 
   * Recursively searches the tree for all intersecting entries.
   * Immediately calls execute() on the passed IntProcedure when 
   * a matching entry is found.
   * 
   * [x] TODO rewrite this to be non-recursive? Make sure it
   * doesn't slow it down.
   */
  private void intersects(Rectangle r, IntProcedure v, Node n) {
    for (int i = 0; i < n.entryCount; i++) {
      if (r.intersects(n.entries[i])) {
        if (n.isLeaf()) {
          v.execute(n.ids[i]);
        } else {
          Node childNode = getNode(n.ids[i]);
          intersects(r, v, childNode);
        }
      }
    }
  }

  /**
   * Used by delete(). Ensures that all nodes from the passed node
   * up to the root have the minimum number of entries.
   * 
   * Note that the parent and parentEntry stacks are expected to
   * contain the nodeIds of all parents up to the root.
   */
  Rectangle oldRectangle = new Rectangle(0, 0, 0, 0);
  private void condenseTree(Node l) {
    // CT1 [Initialize] Set n=l. Set the list of eliminated
    // nodes to be empty.
    Node n = l;
    Node parent = null;
    int parentEntry = 0;
    
    TIntStack eliminatedNodeIds = new TIntStack();
  
    // CT2 [Find parent entry] If N is the root, go to CT6. Otherwise 
    // let P be the parent of N, and let En be N's entry in P  
    while (n.level != treeHeight) {
      parent = getNode(parents.pop());
      parentEntry = parentsEntry.pop();
      
      // CT3 [Eliminiate under-full node] If N has too few entries,
      // delete En from P and add N to the list of eliminated nodes
      if (n.entryCount < minNodeEntries) {
        parent.deleteEntry(parentEntry, minNodeEntries);
        eliminatedNodeIds.push(n.nodeId);
      } else {
        // CT4 [Adjust covering rectangle] If N has not been eliminated,
        // adjust EnI to tightly contain all entries in N
        if (!n.mbr.equals(parent.entries[parentEntry])) {
          oldRectangle.set(parent.entries[parentEntry].min, parent.entries[parentEntry].max);
          parent.entries[parentEntry].set(n.mbr.min, n.mbr.max);
          parent.recalculateMBR(oldRectangle);
        }
      }
      // CT5 [Move up one level in tree] Set N=P and repeat from CT2
      n = parent;
    }
    
    // CT6 [Reinsert orphaned entries] Reinsert all entries of nodes in set Q.
    // Entries from eliminated leaf nodes are reinserted in tree leaves as in 
    // Insert(), but entries from higher level nodes must be placed higher in 
    // the tree, so that leaves of their dependent subtrees will be on the same
    // level as leaves of the main tree
    while (eliminatedNodeIds.size() > 0) {
      Node e = getNode(eliminatedNodeIds.pop());
      for (int j = 0; j < e.entryCount; j++) {
        add(e.entries[j], e.ids[j], e.level); 
        e.entries[j] = null;
      }
      e.entryCount = 0;
      deletedNodeIds.push(e.nodeId);
    }
  }

  /**
   *  Used by add(). Chooses a leaf to add the rectangle to.
   */
  private Node chooseNode(Rectangle r, int level) {
    // CL1 [Initialize] Set N to be the root node
    Node n = getNode(rootNodeId);
    parents.clear();
    parentsEntry.clear();
     
    // CL2 [Leaf check] If N is a leaf, return N
    while (true) {
      if (n == null) {
        System.out.println("Could not get root node (" + rootNodeId + ")");  
      }
   
      if (n.level == level) {
        return n;
      }
      
      // CL3 [Choose subtree] If N is not at the desired level, let F be the entry in N 
      // whose rectangle FI needs least enlargement to include EI. Resolve
      // ties by choosing the entry with the rectangle of smaller area.
      float leastEnlargement = n.getEntry(0).enlargement(r);
      int index = 0; // index of rectangle in subtree
      for (int i = 1; i < n.entryCount; i++) {
        Rectangle tempRectangle = n.getEntry(i);
        float tempEnlargement = tempRectangle.enlargement(r);
        if ((tempEnlargement < leastEnlargement) ||
            ((tempEnlargement == leastEnlargement) && 
             (tempRectangle.area() < n.getEntry(index).area()))) {
          index = i;
          leastEnlargement = tempEnlargement;
        }
      }
      
      parents.push(n.nodeId);
      parentsEntry.push(index);
    
      // CL4 [Descend until a leaf is reached] Set N to be the child node 
      // pointed to by Fp and repeat from CL2
      n = getNode(n.ids[index]);
    }
  }
  
  /**
   * Ascend from a leaf node L to the root, adjusting covering rectangles and
   * propagating node splits as necessary.
   */
  private Node adjustTree(Node n, Node nn) {
    // AT1 [Initialize] Set N=L. If L was split previously, set NN to be 
    // the resulting second node.
    
    // AT2 [Check if done] If N is the root, stop
    while (n.level != treeHeight) {
    
      // AT3 [Adjust covering rectangle in parent entry] Let P be the parent 
      // node of N, and let En be N's entry in P. Adjust EnI so that it tightly
      // encloses all entry rectangles in N.
      Node parent = getNode(parents.pop());
      int entry = parentsEntry.pop(); 
      
      if (parent.ids[entry] != n.nodeId) {
        log.error("Error: entry " + entry + " in node " + 
             parent.nodeId + " should point to node " + 
             n.nodeId + "; actually points to node " + parent.ids[entry]);
      }
      
      if (!parent.entries[entry].equals(n.mbr)) {
        parent.entries[entry].set(n.mbr.min, n.mbr.max);
        parent.mbr.set(parent.entries[0].min, parent.entries[0].max);
        for (int i = 1; i < parent.entryCount; i++) {
          parent.mbr.add(parent.entries[i]);
        }
      }
      
      // AT4 [Propagate node split upward] If N has a partner NN resulting from 
      // an earlier split, create a new entry Enn with Ennp pointing to NN and 
      // Enni enclosing all rectangles in NN. Add Enn to P if there is room. 
      // Otherwise, invoke splitNode to produce P and PP containing Enn and
      // all P's old entries.
      Node newNode = null;
      if (nn != null) {
        if (parent.entryCount < maxNodeEntries) {
          parent.addEntry(nn.mbr, nn.nodeId);
        } else {
          newNode = splitNode(parent, nn.mbr.copy(), nn.nodeId);
        }
      }
      
      // AT5 [Move up to next level] Set N = P and set NN = PP if a split 
      // occurred. Repeat from AT2
      n = parent;
      nn = newNode;
      
      parent = null;
      newNode = null;
    }
    
    return nn;
  }
  
  /**
   * Check the consistency of the tree.
   */
  private void checkConsistency(int nodeId, int expectedLevel, Rectangle expectedMBR) {
    // go through the tree, and check that the internal data structures of 
    // the tree are not corrupted.    
    Node n = getNode(nodeId);
    
    if (n == null) {
      log.error("Error: Could not read node " + nodeId);
    }
    
    if (n.level != expectedLevel) {
      log.error("Error: Node " + nodeId + ", expected level " + expectedLevel + ", actual level " + n.level);
    }
    
    Rectangle calculatedMBR = calculateMBR(n);
    
    if (!n.mbr.equals(calculatedMBR)) {
      log.error("Error: Node " + nodeId + ", calculated MBR does not equal stored MBR");
    }
    
    if (expectedMBR != null && !n.mbr.equals(expectedMBR)) {
      log.error("Error: Node " + nodeId + ", expected MBR (from parent) does not equal stored MBR");
    }
    
    // Check for corruption where a parent entry is the same object as the child MBR
    if (expectedMBR != null && n.mbr.sameObject(expectedMBR)) {
      log.error("Error: Node " + nodeId + " MBR using same rectangle object as parent's entry");
    }
    
    for (int i = 0; i < n.entryCount; i++) {
      if (n.entries[i] == null) {
        log.error("Error: Node " + nodeId + ", Entry " + i + " is null");
      }     
      
      if (n.level > 1) { // if not a leaf
        checkConsistency(n.ids[i], n.level - 1, n.entries[i]); 
      }   
    } 
  }
  
  /**
   * Given a node object, calculate the node MBR from it's entries.
   * Used in consistency checking
   */
  private Rectangle calculateMBR(Node n) {
    Rectangle mbr = new Rectangle(n.entries[0].min, n.entries[0].max);
    
    for (int i = 1; i < n.entryCount; i++) {
      mbr.add(n.entries[i]);
    }
    return mbr; 
  }
  
  /**
   * Computes a checksum for the RTree. The checksum depends only on the entries
   * in the RTree, and is independent of the RTree variant or its properties.
   */
  private long getChecksum() {
  	final SpatialIndexChecksum c = new SpatialIndexChecksum();
    nodeMap.forEachValue(new TObjectProcedure() {
      public boolean execute(Object o) {
      	Node n = (Node) o;
      	if (n.isLeaf()) {
          for (int i = 0; i < n.getEntryCount(); i++) {
            c.update(n.entries[i], n.ids[i]);
          }
      	}
      	return true;
      }	
    });
    return c.getValue();
  }  
  
  
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -