de.openVJJ.plugins.LineFromSorbel2DIntArray.java Source code

Java tutorial

Introduction

Here is the source code for de.openVJJ.plugins.LineFromSorbel2DIntArray.java

Source

/**
 * 
 */
package de.openVJJ.plugins;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import java.util.ArrayList;

import javax.swing.ButtonGroup;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.jdom2.Element;

import de.openVJJ.basic.Connection;
import de.openVJJ.basic.Value;
import de.openVJJ.basic.Connection.ConnectionListener;
import de.openVJJ.basic.Value.Lock;
import de.openVJJ.basic.Plugin;
import de.openVJJ.values.Integer2DArrayValue;
import de.openVJJ.values.PointCloud;
import de.openVJJ.values.PointCloundList;

/**
 * 
 * Copyright (C) 2014 Jan-Erik Matthies
 * 
 * This program 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 3 of the License, or (at your option) any later version.
 * 
 * This program 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 this program;
 * if not, see <http://www.gnu.org/licenses/>.
 * 
 * @author Jan-Erik Matthies
 * 
 */
public class LineFromSorbel2DIntArray extends Plugin {

    public static final String ELEMENT_NAME_LineFromSorbel2DIntArray_CONFIG = "LineFromSorbel2DIntArray";

    /**
     * 
     */
    public LineFromSorbel2DIntArray() {
        addInput("Sorbel", Integer2DArrayValue.class);
        addOutput("Lines", PointCloundList.class);
    }

    /* (non-Javadoc)
     * @see de.openVJJ.basic.Plugin#sendStatics()
     */
    @Override
    public void sendStatics() {
        // TODO Auto-generated method stub

    }

    /* (non-Javadoc)
     * @see de.openVJJ.basic.Plugable#createConnectionListener(java.lang.String, de.openVJJ.basic.Connection)
     */
    @Override
    protected ConnectionListener createConnectionListener(String inpuName, Connection connection) {
        if ("Sorbel".equals(inpuName)) {
            return new ConnectionListener(connection) {

                @Override
                protected void valueReceved(Value value) {
                    Integer2DArrayValue sorbel = (Integer2DArrayValue) value;
                    Lock lock = sorbel.lock();
                    calculate(sorbel.getIngegerArray());
                    sorbel.free(lock);
                }

                @Override
                protected void connectionShutdownCalled() {
                    // TODO Auto-generated method stub

                }
            };
        }
        return null;
    }

