1390 lines
31 KiB
Java
1390 lines
31 KiB
Java
//This file is part of SECONDO.
|
|
|
|
//Copyright (C) 2004, University in Hagen, Department of Computer Science,
|
|
//Database Systems for New Applications.
|
|
|
|
//SECONDO is free software; you can redistribute it and/or modify
|
|
//it under the terms of the GNU General Public License as published by
|
|
//the Free Software Foundation; either version 2 of the License, or
|
|
//(at your option) any later version.
|
|
|
|
//SECONDO is distributed in the hope that it will be useful,
|
|
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
//GNU General Public License for more details.
|
|
|
|
//You should have received a copy of the GNU General Public License
|
|
//along with SECONDO; if not, write to the Free Software
|
|
//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
package viewer.optics;
|
|
|
|
import gui.MainWindow;
|
|
import gui.SecondoObject;
|
|
import gui.idmanager.ID;
|
|
import gui.idmanager.IDManager;
|
|
|
|
import java.awt.BasicStroke;
|
|
import java.awt.Color;
|
|
import java.awt.Component;
|
|
import java.awt.Cursor;
|
|
import java.awt.Dimension;
|
|
import java.awt.Graphics;
|
|
import java.awt.Graphics2D;
|
|
import java.awt.GridBagConstraints;
|
|
import java.awt.GridBagLayout;
|
|
import java.awt.Insets;
|
|
import java.awt.Point;
|
|
import java.awt.Rectangle;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.ActionListener;
|
|
import java.awt.event.ItemEvent;
|
|
import java.awt.event.ItemListener;
|
|
import java.awt.event.KeyEvent;
|
|
import java.awt.event.KeyListener;
|
|
import java.awt.event.MouseEvent;
|
|
import java.awt.event.MouseListener;
|
|
import java.awt.event.MouseMotionListener;
|
|
import java.awt.event.MouseWheelEvent;
|
|
import java.awt.event.MouseWheelListener;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.ArrayList;
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
|
|
import javax.swing.DefaultListCellRenderer;
|
|
import javax.swing.JButton;
|
|
import javax.swing.JCheckBox;
|
|
import javax.swing.JLabel;
|
|
import javax.swing.JLayeredPane;
|
|
import javax.swing.JList;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.JScrollPane;
|
|
import javax.swing.JSlider;
|
|
import javax.swing.JSplitPane;
|
|
import javax.swing.JTextField;
|
|
import javax.swing.ListSelectionModel;
|
|
import javax.swing.event.ChangeEvent;
|
|
import javax.swing.event.ChangeListener;
|
|
import javax.swing.event.ListSelectionEvent;
|
|
import javax.swing.event.ListSelectionListener;
|
|
|
|
import sj.lang.ListExpr;
|
|
import tools.Reporter;
|
|
import viewer.SecondoViewer;
|
|
|
|
/**
|
|
* This class represents the viewer to display the data of optics operator.
|
|
*
|
|
* @author Marius Haug
|
|
*
|
|
*/
|
|
public class OpticsViewer extends SecondoViewer
|
|
implements KeyListener
|
|
,ChangeListener
|
|
,ListSelectionListener
|
|
,MouseWheelListener
|
|
,MouseListener
|
|
,MouseMotionListener
|
|
,ActionListener
|
|
,ItemListener
|
|
{
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
private OpticsBarChart chart = new OpticsBarChart();
|
|
|
|
private JPanel pnlCtrl = new JPanel();
|
|
|
|
private JList lstPoints = new JList(new OpticsPoint[]{});
|
|
|
|
private OpticsPointCellRenderer renderer = new OpticsPointCellRenderer();
|
|
|
|
private JScrollPane sclChart = new JScrollPane(chart);
|
|
private JScrollPane sclPoints = new JScrollPane(lstPoints);
|
|
|
|
private JSplitPane splView = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
|
|
|
private JSlider sldZoom = new JSlider(JSlider.HORIZONTAL);
|
|
|
|
private JTextField txtEps = new JTextField();
|
|
|
|
private JLabel lblEps = new JLabel("Eps");
|
|
|
|
private JButton btnToHeose = new JButton("Create cluster");
|
|
|
|
private MainWindow parent = null;
|
|
|
|
private HashMap<ID, SecondoObject> cachedData = new HashMap<ID, SecondoObject>();
|
|
|
|
private JCheckBox cbOrgCore = new JCheckBox("OC");
|
|
private JCheckBox cbOrgNoise = new JCheckBox("ON");
|
|
private JCheckBox cbSelNoise = new JCheckBox("SN");
|
|
|
|
private ID displayedID = null;
|
|
|
|
public OpticsViewer()
|
|
{
|
|
super();
|
|
create();
|
|
}
|
|
|
|
private void create()
|
|
{
|
|
this.setLayout(new GridBagLayout());
|
|
|
|
lblEps.setPreferredSize(new Dimension(28, 20));
|
|
|
|
txtEps.setPreferredSize(new Dimension(200, 20));
|
|
txtEps.addKeyListener(this);
|
|
txtEps.setFocusTraversalKeysEnabled(false);
|
|
txtEps.setToolTipText("Confirm the maximal displayed eps with TAB or ENTER");
|
|
|
|
sldZoom.setPreferredSize(new Dimension(200, 20));
|
|
sldZoom.setMaximum(5);
|
|
sldZoom.setMinimum(1);
|
|
sldZoom.addChangeListener(this);
|
|
sldZoom.setValue(1);
|
|
sldZoom.addMouseWheelListener(this);
|
|
|
|
cbOrgNoise.setPreferredSize(new Dimension(50, 20));
|
|
cbOrgNoise.setSelected(false);
|
|
cbOrgNoise.setToolTipText("add the \"origin\" noise (reach-dist && core-dist = -1.0) to the selection");
|
|
cbOrgNoise.addItemListener(this);
|
|
|
|
cbOrgCore.setPreferredSize(new Dimension(50, 20));
|
|
cbOrgCore.setSelected(false);
|
|
cbOrgCore.setToolTipText("add the \"origin\" core points (reach-dist = -1.0) to the selection");
|
|
cbOrgCore.addItemListener(this);
|
|
|
|
cbSelNoise.setPreferredSize(new Dimension(50, 20));
|
|
cbSelNoise.setSelected(false);
|
|
cbSelNoise.setToolTipText("add the \"selected\" noise (grey bar) to the selection");
|
|
cbSelNoise.addItemListener(this);
|
|
|
|
btnToHeose.setPreferredSize(new Dimension(140, 20));
|
|
btnToHeose.addActionListener(this);
|
|
|
|
sclChart.getVerticalScrollBar().setUnitIncrement(16);
|
|
sclChart.getHorizontalScrollBar().setUnitIncrement(16);
|
|
|
|
lstPoints.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
|
lstPoints.setCellRenderer(renderer);
|
|
lstPoints.addListSelectionListener(this);
|
|
lstPoints.setFixedCellWidth(200);
|
|
|
|
sclPoints.getVerticalScrollBar().setUnitIncrement(16);
|
|
sclPoints.getHorizontalScrollBar().setUnitIncrement(16);
|
|
|
|
chart.addMouseListener(this);
|
|
chart.addMouseMotionListener(this);
|
|
|
|
splView.add(sclPoints, JSplitPane.LEFT);
|
|
splView.add(sclChart, JSplitPane.RIGHT);
|
|
splView.setPreferredSize(new Dimension(750, 200));
|
|
|
|
pnlCtrl.setLayout(new GridBagLayout());
|
|
pnlCtrl.setPreferredSize(new Dimension(750, 25));
|
|
|
|
pnlCtrl.add(lblEps, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
|
|
,GridBagConstraints.WEST, GridBagConstraints.NONE
|
|
,new Insets(0, 2, 0, 0), 0, 0));
|
|
pnlCtrl.add(txtEps, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0
|
|
,GridBagConstraints.WEST, GridBagConstraints.NONE
|
|
,new Insets(0, 2, 0, 0), 0, 0));
|
|
pnlCtrl.add(sldZoom, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0
|
|
,GridBagConstraints.WEST, GridBagConstraints.NONE
|
|
,new Insets(0, 2, 0, 0), 0, 0));
|
|
pnlCtrl.add(cbOrgCore, new GridBagConstraints(3, 0, 1, 1, 1.0, 0.0
|
|
,GridBagConstraints.EAST, GridBagConstraints.REMAINDER
|
|
,new Insets(0, 2, 0, 0), 0, 0));
|
|
pnlCtrl.add(cbOrgNoise, new GridBagConstraints(4, 0, 1, 1, 0.0, 0.0
|
|
,GridBagConstraints.EAST, GridBagConstraints.NONE
|
|
,new Insets(0, 2, 0, 0), 0, 0));
|
|
pnlCtrl.add(cbSelNoise, new GridBagConstraints(5, 0, 1, 1, 0.0, 0.0
|
|
,GridBagConstraints.EAST, GridBagConstraints.NONE
|
|
,new Insets(0, 2, 0, 0), 0, 0));
|
|
pnlCtrl.add(btnToHeose, new GridBagConstraints(6, 0, 1, 1, 0.0, 0.0
|
|
,GridBagConstraints.EAST, GridBagConstraints.NONE
|
|
,new Insets(0, 2, 0, 0), 0, 0));
|
|
|
|
this.add(pnlCtrl, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0
|
|
,GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL
|
|
, new Insets(2, 2, 2, 2), 0, 0));
|
|
this.add(splView, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0
|
|
,GridBagConstraints.CENTER, GridBagConstraints.BOTH
|
|
,new Insets(0, 0, 0, 0), 0, 0));
|
|
}
|
|
|
|
@Override
|
|
public String getName()
|
|
{
|
|
return "OPTICS-Viewer";
|
|
}
|
|
|
|
@Override
|
|
public boolean addObject(SecondoObject o)
|
|
{
|
|
if(cachedData.get(o.getID()) == null)
|
|
{
|
|
cachedData.put(o.getID(), o);
|
|
return addData(o, false);
|
|
}
|
|
else
|
|
{
|
|
selectObject(o);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void removeObject(SecondoObject o)
|
|
{
|
|
SecondoObject soCached = cachedData.remove(o.getID());
|
|
|
|
if(soCached != null)
|
|
{
|
|
if( displayedID != null
|
|
&& displayedID.equals(o.getID()) )
|
|
{
|
|
chart.clear();
|
|
lstPoints.setListData(new OpticsPoint[]{});
|
|
lstPoints.revalidate();
|
|
txtEps.setText(null);
|
|
}
|
|
|
|
Iterator<ID> it = cachedData.keySet().iterator();
|
|
|
|
if(it.hasNext())
|
|
{
|
|
selectObject(cachedData.get(it.next()));
|
|
}
|
|
|
|
// if( parent != null
|
|
// && (soCached = cachedDataSend.get(o.getID())) != null)
|
|
// {
|
|
// parent.hideObject(new String("Force to delete"), soCached);
|
|
// }
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void removeAll()
|
|
{
|
|
displayedID = null;
|
|
cachedData.clear();
|
|
chart.clear();
|
|
lstPoints.setListData(new OpticsPoint[]{});
|
|
lstPoints.revalidate();
|
|
txtEps.setText(null);
|
|
}
|
|
|
|
@Override
|
|
public boolean canDisplay(SecondoObject o)
|
|
{
|
|
return addData(o, true);
|
|
}
|
|
|
|
private boolean addData(SecondoObject o, boolean checkOnly)
|
|
{
|
|
try
|
|
{
|
|
ListExpr LE = o.toListExpr();
|
|
ListExpr leType = LE.first();
|
|
ListExpr leValue = LE.second();
|
|
|
|
// analyse leType
|
|
ListExpr maintype = leType.first();
|
|
|
|
if( leType.listLength() != 2 || !maintype.isAtom()
|
|
|| maintype.atomType() != ListExpr.SYMBOL_ATOM
|
|
|| !( maintype.symbolValue().equals("rel")
|
|
|| maintype.symbolValue().equals("mrel")
|
|
|| maintype.symbolValue().equals("trel") ) )
|
|
{
|
|
//Reporter.showError("Not a relation!");
|
|
return false;
|
|
}
|
|
|
|
ListExpr tupletype = leType.second();
|
|
|
|
// analyse Tuple
|
|
ListExpr TupleFirst = tupletype.first();
|
|
|
|
if( tupletype.listLength()!= 2 || !TupleFirst.isAtom()
|
|
|| TupleFirst.atomType() != ListExpr.SYMBOL_ATOM
|
|
|| !( TupleFirst.symbolValue().equals("tuple")
|
|
| TupleFirst.symbolValue().equals("mtuple") ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
ListExpr TupleTypeValue = tupletype.second();
|
|
|
|
if(TupleTypeValue.listLength() < 5)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
ListExpr TupleSubType = null;
|
|
int len = TupleTypeValue.listLength();
|
|
int count = 0;
|
|
|
|
//check the optics elements
|
|
while(!TupleTypeValue.isEmpty())
|
|
{
|
|
TupleSubType = TupleTypeValue.first();
|
|
String type = TupleSubType.second().symbolValue();
|
|
|
|
if(count == len-4)
|
|
{
|
|
if(!"real".equals(type) )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if(count == len-3)
|
|
{
|
|
if(!"real".equals(type) )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if(count == len-2)
|
|
{
|
|
if(!"bool".equals(type) )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if(count == len-1)
|
|
{
|
|
if(!"real".equals(type) )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
count++;
|
|
TupleTypeValue = TupleTypeValue.rest();
|
|
}
|
|
|
|
if(!checkOnly)
|
|
{
|
|
add(leValue, leType);
|
|
displayedID = o.getID();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
//e.printStackTrace(System.out);
|
|
//Reporter.showError(e.getStackTrace().toString());
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void add(ListExpr leValue, ListExpr leType)
|
|
{
|
|
try
|
|
{
|
|
setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
|
ArrayList<OpticsPoint> alPoints = new ArrayList<OpticsPoint>();
|
|
ListExpr tupletype = leType.second();
|
|
// analyse the values
|
|
ListExpr TupleValue;
|
|
ListExpr currTmp = null;
|
|
ListExpr TupleTypeValue = tupletype.second();
|
|
int len = TupleTypeValue.listLength();
|
|
int order = 1;
|
|
double eps = 0.0;
|
|
|
|
while(!leValue.isEmpty())
|
|
{
|
|
int count = 0;
|
|
|
|
TupleValue = leValue.first();
|
|
TupleTypeValue = tupletype.second();
|
|
|
|
OpticsPoint op = new OpticsPoint();
|
|
|
|
String name = null;
|
|
String type = null;
|
|
|
|
while( !TupleValue.isEmpty()
|
|
&& !TupleTypeValue.isEmpty() )
|
|
{
|
|
currTmp = TupleValue.first();
|
|
ListExpr TupleSubType = TupleTypeValue.first();
|
|
|
|
name = TupleSubType.first().symbolValue();
|
|
type = TupleSubType.second().symbolValue();
|
|
|
|
if("string".equals(type))
|
|
{
|
|
op.addElem(name, currTmp.stringValue());
|
|
}
|
|
else if("int".equals(type))
|
|
{
|
|
op.addElem(name, currTmp.intValue() + "");
|
|
}
|
|
else if( "real".equals(type) )
|
|
{
|
|
op.addElem(name, currTmp.realValue() + "");
|
|
}
|
|
else if( "bool".equals(type) )
|
|
{
|
|
op.addElem(name, currTmp.boolValue() + "");
|
|
}
|
|
else
|
|
{
|
|
op.addElem(name, "n/a");
|
|
}
|
|
|
|
if(count == len-4)
|
|
{
|
|
op.setCoreDist(currTmp.realValue());
|
|
}
|
|
else if(count == len-3)
|
|
{
|
|
op.setReachDist(currTmp.realValue());
|
|
}
|
|
else if(count == len-1)
|
|
{
|
|
eps = currTmp.realValue();
|
|
}
|
|
|
|
TupleValue = TupleValue.rest();
|
|
TupleTypeValue = TupleTypeValue.rest();
|
|
count++;
|
|
}
|
|
|
|
op.setOrder(order++);
|
|
alPoints.add(op);
|
|
leValue = leValue.rest();
|
|
}
|
|
|
|
txtEps.setText(eps*2 + "");
|
|
chart.setEps(eps*2);
|
|
chart.add(alPoints);
|
|
lstPoints.setListData(alPoints.toArray());
|
|
lstPoints.revalidate();
|
|
sclChart.doLayout();
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
//e.printStackTrace(System.out);
|
|
//Reporter.showError(e.getStackTrace().toString());
|
|
}
|
|
finally
|
|
{
|
|
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isDisplayed(SecondoObject o)
|
|
{
|
|
return displayedID != null && displayedID.equals(o.getID());
|
|
}
|
|
|
|
@Override
|
|
public boolean selectObject(SecondoObject o)
|
|
{
|
|
SecondoObject soCached = cachedData.get(o.getID());
|
|
|
|
if(soCached == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if( displayedID != null
|
|
&& displayedID.equals(o.getID()) )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return addData(soCached, false);
|
|
}
|
|
|
|
@Override
|
|
public void keyPressed(KeyEvent e) {}
|
|
|
|
@Override
|
|
public void keyReleased(KeyEvent e)
|
|
{
|
|
if( e.getSource() == txtEps
|
|
&& ( e.getKeyCode() == KeyEvent.VK_TAB
|
|
|| e.getKeyCode() == KeyEvent.VK_ENTER ) )
|
|
{
|
|
String value = txtEps.getText();
|
|
|
|
if(value != null && !value.trim().equals(""))
|
|
{
|
|
try
|
|
{
|
|
double eps = Double.valueOf(value);
|
|
chart.setEps(eps);
|
|
sclChart.doLayout();
|
|
}
|
|
catch(NumberFormatException ex)
|
|
{
|
|
Reporter.showError("Not a valid number " + ex.getMessage());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void keyTyped(KeyEvent e) {}
|
|
|
|
@Override
|
|
public void valueChanged(ListSelectionEvent e)
|
|
{
|
|
if(e.getSource() == lstPoints)
|
|
{
|
|
OpticsPoint tmp = (OpticsPoint) ((JList) e.getSource()).getSelectedValue();
|
|
if(tmp != null)
|
|
{
|
|
chart.setSelected(tmp.order);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void stateChanged(ChangeEvent e)
|
|
{
|
|
if(e.getSource() == sldZoom)
|
|
{
|
|
chart.setZoom(sldZoom.getValue());
|
|
sclChart.doLayout();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void mouseClicked(MouseEvent e)
|
|
{
|
|
if(e.getSource() == chart)
|
|
{
|
|
int idx = chart.getSelected(e.getX(), e.getY());
|
|
if(idx > -1)
|
|
{
|
|
lstPoints.setSelectedIndex(idx);
|
|
lstPoints.ensureIndexIsVisible(idx);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void mouseWheelMoved(MouseWheelEvent e)
|
|
{
|
|
if(e.getSource() == sldZoom)
|
|
{
|
|
sldZoom.setValue(sldZoom.getValue() + e.getWheelRotation());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void mouseEntered(MouseEvent e) {}
|
|
|
|
@Override
|
|
public void mouseExited(MouseEvent e) {}
|
|
|
|
@Override
|
|
public void mousePressed(MouseEvent e) {}
|
|
|
|
@Override
|
|
public void mouseReleased(MouseEvent e)
|
|
{
|
|
if(e.getSource() == chart)
|
|
{
|
|
chart.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void mouseDragged(MouseEvent e)
|
|
{
|
|
if(e.getSource() == chart)
|
|
{
|
|
if(chart.grabbed)
|
|
{
|
|
chart.setCursor(new Cursor(Cursor.MOVE_CURSOR));
|
|
chart.setEpsLine(e.getY());
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void mouseMoved(MouseEvent e)
|
|
{
|
|
if(e.getSource() == chart)
|
|
{
|
|
if(chart.epsLineFocused(e.getX(), e.getY()))
|
|
{
|
|
chart.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
|
}
|
|
else
|
|
{
|
|
chart.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void actionPerformed(ActionEvent e)
|
|
{
|
|
if(e.getSource() == btnToHeose)
|
|
{
|
|
actionPerformed_btnToHoese(e);
|
|
}
|
|
}
|
|
|
|
private void actionPerformed_btnToHoese(ActionEvent e)
|
|
{
|
|
if(parent == null)
|
|
{
|
|
Component c = getParent();
|
|
|
|
while(parent == null && c != null)
|
|
{
|
|
if(c instanceof MainWindow)
|
|
{
|
|
parent = (MainWindow) c;
|
|
}
|
|
|
|
c = c.getParent();
|
|
}
|
|
|
|
if(parent == null)
|
|
{
|
|
Reporter.showError("Main Window could not determinded ");
|
|
btnToHeose.setEnabled(false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ListExpr le = new ListExpr();
|
|
le.readFromString(cachedData.get(displayedID).toListExpr().writeListExprToString());
|
|
ListExpr type = le.first();
|
|
ListExpr value = le.second();
|
|
|
|
ListExpr attrList = type.second().second();
|
|
ListExpr newAttrList = ListExpr.oneElemList(attrList.first());
|
|
ListExpr lastAttrList = newAttrList;
|
|
|
|
attrList = attrList.rest();
|
|
|
|
while(!attrList.isEmpty())
|
|
{
|
|
lastAttrList = ListExpr.append(lastAttrList, attrList.first());
|
|
attrList = attrList.rest();
|
|
}
|
|
|
|
lastAttrList = ListExpr.append(lastAttrList
|
|
,ListExpr.twoElemList(ListExpr.symbolAtom("ClusterID")
|
|
,ListExpr.symbolAtom("int")));
|
|
|
|
|
|
|
|
ListExpr a = ListExpr.twoElemList(
|
|
ListExpr.symbolAtom("rel")
|
|
,ListExpr.twoElemList(
|
|
ListExpr.symbolAtom("tuple"), newAttrList));
|
|
|
|
ListExpr choice = null;
|
|
ListExpr points = null;
|
|
|
|
int i = 0;
|
|
ListExpr last = null;
|
|
int cid = 0;
|
|
int curCid = 0;
|
|
int lastCount = -1;
|
|
|
|
boolean withSelNoise = cbSelNoise.isSelected();
|
|
boolean withOrgNoise = cbOrgNoise.isSelected();
|
|
boolean withOrgCore = cbOrgCore.isSelected();
|
|
|
|
do
|
|
{
|
|
ListExpr tmp = value.first();
|
|
boolean add = false;
|
|
boolean core = false;
|
|
boolean noise = false;
|
|
OpticsPoint op;
|
|
|
|
if(chart.isSelected(i))
|
|
{
|
|
add = true;
|
|
}
|
|
|
|
if(withOrgCore)
|
|
{
|
|
if( (op = chart.getOpticsPoint(i)) != null
|
|
&& op.reachDist == -1.0 && op.coreDist >= 0.0 )
|
|
{
|
|
core = true;
|
|
}
|
|
}
|
|
|
|
if(withOrgNoise)
|
|
{
|
|
if( (op = chart.getOpticsPoint(i)) != null
|
|
&& op.reachDist == -1.0 && op.coreDist == -1.0 )
|
|
{
|
|
noise = true;
|
|
}
|
|
}
|
|
|
|
if(withSelNoise)
|
|
{
|
|
if(!chart.isSelected(i))
|
|
{
|
|
noise = true;
|
|
}
|
|
}
|
|
|
|
if(add || core || noise)
|
|
{
|
|
if(noise)
|
|
{
|
|
curCid = -1;
|
|
}
|
|
else
|
|
{
|
|
if(core)
|
|
{
|
|
curCid = ++cid;
|
|
}
|
|
else
|
|
{
|
|
cid = i-1 != lastCount ? ++cid : cid;
|
|
curCid = cid;
|
|
}
|
|
}
|
|
|
|
ListExpr valueList = tmp;
|
|
ListExpr newValueList = valueList;
|
|
ListExpr lastValueList = newValueList;
|
|
|
|
valueList = valueList.rest();
|
|
|
|
while(!valueList.isEmpty())
|
|
{
|
|
lastValueList = ListExpr.append(lastValueList, valueList.first());
|
|
valueList = valueList.rest();
|
|
}
|
|
|
|
lastValueList = ListExpr.append(lastValueList
|
|
,ListExpr.intAtom(curCid));
|
|
|
|
if(points == null)
|
|
{
|
|
points = ListExpr.oneElemList(newValueList);
|
|
choice = ListExpr.twoElemList(a, points);
|
|
last = points;
|
|
}
|
|
else
|
|
{
|
|
last = ListExpr.append(last, newValueList);
|
|
}
|
|
|
|
lastCount = i;
|
|
}
|
|
else if(withOrgNoise)
|
|
{
|
|
|
|
}
|
|
|
|
value = value.rest();
|
|
i++;
|
|
} while(!value.isEmpty());
|
|
|
|
ID id = IDManager.getNextID();
|
|
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy hh:mm:ss");
|
|
SecondoObject obj = new SecondoObject("Optics selection + " + sdf.format(new Date()) + " (#" + id + ")", choice);
|
|
obj.setID(id);
|
|
// cachedDataSend.put(displayedID, obj);
|
|
// parent.displayAt("Hoese-Viewer", obj);
|
|
parent.addObject(obj);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void itemStateChanged(ItemEvent e)
|
|
{
|
|
if(e.getSource() == cbSelNoise)
|
|
{
|
|
cbOrgCore.setSelected(false);
|
|
cbOrgNoise.setSelected(false);
|
|
}
|
|
else if(e.getSource() == cbOrgCore)
|
|
{
|
|
cbSelNoise.setSelected(false);
|
|
}
|
|
else if(e.getSource() == cbOrgNoise)
|
|
{
|
|
cbSelNoise.setSelected(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @author Marius Haug
|
|
*
|
|
*/
|
|
class OpticsPoint implements Comparable<OpticsPoint>
|
|
{
|
|
private int order;
|
|
|
|
private double reachDist;
|
|
private double coreDist;
|
|
|
|
private String txt = "";
|
|
|
|
public OpticsPoint() {}
|
|
|
|
public OpticsPoint(int order, double reachDist, double coreDist)
|
|
{
|
|
this.order = order;
|
|
this.reachDist = reachDist;
|
|
this.coreDist = coreDist;
|
|
}
|
|
|
|
public void addElem(String type, String value)
|
|
{
|
|
this.txt = this.txt
|
|
+ "<tr><td><b>" + type
|
|
+ "</b></td><td>:"
|
|
+ "</td><td>" + value
|
|
+ "</td></tr>";
|
|
}
|
|
|
|
public String getTxt()
|
|
{
|
|
return "<html><table border=\"0\", style=\"font-family:arial;font-size:10\">"
|
|
+ txt
|
|
//+ "<tr><td><b>ORDER" + "</b></td><td>:"
|
|
// + "</td><td>" + order
|
|
// + "</td></tr>"
|
|
+ "</table></html>";
|
|
}
|
|
|
|
public void setOrder(int order)
|
|
{
|
|
this.order = order;
|
|
}
|
|
|
|
public int getOrder()
|
|
{
|
|
return order;
|
|
}
|
|
|
|
public void setReachDist(double reachDist)
|
|
{
|
|
this.reachDist = reachDist;
|
|
}
|
|
|
|
public double getReachDist()
|
|
{
|
|
return reachDist;
|
|
}
|
|
|
|
public void setCoreDist(double coreDist)
|
|
{
|
|
this.coreDist = coreDist;
|
|
}
|
|
|
|
public double getCoreDist()
|
|
{
|
|
return coreDist;
|
|
}
|
|
|
|
@Override
|
|
public int compareTo(OpticsPoint o)
|
|
{
|
|
if(this.order < o.order)
|
|
{
|
|
return -1;
|
|
}
|
|
else if(this.order > o.order)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @author Marius Haug
|
|
*
|
|
*/
|
|
class OpticsPointCellRenderer extends DefaultListCellRenderer
|
|
{
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
@Override
|
|
public Component getListCellRendererComponent(JList list, Object value
|
|
,int index, boolean isSelected, boolean cellHasFocus)
|
|
{
|
|
JLabel lbl = (JLabel) super.getListCellRendererComponent(list, value
|
|
,index, isSelected, cellHasFocus);
|
|
|
|
OpticsPoint point = (OpticsPoint) value;
|
|
|
|
lbl.setText(point.getTxt());
|
|
|
|
if(!isSelected)
|
|
{
|
|
lbl.setBackground(index%2 == 0 ? Color.WHITE : Color.LIGHT_GRAY);
|
|
}
|
|
|
|
return lbl;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @author Marius Haug
|
|
*
|
|
*/
|
|
class OpticsBarChart extends JLayeredPane
|
|
{
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
private static final int OFF_SCL_HEIGTH = 40;
|
|
private static final int OFF_SCL_WIDTH = 80;
|
|
private static final int CS_HEIGHT = 200;
|
|
private static final int MARK_WIDTH = 10;
|
|
private static final int TXT_SPACE = 45;
|
|
private static final int MARK_STEP = CS_HEIGHT/10;
|
|
private static final int MARK_STEP_PNT = 10;
|
|
|
|
private int zoomHeight;
|
|
private int zoomWidth;
|
|
private int zoomOff;
|
|
private int zoomMarkStep;
|
|
private int zoomMarkStepPnt;
|
|
private int zoom = 1;
|
|
private int selIdx = -1;
|
|
private int points = 0;
|
|
private int OFF_EPS_LINE = 0;
|
|
private int epsLineOff = 0;
|
|
|
|
private double maxEps = 100;
|
|
|
|
private boolean initialized = false;
|
|
private boolean grabbed = false;
|
|
|
|
private Dimension dimSize = new Dimension(points, (int) maxEps);
|
|
|
|
private ArrayList<OpticsPoint> alPoints = new ArrayList<OpticsPoint>();
|
|
|
|
private Color curColor = Color.BLUE;
|
|
|
|
private Rectangle epsLine = new Rectangle();
|
|
private Rectangle epsLineCalc = new Rectangle();
|
|
|
|
/**
|
|
* Constructor of the class.
|
|
*
|
|
*/
|
|
public OpticsBarChart()
|
|
{
|
|
super();
|
|
this.setLayout(new GridBagLayout());
|
|
}
|
|
|
|
/**
|
|
* Constructor of the class.
|
|
*
|
|
* @param maxEps maximum displayed eps
|
|
*/
|
|
public OpticsBarChart(double maxEps)
|
|
{
|
|
this.maxEps = maxEps * zoom;
|
|
}
|
|
|
|
/**
|
|
* This method sets the points.
|
|
*
|
|
* @param alPoints
|
|
*/
|
|
public void add(ArrayList<OpticsPoint> alPoints)
|
|
{
|
|
clear();
|
|
this.alPoints = alPoints;
|
|
points = alPoints.size();
|
|
initialized = true;
|
|
repaint();
|
|
}
|
|
|
|
/**
|
|
* This method sets the points.
|
|
*
|
|
* @param alPoints
|
|
*/
|
|
public void add(OpticsPoint op, boolean forceRepaint)
|
|
{
|
|
this.alPoints.add(op);
|
|
points = alPoints.size();
|
|
initialized = true;
|
|
|
|
if(forceRepaint)
|
|
{
|
|
repaint();
|
|
}
|
|
}
|
|
|
|
public ArrayList<OpticsPoint> getElements()
|
|
{
|
|
return alPoints;
|
|
}
|
|
|
|
/**
|
|
* Sets the selected bar in the chart.
|
|
*
|
|
* @param selPoint
|
|
*/
|
|
public void setSelected(int selPoint)
|
|
{
|
|
this.selIdx = selPoint-1;
|
|
|
|
Point p = sclChart.getViewport().getViewPosition();
|
|
Dimension d = sclChart.getViewport().getSize();
|
|
int p1X = (int) (OFF_SCL_WIDTH + (zoom* selPoint));
|
|
|
|
if(p.x + d.width < p1X + OFF_SCL_WIDTH)
|
|
{
|
|
p.x = p1X +OFF_SCL_WIDTH - d.width;
|
|
|
|
if(p.x + d.width > (OFF_SCL_WIDTH + (points * zoom)))
|
|
{
|
|
p.x = (OFF_SCL_WIDTH + (points * zoom));
|
|
}
|
|
}
|
|
else if(p.x > p1X -OFF_SCL_WIDTH)
|
|
{
|
|
p.x = p1X - OFF_SCL_WIDTH;
|
|
|
|
if(p.x < 0)
|
|
{
|
|
p.x = 0;
|
|
}
|
|
}
|
|
|
|
sclChart.getViewport().setViewPosition(p);
|
|
|
|
repaint();
|
|
}
|
|
|
|
/**
|
|
* Returns the index of the bar in the chart.
|
|
*
|
|
* @param x
|
|
* @param y
|
|
* @return
|
|
*/
|
|
public int getSelected(int x, int y)
|
|
{
|
|
int i = ((x - OFF_SCL_WIDTH)/zoom) -1;
|
|
|
|
if(i > -1 && i < points)
|
|
{
|
|
OpticsPoint p = alPoints.get(i);
|
|
|
|
int p1Y = (int) OFF_SCL_HEIGTH + zoomHeight;
|
|
int p2Y = (int) ((p.getReachDist() >= maxEps || p.getReachDist() < 0)
|
|
? OFF_SCL_HEIGTH
|
|
: OFF_SCL_HEIGTH + zoomHeight - (scale(p.getReachDist()) * zoom));
|
|
|
|
if(p1Y >= y && p2Y <= y)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
public boolean epsLineFocused(int x, int y)
|
|
{
|
|
if(epsLine.contains(x, y))
|
|
{
|
|
if(!grabbed)
|
|
{
|
|
grabbed = true;
|
|
repaint();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(grabbed)
|
|
{
|
|
grabbed = false;
|
|
repaint();
|
|
}
|
|
}
|
|
|
|
return grabbed;
|
|
}
|
|
|
|
public void setEpsLine(int x)
|
|
{
|
|
OFF_EPS_LINE = (x - OFF_SCL_HEIGTH)/zoom;
|
|
calcStrt();
|
|
repaint();
|
|
}
|
|
|
|
/**
|
|
* This method deletes all points.
|
|
*
|
|
*/
|
|
public void clear()
|
|
{
|
|
initialized = false;
|
|
points = 0;
|
|
alPoints.clear();
|
|
repaint();
|
|
}
|
|
|
|
/**
|
|
* This method sets the zoom factor.
|
|
*
|
|
* @param zoom
|
|
*/
|
|
public void setZoom(int zoom)
|
|
{
|
|
this.zoom = zoom;
|
|
repaint();
|
|
}
|
|
|
|
/**
|
|
* This method sets the max eps displayed in the coordinate system.
|
|
*
|
|
* @param eps
|
|
*/
|
|
public void setEps(double eps)
|
|
{
|
|
maxEps = eps;
|
|
repaint();
|
|
}
|
|
|
|
private void calcStrt()
|
|
{
|
|
zoomWidth = points * zoom;
|
|
zoomHeight = CS_HEIGHT * zoom;
|
|
zoomOff = zoom/2;
|
|
zoomMarkStep = MARK_STEP * zoom;
|
|
zoomMarkStepPnt = MARK_STEP_PNT * zoom;
|
|
epsLineOff = OFF_EPS_LINE * zoom;
|
|
|
|
if(epsLineOff < 0)
|
|
{
|
|
epsLineOff = 0;
|
|
}
|
|
else if(epsLineOff > zoomOff + zoomHeight)
|
|
{
|
|
epsLineOff = zoomOff + zoomHeight;
|
|
}
|
|
|
|
dimSize = new Dimension(OFF_SCL_WIDTH + OFF_SCL_WIDTH + zoomWidth
|
|
,OFF_SCL_HEIGTH + OFF_SCL_HEIGTH + zoomHeight);
|
|
|
|
epsLine.setBounds(OFF_SCL_WIDTH + zoomOff - 5
|
|
,OFF_SCL_HEIGTH - 5 + epsLineOff
|
|
,zoomOff + zoomWidth + 5 + 10
|
|
,zoomOff + 10);
|
|
|
|
epsLineCalc.setBounds(OFF_SCL_WIDTH + zoomOff
|
|
,OFF_SCL_HEIGTH + epsLineOff
|
|
,zoomOff + zoomWidth
|
|
,zoomOff + 1);
|
|
}
|
|
|
|
@Override
|
|
public Dimension getPreferredSize()
|
|
{
|
|
return dimSize;
|
|
}
|
|
|
|
@Override
|
|
public void paint(Graphics g)
|
|
{
|
|
super.paint(g);
|
|
calcStrt();
|
|
paintBars(g);
|
|
paintCoordinateSystem(g);
|
|
}
|
|
|
|
/**
|
|
* This method paints the coordinate system.
|
|
*
|
|
* @param g
|
|
*/
|
|
private void paintCoordinateSystem(Graphics g)
|
|
{
|
|
if(initialized)
|
|
{
|
|
Graphics2D g2 = (Graphics2D) g;
|
|
|
|
g2.setColor(Color.BLACK);
|
|
g2.setStroke(new BasicStroke(1));
|
|
|
|
double eps = maxEps;
|
|
for(int i = 0; i < 10; i++)
|
|
{
|
|
g.drawString(Math.round(eps*100d)/100d + ""
|
|
,OFF_SCL_WIDTH - MARK_WIDTH - TXT_SPACE
|
|
,OFF_SCL_HEIGTH + (zoomMarkStep * i + 5));
|
|
//draw mark lines
|
|
g2.drawLine(OFF_SCL_WIDTH + zoomOff - MARK_WIDTH
|
|
,OFF_SCL_HEIGTH + (zoomMarkStep * i)
|
|
,OFF_SCL_WIDTH + zoomOff
|
|
,OFF_SCL_HEIGTH + (zoomMarkStep * i));
|
|
|
|
eps = eps - (maxEps/10);
|
|
}
|
|
|
|
int steps = points/MARK_STEP_PNT;
|
|
for(int i = 1; i <= steps; i++)
|
|
{
|
|
//draw mark lines
|
|
g2.drawLine(OFF_SCL_WIDTH + (zoomMarkStepPnt * i)
|
|
,OFF_SCL_HEIGTH + zoomOff + zoomHeight
|
|
,OFF_SCL_WIDTH + (zoomMarkStepPnt * i)
|
|
,OFF_SCL_HEIGTH + zoomOff + zoomHeight + MARK_WIDTH);
|
|
|
|
}
|
|
|
|
//draw X-coordinate
|
|
g2.drawLine(OFF_SCL_WIDTH + zoomOff
|
|
,OFF_SCL_HEIGTH - 5
|
|
,OFF_SCL_WIDTH + zoomOff
|
|
,OFF_SCL_HEIGTH + zoomOff + zoomHeight);
|
|
|
|
//draw Y-coordinate
|
|
g2.drawLine(OFF_SCL_WIDTH + zoomOff
|
|
,OFF_SCL_HEIGTH + zoomOff + zoomHeight
|
|
,OFF_SCL_WIDTH + zoomOff + zoomWidth + 5
|
|
,OFF_SCL_HEIGTH + zoomOff + zoomHeight);
|
|
|
|
g2.setColor(Color.BLACK);
|
|
g2.setStroke(new BasicStroke(2));
|
|
|
|
//draw max eps line
|
|
g2.drawLine(OFF_SCL_WIDTH + zoomOff
|
|
,OFF_SCL_HEIGTH + epsLineOff
|
|
,OFF_SCL_WIDTH + zoomOff + zoomWidth + 5
|
|
,OFF_SCL_HEIGTH + epsLineOff);
|
|
|
|
if(grabbed)
|
|
{
|
|
g2.setColor(Color.RED);
|
|
g2.setStroke(new BasicStroke(2));
|
|
g2.drawRect(OFF_SCL_WIDTH + zoomOff - 2
|
|
,OFF_SCL_HEIGTH - 2 + epsLineOff
|
|
,zoomOff + zoomWidth + 5 + 2
|
|
,zoomOff + 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This method paints the points into the coordinate system.
|
|
*
|
|
* @param g
|
|
*/
|
|
private void paintBars(Graphics g)
|
|
{
|
|
if(initialized)
|
|
{
|
|
Graphics2D g2 = (Graphics2D) g;
|
|
g2.setStroke(new BasicStroke(zoom));
|
|
|
|
int iStart = ((getVisibleRect().x - OFF_SCL_WIDTH)/zoom) -1;
|
|
int iEnd = ((getVisibleRect().x + getVisibleRect().width - OFF_SCL_WIDTH)/zoom) -1;
|
|
iStart = iStart < 0 ? 0 : iStart;
|
|
iEnd = iEnd > points ? points : iEnd;
|
|
|
|
for(int i = iStart; i < iEnd; i++)
|
|
{
|
|
OpticsPoint p = alPoints.get(i);//it.next();
|
|
|
|
int p1X = (int) (OFF_SCL_WIDTH + (p.getOrder() * zoom));
|
|
int p1Y = (int) OFF_SCL_HEIGTH + zoomHeight;
|
|
int p2X = (int) (OFF_SCL_WIDTH + (p.getOrder() * zoom));
|
|
int p2Y = (int) ((p.getReachDist() >= maxEps || p.getReachDist() < 0)
|
|
? OFF_SCL_HEIGTH
|
|
: OFF_SCL_HEIGTH + zoomHeight - (scale(p.getReachDist()) * zoom));
|
|
|
|
if(epsLineCalc.intersects(p2X, p2Y, p1X - OFF_SCL_WIDTH
|
|
,p1Y - OFF_SCL_HEIGTH)
|
|
|| p.getReachDist() < 0)
|
|
{
|
|
curColor = Color.LIGHT_GRAY;
|
|
}
|
|
else
|
|
{
|
|
curColor = Color.BLUE;
|
|
}
|
|
|
|
if(i == selIdx)
|
|
{
|
|
g2.setColor(Color.RED);
|
|
}
|
|
else
|
|
{
|
|
g2.setColor(curColor);
|
|
}
|
|
|
|
g2.drawLine(p1X, p1Y, p2X, p2Y);
|
|
}
|
|
}
|
|
|
|
curColor = Color.YELLOW;
|
|
}
|
|
|
|
private double scale(double d)
|
|
{
|
|
return d/(maxEps/CS_HEIGHT);
|
|
}
|
|
|
|
public boolean isSelected(int i)
|
|
{
|
|
if(i >= alPoints.size())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
OpticsPoint p = alPoints.get(i);
|
|
|
|
int p1X = (int) (OFF_SCL_WIDTH + (p.getOrder() * zoom));
|
|
int p1Y = (int) OFF_SCL_HEIGTH + zoomHeight;
|
|
int p2X = (int) (OFF_SCL_WIDTH + (p.getOrder() * zoom));
|
|
int p2Y = (int) ((p.getReachDist() >= maxEps || p.getReachDist() < 0)
|
|
? OFF_SCL_HEIGTH
|
|
: OFF_SCL_HEIGTH + zoomHeight - (scale(p.getReachDist()) * zoom));
|
|
boolean cl = !(epsLineCalc.intersects(p2X, p2Y
|
|
,p1X - OFF_SCL_WIDTH
|
|
,p1Y - OFF_SCL_HEIGTH)
|
|
|| p.getReachDist() < 0);
|
|
return cl;
|
|
}
|
|
|
|
public OpticsPoint getOpticsPoint(int i)
|
|
{
|
|
if(i >= alPoints.size())
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return alPoints.get(i);
|
|
}
|
|
}
|
|
}
|