From 3d5eaa6fa8f627bfc4642a6fcfd27733281fe60b Mon Sep 17 00:00:00 2001 From: tama3 Date: Fri, 8 Jun 2007 08:46:39 +0000 Subject: [PATCH] update mds view; show extraction result of birthmark when double clicking plots in mds view git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/stigmata/trunk@120 acee48c3-7b26-0410-bdac-b3d0e5314bbc --- pom.xml | 2 +- .../naist/se/stigmata/ui/swing/BirthmarkTree.java | 6 +- .../se/stigmata/ui/swing/ChangeColorAction.java | 11 +- .../jp/naist/se/stigmata/ui/swing/ControlPane.java | 12 +- .../naist/se/stigmata/ui/swing/StigmataFrame.java | 83 +++------ .../jp/naist/se/stigmata/ui/swing/Utility.java | 35 ++++ .../se/stigmata/ui/swing/graph/PointComponent.java | 70 -------- .../naist/se/stigmata/ui/swing/mds/Coordinate.java | 92 ++++++++++ .../se/stigmata/ui/swing/mds/GeometoryType.java | 17 ++ .../naist/se/stigmata/ui/swing/mds/LabelMap.java | 73 ++++++++ .../se/stigmata/ui/swing/mds/MDSGraphPanel.java | 193 +++++++++++++++++++++ .../MDSGraphViewer.java} | 135 +++++++++----- .../MDSMethod.java} | 61 +++++-- .../naist/se/stigmata/ui/swing/mds/MarkDrawer.java | 9 + .../se/stigmata/ui/swing/mds/PointComponent.java | 129 ++++++++++++++ .../ui/swing/mds/mark/AbstractMarkDrawer.java | 65 +++++++ .../stigmata/ui/swing/mds/mark/CircleDrawer.java | 28 +++ .../se/stigmata/ui/swing/mds/mark/CrossDrawer.java | 28 +++ .../ui/swing/mds/mark/DownerTriangleDrawer.java | 41 +++++ .../stigmata/ui/swing/mds/mark/DrawerFactory.java | 37 ++++ .../stigmata/ui/swing/mds/mark/LineMarkDrawer.java | 25 +++ .../ui/swing/mds/mark/RectangleDrawer.java | 28 +++ .../stigmata/ui/swing/mds/mark/RhombusDrawer.java | 46 +++++ .../se/stigmata/ui/swing/mds/mark/StarDrawer.java | 28 +++ .../ui/swing/mds/mark/UpperTriangleDrawer.java | 41 +++++ .../se/stigmata/ui/swing/mds/mark/XMarkDrawer.java | 25 +++ .../resources/resources/images/picture_save.png | Bin 0 -> 755 bytes src/main/resources/resources/images/table_save.png | Bin 0 -> 723 bytes src/main/resources/resources/messages.properties | 31 +++- src/site/apt/index.apt | 29 +++- 30 files changed, 1176 insertions(+), 204 deletions(-) delete mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/graph/PointComponent.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/Coordinate.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/GeometoryType.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/LabelMap.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/MDSGraphPanel.java rename src/main/java/jp/naist/se/stigmata/ui/swing/{graph/MultiDimensionalScalingViewer.java => mds/MDSGraphViewer.java} (57%) rename src/main/java/jp/naist/se/stigmata/ui/swing/{graph/MultiDimensionalScalingMethod.java => mds/MDSMethod.java} (63%) create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/MarkDrawer.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/PointComponent.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/AbstractMarkDrawer.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/CircleDrawer.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/CrossDrawer.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/DownerTriangleDrawer.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/DrawerFactory.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/LineMarkDrawer.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/RectangleDrawer.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/RhombusDrawer.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/StarDrawer.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/UpperTriangleDrawer.java create mode 100755 src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/XMarkDrawer.java create mode 100755 src/main/resources/resources/images/picture_save.png create mode 100755 src/main/resources/resources/images/table_save.png diff --git a/pom.xml b/pom.xml index 6d51260..35f988c 100755 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 jp.naist.se stigmata - 1.0-beta4 + 1.0.0 stigmata Java birthmark toolkit http://stigmata.sourceforge.jp/ diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/BirthmarkTree.java b/src/main/java/jp/naist/se/stigmata/ui/swing/BirthmarkTree.java index de1e1ce..5127bfc 100755 --- a/src/main/java/jp/naist/se/stigmata/ui/swing/BirthmarkTree.java +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/BirthmarkTree.java @@ -23,13 +23,13 @@ public class BirthmarkTree extends JTree{ private static final long serialVersionUID = 68345692177534765L; private List birthmarks = new ArrayList(); - // private BirthmarkSet[] birthmarks; private DefaultTreeModel model; private DefaultMutableTreeNode root; public BirthmarkTree(){ - super(new DefaultTreeModel(new DefaultMutableTreeNode(Messages - .getString("birthmarktree.root.label"), true))); + super(new DefaultTreeModel(new DefaultMutableTreeNode( + Messages.getString("birthmarktree.root.label"), true) + )); model = (DefaultTreeModel)getModel(); root = (DefaultMutableTreeNode)model.getRoot(); } diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/ChangeColorAction.java b/src/main/java/jp/naist/se/stigmata/ui/swing/ChangeColorAction.java index 5c8bdb1..95fc1b1 100755 --- a/src/main/java/jp/naist/se/stigmata/ui/swing/ChangeColorAction.java +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/ChangeColorAction.java @@ -18,15 +18,20 @@ public class ChangeColorAction extends AbstractAction{ private boolean colorSelected = false; private ActionListener listener; - public ChangeColorAction(Component component, Color color, ActionListener listener){ - super(Messages.getString("changecolor.button.label"), - Utility.getIcon("changecolor.button.icon")); + public ChangeColorAction(String label, Component component, Color color, ActionListener listener){ + super(Messages.getString(label + ".label"), + Utility.getIcon(label + ".icon")); this.component = component; this.listener = listener; this.color = color; chooser = new JColorChooser(); chooser.setColor(color); + + } + + public ChangeColorAction(Component component, Color color, ActionListener listener){ + this("changecolor", component, color, listener); } public ChangeColorAction(Component component, ActionListener listener){ diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/ControlPane.java b/src/main/java/jp/naist/se/stigmata/ui/swing/ControlPane.java index 5793c8a..2194953 100755 --- a/src/main/java/jp/naist/se/stigmata/ui/swing/ControlPane.java +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/ControlPane.java @@ -94,13 +94,11 @@ public class ControlPane extends JPanel{ filters.reset(); updateEnable(); - int index1 = controlTab.indexOfTab(Messages - .getString("definition.tab.label")); + int index1 = controlTab.indexOfTab(Messages.getString("definition.tab.label")); if(index1 >= 0){ controlTab.removeTabAt(index1); } - int index2 = controlTab.indexOfTab(Messages - .getString("property.tab.label")); + int index2 = controlTab.indexOfTab(Messages.getString("property.tab.label")); if(index2 >= 0){ controlTab.removeTabAt(index2); } @@ -233,8 +231,10 @@ public class ControlPane extends JPanel{ } } - stigmata.extract(birthmarks.getSelectedServices(), targets - .toArray(new String[targets.size()]), context); + stigmata.extract( + birthmarks.getSelectedServices(), + targets.toArray(new String[targets.size()]), context + ); } private void compareRoundRobinWithFiltering(){ diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/StigmataFrame.java b/src/main/java/jp/naist/se/stigmata/ui/swing/StigmataFrame.java index 183ec3a..073267f 100755 --- a/src/main/java/jp/naist/se/stigmata/ui/swing/StigmataFrame.java +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/StigmataFrame.java @@ -5,7 +5,6 @@ package jp.naist.se.stigmata.ui.swing; */ import java.awt.BorderLayout; -import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; @@ -27,9 +26,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.swing.Box; -import javax.swing.JButton; -import javax.swing.JCheckBox; import javax.swing.JCheckBoxMenuItem; import javax.swing.JFileChooser; import javax.swing.JFrame; @@ -62,10 +58,8 @@ import jp.naist.se.stigmata.Stigmata; import jp.naist.se.stigmata.filter.FilteredComparisonResultSet; import jp.naist.se.stigmata.format.FormatManager; import jp.naist.se.stigmata.spi.ResultFormatSpi; -import jp.naist.se.stigmata.ui.swing.graph.MultiDimensionalScalingMethod; -import jp.naist.se.stigmata.ui.swing.graph.MultiDimensionalScalingViewer; import jp.naist.se.stigmata.ui.swing.graph.SimilarityDistributionGraphPane; -import Jama.Matrix; +import jp.naist.se.stigmata.ui.swing.mds.MDSGraphPanel; /** @@ -134,10 +128,17 @@ public class StigmataFrame extends JFrame implements CurrentDirectoryHolder{ return context; } + /** + * Find file to open it. + */ public File getOpenFile(String[] exts, String desc){ return findFile(true, exts, desc); } + /** + * Find file for storing data to it. + * Extension of found file is correct as selected extension. + */ public File getSaveFile(String[] exts, String desc){ return findFile(false, exts, desc); } @@ -305,45 +306,7 @@ public class StigmataFrame extends JFrame implements CurrentDirectoryHolder{ } public void showMDSGraph(BirthmarkSet[] set){ - double[][] matrix = new double[set.length][set.length]; - - String[] labels = new String[set.length]; - for(int i = 0; i < set.length; i++){ - for(int j = 0; j <= i; j++){ - ComparisonPair pair = new ComparisonPair(set[i], set[j], context); - matrix[i][j] = 1d - pair.calculateSimilarity(); - if(i != j){ - matrix[j][i] = matrix[i][j]; - } - } - labels[i] = set[i].getClassName(); - } - final MultiDimensionalScalingViewer viewer = new MultiDimensionalScalingViewer(new MultiDimensionalScalingMethod(new Matrix(matrix)), labels); - viewer.setShowLabel(true); - - JPanel panel = new JPanel(new BorderLayout()); - Box south = Box.createHorizontalBox(); - JButton colorButton = new JButton(new ChangeColorAction(this, Color.BLUE, new ActionListener(){ - public void actionPerformed(ActionEvent e){ - ChangeColorAction action = (ChangeColorAction)e.getSource(); - viewer.setOverColor(action.getColor()); - } - })); - final JCheckBox check = new JCheckBox(Messages.getString("showlabel.button.label"), true); - check.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e){ - viewer.setShowLabel(check.isSelected()); - } - }); - - south.add(Box.createHorizontalGlue()); - south.add(colorButton); - south.add(Box.createHorizontalGlue()); - south.add(check); - south.add(Box.createHorizontalGlue()); - panel.add(viewer, BorderLayout.CENTER); - panel.add(south, BorderLayout.SOUTH); - + MDSGraphPanel panel = new MDSGraphPanel(this, set, context); mappingGraphCount++; Utility.addNewTab("mappinggraph", tabPane, panel, new Object[] { new Integer(mappingGraphCount), }, null); tabPane.setSelectedIndex(tabPane.getTabCount() - 1); @@ -357,18 +320,22 @@ public class StigmataFrame extends JFrame implements CurrentDirectoryHolder{ tabPane.setSelectedIndex(tabPane.getTabCount() - 1); } + public void showExtractionResult(BirthmarkSet[] set, BirthmarkContext context){ + extractCount++; + BirthmarkExtractionResultPane viewer = new BirthmarkExtractionResultPane(this, context, set); + Utility.addNewTab( + "extract", tabPane, viewer, + new Object[] { new Integer(extractCount), }, + new Object[] { Utility.array2String(set[0].getBirthmarkTypes()), } + ); + tabPane.setSelectedIndex(tabPane.getTabCount() - 1); + + } + public void extract(String[] birthmarks, String[] targets, BirthmarkContext context){ try{ BirthmarkSet[] holders = stigmata.extract(birthmarks, targets, context); - extractCount++; - - BirthmarkExtractionResultPane viewer = new BirthmarkExtractionResultPane(this, context, holders); - Utility.addNewTab( - "extract", tabPane, viewer, - new Object[] { new Integer(extractCount), }, - new Object[] { Utility.array2String(birthmarks), Utility.array2String(targets), } - ); - tabPane.setSelectedIndex(tabPane.getTabCount() - 1); + showExtractionResult(holders, context); }catch(Exception e){ showExceptionMessage(e); } @@ -675,9 +642,9 @@ public class StigmataFrame extends JFrame implements CurrentDirectoryHolder{ } sb.append(""); JOptionPane.showMessageDialog( - this, new String(sb), Messages.getString("error.dialog.title"), - JOptionPane.WARNING_MESSAGE - ); + this, new String(sb), Messages.getString("error.dialog.title"), + JOptionPane.WARNING_MESSAGE + ); } private String loadString(String loadFrom){ diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/Utility.java b/src/main/java/jp/naist/se/stigmata/ui/swing/Utility.java index 85195e1..6af7a06 100755 --- a/src/main/java/jp/naist/se/stigmata/ui/swing/Utility.java +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/Utility.java @@ -5,9 +5,13 @@ package jp.naist.se.stigmata.ui.swing; */ import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; +import javax.swing.AbstractAction; +import javax.swing.Action; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; @@ -31,6 +35,19 @@ public class Utility{ private Utility(){ } + public static Action createAction(String key, final ActionListener listener){ + final Icon icon = getIcon(key + ".icon"); + final String label = Messages.getString(key + ".label"); + + return new AbstractAction(label, icon){ + private static final long serialVersionUID = 1349393156253158607L; + + public void actionPerformed(ActionEvent e){ + listener.actionPerformed(e); + } + }; + } + public static void decorateJComponent(JComponent component, String label){ if(Messages.hasString(label + ".tooltip")){ component.setToolTipText(Messages.getString(label + ".tooltip")); @@ -51,6 +68,15 @@ public class Utility{ } } + public static JButton createButton(String label, Action action){ + JButton button = new JButton(action); + button.setActionCommand(label); + if(Messages.hasString(label + ".button.tooltip")){ + button.setToolTipText(Messages.getString(label + ".button.tooltip")); + } + return button; + } + public static JButton createButton(String label){ JButton button = new JButton(Messages.getString(label + ".button.label")); button.setActionCommand(label); @@ -82,6 +108,15 @@ public class Utility{ return item; } + public static JMenuItem createJMenuItem(String label, Action action){ + JMenuItem item = new JMenuItem(action); + item.setActionCommand(label); + if(Messages.hasString(label + ".menuitem.tooltip")){ + item.setToolTipText(Messages.getString(label + ".menuitem.tooltip")); + } + return item; + } + public static JMenuItem createJMenuItem(String label){ JMenuItem item = new JMenuItem(Messages.getString(label + ".menuitem.label")); item.setActionCommand(label); diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/graph/PointComponent.java b/src/main/java/jp/naist/se/stigmata/ui/swing/graph/PointComponent.java deleted file mode 100755 index f08884c..0000000 --- a/src/main/java/jp/naist/se/stigmata/ui/swing/graph/PointComponent.java +++ /dev/null @@ -1,70 +0,0 @@ -package jp.naist.se.stigmata.ui.swing.graph; - -import java.awt.Color; -import java.awt.Graphics; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -import javax.swing.JLabel; - -class PointComponent extends JLabel{ - private static final long serialVersionUID = 6945871049990818511L; - public static final Color DEFAULT_OVER_COLOR = Color.BLUE; - private String label; - private boolean entered = false; - private Color overColor = DEFAULT_OVER_COLOR; - - public PointComponent(String label, double x, double y){ - this(label); - - setToolTipText(String.format("%s [%g, %g]", label, x, y)); - } - - public PointComponent(String label){ - this.label = label; - setSize(10, 10); - setMinimumSize(getSize()); - setMaximumSize(getSize()); - setPreferredSize(getSize()); - - addMouseListener(new MouseAdapter(){ - @Override - public void mouseEntered(MouseEvent e){ - entered = true; - updateUI(); - } - - @Override - public void mouseExited(MouseEvent e){ - entered = false; - updateUI(); - } - }); - setToolTipText(this.label); - } - - public String getLabel(){ - return label; - } - - @Override - public void paintComponent(Graphics g){ - super.paintComponent(g); - if(entered){ - g.setColor(getOverColor()); - g.fillOval(0, 0, 10, 10); - } - else{ - g.setColor(getForeground()); - g.fillOval(4, 4, 3, 3); - } - } - - public Color getOverColor(){ - return overColor; - } - - public void setOverColor(Color overColor){ - this.overColor = overColor; - } -} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/Coordinate.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/Coordinate.java new file mode 100755 index 0000000..d0521f9 --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/Coordinate.java @@ -0,0 +1,92 @@ +package jp.naist.se.stigmata.ui.swing.mds; + +public class Coordinate{ + private double x, y, z; + private String label; + private String showName; + private int groupId = 0; + + public Coordinate(String label, double x, double y){ + this(label, shortenLabel(label), x, y, Double.NaN); + } + + public Coordinate(String label, double x, double y, double z){ + this(label, shortenLabel(label), x, y, z); + } + + public Coordinate(String label, String showName, double x, double y){ + this(label, showName, x, y, Double.NaN); + } + + public Coordinate(String label, String showName, double x, double y, double z){ + this.label = label; + this.showName = showName; + this.x = x; + this.y = y; + this.z = z; + } + + public String toString(){ + return String.format("%s[%d] (%g, %g)", getLabel(), getGroupId(), getX(), getY()); + } + + public int getGroupId(){ + return groupId; + } + + public void setGroupId(int groupId){ + this.groupId = groupId; + } + + public String getLabel(){ + return label; + } + + public void setLabel(String label){ + this.label = label; + } + + public String getShowName(){ + return showName; + } + + public void setShowName(String showName){ + this.showName = showName; + } + + public double getX(){ + return x; + } + + public void setX(double x){ + this.x = x; + } + + public double getY(){ + return y; + } + + public void setY(double y){ + this.y = y; + } + + public double getZ(){ + return z; + } + + public void setZ(double z){ + this.z = z; + } + + private static String shortenLabel(String label){ + int index = label.lastIndexOf('/'); + int firstIndex = label.indexOf('.'); + int lastIndex = label.lastIndexOf('.'); + int length = label.length(); + + if(index < 0 && (firstIndex != lastIndex && lastIndex != (length - 1))){ + index = label.lastIndexOf('.'); + } + return label.substring(index + 1); + } +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/GeometoryType.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/GeometoryType.java new file mode 100755 index 0000000..18d5fce --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/GeometoryType.java @@ -0,0 +1,17 @@ +package jp.naist.se.stigmata.ui.swing.mds; + +public enum GeometoryType{ + RECTANGLE, + UPPER_TRIANGLE, + CIRCLE, + XMARK, + RHOMBUS, + DOWNER_TRIANGLE, + FILLED_RECTANGLE, + CROSS, + FILLED_UPPER_TRIANGLE, + FILLED_CIRCLE, + FILLED_RHOMBUS, + STAR, + FILLED_DOWNER_TRIANGLE, +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/LabelMap.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/LabelMap.java new file mode 100755 index 0000000..a6fff4e --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/LabelMap.java @@ -0,0 +1,73 @@ +package jp.naist.se.stigmata.ui.swing.mds; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class LabelMap{ + private List labels = new ArrayList(); + private Map groups = new HashMap(); + private Map gids = new HashMap(); + + public LabelMap(){ + gids.put("", 0); + } + + public LabelMap(String[] labels){ + this(); + for(String label: labels){ + addLabel(label); + } + } + + public boolean isAvailableLabel(int index){ + return index >= 0 && index < labels.size(); + } + + public void addLabel(String label){ + labels.add(label); + } + + public String getLabel(int index){ + return labels.get(index); + } + + public void setGroup(String label, String groupLabel){ + groups.put(label, groupLabel); + if(gids.get(groupLabel) == null){ + gids.put(groupLabel, groups.size()); + } + } + + public String getGroup(String label){ + String group = groups.get(label); + if(group == null){ + group = ""; + } + return group; + } + + public int getGroupId(String label){ + String glabel = groups.get(label); + Integer i = gids.get(glabel); + if(i == null){ + i = new Integer(0); + } + return i; + } + + public int getGroupCount(){ + return groups.size(); + } + + public synchronized String[] getGroupElements(String group){ + List elements = new ArrayList(); + for(Map.Entry entry: groups.entrySet()){ + if(group.equals(entry.getValue())){ + elements.add(entry.getKey()); + } + } + return elements.toArray(new String[elements.size()]); + } +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/MDSGraphPanel.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/MDSGraphPanel.java new file mode 100755 index 0000000..170976e --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/MDSGraphPanel.java @@ -0,0 +1,193 @@ +package jp.naist.se.stigmata.ui.swing.mds; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URL; +import java.util.Iterator; + +import javax.imageio.ImageIO; +import javax.swing.Action; +import javax.swing.Box; +import javax.swing.JCheckBox; +import javax.swing.JOptionPane; +import javax.swing.JPanel; + +import jp.naist.se.stigmata.BirthmarkContext; +import jp.naist.se.stigmata.BirthmarkSet; +import jp.naist.se.stigmata.ComparisonPair; +import jp.naist.se.stigmata.ui.swing.ChangeColorAction; +import jp.naist.se.stigmata.ui.swing.Messages; +import jp.naist.se.stigmata.ui.swing.PopupButton; +import jp.naist.se.stigmata.ui.swing.StigmataFrame; +import jp.naist.se.stigmata.ui.swing.Utility; +import Jama.Matrix; + +public class MDSGraphPanel extends JPanel{ + private static final long serialVersionUID = -7256554014379112897L; + private StigmataFrame stigmata; + private BirthmarkSet[] set; + private LabelMap labels; + private MDSGraphViewer viewer; + + public MDSGraphPanel(StigmataFrame stigmata, BirthmarkSet[] set){ + this(stigmata, set, stigmata.getContext()); + } + + public MDSGraphPanel(StigmataFrame stigmata, BirthmarkSet[] set, BirthmarkContext context){ + this.stigmata = stigmata; + this.set = set; + + double[][] matrix = initData(set, context); + initLayouts(matrix); + } + + private void saveMDSImage(){ + File file = stigmata.getSaveFile( + Messages.getStringArray("savemds.extensions"), + Messages.getString("savemds.description") + ); + Dimension size = viewer.getSize(); + BufferedImage image = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = image.createGraphics(); + g.setColor(Color.WHITE); + g.fillRect(0, 0, size.width, size.height); + viewer.update(g); + try{ + String name = file.getName(); + ImageIO.write(image, name.substring(name.lastIndexOf('.') + 1), file); + } catch(IOException e){ + JOptionPane.showMessageDialog( + stigmata, e.getMessage(), "File store error", JOptionPane.WARNING_MESSAGE + ); + } + } + + private void saveCoordinate(){ + File file = stigmata.getSaveFile( + Messages.getStringArray("savelocation.extensions"), + Messages.getString("savelocation.description") + ); + PrintWriter out = null; + try{ + out = new PrintWriter(new FileWriter(file)); + for(Iterator i = viewer.coordinates(); i.hasNext(); ){ + Coordinate c = i.next(); + out.printf("%s,%s,%g,%g%n", c.getLabel(), c.getGroupId(), c.getX(), c.getY()); + } + } catch(IOException e){ + JOptionPane.showMessageDialog( + stigmata, e.getMessage(), "File store error", JOptionPane.WARNING_MESSAGE + ); + } finally{ + if(out != null){ + out.close(); + } + } + } + + private double[][] initData(BirthmarkSet[] set, BirthmarkContext context){ + labels = new LabelMap(); + double[][] matrix = new double[set.length][set.length]; + + for(int i = 0; i < set.length; i++){ + for(int j = 0; j <= i; j++){ + ComparisonPair pair = new ComparisonPair(set[i], set[j], context); + matrix[i][j] = 1d - pair.calculateSimilarity(); + if(i != j){ + matrix[j][i] = matrix[i][j]; + } + } + String className = set[i].getClassName(); + labels.addLabel(className); + String groupName = getGroupName(set[i].getLocation()); + labels.setGroup(className, groupName); + } + return matrix; + } + + private String getGroupName(URL location){ + String url = location.toString(); + if(url.startsWith("jar:")){ + url = url.substring("jar:".length(), url.lastIndexOf('!')); + } + return url; + } + + private void initLayouts(double[][] matrix){ + viewer = new MDSGraphViewer(new MDSMethod(new Matrix(matrix)), labels); + viewer.setShowLabel(true); + + Box south = Box.createHorizontalBox(); + + viewer.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e){ + String c = e.getActionCommand(); + for(int i = 0; i < set.length; i++){ + if(c.equals(set[i].getClassName())){ + stigmata.showExtractionResult(new BirthmarkSet[] { set[i], }, stigmata.getContext()); + } + } + } + }); + final JCheckBox check = new JCheckBox(Messages.getString("showlabel.button.label"), true); + check.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e){ + viewer.setShowLabel(check.isSelected()); + } + }); + + Action pointColorAction = new ChangeColorAction( + "updatecolor", stigmata, Color.BLACK, + new ActionListener(){ + public void actionPerformed(ActionEvent e){ + ChangeColorAction action = (ChangeColorAction)e.getSource(); + viewer.setPointColor(action.getColor()); + } + } + ); + Action overColorAction = new ChangeColorAction( + "updateovercolor", stigmata, Color.BLUE, + new ActionListener(){ + public void actionPerformed(ActionEvent e){ + ChangeColorAction action = (ChangeColorAction)e.getSource(); + viewer.setOverColor(action.getColor()); + } + } + ); + Action saveMDSAction = Utility.createAction("savemds", new ActionListener(){ + public void actionPerformed(ActionEvent e){ + saveMDSImage(); + } + }); + Action saveCoordinate = Utility.createAction("savelocation", new ActionListener(){ + public void actionPerformed(ActionEvent e){ + saveCoordinate(); + } + }); + PopupButton colorButton = new PopupButton(Utility.createButton("updatecolor", pointColorAction)); + colorButton.addMenuItem(Utility.createJMenuItem("updateovercolor", overColorAction)); + PopupButton saveButton = new PopupButton(Utility.createButton("savemds", saveMDSAction)); + saveButton.addMenuItem(Utility.createJMenuItem("savelocation", saveCoordinate)); + + south.add(Box.createHorizontalGlue()); + south.add(saveButton); + south.add(Box.createHorizontalGlue()); + south.add(colorButton); + south.add(Box.createHorizontalGlue()); + south.add(check); + south.add(Box.createHorizontalGlue()); + + setLayout(new BorderLayout()); + add(viewer, BorderLayout.CENTER); + add(south, BorderLayout.SOUTH); + } +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/graph/MultiDimensionalScalingViewer.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/MDSGraphViewer.java similarity index 57% rename from src/main/java/jp/naist/se/stigmata/ui/swing/graph/MultiDimensionalScalingViewer.java rename to src/main/java/jp/naist/se/stigmata/ui/swing/mds/MDSGraphViewer.java index 7070f61..1a37bfa 100755 --- a/src/main/java/jp/naist/se/stigmata/ui/swing/graph/MultiDimensionalScalingViewer.java +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/MDSGraphViewer.java @@ -1,4 +1,4 @@ -package jp.naist.se.stigmata.ui.swing.graph; +package jp.naist.se.stigmata.ui.swing.mds; import java.awt.BorderLayout; import java.awt.Color; @@ -6,42 +6,71 @@ import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JLayeredPane; +import jp.naist.se.stigmata.ui.swing.mds.mark.DrawerFactory; import Jama.Matrix; -public class MultiDimensionalScalingViewer extends JLayeredPane{ +public class MDSGraphViewer extends JLayeredPane{ private static final long serialVersionUID = -9196070059428975126L; private static final int POINT_LAYER = DEFAULT_LAYER; private static final int LABEL_LAYER = DEFAULT_LAYER; - private MultiDimensionalScalingMethod mds; - private List list = new ArrayList(); + private MDSMethod mds; + private List plots = new ArrayList(); private Color overColor = PointComponent.DEFAULT_OVER_COLOR; private Color pointColor = getForeground(); private boolean sameAspect = false; private boolean showLabel = false; private List points = new ArrayList(); - private List labellist = new ArrayList(); + private List listeners = new ArrayList(); - public MultiDimensionalScalingViewer(MultiDimensionalScalingMethod mds){ + public MDSGraphViewer(MDSMethod mds){ this(mds, null); } - public MultiDimensionalScalingViewer(MultiDimensionalScalingMethod mds, String[] labels){ + public MDSGraphViewer(MDSMethod mds, LabelMap labels){ this.mds = mds; - setSize(300, 300); + setSize(500, 500); setMinimumSize(getSize()); - setPreferredSize(getSize()); initLayouts(labels); } + public void addActionListener(ActionListener listener){ + listeners.add(listener); + } + + public void removeActionListener(ActionListener listener){ + listeners.remove(listener); + } + + @Override + public void setSize(int x, int y){ + super.setSize(x, y); + setPreferredSize(getSize()); + } + + public Iterator coordinates(){ + return plots.iterator(); + } + + public int getPointCount(){ + return plots.size(); + } + + public Coordinate getCoordinate(int index){ + return plots.get(index); + } + public boolean isShowLabel(){ return showLabel; } @@ -98,24 +127,30 @@ public class MultiDimensionalScalingViewer extends JLayeredPane{ g.drawLine(d.width / 2, d.height, d.width / 2, 0); g.drawLine(0, d.height / 2, d.width, d.height / 2); - updateComponents(d); + updatePointComponents(d); } - private void initLayouts(String[] labels){ + protected void fireEvent(PointComponent p){ + ActionEvent e = new ActionEvent(this, 0, p.getLabel()); + for(ActionListener l: listeners){ + l.actionPerformed(e); + } + } + + private void initLayouts(LabelMap labels){ double[] x = mds.getCoordinate(0); double[] y = mds.getCoordinate(1); + double[] z = mds.getCoordinate(2); - double xmax = 0d; - double ymax = 0d; + double max = 0d; for(int i = 0; i < x.length; i++){ - if(xmax < Math.abs(x[i])) xmax = Math.abs(x[i]); + if(max < Math.abs(x[i])) max = Math.abs(x[i]); } for(int i = 0; i < y.length; i++){ - if(ymax < Math.abs(y[i])) ymax = Math.abs(y[i]); + if(max < Math.abs(y[i])) max = Math.abs(y[i]); } - if(sameAspect){ - if(ymax > xmax) xmax = ymax; - else ymax = xmax; + for(int i = 0; i < z.length; i++){ + if(max < Math.abs(z[i])) max = Math.abs(z[i]); } int w = getWidth(); @@ -123,41 +158,63 @@ public class MultiDimensionalScalingViewer extends JLayeredPane{ int ww = w - 20; int hh = h - 20; + DrawerFactory factory = DrawerFactory.getInstance(); + GeometoryType[] types = GeometoryType.values(); + ActionListener clickedListener = new ActionListener(){ + public void actionPerformed(ActionEvent e){ + fireEvent((PointComponent)e.getSource()); + } + }; for(int i = 0; i < x.length; i++){ - double[] xy = new double[] { x[i] / xmax, - y[i] / ymax, }; - list.add(xy); + double[] xy = new double[] { - x[i] / max, - y[i] / max, z[i] / max, }; double xx = xy[0] * ww / 2 + (w / 2); double yy = xy[1] * hh / 2 + (h / 2); String label = String.valueOf(i); - if(labels != null && labels.length > i){ - label = labels[i]; + if(labels != null && labels.isAvailableLabel(i)){ + label = labels.getLabel(i); + } + Coordinate coordinate = new Coordinate(label, xy[0], xy[1], xy[2]); + if(labels != null){ + coordinate.setGroupId(labels.getGroupId(coordinate.getLabel())); } + plots.add(coordinate); - PointComponent p = new PointComponent(label, x[i], y[i]); + PointComponent p = new PointComponent( + label, x[i], y[i], factory.create(types[coordinate.getGroupId()]) + ); + p.addActionListener(clickedListener); add(p, POINT_LAYER); + JLabel l = new JLabel(coordinate.getShowName()); + add(l, LABEL_LAYER); + p.setShowLabel(l); + Dimension size = p.getSize(); p.setLocation( - new Point((int)(xx - (size.getWidth() / 2d)), (int)(yy - (size.getHeight() / 2))) + new Point((int)(xx - (size.getWidth() / 2d)), (int)(yy - (size.getHeight() / 2d))) ); points.add(p); - JLabel l = new JLabel(p.getLabel()); - add(l, LABEL_LAYER); l.setSize(l.getPreferredSize()); Point pcp = p.getLocation(); Dimension dsize = l.getSize(); l.setLocation(new Point(pcp.x - (dsize.width / 2), pcp.y - 15)); l.setVisible(isShowLabel()); - labellist.add(l); } } - private void updateComponents(Dimension d){ + private void updatePointComponents(Dimension d){ int index = 0; + double width = d.getWidth(); + double height = d.getHeight(); + if(isSameAspect()){ + if(width < height) height = width; + else width = height; + } + for(PointComponent pc: points){ - updateLocation(pc, list.get(index), d); - JLabel label = labellist.get(index); + updateLocation(pc, plots.get(index), width, height, d); + JLabel label = pc.getShowLabel(); Point pcp = pc.getLocation(); Dimension dsize = label.getSize(); label.setLocation(new Point(pcp.x - (dsize.width / 2), pcp.y - 15)); @@ -166,9 +223,9 @@ public class MultiDimensionalScalingViewer extends JLayeredPane{ } } - private void updateLocation(PointComponent c, double[] xy, Dimension d){ - double xx = xy[0] * (d.width - 20) / 2 + (d.width / 2); - double yy = xy[1] * (d.height - 20) / 2 + (d.height / 2); + private void updateLocation(PointComponent c, Coordinate coordinate, double width, double height, Dimension d){ + double xx = coordinate.getX() * (width - 20d) / 2d + (d.getWidth() / 2d); + double yy = coordinate.getY() * (height - 20d) / 2d + (d.getHeight() / 2d); Dimension size = c.getSize(); c.setLocation( new Point((int)(xx - (size.getWidth() / 2d)), (int)(yy - (size.getHeight() / 2))) @@ -176,13 +233,11 @@ public class MultiDimensionalScalingViewer extends JLayeredPane{ } public static void main(String[] args) throws Exception{ - MultiDimensionalScalingMethod mds; - String[] labels = null; - - labels = new String[] { + MDSMethod mds; + LabelMap labels = new LabelMap(new String[] { "Atlanta", "Chicago", "Denver", "Houston", "Los Angeles", "Miami", "New York", "San Francisco", "Seattle", "Washington D.C.", - }; + }); Matrix matrix = new Matrix(new double[][]{ { 0, 587, 1212, 701, 1936, 604, 748, 2139, 2182, 543, }, { 587, 0, 920, 940, 1745, 1188, 713, 1858, 1737, 597, }, @@ -195,10 +250,10 @@ public class MultiDimensionalScalingViewer extends JLayeredPane{ { 2182, 1737, 1021, 1891, 959, 2734, 2408, 678, 0, 2329, }, { 543, 597, 1494, 1220, 2300, 923, 205, 2442, 2329, 0, }, }); - mds = new MultiDimensionalScalingMethod(matrix); + mds = new MDSMethod(matrix); mds.getCoordinateMatrix().print(8, 4); - MultiDimensionalScalingViewer viewer = new MultiDimensionalScalingViewer(mds, labels); + MDSGraphViewer viewer = new MDSGraphViewer(mds, labels); viewer.setShowLabel(true); JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/graph/MultiDimensionalScalingMethod.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/MDSMethod.java similarity index 63% rename from src/main/java/jp/naist/se/stigmata/ui/swing/graph/MultiDimensionalScalingMethod.java rename to src/main/java/jp/naist/se/stigmata/ui/swing/mds/MDSMethod.java index 2c00cb1..461274a 100755 --- a/src/main/java/jp/naist/se/stigmata/ui/swing/graph/MultiDimensionalScalingMethod.java +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/MDSMethod.java @@ -1,14 +1,16 @@ -package jp.naist.se.stigmata.ui.swing.graph; +package jp.naist.se.stigmata.ui.swing.mds; import Jama.EigenvalueDecomposition; import Jama.Matrix; -public class MultiDimensionalScalingMethod{ +public class MDSMethod{ private Matrix target; private Matrix coordinate; + private Matrix eigenValues; + private Matrix eigenVectors; private int[] indexes; - public MultiDimensionalScalingMethod(Matrix matrix){ + public MDSMethod(Matrix matrix){ this.target = matrix; } @@ -19,6 +21,20 @@ public class MultiDimensionalScalingMethod{ return centering.times(target).times(trans).times(-1); } + public Matrix getEigenValues(){ + if(eigenValues == null){ + getCoordinateMatrix(); + } + return (Matrix)eigenValues.clone(); + } + + public Matrix getEigenVectors(){ + if(eigenVectors == null){ + getCoordinateMatrix(); + } + return (Matrix)eigenVectors.clone(); + } + public double[] getCoordinate(int axis){ if(coordinate == null){ getCoordinateMatrix(); @@ -31,26 +47,34 @@ public class MultiDimensionalScalingMethod{ } public Matrix getCoordinateMatrix(){ - Matrix mat = getCenteredInnerProductMatrix(); - EigenvalueDecomposition eigen = mat.eig(); - Matrix eigenVectors = eigen.getV(); - Matrix eigenValues = eigen.getD(); - - for(int i = 0; i < mat.getRowDimension(); i++){ - for(int j = 0; j < mat.getColumnDimension(); j++){ - double v = eigenVectors.get(i, j); - v = v * Math.sqrt(eigenValues.get(j, j)); - eigenVectors.set(i, j, v); + if(coordinate == null){ + Matrix mat = getCenteredInnerProductMatrix(); + EigenvalueDecomposition eigen = mat.eig(); + Matrix eigenVectors = eigen.getV(); + Matrix eigenValues = eigen.getD(); + Matrix coordinate = (Matrix)eigenVectors.clone(); + + int col = mat.getColumnDimension(); + int row = mat.getRowDimension(); + for(int i = 0; i < row; i++){ + for(int j = 0; j < col; j++){ + double v = coordinate.get(i, j); + v = v * Math.sqrt(eigenValues.get(j, j)); + coordinate.set(i, j, v); + } } + sortValues(eigenValues); + this.coordinate = coordinate; + this.eigenVectors = eigenVectors; + this.eigenValues = eigenValues; } - sortValues(eigenVectors); - this.coordinate = eigenVectors; - return eigenVectors; + return coordinate; } protected static Matrix getCenteringMatrix(int n){ Matrix matrix = Matrix.identity(n, n); + for(int i = 0; i < n; i++){ for(int j = 0; j < n; j++){ matrix.set(i, j, matrix.get(i, j) - (1d / n)); @@ -69,7 +93,7 @@ public class MultiDimensionalScalingMethod{ for(int i = 0; i < v.length; i++){ for(int j = i + 1; j < v.length; j++){ - if(v[i] < v[j]){ + if(Math.abs(v[i]) < Math.abs(v[j])){ double tmpValue = v[j]; v[j] = v[i]; v[i] = tmpValue; @@ -79,6 +103,7 @@ public class MultiDimensionalScalingMethod{ } } } + indexes = index; } @@ -95,7 +120,7 @@ public class MultiDimensionalScalingMethod{ { 2182, 1737, 1021, 1891, 959, 2734, 2408, 678, 0, 2329, }, { 543, 597, 1494, 1220, 2300, 923, 205, 2442, 2329, 0, }, }); - MultiDimensionalScalingMethod mds = new MultiDimensionalScalingMethod(matrix); + MDSMethod mds = new MDSMethod(matrix); System.out.println(mds.getCoordinateMatrix()); } } diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/MarkDrawer.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/MarkDrawer.java new file mode 100755 index 0000000..fdcd8e2 --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/MarkDrawer.java @@ -0,0 +1,9 @@ +package jp.naist.se.stigmata.ui.swing.mds; + +import java.awt.Graphics2D; + +public interface MarkDrawer{ + public void draw(Graphics2D g, int w, int h); + + public void drawOver(Graphics2D g, int w, int h); +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/PointComponent.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/PointComponent.java new file mode 100755 index 0000000..a919520 --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/PointComponent.java @@ -0,0 +1,129 @@ +package jp.naist.se.stigmata.ui.swing.mds; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Stroke; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JLabel; + +import jp.naist.se.stigmata.ui.swing.mds.mark.DrawerFactory; + +class PointComponent extends JLabel{ + private static final long serialVersionUID = 6945871049990818511L; + public static final Color DEFAULT_OVER_COLOR = Color.BLUE; + + private boolean entered = false; + private Color overColor = DEFAULT_OVER_COLOR; + private String label; + private MarkDrawer drawer; + private JLabel showLabel = null; + private List listeners = new ArrayList(); + + public PointComponent(String label, double x, double y){ + this(label); + + setToolTipText(String.format("%s [%g, %g]", label, x, y)); + drawer = DrawerFactory.getInstance().create(GeometoryType.UPPER_TRIANGLE); + } + + public PointComponent(String label, double x, double y, MarkDrawer drawer){ + this(label); + this.drawer = drawer; + setToolTipText(String.format("%s [%g, %g]", label, x, y)); + } + + public PointComponent(String label){ + this.label = label; + setSize(10, 10); + setMinimumSize(getSize()); + setMaximumSize(getSize()); + setPreferredSize(getSize()); + + addMouseListener(new MouseAdapter(){ + @Override + public void mouseEntered(MouseEvent e){ + entered = true; + if(showLabel != null){ + showLabel.setVisible(true); + showLabel.repaint(); + } + repaint(); + } + + @Override + public void mouseExited(MouseEvent e){ + entered = false; + if(showLabel != null){ + showLabel.setVisible(false); + showLabel.repaint(); + } + repaint(); + } + + @Override + public void mouseClicked(MouseEvent e){ + if(e.getClickCount() >= 2){ + ActionEvent ae = new ActionEvent(PointComponent.this, 0, null); + for(ActionListener listener: listeners){ + listener.actionPerformed(ae); + } + } + } + }); + setToolTipText(this.label); + } + + public void addActionListener(ActionListener listener){ + listeners.add(listener); + } + + public void removeActionListener(ActionListener listener){ + listeners.remove(listener); + } + + public void setShowLabel(JLabel label){ + this.showLabel = label; + } + + public JLabel getShowLabel(){ + return showLabel; + } + + public String getLabel(){ + return label; + } + + @Override + public void paintComponent(Graphics g){ + super.paintComponent(g); + Graphics2D gg = (Graphics2D)g; + Stroke stroke = gg.getStroke(); + Dimension d = getSize(); + + if(entered){ + g.setColor(getOverColor()); + drawer.drawOver(gg, d.width, d.height); + } + else{ + g.setColor(getForeground()); + drawer.draw(gg, d.width, d.height); + } + gg.setStroke(stroke); + } + + public Color getOverColor(){ + return overColor; + } + + public void setOverColor(Color overColor){ + this.overColor = overColor; + } +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/AbstractMarkDrawer.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/AbstractMarkDrawer.java new file mode 100755 index 0000000..11926b0 --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/AbstractMarkDrawer.java @@ -0,0 +1,65 @@ +package jp.naist.se.stigmata.ui.swing.mds.mark; + + +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.Stroke; + +import jp.naist.se.stigmata.ui.swing.mds.MarkDrawer; + +public abstract class AbstractMarkDrawer implements MarkDrawer{ + private boolean fill; + + public AbstractMarkDrawer(){ + this(false); + } + + public AbstractMarkDrawer(boolean fill){ + setFilled(fill); + } + + public boolean isFilled(){ + return fill; + } + + public void setFilled(boolean fill){ + this.fill = fill; + } + + public abstract Shape getPlainShape(int w, int h); + + public abstract Shape getOveredShape(int w, int h); + + public Stroke getPlainStroke(){ + return null; + } + + public Stroke getOverStroke(){ + return null; + } + + public void draw(Graphics2D g, int w, int h){ + Stroke s = getPlainStroke(); + if(s != null){ + g.setStroke(s); + } + drawImpl(g, getPlainShape(w, h)); + } + + public void drawOver(Graphics2D g, int w, int h){ + Stroke s = getOverStroke(); + if(s != null){ + g.setStroke(s); + } + drawImpl(g, getOveredShape(w, h)); + } + + private void drawImpl(Graphics2D g, Shape s){ + if(isFilled()){ + g.fill(s); + } + else{ + g.draw(s); + } + } +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/CircleDrawer.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/CircleDrawer.java new file mode 100755 index 0000000..64a7c2d --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/CircleDrawer.java @@ -0,0 +1,28 @@ +package jp.naist.se.stigmata.ui.swing.mds.mark; + +import java.awt.Shape; +import java.awt.geom.Ellipse2D; + +public class CircleDrawer extends AbstractMarkDrawer{ + + public CircleDrawer(){ + super(); + } + + public CircleDrawer(boolean fill){ + super(fill); + } + + @Override + public Shape getPlainShape(int w, int h){ + double ww = (double)w / 2d; + double hh = (double)h / 2d; + + return new Ellipse2D.Double(ww - 2d, hh - 2d, 4d, 4d); + } + + @Override + public Shape getOveredShape(int w, int h){ + return new Ellipse2D.Double(0, 0, w - 1d, h - 1d); + } +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/CrossDrawer.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/CrossDrawer.java new file mode 100755 index 0000000..367e5ed --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/CrossDrawer.java @@ -0,0 +1,28 @@ +package jp.naist.se.stigmata.ui.swing.mds.mark; + +import java.awt.Shape; +import java.awt.geom.GeneralPath; + +public class CrossDrawer extends LineMarkDrawer{ + public CrossDrawer(){ + } + + @Override + public Shape getPlainShape(int w, int h){ + float ww = w / 2f; + float hh = h / 2f; + + GeneralPath path = new GeneralPath(); + path.moveTo(0, hh); + path.lineTo(w, hh); + path.moveTo(ww, 0); + path.lineTo(ww, h); + + return path; + } + + @Override + public Shape getOveredShape(int w, int h){ + return getPlainShape(w, h); + } +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/DownerTriangleDrawer.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/DownerTriangleDrawer.java new file mode 100755 index 0000000..802e084 --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/DownerTriangleDrawer.java @@ -0,0 +1,41 @@ +package jp.naist.se.stigmata.ui.swing.mds.mark; + +import java.awt.Shape; +import java.awt.geom.GeneralPath; + +public class DownerTriangleDrawer extends AbstractMarkDrawer{ + + public DownerTriangleDrawer(){ + super(); + } + + public DownerTriangleDrawer(boolean fill){ + super(fill); + } + + @Override + public Shape getPlainShape(int w, int h){ + float ww = (float)w / 2f; + float hh = (float)h / 2f; + + GeneralPath path = new GeneralPath(); + path.moveTo(ww - 2f, hh - 2f); + path.lineTo(ww + 2f, hh - 2f); + path.lineTo(ww, hh - 2f + (float)(2 * Math.sqrt(3))); + path.lineTo(ww - 2f, hh - 2f); + + return path; + } + + @Override + public Shape getOveredShape(int w, int h){ + GeneralPath path = new GeneralPath(); + path.moveTo(0, 0); + path.lineTo(w, 0); + path.lineTo(w / 2f, h); + path.lineTo(0, 0); + + return path; + } + +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/DrawerFactory.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/DrawerFactory.java new file mode 100755 index 0000000..1a9f66d --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/DrawerFactory.java @@ -0,0 +1,37 @@ +package jp.naist.se.stigmata.ui.swing.mds.mark; + +import java.util.HashMap; +import java.util.Map; + +import jp.naist.se.stigmata.ui.swing.mds.GeometoryType; +import jp.naist.se.stigmata.ui.swing.mds.MarkDrawer; + +public class DrawerFactory{ + private static final DrawerFactory instance = new DrawerFactory(); + + private Map drawers = new HashMap(); + + private DrawerFactory(){ + drawers.put(GeometoryType.CROSS, new CrossDrawer()); + drawers.put(GeometoryType.XMARK, new XMarkDrawer()); + drawers.put(GeometoryType.STAR, new StarDrawer()); + drawers.put(GeometoryType.CIRCLE, new CircleDrawer()); + drawers.put(GeometoryType.FILLED_CIRCLE, new CircleDrawer(true)); + drawers.put(GeometoryType.RHOMBUS, new RhombusDrawer()); + drawers.put(GeometoryType.FILLED_RHOMBUS, new RhombusDrawer(true)); + drawers.put(GeometoryType.RECTANGLE, new RectangleDrawer()); + drawers.put(GeometoryType.FILLED_RECTANGLE, new RectangleDrawer(true)); + drawers.put(GeometoryType.UPPER_TRIANGLE, new UpperTriangleDrawer()); + drawers.put(GeometoryType.FILLED_UPPER_TRIANGLE, new UpperTriangleDrawer(true)); + drawers.put(GeometoryType.DOWNER_TRIANGLE, new DownerTriangleDrawer()); + drawers.put(GeometoryType.FILLED_DOWNER_TRIANGLE, new DownerTriangleDrawer(true)); + } + + public static DrawerFactory getInstance(){ + return instance; + } + + public MarkDrawer create(GeometoryType type){ + return drawers.get(type); + } +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/LineMarkDrawer.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/LineMarkDrawer.java new file mode 100755 index 0000000..c6c6d26 --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/LineMarkDrawer.java @@ -0,0 +1,25 @@ +package jp.naist.se.stigmata.ui.swing.mds.mark; + +import java.awt.BasicStroke; +import java.awt.Stroke; + +public abstract class LineMarkDrawer extends AbstractMarkDrawer{ + public LineMarkDrawer(){ + } + + @Override + public boolean isFilled(){ + return false; + } + + @Override + public void setFilled(boolean fill){ + // nothing to to. + } + + @Override + public Stroke getOverStroke(){ + return new BasicStroke(3f); + } + +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/RectangleDrawer.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/RectangleDrawer.java new file mode 100755 index 0000000..e18fff2 --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/RectangleDrawer.java @@ -0,0 +1,28 @@ +package jp.naist.se.stigmata.ui.swing.mds.mark; + +import java.awt.Shape; +import java.awt.geom.Rectangle2D; + +public class RectangleDrawer extends AbstractMarkDrawer{ + + public RectangleDrawer(){ + super(); + } + + public RectangleDrawer(boolean fill){ + super(fill); + } + + @Override + public Shape getPlainShape(int w, int h){ + double ww = (double)w / 2d; + double hh = (double)h / 2d; + + return new Rectangle2D.Double(ww - 2d, hh - 2d, 4d, 4d); + } + + @Override + public Shape getOveredShape(int w, int h){ + return new Rectangle2D.Double(0, 0, w - 1, h - 1); + } +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/RhombusDrawer.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/RhombusDrawer.java new file mode 100755 index 0000000..690ef98 --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/RhombusDrawer.java @@ -0,0 +1,46 @@ +package jp.naist.se.stigmata.ui.swing.mds.mark; + +import java.awt.Shape; +import java.awt.geom.GeneralPath; + +public class RhombusDrawer extends AbstractMarkDrawer{ + + public RhombusDrawer(){ + super(); + } + + public RhombusDrawer(boolean fill){ + super(fill); + } + + @Override + public Shape getPlainShape(int w, int h){ + float ww = (float)w / 2f; + float hh = (float)h / 2f; + + GeneralPath path = new GeneralPath(); + path.moveTo(ww, hh - 2f); + path.lineTo(ww + 2f, hh); + path.lineTo(ww, hh + 2f); + path.lineTo(ww - 2f, hh); + path.lineTo(ww, hh - 2f); + + return path; + } + + @Override + public Shape getOveredShape(int w, int h){ + float ww = (float)w / 2f; + float hh = (float)h / 2f; + + GeneralPath path = new GeneralPath(); + path.moveTo(ww, 0); + path.lineTo(0, hh); + path.lineTo(ww, h - 1f); + path.lineTo(w - 1f, hh); + path.lineTo(ww, 0); + + return path; + } + +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/StarDrawer.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/StarDrawer.java new file mode 100755 index 0000000..01fcd26 --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/StarDrawer.java @@ -0,0 +1,28 @@ +package jp.naist.se.stigmata.ui.swing.mds.mark; + +import java.awt.Shape; +import java.awt.geom.GeneralPath; + +public class StarDrawer extends LineMarkDrawer{ + public StarDrawer(){ + } + + @Override + public Shape getPlainShape(int w, int h){ + float ww = w / 2f; + float hh = h / 2f; + + GeneralPath path = new GeneralPath(); + path.moveTo(0, hh); path.lineTo(w, hh); + path.moveTo(ww, 0); path.lineTo(ww, h); + path.moveTo(0, 0); path.lineTo(w, h); + path.moveTo(w, 0); path.lineTo(0, h); + + return path; + } + + @Override + public Shape getOveredShape(int w, int h){ + return getPlainShape(w, h); + } +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/UpperTriangleDrawer.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/UpperTriangleDrawer.java new file mode 100755 index 0000000..98e67e4 --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/UpperTriangleDrawer.java @@ -0,0 +1,41 @@ +package jp.naist.se.stigmata.ui.swing.mds.mark; + +import java.awt.Shape; +import java.awt.geom.GeneralPath; + +public class UpperTriangleDrawer extends AbstractMarkDrawer{ + + public UpperTriangleDrawer(){ + super(); + } + + public UpperTriangleDrawer(boolean fill){ + super(fill); + } + + @Override + public Shape getPlainShape(int w, int h){ + float ww = (float)w / 2f; + float hh = (float)h / 2f; + + GeneralPath path = new GeneralPath(); + path.moveTo(ww - 2f, hh + 2f); + path.lineTo(ww + 2f, hh + 2f); + path.lineTo(ww, hh + 2f - (float)(2 * Math.sqrt(3))); + path.lineTo(ww - 2f, hh + 2f); + + return path; + } + + @Override + public Shape getOveredShape(int w, int h){ + GeneralPath path = new GeneralPath(); + path.moveTo(0, h - 1f); + path.lineTo(w, h - 1f); + path.lineTo(w / 2f, 0); + path.lineTo(0, h - 1f); + + return path; + } + +} diff --git a/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/XMarkDrawer.java b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/XMarkDrawer.java new file mode 100755 index 0000000..5b78ec4 --- /dev/null +++ b/src/main/java/jp/naist/se/stigmata/ui/swing/mds/mark/XMarkDrawer.java @@ -0,0 +1,25 @@ +package jp.naist.se.stigmata.ui.swing.mds.mark; + +import java.awt.Shape; +import java.awt.geom.GeneralPath; + +public class XMarkDrawer extends LineMarkDrawer{ + public XMarkDrawer(){ + } + + @Override + public Shape getPlainShape(int w, int h){ + GeneralPath path = new GeneralPath(); + path.moveTo(0, 0); + path.lineTo(w, h); + path.moveTo(w, 0); + path.lineTo(0, h); + + return path; + } + + @Override + public Shape getOveredShape(int w, int h){ + return getPlainShape(w, h); + } +} diff --git a/src/main/resources/resources/images/picture_save.png b/src/main/resources/resources/images/picture_save.png new file mode 100755 index 0000000000000000000000000000000000000000..777fb5d2e6a8418c573972246582c21d2c4984e4 GIT binary patch literal 755 zcmVe)^Pp+~01yB`w`9=u(Ho~0 z&q0|Zy>{}2gZl=9K}x9u0000cnYNkw{OYaOaSqCHmHYkvAYHn)ZsML%y6Mn?Rm1M4 zCbIimL%-gdGZROY_IT&jL)x4YKv_2wMMsgSixr3VuIl&xwpoodZKLe>9X|MwKbLly z@9mW{08m0kQ6yEY>2=p_>};yqiMnYtv8~_l+pdQ83=1I;07}RxQW8y8wNsO(vNNsJ zxzT2%smQIeNFo9Nln_CYl7W3j+smTUwfx(8yZemmMmgIvlXtBAH}d|cf5_39J9FWB zT>bgZGbKb&6v=F7!JU=6<_61l#uG1|c+xA2v%dWPU+)_++yuBPsf8gS*uy8tE)TNP^?wUn|FBDi_)Ep5))oIO#kS?(pBVA^IE&o0V2 z1UkY@NmW(0wrgcXNO*bi9DvTz4L^KUm{e2mUH(gvXxc2dSs)?^X1ZCKKmdStIIqc} zY8#!Ri;%QZN+O4dtZAm|x={|gX;Yrg9Xs$WDG3lp>Fmkfnp~qGh?EV=o(rGc zc5iE2*(=lK&%R!Iu5ROK1ORQ0xsI-E$A>rGws+=HNnvgLk2jzGKw)59)ygxcj-Lkr zfNySo7mq#2f!UFlj-4>yTcBWLvS9zN#!QbgB`G2R0KijcuYCLXBg5zC`|}3n1DZUQ la+ac%)7bB~m#l70{SP&gLHlD?H{SpN002ovPDHLkV1hOfWCQ>J literal 0 HcmV?d00001 diff --git a/src/main/resources/resources/images/table_save.png b/src/main/resources/resources/images/table_save.png new file mode 100755 index 0000000000000000000000000000000000000000..25b74d18f740ff208435f72333a1633569c0e833 GIT binary patch literal 723 zcmV;^0xbQBP)9=EBdhkBh&jKg_`&J(Mr{5K9?YB z7%NS3^ZC#w7o(tnOANaU&GbDgva8U-z`c)j6qd7VU7r32pE$mM#UEBK-6|qt9$Fs- z6>t{%pB71ynwG1c@8bc0>raNK6Dt8qRVe;QF-EXH2&zgZfzI{KWSyaNeKXb?5(OWH zv)$_uQKBdbLe2@*YL(JNiVIR}Vqy(9UXB8Al#S?e6$ef`OJ z*^@Dj?#>2+q<{qlHA2?aai;eJ-%1m>7t)ru4w<;#O*nKUzaX~*8Diz*A!^1TLcz. compare.tab.label=Compare Result {0} compare.tab.tooltip=Compare birthmarks <{1}> and <{2}> by {0}. @@ -233,6 +233,29 @@ savebirthmark.button.icon=disk.png birthmarktree.root.label=Birthmark +################################################ +# mds graph pane +################################################ + +savemds.label=Save MDS Graph... +savemds.icon=picture_save.png +savemds.tooltip=Save mds graph image to file. +savemds.button.tooltip=${savemds.tooltip} +savemds.extensions=png, jpg, gif +savemds.description=Save mds graph as image file ({0}) + +savelocation.label=Save coordinate +savelocation.icon=table_save.png +savelocation.tooltip=Save coordinates as csv +savelocation.menuitem.tooltip=${savelocation.tooltip} +savelocation.extensions=csv +savelocation.description=Save coordinates (csv) + +updatecolor.label=Update color... +updateovercolor.label=Update pointed color... +updatecolor.icon=color_swatch.png +updateovercolor.icon=${updatecolor.icon} +updatecolor.button.tooltip= ################################################ # graph pane @@ -250,12 +273,12 @@ minimum.border=Minimum maximum.border=Maximum savegraph.button.label=Save Graph... -savegraph.button.icon=disk.png +savegraph.button.icon=picture_save.png savegraph.extensions=png, jpg, gif savegraph.description=Save graph as image file ({0}) -changecolor.button.label=Change Color... -changecolor.button.icon=color_swatch.png +changecolor.label=Change Color... +changecolor.icon=color_swatch.png changecolor.title=Switch Color showlabel.button.label=Show label diff --git a/src/site/apt/index.apt b/src/site/apt/index.apt index 03faf66..cbd7c1a 100755 --- a/src/site/apt/index.apt +++ b/src/site/apt/index.apt @@ -74,8 +74,35 @@ permissions and limitations under the License. *{{{http://commons.cafebabe.jp/xmlcli/}XmlCli}} 1.0 + *{{{http://math.nist.gov/javanumerics/jama/}Jama}} 1.0.2 (stigmata-1.0.0 later) + [] +**How to install requirement into Maven local repository + + type below command. + +---- +$ mvn install:install-file \ + -Dfile= \ + -DgroupId= \ + -DartifactID= \ + -Dversion= \ + -Dpackaging=jar +---- + + For example, installing Jama-1.0.2.jar into maven local repository, + copy and paste below command. + +---- +$ mvn install:install-file \ + -Dfile=./Jama-1.0.2.jar \ + -DgroupId=Jama \ + -DartifactID=Jama \ + -Dversion=1.0.2 \ + -Dpackaging=jar +---- + *Manually download You can download release build from {{{http://sourceforge.jp/}sourceforge.jp}}. @@ -128,7 +155,7 @@ $ svn checkout http://svn.sourceforge.jp/svnroot/stigmata/trunk/ stigmata You can brouse the source code from following link. - http://svn.sourceforge.jp/cgi-bin/viewcvs.cgi/?root=stigmata + {{{http://svn.sourceforge.jp/cgi-bin/viewcvs.cgi/?root=stigmata}http://svn.sourceforge.jp/cgi-bin/viewcvs.cgi/?root=stigmata}} Related Tools -- 2.11.0