Skip to content

Commit

Permalink
Spatial index in graph view (#202)
Browse files Browse the repository at this point in the history
* Move spatial index to Graph so it can be used in graph views

* Fix

* Add documentation

---------

Co-authored-by: Eduardo Ramos <[email protected]>
  • Loading branch information
mbastian and eduramiba authored Jun 12, 2024
1 parent d006714 commit 2bbedf3
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 45 deletions.
2 changes: 1 addition & 1 deletion src/main/java/org/gephi/graph/api/Configuration.java
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ public boolean isEnableEdgeProperties() {
* If enabled, the spatial index is updated while node positions are updated. If
* unused, disabling it is recommended as it adds some overhead.
* <p>
* The spatial index can be retrieved from {@link GraphModel#getSpatialIndex()}.
* The spatial index can be retrieved from {@link Graph#getSpatialIndex()}.
* <p>
* Default is <code>false</code>.
*
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/org/gephi/graph/api/Graph.java
Original file line number Diff line number Diff line change
Expand Up @@ -557,4 +557,11 @@ public interface Graph {
* @return graph lock
*/
GraphLock getLock();

/**
* Returns the spatial index.
*
* @return spatial index
*/
SpatialIndex getSpatialIndex();
}
7 changes: 0 additions & 7 deletions src/main/java/org/gephi/graph/api/GraphModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -683,13 +683,6 @@ public static interface DefaultColumns {
*/
public GraphObserver createGraphObserver(Graph graph, boolean withGraphDiff);

/**
* Returns the spatial index.
*
* @return spatial index
*/
public SpatialIndex getSpatialIndex();

/**
* Returns the time format used to display time.
*
Expand Down
55 changes: 54 additions & 1 deletion src/main/java/org/gephi/graph/api/Rect2D.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,39 @@ public Rect2D(float minX, float minY, float maxX, float maxY) {
this.maxY = maxY;
}

/**
* Return the rectangle's width.
*
* @return the rectangle's width
*/
public float width() {
return maxX - minX;
}

/**
* Return the rectangle's height.
*
* @return the rectangle's height
*/
public float height() {
return maxY - minY;
}

/**
* Return the rectangle's center, as an array where the first element is the x
* coordinate and the second element is the y coordinate.
*
* @return the rectangle's center
*/
public float[] center() {
return new float[] { (maxX + minX) / 2, (maxY + minY) / 2 };
}

/**
* Return the rectangle's radius.
*
* @return the rectangle's radius
*/
public float radius() {
float width = width();
float height = height();
Expand All @@ -92,11 +113,17 @@ public String toString() {
return toString(FORMAT);
}

public String toString(NumberFormat formatter) {
private String toString(NumberFormat formatter) {
return "(" + formatter.format(minX) + " " + formatter.format(minY) + ") < " + "(" + formatter
.format(maxX) + " " + formatter.format(maxY) + ")";
}

/**
* Returns true if this rectangle contains the given rectangle.
*
* @param rect the rectangle to check
* @return true if this rectangle contains, false otherwise
*/
public boolean contains(Rect2D rect) {
if (rect == this) {
return true;
Expand All @@ -105,6 +132,12 @@ public boolean contains(Rect2D rect) {
return contains(rect.minX, rect.minY, rect.maxX, rect.maxY);
}

/**
* Returns true if this rectangle intersects the given rectangle.
*
* @param rect the rectangle to check
* @return true if this rectangle intersects, false otherwise
*/
public boolean intersects(Rect2D rect) {
if (rect == this) {
return true;
Expand All @@ -113,10 +146,30 @@ public boolean intersects(Rect2D rect) {
return intersects(rect.minX, rect.minY, rect.maxX, rect.maxY);
}

/**
* Returns true if this rectangle contains the given rectangle.
*
* @param minX the x coordinate of the minimum corner
* @param minY the y coordinate of the minimum corner
* @param maxX the x coordinate of the maximum corner
* @param maxY the y coordinate of the maximum corner
*
* @return true if this rectangle contains, false otherwise
*/
public boolean contains(float minX, float minY, float maxX, float maxY) {
return this.minX <= minX && this.minY <= minY && this.maxX >= maxX && this.maxY >= maxY;
}

/**
* Returns true if this rectangle intersects the given rectangle.
*
* @param minX the x coordinate of the minimum corner
* @param minY the y coordinate of the minimum corner
* @param maxX the x coordinate of the maximum corner
* @param maxY the y coordinate of the maximum corner
*
* @return true if this rectangle intersects, false otherwise
*/
public boolean intersects(float minX, float minY, float maxX, float maxY) {
return this.minX <= maxX && minX <= this.maxX && this.maxY >= minY && maxY >= this.minY;
}
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/org/gephi/graph/api/SpatialIndex.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,19 @@
*/
public interface SpatialIndex {

/**
* Returns the nodes in the given area.
*
* @param rect area to query
* @return nodes in the area
*/
NodeIterable getNodesInArea(Rect2D rect);

/**
* Returns the edges in the given area.
*
* @param rect area to query
* @return edges in the area
*/
EdgeIterable getEdgesInArea(Rect2D rect);
}
8 changes: 0 additions & 8 deletions src/main/java/org/gephi/graph/impl/GraphModelImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -369,14 +369,6 @@ public TimeIndex<Edge> getEdgeTimeIndex(GraphView view) {
return null;
}

@Override
public SpatialIndex getSpatialIndex() {
if (!configuration.isEnableSpatialIndex()) {
throw new UnsupportedOperationException("Spatial index is disabled (from Configuration)");
}
return store.spatialIndex;
}

@Override
public GraphObserver createGraphObserver(Graph graph, boolean withGraphDiff) {
store.autoWriteLock();
Expand Down
27 changes: 10 additions & 17 deletions src/main/java/org/gephi/graph/impl/GraphStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,8 @@
import java.util.List;
import java.util.Objects;
import java.util.Set;
import org.gephi.graph.api.Configuration;
import org.gephi.graph.api.DirectedGraph;
import org.gephi.graph.api.DirectedSubgraph;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.EdgeIterable;
import org.gephi.graph.api.ElementIterable;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.GraphView;
import org.gephi.graph.api.Interval;
import org.gephi.graph.api.Node;
import org.gephi.graph.api.NodeIterable;
import org.gephi.graph.api.Origin;
import org.gephi.graph.api.Subgraph;
import org.gephi.graph.api.Table;
import org.gephi.graph.api.TimeFormat;
import org.gephi.graph.api.TimeRepresentation;

import org.gephi.graph.api.*;
import org.gephi.graph.api.types.IntervalSet;
import org.gephi.graph.api.types.TimestampSet;

Expand Down Expand Up @@ -721,6 +706,14 @@ public GraphLockImpl getLock() {
return lock;
}

@Override
public SpatialIndex getSpatialIndex() {
if (spatialIndex == null) {
throw new UnsupportedOperationException("Spatial index is disabled (from Configuration)");
}
return spatialIndex;
}

protected void autoReadLock() {
if (configuration.isEnableAutoLocking()) {
readLock();
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/org/gephi/graph/impl/GraphViewDecorator.java
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,14 @@ public Graph getRootGraph() {
return graphStore;
}

@Override
public SpatialIndex getSpatialIndex() {
if (graphStore.spatialIndex == null) {
throw new UnsupportedOperationException("Spatial index is disabled (from Configuration)");
}
return this;
}

void checkWriteLock() {
if (graphStore.lock != null) {
graphStore.lock.checkHoldWriteLock();
Expand Down Expand Up @@ -821,12 +829,18 @@ boolean isUndirectedToIgnore(final EdgeImpl edge) {

@Override
public NodeIterable getNodesInArea(Rect2D rect) {
if (graphStore.spatialIndex == null) {
throw new UnsupportedOperationException("Spatial index is disabled (from Configuration)");
}
Iterator<Node> iterator = graphStore.spatialIndex.getNodesInArea(rect).iterator();
return new NodeIterableWrapper(new NodeViewIterator(iterator), graphStore.spatialIndex.nodesTree.lock);
}

@Override
public EdgeIterable getEdgesInArea(Rect2D rect) {
if (graphStore.spatialIndex == null) {
throw new UnsupportedOperationException("Spatial index is disabled (from Configuration)");
}
Iterator<Edge> iterator = graphStore.spatialIndex.getEdgesInArea(rect).iterator();
return new EdgeIterableWrapper(new EdgeViewIterator(iterator), graphStore.spatialIndex.nodesTree.lock);
}
Expand Down
18 changes: 7 additions & 11 deletions src/main/java/org/gephi/graph/impl/UndirectedDecorator.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,8 @@

import java.util.Collection;
import java.util.Set;
import org.gephi.graph.api.Edge;
import org.gephi.graph.api.EdgeIterable;
import org.gephi.graph.api.Graph;
import org.gephi.graph.api.GraphModel;
import org.gephi.graph.api.GraphView;
import org.gephi.graph.api.Interval;
import org.gephi.graph.api.Node;
import org.gephi.graph.api.NodeIterable;
import org.gephi.graph.api.Subgraph;
import org.gephi.graph.api.UndirectedGraph;
import org.gephi.graph.api.UndirectedSubgraph;

import org.gephi.graph.api.*;

public class UndirectedDecorator implements UndirectedGraph, UndirectedSubgraph {

Expand Down Expand Up @@ -422,4 +413,9 @@ public void not() {
public Graph getRootGraph() {
return this;
}

@Override
public SpatialIndex getSpatialIndex() {
return store.getSpatialIndex();
}
}
5 changes: 5 additions & 0 deletions src/test/java/org/gephi/graph/impl/BasicGraphStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -1712,4 +1712,9 @@ public void doBreak() {
// Not used because no locking
}
}

@Override
public SpatialIndex getSpatialIndex() {
return null;
}
}

0 comments on commit 2bbedf3

Please sign in to comment.