From 54bd59f81158f67538487d60819dc3e3316eb9b8 Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Tue, 10 Jan 2017 20:39:31 +0100 Subject: [PATCH 01/19] check validate 2d object for linear_extrude --- openpyscad/transformations.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openpyscad/transformations.py b/openpyscad/transformations.py index 740b5b3..769fc53 100644 --- a/openpyscad/transformations.py +++ b/openpyscad/transformations.py @@ -47,4 +47,8 @@ class Minkowski(base.BaseObject): class Linear_Extrude(base.BaseObject): - pass + def _validate_append(self, obj): + from .shapes_2d import Shape2dObject + if not isinstance(obj, Shape2dObject): + raise TypeError("Appended object must be a instance of Shape2dObject.") + From 041b9f43d471ed6f3c2c1b2bb0301419b29c6a1f Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Tue, 10 Jan 2017 20:48:11 +0100 Subject: [PATCH 02/19] correction for pep8 --- openpyscad/transformations.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpyscad/transformations.py b/openpyscad/transformations.py index 769fc53..9cbd90c 100644 --- a/openpyscad/transformations.py +++ b/openpyscad/transformations.py @@ -51,4 +51,3 @@ def _validate_append(self, obj): from .shapes_2d import Shape2dObject if not isinstance(obj, Shape2dObject): raise TypeError("Appended object must be a instance of Shape2dObject.") - From 6c6ee8315b5e013ab90200581fc0ea8da3f135c4 Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Tue, 10 Jan 2017 22:33:04 +0100 Subject: [PATCH 03/19] star and regular_polygon --- openpyscad/__init__.py | 1 + openpyscad/custom2dshapes.py | 26 ++++++++++++++++++++++++++ tests/test_custom2dshapes.py | 14 ++++++++++++++ tests/test_transformations.py | 10 ++++++++++ 4 files changed, 51 insertions(+) create mode 100644 openpyscad/custom2dshapes.py create mode 100644 tests/test_custom2dshapes.py diff --git a/openpyscad/__init__.py b/openpyscad/__init__.py index d49b3b8..06eff88 100644 --- a/openpyscad/__init__.py +++ b/openpyscad/__init__.py @@ -7,6 +7,7 @@ from .shapes_2d import * from .boolean import * from .transformations import * +from .custom2dshapes import Custom2dShapes __name__ = "OpenPySCAD" __version__ = "0.1.2" diff --git a/openpyscad/custom2dshapes.py b/openpyscad/custom2dshapes.py new file mode 100644 index 0000000..8e426a7 --- /dev/null +++ b/openpyscad/custom2dshapes.py @@ -0,0 +1,26 @@ +from math import cos, sin, pi + +from openpyscad.shapes_2d import * + + +class Custom2dShapes(object): + + @staticmethod + def regular_polygon(num, r): + points = list() + for i in range(num): + a_deg = i * 360 / num + a_rad = a_deg * 2 * pi / 360 + points += [[r * cos(a_rad), r * sin(a_rad)]] + regular_poly = Polygon(points) + return(regular_poly) + + def star(num, radii): + points = list() + for i in range(num): + a_deg = i * 360 / num + a_rad = a_deg * 2 * pi / 360 + r = radii[i % len(radii)] + points += [[r * cos(a_rad), r * sin(a_rad)]] + star_object = Polygon(points) + return(star_object) diff --git a/tests/test_custom2dshapes.py b/tests/test_custom2dshapes.py new file mode 100644 index 0000000..5ae4e6d --- /dev/null +++ b/tests/test_custom2dshapes.py @@ -0,0 +1,14 @@ +import unittest +from openpyscad.custom2dshapes import Custom2dShapes as c2d + + +class TestCustom2dShapes(unittest.TestCase): + + def test_regular_polygon(self): + triangle = c2d.regular_polygon(3, 10) + self.assertTrue(c.dumps().startswith("polygon(points=[[10.0, 0.0], [-4.99")) + + def test_star(self): + c = c2d.star(20, [6, 10]) + self.assertTrue(c.dumps().startswith("polygon(points=[[6.0, 0.0], [9.5")) + diff --git a/tests/test_transformations.py b/tests/test_transformations.py index cb77da3..2c47ae6 100644 --- a/tests/test_transformations.py +++ b/tests/test_transformations.py @@ -13,3 +13,13 @@ def test_validate_append(self): c2 = Cube(10) with self.assertRaises(TypeError): offset.append(c2) + +class TestLinearExtrude(unittest.TestCase): + + def test_validate_append_linear_extrude(self): + c1 = Circle(10) + c2 = c1.linear_extrude(height=1.4) + + c3 = Cube(10) + with self.assertRaises(TypeError): + c3.linear_extrude(height=1.2) From abb800e9426797dfa686baff82f21e9f860276c2 Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Tue, 10 Jan 2017 22:35:11 +0100 Subject: [PATCH 04/19] correction in tests --- tests/test_custom2dshapes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_custom2dshapes.py b/tests/test_custom2dshapes.py index 5ae4e6d..394798d 100644 --- a/tests/test_custom2dshapes.py +++ b/tests/test_custom2dshapes.py @@ -6,7 +6,7 @@ class TestCustom2dShapes(unittest.TestCase): def test_regular_polygon(self): triangle = c2d.regular_polygon(3, 10) - self.assertTrue(c.dumps().startswith("polygon(points=[[10.0, 0.0], [-4.99")) + self.assertTrue(triangle.dumps().startswith("polygon(points=[[10.0, 0.0], [-4.99")) def test_star(self): c = c2d.star(20, [6, 10]) From fe394b8d67a47554ca94d4d819d307c8f8973280 Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Tue, 10 Jan 2017 22:39:40 +0100 Subject: [PATCH 05/19] adding staticmethod for star --- openpyscad/custom2dshapes.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpyscad/custom2dshapes.py b/openpyscad/custom2dshapes.py index 8e426a7..2cc3527 100644 --- a/openpyscad/custom2dshapes.py +++ b/openpyscad/custom2dshapes.py @@ -15,6 +15,7 @@ def regular_polygon(num, r): regular_poly = Polygon(points) return(regular_poly) + @staticmethod def star(num, radii): points = list() for i in range(num): From 5d4a6fae9e3b6f7e19aaa36a1e7fe924dd140417 Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Thu, 12 Jan 2017 23:08:06 +0100 Subject: [PATCH 06/19] allowing the value true for parameters --- openpyscad/base.py | 4 ++-- openpyscad/transformations.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openpyscad/base.py b/openpyscad/base.py index 0478212..ebd22bd 100644 --- a/openpyscad/base.py +++ b/openpyscad/base.py @@ -39,7 +39,7 @@ class MetaObject(type): "direction", "language", "script", "_fn"), False), # 3D - "sphere": ("sphere", ("r", "d", "_fa", "_fs", "_fn"), False), + "sphere": ("sphere", ("r", "d", "center", "_fa", "_fs", "_fn"), False), "cube": ("cube", ("size", "center"), False), "cylinder": ("cylinder", ("h", "r", "r1", "r2", "d", "d1", "d2", @@ -158,7 +158,7 @@ def dumps(self, indent_level=0): indent=INDENT * indent_level, prefix=self.mod.get_prefix(), op_name=self._name, - params=self._get_params(), + params=self._get_params().replace('True','true'), content=self._get_content(indent_level) ) diff --git a/openpyscad/transformations.py b/openpyscad/transformations.py index 9cbd90c..0121d1b 100644 --- a/openpyscad/transformations.py +++ b/openpyscad/transformations.py @@ -49,5 +49,5 @@ class Minkowski(base.BaseObject): class Linear_Extrude(base.BaseObject): def _validate_append(self, obj): from .shapes_2d import Shape2dObject - if not isinstance(obj, Shape2dObject): + if not isinstance(obj, (Shape2dObject, transformations)): raise TypeError("Appended object must be a instance of Shape2dObject.") From 331732cd7c3105bb4514e72656a910cf6f745d1a Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Thu, 12 Jan 2017 23:34:50 +0100 Subject: [PATCH 07/19] all transfo put in Transformation class and Rotate_Extrude --- openpyscad/base.py | 6 ++++++ openpyscad/transformations.py | 35 ++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/openpyscad/base.py b/openpyscad/base.py index ebd22bd..f73f3e7 100644 --- a/openpyscad/base.py +++ b/openpyscad/base.py @@ -30,6 +30,8 @@ class MetaObject(type): "linear_extrude": ("linear_extrude", ("height", "center", "convexity", "twist", "slices", "scale"), True), + "rotate_extrude": ("rotate_extrude", ("angle", "convexity", + "_fn"), True), # 2D "circle": ("circle", ("r", "d"), False), "square": ("square", ("size", "center"), False), @@ -252,6 +254,10 @@ def linear_extrude(self, *args, **kwargs): from .transformations import Linear_Extrude return Linear_Extrude(*args, **kwargs).append(self) + def rotate_extrude(self, *args, **kwargs): + from .transformations import Rotate_Extrude + return Rotate_Extrude(*args, **kwargs).append(self) + BaseObject = _BaseObject diff --git a/openpyscad/transformations.py b/openpyscad/transformations.py index 0121d1b..e294e6d 100644 --- a/openpyscad/transformations.py +++ b/openpyscad/transformations.py @@ -4,33 +4,37 @@ __all__ = ["Translate", "Rotate", "Scale", "Resize", "Mirror", "Color", "Offset", "Hull", "Minkowski", "Linear_Extrude"] +class _Transformation(base.BaseObject): + pass + +Transformation = _Transformation # Transformations -class Translate(base.BaseObject): +class Translate(_Transformation): pass -class Rotate(base.BaseObject): +class Rotate(_Transformation): pass -class Scale(base.BaseObject): +class Scale(_Transformation): pass -class Resize(base.BaseObject): +class Resize(_Transformation): pass -class Mirror(base.BaseObject): +class Mirror(_Transformation): pass -class Color(base.BaseObject): +class Color(_Transformation): pass -class Offset(base.BaseObject): +class Offset(_Transformation): def _validate_append(self, obj): from .shapes_2d import Shape2dObject @@ -38,16 +42,25 @@ def _validate_append(self, obj): raise TypeError("Appended object must be a instance of Shape2dObject.") -class Hull(base.BaseObject): +class Hull(_Transformation): pass -class Minkowski(base.BaseObject): +class Minkowski(_Transformation): pass -class Linear_Extrude(base.BaseObject): +class Linear_Extrude(_Transformation): def _validate_append(self, obj): from .shapes_2d import Shape2dObject - if not isinstance(obj, (Shape2dObject, transformations)): + if not isinstance(obj, (Shape2dObject, Transformation)): raise TypeError("Appended object must be a instance of Shape2dObject.") + + + +class Rotate_Extrude(_Transformation): + def _validate_append(self, obj): + from .shapes_2d import Shape2dObject + if not isinstance(obj, (Shape2dObject, Transformation)): + raise TypeError("Appended object must be a instance of Shape2dObject.") + From 41eea0fe6b9bf1924849822fecdb6d2eae1de157 Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Fri, 13 Jan 2017 16:26:47 +0100 Subject: [PATCH 08/19] rotate_extrude tests --- openpyscad/base.py | 2 +- openpyscad/transformations.py | 4 ++-- tests/test_transformations.py | 11 +++++++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/openpyscad/base.py b/openpyscad/base.py index f73f3e7..ce7f1ef 100644 --- a/openpyscad/base.py +++ b/openpyscad/base.py @@ -160,7 +160,7 @@ def dumps(self, indent_level=0): indent=INDENT * indent_level, prefix=self.mod.get_prefix(), op_name=self._name, - params=self._get_params().replace('True','true'), + params=self._get_params().replace('True', 'true'), content=self._get_content(indent_level) ) diff --git a/openpyscad/transformations.py b/openpyscad/transformations.py index e294e6d..e4e29da 100644 --- a/openpyscad/transformations.py +++ b/openpyscad/transformations.py @@ -4,11 +4,13 @@ __all__ = ["Translate", "Rotate", "Scale", "Resize", "Mirror", "Color", "Offset", "Hull", "Minkowski", "Linear_Extrude"] + class _Transformation(base.BaseObject): pass Transformation = _Transformation + # Transformations class Translate(_Transformation): pass @@ -57,10 +59,8 @@ def _validate_append(self, obj): raise TypeError("Appended object must be a instance of Shape2dObject.") - class Rotate_Extrude(_Transformation): def _validate_append(self, obj): from .shapes_2d import Shape2dObject if not isinstance(obj, (Shape2dObject, Transformation)): raise TypeError("Appended object must be a instance of Shape2dObject.") - diff --git a/tests/test_transformations.py b/tests/test_transformations.py index 2c47ae6..5ec223b 100644 --- a/tests/test_transformations.py +++ b/tests/test_transformations.py @@ -23,3 +23,14 @@ def test_validate_append_linear_extrude(self): c3 = Cube(10) with self.assertRaises(TypeError): c3.linear_extrude(height=1.2) + +class TestRotateExtrude(unittest.TestCase): + + def test_validate_append_rotate_extrude(self): + c1 = Circle(10) + c2 = c1.rotate_extrude(angle=90) + + c3 = Cube(10) + with self.assertRaises(TypeError): + c3.rotate_extrude(angle=90) + From bdcabf6ea7c96f65cfd75c833ce11c10be4fdb35 Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Fri, 13 Jan 2017 17:41:47 +0100 Subject: [PATCH 09/19] make hull usable --- openpyscad/base.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openpyscad/base.py b/openpyscad/base.py index ce7f1ef..d85dbd3 100644 --- a/openpyscad/base.py +++ b/openpyscad/base.py @@ -250,6 +250,14 @@ def offset(self, *args, **kwargs): from .transformations import Offset return Offset(*args, **kwargs).append(self) + def minkowski(self, *args, **kwargs): + from .transformations import Minkowski + return Minkowski(*args, **kwargs).append(self) + + def hull(self, *args, **kwargs): + from .transformations import Hull + return Hull(*args, **kwargs).append(self) + def linear_extrude(self, *args, **kwargs): from .transformations import Linear_Extrude return Linear_Extrude(*args, **kwargs).append(self) From dcfe01d7988cedc4863f8b5974600d13e1e8f17f Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Fri, 13 Jan 2017 18:18:36 +0100 Subject: [PATCH 10/19] correcting for pep8 --- openpyscad/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openpyscad/base.py b/openpyscad/base.py index d85dbd3..1e5fbbe 100644 --- a/openpyscad/base.py +++ b/openpyscad/base.py @@ -253,11 +253,11 @@ def offset(self, *args, **kwargs): def minkowski(self, *args, **kwargs): from .transformations import Minkowski return Minkowski(*args, **kwargs).append(self) - + def hull(self, *args, **kwargs): from .transformations import Hull return Hull(*args, **kwargs).append(self) - + def linear_extrude(self, *args, **kwargs): from .transformations import Linear_Extrude return Linear_Extrude(*args, **kwargs).append(self) From f2b144e401783787cb1c7b84907c3a89348e21de Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Sun, 15 Jan 2017 22:49:34 +0100 Subject: [PATCH 11/19] new custom3dshape + tests --- openpyscad/base.py | 43 +++++++++++++++++++++++++++-------- openpyscad/custom2dshapes.py | 6 ++--- openpyscad/custom3dshapes.py | 38 +++++++++++++++++++++++++++++++ openpyscad/transformations.py | 2 +- tests/test_base.py | 14 +++++++++++- tests/test_custom3dshapes.py | 9 ++++++++ 6 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 openpyscad/custom3dshapes.py create mode 100644 tests/test_custom3dshapes.py diff --git a/openpyscad/base.py b/openpyscad/base.py index 1e5fbbe..67e3e1c 100644 --- a/openpyscad/base.py +++ b/openpyscad/base.py @@ -6,7 +6,7 @@ from .modifiers import ModifierMixin -__all__ = ["Empty", "BaseObject"] +__all__ = ["Empty", "BaseObject", "Scad"] INDENT = " " @@ -33,7 +33,7 @@ class MetaObject(type): "rotate_extrude": ("rotate_extrude", ("angle", "convexity", "_fn"), True), # 2D - "circle": ("circle", ("r", "d"), False), + "circle": ("circle", ("r", "d", "_fn"), False), "square": ("square", ("size", "center"), False), "polygon": ("polygon", ("points", "paths", "convexity"), False), "text": ("text", @@ -48,6 +48,7 @@ class MetaObject(type): "center", "_fa", "_fs", "_fn"), False ), + "scad": ("scad", ("scadfile", "version"), False), "polyhedron": ("polyhedron", ("points", "triangles", "faces", "convexity"), False) @@ -108,6 +109,16 @@ def convert_special_args(arg_name): return "$" + arg_name[1:] return arg_name + def _get_attr(self, x): + if x == 'scadfile': + scadfile = getattr(self, x) + with open(scadfile) as f: + content = f.readlines() + content = ''.join(content).rstrip('\n').rstrip(';') + return(content) + else: + return(getattr(self, x)) + args = "" # no-keyword args no_kw_args = list(filter(lambda x: is_no_keyword_args(x), valid_keys)) @@ -115,7 +126,8 @@ def convert_special_args(arg_name): # keyword args kw_args = filter(lambda x: is_keyword_args(x), valid_keys) - args += " ".join(map(lambda x: "{}={},".format(convert_special_args(x), getattr(self, x)), kw_args))[:-1] + args += " ".join(map(lambda x: "{}={},".format(convert_special_args(x), _get_attr(self, x)), kw_args))[:-1] + args = args.replace('scadfile=', '') return args def _get_children_content(self, indent_level=0): @@ -156,13 +168,20 @@ def dump(self, fp): fp.write(self.dumps()) def dumps(self, indent_level=0): - return "{indent}{prefix}{op_name}({params}){content};\n".format( - indent=INDENT * indent_level, - prefix=self.mod.get_prefix(), - op_name=self._name, - params=self._get_params().replace('True', 'true'), - content=self._get_content(indent_level) - ) + if self._name == "scad": + return "{indent}{prefix}{params};\n".format( + indent=INDENT * indent_level, + prefix=self.mod.get_prefix(), + params=self._get_params() + ) + else: + return "{indent}{prefix}{op_name}({params}){content};\n".format( + indent=INDENT * indent_level, + prefix=self.mod.get_prefix(), + op_name=self._name, + params=self._get_params().replace('True', 'true'), + content=self._get_content(indent_level) + ) def write(self, filename, with_print=False): with open(filename, "w") as fp: @@ -274,3 +293,7 @@ class _Empty(_BaseObject): pass Empty = _Empty + + +class Scad(_BaseObject): + pass diff --git a/openpyscad/custom2dshapes.py b/openpyscad/custom2dshapes.py index 2cc3527..02f3f20 100644 --- a/openpyscad/custom2dshapes.py +++ b/openpyscad/custom2dshapes.py @@ -1,6 +1,6 @@ from math import cos, sin, pi -from openpyscad.shapes_2d import * +import openpyscad as ops class Custom2dShapes(object): @@ -12,7 +12,7 @@ def regular_polygon(num, r): a_deg = i * 360 / num a_rad = a_deg * 2 * pi / 360 points += [[r * cos(a_rad), r * sin(a_rad)]] - regular_poly = Polygon(points) + regular_poly = ops.Polygon(points) return(regular_poly) @staticmethod @@ -23,5 +23,5 @@ def star(num, radii): a_rad = a_deg * 2 * pi / 360 r = radii[i % len(radii)] points += [[r * cos(a_rad), r * sin(a_rad)]] - star_object = Polygon(points) + star_object = ops.Polygon(points) return(star_object) diff --git a/openpyscad/custom3dshapes.py b/openpyscad/custom3dshapes.py new file mode 100644 index 0000000..6044f40 --- /dev/null +++ b/openpyscad/custom3dshapes.py @@ -0,0 +1,38 @@ +from math import cos, sin, pi + +import openpyscad as ops + + +class Custom3dShapes(object): + + @staticmethod + def dice(edge=15, fn=32): + """ dice + """ + edge = float(edge) + # dice + c = ops.Cube(edge, center=True) + s = ops.Sphere(edge * 3 / 4, center=True) + dice = c & s + # points + c = ops.Circle(edge / 12, _fn=fn) + h = 0.7 + point = c.linear_extrude(height=h) + point1 = point.translate([0, 0, edge / 2 - h / 2]) + point2_1 = point1.rotate(a=90, v=[1, 0, 0]).translate([edge / 6, 0, edge / 6]) + point2_2 = point2_1.mirror([-edge / 6, 0, -edge / 6]) + point2 = point2_1 + point2_2 + point3 = point2.rotate(a=90, v=[0, 0, 1]) + point1.rotate(a=90, v=[0, 1, 0]) + point4_12 = point2.rotate(a=-90, v=[0, 0, 1]) + point4 = point4_12 + point4_12.mirror([0, 1, 0]) + point5_123 = point3.rotate(a=90, v=[0, 0, 1]) + point5 = point5_123 + point5_123.mirror([1, 0, 0]) + point6_1 = point.translate([0, 0, -(edge / 2 + h / 2)]).translate([0, edge / 6, 0]) + point6_2 = point6_1.translate([edge / 4, 0, 0]) + point6_3 = point6_1.translate([-edge / 4, 0, 0]) + point6_123 = point6_1 + point6_2 + point6_3 + point6_456 = point6_123.mirror([0, 1, 0]) + point6 = point6_123 + point6_456 + dice_with_holes = dice - point1 - point2 - point3 - point4 - point5 - point6 + dice_with_holes = dice_with_holes.mirror([0, 0, 1]) + return(dice_with_holes) diff --git a/openpyscad/transformations.py b/openpyscad/transformations.py index e4e29da..13a4f1d 100644 --- a/openpyscad/transformations.py +++ b/openpyscad/transformations.py @@ -2,7 +2,7 @@ import openpyscad.base as base -__all__ = ["Translate", "Rotate", "Scale", "Resize", "Mirror", "Color", "Offset", "Hull", "Minkowski", "Linear_Extrude"] +__all__ = ["Translate", "Rotate", "Scale", "Resize", "Mirror", "Color", "Offset", "Hull", "Minkowski", "Linear_Extrude", "Rotate_Extrude"] class _Transformation(base.BaseObject): diff --git a/tests/test_base.py b/tests/test_base.py index e46f583..437eba4 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import unittest +import os from openpyscad import * @@ -204,4 +205,15 @@ def test_linear_extrude(self): o1 = o.linear_extrude(height=1.6) self.assertTrue(isinstance(o1, Linear_Extrude)) self.assertEqual(o1.children, [o]) - + + def test_rotate_extrude(self): + o = Circle(10) + o1 = o.rotate_extrude() + self.assertTrue(isinstance(o1, Rotate_Extrude)) + self.assertEqual(o1.children, [o]) + + def test_scad(self): + o = Sphere(3) + sc = Scad(os.path.join(os.path.dirname(os.path.abspath(__file__)),'..','example','example.scad')) + osc = o + sc + self.assertTrue('offset' in osc.dumps()) diff --git a/tests/test_custom3dshapes.py b/tests/test_custom3dshapes.py new file mode 100644 index 0000000..ddd809e --- /dev/null +++ b/tests/test_custom3dshapes.py @@ -0,0 +1,9 @@ +import unittest +from openpyscad.custom3dshapes import Custom3dShapes as c3d + + +class TestCustom3dShapes(unittest.TestCase): + + def test_dice(self): + dice = c3d.dice(15) + self.assertTrue(dice.dumps().startswith("mirror(")) From 4b8ccdf72421cd0784c8a900a5e5f0a559aa05c6 Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Thu, 19 Jan 2017 20:45:06 +0100 Subject: [PATCH 12/19] adding scad file content to other baseobjects --- openpyscad/base.py | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/openpyscad/base.py b/openpyscad/base.py index 67e3e1c..421567a 100644 --- a/openpyscad/base.py +++ b/openpyscad/base.py @@ -3,6 +3,8 @@ # Python 2 and 3: from six import with_metaclass +import os + from .modifiers import ModifierMixin @@ -69,6 +71,7 @@ class _BaseObject(with_metaclass(MetaObject, ModifierMixin, object)): def __init__(self, *args, **kwargs): super(_BaseObject, self).__init__() + self.modules = list() for k, v in kwargs.items(): if hasattr(self.__class__, k): setattr(self, k, v) @@ -92,7 +95,7 @@ def _retrieve_value(self, name): return "{}".format(val) - def _get_params(self): + def _get_params(self, fp): valid_keys = list(filter(lambda x: getattr(self, x) is not None, self._properties)) def is_no_keyword_args(arg_name): @@ -109,12 +112,23 @@ def convert_special_args(arg_name): return "$" + arg_name[1:] return arg_name - def _get_attr(self, x): + def _get_attr(self, x, fp): if x == 'scadfile': scadfile = getattr(self, x) + def rename_scadfile(scadfile): + sf = ''.join(os.path.basename(scadfile).split('.')[:-1]) + scadfile_renamed = sf.lower().strip('_').strip('-') + return(scadfile_renamed) with open(scadfile) as f: content = f.readlines() - content = ''.join(content).rstrip('\n').rstrip(';') + content = ''.join(content).rstrip('\n') + sc = rename_scadfile(scadfile) + module = 'module {sc}() {{{content};}}\n'.format(**{'content': content, 'sc': sc}) + module = module.replace(';;',';') + self.modules.append(module) + if fp is not None: + fp.write(module) + content = '{}()'.format(sc) return(content) else: return(getattr(self, x)) @@ -126,24 +140,24 @@ def _get_attr(self, x): # keyword args kw_args = filter(lambda x: is_keyword_args(x), valid_keys) - args += " ".join(map(lambda x: "{}={},".format(convert_special_args(x), _get_attr(self, x)), kw_args))[:-1] + args += " ".join(map(lambda x: "{}={},".format(convert_special_args(x), _get_attr(self, x, fp)), kw_args))[:-1] args = args.replace('scadfile=', '') return args - def _get_children_content(self, indent_level=0): + def _get_children_content(self, indent_level=0, fp=None): _content = "" if len(self.children) > 0: for child in self.children: - _content += child.dumps(indent_level) + _content += child.dumps(indent_level, fp) return _content - def _get_content(self, indent_level=0): + def _get_content(self, indent_level=0, fp=None): if len(self.children) == 0: return "" else: return "{{\n{children}{indent}}}".format( - children=self._get_children_content(indent_level + 1), + children=self._get_children_content(indent_level + 1, fp=fp), indent=INDENT * indent_level ) @@ -165,22 +179,23 @@ def append(self, obj): return self def dump(self, fp): - fp.write(self.dumps()) + dumps = self.dumps(fp=fp) + fp.write(dumps) - def dumps(self, indent_level=0): + def dumps(self, indent_level=0, fp=None): if self._name == "scad": return "{indent}{prefix}{params};\n".format( indent=INDENT * indent_level, prefix=self.mod.get_prefix(), - params=self._get_params() + params=self._get_params(fp).replace('True', 'true') ) else: return "{indent}{prefix}{op_name}({params}){content};\n".format( indent=INDENT * indent_level, prefix=self.mod.get_prefix(), op_name=self._name, - params=self._get_params().replace('True', 'true'), - content=self._get_content(indent_level) + params=self._get_params(fp).replace('True', 'true'), + content=self._get_content(indent_level, fp=fp) ) def write(self, filename, with_print=False): From 96d85aab635b5fba8c4e0736bc6bcdbc254e3c65 Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Thu, 19 Jan 2017 20:49:28 +0100 Subject: [PATCH 13/19] pep compliant --- openpyscad/base.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openpyscad/base.py b/openpyscad/base.py index 421567a..4050f24 100644 --- a/openpyscad/base.py +++ b/openpyscad/base.py @@ -115,16 +115,17 @@ def convert_special_args(arg_name): def _get_attr(self, x, fp): if x == 'scadfile': scadfile = getattr(self, x) + def rename_scadfile(scadfile): sf = ''.join(os.path.basename(scadfile).split('.')[:-1]) - scadfile_renamed = sf.lower().strip('_').strip('-') + scadfile_renamed = sf.lower().strip('_').strip('-') return(scadfile_renamed) with open(scadfile) as f: content = f.readlines() - content = ''.join(content).rstrip('\n') - sc = rename_scadfile(scadfile) + content = ''.join(content).rstrip('\n') + sc = rename_scadfile(scadfile) module = 'module {sc}() {{{content};}}\n'.format(**{'content': content, 'sc': sc}) - module = module.replace(';;',';') + module = module.replace(';;', ';') self.modules.append(module) if fp is not None: fp.write(module) @@ -187,7 +188,7 @@ def dumps(self, indent_level=0, fp=None): return "{indent}{prefix}{params};\n".format( indent=INDENT * indent_level, prefix=self.mod.get_prefix(), - params=self._get_params(fp).replace('True', 'true') + params=self._get_params(fp).replace('True', 'true') ) else: return "{indent}{prefix}{op_name}({params}){content};\n".format( From 8079587b66d2a1c4e47f269c165ceea75447a41e Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Thu, 19 Jan 2017 22:07:01 +0100 Subject: [PATCH 14/19] add import --- openpyscad/base.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/openpyscad/base.py b/openpyscad/base.py index 4050f24..31eaf62 100644 --- a/openpyscad/base.py +++ b/openpyscad/base.py @@ -8,7 +8,7 @@ from .modifiers import ModifierMixin -__all__ = ["Empty", "BaseObject", "Scad"] +__all__ = ["Empty", "BaseObject", "Scad", "Import"] INDENT = " " @@ -51,6 +51,7 @@ class MetaObject(type): False ), "scad": ("scad", ("scadfile", "version"), False), + "import": ("import", ("file", "convexity"), False), "polyhedron": ("polyhedron", ("points", "triangles", "faces", "convexity"), False) @@ -131,6 +132,13 @@ def rename_scadfile(scadfile): fp.write(module) content = '{}()'.format(sc) return(content) + elif x == 'file': + content = getattr(self, x) + if not content.startswith('"'): + content = '"' + content + if not content.endswith('"'): + content = content + '"' + return(content) else: return(getattr(self, x)) @@ -313,3 +321,7 @@ class _Empty(_BaseObject): class Scad(_BaseObject): pass + + +class Import(_BaseObject): + pass From f3c0214d733ba6ea5e0434d370ac73428f6c4a88 Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Thu, 19 Jan 2017 22:23:12 +0100 Subject: [PATCH 15/19] some bug fixes with tests --- example/example.stl | 814 ++++++++++++++++++++++++++++++++++++++++++++ openpyscad/base.py | 2 +- tests/test_base.py | 8 +- 3 files changed, 822 insertions(+), 2 deletions(-) create mode 100644 example/example.stl diff --git a/example/example.stl b/example/example.stl new file mode 100644 index 0000000..4f91b42 --- /dev/null +++ b/example/example.stl @@ -0,0 +1,814 @@ +solid OpenSCAD_Model + facet normal -0 -0 -1 + outer loop + vertex 9.78148 2.07912 0 + vertex 10 0 0 + vertex 9.13545 4.06737 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 9.13545 4.06737 0 + vertex 6.69131 7.43145 0 + vertex 8.09017 5.87785 0 + endloop + endfacet + facet normal -0 0 -1 + outer loop + vertex 10 0 0 + vertex 9.78148 -2.07912 0 + vertex 9.13545 4.06737 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 9.13545 4.06737 0 + vertex 3.09017 9.51057 0 + vertex 6.69131 7.43145 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 6.69131 7.43145 0 + vertex 3.09017 9.51057 0 + vertex 5 8.66025 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -8.09017 5.87785 0 + vertex -9.13545 -4.06737 0 + vertex -10 5.66554e-15 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 3.09017 9.51057 0 + vertex -1.04528 9.94522 0 + vertex 1.04528 9.94522 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -6.69131 7.43145 0 + vertex -5 8.66025 0 + vertex -1.04528 9.94522 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -1.04528 9.94522 0 + vertex -5 8.66025 0 + vertex -3.09017 9.51057 0 + endloop + endfacet + facet normal -0 0 -1 + outer loop + vertex 3.09017 9.51057 0 + vertex -6.69131 7.43145 0 + vertex -1.04528 9.94522 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -10 5.66554e-15 0 + vertex -9.13545 -4.06737 0 + vertex -9.78148 -2.07912 0 + endloop + endfacet + facet normal 0 -0 -1 + outer loop + vertex -8.09017 5.87785 0 + vertex -6.69131 7.43145 0 + vertex -9.13545 -4.06737 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -8.09017 5.87785 0 + vertex -9.78148 2.07912 0 + vertex -9.13545 4.06737 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -8.09017 5.87785 0 + vertex -10 5.66554e-15 0 + vertex -9.78148 2.07912 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -9.13545 -4.06737 0 + vertex -6.69131 7.43145 0 + vertex -3.09017 -9.51057 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -6.69131 -7.43145 0 + vertex -9.13545 -4.06737 0 + vertex -3.09017 -9.51057 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -3.09017 -9.51057 0 + vertex -6.69131 7.43145 0 + vertex 3.09017 9.51057 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -9.13545 -4.06737 0 + vertex -6.69131 -7.43145 0 + vertex -8.09017 -5.87785 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -3.09017 -9.51057 0 + vertex -5 -8.66025 0 + vertex -6.69131 -7.43145 0 + endloop + endfacet + facet normal -0 0 -1 + outer loop + vertex 9.13545 4.06737 0 + vertex -3.09017 -9.51057 0 + vertex 3.09017 9.51057 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 9.13545 4.06737 0 + vertex 1.04528 -9.94522 0 + vertex -3.09017 -9.51057 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex -3.09017 -9.51057 0 + vertex 1.04528 -9.94522 0 + vertex -1.04528 -9.94522 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 9.13545 4.06737 0 + vertex 5 -8.66025 0 + vertex 1.04528 -9.94522 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 1.04528 -9.94522 0 + vertex 5 -8.66025 0 + vertex 3.09017 -9.51057 0 + endloop + endfacet + facet normal 0 -0 -1 + outer loop + vertex 9.13545 4.06737 0 + vertex 9.78148 -2.07912 0 + vertex 5 -8.66025 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 5 -8.66025 0 + vertex 9.78148 -2.07912 0 + vertex 6.69131 -7.43145 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 6.69131 -7.43145 0 + vertex 9.78148 -2.07912 0 + vertex 8.09017 -5.87785 0 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 8.09017 -5.87785 0 + vertex 9.78148 -2.07912 0 + vertex 9.13545 -4.06737 0 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 9.13545 4.06737 10 + vertex 10 0 10 + vertex 9.78148 2.07912 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 8.09017 5.87785 10 + vertex 6.69131 7.43145 10 + vertex 9.13545 4.06737 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 9.13545 4.06737 10 + vertex 9.78148 -2.07912 10 + vertex 10 0 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 6.69131 7.43145 10 + vertex 3.09017 9.51057 10 + vertex 9.13545 4.06737 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 5 8.66025 10 + vertex 3.09017 9.51057 10 + vertex 6.69131 7.43145 10 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex -10 5.66554e-15 10 + vertex -9.13545 -4.06737 10 + vertex -8.09017 5.87785 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 1.04528 9.94522 10 + vertex -1.04528 9.94522 10 + vertex 3.09017 9.51057 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -1.04528 9.94522 10 + vertex -5 8.66025 10 + vertex -6.69131 7.43145 10 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex -3.09017 9.51057 10 + vertex -5 8.66025 10 + vertex -1.04528 9.94522 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -1.04528 9.94522 10 + vertex -6.69131 7.43145 10 + vertex 3.09017 9.51057 10 + endloop + endfacet + facet normal -0 -0 1 + outer loop + vertex -9.78148 -2.07912 10 + vertex -9.13545 -4.06737 10 + vertex -10 5.66554e-15 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -9.13545 -4.06737 10 + vertex -6.69131 7.43145 10 + vertex -8.09017 5.87785 10 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex -9.13545 4.06737 10 + vertex -9.78148 2.07912 10 + vertex -8.09017 5.87785 10 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex -9.78148 2.07912 10 + vertex -10 5.66554e-15 10 + vertex -8.09017 5.87785 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -3.09017 -9.51057 10 + vertex -6.69131 7.43145 10 + vertex -9.13545 -4.06737 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -3.09017 -9.51057 10 + vertex -9.13545 -4.06737 10 + vertex -6.69131 -7.43145 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 3.09017 9.51057 10 + vertex -6.69131 7.43145 10 + vertex -3.09017 -9.51057 10 + endloop + endfacet + facet normal -0 -0 1 + outer loop + vertex -8.09017 -5.87785 10 + vertex -6.69131 -7.43145 10 + vertex -9.13545 -4.06737 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -6.69131 -7.43145 10 + vertex -5 -8.66025 10 + vertex -3.09017 -9.51057 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 3.09017 9.51057 10 + vertex -3.09017 -9.51057 10 + vertex 9.13545 4.06737 10 + endloop + endfacet + facet normal -0 0 1 + outer loop + vertex -3.09017 -9.51057 10 + vertex 1.04528 -9.94522 10 + vertex 9.13545 4.06737 10 + endloop + endfacet + facet normal 0 -0 1 + outer loop + vertex -1.04528 -9.94522 10 + vertex 1.04528 -9.94522 10 + vertex -3.09017 -9.51057 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 1.04528 -9.94522 10 + vertex 5 -8.66025 10 + vertex 9.13545 4.06737 10 + endloop + endfacet + facet normal 0 -0 1 + outer loop + vertex 3.09017 -9.51057 10 + vertex 5 -8.66025 10 + vertex 1.04528 -9.94522 10 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 5 -8.66025 10 + vertex 9.78148 -2.07912 10 + vertex 9.13545 4.06737 10 + endloop + endfacet + facet normal 0 -0 1 + outer loop + vertex 6.69131 -7.43145 10 + vertex 9.78148 -2.07912 10 + vertex 5 -8.66025 10 + endloop + endfacet + facet normal 0 -0 1 + outer loop + vertex 8.09017 -5.87785 10 + vertex 9.78148 -2.07912 10 + vertex 6.69131 -7.43145 10 + endloop + endfacet + facet normal 0 -0 1 + outer loop + vertex 9.13545 -4.06737 10 + vertex 9.78148 -2.07912 10 + vertex 8.09017 -5.87785 10 + endloop + endfacet + facet normal 0.994522 0.104528 0 + outer loop + vertex 9.78148 2.07912 0 + vertex 10 0 10 + vertex 10 0 0 + endloop + endfacet + facet normal 0.994522 0.104528 -0 + outer loop + vertex 9.78148 2.07912 0 + vertex 9.78148 2.07912 10 + vertex 10 0 10 + endloop + endfacet + facet normal 0.951057 0.309017 0 + outer loop + vertex 9.13545 4.06737 0 + vertex 9.78148 2.07912 10 + vertex 9.78148 2.07912 0 + endloop + endfacet + facet normal 0.951057 0.309017 -0 + outer loop + vertex 9.13545 4.06737 0 + vertex 9.13545 4.06737 10 + vertex 9.78148 2.07912 10 + endloop + endfacet + facet normal 0.866025 0.5 0 + outer loop + vertex 8.09017 5.87785 0 + vertex 9.13545 4.06737 10 + vertex 9.13545 4.06737 0 + endloop + endfacet + facet normal 0.866025 0.5 -0 + outer loop + vertex 8.09017 5.87785 0 + vertex 8.09017 5.87785 10 + vertex 9.13545 4.06737 10 + endloop + endfacet + facet normal 0.743145 0.669131 0 + outer loop + vertex 6.69131 7.43145 0 + vertex 8.09017 5.87785 10 + vertex 8.09017 5.87785 0 + endloop + endfacet + facet normal 0.743145 0.669131 -0 + outer loop + vertex 6.69131 7.43145 0 + vertex 6.69131 7.43145 10 + vertex 8.09017 5.87785 10 + endloop + endfacet + facet normal 0.587785 0.809017 0 + outer loop + vertex 5 8.66025 0 + vertex 6.69131 7.43145 10 + vertex 6.69131 7.43145 0 + endloop + endfacet + facet normal 0.587785 0.809017 -0 + outer loop + vertex 5 8.66025 0 + vertex 5 8.66025 10 + vertex 6.69131 7.43145 10 + endloop + endfacet + facet normal 0.406737 0.913545 0 + outer loop + vertex 3.09017 9.51057 0 + vertex 5 8.66025 10 + vertex 5 8.66025 0 + endloop + endfacet + facet normal 0.406737 0.913545 -0 + outer loop + vertex 3.09017 9.51057 0 + vertex 3.09017 9.51057 10 + vertex 5 8.66025 10 + endloop + endfacet + facet normal 0.207912 0.978148 0 + outer loop + vertex 1.04528 9.94522 0 + vertex 3.09017 9.51057 10 + vertex 3.09017 9.51057 0 + endloop + endfacet + facet normal 0.207912 0.978148 -0 + outer loop + vertex 1.04528 9.94522 0 + vertex 1.04528 9.94522 10 + vertex 3.09017 9.51057 10 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -1.04528 9.94522 0 + vertex 1.04528 9.94522 10 + vertex 1.04528 9.94522 0 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -1.04528 9.94522 0 + vertex -1.04528 9.94522 10 + vertex 1.04528 9.94522 10 + endloop + endfacet + facet normal -0.207912 0.978148 0 + outer loop + vertex -3.09017 9.51057 0 + vertex -1.04528 9.94522 10 + vertex -1.04528 9.94522 0 + endloop + endfacet + facet normal -0.207912 0.978148 0 + outer loop + vertex -3.09017 9.51057 0 + vertex -3.09017 9.51057 10 + vertex -1.04528 9.94522 10 + endloop + endfacet + facet normal -0.406737 0.913545 0 + outer loop + vertex -5 8.66025 0 + vertex -3.09017 9.51057 10 + vertex -3.09017 9.51057 0 + endloop + endfacet + facet normal -0.406737 0.913545 0 + outer loop + vertex -5 8.66025 0 + vertex -5 8.66025 10 + vertex -3.09017 9.51057 10 + endloop + endfacet + facet normal -0.587785 0.809017 0 + outer loop + vertex -6.69131 7.43145 0 + vertex -5 8.66025 10 + vertex -5 8.66025 0 + endloop + endfacet + facet normal -0.587785 0.809017 0 + outer loop + vertex -6.69131 7.43145 0 + vertex -6.69131 7.43145 10 + vertex -5 8.66025 10 + endloop + endfacet + facet normal -0.743145 0.669131 0 + outer loop + vertex -8.09017 5.87785 0 + vertex -6.69131 7.43145 10 + vertex -6.69131 7.43145 0 + endloop + endfacet + facet normal -0.743145 0.669131 0 + outer loop + vertex -8.09017 5.87785 0 + vertex -8.09017 5.87785 10 + vertex -6.69131 7.43145 10 + endloop + endfacet + facet normal -0.866025 0.5 0 + outer loop + vertex -9.13545 4.06737 0 + vertex -8.09017 5.87785 10 + vertex -8.09017 5.87785 0 + endloop + endfacet + facet normal -0.866025 0.5 0 + outer loop + vertex -9.13545 4.06737 0 + vertex -9.13545 4.06737 10 + vertex -8.09017 5.87785 10 + endloop + endfacet + facet normal -0.951057 0.309017 0 + outer loop + vertex -9.78148 2.07912 0 + vertex -9.13545 4.06737 10 + vertex -9.13545 4.06737 0 + endloop + endfacet + facet normal -0.951057 0.309017 0 + outer loop + vertex -9.78148 2.07912 0 + vertex -9.78148 2.07912 10 + vertex -9.13545 4.06737 10 + endloop + endfacet + facet normal -0.994522 0.104528 0 + outer loop + vertex -10 5.66554e-15 0 + vertex -9.78148 2.07912 10 + vertex -9.78148 2.07912 0 + endloop + endfacet + facet normal -0.994522 0.104528 0 + outer loop + vertex -10 5.66554e-15 0 + vertex -10 5.66554e-15 10 + vertex -9.78148 2.07912 10 + endloop + endfacet + facet normal -0.994522 -0.104528 0 + outer loop + vertex -9.78148 -2.07912 0 + vertex -10 5.66554e-15 10 + vertex -10 5.66554e-15 0 + endloop + endfacet + facet normal -0.994522 -0.104528 0 + outer loop + vertex -9.78148 -2.07912 0 + vertex -9.78148 -2.07912 10 + vertex -10 5.66554e-15 10 + endloop + endfacet + facet normal -0.951057 -0.309017 0 + outer loop + vertex -9.13545 -4.06737 0 + vertex -9.78148 -2.07912 10 + vertex -9.78148 -2.07912 0 + endloop + endfacet + facet normal -0.951057 -0.309017 0 + outer loop + vertex -9.13545 -4.06737 0 + vertex -9.13545 -4.06737 10 + vertex -9.78148 -2.07912 10 + endloop + endfacet + facet normal -0.866025 -0.5 0 + outer loop + vertex -8.09017 -5.87785 0 + vertex -9.13545 -4.06737 10 + vertex -9.13545 -4.06737 0 + endloop + endfacet + facet normal -0.866025 -0.5 0 + outer loop + vertex -8.09017 -5.87785 0 + vertex -8.09017 -5.87785 10 + vertex -9.13545 -4.06737 10 + endloop + endfacet + facet normal -0.743145 -0.669131 0 + outer loop + vertex -6.69131 -7.43145 0 + vertex -8.09017 -5.87785 10 + vertex -8.09017 -5.87785 0 + endloop + endfacet + facet normal -0.743145 -0.669131 0 + outer loop + vertex -6.69131 -7.43145 0 + vertex -6.69131 -7.43145 10 + vertex -8.09017 -5.87785 10 + endloop + endfacet + facet normal -0.587785 -0.809017 0 + outer loop + vertex -5 -8.66025 0 + vertex -6.69131 -7.43145 10 + vertex -6.69131 -7.43145 0 + endloop + endfacet + facet normal -0.587785 -0.809017 0 + outer loop + vertex -5 -8.66025 0 + vertex -5 -8.66025 10 + vertex -6.69131 -7.43145 10 + endloop + endfacet + facet normal -0.406737 -0.913545 0 + outer loop + vertex -3.09017 -9.51057 0 + vertex -5 -8.66025 10 + vertex -5 -8.66025 0 + endloop + endfacet + facet normal -0.406737 -0.913545 0 + outer loop + vertex -3.09017 -9.51057 0 + vertex -3.09017 -9.51057 10 + vertex -5 -8.66025 10 + endloop + endfacet + facet normal -0.207912 -0.978148 0 + outer loop + vertex -1.04528 -9.94522 0 + vertex -3.09017 -9.51057 10 + vertex -3.09017 -9.51057 0 + endloop + endfacet + facet normal -0.207912 -0.978148 0 + outer loop + vertex -1.04528 -9.94522 0 + vertex -1.04528 -9.94522 10 + vertex -3.09017 -9.51057 10 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 1.04528 -9.94522 0 + vertex -1.04528 -9.94522 10 + vertex -1.04528 -9.94522 0 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 1.04528 -9.94522 0 + vertex 1.04528 -9.94522 10 + vertex -1.04528 -9.94522 10 + endloop + endfacet + facet normal 0.207912 -0.978148 0 + outer loop + vertex 3.09017 -9.51057 0 + vertex 1.04528 -9.94522 10 + vertex 1.04528 -9.94522 0 + endloop + endfacet + facet normal 0.207912 -0.978148 0 + outer loop + vertex 3.09017 -9.51057 0 + vertex 3.09017 -9.51057 10 + vertex 1.04528 -9.94522 10 + endloop + endfacet + facet normal 0.406737 -0.913545 0 + outer loop + vertex 5 -8.66025 0 + vertex 3.09017 -9.51057 10 + vertex 3.09017 -9.51057 0 + endloop + endfacet + facet normal 0.406737 -0.913545 0 + outer loop + vertex 5 -8.66025 0 + vertex 5 -8.66025 10 + vertex 3.09017 -9.51057 10 + endloop + endfacet + facet normal 0.587785 -0.809017 0 + outer loop + vertex 6.69131 -7.43145 0 + vertex 5 -8.66025 10 + vertex 5 -8.66025 0 + endloop + endfacet + facet normal 0.587785 -0.809017 0 + outer loop + vertex 6.69131 -7.43145 0 + vertex 6.69131 -7.43145 10 + vertex 5 -8.66025 10 + endloop + endfacet + facet normal 0.743145 -0.669131 0 + outer loop + vertex 8.09017 -5.87785 0 + vertex 6.69131 -7.43145 10 + vertex 6.69131 -7.43145 0 + endloop + endfacet + facet normal 0.743145 -0.669131 0 + outer loop + vertex 8.09017 -5.87785 0 + vertex 8.09017 -5.87785 10 + vertex 6.69131 -7.43145 10 + endloop + endfacet + facet normal 0.866025 -0.5 0 + outer loop + vertex 9.13545 -4.06737 0 + vertex 8.09017 -5.87785 10 + vertex 8.09017 -5.87785 0 + endloop + endfacet + facet normal 0.866025 -0.5 0 + outer loop + vertex 9.13545 -4.06737 0 + vertex 9.13545 -4.06737 10 + vertex 8.09017 -5.87785 10 + endloop + endfacet + facet normal 0.951057 -0.309017 0 + outer loop + vertex 9.78148 -2.07912 0 + vertex 9.13545 -4.06737 10 + vertex 9.13545 -4.06737 0 + endloop + endfacet + facet normal 0.951057 -0.309017 0 + outer loop + vertex 9.78148 -2.07912 0 + vertex 9.78148 -2.07912 10 + vertex 9.13545 -4.06737 10 + endloop + endfacet + facet normal 0.994522 -0.104528 0 + outer loop + vertex 10 0 0 + vertex 9.78148 -2.07912 10 + vertex 9.78148 -2.07912 0 + endloop + endfacet + facet normal 0.994522 -0.104528 0 + outer loop + vertex 10 0 0 + vertex 10 0 10 + vertex 9.78148 -2.07912 10 + endloop + endfacet +endsolid OpenSCAD_Model diff --git a/openpyscad/base.py b/openpyscad/base.py index 31eaf62..0b8b4bd 100644 --- a/openpyscad/base.py +++ b/openpyscad/base.py @@ -96,7 +96,7 @@ def _retrieve_value(self, name): return "{}".format(val) - def _get_params(self, fp): + def _get_params(self, fp=None): valid_keys = list(filter(lambda x: getattr(self, x) is not None, self._properties)) def is_no_keyword_args(arg_name): diff --git a/tests/test_base.py b/tests/test_base.py index 437eba4..c32d011 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -216,4 +216,10 @@ def test_scad(self): o = Sphere(3) sc = Scad(os.path.join(os.path.dirname(os.path.abspath(__file__)),'..','example','example.scad')) osc = o + sc - self.assertTrue('offset' in osc.dumps()) + self.assertTrue('example' in osc.dumps()) + + def test_import(self): + o = Sphere(3) + sc = Import(os.path.join(os.path.dirname(os.path.abspath(__file__)),'..','example','example.stl')) + osc = o + sc + self.assertTrue('example.stl' in osc.dumps()) From 08d7f141e819027d8bf10ab7cd215d669fd7c0b7 Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Thu, 19 Jan 2017 22:41:04 +0100 Subject: [PATCH 16/19] adding surface() --- openpyscad/base.py | 1 + openpyscad/shapes_2d.py | 6 +++++- openpyscad/transformations.py | 3 +-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/openpyscad/base.py b/openpyscad/base.py index 0b8b4bd..bb11634 100644 --- a/openpyscad/base.py +++ b/openpyscad/base.py @@ -42,6 +42,7 @@ class MetaObject(type): ("text", "size", "font", "halign", "valign", "spacing", "direction", "language", "script", "_fn"), False), + "surface": ("surface", ("file", "center", "invert", "convexity"), False), # 3D "sphere": ("sphere", ("r", "d", "center", "_fa", "_fs", "_fn"), False), "cube": ("cube", ("size", "center"), False), diff --git a/openpyscad/shapes_2d.py b/openpyscad/shapes_2d.py index e77c9b8..e4eec1f 100644 --- a/openpyscad/shapes_2d.py +++ b/openpyscad/shapes_2d.py @@ -2,7 +2,7 @@ from .base import _BaseObject -__all__ = ["Circle", "Square", "Polygon", "Text"] +__all__ = ["Circle", "Square", "Polygon", "Text", "Surface"] class _Shape2dObject(_BaseObject): @@ -25,3 +25,7 @@ class Polygon(_Shape2dObject): class Text(_Shape2dObject): pass + + +class Surface(_Shape2dObject): + pass diff --git a/openpyscad/transformations.py b/openpyscad/transformations.py index 13a4f1d..e0b5d05 100644 --- a/openpyscad/transformations.py +++ b/openpyscad/transformations.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- import openpyscad.base as base - __all__ = ["Translate", "Rotate", "Scale", "Resize", "Mirror", "Color", "Offset", "Hull", "Minkowski", "Linear_Extrude", "Rotate_Extrude"] @@ -56,7 +55,7 @@ class Linear_Extrude(_Transformation): def _validate_append(self, obj): from .shapes_2d import Shape2dObject if not isinstance(obj, (Shape2dObject, Transformation)): - raise TypeError("Appended object must be a instance of Shape2dObject.") + raise TypeError("Appended object must be a instance of Shape2dObject or Transformation.") class Rotate_Extrude(_Transformation): From 4be3015cecb1994f69cbc6f0a0646d23c63eb34f Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Thu, 19 Jan 2017 22:59:36 +0100 Subject: [PATCH 17/19] correction: output of surface is a 3d object not a 2d object --- openpyscad/base.py | 2 +- openpyscad/shapes_2d.py | 6 +----- openpyscad/shapes_3d.py | 6 +++++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openpyscad/base.py b/openpyscad/base.py index bb11634..c7d6455 100644 --- a/openpyscad/base.py +++ b/openpyscad/base.py @@ -42,7 +42,6 @@ class MetaObject(type): ("text", "size", "font", "halign", "valign", "spacing", "direction", "language", "script", "_fn"), False), - "surface": ("surface", ("file", "center", "invert", "convexity"), False), # 3D "sphere": ("sphere", ("r", "d", "center", "_fa", "_fs", "_fn"), False), "cube": ("cube", ("size", "center"), False), @@ -53,6 +52,7 @@ class MetaObject(type): ), "scad": ("scad", ("scadfile", "version"), False), "import": ("import", ("file", "convexity"), False), + "surface": ("surface", ("file", "center", "invert", "convexity"), False), "polyhedron": ("polyhedron", ("points", "triangles", "faces", "convexity"), False) diff --git a/openpyscad/shapes_2d.py b/openpyscad/shapes_2d.py index e4eec1f..e77c9b8 100644 --- a/openpyscad/shapes_2d.py +++ b/openpyscad/shapes_2d.py @@ -2,7 +2,7 @@ from .base import _BaseObject -__all__ = ["Circle", "Square", "Polygon", "Text", "Surface"] +__all__ = ["Circle", "Square", "Polygon", "Text"] class _Shape2dObject(_BaseObject): @@ -25,7 +25,3 @@ class Polygon(_Shape2dObject): class Text(_Shape2dObject): pass - - -class Surface(_Shape2dObject): - pass diff --git a/openpyscad/shapes_3d.py b/openpyscad/shapes_3d.py index 4a5179e..97ac90b 100644 --- a/openpyscad/shapes_3d.py +++ b/openpyscad/shapes_3d.py @@ -2,7 +2,7 @@ from .base import _BaseObject -__all__ = ["Sphere", "Cube", "Cylinder", "Polyhedron"] +__all__ = ["Sphere", "Cube", "Cylinder", "Polyhedron", "Surface"] # 3D @@ -24,3 +24,7 @@ class Cylinder(_Shape3dObject): class Polyhedron(_Shape3dObject): pass + + +class Surface(_Shape3dObject): + pass From 9c383b159b8cc44854b6da424fdcc92343a0a93e Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Sun, 29 Jan 2017 22:32:02 +0100 Subject: [PATCH 18/19] new tests to improve coverage --- example_module.scad | 4 ++++ tests/test_base.py | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 example_module.scad diff --git a/example_module.scad b/example_module.scad new file mode 100644 index 0000000..e9851a4 --- /dev/null +++ b/example_module.scad @@ -0,0 +1,4 @@ +module example() {offset(r=10){ + circle(r=10); +};} +example(); diff --git a/tests/test_base.py b/tests/test_base.py index c32d011..ec006e3 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -200,6 +200,20 @@ def test_offset(self): with self.assertRaises(TypeError): o.offset([10, 10, 10]) + def test_hull(self): + c = Cube(10) + s = Sphere(3) + s = s.translate([8, 0, 0]) + h = (c + s).hull() + self.assertTrue('hull' in h.dumps()) + + def test_minkowski(self): + c = Cube(10) + s = Sphere(3) + s = s.translate([8, 0, 0]) + h = (c + s).minkowski() + self.assertTrue('minkowski' in h.dumps()) + def test_linear_extrude(self): o = Circle(10) o1 = o.linear_extrude(height=1.6) @@ -212,6 +226,11 @@ def test_rotate_extrude(self): self.assertTrue(isinstance(o1, Rotate_Extrude)) self.assertEqual(o1.children, [o]) + def test_scad_write(self): + sc = Scad(os.path.join(os.path.dirname(os.path.abspath(__file__)),'..','example','example.scad')) + self.assertTrue('example' in sc.dumps()) + sc.write('example_module.scad') + def test_scad(self): o = Sphere(3) sc = Scad(os.path.join(os.path.dirname(os.path.abspath(__file__)),'..','example','example.scad')) From 2555f7b27096015cbcf8c9b4aa1180a8644d0e02 Mon Sep 17 00:00:00 2001 From: jpoullet2000 Date: Sun, 29 Jan 2017 22:37:51 +0100 Subject: [PATCH 19/19] remove example_module.scad --- .gitignore | 1 + example_module.scad | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 example_module.scad diff --git a/.gitignore b/.gitignore index b9b09fd..9bf99e6 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,4 @@ target/ # Created by nosetests cover/ +example_module.scad diff --git a/example_module.scad b/example_module.scad deleted file mode 100644 index e9851a4..0000000 --- a/example_module.scad +++ /dev/null @@ -1,4 +0,0 @@ -module example() {offset(r=10){ - circle(r=10); -};} -example();