diff --git a/.gitignore b/.gitignore index 5241a722..cee99345 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -*.class \ No newline at end of file +*.class +/bin/ \ No newline at end of file diff --git a/README.md b/README.md index c6621720..31d44bc9 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,16 @@ # w0rthy's Array Visualizer, Revamped [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=Q5QLCFZ8G7WY6¤cy_code=USD&source=url) -Over 75 sorting algorithms animated with 10 unique graphic designs +Over 75 sorting algorithms animated with 12 unique graphic designs This new version of the program features additions inspired by Timo Bingmann's "The Sound of Sorting" and w0rthy's updates to the original visualizer. -To build (After -cp, use ";" with Windows and ":" with Mac/Linux): +To compile (After -cp, use ";" with Windows and ":" with Mac/Linux): ``` ant java -cp bin;lib/classgraph-4.8.47.jar main.ArrayVisualizer ``` +To build a runnable jar, simply run Apache Ant inside the 'dist' directory! ### Features: - 40+ new sorting algorithms @@ -23,6 +24,13 @@ java -cp bin;lib/classgraph-4.8.47.jar main.ArrayVisualizer - Toggle Timo Bingmann's "end sweep" animation - Refactored / optimized code +## 6/8/2020 - Version 3.5 +- NEW VISUALS: Sine Wave and Wave Dots!! +- New sort: Bogobogosort +- The bogo shuffle method is now unbiased +- MultipleSortThreads further refactored +- Visuals, VisualStyles enum, and Renderer significantly refactored (more to come!) + ## 6/4/2020 - Version 3.2 - New sort: Optimized Cocktail Shaker Sort - Significant refactoring for MultipleSortThreads and RunAllSorts diff --git a/bin/.gitignore b/bin/.gitignore deleted file mode 100644 index edcc0ea2..00000000 --- a/bin/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -/SortPrompt.form -/UtilFrame.form -/ViewPrompt.form -/frames/ -/main/ -/prompts/ -/sorts/ -/templates/ -/test/ -/threads/ -/utils/ -/visuals/ diff --git a/bin/SortPrompt.form b/bin/SortPrompt.form deleted file mode 100644 index 08d82518..00000000 --- a/bin/SortPrompt.form +++ /dev/null @@ -1,138 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/bin/UtilFrame.form b/bin/UtilFrame.form deleted file mode 100644 index 13edae8e..00000000 --- a/bin/UtilFrame.form +++ /dev/null @@ -1,123 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/bin/ViewPrompt.form b/bin/ViewPrompt.form deleted file mode 100644 index 9860af11..00000000 --- a/bin/ViewPrompt.form +++ /dev/null @@ -1,169 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/bin/soundfont/sfx.sf2 b/bin/soundfont/sfx.sf2 deleted file mode 100644 index 6445a80a..00000000 Binary files a/bin/soundfont/sfx.sf2 and /dev/null differ diff --git a/dist/arrayVisualizer.jar b/dist/arrayVisualizer.jar index 702da50f..a22f4497 100644 Binary files a/dist/arrayVisualizer.jar and b/dist/arrayVisualizer.jar differ diff --git a/dist/Java.xml b/dist/build.xml similarity index 93% rename from dist/Java.xml rename to dist/build.xml index d5e40e15..a0fabb51 100644 --- a/dist/Java.xml +++ b/dist/build.xml @@ -16,6 +16,7 @@ + diff --git a/src/main/ArrayVisualizer.java b/src/main/ArrayVisualizer.java index 82db450a..f463a546 100644 --- a/src/main/ArrayVisualizer.java +++ b/src/main/ArrayVisualizer.java @@ -2,7 +2,6 @@ import java.awt.BasicStroke; import java.awt.Color; -import java.awt.Dialog; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; @@ -10,26 +9,30 @@ import java.awt.Image; import java.awt.Stroke; import java.awt.Toolkit; -import java.awt.Window; import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.util.Locale; -import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JOptionPane; import frames.ArrayFrame; import frames.UtilFrame; +import templates.Visual; import utils.Delays; -import utils.Renderer; import utils.Highlights; import utils.Reads; +import utils.Renderer; import utils.Sounds; import utils.Timer; import utils.Writes; +import visuals.Bars; +import visuals.Circular; +import visuals.Hoops; +import visuals.Mesh; +import visuals.Pixels; import visuals.VisualStyles; /* TO-DO LIST: @@ -152,6 +155,8 @@ final public class ArrayVisualizer { private UtilFrame UtilFrame; private ArrayFrame ArrayFrame; + private Visual[] visualClasses; + private Thread sortingThread; private Thread visualsThread; @@ -176,6 +181,7 @@ final public class ArrayVisualizer { private volatile boolean PIXELDRAW; private volatile boolean RAINBOW; private volatile boolean SPIRALDRAW; + private volatile boolean WAVEDRAW; private volatile int cx; private volatile int cy; @@ -211,23 +217,23 @@ public ArrayVisualizer() { this.ArrayManager = new ArrayManager(this); this.SortAnalyzer = new SortAnalyzer(this); - SortAnalyzer.analyzeSorts(); - this.ComparisonSorts = SortAnalyzer.getComparisonSorts(); - this.DistributionSorts = SortAnalyzer.getDistributionSorts(); - this.InvalidSorts = SortAnalyzer.getInvalidSorts(); + this.SortAnalyzer.analyzeSorts(); + this.ComparisonSorts = this.SortAnalyzer.getComparisonSorts(); + this.DistributionSorts = this.SortAnalyzer.getDistributionSorts(); + this.InvalidSorts = this.SortAnalyzer.getInvalidSorts(); this.category = ""; this.heading = ""; this.typeFace = new Font("Times New Roman", Font.PLAIN, (int) (640 / (1280.0 * 25))); this.formatter = (DecimalFormat) NumberFormat.getInstance(Locale.US); - this.symbols = formatter.getDecimalFormatSymbols(); + this.symbols = this.formatter.getDecimalFormatSymbols(); this.formatter.setRoundingMode(RoundingMode.HALF_UP); this.UtilFrame = new UtilFrame(this.array, this); this.ArrayFrame = new ArrayFrame(this.array, this); - UtilFrame.reposition(this.ArrayFrame); + this.UtilFrame.reposition(this.ArrayFrame); this.SHUFFLEANIM = true; this.ANALYZE = false; @@ -246,7 +252,7 @@ public ArrayVisualizer() { this.ch = 0; this.cw = 0; - ArrayManager.initializeArray(this.array); + this.ArrayManager.initializeArray(this.array); //TODO: Overhaul visual code to properly reflect Swing (JavaFX?) style and conventions @@ -254,36 +260,43 @@ public ArrayVisualizer() { this.visualsThread = new Thread() { @Override public void run() { - Renderer.initializeVisuals(ArrayVisualizer.this, ArrayVisualizer.this.VisualStyles); + utils.Renderer.initializeVisuals(ArrayVisualizer.this); - Graphics background = window.getGraphics(); + Graphics background = ArrayVisualizer.this.window.getGraphics(); background.setColor(Color.BLACK); int coltmp = 255; + ArrayVisualizer.this.visualClasses = new Visual[5]; + ArrayVisualizer.this.visualClasses[0] = new Bars(ArrayVisualizer.this); + ArrayVisualizer.this.visualClasses[1] = new Circular(ArrayVisualizer.this); + ArrayVisualizer.this.visualClasses[2] = new Hoops(ArrayVisualizer.this); + ArrayVisualizer.this.visualClasses[3] = new Mesh(ArrayVisualizer.this); + ArrayVisualizer.this.visualClasses[4] = new Pixels(ArrayVisualizer.this); + while(true) { - Renderer.updateVisuals(ArrayVisualizer.this); - Renderer.drawVisual(ArrayVisualizer.this.VisualStyles, array, ArrayVisualizer.this, mainRender, extraRender, Highlights); + ArrayVisualizer.this.Renderer.updateVisuals(ArrayVisualizer.this); + ArrayVisualizer.this.Renderer.drawVisual(ArrayVisualizer.this.VisualStyles, ArrayVisualizer.this.array, ArrayVisualizer.this, ArrayVisualizer.this.Highlights); - mainRender.setColor(new Color(coltmp,coltmp,coltmp)); - if(TEXTDRAW) { - Font f = mainRender.getFont(); - mainRender.setFont(typeFace); - mainRender.drawString(category + ": " + heading, 15, (int)(cw/1280.0*30)+30); - mainRender.drawString(formatter.format(currentLen) + " Numbers", 15, (int)(cw/1280.0*55)+30); - mainRender.drawString(String.format("Delay: " + Delays.displayCurrentDelay() + "ms"), 15, (int)(cw/1280.0*95)+30); - mainRender.drawString(String.format("Visual Time: " + Timer.getVisualTime()), 15, (int)(cw/1280.0*120)+30); - mainRender.drawString(String.format("Sort Time: " + Timer.getRealTime()), 15, (int)(cw/1280.0*145)+30); - mainRender.drawString(Reads.displayComparisons(), 15, (int)(cw/1280.0*185)+30); - mainRender.drawString(Writes.getSwaps(), 15, (int)(cw/1280.0*210)+30); - mainRender.drawString(Writes.getReversals(), 15, (int)(cw/1280.0*235)+30); - mainRender.drawString(Writes.getWrites(), 15, (int)(cw/1280.0*275)+30); - mainRender.drawString(Writes.getTempWrites(), 15, (int)(cw/1280.0*300)+30); - mainRender.setFont(f); + ArrayVisualizer.this.mainRender.setColor(new Color(coltmp, coltmp, coltmp)); + if(ArrayVisualizer.this.TEXTDRAW) { + Font f = ArrayVisualizer.this.mainRender.getFont(); + ArrayVisualizer.this.mainRender.setFont(ArrayVisualizer.this.typeFace); + ArrayVisualizer.this.mainRender.drawString(ArrayVisualizer.this.category + ": " + ArrayVisualizer.this.heading, 15, (int)(ArrayVisualizer.this.cw/1280.0*30)+30); + ArrayVisualizer.this.mainRender.drawString(ArrayVisualizer.this.formatter.format(ArrayVisualizer.this.currentLen) + " Numbers", 15, (int)(ArrayVisualizer.this.cw/1280.0*55)+30); + ArrayVisualizer.this.mainRender.drawString(String.format("Delay: " + ArrayVisualizer.this.Delays.displayCurrentDelay() + "ms"), 15, (int)(ArrayVisualizer.this.cw/1280.0*95)+30); + ArrayVisualizer.this.mainRender.drawString(String.format("Visual Time: " + ArrayVisualizer.this.Timer.getVisualTime()), 15, (int)(ArrayVisualizer.this.cw/1280.0*120)+30); + ArrayVisualizer.this.mainRender.drawString(String.format("Sort Time: " + ArrayVisualizer.this.Timer.getRealTime()), 15, (int)(ArrayVisualizer.this.cw/1280.0*145)+30); + ArrayVisualizer.this.mainRender.drawString(ArrayVisualizer.this.Reads.displayComparisons(), 15, (int)(ArrayVisualizer.this.cw/1280.0*185)+30); + ArrayVisualizer.this.mainRender.drawString(ArrayVisualizer.this.Writes.getSwaps(), 15, (int)(ArrayVisualizer.this.cw/1280.0*210)+30); + ArrayVisualizer.this.mainRender.drawString(ArrayVisualizer.this.Writes.getReversals(), 15, (int)(ArrayVisualizer.this.cw/1280.0*235)+30); + ArrayVisualizer.this.mainRender.drawString(ArrayVisualizer.this.Writes.getWrites(), 15, (int)(ArrayVisualizer.this.cw/1280.0*275)+30); + ArrayVisualizer.this.mainRender.drawString(ArrayVisualizer.this.Writes.getTempWrites(), 15, (int)(ArrayVisualizer.this.cw/1280.0*300)+30); + ArrayVisualizer.this.mainRender.setFont(f); } - background.drawImage(img, 0, 0, null); + background.drawImage(ArrayVisualizer.this.img, 0, 0, null); }}}; - Sounds.startAudioThread(); + this.Sounds.startAudioThread(); this.drawWindows(); } @@ -315,6 +328,10 @@ public Writes getWrites() { return this.Writes; } + public Visual[] getVisuals() { + return this.visualClasses; + } + public UtilFrame getUtilFrame() { return this.UtilFrame; } @@ -333,7 +350,7 @@ public void setSortingThread(Thread thread) { this.sortingThread = thread; } public void runSortingThread() { - sortingThread.start(); + this.sortingThread.start(); } public int getMinimumLength() { @@ -344,9 +361,9 @@ public int getMaximumLength() { } public void resetAllStatistics() { - Reads.resetStatistics(); - Writes.resetStatistics(); - Timer.manualSetTime(0); + this.Reads.resetStatistics(); + this.Writes.resetStatistics(); + this.Timer.manualSetTime(0); } // These next five methods should be part of ArrayManager @@ -394,10 +411,10 @@ public JFrame getMainWindow() { } public void setWindowHeight() { - this.ch = window.getHeight(); + this.ch = this.window.getHeight(); } public void setWindowWidth() { - this.cw = window.getWidth(); + this.cw = this.window.getWidth(); } // TODO: @@ -405,16 +422,16 @@ public void setWindowWidth() { // AND WINDOW HEIGHT/WIDTH/X/Y SHOULD CORRESPOND TO WINDOW FIELD public int currentHeight() { - return window.getHeight(); + return this.window.getHeight(); } public int currentWidth() { - return window.getWidth(); + return this.window.getWidth(); } public int currentX() { - return window.getX(); + return this.window.getX(); } public int currentY() { - return window.getY(); + return this.window.getY(); } public int windowHeight() { @@ -437,7 +454,7 @@ public int windowYCoordinate() { } public void createVolatileImage() { - this.img = window.createVolatileImage(cw, ch); + this.img = this.window.createVolatileImage(this.cw, this.ch); } public void setThickStroke(Stroke stroke) { this.thickStroke = stroke; @@ -448,28 +465,39 @@ public Stroke getThickStroke() { public Stroke getDefaultStroke() { return new BasicStroke(3f * (this.currentWidth() / 1280f)); } + public Graphics2D getMainRender() { + return this.mainRender; + } + public Graphics2D getExtraRender() { + return this.extraRender; + } public void setMainRender() { - this.mainRender = (Graphics2D) img.getGraphics(); + this.mainRender = (Graphics2D) this.img.getGraphics(); } public void setExtraRender() { - this.extraRender = (Graphics2D) img.getGraphics(); + this.extraRender = (Graphics2D) this.img.getGraphics(); + } + public void updateVisuals() { + for(Visual visual : this.visualClasses) { + visual.updateRender(this); + } } public void resetMainStroke() { - mainRender.setStroke(this.getDefaultStroke()); + this.mainRender.setStroke(this.getDefaultStroke()); } public void renderBackground() { - mainRender.setColor(new Color(0, 0, 0)); // Pure black - mainRender.fillRect(0, 0, img.getWidth(null), img.getHeight(null)); + this.mainRender.setColor(new Color(0, 0, 0)); // Pure black + this.mainRender.fillRect(0, 0, this.img.getWidth(null), this.img.getHeight(null)); } public void updateCoordinates() { - this.cx = window.getX(); - this.cy = window.getY(); + this.cx = this.window.getX(); + this.cy = this.window.getY(); } public void updateDimensions() { - this.cw = window.getWidth(); - this.ch = window.getHeight(); + this.cw = this.window.getWidth(); + this.ch = this.window.getHeight(); } public void updateFontSize() { this.typeFace = new Font("Times New Roman",Font.PLAIN,(int)(this.cw/1280.0*25)); @@ -486,11 +514,12 @@ public int halfCircle() { return (this.currentLen / 2); } + //TODO: This method is *way* too long. Break it apart. public synchronized void verifySortAndSweep() { - Highlights.toggleFancyFinish(true); - Highlights.resetFancyFinish(); + this.Highlights.toggleFancyFinish(true); + this.Highlights.resetFancyFinish(); - Delays.setSleepRatio(1); + this.Delays.setSleepRatio(1); double sleepRatio = 0; @@ -511,63 +540,63 @@ public synchronized void verifySortAndSweep() { default: sleepRatio = 64; } - long tempComps = Reads.getComparisons(); - Reads.setComparisons(0); + long tempComps = this.Reads.getComparisons(); + this.Reads.setComparisons(0); String temp = this.heading; this.heading = "Verifying sort..."; for(int i = 0; i < this.currentLen + this.getLogBaseTwoOfLength(); i++) { - if(i < this.currentLen) Highlights.markArray(1, i); - Highlights.incrementFancyFinishPosition(); + if(i < this.currentLen) this.Highlights.markArray(1, i); + this.Highlights.incrementFancyFinishPosition(); if(i < this.currentLen - 1) { - if(Reads.compare(array[i], array[i + 1]) == 1) { - Highlights.clearMark(1); + if(this.Reads.compare(this.array[i], this.array[i + 1]) == 1) { + this.Highlights.clearMark(1); - Sounds.toggleSound(false); - Highlights.toggleFancyFinish(false); + this.Sounds.toggleSound(false); + this.Highlights.toggleFancyFinish(false); for(int j = i + 1; j < this.currentLen; j++) { - Highlights.markArray(j, j); - Delays.sleep(sleepRatio / this.getLogBaseTwoOfLength()); + this.Highlights.markArray(j, j); + this.Delays.sleep(sleepRatio / this.getLogBaseTwoOfLength()); } - JOptionPane.showMessageDialog(window, "The sort was unsuccessful;\nIndices " + i + " and " + (i + 1) + " are out of order!", "Error", JOptionPane.OK_OPTION, null); + JOptionPane.showMessageDialog(this.window, "The sort was unsuccessful;\nIndices " + i + " and " + (i + 1) + " are out of order!", "Error", JOptionPane.OK_OPTION, null); - Highlights.clearAllMarks(); + this.Highlights.clearAllMarks(); i = this.currentLen + this.getLogBaseTwoOfLength(); - Sounds.toggleSound(true); + this.Sounds.toggleSound(true); } } - if(Highlights.fancyFinishEnabled()) { - Delays.sleep(sleepRatio / this.getLogBaseTwoOfLength()); + if(this.Highlights.fancyFinishEnabled()) { + this.Delays.sleep(sleepRatio / this.getLogBaseTwoOfLength()); } } - Highlights.clearMark(1); + this.Highlights.clearMark(1); this.heading = temp; - Reads.setComparisons(tempComps); + this.Reads.setComparisons(tempComps); - if(Highlights.fancyFinishActive()) { - Highlights.toggleFancyFinish(false); + if(this.Highlights.fancyFinishActive()) { + this.Highlights.toggleFancyFinish(false); } - Highlights.resetFancyFinish(); + this.Highlights.resetFancyFinish(); } public void endSort() { - Timer.disableRealTimer(); - Highlights.clearAllMarks(); + this.Timer.disableRealTimer(); + this.Highlights.clearAllMarks(); - double speed = Delays.getSleepRatio(); + double speed = this.Delays.getSleepRatio(); this.verifySortAndSweep(); - Delays.setSleepRatio(speed); - Delays.changeSkipped(false); + this.Delays.setSleepRatio(speed); + this.Delays.changeSkipped(false); - Highlights.clearAllMarks(); + this.Highlights.clearAllMarks(); } public void togglePointer(boolean Bool) { @@ -594,6 +623,9 @@ public void toggleStatistics(boolean Bool) { public void toggleColor(boolean Bool) { this.COLOR = Bool; } + public void toggleWave(boolean Bool) { + this.WAVEDRAW = Bool; + } public void setVisual(VisualStyles choice) { this.VisualStyles = choice; @@ -607,8 +639,8 @@ public void setCurrentGap(int gap) { } public void repositionFrames() { - ArrayFrame.reposition(); - UtilFrame.reposition(ArrayFrame); + this.ArrayFrame.reposition(); + this.UtilFrame.reposition(this.ArrayFrame); } public boolean rainbowEnabled() { @@ -629,6 +661,9 @@ public boolean pixelsEnabled() { public boolean linesEnabled() { return this.LINEDRAW; } + public boolean waveEnabled() { + return this.WAVEDRAW; + } public DecimalFormat getNumberFormat() { return this.formatter; @@ -639,40 +674,40 @@ private void drawWindows() { this.category = "Select a Sort"; // For recording with OBS (don't ask where these numbers came from. I don't get it myself) - if(OBS) { + if(this.OBS) { int x = (int) (1920 * (double) (1920 / 1916)); int y = (int) (1080 * (double) (1080 / 1020)); - window.setSize(new Dimension(x, y)); + this.window.setSize(new Dimension(x, y)); } else { // Consider changing back to discrete 16:9 dimension Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - window.setSize((int) (screenSize.getWidth() / 2d), (int) (screenSize.getHeight() / 2d)); + this.window.setSize((int) (screenSize.getWidth() / 2d), (int) (screenSize.getHeight() / 2d)); } - window.setLocation(0, 0); - window.setVisible(true); - window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - window.setTitle("w0rthy's Array Visualizer - " + (ComparisonSorts[0].length + DistributionSorts[0].length) + " Sorting Algorithms with 10 Different Visual Styles"); - window.setBackground(Color.BLACK); + this.window.setLocation(0, 0); + this.window.setVisible(true); + this.window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + this.window.setTitle("w0rthy's Array Visualizer - " + (this.ComparisonSorts[0].length + this.DistributionSorts[0].length) + " Sorting Algorithms with 12 Different Visual Styles"); + this.window.setBackground(Color.BLACK); - symbols.setGroupingSeparator(','); - formatter.setDecimalFormatSymbols(symbols); + this.symbols.setGroupingSeparator(','); + this.formatter.setDecimalFormatSymbols(this.symbols); //TODO: Consider removing insets from window size - this.cw = window.getWidth(); - this.ch = window.getHeight(); + this.cw = this.window.getWidth(); + this.ch = this.window.getHeight(); - visualsThread.start(); + this.visualsThread.start(); - UtilFrame.setVisible(true); - ArrayFrame.setVisible(true); + this.UtilFrame.setVisible(true); + this.ArrayFrame.setVisible(true); if(this.InvalidSorts != null) { String output = ""; - for(int i = 0; i < InvalidSorts.length; i++) { - output += InvalidSorts[i] + "\n"; + for(int i = 0; i < this.InvalidSorts.length; i++) { + output += this.InvalidSorts[i] + "\n"; } - JOptionPane.showMessageDialog(window, "The following algorithms were not loaded due to errors:\n" + output, "Warning", JOptionPane.WARNING_MESSAGE); + JOptionPane.showMessageDialog(this.window, "The following algorithms were not loaded due to errors:\n" + output, "Warning", JOptionPane.WARNING_MESSAGE); } } diff --git a/src/prompts/ViewPrompt.java b/src/prompts/ViewPrompt.java index b2d76efe..92c6043d 100644 --- a/src/prompts/ViewPrompt.java +++ b/src/prompts/ViewPrompt.java @@ -10,6 +10,10 @@ import main.ArrayVisualizer; import templates.Frame; import visuals.VisualStyles; +import javax.swing.JButton; +import javax.swing.GroupLayout.Alignment; +import javax.swing.GroupLayout; +import javax.swing.LayoutStyle.ComponentPlacement; /* * @@ -81,6 +85,8 @@ private void initComponents() { this.spiralDots= new javax.swing.JButton(); this.rainbow = new javax.swing.JButton(); this.hoops = new javax.swing.JButton(); + this.sineWave = new javax.swing.JButton(); + this.waveDots = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setResizable(false); @@ -166,58 +172,77 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { spiralDotsActionPerformed(evt); } }); - + + sineWave.setText("Sine Wave"); + sineWave.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + sineWaveActionPerformed(evt); + } + }); + waveDots.setText("Wave Dots"); + waveDots.addActionListener(new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + waveDotsActionPerformed(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER, true) - .addGroup(layout.createSequentialGroup() - .addGap(18, 18, 18) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, true) - .addComponent(this.barGraph, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.rainbow, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.colorCircle, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.disparity, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.disparityDots, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, true) - .addComponent(this.dotGraph, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.triangleMesh, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.spiral, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.hoops, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(this.spiralDots, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGap(18, 18, 18)) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER, true) - .addComponent(this.jLabel1)) - ); + layout.createParallelGroup(Alignment.CENTER) + .addComponent(jLabel1) + .addGroup(Alignment.LEADING, layout.createSequentialGroup() + .addGap(18) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(barGraph, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 105, Short.MAX_VALUE) + .addComponent(rainbow, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 105, Short.MAX_VALUE) + .addComponent(colorCircle, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 105, Short.MAX_VALUE) + .addComponent(disparity, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(disparityDots, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 105, Short.MAX_VALUE) + .addComponent(sineWave, GroupLayout.DEFAULT_SIZE, 105, Short.MAX_VALUE)) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(waveDots, GroupLayout.DEFAULT_SIZE, 101, Short.MAX_VALUE) + .addComponent(dotGraph, GroupLayout.DEFAULT_SIZE, 101, Short.MAX_VALUE) + .addComponent(triangleMesh, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(spiral, GroupLayout.DEFAULT_SIZE, 101, Short.MAX_VALUE) + .addComponent(hoops, GroupLayout.DEFAULT_SIZE, 101, Short.MAX_VALUE) + .addComponent(spiralDots, GroupLayout.DEFAULT_SIZE, 101, Short.MAX_VALUE)) + .addGap(18)) + ); layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER, true) + layout.createParallelGroup(Alignment.CENTER) .addGroup(layout.createSequentialGroup() - .addGap(7, 7, 7) - .addComponent(this.jLabel1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE, true) - .addComponent(this.barGraph, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(this.dotGraph, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE, true) - .addComponent(this.rainbow, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(this.triangleMesh, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE, true) - .addComponent(this.colorCircle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(this.hoops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE, true) - .addComponent(this.disparity, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(this.spiral, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE, true) - .addComponent(this.disparityDots, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(this.spiralDots, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addContainerGap(18, Short.MAX_VALUE)) - ); + .addGap(7) + .addComponent(jLabel1) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(barGraph) + .addComponent(dotGraph)) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(rainbow) + .addComponent(triangleMesh)) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(colorCircle) + .addComponent(hoops)) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(disparity) + .addComponent(spiral)) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(disparityDots) + .addComponent(spiralDots)) + .addPreferredGap(ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(sineWave) + .addComponent(waveDots)) + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + getContentPane().setLayout(layout); pack(); }// //GEN-END:initComponents @@ -228,6 +253,7 @@ private void setAllFieldsFalse(){ ArrayVisualizer.togglePixels(false); ArrayVisualizer.toggleRainbow(false); ArrayVisualizer.toggleSpiral(false); + ArrayVisualizer.toggleWave(false); } private void barGraphActionPerformed(java.awt.event.ActionEvent evt) { @@ -306,6 +332,21 @@ private void spiralDotsActionPerformed(java.awt.event.ActionEvent evt) { UtilFrame.jButton2ResetText(); dispose(); } + private void sineWaveActionPerformed(java.awt.event.ActionEvent evt) { + setAllFieldsFalse(); + ArrayVisualizer.setVisual(VisualStyles.BARS); + ArrayVisualizer.toggleWave(true); + UtilFrame.jButton2ResetText(); + dispose(); + } + private void waveDotsActionPerformed(java.awt.event.ActionEvent evt) { + setAllFieldsFalse(); + ArrayVisualizer.setVisual(VisualStyles.PIXELS); + ArrayVisualizer.togglePixels(true); + ArrayVisualizer.toggleWave(true); + UtilFrame.jButton2ResetText(); + dispose(); + } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton barGraph; @@ -318,7 +359,7 @@ private void spiralDotsActionPerformed(java.awt.event.ActionEvent evt) { private javax.swing.JButton disparityDots; private javax.swing.JButton rainbow; private javax.swing.JButton hoops; + private javax.swing.JButton sineWave; + private javax.swing.JButton waveDots; private javax.swing.JLabel jLabel1; - // End of variables declaration//GEN-END:variables - } \ No newline at end of file diff --git a/src/sorts/BogoBogoSort.java b/src/sorts/BogoBogoSort.java new file mode 100644 index 00000000..4445add5 --- /dev/null +++ b/src/sorts/BogoBogoSort.java @@ -0,0 +1,41 @@ +package sorts; + +import templates.BogoSorting; + +public final class BogoBogoSort extends BogoSorting { + public BogoBogoSort(utils.Delays delayOps, utils.Highlights markOps, utils.Reads readOps, utils.Writes writeOps) { + super(delayOps, markOps, readOps, writeOps); + + this.setSortPromptID("Bogobogo"); + this.setRunAllID("Bogobogo Sort"); + this.setReportSortID("Bogobogosort"); + this.setCategory("Distributive Sorts"); + this.isComparisonBased(false); //Comparisons are not used to swap elements + this.isBucketSort(false); + this.isRadixSort(false); + this.isUnreasonablySlow(true); + this.setUnreasonableLimit(8); + this.isBogoSort(true); + } + + @Override + public void runSort(int[] array, int currentLength, int bucketCount) { + int bogoLength = 2; + boolean arrayNotSorted = true; + + while(arrayNotSorted) { + if(bogoIsSorted(array, bogoLength)) { + if(bogoLength == currentLength) { + arrayNotSorted = false; + } + else { + bogoLength++; + } + } + else { + bogoLength = 2; + } + if(arrayNotSorted) bogoSwap(array, bogoLength, 0); + } + } +} \ No newline at end of file diff --git a/src/templates/BogoSorting.java b/src/templates/BogoSorting.java index 52480dc1..55ae58d9 100644 --- a/src/templates/BogoSorting.java +++ b/src/templates/BogoSorting.java @@ -37,12 +37,12 @@ protected BogoSorting(Delays delayOps, Highlights markOps, Reads readOps, Writes } private static int randomPosition(int length, int offset) { - return (int) ((Math.random() * (length - offset)) + offset); + return (int) (Math.random() * (length - offset)); } protected void bogoSwap(int[] array, int length, int offset){ for(int i = offset; i < length; i++) { - Writes.swap(array, i, BogoSorting.randomPosition(length, offset), 0, true, false); + Writes.swap(array, i, BogoSorting.randomPosition(length, i) + i, 0, true, false); } } diff --git a/src/templates/MultipleSortThread.java b/src/templates/MultipleSortThread.java index 55ee4a24..141ac12c 100644 --- a/src/templates/MultipleSortThread.java +++ b/src/templates/MultipleSortThread.java @@ -59,8 +59,14 @@ protected synchronized void runIndividualSort(Sort sort, int bucketCount, int[] protected abstract void executeSortList(int[] array) throws Exception; protected abstract void runThread(int[] array, int current, int total, boolean runAllActive) throws Exception; - public abstract void reportCategorySorts(int[] array) throws Exception; - public abstract void reportAllSorts(int[] array, int current, int total) throws Exception; + + public synchronized void reportCategorySorts(int[] array) throws Exception { + this.runThread(array, 0, 0, false); + } + + public synchronized void reportAllSorts(int[] array, int current, int total) throws Exception { + this.runThread(array, current, total, true); + } public int getSortCount() { return this.sortCount; diff --git a/src/templates/Visual.java b/src/templates/Visual.java new file mode 100644 index 00000000..a8e35fd6 --- /dev/null +++ b/src/templates/Visual.java @@ -0,0 +1,128 @@ +package templates; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; + +import main.ArrayVisualizer; +import utils.Highlights; +import utils.Renderer; + +public abstract class Visual { + protected Graphics2D mainRender; + protected Graphics2D extraRender; + + public Visual(ArrayVisualizer ArrayVisualizer) { + this.updateRender(ArrayVisualizer); + } + + public void updateRender(ArrayVisualizer ArrayVisualizer) { + this.mainRender = ArrayVisualizer.getMainRender(); + this.extraRender = ArrayVisualizer.getExtraRender(); + } + + public static Color getIntColor(int i, int length) { + return Color.getHSBColor(((float) i / length), 1.0F, 0.8F); + } + + public static void markBar(Graphics2D bar, boolean color, boolean rainbow, boolean analysis) { + if(color || rainbow) { + /* + if(analysis) bar.setColor(Color.WHITE); + else bar.setColor(Color.BLACK); + */ + if(analysis) bar.setColor(Color.LIGHT_GRAY); + else bar.setColor(Color.WHITE); + } + else if(analysis) bar.setColor(Color.BLUE); + else bar.setColor(Color.RED); + } + private static void markBarFancy(Graphics2D bar, boolean color, boolean rainbow) { + if(!color && !rainbow) bar.setColor(Color.RED); + else bar.setColor(Color.BLACK); + } + + public static void lineMark(Graphics2D line, double width, boolean color, boolean analysis) { + line.setStroke(new BasicStroke((float) (9f * (width / 1280f)))); + if(color) line.setColor(Color.BLACK); + else if(analysis) line.setColor(Color.BLUE); + else line.setColor(Color.RED); + } + //TODO: Change name to markLineFancy + public static void lineFancy(Graphics2D line, double width) { + line.setColor(Color.GREEN); + line.setStroke(new BasicStroke((float) (9f * (width / 1280f)))); + } + //TODO: Change name to clearLine + public static void lineClear(Graphics2D line, boolean color, int[] array, int i, int length, double width) { + if(color) line.setColor(getIntColor(array[i], length)); + else line.setColor(Color.WHITE); + line.setStroke(new BasicStroke((float) (3f * (width / 1280f)))); + } + + public static void setRectColor(Graphics2D rect, boolean color, boolean analysis) { + if(color) rect.setColor(Color.WHITE); + else if(analysis) rect.setColor(Color.BLUE); + else rect.setColor(Color.RED); + } + + @SuppressWarnings("fallthrough") + //The longer the array length, the more bars marked. Makes the visual easier to see when bars are thinner. + public static void colorMarkedBars(int logOfLen, int index, Highlights Highlights, Graphics2D mainRender, boolean colorEnabled, boolean rainbowEnabled, boolean analysis) { + switch(logOfLen) { + case 14: if(Highlights.containsPosition(index - 10) + || Highlights.containsPosition(index - 9) + || Highlights.containsPosition(index - 8)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); + case 13: if(Highlights.containsPosition(index - 7) + || Highlights.containsPosition(index - 6) + || Highlights.containsPosition(index - 5)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); + case 12: if(Highlights.containsPosition(index - 4) + || Highlights.containsPosition(index - 3)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); + case 11: if(Highlights.containsPosition(index - 2)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); + case 10: if(Highlights.containsPosition(index - 1)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); + default: if(Highlights.containsPosition(index)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); + } + } + + @SuppressWarnings("fallthrough") + public static void drawFancyFinish(int logOfLen, int index, int position, Graphics2D mainRender, boolean colorEnabled, boolean rainbowEnabled) { + switch(logOfLen) { + case 14: if(index == position - 13) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + case 13: if(index == position - 12) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + case 12: if(index == position - 11) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + case 11: if(index == position - 10) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + case 10: if(index == position - 9) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + case 9: if(index == position - 8) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + case 8: if(index == position - 7) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + case 7: if(index == position - 6) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + case 6: if(index == position - 5) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + case 5: if(index == position - 4) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + case 4: if(index == position - 3) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + case 3: if(index == position - 2) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + case 2: if(index == position - 1) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + default: if(index == position) markBarFancy(mainRender, colorEnabled, rainbowEnabled); + } + } + + @SuppressWarnings("fallthrough") + public static void drawFancyFinishLine(int logOfLen, int index, int position, Graphics2D mainRender, double width, boolean colorEnabled) { + switch(logOfLen) { + case 14: if(index == position - 13) lineMark(mainRender, width, colorEnabled, false); + case 13: if(index == position - 12) lineMark(mainRender, width, colorEnabled, false); + case 12: if(index == position - 11) lineMark(mainRender, width, colorEnabled, false); + case 11: if(index == position - 10) lineMark(mainRender, width, colorEnabled, false); + case 10: if(index == position - 9) lineMark(mainRender, width, colorEnabled, false); + case 9: if(index == position - 8) lineMark(mainRender, width, colorEnabled, false); + case 8: if(index == position - 7) lineMark(mainRender, width, colorEnabled, false); + case 7: if(index == position - 6) lineMark(mainRender, width, colorEnabled, false); + case 6: if(index == position - 5) lineMark(mainRender, width, colorEnabled, false); + case 5: if(index == position - 4) lineMark(mainRender, width, colorEnabled, false); + case 4: if(index == position - 3) lineMark(mainRender, width, colorEnabled, false); + case 3: if(index == position - 2) lineMark(mainRender, width, colorEnabled, false); + case 2: if(index == position - 1) lineMark(mainRender, width, colorEnabled, false); + default: if(index == position) lineMark(mainRender, width, colorEnabled, false); + } + } + + public abstract void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights); +} \ No newline at end of file diff --git a/src/threads/RunConcurrentSorts.java b/src/threads/RunConcurrentSorts.java index 9259c26d..a70ac38d 100644 --- a/src/threads/RunConcurrentSorts.java +++ b/src/threads/RunConcurrentSorts.java @@ -109,14 +109,4 @@ public void run() { ArrayVisualizer.runSortingThread(); } - - @Override - public synchronized void reportCategorySorts(int[] array) throws Exception { - this.runThread(array, 0, 0, false); - } - - @Override - public synchronized void reportAllSorts(int[] array, int current, int total) throws Exception { - this.runThread(array, current, total, true); - } } \ No newline at end of file diff --git a/src/threads/RunDistributionSorts.java b/src/threads/RunDistributionSorts.java index 2a53a0d6..c8279716 100644 --- a/src/threads/RunDistributionSorts.java +++ b/src/threads/RunDistributionSorts.java @@ -138,14 +138,4 @@ public void run() { }); ArrayVisualizer.runSortingThread(); } - - @Override - public synchronized void reportCategorySorts(int[] array) throws Exception { - this.runThread(array, 0, 0, false); - } - - @Override - public synchronized void reportAllSorts(int[] array, int current, int total) throws Exception { - this.runThread(array, current, total, true); - } } \ No newline at end of file diff --git a/src/threads/RunExchangeSorts.java b/src/threads/RunExchangeSorts.java index 77ebf31f..5926f30c 100644 --- a/src/threads/RunExchangeSorts.java +++ b/src/threads/RunExchangeSorts.java @@ -141,14 +141,4 @@ public void run() { }); ArrayVisualizer.runSortingThread(); } - - @Override - public synchronized void reportCategorySorts(int[] array) throws Exception { - this.runThread(array, 0, 0, false); - } - - @Override - public synchronized void reportAllSorts(int[] array, int current, int total) throws Exception { - this.runThread(array, current, total, true); - } } \ No newline at end of file diff --git a/src/threads/RunHybridSorts.java b/src/threads/RunHybridSorts.java index ed1641aa..3ca2a196 100644 --- a/src/threads/RunHybridSorts.java +++ b/src/threads/RunHybridSorts.java @@ -141,14 +141,4 @@ public void run() { }); ArrayVisualizer.runSortingThread(); } - - @Override - public synchronized void reportCategorySorts(int[] array) throws Exception { - this.runThread(array, 0, 0, false); - } - - @Override - public synchronized void reportAllSorts(int[] array, int current, int total) throws Exception { - this.runThread(array, current, total, true); - } } \ No newline at end of file diff --git a/src/threads/RunImpracticalSorts.java b/src/threads/RunImpracticalSorts.java index c9fa2e86..69da1159 100644 --- a/src/threads/RunImpracticalSorts.java +++ b/src/threads/RunImpracticalSorts.java @@ -125,14 +125,4 @@ public void run() { }); ArrayVisualizer.runSortingThread(); } - - @Override - public synchronized void reportCategorySorts(int[] array) throws Exception { - this.runThread(array, 0, 0, false); - } - - @Override - public synchronized void reportAllSorts(int[] array, int current, int total) throws Exception { - this.runThread(array, current, total, true); - } } \ No newline at end of file diff --git a/src/threads/RunInsertionSorts.java b/src/threads/RunInsertionSorts.java index a7944ed6..0a850f5e 100644 --- a/src/threads/RunInsertionSorts.java +++ b/src/threads/RunInsertionSorts.java @@ -105,14 +105,4 @@ public void run() { }); ArrayVisualizer.runSortingThread(); } - - @Override - public synchronized void reportCategorySorts(int[] array) throws Exception { - this.runThread(array, 0, 0, false); - } - - @Override - public synchronized void reportAllSorts(int[] array, int current, int total) throws Exception { - this.runThread(array, current, total, true); - } } \ No newline at end of file diff --git a/src/threads/RunMergeSorts.java b/src/threads/RunMergeSorts.java index 689a5af0..e52a26c9 100644 --- a/src/threads/RunMergeSorts.java +++ b/src/threads/RunMergeSorts.java @@ -100,14 +100,4 @@ public void run() { }); ArrayVisualizer.runSortingThread(); } - - @Override - public synchronized void reportCategorySorts(int[] array) throws Exception { - this.runThread(array, 0, 0, false); - } - - @Override - public synchronized void reportAllSorts(int[] array, int current, int total) throws Exception { - this.runThread(array, current, total, true); - } } \ No newline at end of file diff --git a/src/threads/RunMiscellaneousSorts.java b/src/threads/RunMiscellaneousSorts.java index 024b0013..3f782a90 100644 --- a/src/threads/RunMiscellaneousSorts.java +++ b/src/threads/RunMiscellaneousSorts.java @@ -88,14 +88,4 @@ public void run() { }); ArrayVisualizer.runSortingThread(); } - - @Override - public synchronized void reportCategorySorts(int[] array) throws Exception { - this.runThread(array, 0, 0, false); - } - - @Override - public synchronized void reportAllSorts(int[] array, int current, int total) throws Exception { - this.runThread(array, current, total, true); - } } \ No newline at end of file diff --git a/src/threads/RunSelectionSorts.java b/src/threads/RunSelectionSorts.java index 7f03ea00..16b76546 100644 --- a/src/threads/RunSelectionSorts.java +++ b/src/threads/RunSelectionSorts.java @@ -128,14 +128,4 @@ public void run() { }); ArrayVisualizer.runSortingThread(); } - - @Override - public synchronized void reportCategorySorts(int[] array) throws Exception { - this.runThread(array, 0, 0, false); - } - - @Override - public synchronized void reportAllSorts(int[] array, int current, int total) throws Exception { - this.runThread(array, current, total, true); - } } \ No newline at end of file diff --git a/src/utils/Renderer.java b/src/utils/Renderer.java index 87556592..a46fa377 100644 --- a/src/utils/Renderer.java +++ b/src/utils/Renderer.java @@ -1,15 +1,8 @@ package utils; import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; import main.ArrayVisualizer; -import visuals.Bars; -import visuals.Circular; -import visuals.Hoops; -import visuals.Mesh; -import visuals.Pixels; import visuals.VisualStyles; /* @@ -38,6 +31,8 @@ of this software and associated documentation files (the "Software"), to deal * */ +// TODO: Many of these methods should exist solely in visual classes + final class WindowState { private boolean windowUpdated; private boolean windowResized; @@ -57,12 +52,6 @@ public boolean resized() { } final public class Renderer { - private Bars Bars; - private Circular Circular; - private Hoops Hoops; - private Mesh Mesh; - private Pixels Pixels; - private volatile double xscl; //TODO: Change to xScale/yScale private volatile double yscl; @@ -71,8 +60,6 @@ final public class Renderer { private int linkedpixdrawx; //TODO: Change names private int linkedpixdrawy; - private int frames; - private int doth; //TODO: Change names private int dotw; private int dots; //TODO: Change name to dotDims/dotDimensions @@ -118,27 +105,24 @@ public void setLineY(int y) { this.linkedpixdrawy = y; } - public void updateGraphics(ArrayVisualizer ArrayVisualizer) { + public static void createRenders(ArrayVisualizer ArrayVisualizer) { ArrayVisualizer.createVolatileImage(); ArrayVisualizer.setMainRender(); ArrayVisualizer.setExtraRender(); } - public void initializeVisuals(ArrayVisualizer ArrayVisualizer, VisualStyles VisualStyles) { - this.Bars = new Bars(); - this.Circular = new Circular(); - this.Hoops = new Hoops(); - this.Mesh = new Mesh(); - this.Pixels = new Pixels(); - - this.frames = 0; - this.updateGraphics(ArrayVisualizer); + public static void initializeVisuals(ArrayVisualizer ArrayVisualizer) { + Renderer.createRenders(ArrayVisualizer); ArrayVisualizer.updateFontSize(); ArrayVisualizer.repositionFrames(); } + public static void updateGraphics(ArrayVisualizer ArrayVisualizer) { + Renderer.createRenders(ArrayVisualizer); + ArrayVisualizer.updateVisuals(); + } - private WindowState checkWindowResizeAndReposition(ArrayVisualizer ArrayVisualizer) { + private static WindowState checkWindowResizeAndReposition(ArrayVisualizer ArrayVisualizer) { boolean windowUpdate = false; boolean windowResize = false; @@ -174,7 +158,7 @@ public void updateVisuals(ArrayVisualizer ArrayVisualizer) { if(WindowState.resized()) { ArrayVisualizer.updateDimensions(); - this.updateGraphics(ArrayVisualizer); + updateGraphics(ArrayVisualizer); } ArrayVisualizer.updateFontSize(); @@ -193,8 +177,6 @@ public void updateVisuals(ArrayVisualizer ArrayVisualizer) { this.linkedpixdrawx = 0; this.linkedpixdrawy = 0; - this.frames++; - this.dotw = (int) (2 * (ArrayVisualizer.currentWidth() / 640.0)); this.doth = (int) (2 * (ArrayVisualizer.currentHeight() / 480.0)); this.dots = (this.dotw + this.doth) / 2; //TODO: Does multiply/divide by 2 like this cancel out?? @@ -202,192 +184,7 @@ public void updateVisuals(ArrayVisualizer ArrayVisualizer) { ArrayVisualizer.resetMainStroke(); } - public Color getIntColor(int i, int length) { - return Color.getHSBColor(((float) i / length), 1.0F, 0.8F); - } - - public void markBar(Graphics2D bar, boolean color, boolean rainbow, boolean analysis) { - if(color || rainbow) { - if(analysis) bar.setColor(Color.WHITE); - else bar.setColor(Color.BLACK); - } - else if(analysis) bar.setColor(Color.BLUE); - else bar.setColor(Color.RED); - } - private void markBarFancy(Graphics2D bar, boolean color, boolean rainbow) { - if(!color && !rainbow) bar.setColor(Color.RED); - else bar.setColor(Color.BLACK); - } - - public void lineMark(Graphics2D line, double width, boolean color, boolean analysis) { - line.setStroke(new BasicStroke((float) (9f * (width / 1280f)))); - if(color) line.setColor(Color.BLACK); - else if(analysis) line.setColor(Color.BLUE); - else line.setColor(Color.RED); - } - //TODO: Change name to markLineFancy - public void lineFancy(Graphics2D line, double width) { - line.setColor(Color.GREEN); - line.setStroke(new BasicStroke((float) (9f * (width / 1280f)))); - } - //TODO: Change name to clearLine - public void lineClear(Graphics2D line, boolean color, int[] array, int i, int length, double width) { - if(color) line.setColor(getIntColor(array[i], length)); - else line.setColor(Color.WHITE); - line.setStroke(new BasicStroke((float) (3f * (width / 1280f)))); - } - - public void setRectColor(Graphics2D rect, boolean color, boolean analysis) { - if(color) rect.setColor(Color.WHITE); - else if(analysis) rect.setColor(Color.BLUE); - else rect.setColor(Color.RED); - } - - @SuppressWarnings("fallthrough") - //The longer the array length, the more bars marked. Makes the visual easier to see when bars are thinner. - public void colorMarkedBars(int logOfLen, int index, Highlights Highlights, Graphics2D mainRender, boolean colorEnabled, boolean rainbowEnabled, boolean analysis) { - switch(logOfLen) { - case 14: if(Highlights.containsPosition(index - 10) - || Highlights.containsPosition(index - 9) - || Highlights.containsPosition(index - 8)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); - case 13: if(Highlights.containsPosition(index - 7) - || Highlights.containsPosition(index - 6) - || Highlights.containsPosition(index - 5)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); - case 12: if(Highlights.containsPosition(index - 4) - || Highlights.containsPosition(index - 3)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); - case 11: if(Highlights.containsPosition(index - 2)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); - case 10: if(Highlights.containsPosition(index - 1)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); - default: if(Highlights.containsPosition(index)) markBar(mainRender, colorEnabled, rainbowEnabled, analysis); - } - } - - @SuppressWarnings("fallthrough") - public void markHoops(int logOfLen, int index, Highlights Highlights, Graphics2D mainRender) { - switch(logOfLen) { - case 14: if(Highlights.containsPosition(index - 13)) mainRender.setColor(Color.BLACK); - case 13: if(Highlights.containsPosition(index - 12)) mainRender.setColor(Color.BLACK); - case 12: if(Highlights.containsPosition(index - 11)) mainRender.setColor(Color.BLACK); - case 11: if(Highlights.containsPosition(index - 10)) mainRender.setColor(Color.BLACK); - case 10: if(Highlights.containsPosition(index - 9)) mainRender.setColor(Color.BLACK); - case 9: if(Highlights.containsPosition(index - 8)) mainRender.setColor(Color.BLACK); - case 8: if(Highlights.containsPosition(index - 7)) mainRender.setColor(Color.BLACK); - case 7: if(Highlights.containsPosition(index - 6)) mainRender.setColor(Color.BLACK); - case 6: if(Highlights.containsPosition(index - 5)) mainRender.setColor(Color.BLACK); - case 5: if(Highlights.containsPosition(index - 4)) mainRender.setColor(Color.BLACK); - case 4: if(Highlights.containsPosition(index - 3)) mainRender.setColor(Color.BLACK); - case 3: if(Highlights.containsPosition(index - 2)) mainRender.setColor(Color.BLACK); - case 2: if(Highlights.containsPosition(index - 1)) mainRender.setColor(Color.BLACK); - default: if(Highlights.containsPosition(index)) mainRender.setColor(Color.BLACK); - } - } - - @SuppressWarnings("fallthrough") - public void drawFancyFinish(int logOfLen, int index, int position, Graphics2D mainRender, boolean colorEnabled, boolean rainbowEnabled) { - switch(logOfLen) { - case 14: if(index == position - 13) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - case 13: if(index == position - 12) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - case 12: if(index == position - 11) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - case 11: if(index == position - 10) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - case 10: if(index == position - 9) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - case 9: if(index == position - 8) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - case 8: if(index == position - 7) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - case 7: if(index == position - 6) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - case 6: if(index == position - 5) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - case 5: if(index == position - 4) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - case 4: if(index == position - 3) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - case 3: if(index == position - 2) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - case 2: if(index == position - 1) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - default: if(index == position) markBarFancy(mainRender, colorEnabled, rainbowEnabled); - } - } - - @SuppressWarnings("fallthrough") - public void drawFancyFinishLine(int logOfLen, int index, int position, Graphics2D mainRender, double width, boolean colorEnabled) { - switch(logOfLen) { - case 14: if(index == position - 13) lineMark(mainRender, width, colorEnabled, false); - case 13: if(index == position - 12) lineMark(mainRender, width, colorEnabled, false); - case 12: if(index == position - 11) lineMark(mainRender, width, colorEnabled, false); - case 11: if(index == position - 10) lineMark(mainRender, width, colorEnabled, false); - case 10: if(index == position - 9) lineMark(mainRender, width, colorEnabled, false); - case 9: if(index == position - 8) lineMark(mainRender, width, colorEnabled, false); - case 8: if(index == position - 7) lineMark(mainRender, width, colorEnabled, false); - case 7: if(index == position - 6) lineMark(mainRender, width, colorEnabled, false); - case 6: if(index == position - 5) lineMark(mainRender, width, colorEnabled, false); - case 5: if(index == position - 4) lineMark(mainRender, width, colorEnabled, false); - case 4: if(index == position - 3) lineMark(mainRender, width, colorEnabled, false); - case 3: if(index == position - 2) lineMark(mainRender, width, colorEnabled, false); - case 2: if(index == position - 1) lineMark(mainRender, width, colorEnabled, false); - default: if(index == position) lineMark(mainRender, width, colorEnabled, false); - } - } - - @SuppressWarnings("fallthrough") - public void drawFancyFinishHoops(int logOfLen, int index, int position, Graphics2D mainRender) { - switch(logOfLen) { - case 14: if(index == position - 13) mainRender.setColor(Color.BLACK); - case 13: if(index == position - 12) mainRender.setColor(Color.BLACK); - case 12: if(index == position - 11) mainRender.setColor(Color.BLACK); - case 11: if(index == position - 10) mainRender.setColor(Color.BLACK); - case 10: if(index == position - 9) mainRender.setColor(Color.BLACK); - case 9: if(index == position - 8) mainRender.setColor(Color.BLACK); - case 8: if(index == position - 7) mainRender.setColor(Color.BLACK); - case 7: if(index == position - 6) mainRender.setColor(Color.BLACK); - case 6: if(index == position - 5) mainRender.setColor(Color.BLACK); - case 5: if(index == position - 4) mainRender.setColor(Color.BLACK); - case 4: if(index == position - 3) mainRender.setColor(Color.BLACK); - case 3: if(index == position - 2) mainRender.setColor(Color.BLACK); - case 2: if(index == position - 1) mainRender.setColor(Color.BLACK); - default: if(index == position) mainRender.setColor(Color.BLACK); - } - } - - public int getTriangleHeight(int length, double height) { - switch(length) { - case 2: height *= 20; break; - case 4: height *= 13; break; - case 8: height *= 8; break; - case 16: - case 32: height *= 4.4; break; - case 64: height *= 2.3; break; - case 128: height *= 2.35; break; - case 256: height *= 1.22; break; - default: height *= 1; - } - - return (int) height; - } - - public int getTrianglesPerRow(int length, int trianglesPerColumn) { - int trianglesPerRow; - - switch(length) { - case 32: - case 64: trianglesPerRow = 4; break; - case 128: - case 256: trianglesPerRow = 8; break; - default: trianglesPerRow = Math.max(length / trianglesPerColumn, 2); - } - - return trianglesPerRow; - } - - public void drawCircle(int[] array, ArrayVisualizer ArrayVisualizer, Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { - Circular.drawVisual(array, ArrayVisualizer, this, mainRender, extraRender, Highlights); - } - public void drawHoops(int[] array, ArrayVisualizer ArrayVisualizer, Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { - Hoops.drawVisual(array, ArrayVisualizer, this, mainRender, extraRender, Highlights); - } - public void drawMesh(int[] array, ArrayVisualizer ArrayVisualizer, Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { - Mesh.drawVisual(array, ArrayVisualizer, this, mainRender, extraRender, Highlights); - } - public void drawBars(int[] array, ArrayVisualizer ArrayVisualizer, Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { - Bars.drawVisual(array, ArrayVisualizer, this, mainRender, extraRender, Highlights); - } - public void drawPixels(int[] array, ArrayVisualizer ArrayVisualizer, Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { - Pixels.drawVisual(array, ArrayVisualizer, this, mainRender, extraRender, Highlights); - } - - public void drawVisual(VisualStyles VisualStyles, int[] array, ArrayVisualizer ArrayVisualizer, Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { - VisualStyles.drawVisual(array, ArrayVisualizer, this, mainRender, extraRender, Highlights); + public void drawVisual(VisualStyles VisualStyles, int[] array, ArrayVisualizer ArrayVisualizer, Highlights Highlights) { + VisualStyles.drawVisual(array, ArrayVisualizer, this, Highlights); } } \ No newline at end of file diff --git a/src/visuals/Bars.java b/src/visuals/Bars.java index 0270a778..eb4a9ee2 100644 --- a/src/visuals/Bars.java +++ b/src/visuals/Bars.java @@ -1,11 +1,9 @@ package visuals; -import java.awt.BasicStroke; import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Stroke; import main.ArrayVisualizer; +import templates.Visual; import utils.Highlights; import utils.Renderer; @@ -35,28 +33,33 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class Bars { - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { +final public class Bars extends Visual { + public Bars(ArrayVisualizer ArrayVisualizer) { + super(ArrayVisualizer); + } + + @Override + public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { for(int i = 0; i < ArrayVisualizer.getCurrentLength(); i++){ if(Highlights.fancyFinishActive()) { if(i < Highlights.getFancyFinishPosition()) { - mainRender.setColor(Color.GREEN); + this.mainRender.setColor(Color.GREEN); } else if(ArrayVisualizer.rainbowEnabled() || ArrayVisualizer.colorEnabled()) { - mainRender.setColor(Renderer.getIntColor(array[i], ArrayVisualizer.getCurrentLength())); + this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); } - else mainRender.setColor(Color.WHITE); + else this.mainRender.setColor(Color.WHITE); - Renderer.drawFancyFinish(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights.getFancyFinishPosition(), mainRender, ArrayVisualizer.colorEnabled(), ArrayVisualizer.rainbowEnabled()); + drawFancyFinish(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights.getFancyFinishPosition(), this.mainRender, ArrayVisualizer.colorEnabled(), ArrayVisualizer.rainbowEnabled()); } else { if(ArrayVisualizer.rainbowEnabled() || ArrayVisualizer.colorEnabled()) { - mainRender.setColor(Renderer.getIntColor(array[i], ArrayVisualizer.getCurrentLength())); + this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); } - else mainRender.setColor(Color.WHITE); + else this.mainRender.setColor(Color.WHITE); if(ArrayVisualizer.getCurrentLength() != 2) { - Renderer.colorMarkedBars(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights, mainRender, ArrayVisualizer.colorEnabled(), ArrayVisualizer.rainbowEnabled(), ArrayVisualizer.analysisEnabled()); + colorMarkedBars(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights, this.mainRender, ArrayVisualizer.colorEnabled(), ArrayVisualizer.rainbowEnabled(), ArrayVisualizer.analysisEnabled()); } } /* @@ -72,11 +75,18 @@ else if(ArrayVisualizer.rainbowEnabled() || ArrayVisualizer.colorEnabled()) { if(ArrayVisualizer.rainbowEnabled()) { if(width > 0) { - mainRender.fillRect(Renderer.getOffset() + 20, 0, width, ArrayVisualizer.windowHeight()); + this.mainRender.fillRect(Renderer.getOffset() + 20, 0, width, ArrayVisualizer.windowHeight()); } Renderer.setOffset(Renderer.getOffset() + width); } + else if(ArrayVisualizer.waveEnabled()) { + if(width > 0) { + y = (int) ((ArrayVisualizer.windowHeight() / 4) * Math.sin((2 * Math.PI * ((double) array[i] / ArrayVisualizer.getCurrentLength()))) + ArrayVisualizer.windowHalfHeight()); + this.mainRender.fillRect(Renderer.getOffset() + 20, y, width, 20); + } + Renderer.setOffset(Renderer.getOffset() + width); + } else { if(width > 0) { /* @@ -85,9 +95,11 @@ else if(ArrayVisualizer.rainbowEnabled() || ArrayVisualizer.colorEnabled()) { gap = 5; } */ - + y = (int) (((ArrayVisualizer.windowHeight() - 20)) - (array[i] + 1) * Renderer.getYScale()); - mainRender.fillRect(Renderer.getOffset() + 20, y /*- markHeight*/, width /*- gap*/, (int) ((array[i] + 1) * Renderer.getYScale()) /*+ markHeight*/); + mainRender.fillRect(Renderer.getOffset() + 20, y, width, (int) ((array[i] + 1) * Renderer.getYScale())); + + //mainRender.fillRect(Renderer.getOffset() + 20, y /*- markHeight*/, width /*- gap*/, (int) ((array[i] + 1) * Renderer.getYScale()) /*+ markHeight*/); /* double thickness = 1; diff --git a/src/visuals/Circular.java b/src/visuals/Circular.java index 49eb5050..753a4d96 100644 --- a/src/visuals/Circular.java +++ b/src/visuals/Circular.java @@ -2,10 +2,10 @@ import java.awt.BasicStroke; import java.awt.Color; -import java.awt.Graphics2D; import java.awt.Polygon; import main.ArrayVisualizer; +import templates.Visual; import utils.Highlights; import utils.Renderer; @@ -35,11 +35,13 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class Circular { - final private double CIRC_HEIGHT_RATIO = (9/6.0843731432) * (16/9d); - final private double CIRC_WIDTH_RATIO = (16/6.0843731432) * (16/9d); +final public class Circular extends Visual { + final private static double CIRC_HEIGHT_RATIO = (9/6.0843731432) * (16/9d); + final private static double CIRC_WIDTH_RATIO = (16/6.0843731432) * (16/9d); - private boolean drawRect; + public Circular(ArrayVisualizer ArrayVisualizer) { + super(ArrayVisualizer); + } // The reason we use cosine with height (expressed in terms of y) and sine with width (expressed in terms of x) is because our circles are rotated 90 degrees. // After that rotation, sine is on the x-axis and cosine is on the y-axis. @@ -55,27 +57,29 @@ private static double getCosOfDegrees(double d, int halfCirc) { return Math.cos((d * Math.PI) / halfCirc); } - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { + @Override + public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { for(int i = 0; i < ArrayVisualizer.getCurrentLength(); i++){ if(i < Highlights.getFancyFinishPosition()) { - mainRender.setColor(Color.getHSBColor((1f/3f), 1f, 0.8f)); + this.mainRender.setColor(Color.getHSBColor((1f/3f), 1f, 0.8f)); } else if(!ArrayVisualizer.colorEnabled() && (ArrayVisualizer.spiralEnabled() || ArrayVisualizer.distanceEnabled() || ArrayVisualizer.pixelsEnabled())) { - mainRender.setColor(Color.WHITE); + this.mainRender.setColor(Color.WHITE); } - else mainRender.setColor(Renderer.getIntColor(array[i], ArrayVisualizer.getCurrentLength())); + else this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); if(Highlights.fancyFinishActive()) { - Renderer.drawFancyFinish(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights.getFancyFinishPosition(), mainRender, ArrayVisualizer.rainbowEnabled(), ArrayVisualizer.colorEnabled()); + drawFancyFinish(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights.getFancyFinishPosition(), this.mainRender, ArrayVisualizer.rainbowEnabled(), ArrayVisualizer.colorEnabled()); } else { + /* if(ArrayVisualizer.pointerActive()) { if(Highlights.containsPosition(i)) { if(ArrayVisualizer.analysisEnabled()) { - extraRender.setColor(Color.GRAY); + this.extraRender.setColor(Color.GRAY); } else { - extraRender.setColor(Color.WHITE); + this.extraRender.setColor(Color.WHITE); } //Create new Polygon for the pointer @@ -114,14 +118,14 @@ else if(!ArrayVisualizer.colorEnabled() && (ArrayVisualizer.spiralEnabled() || A pointer.addPoint(pointerXValues[j], pointerYValues[j]); } - extraRender.fillPolygon(pointer); + this.extraRender.fillPolygon(pointer); } } - else if(ArrayVisualizer.getCurrentLength() != 2){ - Renderer.colorMarkedBars(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights, mainRender, ArrayVisualizer.rainbowEnabled(), ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); + else */ if(ArrayVisualizer.getCurrentLength() != 2){ + colorMarkedBars(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights, this.mainRender, ArrayVisualizer.rainbowEnabled(), ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); } } - + if(ArrayVisualizer.distanceEnabled()) { //TODO: Rewrite this abomination double len = ((ArrayVisualizer.getCurrentLength() / 2d) - Math.min(Math.min(Math.abs(i - array[i]), Math.abs(i - array[i] + ArrayVisualizer.getCurrentLength())), Math.abs(i - array[i] - ArrayVisualizer.getCurrentLength()))) / (ArrayVisualizer.getCurrentLength() / 2d); @@ -134,43 +138,43 @@ else if(ArrayVisualizer.getCurrentLength() != 2){ if(i > 0) { if(Highlights.fancyFinishActive()) { if(i < Highlights.getFancyFinishPosition()) { - Renderer.lineFancy(mainRender, ArrayVisualizer.currentWidth()); + lineFancy(this.mainRender, ArrayVisualizer.currentWidth()); } else { - Renderer.lineClear(mainRender, ArrayVisualizer.colorEnabled(), array, i, ArrayVisualizer.getCurrentLength(), ArrayVisualizer.currentWidth()); + lineClear(this.mainRender, ArrayVisualizer.colorEnabled(), array, i, ArrayVisualizer.getCurrentLength(), ArrayVisualizer.currentWidth()); } - Renderer.drawFancyFinishLine(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights.getFancyFinishPosition(), mainRender, ArrayVisualizer.currentWidth(), ArrayVisualizer.colorEnabled()); + drawFancyFinishLine(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights.getFancyFinishPosition(), this.mainRender, ArrayVisualizer.currentWidth(), ArrayVisualizer.colorEnabled()); } else { if(Highlights.containsPosition(i)) { - Renderer.lineMark(mainRender, ArrayVisualizer.currentWidth(), ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); + lineMark(this.mainRender, ArrayVisualizer.currentWidth(), ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); } - else Renderer.lineClear(mainRender, ArrayVisualizer.colorEnabled(), array, i, ArrayVisualizer.getCurrentLength(), ArrayVisualizer.currentWidth()); + else lineClear(this.mainRender, ArrayVisualizer.colorEnabled(), array, i, ArrayVisualizer.getCurrentLength(), ArrayVisualizer.currentWidth()); } - mainRender.drawLine(linkedpixX, linkedpixY, Renderer.getLineX(), Renderer.getLineY()); + this.mainRender.drawLine(linkedpixX, linkedpixY, Renderer.getLineX(), Renderer.getLineY()); } Renderer.setLineX(linkedpixX); Renderer.setLineY(linkedpixY); } else { + boolean drawRect = false; if(Highlights.containsPosition(i)) { - Renderer.setRectColor(extraRender, ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); + setRectColor(this.extraRender, ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); drawRect = true; } - else drawRect = false; if(drawRect) { - extraRender.setStroke(ArrayVisualizer.getThickStroke()); + this.extraRender.setStroke(ArrayVisualizer.getThickStroke()); if(Highlights.fancyFinishActive()) { - extraRender.fillRect((linkedpixX - Renderer.getDotWidth() / 2) - 10, (linkedpixY - Renderer.getDotHeight() / 2) - 10, Renderer.getDotWidth() + 20, Renderer.getDotHeight() + 20); + this.extraRender.fillRect((linkedpixX - Renderer.getDotWidth() / 2) - 10, (linkedpixY - Renderer.getDotHeight() / 2) - 10, Renderer.getDotWidth() + 20, Renderer.getDotHeight() + 20); } else { - extraRender.drawRect((linkedpixX - Renderer.getDotWidth() / 2) - 10, (linkedpixY - Renderer.getDotHeight() / 2) - 10, Renderer.getDotWidth() + 20, Renderer.getDotHeight() + 20); + this.extraRender.drawRect((linkedpixX - Renderer.getDotWidth() / 2) - 10, (linkedpixY - Renderer.getDotHeight() / 2) - 10, Renderer.getDotWidth() + 20, Renderer.getDotHeight() + 20); } - extraRender.setStroke(new BasicStroke(3f * (ArrayVisualizer.currentWidth() / 1280f))); + this.extraRender.setStroke(new BasicStroke(3f * (ArrayVisualizer.currentWidth() / 1280f))); } - mainRender.fillRect(linkedpixX - Renderer.getDotWidth() / 2, linkedpixY - Renderer.getDotHeight() / 2, Renderer.getDotWidth(), Renderer.getDotHeight()); + this.mainRender.fillRect(linkedpixX - Renderer.getDotWidth() / 2, linkedpixY - Renderer.getDotHeight() / 2, Renderer.getDotWidth(), Renderer.getDotHeight()); } } else { @@ -185,7 +189,7 @@ else if(ArrayVisualizer.getCurrentLength() != 2){ p.addPoint(ArrayVisualizer.windowHalfWidth() + (int) (Circular.getSinOfDegrees(i + 1, ArrayVisualizer.halfCircle()) * (((ArrayVisualizer.currentWidth() - 64) / CIRC_WIDTH_RATIO) * len)), ArrayVisualizer.windowHalfHeight() - (int) (Circular.getCosOfDegrees(i + 1, ArrayVisualizer.halfCircle()) * (((ArrayVisualizer.currentHeight() - 96) / CIRC_HEIGHT_RATIO) * len))); - mainRender.fillPolygon(p); + this.mainRender.fillPolygon(p); } } else if(ArrayVisualizer.spiralEnabled()) { @@ -194,19 +198,19 @@ else if(ArrayVisualizer.spiralEnabled()) { if(i > 0) { if(Highlights.fancyFinishActive()) { if(i < Highlights.getFancyFinishPosition()) { - Renderer.lineFancy(mainRender, ArrayVisualizer.currentWidth()); + lineFancy(this.mainRender, ArrayVisualizer.currentWidth()); } - else Renderer.lineClear(mainRender, ArrayVisualizer.colorEnabled(), array, i, ArrayVisualizer.getCurrentLength(), ArrayVisualizer.currentWidth()); + else lineClear(this.mainRender, ArrayVisualizer.colorEnabled(), array, i, ArrayVisualizer.getCurrentLength(), ArrayVisualizer.currentWidth()); - Renderer.drawFancyFinishLine(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights.getFancyFinishPosition(), mainRender, ArrayVisualizer.currentWidth(), ArrayVisualizer.colorEnabled()); + drawFancyFinishLine(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights.getFancyFinishPosition(), this.mainRender, ArrayVisualizer.currentWidth(), ArrayVisualizer.colorEnabled()); } else { if(Highlights.containsPosition(i)) { - Renderer.lineMark(mainRender, ArrayVisualizer.currentWidth(), ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); + lineMark(this.mainRender, ArrayVisualizer.currentWidth(), ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); } - else Renderer.lineClear(mainRender, ArrayVisualizer.colorEnabled(), array, i, ArrayVisualizer.getCurrentLength(), ArrayVisualizer.currentWidth()); + else lineClear(this.mainRender, ArrayVisualizer.colorEnabled(), array, i, ArrayVisualizer.getCurrentLength(), ArrayVisualizer.currentWidth()); } - mainRender.drawLine(ArrayVisualizer.windowHalfWidth() + (int) (Circular.getSinOfDegrees(i, ArrayVisualizer.halfCircle()) * ((((ArrayVisualizer.windowWidth() - 64) / 3.0) * array[i]) / ArrayVisualizer.getCurrentLength())), + this.mainRender.drawLine(ArrayVisualizer.windowHalfWidth() + (int) (Circular.getSinOfDegrees(i, ArrayVisualizer.halfCircle()) * ((((ArrayVisualizer.windowWidth() - 64) / 3.0) * array[i]) / ArrayVisualizer.getCurrentLength())), ArrayVisualizer.windowHalfHeight() - (int) (Circular.getCosOfDegrees(i, ArrayVisualizer.halfCircle()) * ((((ArrayVisualizer.windowHeight() - 96) / 2.0) * array[i]) / ArrayVisualizer.getCurrentLength())), Renderer.getLineX(), Renderer.getLineY()); @@ -215,32 +219,32 @@ else if(ArrayVisualizer.spiralEnabled()) { Renderer.setLineY(ArrayVisualizer.windowHalfHeight() - (int) (Circular.getCosOfDegrees(i, ArrayVisualizer.halfCircle()) * ((((ArrayVisualizer.windowHeight() - 96) / 2.0) * array[i]) / ArrayVisualizer.getCurrentLength()))); } else { + boolean drawRect = false; if(Highlights.containsPosition(i)) { - Renderer.setRectColor(extraRender, ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); + setRectColor(this.extraRender, ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); drawRect = true; } - else drawRect = false; int rectx = ArrayVisualizer.windowHalfWidth() + (int) (Circular.getSinOfDegrees(i, ArrayVisualizer.halfCircle()) * (((((ArrayVisualizer.windowWidth() - 64) / 3.0) * array[i]) / ArrayVisualizer.getCurrentLength()))); int recty = ArrayVisualizer.windowHalfHeight() - (int) (Circular.getCosOfDegrees(i, ArrayVisualizer.halfCircle()) * (((((ArrayVisualizer.windowHeight() - 96) / 2.0) * array[i]) / ArrayVisualizer.getCurrentLength()))); - mainRender.fillRect(rectx, recty, Renderer.getDotWidth(), Renderer.getDotHeight()); + this.mainRender.fillRect(rectx, recty, Renderer.getDotWidth(), Renderer.getDotHeight()); if(drawRect) { - extraRender.setStroke(ArrayVisualizer.getThickStroke()); + this.extraRender.setStroke(ArrayVisualizer.getThickStroke()); if(Highlights.fancyFinishActive()) { - extraRender.fillRect(rectx - 10, recty - 10, Renderer.getDotWidth() + 20, Renderer.getDotHeight() + 20); + this.extraRender.fillRect(rectx - 10, recty - 10, Renderer.getDotWidth() + 20, Renderer.getDotHeight() + 20); } else { - extraRender.drawRect(rectx - 10, recty - 10, Renderer.getDotWidth() + 20, Renderer.getDotHeight() + 20); + this.extraRender.drawRect(rectx - 10, recty - 10, Renderer.getDotWidth() + 20, Renderer.getDotHeight() + 20); } - extraRender.setStroke(new BasicStroke(3f * (ArrayVisualizer.currentWidth() / 1280f))); + this.extraRender.setStroke(new BasicStroke(3f * (ArrayVisualizer.currentWidth() / 1280f))); } } } else { if(Highlights.containsPosition(i)) { - Renderer.markBar(mainRender, ArrayVisualizer.colorEnabled(), ArrayVisualizer.rainbowEnabled(), ArrayVisualizer.analysisEnabled()); + markBar(this.mainRender, ArrayVisualizer.colorEnabled(), ArrayVisualizer.rainbowEnabled(), ArrayVisualizer.analysisEnabled()); } Polygon p = new Polygon(); @@ -254,7 +258,7 @@ else if(ArrayVisualizer.spiralEnabled()) { p.addPoint(ArrayVisualizer.windowHalfWidth() + (int) (Circular.getSinOfDegrees(i + 1, ArrayVisualizer.halfCircle()) * ((((ArrayVisualizer.windowWidth() - 64) / 3.0) * array[Math.min(i + 1, ArrayVisualizer.getCurrentLength() - 1)]) / ArrayVisualizer.getCurrentLength())), ArrayVisualizer.windowHalfHeight() - (int) (Circular.getCosOfDegrees(i + 1, ArrayVisualizer.halfCircle()) * ((((ArrayVisualizer.windowHeight() - 96) / 2.0) * array[Math.min(i + 1, ArrayVisualizer.getCurrentLength() - 1)]) / ArrayVisualizer.getCurrentLength()))); - mainRender.fillPolygon(p); + this.mainRender.fillPolygon(p); } } else { @@ -269,7 +273,7 @@ else if(ArrayVisualizer.spiralEnabled()) { p.addPoint(ArrayVisualizer.windowHalfWidth() + (int) (Circular.getSinOfDegrees(i + 1, ArrayVisualizer.halfCircle()) * ((ArrayVisualizer.windowWidth() - 64) / CIRC_WIDTH_RATIO)), ArrayVisualizer.windowHalfHeight() - (int) (Circular.getCosOfDegrees(i + 1, ArrayVisualizer.halfCircle()) * ((ArrayVisualizer.windowHeight() - 96) / CIRC_HEIGHT_RATIO))); - mainRender.fillPolygon(p); + this.mainRender.fillPolygon(p); } } } diff --git a/src/visuals/Hoops.java b/src/visuals/Hoops.java index c4e8f7f7..9041e6e2 100644 --- a/src/visuals/Hoops.java +++ b/src/visuals/Hoops.java @@ -5,6 +5,7 @@ import java.awt.Graphics2D; import main.ArrayVisualizer; +import templates.Visual; import utils.Highlights; import utils.Renderer; @@ -34,11 +35,56 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class Hoops { +final public class Hoops extends Visual { + public Hoops(ArrayVisualizer ArrayVisualizer) { + super(ArrayVisualizer); + } + + @SuppressWarnings("fallthrough") + public static void markHoops(int logOfLen, int index, Highlights Highlights, Graphics2D mainRender) { + switch(logOfLen) { + case 14: if(Highlights.containsPosition(index - 13)) mainRender.setColor(Color.BLACK); + case 13: if(Highlights.containsPosition(index - 12)) mainRender.setColor(Color.BLACK); + case 12: if(Highlights.containsPosition(index - 11)) mainRender.setColor(Color.BLACK); + case 11: if(Highlights.containsPosition(index - 10)) mainRender.setColor(Color.BLACK); + case 10: if(Highlights.containsPosition(index - 9)) mainRender.setColor(Color.BLACK); + case 9: if(Highlights.containsPosition(index - 8)) mainRender.setColor(Color.BLACK); + case 8: if(Highlights.containsPosition(index - 7)) mainRender.setColor(Color.BLACK); + case 7: if(Highlights.containsPosition(index - 6)) mainRender.setColor(Color.BLACK); + case 6: if(Highlights.containsPosition(index - 5)) mainRender.setColor(Color.BLACK); + case 5: if(Highlights.containsPosition(index - 4)) mainRender.setColor(Color.BLACK); + case 4: if(Highlights.containsPosition(index - 3)) mainRender.setColor(Color.BLACK); + case 3: if(Highlights.containsPosition(index - 2)) mainRender.setColor(Color.BLACK); + case 2: if(Highlights.containsPosition(index - 1)) mainRender.setColor(Color.BLACK); + default: if(Highlights.containsPosition(index)) mainRender.setColor(Color.BLACK); + } + } + + @SuppressWarnings("fallthrough") + public static void drawFancyFinishHoops(int logOfLen, int index, int position, Graphics2D mainRender) { + switch(logOfLen) { + case 14: if(index == position - 13) mainRender.setColor(Color.BLACK); + case 13: if(index == position - 12) mainRender.setColor(Color.BLACK); + case 12: if(index == position - 11) mainRender.setColor(Color.BLACK); + case 11: if(index == position - 10) mainRender.setColor(Color.BLACK); + case 10: if(index == position - 9) mainRender.setColor(Color.BLACK); + case 9: if(index == position - 8) mainRender.setColor(Color.BLACK); + case 8: if(index == position - 7) mainRender.setColor(Color.BLACK); + case 7: if(index == position - 6) mainRender.setColor(Color.BLACK); + case 6: if(index == position - 5) mainRender.setColor(Color.BLACK); + case 5: if(index == position - 4) mainRender.setColor(Color.BLACK); + case 4: if(index == position - 3) mainRender.setColor(Color.BLACK); + case 3: if(index == position - 2) mainRender.setColor(Color.BLACK); + case 2: if(index == position - 1) mainRender.setColor(Color.BLACK); + default: if(index == position) mainRender.setColor(Color.BLACK); + } + } + //TODO: Fix scaling to ensure Hoops close at the center //TODO: Too many rings highlighted at once!! - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { - mainRender.setStroke(new BasicStroke(1.0f)); //thin strokes significantly increased performance + @Override + public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { + this.mainRender.setStroke(new BasicStroke(1.0f)); //thin strokes significantly increased performance //This StackOverflow thread may be related: https://stackoverflow.com/questions/47102734/performances-issue-when-drawing-dashed-line-in-java @@ -48,23 +94,23 @@ public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Re for(int i = 0; i < ArrayVisualizer.getCurrentLength(); i++) { if(Highlights.fancyFinishActive()) { if(i < Highlights.getFancyFinishPosition()) { - mainRender.setColor(Color.GREEN); + this.mainRender.setColor(Color.GREEN); } - else mainRender.setColor(Renderer.getIntColor(array[i], ArrayVisualizer.getCurrentLength())); + else this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); - Renderer.drawFancyFinishHoops(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights.getFancyFinishPosition(), mainRender); + drawFancyFinishHoops(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights.getFancyFinishPosition(), this.mainRender); } else { - mainRender.setColor(Renderer.getIntColor(array[i], ArrayVisualizer.getCurrentLength())); + this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); } if(ArrayVisualizer.getCurrentLength() != 2) { - Renderer.markHoops(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights, mainRender); + markHoops(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights, this.mainRender); } int radius = (int) (diameter / 2.0); - mainRender.drawOval(ArrayVisualizer.windowHalfWidth() - radius, + this.mainRender.drawOval(ArrayVisualizer.windowHalfWidth() - radius, ArrayVisualizer.windowHalfHeight() - radius + 12, (int) diameter, (int) diameter); diff --git a/src/visuals/Mesh.java b/src/visuals/Mesh.java index 69ef1100..03bbf650 100644 --- a/src/visuals/Mesh.java +++ b/src/visuals/Mesh.java @@ -1,9 +1,9 @@ package visuals; import java.awt.Color; -import java.awt.Graphics2D; import main.ArrayVisualizer; +import templates.Visual; import utils.Highlights; import utils.Renderer; @@ -33,12 +33,48 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class Mesh { - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { - int trih = Renderer.getTriangleHeight(ArrayVisualizer.getCurrentLength(), ArrayVisualizer.windowHeight() / 20); //Height of triangles to use, Width will be scaled accordingly +final public class Mesh extends Visual { + public Mesh(ArrayVisualizer ArrayVisualizer) { + super(ArrayVisualizer); + } + + //TODO: Change these to be more consistent between array lengths. These heights and counts are a bit random. + public static int getTriangleHeight(int length, double height) { + switch(length) { + case 2: height *= 20; break; + case 4: height *= 13; break; + case 8: height *= 8; break; + case 16: + case 32: height *= 4.4; break; + case 64: height *= 2.3; break; + case 128: height *= 2.35; break; + case 256: height *= 1.22; break; + default: height *= 1; + } + + return (int) height; + } + + public static int getTrianglesPerRow(int length, int trianglesPerColumn) { + int trianglesPerRow; + + switch(length) { + case 32: + case 64: trianglesPerRow = 4; break; + case 128: + case 256: trianglesPerRow = 8; break; + default: trianglesPerRow = Math.max(length / trianglesPerColumn, 2); + } + + return trianglesPerRow; + } + + @Override + public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { + int trih = getTriangleHeight(ArrayVisualizer.getCurrentLength(), ArrayVisualizer.windowHeight() / 20); //Height of triangles to use, Width will be scaled accordingly int tripercol = (ArrayVisualizer.windowHeight() / trih) * 2; //Triangles per column - int triperrow = Renderer.getTrianglesPerRow(ArrayVisualizer.getCurrentLength(), tripercol); //Triangles per row + int triperrow = getTrianglesPerRow(ArrayVisualizer.getCurrentLength(), tripercol); //Triangles per row double triw = (double) ArrayVisualizer.windowWidth() / triperrow; //Width of triangles to use @@ -50,15 +86,15 @@ public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Re for(int i = 0; i < ArrayVisualizer.getCurrentLength(); i++){ if(Highlights.containsPosition(i) && ArrayVisualizer.getCurrentLength() != 2) { - if(ArrayVisualizer.analysisEnabled()) mainRender.setColor(Color.WHITE); - else mainRender.setColor(Color.BLACK); + if(ArrayVisualizer.analysisEnabled()) this.mainRender.setColor(Color.WHITE); + else this.mainRender.setColor(Color.BLACK); } else { //TODO: Clean up this visual trick if(Highlights.fancyFinishActive() && (i < Highlights.getFancyFinishPosition() && i > Highlights.getFancyFinishPosition() - ArrayVisualizer.getLogBaseTwoOfLength())) { - mainRender.setColor(Color.GREEN); + this.mainRender.setColor(Color.GREEN); } - else mainRender.setColor(Renderer.getIntColor(array[i], ArrayVisualizer.getCurrentLength())); + else this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); } //If i/triperrow is even, then triangle points right, else left boolean direction = false; @@ -89,7 +125,7 @@ public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Re } //Draw it - mainRender.fillPolygon(triptsx, triptsy, triptsx.length); + this.mainRender.fillPolygon(triptsx, triptsy, triptsx.length); //If at the end of a row, reset curx //(i != 0 || i != currentLen - 1) diff --git a/src/visuals/Pixels.java b/src/visuals/Pixels.java index 515512dc..a1fad716 100644 --- a/src/visuals/Pixels.java +++ b/src/visuals/Pixels.java @@ -2,9 +2,9 @@ import java.awt.BasicStroke; import java.awt.Color; -import java.awt.Graphics2D; import main.ArrayVisualizer; +import templates.Visual; import utils.Highlights; import utils.Renderer; @@ -34,18 +34,33 @@ of this software and associated documentation files (the "Software"), to deal * */ -final public class Pixels { - private boolean drawRect; - - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { +final public class Pixels extends Visual { + public Pixels(ArrayVisualizer ArrayVisualizer) { + super(ArrayVisualizer); + } + + @Override + public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { if(ArrayVisualizer.linesEnabled()) { - Renderer.setLineY((int) ((ArrayVisualizer.windowHeight() - 20) - array[0] * Renderer.getYScale())); + //TODO: Wave visual needs to be *heavily* refactored + if(ArrayVisualizer.waveEnabled()) { + Renderer.setLineY((int) ((ArrayVisualizer.windowHeight() / 4) * Math.sin((2 * Math.PI * ((double) array[1] / ArrayVisualizer.getCurrentLength()))) + ArrayVisualizer.windowHalfHeight())); + } + else { + Renderer.setLineY((int) ((ArrayVisualizer.windowHeight() - 20) - array[0] * Renderer.getYScale())); + } for(int i = 0; i < ArrayVisualizer.getCurrentLength(); i++) { - int y = (int) ((ArrayVisualizer.windowHeight() - 20) - (Math.max(array[i], 1) * Renderer.getYScale())); - - // Quick patch to fix the first line being horizontal for some reason - if(i == 0) y += ((ArrayVisualizer.windowHeight() - 20) - array[1] * Renderer.getYScale()) - - ((ArrayVisualizer.windowHeight() - 20) - array[2] * Renderer.getYScale()); + int y; + if(ArrayVisualizer.waveEnabled()) { + y = (int) ((ArrayVisualizer.windowHeight() / 4) * Math.sin((2 * Math.PI * ((double) array[i] / ArrayVisualizer.getCurrentLength()))) + ArrayVisualizer.windowHalfHeight()); + } + else { + y = (int) ((ArrayVisualizer.windowHeight() - 20) - (Math.max(array[i], 1) * Renderer.getYScale())); + + // Quick patch to fix the first line being horizontal for some reason + if(i == 0) y += ((ArrayVisualizer.windowHeight() - 20) - array[1] * Renderer.getYScale()) + - ((ArrayVisualizer.windowHeight() - 20) - array[2] * Renderer.getYScale()); + } int width = (int) (Renderer.getXScale() * (i + 1)) - Renderer.getOffset(); @@ -53,18 +68,18 @@ public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Re if(i > 0) { if(Highlights.fancyFinishActive()) { if(i < Highlights.getFancyFinishPosition()) { - Renderer.lineFancy(mainRender, ArrayVisualizer.currentWidth()); + lineFancy(this.mainRender, ArrayVisualizer.currentWidth()); } - else Renderer.lineClear(mainRender, ArrayVisualizer.colorEnabled(), array, i, ArrayVisualizer.getCurrentLength(), ArrayVisualizer.currentWidth()); + else lineClear(this.mainRender, ArrayVisualizer.colorEnabled(), array, i, ArrayVisualizer.getCurrentLength(), ArrayVisualizer.currentWidth()); - Renderer.drawFancyFinishLine(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights.getFancyFinishPosition(), mainRender, ArrayVisualizer.currentWidth(), ArrayVisualizer.colorEnabled()); + drawFancyFinishLine(ArrayVisualizer.getLogBaseTwoOfLength(), i, Highlights.getFancyFinishPosition(), this.mainRender, ArrayVisualizer.currentWidth(), ArrayVisualizer.colorEnabled()); } else if(Highlights.containsPosition(i) && ArrayVisualizer.getCurrentLength() != 2) { - Renderer.lineMark(mainRender, ArrayVisualizer.currentWidth(), ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); + lineMark(this.mainRender, ArrayVisualizer.currentWidth(), ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); } - else Renderer.lineClear(mainRender, ArrayVisualizer.colorEnabled(), array, i, ArrayVisualizer.getCurrentLength(), ArrayVisualizer.currentWidth()); + else lineClear(this.mainRender, ArrayVisualizer.colorEnabled(), array, i, ArrayVisualizer.getCurrentLength(), ArrayVisualizer.currentWidth()); - mainRender.drawLine(Renderer.getOffset() + 20, y, Renderer.getLineX() + 20, Renderer.getLineY()); + this.mainRender.drawLine(Renderer.getOffset() + 20, y, Renderer.getLineX() + 20, Renderer.getLineY()); } Renderer.setLineX(Renderer.getOffset()); Renderer.setLineY(y); @@ -75,43 +90,48 @@ else if(Highlights.containsPosition(i) && ArrayVisualizer.getCurrentLength() != else { for(int i = 0; i < ArrayVisualizer.getCurrentLength(); i++) { if(i < Highlights.getFancyFinishPosition()) { - mainRender.setColor(Color.GREEN); + this.mainRender.setColor(Color.GREEN); } else if(i == Highlights.getFancyFinishPosition() && Highlights.fancyFinishActive()) { if(ArrayVisualizer.colorEnabled()) { - mainRender.setColor(Color.WHITE); + this.mainRender.setColor(Color.WHITE); } - else mainRender.setColor(Color.RED); + else this.mainRender.setColor(Color.RED); } else if(ArrayVisualizer.colorEnabled()) { - mainRender.setColor(Renderer.getIntColor(array[i], ArrayVisualizer.getCurrentLength())); + this.mainRender.setColor(getIntColor(array[i], ArrayVisualizer.getCurrentLength())); } - else mainRender.setColor(Color.WHITE); + else this.mainRender.setColor(Color.WHITE); int y = 0; int width = (int) (Renderer.getXScale() * (i + 1)) - Renderer.getOffset(); + boolean drawRect = false; if(Highlights.containsPosition(i) && ArrayVisualizer.getCurrentLength() != 2) { - Renderer.setRectColor(extraRender, ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); + setRectColor(this.extraRender, ArrayVisualizer.colorEnabled(), ArrayVisualizer.analysisEnabled()); drawRect = true; } - else drawRect = false; if(width > 0) { - y = (int) ((ArrayVisualizer.windowHeight() - 20) - (array[i] * Renderer.getYScale())); - mainRender.fillRect(Renderer.getOffset() + 20, y, Renderer.getDotDimensions(), Renderer.getDotDimensions()); + if(ArrayVisualizer.waveEnabled()) { + y = (int) ((ArrayVisualizer.windowHeight() / 4) * Math.sin((2 * Math.PI * ((double) array[i] / ArrayVisualizer.getCurrentLength()))) + ArrayVisualizer.windowHalfHeight()); + } + else { + y = (int) ((ArrayVisualizer.windowHeight() - 20) - (array[i] * Renderer.getYScale())); + } + this.mainRender.fillRect(Renderer.getOffset() + 20, y, Renderer.getDotDimensions(), Renderer.getDotDimensions()); if(drawRect) { - extraRender.setStroke(ArrayVisualizer.getThickStroke()); + this.extraRender.setStroke(ArrayVisualizer.getThickStroke()); if(Highlights.fancyFinishActive()) { - extraRender.fillRect(Renderer.getOffset() + 10, y - 10, Renderer.getDotDimensions() + 20, Renderer.getDotDimensions() + 20); + this.extraRender.fillRect(Renderer.getOffset() + 10, y - 10, Renderer.getDotDimensions() + 20, Renderer.getDotDimensions() + 20); } else { - extraRender.drawRect(Renderer.getOffset() + 10, y - 10, Renderer.getDotDimensions() + 20, Renderer.getDotDimensions() + 20); + this.extraRender.drawRect(Renderer.getOffset() + 10, y - 10, Renderer.getDotDimensions() + 20, Renderer.getDotDimensions() + 20); } - extraRender.setStroke(new BasicStroke(3f * (ArrayVisualizer.currentWidth() / 1280f))); //TODO: This BasicStroke should have a getDefaultStroke() method + this.extraRender.setStroke(new BasicStroke(3f * (ArrayVisualizer.currentWidth() / 1280f))); //TODO: This BasicStroke should have a getDefaultStroke() method } } Renderer.setOffset(Renderer.getOffset() + width); diff --git a/src/visuals/VisualStyles.java b/src/visuals/VisualStyles.java index 46b7c600..d7b8f683 100644 --- a/src/visuals/VisualStyles.java +++ b/src/visuals/VisualStyles.java @@ -1,7 +1,5 @@ package visuals; -import java.awt.Graphics2D; - import main.ArrayVisualizer; import utils.Highlights; import utils.Renderer; @@ -33,45 +31,40 @@ of this software and associated documentation files (the "Software"), to deal */ public enum VisualStyles { - CIRCULAR { + BARS { @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, - Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { - Renderer.drawCircle(array, ArrayVisualizer, mainRender, extraRender, Highlights); + public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { + ArrayVisualizer.getVisuals()[0].drawVisual(array, ArrayVisualizer, Renderer, Highlights); } }, - HOOPS { + CIRCULAR { @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, - Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { - Renderer.drawHoops(array, ArrayVisualizer, mainRender, extraRender, Highlights); + public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { + ArrayVisualizer.getVisuals()[1].drawVisual(array, ArrayVisualizer, Renderer, Highlights); } }, - MESH { + HOOPS { @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, - Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { - Renderer.drawMesh(array, ArrayVisualizer, mainRender, extraRender, Highlights); + public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { + ArrayVisualizer.getVisuals()[2].drawVisual(array, ArrayVisualizer, Renderer, Highlights); } }, - BARS { + MESH { @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, - Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { - Renderer.drawBars(array, ArrayVisualizer, mainRender, extraRender, Highlights); + public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { + ArrayVisualizer.getVisuals()[3].drawVisual(array, ArrayVisualizer, Renderer, Highlights); } }, PIXELS { @Override - public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, - Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights) { - Renderer.drawPixels(array, ArrayVisualizer, mainRender, extraRender, Highlights); + public void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights) { + ArrayVisualizer.getVisuals()[4].drawVisual(array, ArrayVisualizer, Renderer, Highlights); } }; - public VisualStyles getVisual() { + public VisualStyles getCurrentVisual() { return this; } - public abstract void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Graphics2D mainRender, Graphics2D extraRender, Highlights Highlights); + public abstract void drawVisual(int[] array, ArrayVisualizer ArrayVisualizer, Renderer Renderer, Highlights Highlights); } \ No newline at end of file