mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-10 17:22:09 +10:00
Cleanup
This commit is contained in:
@@ -34,6 +34,10 @@ import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
|||||||
*/
|
*/
|
||||||
public class FontConverter extends com.thoughtworks.xstream.converters.extended.FontConverter {
|
public class FontConverter extends com.thoughtworks.xstream.converters.extended.FontConverter {
|
||||||
|
|
||||||
|
public FontConverter() {
|
||||||
|
super(null);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void marshal(Object object, HierarchicalStreamWriter writer, MarshallingContext context) {
|
public void marshal(Object object, HierarchicalStreamWriter writer, MarshallingContext context) {
|
||||||
Font f = (Font) object;
|
Font f = (Font) object;
|
||||||
|
|||||||
@@ -13,18 +13,20 @@ import java.util.Queue;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of an arbitrary-dimension RTree. Based on R-Trees: A Dynamic
|
* Implementation of an arbitrary-dimension RTree. Based on R-Trees: A Dynamic Index Structure for
|
||||||
* Index Structure for Spatial Searching (Antonn Guttmann, 1984)
|
* Spatial Searching (Antonn Guttmann, 1984)
|
||||||
* <p>
|
* <p>
|
||||||
* This class is not thread-safe.
|
* This class is not thread-safe.
|
||||||
* <p>
|
* <p>
|
||||||
* Copyright 2010 Russ Weeks rweeks@newbrightidea.com Licensed under the GNU
|
* Copyright 2010 Russ Weeks rweeks@newbrightidea.com Licensed under the GNU LGPL License details
|
||||||
* LGPL License details here: http://www.gnu.org/licenses/lgpl-3.0.txt
|
* here: http://www.gnu.org/licenses/lgpl-3.0.txt
|
||||||
*
|
*
|
||||||
* @param <T> the type of entry to store in this RTree.
|
* @param <T> the type of entry to store in this RTree.
|
||||||
*/
|
*/
|
||||||
public class RTree<T> {
|
public class RTree<T> {
|
||||||
public enum SeedPicker {LINEAR, QUADRATIC}
|
public enum SeedPicker {
|
||||||
|
LINEAR, QUADRATIC
|
||||||
|
}
|
||||||
|
|
||||||
private final int maxEntries;
|
private final int maxEntries;
|
||||||
private final int minEntries;
|
private final int minEntries;
|
||||||
@@ -70,8 +72,8 @@ public class RTree<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a new RTree using default parameters: maximum 50 entries per node
|
* Builds a new RTree using default parameters: maximum 50 entries per node minimum 2 entries per
|
||||||
* minimum 2 entries per node 2 dimensions
|
* node 2 dimensions
|
||||||
*/
|
*/
|
||||||
public RTree() {
|
public RTree() {
|
||||||
this(50, 2, 2, SeedPicker.LINEAR);
|
this(50, 2, 2, SeedPicker.LINEAR);
|
||||||
@@ -85,8 +87,7 @@ public class RTree<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the minimum number of entries per node for all nodes except the
|
* @return the minimum number of entries per node for all nodes except the root.
|
||||||
* root.
|
|
||||||
*/
|
*/
|
||||||
public int getMinEntries() {
|
public int getMinEntries() {
|
||||||
return minEntries;
|
return minEntries;
|
||||||
@@ -109,11 +110,10 @@ public class RTree<T> {
|
|||||||
/**
|
/**
|
||||||
* Searches the RTree for objects overlapping with the given rectangle.
|
* Searches the RTree for objects overlapping with the given rectangle.
|
||||||
*
|
*
|
||||||
* @param coords the corner of the rectangle that is the lower bound of every
|
* @param coords the corner of the rectangle that is the lower bound of every dimension (eg. the
|
||||||
* dimension (eg. the top-left corner)
|
* top-left corner)
|
||||||
* @param dimensions the dimensions of the rectangle.
|
* @param dimensions the dimensions of the rectangle.
|
||||||
* @return a list of objects whose rectangles overlap with the given
|
* @return a list of objects whose rectangles overlap with the given rectangle.
|
||||||
* rectangle.
|
|
||||||
*/
|
*/
|
||||||
public List<T> search(float[] coords, float[] dimensions) {
|
public List<T> search(float[] coords, float[] dimensions) {
|
||||||
assert (coords.length == numDims);
|
assert (coords.length == numDims);
|
||||||
@@ -125,16 +125,17 @@ public class RTree<T> {
|
|||||||
|
|
||||||
public List<T> search(Area area) {
|
public List<T> search(Area area) {
|
||||||
Rectangle2D bounds2D = area.getBounds2D();
|
Rectangle2D bounds2D = area.getBounds2D();
|
||||||
return search(new float[] { (float) bounds2D.getMinX(), (float) bounds2D.getMinY() } , new float[] { (float) bounds2D.getWidth(), (float) bounds2D.getHeight() });
|
return search(new float[] {(float) bounds2D.getMinX(), (float) bounds2D.getMinY()},
|
||||||
|
new float[] {(float) bounds2D.getWidth(), (float) bounds2D.getHeight()});
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<T> search(Point2D point, double t) {
|
public List<T> search(Point2D point, double t) {
|
||||||
return search(new float[] { (float) (point.getX() - t / 2), (float) (point.getY() - t / 2) },
|
return search(new float[] {(float) (point.getX() - t / 2), (float) (point.getY() - t / 2)},
|
||||||
new float[] { (float) t, (float) t });
|
new float[] {(float) t, (float) t});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void search(float[] coords, float[] dimensions, Node n,
|
@SuppressWarnings("unchecked")
|
||||||
LinkedList<T> results) {
|
private void search(float[] coords, float[] dimensions, Node n, LinkedList<T> results) {
|
||||||
if (n.leaf) {
|
if (n.leaf) {
|
||||||
for (Node e : n.children) {
|
for (Node e : n.children) {
|
||||||
if (isOverlap(coords, dimensions, e.coords, e.dimensions)) {
|
if (isOverlap(coords, dimensions, e.coords, e.dimensions)) {
|
||||||
@@ -153,8 +154,7 @@ public class RTree<T> {
|
|||||||
/**
|
/**
|
||||||
* Deletes the entry associated with the given rectangle from the RTree
|
* Deletes the entry associated with the given rectangle from the RTree
|
||||||
*
|
*
|
||||||
* @param coords the corner of the rectangle that is the lower bound in every
|
* @param coords the corner of the rectangle that is the lower bound in every dimension
|
||||||
* dimension
|
|
||||||
* @param dimensions the dimensions of the rectangle
|
* @param dimensions the dimensions of the rectangle
|
||||||
* @param entry the entry to delete
|
* @param entry the entry to delete
|
||||||
* @return true iff the entry was deleted from the RTree.
|
* @return true iff the entry was deleted from the RTree.
|
||||||
@@ -194,6 +194,7 @@ public class RTree<T> {
|
|||||||
return delete(coords, pointDims, entry);
|
return delete(coords, pointDims, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
private Node findLeaf(Node n, float[] coords, float[] dimensions, T entry) {
|
private Node findLeaf(Node n, float[] coords, float[] dimensions, T entry) {
|
||||||
if (n.leaf) {
|
if (n.leaf) {
|
||||||
for (Node c : n.children) {
|
for (Node c : n.children) {
|
||||||
@@ -263,11 +264,9 @@ public class RTree<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts the given entry into the RTree, associated with the given
|
* Inserts the given entry into the RTree, associated with the given rectangle.
|
||||||
* rectangle.
|
|
||||||
*
|
*
|
||||||
* @param coords the corner of the rectangle that is the lower bound in every
|
* @param coords the corner of the rectangle that is the lower bound in every dimension
|
||||||
* dimension
|
|
||||||
* @param dimensions the dimensions of the rectangle
|
* @param dimensions the dimensions of the rectangle
|
||||||
* @param entry the entry to insert
|
* @param entry the entry to insert
|
||||||
*/
|
*/
|
||||||
@@ -294,8 +293,8 @@ public class RTree<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void insert(Point2D p, double t, T entry) {
|
public void insert(Point2D p, double t, T entry) {
|
||||||
insert(new float[] {(float) (p.getX() - t / 2), (float) (p.getY() - t /2) },
|
insert(new float[] {(float) (p.getX() - t / 2), (float) (p.getY() - t / 2)},
|
||||||
new float[] {(float) t, (float) t }, entry);
|
new float[] {(float) t, (float) t}, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -308,11 +307,12 @@ public class RTree<T> {
|
|||||||
insert(coords, pointDims, entry);
|
insert(coords, pointDims, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void visit(NodeVisitor<T> nv) {
|
public void visit(NodeVisitor<T> nv) {
|
||||||
float[] coordBuf = new float[numDims];
|
float[] coordBuf = new float[numDims];
|
||||||
float[] dimBuf = new float[numDims];
|
float[] dimBuf = new float[numDims];
|
||||||
Queue<Node> toVisit = new LinkedList<>();
|
Queue<Node> toVisit = new LinkedList<>();
|
||||||
Map<Node,Integer> nodeDepths = new HashMap<>();
|
Map<Node, Integer> nodeDepths = new HashMap<>();
|
||||||
nodeDepths.put(root, 0);
|
nodeDepths.put(root, 0);
|
||||||
toVisit.add(root);
|
toVisit.add(root);
|
||||||
while (!toVisit.isEmpty()) {
|
while (!toVisit.isEmpty()) {
|
||||||
@@ -323,7 +323,7 @@ public class RTree<T> {
|
|||||||
System.arraycopy(currentNode.coords, 0, coordBuf, 0, numDims);
|
System.arraycopy(currentNode.coords, 0, coordBuf, 0, numDims);
|
||||||
System.arraycopy(currentNode.dimensions, 0, dimBuf, 0, numDims);
|
System.arraycopy(currentNode.dimensions, 0, dimBuf, 0, numDims);
|
||||||
if (currentNode instanceof RTree.Entry) {
|
if (currentNode instanceof RTree.Entry) {
|
||||||
nv.visit(nodeDepths.get(currentNode), coordBuf, dimBuf, ((Entry)currentNode).entry);
|
nv.visit(nodeDepths.get(currentNode), coordBuf, dimBuf, ((Entry) currentNode).entry);
|
||||||
} else {
|
} else {
|
||||||
nv.visit(nodeDepths.get(currentNode), coordBuf, dimBuf, null);
|
nv.visit(nodeDepths.get(currentNode), coordBuf, dimBuf, null);
|
||||||
}
|
}
|
||||||
@@ -367,8 +367,7 @@ public class RTree<T> {
|
|||||||
// could be modified and inlined because it's only adjusting for the addition
|
// could be modified and inlined because it's only adjusting for the addition
|
||||||
// of a single node. Left as-is for now for readability.
|
// of a single node. Left as-is for now for readability.
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Node[] nn = new RTree.Node[]
|
Node[] nn = new RTree.Node[] {n, new Node(n.coords, n.dimensions, n.leaf)};
|
||||||
{n, new Node(n.coords, n.dimensions, n.leaf)};
|
|
||||||
nn[1].parent = n.parent;
|
nn[1].parent = n.parent;
|
||||||
if (nn[1].parent != null) {
|
if (nn[1].parent != null) {
|
||||||
nn[1].parent.children.add(nn[1]);
|
nn[1].parent.children.add(nn[1]);
|
||||||
@@ -431,7 +430,8 @@ public class RTree<T> {
|
|||||||
float maxWaste = -1.0f * Float.MAX_VALUE;
|
float maxWaste = -1.0f * Float.MAX_VALUE;
|
||||||
for (Node n1 : nn) {
|
for (Node n1 : nn) {
|
||||||
for (Node n2 : nn) {
|
for (Node n2 : nn) {
|
||||||
if (n1 == n2) continue;
|
if (n1 == n2)
|
||||||
|
continue;
|
||||||
float n1a = getArea(n1.dimensions);
|
float n1a = getArea(n1.dimensions);
|
||||||
float n2a = getArea(n2.dimensions);
|
float n2a = getArea(n2.dimensions);
|
||||||
float ja = 1.0f;
|
float ja = 1.0f;
|
||||||
@@ -456,7 +456,8 @@ public class RTree<T> {
|
|||||||
/**
|
/**
|
||||||
* Implementation of QuadraticPickNext
|
* Implementation of QuadraticPickNext
|
||||||
*
|
*
|
||||||
* @param cc the children to be divided between the new nodes, one item will be removed from this list.
|
* @param cc the children to be divided between the new nodes, one item will be removed from this
|
||||||
|
* list.
|
||||||
* @param nn the candidate nodes for the children to be added to.
|
* @param nn the candidate nodes for the children to be added to.
|
||||||
*/
|
*/
|
||||||
private Node qPickNext(LinkedList<Node> cc, Node[] nn) {
|
private Node qPickNext(LinkedList<Node> cc, Node[] nn) {
|
||||||
@@ -477,8 +478,8 @@ public class RTree<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of LinearPickSeeds
|
// Implementation of LinearPickSeeds
|
||||||
private RTree<T>.Node[] lPickSeeds(LinkedList<Node> nn) {
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
private RTree<T>.Node[] lPickSeeds(LinkedList<Node> nn) {
|
||||||
RTree<T>.Node[] bestPair = new RTree.Node[2];
|
RTree<T>.Node[] bestPair = new RTree.Node[2];
|
||||||
boolean foundBestPair = false;
|
boolean foundBestPair = false;
|
||||||
float bestSep = 0.0f;
|
float bestSep = 0.0f;
|
||||||
@@ -502,8 +503,7 @@ public class RTree<T> {
|
|||||||
nMinUb = n;
|
nMinUb = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float sep = (nMaxLb == nMinUb) ? -1.0f :
|
float sep = (nMaxLb == nMinUb) ? -1.0f : Math.abs((dimMinUb - dimMaxLb) / (dimUb - dimLb));
|
||||||
Math.abs((dimMinUb - dimMaxLb) / (dimUb - dimLb));
|
|
||||||
if (sep >= bestSep) {
|
if (sep >= bestSep) {
|
||||||
bestPair[0] = nMaxLb;
|
bestPair[0] = nMaxLb;
|
||||||
bestPair[1] = nMinUb;
|
bestPair[1] = nMinUb;
|
||||||
@@ -515,7 +515,7 @@ public class RTree<T> {
|
|||||||
// algorithm does not find a best pair. Just pick the first 2
|
// algorithm does not find a best pair. Just pick the first 2
|
||||||
// children.
|
// children.
|
||||||
if (!foundBestPair) {
|
if (!foundBestPair) {
|
||||||
bestPair = new RTree.Node[]{nn.get(0), nn.get(1)};
|
bestPair = new RTree.Node[] {nn.get(0), nn.get(1)};
|
||||||
}
|
}
|
||||||
nn.remove(bestPair[0]);
|
nn.remove(bestPair[0]);
|
||||||
nn.remove(bestPair[1]);
|
nn.remove(bestPair[1]);
|
||||||
@@ -525,15 +525,19 @@ public class RTree<T> {
|
|||||||
/**
|
/**
|
||||||
* Implementation of LinearPickNext
|
* Implementation of LinearPickNext
|
||||||
*
|
*
|
||||||
* @param cc the children to be divided between the new nodes, one item will be removed from this list.
|
* @param cc the children to be divided between the new nodes, one item will be removed from this
|
||||||
|
* list.
|
||||||
*/
|
*/
|
||||||
private Node lPickNext(LinkedList<Node> cc) {
|
private Node lPickNext(LinkedList<Node> cc) {
|
||||||
return cc.pop();
|
return cc.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tighten(Node... nodes) {
|
private void tighten(Node[] nn) {
|
||||||
assert (nodes.length >= 1) : "Pass some nodes to tighten!";
|
for (Node n : nn)
|
||||||
for (Node n : nodes) {
|
tighten(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tighten(Node n) {
|
||||||
assert (n.children.size() > 0) : "tighten() called on empty node!";
|
assert (n.children.size() > 0) : "tighten() called on empty node!";
|
||||||
float[] minCoords = new float[numDims];
|
float[] minCoords = new float[numDims];
|
||||||
float[] maxCoords = new float[numDims];
|
float[] maxCoords = new float[numDims];
|
||||||
@@ -561,7 +565,6 @@ public class RTree<T> {
|
|||||||
System.arraycopy(minCoords, 0, n.coords, 0, numDims);
|
System.arraycopy(minCoords, 0, n.coords, 0, numDims);
|
||||||
System.arraycopy(maxCoords, 0, n.dimensions, 0, numDims);
|
System.arraycopy(maxCoords, 0, n.dimensions, 0, numDims);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private RTree<T>.Node chooseLeaf(RTree<T>.Node n, RTree<T>.Entry e) {
|
private RTree<T>.Node chooseLeaf(RTree<T>.Node n, RTree<T>.Entry e) {
|
||||||
if (n.leaf) {
|
if (n.leaf) {
|
||||||
@@ -590,8 +593,7 @@ public class RTree<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the increase in area necessary for the given rectangle to cover the
|
* Returns the increase in area necessary for the given rectangle to cover the given entry.
|
||||||
* given entry.
|
|
||||||
*/
|
*/
|
||||||
private float getRequiredExpansion(float[] coords, float[] dimensions, Node e) {
|
private float getRequiredExpansion(float[] coords, float[] dimensions, Node e) {
|
||||||
float area = getArea(dimensions);
|
float area = getArea(dimensions);
|
||||||
@@ -618,8 +620,8 @@ public class RTree<T> {
|
|||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isOverlap(float[] scoords, float[] sdimensions,
|
private boolean isOverlap(float[] scoords, float[] sdimensions, float[] coords,
|
||||||
float[] coords, float[] dimensions) {
|
float[] dimensions) {
|
||||||
final float FUDGE_FACTOR = 1.001f;
|
final float FUDGE_FACTOR = 1.001f;
|
||||||
for (int i = 0; i < scoords.length; i++) {
|
for (int i = 0; i < scoords.length; i++) {
|
||||||
boolean overlapInThisDimension = false;
|
boolean overlapInThisDimension = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user