ocp-vscode 2.2.2__tar.gz → 2.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 (23) hide show
  1. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/PKG-INFO +6 -1
  2. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/README.md +20 -0
  3. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode/__init__.py +19 -1
  4. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode/comms.py +17 -6
  5. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode/config.py +15 -1
  6. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode/show.py +71 -80
  7. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode.egg-info/PKG-INFO +7 -2
  8. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode.egg-info/SOURCES.txt +0 -1
  9. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode.egg-info/requires.txt +1 -1
  10. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/setup.cfg +1 -1
  11. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/setup.py +2 -2
  12. ocp_vscode-2.2.2/test/test_serialisation.py +0 -566
  13. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/LICENSE +0 -0
  14. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode/animation.py +0 -0
  15. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode/backend.py +0 -0
  16. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode/build123d.py +0 -0
  17. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode/colors.py +0 -0
  18. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode/state.py +0 -0
  19. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode.egg-info/dependency_links.txt +0 -0
  20. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode.egg-info/not-zip-safe +0 -0
  21. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/ocp_vscode.egg-info/top_level.txt +0 -0
  22. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/test/test_for_backend.py +0 -0
  23. {ocp_vscode-2.2.2 → ocp_vscode-2.3.0}/test/testextension.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ocp_vscode
3
- Version: 2.2.2
3
+ Version: 2.3.0
4
4
  Summary: OCP CAD Viewer for VSCode
5
5
  Home-page: https://github.com/bernhard-42/vscode-ocp-cad-viewer
6
6
  Author: Bernhard Walter
@@ -17,5 +17,10 @@ Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.11
18
18
  Requires-Python: >=3.9
19
19
  License-File: LICENSE
20
+ Requires-Dist: ocp-tessellate<2.4.0,>=2.3.0
21
+ Requires-Dist: requests
22
+ Requires-Dist: ipykernel
23
+ Requires-Dist: orjson
24
+ Requires-Dist: websockets<11.1,>=11.0
20
25
 
21
26
  An extension to show OCP cad CAD objects (CadQuery, build123d) in VS Code via threejs
@@ -185,8 +185,28 @@ You can also use "Library Manager" in the _OCP CAD Viewer_ sidebar to manage the
185
185
  - `reset_camera=Camera.KEEP` will keep position, rotation and panning. However, panning can be problematic. When the next object to be shown is much larger or smaller and the object before was panned, it can happen that nothing is visible (the new object at the pan location is outside of the viewer frustum). OCP CAD Viewer checks whether the bounding box of an object is 2x smaller or larger than the one of the last shown object. If so, it falls back to `Camera.CENTER`. A notification is written to the OCP CAD Viewer output panel.
186
186
  - `reset_camera=Camera.RESET` will ensure that position, rotation and panning will be reset to the initial default
187
187
 
188
+ ## Development
189
+
190
+ Testing:
191
+
192
+ Native tessellator can be set via `NATIVE_TESSELLATOR=1`and Python tessellator via `NATIVE_TESSELLATOR=0`.
193
+
194
+ When `OCP_VSCODE_PYTEST=1` is set, `show` will not send the tessellated results to the viewer, but return it to the caller for inspection.
195
+
196
+ A full test cycle consist of:
197
+
198
+ ```bash
199
+ NATIVE_TESSELLATOR=0 OCP_VSCODE_PYTEST=1 pytest -v -s pytests/
200
+ NATIVE_TESSELLATOR=1 OCP_VSCODE_PYTEST=1 pytest -v -s pytests/
201
+ ```
202
+
188
203
  ## Changes
189
204
 
205
+ v2.3.0
206
+ - Add newest ocp-tessellate to allow using native tessellator from ocp_addons
207
+ - Fine tune communication to ensure the memory view of buffers will be passed through to javascript for performance
208
+ - Use of the new protocol v3 of three-cad-viewer
209
+
190
210
  v2.2.2
191
211
  - Fix regression in measure tools
192
212
 
@@ -15,7 +15,7 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
  #
18
- __version__ = "2.2.2"
18
+ __version__ = "2.3.0"
19
19
 
20
20
  from .show import *
21
21
  from .config import *
@@ -24,3 +24,21 @@ from .comms import *
24
24
  from .colors import *
25
25
  from .animation import Animation
26
26
  from ocp_tessellate.cad_objects import ImageFace
27
+
28
+ try:
29
+ from ocp_tessellate.tessellator import (
30
+ enable_native_tessellator,
31
+ disable_native_tessellator,
32
+ is_native_tessellator_enabled,
33
+ )
34
+
35
+ if is_native_tessellator_enabled():
36
+ print(
37
+ "Enabled native tessellator, to disable, call `disable_native_tessellator()`\n"
38
+ )
39
+ else:
40
+ print(
41
+ "Found native tessellator, to ansable, call `enable_native_tessellator()`\n"
42
+ )
43
+ except:
44
+ pass
@@ -20,6 +20,7 @@ from ocp_tessellate.ocp_utils import (
20
20
  )
21
21
  from .state import get_state, update_state, get_config_file
22
22
 
23
+
23
24
  # pylint: disable=unused-import
24
25
  try:
25
26
  from IPython import get_ipython
@@ -34,6 +35,7 @@ CMD_PORT = 3939
34
35
 
35
36
  INIT_DONE = False
36
37
 
38
+
37
39
  #
38
40
  # Send data to the viewer
39
41
  #
