Rev 4382 |
View as "text/plain" |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
package uk.me.parabola.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import uk.me.parabola.imgfmt.app.Area;
import uk.me.parabola.imgfmt.app.Coord;
import uk.me.parabola.util.QuadTreeNode.QuadTreePolygon;
public class QuadTree
{
private final QuadTreeNode root
;
private long itemCount
;
public QuadTree
(Area bbox
) {
this.
root =
new QuadTreeNode
(bbox
);
this.
itemCount =
0;
}
public boolean addAll
(Collection<Coord
> coordList
) {
long oldCount = itemCount
;
for (Coord c : coordList
) {
add
(c
);
}
return itemCount
> oldCount
;
}
public boolean add
(Coord c
) {
boolean added = root.
add(c
);
if (added
) {
itemCount++
;
}
return added
;
}
public List<Coord
> get
(Area bbox
) {
return root.
get(bbox,
new ArrayList<>(2000));
}
public List<Coord
> get
(Collection<List<Coord
>> polygons
) {
return root.
get(new QuadTreePolygon
(polygons
),
new ArrayList<>(2000));
}
public List<Coord
> get
(List<Coord
> polygon
) {
return get
(polygon,
0);
}
public List<Coord
> get
(List<Coord
> polygon,
int offset
) {
if (polygon.
size() < 3) {
return Collections.
emptyList();
}
if (!polygon.
get(0).
equals(polygon.
get(polygon.
size() -
1))) {
throw new IllegalArgumentException("polygon is not closed");
}
List<Coord
> points = root.
get(new QuadTreePolygon
(polygon
),
new ArrayList<>(2000));
if (offset
> 0) {
ListIterator<Coord
> pointIter = points.
listIterator();
while (pointIter.
hasNext()) {
if (isCloseToPolygon
(pointIter.
next(), polygon, offset
)) {
pointIter.
remove();
}
}
}
return points
;
}
public void clear
() {
itemCount =
0;
root.
clear();
}
public long getSize
() {
return itemCount
;
}
private static boolean isCloseToPolygon
(Coord point,
List<Coord
> polygon,
int gap
) {
Iterator<Coord
> polyIter = polygon.
iterator();
Coord c2 = polyIter.
next();
while (polyIter.
hasNext()) {
Coord c1 = c2
;
c2 = polyIter.
next();
double dist = point.
shortestDistToLineSegment(c1, c2
);
if (dist
<= gap
) {
return true;
}
}
return false;
}
}