yapCAD 0.2.5__tar.gz → 0.3.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 (81) hide show
  1. {yapCAD-0.2.5 → yapcad-0.3.0}/.gitignore +5 -0
  2. {yapCAD-0.2.5 → yapcad-0.3.0}/CHANGELOG.rst +21 -0
  3. {yapCAD-0.2.5 → yapcad-0.3.0}/PKG-INFO +29 -5
  4. {yapCAD-0.2.5 → yapcad-0.3.0}/README.md +19 -0
  5. {yapCAD-0.2.5 → yapcad-0.3.0}/README.rst +16 -0
  6. {yapCAD-0.2.5 → yapcad-0.3.0}/docs/README.rst +16 -0
  7. {yapCAD-0.2.5 → yapcad-0.3.0}/docs/conf.py +17 -5
  8. {yapCAD-0.2.5 → yapcad-0.3.0}/docs/index.rst +1 -1
  9. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/boxcut/boxcut.py +11 -8
  10. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/example1.py +12 -5
  11. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/example10.py +18 -5
  12. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/example11.py +18 -5
  13. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/example12.py +22 -7
  14. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/example8-gl.py +10 -2
  15. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/example9.py +10 -2
  16. {yapCAD-0.2.5 → yapcad-0.3.0}/pyproject.toml +9 -6
  17. {yapCAD-0.2.5 → yapcad-0.3.0}/requirements.txt +6 -3
  18. {yapCAD-0.2.5 → yapcad-0.3.0}/setup.cfg +8 -1
  19. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapCAD.egg-info/PKG-INFO +29 -5
  20. yapcad-0.3.0/src/yapCAD.egg-info/requires.txt +12 -0
  21. yapcad-0.3.0/src/yapcad/__init__.py +11 -0
  22. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapcad/combine.py +14 -8
  23. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapcad/geom.py +12 -14
  24. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapcad/geometry.py +2 -2
  25. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapcad/xform.py +10 -4
  26. {yapCAD-0.2.5 → yapcad-0.3.0}/tests/test_xform.py +10 -0
  27. yapCAD-0.2.5/src/yapCAD.egg-info/requires.txt +0 -11
  28. yapCAD-0.2.5/src/yapcad/__init__.py +0 -11
  29. {yapCAD-0.2.5 → yapcad-0.3.0}/.coveragerc +0 -0
  30. {yapCAD-0.2.5 → yapcad-0.3.0}/.readthedocs.yml +0 -0
  31. {yapCAD-0.2.5 → yapcad-0.3.0}/AUTHORS.rst +0 -0
  32. {yapCAD-0.2.5 → yapcad-0.3.0}/LICENSE +0 -0
  33. {yapCAD-0.2.5 → yapcad-0.3.0}/LICENSE.txt +0 -0
  34. {yapCAD-0.2.5 → yapcad-0.3.0}/docs/Makefile +0 -0
  35. {yapCAD-0.2.5 → yapcad-0.3.0}/docs/_static/.gitignore +0 -0
  36. {yapCAD-0.2.5 → yapcad-0.3.0}/docs/authors.rst +0 -0
  37. {yapCAD-0.2.5 → yapcad-0.3.0}/docs/changelog.rst +0 -0
  38. {yapCAD-0.2.5 → yapcad-0.3.0}/docs/images/laserbox.jpg +0 -0
  39. {yapCAD-0.2.5 → yapcad-0.3.0}/docs/images/yapCadSplash.png +0 -0
  40. {yapCAD-0.2.5 → yapcad-0.3.0}/docs/license.rst +0 -0
  41. {yapCAD-0.2.5 → yapcad-0.3.0}/dxf/README.md +0 -0
  42. {yapCAD-0.2.5 → yapcad-0.3.0}/dxf/README.rst +0 -0
  43. {yapCAD-0.2.5 → yapcad-0.3.0}/dxf/boxout.dxf +0 -0
  44. {yapCAD-0.2.5 → yapcad-0.3.0}/dxf/example1-out.dxf +0 -0
  45. {yapCAD-0.2.5 → yapcad-0.3.0}/dxf/example10-out.dxf +0 -0
  46. {yapCAD-0.2.5 → yapcad-0.3.0}/dxf/example3-out.dxf +0 -0
  47. {yapCAD-0.2.5 → yapcad-0.3.0}/dxf/example4-out.dxf +0 -0
  48. {yapCAD-0.2.5 → yapcad-0.3.0}/dxf/example5-out.dxf +0 -0
  49. {yapCAD-0.2.5 → yapcad-0.3.0}/dxf/example6-out.dxf +0 -0
  50. {yapCAD-0.2.5 → yapcad-0.3.0}/dxf/example7-out.dxf +0 -0
  51. {yapCAD-0.2.5 → yapcad-0.3.0}/dxf/example8-out.dxf +0 -0
  52. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/README.md +0 -0
  53. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/README.rst +0 -0
  54. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/boxcut/README.md +0 -0
  55. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/boxcut/README.rst +0 -0
  56. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/example2.py +0 -0
  57. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/example3.py +0 -0
  58. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/example4.py +0 -0
  59. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/example5.py +0 -0
  60. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/example6.py +0 -0
  61. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/example7.py +0 -0
  62. {yapCAD-0.2.5 → yapcad-0.3.0}/examples/example8.py +0 -0
  63. {yapCAD-0.2.5 → yapcad-0.3.0}/images/README.md +0 -0
  64. {yapCAD-0.2.5 → yapcad-0.3.0}/images/README.rst +0 -0
  65. {yapCAD-0.2.5 → yapcad-0.3.0}/images/example6-out.png +0 -0
  66. {yapCAD-0.2.5 → yapcad-0.3.0}/images/example8-out.png +0 -0
  67. {yapCAD-0.2.5 → yapcad-0.3.0}/images/yapCAD01.png +0 -0
  68. {yapCAD-0.2.5 → yapcad-0.3.0}/images/yapCAD02.png +0 -0
  69. {yapCAD-0.2.5 → yapcad-0.3.0}/images/yapCadSplash.png +0 -0
  70. {yapCAD-0.2.5 → yapcad-0.3.0}/setup.py +0 -0
  71. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapCAD.egg-info/SOURCES.txt +0 -0
  72. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapCAD.egg-info/dependency_links.txt +0 -0
  73. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapCAD.egg-info/not-zip-safe +0 -0
  74. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapCAD.egg-info/top_level.txt +0 -0
  75. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapcad/drawable.py +0 -0
  76. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapcad/ezdxf_drawable.py +0 -0
  77. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapcad/geom3d.py +0 -0
  78. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapcad/poly.py +0 -0
  79. {yapCAD-0.2.5 → yapcad-0.3.0}/src/yapcad/pyglet_drawable.py +0 -0
  80. {yapCAD-0.2.5 → yapcad-0.3.0}/tests/conftest.py +0 -0
  81. {yapCAD-0.2.5 → yapcad-0.3.0}/tests/test_geom.py +0 -0
