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

edu.uci.ics.jung.visualization.spatial.rtree.RStarLeafSplitter Maven / Gradle / Ivy

package edu.uci.ics.jung.visualization.spatial.rtree;

import static edu.uci.ics.jung.visualization.spatial.rtree.Node.M;
import static edu.uci.ics.jung.visualization.spatial.rtree.Node.m;

import com.google.common.collect.Lists;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * splits a Collection of Map.Entries according to R*-Tree semantics
 *
 * @param 
 */
public class RStarLeafSplitter implements LeafSplitter {

  private static final Logger log = LoggerFactory.getLogger(RStarLeafSplitter.class);
  private final Comparator> horizontalEdgeComparator =
      new HorizontalEdgeMapEntryComparator();
  private final Comparator> verticalEdgeComparator =
      new VerticalEdgeMapEntryComparator();

  public Pair> split(
      Collection> entries, Map.Entry newEntry) {
    return chooseSplitNodes(entries, newEntry);
  }

  private Pair> chooseSplitNodes(
      Collection> entries, Map.Entry newEntry) {
    Pair>> pair = chooseSplit(entries, newEntry);
    LeafNode leafNodeLeft = LeafNode.create(pair.left);
    LeafNode leafNodeRight = LeafNode.create(pair.right);
    return Pair.of(leafNodeLeft, leafNodeRight);
  }

  /**
   * R*-Tree method
   *
   * @param entries
   * @param newEntry
   * @return
   */
  private Pair>> chooseSplit(
      Collection> entries, Map.Entry newEntry) {
    // make 2 lists to sort
    List> xAxisList = Lists.newArrayList(entries);
    xAxisList.add(newEntry);
    List> yAxisList = Lists.newArrayList(entries);
    yAxisList.add(newEntry);

    // sort them by min value then max value
    xAxisList.sort(horizontalEdgeComparator);
    yAxisList.sort(verticalEdgeComparator);

    // create containers for the 2 lists to split
    List>>> horizontalGroup = Lists.newArrayList();
    List>>> verticalGroup = Lists.newArrayList();

    // iterate over the lists to create collections with different midpoints
    for (int k = 0; k < M - 2 * m + 2; k++) {
      horizontalGroup.add(
          Pair.of(xAxisList.subList(0, m - 1 + k), xAxisList.subList(m - 1 + k, xAxisList.size())));
      verticalGroup.add(
          Pair.of(yAxisList.subList(0, m - 1 + k), yAxisList.subList(m - 1 + k, yAxisList.size())));
    }
    if (log.isTraceEnabled()) {
      log.trace("horizontalGroup size is {}", horizontalGroup.size());
      for (Pair>> pair : horizontalGroup) {
        log.trace("size of pair lists are {} and {}", pair.left.size(), pair.right.size());
      }
      log.trace("verticalGroup size is {}", verticalGroup.size());
      for (Pair>> pair : verticalGroup) {
        log.trace("size of pair lists are {} and {}", pair.left.size(), pair.right.size());
      }
    }

    // sum up the margin values from each group
    int sumXMarginValue = 0;
    for (Pair>> pair : horizontalGroup) {
      sumXMarginValue += Node.entryMargin(pair.left, pair.right);
    }
    int sumYMarginValue = 0;
    for (Pair>> pair : verticalGroup) {
      sumYMarginValue += Node.entryMargin(pair.left, pair.right);
    }
    // use the group (horizontal or vertical) that has the smallest margin value su
    if (sumXMarginValue < sumYMarginValue) {
      // split on x axis
      return chooseSplitIndex(horizontalGroup);
    } else {
      // split on y axis
      return chooseSplitIndex(verticalGroup);
    }
  }

  /**
   * R*-Tree method
   *
   * @param group
   * @return
   */
  private Pair>> chooseSplitIndex(
      List>>> group) {
    double minOverlap = 0;
    double minArea = 0;
    Optional>>> winner = Optional.empty();
    // find the Pair of lists with the mim overlap or min area
    for (Pair>> pair : group) {
      double nodeOverlap = Node.entryOverlap(pair.left, pair.right);
      double nodeArea = Node.entryArea(pair.left, pair.right);
      // no winner yet. first node wins by default
      if (!winner.isPresent()) {
        minOverlap = nodeOverlap;
        minArea = nodeArea;
        winner = Optional.of(pair);
      } else if (nodeOverlap == minOverlap) {
        // tie for overlap, try area
        if (nodeArea < minArea) {
          minOverlap = nodeOverlap;
          minArea = nodeArea;
          winner = Optional.of(pair);
        }
      } else if (nodeOverlap < minOverlap) {
        // winner has the smallest overlap
        minOverlap = nodeOverlap;
        minArea = nodeArea;
        winner = Optional.of(pair);
      }
    }
    return winner.orElse(null);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy