package cz.fidentis.analyst.gui;

import static cz.fidentis.analyst.gui.UserInterface.frameMain;
import cz.fidentis.analyst.mesh.core.MeshFacet;
import cz.fidentis.analyst.mesh.core.MeshModel;
import cz.fidentis.analyst.symmetry.Config;
import cz.fidentis.analyst.symmetry.Plane;
import cz.fidentis.analyst.symmetry.SignificantPoints;
import cz.fidentis.analyst.symmetry.SymmetryEstimator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;

/**
 * Panel for estimating approximate symmetry of the model
 *
 * @author Natalia Bebjakova
 */
public final class SymmetryPanel extends javax.swing.JPanel {
    
    /**
     * Configuration with optional parameters of the algorithm 
     */
    private Config config;
    
    /**
     * GL Canvas on which model is displayed
     */
    private Canvas canvas;
    
    /**
     * Computed approximate plane of the symmetry
     */
    private Plane symmetryPlane;

    /**
     * 
     * @return GL canvas for displaying the model
     */
    public Canvas getCanvas() {
        return canvas;
    }

    /**
     * Sets canvas for displaying the model
     * 
     * @param canvas GL Canvas
     */
    public void setCanvas(Canvas canvas) {
        this.canvas = canvas;
    }

    /**
     * 
     * @return Configuration for computing symmetry
     */
    public Config getConfig() {
        return config;
    }

    /**
     * 
     * @param config Configuration for computing symmetry
     */
    public void setConfig(Config config) {
        this.config = config;
    }
    
        
    /**
     * Sets configuration values according to text fields on panel
     * User can change this text fields
     */
    public void setConfigParams() {
        config.setMaxRelDistance(Double.parseDouble(distanceTextField.getText()));
        config.setMinAngleCos(Double.parseDouble(textFieldMinCos.getText()));
        config.setMinCurvRatio(Double.parseDouble(textFieldCurvature.getText()));
        config.setMinNormAngleCos(Double.parseDouble(normalTextField.getText()));
        config.setSignificantPointCount(Integer.parseInt(significantTextField.getText()));
    }
    
    /**
     * Sets values in text field according to configuration
     */
    public void setTextFieldsDueToConfig() {
        distanceTextField.setText(Double.toString(config.getMaxRelDistance()));
        textFieldMinCos.setText(Double.toString(config.getMinAngleCos()));
        textFieldCurvature.setText(Double.toString(config.getMinCurvRatio()));
        normalTextField.setText(Double.toString(config.getMinNormAngleCos()));
        significantTextField.setText(Integer.toString(config.getSignificantPointCount()));    
    }
    
    /**
     * 
     * @param slider Slider 
     * @param field text field which belongs to slider
     */
    public void setSlider(JSlider slider, JTextField field) {
        slider.setValue((int) (Double.parseDouble(field.getText()) * 100));
        
        slider.addChangeListener((ChangeEvent ce) -> {
            field.setText(""+slider.getValue()/100.0);
            defaultValues.setVisible(true);
        });
        
    }
    
    /**
     * Sets values of the sliders according to textFields 
     */
    public void setSliders() {
        setSlider(relativeDistanceSlider, distanceTextField);
        setSlider(curavatureSlider, textFieldCurvature);
        setSlider(angleCosineSlider, textFieldMinCos);
        setSlider(normalAngleSlider, normalTextField);
                
        significantPointSlider.setValue((int) (Double.parseDouble(significantTextField.getText())));
        significantPointSlider.addChangeListener((ChangeEvent ce) -> {
            significantTextField.setText("" + significantPointSlider.getValue());
        });
    }
    
    /**
     * If plane of symmtery is computed, three new buttons are shown on panel
     * 
     * @param isComputed true if plane is computed and shown on model otherwise false
     */
    public void showPlaneButtonsOnPanel(boolean isComputed) {
        originalModelButton.setVisible(isComputed);
        showPlaneLabel.setVisible(isComputed);
    }
    
    /**
     * Creates new form symmetryPanel
     */
    public SymmetryPanel() {
        initComponents();
        config = Config.getDefault();
        setSliders();
        
        showPlaneButtonsOnPanel(false);
    }