@@ -58,9 +60,14 @@ __all__ = [
58
60
  "set_port",
59
61
  "get_port",
60
62
  "listener",
63
+ "is_pytest",
61
64
  ]
62
65
 
63
66
 
67
+ def is_pytest():
68
+ return os.environ.get("OCP_VSCODE_PYTEST") == "1"
69
+
70
+
64
71
  def port_check(port):
65
72
  """Check whether the port is listening"""
66
73
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -85,6 +92,9 @@ def default(obj):
85
92
 
86
93
  def get_port():
87
94
  """Get the port"""
95
+ if is_pytest():
96
+ return 3939
97
+
88
98
  if not INIT_DONE:
89
99
  find_and_set_port()
90
100
  set_connection_file()
@@ -131,12 +141,13 @@ def _send(data, message_type, port=None, timeit=False):
131
141
  result = json.loads(ws.recv())
132
142
  except Exception as ex: # pylint: disable=broad-except
133
143
  print(ex)
134
- try:
135
- ws.close()
136
- except: # pylint: disable=bare-except
137
- pass
138
144
 
139
- return result
145
+ # try:
146
+ # ws.close()
147
+ # except Exception as ex: # pylint: disable=bare-except
148
+ # pass
149
+
150
+ return result
140
151
 
141
152
  except Exception as ex: # pylint: disable=broad-except
142
153
  print(
@@ -278,4 +289,4 @@ def set_connection_file():
278
289
  elif not JCONSOLE:
279
290
  print("Jupyter console not installed")
280
291
  else:
281
- print("Jupyter kernel not running")
292
+ print("Jupyter kernel not running")
@@ -18,7 +18,7 @@
18
18
 
19
19
  from enum import Enum
20
20
 
21
- from .comms import send_command, send_config, get_port
21
+ from .comms import send_command, send_config, get_port, is_pytest
22
22
 
23
23
  __all__ = [
24
24
  "workspace_config",
@@ -401,6 +401,10 @@ def ui_filter(conf):
401
401
 
402
402
  def status(port=None, debug=False):
403
403
  """Get viewer status"""
404
+
405
+ if is_pytest():
406
+ return {}
407
+
404
408
  if port is None:
405
409
  port = get_port()
406
410
  try:
@@ -418,6 +422,16 @@ def status(port=None, debug=False):
418
422
 
419
423
  def workspace_config(port=None):
420
424
  """Get viewer workspace config"""
425
+
426
+ if is_pytest():
427
+ return {
428
+ "measure_tools": False,
429
+ "_splash": False,
430
+ "default_facecolor": (1, 234, 56),
431
+ "default_thickedgecolor": (123, 45, 6),
432
+ "default_vertexcolor": (123, 45, 6),
433
+ }
434
+
421
435
  if port is None:
422
436
  port = get_port()
423
437
  try:
@@ -16,7 +16,9 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
+ import os
19
20
  import re
21
+ import types
20
22
 
21
23
  from ocp_tessellate import PartGroup
22
24
  from ocp_tessellate.convert import (
@@ -50,7 +52,7 @@ from ocp_tessellate.cad_objects import (
50
52
  )
51
53
  import ocp_tessellate.convert as oc
52
54
 
53
- from .config import (
55
+ from ocp_vscode.config import (
54
56
  preset,
55
57
  get_changed_config,
56
58
  workspace_config,
@@ -61,8 +63,8 @@ from .config import (
61
63
  Collapse,
62
64
  check_deprecated,
63
65
  )
64
- from .comms import send_backend, send_data
65
- from .colors import get_colormap, web_to_rgb, BaseColorMap
66
+ from ocp_vscode.comms import send_backend, send_data, is_pytest
67
+ from ocp_vscode.colors import get_colormap, web_to_rgb, BaseColorMap
66
68
 
67
69
  __all__ = ["show", "show_object", "reset_show", "show_all", "show_clear"]
68
70
 
@@ -140,7 +142,7 @@ def _tessellate(
140
142
 
141
143
  with Timer(timeit, "", "to_assembly", 1):
142
144
  changed_config = get_changed_config()
143
- part_group = to_assembly(
145
+ part_group, instances = to_assembly(
144
146
  *cad_objs,
145
147
  names=names,
146
148
  colors=colors,
@@ -216,7 +218,7 @@ def _tessellate(
216
218
  keymap.reset()
217
219
 
218
220
  instances, shapes, states, mapping = tessellate_group(
219
- part_group, params, progress, params.get("timeit")
221
+ part_group, instances, params, progress, params.get("timeit")
220
222
  )
221
223
 
222
224
  if parallel:
@@ -230,7 +232,13 @@ def _tessellate(
230
232
  )
231
233
 
232
234
  with Timer(timeit, "", "bb", 1):
233
- bb = combined_bb(shapes).to_dict()
235
+ bb = combined_bb(shapes)
236
+ if bb is None:
237
+ bb = dict(
238
+ xmin=-1e-6, ymin=-1e-6, zmin=-1e-6, xmax=1e-6, ymax=1e-6, zmax=1e-6
239
+ )
240
+ else:
241
+ bb = bb.to_dict()
234
242
 
235
243
  # add global bounding box
236
244
  shapes["bb"] = bb
@@ -272,14 +280,18 @@ def _convert(
272
280
  config["explode"] = kwargs["explode"]
273
281
 
274
282
  with Timer(timeit, "", "create data obj", 1):
283
+ if is_pytest():
284
+ return (instances, shapes, states, config, count_shapes), mapping
285
+
275
286
  return {
276
287
  "data": numpy_to_buffer_json(
277
- dict(instances=instances, shapes=shapes, states=states)
288
+ dict(instances=instances, shapes=shapes, states=states),
278
289
  ),
279
290
  "type": "data",
280
291
  "config": config,
281
292
  "count": count_shapes,
282
293
  }, mapping
294
+ return result
283
295
 
284
296
 
285
297
  class Progress:
@@ -287,7 +299,7 @@ class Progress:
287
299
 
288
300
  def __init__(self, levels=None):
289
301
  if levels is None:
290
- self.levels = ["+", "c", "-"]
302
+ self.levels = ["+c-*"]
291
303
  else:
292
304
  self.levels = levels
293
305
 
@@ -318,7 +330,7 @@ def show(
318
330
  colors=None,
319
331
  alphas=None,
320
332
  port=None,
321
- progress="-+c",
333
+ progress="-+*c",
322
334
  glass=None,
323
335
  tools=None,
324
336
  measure_tools=None,
@@ -388,8 +400,11 @@ def show(
388
400
  colors: List of colors for the cad_objs. Needs to have the same length as cad_objs
389
401
  alphas: List of alpha values for the cad_objs. Needs to have the same length as cad_objs
390
402
  port: The port the viewer listens to. Typically use 'set_port(port)' instead
391
- progress: Show progress of tessellation with None is no progress indicator. (default="-+c")
392
- for object: "-": is reference, "+": gets tessellated, "c": from cache
403
+ progress: Show progress of tessellation with None is no progress indicator. (default="-+*c")
404
+ for object: "-": is reference,
405
+ "+": gets tessellated with Python code,
406
+ "*": gets tessellated with native code,
407
+ "c": from cache
393
408
 
394
409
  Valid keywords to configure the viewer (**kwargs):
395
410
  - UI
@@ -552,6 +567,9 @@ def show(
552
567
  else:
553
568
  LAST_CALL = "other"
554
569
 
570
+ if is_pytest():
571
+ return t, mapping
572
+
555
573
  with Timer(timeit, "", "send"):
556
574
  send_data(t, port=port, timeit=timeit)
557
575
 
@@ -574,7 +592,7 @@ def show_object(
574
592
  parent=None,
575
593
  clear=False,
576
594
  port=None,
577
- progress="-+c",
595
+ progress="-+*c",
578
596
  glass=None,
579
597
  tools=None,
580
598
  measure_tools=None,
@@ -646,8 +664,12 @@ def show_object(
646
664
  clear: In interactice mode, clear the stack of objects to be shown
647
665
  (typically used for the first object)
648
666
  port: The port the viewer listens to. Typically use 'set_port(port)' instead
649
- progress: Show progress of tessellation with None is no progress indicator. (default="-+c")
650
- for object: "-": is reference, "+": gets tessellated, "c": from cache
667
+ progress: Show progress of tessellation with None is no progress indicator. (default="-+*c")
668
+ for object: "-": is reference,
669
+ "+": gets tessellated with Python code,
670
+ "*": gets tessellated with native code,
671
+ "c": from cache
672
+
651
673
 
652
674
  Valid keywords to configure the viewer (**kwargs):
653
675
  - UI
@@ -778,44 +800,13 @@ def show_clear():
778
800
  send_data(data)
779
801
 
780
802
 
781
- def ocp_group(obj, name):
782
-
783
- def to_group(obj, name, group):
784
- if isinstance(obj, list):
785
- sub_group = OCP_PartGroup([], name=name)
786
- for i, el in enumerate(obj):
787
- new_obj = to_group(el, f"{name}[{i}]", sub_group)
788
- if new_obj is not None:
789
- sub_group.add(new_obj)
790
- group.add(sub_group)
791
- elif isinstance(obj, dict):
792
- sub_group = OCP_PartGroup([], name=name)
793
- for name, el in obj.items():
794
- new_obj = to_group(el, name, sub_group)
795
- if new_obj is not None:
796
- sub_group.add(new_obj)
797
- group.add(sub_group)
798
- else:
799
- if (
800
- (is_wrapped(obj) and not obj.__class__.__name__ == "Color")
801
- or is_build123d(obj)
802
- or is_cadquery(obj)
803
- ):
804
- new_obj = conv(obj)
805
- new_obj.name = name
806
- group.add(new_obj)
807
- else:
808
- ...
809
- # print(
810
- # f"show_all: Type {type(obj)} for name {name} cannot be visualized"
811
- # )
812
-
813
- group = OCP_PartGroup([], name=name)
814
- to_group(obj, name, group)
815
- return group.objects[0]
816
-
817
-
818
- def show_all(variables=None, exclude=None, classes=None, _visual_debug=False, **kwargs):
803
+ def show_all(
804
+ variables=None,
805
+ exclude=None,
806
+ classes=None,
807
+ _visual_debug=False,
808
+ **kwargs,
809
+ ):
819
810
  """Show all variables in the current scope"""
820
811
  import inspect # pylint: disable=import-outside-toplevel
821
812
 
@@ -840,22 +831,23 @@ def show_all(variables=None, exclude=None, classes=None, _visual_debug=False, **
840
831
  names = []
841
832
  for name, obj in variables.items():
842
833
  if (
834
+ # ignore classes and ipython and jupyter variables
843
835
  isinstance(obj, type)
844
- or name in ["_", "__", "___"]
836
+ or name in exclude + ["_", "__", "___", "_ih", "_oh", "_dh", "Out", "In"]
845
837
  or name.startswith("__")
846
838
  or re.search("_\\d+", name) is not None
839
+ # pylint: disable=protected-access
840
+ or (hasattr(obj, "_obj") and obj._obj is None)
841
+ or callable(obj)
842
+ or isinstance(obj, (int, float, str, bool, types.ModuleType))
847
843
  ):
848
- continue # ignore classes and jupyter variables
844
+ continue
845
+
849
846
  if hasattr(obj, "area") and obj.area > 1e99: # inifinite face
850
847
  print(f"infinite face {name} skipped")
851
848
  continue
852
849
 
853
- if name not in exclude and (classes is None or isinstance(obj, tuple(classes))):
854
- if (
855
- hasattr(obj, "_obj")
856
- and obj._obj is None # pylint: disable=protected-access
857
- ):
858
- continue
850
+ if classes is None or isinstance(obj, tuple(classes)):
859
851
 
860
852
  if hasattr(obj, "locations") and hasattr(obj, "local_locations"):
861
853
  obj = obj.locations
@@ -881,6 +873,7 @@ def show_all(variables=None, exclude=None, classes=None, _visual_debug=False, **
881
873
  and hasattr(obj, "position")
882
874
  and hasattr(obj, "direction")
883
875
  )
876
+ or isinstance(obj, (list, tuple, dict))
884
877
  ):
885
878
  objects.append(obj)
886
879
  names.append(name)
@@ -898,27 +891,25 @@ def show_all(variables=None, exclude=None, classes=None, _visual_debug=False, **
898
891
  objects.append(pg)
899
892
  names.append(name)
900
893
 
901
- elif isinstance(obj, (list, tuple, dict)):
902
- if not name in [
903
- "_ih",
904
- "_oh",
905
- "_dh",
906
- "Out",
907
- "In",
908
- ]: # no IPython dicts and lists
909
- obj = ocp_group(obj, name)
910
- if len(obj.objects) > 0:
911
- objects.append(obj)
912
- obj.name = name
913
- names.append(name)
894
+ else:
895
+ print(
896
+ f"show_all: Type {type(obj)} for name {name} cannot be visualized"
897
+ )
914
898
 
915
899
  if len(objects) > 0:
916
- show(
917
- *objects,
918
- names=names,
919
- collapse=Collapse.ROOT,
920
- _force_in_debug=_visual_debug,
921
- **kwargs,
922
- )
900
+ try:
901
+ result = show(
902
+ *objects,
903
+ names=names,
904
+ collapse=Collapse.ROOT,
905
+ _force_in_debug=_visual_debug,
906
+ **kwargs,
907
+ )
908
+ if is_pytest():
909
+ return result
910
+ except Exception as ex: # pylint: disable=broad-exception-caught
911
+ print("show_all:", ex)
923
912
  else:
913
+ if is_pytest():
914
+ return None
924
915
  show_clear()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
- Name: ocp-vscode
3
- Version: 2.2.2
2
+ Name: ocp_vscode
3
+ Version: 2.3.0
4
4
  Summary: OCP CAD Viewer for VSCode
5
5
  Home-page: https://github.com/bernhard-42/vscode-ocp-cad-viewer
6
6
  Author: Bernhard Walter
@@ -17,5 +17,10 @@ Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.11
18
18
  Requires-Python: >=3.9
19
19
  License-File: LICENSE
20
+ Requires-Dist: ocp-tessellate<2.4.0,>=2.3.0
21
+ Requires-Dist: requests
22
+ Requires-Dist: ipykernel
23
+ Requires-Dist: orjson
24
+ Requires-Dist: websockets<11.1,>=11.0
20
25
 
21
26
  An extension to show OCP cad CAD objects (CadQuery, build123d) in VS Code via threejs
@@ -18,5 +18,4 @@ ocp_vscode.egg-info/not-zip-safe
18
18
  ocp_vscode.egg-info/requires.txt
19
19
  ocp_vscode.egg-info/top_level.txt
20
20
  test/test_for_backend.py
21
- test/test_serialisation.py
22
21
  test/testextension.py
@@ -1,4 +1,4 @@
1
- ocp-tessellate<2.3.0,>=2.2.2
1
+ ocp-tessellate<2.4.0,>=2.3.0
2
2
  requests
3
3
  ipykernel
4
4
  orjson
@@ -1,5 +1,5 @@
1
1
  [bumpversion]
2
- current_version = 2.2.2
2
+ current_version = 2.3.0
3
3
  commit = False
4
4
  tag = False
5
5
  parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?P<release>\D*)(?P<build>\d*)
@@ -2,13 +2,13 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup_args = {
4
4
  "name": "ocp_vscode",
5
- "version": "2.2.2",
5
+ "version": "2.3.0",
6
6
  "description": "OCP CAD Viewer for VSCode",
7
7
  "long_description": "An extension to show OCP cad CAD objects (CadQuery, build123d) in VS Code via threejs",
8
8
  "include_package_data": True,
9
9
  "python_requires": ">=3.9",
10
10
  "install_requires": [
11
- "ocp-tessellate>=2.2.2,<2.3.0",
11
+ "ocp-tessellate>=2.3.0,<2.4.0",
12
12
  "requests",
13
13
  "ipykernel",
14
14
  "orjson",
@@ -1,566 +0,0 @@
1
- # pylint: disable=missing-class-docstring,missing-function-docstring
2
-
3
- import unittest
4
- import pytest
5
- import json
6
- import math
7
- from OCP.BRepPrimAPI import BRepPrimAPI_MakeBox
8
- from OCP.BRepFilletAPI import BRepFilletAPI_MakeFillet
9
- from OCP.gp import gp_Pnt, gp_Vec, gp_Dir
10
- from ocp_vscode.show import _convert
11
- from ocp_vscode.backend import ViewerBackend
12
- from ocp_vscode.comms import default
13
- from ocp_vscode.build123d import *
14
- from ocp_tessellate.ocp_utils import get_edges, get_faces, get_vertices
15
-
16
-
17
- class DirectApiTestCase(unittest.TestCase):
18
- def assertTupleAlmostEquals(self, first, second, places, msg=None):
19
- """Check Tuples"""
20
- self.assertEqual(len(second), len(first))
21
- for i, j in zip(second, first):
22
- self.assertAlmostEqual(i, j, places, msg=msg)
23
-
24
- def assertTupleOfTupleAlmostEquals(self, first, second, places, msg=None):
25
- """Check Tuples"""
26
- self.assertEqual(len(second), len(first))
27
- for i, j in zip(second, first):
28
- self.assertTupleAlmostEquals(i, j, places, msg=msg)
29
-
30
- def assertVectorAlmostEquals(self, first, second, places, msg=None):
31
- second_vector = Vector(second)
32
- self.assertAlmostEqual(first.X, second_vector.X, places, msg=msg)
33
- self.assertAlmostEqual(first.Y, second_vector.Y, places, msg=msg)
34
- self.assertAlmostEqual(first.Z, second_vector.Z, places, msg=msg)
35
-
36
-
37
- class VectorTests(DirectApiTestCase):
38
- def test_tuple(self):
39
- vec = Vector(1, 2, 3)
40
- vec2 = Vector((1, 2, 3))
41
- self.assertTupleAlmostEquals(vec.to_tuple(), (1, 2, 3), 6)
42
- self.assertTupleAlmostEquals(vec2.to_tuple(), (1, 2, 3), 6)
43
-
44
- def test_gp_pnt(self):
45
- vec = Vector(gp_Pnt(1, 2, 3))
46
- self.assertTupleAlmostEquals(vec.to_tuple(), (1, 2, 3), 6)
47
-
48
- def test_gp_vec(self):
49
- vec = Vector(gp_Vec(1, 2, 3))
50
- self.assertTupleAlmostEquals(vec.to_tuple(), (1, 2, 3), 6)
51
-
52
- def test_gp_dir(self):
53
- vec = Vector(gp_Dir(1, 2, 3))
54
- norm = math.sqrt(1**2 + 2**2 + 3**2)
55
- self.assertTupleAlmostEquals(vec.to_tuple(), (1 / norm, 2 / norm, 3 / norm), 6)
56
-
57
- def test_normalized(self):
58
- vec = Vector(gp_Vec(1, 2, 3)).normalized()
59
- vec2 = Vector(gp_Dir(1, 2, 3))
60
- self.assertTupleAlmostEquals(vec.to_tuple(), vec2.to_tuple(), 6)
61
-
62
- def test_angle(self):
63
- vec = Vector(1, 0, 0)
64
- self.assertAlmostEqual(vec.get_angle(Vector(0, 1, 0)), 90, 6)
65
- self.assertAlmostEqual(vec.get_angle(Vector(1, 1, 0)), 45, 6)
66
- self.assertAlmostEqual(vec.get_angle(Vector(1, -1, 0)), 45, 6)
67
-
68
-
69
- class AxisTests(DirectApiTestCase):
70
- def test_axis(self):
71
- a = Axis()
72
- self.assertTupleAlmostEquals(a.position.to_tuple(), (0, 0, 0), 6)
73
- self.assertTupleAlmostEquals(a.direction.to_tuple(), (0, 0, 1), 6)
74
- b = Axis((1, 2, 3), (4, 5, 6))
75
- self.assertTupleAlmostEquals(b.position.to_tuple(), (1, 2, 3), 6)
76
- self.assertTupleAlmostEquals(b.direction.to_tuple(), (4, 5, 6), 6)
77
-
78
- def test_axis_x(self):
79
- a = Axis.X
80
- self.assertTupleAlmostEquals(a.position.to_tuple(), (0, 0, 0), 6)
81
- self.assertTupleAlmostEquals(a.direction.to_tuple(), (1, 0, 0), 6)
82
-
83
- def test_axis_y(self):
84
- a = Axis.Y
85
- self.assertTupleAlmostEquals(a.position.to_tuple(), (0, 0, 0), 6)
86
- self.assertTupleAlmostEquals(a.direction.to_tuple(), (0, 1, 0), 6)
87
-
88
- def test_axis_z(self):
89
- a = Axis.Z
90
- self.assertTupleAlmostEquals(a.position.to_tuple(), (0, 0, 0), 6)
91
- self.assertTupleAlmostEquals(a.direction.to_tuple(), (0, 0, 1), 6)
92
-
93
-
94
- class PlaneTests(DirectApiTestCase):
95
- def test_face(self):
96
- box = BRepPrimAPI_MakeBox(1.0, 2.0, 3.0).Solid()
97
- fillet = BRepFilletAPI_MakeFillet(box)
98
- for edge in get_edges(box):
99
- fillet.Add(0.2, edge)
100
- fillet.Build()
101
- box = Solid(fillet.Shape())
102
-
103
- faces = box.faces()
104
- p = Plane(faces[0])
105
-
106
- self.assertTupleAlmostEquals(p.origin.to_tuple(), (0.0, 1.0, 1.5), 6)
107
- self.assertTupleAlmostEquals(p.x_dir.to_tuple(), (0.0, 0.0, 1.0), 6)
108
- self.assertTupleAlmostEquals(p.z_dir.to_tuple(), (-1.0, 0.0, 0.0), 6)
109
-
110
- p = Plane(faces[23])
111
-
112
- self.assertTupleAlmostEquals(p.origin.to_tuple(), (1.0, 1.0, 1.5), 6)
113
- self.assertTupleAlmostEquals(p.x_dir.to_tuple(), (0.0, 0.0, 1.0), 6)
114
- self.assertTupleAlmostEquals(p.z_dir.to_tuple(), (1.0, 0.0, 0.0), 6)
115
-
116
- p = Plane(faces[10])
117
-
118
- self.assertTupleAlmostEquals(p.origin.to_tuple(), (0.5, 1.0, 3), 6)
119
- self.assertTupleAlmostEquals(p.x_dir.to_tuple(), (1.0, 0.0, 0), 6)
120
- self.assertTupleAlmostEquals(p.z_dir.to_tuple(), (0.0, 0.0, 1.0), 6)
121
-
122
- def test_edge(self):
123
- p = Plane(Vector(1, 1, 1), z_dir=(0, 1, 0))
124
-
125
- self.assertTupleAlmostEquals(p.origin.to_tuple(), (1, 1, 1), 6)
126
- self.assertTupleAlmostEquals(p.x_dir.to_tuple(), (0, 0, 1), 6)
127
- self.assertTupleAlmostEquals(p.z_dir.to_tuple(), (0, 1, 0), 6)
128
-
129
-
130
- class ShapeListTests(DirectApiTestCase):
131
- def test_lists(self):
132
- box = BRepPrimAPI_MakeBox(1.0, 2.0, 3.0).Solid()
133
- fillet = BRepFilletAPI_MakeFillet(box)
134
- for edge in get_edges(box):
135
- fillet.Add(0.2, edge)
136
- fillet.Build()
137
- box = Solid(fillet.Shape())
138
-
139
- faces = box.faces()
140
- edges = box.edges()
141
- vertices = box.vertices()
142
-
143
- self.assertEqual(len(faces), 26)
144
- self.assertEqual(len(edges), 48)
145
- self.assertEqual(len(vertices), 24)
146
-
147
- self.assertEqual(len(box.edges().filter_by("LINE")), 24)
148
- self.assertEqual(len(box.edges().filter_by("CIRCLE")), 24)
149
- self.assertEqual(len(box.edges().filter_by("OTHER")), 0)
150
-
151
- self.assertEqual(len(box.faces().filter_by("PLANE")), 6)
152
- self.assertEqual(len(box.faces().filter_by("CYLINDER")), 12)
153
- self.assertEqual(len(box.faces().filter_by("SPHERE")), 8)
154
- self.assertEqual(len(box.faces().filter_by("OTHER")), 0)
155
-
156
-
157
- class ObjectTests(DirectApiTestCase):
158
- def test_load(self):
159
- box = BRepPrimAPI_MakeBox(1.0, 2.0, 3.0).Solid()
160
- _, mapping = _convert(box)
161
- data = {"model": mapping}
162
- j = json.dumps(data, default=default).encode("utf-8")
163
-
164
- backend = ViewerBackend(9999)
165
- backend.load_model(json.loads(j)["model"])
166
-
167
- self.assertEqual(
168
- list(backend.model.keys()),
169
- [
170
- "/Group/Solid",
171
- "/Group/Solid/faces/faces_0",
172
- "/Group/Solid/faces/faces_1",
173
- "/Group/Solid/faces/faces_2",
174
- "/Group/Solid/faces/faces_3",
175
- "/Group/Solid/faces/faces_4",
176
- "/Group/Solid/faces/faces_5",
177
- "/Group/Solid/edges/edges_0",
178
- "/Group/Solid/edges/edges_1",
179
- "/Group/Solid/edges/edges_2",
180
- "/Group/Solid/edges/edges_3",
181
- "/Group/Solid/edges/edges_4",
182
- "/Group/Solid/edges/edges_5",
183
- "/Group/Solid/edges/edges_6",
184
- "/Group/Solid/edges/edges_7",
185
- "/Group/Solid/edges/edges_8",
186
- "/Group/Solid/edges/edges_9",
187
- "/Group/Solid/edges/edges_10",
188
- "/Group/Solid/edges/edges_11",
189
- "/Group/Solid/vertices/vertices0",
190
- "/Group/Solid/vertices/vertices1",
191
- "/Group/Solid/vertices/vertices2",
192
- "/Group/Solid/vertices/vertices3",
193
- "/Group/Solid/vertices/vertices4",
194
- "/Group/Solid/vertices/vertices5",
195
- "/Group/Solid/vertices/vertices6",
196
- "/Group/Solid/vertices/vertices7",
197
- ],
198
- )
199
- self.assertEqual(
200
- [isinstance(v, Face) for k, v in backend.model.items()],
201
- [
202
- False,
203
- True,
204
- True,
205
- True,
206
- True,
207
- True,
208
- True,
209
- False,
210
- False,
211
- False,
212
- False,
213
- False,
214
- False,
215
- False,
216
- False,
217
- False,
218
- False,
219
- False,
220
- False,
221
- False,
222
- False,
223
- False,
224
- False,
225
- False,
226
- False,
227
- False,
228
- False,
229
- ],
230
- )
231
- self.assertEqual(
232
- [isinstance(v, Edge) for k, v in backend.model.items()],
233
- [
234
- False,
235
- False,
236
- False,
237
- False,
238
- False,
239
- False,
240
- False,
241
- True,
242
- True,
243
- True,
244
- True,
245
- True,
246
- True,
247
- True,
248
- True,
249
- True,
250
- True,
251
- True,
252
- True,
253
- False,
254
- False,
255
- False,
256
- False,
257
- False,
258
- False,
259
- False,
260
- False,
261
- ],
262
- )
263
- self.assertEqual(
264
- [isinstance(v, Vertex) for k, v in backend.model.items()],
265
- [
266
- False,
267
- False,
268
- False,
269
- False,
270
- False,
271
- False,
272
- False,
273
- False,
274
- False,
275
- False,
276
- False,
277
- False,
278
- False,
279
- False,
280
- False,
281
- False,
282
- False,
283
- False,
284
- False,
285
- True,
286
- True,
287
- True,
288
- True,
289
- True,
290
- True,
291
- True,
292
- True,
293
- ],
294
- )
295
- self.assertEqual(
296
- [isinstance(v, Compound) for k, v in backend.model.items()],
297
- [
298
- True,
299
- False,
300
- False,
301
- False,
302
- False,
303
- False,
304
- False,
305
- False,
306
- False,
307
- False,
308
- False,
309
- False,
310
- False,
311
- False,
312
- False,
313
- False,
314
- False,
315
- False,
316
- False,
317
- False,
318
- False,
319
- False,
320
- False,
321
- False,
322
- False,
323
- False,
324
- False,
325
- ],
326
- )
327
- self.assertEqual(
328
- [v.area for k, v in backend.model.items() if isinstance(v, Face)],
329
- [6.0, 6.0, 3.0, 3.0, 2.0, 2.0],
330
- )
331
- self.assertEqual(
332
- [v.length for k, v in backend.model.items() if isinstance(v, Edge)],
333
- [3.0, 2.0, 3.0, 2.0, 3.0, 2.0, 3.0, 2.0, 1.0, 1.0, 1.0, 1.0],
334
- )
335
- self.assertEqual(backend.model["/Group/Solid"].volume, 6)
336
-
337
- def test_fillet(self):
338
- box = BRepPrimAPI_MakeBox(1.0, 2.0, 3.0).Solid()
339
- fillet = BRepFilletAPI_MakeFillet(box)
340
- for edge in get_edges(box):
341
- fillet.Add(0.2, edge)
342
- fillet.Build()
343
- box = Solid(fillet.Shape())
344
- _, mapping = _convert(box)
345
- data = {"model": mapping}
346
- j = json.dumps(data, default=default).encode("utf-8")
347
-
348
- backend = ViewerBackend(9999)
349
- backend.load_model(json.loads(j)["model"])
350
-
351
- self.assertEqual(
352
- [v.geom_type() for k, v in backend.model.items()],
353
- [
354
- "Solid",
355
- "PLANE",
356
- "CYLINDER",
357
- "CYLINDER",
358
- "CYLINDER",
359
- "CYLINDER",
360
- "SPHERE",
361
- "SPHERE",
362
- "PLANE",
363
- "PLANE",
364
- "SPHERE",
365
- "PLANE",
366
- "SPHERE",
367
- "PLANE",
368
- "CYLINDER",
369
- "CYLINDER",
370
- "CYLINDER",
371
- "CYLINDER",
372
- "CYLINDER",
373
- "CYLINDER",
374
- "CYLINDER",
375
- "CYLINDER",
376
- "SPHERE",
377
- "SPHERE",
378
- "PLANE",
379
- "SPHERE",
380
- "SPHERE",
381
- "LINE",
382
- "LINE",
383
- "LINE",
384
- "LINE",
385
- "CIRCLE",
386
- "CIRCLE",
387
- "LINE",
388
- "CIRCLE",
389
- "LINE",
390
- "CIRCLE",
391
- "CIRCLE",
392
- "LINE",
393
- "CIRCLE",
394
- "CIRCLE",
395
- "CIRCLE",
396
- "LINE",
397
- "OTHER",
398
- "CIRCLE",
399
- "OTHER",
400
- "CIRCLE",
401
- "LINE",
402
- "LINE",
403
- "LINE",
404
- "LINE",
405
- "LINE",
406
- "LINE",
407
- "OTHER",
408
- "CIRCLE",
409
- "LINE",
410
- "LINE",
411
- "LINE",
412
- "OTHER",
413
- "CIRCLE",
414
- "LINE",
415
- "LINE",
416
- "LINE",
417
- "CIRCLE",
418
- "CIRCLE",
419
- "LINE",
420
- "CIRCLE",
421
- "CIRCLE",
422
- "CIRCLE",
423
- "CIRCLE",
424
- "LINE",
425
- "CIRCLE",
426
- "CIRCLE",
427
- "CIRCLE",
428
- "LINE",
429
- "CIRCLE",
430
- "LINE",
431
- "CIRCLE",
432
- "CIRCLE",
433
- "OTHER",
434
- "OTHER",
435
- "OTHER",
436
- "OTHER",
437
- "Vertex",
438
- "Vertex",
439
- "Vertex",
440
- "Vertex",
441
- "Vertex",
442
- "Vertex",
443
- "Vertex",
444
- "Vertex",
445
- "Vertex",
446
- "Vertex",
447
- "Vertex",
448
- "Vertex",
449
- "Vertex",
450
- "Vertex",
451
- "Vertex",
452
- "Vertex",
453
- "Vertex",
454
- "Vertex",
455
- "Vertex",
456
- "Vertex",
457
- "Vertex",
458
- "Vertex",
459
- "Vertex",
460
- "Vertex",
461
- ],
462
- )
463
- vec = [v.to_tuple() for v in backend.model.values() if isinstance(v, Vertex)]
464
- self.assertTupleOfTupleAlmostEquals(
465
- vec,
466
- [
467
- (-2.7755575615628914e-17, 0.19999999999999998, 0.19999999999999998),
468
- (-2.7755575615628914e-17, 0.19999999999999998, 2.8),
469
- (-2.7755575615628914e-17, 1.8, 0.19999999999999998),
470
- (-2.7755575615628914e-17, 1.8, 2.8),
471
- (0.19999999999999998, -2.7755575615628914e-17, 0.19999999999999998),
472
- (0.19999999999999998, -2.7755575615628914e-17, 2.8),
473
- (0.19999999999999998, 0.19999999999999998, 0.0),
474
- (0.19999999999999998, 1.8, 0.0),
475
- (0.19999999999999998, 0.19999999999999998, 3.0),
476
- (0.19999999999999998, 1.8, 3.0),
477
- (0.19999999999999998, 2.0, 0.19999999999999998),
478
- (0.19999999999999998, 2.0, 2.8),
479
- (0.8, -2.7755575615628914e-17, 0.19999999999999998),
480
- (0.8, -2.7755575615628914e-17, 2.8),
481
- (0.8, 0.19999999999999998, 0.0),
482
- (0.8, 1.8, 0.0),
483
- (0.8, 0.19999999999999998, 3.0),
484
- (0.8, 1.8, 3.0),
485
- (0.8, 2.0, 0.19999999999999998),
486
- (0.8, 2.0, 2.8),
487
- (1.0, 0.19999999999999998, 0.19999999999999998),
488
- (1.0, 0.19999999999999998, 2.8),
489
- (1.0, 1.8, 0.19999999999999998),
490
- (1.0, 1.8, 2.8),
491
- ],
492
- 6,
493
- )
494
-
495
- vec = [
496
- (v.radius if v.geom_type() in ["CIRCLE"] else -1, v.length)
497
- for v in backend.model.values()
498
- if isinstance(v, Edge)
499
- ]
500
- self.assertTupleOfTupleAlmostEquals(
501
- vec,
502
- [
503
- (-1, 2.5999999999999996),
504
- (-1, 1.6),
505
- (-1, 1.6),
506
- (-1, 2.5999999999999996),
507
- (0.2, 0.3141592653589793),
508
- (0.2, 0.3141592653589793),
509
- (-1, 2.5999999999999996),
510
- (0.2, 0.3141592653589793),
511
- (-1, 1.6),
512
- (0.2, 0.3141592653589793),
513
- (0.2, 0.3141592653589793),
514
- (-1, 1.6),
515
- (0.2, 0.3141592653589793),
516
- (0.2, 0.3141592653589793),
517
- (0.2, 0.3141592653589793),
518
- (-1, 2.5999999999999996),
519
- (-1, 1.92367069372179e-17),
520
- (0.2, 0.3141592653589793),
521
- (-1, 1.92367069372179e-17),
522
- (0.2, 0.3141592653589793),
523
- (-1, 0.6000000000000001),
524
- (-1, 0.6000000000000001),
525
- (-1, 2.5999999999999996),
526
- (-1, 0.6000000000000001),
527
- (-1, 0.6000000000000001),
528
- (-1, 1.6),
529
- (-1, 1.92367069372179e-17),
530
- (0.2, 0.3141592653589793),
531
- (-1, 0.6000000000000001),
532
- (-1, 0.6000000000000001),
533
- (-1, 1.6),
534
- (-1, 1.92367069372179e-17),
535
- (0.2, 0.3141592653589793),
536
- (-1, 0.6000000000000001),
537
- (-1, 0.6000000000000001),
538
- (-1, 2.5999999999999996),
539
- (0.2, 0.3141592653589793),
540
- (0.2, 0.3141592653589793),
541
- (-1, 2.5999999999999996),
542
- (0.2, 0.3141592653589793),
543
- (0.2, 0.3141592653589793),
544
- (0.2, 0.3141592653589793),
545
- (0.2, 0.3141592653589793),
546
- (-1, 1.6),
547
- (0.2, 0.3141592653589793),
548
- (0.2, 0.3141592653589793),
549
- (0.2, 0.3141592653589793),
550
- (-1, 1.6),
551
- (0.2, 0.3141592653589793),
552
- (-1, 2.5999999999999996),
553
- (0.2, 0.3141592653589793),
554
- (0.2, 0.3141592653589793),
555
- (-1, 1.92367069372179e-17),
556
- (-1, 1.92367069372179e-17),
557
- (-1, 1.92367069372179e-17),
558
- (-1, 1.92367069372179e-17),
559
- ],
560
- 6,
561
- )
562
- # vec = [
563
- # (, v.length, v.width, v.area)
564
- # for v in backend.model.values()
565
- # if isinstance(v, Face)
566
- # ]
File without changes