geometry: bordermesh: fix bug with one-way routes, move route calculation into triangulate()
Fixes #19
This commit is contained in:
parent
51fdc80542
commit
e21115cc65
@ -24,35 +24,11 @@ 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>();
|
|
||||||
if (m_neighbors.containsKey(region)) {
|
if (m_neighbors.containsKey(region)) {
|
||||||
Collection<Region> allNeighbors = m_neighbors.get(region);
|
return m_neighbors.get(region);
|
||||||
for(Region neighbor : allNeighbors) {
|
|
||||||
int crossings = 0;
|
|
||||||
Vector2D start = new Vector2D(region.location().getBlockX(), region.location().getBlockZ());
|
|
||||||
Vector2D neighborEnd = new Vector2D(neighbor.location().getBlockX(), neighbor.location().getBlockZ());
|
|
||||||
for(Region distantNeighbor : m_regions) {
|
|
||||||
if (distantNeighbor.equals(neighbor)) {
|
|
||||||
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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (crossings == 1 || crossings == 0) {
|
|
||||||
ret.add(neighbor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
return new ArrayList<Region>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BorderMesh(Collection<Region> regions) {
|
public BorderMesh(Collection<Region> regions) {
|
||||||
@ -191,10 +167,12 @@ public class BorderMesh {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HashMap<Region, Set<Region>> allNeighborSet = new HashMap<Region, Set<Region>>();
|
||||||
|
|
||||||
// Now we go back through our region mesh to generate vornoi points
|
// Now we go back through our region mesh to generate vornoi points
|
||||||
for(Region region : m_regions) {
|
for(Region region : m_regions) {
|
||||||
ArrayList<Vector2D> points = new ArrayList<Vector2D>();
|
ArrayList<Vector2D> points = new ArrayList<Vector2D>();
|
||||||
HashSet<Region> neighbors = new HashSet<Region>();
|
HashSet<Region> allNeighbors = new HashSet<Region>();
|
||||||
log.info("Executing voronoi transform...");
|
log.info("Executing voronoi transform...");
|
||||||
for(Triangle tri : triangleSoup) {
|
for(Triangle tri : triangleSoup) {
|
||||||
if (tri.region == region) {
|
if (tri.region == region) {
|
||||||
@ -205,36 +183,58 @@ public class BorderMesh {
|
|||||||
Location neighborLoc = neighbor.location();
|
Location neighborLoc = neighbor.location();
|
||||||
Vector2D neighborCenter = new Vector2D(neighborLoc.getBlockX(), neighborLoc.getBlockZ());
|
Vector2D neighborCenter = new Vector2D(neighborLoc.getBlockX(), neighborLoc.getBlockZ());
|
||||||
if (vecEquals(tri.a, neighborCenter) || vecEquals(tri.b, neighborCenter) || vecEquals(tri.c, neighborCenter)) {
|
if (vecEquals(tri.a, neighborCenter) || vecEquals(tri.b, neighborCenter) || vecEquals(tri.c, neighborCenter)) {
|
||||||
neighbors.add(neighbor);
|
allNeighbors.add(neighbor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
points.add(tri.circumcenter());
|
points.add(tri.circumcenter());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allNeighborSet.put(region, allNeighbors);
|
||||||
|
|
||||||
// Sort points into a renderable polygon based on direction to center
|
// Sort points into a renderable polygon based on direction to center
|
||||||
Location loc = region.location();
|
Location loc = region.location();
|
||||||
Vector2D regionCenter = new Vector2D(loc.getBlockX(), loc.getBlockZ());
|
Vector2D regionCenter = new Vector2D(loc.getBlockX(), loc.getBlockZ());
|
||||||
points.sort((Vector2D a, Vector2D b) -> Double.compare(direction(a, regionCenter), direction(b, regionCenter)));
|
points.sort((Vector2D a, Vector2D b) -> Double.compare(direction(a, regionCenter), direction(b, regionCenter)));
|
||||||
log.info("Border for " + region.name() + " is defined by " + points.size() + " points");
|
log.fine("Border for " + region.name() + " is defined by " + points.size() + " points");
|
||||||
Polygon polygon = new Polygon(points);
|
Polygon polygon = new Polygon(points);
|
||||||
m_polygons.put(region, polygon);
|
m_polygons.put(region, polygon);
|
||||||
m_neighbors.put(region, neighbors);
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that we have the borders, we generate valid routes that cross
|
||||||
|
// zero or one border lines at most.
|
||||||
|
for(Region region : m_regions) {
|
||||||
|
Set<Region> routedNeighbors = new HashSet<Region>();
|
||||||
|
for(Region neighbor : allNeighborSet.get(region)) {
|
||||||
|
int crossings = 0;
|
||||||
|
Vector2D start = new Vector2D(region.location().getBlockX(), region.location().getBlockZ());
|
||||||
|
Vector2D neighborEnd = new Vector2D(neighbor.location().getBlockX(), neighbor.location().getBlockZ());
|
||||||
|
for(Region distantNeighbor : m_regions) {
|
||||||
|
if (distantNeighbor.equals(neighbor) || distantNeighbor.equals(region)) {
|
||||||
|
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)) {
|
||||||
|
log.fine("Intersect " + distantNeighbor.name());
|
||||||
|
crossings++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.fine("Route: " + region.name() + " -> " + neighbor.name() + "\t" + crossings);
|
||||||
|
if (crossings == 1 || crossings == 0) {
|
||||||
|
routedNeighbors.add(neighbor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_neighbors.put(region, routedNeighbors);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public boolean validNeighbors(Region regionA, Region regionB) {
|
|
||||||
Polygon polyA = polygonForRegion(regionA);
|
|
||||||
Polygon polyB = polygonForRegion(regionA);
|
|
||||||
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