@@ -48,6 +48,11 @@ MANIFEST
48
48
 
49
49
  # Per-project virtualenvs
50
50
  .venv*/
51
+ venv/
52
+ v_*/
53
+
54
+ #cached python version for pyenv
55
+ .python-version
51
56
 
52
57
  # generated DXF files in examples
53
58
  examples/*.dxf
@@ -2,6 +2,27 @@
2
2
  Changelog
3
3
  =========
4
4
 
5
+ Version 0.3.0
6
+ =============
7
+
8
+ what's new:
9
+ -----------
10
+
11
+ - Require Python 3.10+ and align dependency metadata with current
12
+ interpreter and library versions.
13
+ - Pin pyglet to 1.x rendering backend and add fallback
14
+ guards to every OpenGL-enabled example so they degrade gracefully on
15
+ systems without a working pyglet/Cocoa stack.
16
+ - Sphinx documentation now builds even when optional themes are
17
+ missing, and `sphinx-apidoc` no longer depends on ``pkg_resources``.
18
+
19
+ Known problems
20
+ --------------
21
+
22
+ - Incomplete documentation, especially outside the ``yapcad.geom`` module.
23
+ - Occasional problems with complex boolean operations.
24
+ - Incomplete functionality around 3D modeling.
25
+
5
26
  Version 0.1.5
6
27
  =============
7
28
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: yapCAD
3
- Version: 0.2.5
3
+ Version: 0.3.0
4
4
  Summary: yet another procedural CAD and computational geometry system
5
5
  Author-email: Richard DeVaul <richard.devaul@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/rdevaul/yapCAD/
@@ -8,13 +8,21 @@ Project-URL: Documentation, https://yapcad.readthedocs.io/en/latest/
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.7
11
+ Requires-Python: >=3.10
12
12
  Description-Content-Type: text/x-rst
13
- Provides-Extra: testing
14
- Provides-Extra: tests
15
13
  License-File: LICENSE
16
14
  License-File: LICENSE.txt
17
15
  License-File: AUTHORS.rst
16
+ Requires-Dist: ezdxf>=1.1
17
+ Requires-Dist: pyglet<2,>=1.5
18
+ Requires-Dist: mpmath>=1.2
19
+ Requires-Dist: pyobjc-core; platform_system == "Darwin"
20
+ Requires-Dist: pyobjc-framework-Cocoa; platform_system == "Darwin"
21
+ Requires-Dist: pyobjc-framework-Quartz; platform_system == "Darwin"
22
+ Provides-Extra: tests
23
+ Requires-Dist: pytest; extra == "tests"
24
+ Requires-Dist: pytest-cov; extra == "tests"
25
+ Dynamic: license-file
18
26
 
19
27
  **yapCAD**
20
28
  ==========
@@ -106,6 +114,22 @@ supported by Sphinx. See the `Sphinx
106
114
  documentation <https://www.sphinx-doc.org/en/master/>`__ for more
107
115
  information.
108
116
 
117
+ running tests
118
+ ~~~~~~~~~~~~~
119
+
120
+ The repository includes a small pytest suite that exercises the core
121
+ geometry primitives. Install the testing dependencies and run pytest
122
+ from the project root with the source tree on ``PYTHONPATH``::
123
+
124
+ python3 -m pip install pytest pytest-cov
125
+ PYTHONPATH=./src python3 -m pytest
126
+
127
+ The default configuration enables coverage reporting via
128
+ ``pytest-cov``. If you prefer to skip coverage, you can override the
129
+ options::
130
+
131
+ PYTHONPATH=./src python3 -m pytest --override-ini addopts=
132
+
109
133
  **yapCAD** goals
110
134
  ----------------
111
135
 
@@ -68,6 +68,25 @@ supported by Sphinx. See the [Sphinx
68
68
  documentation](https://www.sphinx-doc.org/en/master/) for more
69
69
  information.
70
70
 
71
+ ### running tests
72
+
73
+ The repository includes a small pytest suite that exercises the core
74
+ geometry primitives. Install the testing dependencies and run pytest
75
+ from the project root with the source tree on `PYTHONPATH`:
76
+
77
+ ```bash
78
+ python3 -m pip install pytest pytest-cov
79
+ PYTHONPATH=./src python3 -m pytest
80
+ ```
81
+
82
+ The default configuration enables coverage reporting via
83
+ `pytest-cov`. If you prefer to skip coverage, you can override the
84
+ options:
85
+
86
+ ```bash
87
+ PYTHONPATH=./src python3 -m pytest --override-ini addopts=
88
+ ```
89
+
71
90
  ## **yapCAD** goals
72
91
 
73
92
  The purpose of **yapCAD** is to support 2D and 3D computational
@@ -88,6 +88,22 @@ supported by Sphinx. See the `Sphinx
88
88
  documentation <https://www.sphinx-doc.org/en/master/>`__ for more
89
89
  information.
90
90
 
91
+ running tests
92
+ ~~~~~~~~~~~~~
93
+
94
+ The repository includes a small pytest suite that exercises the core
95
+ geometry primitives. Install the testing dependencies and run pytest
96
+ from the project root with the source tree on ``PYTHONPATH``::
97
+
98
+ python3 -m pip install pytest pytest-cov
99
+ PYTHONPATH=./src python3 -m pytest
100
+
101
+ The default configuration enables coverage reporting via
102
+ ``pytest-cov``. If you prefer to skip coverage, you can override the
103
+ options::
104
+
105
+ PYTHONPATH=./src python3 -m pytest --override-ini addopts=
106
+
91
107
  **yapCAD** goals
92
108
  ----------------
93
109
 
@@ -88,6 +88,22 @@ supported by Sphinx. See the `Sphinx
88
88
  documentation <https://www.sphinx-doc.org/en/master/>`__ for more
89
89
  information.
90
90
 
91
+ running tests
92
+ ~~~~~~~~~~~~~
93
+
94
+ The repository includes a small pytest suite that exercises the core
95
+ geometry primitives. Install the testing dependencies and run pytest
96
+ from the project root with the source tree on ``PYTHONPATH``::
97
+
98
+ python3 -m pip install pytest pytest-cov
99
+ PYTHONPATH=./src python3 -m pytest
100
+
101
+ The default configuration enables coverage reporting via
102
+ ``pytest-cov``. If you prefer to skip coverage, you can override the
103
+ options::
104
+
105
+ PYTHONPATH=./src python3 -m pytest --override-ini addopts=
106
+
91
107
  **yapCAD** goals
92
108
  ----------------
93
109
 
@@ -13,7 +13,12 @@ import sys
13
13
  import inspect
14
14
  import shutil
15
15
 
16
- import sphinx_rtd_theme
16
+ try:
17
+ import sphinx_rtd_theme # optional theme used on RTD
18
+ _has_rtd_theme = True
19
+ except ImportError:
20
+ sphinx_rtd_theme = None
21
+ _has_rtd_theme = False
17
22
 
18
23
  __location__ = os.path.join(os.getcwd(), os.path.dirname(
19
24
  inspect.getfile(inspect.currentframe())))
@@ -45,13 +50,17 @@ except FileNotFoundError:
45
50
 
46
51
  try:
47
52
  import sphinx
48
- from pkg_resources import parse_version
49
53
 
50
54
  cmd_line_template = "sphinx-apidoc -f -o {outputdir} {moduledir}"
51
55
  cmd_line = cmd_line_template.format(outputdir=output_dir, moduledir=module_dir)
52
56
 
53
57
  args = cmd_line.split(" ")
54
- if parse_version(sphinx.__version__) >= parse_version('1.7'):
58
+ # sphinx-apidoc switched to a subcommand style interface in 1.7
59
+ try:
60
+ major, minor, *_ = (int(x) for x in sphinx.__version__.split('.')[:2])
61
+ except ValueError:
62
+ major, minor = 1, 7
63
+ if (major, minor) >= (1, 7):
55
64
  args = args[1:]
56
65
 
57
66
  apidoc.main(args)
@@ -68,7 +77,10 @@ except Exception as e:
68
77
  extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo',
69
78
  'sphinx.ext.autosummary', 'sphinx.ext.viewcode', 'sphinx.ext.coverage',
70
79
  'sphinx.ext.doctest', 'sphinx.ext.ifconfig', 'sphinx.ext.mathjax',
71
- 'sphinx.ext.napoleon', 'sphinx_rtd_theme']
80
+ 'sphinx.ext.napoleon']
81
+
82
+ if _has_rtd_theme:
83
+ extensions.append('sphinx_rtd_theme')
72
84
 
73
85
  # Add any paths that contain templates here, relative to this directory.
74
86
  templates_path = ['_templates']
@@ -138,7 +150,7 @@ pygments_style = 'sphinx'
138
150
  # The theme to use for HTML and HTML Help pages. See the documentation for
139
151
  # a list of builtin themes.
140
152
  #html_theme = 'alabaster'
141
- html_theme = 'sphinx_rtd_theme'
153
+ html_theme = 'sphinx_rtd_theme' if _has_rtd_theme else 'alabaster'
142
154
 
143
155
  # Theme options are theme-specific and customize the look and feel of a theme
144
156
  # further. For a list of options available for each theme, see the
@@ -11,7 +11,7 @@ pretty early state, though we hope you will find it useful.
11
11
  **yapCAD** was created to solve some fairly specific problems in
12
12
  procedural CAD and `parametric design`_ , and at present is most
13
13
  developed for generating 2D drawings in the `AutoCad DXF`_ format.
14
- If you don't know what procedural CAD or paramaterized design
14
+ If you don't know what procedural CAD or parameterized design
15
15
  might be useful for, this may not be the tool for you.
16
16
 
17
17
  On the other hand, if you are tired of manually editing your CAD
@@ -561,8 +561,17 @@ if __name__ == "__main__":
561
561
  dd.display()
562
562
 
563
563
  if ogl:
564
- from yapcad.pyglet_drawable import *
565
- dd2 = pygletDraw()
564
+ try:
565
+ from yapcad.pyglet_drawable import *
566
+ dd2 = pygletDraw()
567
+ except RuntimeError as err:
568
+ print("\nSkipping 3D visualization: {}".format(err))
569
+ ogl = False
570
+ except Exception as err:
571
+ print("\nSkipping 3D visualization due to unexpected error: {}".format(err))
572
+ ogl = False
573
+
574
+ if ogl:
566
575
  # magnification factor for text
567
576
  dd2.magnify=1.5
568
577
  # compute the camera distance assuming a 60 degree (pi/6) FOV
@@ -571,13 +580,9 @@ if __name__ == "__main__":
571
580
  dist = ((maxd/2) / math.sin(pi/6))*math.cos(pi/6)
572
581
  dd2.cameradist = dist-box_height*2
573
582
 
574
-
575
583
  twoDDraw(polys,dd2,-box_height*2)
576
584
 
577
585
  oglGeom = makeOglGeom()
578
- #print("oglGeom: ",oglGeom)
579
-
580
- #oglGeom = translate(oglGeom,point(0,0,box_height))
581
586
 
582
587
  dd2.layer='PATHS'
583
588
  for i in range(len(oglGeom)):
@@ -587,8 +592,6 @@ if __name__ == "__main__":
587
592
  dd2.linecolor = 'aqua'
588
593
  else:
589
594
  dd2.linecolor = 'fuchsia'
590
-
591
595
  dd2.draw(oglGeom[i])
592
596
  dd2.display()
593
597
  print("done")
594
-
@@ -7,7 +7,11 @@ from yapcad.geom import *
7
7
 
8
8
  #set up openGL rendering
9
9
  def setupGL():
10
- dGl =pygletDraw()
10
+ try:
11
+ dGl = pygletDraw()
12
+ except RuntimeError as err:
13
+ print("\nSkipping OpenGL rendering: {}".format(err))
14
+ return None
11
15
  dGl.magnify = 1.0
12
16
  dGl.linecolor = 'white'
13
17
  dGl.cameradist = 25
@@ -107,15 +111,18 @@ if __name__ == "__main__":
107
111
  ## add a drawing legend in the OpenGL rendering, setting the
108
112
  ## color eplicitly to yellow
109
113
 
110
- dGl.linecolor = 'yellow'
111
- legend(dGl)
114
+ if dGl:
115
+ dGl.linecolor = 'yellow'
116
+ legend(dGl)
112
117
 
113
118
  ## draw the geometry in OpenGL
114
- drawGlist(geomlist,dGl)
119
+ if dGl:
120
+ drawGlist(geomlist,dGl)
115
121
 
116
122
  ## write out the DXF file as example1-out.dxf
117
123
  d.display()
118
124
 
119
125
  ## create the interactive OpenGL rendering -- do this last
120
- dGl.display()
126
+ if dGl:
127
+ dGl.display()
121
128
 
@@ -203,17 +203,30 @@ if __name__ == "__main__":
203
203
  quit()
204
204
  if len(sys.argv) > 2 and renderOgl==False:
205
205
  filename = sys.argv[2]+".dxf"
206
- dd = []
206
+ requestedOgl = renderOgl
207
+ dd = None
207
208
  if renderOgl:
208
209
  print("OpenGL rendering selected")
209
- from yapcad.pyglet_drawable import *
210
- dd=pygletDraw()
211
- else:
212
- print("DXF rendering selected")
210
+ try:
211
+ from yapcad.pyglet_drawable import *
212
+ dd=pygletDraw()
213
+ except RuntimeError as err:
214
+ print("\nSkipping OpenGL rendering: {}".format(err))
215
+ renderOgl = False
216
+ except Exception as err:
217
+ print("\nSkipping OpenGL rendering due to unexpected error: {}".format(err))
218
+ renderOgl = False
219
+
220
+ if not renderOgl or dd is None:
221
+ if requestedOgl and dd is None:
222
+ print("Falling back to DXF rendering")
223
+ else:
224
+ print("DXF rendering selected")
213
225
  from yapcad.ezdxf_drawable import *
214
226
  #set up DXF rendering
215
227
  dd=ezdxfDraw()
216
228
  dd.filename = filename
229
+ renderOgl = False
217
230
  print("rendering...")
218
231
  testAndDraw(dd)
219
232
  print("done")
@@ -106,17 +106,30 @@ if __name__ == "__main__":
106
106
  quit()
107
107
  if len(sys.argv) > 2 and renderOgl==False:
108
108
  filename = sys.argv[2]+".dxf"
109
- dd = []
109
+ requestedOgl = renderOgl
110
+ dd = None
110
111
  if renderOgl:
111
112
  print("OpenGL rendering selected")
112
- from yapcad.pyglet_drawable import *
113
- dd=pygletDraw()
114
- else:
115
- print("DXF rendering selected")
113
+ try:
114
+ from yapcad.pyglet_drawable import *
115
+ dd=pygletDraw()
116
+ except RuntimeError as err:
117
+ print("\nSkipping OpenGL rendering: {}".format(err))
118
+ renderOgl = False
119
+ except Exception as err:
120
+ print("\nSkipping OpenGL rendering due to unexpected error: {}".format(err))
121
+ renderOgl = False
122
+
123
+ if not renderOgl or dd is None:
124
+ if requestedOgl and dd is None:
125
+ print("Falling back to DXF rendering")
126
+ else:
127
+ print("DXF rendering selected")
116
128
  from yapcad.ezdxf_drawable import *
117
129
  #set up DXF rendering
118
130
  dd=ezdxfDraw()
119
131
  dd.filename = filename
132
+ renderOgl = False
120
133
  print("rendering...")
121
134
  testAndDraw(dd)
122
135
  print("done")
@@ -44,6 +44,7 @@ def geometry():
44
44
  jigsaw=makeJigsawPiece(poly=True)
45
45
  bigc= makeCircle(point(0,0,0),20)
46
46
  nb = Boolean('union',[logopoly,bigc])
47
+ nb = nb.scale(0.8,poly=True)
47
48
  nb = nb.translate(point(0,-50),poly=True)
48
49
  docGeomList.append(nb.geom())
49
50
 
@@ -74,6 +75,8 @@ def testAndDraw(dd):
74
75
  else:
75
76
  dd.linecolor = 'aqua'
76
77
  dd.draw(geom2)
78
+ dd.linecolor = 'red'
79
+ dd.draw(translate(geom,point(0,0,5)))
77
80
 
78
81
  if not renderOgl:
79
82
  dd.layer = 'DOCUMENTATION'
@@ -114,20 +117,32 @@ if __name__ == "__main__":
114
117
  quit()
115
118
  if len(sys.argv) > 2 and renderOgl==False:
116
119
  filename = sys.argv[2]+".dxf"
117
- dd = []
120
+ requestedOgl = renderOgl
121
+ dd = None
118
122
  if renderOgl:
119
123
  print("OpenGL rendering selected")
120
- from yapcad.pyglet_drawable import *
121
- dd=pygletDraw()
122
- dd.cameradist=170.0
123
-
124
- else:
125
- print("DXF rendering selected")
124
+ try:
125
+ from yapcad.pyglet_drawable import *
126
+ dd=pygletDraw()
127
+ dd.cameradist=170.0
128
+ except RuntimeError as err:
129
+ print("\nSkipping OpenGL rendering: {}".format(err))
130
+ renderOgl = False
131
+ except Exception as err:
132
+ print("\nSkipping OpenGL rendering due to unexpected error: {}".format(err))
133
+ renderOgl = False
134
+
135
+ if not renderOgl or dd is None:
136
+ if requestedOgl and dd is None:
137
+ print("Falling back to DXF rendering")
138
+ else:
139
+ print("DXF rendering selected")
126
140
  from yapcad.ezdxf_drawable import *
127
141
  #set up DXF rendering
128
142
  dd=ezdxfDraw()
129
143
  dd.filename = filename
130
144
  drawLegend(dd)
145
+ renderOgl = False
131
146
  print("rendering...")
132
147
 
133
148
  testAndDraw(dd)
@@ -1,5 +1,6 @@
1
1
  ## yapCAD poly() intersecton and drawing examples
2
2
 
3
+ import sys
3
4
  from yapcad.geom import *
4
5
  from yapcad.poly import *
5
6
  import random
@@ -14,8 +15,15 @@ if __name__ == "__main__":
14
15
  making and then mirroring random "flowers." Renders output interactively with OpenGL.
15
16
  """)
16
17
 
17
- from yapcad.pyglet_drawable import *
18
- dd=pygletDraw()
18
+ try:
19
+ from yapcad.pyglet_drawable import *
20
+ dd=pygletDraw()
21
+ except RuntimeError as err:
22
+ print("\nSkipping OpenGL rendering: {}".format(err))
23
+ sys.exit(0)
24
+ except Exception as err:
25
+ print("\nSkipping OpenGL rendering due to unexpected error: {}".format(err))
26
+ sys.exit(1)
19
27
  dd.cameradist=150.0
20
28
  glist = mirrorArray()
21
29
 
@@ -117,7 +117,16 @@ def sphere(diameter,center=point(0,0,0),depth=2):
117
117
 
118
118
 
119
119
  if __name__ == "__main__":
120
- from yapcad.pyglet_drawable import *
120
+ import sys
121
+ try:
122
+ from yapcad.pyglet_drawable import *
123
+ dd=pygletDraw()
124
+ except RuntimeError as err:
125
+ print("\nSkipping OpenGL rendering: {}".format(err))
126
+ sys.exit(0)
127
+ except Exception as err:
128
+ print("\nSkipping OpenGL rendering due to unexpected error: {}".format(err))
129
+ sys.exit(1)
121
130
  print("example9.py -- yapCAD 3D geometry demonstration")
122
131
  print("""
123
132
  This is a demonstration of the creation and rendering of
@@ -127,7 +136,6 @@ engine.
127
136
  In this example we create an icosohedron centered at the orign and
128
137
  tesellate it spherically""")
129
138
 
130
- dd=pygletDraw()
131
139
  dd.linecolor = 'white'
132
140
 
133
141
  verts,normals,faces = sphere(50.0,point(0,0,0),3)
@@ -1,22 +1,25 @@
1
1
  [project]
2
2
  name = "yapCAD"
3
- version = "0.2.5"
3
+ version = "0.3.0"
4
4
  authors = [
5
5
  { name="Richard DeVaul", email="richard.devaul@gmail.com" },
6
6
  ]
7
7
  description = "yet another procedural CAD and computational geometry system"
8
8
  readme = "README.rst"
9
- requires-python = ">=3.7"
9
+ requires-python = ">=3.10"
10
10
  classifiers = [
11
11
  "Programming Language :: Python :: 3",
12
12
  "License :: OSI Approved :: MIT License",
13
13
  "Operating System :: OS Independent",
14
14
  ]
15
15
  dependencies = [
16
- "ezdxf",
17
- "pyglet < 2",
18
- "mpmath"
19
- ]
16
+ "ezdxf>=1.1",
17
+ "pyglet>=1.5,<2",
18
+ "mpmath>=1.2",
19
+ "pyobjc-core; platform_system == 'Darwin'",
20
+ "pyobjc-framework-Cocoa; platform_system == 'Darwin'",
21
+ "pyobjc-framework-Quartz; platform_system == 'Darwin'"
22
+ ]
20
23
 
21
24
  [project.optional-dependencies]
22
25
  tests = [
@@ -15,6 +15,9 @@
15
15
  # numpy==1.13.3
16
16
  # scipy==1.0
17
17
  #
18
- ezdxf
19
- pyglet<2
20
- mpmath
18
+ ezdxf>=1.1
19
+ pyglet>=1.5,<2
20
+ mpmath>=1.2
21
+ pyobjc-core; platform_system == "Darwin"
22
+ pyobjc-framework-Cocoa; platform_system == "Darwin"
23
+ pyobjc-framework-Quartz; platform_system == "Darwin"
@@ -7,7 +7,14 @@ include_package_data = True
7
7
  package_dir =
8
8
  =src
9
9
  setup_requires = pyscaffold>=3.2a0,<3.3a0
10
- install_requires = ezdxf; pyglet<2; mpmath
10
+ install_requires =
11
+ ezdxf>=1.1
12
+ pyglet>=1.5,<2
13
+ mpmath>=1.2
14
+ pyobjc-core; platform_system == "Darwin"
15
+ pyobjc-framework-Cocoa; platform_system == "Darwin"
16
+ pyobjc-framework-Quartz; platform_system == "Darwin"
17
+ python_requires = >=3.10
11
18
 
12
19
  [options.packages.find]
13
20
  where = src
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: yapCAD
3
- Version: 0.2.5
3
+ Version: 0.3.0
4
4
  Summary: yet another procedural CAD and computational geometry system
5
5
  Author-email: Richard DeVaul <richard.devaul@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/rdevaul/yapCAD/
@@ -8,13 +8,21 @@ Project-URL: Documentation, https://yapcad.readthedocs.io/en/latest/
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.7
11
+ Requires-Python: >=3.10
12
12
  Description-Content-Type: text/x-rst
13
- Provides-Extra: testing
14
- Provides-Extra: tests
15
13
  License-File: LICENSE
16
14
  License-File: LICENSE.txt
17
15
  License-File: AUTHORS.rst
16
+ Requires-Dist: ezdxf>=1.1
17
+ Requires-Dist: pyglet<2,>=1.5
18
+ Requires-Dist: mpmath>=1.2
19
+ Requires-Dist: pyobjc-core; platform_system == "Darwin"
20
+ Requires-Dist: pyobjc-framework-Cocoa; platform_system == "Darwin"
21
+ Requires-Dist: pyobjc-framework-Quartz; platform_system == "Darwin"
22
+ Provides-Extra: tests
23
+ Requires-Dist: pytest; extra == "tests"
24
+ Requires-Dist: pytest-cov; extra == "tests"
25
+ Dynamic: license-file
18
26
 
19
27
  **yapCAD**
20
28
  ==========
@@ -106,6 +114,22 @@ supported by Sphinx. See the `Sphinx
106
114
  documentation <https://www.sphinx-doc.org/en/master/>`__ for more
107
115
  information.
108
116
 
117
+ running tests
118
+ ~~~~~~~~~~~~~
119
+
120
+ The repository includes a small pytest suite that exercises the core
121
+ geometry primitives. Install the testing dependencies and run pytest
122
+ from the project root with the source tree on ``PYTHONPATH``::
123
+
124
+ python3 -m pip install pytest pytest-cov
125
+ PYTHONPATH=./src python3 -m pytest
126
+
127
+ The default configuration enables coverage reporting via
128
+ ``pytest-cov``. If you prefer to skip coverage, you can override the
129
+ options::
130
+
131
+ PYTHONPATH=./src python3 -m pytest --override-ini addopts=
132
+
109
133
  **yapCAD** goals
110
134
  ----------------
111
135
 
@@ -0,0 +1,12 @@
1
+ ezdxf>=1.1
2
+ pyglet<2,>=1.5
3
+ mpmath>=1.2
4
+
5
+ [:platform_system == "Darwin"]
6
+ pyobjc-core
7
+ pyobjc-framework-Cocoa
8
+ pyobjc-framework-Quartz
9
+
10
+ [tests]
11
+ pytest
12
+ pytest-cov
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+ try: # Python >= 3.8
3
+ from importlib.metadata import PackageNotFoundError, version
4
+ except ModuleNotFoundError: # pragma: no cover - for Python < 3.8
5
+ from importlib_metadata import PackageNotFoundError, version
6
+
7
+
8
+ try:
9
+ __version__ = version("yapCAD")
10
+ except PackageNotFoundError: # pragma: no cover - handled when package not installed
11
+ __version__ = "unknown"
@@ -10,16 +10,22 @@ class Boolean(IntersectGeometry):
10
10
 
11
11
  types = ('union','intersection','difference')
12
12
 
13
- def __init__(self,type='union',polys=[]):
13
+ def __init__(self, type='union', polys=None):
14
+ super().__init__()
15
+ if type not in self.types:
16
+ raise ValueError('invalid type passed to Boolean(): {}'.format(type))
17
+
18
+ if polys is None:
19
+ polys = []
20
+
14
21
  for p in polys:
15
- if not ( isinstance(p,Polygon) or isinstance(p,Boolean) ):
22
+ if not (isinstance(p, Polygon) or isinstance(p, Boolean)):
16
23
  raise ValueError('non-poly or non-boolean passed to Boolean(): {}'.format(p))
17
- if not type in self.types:
18
- raise ValueError('invalid type passed to Boolean(): {}'.format(tpe))
19
- self._elem=list(polys)
20
- self._type=type
21
- self._update=True
22
- self._outline=[]
24
+
25
+ self._elem = list(polys)
26
+ self._type = type
27
+ self._update = True
28
+ self._outline = []
23
29
 
24
30
 
25
31
  def combine_geom(self,g1,g2):
@@ -1870,7 +1870,6 @@ def isinsidepolyXY(a,p):
1870
1870
 
1871
1871
  """
1872
1872
  closed=False
1873
-
1874
1873
  if len(a) > 2 and dist(a[0],a[-1]) < epsilon:
1875
1874
  closed = True
1876
1875
 
@@ -1887,12 +1886,11 @@ def isinsidepolyXY(a,p):
1887
1886
  if not isinsidebbox(bb,p):
1888
1887
  return False
1889
1888
  ## inside the bounding box, do intersection testing
1890
- p2 = add([1,1,0,1],bb[1])
1889
+ p2 = add([0.01,0.01,0,1],bb[1])
1891
1890
  if vclose(p2,p): ## did we randomly pick an outside point near the
1892
- ## test point?
1893
- p2 = sub(bb[0],[1,1,0,1])
1891
+ ## test point? If so, test point is outside bb
1892
+ return False
1894
1893
  l = line(p,p2)
1895
-
1896
1894
  pp = intersectSimplePolyXY(l,a)
1897
1895
  if pp == False:
1898
1896
  return False
@@ -2285,10 +2283,10 @@ def isinsidegeomlistXY(a,p):
2285
2283
  bb = geomlistbbox(a)
2286
2284
  if not isinsidebbox(bb,p):
2287
2285
  return False
2288
- p2 = add([1,1,0,1],bb[1])
2286
+ p2 = add([0.1,0.1,0,1],bb[1])
2289
2287
  if vclose(p2,p): ## did we randomly pick an outside point near the
2290
- ## test point?
2291
- p2 = sub(bb[0],[1,1,0,1])
2288
+ ## test point? If so, test point is outside bb
2289
+ return False
2292
2290
  l = line(p,p2)
2293
2291
 
2294
2292
  pp = intersectGeomListXY(l,a)
@@ -2365,7 +2363,7 @@ def intersectGeomListXY(g,gl,inside=True,params=False):
2365
2363
  raise ValueError('bad gtype in intersectGeomListXY, this should never happen')
2366
2364
 
2367
2365
  dst = 0.0
2368
- if len(gl) > 2:
2366
+ if len(gl) > 1:
2369
2367
  for i in range(len(gl)):
2370
2368
  g2 = gl[i]
2371
2369
  uu = []
@@ -2389,12 +2387,12 @@ def intersectGeomListXY(g,gl,inside=True,params=False):
2389
2387
  elif gtype == 'poly' and gtype2 == 'poly':
2390
2388
  zz1 = []
2391
2389
  zz2 = []
2392
- for i in range(1,len(g)):
2393
- zz = intersectSimplePolyXY(line(g[i-1],g[i]),
2390
+ for j in range(1,len(g)):
2391
+ zz = intersectSimplePolyXY(line(g[j-1],g[j]),
2394
2392
  g2, params=True)
2395
2393
  if not isinstance(zz,bool):
2396
- zz1.append(zz[0])
2397
- zz2.append(zz[1])
2394
+ zz1 = zz1 + zz[0]
2395
+ zz2 = zz2 + zz[1]
2398
2396
  if len(zz1) > 0:
2399
2397
  uu = [ zz1,zz2 ]
2400
2398
  elif gtype == 'simple' and gtype2 == 'glist':
@@ -2543,7 +2541,7 @@ def center(x):
2543
2541
  pl = []
2544
2542
  for g in x:
2545
2543
  pl.append(center(g))
2546
- return polycenter(pl)
2544
+ return center(pl)
2547
2545
  else:
2548
2546
  raise ValueError("inappropriate type for center(): ",format(x))
2549
2547
 
@@ -18,7 +18,7 @@
18
18
  ## classically-definalble gap (or the possibility thereof) then
19
19
  ## implement Geometry instead
20
20
 
21
- import copy
21
+ from copy import deepcopy
22
22
  from yapcad.geom import *
23
23
 
24
24
 
@@ -43,7 +43,7 @@ class Geometry:
43
43
  return
44
44
 
45
45
  def geom(self):
46
- if self.update:
46
+ if self._update:
47
47
  self._updateInternals()
48
48
  return deepcopy(self._elem)
49
49
 
@@ -165,11 +165,17 @@ class Matrix:
165
165
  self.m[j] = x
166
166
 
167
167
 
168
- # matrix multiply. If x is a matrix, compute MX. If X is a
168
+ # matrix multiply. If x is a matrix, compute MX. If x is a
169
169
  # vector, compute Mx. If x is a scalar, compute xM. If x isn't any
170
- # of these, return False. Respects transpose flag.
171
-
170
+ # of these, a ValueError is raised. Respects transpose flag.
171
+
172
172
  def mul(self,x):
173
+ """Return the product of this matrix and ``x``.
174
+
175
+ ``x`` may be another :class:`Matrix`, a 4D vector, or a scalar. In
176
+ each case the appropriate matrix multiplication is performed. If
177
+ ``x`` is none of these types, a :class:`ValueError` is raised.
178
+ """
173
179
  if isinstance(x,Matrix):
174
180
  result = Matrix()
175
181
  for i in range(4):
@@ -232,7 +238,7 @@ def Rotation(axis,angle,inverse=False):
232
238
 
233
239
  def Translation(delta,inverse=False):
234
240
  if inverse:
235
- delta = mul(delta,-1.0)
241
+ delta = geom.scale3(delta, -1.0)
236
242
  dx = delta[0]
237
243
  dy = delta[1]
238
244
  dz = delta[2]
@@ -26,6 +26,16 @@ class TestXform:
26
26
  ## homogeneous coordinates test
27
27
  assert(geom.homo(foo.mul(baz)) ==
28
28
  [18.0/102.0, 46.0/102.0, 74.0/102.0, 1.0])
29
+
30
+ def test_translation(self):
31
+ p = geom.vect(1,2,3)
32
+ dx = 4
33
+ dy = -2
34
+ dz = 1
35
+ T = Translation([dx,dy,dz])
36
+ assert(T.mul(p) == geom.vect(1+dx,2+dy,3+dz))
37
+ Tinv = Translation([dx,dy,dz],inverse=True)
38
+ assert(Tinv.mul(p) == geom.vect(1-dx,2-dy,3-dz))
29
39
 
30
40
 
31
41
 
@@ -1,11 +0,0 @@
1
- ezdxf
2
- pyglet<2
3
- mpmath
4
-
5
- [testing]
6
- pytest
7
- pytest-cov
8
-
9
- [tests]
10
- pytest
11
- pytest-cov
@@ -1,11 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- from pkg_resources import get_distribution, DistributionNotFound
3
-
4
- try:
5
- # Change here if project is renamed and does not equal the package name
6
- dist_name = 'yapCAD'
7
- __version__ = get_distribution(dist_name).version
8
- except DistributionNotFound:
9
- __version__ = 'unknown'
10
- finally:
11
- del get_distribution, DistributionNotFound
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes