Dialog created.
authorilb@NIH.GOV <ilb@NIH.GOV@ba61647d-9d00-f842-95cd-605cb4296b96>
Mon, 11 Dec 2017 21:25:42 +0000 (21:25 +0000)
committerilb@NIH.GOV <ilb@NIH.GOV@ba61647d-9d00-f842-95cd-605cb4296b96>
Mon, 11 Dec 2017 21:25:42 +0000 (21:25 +0000)
git-svn-id: https://citdcbmipav.cit.nih.gov/repos-pub/mipav/trunk@15304 ba61647d-9d00-f842-95cd-605cb4296b96

mipav/src/gov/nih/mipav/view/dialogs/JDialogDoublyConnectedSC.java [new file with mode: 0644]

diff --git a/mipav/src/gov/nih/mipav/view/dialogs/JDialogDoublyConnectedSC.java b/mipav/src/gov/nih/mipav/view/dialogs/JDialogDoublyConnectedSC.java
new file mode 100644 (file)
index 0000000..bec52e5
--- /dev/null
@@ -0,0 +1,540 @@
+package gov.nih.mipav.view.dialogs;\r
+\r
+\r
+import gov.nih.mipav.model.algorithms.*;\r
+import gov.nih.mipav.model.structures.*;\r
+import gov.nih.mipav.view.*;\r
+\r
+import java.awt.*;\r
+import java.awt.event.*;\r
+import java.util.*;\r
+\r
+import javax.swing.*;\r
+\r
+import WildMagic.LibFoundation.Mathematics.Vector3f;\r
+\r
+\r
+/**\r
+ * Dialog to get Schwarz-Christoffel mapping of region between 2 polygons to an annulus\r
+ */\r
+public class JDialogDoublyConnectedSC extends JDialogBase implements AlgorithmInterface, ItemListener, WindowListener {\r
+       \r
+       /** Use serialVersionUID for interoperability. */\r
+    private static final long serialVersionUID = 0L;\r
+\r
+       \r
+        private ButtonGroup VOIGroup;\r
+        \r
+        private JRadioButton outerButton;\r
+        \r
+        private JRadioButton innerButton;\r
+        \r
+        private ViewJComponentEditImage componentImage;\r
+        \r
+        private ModelImage image;\r
+        \r
+        private ModelImage resultImage = null;\r
+        \r
+        private int[] extents = new int[2];\r
+        \r
+        private int xDim;\r
+        \r
+        private DoublyConnectedSC dcscAlgo;\r
+        \r
+        private JTextField xText;\r
+        \r
+        private ViewVOIVector VOIs;\r
+        \r
+       // M[0] points of outer polygon\r
+       private double Z0[][] = null;\r
+       // N[0] points of inner polygon\r
+       private double Z1[][] = null;\r
+       \r
+       // The number of Gauss-Jacobi points\r
+       // Recommended values for NPTQ are 2-8.\r
+       private int NPTQ = 8;\r
+       \r
+       private JTextField nptqText;\r
+       \r
+       private JCheckBox displayCheckBox;\r
+       // Screen display of the residual of the system as the iteration goes on, 1 for "YES", 2 for "NO"\r
+    private int ISPRT;\r
+    \r
+    //IGUESS    (=0 )A NON-EQUALLY SPACED INITIAL GUESS OR(=1)THE\r
+       //C            OTHER  EQUALLY-SPACED  INITIAL GUESS PROVIDED, OR\r
+       //C            (=2)USER-SUPPLIED INITIAL GUESS WHICH IS REQUIRED\r
+       //C            TO BE THE ARGUMENTS OF THE INITIAL PREVERTICES.\r
+       //C            ROUTINE ARGUM MAY BE USED FOR COMPUTING ARGUMENTS\r
+       //C            IF NEEDED. NOTE: C WILL BE COMPUTED IN THE ROUTINE\r
+       //C            (NOT SUPPLIED!)\r
+    private int IGUESS = 1;\r
+    \r
+    private ButtonGroup guessGroup;\r
+    private JRadioButton nonequalButton;\r
+    private JRadioButton equalButton;\r
+    private JRadioButton preverticesButton;\r
+    // LINEARC   INTEGER VARIABLE TO CONTROL INTEGRATION PATH.IN PATICULAR:\r
+    //C            LINEARC=0:INTEGRATING ALONG LINE SEGMENT WHENEVER POSSIBLE\r
+    //C            LINEARC=1:INTEGRATING ALONG CIRCULAR ARC WHENEVER POSSIBLE\r
+    private int LINEARC = 1;\r
+    private ButtonGroup integrationGroup;\r
+    private JRadioButton lineButton;\r
+    private JRadioButton circularButton;\r
+    // TOL       A TOLERANCE TO CONTROL THE CONVERGENCE IN HYBRD\r
+    private double TOL = 1.0E-10;\r
+    private JTextField tolText;\r
+        \r
+       //~ Constructors ---------------------------------------------------------------------------------------------------\r
+\r
+           /**\r
+            * Creates a new JDialogFRAP object.\r
+            *\r
+            * @param  image  DOCUMENT ME!\r
+            */\r
+           public JDialogDoublyConnectedSC(ModelImage image) {\r
+               super();\r
+               this.image = image;\r
+               parentFrame = image.getParentFrame();\r
+               componentImage = ((ViewJFrameImage) parentFrame).getComponentImage();\r
+           }\r
+\r
+           /**\r
+            * Creates new dialog.\r
+            *\r
+            * @param  theParentFrame  Parent frame\r
+            * @param  im              Source image\r
+            */\r
+           public JDialogDoublyConnectedSC(Frame theParentFrame, ModelImage im) {\r
+               super(theParentFrame, false);\r
+               image = im;\r
+               componentImage = ((ViewJFrameImage) theParentFrame).getComponentImage();\r
+               init();\r
+           }\r
+           \r
+           /**\r
+            * Closes dialog box when the OK button is pressed and calls the algorithm.\r
+            *\r
+            * @param  event  Event that triggers function.\r
+            */\r
+           public void actionPerformed(ActionEvent event) {\r
+               String command = event.getActionCommand();\r
+               Object source = event.getSource();\r
+\r
+               if (command.equals("OK")) {\r
+\r
+                   if (setVariables()) {\r
+                       callAlgorithm();\r
+                   }\r
+               } else if (command.equals("Script")) {\r
+                   callAlgorithm();\r
+               } else if (command.equals("Help")) {\r
+                   //MipavUtil.showWebHelp("DoublyConnectedSC");\r
+               } else if (command.equals("Cancel")) {\r
+                   componentImage.getVOIHandler().setPresetHue(-1.0f);\r
+                   dispose();\r
+               } else if ((source == outerButton) || (source == innerButton)) {\r
+\r
+                   if (outerButton.isSelected()) {\r
+                       componentImage.getVOIHandler().newVOI(0.0f); // red\r
+                       //componentImage.setCursorMode(ViewJComponentEditImage.NEW_VOI);\r
+                       //componentImage.getVOIHandler().setPresetHue(0.0f); // red\r
+                   } else if (innerButton.isSelected()) {\r
+                       componentImage.getVOIHandler().newVOI(1.0f / 3.0f); // green\r
+                       //componentImage.setCursorMode(ViewJComponentEditImage.NEW_VOI);\r
+                       //componentImage.getVOIHandler().setPresetHue(1.0f / 3.0f); // green\r
+                   }\r
+               } else {\r
+                   super.actionPerformed(event);\r
+               }\r
+           }\r
+           \r
+           /**\r
+            * DOCUMENT ME!\r
+            */\r
+           private void callAlgorithm() {\r
+\r
+               try {\r
+                   String name = makeImageName(image.getImageName(), "_annulus");\r
+                   extents[0] = xDim;\r
+                   extents[1] = xDim;\r
+                   resultImage = new ModelImage(image.getType(), extents, name);\r
+                   resultImage.setImageName(name);\r
+\r
+                   // Make algorithm\r
+                   dcscAlgo = new DoublyConnectedSC(resultImage, image, Z0, Z1, NPTQ, ISPRT, IGUESS, LINEARC, TOL);\r
+\r
+                   // This is very important. Adding this object as a listener allows the algorithm to\r
+                   // notify this object when it has completed of failed. See algorithm performed event.\r
+                   // This is made possible by implementing AlgorithmedPerformed interface\r
+                   dcscAlgo.addListener(this);\r
+\r
+                   // Hide dialog\r
+                   setVisible(false);\r
+\r
+                   if (isRunInSeparateThread()) {\r
+\r
+                       // Start the thread as a low priority because we wish to still have user interface work fast.\r
+                       if (dcscAlgo.startMethod(Thread.MIN_PRIORITY) == false) {\r
+                           MipavUtil.displayError("A thread is already running on this object");\r
+                       }\r
+                   } else {\r
+\r
+                       dcscAlgo.run();\r
+                   }\r
+               } catch (OutOfMemoryError x) {\r
+\r
+                   System.gc();\r
+                   MipavUtil.displayError("Dialog Region between 2 polygons to annulus: unable to allocate enough memory");\r
+\r
+                   return;\r
+               }\r
+           }\r
+           \r
+           /**\r
+            * This method is required if the AlgorithmPerformed interface is implemented. It is called by the algorithm when it\r
+            * has completed or failed to to complete, so that the dialog can be display the result image and/or clean up.\r
+            *\r
+            * @param  algorithm  Algorithm that caused the event.\r
+            */\r
+           public void algorithmPerformed(AlgorithmBase algorithm) {\r
+\r
+\r
+               if (algorithm instanceof DoublyConnectedSC) {\r
+                   Preferences.debug("Region between 2 polygons to annulus: " + algorithm.getElapsedTime());\r
+                   image.clearMask();\r
+\r
+                   if ((dcscAlgo.isCompleted() == true) && (resultImage != null)) {\r
+\r
+\r
+                       resultImage.clearMask();\r
+\r
+                       try {\r
+                           openNewFrame(resultImage);\r
+                       } catch (OutOfMemoryError error) {\r
+                           System.gc();\r
+                           MipavUtil.displayError("Out of memory: unable to open new frame");\r
+                       }\r
+                   } else if (resultImage != null) {\r
+\r
+                       // algorithm failed but result image still has garbage\r
+                       resultImage.disposeLocal(); // clean up memory\r
+                       resultImage = null;\r
+                       System.gc();\r
+\r
+                   }\r
+\r
+                   // insertScriptLine(algorithm);\r
+               } // if (algorithm instanceof DoublyConnectedSC)\r
+\r
+               if (dcscAlgo != null) {\r
+                   dcscAlgo.finalize();\r
+                   dcscAlgo = null;\r
+               }\r
+\r
+               dispose();\r
+           }\r
+       \r
+       /**\r
+     * Initializes GUI components and displays dialog.\r
+     */\r
+    private void init() {\r
+        JPanel paramPanel;\r
+        JPanel VOIPanel;\r
+\r
+        setForeground(Color.black);\r
+        setTitle("Transform region between 2 polygons to an annulus");\r
+\r
+        VOIPanel = new JPanel(new GridBagLayout());\r
+        VOIPanel.setBorder(buildTitledBorder("Select outer or inner points"));\r
+\r
+        GridBagConstraints gbc = new GridBagConstraints();\r
+        gbc.gridwidth = 1;\r
+        gbc.gridheight = 1;\r
+        gbc.anchor = GridBagConstraints.WEST;\r
+        gbc.weightx = 1;\r
+        gbc.insets = new Insets(3, 3, 3, 3);\r
+        gbc.fill = GridBagConstraints.HORIZONTAL;\r
+        gbc.gridx = 0;\r
+        gbc.gridy = 0;\r
+        \r
+        JLabel requireLabel = new JLabel("Points must be entered in counterclockwise order");\r
+        requireLabel.setForeground(Color.black);\r
+        requireLabel.setFont(serif12);\r
+        VOIPanel.add(requireLabel, gbc);\r
+        \r
+        JLabel requireLabel2 = new JLabel("The last inner vertex is the closest inner vertex to the last outer vertex");\r
+        requireLabel2.setForeground(Color.black);\r
+        requireLabel2.setFont(serif12);\r
+        gbc.gridy++;\r
+        VOIPanel.add(requireLabel2, gbc);\r
+\r
+        VOIGroup = new ButtonGroup();\r
+\r
+        outerButton = new JRadioButton("Add required outer VOI points", true);\r
+        outerButton.setForeground(Color.red);\r
+        outerButton.setFont(serif12);\r
+        outerButton.addActionListener(this);\r
+        VOIGroup.add(outerButton);\r
+        gbc.gridy++;\r
+        VOIPanel.add(outerButton, gbc);\r
+        componentImage.getVOIHandler().newVOI(0.0f); // red\r
+        //componentImage.setCursorMode(ViewJComponentEditImage.NEW_VOI);\r
+        //componentImage.getVOIHandler().setPresetHue(0.0f); // red\r
+\r
+        innerButton = new JRadioButton("Add required inner VOI points", false);\r
+        innerButton.setForeground(Color.green.darker());\r
+        innerButton.setFont(serif12);\r
+        innerButton.addActionListener(this);\r
+        VOIGroup.add(innerButton);\r
+        gbc.gridy++;\r
+        VOIPanel.add(innerButton, gbc);\r
+        \r
+        paramPanel = new JPanel(new GridBagLayout());\r
+\r
+        GridBagConstraints gbc2 = new GridBagConstraints();\r
+        gbc2.gridwidth = 1;\r
+        gbc2.gridheight = 1;\r
+        gbc2.anchor = GridBagConstraints.WEST;\r
+        gbc2.weightx = 1;\r
+        gbc2.insets = new Insets(3, 3, 3, 3);\r
+        gbc2.fill = GridBagConstraints.HORIZONTAL;\r
+        gbc2.gridx = 0;\r
+        gbc2.gridy = 0;\r
+        \r
+        JLabel xLabel = new JLabel("X dimension = y dimension of output image ");\r
+        xLabel.setForeground(Color.black);\r
+        xLabel.setFont(serif12);\r
+        xLabel.setEnabled(true);\r
+        gbc2.gridx = 0;\r
+        gbc2.gridy++;\r
+        paramPanel.add(xLabel, gbc2);\r
+\r
+        xText = new JTextField(10);\r
+        xText.setText(String.valueOf(image.getExtents()[0]));\r
+        xText.setFont(serif12);\r
+        xText.setEnabled(true);\r
+        gbc2.gridx = 1;\r
+        paramPanel.add(xText, gbc2);\r
+        \r
+        JLabel nptqLabel = new JLabel("Number of Gauss-Jacobi points (recommended 2-8):");\r
+        nptqLabel.setForeground(Color.black);\r
+        nptqLabel.setFont(serif12);\r
+        paramPanel.add(nptqLabel, gbc2);\r
+        \r
+        nptqText = new JTextField("8");\r
+        nptqText.setFont(serif12);\r
+        nptqText.setForeground(Color.black);\r
+        gbc2.gridx = 1;\r
+        paramPanel.add(nptqText, gbc2);\r
+        \r
+        displayCheckBox = new JCheckBox("Display system residuals during iterations");\r
+        displayCheckBox.setFont(serif12);\r
+        displayCheckBox.setForeground(Color.black);\r
+        displayCheckBox.setSelected(false);\r
+        gbc2.gridx = 0;\r
+        gbc2.gridy++;\r
+        paramPanel.add(displayCheckBox, gbc2);\r
+        \r
+        guessGroup = new ButtonGroup();\r
+        \r
+        nonequalButton = new JRadioButton("Non-equally spaced initial guess", false);\r
+        nonequalButton.setForeground(Color.black);\r
+        nonequalButton.setFont(serif12);\r
+        guessGroup.add(nonequalButton);\r
+        gbc2.gridy++;\r
+        paramPanel.add(nonequalButton, gbc2);\r
+        \r
+        equalButton = new JRadioButton("Equally spaced initial guess", true);\r
+        equalButton.setForeground(Color.black);\r
+        equalButton.setFont(serif12);\r
+        guessGroup.add(equalButton);\r
+        gbc2.gridy++;\r
+        paramPanel.add(equalButton, gbc2);\r
+        \r
+        preverticesButton = new JRadioButton("Arguments of initial prevertices initial guess", false);\r
+        preverticesButton.setForeground(Color.black);\r
+        preverticesButton.setFont(serif12);\r
+        guessGroup.add(preverticesButton);\r
+        gbc2.gridy++;\r
+        paramPanel.add(preverticesButton, gbc2);\r
+        \r
+        integrationGroup = new ButtonGroup();\r
+        lineButton = new JRadioButton("Integrating along line segment whenever possible", false);\r
+        lineButton.setForeground(Color.black);\r
+        lineButton.setFont(serif12);\r
+        integrationGroup.add(lineButton);\r
+        gbc2.gridy++;\r
+        paramPanel.add(lineButton, gbc2);\r
+        \r
+        circularButton = new JRadioButton("Integrating along line segment whenever possible", true);\r
+        circularButton.setForeground(Color.black);\r
+        circularButton.setFont(serif12);\r
+        integrationGroup.add(circularButton);\r
+        gbc2.gridy++;\r
+        paramPanel.add(circularButton, gbc2);\r
+        \r
+        JLabel tolLabel = new JLabel("A tolerance to control the convergence in HYBRD:");\r
+        tolLabel.setForeground(Color.black);\r
+        tolLabel.setFont(serif12);\r
+        paramPanel.add(tolLabel, gbc2);\r
+        \r
+        tolText = new JTextField("1.0E-10");\r
+        tolText.setFont(serif12);\r
+        tolText.setForeground(Color.black);\r
+        gbc2.gridx = 1;\r
+        paramPanel.add(tolText, gbc2);\r
+        \r
+        getContentPane().add(VOIPanel, BorderLayout.NORTH);\r
+        getContentPane().add(paramPanel, BorderLayout.CENTER);\r
+        getContentPane().add(buildButtons(), BorderLayout.SOUTH);\r
+\r
+        pack();\r
+        setVisible(true);\r
+    }\r
+    \r
+    /**\r
+     * Use the GUI results to set up the variables needed to run the algorithm.\r
+     *\r
+     * @return  <code>true</code> if parameters set successfully, <code>false</code> otherwise.\r
+     */\r
+    private boolean setVariables() {\r
+        int i, j;\r
+        int nVOIs;\r
+        float[] hsb;\r
+        float hue;\r
+        String tmpStr;\r
+        VOIs = image.getVOIs();\r
+        nVOIs = VOIs.size();\r
+        VOI presentVOI;\r
+        Vector<VOIBase> curves;\r
+        int nPtsOuter = 0;\r
+        int nPtsInner = 0;\r
+        Vector3f[] tmpPts = null;\r
+        int numInner;\r
+        int numOuter;\r
+\r
+        for (i = 0; i < nVOIs; i++) {\r
+               presentVOI = image.getVOIs().VOIAt(i);\r
+            if (presentVOI.getCurveType() == VOI.POINT) {\r
+               curves = presentVOI.getCurves();\r
+                hsb = Color.RGBtoHSB(presentVOI.getColor().getRed(), presentVOI.getColor().getGreen(),\r
+                                     presentVOI.getColor().getBlue(), null);\r
+                hue = hsb[0];\r
+\r
+                if ((Math.abs(hue - 0.0f)) < 0.0001f) {\r
+                    nPtsOuter += curves.size();\r
+                } else if ((Math.abs(hue - (1.0f / 3.0f))) < 0.0001f) {\r
+                    nPtsInner += curves.size();\r
+                    \r
+                } else {\r
+                    MipavUtil.displayError("VOI hue = " + hue + " Must be 0 for red or " +\r
+                                           "1/3 for green");\r
+\r
+                    return false;\r
+                }\r
+            }\r
+        } // for (i = 0; i < nVOIs; i++)\r
+        \r
+        if (nPtsOuter < 3) {\r
+            MipavUtil.displayError("At least 3 outer points required");\r
+            return false;\r
+        }\r
+        \r
+        if (nPtsInner == 0) {\r
+               MipavUtil.displayError("No inner points found");\r
+               return false;\r
+        }\r
+        \r
+        Z0 = new double[nPtsOuter][2];\r
+        Z1 = new double[nPtsInner][2];\r
+        \r
+        numInner = 0;\r
+        numOuter = 0;\r
+        for (i = 0; i < nVOIs; i++) {\r
+               presentVOI = image.getVOIs().VOIAt(i);\r
+            if (presentVOI.getCurveType() == VOI.POINT) {\r
+               tmpPts = presentVOI.exportAllPoints();\r
+                hsb = Color.RGBtoHSB(presentVOI.getColor().getRed(), presentVOI.getColor().getGreen(),\r
+                                     presentVOI.getColor().getBlue(), null);\r
+                hue = hsb[0];\r
+\r
+                if ((Math.abs(hue - 0.0f)) < 0.0001f) {\r
+                       // Invert so y axis increases going up so can use ccw ordering\r
+                       for (j = 0; j < tmpPts.length; j++) {\r
+                           Z0[numOuter][0] = tmpPts[j].X;\r
+                           Z0[numOuter++][1] = image.getExtents()[1] - 1 - tmpPts[j].Y;\r
+                       }\r
+                } else if ((Math.abs(hue - (1.0f / 3.0f))) < 0.0001f) {\r
+                       // Invert so y axis increases going up so can use ccw ordering\r
+                       for (j = 0; j < tmpPts.length; j++) {\r
+                           Z1[numInner][0] = tmpPts[j].X;\r
+                           Z1[numInner++][1] = image.getExtents()[1] - 1 - tmpPts[j].Y;\r
+                       }   \r
+                    \r
+                } else {\r
+                    MipavUtil.displayError("VOI hue = " + hue + " Must be 0 for red or " +\r
+                                           "1/3 for green");\r
+\r
+                    return false;\r
+                }\r
+            }\r
+        } // for (i = 0; i < nVOIs; i++)\r
+        \r
+        if (!testParameter(xText.getText(), 5, 1000000)) {\r
+            xText.requestFocus();\r
+            xText.selectAll();\r
+\r
+            return false;\r
+        } else {\r
+            xDim = Integer.valueOf(xText.getText()).intValue();\r
+        }\r
+        \r
+        tmpStr = nptqText.getText();\r
+       \r
+        if (testParameter(tmpStr, 2, 20)) {\r
+            NPTQ = Integer.valueOf(tmpStr).intValue();\r
+        } else {\r
+            nptqText.requestFocus();\r
+            nptqText.selectAll();\r
+\r
+            return false;\r
+        }\r
+        \r
+        if (displayCheckBox.isSelected()) {\r
+            ISPRT = 1; \r
+        }\r
+        else {\r
+               ISPRT = 2;\r
+        }\r
+        \r
+        if (nonequalButton.isSelected()) {\r
+               IGUESS = 0;\r
+        }\r
+        else if (equalButton.isSelected()) {\r
+               IGUESS = 1;\r
+        }\r
+        else {\r
+               IGUESS = 2;\r
+        }\r
+        \r
+        if (lineButton.isSelected()) {\r
+               LINEARC = 0;\r
+        }\r
+        else {\r
+               LINEARC = 1;\r
+        }\r
+        \r
+        tmpStr = tolText.getText();\r
+        \r
+        if (testParameter(tmpStr, 1.0E-16, 1.0E-3)) {\r
+            TOL = Double.valueOf(tmpStr).doubleValue();\r
+        } else {\r
+            tolText.requestFocus();\r
+            tolText.selectAll();\r
+\r
+            return false;\r
+        }\r
+\r
+        return true;\r
+    }\r
+}
\ No newline at end of file