started work on Editor, and other changes

switched to DataInputStream-based ‘From Bytes’ methods, instead of
byte[] array-based.
This commit is contained in:
BuildTools 2017-01-11 14:08:08 -05:00
parent e17a949a53
commit 744d206a6a
9 changed files with 272 additions and 101 deletions

View file

@ -1,6 +1,19 @@
package regions;
import java.util.List;
public abstract class Directory
{
String name;
public final Directory parent;
public final List<Directory> children;
public final List<Tree> trees;
public Directory(String name, Directory parent, List<Directory> children, List<Tree> trees)
{
this.name = name;
this.parent = parent;
this.children = children;
this.trees = trees;
}
}

View file

@ -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);
}
}

View file

@ -0,0 +1,11 @@
package regions;
public class OctreeEditor implements TreeEditor
{
private final Octree tree;
OctreeEditor(Octree tree)
{
this.tree = tree;
}
}

View file

@ -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<Directory> children;
public final List<Tree> trees;
public Owner(String name, Directory parent, List<Directory> children, List<Tree> trees)
{
this.name = name;
this.parent = parent;
this.children = children;
this.trees = trees;
}
}

View file

@ -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);
}
}

View file

@ -0,0 +1,11 @@
package regions;
public class QuadtreeEditor implements TreeEditor
{
private final Quadtree tree;
QuadtreeEditor(Quadtree tree)
{
this.tree = tree;
}
}

View file

@ -1,6 +0,0 @@
package regions;
public class RegionTreeEditor
{
}

View file

@ -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
* <tt>Node parseBytes()</tt>, 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.<p>
*
* Given a byte array, interprets each byte as four 2-bit values, where 00 = partially full,
* 01 = empty (<tt>false</tt>) and 10 = full (<tt>true</tt>). Octree nodes use 2 bytes
* each, Quadtree nodes use 1 byte each. Assumes a depth-first arrangement.<p>
* Interprets each byte as four 2-bit values, where 00 = partial, 01 = empty (<tt>false</tt>)
* and 10 = full (<tt>true</tt>). Octree nodes use 2 bytes each, Quadtree nodes use 1 byte each.
* Assumes a depth-first arrangement.<p>
*
* @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
* <tt>Node parseBytes(IntReference index, byte[] bytes, int parentByte)</tt><p>
* Interprets each byte as four 2-bit values, where 00 = partial, 01 = empty (<tt>false</tt>)
* and 10 = full (<tt>true</tt>). Octree nodes use 2 bytes each, Quadtree nodes use 1 byte each.
* Assumes a depth-first arrangement.<p>
*
* Given a byte array, interprets each byte as four 2-bit values, where 00 = partially full,
* 01 = empty (<tt>false</tt>) and 10 = full (<tt>true</tt>). Octree nodes use 2 bytes
* each, Quadtree nodes use 1 byte each. Assumes a depth-first arrangement.<p>
*
* @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
* <tt>Node parseBytes(IntReference index, byte[] bytes, int parentByte)</tt><p>
* Interprets each byte as four 2-bit values, where 00 = partial, 01 = empty (<tt>false</tt>)
* and 10 = full (<tt>true</tt>). Octree nodes use 2 bytes each, Quadtree nodes use 1 byte each.
* Assumes a depth-first arrangement.<p>
*
* Given a byte array, interprets each byte as four 2-bit values, where 00 = partially full,
* 01 = empty (<tt>false</tt>) and 10 = full (<tt>true</tt>). Octree nodes use 2 bytes
* each, Quadtree nodes use 1 byte each. Assumes a depth-first arrangement.<p>
*
* @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
* <tt>{@link #getByte(Node, Node, Node, Node) getByte(children)}</tt> for each encountered
* node in the tree, skipping childless nodes.<p>
*
* 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
* <tt>{@link #getByte(Node, Node, Node, Node) getByte(children)}</tt> for each encountered
* node in the tree, skipping childless nodes.<p>
*
* @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
* <tt>{@link #getByte(Node, Node, Node, Node) getByte(children)}</tt> for each encountered
* node in the tree, skipping childless nodes.<p>
*
* 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 <tt>{@link #writeBytes(Node, OutputStream)}</tt>, 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
* <tt>{@link #getByte(Node, Node, Node, Node) getByte(children)}</tt> for each encountered
* node in the tree, skipping childless nodes.<p>
*
* 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 <tt>{@link #writeBytes(Node, OutputStream)}</tt> 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 <tt>{@link #writeBytes(Node, OutputStream)}</tt> 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 <tt>{@link #writeBytes(Node, OutputStream)}</tt> 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 <tt>{@link #writeBytes(Node, OutputStream)}</tt> 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].<p>
*
* <b>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();
}

View file

@ -0,0 +1,16 @@
package regions;
/**
*
*
* @author Kevin Mathewson
*
*/
public interface TreeEditor
{
public abstract class ChangeQueue<T extends Edit>{}
public abstract class Edit{}
public void edit(Edit edit);
}