Encapsulate the coordinate calculation logic in separate classes.
This commit is contained in:
		
							parent
							
								
									6060a08573
								
							
						
					
					
						commit
						66ddb27291
					
				
					 1 changed files with 129 additions and 45 deletions
				
			
		|  | @ -1,6 +1,7 @@ | ||||||
| package ch.fritteli.labyrinth; | package ch.fritteli.labyrinth; | ||||||
| 
 | 
 | ||||||
| import lombok.NonNull; | import lombok.NonNull; | ||||||
|  | import lombok.Value; | ||||||
| import org.apache.pdfbox.pdmodel.PDDocument; | import org.apache.pdfbox.pdmodel.PDDocument; | ||||||
| import org.apache.pdfbox.pdmodel.PDDocumentInformation; | import org.apache.pdfbox.pdmodel.PDDocumentInformation; | ||||||
| import org.apache.pdfbox.pdmodel.PDPage; | import org.apache.pdfbox.pdmodel.PDPage; | ||||||
|  | @ -47,10 +48,8 @@ public class PDFRenderer implements Renderer<byte[]> { | ||||||
|              final PDPageContentStream solutionPageContentStream = new PDPageContentStream(pdDocument, solution)) { |              final PDPageContentStream solutionPageContentStream = new PDPageContentStream(pdDocument, solution)) { | ||||||
|             setUpPageContentStream(labyrinthPageContentStream); |             setUpPageContentStream(labyrinthPageContentStream); | ||||||
|             setUpPageContentStream(solutionPageContentStream); |             setUpPageContentStream(solutionPageContentStream); | ||||||
|             this.drawHorizonzalLines(labyrinth, labyrinthPageContentStream); |             this.drawHorizonzalLines(labyrinth, labyrinthPageContentStream, solutionPageContentStream); | ||||||
|             this.drawVerticalLines(labyrinth, labyrinthPageContentStream); |             this.drawVerticalLines(labyrinth, labyrinthPageContentStream, solutionPageContentStream); | ||||||
|             this.drawHorizonzalLines(labyrinth, solutionPageContentStream); |  | ||||||
|             this.drawVerticalLines(labyrinth, solutionPageContentStream); |  | ||||||
|             this.drawSolution(labyrinth, solutionPageContentStream); |             this.drawSolution(labyrinth, solutionPageContentStream); | ||||||
|         } catch (IOException e) { |         } catch (IOException e) { | ||||||
|             e.printStackTrace(); |             e.printStackTrace(); | ||||||
|  | @ -74,132 +73,158 @@ public class PDFRenderer implements Renderer<byte[]> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void drawHorizonzalLines(@NonNull final Labyrinth labyrinth, |     private void drawHorizonzalLines(@NonNull final Labyrinth labyrinth, | ||||||
|                                      @NonNull final PDPageContentStream pdPageContentStream) throws IOException { |                                      @NonNull final PDPageContentStream... contentStreams) throws IOException { | ||||||
|         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. |         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. | ||||||
|         final float labyrinthHeight = labyrinth.getHeight() * SCALE; |         Coordinate coordinate = new Coordinate(0f, 0f); | ||||||
|         for (int y = 0; y < labyrinth.getHeight(); y++) { |         for (int y = 0; y < labyrinth.getHeight(); y++) { | ||||||
|             boolean isPainting = false; |             boolean isPainting = false; | ||||||
|             final float yCoordinate = labyrinthHeight - y * SCALE + MARGIN; |             coordinate = coordinate.withY(y, labyrinth); | ||||||
|             for (int x = 0; x < labyrinth.getWidth(); x++) { |             for (int x = 0; x < labyrinth.getWidth(); x++) { | ||||||
|                 final Tile currentTile = labyrinth.getTileAt(x, y); |                 final Tile currentTile = labyrinth.getTileAt(x, y); | ||||||
|                 final float xCoordinate = x * SCALE + MARGIN; |                 coordinate = coordinate.withX(x); | ||||||
|                 if (currentTile.hasWallAt(Direction.TOP)) { |                 if (currentTile.hasWallAt(Direction.TOP)) { | ||||||
|                     if (!isPainting) { |                     if (!isPainting) { | ||||||
|                         pdPageContentStream.moveTo(xCoordinate, yCoordinate); |                         for (final PDPageContentStream contentStream : contentStreams) { | ||||||
|  |                             contentStream.moveTo(coordinate.getX(), coordinate.getY()); | ||||||
|  |                         } | ||||||
|                         isPainting = true; |                         isPainting = true; | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     if (isPainting) { |                     if (isPainting) { | ||||||
|                         pdPageContentStream.lineTo(xCoordinate, yCoordinate); |                         for (final PDPageContentStream contentStream : contentStreams) { | ||||||
|                         pdPageContentStream.stroke(); |                             contentStream.lineTo(coordinate.getX(), coordinate.getY()); | ||||||
|  |                             contentStream.stroke(); | ||||||
|  |                         } | ||||||
|                         isPainting = false; |                         isPainting = false; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (isPainting) { |             if (isPainting) { | ||||||
|                 final float xCoordinate = labyrinth.getWidth() * SCALE + MARGIN; |                 coordinate = coordinate.withX(labyrinth.getWidth()); | ||||||
|                 pdPageContentStream.lineTo(xCoordinate, yCoordinate); |                 for (final PDPageContentStream contentStream : contentStreams) { | ||||||
|                 pdPageContentStream.stroke(); |                     contentStream.lineTo(coordinate.getX(), coordinate.getY()); | ||||||
|  |                     contentStream.stroke(); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         boolean isPainting = false; |         boolean isPainting = false; | ||||||
|         int y = labyrinth.getHeight(); |         int y = labyrinth.getHeight(); | ||||||
|         final float yCoordinate = /*labyrinthHeight - y * SCALE +*/ MARGIN; |         coordinate = coordinate.withY(labyrinth.getHeight(), labyrinth); | ||||||
|         for (int x = 0; x < labyrinth.getWidth(); x++) { |         for (int x = 0; x < labyrinth.getWidth(); x++) { | ||||||
|             final Tile currentTile = labyrinth.getTileAt(x, y - 1); |             final Tile currentTile = labyrinth.getTileAt(x, y - 1); | ||||||
|             final float xCoordinate = x * SCALE + MARGIN; |             coordinate = coordinate.withX(x); | ||||||
|             if (currentTile.hasWallAt(Direction.BOTTOM)) { |             if (currentTile.hasWallAt(Direction.BOTTOM)) { | ||||||
|                 if (!isPainting) { |                 if (!isPainting) { | ||||||
|                     pdPageContentStream.moveTo(xCoordinate, yCoordinate); |                     for (final PDPageContentStream contentStream : contentStreams) { | ||||||
|  |                         contentStream.moveTo(coordinate.getX(), coordinate.getY()); | ||||||
|  |                     } | ||||||
|                     isPainting = true; |                     isPainting = true; | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 if (isPainting) { |                 if (isPainting) { | ||||||
|                     pdPageContentStream.lineTo(xCoordinate, yCoordinate); |                     for (final PDPageContentStream contentStream : contentStreams) { | ||||||
|                     pdPageContentStream.stroke(); |                         contentStream.lineTo(coordinate.getX(), coordinate.getY()); | ||||||
|  |                         contentStream.stroke(); | ||||||
|  |                     } | ||||||
|                     isPainting = false; |                     isPainting = false; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         final float xCoordinate = labyrinth.getWidth() * SCALE + MARGIN; |  | ||||||
|         if (isPainting) { |         if (isPainting) { | ||||||
|             pdPageContentStream.lineTo(xCoordinate, yCoordinate); |             coordinate = coordinate.withX(labyrinth.getWidth()); | ||||||
|             pdPageContentStream.stroke(); |             for (final PDPageContentStream contentStream : contentStreams) { | ||||||
|  |                 contentStream.lineTo(coordinate.getX(), coordinate.getY()); | ||||||
|  |                 contentStream.stroke(); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void drawVerticalLines(@NonNull final Labyrinth labyrinth, |     private void drawVerticalLines(@NonNull final Labyrinth labyrinth, | ||||||
|                                    @NonNull final PDPageContentStream pdPageContentStream) throws IOException { |                                    @NonNull final PDPageContentStream... contentStreams) throws IOException { | ||||||
|         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. |         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. | ||||||
|  |         Coordinate coordinate = new Coordinate(0f, 0f); | ||||||
|         final float labyrinthHeight = labyrinth.getHeight() * SCALE; |         final float labyrinthHeight = labyrinth.getHeight() * SCALE; | ||||||
|         for (int x = 0; x < labyrinth.getWidth(); x++) { |         for (int x = 0; x < labyrinth.getWidth(); x++) { | ||||||
|             boolean isPainting = false; |             boolean isPainting = false; | ||||||
|             final float xCoordinate = x * SCALE + MARGIN; |             coordinate = coordinate.withX(x); | ||||||
|             for (int y = 0; y < labyrinth.getHeight(); y++) { |             for (int y = 0; y < labyrinth.getHeight(); y++) { | ||||||
|                 final Tile currentTile = labyrinth.getTileAt(x, y); |                 final Tile currentTile = labyrinth.getTileAt(x, y); | ||||||
|                 final float yCoordinate = labyrinthHeight - y * SCALE + MARGIN; |                 coordinate = coordinate.withY(y, labyrinth); | ||||||
|                 if (currentTile.hasWallAt(Direction.LEFT)) { |                 if (currentTile.hasWallAt(Direction.LEFT)) { | ||||||
|                     if (!isPainting) { |                     if (!isPainting) { | ||||||
|                         pdPageContentStream.moveTo(xCoordinate, yCoordinate); |                         for (final PDPageContentStream contentStream : contentStreams) { | ||||||
|  |                             contentStream.moveTo(coordinate.getX(), coordinate.getY()); | ||||||
|  |                         } | ||||||
|                         isPainting = true; |                         isPainting = true; | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     if (isPainting) { |                     if (isPainting) { | ||||||
|                         pdPageContentStream.lineTo(xCoordinate, yCoordinate); |                         for (final PDPageContentStream contentStream : contentStreams) { | ||||||
|                         pdPageContentStream.stroke(); |                             contentStream.lineTo(coordinate.getX(), coordinate.getY()); | ||||||
|  |                             contentStream.stroke(); | ||||||
|  |                         } | ||||||
|                         isPainting = false; |                         isPainting = false; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (isPainting) { |             if (isPainting) { | ||||||
|                 pdPageContentStream.lineTo(xCoordinate, MARGIN); |                 coordinate = coordinate.withY(labyrinth.getHeight(), labyrinth); | ||||||
|                 pdPageContentStream.stroke(); |                 for (final PDPageContentStream contentStream : contentStreams) { | ||||||
|  |                     contentStream.lineTo(coordinate.getX(), coordinate.getY()); | ||||||
|  |                     contentStream.stroke(); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         boolean isPainting = false; |         boolean isPainting = false; | ||||||
|         int x = labyrinth.getWidth(); |         int x = labyrinth.getWidth(); | ||||||
|         final float xCoordinate = x * SCALE + MARGIN; |         coordinate = coordinate.withX(labyrinth.getWidth()); | ||||||
|         for (int y = 0; y < labyrinth.getHeight(); y++) { |         for (int y = 0; y < labyrinth.getHeight(); y++) { | ||||||
|             final Tile currentTile = labyrinth.getTileAt(x - 1, y); |             final Tile currentTile = labyrinth.getTileAt(x - 1, y); | ||||||
|             final float yCoordinate = labyrinthHeight - y * SCALE + MARGIN; |             coordinate = coordinate.withY(y, labyrinth); | ||||||
|             if (currentTile.hasWallAt(Direction.RIGHT)) { |             if (currentTile.hasWallAt(Direction.RIGHT)) { | ||||||
|                 if (!isPainting) { |                 if (!isPainting) { | ||||||
|                     pdPageContentStream.moveTo(xCoordinate, yCoordinate); |                     for (final PDPageContentStream contentStream : contentStreams) { | ||||||
|  |                         contentStream.moveTo(coordinate.getX(), coordinate.getY()); | ||||||
|  |                     } | ||||||
|                     isPainting = true; |                     isPainting = true; | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 if (isPainting) { |                 if (isPainting) { | ||||||
|                     pdPageContentStream.lineTo(xCoordinate, yCoordinate); |                     for (final PDPageContentStream contentStream : contentStreams) { | ||||||
|                     pdPageContentStream.stroke(); |                         contentStream.lineTo(coordinate.getX(), coordinate.getY()); | ||||||
|  |                         contentStream.stroke(); | ||||||
|  |                     } | ||||||
|                     isPainting = false; |                     isPainting = false; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (isPainting) { |         if (isPainting) { | ||||||
|             pdPageContentStream.lineTo(xCoordinate, MARGIN); |             coordinate = coordinate.withY(labyrinth.getHeight(), labyrinth); | ||||||
|             pdPageContentStream.stroke(); |             for (final PDPageContentStream contentStream : contentStreams) { | ||||||
|  |                 contentStream.lineTo(coordinate.getX(), coordinate.getY()); | ||||||
|  |                 contentStream.stroke(); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void drawSolution(@NonNull final Labyrinth labyrinth, |     private void drawSolution(@NonNull final Labyrinth labyrinth, | ||||||
|                               @NonNull final PDPageContentStream pdPageContentStream) throws IOException { |                               @NonNull final PDPageContentStream pageContentStream) throws IOException { | ||||||
|         // Draw the solution in red |         // Draw the solution in red | ||||||
|         pdPageContentStream.setStrokingColor(Color.RED); |         pageContentStream.setStrokingColor(Color.RED); | ||||||
|         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. |         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. | ||||||
|         final float labyrinthHeight = labyrinth.getHeight() * SCALE; |  | ||||||
|         final Position end = labyrinth.getEnd(); |         final Position end = labyrinth.getEnd(); | ||||||
|         Position currentPosition = labyrinth.getStart(); |         Position currentPosition = labyrinth.getStart(); | ||||||
|         Position previousPosition = null; |         Position previousPosition = null; | ||||||
|         pdPageContentStream.moveTo(MARGIN + currentPosition.getX() * SCALE + SCALE / 2, MARGIN + labyrinthHeight - (currentPosition.getY() * SCALE + SCALE / 2)); |         SolutionCoordinate coordinate = new SolutionCoordinate(currentPosition.getX(), currentPosition.getY(), labyrinth); | ||||||
|  |         pageContentStream.moveTo(coordinate.getX(), coordinate.getY()); | ||||||
|         do { |         do { | ||||||
|             Position newCurrent = this.findNextSolutionPosition(labyrinth, previousPosition, currentPosition); |             Position newCurrent = this.findNextSolutionPosition(labyrinth, previousPosition, currentPosition); | ||||||
|             previousPosition = currentPosition; |             previousPosition = currentPosition; | ||||||
|             currentPosition = newCurrent; |             currentPosition = newCurrent; | ||||||
|             final float xCoordinate = MARGIN + currentPosition.getX() * SCALE + SCALE / 2; |             coordinate = new SolutionCoordinate(currentPosition.getX(), currentPosition.getY(), labyrinth); | ||||||
|             final float yCoordinate = MARGIN + labyrinthHeight - (currentPosition.getY() * SCALE + SCALE / 2); |             pageContentStream.lineTo(coordinate.getX(), coordinate.getY()); | ||||||
|             pdPageContentStream.lineTo(xCoordinate, yCoordinate); |  | ||||||
|         } while (!currentPosition.equals(end)); |         } while (!currentPosition.equals(end)); | ||||||
|         pdPageContentStream.stroke(); |         pageContentStream.stroke(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NonNull | ||||||
|  | @ -218,4 +243,63 @@ public class PDFRenderer implements Renderer<byte[]> { | ||||||
|         } |         } | ||||||
|         throw new IllegalStateException("We *SHOULD* never have gotten here. ... famous last words ..."); |         throw new IllegalStateException("We *SHOULD* never have gotten here. ... famous last words ..."); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     @Value | ||||||
|  |     private static class Coordinate { | ||||||
|  |         float x; | ||||||
|  |         float y; | ||||||
|  | 
 | ||||||
|  |         public Coordinate(final float x, final float y) { | ||||||
|  |             this.x = x; | ||||||
|  |             this.y = y; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static float calcX(final int x) { | ||||||
|  |             return x * SCALE + MARGIN; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static float calcY(final int y, @NonNull final Labyrinth labyrinth) { | ||||||
|  |             return (labyrinth.getHeight() - y) * SCALE + MARGIN; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Coordinate withX(final int x) { | ||||||
|  |             return new Coordinate(calcX(x), this.y); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Coordinate withY(final int y, @NonNull final Labyrinth labyrinth) { | ||||||
|  |             return new Coordinate(this.x, calcY(y, labyrinth)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     @Value | ||||||
|  |     private static class SolutionCoordinate { | ||||||
|  |         float x; | ||||||
|  |         float y; | ||||||
|  | 
 | ||||||
|  |         public SolutionCoordinate(final float x, final float y) { | ||||||
|  |             this.x = x; | ||||||
|  |             this.y = y; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public SolutionCoordinate(final int x, final int y, @NonNull final Labyrinth labyrinth) { | ||||||
|  |             this.x = calcX(x); | ||||||
|  |             this.y = calcY(y, labyrinth); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static float calcX(final int x) { | ||||||
|  |             return x * SCALE + SCALE / 2 + MARGIN; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static float calcY(final int y, @NonNull final Labyrinth labyrinth) { | ||||||
|  |             return (labyrinth.getHeight() - y) * SCALE - SCALE / 2 + MARGIN; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public SolutionCoordinate withX(final int x) { | ||||||
|  |             return new SolutionCoordinate(calcX(x), this.y); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public SolutionCoordinate withY(final int y, @NonNull final Labyrinth labyrinth) { | ||||||
|  |             return new SolutionCoordinate(this.x, calcY(y, labyrinth)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue