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;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
|
@ -47,10 +48,8 @@ public class PDFRenderer implements Renderer<byte[]> {
|
|||
final PDPageContentStream solutionPageContentStream = new PDPageContentStream(pdDocument, solution)) {
|
||||
setUpPageContentStream(labyrinthPageContentStream);
|
||||
setUpPageContentStream(solutionPageContentStream);
|
||||
this.drawHorizonzalLines(labyrinth, labyrinthPageContentStream);
|
||||
this.drawVerticalLines(labyrinth, labyrinthPageContentStream);
|
||||
this.drawHorizonzalLines(labyrinth, solutionPageContentStream);
|
||||
this.drawVerticalLines(labyrinth, solutionPageContentStream);
|
||||
this.drawHorizonzalLines(labyrinth, labyrinthPageContentStream, solutionPageContentStream);
|
||||
this.drawVerticalLines(labyrinth, labyrinthPageContentStream, solutionPageContentStream);
|
||||
this.drawSolution(labyrinth, solutionPageContentStream);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -74,132 +73,158 @@ public class PDFRenderer implements Renderer<byte[]> {
|
|||
}
|
||||
|
||||
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.
|
||||
final float labyrinthHeight = labyrinth.getHeight() * SCALE;
|
||||
Coordinate coordinate = new Coordinate(0f, 0f);
|
||||
for (int y = 0; y < labyrinth.getHeight(); y++) {
|
||||
boolean isPainting = false;
|
||||
final float yCoordinate = labyrinthHeight - y * SCALE + MARGIN;
|
||||
coordinate = coordinate.withY(y, labyrinth);
|
||||
for (int x = 0; x < labyrinth.getWidth(); x++) {
|
||||
final Tile currentTile = labyrinth.getTileAt(x, y);
|
||||
final float xCoordinate = x * SCALE + MARGIN;
|
||||
coordinate = coordinate.withX(x);
|
||||
if (currentTile.hasWallAt(Direction.TOP)) {
|
||||
if (!isPainting) {
|
||||
pdPageContentStream.moveTo(xCoordinate, yCoordinate);
|
||||
for (final PDPageContentStream contentStream : contentStreams) {
|
||||
contentStream.moveTo(coordinate.getX(), coordinate.getY());
|
||||
}
|
||||
isPainting = true;
|
||||
}
|
||||
} else {
|
||||
if (isPainting) {
|
||||
pdPageContentStream.lineTo(xCoordinate, yCoordinate);
|
||||
pdPageContentStream.stroke();
|
||||
for (final PDPageContentStream contentStream : contentStreams) {
|
||||
contentStream.lineTo(coordinate.getX(), coordinate.getY());
|
||||
contentStream.stroke();
|
||||
}
|
||||
isPainting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isPainting) {
|
||||
final float xCoordinate = labyrinth.getWidth() * SCALE + MARGIN;
|
||||
pdPageContentStream.lineTo(xCoordinate, yCoordinate);
|
||||
pdPageContentStream.stroke();
|
||||
coordinate = coordinate.withX(labyrinth.getWidth());
|
||||
for (final PDPageContentStream contentStream : contentStreams) {
|
||||
contentStream.lineTo(coordinate.getX(), coordinate.getY());
|
||||
contentStream.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean isPainting = false;
|
||||
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++) {
|
||||
final Tile currentTile = labyrinth.getTileAt(x, y - 1);
|
||||
final float xCoordinate = x * SCALE + MARGIN;
|
||||
coordinate = coordinate.withX(x);
|
||||
if (currentTile.hasWallAt(Direction.BOTTOM)) {
|
||||
if (!isPainting) {
|
||||
pdPageContentStream.moveTo(xCoordinate, yCoordinate);
|
||||
for (final PDPageContentStream contentStream : contentStreams) {
|
||||
contentStream.moveTo(coordinate.getX(), coordinate.getY());
|
||||
}
|
||||
isPainting = true;
|
||||
}
|
||||
} else {
|
||||
if (isPainting) {
|
||||
pdPageContentStream.lineTo(xCoordinate, yCoordinate);
|
||||
pdPageContentStream.stroke();
|
||||
for (final PDPageContentStream contentStream : contentStreams) {
|
||||
contentStream.lineTo(coordinate.getX(), coordinate.getY());
|
||||
contentStream.stroke();
|
||||
}
|
||||
isPainting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
final float xCoordinate = labyrinth.getWidth() * SCALE + MARGIN;
|
||||
if (isPainting) {
|
||||
pdPageContentStream.lineTo(xCoordinate, yCoordinate);
|
||||
pdPageContentStream.stroke();
|
||||
coordinate = coordinate.withX(labyrinth.getWidth());
|
||||
for (final PDPageContentStream contentStream : contentStreams) {
|
||||
contentStream.lineTo(coordinate.getX(), coordinate.getY());
|
||||
contentStream.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
Coordinate coordinate = new Coordinate(0f, 0f);
|
||||
final float labyrinthHeight = labyrinth.getHeight() * SCALE;
|
||||
for (int x = 0; x < labyrinth.getWidth(); x++) {
|
||||
boolean isPainting = false;
|
||||
final float xCoordinate = x * SCALE + MARGIN;
|
||||
coordinate = coordinate.withX(x);
|
||||
for (int y = 0; y < labyrinth.getHeight(); 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 (!isPainting) {
|
||||
pdPageContentStream.moveTo(xCoordinate, yCoordinate);
|
||||
for (final PDPageContentStream contentStream : contentStreams) {
|
||||
contentStream.moveTo(coordinate.getX(), coordinate.getY());
|
||||
}
|
||||
isPainting = true;
|
||||
}
|
||||
} else {
|
||||
if (isPainting) {
|
||||
pdPageContentStream.lineTo(xCoordinate, yCoordinate);
|
||||
pdPageContentStream.stroke();
|
||||
for (final PDPageContentStream contentStream : contentStreams) {
|
||||
contentStream.lineTo(coordinate.getX(), coordinate.getY());
|
||||
contentStream.stroke();
|
||||
}
|
||||
isPainting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isPainting) {
|
||||
pdPageContentStream.lineTo(xCoordinate, MARGIN);
|
||||
pdPageContentStream.stroke();
|
||||
coordinate = coordinate.withY(labyrinth.getHeight(), labyrinth);
|
||||
for (final PDPageContentStream contentStream : contentStreams) {
|
||||
contentStream.lineTo(coordinate.getX(), coordinate.getY());
|
||||
contentStream.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean isPainting = false;
|
||||
int x = labyrinth.getWidth();
|
||||
final float xCoordinate = x * SCALE + MARGIN;
|
||||
coordinate = coordinate.withX(labyrinth.getWidth());
|
||||
for (int y = 0; y < labyrinth.getHeight(); 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 (!isPainting) {
|
||||
pdPageContentStream.moveTo(xCoordinate, yCoordinate);
|
||||
for (final PDPageContentStream contentStream : contentStreams) {
|
||||
contentStream.moveTo(coordinate.getX(), coordinate.getY());
|
||||
}
|
||||
isPainting = true;
|
||||
}
|
||||
} else {
|
||||
if (isPainting) {
|
||||
pdPageContentStream.lineTo(xCoordinate, yCoordinate);
|
||||
pdPageContentStream.stroke();
|
||||
for (final PDPageContentStream contentStream : contentStreams) {
|
||||
contentStream.lineTo(coordinate.getX(), coordinate.getY());
|
||||
contentStream.stroke();
|
||||
}
|
||||
isPainting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isPainting) {
|
||||
pdPageContentStream.lineTo(xCoordinate, MARGIN);
|
||||
pdPageContentStream.stroke();
|
||||
coordinate = coordinate.withY(labyrinth.getHeight(), labyrinth);
|
||||
for (final PDPageContentStream contentStream : contentStreams) {
|
||||
contentStream.lineTo(coordinate.getX(), coordinate.getY());
|
||||
contentStream.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawSolution(@NonNull final Labyrinth labyrinth,
|
||||
@NonNull final PDPageContentStream pdPageContentStream) throws IOException {
|
||||
@NonNull final PDPageContentStream pageContentStream) throws IOException {
|
||||
// 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.
|
||||
final float labyrinthHeight = labyrinth.getHeight() * SCALE;
|
||||
final Position end = labyrinth.getEnd();
|
||||
Position currentPosition = labyrinth.getStart();
|
||||
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 {
|
||||
Position newCurrent = this.findNextSolutionPosition(labyrinth, previousPosition, currentPosition);
|
||||
previousPosition = currentPosition;
|
||||
currentPosition = newCurrent;
|
||||
final float xCoordinate = MARGIN + currentPosition.getX() * SCALE + SCALE / 2;
|
||||
final float yCoordinate = MARGIN + labyrinthHeight - (currentPosition.getY() * SCALE + SCALE / 2);
|
||||
pdPageContentStream.lineTo(xCoordinate, yCoordinate);
|
||||
coordinate = new SolutionCoordinate(currentPosition.getX(), currentPosition.getY(), labyrinth);
|
||||
pageContentStream.lineTo(coordinate.getX(), coordinate.getY());
|
||||
} while (!currentPosition.equals(end));
|
||||
pdPageContentStream.stroke();
|
||||
pageContentStream.stroke();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
@ -218,4 +243,63 @@ public class PDFRenderer implements Renderer<byte[]> {
|
|||
}
|
||||
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…
Reference in a new issue