Skip to content

Commit

Permalink
add cli-based implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
superstes committed Jan 14, 2025
1 parent ffcecaf commit 45a0663
Show file tree
Hide file tree
Showing 16 changed files with 593 additions and 41 deletions.
16 changes: 13 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,27 @@ jobs:
python-version: '3.11'

- name: Install dependencies
run: pip install -r requirements_test.txt >/dev/null
run: |
pip install -r requirements_test.txt >/dev/null
pip install -r examples/requirements.txt >/dev/null
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'

- name: Building C-library
run: bash build.sh
- name: Building Go Binaries
run: |
bash src/cmd/build.sh
bash src/lib/build.sh
- name: Running Unit Tests
run: |
python3 -m pytest --version
python3 -m pytest
- name: Running examples
run: |
python3 examples/minimal_cgo.py
python3 examples/generate_map_cli.py
python3 examples/generate_map_cgo.py
11 changes: 8 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
noise.h
noise.so
examples/map.png
noise_cgo.h
noise_cgo.so
examples/map.png
noise_cli
*.json
.pytest_cache/
.idea/
__pycache__
54 changes: 49 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,61 @@ This repository contains a simple Python3-wrapper around the [opensimplex-go](ht

It should be an alternative to the full [Python3-implementation of opensimplex](https://pypi.org/project/opensimplex/).

----

## Usage

You first need to install Go to compile the C-library: [Golang download/install](https://go.dev/doc/install)

Compile: `go build -buildmode=c-shared -o noise.so noise.go`
### CLI Implementation

Compile: `bash src/cmd/build.sh`

Test it: `python3 examples/generate_map_cli.py`

This way it basically calls the standalone golang binary in a subprocess and loads the resulting data from a temporary file.

It currently only supports generating whole 2D noise-maps.

Usage:

Test it: `python3 examples/minimal.py`
```bash
Usage of noise_cli:
-exponentiation float
Exponentiation (default 5)
-height float
Height (default 135)
-lacunarity float
Lacunarity (default 1.5)
-octaves int
Octaves (default 10)
-out string
Map Output File (default "/tmp/map.json")
-persistence float
Persistence (default 0.7)
-scale float
Scale (default 50)
-seed int
Seed
-silent
Do not show output
-size int
Map Size (default 1000)
-x float
Position X
-y float
Position Y
```

For more information see: [Examples](https://github.com/O-X-L/python-opensimplex/blob/latest/examples)
----

### CGO Implementation

Compile: `bash src/lib/build.sh`

Test it: `python3 examples/minimal_cgo.py` or `python3 examples/generate_map_cgo.py`

The CGO implementation is very slow. Not yet sure why that is..

----

## Credits

Expand Down
98 changes: 98 additions & 0 deletions examples/generate_map_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/usr/bin/env python3

# Source: https://github.com/O-X-L/python-opensimplex
# Copyright: Rath Pascal
# License: MIT

from time import time
from pathlib import Path
from cProfile import Profile
from io import StringIO
from pstats import Stats
from typing import Callable, Any

import numpy as np
from PIL import Image

EXAMPLE_PATH = Path(__file__).parent.resolve()
BASE_PATH = EXAMPLE_PATH.parent.resolve()

COLOR_DEEPWATER = (0, 62, 178)
COLOR_WATER = (9, 82, 198)
COLOR_SAND = (254, 224, 179)
COLOR_GRASS = (9, 120, 93)
COLOR_DARKGRASS = (10, 107, 72)
COLOR_DARKESTGRASS = (11, 94, 51)
COLOR_DARKROCKS = (140, 142, 123)
COLOR_ROCKS = (160, 162, 143)
COLOR_BLACKROCKS = (53, 54, 68)
COLOR_SNOW = (255, 255, 255)


def _get_color(height: float, max_height: float):
factor = 255 / max_height
h = height * factor

if h < 0:
h = 0

if h > 255:
h = 255

if h <= 0.5:
return COLOR_DEEPWATER
if h <= 1.2:
return COLOR_WATER
if h <= 2:
return COLOR_SAND
if h <= 18:
return COLOR_GRASS
if h <= 30:
return COLOR_DARKGRASS
if h <= 60:
return COLOR_DARKESTGRASS
if h <= 125:
return COLOR_DARKROCKS
if h <= 145:
return COLOR_ROCKS
if h <= 220:
return COLOR_BLACKROCKS

return COLOR_SNOW


def _create_img(size: int, map_data: list[float], max_height: float):
out_img = f"{EXAMPLE_PATH}/map.png"
print(f'Saving to image: {out_img}')
colour_map = np.zeros((size, size, 3), dtype=np.uint8)

for i in range(size * size):
xi, yi, zi = i * 3, i * 3 + 1, i * 3 + 2
colour_map[map_data[xi], map_data[yi]] = _get_color(map_data[zi], max_height)

image = Image.fromarray(colour_map, 'RGB')
image.save(out_img)
return image


def _profile(
target: Callable, args: list = None, kwargs: dict = None,
lines: int = 20, sort: str = 'tottime'
) -> tuple[Any, str]:
if args is None or not isinstance(args, list):
args = []

if kwargs is None or not isinstance(kwargs, dict):
kwargs = {}

p = Profile()
p.enable()

output = target(*args, **kwargs)

p.disable()

s = StringIO()
ps = Stats(p, stream=s).sort_stats(sort)
ps.print_stats(lines)
return output, s.getvalue()
66 changes: 66 additions & 0 deletions examples/generate_map_cgo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env python3

# Source: https://github.com/O-X-L/python-opensimplex
# Copyright: Rath Pascal
# License: MIT

from time import time
from sys import path as sys_path

from generate_map_base import BASE_PATH, _create_img, _profile

sys_path.append(str(BASE_PATH))

# pylint: disable=C0413
from opensimplex_cgo import OpenSimplexExtended, OpenSimplexConfig


map_size = 50
pos_x = 0
pos_y = 0

terrain_config = OpenSimplexConfig(
octaves=10,
persistence=0.7,
lacunarity=1.5,
exponentiation=5.0,
height=135.0,
scale=50,
seed=3498230422,
)

terrain_noise = OpenSimplexExtended(terrain_config)
A = 0.5
area = map_size * map_size


def _generate(pos_x: float = 0, pos_y: float = 0) -> tuple[list[float], float]:
print(f'Generating map.. {map_size}x{map_size}')
d = []
m = 0
idx = 0

for x in range(0, map_size):
for y in range(0, map_size):
if idx != 0 and idx % 1_000 == 0:
print(f'Status: {round((100 / area) * idx, 0)}% ({int(time())-start_time}s)')

xa, ya = x + pos_x, y + pos_y
h = terrain_noise.get_2d(xa, ya)
d.extend([xa, ya, h])
if h > m:
m = h

idx += 1

return d, m


def main():
map_data, max_height = _generate()
_create_img(size=map_size, map_data=map_data, max_height=max_height)


if __name__ == '__main__':
start_time = int(time())
print(_profile(main)[1])
44 changes: 44 additions & 0 deletions examples/generate_map_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env python3

# Source: https://github.com/O-X-L/python-opensimplex
# Copyright: Rath Pascal
# License: MIT

from sys import path as sys_path

from generate_map_base import BASE_PATH, _create_img, _profile

sys_path.append(str(BASE_PATH))

# pylint: disable=C0413
from opensimplex_cli import OpenSimplexConfig, OpenSimplexCLI

map_size = 1000
pos_x = 0
pos_y = 0

terrain_config = OpenSimplexConfig(
octaves=10,
persistence=0.7,
lacunarity=1.5,
exponentiation=5.0,
height=135.0,
scale=50,
seed=3498230422,
)

terrain_noise = OpenSimplexCLI(terrain_config)


def _generate(pos_x: float = 0, pos_y: float = 0) -> tuple[list[float], float]:
print(f'Generating map.. {map_size}x{map_size}')
return terrain_noise.get_2d_array(size=map_size, pos_x=pos_x, pos_y=pos_y)


def main():
map_data, max_height = _generate()
_create_img(size=map_size, map_data=map_data, max_height=max_height)


if __name__ == '__main__':
print(_profile(main)[1])
2 changes: 1 addition & 1 deletion examples/minimal.py → examples/minimal_cgo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
sys_path.append(str(BASE_PATH))

# pylint: disable=C0413
from opensimplex_go import OpenSimplex
from opensimplex_cgo import OpenSimplex

print('2D Noise Sample:', OpenSimplex().get_2d(20, 40))
2 changes: 2 additions & 0 deletions examples/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pillow
numpy
Loading

0 comments on commit 45a0663

Please sign in to comment.