added mixed building generation
This commit is contained in:
+31
-1
@@ -118,7 +118,11 @@ func GenerateBuildings(img *image.RGBA, width, height int, settings *Settings, r
|
|||||||
|
|
||||||
// Attempt to create a building at the selected center
|
// Attempt to create a building at the selected center
|
||||||
size := settings.MinBuildingSize + randSrc.Float64()*(settings.MaxBuildingSize-settings.MinBuildingSize)
|
size := settings.MinBuildingSize + randSrc.Float64()*(settings.MaxBuildingSize-settings.MinBuildingSize)
|
||||||
pixels, ok := getBuildingPixels(center, size, settings.BuildingShape, isWater, isRoad, isBuilding, width, height, randSrc)
|
shape := settings.BuildingShape
|
||||||
|
if shape == "mixed" {
|
||||||
|
shape = chooseShape(randSrc, settings.BuildingShapeRatios)
|
||||||
|
}
|
||||||
|
pixels, ok := getBuildingPixels(center, size, shape, isWater, isRoad, isBuilding, width, height, randSrc)
|
||||||
if ok {
|
if ok {
|
||||||
// If successful, draw the building and update data structures
|
// If successful, draw the building and update data structures
|
||||||
for _, p := range pixels {
|
for _, p := range pixels {
|
||||||
@@ -134,6 +138,32 @@ func GenerateBuildings(img *image.RGBA, width, height int, settings *Settings, r
|
|||||||
return buildingPixels
|
return buildingPixels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// chooseShape selects a building shape based on the provided ratios.
|
||||||
|
func chooseShape(randSrc *rand.Rand, ratios map[string]float64) string {
|
||||||
|
// Create a slice of shapes and their cumulative weights
|
||||||
|
var shapes []string
|
||||||
|
var weights []float64
|
||||||
|
var cumulativeWeight float64
|
||||||
|
for shape, weight := range ratios {
|
||||||
|
shapes = append(shapes, shape)
|
||||||
|
cumulativeWeight += weight
|
||||||
|
weights = append(weights, cumulativeWeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a random number between 0 and the total weight
|
||||||
|
randNum := randSrc.Float64() * cumulativeWeight
|
||||||
|
|
||||||
|
// Find the shape corresponding to the random number
|
||||||
|
for i, weight := range weights {
|
||||||
|
if randNum < weight {
|
||||||
|
return shapes[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default to the first shape if something goes wrong
|
||||||
|
return shapes[0]
|
||||||
|
}
|
||||||
|
|
||||||
// getBuildingPixels determines the pixels for a single building based on its shape and checks for collisions.
|
// getBuildingPixels determines the pixels for a single building based on its shape and checks for collisions.
|
||||||
func getBuildingPixels(center image.Point, size float64, shape string, isWater, isRoad, isBuilding map[image.Point]bool, width, height int, randSrc *rand.Rand) ([]image.Point, bool) {
|
func getBuildingPixels(center image.Point, size float64, shape string, isWater, isRoad, isBuilding map[image.Point]bool, width, height int, randSrc *rand.Rand) ([]image.Point, bool) {
|
||||||
var pixels []image.Point
|
var pixels []image.Point
|
||||||
|
|||||||
@@ -650,11 +650,147 @@ func main() {
|
|||||||
buildingDistributionSlider.SetValue(settings.BuildingDistribution)
|
buildingDistributionSlider.SetValue(settings.BuildingDistribution)
|
||||||
|
|
||||||
buildingShapeLabel := widget.NewLabel("Building Shape:")
|
buildingShapeLabel := widget.NewLabel("Building Shape:")
|
||||||
buildingShapeSelect := widget.NewSelect([]string{"squares", "circles", "rectangles"}, func(s string) {
|
buildingShapeSelect := widget.NewSelect([]string{"squares", "circles", "rectangles", "mixed"}, func(s string) {
|
||||||
settings.BuildingShape = s
|
settings.BuildingShape = s
|
||||||
})
|
})
|
||||||
buildingShapeSelect.SetSelected(settings.BuildingShape)
|
buildingShapeSelect.SetSelected(settings.BuildingShape)
|
||||||
|
|
||||||
|
// Create sliders for building shape ratios (visible only when "mixed" is selected)
|
||||||
|
squareRatioSlider := widget.NewSlider(0, 100)
|
||||||
|
circleRatioSlider := widget.NewSlider(0, 100)
|
||||||
|
rectangleRatioSlider := widget.NewSlider(0, 100)
|
||||||
|
|
||||||
|
squareRatioLabel := widget.NewLabel(fmt.Sprintf("Squares: %.0f%%", settings.BuildingShapeRatios["squares"]))
|
||||||
|
circleRatioLabel := widget.NewLabel(fmt.Sprintf("Circles: %.0f%%", settings.BuildingShapeRatios["circles"]))
|
||||||
|
rectangleRatioLabel := widget.NewLabel(fmt.Sprintf("Rectangles: %.0f%%", settings.BuildingShapeRatios["rectangles"]))
|
||||||
|
|
||||||
|
squareRatioSlider.SetValue(settings.BuildingShapeRatios["squares"])
|
||||||
|
circleRatioSlider.SetValue(settings.BuildingShapeRatios["circles"])
|
||||||
|
rectangleRatioSlider.SetValue(settings.BuildingShapeRatios["rectangles"])
|
||||||
|
|
||||||
|
ratioContainer := container.NewVBox(
|
||||||
|
squareRatioLabel,
|
||||||
|
squareRatioSlider,
|
||||||
|
circleRatioLabel,
|
||||||
|
circleRatioSlider,
|
||||||
|
rectangleRatioLabel,
|
||||||
|
rectangleRatioSlider,
|
||||||
|
)
|
||||||
|
|
||||||
|
updateRatioSliders := func() {
|
||||||
|
squareRatioSlider.SetValue(settings.BuildingShapeRatios["squares"])
|
||||||
|
circleRatioSlider.SetValue(settings.BuildingShapeRatios["circles"])
|
||||||
|
rectangleRatioSlider.SetValue(settings.BuildingShapeRatios["rectangles"])
|
||||||
|
squareRatioLabel.SetText(fmt.Sprintf("Squares: %.0f%%", settings.BuildingShapeRatios["squares"]))
|
||||||
|
circleRatioLabel.SetText(fmt.Sprintf("Circles: %.0f%%", settings.BuildingShapeRatios["circles"]))
|
||||||
|
rectangleRatioLabel.SetText(fmt.Sprintf("Rectangles: %.0f%%", settings.BuildingShapeRatios["rectangles"]))
|
||||||
|
}
|
||||||
|
|
||||||
|
squareRatioSlider.OnChanged = func(val float64) {
|
||||||
|
if settings.BuildingShape != "mixed" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
oldVal := settings.BuildingShapeRatios["squares"]
|
||||||
|
diff := val - oldVal
|
||||||
|
settings.BuildingShapeRatios["squares"] = val
|
||||||
|
settings.BuildingShapeRatios["circles"] -= diff / 2
|
||||||
|
settings.BuildingShapeRatios["rectangles"] -= diff / 2
|
||||||
|
|
||||||
|
// Clamp values to 0-100 range
|
||||||
|
if settings.BuildingShapeRatios["circles"] < 0 {
|
||||||
|
settings.BuildingShapeRatios["rectangles"] += settings.BuildingShapeRatios["circles"]
|
||||||
|
settings.BuildingShapeRatios["circles"] = 0
|
||||||
|
}
|
||||||
|
if settings.BuildingShapeRatios["rectangles"] < 0 {
|
||||||
|
settings.BuildingShapeRatios["circles"] += settings.BuildingShapeRatios["rectangles"]
|
||||||
|
settings.BuildingShapeRatios["rectangles"] = 0
|
||||||
|
}
|
||||||
|
if settings.BuildingShapeRatios["circles"] > 100 {
|
||||||
|
settings.BuildingShapeRatios["rectangles"] += settings.BuildingShapeRatios["circles"] - 100
|
||||||
|
settings.BuildingShapeRatios["circles"] = 100
|
||||||
|
}
|
||||||
|
if settings.BuildingShapeRatios["rectangles"] > 100 {
|
||||||
|
settings.BuildingShapeRatios["circles"] += settings.BuildingShapeRatios["rectangles"] - 100
|
||||||
|
settings.BuildingShapeRatios["rectangles"] = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRatioSliders()
|
||||||
|
}
|
||||||
|
|
||||||
|
circleRatioSlider.OnChanged = func(val float64) {
|
||||||
|
if settings.BuildingShape != "mixed" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
oldVal := settings.BuildingShapeRatios["circles"]
|
||||||
|
diff := val - oldVal
|
||||||
|
settings.BuildingShapeRatios["circles"] = val
|
||||||
|
settings.BuildingShapeRatios["squares"] -= diff / 2
|
||||||
|
settings.BuildingShapeRatios["rectangles"] -= diff / 2
|
||||||
|
// Clamp values to 0-100 range
|
||||||
|
if settings.BuildingShapeRatios["squares"] < 0 {
|
||||||
|
settings.BuildingShapeRatios["rectangles"] += settings.BuildingShapeRatios["squares"]
|
||||||
|
settings.BuildingShapeRatios["squares"] = 0
|
||||||
|
}
|
||||||
|
if settings.BuildingShapeRatios["rectangles"] < 0 {
|
||||||
|
settings.BuildingShapeRatios["squares"] += settings.BuildingShapeRatios["rectangles"]
|
||||||
|
settings.BuildingShapeRatios["rectangles"] = 0
|
||||||
|
}
|
||||||
|
if settings.BuildingShapeRatios["squares"] > 100 {
|
||||||
|
settings.BuildingShapeRatios["rectangles"] += settings.BuildingShapeRatios["squares"] - 100
|
||||||
|
settings.BuildingShapeRatios["squares"] = 100
|
||||||
|
}
|
||||||
|
if settings.BuildingShapeRatios["rectangles"] > 100 {
|
||||||
|
settings.BuildingShapeRatios["squares"] += settings.BuildingShapeRatios["rectangles"] - 100
|
||||||
|
settings.BuildingShapeRatios["rectangles"] = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRatioSliders()
|
||||||
|
}
|
||||||
|
|
||||||
|
rectangleRatioSlider.OnChanged = func(val float64) {
|
||||||
|
if settings.BuildingShape != "mixed" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
oldVal := settings.BuildingShapeRatios["rectangles"]
|
||||||
|
diff := val - oldVal
|
||||||
|
settings.BuildingShapeRatios["rectangles"] = val
|
||||||
|
settings.BuildingShapeRatios["squares"] -= diff / 2
|
||||||
|
settings.BuildingShapeRatios["circles"] -= diff / 2
|
||||||
|
|
||||||
|
// Clamp values to 0-100 range
|
||||||
|
if settings.BuildingShapeRatios["squares"] < 0 {
|
||||||
|
settings.BuildingShapeRatios["circles"] += settings.BuildingShapeRatios["squares"]
|
||||||
|
settings.BuildingShapeRatios["squares"] = 0
|
||||||
|
}
|
||||||
|
if settings.BuildingShapeRatios["circles"] < 0 {
|
||||||
|
settings.BuildingShapeRatios["squares"] += settings.BuildingShapeRatios["circles"]
|
||||||
|
settings.BuildingShapeRatios["circles"] = 0
|
||||||
|
}
|
||||||
|
if settings.BuildingShapeRatios["squares"] > 100 {
|
||||||
|
settings.BuildingShapeRatios["circles"] += settings.BuildingShapeRatios["squares"] - 100
|
||||||
|
settings.BuildingShapeRatios["squares"] = 100
|
||||||
|
}
|
||||||
|
if settings.BuildingShapeRatios["circles"] > 100 {
|
||||||
|
settings.BuildingShapeRatios["squares"] += settings.BuildingShapeRatios["circles"] - 100
|
||||||
|
settings.BuildingShapeRatios["circles"] = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRatioSliders()
|
||||||
|
}
|
||||||
|
|
||||||
|
buildingShapeSelect.OnChanged = func(s string) {
|
||||||
|
settings.BuildingShape = s
|
||||||
|
if s == "mixed" {
|
||||||
|
ratioContainer.Show()
|
||||||
|
} else {
|
||||||
|
ratioContainer.Hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Initial visibility check
|
||||||
|
if settings.BuildingShape != "mixed" {
|
||||||
|
ratioContainer.Hide()
|
||||||
|
}
|
||||||
|
|
||||||
buildingsTab := container.NewTabItem("Buildings", container.NewVBox(
|
buildingsTab := container.NewTabItem("Buildings", container.NewVBox(
|
||||||
numBuildingsLabel,
|
numBuildingsLabel,
|
||||||
numBuildingsSlider,
|
numBuildingsSlider,
|
||||||
@@ -666,6 +802,7 @@ func main() {
|
|||||||
buildingDistributionSlider,
|
buildingDistributionSlider,
|
||||||
buildingShapeLabel,
|
buildingShapeLabel,
|
||||||
buildingShapeSelect,
|
buildingShapeSelect,
|
||||||
|
ratioContainer,
|
||||||
))
|
))
|
||||||
|
|
||||||
imageTab := container.NewTabItem("Image", container.NewVBox(
|
imageTab := container.NewTabItem("Image", container.NewVBox(
|
||||||
|
|||||||
+19
-2
@@ -45,6 +45,9 @@ type Settings struct {
|
|||||||
BuildingDistribution float64 `json:"building_distribution"`
|
BuildingDistribution float64 `json:"building_distribution"`
|
||||||
BuildingShape string `json:"building_shape"`
|
BuildingShape string `json:"building_shape"`
|
||||||
|
|
||||||
|
// Ratios for mixed building shapes
|
||||||
|
BuildingShapeRatios map[string]float64 `json:"building_shape_ratios"`
|
||||||
|
|
||||||
// General settings
|
// General settings
|
||||||
Seed int64 `json:"seed"`
|
Seed int64 `json:"seed"`
|
||||||
LastExportPath string `json:"last_export_path"`
|
LastExportPath string `json:"last_export_path"`
|
||||||
@@ -123,8 +126,13 @@ func LoadSettings() (*Settings, error) {
|
|||||||
MinBuildingSize: 10,
|
MinBuildingSize: 10,
|
||||||
MaxBuildingSize: 30,
|
MaxBuildingSize: 30,
|
||||||
BuildingDistribution: 20,
|
BuildingDistribution: 20,
|
||||||
BuildingShape: "squares",
|
BuildingShape: "mixed",
|
||||||
LastExportPath: homeDir,
|
BuildingShapeRatios: map[string]float64{
|
||||||
|
"squares": 40,
|
||||||
|
"circles": 30,
|
||||||
|
"rectangles": 30,
|
||||||
|
},
|
||||||
|
LastExportPath: homeDir,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -138,6 +146,15 @@ func LoadSettings() (*Settings, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure BuildingShapeRatios is initialized
|
||||||
|
if settings.BuildingShapeRatios == nil {
|
||||||
|
settings.BuildingShapeRatios = map[string]float64{
|
||||||
|
"squares": 40,
|
||||||
|
"circles": 30,
|
||||||
|
"rectangles": 30,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure LastExportPath is set to a default value if it's empty
|
// Ensure LastExportPath is set to a default value if it's empty
|
||||||
if settings.LastExportPath == "" {
|
if settings.LastExportPath == "" {
|
||||||
homeDir, err := os.UserHomeDir()
|
homeDir, err := os.UserHomeDir()
|
||||||
|
|||||||
Reference in New Issue
Block a user