reworked road generation with focus on main roads, secondary streets and smaller arterial roads
This commit is contained in:
+53
-4
@@ -173,22 +173,68 @@ func GenerateBuildings(
|
||||
searchTries := 100 // Number of attempts to find a spot for a building around an anchor
|
||||
maxPlacementAttempts := settings.NumBuildings * 5 // To prevent infinite loops
|
||||
minBuildingSizePx, maxBuildingSizePx := getBuildingSizeRangePixels(settings, width, height)
|
||||
anchorUsage := make(map[image.Point]int, len(anchorPoints))
|
||||
normalAnchorCap := 0
|
||||
exitAnchorCap := 0
|
||||
if len(normalRoadAnchors) > 0 {
|
||||
normalAnchorCap = max(2, int(math.Ceil((float64(settings.NumBuildings)/float64(len(normalRoadAnchors)))*1.15)))
|
||||
}
|
||||
if len(exitRoadAnchors) > 0 {
|
||||
exitAnchorCap = max(1, int(math.Ceil((float64(settings.NumBuildings)/float64(len(exitRoadAnchors)))*0.20)))
|
||||
}
|
||||
|
||||
pickAnchorWithCapacity := func(candidates []image.Point, capLimit int) (image.Point, bool) {
|
||||
if len(candidates) == 0 {
|
||||
return image.Point{}, false
|
||||
}
|
||||
if capLimit <= 0 {
|
||||
return candidates[randSrc.Intn(len(candidates))], true
|
||||
}
|
||||
best := candidates[randSrc.Intn(len(candidates))]
|
||||
bestCount := anchorUsage[best]
|
||||
for tries := 0; tries < min(16, len(candidates)*2); tries++ {
|
||||
candidate := candidates[randSrc.Intn(len(candidates))]
|
||||
count := anchorUsage[candidate]
|
||||
if count < capLimit {
|
||||
return candidate, true
|
||||
}
|
||||
if count < bestCount {
|
||||
best = candidate
|
||||
bestCount = count
|
||||
}
|
||||
}
|
||||
if bestCount < capLimit {
|
||||
return best, true
|
||||
}
|
||||
return image.Point{}, false
|
||||
}
|
||||
|
||||
for buildingsPlaced < settings.NumBuildings && maxPlacementAttempts > 0 {
|
||||
maxPlacementAttempts--
|
||||
|
||||
// Select an anchor point for the new building
|
||||
var anchor image.Point
|
||||
usedRoadAnchor := false
|
||||
if randSrc.Float64() > settings.BuildingDistribution/100.0 {
|
||||
// Buildings should only rarely use exit-road anchors.
|
||||
useExitAnchor := len(exitRoadAnchors) > 0 && randSrc.Float64() < 0.02
|
||||
if useExitAnchor {
|
||||
anchor = exitRoadAnchors[randSrc.Intn(len(exitRoadAnchors))]
|
||||
if a, ok := pickAnchorWithCapacity(exitRoadAnchors, exitAnchorCap); ok {
|
||||
anchor = a
|
||||
usedRoadAnchor = true
|
||||
}
|
||||
} else if len(normalRoadAnchors) > 0 {
|
||||
anchor = normalRoadAnchors[randSrc.Intn(len(normalRoadAnchors))]
|
||||
if a, ok := pickAnchorWithCapacity(normalRoadAnchors, normalAnchorCap); ok {
|
||||
anchor = a
|
||||
usedRoadAnchor = true
|
||||
}
|
||||
} else if len(anchorPoints) > 0 {
|
||||
anchor = anchorPoints[randSrc.Intn(len(anchorPoints))]
|
||||
} else {
|
||||
if a, ok := pickAnchorWithCapacity(anchorPoints, normalAnchorCap); ok {
|
||||
anchor = a
|
||||
usedRoadAnchor = true
|
||||
}
|
||||
}
|
||||
if !usedRoadAnchor {
|
||||
p, ok := sampleRandomLandPoint(width, height, waterMask, roadMask, randSrc)
|
||||
if !ok {
|
||||
continue
|
||||
@@ -247,6 +293,9 @@ func GenerateBuildings(
|
||||
img.Set(p.X, p.Y, buildingColor)
|
||||
buildingMask.SetPoint(p)
|
||||
}
|
||||
if usedRoadAnchor {
|
||||
anchorUsage[anchor]++
|
||||
}
|
||||
buildings = append(buildings, pixels)
|
||||
buildingsPlaced++
|
||||
break // Move to the next building
|
||||
|
||||
Reference in New Issue
Block a user