diff --git a/roads.go b/roads.go index 9febd5c..7a3bd23 100644 --- a/roads.go +++ b/roads.go @@ -368,11 +368,17 @@ func generatePOIs(width, height int, settings *Settings, waterMask *PixelMask, r break } p := image.Point{X: x, Y: y} + centerDist := math.Hypot(float64(x-centerX), float64(y-centerY)) + centerFactor := 1.0 - clamp01(centerDist/(effectiveRadius+1)) + localSpacing := avgBuildingSize * (1.36 - 0.68*centerFactor) + if localSpacing < 4 { + localSpacing = 4 + } // Keep larger spacing between intersections so buildings have room. - if waterMask.GetPoint(p) || isTooCloseToExisting(pois, x, y, avgBuildingSize*1.1) { + if waterMask.GetPoint(p) || isTooCloseToExisting(pois, x, y, localSpacing) { continue } - pois = append(pois, &PointOfInterest{X: x, Y: y, TargetDegree: sampleTargetDegree(randSrc)}) + pois = append(pois, &PointOfInterest{X: x, Y: y, TargetDegree: sampleTargetDegree(randSrc, centerFactor)}) } if len(pois) == 0 { @@ -383,7 +389,7 @@ func generatePOIs(width, height int, settings *Settings, waterMask *PixelMask, r centerDist := math.Hypot(float64(poi.X-centerX), float64(poi.Y-centerY)) centerFactor := 1.0 - clamp01(centerDist/(effectiveRadius+1)) sizeFactor := clamp01((avgBuildingSize - 4.0) / 40.0) - poi.ArterialWeight = clamp01(0.60*centerFactor + 0.40*sizeFactor) + poi.ArterialWeight = clamp01(0.72*centerFactor + 0.28*sizeFactor) } return pois @@ -395,7 +401,7 @@ func estimateCoreNodeCount(width, height int, distribution, avgBuildingSize floa if spacing < 6 { spacing = 6 } - byArea := int((targetArea / (spacing * spacing)) * 0.18) + byArea := int((targetArea / (spacing * spacing)) * 0.20) buildingPressure := int(math.Sqrt(float64(max(numBuildings, 1))) * (0.7 + distribution*0.9)) nodes := byArea + buildingPressure if nodes < 8 { @@ -475,19 +481,22 @@ func sampleEdgePOI(width, height int, randSrc *rand.Rand) *PointOfInterest { } } -func sampleTargetDegree(randSrc *rand.Rand) int { +func sampleTargetDegree(randSrc *rand.Rand, centerFactor float64) int { + centerFactor = clamp01(centerFactor) r := randSrc.Float64() switch { - case r < 0.03: + case r < 0.04-0.02*centerFactor: return 1 - case r < 0.17: + case r < 0.18-0.06*centerFactor: return 2 - case r < 0.40: + case r < 0.42-0.06*centerFactor: return 3 - case r < 0.85: + case r < 0.86-0.20*centerFactor: return 4 - default: + case r < 0.97-0.08*(1.0-centerFactor): return 5 + default: + return 6 } } @@ -683,7 +692,8 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings, b := pois[c.b] centerPenalty := centerCloseness(a) * centerCloseness(b) * 0.45 degreePenalty := clamp01(float64(a.Connections+b.Connections) / 8.0) - score := c.arterialMean*0.58 + clamp01(c.dist/edgeDist)*0.27 + c.score*0.15 - centerPenalty - degreePenalty*0.18 + coreBonus := (centerCloseness(a) + centerCloseness(b)) * 0.22 + score := c.arterialMean*0.58 + clamp01(c.dist/edgeDist)*0.27 + c.score*0.15 + coreBonus - centerPenalty - degreePenalty*0.18 if score > bestScore { bestScore = score bestIdx = idx @@ -733,7 +743,8 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings, if !a.IsExit && !b.IsExit { longDiagonalPenalty = clamp01((c.dist-edgeDist*0.45)/(edgeDist*0.35)) * 0.28 } - score := c.score*0.28 + c.arterialMean*0.27 + distScore*0.35 + connectedBonus - centerPenalty - degreePenalty*0.14 - longDiagonalPenalty + coreBonus := (centerCloseness(a) + centerCloseness(b)) * 0.18 + score := c.score*0.28 + c.arterialMean*0.27 + distScore*0.35 + connectedBonus + coreBonus - centerPenalty - degreePenalty*0.14 - longDiagonalPenalty if score > bestScore { bestScore = score bestIdx = idx @@ -776,6 +787,9 @@ func connectPOIs(pois []*PointOfInterest, width, height int, settings *Settings, if !a.IsExit && !b.IsExit && pick.dist > edgeDist*0.42 { continue } + if centerCloseness(a)+centerCloseness(b) < 0.35 && randSrc.Float64() < 0.55 { + continue + } addEdge(pick, RoadTierLocal) }