Merging MK revs 298:303 - simple plot legend, some additions for statistics on feasibility

This commit is contained in:
Marcel Kronfeld 2009-06-22 15:44:24 +00:00
parent 52d707f0e0
commit 014258e1a4
14 changed files with 587 additions and 174 deletions

View File

@ -30,6 +30,7 @@ import java.util.ArrayList;
import java.util.Date;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
@ -57,9 +58,12 @@ public class FunctionArea extends DArea implements Serializable {
private ScaledBorder m_Border;
private boolean m_log = false;
private boolean notifyNegLog = true;
private boolean m_legend = true;
private int m_x;
private int m_y;
private GraphPointSetLegend legendBox = null;
private DPointIcon m_CurrentPointIcon;
/**
*
@ -90,6 +94,16 @@ public class FunctionArea extends DArea implements Serializable {
notifyNegLog = true;
}
/**
* Set a legend for the function area. If null is given, the former legend is deactivated.
*
* @param lBox
*/
protected void setLegend(GraphPointSetLegend lBox) {
legendBox=lBox;
if (lBox!=null && m_legend) repaint();
}
/**
* Plot a circle icon to the function area which is annotated with a char and
* a double value.
@ -172,7 +186,7 @@ public class FunctionArea extends DArea implements Serializable {
popRep.setIcon(icon);
addDElement(popRep);
}
/**
*
*/
@ -181,8 +195,8 @@ public class FunctionArea extends DArea implements Serializable {
if ((m_PointSetContainer == null) || (m_PointSetContainer.size() == 0))
return ret;
int minindex = getNearestGraphIndex(x, y);
ret = ((GraphPointSet) (m_PointSetContainer.get(minindex))).getInfoString();
return ret;
if (minindex>=0) return ((GraphPointSet) (m_PointSetContainer.get(minindex))).getInfoString();
else return "none";
}
/**
@ -196,8 +210,7 @@ public class FunctionArea extends DArea implements Serializable {
ret = ((GraphPointSet) (m_PointSetContainer.get(minindex))).isStatisticsGraph();
return ret;
}
/**
*
*/
@ -209,20 +222,18 @@ public class FunctionArea extends DArea implements Serializable {
DPoint point2 = null;
double dist = 0;
for (int i = 0; i < m_PointSetContainer.size(); i++) {
if (m_PointSetContainer.get(i)instanceof GraphPointSet) {
GraphPointSet pointset = (GraphPointSet) (m_PointSetContainer.get(i));
point2 = pointset.getNearestDPoint(point1);
if (point2 == null)
continue;
if (point1 == null)
System.err.println("point1 == null");
GraphPointSet pointset = m_PointSetContainer.get(i);
point2 = pointset.getNearestDPoint(point1);
if (point2 == null)
continue;
if (point1 == null)
System.err.println("point1 == null");
dist = (point1.x - point2.x) * (point1.x - point2.x) + (point1.y - point2.y) * (point1.y - point2.y);
//System.out.println("dist="+dist+"i="+i);
if (dist < distmin) {
distmin = dist;
minindex = i;
}
dist = (point1.x - point2.x) * (point1.x - point2.x) + (point1.y - point2.y) * (point1.y - point2.y);
//System.out.println("dist="+dist+"i="+i);
if (dist < distmin) {
distmin = dist;
minindex = i;
}
}
return minindex;
@ -350,7 +361,13 @@ public class FunctionArea extends DArea implements Serializable {
}
/**
@Override
public void paint(Graphics g) {
super.paint(g);
if (legendBox!=null && (m_legend)) legendBox.paintIn(g, m_Border.getInnerRect(this));
}
/**
*
*/
public void setConnectedPoint(double[] p, int graphLabel) {
@ -428,6 +445,7 @@ public class FunctionArea extends DArea implements Serializable {
return;
int GraphLabel = ((GraphPointSet) (this.m_PointSetContainer.get(index))).getGraphLabel();
clearGraph(GraphLabel);
updateLegend();
}
/**
@ -439,6 +457,7 @@ public class FunctionArea extends DArea implements Serializable {
return;
int GraphLabel = ((GraphPointSet) (this.m_PointSetContainer.get(index))).getGraphLabel();
changeColorGraph(GraphLabel);
updateLegend();
}
/**
@ -589,7 +608,7 @@ public class FunctionArea extends DArea implements Serializable {
//setVisibleRectangle( 0.001, 0.001, 100000, 1000 );
setYScale(new Exp());
m_Border.setSrcdY(Math.log(10));
((java.text.DecimalFormat) m_Border.format_y).applyPattern("0.###E0");
m_Border.applyPattern(false, "0.###E0");
m_log = true;
} else {
m_log = false;
@ -769,6 +788,14 @@ public class FunctionArea extends DArea implements Serializable {
}
if (FunctionArea.this.m_PointSetContainer.size() > 0) {
JMenuItem togLegend = new JMenuItem("Toggle legend");
togLegend.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ee) {
toggleLegend();
}
});
GraphMenu.add(togLegend);
JMenuItem removeGraph = new JMenuItem("Remove graph");
removeGraph.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ee) {
@ -776,8 +803,7 @@ public class FunctionArea extends DArea implements Serializable {
}
});
GraphMenu.add(removeGraph);
}
if (FunctionArea.this.m_PointSetContainer.size() > 0) {
JMenuItem changecolorGraph = new JMenuItem("Change color");
changecolorGraph.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ee) {
@ -785,8 +811,7 @@ public class FunctionArea extends DArea implements Serializable {
}
});
GraphMenu.add(changecolorGraph);
}
if (FunctionArea.this.m_PointSetContainer.size() > 0) {
JMenuItem removePoint = new JMenuItem("Remove point");
removePoint.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ee) {
@ -795,36 +820,13 @@ public class FunctionArea extends DArea implements Serializable {
});
GraphMenu.add(removePoint);
}
// if (isStatisticsGraph(e.getX(),e.getY())==true) {
// if (getVar(e.getX(),e.getY())==false) {
// JMenuItem showVar = new JMenuItem("Show varianz ");
// showVar.addActionListener(new ActionListener() {
// //
// public void actionPerformed(ActionEvent ee) {
// setVar(m_x,m_y,true);
// }
// });
// GraphMenu.add(showVar);
// }
// else {
// JMenuItem hideVar = new JMenuItem("Hide varianz ");
// hideVar.addActionListener(new ActionListener() {
// //
// public void actionPerformed(ActionEvent ee) {
// setVar(m_x,m_y,false);
// }
// });
// GraphMenu.add(hideVar);
// }
// }
GraphMenu.show(FunctionArea.this, e.getX(), e.getY());
}
}
});
}
/** This method allows to add a selection listner to the PointIcon
/** This method allows to add a selection listener to the PointIcon
* it should need more than one listener to this abstruse event
* @param a The selection listener
*/
@ -832,17 +834,37 @@ public class FunctionArea extends DArea implements Serializable {
this.m_RefPointListener = a;
}
/** This method returns the selection listner to the PointIcon
/** This method returns the selection listener to the PointIcon
* @return InterfaceSelectionListener
*/
public InterfaceRefPointListener getRefPointSelectionListener() {
return this.m_RefPointListener;
}
/** This method allows to remove the selection listner to the PointIcon
/** This method allows to remove the selection listener to the PointIcon
*/
public void removeRefPointSelectionListeners() {
this.m_RefPointListener = null;
}
/**
* Recreate the legend object with the current point sets.
*
*/
public void updateLegend() {
GraphPointSetLegend lb = new GraphPointSetLegend(m_PointSetContainer);
setLegend(lb);
}
/**
* Reset the legend clearing all information.
*/
public void clearLegend() {
setLegend(null);
}
private void toggleLegend() {
m_legend=!m_legend;
repaint();
}
}

View File

@ -27,7 +27,7 @@ import java.util.Arrays;
*
*/
public class GraphPointSet {
private String m_InfoString = "InfoString";
private String m_InfoString = "Incomplete_Run";
private int m_GraphLabel;
private int colorOffset = 0;
private ArrayList m_PointSetContainer = new ArrayList();

View File

@ -0,0 +1,118 @@
package eva2.gui;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import wsi.ra.chart2d.SlimRect;
import eva2.tools.Pair;
/**
* A class representing the legend of a plot. It is created from a list of GraphPointSets as
* used in FunctionArea. Painting is done in FunctionArea. As an alternative, an own frame
* could be created.
*
* @author mkron
*
*/
public class GraphPointSetLegend {
Pair<String,Color>[] legendEntries;
public GraphPointSetLegend(List<GraphPointSet> pointSetContainer) {
legendEntries = new Pair[pointSetContainer.size()];
for (int i = 0; i < pointSetContainer.size(); i++) {
GraphPointSet pointset = pointSetContainer.get(i);
legendEntries[i] = new Pair<String,Color>(pointset.getInfoString(), pointset.getColor());
}
}
/**
* Add the legend labels to a container.
* @param comp
*/
public void addToContainer(JComponent comp) {
for (int i = 0; i < legendEntries.length; i++) {
JLabel label = new JLabel(legendEntries[i].head);
label.setForeground(legendEntries[i].tail);
comp.add(label);
}
}
public static JPanel makeLegendPanel(Color bgCol, ArrayList<GraphPointSet> pointSetContainer) {
JPanel pan = new JPanel();
pan.setBackground(bgCol);
pan.setLayout(new BoxLayout(pan, BoxLayout.Y_AXIS));
GraphPointSetLegend lBox=new GraphPointSetLegend(pointSetContainer);
lBox.addToContainer(pan);
return pan;
}
public static JFrame makeLegendFrame(Color bgCol, ArrayList<GraphPointSet> pointSetContainer) {
JFrame frame = new JFrame("Legend");
// LegendBox lBox = new LegendBox(bgCol, pointSetContainer);
frame.add(makeLegendPanel(bgCol, pointSetContainer));
frame.pack();
frame.setVisible(true);
return frame;
}
public void paintIn(JComponent component) {
Graphics g = component.getGraphics();
FontMetrics fm = g.getFontMetrics();
int yOffs=5+fm.getHeight();
int xOffs=0;
Color origCol = g.getColor();
for (int i=0; i<legendEntries.length; i++) {
g.setColor(legendEntries[i].tail);
Rectangle2D rect = fm.getStringBounds(legendEntries[i].head, g);
xOffs = (int) (component.getWidth()-rect.getWidth()-5);
g.drawString(legendEntries[i].head, xOffs, yOffs);
yOffs+=(5+rect.getHeight());
}
g.setColor(origCol);
}
// public void paintIn(Graphics g, Dimension dim) {
// paintIn(g, dim.width);
// }
//
// public void paintIn(Graphics g, Rectangle rect) {
// paintIn(g, rect.width);
// }
//
// public void paintIn(Graphics g, DRectangle rect) {
// paintIn(g, (int)rect.width);
// }
public void paintIn(Graphics g, SlimRect rect) {
paintIn(g, (int)rect.getX(), (int)rect.getY(), (int)rect.getX()+(int)rect.getWidth());
}
private void paintIn(Graphics g, int x, int y, int maxX) {
FontMetrics fm = g.getFontMetrics();
// System.out.println("In LegendBox.paintIn!");
int yOffs=5+y+fm.getHeight();
int xOffs=x;
Color origCol = g.getColor();
for (int i=0; i<legendEntries.length; i++) {
g.setColor(legendEntries[i].tail);
Rectangle2D stringBounds = fm.getStringBounds(legendEntries[i].head, g);
xOffs = (int) (maxX-stringBounds.getWidth()-5);
g.drawString(legendEntries[i].head, xOffs, yOffs);
// g.drawString(legendEntries[i].head, 80, 80);
yOffs+=(5+stringBounds.getHeight());
}
g.setColor(origCol);
}
}

View File

@ -68,6 +68,10 @@ public class GraphWindow {
return (m_Plotter != null) && (m_Plotter.isValid());
}
public PlotInterface getPlotter() {
return m_Plotter;
}
/**
*
*/
@ -101,7 +105,7 @@ public class GraphWindow {
*/
public Graph getNewGraph(String InfoString) {
m_GraphCounter++;
if (TRACE) System.out.println("Graph.getNewGraph No:"+m_GraphCounter);
if (TRACE) System.out.println("Graph.getNewGraph No:"+m_GraphCounter + " - " + InfoString);
return new Graph (InfoString,m_Plotter,m_GraphCounter);
}
}

View File

@ -327,6 +327,7 @@ public class Plot implements PlotInterface, Serializable {
public void clearAll () {
m_PlotArea.clearAll();
m_PlotArea.removeAllDElements();
m_PlotArea.clearLegend();
m_Frame.repaint();
}
/**
@ -443,6 +444,7 @@ public class Plot implements PlotInterface, Serializable {
public String getName() {
return this.m_PlotName;
}
/**
*
*/

View File

@ -50,6 +50,7 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
private double m_ConstraintViolation = 0;
public boolean m_AreaConst4ParallelViolated = false;
public boolean m_Marked = false; // is for GUI only!
public boolean m_isPenalized = false; // may be set true for penalty based constraints
protected double[] m_SelectionProbability = new double[1];;
public double m_CrossoverProbability = 1.0;
@ -144,6 +145,7 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
m_ConstraintViolation = individual.m_ConstraintViolation;
m_AreaConst4ParallelViolated = individual.m_AreaConst4ParallelViolated;
m_Marked = individual.m_Marked;
m_isPenalized = individual.m_isPenalized;
individualIndex = individual.individualIndex;
if (individual.parentIDs != null) {
parentIDs = new Long[individual.parentIDs.length];
@ -447,6 +449,7 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
* individual
*/
public void resetConstraintViolation() {
m_isPenalized=false;
this.m_ConstraintViolation = 0;
}
@ -494,6 +497,21 @@ public abstract class AbstractEAIndividual implements IndividualInterface, java.
this.m_Marked = true;
}
/**
* Allows marking an individual as infeasible if fitness penalty is used.
* @return
*/
public boolean isMarkedPenalized() {
return m_isPenalized;
}
/**
* Allows marking an individual as infeasible if fitness penalty is used.
* @return
*/
public void SetMarkPenalized(boolean p) {
m_isPenalized=p;
}
/** This method can be used to read the current fitness of the individual.
* Please note that the fitness can be based on multiple criteria therefore
* double[] is used instead of a single double.

View File

@ -444,6 +444,50 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
return getIndexOfBestOrWorstIndividual(false, false, fitIndex);
}
/**
* Return the best feasible individual or null if the population contains
* no or only infeasible individuals. This considers both aspects: the constraint setting
* as well as penalization. An individual is feasible only if it is both unpenalized and
* not violating the constraints.
*
* @param fitIndex
* @return the best feasible individual or null if none is feasible
*/
public AbstractEAIndividual getBestFeasibleIndividual(int fitIndex) {
int index=getIndexOfBestOrWorstFeasibleIndividual(true, fitIndex);
if (index<0) return null;
else return getEAIndividual(index);
}
// /**
// * Return the best individual which has a zero penalty value (is feasible concerning
// * penalty). If all are penalized, null is returned.
// *
// * @param fitIndex
// * @return
// */
// public AbstractEAIndividual getBestUnpenalizedIndividual(int fitIndex) {
// int result = -1;
// double[] curSelFitness = null;
// boolean allViolate = true;
//
// for (int i = 0; i < super.size(); i++) {
// if (!(getEAIndividual(i).isMarkedPenalized())) {
// allViolate = false;
// if ((result<0) || (compareFit(true, getEAIndividual(i).getFitness(), curSelFitness, fitIndex))) {
// // fit i is better than remembered
// result = i;
// curSelFitness = getEAIndividual(i).getFitness(); // remember fit i
// }
// }
// }
// if (allViolate) {
// return null;
// } else {
// return getEAIndividual(result);
// }
// }
/**
* This method will return the index of the current best (worst) individual from the
* population. If indicated, only those are regarded which do not violate the constraints.
@ -485,7 +529,8 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
minViol = ((AbstractEAIndividual)super.get(i)).getConstraintViolation();
}
}
System.err.println("Population reports: All individuals violate the constraints, choosing smallest constraint violation.");
// System.err.println("Population reports: All individuals violate the constraints, choosing smallest constraint violation.");
// this is now really reported nicer...
} else {
// not all violate, maybe all are NaN!
// so just select a random one
@ -496,6 +541,31 @@ public class Population extends ArrayList implements PopulationInterface, Clonea
return result;
}
/**
* Search the population for the best (worst) considering the given criterion (or all criteria
* for fitIndex<0) which also does not violate constraints.
* Returns -1 if no feasible solution is found, else the index of the best feasible solution.
*
* @param bBest
* @param fitIndex
* @return -1 if no feasible solution is found, else the index of the best feasible individual
*/
public int getIndexOfBestOrWorstFeasibleIndividual(boolean bBest, int fitIndex) {
int result = -1;
double[] curSelFitness = null;
for (int i = 0; i < super.size(); i++) {
if (!(getEAIndividual(i).violatesConstraint()) && !(getEAIndividual(i).isMarkedPenalized())) {
if ((result<0) || (compareFit(bBest, getEAIndividual(i).getFitness(), curSelFitness, fitIndex))) {
// fit i is better than remembered
result = i;
curSelFitness = getEAIndividual(i).getFitness(); // remember fit i
}
}
}
return result;
}
/**
* This method returns the current best individual from the population.
* If the population is empty, null is returned.

View File

@ -11,10 +11,20 @@ import eva2.gui.BeanInspector;
import eva2.server.go.IndividualInterface;
import eva2.server.go.PopulationInterface;
import eva2.server.go.individuals.AbstractEAIndividual;
import eva2.server.go.populations.Population;
import eva2.server.go.problems.InterfaceAdditionalPopulationInformer;
import eva2.tools.Mathematics;
/**
* An abstract class handling statistics. Most important stuff happens in startOptPerformed, stopOptPerformed
* and createNextGenerationPerformed. Any measures (run based or multi-run based) are reset in startOptPerformed,
* updated per iteration in createNextGenerationPerformed and reported to listeners in stopOptPerformed.
* Several different verbosity levels are regarded.
* The method plotCurrentResults should be implemented to plot further results per iteration.
*
* @author mkron
*
*/
public abstract class AbstractStatistics implements InterfaceTextListener, InterfaceStatistics {
private PrintWriter resultOut;
public final static boolean TRACE = false;
@ -42,14 +52,19 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
protected int functionCalls;
protected int functionCallSum;
protected int convergenceCnt;
protected int feasibleFoundAfter;
protected int numOfRunsFeasibleFound;
protected double feasibleFoundAfterSum;
protected int optRunsPerformed;
protected double[] currentBestFit;
protected double[] currentBestFeasibleFit;
protected double[] meanBestFeasibleFit;
protected double[] meanFitness;
protected double[] currentWorstFit;
protected double[] meanBestOfRunFitness;
protected double avgPopDist;
protected double maxPopDist;
protected IndividualInterface bestCurrentIndividual, bestRunIndividual, bestIndividualAllover;
protected IndividualInterface bestCurrentIndividual, bestRunIndividual, bestRunFeasibleIndy, bestIndividualAllover;
private ArrayList<InterfaceTextListener> textListeners;
@ -121,11 +136,17 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
initOutput(infoString);
bestIndividualAllover = null;
meanBestOfRunFitness = null;
meanBestFeasibleFit = null;
if (refineMultiRuns) meanCollection = new ArrayList<double[][]>();
else meanCollection = null;
feasibleFoundAfterSum=-1;
numOfRunsFeasibleFound=0;
}
feasibleFoundAfter=-1;
bestCurrentIndividual = null;
bestRunIndividual = null;
currentBestFeasibleFit=null;
bestRunFeasibleIndy = null;
runIterCnt = 0;
if (printRunIntroVerbosity()) printToTextListener("\n****** Multirun "+runNumber);
if (params != null) {
@ -165,6 +186,32 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
meanBestOfRunFitness=bestRunIndividual.getFitness().clone();
} else addMean(meanBestOfRunFitness, bestRunIndividual.getFitness());
}
if (feasibleFoundAfter>0) {
if (printRunStoppedVerbosity()) printToTextListener(" Feasible ind. found after " + feasibleFoundAfter + " evaluations.\n");
} else {
if (printRunStoppedVerbosity()) printToTextListener(" NO feasible individual found.\n");
}
if (bestRunFeasibleIndy != null) {
if (meanBestFeasibleFit==null) {
meanBestFeasibleFit=currentBestFeasibleFit.clone();
} else addMean(meanBestFeasibleFit, currentBestFeasibleFit);
if (printRunStoppedVerbosity()) {
if ((bestRunFeasibleIndy instanceof AbstractEAIndividual) && ((AbstractEAIndividual)bestRunFeasibleIndy).equalGenotypes((AbstractEAIndividual)bestRunIndividual)) {
printToTextListener(" Run best feasible individual equals best individual.\n");
} else {
if (bestRunFeasibleIndy instanceof AbstractEAIndividual) {
if (((AbstractEAIndividual)bestRunIndividual).violatesConstraint())
printToTextListener(" Run best individual violates constraints by " + ((AbstractEAIndividual)bestRunIndividual).getConstraintViolation() + "\n");
if (((AbstractEAIndividual)bestRunIndividual).isMarkedPenalized())
printToTextListener(" Run best individual is penalized.\n");
}
printToTextListener(" Run best feasible ind.: " + BeanInspector.toString(bestRunFeasibleIndy) + "\n");
printToTextListener(" Feas. solution data : " + AbstractEAIndividual.getDefaultDataString(bestRunFeasibleIndy) + "\n");
printToTextListener(" Feas. solution fit : " + BeanInspector.toString(bestRunFeasibleIndy.getFitness()) + "\n");
}
}
}
// if (currentBestFit!= null) {
// if (printRunStoppedVerbosity()) printToTextListener(" Best Fitness: " + BeanInspector.toString(currentBestFit) + "\n");
// }
@ -174,6 +221,12 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
protected void finalizeOutput() {
if (printFinalVerbosity()) printToTextListener("*******\n Runs performed: " + optRunsPerformed + ", reached target " + convergenceCnt + " times with threshold " + m_StatsParams.getConvergenceRateThreshold() + ", rate " + convergenceCnt/(double)m_StatsParams.getMultiRuns() + '\n');
if (printFinalVerbosity()) printToTextListener(" Average function calls: " + (functionCallSum/optRunsPerformed) + "\n");
if (printFinalVerbosity() && (feasibleFoundAfterSum>=0.)) {
printToTextListener(" Feasible solution found in " + numOfRunsFeasibleFound + " of " + optRunsPerformed + " runs \n");
printToTextListener(" Average evaluations until feasible ind. was found in " + numOfRunsFeasibleFound + " runs: " + feasibleFoundAfterSum/numOfRunsFeasibleFound + " evaluations\n");
}
if (printFinalVerbosity() && (bestIndividualAllover != null)) printToTextListener(" Overall best individual: " + BeanInspector.toString(bestIndividualAllover) + '\n');
if (printFinalVerbosity() && (bestIndividualAllover != null)) printToTextListener(" Overall solution data : " + AbstractEAIndividual.getDefaultDataString(bestIndividualAllover) + '\n');
if (printFinalVerbosity() && (bestIndividualAllover != null)) printToTextListener(" Overall solution fit : " + BeanInspector.toString(bestIndividualAllover.getFitness()) + '\n');
@ -181,7 +234,13 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
if (meanBestOfRunFitness!=null) {
Mathematics.svDiv((double)optRunsPerformed, meanBestOfRunFitness, meanBestOfRunFitness);
if (printFinalVerbosity()) {
printToTextListener(" Averaged best fitness per run: " + BeanInspector.toString(meanBestOfRunFitness)+"\n");
printToTextListener(" Average best fitness per run: " + BeanInspector.toString(meanBestOfRunFitness)+"\n");
}
}
if (meanBestFeasibleFit!=null) {
Mathematics.svDiv((double)numOfRunsFeasibleFound, meanBestFeasibleFit, meanBestFeasibleFit);
if (printFinalVerbosity()) {
printToTextListener(" Average best feasible fitness in " + numOfRunsFeasibleFound + " runs: " + BeanInspector.toString(meanBestFeasibleFit)+"\n");
}
}
if (refineMultiRuns && (meanCollection != null)) {
@ -298,6 +357,7 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
functionCalls = calls;
currentBestFit = bestfit;
currentWorstFit = worstfit;
currentBestFeasibleFit = null;
meanFitness = null;
if (firstPlot) {
@ -336,6 +396,7 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
initPlots(m_StatsParams.getPlotDescriptions());
// if (doTextOutput()) printToTextListener(getOutputHeader(informer, pop)+'\n');
firstPlot = false;
currentBestFeasibleFit=null;
}
if ((runIterCnt==0) && printHeaderByVerbosity()) printToTextListener(getOutputHeader(informerList, pop)+'\n');
@ -361,6 +422,23 @@ public abstract class AbstractStatistics implements InterfaceTextListener, Inter
if (currentBestFit == null) {
System.err.println("BestFitness==null !");
}
if (pop instanceof Population) {
AbstractEAIndividual curBestFeasible = ((Population)pop).getBestFeasibleIndividual(-1);
if (curBestFeasible!=null) { // a feasible ind. was found!
if (currentBestFeasibleFit==null) { // feasible indy found for the first time
numOfRunsFeasibleFound++;
feasibleFoundAfter=((Population)pop).getFunctionCalls();
if (feasibleFoundAfterSum<0) feasibleFoundAfterSum=0.; // initial signalling value was -1.
feasibleFoundAfterSum+=feasibleFoundAfter;
}
currentBestFeasibleFit = curBestFeasible.getFitness().clone();
if ((bestRunFeasibleIndy==null) || (secondIsBetter(bestRunFeasibleIndy, curBestFeasible))) {
bestRunFeasibleIndy=curBestFeasible;
}
}
}
meanFitness = pop.getMeanFitness().clone();
currentWorstFit = pop.getWorstIndividual().getFitness().clone();
functionCalls = pop.getFunctionCalls();

View File

@ -18,20 +18,21 @@ import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import wsi.ra.jproxy.MainAdapterClient;
import wsi.ra.jproxy.RMIProxyLocal;
import wsi.ra.jproxy.RMIProxyRemote;
import eva2.gui.BeanInspector;
import eva2.gui.Graph;
import eva2.gui.GraphWindow;
import eva2.gui.JTextoutputFrame;
import eva2.gui.JTextoutputFrameInterface;
import eva2.gui.Plot;
import eva2.gui.PlotInterface;
import eva2.server.EvAServer;
import eva2.server.go.PopulationInterface;
import eva2.server.go.problems.InterfaceAdditionalPopulationInformer;
import eva2.tools.EVAERROR;
import wsi.ra.jproxy.MainAdapterClient;
import wsi.ra.jproxy.RMIProxyLocal;
import wsi.ra.jproxy.RMIProxyRemote;
/*==========================================================================*
* CLASS DECLARATION
*==========================================================================*/
@ -105,39 +106,48 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl
// m_TextCounter = m_StatisticsParameter.GetTextoutput();
m_PlotCounter = m_StatsParams.GetPlotoutput();
if ((m_FitnessFrame!=null) && (m_FitnessFrame[0]!=null)) {
PlotInterface p = m_FitnessFrame[0].getPlotter();
if ((p!=null) && p.isValid()) ((Plot)p).getFunctionArea().clearLegend();
}
}
public void stopOptPerformed(boolean normal, String stopMessage) {
super.stopOptPerformed(normal, stopMessage);
if (optRunsPerformed > m_StatsParams.getMultiRuns()) {
// this may happen if the user reduces the multirun parameter during late multiruns
System.err.println("error: more runs performed than defined.");
}
int fullRuns=optRunsPerformed;
if (!normal) fullRuns--;
// unite the graphs only if the break was "normal"
if (normal && (m_StatsParams.getMultiRuns() > 1) && (m_StatGraph != null)) {
if ((m_StatsParams.getMultiRuns() > 1) && (m_StatGraph != null)) {
// unite the point sets for a multirun
for (int i = 0; i < m_FitnessGraph.length; i++) {
for (int j = 0; j < m_FitnessGraph[i].length; j++) {
if (m_FitnessFrame[i].isValid()) {
m_StatGraph[i][j].setInfoString(
(m_FitnessGraph[i][j].getInfo().length() > 0 ? (m_FitnessGraph[i][j].getInfo() + "_") : "" )
+ (m_StatsParams.GetInfoString().length() > 0 ? (m_StatsParams.GetInfoString() + "_") : "" )
+ m_StatsParams.GetInfoString()
+ "Mean_of_" + fullRuns + " ",
(float) 2.0);
if (normal && m_FitnessFrame[i].isValid()) {
m_StatGraph[i][j].addGraph(m_FitnessGraph[i][j]);
m_StatGraph[i][j].setInfoString(
(m_FitnessGraph[i][j].getInfo().length() > 0 ? (m_FitnessGraph[i][j].getInfo() + "_") : "" )
+ (m_StatsParams.GetInfoString().length() > 0 ? (m_StatsParams.GetInfoString() + "_") : "" )
+ m_StatsParams.GetInfoString()
+ "Mean_of_" + optRunsPerformed + " ",
(float) 2.0);
m_FitnessGraph[i][j].clear();
}
}
}
}
// this is inconsistent, shouldnt be necessary here but reset in startOpt...
// if (optRunsPerformed == m_StatisticsParameter.getMultiRuns()) {
// finalizeRuns(m_ConvergenceCnt);
// m_OptRunsPerformed = 0;
// m_ConvergenceCnt = 0;
// }
PlotInterface p = m_FitnessFrame[0].getPlotter();
if ((optRunsPerformed >= m_StatsParams.getMultiRuns()) || !normal) {
// update the legend after the last multirun or after a user break
if ((p!=null) && p.isValid()) {
((Plot)p).getFunctionArea().updateLegend();
}
}
}
public void maybeShowProxyPrinter() {
@ -149,13 +159,13 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl
maybeShowProxyPrinter();
int graphCount = description.size();
// System.out.println("Initializing " + graphCount + " plots (StatisticsWithGUI)");
m_FitnessFrame = new GraphWindow[graphCount];
for (int i = 0; i < m_FitnessFrame.length; i++) {
// m_FitnessFrame[i] = GraphWindow.getInstance(m_MainAdapterClient, m_GraphInfoString + " " + i + " " + " on " + m_MyHostName + ", VM " + EvAServer.m_NumberOfVM, "function calls", "fitness");
m_FitnessFrame[i] = GraphWindow.getInstance(m_MainAdapterClient, "Optimization " + i + " " + " on " + m_MyHostName + ", VM " + EvAServer.m_NumberOfVM, "function calls", "fitness");
}
m_FitnessGraph = new Graph[graphCount][];
// contains one graph for every value to be plotted (best / worst / best+worst)
// TODO Im really not sure why this is a 2-dimensional array. shouldnt one be enough?
@ -163,7 +173,7 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl
m_FitnessGraph[i] = new Graph[((String[]) description.get(i)).length];
for (int j = 0; j < m_FitnessGraph[i].length; j++) {
String[] d = (String[]) description.get(i);
// this is where the column string for ascii export is created!
// this is where the column string for ascii export is created! Uah!
m_FitnessGraph[i][j] =
m_FitnessFrame[i].getNewGraph(d[j] + "_" +
m_StatsParams.GetInfoString() +
@ -215,12 +225,20 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl
m_PlotCounter = m_StatsParams.GetPlotoutput();
boolean doPlotBest = (fitnessplot_setting == StatsParameter.PLOT_BEST)
|| (fitnessplot_setting == StatsParameter.PLOT_BEST_AND_WORST)
|| (fitnessplot_setting == StatsParameter.PLOT_CURBEST_AND_RUNBEST)
|| (fitnessplot_setting == StatsParameter.PLOT_BEST_AND_MEASURES);
boolean doPlotWorst = (fitnessplot_setting == StatsParameter.PLOT_WORST)
|| (fitnessplot_setting == StatsParameter.PLOT_BEST_AND_WORST);
boolean doPlotMeasures = (fitnessplot_setting == StatsParameter.PLOT_BEST_AND_MEASURES);
boolean doPlotBestFeasible = false;
// TODO <-- das hier besser?
// Oder erstmal ganz weg und dafür gesamtergebnis berechnen (textfenster)
// ZB: wie oft wurde feasible sol. gefunden (analog convergence counter)
// Durchschnitt: erste feasible sol., fitness der feasible sol...
int subGraph=0;
if (doPlotBest) {
plotFitnessPoint(0, 0, functionCalls, currentBestFit[0]);
plotFitnessPoint(0, subGraph++, functionCalls, currentBestFit[0]);
if (fitnessplot_setting == StatsParameter.PLOT_CURBEST_AND_RUNBEST) plotFitnessPoint(0, subGraph++, functionCalls, bestRunIndividual.getFitness()[0]);
}
if (doPlotWorst) {
// schlechteste Fitness plotten
@ -229,11 +247,14 @@ public class StatisticsWithGUI extends AbstractStatistics implements Serializabl
System.err.println("m_WorstFitness==null in plotStatisticsPerformed");
return;
}
plotFitnessPoint(0, (doPlotBest ? 1 : 0) , functionCalls, currentWorstFit[0]);
plotFitnessPoint(0, subGraph++ , functionCalls, currentWorstFit[0]);
}
if (doPlotMeasures) {
plotFitnessPoint(0, 1, functionCalls, avgPopDist);
plotFitnessPoint(0, 2, functionCalls, maxPopDist);
plotFitnessPoint(0, subGraph++, functionCalls, avgPopDist);
plotFitnessPoint(0, subGraph++, functionCalls, maxPopDist);
}
if (doPlotBestFeasible && currentBestFeasibleFit!=null) {
plotFitnessPoint(0, subGraph++, functionCalls, currentBestFeasibleFit[0]);
}
}
}

View File

@ -33,11 +33,13 @@ public class StatsParameter implements InterfaceStatisticsParameter, Serializabl
public final static int PLOT_WORST = 1;
public final static int PLOT_BEST_AND_WORST = 2;
public final static int PLOT_BEST_AND_MEASURES = 3;
public final static int PLOT_CURBEST_AND_RUNBEST = 4;
public final static Tag[] TAGS_PLOT_FITNESS = {
new Tag(PLOT_BEST, "plot best fitness"),
new Tag(PLOT_WORST, "plot worst fitness"),
new Tag(PLOT_BEST_AND_WORST, "both best and worst"),
new Tag(PLOT_BEST_AND_MEASURES, "both best and population measures")
new Tag(PLOT_BEST_AND_MEASURES, "both best and population measures"),
new Tag(PLOT_CURBEST_AND_RUNBEST, "current best and best of run")
};
public final static int VERBOSITY_NONE = 0;
@ -113,7 +115,9 @@ public class StatsParameter implements InterfaceStatisticsParameter, Serializabl
case StatsParameter.PLOT_BEST_AND_MEASURES:
desc.add(new String[] {"Best", "AvgDist", "MaxDist"});
break;
}
case StatsParameter.PLOT_CURBEST_AND_RUNBEST:
desc.add(new String[] {"Cur.Best", "Run Best"});
break; }
return desc;
}

View File

@ -88,11 +88,10 @@ private static final boolean TRACE = false;
* the measures of the area
* it calculates the coordinates
*/
private DMeasures measures;
protected DMeasures measures;
private DBorder dborder = new DBorder();
/**
* initializes the DArea with the initial capacity of 10 components
*/
@ -142,6 +141,7 @@ private static final boolean TRACE = false;
if( max_y != null ) srect.height = Math.min(srect.height, getMaxY() - getMinY());
return srect;
}
/**
* switches the auto focus of this DArea on or off
*
@ -406,16 +406,20 @@ private static final boolean TRACE = false;
if( auto_focus ) {
container.restore();
visible_rect = (DRectangle)container.getRectangle().clone();
// grid.updateDistByRect(visible_rect);
}
if( visible_rect.isEmpty() ) {
visible_rect = (DRectangle)min_rect.clone();
// grid.updateDistByRect(visible_rect);
}
if( visible_rect.isEmpty() ) visible_rect = (DRectangle)min_rect.clone();
super.paint( g );
measures.setGraphics( g );
if( grid.isVisible() && !grid_to_front ) paintGrid( measures );
container.paint( measures );
if( grid.isVisible() && grid_to_front ) paintGrid( measures );
if( grid.isVisible() && grid_to_front ) paintGrid( measures );
}
/**
* repaints a part of the visible area
*
@ -685,8 +689,8 @@ private static final boolean TRACE = false;
return;
}
else{
grid.hor_dist = ScaledBorder.aBitBigger( grid.rectangle.width / max_grid );
grid.ver_dist = ScaledBorder.aBitBigger( grid.rectangle.height / max_grid );
grid.setDistances(ScaledBorder.aBitBigger( grid.rectangle.width / max_grid ),
ScaledBorder.aBitBigger( grid.rectangle.height / max_grid ));
}
}
grid.paint( m );
@ -704,8 +708,7 @@ private static final boolean TRACE = false;
if( TRACE ) System.out.println("DArea.paintGrid(ScaledBorder, DMeasures)");
Dimension d = getSize();
FontMetrics fm = m.getGraphics().getFontMetrics();
grid.hor_dist = sb.getSrcdX(fm, d);
grid.ver_dist = sb.getSrcdY(fm, d);
grid.setDistances(sb.getSrcdX(fm, d), sb.getSrcdY(fm, d));
if( m.x_scale == null && m.y_scale == null ) grid.paint( m );
@ -716,10 +719,10 @@ private static final boolean TRACE = false;
SlimRect rect = getSlimRectangle();
SlimRect src_rect = m.getSourceOf( rect );
int x = (int)(src_rect.x / grid.hor_dist),
y = (int)(src_rect.y / grid.ver_dist);
if( x * grid.hor_dist < src_rect.x ) x++;
if( y * grid.ver_dist < src_rect.y ) y++;
int x = (int)(src_rect.x / grid.getHorDist()),
y = (int)(src_rect.y / grid.getVerDist());
if( x * grid.getHorDist() < src_rect.x ) x++;
if( y * grid.getVerDist() < src_rect.y ) y++;
// DPoint min = new DPoint( rect.x, rect.y ),
// max = new DPoint( min.x + rect.width, min.y + rect.height );
@ -727,14 +730,14 @@ private static final boolean TRACE = false;
double pos;
for( ; (pos = x * grid.hor_dist) < src_rect.x + src_rect.width; x++ ){
for( ; (pos = x * grid.getHorDist()) < src_rect.x + src_rect.width; x++ ){
if( m.x_scale != null ) pos = m.x_scale.getImageOf( pos );
Point p1 = m.getPoint( pos, miny ),
p2 = m.getPoint( pos, maxy );
g.drawLine( p1.x, p1.y, p2.x, p2.y );
}
for( ; (pos = y * grid.ver_dist) < src_rect.y + src_rect.height; y++ ){
for( ; (pos = y * grid.getVerDist()) < src_rect.y + src_rect.height; y++ ){
if( m.y_scale != null ) pos = m.y_scale.getImageOf( pos );
Point p1 = m.getPoint( minx, pos ),
p2 = m.getPoint( maxx, pos );

View File

@ -31,7 +31,7 @@ public class DGrid extends DComponent
/**
* the distances between the lines
*/
double hor_dist, ver_dist;
private double hor_dist, ver_dist;
private Color DEFAULT_COLOR = Color.lightGray;
@ -68,7 +68,20 @@ public class DGrid extends DComponent
this.ver_dist = ver_dist;
this.color = color;
}
public void setDistances(double hor, double ver) {
hor_dist=hor;
ver_dist=ver;
// System.out.println("set new Grid distances " + this.toString());
}
public double getHorDist() {
return hor_dist;
}
public double getVerDist() {
return ver_dist;
}
/**
* paints the grid...
*
@ -84,7 +97,7 @@ public class DGrid extends DComponent
minX = (int)( rectangle.x / hor_dist );
if( minX * hor_dist <= rectangle.x ) minX++;
minX *= hor_dist;
minY = (int)( rectangle.y / ver_dist );
minY = ( rectangle.y / ver_dist );
if( minY * ver_dist <= rectangle.y ) minY++;
minY *= ver_dist;
@ -98,16 +111,32 @@ public class DGrid extends DComponent
p1.x = rectangle.x;
p2.x = p1.x + rectangle.width;
for( pos = minY; pos<=rectangle.y + rectangle.height; pos += ver_dist ){
pos = minY;
while ( pos<=rectangle.y + rectangle.height){
p1.y = p2.y = pos;
l = new DLine( p1, p2, color );
l.paint( m );
if (pos+ver_dist<=pos) {
System.err.println("Overflow error in DGrid!");
pos *= 1.01;
} else pos += ver_dist;
// System.out.println("pos is " + pos + ", loop until " + rectangle.y + rectangle.height);
}
}
public String toString(){
return "chart2d.DGrid[ hor: "+hor_dist+", ver: "+ver_dist+" ]";
}
// public void updateDistByRect(DRectangle rect) {
// System.out.println(rect);
// if (!rect.isEmpty() && (hor_dist>0 && ver_dist>0)) {
// double horRatio = Math.abs(rectangle.x)/hor_dist;
// double verRatio = Math.abs(rectangle.y)/ver_dist;
//// rectangle = visRect;
// setDistances(rect.x*horRatio, rect.y*verRatio);
// }
// }
}
/****************************************************************************

View File

@ -1,23 +1,5 @@
/**
* Filename: $RCSfile: ScaledBorder.java,v $
* Purpose:
* Language: Java
* Compiler: JDK 1.3
* Authors: Fabian Hennecke
* Version: $Revision: 1.1.1.1 $
* $Date: 2003/07/03 14:59:42 $
* $Author: ulmerh $
* Copyright (c) Dept. Computer Architecture, University of Tuebingen, Germany
*/
package wsi.ra.chart2d;
/*==========================================================================*
* IMPORTS
*==========================================================================*/
import java.awt.* ;
import javax.swing.BorderFactory;
import javax.swing.border.* ;
@ -25,13 +7,9 @@ import java.awt.geom.AffineTransform ;
import java.text.NumberFormat;
import java.text.DecimalFormat;
/*==========================================================================*
* CLASS DECLARATION
*==========================================================================*/
/**
* ScaledBorder puts an border around Components
* ( especially around DrawingAreas ) with scaled and labeled axes
* ( especially around DrawingAreas ) with scaled and labeled axes.
*/
public class ScaledBorder implements Border
{
@ -125,7 +103,7 @@ public class ScaledBorder implements Border
* formatters of the x- and y-axis numbers
* @see java.text.NumberFormat
*/
public NumberFormat format_x = new DecimalFormat(),
private NumberFormat format_x = new DecimalFormat(),
format_y = new DecimalFormat();
private double src_dX = -1, src_dY = -1;
@ -195,6 +173,22 @@ public class ScaledBorder implements Border
src_dY = dY;
}
/**
* Returns the inner rectangle in pixel coordinates.
*
* @param c
* @return
*/
public SlimRect getInnerRect(Component c) {
Insets inner_insets = getBorderInsets(c);
Dimension d = c.getSize();
int width = d.width - inner_insets.left - inner_insets.right;
int height = d.height - inner_insets.top - inner_insets.bottom;
SlimRect rect=new SlimRect(inner_insets.left, inner_insets.top, width, height);
return rect;
}
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height){
if( under_construction ) System.out.println("ScaledBorder.paintBorder()");
if( foreground == null ) foreground = c.getForeground();
@ -280,48 +274,68 @@ public class ScaledBorder implements Border
inner_insets.top + cd.height );
}
drawYValues( g, inner_insets, cd );
drawYValues( g, inner_insets);
drawXValues( g, inner_insets, cd );
g.setColor( old_color );
}
/**
* The scaling of the y-axis is defined here.
*
* @param g
* @param insets
*/
private void drawYValues( Graphics g, Insets insets){
if( under_construction ) System.out.println("ScaledBorder.drawYValues()");
private void drawYValues( Graphics g, Insets insets, Dimension cd ){
if( under_construction ) System.out.println("ScaledBorder.drawYValues()");
FontMetrics fm = g.getFontMetrics();
int n, fontAsc = fm.getAscent(), v2m = fm.stringWidth("0") / y_values2marker;
n = (int)( src_rect.y / src_dY );
if( n * src_dY < src_rect.y || ( src_rect.x == 0 && src_rect.y == 0 ) ) n++;
double v, minx = src_rect.x;
if( x_scale != null ) minx = x_scale.getImageOf( minx );
for(; (v = n * src_dY) <= src_rect.y + src_rect.height; n++ ){
if( y_scale != null ) v = y_scale.getImageOf( v );
String text = format_y.format(v);
try{ v = format_y.parse(text).doubleValue(); }
catch( java.text.ParseException ex ){ }
Point p = m.getPoint( minx, v );
if( p != null ){
g.drawString( text,
insets.left - fm.stringWidth( text ) - v2m - marker_length,
p.y + fontAsc / 2 );
g.drawLine( insets.left - marker_length, p.y, insets.left, p.y );
}
}
FontMetrics fm = g.getFontMetrics();
int fontAsc = fm.getAscent(), v2m = fm.stringWidth("0") / y_values2marker;
int n = (int)( src_rect.y / src_dY );
// if( n * src_dY < src_rect.y || ( src_rect.x == 0 && src_rect.y == 0 ) ) n++;
if( n * src_dY < src_rect.y || ( src_rect.x == 0 && src_rect.y == 0 ) ) {
if (n+1 > n) n++;
else System.err.println("Overflow error A in ScaledBorder!");
}
double v, scaledV, minx = src_rect.x;
if( x_scale != null ) minx = x_scale.getImageOf( minx );
v = n * src_dY;
while (v <= src_rect.y + src_rect.height){
if( y_scale != null ) scaledV = y_scale.getImageOf( v );
else scaledV=v;
String text = format_y.format(scaledV);
try{ scaledV = format_y.parse(text).doubleValue(); }
catch( java.text.ParseException ex ){ }
Point p = m.getPoint( minx, scaledV );
if( p != null ){
g.drawString( text,
insets.left - fm.stringWidth( text ) - v2m - marker_length,
p.y + fontAsc / 2 );
g.drawLine( insets.left - marker_length, p.y, insets.left, p.y );
}
if (v+src_dY<= v) {
System.err.println("Overflow error B in ScaledBorder!");
v*=1.01;
}
v += src_dY;
}
}
public double getSrcdY( FontMetrics fm, Dimension cd ){
if( under_construction ) System.out.println("ScaledBorder.getSrcdY()");
if( (!do_refresh && src_dY != -1) || !auto_scale_y ) return src_dY;
int max = cd.height / fm.getHeight();
double minsrc_dY = 2 * src_rect.height / (double)max; // die 2 einfach mal so eingesetzt <--------------------------
src_dY = aBitBigger( minsrc_dY );
if( src_dY < minimal_increment ) src_dY = minimal_increment;
return src_dY;
return getSrcdY(fm.getHeight(), cd.height);
}
public double getSrcdY( int fontMetricsHeight, int componentHeight ){
if( under_construction ) System.out.println("ScaledBorder.getSrcdY()");
if( (!do_refresh && src_dY != -1) || !auto_scale_y ) return src_dY;
int max = componentHeight / fontMetricsHeight;
double minsrc_dY = 2 * src_rect.height / (double)max; // die 2 einfach mal so eingesetzt <--------------------------
src_dY = aBitBigger( minsrc_dY );
if( src_dY < minimal_increment ) src_dY = minimal_increment;
return src_dY;
}
private void drawXValues( Graphics g, Insets insets, Dimension cd ){
if( under_construction ) System.out.println("ScaledBorder.drawXValues()");
@ -418,11 +432,19 @@ public class ScaledBorder implements Border
public boolean isBorderOpaque(){
return outer_border.isBorderOpaque();
}
//
// private String stringOf( double v ){
// if( (int)v == v ) return String.valueOf( (int)v );
// return String.valueOf( v );
// }
/**
* Apply a decimal format pattern to x (bXorY true) or y (bXorY false) axis.
*
* @see #java.text.DecimalFormat.applyPattern
*
* @param bXorY
* @param pattern
*/
public void applyPattern(boolean bXorY, String pattern) {
if (bXorY) ((java.text.DecimalFormat)format_x).applyPattern(pattern);
else ((java.text.DecimalFormat)format_y).applyPattern(pattern);
}
public Insets getBorderInsets(Component c){
if( under_construction ) System.out.println("ScaledBorder.getBorderInsets()");
@ -452,17 +474,24 @@ public class ScaledBorder implements Border
if( y_label != null ) insets.left += fm.getAscent() + fm.getDescent();
insets.left += y_label2values * digit_width;
getSrcdY( fm, c.getSize() );
int n, maxWidth = 0;
n = (int)( src_rect.y / src_dY );
if( n * src_dY < src_rect.y ) n++;
while( n * src_dY <= src_rect.y + src_rect.height ){
double start, n, inc;
int maxWidth = 0;
start = src_dY*(int)( src_rect.y / src_dY );
n=start;
if ( n < src_rect.y ) n+=src_dY;
if (((src_rect.y + src_rect.height)-start)>20) inc = ((src_rect.y + src_rect.height)- start)/20.;
else inc = src_dY;
for (; n <= src_rect.y + src_rect.height; n+=inc ){
// TODO here might be a bug for mean values
double v = n * src_dY;
double v = n;
if( y_scale != null ) v = y_scale.getImageOf( v );
int w = fm.stringWidth( format_y.format(v) );
if( w > maxWidth ) maxWidth = w;
n++;
// avoid nearly endless loop for large src_rect.y value and small src_dY
}
insets.left += 1 + y_label2border + maxWidth + digit_width / y_values2marker + marker_length;
// bottom:
@ -477,9 +506,9 @@ public class ScaledBorder implements Border
if( show_arrows ) insets.right += x_values2arrow + arrow_length;
insets.right += axis2border;
getSrcdX( fm, c.getSize() );
n = (int)( src_rect.x + src_rect.width / src_dX );
if( n < 0 ) n ++;
int w = fm.stringWidth( format_x.format(n * src_dX) );
int k = (int)( src_rect.x + src_rect.width / src_dX );
if( k < 0 ) k ++;
int w = fm.stringWidth( format_x.format(k * src_dX) );
if( w / 2 > insets.right ) insets.right = w / 2;
old_insets = insets;

View File

@ -116,4 +116,19 @@ public class SlimRect {
public boolean hasEmptyIntersection(SlimRect r){
return (getIntersection(r)==null);
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
}