    /* (non-Javadoc)
     * @see de.openVJJ.basic.Plugable#getConfigPannel()
     */
    @Override
    public JPanel getConfigPannel() {
        JPanel configPanel = new JPanel();

        configPanel.setLayout(new GridBagLayout());
        GridBagConstraints gridBagConstraints = new GridBagConstraints();

        JRadioButton xButton = new JRadioButton("X");
        xButton.addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                xDirection = ((JRadioButton) e.getSource()).isSelected();

            }
        });

        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        configPanel.add(xButton, gridBagConstraints);

        JRadioButton yButton = new JRadioButton("y");

        gridBagConstraints.gridy = 1;
        configPanel.add(yButton, gridBagConstraints);

        ButtonGroup group = new ButtonGroup();
        group.add(yButton);
        group.add(xButton);

        xButton.setSelected(xDirection);
        yButton.setSelected(!xDirection);

        JLabel limitLabel = new JLabel("max Lines");
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        configPanel.add(limitLabel, gridBagConstraints);

        JFormattedTextField limitTextField = new JFormattedTextField(NumberFormat.getNumberInstance());
        limitTextField.setValue(lineLimit);
        limitTextField.setColumns(3);
        limitTextField.addPropertyChangeListener("value", new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                lineLimit = ((Number) ((JFormattedTextField) evt.getSource()).getValue()).intValue();
            }
        });

        gridBagConstraints.gridx = 1;
        configPanel.add(limitTextField, gridBagConstraints);

        JLabel histeryLabel = new JLabel("min Val");
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        configPanel.add(histeryLabel, gridBagConstraints);

        JFormattedTextField histeryTextField = new JFormattedTextField(NumberFormat.getNumberInstance());
        histeryTextField.setValue(histery);
        histeryTextField.setColumns(3);
        histeryTextField.addPropertyChangeListener("value", new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                histery = ((Number) ((JFormattedTextField) evt.getSource()).getValue()).intValue();
            }
        });
        gridBagConstraints.gridx = 1;
        configPanel.add(histeryTextField, gridBagConstraints);

        JLabel minLengthLabel = new JLabel("min length");
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        configPanel.add(minLengthLabel, gridBagConstraints);

        JFormattedTextField minLengthTextField = new JFormattedTextField(NumberFormat.getNumberInstance());
        minLengthTextField.setValue(minLength);
        minLengthTextField.setColumns(3);
        minLengthTextField.addPropertyChangeListener("value", new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                minLength = ((Number) ((JFormattedTextField) evt.getSource()).getValue()).intValue();
            }
        });
        gridBagConstraints.gridx = 1;
        configPanel.add(minLengthTextField, gridBagConstraints);

        return configPanel;
    }

    /**
     * for saving configuration 
     * @param element to save configuration to.
     */
    public void getConfig(Element element) {
        Element myConfigElement = new Element(ELEMENT_NAME_LineFromSorbel2DIntArray_CONFIG);
        element.addContent(myConfigElement);
        myConfigElement.setAttribute("directionx", String.valueOf(xDirection));
        myConfigElement.setAttribute("lineLimit", String.valueOf(lineLimit));
        myConfigElement.setAttribute("histery", String.valueOf(histery));
        myConfigElement.setAttribute("minLength", String.valueOf(minLength));
        super.getConfig(element);
    }

    /**
     * for restoring from saved configuration
     * @param element XML Element
     */
    public void setConfig(Element element) {
        Element myConfigElement = element.getChild(ELEMENT_NAME_LineFromSorbel2DIntArray_CONFIG);
        if (myConfigElement != null) {
            String val = myConfigElement.getAttributeValue("directionx");
            if (val != null) {
                xDirection = Boolean.parseBoolean(val);
            }
            val = myConfigElement.getAttributeValue("lineLimit");
            if (val != null) {
                lineLimit = Integer.parseInt(val);
            }
            val = myConfigElement.getAttributeValue("histery");
            if (val != null) {
                histery = Integer.parseInt(val);
            }
            val = myConfigElement.getAttributeValue("minLength");
            if (val != null) {
                minLength = Integer.parseInt(val);
            }
        }
        super.setConfig(element);
    }

    private boolean xDirection = true;
    private int lineLimit = 500;
    private int histery = 30;
    private boolean copyValue = true;
    private int minLength = 0;

    private void calculate(int[][] sorbel) {
        if (copyValue) {
            sorbel = copySorbel(sorbel);
        }
        PointCloundList lines;
        if (xDirection) {
            lines = processX(sorbel);
        } else {
            lines = processY(sorbel);
        }
        getConnection("Lines").transmitValue(lines);
    }

    private int[][] copySorbel(int[][] toCopy) {
        int[][] myInt = new int[toCopy.length][];
        for (int i = 0; i < toCopy.length; i++) {
            int[] aMatrix = toCopy[i];
            int aLength = aMatrix.length;
            myInt[i] = new int[aLength];
            System.arraycopy(aMatrix, 0, myInt[i], 0, aLength);
        }
        return myInt;
    }

    private PointCloundList processX(int[][] sorbel) {

        int xMax = sorbel.length - 1;
        int yMax = sorbel[0].length - 1;
        ArrayList<PointCloud> lines = new ArrayList<PointCloud>();
        for (int cykle = 0; cykle < lineLimit; cykle++) {
            Point point = getStrongest(sorbel);
            if (point == null) {
                break;
            }

            deactivatePoint(sorbel, point);
            ArrayList<Point> points = new ArrayList<Point>();
            points.add(point);
            PointCloud line = new PointCloud(points);

            combinedLineU(point, sorbel, line, 0, 0, yMax);
            combinedLineD(point, sorbel, line, xMax, 0, yMax);

            if (line.getValue().size() > minLength) {
                lines.add(line);
            } else {
                cykle--;
            }

        }
        return new PointCloundList(lines);
    }

    private PointCloundList processY(int[][] sorbel) {

        int xMax = sorbel.length - 1;
        int yMax = sorbel[0].length - 1;
        ArrayList<PointCloud> lines = new ArrayList<PointCloud>();
        for (int cykle = 0; cykle < lineLimit; cykle++) {
            Point point = getStrongest(sorbel);
            if (point == null) {
                break;
            }

            deactivatePoint(sorbel, point);
            ArrayList<Point> points = new ArrayList<Point>();
            points.add(point);
            PointCloud line = new PointCloud(points);

            combinedLineL(point, sorbel, line, 0, 0, xMax);
            combinedLineR(point, sorbel, line, yMax, 0, xMax);

            if (line.getValue().size() > minLength) {
                lines.add(line);
            } else {
                cykle--;
            }

        }
        return new PointCloundList(lines);
    }

    private final static int USED_POINT = -1;

    private void deactivatePoint(int[][] valueMatrix, Point point) {
        valueMatrix[point.x][point.y] = USED_POINT;
    }

    private Point getStrongest(int[][] sorbelresult) {
        Point point = new Point();
        int ValMax = -1;

        int xMax = sorbelresult.length;
        int yMax = sorbelresult[0].length;
        for (int x = 0; x < xMax; x++) {
            for (int y = 0; y < yMax; y++) {
                int res = sorbelresult[x][y];
                if (res > ValMax) {
                    ValMax = res;
                    point.x = x;
                    point.y = y;
                }
            }
        }
        if (ValMax < histery) {
            return null;
        }
        return point;
    }

    private void combinedLineU(Point position, int[][] sorbel, PointCloud line, int xMin, int yMin, int yMax) {
        if (position.x <= xMin) {
            return;
        }
        Point next = new Point();
        int x = position.x - 1;
        int y = position.y - 1;
        int val = USED_POINT;
        if (y >= yMin) {
            val = sorbel[x][y];
            next.x = x;
            next.y = y;
        }
        y++;
        if (y >= yMin) {
            if (sorbel[x][y] > val) {
                val = sorbel[x][y];
                next.x = x;
                next.y = y;
            }
        }
        y++;
        if (y <= yMax) {
            if (sorbel[x][y] > val) {
                val = sorbel[x][y];
                next.x = x;
                next.y = y;
            }
        }
        if (val != USED_POINT && val > histery) {
            deactivatePoint(sorbel, next);
            line.getValue().add(next);
            thinlineL(next, sorbel, yMin, val);
            thinlineR(next, sorbel, yMax, val);
            combinedLineU(next, sorbel, line, xMin, yMin, yMax);
        }
    }

    private void thinlineL(Point position, int[][] sorbel, int yMin, int last) {
        Point watch = new Point();
        watch.x = position.x;
        watch.y = position.y - 1;
        if (watch.y <= yMin) {
            return;
        }
        if (sorbel[watch.x][watch.y] < last) {
            last = sorbel[watch.x][watch.y];
            sorbel[watch.x][watch.y] = USED_POINT;
            if (last < histery) {
                return;
            }
            thinlineL(watch, sorbel, yMin, last);
        }
    }

    private void thinlineR(Point position, int[][] sorbel, int yMax, int last) {
        Point watch = new Point();
        watch.x = position.x;
        watch.y = position.y + 1;
        if (watch.y >= yMax) {
            return;
        }
        if (sorbel[watch.x][watch.y] < last) {
            last = sorbel[watch.x][watch.y];
            sorbel[watch.x][watch.y] = USED_POINT;
            if (last < histery) {
                return;
            }
            thinlineR(watch, sorbel, yMax, last);
        }
    }

    private void combinedLineD(Point position, int[][] sorbel, PointCloud line, int xMax, int yMin, int yMax) {
        if (position.x >= xMax) {
            return;
        }
        Point next = new Point();
        int x = position.x + 1;
        int y = position.y - 1;
        int val = USED_POINT;
        if (y >= yMin) {
            val = sorbel[x][y];
            next.x = x;
            next.y = y;
        }
        y++;
        if (sorbel[x][y] > val) {
            val = sorbel[x][y];
            next.x = x;
            next.y = y;
        }
        y++;
        if (y <= yMax) {
            if (sorbel[x][y] > val) {
                val = sorbel[x][y];
                next.x = x;
                next.y = y;
            }
        }
        if (val != USED_POINT && val > histery) {
            deactivatePoint(sorbel, next);
            line.getValue().add(next);
            thinlineL(next, sorbel, yMin, val);
            thinlineR(next, sorbel, yMax, val);
            combinedLineD(next, sorbel, line, xMax, yMin, yMax);
        }
    }

    private void combinedLineL(Point position, int[][] sorbel, PointCloud line, int yMin, int xMin, int xMax) {
        if (position.y <= yMin) {
            return;
        }
        Point next = new Point();
        int x = position.x - 1;
        int y = position.y - 1;
        int val = USED_POINT;
        if (x >= xMin) {
            val = sorbel[x][y];
            next.x = x;
            next.y = y;
        }
        x++;
        if (sorbel[x][y] > val) {
            val = sorbel[x][y];
            next.x = x;
            next.y = y;
        }
        x++;
        if (x <= xMax) {
            if (sorbel[x][y] > val) {
                val = sorbel[x][y];
                next.x = x;
                next.y = y;
            }
        }
        if (val != USED_POINT && val > histery) {
            deactivatePoint(sorbel, next);
            line.getValue().add(next);
            thinlineU(next, sorbel, xMin, val);
            thinlineD(next, sorbel, xMax, val);
            combinedLineL(next, sorbel, line, yMin, xMin, xMax);
        }

    }

    private void thinlineU(Point position, int[][] sorbel, int xMin, int last) {
        Point watch = new Point();
        watch.x = position.x - 1;
        watch.y = position.y;
        if (watch.x <= xMin) {
            return;
        }
        if (sorbel[watch.x][watch.y] < last) {
            last = sorbel[watch.x][watch.y];
            sorbel[watch.x][watch.y] = USED_POINT;
            if (last < histery) {
                return;
            }
            thinlineU(watch, sorbel, xMin, last);
        }
    }

    private void thinlineD(Point position, int[][] sorbel, int xMax, int last) {
        Point watch = new Point();
        watch.x = position.x + 1;
        watch.y = position.y;
        if (watch.x >= xMax) {
            return;
        }
        if (sorbel[watch.x][watch.y] < last) {
            last = sorbel[watch.x][watch.y];
            sorbel[watch.x][watch.y] = USED_POINT;
            if (last < histery) {
                return;
            }
            thinlineD(watch, sorbel, xMax, last);
        }
    }

    private void combinedLineR(Point position, int[][] sorbel, PointCloud line, int yMax, int xMin, int xMax) {
        if (position.y >= yMax) {
            return;
        }

        Point next = new Point();
        int x = position.x - 1;
        int y = position.y + 1;
        int val = USED_POINT;
        if (x >= xMin) {
            val = sorbel[x][y];
            next.x = x;
            next.y = y;
        }
        x++;
        if (sorbel[x][y] > val) {
            val = sorbel[x][y];
            next.x = x;
            next.y = y;
        }
        x++;
        if (x <= xMax) {
            if (sorbel[x][y] > val) {
                val = sorbel[x][y];
                next.x = x;
                next.y = y;
            }
        }
        if (val != USED_POINT && val > histery) {
            deactivatePoint(sorbel, next);
            line.getValue().add(next);
            thinlineU(next, sorbel, xMin, val);
            thinlineD(next, sorbel, xMax, val);
            combinedLineR(next, sorbel, line, yMax, xMin, xMax);
        }

    }

}