com.googlecode.blaisemath.graph.layout.SpringLayoutState Maven / Gradle / Ivy
package com.googlecode.blaisemath.graph.layout;
/*
* #%L
* BlaiseGraphTheory (v3)
* --
* Copyright (C) 2009 - 2019 Elisha Peterson
* --
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import com.google.common.collect.Lists;
import com.googlecode.blaisemath.graph.IterativeGraphLayoutState;
import java.awt.geom.Point2D;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* State object for spring layout. This tracks node locations and velocities, and divides node space up into regions to allow for more efficient
* layout calculations. This class may be safely modified by multiple threads simultaneously.
* @param graph node type
* @author Elisha Peterson
*/
public final class SpringLayoutState extends IterativeGraphLayoutState {
private static final Logger LOG = Logger.getLogger(SpringLayoutState.class.getName());
/** # of regions away from origin in x and y directions. Region size is determined by the maximum repel distance. */
private static final int REGION_N = 5;
/** Regions used for localizing computation */
LayoutRegion[][] regions;
/** Points that are not in a region */
LayoutRegion oRegion;
/** List of all regions */
List> allRegions;
//region UPDATERS
Point2D.Double getLoc(N io) {
return loc.get(io);
}
void putLoc(N io, Point2D.Double pt) {
loc.put(io, pt);
}
Point2D.Double getVel(N io) {
return vel.get(io);
}
void putVel(N io, Point2D.Double pt) {
vel.put(io, pt);
}
//endregion
//region MANAGING REGIONS
/** Updates the alignment of points to region */
void updateRegions(double regionSz) {
if (regions == null) {
initRegions();
}
for (LayoutRegion r : allRegions) {
r.clear();
}
for (Map.Entry en : loc.entrySet()) {
LayoutRegion r = regionByLoc(en.getValue(), regionSz);
if (r != null) {
r.put(en.getKey(), en.getValue());
} else {
LOG.log(Level.WARNING, "Point not in any region: {0}", en);
}
}
}
/** Return region for specified point */
private LayoutRegion regionByLoc(Point2D.Double p, double regionSz) {
int ix = (int) ((p.x + REGION_N * regionSz) / regionSz);
int iy = (int) ((p.y + REGION_N * regionSz) / regionSz);
if (ix < 0 || ix > 2 * REGION_N || iy < 0 || iy > 2 * REGION_N) {
return oRegion;
}
return regions[ix][iy];
}
/** Initializes regions */
private void initRegions() {
regions = new LayoutRegion[2 * REGION_N + 1][2 * REGION_N + 1];
allRegions = Lists.newArrayList();
for (int ix = -REGION_N; ix <= REGION_N; ix++) {
for (int iy = -REGION_N; iy <= REGION_N; iy++) {
LayoutRegion region = new LayoutRegion();
regions[ix + REGION_N][iy + REGION_N] = region;
allRegions.add(region);
}
}
// set up adjacencies
for (int ix = -REGION_N; ix <= REGION_N; ix++) {
for (int iy = -REGION_N; iy <= REGION_N; iy++) {
for (int ix2 = Math.max(ix - 1, -REGION_N); ix2 <= Math.min(ix + 1, REGION_N); ix2++) {
for (int iy2 = Math.max(iy - 1, -REGION_N); iy2 <= Math.min(iy + 1, REGION_N); iy2++) {
regions[ix + REGION_N][iy + REGION_N].addAdjacentRegion(regions[ix2 + REGION_N][iy2 + REGION_N]);
}
}
}
}
// set up adjacencies with outer region
oRegion = new LayoutRegion<>();
allRegions.add(oRegion);
oRegion.addAdjacentRegion(oRegion);
for (int ix = -REGION_N; ix <= REGION_N; ix++) {
LayoutRegion min = regions[ix + REGION_N][0];
LayoutRegion max = regions[ix + REGION_N][2 * REGION_N];
min.addAdjacentRegion(oRegion);
max.addAdjacentRegion(oRegion);
oRegion.addAdjacentRegion(min);
oRegion.addAdjacentRegion(max);
}
for (int iy = -REGION_N + 1; iy <= REGION_N - 1; iy++) {
LayoutRegion min = regions[0][iy + REGION_N];
LayoutRegion max = regions[2 * REGION_N][iy + REGION_N];
min.addAdjacentRegion(oRegion);
max.addAdjacentRegion(oRegion);
oRegion.addAdjacentRegion(min);
oRegion.addAdjacentRegion(max);
}
}
//endregion
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy