pyiges 0.3.2__tar.gz → 0.3.4__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 (33) hide show
  1. {pyiges-0.3.2 → pyiges-0.3.4}/.github/workflows/testing-and-deployment.yml +26 -8
  2. {pyiges-0.3.2 → pyiges-0.3.4}/.pre-commit-config.yaml +9 -9
  3. {pyiges-0.3.2 → pyiges-0.3.4}/PKG-INFO +1 -1
  4. {pyiges-0.3.2 → pyiges-0.3.4}/pyproject.toml +6 -1
  5. {pyiges-0.3.2 → pyiges-0.3.4}/src/pyiges/__init__.py +3 -2
  6. {pyiges-0.3.2 → pyiges-0.3.4}/src/pyiges/check_imports.py +9 -0
  7. {pyiges-0.3.2 → pyiges-0.3.4}/src/pyiges/constants.py +1 -1
  8. {pyiges-0.3.2 → pyiges-0.3.4}/src/pyiges/entity.py +9 -1
  9. {pyiges-0.3.2 → pyiges-0.3.4}/src/pyiges/examples/__init__.py +2 -0
  10. {pyiges-0.3.2 → pyiges-0.3.4}/src/pyiges/geometry.py +110 -69
  11. {pyiges-0.3.2 → pyiges-0.3.4}/src/pyiges/iges.py +23 -15
  12. pyiges-0.3.4/src/pyiges/reader.py +49 -0
  13. pyiges-0.3.2/src/pyiges/faces.py +0 -19
  14. {pyiges-0.3.2 → pyiges-0.3.4}/.flake8 +0 -0
  15. {pyiges-0.3.2 → pyiges-0.3.4}/.gitignore +0 -0
  16. {pyiges-0.3.2 → pyiges-0.3.4}/CONTRIBUTING.rst +0 -0
  17. {pyiges-0.3.2 → pyiges-0.3.4}/LICENSE +0 -0
  18. {pyiges-0.3.2 → pyiges-0.3.4}/MANIFEST.in +0 -0
  19. {pyiges-0.3.2 → pyiges-0.3.4}/Makefile +0 -0
  20. {pyiges-0.3.2 → pyiges-0.3.4}/README.rst +0 -0
  21. {pyiges-0.3.2 → pyiges-0.3.4}/docs/Makefile +0 -0
  22. {pyiges-0.3.2 → pyiges-0.3.4}/docs/conf.py +0 -0
  23. {pyiges-0.3.2 → pyiges-0.3.4}/docs/geometry.rst +0 -0
  24. {pyiges-0.3.2 → pyiges-0.3.4}/docs/images/impeller_lines.png +0 -0
  25. {pyiges-0.3.2 → pyiges-0.3.4}/docs/images/impeller_surf.png +0 -0
  26. {pyiges-0.3.2 → pyiges-0.3.4}/docs/index.rst +0 -0
  27. {pyiges-0.3.2 → pyiges-0.3.4}/docs/make.bat +0 -0
  28. {pyiges-0.3.2 → pyiges-0.3.4}/docs/pyiges.rst +0 -0
  29. {pyiges-0.3.2 → pyiges-0.3.4}/src/pyiges/examples/impeller.igs +0 -0
  30. {pyiges-0.3.2 → pyiges-0.3.4}/src/pyiges/examples/sample.igs +0 -0
  31. {pyiges-0.3.2 → pyiges-0.3.4}/tests/conftest.py +0 -0
  32. {pyiges-0.3.2 → pyiges-0.3.4}/tests/reference_data/example-arcs.iges +0 -0
  33. {pyiges-0.3.2 → pyiges-0.3.4}/tests/test_pyiges.py +0 -0
@@ -44,15 +44,33 @@ jobs:
44
44
  flit build
45
45
  twine check dist/*
46
46
 
47
- - name: Upload to PyPi
48
- if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
47
+ pypi:
48
+ name: Publish to PyPI
49
+ if: github.event_name == 'push' && contains(github.ref, 'refs/tags')
50
+ needs: [unit_tests]
51
+ runs-on: ubuntu-latest
52
+ environment:
53
+ name: pypi
54
+ url: https://pypi.org/p/pyiges
55
+ permissions:
56
+ id-token: write # this permission is mandatory for trusted publishing
57
+ steps:
58
+ - uses: actions/checkout@v4
59
+ with:
60
+ persist-credentials: false
61
+
62
+ - name: Set up Python
63
+ uses: actions/setup-python@v5
64
+ with:
65
+ python-version: '3.13'
66
+
67
+ - name: Build package
49
68
  run: |
50
- pip install twine
51
- twine upload --skip-existing dist/pyiges*
52
- env:
53
- TWINE_USERNAME: __token__
54
- TWINE_PASSWORD: ${{ secrets.TWINE_TOKEN }}
55
- TWINE_REPOSITORY_URL: https://upload.pypi.org/legacy/
69
+ pip install flit
70
+ flit build
71
+
72
+ - name: Publish package distributions to PyPI
73
+ uses: pypa/gh-action-pypi-publish@release/v1
56
74
 
57
75
  Release:
58
76
  if: github.event_name == 'push' && contains(github.ref, 'refs/tags')
@@ -5,7 +5,7 @@ ci:
5
5
 
6
6
  repos:
7
7
  - repo: https://github.com/astral-sh/ruff-pre-commit
8
- rev: v0.11.12
8
+ rev: v0.15.9
9
9
  hooks:
10
10
  - id: ruff-check
11
11
  args: [--fix, --exit-non-zero-on-fix]
@@ -13,13 +13,13 @@ repos:
13
13
  - id: ruff-format
14
14
 
15
15
  - repo: https://github.com/keewis/blackdoc
16
- rev: v0.3.9
16
+ rev: v0.4.6
17
17
  hooks:
18
18
  - id: blackdoc
19
19
  exclude: README.rst
20
20
 
21
21
  - repo: https://github.com/codespell-project/codespell
22
- rev: v2.4.1
22
+ rev: v2.4.2
23
23
  hooks:
24
24
  - id: codespell
25
25
  args: [--skip=*.vt*]
@@ -29,23 +29,23 @@ repos:
29
29
  hooks:
30
30
  - id: pydocstyle
31
31
  additional_dependencies: [tomli==2.0.1]
32
- files: ^src/pyminiply/.*\.py
32
+ files: ^src/pyiges/.*\.py
33
33
 
34
34
  - repo: https://github.com/pre-commit/mirrors-mypy
35
- rev: v1.16.0
35
+ rev: v1.20.0
36
36
  hooks:
37
37
  - id: mypy
38
38
  additional_dependencies: [numpy>=2.0, pytest-stub]
39
39
 
40
40
  - repo: https://github.com/pre-commit/pre-commit-hooks
41
- rev: v5.0.0
41
+ rev: v6.0.0
42
42
  hooks:
43
43
  - id: check-merge-conflict
44
44
  - id: debug-statements
45
45
  - id: trailing-whitespace
46
46
 
47
47
  - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
48
- rev: v2.14.0
48
+ rev: v2.16.0
49
49
  hooks:
50
50
  - id: pretty-format-toml
51
51
  args: [--autofix]
@@ -53,11 +53,11 @@ repos:
53
53
  args: [--autofix, --indent, '2']
54
54
 
55
55
  - repo: https://github.com/pre-commit/mirrors-clang-format
56
- rev: v20.1.5
56
+ rev: v22.1.2
57
57
  hooks:
58
58
  - id: clang-format
59
59
 
60
60
  - repo: https://github.com/python-jsonschema/check-jsonschema
61
- rev: 0.33.0
61
+ rev: 0.37.1
62
62
  hooks:
63
63
  - id: check-github-workflows
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyiges
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: Pythonic IGES reader
5
5
  Keywords: iges,cad,nurbs,bspline
6
6
  Author-email: PyVista Developers <info@pyvista.org>
@@ -30,7 +30,12 @@ license = {text = "MIT"}
30
30
  name = "pyiges"
31
31
  readme = "README.rst"
32
32
  requires-python = ">=3.9"
33
- version = "0.3.2"
33
+ version = "0.3.4"
34
+
35
+ # Requires pyvista >= 0.48
36
+ [project.entry-points."pyvista.readers"]
37
+ ".iges" = "pyiges:read_as_mesh"
38
+ ".igs" = "pyiges:read_as_mesh"
34
39
 
35
40
  [project.optional-dependencies]
36
41
  docs = [
@@ -3,10 +3,11 @@
3
3
  from importlib.metadata import PackageNotFoundError, version
4
4
 
5
5
  from pyiges.iges import Iges, read
6
+ from pyiges.reader import read_as_mesh
6
7
 
7
8
  try:
8
- __version__ = version("pyminiply")
9
+ __version__ = version("pyiges")
9
10
  except PackageNotFoundError:
10
11
  __version__ = "unknown"
11
12
 
12
- __all__ = ["read", "Iges", "__version__"]
13
+ __all__ = ["read", "read_as_mesh", "Iges", "__version__"]
@@ -1,3 +1,5 @@
1
+ """Optional-dependency probes for the ``[full]`` install variant."""
2
+
1
3
  try:
2
4
  import geomdl
3
5
  import pyvista
@@ -17,6 +19,13 @@ except (ModuleNotFoundError, ImportError) as exc:
17
19
 
18
20
 
19
21
  def assert_full_module_variant(inner_func):
22
+ """Wrap a function to require the optional ``[full]`` install variant.
23
+
24
+ Raises an exception at call time if any of ``pyvista``, ``geomdl``,
25
+ or VTK could not be imported, instructing the user to install
26
+ ``pyiges[full]``.
27
+ """
28
+
20
29
  def safe_func(*a, **kw):
21
30
  if not _IS_FULL_MODULE:
22
31
  raise Exception(_PROBLEM_MSG)
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env python
1
+ """IGES protocol constants."""
2
2
 
3
3
  line_font_pattern = {
4
4
  None: "Default",
@@ -6,7 +6,7 @@ from pyiges.constants import line_font_pattern
6
6
 
7
7
 
8
8
  class Entity:
9
- """Generic IGES entity
9
+ """Generic IGES entity.
10
10
 
11
11
  Examples
12
12
  --------
@@ -35,11 +35,18 @@ class Entity:
35
35
  """
36
36
 
37
37
  def __init__(self, iges):
38
+ """Initialize an empty entity bound to its parent ``Iges`` reader."""
38
39
  self.d = dict()
39
40
  self.parameters = []
40
41
  self.iges = iges
41
42
 
42
43
  def add_section(self, string, key, type="int"):
44
+ """Parse one fixed-width directory-section field and store it under ``key``.
45
+
46
+ Handles the special-case ``status_number`` field, which is four
47
+ space-padded 2-digit values that must be normalised before
48
+ casting to ``int``.
49
+ """
43
50
  string = string.strip()
44
51
  if type == "string":
45
52
  self.d[key] = string
@@ -63,6 +70,7 @@ class Entity:
63
70
  self.d[key] = None
64
71
 
65
72
  def __str__(self):
73
+ """Return the multi-line directory-section dump used by ``print``."""
66
74
  s = "----- Entity -----" + os.linesep
67
75
  s += str(self.d["entity_type_number"]) + os.linesep
68
76
  s += str(self.d["parameter_pointer"]) + os.linesep
@@ -1,3 +1,5 @@
1
+ """Bundled example IGES files for documentation and tests."""
2
+
1
3
  import os
2
4
 
3
5
  filepath = os.path.dirname(__file__)
@@ -1,3 +1,5 @@
1
+ """IGES entity classes for points, curves, surfaces, and B-Rep elements."""
2
+
1
3
  import os
2
4
 
3
5
  import numpy as np
@@ -8,10 +10,11 @@ from pyiges.entity import Entity
8
10
 
9
11
 
10
12
  def parse_float(str_value):
11
- """
12
- This function converts a string to float just like the built-in
13
- float() function. In addition to "normal" numbers it also handles
14
- numbers such as 1.2D3 (equivalent to 1.2E3).
13
+ """Convert a string to ``float``, accepting Fortran ``D`` exponents.
14
+
15
+ In addition to "normal" numbers it also handles values such as
16
+ ``1.2D3`` (equivalent to ``1.2E3``) that appear in IGES files
17
+ written by Fortran-era CAD systems.
15
18
  """
16
19
  try:
17
20
  return float(str_value)
@@ -20,7 +23,7 @@ def parse_float(str_value):
20
23
 
21
24
 
22
25
  class Point(Entity):
23
- """IGES Point"""
26
+ """IGES Point."""
24
27
 
25
28
  def _add_parameters(self, parameters):
26
29
  self._x = parse_float(parameters[1])
@@ -29,35 +32,37 @@ class Point(Entity):
29
32
 
30
33
  @property
31
34
  def x(self):
32
- """X coordinate"""
35
+ """X coordinate."""
33
36
  return self._x
34
37
 
35
38
  @property
36
39
  def y(self):
37
- """Y coordinate"""
40
+ """Y coordinate."""
38
41
  return self._y
39
42
 
40
43
  @property
41
44
  def z(self):
42
- """Z coordinate"""
45
+ """Z coordinate."""
43
46
  return self._z
44
47
 
45
48
  @property
46
49
  def coordinate(self):
47
- """Coordinate of the point as a numpy array"""
50
+ """Coordinate of the point as a numpy array."""
48
51
  return np.array([self._x, self._y, self._z])
49
52
 
50
53
  def __repr__(self):
54
+ """Return a multi-line string with the point coordinates."""
51
55
  s = "--- IGES Point ---" + os.linesep
52
56
  s += f"{self._x}, {self._y}, {self._z} {os.linesep}"
53
57
  return s
54
58
 
55
59
  def __str__(self):
60
+ """Return the same multi-line representation as ``__repr__``."""
56
61
  return self.__repr__()
57
62
 
58
63
  @assert_full_module_variant
59
64
  def to_vtk(self):
60
- """Point represented as a ``pyvista.PolyData`` Mesh
65
+ """Return the point as a ``pyvista.PolyData`` mesh.
61
66
 
62
67
  Returns
63
68
  -------
@@ -68,7 +73,7 @@ class Point(Entity):
68
73
 
69
74
 
70
75
  class Line(Entity):
71
- """IGES Straight line segment"""
76
+ """IGES straight line segment."""
72
77
 
73
78
  def _add_parameters(self, parameters):
74
79
  self._x1 = parse_float(parameters[1])
@@ -80,10 +85,11 @@ class Line(Entity):
80
85
 
81
86
  @property
82
87
  def coordinates(self):
83
- """Starting and ending point of the line as a ``numpy`` array"""
88
+ """Starting and ending point of the line as a ``numpy`` array."""
84
89
  return np.array([[self._x1, self._y1, self._z1], [self._x2, self._y2, self._z2]])
85
90
 
86
91
  def __repr__(self):
92
+ """Return a multi-line string with the line endpoints."""
87
93
  s = "--- IGES Line ---" + os.linesep
88
94
  s += Entity.__str__(self) + os.linesep
89
95
  s += f"From point {self._x1}, {self._y1}, {self._z1} {os.linesep}"
@@ -92,19 +98,25 @@ class Line(Entity):
92
98
 
93
99
  @assert_full_module_variant
94
100
  def to_vtk(self, resolution=1):
95
- """Line represented as a ``pyvista.PolyData`` Mesh
101
+ """Return the line as a ``pyvista.PolyData`` mesh.
96
102
 
97
103
  Returns
98
104
  -------
99
105
  mesh : ``pyvista.PolyData``
100
106
  ``pyvista`` mesh
101
107
  """
102
- return pv.Line([self._x1, self._y1, self._z1], [self._x2, self._y2, self._z2], resolution)
108
+ return pv.Line(
109
+ [self._x1, self._y1, self._z1],
110
+ [self._x2, self._y2, self._z2],
111
+ resolution=resolution,
112
+ )
103
113
 
104
114
 
105
115
  class Transformation(Entity):
106
- """Transforms entities by matrix multiplication and vector
107
- addition to give a translation, as shown below:
116
+ """IGES Type 124 transformation matrix.
117
+
118
+ Transforms entities by matrix multiplication and vector addition
119
+ to give a translation, as shown below.
108
120
 
109
121
  Notes
110
122
  -----
@@ -117,7 +129,8 @@ class Transformation(Entity):
117
129
  """
118
130
 
119
131
  def _add_parameters(self, parameters):
120
- """
132
+ """Parse the twelve REAL coefficients of the 3x4 transform matrix.
133
+
121
134
  Index in list Type of data Name Description
122
135
  1 REAL R11 First row
123
136
  2 REAL R12 ..
@@ -142,12 +155,13 @@ class Transformation(Entity):
142
155
  self.t3 = parse_float(parameters[12])
143
156
 
144
157
  def __repr__(self):
158
+ """Return a multi-line string with the affine matrix."""
145
159
  txt = "IGES 124 Transformation Matrix\n"
146
160
  txt += str(self.to_affine())
147
161
  return txt
148
162
 
149
163
  def to_affine(self):
150
- """Return a 4x4 affline transformation matrix"""
164
+ """Return a 4x4 affine transformation matrix."""
151
165
  return np.array(
152
166
  [
153
167
  [self.r11, self.r12, self.r13, self.t1],
@@ -159,7 +173,7 @@ class Transformation(Entity):
159
173
 
160
174
  @assert_full_module_variant
161
175
  def _to_vtk(self):
162
- """Convert to a vtk transformation matrix"""
176
+ """Convert to a vtk transformation matrix."""
163
177
  vtkmatrix = pv.vtkmatrix_from_array(self.to_affine())
164
178
  import vtk
165
179
 
@@ -169,13 +183,12 @@ class Transformation(Entity):
169
183
 
170
184
 
171
185
  class ConicArc(Entity):
172
- """Conic Arc (Type 104)
173
- Arc defined by the equation:
174
- ``A*x**2 + B*x*y + C*y**2 + D*x + E*y + F = 0``
175
-
176
- with a Transformation Matrix (Entity 124). Can define
177
- an ellipse, parabola, or hyperbola.
186
+ """IGES Type 104 conic arc.
178
187
 
188
+ Arc defined by the equation
189
+ ``A*x**2 + B*x*y + C*y**2 + D*x + E*y + F = 0``
190
+ with a Transformation Matrix (Entity 124). Can define an ellipse,
191
+ parabola, or hyperbola.
179
192
  """
180
193
 
181
194
  # The definitions of the terms ellipse, parabola, and hyperbola
@@ -192,7 +205,8 @@ class ConicArc(Entity):
192
205
  # A parabola if Q2 = 0 and Q1 != 0.
193
206
 
194
207
  def _add_parameters(self, parameters):
195
- """
208
+ """Parse the six conic coefficients and two endpoints.
209
+
196
210
  Index Type Name Description
197
211
  1 REAL A coefficient of xt^2
198
212
  2 REAL B coefficient of xtyt
@@ -221,6 +235,7 @@ class ConicArc(Entity):
221
235
  self.z2 = parameters[12] # z coordinate of end point
222
236
 
223
237
  def __repr__(self):
238
+ """Return a multi-line string with the conic coefficients."""
224
239
  info = "Conic Arc\nIGES Type 104\n"
225
240
  info += f"Start: ({self.x1:f}, {self.y1:f}, {self.z1:f})\n"
226
241
  info += f"End: ({self.x2:f}, {self.y2:f}, {self.z2:f})\n"
@@ -234,6 +249,7 @@ class ConicArc(Entity):
234
249
 
235
250
  @assert_full_module_variant
236
251
  def to_vtk(self):
252
+ """Tessellate the conic arc as a ``pyvista.PolyData`` (not yet implemented)."""
237
253
  # a*x**2 + b*x*y + c*y**2 + d*x + e*y + f = 0
238
254
  # from sympy import Symbol
239
255
  # from sympy.solvers import Solve
@@ -254,9 +270,9 @@ class ConicArc(Entity):
254
270
 
255
271
 
256
272
  class RationalBSplineCurve(Entity):
257
- """Rational B-Spline Curve
258
- IGES Spec v5.3 p. 123 Section 4.23
259
- See also Appendix B, p. 545
273
+ """Rational B-Spline curve.
274
+
275
+ See IGES Spec v5.3 p. 123 Section 4.23, and Appendix B p. 545.
260
276
  """
261
277
 
262
278
  def _add_parameters(self, parameters):
@@ -304,6 +320,7 @@ class RationalBSplineCurve(Entity):
304
320
  self.planar_curve = False
305
321
 
306
322
  def __str__(self):
323
+ """Return a multi-line string with knots, weights, and control points."""
307
324
  s = "--- Rational B-Spline Curve ---" + os.linesep
308
325
  s += Entity.__str__(self) + os.linesep
309
326
  s += str(self.T) + os.linesep
@@ -316,6 +333,7 @@ class RationalBSplineCurve(Entity):
316
333
 
317
334
  @assert_full_module_variant
318
335
  def to_geomdl(self):
336
+ """Return a ``geomdl.NURBS.Curve`` built from this entity's parameters."""
319
337
  from geomdl import NURBS
320
338
 
321
339
  curve = NURBS.Curve()
@@ -327,7 +345,14 @@ class RationalBSplineCurve(Entity):
327
345
 
328
346
  @assert_full_module_variant
329
347
  def to_vtk(self, delta=0.01):
330
- """Set evaluation delta (controls the number of curve points)"""
348
+ """Tessellate the curve as a ``pyvista.PolyData`` polyline.
349
+
350
+ Parameters
351
+ ----------
352
+ delta : float, optional
353
+ Evaluation delta passed to ``geomdl``. Smaller values give
354
+ denser tessellations at the cost of compute time.
355
+ """
331
356
  # Create a 3-dimensional B-spline Curve
332
357
  curve = self.to_geomdl()
333
358
  curve.delta = delta
@@ -345,8 +370,7 @@ class RationalBSplineCurve(Entity):
345
370
 
346
371
 
347
372
  class RationalBSplineSurface(Entity):
348
- """Rational B-Spline Surface
349
-
373
+ """Rational B-Spline surface.
350
374
 
351
375
  Examples
352
376
  --------
@@ -395,37 +419,37 @@ class RationalBSplineSurface(Entity):
395
419
 
396
420
  @property
397
421
  def k1(self):
398
- """Upper index of first sum"""
422
+ """Upper index of first sum."""
399
423
  return self._k1
400
424
 
401
425
  @property
402
426
  def k2(self):
403
- """Upper index of second sum"""
427
+ """Upper index of second sum."""
404
428
  return self._k2
405
429
 
406
430
  @property
407
431
  def m1(self):
408
- """Degree of first basis functions"""
432
+ """Degree of first basis functions."""
409
433
  return self._m1
410
434
 
411
435
  @property
412
436
  def m2(self):
413
- """Degree of second basis functions"""
437
+ """Degree of second basis functions."""
414
438
  return self._m2
415
439
 
416
440
  @property
417
441
  def flag1(self):
418
- """Closed in the first direction"""
442
+ """Closed in the first direction."""
419
443
  return self._flag1
420
444
 
421
445
  @property
422
446
  def flag2(self):
423
- """Closed in the second direction"""
447
+ """Closed in the second direction."""
424
448
  return self._flag2
425
449
 
426
450
  @property
427
451
  def flag3(self):
428
- """Polynominal
452
+ """Polynomial flag.
429
453
 
430
454
  ``False`` - rational
431
455
  ``True`` - polynomial
@@ -434,51 +458,51 @@ class RationalBSplineSurface(Entity):
434
458
 
435
459
  @property
436
460
  def flag4(self):
437
- """First direction periodic"""
461
+ """First direction periodic."""
438
462
  return self._flag4
439
463
 
440
464
  @property
441
465
  def flag5(self):
442
- """Second direction Periodic"""
466
+ """Second direction periodic."""
443
467
  return self._flag5
444
468
 
445
469
  @property
446
470
  def knot1(self):
447
- """First Knot Sequences"""
471
+ """First knot sequence."""
448
472
  return self._knot1
449
473
 
450
474
  @property
451
475
  def knot2(self):
452
- """Second Knot Sequences"""
476
+ """Second knot sequence."""
453
477
  return self._knot2
454
478
 
455
479
  @property
456
480
  def weights(self):
457
- """First Knot Sequences"""
481
+ """Control-point weights."""
458
482
  return self._weights
459
483
 
460
484
  def control_points(self):
461
- """Control points"""
485
+ """Control points."""
462
486
  return self._cp
463
487
 
464
488
  @property
465
489
  def u0(self):
466
- """Start first parameter value"""
490
+ """Start first parameter value."""
467
491
  return self._u0
468
492
 
469
493
  @property
470
494
  def u1(self):
471
- """End first parameter value"""
495
+ """End first parameter value."""
472
496
  return self._u1
473
497
 
474
498
  @property
475
499
  def v0(self):
476
- """Start second parameter value"""
500
+ """Start second parameter value."""
477
501
  return self._v0
478
502
 
479
503
  @property
480
504
  def v1(self):
481
- """End second parameter value"""
505
+ """End second parameter value."""
482
506
  return self._v1
483
507
 
484
508
  def _add_parameters(self, input_parameters):
@@ -516,6 +540,7 @@ class RationalBSplineSurface(Entity):
516
540
  self._v1 = parameters[-0] # End second parameter value
517
541
 
518
542
  def __repr__(self):
543
+ """Return a multi-line summary of the surface parameters."""
519
544
  info = "Rational B-Spline Surface\n"
520
545
  info += " Upper index of first sum: %d\n" % self._k1
521
546
  info += " Upper index of second sum: %d\n" % self._k2
@@ -560,7 +585,7 @@ class RationalBSplineSurface(Entity):
560
585
 
561
586
  @assert_full_module_variant
562
587
  def to_geomdl(self):
563
- """Return a ``geommdl.BSpline.Surface``"""
588
+ """Return a ``geomdl.BSpline.Surface`` built from this entity's parameters."""
564
589
  from geomdl import BSpline
565
590
 
566
591
  surf = BSpline.Surface()
@@ -581,7 +606,7 @@ class RationalBSplineSurface(Entity):
581
606
 
582
607
  @assert_full_module_variant
583
608
  def to_vtk(self, delta=0.025):
584
- """Return a pyvista.PolyData Mesh
609
+ """Return a pyvista.PolyData mesh.
585
610
 
586
611
  Parameters
587
612
  ----------
@@ -614,11 +639,10 @@ class RationalBSplineSurface(Entity):
614
639
 
615
640
 
616
641
  class CircularArc(Entity):
617
- """Circular Arc
618
-
619
- Type 100: Simple circular arc of constant radius. Usually defined
620
- with a Transformation Matrix Entity (Type 124).
642
+ """IGES Type 100 circular arc.
621
643
 
644
+ Simple circular arc of constant radius. Usually defined with a
645
+ Transformation Matrix Entity (Type 124).
622
646
  """
623
647
 
624
648
  def _add_parameters(self, parameters):
@@ -641,7 +665,7 @@ class CircularArc(Entity):
641
665
 
642
666
  @assert_full_module_variant
643
667
  def to_vtk(self, resolution=20):
644
- """Circular arc represented as a ``pyvista.PolyData`` Mesh
668
+ """Return the circular arc as a ``pyvista.PolyData`` mesh.
645
669
 
646
670
  Returns
647
671
  -------
@@ -660,10 +684,12 @@ class CircularArc(Entity):
660
684
 
661
685
  @property
662
686
  def transform(self):
687
+ """Return the referenced :class:`Transformation` entity, if any."""
663
688
  if self._transform is not None:
664
689
  return self.iges[self._transform]
665
690
 
666
691
  def __repr__(self):
692
+ """Return a multi-line string with the arc's center and endpoints."""
667
693
  info = "Circular Arc\nIGES Type 100\n"
668
694
  info += f"Center: ({self.x:f}, {self.y:f})\n"
669
695
  info += f"Start: ({self.x1:f}, {self.y1:f})\n"
@@ -673,12 +699,15 @@ class CircularArc(Entity):
673
699
 
674
700
 
675
701
  class Face(Entity):
676
- """Defines a bound portion of three dimensional space (R^3) which
677
- has a finite area. Used to construct B-Rep Geometries."""
702
+ """IGES Type 510 face.
703
+
704
+ Defines a bound portion of three-dimensional space (R^3) which has
705
+ a finite area. Used to construct B-Rep geometries.
706
+ """
678
707
 
679
708
  def _add_parameters(self, parameters):
680
- """
681
- Parameter Data
709
+ """Parse the surface pointer, outer-loop flag, and per-loop pointers.
710
+
682
711
  Index Type Name Description
683
712
  Pointer Surface Underlying surface
684
713
  2 INT N Number of loops
@@ -698,6 +727,7 @@ class Face(Entity):
698
727
 
699
728
  @property
700
729
  def loops(self):
730
+ """Resolve the face's loop pointers into a list of :class:`Loop` entities."""
701
731
  loops = []
702
732
  for ptr in self.loop_pointers:
703
733
  loops.append(self.iges.from_pointer(ptr))
@@ -705,6 +735,7 @@ class Face(Entity):
705
735
  return loops
706
736
 
707
737
  def __repr__(self):
738
+ """Return a short identifier string for the face."""
708
739
  info = "IGES Type 510: Face\n"
709
740
  # info += 'Center: (%f, %f)\n' % (self.x, self.y)
710
741
  # info += 'Start: (%f, %f)\n' % (self.x1, self.y1)
@@ -714,11 +745,14 @@ class Face(Entity):
714
745
 
715
746
 
716
747
  class Loop(Entity):
717
- """Defines a loop, specifying a bounded face, for B-Rep
718
- geometries."""
748
+ """IGES Type 508 loop.
749
+
750
+ Defines a loop, specifying a bounded face, for B-Rep geometries.
751
+ """
719
752
 
720
753
  def _add_parameters(self, parameters):
721
- """Parameter Data
754
+ """Parse the loop's per-edge type, vertex/edge pointers, and curves.
755
+
722
756
  Index Type Name Description
723
757
  1 INT N N Edges in loop
724
758
  2 INT Type1 Type of Edge 1
@@ -766,22 +800,27 @@ class Loop(Entity):
766
800
  # for
767
801
 
768
802
  def curves(self):
769
- """list of curves"""
803
+ """Return the list of curves bounding the loop (not yet implemented)."""
770
804
  pass
771
805
 
772
806
  def __repr__(self):
807
+ """Return a short identifier string for the loop."""
773
808
  info = "IGES Type 508: Loop\n"
774
809
  return info
775
810
 
776
811
 
777
812
  class EdgeList(Entity):
778
- """Provides a list of edges, comprised of vertices, for specifying
779
- B-Rep Geometries."""
813
+ """IGES Type 504 edge list.
814
+
815
+ Provides a list of edges, comprised of vertices, for specifying
816
+ B-Rep geometries.
817
+ """
780
818
 
781
819
  _iges_type = 504
782
820
 
783
821
  def _add_parameters(self, parameters):
784
- """
822
+ """Parse the edge count and per-edge curve/vertex pointer tuples.
823
+
785
824
  Parameter Data
786
825
  Index in list Type of data Name Description
787
826
  INT N Number of Edges in list
@@ -819,11 +858,13 @@ class EdgeList(Entity):
819
858
  # for
820
859
 
821
860
  def __getitem__(self, indices):
861
+ """Resolve the model-space curve for the edge at ``indices``."""
822
862
  # TODO: limit spline based on start and end point
823
863
  ptr = self.edges[indices]["curve1"]
824
864
  return self.iges.from_pointer(ptr)
825
865
 
826
866
  def __len__(self):
867
+ """Return the number of edges in the list."""
827
868
  return len(self.edges)
828
869
 
829
870
  def __repr__(self):
@@ -832,12 +873,12 @@ class EdgeList(Entity):
832
873
 
833
874
 
834
875
  class VertexList(Entity):
835
- """Vertex List (Type 502 Form 1)"""
876
+ """IGES Type 502 Form 1 vertex list."""
836
877
 
837
878
  _iges_type = 502
838
879
 
839
880
  def _add_parameters(self, parameters):
840
- """Adds Parameter Data.
881
+ """Add parameter data.
841
882
 
842
883
  Index in list Type of data Name Description
843
884
  INT N Number of vertices in list
@@ -1,3 +1,5 @@
1
+ """IGES file reader and the top-level :class:`Iges` container."""
2
+
1
3
  from tqdm import tqdm
2
4
 
3
5
  from pyiges import geometry
@@ -6,7 +8,7 @@ from pyiges.entity import Entity
6
8
 
7
9
 
8
10
  class Iges:
9
- """pyiges.Iges object
11
+ """In-memory representation of a parsed IGES file.
10
12
 
11
13
  Parameters
12
14
  ----------
@@ -24,11 +26,12 @@ class Iges:
24
26
  """
25
27
 
26
28
  def __init__(self, filename):
29
+ """Read ``filename`` and populate the entity list."""
27
30
  self._read(filename)
28
31
  self._desc = ""
29
32
 
30
33
  def entities(self):
31
- """Return a list of all entities
34
+ """Return a list of all entities.
32
35
 
33
36
  Examples
34
37
  --------
@@ -51,7 +54,7 @@ class Iges:
51
54
  merge=True,
52
55
  progress=tqdm,
53
56
  ):
54
- """Converts entities to a vtk object
57
+ """Convert entities to a vtk object.
55
58
 
56
59
  Parameters
57
60
  ----------
@@ -124,27 +127,27 @@ class Iges:
124
127
  return items
125
128
 
126
129
  def points(self, as_vtk=False, merge=False, **kwargs):
127
- """Return all points"""
130
+ """Return all points."""
128
131
  return self._return_type(geometry.Point, as_vtk, merge, **kwargs)
129
132
 
130
133
  def edge_lists(self, as_vtk=False, merge=False, **kwargs):
131
- """All Edge Lists"""
134
+ """Return all edge lists."""
132
135
  return self._return_type(geometry.EdgeList, as_vtk, merge, **kwargs)
133
136
 
134
137
  def vertex_lists(self, as_vtk=False, merge=False, **kwargs):
135
- """All Point Lists"""
138
+ """Return all point lists."""
136
139
  return self._return_type(geometry.VertexList, as_vtk, merge, **kwargs)
137
140
 
138
141
  def lines(self, as_vtk=False, merge=False, **kwargs):
139
- """All lines"""
142
+ """Return all lines."""
140
143
  return self._return_type(geometry.Line, as_vtk, merge, **kwargs)
141
144
 
142
145
  def bsplines(self, as_vtk=False, merge=False, **kwargs):
143
- """All bsplines"""
146
+ """Return all bsplines."""
144
147
  return self._return_type(geometry.RationalBSplineCurve, as_vtk, merge, **kwargs)
145
148
 
146
149
  def bspline_surfaces(self, as_vtk=False, merge=False, **kwargs):
147
- """All bsplines
150
+ """Return all bspline surfaces.
148
151
 
149
152
  Examples
150
153
  --------
@@ -182,20 +185,23 @@ class Iges:
182
185
  return self._return_type(geometry.RationalBSplineSurface, as_vtk, merge, **kwargs)
183
186
 
184
187
  def circular_arcs(self, to_vtk=False, merge=False, **kwargs):
185
- """All circular_arcs"""
188
+ """Return all circular arcs."""
186
189
  return self._return_type(geometry.CircularArc, to_vtk, merge, **kwargs)
187
190
 
188
191
  def conic_arcs(self, as_vtk=False, merge=False, **kwargs):
192
+ """Return all conic arcs."""
189
193
  return self._return_type(geometry.ConicArc, as_vtk, merge, **kwargs)
190
194
 
191
195
  def faces(self, as_vtk=False, merge=False, **kwargs):
196
+ """Return all B-Rep faces."""
192
197
  return self._return_type(geometry.Face, as_vtk, merge, **kwargs)
193
198
 
194
199
  def loops(self, as_vtk=False, merge=False, **kwargs):
200
+ """Return all B-Rep loops."""
195
201
  return self._return_type(geometry.Loop, as_vtk, merge, **kwargs)
196
202
 
197
203
  def _return_type(self, iges_type, to_vtk=False, merge=False, **kwargs):
198
- """Return an iges type"""
204
+ """Return entities matching ``iges_type``, optionally tessellated and merged."""
199
205
  items = []
200
206
  for entity in self:
201
207
  if isinstance(entity, iges_type):
@@ -216,19 +222,22 @@ class Iges:
216
222
  return items
217
223
 
218
224
  def __iter__(self):
225
+ """Iterate over the contained entities."""
219
226
  yield from self._entities
220
227
 
221
228
  def __len__(self):
229
+ """Return the number of contained entities."""
222
230
  return len(self._entities)
223
231
 
224
232
  def __repr__(self):
233
+ """Return a short summary string with the entity count."""
225
234
  info = "pyiges.Iges object\n"
226
235
  info += "Description: %s\n" % self._desc
227
236
  info += "Number of Entities: %d" % len(self)
228
237
  return info
229
238
 
230
239
  def from_pointer(self, ptr):
231
- """Return an iges object according to an iges pointer"""
240
+ """Return the entity addressed by an IGES pointer."""
232
241
  return self[self._pointers[ptr]]
233
242
 
234
243
  @staticmethod
@@ -405,12 +414,12 @@ class Iges:
405
414
  self._pointers = pointer_dict
406
415
 
407
416
  def __getitem__(self, index):
408
- """Get an item by its pointer"""
417
+ """Get an item by its pointer."""
409
418
  return self._entities[self._pointers[index]]
410
419
 
411
420
  @property
412
421
  def items(self):
413
- """IGES items
422
+ """Return the list of contained IGES entities.
414
423
 
415
424
  Examples
416
425
  --------
@@ -428,7 +437,6 @@ class Iges:
428
437
  def read(filename):
429
438
  """Read an iges file.
430
439
 
431
-
432
440
  Parameters
433
441
  ----------
434
442
  filename : str
@@ -0,0 +1,49 @@
1
+ """PyVista reader-registry integration for IGES files."""
2
+
3
+ import os
4
+
5
+ try:
6
+ # On pyvista >= 0.48, raising ``LocalFileRequiredError`` from a
7
+ # reader entry point makes ``pv.read("http://.../foo.igs")``
8
+ # download the file first and retry against the local copy.
9
+ from pyvista import LocalFileRequiredError as _LocalFileRequiredError
10
+ from pyvista import has_scheme as _has_scheme
11
+ except ImportError: # pragma: no cover - older pyvista or no pyvista installed
12
+ _LocalFileRequiredError = None
13
+ _has_scheme = None
14
+
15
+ from pyiges.iges import Iges
16
+
17
+
18
+ def read_as_mesh(filename, merge=True):
19
+ """Read an IGES file and return it as a PyVista mesh.
20
+
21
+ Wraps :class:`pyiges.Iges` and converts all supported entities to
22
+ a PyVista object via :meth:`pyiges.Iges.to_vtk`. Suitable for use
23
+ as a PyVista reader-registry entry point.
24
+
25
+ Parameters
26
+ ----------
27
+ filename : str | os.PathLike
28
+ Path to the IGES file.
29
+ merge : bool, default: True
30
+ If ``True``, return a single :class:`pyvista.PolyData`
31
+ containing all converted entities. If ``False``, return a
32
+ :class:`pyvista.MultiBlock`.
33
+
34
+ Returns
35
+ -------
36
+ pyvista.PolyData or pyvista.MultiBlock
37
+ The converted geometry.
38
+
39
+ Raises
40
+ ------
41
+ pyvista.LocalFileRequiredError
42
+ If a remote URI is passed and ``pyvista >= 0.48`` is installed.
43
+ The PyVista reader registry uses this to download the file and
44
+ retry against the local copy.
45
+ """
46
+ fname = os.fspath(filename)
47
+ if _has_scheme is not None and _has_scheme(fname):
48
+ raise _LocalFileRequiredError
49
+ return Iges(fname).to_vtk(merge=merge)
@@ -1,19 +0,0 @@
1
- """
2
- Face (Type 510)
3
- Defines a bound portion of three dimensional space (R^3) which has a
4
- finite area. Used to construct B-Rep Geometries.
5
-
6
- Parameter Data
7
- Index in list Type of data Name Description
8
- Pointer Surface Underlying surface
9
- 2 INT N Number of loops
10
- 3 BOOL Flag Outer loop flag:
11
- True indicates Loop1 is outer loop.
12
- False indicates no outer loop.
13
- 4 Pointer Loop1 Pointer to first loop of the face
14
- .
15
- . .
16
- . .
17
- .
18
- 3+N Pointer LoopN Pointer to last loop of the face
19
- """
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