    /**
     * Calculate approxy symmetry of the model 
     * Accuracy of the symmetry plane is influenced by configuration represented by config
     * 
     * @throws InterruptedException exception can be thrown beacause of progress monitor
     */
    private void computeSymmetryPlane() throws InterruptedException {
        MeshModel model = new MeshModel();
        canvas.changeModel(canvas.getLoadedFace().getMeshModel());
        SymmetryEstimator est = new SymmetryEstimator(config, SignificantPoints.CurvatureAlg.GAUSSIAN); // MISTO TRUE MUSI BYT VYBER STRATEGIE VYPOCTU ZAKRIVENI!!!
        canvas.getLoadedFace().getMeshModel().getFacets().get(0).accept(est);
        symmetryPlane = est.getSymmetryPlane();
        MeshFacet facet = est.getSymmetryPlaneMesh();
        if (facet != null) {
            model.addFacet(facet);
            this.canvas.changeModel(model);
        }
    }


    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     * 
     * Code generated by NetBeans
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        symetrySpecificationPanel = new javax.swing.JPanel();
        curavatureSlider = new javax.swing.JSlider();
        angleCosineSlider = new javax.swing.JSlider();
        minCurvatio = new javax.swing.JLabel();
        minCurvatio2 = new javax.swing.JLabel();
        normalAngleSlider = new javax.swing.JSlider();
        minCurvatio3 = new javax.swing.JLabel();
        significantPointSlider = new javax.swing.JSlider();
        minCurvatio4 = new javax.swing.JLabel();
        relativeDistanceSlider = new javax.swing.JSlider();
        significantPointLabel = new javax.swing.JLabel();
        symetryButton = new javax.swing.JLabel();
        averagingCheckBox = new javax.swing.JCheckBox();
        textFieldCurvature = new javax.swing.JTextField();
        textFieldMinCos = new javax.swing.JTextField();
        normalTextField = new javax.swing.JTextField();
        distanceTextField = new javax.swing.JTextField();
        significantTextField = new javax.swing.JTextField();
        minCurvatio8 = new javax.swing.JLabel();
        jLabel1 = new javax.swing.JLabel();
        originalModelButton = new javax.swing.JLabel();
        showPlaneLabel = new javax.swing.JLabel();
        defaultValues = new javax.swing.JLabel();
        infoPoints = new javax.swing.JLabel();
        infoMinAngleCos = new javax.swing.JLabel();
        infoRelDist = new javax.swing.JLabel();
        infoNormalAngle = new javax.swing.JLabel();
        infoMinCurv = new javax.swing.JLabel();

        symetrySpecificationPanel.setBackground(new java.awt.Color(176, 230, 226));

        curavatureSlider.setBackground(new java.awt.Color(250, 250, 250));
        curavatureSlider.setMajorTickSpacing(1);
        curavatureSlider.setMinimum(50);
        curavatureSlider.setSnapToTicks(true);
        curavatureSlider.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        curavatureSlider.setOpaque(false);

        angleCosineSlider.setMinimum(80);
        angleCosineSlider.setSnapToTicks(true);
        angleCosineSlider.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        angleCosineSlider.setOpaque(false);

        minCurvatio.setFont(new java.awt.Font("Arial", 1, 14)); // NOI18N
        minCurvatio.setForeground(new java.awt.Color(20, 114, 105));
        minCurvatio.setText("Min. Curvature Ratio");

        minCurvatio2.setFont(new java.awt.Font("Arial", 1, 14)); // NOI18N
        minCurvatio2.setForeground(new java.awt.Color(20, 114, 105));
        minCurvatio2.setText("Min. Angle Cosine");

        normalAngleSlider.setMinimum(80);
        normalAngleSlider.setSnapToTicks(true);
        normalAngleSlider.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        normalAngleSlider.setOpaque(false);

        minCurvatio3.setFont(new java.awt.Font("Arial", 1, 14)); // NOI18N
        minCurvatio3.setForeground(new java.awt.Color(20, 114, 105));
        minCurvatio3.setText("Relative Distance");

