commit 50ab3a0c314f96fd5665e366028e21b59cf2c8ae
Author: Hannes <13hannes11@gmail.com>
Date: Fri Jul 15 14:13:55 2016 +0200
Initial commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4eb8642
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,91 @@
+# Created by https://www.gitignore.io/api/intellij,java,windows
+
+### Intellij ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff:
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/dictionaries
+.idea/vcs.xml
+.idea/jsLibraryMappings.xml
+
+# Sensitive or high-churn files:
+.idea/dataSources.ids
+.idea/dataSources.xml
+.idea/dataSources.local.xml
+.idea/sqlDataSources.xml
+.idea/dynamic.xml
+.idea/uiDesigner.xml
+
+# Gradle:
+.idea/gradle.xml
+.idea/libraries
+
+# Mongo Explorer plugin:
+.idea/mongoSettings.xml
+
+## File-based project format:
+*.iws
+
+## Plugin-specific files:
+
+# IntelliJ
+/out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+### Intellij Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+
+### Windows ###
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+
+### Java ###
+*.class
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
\ No newline at end of file
diff --git a/XKCDPoster.iml b/XKCDPoster.iml
new file mode 100644
index 0000000..d5c0743
--- /dev/null
+++ b/XKCDPoster.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ImageMegapixelComparator.java b/src/ImageMegapixelComparator.java
new file mode 100644
index 0000000..d0ec52f
--- /dev/null
+++ b/src/ImageMegapixelComparator.java
@@ -0,0 +1,22 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package xkcd;
+
+import java.awt.image.BufferedImage;
+import java.util.Comparator;
+
+/**
+ *
+ * @author Hannes
+ */
+public class ImageMegapixelComparator implements Comparator {
+
+ @Override
+ public int compare(BufferedImage o1, BufferedImage o2) {
+ return o2.getWidth() * o2.getHeight() - o1.getWidth() * o1.getHeight();
+ }
+
+}
diff --git a/src/Main.java b/src/Main.java
new file mode 100644
index 0000000..cf48562
--- /dev/null
+++ b/src/Main.java
@@ -0,0 +1,29 @@
+import xkcd.construction.ImageArranger;
+import xkcd.construction.ImageDataLoader;
+import xkcd.construction.ImageSticher;
+import xkcd.rectangle.imagepath.PathRectangle;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+
+public class Main {
+
+ static final String PATH = "C:\\Users\\Hannes\\xkcd\\";
+
+ public static void main(final String[] args) throws IOException {
+ System.out.println("Loading Now!");
+ final ImageDataLoader loader = new ImageDataLoader();
+ Collection images = loader.load(new File(PATH));
+
+ System.out.println("Arranging Now!");
+ final ImageArranger arranger = new ImageArranger();
+ images = arranger.arrangeRectangles(images, 3D / 2D);
+ System.out.println("Count: " + images.size());
+
+ System.out.println("Saving Now!");
+ final ImageSticher sticher = new ImageSticher(images);
+ sticher.saveImage(new File("C:\\Users\\Hannes\\Desktop\\savedNew.png"));
+ System.out.println("DONE!");
+ }
+}
diff --git a/src/RectangleImage.java b/src/RectangleImage.java
new file mode 100644
index 0000000..93cf1bf
--- /dev/null
+++ b/src/RectangleImage.java
@@ -0,0 +1,58 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package xkcd;
+
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+
+/**
+ *
+ * @author Hannes
+ */
+public class RectangleImage {
+ Rectangle r;
+
+ public RectangleImage(BufferedImage image, int x, int y) {
+ r = new Rectangle(x, y, image.getWidth(), image.getHeight());
+ }
+ public RectangleImage(Rectangle rec){
+ r = rec;
+ }
+
+ public int getHeight() {
+ return r.height;
+ }
+
+ public int getWidth() {
+ return r.width;
+ }
+
+ public int getBoundY() {
+ return r.y + r.height;
+ }
+
+ public int getBoundX() {
+ return r.x + r.width;
+ }
+
+ public int getX() {
+ return r.x;
+ }
+
+ public int getY() {
+ return r.y;
+ }
+
+ public Rectangle getRectangle() {
+ return r;
+ }
+ public void setY(int y){
+ r.y = y;
+ }
+ public boolean intersects(RectangleImage image) {
+ return r.intersects(image.getRectangle());
+ }
+}
diff --git a/src/xkcd/construction/ImageArranger.java b/src/xkcd/construction/ImageArranger.java
new file mode 100644
index 0000000..00c86dc
--- /dev/null
+++ b/src/xkcd/construction/ImageArranger.java
@@ -0,0 +1,260 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package xkcd.construction;
+
+import xkcd.construction.comparator.AreaComparator;
+import xkcd.construction.comparator.HeightFirstComparator;
+import xkcd.construction.comparator.WidthFirstComparator;
+import xkcd.rectangle.freespace.ClockwiseSplitFreeSpaceRectangle;
+import xkcd.rectangle.freespace.FreeSpaceFactory;
+import xkcd.rectangle.freespace.FreeSpaceRectangle;
+import xkcd.rectangle.imagepath.PathRectangle;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Hannes
+ */
+public class ImageArranger {
+
+ private double ratio;
+ private final boolean top;
+ private final boolean left;
+
+ private FreeSpaceRectangle currentBounds;
+
+ private final TreeSet freeSpaceArea;
+
+ private final TreeSet widthSortedSet;
+ private final TreeSet heightSortedSet;
+
+ private final Collection placed;
+
+ public ImageArranger() {
+ ratio = 1D;
+ currentBounds = null;
+
+ left = false; //Bug with left = true
+ top = false;
+
+ widthSortedSet = new TreeSet<>(new WidthFirstComparator());
+ heightSortedSet = new TreeSet<>(new HeightFirstComparator());
+
+ freeSpaceArea = new TreeSet<>(new AreaComparator());
+
+ placed = new ArrayList<>();
+
+ }
+
+ /**
+ * Shifts the left top corener to the coordinates (0;0)
+ */
+ private void shiftToLeftTop() {
+ if (currentBounds == null)
+ return;
+ final int x = (int) -currentBounds.getX();
+ final int y = (int) -currentBounds.getY();
+
+ for (final PathRectangle rect : placed) {
+ rect.setX((int) (rect.getX() + x));
+ rect.setY((int) (rect.getY() + y));
+ }
+ currentBounds.setX(0);
+ currentBounds.setY(0);
+ }
+
+ public Collection arrangeRectangles(final Collection rectangles, final double heightToWidthRatio) {
+ System.out.println("Size: " + rectangles);
+ ratio = heightToWidthRatio;
+
+ widthSortedSet.addAll(rectangles);
+ heightSortedSet.addAll(rectangles);
+
+ freeSpaceArea.add(new ClockwiseSplitFreeSpaceRectangle(0, 0, 30000, 15000));
+ //expandAndPlace(getNextPathRectangle(widthSortedSet.last(), heightSortedSet.last()));
+ while (widthSortedSet.size() > 0 && heightSortedSet.size() > 0) {
+ //expandAndPlace(getNextPathRectangle(widthSortedSet.last(), heightSortedSet.last()));
+
+ final Iterator heightIterator = heightSortedSet.descendingIterator();
+ final Iterator widthIterator = widthSortedSet.descendingIterator();
+
+ final Collection pathRectToRemove = new LinkedList<>();
+ boolean oneFree = false;
+
+ while (heightIterator.hasNext() || widthIterator.hasNext()) {
+ PathRectangle tmpPathRect = null;
+ if (heightIterator.hasNext()) {
+ tmpPathRect = heightIterator.next();
+ }
+ if (widthIterator.hasNext()) {
+ if (tmpPathRect == null) {
+ tmpPathRect = widthIterator.next();
+ } else {
+ tmpPathRect = getNextPathRectangle(widthIterator.next(), tmpPathRect);
+ }
+ }
+ final Collection freeSpaceToAdd = new ArrayList<>();
+ for (final Iterator iterator = freeSpaceArea.iterator(); iterator.hasNext(); ) {
+ final FreeSpaceRectangle nextFree = iterator.next();
+ if (nextFree.couldContain(tmpPathRect) && !placed.contains(tmpPathRect)) {
+ //place(nextFree, tmpPathRect, freeSpaceToAdd);
+ oneFree = true;
+
+ iterator.remove();
+ tmpPathRect.setX((int) nextFree.getX());
+ tmpPathRect.setY((int) nextFree.getY());
+
+
+ freeSpaceToAdd.addAll(nextFree.divideUp(tmpPathRect));
+ placed.add(tmpPathRect);
+ System.out.println("Size: " + placed.size());
+ //DEBUG
+ if (Math.abs(tmpPathRect.getWidth() - 612) < 1.0 && Math.abs(tmpPathRect.getHeight() - 6370) < 1.0)
+ System.out.print("EXISTS");
+ //ENDDEBUG
+ System.out.println(tmpPathRect);
+ //System.out.println("Freespace to add: " + freeSpaceToAdd.size());
+
+
+ pathRectToRemove.add(tmpPathRect);
+
+ break;
+ }
+ }
+ freeSpaceArea.addAll(freeSpaceToAdd);
+ }
+ if (!oneFree) {
+ System.out.println("No Space Left");
+ break;
+ }
+ widthSortedSet.removeAll(pathRectToRemove);
+ heightSortedSet.removeAll(pathRectToRemove);
+ //TODO: freeSpaceArea.clear();
+ }
+ shiftToLeftTop();
+
+ //
+ double spaceHeight = 0;
+ double spaceWidth = 0;
+ for (final FreeSpaceRectangle rect : freeSpaceArea) {
+ if (rect.getWidth() + rect.getX() > spaceWidth) {
+ spaceWidth = rect.getWidth() + rect.getX();
+ }
+ if (rect.getHeight() + rect.getY() > spaceHeight) {
+ spaceHeight = rect.getHeight() + rect.getY();
+ }
+ }
+ final double multiplier = 0.1;
+ final BufferedImage bImage = new BufferedImage((int) (spaceWidth * multiplier), (int) (spaceHeight * multiplier), BufferedImage.TYPE_INT_ARGB);
+
+ for (final FreeSpaceRectangle rect : freeSpaceArea) {
+ final Graphics g = bImage.getGraphics();
+
+
+ g.setColor(Color.blue);
+ g.fillRect((int) (rect.getX() * multiplier), (int) (rect.getY() * multiplier), (int) (rect.getWidth() * multiplier), (int) (rect.getHeight() * multiplier));
+ g.setColor(Color.red);
+ g.drawRect((int) (rect.getX() * multiplier), (int) (rect.getY() * multiplier), (int) (rect.getWidth() * multiplier), (int) (rect.getHeight() * multiplier));
+ }
+ try {
+ ImageIO.write(bImage, "png", new File("C:\\Users\\Hannes\\Desktop\\savedNewFreeSpace.png"));
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ //
+ return placed;
+ }
+
+ private PathRectangle getNextPathRectangle(final PathRectangle widthRec, final PathRectangle heightRect) {
+ return (widthRec.getWidth() > heightRect.getHeight())
+ ? widthRec : heightRect;
+ }
+
+ /*
+ private void place(FreeSpaceRectangle freeSpace, PathRectangle toPlace,){
+ freeSpaceArea.remove(freeSpace);
+ freeSpaceArea.addAll(freeSpace.divideUp(toPlace));
+
+ heightSortedSet.remove(toPlace);
+ widthSortedSet.remove(toPlace);
+ placed.add(toPlace);
+
+ toPlace.setX((int) freeSpace.getX());
+ toPlace.setY((int) freeSpace.getY());
+ }*/
+
+ private void expandAndPlace(final PathRectangle rect) {
+ final FreeSpaceFactory factory = new FreeSpaceFactory();
+ if (currentBounds == null) {
+ currentBounds = factory.getFreeSpaceRect(0, 0, (int) rect.getWidth(), (int) rect.getHeight());
+
+ rect.setX(0);
+ rect.setY(0);
+
+ addPlaced(rect);
+ } else {
+ final FreeSpaceRectangle tmpNewFree = factory.getFreeSpaceRect((int) currentBounds.getX(), (int) currentBounds.getY(),
+ (int) currentBounds.getWidth(),
+ (int) currentBounds.getHeight());
+ //Top or Bottom
+ if (rect.height > rect.width) {
+
+ tmpNewFree.setHeight((int) (currentBounds.getHeight() + rect.getHeight()));
+ tmpNewFree.setWidth((int) (tmpNewFree.getHeight() * ratio));
+
+ if (top) {
+ final int x = (int) currentBounds.getX();
+ final int y = (int) (currentBounds.getY() - rect.getHeight());
+
+ rect.setX(x);
+ rect.setY(y);
+ tmpNewFree.setX(x);
+ tmpNewFree.setY(y);
+ } else {
+ rect.setX((int) currentBounds.getX());
+ rect.setY((int) (currentBounds.getY() + currentBounds.getHeight()));
+ }
+ //top = !top;
+ } // Left and Right
+ else {
+ tmpNewFree.setWidth((int) (currentBounds.getWidth() + rect.getWidth()));
+ tmpNewFree.setHeight((int) (tmpNewFree.getWidth() / ratio));
+ if (left) {
+ //TODO look for bug
+ final int x = (int) (currentBounds.getX() - rect.getWidth());
+ final int y = (int) currentBounds.getY();
+
+ rect.setX(x);
+ rect.setY(y);
+ tmpNewFree.setX(x);
+ tmpNewFree.setY(y);
+ } else {
+ rect.setX((int) (currentBounds.getX() + currentBounds.getWidth()));
+ rect.setY((int) currentBounds.getY());
+ }
+ //left = !left;
+ }
+ addPlaced(rect);
+ for (final FreeSpaceRectangle freeSpaceRect : tmpNewFree.divideUp(rect)) {
+ freeSpaceArea.addAll(freeSpaceRect.divideUp(currentBounds));
+ freeSpaceArea.remove(freeSpaceRect);
+ }
+ currentBounds = tmpNewFree;
+ }
+ }
+
+ private void addPlaced(final PathRectangle rect) {
+ widthSortedSet.remove(rect);
+ heightSortedSet.remove(rect);
+ placed.add(rect);
+ System.out.println(rect);
+ }
+}
diff --git a/src/xkcd/construction/ImageDataLoader.java b/src/xkcd/construction/ImageDataLoader.java
new file mode 100644
index 0000000..8be25c1
--- /dev/null
+++ b/src/xkcd/construction/ImageDataLoader.java
@@ -0,0 +1,60 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package xkcd.construction;
+
+import xkcd.rectangle.imagepath.PathRectangle;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author Hannes
+ */
+public class ImageDataLoader {
+ public ImageDataLoader() {
+ }
+
+ public Collection load(final File path) {
+ final Collection rectangles = new ArrayList<>();
+
+ rectangles.addAll(loadFromDirectory(path));
+
+ return rectangles;
+ }
+
+ private Collection loadFromDirectory(final File directory) {
+ final Collection rectangles = new ArrayList<>();
+
+ for (final File fileEntry : directory.listFiles()) {
+ if (fileEntry.isDirectory()) {
+ rectangles.addAll(loadFromDirectory(fileEntry));
+ } else {
+ if (loadFile(fileEntry) != null) {
+ rectangles.add(loadFile(fileEntry));
+ }
+ }
+ }
+ return rectangles;
+ }
+
+ private PathRectangle loadFile(final File file) {
+ try {
+ final BufferedImage tmpImage = ImageIO.read(file);
+ //TODO use correct rotation data of an Image and rotate image if necessary
+ if (tmpImage == null) {
+ return null;
+ }
+ return new PathRectangle(file, 0, 0, tmpImage.getWidth(), tmpImage.getHeight());
+
+ } catch (final IOException ex) {
+ return null;
+ }
+ }
+}
diff --git a/src/xkcd/construction/ImageSticher.java b/src/xkcd/construction/ImageSticher.java
new file mode 100644
index 0000000..b281f29
--- /dev/null
+++ b/src/xkcd/construction/ImageSticher.java
@@ -0,0 +1,79 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package xkcd.construction;
+
+import xkcd.rectangle.imagepath.PathRectangle;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * @author Hannes
+ */
+public class ImageSticher {
+ private final double scaleTo = 1D;
+ private static final int IMAGE_TYPE = BufferedImage.TYPE_4BYTE_ABGR;
+ private static final Color BACKGROUND_COLOR = Color.BLACK;
+
+ private BufferedImage collage;
+ private final Collection rectangles;
+
+ public ImageSticher(final Collection rect) {
+ this.rectangles = rect;
+ System.out.println("Count: " + rectangles.size());
+ this.initBufferedImage();
+ }
+
+ public void saveImage(final File saveFile) throws IOException {
+ initBufferedImage();
+ for (final PathRectangle rectangle : rectangles) {
+ try {
+ final BufferedImage image = loadImage(rectangle.getPath());
+ //System.out.println(rectangle);
+ //DEBUG
+ if (Math.abs(rectangle.getX()) < 1.0 && Math.abs(rectangle.getX() - 6370) < 1.0)
+ System.out.print("EXISTS");
+ //ENDDEBUG
+ collage.getGraphics().drawImage(image, (int) (rectangle.getX() * scaleTo), (int) (rectangle.getY() * scaleTo),
+ (int) (rectangle.getWidth() * scaleTo), (int) (rectangle.getHeight() * scaleTo), null);
+ } catch (final IOException ex) {
+ System.err.println(ex.getMessage());
+ }
+ }
+ ImageIO.write(collage, "png", saveFile);
+ }
+
+ private void initBufferedImage() {
+ int width = 0;
+ int height = 0;
+ for (final PathRectangle rectangle : rectangles) {
+ final int tmpWidth = (int) (rectangle.getWidth() + rectangle.getX());
+ final int tmpHeight = (int) (rectangle.getHeight() + rectangle.getY());
+
+
+ if (tmpWidth > width) {
+ width = tmpWidth;
+ }
+ if (tmpHeight > height) {
+ height = tmpHeight;
+ }
+ }
+
+ collage = new BufferedImage((int) (width * scaleTo), (int) (height * scaleTo), IMAGE_TYPE);
+
+ //collage.getGraphics().setColor(BACKGROUND_COLOR);
+ //collage.getGraphics().drawRect(0, 0, collage.getWidth(), collage.getHeight());
+ //collage.getGraphics().fillRect(0, 0, collage.getWidth(), collage.getHeight());
+ }
+
+ private BufferedImage loadImage(final File filePath) throws IOException {
+ return ImageIO.read(filePath);
+ }
+}
diff --git a/src/xkcd/construction/comparator/AreaComparator.java b/src/xkcd/construction/comparator/AreaComparator.java
new file mode 100644
index 0000000..49ece57
--- /dev/null
+++ b/src/xkcd/construction/comparator/AreaComparator.java
@@ -0,0 +1,22 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package xkcd.construction.comparator;
+
+import java.util.Comparator;
+import xkcd.rectangle.CustomRectangle;
+
+/**
+ *
+ * @author Hannes
+ */
+public class AreaComparator implements Comparator {
+
+ @Override
+ public int compare(CustomRectangle o1, CustomRectangle o2) {
+ return Double.compare(o1.width * o1.height, o2.width * o2.height);
+ }
+
+}
diff --git a/src/xkcd/construction/comparator/HeightFirstComparator.java b/src/xkcd/construction/comparator/HeightFirstComparator.java
new file mode 100644
index 0000000..100b6e5
--- /dev/null
+++ b/src/xkcd/construction/comparator/HeightFirstComparator.java
@@ -0,0 +1,26 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package xkcd.construction.comparator;
+
+import java.util.Comparator;
+import xkcd.rectangle.CustomRectangle;
+
+/**
+ *
+ * @author Hannes
+ */
+public class HeightFirstComparator implements Comparator {
+
+ @Override
+ public int compare(CustomRectangle o1, CustomRectangle o2) {
+ if (Double.compare(o1.getHeight(), o2.getHeight()) == 0) {
+ return Double.compare(o1.getWidth(), o2.getWidth());
+ } else {
+ return Double.compare(o1.getHeight(), o2.getHeight());
+ }
+ }
+
+}
diff --git a/src/xkcd/construction/comparator/WidthFirstComparator.java b/src/xkcd/construction/comparator/WidthFirstComparator.java
new file mode 100644
index 0000000..48b48ff
--- /dev/null
+++ b/src/xkcd/construction/comparator/WidthFirstComparator.java
@@ -0,0 +1,26 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package xkcd.construction.comparator;
+
+import java.util.Comparator;
+import xkcd.rectangle.CustomRectangle;
+
+/**
+ *
+ * @author Hannes
+ */
+public class WidthFirstComparator implements Comparator {
+
+ @Override
+ public int compare(CustomRectangle o1, CustomRectangle o2) {
+ if (Double.compare(o1.getWidth(), o2.getWidth()) == 0) {
+ return Double.compare(o1.getHeight(), o2.getHeight());
+ } else {
+ return Double.compare(o1.getWidth(), o2.getWidth());
+ }
+ }
+
+}
diff --git a/src/xkcd/rectangle/CustomRectangle.java b/src/xkcd/rectangle/CustomRectangle.java
new file mode 100644
index 0000000..3787ffc
--- /dev/null
+++ b/src/xkcd/rectangle/CustomRectangle.java
@@ -0,0 +1,46 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package xkcd.rectangle;
+
+import java.awt.*;
+
+/**
+ * @author Hannes
+ */
+public abstract class CustomRectangle extends Rectangle {
+
+ public CustomRectangle(final int x, final int y, final int width, final int height) {
+ super(x, y, width, height);
+ }
+
+
+ public final void setX(final int x) {
+ this.setLocation(x, (int) this.getY());
+ }
+
+ public final void setY(final int y) {
+ this.setLocation((int) this.getX(), y);
+ }
+
+ public final void setWidth(final int width) {
+ this.setSize(width, (int) this.getHeight());
+ }
+
+ public final void setHeight(final int height) {
+ this.setSize((int) this.getWidth(), height);
+ }
+
+ public final boolean couldContain(final Rectangle rect) {
+ return (rect.getWidth() <= this.getWidth() && rect.getHeight() <= this.getHeight());
+ }
+
+ @Override
+ public String toString() {
+ String str = "";
+ str += "X: " + this.getX() + " Y: " + this.getY() + " w: " + this.getWidth() + " h: " + this.getHeight();
+ return str;
+ }
+}
diff --git a/src/xkcd/rectangle/freespace/ClockwiseSplitFreeSpaceRectangle.java b/src/xkcd/rectangle/freespace/ClockwiseSplitFreeSpaceRectangle.java
new file mode 100644
index 0000000..e2a6c3d
--- /dev/null
+++ b/src/xkcd/rectangle/freespace/ClockwiseSplitFreeSpaceRectangle.java
@@ -0,0 +1,70 @@
+package xkcd.rectangle.freespace;
+
+import xkcd.rectangle.CustomRectangle;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author Hannes
+ */
+public class ClockwiseSplitFreeSpaceRectangle extends FreeSpaceRectangle {
+
+ public ClockwiseSplitFreeSpaceRectangle(final int x, final int y, final int width, final int height) {
+ super(x, y, width, height);
+ }
+
+ @Override
+ public Collection divideUp(final CustomRectangle r) {
+ //System.out.println("Main: " + r.toString());
+ //System.out.println("THIS: " + this.toString());
+ final Collection rectangles = new ArrayList<>();
+ if (!this.contains(r)) {
+ return rectangles;
+ }
+ final FreeSpaceFactory factory = new FreeSpaceFactory();
+
+ //Left
+ int x = 0;
+ int y = 0;
+ int tmpWidth = (int) (r.getX() - this.getX());
+ int tmpHeight = (int) (r.getY() + r.getHeight() - this.getY());
+
+ if (tmpHeight > 0 && tmpWidth > 0) {
+ rectangles.add(factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight));
+ //System.out.println("Left: " + factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight).toString());
+ }
+ //Top
+ x = (int) r.getX();
+ y = (int) this.getY();
+ tmpWidth = (int) (this.getX() + this.getWidth() - r.getX());
+ tmpHeight = (int) (r.getY() - this.getY());
+
+ if (tmpHeight > 0 && tmpWidth > 0) {
+ rectangles.add(factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight));
+ //System.out.println("Top: " + factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight).toString());
+ }
+ //Right
+ x = (int) (r.getX() + r.getWidth());
+ y = (int) r.getY();
+ tmpWidth = (int) (this.getX() + this.getWidth() - (r.getX() + r.getWidth()));
+ tmpHeight = (int) (this.getY() + this.getHeight() - r.getY());
+
+ if (tmpHeight > 0 && tmpWidth > 0) {
+ rectangles.add(factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight));
+ //System.out.println("Right: " + factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight).toString());
+ }
+
+ //Bottom
+ x = (int) this.getX();
+ y = (int) (r.getY() + r.getHeight());
+ tmpWidth = (int) ((r.getX() + r.getWidth()) - this.getX());
+ tmpHeight = (int) (this.getY() + this.getHeight() - (r.getY() + r.getHeight()));
+
+ if (tmpHeight > 0 && tmpWidth > 0) {
+ rectangles.add(factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight));
+ //System.out.println("Bottom: " + factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight).toString());
+ }
+ return rectangles;
+ }
+}
diff --git a/src/xkcd/rectangle/freespace/CounterclockwiseFreeSpaceRectangle.java b/src/xkcd/rectangle/freespace/CounterclockwiseFreeSpaceRectangle.java
new file mode 100644
index 0000000..2033c94
--- /dev/null
+++ b/src/xkcd/rectangle/freespace/CounterclockwiseFreeSpaceRectangle.java
@@ -0,0 +1,70 @@
+package xkcd.rectangle.freespace;
+
+import xkcd.rectangle.CustomRectangle;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author Hannes
+ */
+public class CounterclockwiseFreeSpaceRectangle extends FreeSpaceRectangle {
+
+ public CounterclockwiseFreeSpaceRectangle(final int x, final int y, final int width, final int height) {
+ super(x, y, width, height);
+ }
+
+ @Override
+ public Collection divideUp(final CustomRectangle r) {
+ //System.out.println("Main: " + r.toString());
+ //System.out.println("THIS: " + this.toString());
+ final Collection rectangles = new ArrayList<>();
+ if (!this.contains(r)) {
+ return rectangles;
+ }
+ final FreeSpaceFactory factory = new FreeSpaceFactory();
+
+ //Left
+ int x = 0;
+ int y = 0;
+ int tmpWidth = (int) ((r.getX() + r.getWidth()) - this.getX());
+ int tmpHeight = (int) (r.getY() - this.getY());
+
+ if (tmpHeight > 0 && tmpWidth > 0) {
+ rectangles.add(factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight));
+ //System.out.println("Left: " + factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight).toString());
+ }
+ //Top
+ x = (int) (r.getX() + r.getWidth());
+ y = (int) this.getY();
+ tmpWidth = (int) (this.getX() + this.getWidth() - (r.getX() + r.getWidth()));
+ tmpHeight = (int) (r.getY() + r.getHeight() - this.getY());
+
+ if (tmpHeight > 0 && tmpWidth > 0) {
+ rectangles.add(factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight));
+ //System.out.println("Top: " + factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight).toString());
+ }
+ //Right
+ x = (int) (r.getX());
+ y = (int) (r.getY() + r.getHeight());
+ tmpWidth = (int) (this.getX() + this.getWidth() - r.getX());
+ tmpHeight = (int) (this.getY() + this.getHeight() - (r.getY() + r.getHeight()));
+
+ if (tmpHeight > 0 && tmpWidth > 0) {
+ rectangles.add(factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight));
+ //System.out.println("Right: " + factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight).toString());
+ }
+
+ //Bottom
+ x = (int) this.getX();
+ y = (int) (r.getY());
+ tmpWidth = (int) (r.getX() - this.getX());
+ tmpHeight = (int) (this.getY() + this.getHeight() - r.getY());
+
+ if (tmpHeight > 0 && tmpWidth > 0) {
+ rectangles.add(factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight));
+ //System.out.println("Bottom: " + factory.getFreeSpaceRect(x, y, tmpWidth, tmpHeight).toString());
+ }
+ return rectangles;
+ }
+}
diff --git a/src/xkcd/rectangle/freespace/FreeSpaceFactory.java b/src/xkcd/rectangle/freespace/FreeSpaceFactory.java
new file mode 100644
index 0000000..8062fdd
--- /dev/null
+++ b/src/xkcd/rectangle/freespace/FreeSpaceFactory.java
@@ -0,0 +1,28 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package xkcd.rectangle.freespace;
+
+/**
+ * @author Hannes
+ */
+public class FreeSpaceFactory {
+ private int counter;
+
+ public FreeSpaceFactory() {
+ counter = 0;
+ }
+
+ public FreeSpaceRectangle getFreeSpaceRect(final int x, final int y, final int width, final int height) {
+ counter++;
+ switch (counter % 2) {
+ case 1:
+ return new ClockwiseSplitFreeSpaceRectangle(x, y, width, height);
+ //case 0
+ default:
+ return new CounterclockwiseFreeSpaceRectangle(x, y, width, height);
+ }
+ }
+}
diff --git a/src/xkcd/rectangle/freespace/FreeSpaceRectangle.java b/src/xkcd/rectangle/freespace/FreeSpaceRectangle.java
new file mode 100644
index 0000000..1db7b51
--- /dev/null
+++ b/src/xkcd/rectangle/freespace/FreeSpaceRectangle.java
@@ -0,0 +1,31 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package xkcd.rectangle.freespace;
+
+import java.util.Collection;
+import xkcd.rectangle.CustomRectangle;
+
+/**
+ *
+ * @author Hannes
+ */
+public abstract class FreeSpaceRectangle extends CustomRectangle {
+
+ public FreeSpaceRectangle(int x, int y, int width, int height) {
+ super(x, y, width, height);
+ }
+
+ /**
+ * Method returns the smaller rectangles that will be generated if 'r' is placed inside the xkcd.rectangle
+ * If r is outsdie of this xkcd.rectangle the Collection will conly contain this.
+ * Otherwise it will only contain subrectangles.
+ * @param r
+ * the xkcd.rectangle which is placed and arround which shall be split
+ * @return
+ * xkcd.rectangle
+ */
+ public abstract Collection divideUp(CustomRectangle r);
+}
diff --git a/src/xkcd/rectangle/freespace/LeftRightSplitFreeSpaceRectangle.java b/src/xkcd/rectangle/freespace/LeftRightSplitFreeSpaceRectangle.java
new file mode 100644
index 0000000..740208a
--- /dev/null
+++ b/src/xkcd/rectangle/freespace/LeftRightSplitFreeSpaceRectangle.java
@@ -0,0 +1,17 @@
+package xkcd.rectangle.freespace;
+
+import xkcd.rectangle.CustomRectangle;
+
+import java.util.Collection;
+
+public class LeftRightSplitFreeSpaceRectangle extends FreeSpaceRectangle {
+
+ public LeftRightSplitFreeSpaceRectangle(final int x, final int y, final int width, final int height) {
+ super(x, y, width, height);
+ }
+
+ @Override
+ public Collection divideUp(final CustomRectangle r) {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+}
diff --git a/src/xkcd/rectangle/freespace/OptimalSplitFreeSpaceRectangle.java b/src/xkcd/rectangle/freespace/OptimalSplitFreeSpaceRectangle.java
new file mode 100644
index 0000000..d12ebf0
--- /dev/null
+++ b/src/xkcd/rectangle/freespace/OptimalSplitFreeSpaceRectangle.java
@@ -0,0 +1,20 @@
+package xkcd.rectangle.freespace;
+
+import xkcd.rectangle.CustomRectangle;
+
+import java.util.Collection;
+
+/**
+ * @author Hannes
+ */
+public class OptimalSplitFreeSpaceRectangle extends FreeSpaceRectangle {
+
+ public OptimalSplitFreeSpaceRectangle(final int x, final int y, final int width, final int height) {
+ super(x, y, width, height);
+ }
+
+ @Override
+ public Collection divideUp(final CustomRectangle r) {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+}
diff --git a/src/xkcd/rectangle/freespace/TopBottomSplitFreeSpaceRectangle.java b/src/xkcd/rectangle/freespace/TopBottomSplitFreeSpaceRectangle.java
new file mode 100644
index 0000000..e556e03
--- /dev/null
+++ b/src/xkcd/rectangle/freespace/TopBottomSplitFreeSpaceRectangle.java
@@ -0,0 +1,21 @@
+package xkcd.rectangle.freespace;
+
+import xkcd.rectangle.CustomRectangle;
+
+import java.util.Collection;
+
+/**
+ * @param
+ * @author Hannes
+ */
+public class TopBottomSplitFreeSpaceRectangle extends FreeSpaceRectangle {
+
+ public TopBottomSplitFreeSpaceRectangle(final int x, final int y, final int width, final int height) {
+ super(x, y, width, height);
+ }
+
+ @Override
+ public Collection divideUp(final CustomRectangle r) {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+}
diff --git a/src/xkcd/rectangle/imagepath/PathRectangle.java b/src/xkcd/rectangle/imagepath/PathRectangle.java
new file mode 100644
index 0000000..effb0bb
--- /dev/null
+++ b/src/xkcd/rectangle/imagepath/PathRectangle.java
@@ -0,0 +1,38 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package xkcd.rectangle.imagepath;
+
+import xkcd.rectangle.CustomRectangle;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * @author Hannes
+ */
+public class PathRectangle extends CustomRectangle {
+ private final File path;
+
+ public PathRectangle(final File filePath, final int x, final int y, final int width, final int height) throws FileNotFoundException {
+ super(x, y, width, height);
+ path = filePath;
+ if (!path.exists()) {
+ throw new FileNotFoundException("The filepath is not valid");
+ }
+ }
+
+ /**
+ * @return the path
+ */
+ public File getPath() {
+ return path;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " Path: " + path.toString();
+ }
+}