ocga-cli 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. ocga_cli-0.1.0/LICENSE +21 -0
  2. ocga_cli-0.1.0/MANIFEST.in +18 -0
  3. ocga_cli-0.1.0/PKG-INFO +85 -0
  4. ocga_cli-0.1.0/README.md +63 -0
  5. ocga_cli-0.1.0/docs/OCGA.md +156 -0
  6. ocga_cli-0.1.0/docs/ocga_samples/alexander_column-rewrite.osm +790 -0
  7. ocga_cli-0.1.0/docs/ocga_samples/alexander_column.ocga +151 -0
  8. ocga_cli-0.1.0/docs/ocga_samples/alexander_column.osm +36 -0
  9. ocga_cli-0.1.0/docs/ocga_samples/church_at_the_kaluga_gate-rewrite.osm +752 -0
  10. ocga_cli-0.1.0/docs/ocga_samples/church_at_the_kaluga_gate.ocga +93 -0
  11. ocga_cli-0.1.0/docs/ocga_samples/church_at_the_kaluga_gate.osm +85 -0
  12. ocga_cli-0.1.0/docs/ocga_samples/church_of_st_louis-rewrite.osm +994 -0
  13. ocga_cli-0.1.0/docs/ocga_samples/church_of_st_louis.ocga +190 -0
  14. ocga_cli-0.1.0/docs/ocga_samples/church_of_st_louis.osm +89 -0
  15. ocga_cli-0.1.0/docs/ocga_samples/danilov_belltower.ocga +106 -0
  16. ocga_cli-0.1.0/docs/ocga_samples/danilov_belltower.osm +90 -0
  17. ocga_cli-0.1.0/docs/ocga_samples/gorky_park_entrance-rewrite.osm +2574 -0
  18. ocga_cli-0.1.0/docs/ocga_samples/gorky_park_entrance.ocga +193 -0
  19. ocga_cli-0.1.0/docs/ocga_samples/gorky_park_entrance.osm +65 -0
  20. ocga_cli-0.1.0/docs/ocga_samples/gorky_park_rotunda-rewrite.osm +949 -0
  21. ocga_cli-0.1.0/docs/ocga_samples/gorky_park_rotunda.ocga +86 -0
  22. ocga_cli-0.1.0/docs/ocga_samples/gorky_park_rotunda.osm +43 -0
  23. ocga_cli-0.1.0/docs/ocga_samples/komsomolskaya_station-rewrite.osm +3812 -0
  24. ocga_cli-0.1.0/docs/ocga_samples/komsomolskaya_station.ocga +231 -0
  25. ocga_cli-0.1.0/docs/ocga_samples/komsomolskaya_station.osm +74 -0
  26. ocga_cli-0.1.0/docs/ocga_samples/main_cathedral_of_russian_army-rewrite.osm +1524 -0
  27. ocga_cli-0.1.0/docs/ocga_samples/main_cathedral_of_russian_army.ocga +255 -0
  28. ocga_cli-0.1.0/docs/ocga_samples/main_cathedral_of_russian_army.osm +90 -0
  29. ocga_cli-0.1.0/docs/ocga_samples/moscow_manege-rewrite.osm +10158 -0
  30. ocga_cli-0.1.0/docs/ocga_samples/moscow_manege.ocga +98 -0
  31. ocga_cli-0.1.0/docs/ocga_samples/moscow_manege.osm +114 -0
  32. ocga_cli-0.1.0/docs/ocga_samples/novokuznetskaya-rewrite.osm +1260 -0
  33. ocga_cli-0.1.0/docs/ocga_samples/novokuznetskaya.ocga +86 -0
  34. ocga_cli-0.1.0/docs/ocga_samples/novokuznetskaya.osm +70 -0
  35. ocga_cli-0.1.0/docs/ocga_samples/rossi_pavilion.ocga +279 -0
  36. ocga_cli-0.1.0/docs/ocga_samples/rossi_pavilion.osm +58 -0
  37. ocga_cli-0.1.0/docs/ocga_samples/tsaritsino_rotunda-rewrite.osm +4197 -0
  38. ocga_cli-0.1.0/docs/ocga_samples/tsaritsino_rotunda.ocga +149 -0
  39. ocga_cli-0.1.0/docs/ocga_samples/tsaritsino_rotunda.osm +51 -0
  40. ocga_cli-0.1.0/example.bat +24 -0
  41. ocga_cli-0.1.0/example.sh +18 -0
  42. ocga_cli-0.1.0/pyproject.toml +37 -0
  43. ocga_cli-0.1.0/setup.cfg +4 -0
  44. ocga_cli-0.1.0/src/ocga/__init__.py +8 -0
  45. ocga_cli-0.1.0/src/ocga/cli.py +26 -0
  46. ocga_cli-0.1.0/src/ocga/mdlMisc.py +269 -0
  47. ocga_cli-0.1.0/src/ocga/mdlOsmParser.py +486 -0
  48. ocga_cli-0.1.0/src/ocga/ocga_engine.py +1590 -0
  49. ocga_cli-0.1.0/src/ocga/ocgaparser/__init__.py +7 -0
  50. ocga_cli-0.1.0/src/ocga/ocgaparser/main.py +228 -0
  51. ocga_cli-0.1.0/src/ocga/ocgaparser/ocga.g4 +175 -0
  52. ocga_cli-0.1.0/src/ocga/ocgaparser/ocga.interp +174 -0
  53. ocga_cli-0.1.0/src/ocga/ocgaparser/ocga.tokens +139 -0
  54. ocga_cli-0.1.0/src/ocga/ocgaparser/ocgaLexer.interp +233 -0
  55. ocga_cli-0.1.0/src/ocga/ocgaparser/ocgaLexer.py +361 -0
  56. ocga_cli-0.1.0/src/ocga/ocgaparser/ocgaLexer.tokens +139 -0
  57. ocga_cli-0.1.0/src/ocga/ocgaparser/ocgaListener.py +189 -0
  58. ocga_cli-0.1.0/src/ocga/ocgaparser/ocgaParser.py +2240 -0
  59. ocga_cli-0.1.0/src/ocga/ocgaparser/ocgaVisitor.py +60 -0
  60. ocga_cli-0.1.0/src/ocga/ocgaparser/rebuild_parser.bat +2 -0
  61. ocga_cli-0.1.0/src/ocga/osmparser/__init__.py +9 -0
  62. ocga_cli-0.1.0/src/ocga/osmparser/main.py +85 -0
  63. ocga_cli-0.1.0/src/ocga/osmparser/mdlXmlParser.py +64 -0
  64. ocga_cli-0.1.0/src/ocga/osmparser/osmGeometry.py +439 -0
  65. ocga_cli-0.1.0/src/ocga_cli.egg-info/PKG-INFO +85 -0
  66. ocga_cli-0.1.0/src/ocga_cli.egg-info/SOURCES.txt +69 -0
  67. ocga_cli-0.1.0/src/ocga_cli.egg-info/dependency_links.txt +1 -0
  68. ocga_cli-0.1.0/src/ocga_cli.egg-info/entry_points.txt +2 -0
  69. ocga_cli-0.1.0/src/ocga_cli.egg-info/requires.txt +1 -0
  70. ocga_cli-0.1.0/src/ocga_cli.egg-info/top_level.txt +1 -0
  71. ocga_cli-0.1.0/tests/test_main.py +87 -0
