有没有办法在 openSCAD 的测试中设置两个外部变量值?

Is there a way to set two outer variable value in a test in openSCAD?

据我了解,openSCAD 试图成为一种函数式语言,因此无法从上下文内部设置外部变量值。例如:

(p, q) = true ? (1, 2) : (3, 4);
if (faces==4) {
  p=3; q=3;
} else if (faces==6) {
  p=4; q=3;
} else if (faces==8) {
  p=3; q=4;
} else if (faces==12) {
  p=5; q=3;
} else if (faces==20) {
  p=3; q=5;
} else {
  message = str("platon solid cannot have ", faces, " faces (only 4, 6, 8, 12 and 20).");
  assert (false, message);
}
dihedral = 2*asin(cos(180/p)/sin(180/p)); // Won't work

在像 python 这样的语言中,解决此类问题的简单方法是 return 一个元组。例如:

def platon(faces):
    if faces==4: return 3, 3
    if faces==6: return 4, 3
    if faces==8: return 3, 4
    if faces==12: return 5, 3
    if faces==20: return 3, 5
    raise ValueError(f"platon solid cannot have {faces} faces (only 4, 6, 8, 12 and 20)."

p, q = platon(N)
dihedral = 2*asin(cos(180/p)/sin(180/p))

但看起来 openSCAD 一次无法 return 多于一个变量... 有没有办法(解决方法除外)来解决此类问题?

Indeed:

OpenSCAD is a Functional programming language, as such variables are bound to expressions and keep a single value during their entire lifetime due to the requirements of referential transparency. In imperative languages, such as C, the same behavior is seen as constants, which are typically contrasted with normal variables.

另请注意:

OpenSCAD variables are created by a statement with a name or identifier, assignment via an expression and a semicolon. The role of arrays, found in many imperative languages, is handled in OpenSCAD via vectors.

此外,条件语句可以用来解决这个具体问题,你需要确保变量的单一赋值。

faces = 8;
vector = faces == 4 ? [3,3] : faces == 6 ? [4,3] : faces == 8 ? [3,4] : faces == 12 ? [5,3] : faces == 20 ? [3,5] : [0,0];
echo("Vector is ", vector);
if (vector[0] == 0 && vector[1] == 0) {
    message = str("platon solid cannot have ", faces, " faces (only 4, 6, 8, 12 and 20).");
    assert (false, message);
    } else {
    // do note that this is a different equation than in the example 
    // to demonstrate usage of both vector elements!!!
    dihedral = 2*asin(cos(180/vector[0])/sin(180/vector[1])); // Will work
    echo("Dihedral is ", dihedral);
    }

以上结果:

Parsing design (AST generation)...
Saved backup file: C:/Users/User/Documents/OpenSCAD/backups/unsaved-backup-VmsPOXsj.scad
Compiling design (CSG Tree generation)...
ECHO: "Vector is ", [3, 4]
ECHO: "Dihedral is ", 90
Compiling design (CSG Products generation)...
Geometries in cache: 0
Geometry cache size in bytes: 0
CGAL Polyhedrons in cache: 0
CGAL cache size in bytes: 0
Compiling design (CSG Products normalization)...
Normalized tree has 1 elements!
Compile and preview finished.
Total rendering time: 0:00:00.023

faces = 5 脚本将抛出断言:

 
Parsing design (AST generation)...
Saved backup file: C:/Users/User/Documents/OpenSCAD/backups/unsaved-backup-VmsPOXsj.scad
Compiling design (CSG Tree generation)...
ECHO: "Vector is ", [0, 0]
ERROR: Assertion 'false' failed: "platon solid cannot have 5 faces (only 4, 6, 8, 12 and 20)." in file openscad-2021.01, line 7 
TRACE: called by 'assert' in file openscad-2021.01, line 7 
TRACE: called by 'if' in file openscad-2021.01, line 5 
Compiling design (CSG Products generation)...
Geometries in cache: 0
Geometry cache size in bytes: 0
CGAL Polyhedrons in cache: 0
CGAL cache size in bytes: 0
Compiling design (CSG Products normalization)...
Normalized tree has 1 elements!
Compile and preview finished.
Total rendering time: 0:00:00.051
<span class="math-container">```</span>