Class FractalCanvas

  • All Implemented Interfaces:
    java.awt.event.ComponentListener, java.awt.image.ImageObserver, java.awt.MenuContainer, java.io.Serializable, java.util.EventListener, javax.accessibility.Accessible

    public class FractalCanvas
    extends javax.swing.JPanel
    implements java.awt.event.ComponentListener
    This class performs the drawing of the fractal, using a number of threads/runnables to compute the image in chunks.

    Each Runnable has is own local version of Jep, and its own copy of the expression. These are set during construction of the runnable.

     Jep localJep = new Jep(new LightWeightComponentSet(jep));
     ImportationVisitor iv = new ImportationVisitor(localJep);
     Node localExpression = iv.deepCopy(expression);
     Complex localC = new Complex(0, 0); // A single mutable value
     Complex localZ = new Complex(0, 0);
     localJep.addVariable("c", localC);
     localJep.addVariable("z", localZ);
     

    These are copies are used in the main evaluation loop.

     localC.set(x, y);
     localZ.set(0, 0);
     int count = 0;
     while (count < iterations && localZ.abs2() < 4.0) {
            localZ.set((Complex) localJep.evaluate(localExpression));
            count++;
     }
     

    Scheduling of threads is managed by a ThreadPoolExecutor with 10 threads

     ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 100, 10, TimeUnit.SECONDS,
                    new ArrayBlockingQueue<Runnable>(100));
     
    When a new image is needed a set of Runnables is created and sent to the executor.
     try {
             for (int i = 0; i < nDivisions; ++i) {
                for (int j = 0; j < nDivisions; ++j) {
              Runnable blockRunner = new CalcBlockRunnable(i * wid, j * high, wid, high);
              Future<Integer> future = executor.submit(blockRunner, wid * high);
              synchronized (futures) {
                  futures.add(future);
              }
          }
       }
     } catch (RejectedExecutionException ex) {
         System.out.println("Rejected execution " + ex.toString());
     } catch (JepException ex) {
         System.out.println(ex);
     }
     

    Each of these has a Future value used to count the number of completed runnables and cancel the tasks if needed. An ArrayList of these futures is kept. If the screen needs to be redrawn before every task is finished then they are killed by first calling future.cancel(true) and then purging them with executor.purge().

    An additional thread is used to collect statistics about completed tasks. A ConcurrentLinkedDeque<Integer> is used to send messages to this queue, and a Lock and Condition is used to wake this thread when there is a new message.

     ConcurrentLinkedDeque<Integer> reportQueue = new ConcurrentLinkedDeque<Integer>();
     Reporter reporter = new Reporter();
     Thread reportThead = new Thread(reporter, "ReportThread");
     reportThead.start();
     // Lock for reporter
     private Lock lock = new ReentrantLock();
     // Condition to signal when the reportQueue has data
     private Condition notEmpty = lock.newCondition();
     

    Messages are sent to this queue using

     lock.lock();
     reportQueue.add(nItts);
     notEmpty.signal();
     lock.unlock();
     

    And the report thread waits for messages

     lock.lock();
     while(true) {
         while(reportQueue.isEmpty()) {
               notEmpty.awaitUninterruptibly();
         }
         Integer itts =  reportQueue.pollFirst();
         ...
     }
     

    The image is created using a MemoryImageSource backed by a shared pixel array.

     int[] pixels = new int[dimensions.width * dimensions.height];
     MemoryImageSource source = new MemoryImageSource(dimensions.width, dimensions.height, pixels, 0, dimensions.width);
     source.setAnimated(true);
     Image outImage = Toolkit.getDefaultToolkit().createImage(source);
     

    The pixels are simply set by the runnable pixels[index] = Color.getRGB() and when an entire block is finished image consumers are informed using source.newPixels(rect.x,rect.y,rect.width,rect.height ). The paint method simply uses the Graphic.drawImage using Component imageUpdate() callback method to paint more of the image as it becomes available.

     public void paint(Graphics g) {
         g.drawImage(outImage, 0, 0, this);
     }
     
    See Also:
    Serialized Form
    • Nested Class Summary

      • Nested classes/interfaces inherited from class javax.swing.JPanel

        javax.swing.JPanel.AccessibleJPanel
      • Nested classes/interfaces inherited from class javax.swing.JComponent

        javax.swing.JComponent.AccessibleJComponent
      • Nested classes/interfaces inherited from class java.awt.Container

        java.awt.Container.AccessibleAWTContainer
      • Nested classes/interfaces inherited from class java.awt.Component

        java.awt.Component.AccessibleAWTComponent, java.awt.Component.BaselineResizeBehavior, java.awt.Component.BltBufferStrategy, java.awt.Component.FlipBufferStrategy
    • Field Summary

      • Fields inherited from class javax.swing.JComponent

        listenerList, TOOL_TIP_TEXT_KEY, ui, UNDEFINED_CONDITION, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, WHEN_FOCUSED, WHEN_IN_FOCUSED_WINDOW
      • Fields inherited from class java.awt.Component

        accessibleContext, BOTTOM_ALIGNMENT, CENTER_ALIGNMENT, LEFT_ALIGNMENT, RIGHT_ALIGNMENT, TOP_ALIGNMENT
      • Fields inherited from interface java.awt.image.ImageObserver

        ABORT, ALLBITS, ERROR, FRAMEBITS, HEIGHT, PROPERTIES, SOMEBITS, WIDTH
    • Constructor Summary

      Constructors 
      Constructor Description
      FractalCanvas​(java.lang.String initialExpression, Fractal parent)
      Constructor.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void componentHidden​(java.awt.event.ComponentEvent e)  
      void componentMoved​(java.awt.event.ComponentEvent e)  
      void componentResized​(java.awt.event.ComponentEvent e)  
      void componentShown​(java.awt.event.ComponentEvent e)  
      void paint​(java.awt.Graphics g)  
      void render()  
      boolean setColorExpression​(java.lang.String str)
      Parses a new expression for colors
      boolean setExpressionString​(java.lang.String newString)
      Parses a new expression
      void setIterations​(int iterations_in)
      Sets number of iterations
      void shiftSelection​(com.singularsys.jepexamples.applets.FractalCanvas.RegionListener regionListener)
      Responds to mouse drag events translates the scene.
      void zoomIn​(Complex mid)
      Zoom in the sceen
      void zoomOut()
      Zoom out the scene.
      • Methods inherited from class javax.swing.JPanel

        getAccessibleContext, getUI, getUIClassID, paramString, setUI, updateUI
      • Methods inherited from class javax.swing.JComponent

        addAncestorListener, addNotify, addVetoableChangeListener, computeVisibleRect, contains, createToolTip, disable, enable, firePropertyChange, firePropertyChange, firePropertyChange, fireVetoableChange, getActionForKeyStroke, getActionMap, getAlignmentX, getAlignmentY, getAncestorListeners, getAutoscrolls, getBaseline, getBaselineResizeBehavior, getBorder, getBounds, getClientProperty, getComponentGraphics, getComponentPopupMenu, getConditionForKeyStroke, getDebugGraphicsOptions, getDefaultLocale, getFontMetrics, getGraphics, getHeight, getInheritsPopupMenu, getInputMap, getInputMap, getInputVerifier, getInsets, getInsets, getListeners, getLocation, getMaximumSize, getMinimumSize, getNextFocusableComponent, getPopupLocation, getPreferredSize, getRegisteredKeyStrokes, getRootPane, getSize, getToolTipLocation, getToolTipText, getToolTipText, getTopLevelAncestor, getTransferHandler, getVerifyInputWhenFocusTarget, getVetoableChangeListeners, getVisibleRect, getWidth, getX, getY, grabFocus, hide, isDoubleBuffered, isLightweightComponent, isManagingFocus, isOpaque, isOptimizedDrawingEnabled, isPaintingForPrint, isPaintingOrigin, isPaintingTile, isRequestFocusEnabled, isValidateRoot, paintBorder, paintChildren, paintComponent, paintImmediately, paintImmediately, print, printAll, printBorder, printChildren, printComponent, processComponentKeyEvent, processKeyBinding, processKeyEvent, processMouseEvent, processMouseMotionEvent, putClientProperty, registerKeyboardAction, registerKeyboardAction, removeAncestorListener, removeNotify, removeVetoableChangeListener, repaint, repaint, requestDefaultFocus, requestFocus, requestFocus, requestFocusInWindow, requestFocusInWindow, resetKeyboardActions, reshape, revalidate, scrollRectToVisible, setActionMap, setAlignmentX, setAlignmentY, setAutoscrolls, setBackground, setBorder, setComponentPopupMenu, setDebugGraphicsOptions, setDefaultLocale, setDoubleBuffered, setEnabled, setFocusTraversalKeys, setFont, setForeground, setInheritsPopupMenu, setInputMap, setInputVerifier, setMaximumSize, setMinimumSize, setNextFocusableComponent, setOpaque, setPreferredSize, setRequestFocusEnabled, setToolTipText, setTransferHandler, setUI, setVerifyInputWhenFocusTarget, setVisible, unregisterKeyboardAction, update
      • Methods inherited from class java.awt.Container

        add, add, add, add, add, addContainerListener, addImpl, addPropertyChangeListener, addPropertyChangeListener, applyComponentOrientation, areFocusTraversalKeysSet, countComponents, deliverEvent, doLayout, findComponentAt, findComponentAt, getComponent, getComponentAt, getComponentAt, getComponentCount, getComponents, getComponentZOrder, getContainerListeners, getFocusTraversalKeys, getFocusTraversalPolicy, getLayout, getMousePosition, insets, invalidate, isAncestorOf, isFocusCycleRoot, isFocusCycleRoot, isFocusTraversalPolicyProvider, isFocusTraversalPolicySet, layout, list, list, locate, minimumSize, paintComponents, preferredSize, printComponents, processContainerEvent, processEvent, remove, remove, removeAll, removeContainerListener, setComponentZOrder, setFocusCycleRoot, setFocusTraversalPolicy, setFocusTraversalPolicyProvider, setLayout, transferFocusDownCycle, validate, validateTree
      • Methods inherited from class java.awt.Component

        action, add, addComponentListener, addFocusListener, addHierarchyBoundsListener, addHierarchyListener, addInputMethodListener, addKeyListener, addMouseListener, addMouseMotionListener, addMouseWheelListener, bounds, checkImage, checkImage, coalesceEvents, contains, createImage, createImage, createVolatileImage, createVolatileImage, disableEvents, dispatchEvent, enable, enableEvents, enableInputMethods, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, firePropertyChange, getBackground, getBounds, getColorModel, getComponentListeners, getComponentOrientation, getCursor, getDropTarget, getFocusCycleRootAncestor, getFocusListeners, getFocusTraversalKeysEnabled, getFont, getForeground, getGraphicsConfiguration, getHierarchyBoundsListeners, getHierarchyListeners, getIgnoreRepaint, getInputContext, getInputMethodListeners, getInputMethodRequests, getKeyListeners, getLocale, getLocation, getLocationOnScreen, getMouseListeners, getMouseMotionListeners, getMousePosition, getMouseWheelListeners, getName, getParent, getPropertyChangeListeners, getPropertyChangeListeners, getSize, getToolkit, getTreeLock, gotFocus, handleEvent, hasFocus, imageUpdate, inside, isBackgroundSet, isCursorSet, isDisplayable, isEnabled, isFocusable, isFocusOwner, isFocusTraversable, isFontSet, isForegroundSet, isLightweight, isMaximumSizeSet, isMinimumSizeSet, isPreferredSizeSet, isShowing, isValid, isVisible, keyDown, keyUp, list, list, list, location, lostFocus, mouseDown, mouseDrag, mouseEnter, mouseExit, mouseMove, mouseUp, move, nextFocus, paintAll, postEvent, prepareImage, prepareImage, processComponentEvent, processFocusEvent, processHierarchyBoundsEvent, processHierarchyEvent, processInputMethodEvent, processMouseWheelEvent, remove, removeComponentListener, removeFocusListener, removeHierarchyBoundsListener, removeHierarchyListener, removeInputMethodListener, removeKeyListener, removeMouseListener, removeMouseMotionListener, removeMouseWheelListener, removePropertyChangeListener, removePropertyChangeListener, repaint, repaint, repaint, requestFocus, requestFocus, requestFocusInWindow, resize, resize, setBounds, setBounds, setComponentOrientation, setCursor, setDropTarget, setFocusable, setFocusTraversalKeysEnabled, setIgnoreRepaint, setLocale, setLocation, setLocation, setMixingCutoutShape, setName, setSize, setSize, show, show, size, toString, transferFocus, transferFocusBackward, transferFocusUpCycle
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
    • Constructor Detail

      • FractalCanvas

        public FractalCanvas​(java.lang.String initialExpression,
                             Fractal parent)
        Constructor.
    • Method Detail

      • setExpressionString

        public boolean setExpressionString​(java.lang.String newString)
        Parses a new expression
        Returns:
        true on successful parse
      • setColorExpression

        public boolean setColorExpression​(java.lang.String str)
        Parses a new expression for colors
        Returns:
        true on successful parse
      • setIterations

        public void setIterations​(int iterations_in)
        Sets number of iterations
        Parameters:
        iterations_in -
      • paint

        public void paint​(java.awt.Graphics g)
        Overrides:
        paint in class javax.swing.JComponent
      • shiftSelection

        public void shiftSelection​(com.singularsys.jepexamples.applets.FractalCanvas.RegionListener regionListener)
        Responds to mouse drag events translates the scene.
      • zoomIn

        public void zoomIn​(Complex mid)
        Zoom in the sceen
        Parameters:
        mid - midpoint of the new scene
      • zoomOut

        public void zoomOut()
        Zoom out the scene.
      • componentResized

        public void componentResized​(java.awt.event.ComponentEvent e)
        Specified by:
        componentResized in interface java.awt.event.ComponentListener
      • componentMoved

        public void componentMoved​(java.awt.event.ComponentEvent e)
        Specified by:
        componentMoved in interface java.awt.event.ComponentListener
      • componentShown

        public void componentShown​(java.awt.event.ComponentEvent e)
        Specified by:
        componentShown in interface java.awt.event.ComponentListener
      • componentHidden

        public void componentHidden​(java.awt.event.ComponentEvent e)
        Specified by:
        componentHidden in interface java.awt.event.ComponentListener
      • render

        public void render()