mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-02-17 17:09:45 +00:00
Add regression run to CI.
This commit is contained in:
parent
1cd153d588
commit
f727a9c3f1
7 changed files with 369 additions and 65 deletions
|
@ -8,7 +8,34 @@ on: [push]
|
||||||
|
|
||||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||||
jobs:
|
jobs:
|
||||||
# This workflow contains a single job called "gendocs"
|
Regressions:
|
||||||
|
# The type of runner that the job will run on
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Wiki Checkout
|
||||||
|
run: |
|
||||||
|
cd $GITHUB_WORKSPACE
|
||||||
|
git clone https://github.com/revarbat/BOSL2.wiki.git
|
||||||
|
|
||||||
|
- name: Install wget
|
||||||
|
run: sudo apt-get install wget
|
||||||
|
|
||||||
|
- name: Get OpenSCAD Appimage
|
||||||
|
run: |
|
||||||
|
cd $GITHUB_WORKSPACE
|
||||||
|
wget https://files.openscad.org/OpenSCAD-2019.05-x86_64.AppImage
|
||||||
|
sudo mv OpenSCAD-2019.05-x86_64.AppImage /usr/local/bin/openscad
|
||||||
|
sudo chmod +x /usr/local/bin/openscad
|
||||||
|
|
||||||
|
- name: Run Regression Tests
|
||||||
|
run: |
|
||||||
|
cd $GITHUB_WORKSPACE
|
||||||
|
export OPENSCADPATH=$(dirname $GITHUB_WORKSPACE)
|
||||||
|
./scripts/run_tests.sh
|
||||||
|
|
||||||
CheckDocs:
|
CheckDocs:
|
||||||
# The type of runner that the job will run on
|
# The type of runner that the job will run on
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -36,15 +63,15 @@ jobs:
|
||||||
- name: Install Pillow
|
- name: Install Pillow
|
||||||
run: sudo pip3 install Pillow
|
run: sudo pip3 install Pillow
|
||||||
|
|
||||||
- name: Install wget
|
# - name: Install wget
|
||||||
run: sudo apt-get install wget
|
# run: sudo apt-get install wget
|
||||||
|
|
||||||
- name: Get OpenSCAD Appimage
|
- name: Install OpenSCAD
|
||||||
run: |
|
run: |
|
||||||
cd $GITHUB_WORKSPACE
|
cd $GITHUB_WORKSPACE
|
||||||
wget https://files.openscad.org/OpenSCAD-2019.05-x86_64.AppImage
|
wget https://files.openscad.org/OpenSCAD-2019.05-x86_64.AppImage
|
||||||
mv OpenSCAD-2019.05-x86_64.AppImage openscad
|
sudo mv OpenSCAD-2019.05-x86_64.AppImage /usr/local/bin/openscad
|
||||||
chmod +x openscad
|
sudo chmod +x /usr/local/bin/openscad
|
||||||
|
|
||||||
- name: Generate Index
|
- name: Generate Index
|
||||||
run: |
|
run: |
|
||||||
|
@ -54,8 +81,6 @@ jobs:
|
||||||
- name: Generating Docs
|
- name: Generating Docs
|
||||||
run: |
|
run: |
|
||||||
cd $GITHUB_WORKSPACE
|
cd $GITHUB_WORKSPACE
|
||||||
export PATH=$GITHUB_WORKSPACE:$PATH
|
|
||||||
export OPENSCADPATH=$(dirname $GITHUB_WORKSPACE)
|
export OPENSCADPATH=$(dirname $GITHUB_WORKSPACE)
|
||||||
echo "Using OPENSCADPATH=$OPENSCADPATH"
|
./scripts/make_all_docs.sh -t -i
|
||||||
./scripts/make_all_docs.sh -i
|
|
||||||
|
|
18
affine.scad
18
affine.scad
|
@ -245,13 +245,14 @@ function affine3d_rot_from_to(from, to) =
|
||||||
|
|
||||||
|
|
||||||
// Function: affine_frame_map()
|
// Function: affine_frame_map()
|
||||||
// Usage: map = affine_frame_map(x=v1,y=v2);
|
// Usage:
|
||||||
// map = affine_frame_map(x=v1,z=v2);
|
// map = affine_frame_map(x=v1,y=v2);
|
||||||
// map = affine_frame_map(y=v1,y=v2);
|
// map = affine_frame_map(x=v1,z=v2);
|
||||||
// map = affine_frame_map(v1,v2,v3);
|
// map = affine_frame_map(y=v1,y=v2);
|
||||||
|
// map = affine_frame_map(v1,v2,v3);
|
||||||
// Description:
|
// Description:
|
||||||
// Returns a transformation that maps one coordinate frame to another. You must specify two or three of `x`, `y`, and `z`. The specified
|
// Returns a transformation that maps one coordinate frame to another. You must specify two or three of `x`, `y`, and `z`. The specified
|
||||||
// axes are mapped to the vectors you supplied. If you give two inputs, the third vector is mapped to the appropriate normal to maintain a right hand coordinate system.
|
// axes are mapped to the vectors you supplied. If you give two inputs, the third vector is mapped to the appropriate normal to maintain a right hand coordinate system.
|
||||||
// If the vectors you give are orthogonal the result will be a rotation and the `reverse` parameter will supply the inverse map, which enables you
|
// If the vectors you give are orthogonal the result will be a rotation and the `reverse` parameter will supply the inverse map, which enables you
|
||||||
// to map two arbitrary coordinate systems to each other by using the canonical coordinate system as an intermediary. You cannot use the `reverse` option
|
// to map two arbitrary coordinate systems to each other by using the canonical coordinate system as an intermediary. You cannot use the `reverse` option
|
||||||
// with non-orthogonal inputs.
|
// with non-orthogonal inputs.
|
||||||
|
@ -261,8 +262,8 @@ function affine3d_rot_from_to(from, to) =
|
||||||
// z = Destination vector for z axis
|
// z = Destination vector for z axis
|
||||||
// reverse = reverse direction of the map for orthogonal inputs. Default: false
|
// reverse = reverse direction of the map for orthogonal inputs. Default: false
|
||||||
// Examples:
|
// Examples:
|
||||||
// T = affine_frame_map(x=[1,1,0], y=[-1,1]); // This map is just a rotation around the z axis
|
// T = affine_frame_map(x=[1,1,0], y=[-1,1,0]); // This map is just a rotation around the z axis
|
||||||
// T = affine_frame_map(x=[1,0,0], y=[1,1]); // This map is not a rotation because x and y aren't orthogonal
|
// T = affine_frame_map(x=[1,0,0], y=[1,1,0]); // This map is not a rotation because x and y aren't orthogonal
|
||||||
// // The next map sends [1,1,0] to [0,1,1] and [-1,1,0] to [0,-1,1]
|
// // The next map sends [1,1,0] to [0,1,1] and [-1,1,0] to [0,-1,1]
|
||||||
// T = affine_frame_map(x=[0,1,1], y=[0,-1,1]) * affine_frame_map(x=[1,1,0], y=[-1,1,0],reverse=true);
|
// T = affine_frame_map(x=[0,1,1], y=[0,-1,1]) * affine_frame_map(x=[1,1,0], y=[-1,1,0],reverse=true);
|
||||||
function affine_frame_map(x,y,z, reverse=false) =
|
function affine_frame_map(x,y,z, reverse=false) =
|
||||||
|
@ -319,7 +320,7 @@ function affine3d_mirror(v) =
|
||||||
|
|
||||||
// Function: affine3d_skew()
|
// Function: affine3d_skew()
|
||||||
// Usage:
|
// Usage:
|
||||||
// mat = affine3d_skew([sxy], [sxz], [syx], [xyz], [szx], [szy]);
|
// mat = affine3d_skew([sxy], [sxz], [syx], [syz], [szx], [szy]);
|
||||||
// Description:
|
// Description:
|
||||||
// Returns the 4x4 affine3d matrix to perform a skew transformation.
|
// Returns the 4x4 affine3d matrix to perform a skew transformation.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
|
@ -433,6 +434,7 @@ function apply(transform,points) =
|
||||||
// transformed = apply_list(path3d(circle(r=3)),[xrot(45)]); // Rotates 3d circle data around x axis
|
// transformed = apply_list(path3d(circle(r=3)),[xrot(45)]); // Rotates 3d circle data around x axis
|
||||||
// transformed = apply_list(circle(r=3), [scale(3), right(4), rot(45)]); // Scales, then translates, and then rotates 2d circle data
|
// transformed = apply_list(circle(r=3), [scale(3), right(4), rot(45)]); // Scales, then translates, and then rotates 2d circle data
|
||||||
function apply_list(points,transform_list) =
|
function apply_list(points,transform_list) =
|
||||||
|
transform_list == []? points :
|
||||||
is_vector(points) ? apply_list([points],transform_list)[0] :
|
is_vector(points) ? apply_list([points],transform_list)[0] :
|
||||||
let(
|
let(
|
||||||
tdims = array_dim(transform_list),
|
tdims = array_dim(transform_list),
|
||||||
|
|
|
@ -127,22 +127,29 @@ def git_checkout(filename):
|
||||||
err = p.stdout.read()
|
err = p.stdout.read()
|
||||||
|
|
||||||
|
|
||||||
def run_openscad_script(libfile, infile, imgfile, imgsize=(320,240), eye=None, show_edges=False, render=False):
|
def run_openscad_script(libfile, infile, imgfile, imgsize=(320,240), eye=None, show_edges=False, render=False, test_only=False):
|
||||||
scadcmd = [
|
if test_only:
|
||||||
OPENSCAD,
|
scadcmd = [
|
||||||
"-o", imgfile,
|
OPENSCAD,
|
||||||
"--imgsize={},{}".format(imgsize[0]*2, imgsize[1]*2),
|
"-o", "foo.term",
|
||||||
"--hardwarnings",
|
"--hardwarnings"
|
||||||
"--projection=o",
|
]
|
||||||
"--autocenter",
|
|
||||||
"--viewall"
|
|
||||||
]
|
|
||||||
if eye is not None:
|
|
||||||
scadcmd.extend(["--camera", eye+",0,0,0"])
|
|
||||||
if show_edges:
|
|
||||||
scadcmd.extend(["--view=axes,scales,edges"])
|
|
||||||
else:
|
else:
|
||||||
scadcmd.extend(["--view=axes,scales"])
|
scadcmd = [
|
||||||
|
OPENSCAD,
|
||||||
|
"-o", imgfile,
|
||||||
|
"--imgsize={},{}".format(imgsize[0]*2, imgsize[1]*2),
|
||||||
|
"--hardwarnings",
|
||||||
|
"--projection=o",
|
||||||
|
"--autocenter",
|
||||||
|
"--viewall"
|
||||||
|
]
|
||||||
|
if eye is not None:
|
||||||
|
scadcmd.extend(["--camera", eye+",0,0,0"])
|
||||||
|
if show_edges:
|
||||||
|
scadcmd.extend(["--view=axes,scales,edges"])
|
||||||
|
else:
|
||||||
|
scadcmd.extend(["--view=axes,scales"])
|
||||||
if render: # Force render
|
if render: # Force render
|
||||||
scadcmd.extend(["--render", ""])
|
scadcmd.extend(["--render", ""])
|
||||||
scadcmd.append(infile)
|
scadcmd.append(infile)
|
||||||
|
@ -151,6 +158,8 @@ def run_openscad_script(libfile, infile, imgfile, imgsize=(320,240), eye=None, s
|
||||||
p = subprocess.Popen(scadcmd, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
|
p = subprocess.Popen(scadcmd, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
|
||||||
(stdoutdata, stderrdata) = p.communicate(None)
|
(stdoutdata, stderrdata) = p.communicate(None)
|
||||||
res = p.returncode
|
res = p.returncode
|
||||||
|
if test_only and os.path.isfile("foo.term"):
|
||||||
|
os.unlink("foo.term")
|
||||||
if res != 0 or b"ERROR:" in stderrdata or b"TRACE:" in stderrdata:
|
if res != 0 or b"ERROR:" in stderrdata or b"TRACE:" in stderrdata:
|
||||||
print("\n\n{}".format(stderrdata.decode('utf-8')))
|
print("\n\n{}".format(stderrdata.decode('utf-8')))
|
||||||
print("////////////////////////////////////////////////////")
|
print("////////////////////////////////////////////////////")
|
||||||
|
@ -177,6 +186,7 @@ class ImageProcessing(object):
|
||||||
self.imgroot = ""
|
self.imgroot = ""
|
||||||
self.keep_scripts = False
|
self.keep_scripts = False
|
||||||
self.force = False
|
self.force = False
|
||||||
|
self.test_only = False
|
||||||
|
|
||||||
def set_keep_scripts(self, x):
|
def set_keep_scripts(self, x):
|
||||||
self.keep_scripts = x
|
self.keep_scripts = x
|
||||||
|
@ -187,9 +197,10 @@ class ImageProcessing(object):
|
||||||
def set_commoncode(self, code):
|
def set_commoncode(self, code):
|
||||||
self.commoncode = code
|
self.commoncode = code
|
||||||
|
|
||||||
def process_examples(self, imgroot, force=False):
|
def process_examples(self, imgroot, force=False, test_only=False):
|
||||||
self.imgroot = imgroot
|
self.imgroot = imgroot
|
||||||
self.force = force
|
self.force = force
|
||||||
|
self.test_only = test_only
|
||||||
self.hashes = {}
|
self.hashes = {}
|
||||||
with dbm.gnu.open("examples_hashes.gdbm", "c") as db:
|
with dbm.gnu.open("examples_hashes.gdbm", "c") as db:
|
||||||
for libfile, imgfile, code, extype in self.examples:
|
for libfile, imgfile, code, extype in self.examples:
|
||||||
|
@ -204,6 +215,7 @@ class ImageProcessing(object):
|
||||||
print(" {}".format(imgfile), end='')
|
print(" {}".format(imgfile), end='')
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
test_only = self.test_only
|
||||||
scriptfile = "tmp_{0}.scad".format(imgfile.replace(".", "_"))
|
scriptfile = "tmp_{0}.scad".format(imgfile.replace(".", "_"))
|
||||||
targimgfile = self.imgroot + imgfile
|
targimgfile = self.imgroot + imgfile
|
||||||
newimgfile = self.imgroot + "_new_" + imgfile
|
newimgfile = self.imgroot + "_new_" + imgfile
|
||||||
|
@ -248,7 +260,7 @@ class ImageProcessing(object):
|
||||||
render = "FR" in extype
|
render = "FR" in extype
|
||||||
|
|
||||||
tmpimgs = []
|
tmpimgs = []
|
||||||
if "Spin" in extype:
|
if "Spin" in extype and not test_only:
|
||||||
for ang in range(0,359,10):
|
for ang in range(0,359,10):
|
||||||
tmpimgfile = "{0}tmp_{2}_{1}.png".format(self.imgroot, ang, imgfile.replace(".", "_"))
|
tmpimgfile = "{0}tmp_{2}_{1}.png".format(self.imgroot, ang, imgfile.replace(".", "_"))
|
||||||
arad = ang * math.pi / 180;
|
arad = ang * math.pi / 180;
|
||||||
|
@ -262,7 +274,8 @@ class ImageProcessing(object):
|
||||||
imgsize=(imgsize[0]*2,imgsize[1]*2),
|
imgsize=(imgsize[0]*2,imgsize[1]*2),
|
||||||
eye=eye,
|
eye=eye,
|
||||||
show_edges=show_edges,
|
show_edges=show_edges,
|
||||||
render=render
|
render=render,
|
||||||
|
test_only=test_only
|
||||||
)
|
)
|
||||||
tmpimgs.append(tmpimgfile)
|
tmpimgs.append(tmpimgfile)
|
||||||
print(".", end='')
|
print(".", end='')
|
||||||
|
@ -275,39 +288,42 @@ class ImageProcessing(object):
|
||||||
imgsize=(imgsize[0]*2,imgsize[1]*2),
|
imgsize=(imgsize[0]*2,imgsize[1]*2),
|
||||||
eye=eye,
|
eye=eye,
|
||||||
show_edges=show_edges,
|
show_edges=show_edges,
|
||||||
render=render
|
render=render,
|
||||||
|
test_only=test_only
|
||||||
)
|
)
|
||||||
tmpimgs.append(tmpimgfile)
|
tmpimgs.append(tmpimgfile)
|
||||||
|
|
||||||
if not self.keep_scripts:
|
if not self.keep_scripts:
|
||||||
os.unlink(scriptfile)
|
os.unlink(scriptfile)
|
||||||
|
|
||||||
if len(tmpimgs) == 1:
|
if not test_only:
|
||||||
image_resize(tmpimgfile, newimgfile, imgsize)
|
if len(tmpimgs) == 1:
|
||||||
os.unlink(tmpimgs.pop(0))
|
image_resize(tmpimgfile, newimgfile, imgsize)
|
||||||
else:
|
os.unlink(tmpimgs.pop(0))
|
||||||
make_animated_gif(tmpimgs, newimgfile, size=imgsize)
|
else:
|
||||||
for tmpimg in tmpimgs:
|
make_animated_gif(tmpimgs, newimgfile, size=imgsize)
|
||||||
os.unlink(tmpimg)
|
for tmpimg in tmpimgs:
|
||||||
|
os.unlink(tmpimg)
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
# Time to compare image.
|
if not test_only:
|
||||||
if not os.path.isfile(targimgfile):
|
# Time to compare image.
|
||||||
print(" NEW IMAGE\n")
|
if not os.path.isfile(targimgfile):
|
||||||
os.rename(newimgfile, targimgfile)
|
print(" NEW IMAGE\n")
|
||||||
else:
|
|
||||||
if targimgfile.endswith(".gif"):
|
|
||||||
issame = filecmp.cmp(targimgfile, newimgfile, shallow=False)
|
|
||||||
else:
|
|
||||||
issame = image_compare(targimgfile, newimgfile);
|
|
||||||
if issame:
|
|
||||||
os.unlink(newimgfile)
|
|
||||||
else:
|
|
||||||
print(" UPDATED IMAGE\n")
|
|
||||||
os.unlink(targimgfile)
|
|
||||||
os.rename(newimgfile, targimgfile)
|
os.rename(newimgfile, targimgfile)
|
||||||
self.hashes[key] = hash
|
else:
|
||||||
|
if targimgfile.endswith(".gif"):
|
||||||
|
issame = filecmp.cmp(targimgfile, newimgfile, shallow=False)
|
||||||
|
else:
|
||||||
|
issame = image_compare(targimgfile, newimgfile);
|
||||||
|
if issame:
|
||||||
|
os.unlink(newimgfile)
|
||||||
|
else:
|
||||||
|
print(" UPDATED IMAGE\n")
|
||||||
|
os.unlink(targimgfile)
|
||||||
|
os.rename(newimgfile, targimgfile)
|
||||||
|
self.hashes[key] = hash
|
||||||
|
|
||||||
|
|
||||||
imgprc = ImageProcessing()
|
imgprc = ImageProcessing()
|
||||||
|
@ -772,7 +788,7 @@ class LibFile(object):
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
def processFile(infile, outfile=None, gen_imgs=False, imgroot="", prefix="", force=False):
|
def processFile(infile, outfile=None, gen_imgs=False, test_only=False, imgroot="", prefix="", force=False):
|
||||||
if imgroot and not imgroot.endswith('/'):
|
if imgroot and not imgroot.endswith('/'):
|
||||||
imgroot += "/"
|
imgroot += "/"
|
||||||
|
|
||||||
|
@ -792,7 +808,7 @@ def processFile(infile, outfile=None, gen_imgs=False, imgroot="", prefix="", for
|
||||||
print(line, file=f)
|
print(line, file=f)
|
||||||
|
|
||||||
if gen_imgs:
|
if gen_imgs:
|
||||||
imgprc.process_examples(imgroot, force=force)
|
imgprc.process_examples(imgroot, force=force, test_only=test_only)
|
||||||
|
|
||||||
if outfile:
|
if outfile:
|
||||||
f.close()
|
f.close()
|
||||||
|
@ -800,6 +816,8 @@ def processFile(infile, outfile=None, gen_imgs=False, imgroot="", prefix="", for
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(prog='docs_gen')
|
parser = argparse.ArgumentParser(prog='docs_gen')
|
||||||
|
parser.add_argument('-t', '--test-only', action="store_true",
|
||||||
|
help="If given, don't generate images, but do try executing the scripts.")
|
||||||
parser.add_argument('-k', '--keep-scripts', action="store_true",
|
parser.add_argument('-k', '--keep-scripts', action="store_true",
|
||||||
help="If given, don't delete the temporary image OpenSCAD scripts.")
|
help="If given, don't delete the temporary image OpenSCAD scripts.")
|
||||||
parser.add_argument('-c', '--comments-only', action="store_true",
|
parser.add_argument('-c', '--comments-only', action="store_true",
|
||||||
|
@ -820,6 +838,7 @@ def main():
|
||||||
args.infile,
|
args.infile,
|
||||||
outfile=args.outfile,
|
outfile=args.outfile,
|
||||||
gen_imgs=args.images,
|
gen_imgs=args.images,
|
||||||
|
test_only=args.test_only,
|
||||||
imgroot=args.imgroot,
|
imgroot=args.imgroot,
|
||||||
prefix="// " if args.comments_only else "",
|
prefix="// " if args.comments_only else "",
|
||||||
force=args.force
|
force=args.force
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
|
|
||||||
FORCED=""
|
FORCED=""
|
||||||
IMGGEN=""
|
IMGGEN=""
|
||||||
|
TESTONLY=""
|
||||||
FILES=""
|
FILES=""
|
||||||
DISPMD=""
|
DISPMD=""
|
||||||
for opt in "$@" ; do
|
for opt in "$@" ; do
|
||||||
case $opt in
|
case $opt in
|
||||||
-f ) FORCED=$opt ;;
|
-f ) FORCED=$opt ;;
|
||||||
-i ) IMGGEN=$opt ;;
|
-i ) IMGGEN=$opt ;;
|
||||||
|
-t ) TESTONLY=$opt ;;
|
||||||
-d ) DISPMD=$opt ;;
|
-d ) DISPMD=$opt ;;
|
||||||
-* ) echo "Unknown option $opt"; exit -1 ;;
|
-* ) echo "Unknown option $opt"; exit -1 ;;
|
||||||
* ) FILES="$FILES $opt" ;;
|
* ) FILES="$FILES $opt" ;;
|
||||||
|
@ -32,11 +34,11 @@ rm -f tmpscad*.scad
|
||||||
for lib in $PREVIEW_LIBS; do
|
for lib in $PREVIEW_LIBS; do
|
||||||
lib="$(basename $lib .scad)"
|
lib="$(basename $lib .scad)"
|
||||||
mkdir -p images/$lib
|
mkdir -p images/$lib
|
||||||
if [ "$IMGGEN" != "" ]; then
|
if [ "$IMGGEN" != "" -a "$TESTONLY" != ""]; then
|
||||||
rm -f images/$lib/*.png images/$lib/*.gif
|
rm -f images/$lib/*.png images/$lib/*.gif
|
||||||
fi
|
fi
|
||||||
echo "$lib.scad"
|
echo "$lib.scad"
|
||||||
../scripts/docs_gen.py ../$lib.scad -o $lib.scad.md -c $IMGGEN $FORCED -I images/$lib/ || exit 1
|
../scripts/docs_gen.py ../$lib.scad -o $lib.scad.md -c $IMGGEN $FORCED $TESTONLY -I images/$lib/ || exit 1
|
||||||
if [ "$DISPMD" != "" ]; then
|
if [ "$DISPMD" != "" ]; then
|
||||||
open -a Typora $lib.scad.md
|
open -a Typora $lib.scad.md
|
||||||
fi
|
fi
|
||||||
|
|
256
tests/test_affine.scad
Normal file
256
tests/test_affine.scad
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
include <BOSL2/std.scad>
|
||||||
|
|
||||||
|
|
||||||
|
module test_ident() {
|
||||||
|
assert(ident(3) == [[1,0,0],[0,1,0],[0,0,1]]);
|
||||||
|
assert(ident(4) == [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
|
||||||
|
}
|
||||||
|
test_ident();
|
||||||
|
|
||||||
|
|
||||||
|
module test_is_2d_transform() {
|
||||||
|
assert(!is_2d_transform(affine2d_identity()));
|
||||||
|
assert(!is_2d_transform(affine2d_translate([5,8])));
|
||||||
|
assert(!is_2d_transform(affine2d_scale([3,4])));
|
||||||
|
assert(!is_2d_transform(affine2d_zrot(30)));
|
||||||
|
assert(!is_2d_transform(affine2d_mirror([-1,1])));
|
||||||
|
assert(!is_2d_transform(affine2d_skew(30,15)));
|
||||||
|
|
||||||
|
assert(is_2d_transform(affine3d_identity()));
|
||||||
|
assert(is_2d_transform(affine3d_translate([30,40,0])));
|
||||||
|
assert(!is_2d_transform(affine3d_translate([30,40,50])));
|
||||||
|
assert(is_2d_transform(affine3d_scale([3,4,1])));
|
||||||
|
assert(!is_2d_transform(affine3d_xrot(30)));
|
||||||
|
assert(!is_2d_transform(affine3d_yrot(30)));
|
||||||
|
assert(is_2d_transform(affine3d_zrot(30)));
|
||||||
|
assert(is_2d_transform(affine3d_skew(sxy=2)));
|
||||||
|
assert(is_2d_transform(affine3d_skew(syx=2)));
|
||||||
|
assert(!is_2d_transform(affine3d_skew(szx=2)));
|
||||||
|
assert(!is_2d_transform(affine3d_skew(szy=2)));
|
||||||
|
}
|
||||||
|
test_is_2d_transform();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine2d_to_3d() {
|
||||||
|
assert(affine2d_to_3d(affine2d_identity()) == affine3d_identity());
|
||||||
|
assert(affine2d_to_3d(affine2d_zrot(30)) == affine3d_zrot(30));
|
||||||
|
}
|
||||||
|
test_affine2d_to_3d();
|
||||||
|
|
||||||
|
|
||||||
|
// 2D
|
||||||
|
|
||||||
|
module test_affine2d_identity() {
|
||||||
|
assert(affine2d_identity() == [[1,0,0],[0,1,0],[0,0,1]]);
|
||||||
|
}
|
||||||
|
test_affine2d_identity();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine2d_translate() {
|
||||||
|
assert(affine2d_translate([0,0]) == [[1,0,0],[0,1,0],[0,0,1]]);
|
||||||
|
assert(affine2d_translate([10,20]) == [[1,0,10],[0,1,20],[0,0,1]]);
|
||||||
|
assert(affine2d_translate([20,10]) == [[1,0,20],[0,1,10],[0,0,1]]);
|
||||||
|
}
|
||||||
|
test_affine2d_translate();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine2d_scale() {
|
||||||
|
assert(affine2d_scale([1,1]) == [[1,0,0],[0,1,0],[0,0,1]]);
|
||||||
|
assert(affine2d_scale([2,3]) == [[2,0,0],[0,3,0],[0,0,1]]);
|
||||||
|
assert(affine2d_scale([5,4]) == [[5,0,0],[0,4,0],[0,0,1]]);
|
||||||
|
}
|
||||||
|
test_affine2d_scale();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine2d_mirror() {
|
||||||
|
assert(approx(affine2d_mirror([1,1]),[[0,-1,0],[-1,0,0],[0,0,1]]));
|
||||||
|
assert(affine2d_mirror([1,0]) == [[-1,0,0],[0,1,0],[0,0,1]]);
|
||||||
|
assert(affine2d_mirror([0,1]) == [[1,0,0],[0,-1,0],[0,0,1]]);
|
||||||
|
}
|
||||||
|
test_affine2d_mirror();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine2d_zrot() {
|
||||||
|
for(a = [-360:2/3:360]) {
|
||||||
|
assert(affine2d_zrot(a) == [[cos(a),-sin(a),0],[sin(a),cos(a),0],[0,0,1]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test_affine2d_zrot();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine2d_skew() {
|
||||||
|
for(ya = [-89:3:89]) {
|
||||||
|
for(xa = [-89:3:89]) {
|
||||||
|
assert(affine2d_skew(xa=xa, ya=ya) == [[1,tan(xa),0],[tan(ya),1,0],[0,0,1]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test_affine2d_skew();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine2d_chain() {
|
||||||
|
t = affine2d_translate([15,30]);
|
||||||
|
s = affine2d_scale([1.5,2]);
|
||||||
|
r = affine2d_zrot(30);
|
||||||
|
assert(affine2d_chain([t,s,r]) == r * s * t);
|
||||||
|
}
|
||||||
|
test_affine2d_chain();
|
||||||
|
|
||||||
|
|
||||||
|
// 3D
|
||||||
|
|
||||||
|
module test_affine3d_identity() {
|
||||||
|
assert(affine3d_identity() == [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
|
||||||
|
}
|
||||||
|
test_affine3d_identity();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine3d_translate() {
|
||||||
|
assert(affine3d_translate([10,20,30]) == [[1,0,0,10],[0,1,0,20],[0,0,1,30],[0,0,0,1]]);
|
||||||
|
assert(affine3d_translate([3,2,1]) == [[1,0,0,3],[0,1,0,2],[0,0,1,1],[0,0,0,1]]);
|
||||||
|
}
|
||||||
|
test_affine3d_translate();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine3d_scale() {
|
||||||
|
assert(affine3d_scale([3,2,4]) == [[3,0,0,0],[0,2,0,0],[0,0,4,0],[0,0,0,1]]);
|
||||||
|
}
|
||||||
|
test_affine3d_scale();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine3d_mirror() {
|
||||||
|
assert(affine3d_mirror([1,0,0]) == [[-1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
|
||||||
|
assert(affine3d_mirror([0,1,0]) == [[1,0,0,0],[0,-1,0,0],[0,0,1,0],[0,0,0,1]]);
|
||||||
|
assert(affine3d_mirror([0,0,1]) == [[1,0,0,0],[0,1,0,0],[0,0,-1,0],[0,0,0,1]]);
|
||||||
|
assert(approx(affine3d_mirror([1,1,1]), [[1/3,-2/3,-2/3,0],[-2/3,1/3,-2/3,0],[-2/3,-2/3,1/3,0],[0,0,0,1]]));
|
||||||
|
}
|
||||||
|
test_affine3d_mirror();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine3d_xrot() {
|
||||||
|
for(a = [-360:2/3:360]) {
|
||||||
|
assert(approx(affine3d_xrot(a), [[1,0,0,0],[0,cos(a),-sin(a),0],[0,sin(a),cos(a),0],[0,0,0,1]]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test_affine3d_xrot();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine3d_yrot() {
|
||||||
|
for(a = [-360:2/3:360]) {
|
||||||
|
assert(approx(affine3d_yrot(a), [[cos(a),0,sin(a),0],[0,1,0,0],[-sin(a),0,cos(a),0],[0,0,0,1]]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test_affine3d_yrot();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine3d_zrot() {
|
||||||
|
for(a = [-360:2/3:360]) {
|
||||||
|
assert(approx(affine3d_zrot(a), [[cos(a),-sin(a),0,0],[sin(a),cos(a),0,0],[0,0,1,0],[0,0,0,1]]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test_affine3d_zrot();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine3d_rot_by_axis() {
|
||||||
|
for(a = [-360:2/3:360]) {
|
||||||
|
assert(approx(affine3d_rot_by_axis(RIGHT,a), [[1,0,0,0],[0,cos(a),-sin(a),0],[0,sin(a),cos(a),0],[0,0,0,1]]));
|
||||||
|
assert(approx(affine3d_rot_by_axis(BACK,a), [[cos(a),0,sin(a),0],[0,1,0,0],[-sin(a),0,cos(a),0],[0,0,0,1]]));
|
||||||
|
assert(approx(affine3d_rot_by_axis(UP,a), [[cos(a),-sin(a),0,0],[sin(a),cos(a),0,0],[0,0,1,0],[0,0,0,1]]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test_affine3d_rot_by_axis();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine3d_rot_from_to() {
|
||||||
|
assert(approx(affine3d_rot_from_to(UP,FRONT), affine3d_xrot(90)));
|
||||||
|
assert(approx(affine3d_rot_from_to(UP,RIGHT), affine3d_yrot(90)));
|
||||||
|
assert(approx(affine3d_rot_from_to(BACK,LEFT), affine3d_zrot(90)));
|
||||||
|
}
|
||||||
|
test_affine3d_rot_from_to();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine3d_skew() {
|
||||||
|
assert(affine3d_skew(sxy=2) == [[1,2,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
|
||||||
|
assert(affine3d_skew(sxz=2) == [[1,0,2,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]);
|
||||||
|
assert(affine3d_skew(syx=2) == [[1,0,0,0],[2,1,0,0],[0,0,1,0],[0,0,0,1]]);
|
||||||
|
assert(affine3d_skew(syz=2) == [[1,0,0,0],[0,1,2,0],[0,0,1,0],[0,0,0,1]]);
|
||||||
|
assert(affine3d_skew(szx=2) == [[1,0,0,0],[0,1,0,0],[2,0,1,0],[0,0,0,1]]);
|
||||||
|
assert(affine3d_skew(szy=2) == [[1,0,0,0],[0,1,0,0],[0,2,1,0],[0,0,0,1]]);
|
||||||
|
}
|
||||||
|
test_affine3d_skew();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine3d_skew_xy() {
|
||||||
|
for(ya = [-89:3:89]) {
|
||||||
|
for(xa = [-89:3:89]) {
|
||||||
|
assert(affine3d_skew_xy(xa=xa, ya=ya) == [[1,0,tan(xa),0],[0,1,tan(ya),0],[0,0,1,0],[0,0,0,1]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test_affine3d_skew_xy();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine3d_skew_xz() {
|
||||||
|
for(za = [-89:3:89]) {
|
||||||
|
for(xa = [-89:3:89]) {
|
||||||
|
assert(affine3d_skew_xz(xa=xa, za=za) == [[1,tan(xa),0,0],[0,1,0,0],[0,tan(za),1,0],[0,0,0,1]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test_affine3d_skew_xz();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine3d_skew_yz() {
|
||||||
|
for(za = [-89:3:89]) {
|
||||||
|
for(ya = [-89:3:89]) {
|
||||||
|
assert(affine3d_skew_yz(ya=ya, za=za) == [[1,0,0,0],[tan(ya),1,0,0],[tan(za),0,1,0],[0,0,0,1]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test_affine3d_skew_yz();
|
||||||
|
|
||||||
|
|
||||||
|
module test_affine3d_chain() {
|
||||||
|
t = affine3d_translate([15,30,23]);
|
||||||
|
s = affine3d_scale([1.5,2,1.8]);
|
||||||
|
r = affine3d_zrot(30);
|
||||||
|
assert(affine3d_chain([t,s,r]) == r * s * t);
|
||||||
|
}
|
||||||
|
test_affine3d_chain();
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
|
||||||
|
module test_affine_frame_map() {
|
||||||
|
assert(approx(affine_frame_map(x=[1,1,0], y=[-1,1,0]), affine3d_zrot(45)));
|
||||||
|
}
|
||||||
|
test_affine_frame_map();
|
||||||
|
|
||||||
|
|
||||||
|
module test_apply() {
|
||||||
|
assert(approx(apply(affine3d_xrot(90),2*UP),2*FRONT));
|
||||||
|
assert(approx(apply(affine3d_yrot(90),2*UP),2*RIGHT));
|
||||||
|
assert(approx(apply(affine3d_zrot(90),2*UP),2*UP));
|
||||||
|
assert(approx(apply(affine3d_zrot(90),2*RIGHT),2*BACK));
|
||||||
|
assert(approx(apply(affine3d_zrot(90),2*BACK+2*RIGHT),2*BACK+2*LEFT));
|
||||||
|
assert(approx(apply(affine3d_xrot(135),2*BACK+2*UP),2*sqrt(2)*FWD));
|
||||||
|
assert(approx(apply(affine3d_yrot(135),2*RIGHT+2*UP),2*sqrt(2)*DOWN));
|
||||||
|
assert(approx(apply(affine3d_zrot(45),2*BACK+2*RIGHT),2*sqrt(2)*BACK));
|
||||||
|
}
|
||||||
|
test_apply();
|
||||||
|
|
||||||
|
|
||||||
|
module test_apply_list() {
|
||||||
|
assert(approx(apply_list(25*(BACK+UP), []), 25*(BACK+UP)));
|
||||||
|
assert(approx(apply_list(25*(BACK+UP), [affine3d_xrot(135)]), 25*sqrt(2)*FWD));
|
||||||
|
assert(approx(apply_list(25*(RIGHT+UP), [affine3d_yrot(135)]), 25*sqrt(2)*DOWN));
|
||||||
|
assert(approx(apply_list(25*(BACK+RIGHT), [affine3d_zrot(45)]), 25*sqrt(2)*BACK));
|
||||||
|
assert(approx(apply_list(25*(BACK+UP), [affine3d_xrot(135), affine3d_translate([30,40,50])]), 25*sqrt(2)*FWD+[30,40,50]));
|
||||||
|
assert(approx(apply_list(25*(RIGHT+UP), [affine3d_yrot(135), affine3d_translate([30,40,50])]), 25*sqrt(2)*DOWN+[30,40,50]));
|
||||||
|
assert(approx(apply_list(25*(BACK+RIGHT), [affine3d_zrot(45), affine3d_translate([30,40,50])]), 25*sqrt(2)*BACK+[30,40,50]));
|
||||||
|
}
|
||||||
|
test_apply_list();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// vim: expandtab tabstop=4 shiftwidth=4 softtabstop=4 nowrap
|
|
@ -36,8 +36,8 @@ test_vnf_faces();
|
||||||
|
|
||||||
module test_vnf_get_vertex() {
|
module test_vnf_get_vertex() {
|
||||||
vnf = [[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]];
|
vnf = [[[-1,-1,-1],[1,-1,-1],[0,1,-1],[0,0,1]],[[0,1,2],[0,3,1],[1,3,2],[2,3,0]]];
|
||||||
assert(vnf_get_vertex(vnf,[0,1,-1]) == [2,vnf]);
|
assert(vnf_get_vertex(vnf,[0,1,-1]) == [[2],vnf]);
|
||||||
assert(vnf_get_vertex(vnf,[0,1,2]) == [4,[concat(vnf[0],[[0,1,2]]),vnf[1]]]);
|
assert(vnf_get_vertex(vnf,[0,1,2]) == [[4],[concat(vnf[0],[[0,1,2]]),vnf[1]]]);
|
||||||
}
|
}
|
||||||
test_vnf_get_vertex();
|
test_vnf_get_vertex();
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
BOSL_VERSION = [2,0,354];
|
BOSL_VERSION = [2,0,355];
|
||||||
|
|
||||||
|
|
||||||
// Section: BOSL Library Version Functions
|
// Section: BOSL Library Version Functions
|
||||||
|
|
Loading…
Reference in a new issue