public RiverNode(Garden garden, RiverNode parent, Point3i location, RiverNode child) { super(garden, 0, parent, location, 1, GardenCategory.CATEGORY_WATER); parent.child = this; this.child = child; crossSectionalArea = parent.crossSectionalArea; // System.out.println("Connecting tributary to another river @ " + location); }
private void addCrossSectionalArea(RiverNode node, int crossSectionalArea) { Set<RiverNode> processedNodes = new HashSet<RiverNode>(); while (node != null) { if (processedNodes.contains(node)) { logger.severe("Loop in river!"); return; } else { processedNodes.add(node); } node.crossSectionalArea += crossSectionalArea; drawLine( node.parent.location, node.location, (int) Math.round(Math.sqrt(node.crossSectionalArea)), false, category); node = node.child; } }
@Override protected boolean sprout() { boolean endRiver = child != null; if (garden.isWater(location.x, location.y)) { // There is already water here; end the river here // TODO: grow lake? endRiver = true; } if (parent != null) { drawLine( parent.location, location, (int) Math.round(Math.sqrt(crossSectionalArea)), false, category); } if (endRiver) { return (parent != null); } // Find coordinates of lowest point on a surrounding circle // Midpoint circle ("Bresenham's") algorithm final boolean[] lowerPointFound = new boolean[1]; final int[] lowestHeightCoords = new int[2]; int radius = 0; for (int r = 3; (!lowerPointFound[0]) && (r <= 9); r += 2) { radius = r; final float[] lowestHeight = {garden.getHeight(location.x, location.y)}; GeometryUtil.visitCircle( r, new GeometryVisitor() { @Override public boolean visit(int dx, int dy, float d) { float height = garden.getHeight(location.x + dx, location.y + dy); if (height < lowestHeight[0]) { lowestHeight[0] = height; lowestHeightCoords[0] = location.x + dx; lowestHeightCoords[1] = location.y + dy; lowerPointFound[0] = true; } return true; } }); } if (lowerPointFound[0]) { // Find existing nodes to connect with (not belonging to the same // river) List<RiverNode> nearbyNodes = garden.findSeeds(RiverNode.class, lowestHeightCoords[0], lowestHeightCoords[1], radius); int ownNodesEncountered = 0; for (RiverNode riverNode : nearbyNodes) { if (riverNode.getOrigin() == getOrigin()) { // Another node of same river ownNodesEncountered++; if (ownNodesEncountered < 2) { continue; } else { // We seem to be circing the drain. Abort! Abort! return true; } } if (riverNode.child != null) { garden.plantSeed(new RiverNode(garden, this, riverNode.location, riverNode.child)); addCrossSectionalArea(riverNode.child, crossSectionalArea); } else { garden.plantSeed(new RiverNode(garden, this, riverNode.location)); } return true; } garden.plantSeed( new RiverNode( garden, this, new Point3i(lowestHeightCoords[0], lowestHeightCoords[1], -1))); return true; } else { // No lower point around; end the river here // TODO: start a lake? return (parent != null); } }
public RiverNode(Garden garden, RiverNode parent, Point3i location) { super(garden, 0, parent, location, 1, GardenCategory.CATEGORY_WATER); parent.child = this; crossSectionalArea = parent.crossSectionalArea; // System.out.println("Extending river to " + location); }