geometry: bordermesh: fix region linking to prevent routes that run through unrelated regions
This commit is contained in:
parent
ac14a78d7f
commit
092ed9c6d0
@ -24,23 +24,31 @@ public class BorderMesh {
|
|||||||
Map<Region, Polygon> m_polygons;
|
Map<Region, Polygon> m_polygons;
|
||||||
Map<Region, Set<Region>> m_neighbors;
|
Map<Region, Set<Region>> m_neighbors;
|
||||||
|
|
||||||
|
// TODO: Probably need to cache the neighbors after doing all this
|
||||||
|
// intersection work! Should be generated during triangulate()
|
||||||
public Collection<Region> neighbors(Region region) {
|
public Collection<Region> neighbors(Region region) {
|
||||||
Collection<Region> ret = new ArrayList<Region>();
|
Collection<Region> ret = new ArrayList<Region>();
|
||||||
if (m_neighbors.containsKey(region)) {
|
if (m_neighbors.containsKey(region)) {
|
||||||
Collection<Region> allNeighbors = m_neighbors.get(region);
|
Collection<Region> allNeighbors = m_neighbors.get(region);
|
||||||
if (false /*isFrontier(region)*/) {
|
for(Region neighbor : allNeighbors) {
|
||||||
//log.trace("Region " + region.name() + " is a frontier");
|
int crossings = 0;
|
||||||
for(Region neighbor : allNeighbors) {
|
Vector2D start = new Vector2D(region.location().getBlockX(), region.location().getBlockZ());
|
||||||
if (!isFrontier(neighbor)) {
|
Vector2D neighborEnd = new Vector2D(neighbor.location().getBlockX(), neighbor.location().getBlockZ());
|
||||||
ret.add(neighbor);
|
for(Region distantNeighbor : m_regions) {
|
||||||
} else {
|
if (distantNeighbor.equals(neighbor)) {
|
||||||
//log.trace("Not linking " + region.name() + " to " + neighbor.name() + " as it is also a frontier");
|
continue;
|
||||||
|
}
|
||||||
|
Polygon poly = m_polygons.get(distantNeighbor);
|
||||||
|
for(Polygon.Segment edge : poly.segments()) {
|
||||||
|
// Check if the line from region->neighbor intersects with
|
||||||
|
// any polygon
|
||||||
|
if (doIntersect(start, neighborEnd, edge.start, edge.end)) {
|
||||||
|
crossings++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
if (crossings == 1 || crossings == 0) {
|
||||||
//log.trace("Region " + region.name() + " is not a frontier");
|
ret.add(neighbor);
|
||||||
for(Region neighbor : allNeighbors) {
|
|
||||||
ret.add(neighbor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,6 +66,24 @@ public class BorderMesh {
|
|||||||
public double y[];
|
public double y[];
|
||||||
public double z[];
|
public double z[];
|
||||||
|
|
||||||
|
public class Segment {
|
||||||
|
public Vector2D start;
|
||||||
|
public Vector2D end;
|
||||||
|
public Segment(Vector2D start, Vector2D end) {
|
||||||
|
this.start = start;
|
||||||
|
this.end = end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Segment> segments() {
|
||||||
|
List<Segment> ret = new ArrayList<Segment>();
|
||||||
|
for(int i = 0; i < x.length-1; i++) {
|
||||||
|
ret.add(new Segment(new Vector2D(x[i], z[i]), new Vector2D(x[i+1], z[i+1])));
|
||||||
|
}
|
||||||
|
ret.add(new Segment(new Vector2D(x[x.length-1], z[z.length-1]), new Vector2D(x[0], z[0])));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
public Polygon(List<Vector2D> points) {
|
public Polygon(List<Vector2D> points) {
|
||||||
x = new double[points.size()];
|
x = new double[points.size()];
|
||||||
y = new double[points.size()];
|
y = new double[points.size()];
|
||||||
@ -93,6 +119,27 @@ public class BorderMesh {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int orientation(Vector2D p, Vector2D q, Vector2D r) {
|
||||||
|
int val = (int)((q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y));
|
||||||
|
if (val == 0) return 0; // colinear
|
||||||
|
return (val > 0) ? 1 : 2; // Clockwise or counter-clockwise
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean doIntersect(Vector2D p1, Vector2D q1, Vector2D p2, Vector2D q2) {
|
||||||
|
int o1 = orientation(p1, q1, p2);
|
||||||
|
int o2 = orientation(p1, q1, q2);
|
||||||
|
int o3 = orientation(p2, q2, p1);
|
||||||
|
int o4 = orientation(p2, q2, q1);
|
||||||
|
|
||||||
|
if (o1 != o2 && o3 != o4) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It probably isn't possible to generate a route that is colinear with a
|
||||||
|
// region border, so assume it isn't intersecting.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public Polygon polygonForRegion(Region r) {
|
public Polygon polygonForRegion(Region r) {
|
||||||
return m_polygons.get(r);
|
return m_polygons.get(r);
|
||||||
}
|
}
|
||||||
@ -188,16 +235,6 @@ public class BorderMesh {
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public boolean isFrontier(Region region) {
|
|
||||||
Polygon poly = polygonForRegion(region);
|
|
||||||
Location center = region.location();
|
|
||||||
if (poly.contains(center.getBlockX(), center.getBlockZ())) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean vecEquals(Vector2D a, Vector2D b) {
|
private boolean vecEquals(Vector2D a, Vector2D b) {
|
||||||
return a.x == b.x && a.y == b.y;
|
return a.x == b.x && a.y == b.y;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user