Skip to content

Commit

Permalink
Develop (#5)
Browse files Browse the repository at this point in the history
Added working docker container to run
  • Loading branch information
nat-a-cyborg authored Nov 27, 2023
1 parent 5ecc138 commit 94ceb2b
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 72 deletions.
2 changes: 1 addition & 1 deletion .unibeautifyrc.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
Python:
beautifiers:
- YAPF
- YAPF
YAPF:
prefer_beautifier_config: true
19 changes: 19 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM cadquery/cadquery:latest
USER root

LABEL maintainer="nat@a-cyborg.com"

RUN apt-get update
RUN apt-get install bc
RUN apt-get clean && \
rm -rf /var/lib/apt/lists/*
RUN pip install applescript

WORKDIR /home

COPY run.sh .
COPY logo_stamp.step .
COPY octahedroflake.py .

RUN chmod +x run.sh
CMD ["/home/run.sh"]
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
This repository contains the CadQuery code and an accompanying Bash script to generate a 3D octahedron fractal called the "Octahedroflake." The Octahedroflake is a higher-dimensional analog of the Sierpinski Triangle.

[![Social Preview](https://repository-images.githubusercontent.com/626647438/cb055930-87fd-490b-80b1-48fa105da8bc)](https://www.printables.com/model/432767)

## Table of Contents

- [Pre-generated Models](#pre-generated-models)
Expand Down Expand Up @@ -47,6 +48,12 @@ To view a full list of command-line options, run:
./run.sh -h
```

### Running directly

```
python3 /home/octahedroflake.py --iterations 6 --layer-height 0.2 --nozzle-diameter 0.4 --size-multiplier 1.377628
```

## File Descriptions

### [octahedroflake.py](https://github.com/nat-a-cyborg/octahedroflake/blob/main/octahedroflake.py)
Expand All @@ -55,7 +62,6 @@ This Python script generates the Octahedroflake using CadQuery. It defines the p

### [run.sh](https://github.com/nat-a-cyborg/octahedroflake/blob/main/run.sh)


This Bash script streamlines running the \`octahedroflake.py\` script by offering a user-friendly interface. Specify various parameters, such as the number of iterations, layer height, nozzle diameter, and model height, through command-line arguments or interactive prompts. The script also provides a summary of the resulting model's dimensions and other characteristics.

## Restrictions on Selling the Model
Expand All @@ -66,6 +72,16 @@ The Octahedroflake model is for personal use only. Please refrain from selling t

As my first CadQuery project, I welcome any input or feedback. Please feel free to open an issue or submit a pull request if you have suggestions for improvements.

## Docker

### BUILD

`docker build -t cadquery:fractal .`

### RUN

`docker run -v $(pwd)/output:/home/output -it cadquery:fractal`

## License

Shield: [![CC BY-NC-SA 4.0][cc-by-nc-sa-shield]][cc-by-nc-sa]
Expand All @@ -77,4 +93,4 @@ This work is licensed under a

[cc-by-nc-sa]: http://creativecommons.org/licenses/by-nc-sa/4.0/
[cc-by-nc-sa-image]: https://licensebuttons.net/l/by-nc-sa/4.0/88x31.png
[cc-by-nc-sa-shield]: https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg
[cc-by-nc-sa-shield]: https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg
84 changes: 56 additions & 28 deletions octahedroflake.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""
octahedroflake.py
This script generates a printable 3D octahedron fractal called the "Octahedroflake," which is a higher-dimensional analog of the Sierpinski Triangle. The algorithm used to create the Octahedroflake is based on the iterative subdivision of an octahedron.
This script generates a printable 3D octahedron fractal called the "Octahedroflake,"
which is a higher-dimensional analog of the Sierpinski Triangle. The algorithm used
to create the Octahedroflake is based on the iterative subdivision of an octahedron.
For more information about an octahedron flake, see:
https://en.wikipedia.org/wiki/N-flake#Octahedron_flake
Expand All @@ -19,7 +21,7 @@
-m, --model-height Model height in mm (default: 60).
"""

#!/usr/bin/env python
# !/usr/bin/env python
# -*- coding: utf-8 -*-

import os
Expand All @@ -30,6 +32,9 @@
import inspect
import math
import argparse
import platform
import applescript

import cadquery as cq
from cadquery import exporters

Expand Down Expand Up @@ -123,6 +128,14 @@ def cache_model(part, part_name, order=None):
part_cash[coded_part_name] = part
report(f" 📥 {part_name}", order=order)

def save_comments(file_path, note):
if platform.system() == "Darwin": # Checks if the OS is macOS
note += f"\nNOZZLE_DIAMETER: {NOZZLE_DIAMETER}"
note += f"\nLAYER_HEIGHT: {LAYER_HEIGHT}"
note += f"\nFINAL_ORDER: {FINAL_ORDER}"
note += f"\nSIZE_MULTIPLER: {SIZE_MULTIPLER}"
applescript.tell.app("Finder", f'set comment of (POSIX file "{file_path}" as alias) to "{note}" as Unicode text')

def output(result, *, name, path, stl=False, step=False, svg=False):
file_path = path

Expand All @@ -133,22 +146,24 @@ def output(result, *, name, path, stl=False, step=False, svg=False):

name = remove_blanks(name)
if stl:
file_name = file_path + name + '.stl'
exporters.export(result, file_name)
file_path = file_path + name + '.stl'
exporters.export(result, file_path)
save_comments(file_path, name)

if step:
file_name = file_path + name + '.STEP'
report(f'💾 {file_name}')
exporters.export(result, file_name, exporters.ExportTypes.STEP)
file_path = file_path + name + '.STEP'
report(f'💾 {file_path}')
exporters.export(result, file_path, exporters.ExportTypes.STEP)
save_comments(file_path, name)

if svg:
file_name = file_path + name + '.svg'
report(f'💾 {file_name}')
exporters.export(result, file_name)
file_path = file_path + name + '.svg'
report(f'💾 {file_path}')
exporters.export(result, file_path)

exporters.export(
result.rotateAboutCenter((0, 0, 1), 135).rotateAboutCenter((0, 1, 0), 90),
file_name,
file_path,
opt={
"width": 1000,
"height": 1000,
Expand All @@ -163,24 +178,14 @@ def output(result, *, name, path, stl=False, step=False, svg=False):
},
)

def show_thing(thing, *, name=None, alpha=0, color=(10, 160, 240)):
try:
show_object(
thing, name=name, options={
'alpha': alpha,
'color': color
}
)
except:
pass

def save_caches_to_disk():
def save_caches_to_disk(clear=True):
global part_cash
for part_name, part in part_cash.items():
if not exists(f'{PART_CACHE_STEP_DIR}/{part_name}.STEP'):
output(result=part, name=part_name, path=PART_CACHE_STEP_DIR, step=True)

part_cash = {} # Clear out the ram cache
if clear:
part_cash = {} # Clear out the ram cache

def make_single_pyramid(order):
part_name = inspect.currentframe().f_code.co_name
Expand Down Expand Up @@ -401,6 +406,9 @@ def export_pyramid():
output(pyramid_with_base, name=pyramid_name, path=directory, stl=True)

def make_branded_pyramid():

report('👷🏻‍♀️ About to make a branded pyramid', order=FINAL_ORDER)

part_name = inspect.currentframe().f_code.co_name

cached = get_cached_model(part_name, FINAL_ORDER)
Expand All @@ -411,7 +419,25 @@ def make_branded_pyramid():
cache_model(branded_pyramid, part_name, order=FINAL_ORDER)
return branded_pyramid

def make_octahedron_fractal():
def make_unbranded_pyramid():
report('👷🏻‍♀️ About to make an unbranded pyramid', order=FINAL_ORDER)

part_name = inspect.currentframe().f_code.co_name

cached = get_cached_model(part_name, FINAL_ORDER)
if cached is not None:
return cached

fractal_pyramid = make_fractal_pyramid(order=FINAL_ORDER)

report('👷🏻‍♀️ finished fractaling! now we brand and combine...', order=FINAL_ORDER)

save_caches_to_disk(clear=False)

cache_model(fractal_pyramid, part_name, order=FINAL_ORDER)
return fractal_pyramid

def make_octahedron_fractal(branded=True):
part_name = inspect.currentframe().f_code.co_name
part_name = f'{part_name}-'

Expand All @@ -421,16 +447,18 @@ def make_octahedron_fractal():

report('💠 make it!', order=FINAL_ORDER)

save_caches_to_disk()
stand = None
branded_pyramid = make_branded_pyramid()

pyramid = make_branded_pyramid() if branded else make_unbranded_pyramid()
export_pyramid()
mirrored = make_final_mirror()
stand = make_stand(max(0, FINAL_ORDER - 2))
save_caches_to_disk()

report('🔗 combine with mirrored and stand', order=FINAL_ORDER)

result = (branded_pyramid.union(mirrored).translate((0, 0, PYRAMID_HEIGHT * pow(2, FINAL_ORDER))).union(stand))
result = (pyramid.union(mirrored).translate((0, 0, PYRAMID_HEIGHT * pow(2, FINAL_ORDER))).union(stand))

cache_model(result, part_name, order=FINAL_ORDER)
return result
Expand All @@ -443,7 +471,7 @@ def run():
report(f'full height: {str(FULL_HEIGHT)}')
report(f'edge size: {EDGE_SIZE}')

flake = make_octahedron_fractal() #.rotateAboutCenter((0, 0, 1), 45)
flake = make_octahedron_fractal() # .rotateAboutCenter((0, 0, 1), 45)
save_caches_to_disk()

name = f'''Octahedroflake-{FINAL_ORDER}_{FULL_HEIGHT}mm_for_{str(round(LAYER_HEIGHT,2))}mm_layer_height_and_{str(round(NOZZLE_DIAMETER,2))}mm_nozzle'''
Expand Down
84 changes: 43 additions & 41 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ readonly RESET=$(tput sgr0)
readonly DEFAULT_ITERATIONS=4
readonly DEFAULT_LAYER_HEIGHT=0.2
readonly DEFAULT_NOZZLE_DIAMETER=0.4
readonly DEFAULT_MODEL_HEIGHT=150.0
readonly DEFAULT_MODEL_HEIGHT=200.0

# Define usage and help message
usage() {
Expand All @@ -43,33 +43,33 @@ no_prompt=false
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
help_message
;;
-i|--iterations)
iterations="$2"
shift
;;
-l|--layer-height)
layer_height="$2"
shift
;;
-n|--nozzle-diameter)
nozzle_diameter="$2"
shift
;;
-m|--model-height)
model_height="$2"
shift
;;
--no-prompt)
no_prompt=true
;;
*)
echo "Invalid option: $1"
usage
exit 1
;;
-h | --help)
help_message
;;
-i | --iterations)
iterations="$2"
shift
;;
-l | --layer-height)
layer_height="$2"
shift
;;
-n | --nozzle-diameter)
nozzle_diameter="$2"
shift
;;
-m | --model-height)
model_height="$2"
shift
;;
--no-prompt)
no_prompt=true
;;
*)
echo "Invalid option: $1"
usage
exit 1
;;
esac
shift
done
Expand Down Expand Up @@ -122,32 +122,31 @@ confirm() {
echo "${YELLOW}Height factor:${RESET} ${height_factor}"
echo "${YELLOW}Full size:${RESET} ${full_size} mm"
echo "${YELLOW}Size multiplier:${RESET} ${size_multiplier}"

echo "python3 $(dirname "$0")/octahedroflake.py" --iterations "$iterations" --layer-height "$layer_height" --nozzle-diameter "$nozzle_diameter" --size-multiplier "$size_multiplier"

read -rp "${YELLOW}Do you want to continue? [Y/n]${RESET} " response
case "$response" in
[yY]|"")
return 0
;;
[nN])
get_parameters
;;
*)
echo "Invalid response. Please enter 'y', 'n', or press the return key."
;;
[yY] | "")
return 0
;;
[nN])
get_parameters
;;
*)
echo "Invalid response. Please enter 'y', 'n', or press the return key."
;;
esac
done
fi
}


# Main function
main() {
get_parameters
confirm

echo "${GREEN}Running the Python script...${RESET}"
python "$(dirname "$0")/octahedroflake.py" --iterations "$iterations" --layer-height "$layer_height" --nozzle-diameter "$nozzle_diameter" --size-multiplier "$size_multiplier"
python3 "$(dirname "$0")/octahedroflake.py" --iterations "$iterations" --layer-height "$layer_height" --nozzle-diameter "$nozzle_diameter" --size-multiplier "$size_multiplier"
echo "${GREEN}Done.${RESET}"
}

Expand All @@ -165,4 +164,7 @@ if ! $no_prompt; then
fi
fi

open "$DIR/output"
echo "files are in /output"
if command -v open >/dev/null 2>&1; then
open "$DIR/output"
fi

0 comments on commit 94ceb2b

Please sign in to comment.