ocga_cli-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Zkir
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,18 @@
1
+ # Include essential documentation, license, and example files
2
+ include README.md
3
+ include LICENSE
4
+ include example.bat
5
+ include example.sh
6
+
7
+ # Recursively include the source code directory
8
+ graft src
9
+
10
+ # include tests and docs. Not that tests require samples in the doc foloder
11
+ graft docs
12
+ graft tests
13
+
14
+ # Exclude generated output from the docs folder
15
+ prune docs/ocga_output
16
+
17
+ global-exclude *.py[co]
18
+ global-exclude __pycache__
@@ -0,0 +1,85 @@
1
+ Metadata-Version: 2.4
2
+ Name: ocga-cli
3
+ Version: 0.1.0
4
+ Summary: A procedural modeling engine for OpenStreetMap building generation.
5
+ Author-email: Zkir <zkir@zkir.ru>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Zkir/ocga
8
+ Project-URL: Bug Tracker, https://github.com/Zkir/ocga/issues
9
+ Project-URL: Documentation, https://github.com/Zkir/ocga/blob/main/docs/OCGA.md
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Topic :: Scientific/Engineering :: GIS
14
+ Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Classifier: Intended Audience :: Science/Research
17
+ Requires-Python: >=3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: antlr4-python3-runtime
21
+ Dynamic: license-file
22
+
23
+ # OCGA: Procedural 3D Buildings for OpenStreetMap
24
+
25
+ Creating detailed [3D buildings](https://wiki.openstreetmap.org/wiki/Simple_3D_Buildings) in OSM by manually adding **building:part's** and moving nodes back and forth is tedious and slow.
26
+
27
+ OCGA (OSM Computer-Generated Architecture) is built on a key insight: much like music, architecture is often based on the **repetition of common elements and patterns**.
28
+
29
+ Because architecture is inherently rule-based, we can leverage a different approach: **procedural generation**. Instead of building models by hand, you define these architectural patterns using a simple `.ocga` language, and let the engine execute the repetitive work of generating the complex geometry for you.
30
+
31
+ To achieve this, we have developed a new, unique domain-specific language: **OCGA**. This project provides both the **[OCGA language specification](https://github.com/Zkir/ocga/blob/main/docs/OCGA.md)** and a simple **command-line tool** that interprets this new language, enabling rapid creation of detailed building models.
32
+
33
+ While certain ideas were adopted from ESRI's CityEngine, OCGA is not its clone, and many things are implemented differently.
34
+
35
+
36
+ ## Installation
37
+
38
+ Install the package from PyPI:
39
+ ```bash
40
+ pip install ocga
41
+ ```
42
+
43
+ ## Workflow
44
+
45
+ The intended cycle for using OCGA is as follows:
46
+
47
+ 1. **Create an Outline:** Start by saving a building's footprint/outline into its own `.osm` file.
48
+
49
+ 2. **Define the Rules:** Write a corresponding `.ocga` rules file tailored to that building's architecture. This is where you describe how to procedurally generate the model's parts.
50
+
51
+ 3. **Generate the Model:** Run the `ocga` command-line tool, providing it with your outline and rules files.
52
+ ```bash
53
+ ocga -i <path/to/your_building.osm> -r <path/to/your_rules.ocga> -o <path/to/generated_model.osm>
54
+ ```
55
+
56
+ 4. **Verify Before Uploading!** Before you upload the data to OpenStreetMap, it is **crucial** to visually inspect the generated model.
57
+ - **Primary Method (JOSM):** The easiest way is to open the generated `.osm` file in JOSM and use the **[UrbanEye3D](https://wiki.openstreetmap.org/wiki/JOSM/Plugins/Urban_Eye_3D)** plugin viewer.
58
+ - **Alternative Method:** You can use `osm2world` to export the model to a `.gltf` file, which can then be opened in any standard 3D viewer (like the built-in Windows 3D Viewer or `f3d` on Linux).
59
+
60
+ 5. **Upload to OpenStreetMap:** Once you are satisfied, you can upload the data from JOSM. You may need to merge the layer containing the generated model with your main data layer before uploading.
61
+
62
+ ## Usage as a Library
63
+
64
+ While the primary use case for OCGA is the command-line tool, its core engine can be imported and used directly in your own Python projects, as permitted by the MIT license.
65
+
66
+ The main entry point function is `ocga_process2`, which can be imported from the top-level package. Its function is analogous to the CLI tool:
67
+
68
+ ```python
69
+ from ocga import ocga_process2
70
+
71
+ input_file = "path/to/building.osm"
72
+ rules_file = "path/to/rules.ocga"
73
+ output_file = "path/to/generated.osm"
74
+
75
+ # The other arguments are optional
76
+ ocga_process2(input_file, output_file, rules_file)
77
+ ```
78
+
79
+ Other functions from the engine modules (e.g., from `ocga.ocga_engine`) can also be imported, but their APIs are not guaranteed to be stable and may change. Use them at your own risk.
80
+
81
+ ## Language and Examples
82
+
83
+ - For a complete guide to the syntax and operations, see the **[OCGA Language Reference](https://github.com/Zkir/ocga/blob/main/docs/OCGA.md)**.
84
+ - A collection of sample `.osm` and `.ocga` files can be found in the **[docs/ocga_samples](https://github.com/Zkir/ocga/tree/main/docs/ocga_samples)** directory.
85
+ - The `example.bat` and `example.sh` scripts in the root directory demonstrate how to run the tool on these samples.
@@ -0,0 +1,63 @@
1
+ # OCGA: Procedural 3D Buildings for OpenStreetMap
2
+
3
+ Creating detailed [3D buildings](https://wiki.openstreetmap.org/wiki/Simple_3D_Buildings) in OSM by manually adding **building:part's** and moving nodes back and forth is tedious and slow.
4
+
5
+ OCGA (OSM Computer-Generated Architecture) is built on a key insight: much like music, architecture is often based on the **repetition of common elements and patterns**.
6
+
7
+ Because architecture is inherently rule-based, we can leverage a different approach: **procedural generation**. Instead of building models by hand, you define these architectural patterns using a simple `.ocga` language, and let the engine execute the repetitive work of generating the complex geometry for you.
8
+
9
+ To achieve this, we have developed a new, unique domain-specific language: **OCGA**. This project provides both the **[OCGA language specification](https://github.com/Zkir/ocga/blob/main/docs/OCGA.md)** and a simple **command-line tool** that interprets this new language, enabling rapid creation of detailed building models.
10
+
11
+ While certain ideas were adopted from ESRI's CityEngine, OCGA is not its clone, and many things are implemented differently.
12
+
13
+
14
+ ## Installation
15
+
16
+ Install the package from PyPI:
17
+ ```bash
18
+ pip install ocga
19
+ ```
20
+
21
+ ## Workflow
22
+
23
+ The intended cycle for using OCGA is as follows:
24
+
25
+ 1. **Create an Outline:** Start by saving a building's footprint/outline into its own `.osm` file.
26
+
27
+ 2. **Define the Rules:** Write a corresponding `.ocga` rules file tailored to that building's architecture. This is where you describe how to procedurally generate the model's parts.
28
+
29
+ 3. **Generate the Model:** Run the `ocga` command-line tool, providing it with your outline and rules files.
30
+ ```bash
31
+ ocga -i <path/to/your_building.osm> -r <path/to/your_rules.ocga> -o <path/to/generated_model.osm>
32
+ ```
33
+
34
+ 4. **Verify Before Uploading!** Before you upload the data to OpenStreetMap, it is **crucial** to visually inspect the generated model.
35
+ - **Primary Method (JOSM):** The easiest way is to open the generated `.osm` file in JOSM and use the **[UrbanEye3D](https://wiki.openstreetmap.org/wiki/JOSM/Plugins/Urban_Eye_3D)** plugin viewer.
36
+ - **Alternative Method:** You can use `osm2world` to export the model to a `.gltf` file, which can then be opened in any standard 3D viewer (like the built-in Windows 3D Viewer or `f3d` on Linux).
37
+
38
+ 5. **Upload to OpenStreetMap:** Once you are satisfied, you can upload the data from JOSM. You may need to merge the layer containing the generated model with your main data layer before uploading.
39
+
40
+ ## Usage as a Library
41
+
42
+ While the primary use case for OCGA is the command-line tool, its core engine can be imported and used directly in your own Python projects, as permitted by the MIT license.
43
+
44
+ The main entry point function is `ocga_process2`, which can be imported from the top-level package. Its function is analogous to the CLI tool:
45
+
46
+ ```python
47
+ from ocga import ocga_process2
48
+
49
+ input_file = "path/to/building.osm"
50
+ rules_file = "path/to/rules.ocga"
51
+ output_file = "path/to/generated.osm"
52
+
53
+ # The other arguments are optional
54
+ ocga_process2(input_file, output_file, rules_file)
55
+ ```
56
+
57
+ Other functions from the engine modules (e.g., from `ocga.ocga_engine`) can also be imported, but their APIs are not guaranteed to be stable and may change. Use them at your own risk.
58
+
59
+ ## Language and Examples
60
+
61
+ - For a complete guide to the syntax and operations, see the **[OCGA Language Reference](https://github.com/Zkir/ocga/blob/main/docs/OCGA.md)**.
62
+ - A collection of sample `.osm` and `.ocga` files can be found in the **[docs/ocga_samples](https://github.com/Zkir/ocga/tree/main/docs/ocga_samples)** directory.
63
+ - The `example.bat` and `example.sh` scripts in the root directory demonstrate how to run the tool on these samples.
@@ -0,0 +1,156 @@
1
+ # OCGA Language Reference
2
+
3
+ This document describes the OCGA (OpenStreetMap Computer Generated Architecture) language, its syntax, and supported operations.
4
+
5
+
6
+ ## Execution Model
7
+
8
+ OCGA is a declarative language used to define rules for generating 3D building models (building:part's) from 2D OpenStreetMap data.
9
+
10
+ OCGA processes shapes through a series of rule applications. The workflow operates as follows:
11
+
12
+ 1. **Input:** The engine starts with an `.osm` file containing one or more building outlines.
13
+ 2. **Entry Point:** The special rule named **`building`** is the entry point, which is automatically applied to all objects with a `building` tag found in the input file.
14
+ 3. **Transformation and Subdivision:** When a rule is applied to an object, it can perform various operations: modify geometry, assign tags, or, most importantly, subdivide the object into new parts using operators like `split`, `comp`, or `continue`.
15
+ 4. **Rule Chaining:** When an object is subdivided, each new part is assigned a new rule name. This new rule will be applied to the corresponding part on a subsequent cycle.
16
+ 5. **Termination:** The engine runs in a loop. It continues processing as long as there are objects with unprocessed rules. When a full processing cycle completes and there are no more new parts with rules to apply, the execution stops, and the final geometry is produced.
17
+
18
+ ## 1. Language Syntax
19
+
20
+ ### Program Structure
21
+
22
+ An OCGA program (`.ocga` file) generally follows this structure:
23
+
24
+ ```ocga
25
+ ocga <VERSION_NUMBER>
26
+ const <CONSTANT_NAME> = <expression>
27
+ ...
28
+ const <ANOTHER_CONSTANT_NAME> = <expression>
29
+ ...
30
+ rule <RULE_NAME> :
31
+ <operator1>
32
+ <operator2>
33
+ ...
34
+ rule <ANOTHER_RULE_NAME> :
35
+ <operatorN>
36
+ ...
37
+ ```
38
+
39
+ * **`ocga <VERSION_NUMBER>`**: The program must start with an `ocga` keyword followed by a version number.
40
+ * **`const <CONSTANT_NAME> = <expression>`**: (Optional) Defines a constant that can be used in expressions.
41
+ * **`rule <RULE_NAME> :`**: Defines a named block of one or more operators. The engine applies rules to objects when their conditions are met.
42
+ * **Entry Point:** The rule named **`building`** is the special entry point. It is automatically applied to top-level objects from the input `.osm` file that have a `building` tag.
43
+ * `<RULE_NAME>`: An identifier for the rule (e.g., `building`, `MainWall`, `Window`). Other rules are typically applied to the new objects created by `split` or `comp` operations.
44
+
45
+ ### Conditional Statements
46
+
47
+ OCGA supports `if-then-else` conditional logic:
48
+
49
+ ```ocga
50
+ if <logical_expression> then
51
+ <operator1>
52
+ <operator2>
53
+ else
54
+ <operator3>
55
+ endif
56
+ ```
57
+
58
+ * **`if <logical_expression> then ... endif`**: Executes operators if the `logical_expression` is true.
59
+ * **`else ...`**: (Optional) Executes operators if the `logical_expression` is false.
60
+
61
+ ### Expressions
62
+
63
+ * **`expr` (Arithmetic Expression)**: Can include numbers, literals, constants, relative numbers, and basic arithmetic operations (`+`, `-`, `*`, `/`, `%`).
64
+ * **Relative Numbers**: Numbers prefixed with an apostrophe (e.g., `'0.5`) are treated as relative values, often calculated based on the current object's scope dimensions.
65
+ * **`lexpr` (Logical Expression)**: Used in `if` statements. Supports comparisons (`<`, `>`, `<=`, `>=`, `==`, `!=`), `not`, `and`, `or`.
66
+ * **`list`**: A list of numbers enclosed in square brackets (e.g., `[0, 1, 5]`), typically used to specify indices of edges or nodes.
67
+
68
+ ### Split Patterns
69
+
70
+ Used with `split_x`, `split_y`, `split_z` operators to define how an object is subdivided and which rule applies to each subdivision.
71
+
72
+ ```ocga
73
+ <split_selector> : <rule_name> | <split_selector> : <rule_name> | <split_selector> : <rule_name>
74
+ ```
75
+
76
+ * **`<split_selector>`**:
77
+ * A number (e.g., `10`, `'0.3`) indicating a fixed size or a relative proportion.
78
+ * `~<NUMBER>`: An "approximately" size, where the number acts as a weight, and the actual size is calculated proportionally based on remaining space.
79
+ * **`<rule_name>`**: The rule to apply to the newly created object (subdivision).
80
+ * **Compound Split Patterns**: `(<split_pattern>) * <NUMBER>` can be used for repeating sections of a split pattern.
81
+
82
+ ### Comments
83
+
84
+ Single-line comments start with `#`.
85
+
86
+ ## 2. Supported Operations
87
+
88
+ Operations manipulate the current 3D object (a `T3DObject`). Many operations produce new objects, which are then added to the processing queue.
89
+
90
+ ### Attributes (Tagging)
91
+
92
+ * **`tag <key>, <value>`**: Sets an OpenStreetMap tag (`key=value`) on the current object.
93
+ * **`colour <value>`**: Sets the `building:colour` tag. Hexadecimal values can be prefixed with `&` (e.g., `&RRGGBB`).
94
+ * **`material <value>`**: Sets the `building:material` tag.
95
+ * **`roof_colour <value>`**: Sets the `roof:colour` tag.
96
+ * **`roof_material <value>`**: Sets the `roof:material` tag.
97
+ * **`roof_direction <value>`**: Sets the `roof:direction` tag, typically an angle in degrees.
98
+
99
+ ### Scope Operations
100
+
101
+ * **`align_scope ('geometry' | 'x_to_longer_side')`**: Aligns the object's local coordinate system (scope).
102
+ * `'geometry'`: Aligns to the geometry's bounding box.
103
+ * `'x_to_longer_side'`: Rotates the scope so its X-axis aligns with the longer side of the object.
104
+ * **`rotate_scope <angle_z>`**: Rotates the object's local coordinate system around the Z-axis by `angle_z` degrees.
105
+
106
+ ### Geometry Creation
107
+
108
+ * **`outer_rectangle <rule_name>`**: Replaces the current object's geometry with its outer bounding rectangle, then applies `rule_name` to this new shape.
109
+ * **`primitive_cylinder <radius>` / `primitive_cylinder <radius>, [<nVertices>]` / `primitive_cylinder <radius>, [<nVertices>], [<pattern>]`**: Replaces the current object's geometry with a circular/cylindrical shape.
110
+ * `radius`: The radius of the circle.
111
+ * `nVertices`: (Optional) Number of vertices for the approximation of the circle (default 12).
112
+ * `pattern`: (Optional) Pattern for angular distribution of vertices.
113
+ * **`primitive_halfcylinder <radius>, [<nVertices>]`**: Replaces the current object's geometry with a half-circular/half-cylindrical shape.
114
+ * **`create_roof <roof_shape>, <roof_height>`**: Sets `roof:shape` and `roof:height` tags for the current object. `roof_height` can be relative to the object's current Z-scope.
115
+
116
+ ### Geometry Subdivision
117
+
118
+ These operations split the current object into multiple new objects, typically applying a rule to each new part. The original object is often 'nil'-ed (removed) after the split.
119
+
120
+ * **`split_x <split_pattern>`**: Splits the object along its local X-axis according to the `split_pattern`.
121
+ * **`split_y <split_pattern>`**: Splits the object along its local Y-axis according to the `split_pattern`.
122
+ * **`split_z <split_pattern>`**: Splits the object along its local Z-axis (height) according to the `split_pattern`. Handles roof preservation.
123
+ * **`comp_border <distance>, <rule_name>`**: Creates new objects representing an offset border around the current object, then applies `rule_name`. Designed for symmetrical shapes.
124
+ * **`comp_edges <distance>, <rule_name>`**: Creates new objects, each representing a "band" along an edge of the current object (similar to `comp_border` but for each edge individually), then applies `rule_name`.
125
+ * **`comp_roof <rule_name>`**: Creates a new object that represents the roof of the current object (with adjusted `min_height` and `height`), then applies `rule_name`.
126
+
127
+ ### Transformations
128
+
129
+ These operations modify the scale, position, or rotation of the current object.
130
+
131
+ * **`scale <sx>, <sy>, [<sz>]`**: Scales the current object along its local X, Y, and optionally Z axes. `sx`, `sy`, `sz` can be relative.
132
+ * **`translate <dx>, <dy>, [<dz>]`**: Translates (moves) the current object along its local X, Y, and optionally Z axes. `dx`, `dy`, `dz` can be relative.
133
+ * **`rotate <angle_z>`**: Rotates the current object around its local Z-axis by `angle_z` degrees.
134
+
135
+ ### Geometry Modifications
136
+
137
+ * **`bevel <radius>, [<node_list>]`**: Applies a bevel (rounding or chamfering of corners) to the current object.
138
+ * `radius`: The radius of the bevel.
139
+ * `node_list`: (Optional) A list of node indices to apply the bevel to. Only works for closed polygons.
140
+ * **`insert2 <a_param>, <b_param>, [<edge_list>]`**: Inserts new geometry into the current object's edges. Creates new nodes along the edges, potentially pushing them inwards or outwards.
141
+ * `a_param`: Controls the distance along the edge where new nodes are inserted.
142
+ * `b_param`: Controls the offset distance (e.g., inwards/outwards) from the edge.
143
+ * `edge_list`: (Optional) A list of edge indices to apply the operation to. Only works for closed polygons.
144
+
145
+ ### Flow Control Operations
146
+
147
+ * **`massModel <rule_name>`**: For a building outline, it applies a `split_z` operation to generate a mass model part and then applies `rule_name` to it.
148
+ * **`continue <rule_name>`**: This is a fundamental object transformation, not a subroutine call. It performs the following steps:
149
+ 1. A new object, identical to the current one, is created.
150
+ 2. This new object is scheduled to be processed by `<rule_name>` on the next cycle of the engine.
151
+ 3. The original object remains in the current context, and subsequent operations within the same rule block can still act on it.
152
+ This allows for powerful, non-destructive transformations. For example, using `continue` twice with different rules will result in two new, identical objects being created from the original, each scheduled for a different rule. Not allowed for top-level buildings.
153
+ * **`nope`**: A no-operation, effectively doing nothing. Can be useful as a placeholder.
154
+ * **`restore`**: Ensures the current object remains in the list of active objects, useful if it was previously removed (e.g., by a `split` operation).
155
+ * **`nil`**: Removes the current object from the list of active objects. Useful for creating holes.
156
+ * **`print <expression>`**: Prints the value of the expression to the console (for debugging).