        significantPointSlider.setMajorTickSpacing(100);
        significantPointSlider.setMaximum(300);
        significantPointSlider.setSnapToTicks(true);
        significantPointSlider.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        significantPointSlider.setOpaque(false);

        minCurvatio4.setFont(new java.awt.Font("Arial", 1, 14)); // NOI18N
        minCurvatio4.setForeground(new java.awt.Color(20, 114, 105));
        minCurvatio4.setText("Normal Angle Cosine");

        relativeDistanceSlider.setMaximum(5);
        relativeDistanceSlider.setSnapToTicks(true);
        relativeDistanceSlider.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        relativeDistanceSlider.setOpaque(false);

        significantPointLabel.setFont(new java.awt.Font("Arial", 1, 14)); // NOI18N
        significantPointLabel.setForeground(new java.awt.Color(20, 114, 105));
        significantPointLabel.setText("Significant Points");

        symetryButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/symetryCount.png"))); // NOI18N
        symetryButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        symetryButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                symetryButtonMouseMoved(evt);
            }
        });
        symetryButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                symetryButtonMouseClicked(evt);
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                symetryButtonMouseExited(evt);
            }
        });

        averagingCheckBox.setSelected(true);
        averagingCheckBox.setOpaque(false);
        averagingCheckBox.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                averagingCheckBoxMouseClicked(evt);
            }
        });

        textFieldCurvature.setText("0.5");
        textFieldCurvature.setToolTipText("");

        textFieldMinCos.setText("0.985");
        textFieldMinCos.setToolTipText("");

        normalTextField.setText("0.985");
        normalTextField.setToolTipText("");

        distanceTextField.setText("0.01");
        distanceTextField.setToolTipText("");

        significantTextField.setText("200");
        significantTextField.setToolTipText("");

        minCurvatio8.setFont(new java.awt.Font("Arial", 1, 14)); // NOI18N
        minCurvatio8.setForeground(new java.awt.Color(20, 114, 105));
        minCurvatio8.setText("Averaging");
        minCurvatio8.setToolTipText("Average planes with highest number of votes");

        originalModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/originalModel.png"))); // NOI18N
        originalModelButton.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        originalModelButton.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                originalModelButtonMouseMoved(evt);
            }
        });
        originalModelButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                originalModelButtonMouseClicked(evt);
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                originalModelButtonMouseExited(evt);
            }
        });

        showPlaneLabel.setFont(new java.awt.Font("Arial", 1, 16)); // NOI18N
        showPlaneLabel.setForeground(new java.awt.Color(20, 114, 105));
        showPlaneLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/show2.png"))); // NOI18N
        showPlaneLabel.setText("Show plane");
        showPlaneLabel.setToolTipText("Show approximate plane of symmetry");
        showPlaneLabel.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        showPlaneLabel.setDoubleBuffered(true);
        showPlaneLabel.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                showPlaneLabelMouseClicked(evt);
            }
        });

        defaultValues.setFont(new java.awt.Font("Arial", 0, 14)); // NOI18N
        defaultValues.setForeground(new java.awt.Color(20, 114, 105));
        defaultValues.setText("Default values");
        defaultValues.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        defaultValues.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                defaultValuesMouseClicked(evt);
            }
        });

        infoPoints.setIcon(new javax.swing.ImageIcon(getClass().getResource("/info.png"))); // NOI18N
        infoPoints.setToolTipText("Info ");
        infoPoints.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        infoPoints.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                infoPointsMouseClicked(evt);
            }
        });

        infoMinAngleCos.setIcon(new javax.swing.ImageIcon(getClass().getResource("/info.png"))); // NOI18N
        infoMinAngleCos.setToolTipText("Info ");
        infoMinAngleCos.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        infoMinAngleCos.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                infoMinAngleCosMouseClicked(evt);
            }
        });

        infoRelDist.setIcon(new javax.swing.ImageIcon(getClass().getResource("/info.png"))); // NOI18N
        infoRelDist.setToolTipText("Info ");
        infoRelDist.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        infoRelDist.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                infoRelDistMouseClicked(evt);
            }
        });

        infoNormalAngle.setIcon(new javax.swing.ImageIcon(getClass().getResource("/info.png"))); // NOI18N
        infoNormalAngle.setToolTipText("Info ");
        infoNormalAngle.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        infoNormalAngle.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                infoNormalAngleMouseClicked(evt);
            }
        });

        infoMinCurv.setIcon(new javax.swing.ImageIcon(getClass().getResource("/info.png"))); // NOI18N
        infoMinCurv.setToolTipText("Info ");
        infoMinCurv.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        infoMinCurv.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                infoMinCurvMouseClicked(evt);
            }
        });

        javax.swing.GroupLayout symetrySpecificationPanelLayout = new javax.swing.GroupLayout(symetrySpecificationPanel);
        symetrySpecificationPanel.setLayout(symetrySpecificationPanelLayout);
        symetrySpecificationPanelLayout.setHorizontalGroup(
            symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addComponent(defaultValues))
                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                        .addGap(17, 17, 17)
                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                                .addGap(154, 154, 154)
                                .addComponent(jLabel1))
                            .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                                .addComponent(showPlaneLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 147, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(originalModelButton, javax.swing.GroupLayout.PREFERRED_SIZE, 181, javax.swing.GroupLayout.PREFERRED_SIZE))))
                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                                .addGap(10, 10, 10)
                                .addComponent(minCurvatio8)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(averagingCheckBox)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(symetryButton))
                            .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(infoMinAngleCos)
                                    .addComponent(infoRelDist)
                                    .addComponent(infoNormalAngle)
                                    .addComponent(infoPoints)
                                    .addComponent(infoMinCurv))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(minCurvatio4, javax.swing.GroupLayout.DEFAULT_SIZE, 157, Short.MAX_VALUE)
                                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                            .addComponent(minCurvatio)
                                            .addComponent(minCurvatio3)
                                            .addComponent(minCurvatio2)
                                            .addComponent(significantPointLabel))
                                        .addGap(0, 0, Short.MAX_VALUE)))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                    .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                        .addComponent(curavatureSlider, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                                        .addComponent(relativeDistanceSlider, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                                        .addComponent(significantPointSlider, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 164, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addComponent(angleCosineSlider, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 164, javax.swing.GroupLayout.PREFERRED_SIZE))
                                    .addComponent(normalAngleSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 164, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addGap(18, 18, 18)
                                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                    .addComponent(distanceTextField)
                                    .addComponent(normalTextField)
                                    .addComponent(significantTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addComponent(textFieldCurvature, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addComponent(textFieldMinCos, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE))))))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        symetrySpecificationPanelLayout.setVerticalGroup(
            symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(infoPoints)
                        .addComponent(significantPointLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(significantTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(significantPointSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(minCurvatio, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                        .addComponent(textFieldCurvature, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(4, 4, 4))
                    .addComponent(infoMinCurv)
                    .addComponent(curavatureSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(infoMinAngleCos, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(minCurvatio2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(textFieldMinCos, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(angleCosineSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(normalAngleSlider, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(normalTextField))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(distanceTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(minCurvatio4, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(infoNormalAngle))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(infoRelDist, javax.swing.GroupLayout.Alignment.TRAILING)
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(relativeDistanceSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(minCurvatio3, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addGap(13, 13, 13)))
                .addComponent(defaultValues)
                .addGap(17, 17, 17)
                .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                        .addComponent(symetryButton, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(originalModelButton)
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addGroup(symetrySpecificationPanelLayout.createSequentialGroup()
                        .addGroup(symetrySpecificationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(averagingCheckBox)
                            .addComponent(minCurvatio8, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 53, Short.MAX_VALUE)
                        .addComponent(jLabel1)
                        .addGap(45, 45, 45)
                        .addComponent(showPlaneLabel)
                        .addContainerGap(27, Short.MAX_VALUE))))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(symetrySpecificationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(symetrySpecificationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents

    /**
     * 
     * @param evt Final computed plane is shown to user
     */
    private void showPlaneLabelMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_showPlaneLabelMouseClicked
        JOptionPane.showMessageDialog(frameMain, "Approximate plane of symmetry:  \n" + symmetryPlane.getNormal().x + "\n" + symmetryPlane.getNormal().y + "\n" + symmetryPlane.getNormal().z + "\n" +
            symmetryPlane.getDistance() + "\n", "Final plane.", 0, new ImageIcon(getClass().getResource("/showPlanePane.png")));
    }//GEN-LAST:event_showPlaneLabelMouseClicked

    /**
     * 
     * @param evt Changes button
     */
    private void originalModelButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_originalModelButtonMouseExited
        originalModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/originalModel.png")));
    }//GEN-LAST:event_originalModelButtonMouseExited

    /**
     * 
     * @param evt Original model (without plane) is displayed
     */
    private void originalModelButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_originalModelButtonMouseClicked
        canvas.changeModel(canvas.getLoadedFace().getMeshModel());
        showPlaneButtonsOnPanel(false);
    }//GEN-LAST:event_originalModelButtonMouseClicked

    /**
     * 
     * @param evt Changes button
     */
    private void originalModelButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_originalModelButtonMouseMoved
        originalModelButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/originalModelPressed.png")));
    }//GEN-LAST:event_originalModelButtonMouseMoved

    /**
     * 
     * @param evt Decides if averaging is ON or OFF
     */
    private void averagingCheckBoxMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_averagingCheckBoxMouseClicked
        if(config.isAveraging()) {
            config.setAveraging(false);
        } else {
            config.setAveraging(true);
        }
    }//GEN-LAST:event_averagingCheckBoxMouseClicked

    /**
     * 
     * @param evt Changes button
     */
    private void symetryButtonMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_symetryButtonMouseExited
        symetryButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/symetryCount.png")));
    }//GEN-LAST:event_symetryButtonMouseExited

    /**
     * 
     * @param evt Symmetry is estimated. If model is not loaded, user is warned 
     */
    private void symetryButtonMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_symetryButtonMouseClicked
        setConfigParams();
        if (canvas.getModel().getFacets().isEmpty()){
            JOptionPane.showMessageDialog(frameMain, "You have to load the model.", "Model not loaded",
                0, new ImageIcon(getClass().getResource("/notLoadedModel.png")));
        } else {
            try {
                computeSymmetryPlane();
            } catch (InterruptedException ex) {
                Logger.getLogger(SymmetryPanel.class.getName()).log(Level.SEVERE, null, ex);
            }
            showPlaneButtonsOnPanel(true);
        }
    }//GEN-LAST:event_symetryButtonMouseClicked

    /**
    * 
    * @param evt Changes button
    */
    private void symetryButtonMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_symetryButtonMouseMoved
        symetryButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/symetryCountClicked.png")));
    }//GEN-LAST:event_symetryButtonMouseMoved

    /**
     * 
     * @param evt configuration is set to deafult values
     */
    private void defaultValuesMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_defaultValuesMouseClicked
        config = Config.getDefault();
        setTextFieldsDueToConfig();
        setSliders();
    }//GEN-LAST:event_defaultValuesMouseClicked

    /**
     * Shows details about minimum curv ratio parameter
     * 
     * @param evt 
     */
    private void infoMinCurvMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_infoMinCurvMouseClicked
        JOptionPane.showMessageDialog(frameMain,
                "Entered number represents how similar the curvature in two vertices must be\n"
                        + "to take into account these vertices while counting the plane of approximate symmetry.\n"
                        + "The higher the number is the more similar they must be.\n\n"
                        
                        + "Higher number → fewer pairs of vertices satisfy the criterion → shorter calculation, possibly less accurate result.\n"
                        + "Lower number → more pairs of vertices satisfy the criterion → longer calculation, possibly more accurate result.",
                "Minimum curvature ratio",
                0, new ImageIcon(getClass().getResource("/curvature.png")));
    }//GEN-LAST:event_infoMinCurvMouseClicked

    /**
     * Shows details about maximum relative distance parameter
     * 
     * @param evt 
    */
    private void infoRelDistMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_infoRelDistMouseClicked
        JOptionPane.showMessageDialog(frameMain,
                "Entered number represents how far middle point of two vertices can be from candidate plane of symmetry\n"
                        + "to give this plane vote. Plane with highest number of votes is plane of approximate symmetry.\n\n"
                        
                        + "Higher number → more pairs of vertices satisfy the criterion → longer calculation, possibly more accurate result.\n"
                        + "Lower number → fewer pairs of vertices satisfy the criterion → shorter calculation, possibly less accurate result.",
                "Maximum relative distance from plane",
                0, new ImageIcon(getClass().getResource("/distance.png")));
    }//GEN-LAST:event_infoRelDistMouseClicked

    /**
     * Shows details about significant points parameter
     * 
     * @param evt 
     */
    private void infoPointsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_infoPointsMouseClicked
        JOptionPane.showMessageDialog(frameMain, 
                "Entered number represents amount of points of the mesh that are taken into account\n"
                        + "while counting the plane of approximate symmetry.\n\n"
                        
                        + "Higher number → longer calculation, possibly more accurate result.\n"
                        + "Lower number → shorter calculation, possibly less accurate result.", 
                "Significant points",
                0, new ImageIcon(getClass().getResource("/points.png")));
    }//GEN-LAST:event_infoPointsMouseClicked

    /**
     * Shows details about minimum angle cosine parameter
     * 
     * @param evt 
     */
    private void infoMinAngleCosMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_infoMinAngleCosMouseClicked
        JOptionPane.showMessageDialog(frameMain,
                "Entered number represents how large the angle between normal vector of candidate plane and the vector\n"
                        + "of two vertices can be to take into account these vertices while counting the approximate symmetry.\n\n"
                        
                        + "Higher number → fewer pairs of vertices satisfy the criterion → shorter calculation, possibly less accurate result.\n"
                        + "Lower number → more pairs of vertices satisfy the criterion → longer calculation, possibly more accurate result.",
                "Minimum angle",
                0, new ImageIcon(getClass().getResource("/angle.png")));
    }//GEN-LAST:event_infoMinAngleCosMouseClicked

    /**
     * Shows details about minimum normal angle cosine parameter
     * 
     * @param evt 
     */
    private void infoNormalAngleMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_infoNormalAngleMouseClicked
        JOptionPane.showMessageDialog(frameMain,
                "Entered number represents how large the angle between normal vector of candidate plane and vector\n"
                        + "from subtraction of normal vectors of two vertices can be to take into account these vertices while counting the approximate symmetry.\n\n"
                        
                        + "Higher number → fewer pairs of vertices satisfy the criterion → shorter calculation, possibly less accurate result.\n"
                        + "Lower number → more pairs of vertices satisfy the criterion → longer calculation, possibly more accurate result.",
                "Minimum normal angle",
                0, new ImageIcon(getClass().getResource("/angle.png")));
    }//GEN-LAST:event_infoNormalAngleMouseClicked


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JSlider angleCosineSlider;
    private javax.swing.JCheckBox averagingCheckBox;
    private javax.swing.JSlider curavatureSlider;
    private javax.swing.JLabel defaultValues;
    private javax.swing.JTextField distanceTextField;
    private javax.swing.JLabel infoMinAngleCos;
    private javax.swing.JLabel infoMinCurv;
    private javax.swing.JLabel infoNormalAngle;
    private javax.swing.JLabel infoPoints;
    private javax.swing.JLabel infoRelDist;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel minCurvatio;
    private javax.swing.JLabel minCurvatio2;
    private javax.swing.JLabel minCurvatio3;
    private javax.swing.JLabel minCurvatio4;
    private javax.swing.JLabel minCurvatio8;
    private javax.swing.JSlider normalAngleSlider;
    private javax.swing.JTextField normalTextField;
    private javax.swing.JLabel originalModelButton;
    private javax.swing.JSlider relativeDistanceSlider;
    private javax.swing.JLabel showPlaneLabel;
    private javax.swing.JLabel significantPointLabel;
    private javax.swing.JSlider significantPointSlider;
    private javax.swing.JTextField significantTextField;
    private javax.swing.JLabel symetryButton;
    private javax.swing.JPanel symetrySpecificationPanel;
    private javax.swing.JTextField textFieldCurvature;
    private javax.swing.JTextField textFieldMinCos;
    // End of variables declaration//GEN-END:variables
}
