diff --git a/src/regions/Directory.java b/src/regions/Directory.java index dd3fa51..e9d9b22 100644 --- a/src/regions/Directory.java +++ b/src/regions/Directory.java @@ -1,6 +1,19 @@ package regions; +import java.util.List; + public abstract class Directory { - + String name; + public final Directory parent; + public final List children; + public final List trees; + + public Directory(String name, Directory parent, List children, List trees) + { + this.name = name; + this.parent = parent; + this.children = children; + this.trees = trees; + } } diff --git a/src/regions/Octree.java b/src/regions/Octree.java index b46dd9d..6f451c4 100644 --- a/src/regions/Octree.java +++ b/src/regions/Octree.java @@ -1,5 +1,7 @@ package regions; +import java.io.DataInputStream; +import java.io.File; import java.io.IOException; import java.io.OutputStream; @@ -11,23 +13,25 @@ public class Octree extends Tree ------------------------------------------------------------------------------ ----------------------------------------------------------------------------*/ - Node parseBytes(IntReference index, byte[] bytes, int parentByte) + public Node parseBytes(DataInputStream input, int parentByte) throws IOException { if (parentByte == 0b00000010) return new Node(true); if (parentByte == 0b00000001) return new Node(false); - byte a = bytes[index.ref++], - b = bytes[index.ref++]; + int a = input.read(), + b = input.read(); - return new Node( new Node[] { parseBytes(index, bytes, (a >>> 6 & 3)), - parseBytes(index, bytes, (a >>> 4 & 3)), - parseBytes(index, bytes, (a >>> 2 & 3)), - parseBytes(index, bytes, (a & 3)), + return a == -1 || b == -1 ? + new Node( false ) : + new Node( new Node[] { parseBytes(input, (a >>> 6 & 3)), + parseBytes(input, (a >>> 4 & 3)), + parseBytes(input, (a >>> 2 & 3)), + parseBytes(input, (a & 3)), - parseBytes(index, bytes, (b >>> 6 & 3)), - parseBytes(index, bytes, (b >>> 4 & 3)), - parseBytes(index, bytes, (b >>> 2 & 3)), - parseBytes(index, bytes, (b & 3)) + parseBytes(input, (b >>> 6 & 3)), + parseBytes(input, (b >>> 4 & 3)), + parseBytes(input, (b >>> 2 & 3)), + parseBytes(input, (b & 3)) }); } @@ -66,8 +70,12 @@ public class Octree extends Tree ------------------------------------------------------------------------------ ----------------------------------------------------------------------------*/ - public Octree(Owner owner, byte[] bytes) + public Octree(int[][] bounds, File file, byte[] bytes) { - super(owner, bytes); + super(bounds, file); + } + OctreeEditor newEditor() + { + return new OctreeEditor(this); } } diff --git a/src/regions/OctreeEditor.java b/src/regions/OctreeEditor.java new file mode 100644 index 0000000..67333eb --- /dev/null +++ b/src/regions/OctreeEditor.java @@ -0,0 +1,11 @@ +package regions; + +public class OctreeEditor implements TreeEditor +{ + private final Octree tree; + + OctreeEditor(Octree tree) + { + this.tree = tree; + } +} diff --git a/src/regions/Owner.java b/src/regions/Owner.java deleted file mode 100644 index 4cd1c0a..0000000 --- a/src/regions/Owner.java +++ /dev/null @@ -1,19 +0,0 @@ -package regions; - -import java.util.List; - -public class Owner extends Directory -{ - public final String name; - public final Directory parent; - public final List children; - public final List trees; - - public Owner(String name, Directory parent, List children, List trees) - { - this.name = name; - this.parent = parent; - this.children = children; - this.trees = trees; - } -} diff --git a/src/regions/Quadtree.java b/src/regions/Quadtree.java index 1e30f3f..c6b5bb9 100644 --- a/src/regions/Quadtree.java +++ b/src/regions/Quadtree.java @@ -1,5 +1,7 @@ package regions; +import java.io.DataInputStream; +import java.io.File; import java.io.IOException; import java.io.OutputStream; @@ -11,17 +13,19 @@ public class Quadtree extends Tree ------------------------------------------------------------------------------ ----------------------------------------------------------------------------*/ - Node parseBytes(IntReference index, byte[] bytes, int parentByte) + public Node parseBytes(DataInputStream input, int parentByte) throws IOException { if (parentByte == 0b00000010) return new Node(true); if (parentByte == 0b00000001) return new Node(false); - byte a = bytes[index.ref++]; + int a = input.read(); - return new Node( new Node[] { parseBytes(index, bytes, (a >>> 6 & 3)), - parseBytes(index, bytes, (a >>> 4 & 3)), - parseBytes(index, bytes, (a >>> 2 & 3)), - parseBytes(index, bytes, (a & 3)) + return a == -1 ? + new Node( false ) : + new Node( new Node[] { parseBytes(input, (a >>> 6 & 3)), + parseBytes(input, (a >>> 4 & 3)), + parseBytes(input, (a >>> 2 & 3)), + parseBytes(input, (a & 3)) }); } @@ -54,8 +58,12 @@ public class Quadtree extends Tree ------------------------------------------------------------------------------ ----------------------------------------------------------------------------*/ - public Quadtree(Owner owner, byte[] bytes) + public Quadtree(int[][] bounds, File file) { - super(owner, bytes); + super(bounds, file); + } + public QuadtreeEditor newEditor() + { + return new QuadtreeEditor(this); } } diff --git a/src/regions/QuadtreeEditor.java b/src/regions/QuadtreeEditor.java new file mode 100644 index 0000000..24ae6ff --- /dev/null +++ b/src/regions/QuadtreeEditor.java @@ -0,0 +1,11 @@ +package regions; + +public class QuadtreeEditor implements TreeEditor +{ + private final Quadtree tree; + + QuadtreeEditor(Quadtree tree) + { + this.tree = tree; + } +} diff --git a/src/regions/RegionTreeEditor.java b/src/regions/RegionTreeEditor.java deleted file mode 100644 index e4001e7..0000000 --- a/src/regions/RegionTreeEditor.java +++ /dev/null @@ -1,6 +0,0 @@ -package regions; - -public class RegionTreeEditor -{ - -} diff --git a/src/regions/Tree.java b/src/regions/Tree.java index d110e02..3b2e15f 100644 --- a/src/regions/Tree.java +++ b/src/regions/Tree.java @@ -1,7 +1,10 @@ package regions; +import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -46,12 +49,16 @@ public abstract class Tree this.full = full; this.children = new Node[0]; } - public Node(Node[] nodes) { this.full = false; this.children = nodes; } + public Node() + { + this.full = false; + this.children = new Node[0]; + } } @@ -64,70 +71,59 @@ public abstract class Tree ----------------------------------------------------------------------------*/ - /** - * Defines an object containing a single int field. Used by the nested, recursive method - * Node parseBytes(), so all the child-calls and parent-calls of the method can - * refer to the same integer, representing the current index within the parsed byte array. - */ - static final class IntReference - { - int ref; - - IntReference(int i) - { - this.ref = i; - } - } - - /** * An abstract method, implemented slightly differently by octrees and quadtrees because * octrees have 8 branches per node and quadtrees only 4.

* - * Given a byte array, interprets each byte as four 2-bit values, where 00 = partially full, - * 01 = empty (false) and 10 = full (true). Octree nodes use 2 bytes - * each, Quadtree nodes use 1 byte each. Assumes a depth-first arrangement.

+ * Interprets each byte as four 2-bit values, where 00 = partial, 01 = empty (false) + * and 10 = full (true). Octree nodes use 2 bytes each, Quadtree nodes use 1 byte each. + * Assumes a depth-first arrangement.

* - * @param index current position in the byte array - * @param bytes byte array, presumably read from a binary file - * @param parentByte the 2-bit value (00000010, 00000001 or 00000000) + * @param input DataInputStream of source bytes + * @param parentBits the 2-bit value (00, 01, or 10) * @return a new Node + * @throws IOException */ - abstract Node parseBytes(IntReference index, byte[] bytes, int parentByte); + public abstract Node parseBytes(DataInputStream input, int parentBits) throws IOException; /** - * A simplified public alias for the package-private abstract method - * Node parseBytes(IntReference index, byte[] bytes, int parentByte)

+ * Interprets each byte as four 2-bit values, where 00 = partial, 01 = empty (false) + * and 10 = full (true). Octree nodes use 2 bytes each, Quadtree nodes use 1 byte each. + * Assumes a depth-first arrangement.

* - * Given a byte array, interprets each byte as four 2-bit values, where 00 = partially full, - * 01 = empty (false) and 10 = full (true). Octree nodes use 2 bytes - * each, Quadtree nodes use 1 byte each. Assumes a depth-first arrangement.

- * - * @param startAtIndex where in the byte[] array to begin - * @param bytes byte array, presumably read from a binary file + * @param input DataInputStream containing source bytes * @return a new Node */ - public Node parseBytes(int startAtIndex, byte[] bytes) + public Node parseBytes(DataInputStream input) { - return parseBytes ( new IntReference(startAtIndex), bytes, 0 ); + try { return parseBytes(input, 0); } + catch (IOException e) { return new Node(); } } /** - * A simplified public alias for the package-private abstract method - * Node parseBytes(IntReference index, byte[] bytes, int parentByte)

+ * Interprets each byte as four 2-bit values, where 00 = partial, 01 = empty (false) + * and 10 = full (true). Octree nodes use 2 bytes each, Quadtree nodes use 1 byte each. + * Assumes a depth-first arrangement.

* - * Given a byte array, interprets each byte as four 2-bit values, where 00 = partially full, - * 01 = empty (false) and 10 = full (true). Octree nodes use 2 bytes - * each, Quadtree nodes use 1 byte each. Assumes a depth-first arrangement.

- * - * @param bytes byte array, presumably read from a binary file + * @param file binary file to read bytes from * @return a new Node */ - public Node parseBytes(byte[] bytes) + public Node parseBytes(File file) { - return parseBytes ( new IntReference(0), bytes, 0 ); + if (file.getUsableSpace() == 0) + { + return new Node(); + } + try + { + return parseBytes(new DataInputStream(new BufferedInputStream(new FileInputStream(file)))); + } + catch (FileNotFoundException e) + { + return new Node(); + } } @@ -192,15 +188,31 @@ public abstract class Tree public abstract void writeBytes(Node node, OutputStream output); + + /*------------------------------------- + OVERLOADS : getBytes() + -------------------------------------*/ /** - * Parses the tree rooted at this node, appending in depth-first order the result of invoking + * Parses the tree from the root, appending in depth-first order the result of invoking * {@link #getByte(Node, Node, Node, Node) getByte(children)} for each encountered * node in the tree, skipping childless nodes.

* - * Writes to a ByteArrayOutputStream. + * @return byte array representing the root node and all its child nodes + */ + public byte[] getBytes() + { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + writeBytes(root, output); + return output.toByteArray(); + } + + /** + * Parses the tree from this node, appending in depth-first order the result of invoking + * {@link #getByte(Node, Node, Node, Node) getByte(children)} for each encountered + * node in the tree, skipping childless nodes.

* - * @param node the root node of the tree to be parsed - * @return a byte array representing the root node and all its child nodes + * @param node the node to parse from + * @return byte array representing the root node and all its child nodes */ public byte[] getBytes(Node node) { @@ -209,10 +221,104 @@ public abstract class Tree return output.toByteArray(); } + /** + * Parses the tree from the root, appending in depth-first order the result of invoking + * {@link #getByte(Node, Node, Node, Node) getByte(children)} for each encountered + * node in the tree, skipping childless nodes.

+ * + * Writes to the given ByteArrayOutputStream. + * + * @param output the ByteArrayOutputStream to write to + * @return byte array representing the root node and all its child nodes + */ + public byte[] getBytes(ByteArrayOutputStream output) + { + writeBytes(root, output); + return output.toByteArray(); + } /** - * Performs {@link #writeBytes(Node, OutputStream)}, using a FileOutputStream of the - * given file as the OutputStream argument. + * Parses the tree from this node, appending in depth-first order the result of invoking + * {@link #getByte(Node, Node, Node, Node) getByte(children)} for each encountered + * node in the tree, skipping childless nodes.

+ * + * Writes to the given ByteArrayOutputStream. + * + * @param node the node to parse from + * @param output the ByteArrayOutputStream to write to + * @return byte array representing the root node and all its child nodes + */ + public byte[] getBytes(Node node, ByteArrayOutputStream output) + { + writeBytes(node, output); + return output.toByteArray(); + } + + + + /*------------------------------------- + OVERLOADS : saveToFile() + -------------------------------------*/ + /** + * Performs {@link #writeBytes(Node, OutputStream)} from the root node, using a + * FileOutputStream of the source file as the OutputStream argument. + * + * @param node the root node of the tree to be parsed + * @param destination the file to save to + */ + public void saveToFile() + { + try + { + FileOutputStream output = new FileOutputStream (file, true); + writeBytes(root, output); + output.close(); + } + catch (FileNotFoundException e) { e.printStackTrace(); } + catch (IOException e) { e.printStackTrace(); } + } + + /** + * Performs {@link #writeBytes(Node, OutputStream)} from the given node, using a + * FileOutputStream of the source file as the OutputStream argument. + * + * @param node the root node of the tree to be parsed + * @param destination the file to save to + */ + public void saveToFile(Node node) + { + try + { + FileOutputStream output = new FileOutputStream (file, true); + writeBytes(node, output); + output.close(); + } + catch (FileNotFoundException e) { e.printStackTrace(); } + catch (IOException e) { e.printStackTrace(); } + } + + /** + * Performs {@link #writeBytes(Node, OutputStream)} from the root node, using a + * FileOutputStream of the given file as the OutputStream argument. + * + * @param node the root node of the tree to be parsed + * @param destination the file to save to + */ + public void saveToFile(File destination) + { + try + { + FileOutputStream output = new FileOutputStream (destination, true); + writeBytes(root, output); + output.close(); + } + catch (FileNotFoundException e) { e.printStackTrace(); } + catch (IOException e) { e.printStackTrace(); } + } + + /** + * Performs {@link #writeBytes(Node, OutputStream)} from the given node, using a + * FileOutputStream of the given file as the OutputStream argument. * * @param node the root node of the tree to be parsed * @param destination the file to save to @@ -238,12 +344,35 @@ public abstract class Tree ----------------------------------------------------------------------------*/ - public final Owner owner; - public final Node root; + /** + * Minimum and maximum bounds [ [min] [max] ]. + * Quadtrees store [x,z], Octrees store [x,z,y]. + */ + public int[][] bounds; + /** + * Minimum and maximum bounds [ [min] [max] ]. + * Quadtrees store [x,z], Octrees store [x,z,y].

+ * + * Bounds of the shape itself, + * not including empty nodes. + */ + public int[][] boundsTrue; + public final File file; + public final Node root; + public final TreeEditor editor; - public Tree(Owner owner, byte[] bytes) + public Tree(int[][] bounds, File file) { - this.owner = owner; - this.root = parseBytes(bytes); + this.bounds = bounds; + this.file = file; + this.root = parseBytes(file); + this.editor = newEditor(); } + + /** + * An abstract method, returning a new subclass-specific + * instance implementing the interface TreeEditor + * @return a new TreeEditor + */ + abstract TreeEditor newEditor(); } diff --git a/src/regions/TreeEditor.java b/src/regions/TreeEditor.java new file mode 100644 index 0000000..f8b9c3e --- /dev/null +++ b/src/regions/TreeEditor.java @@ -0,0 +1,16 @@ +package regions; + +/** + * + * + * @author Kevin Mathewson + * + */ +public interface TreeEditor +{ + public abstract class ChangeQueue{} + + public abstract class Edit{} + + public void edit(Edit edit); +}