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

com.googlecode.blaisemath.graph.layout.IterativeGraphLayoutManager Maven / Gradle / Ivy

/**
 * IterativeGraphLayoutManager.java
 * Created Jan 16, 2016
 */
package com.googlecode.blaisemath.graph.layout;

/*
 * #%L
 * BlaiseGraphTheory (v3)
 * --
 * Copyright (C) 2009 - 2018 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.base.Function;
import com.googlecode.blaisemath.annotation.InvokedFromThread;
import com.googlecode.blaisemath.graph.Graph;
import com.googlecode.blaisemath.graph.IterativeGraphLayout;
import com.googlecode.blaisemath.graph.IterativeGraphLayoutState;
import com.googlecode.blaisemath.util.coordinate.CoordinateChangeEvent;
import com.googlecode.blaisemath.util.coordinate.CoordinateListener;
import com.googlecode.blaisemath.util.coordinate.CoordinateManager;
import java.awt.geom.Point2D;
import java.util.Map;

/**
 * 

* Manages an iterative graph layout, including its state and parameters. * This class is not thread safe. *

* @author elisha */ public final class IterativeGraphLayoutManager { /** Default # iterations per layout step */ private static final int DEFAULT_ITER_PER_LOOP = 2; /** Cooling curve. Determines the cooling parameter at each step, as a product of initial cooling parameter. */ private static final Function COOLING_CURVE = new Function(){ @Override public Double apply(Integer x) { return .1 + .9/Math.log10(x+10.0); } }; /** The graph for layouts */ private Graph graph; /** The coordinate manager to update after layout */ private CoordinateManager coordManager; /** Listener for coordinate updates */ private final CoordinateListener coordListener; /** Contains the algorithm for iterating graph layouts. */ private IterativeGraphLayout layout; /** State for the iterative layout */ private IterativeGraphLayoutState state; /** Parameters for the iterative layout */ private Object params; /** Layout iteration number. */ private int iteration = 0; /** # of iterations per loop */ private int iterPerLoop = DEFAULT_ITER_PER_LOOP; // public IterativeGraphLayoutManager() { this.coordListener = new CoordinateListener(){ @InvokedFromThread("unknown") @Override public void coordinatesChanged(CoordinateChangeEvent evt) { requestPositions(((CoordinateManager)evt.getSource()).getActiveLocationCopy(), true); } }; setCoordinateManager(CoordinateManager.create(GraphLayoutManager.NODE_CACHE_SIZE)); } // // public IterativeGraphLayout getLayout() { return layout; } public void setLayout(IterativeGraphLayout layout) { if (this.layout != layout) { this.layout = layout; reset(); } } public Graph getGraph() { return graph; } public void setGraph(Graph graph) { this.graph = graph; } public CoordinateManager getCoordinateManager() { return coordManager; } public void setCoordinateManager(CoordinateManager coordManager) { CoordinateManager old = this.coordManager; if (old != coordManager) { if (old != null) { old.removeCoordinateListener(coordListener); } this.coordManager = coordManager; coordManager.addCoordinateListener(coordListener); } } public IterativeGraphLayoutState getState() { return state; } /** * Get parameters associated with the current layout. * @return parameters */ public Object getParameters() { return params; } /** * Set parameters for the current layout * @param params new parameters */ public void setParameters(Object params) { this.params = params; } /** * Get the # of algorithm iterations per update loop * @return iterations */ public int getIterationsPerLoop() { return iterPerLoop; } /** * Set the # of algorithm iterations per update loop * @param iter # of iterations */ public void setIterationsPerLoop(int iter) { this.iterPerLoop = iter; } // /** * Re-initialize the graph layout, resetting iteration, state, and params. * If the type of params is still valid for the new layout, it is not changed. */ void reset() { if (layout == null) { state = null; params = null; } else { state = layout.createState(); state.requestPositions(coordManager.getActiveLocationCopy(), true); Object newParams = layout.createParameters(); Class oldParamsType = params == null ? null : params.getClass(); Class newParamsType = newParams == null ? null : newParams.getClass(); if (newParamsType != oldParamsType) { params = newParams; } } iteration = 0; } /** * Perform a single layout loop. Depending on the manager's settings, this * may invoke the background graph layout 1 or more times. * @return energy of last loop * @throws InterruptedException if layout interrupted after an intermediate iteration */ public double runOneLoop() throws InterruptedException { double energy = 0; for (int i = 0; i < iterPerLoop; i++) { energy = layout.iterate(graph, state, params); checkInterrupt(); } coordManager.setCoordinateMap(state.getPositionsCopy()); iteration += iterPerLoop; state.setCoolingParameter(COOLING_CURVE.apply(Math.max(0, iteration - 100))); checkInterrupt(); return energy; } private void checkInterrupt() throws InterruptedException { if (Thread.interrupted()) { throw new InterruptedException("Layout canceled"); } } // public void requestPositions(Map loc, boolean resetNodes) { if (state != null) { state.requestPositions(loc, resetNodes); } } // }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy