diffinytrace 2.1__py3-none-any.whl
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.
- diffinytrace/__init__.py +122 -0
- diffinytrace/basis_functions/__init__.py +14 -0
- diffinytrace/basis_functions/bspline.py +521 -0
- diffinytrace/basis_functions/chebyshev.py +3 -0
- diffinytrace/basis_functions/legendre.py +77 -0
- diffinytrace/basis_functions/zernike.py +235 -0
- diffinytrace/config.py +140 -0
- diffinytrace/constraints.py +54 -0
- diffinytrace/element.py +1660 -0
- diffinytrace/export/__init__.py +8 -0
- diffinytrace/export/cad.py +253 -0
- diffinytrace/gaussian_smoother.py +530 -0
- diffinytrace/hat_smoother.py +44 -0
- diffinytrace/integrators.py +452 -0
- diffinytrace/intersection.py +285 -0
- diffinytrace/optimize.py +808 -0
- diffinytrace/physical_object.py +150 -0
- diffinytrace/plotting/__init__.py +16 -0
- diffinytrace/plotting/core.py +92 -0
- diffinytrace/plotting/quantity2D.py +188 -0
- diffinytrace/plotting/system2D.py +220 -0
- diffinytrace/plotting/system3D.py +327 -0
- diffinytrace/plotting/wavelength.py +231 -0
- diffinytrace/refractive_index.py +101 -0
- diffinytrace/render.py +77 -0
- diffinytrace/source.py +661 -0
- diffinytrace/spectrum.py +79 -0
- diffinytrace/surface.py +468 -0
- diffinytrace/target_grid.py +399 -0
- diffinytrace/transforms.py +472 -0
- diffinytrace/utils/__init__.py +7 -0
- diffinytrace/utils/autograd.py +116 -0
- diffinytrace/utils/irradiance_importer.py +134 -0
- diffinytrace-2.1.dist-info/METADATA +26 -0
- diffinytrace-2.1.dist-info/RECORD +38 -0
- diffinytrace-2.1.dist-info/WHEEL +5 -0
- diffinytrace-2.1.dist-info/licenses/LICENSE +21 -0
- diffinytrace-2.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides functions for exporting CAD data to different formats.
|
|
3
|
+
It includes functions for exporting to STEP, IGES, and STL formats.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# Copyright (c) 2025 Martin Pflaum
|
|
7
|
+
# This file is part of the diffinytrace project, licensed under the MIT License.
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"lens_to_solid",
|
|
11
|
+
"extract_knots_and_multiplicities",
|
|
12
|
+
"makeNurbsFace",
|
|
13
|
+
"makeBsplineFace",
|
|
14
|
+
"export_lens",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
import torch
|
|
18
|
+
import cadquery as cq
|
|
19
|
+
from collections import Counter
|
|
20
|
+
from typing import List, Tuple
|
|
21
|
+
import copy
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
from OCP.TColgp import TColgp_Array2OfPnt
|
|
25
|
+
from OCP.TColStd import TColStd_Array2OfReal, TColStd_Array1OfReal, TColStd_Array1OfInteger
|
|
26
|
+
from OCP.Message import Message, Message_Gravity
|
|
27
|
+
|
|
28
|
+
for printer in Message.DefaultMessenger_s().Printers():
|
|
29
|
+
printer.SetTraceLevel(Message_Gravity.Message_Fail)
|
|
30
|
+
|
|
31
|
+
from OCP.Precision import Precision
|
|
32
|
+
from OCP.Geom import Geom_BSplineSurface
|
|
33
|
+
|
|
34
|
+
from OCP.BRepBuilderAPI import (
|
|
35
|
+
BRepBuilderAPI_MakeFace,
|
|
36
|
+
)
|
|
37
|
+
import numpy as np
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def lens_to_solid(lens,
|
|
41
|
+
resolution: int,
|
|
42
|
+
tol:float = 0.001,
|
|
43
|
+
smoothing = None,
|
|
44
|
+
minDeg: int = 1,
|
|
45
|
+
maxDeg: int = 3) -> cq.Solid:
|
|
46
|
+
"""
|
|
47
|
+
Convert a lens object to a CAD solid.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
lens: The lens object to be converted.
|
|
51
|
+
resolution (int): Resolution of the CAD model.
|
|
52
|
+
tol (float): Tolerance for the CAD model.
|
|
53
|
+
smoothing: Smoothing parameter for the CAD model.
|
|
54
|
+
minDeg (int): Minimum degree for the B-spline surface.
|
|
55
|
+
maxDeg (int): Maximum degree for the B-spline surface.
|
|
56
|
+
Returns:
|
|
57
|
+
cq.Solid: The CAD solid representing the lens.
|
|
58
|
+
"""
|
|
59
|
+
#direction
|
|
60
|
+
dtype = torch.float
|
|
61
|
+
device = "cpu"
|
|
62
|
+
lens = copy.deepcopy(lens)
|
|
63
|
+
lens.to(dtype)
|
|
64
|
+
lens.to(device)
|
|
65
|
+
|
|
66
|
+
local_direction = torch.tensor([0.,0.,1.0],dtype=dtype,device=device)
|
|
67
|
+
transform = lens.surface1.get_transform()
|
|
68
|
+
direction = transform.to_global_dir(local_direction).detach().cpu().numpy()
|
|
69
|
+
|
|
70
|
+
lens_thickness = lens.lens_thickness.detach().cpu().numpy()
|
|
71
|
+
surface1,surface2 = lens.surface1,lens.surface2
|
|
72
|
+
|
|
73
|
+
face1 = surface1.get_CAD_face(resolution,tol=tol,smoothing=smoothing,minDeg=minDeg,maxDeg=maxDeg)
|
|
74
|
+
face2 = surface2.get_CAD_face(resolution,tol=tol,smoothing=smoothing,minDeg=minDeg,maxDeg=maxDeg)
|
|
75
|
+
|
|
76
|
+
if lens.is_square:
|
|
77
|
+
outer_face = cq.Face.makeRuledSurface(face1.outerWire(), face2.outerWire())
|
|
78
|
+
shell = cq.Shell.makeShell([outer_face,face1,face2])
|
|
79
|
+
solid = cq.Solid.makeSolid(shell)
|
|
80
|
+
return solid
|
|
81
|
+
|
|
82
|
+
lens_thickness = lens_thickness*5.
|
|
83
|
+
affine_matrix = lens.surface1.get_transform().get_transformation_matrix().detach().cpu().numpy()
|
|
84
|
+
off_vec = affine_matrix[:3, 3]
|
|
85
|
+
off_vec = off_vec-lens_thickness*direction
|
|
86
|
+
# Extract rotation (and scale)
|
|
87
|
+
cylinder_solid = cq.Solid.makeCylinder(lens.aperture_radius, lens_thickness*2., cq.Vector(off_vec[0],off_vec[1],off_vec[2]), cq.Vector(direction[0],direction[1],direction[2]))
|
|
88
|
+
#if not lens.is_square:
|
|
89
|
+
face1 = face1.intersect(cylinder_solid)
|
|
90
|
+
face2 = face2.intersect(cylinder_solid)
|
|
91
|
+
|
|
92
|
+
face1_edge = [edge for edge in face1.edges()]
|
|
93
|
+
face2_edge = [edge for edge in face2.edges()]
|
|
94
|
+
outer_faces = []
|
|
95
|
+
for k in range(len(face1_edge)):
|
|
96
|
+
outer_faces += [cq.Face.makeRuledSurface(face1_edge[k],face2_edge[k])]
|
|
97
|
+
|
|
98
|
+
shell = cq.Shell.makeShell(outer_faces+[face1,face2])
|
|
99
|
+
solid = cq.Solid.makeSolid(shell)
|
|
100
|
+
return solid
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def extract_knots_and_multiplicities(knots: List[float]) -> Tuple[List[float], List[int]]:
|
|
104
|
+
"""
|
|
105
|
+
Extract unique knots and their multiplicities from a knot vector.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
knots (List[float]): The knot vector with implicit multiplicities.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
unique_knots (List[float]): A list of unique knots.
|
|
112
|
+
multiplicities (List[int]): A list of multiplicities corresponding to the unique knots.
|
|
113
|
+
"""
|
|
114
|
+
unique_knots = []
|
|
115
|
+
multiplicities = []
|
|
116
|
+
|
|
117
|
+
# Count occurrences of each knot
|
|
118
|
+
knot_counts = Counter(knots)
|
|
119
|
+
|
|
120
|
+
# Sort the knots to ensure increasing order
|
|
121
|
+
sorted_knots = sorted(knot_counts.items())
|
|
122
|
+
|
|
123
|
+
for knot, count in sorted_knots:
|
|
124
|
+
unique_knots.append(knot)
|
|
125
|
+
multiplicities.append(count)
|
|
126
|
+
|
|
127
|
+
return unique_knots, multiplicities
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def makeNurbsFace(
|
|
131
|
+
control_points,
|
|
132
|
+
weights,
|
|
133
|
+
U1,
|
|
134
|
+
U2,
|
|
135
|
+
u_degree: int,
|
|
136
|
+
v_degree: int,
|
|
137
|
+
u_periodic: bool = False,
|
|
138
|
+
v_periodic: bool = False
|
|
139
|
+
)->cq.Face:
|
|
140
|
+
"""
|
|
141
|
+
Create a B-spline surface from control points, weights, and implicit knot vectors.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
control_points (list): 2D list of control points as Vectors.
|
|
145
|
+
weights (list): 2D list of weights for each control point.
|
|
146
|
+
U1 (list): Knot vector in U direction with implicit multiplicities.
|
|
147
|
+
U2 (list): Knot vector in V direction with implicit multiplicities.
|
|
148
|
+
u_degree (int): Degree of the B-spline in the U direction.
|
|
149
|
+
v_degree (int): Degree of the B-spline in the V direction.
|
|
150
|
+
u_periodic (bool): If True, makes the surface periodic in the U direction.
|
|
151
|
+
v_periodic (bool): If True, makes the surface periodic in the V direction.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
cq.Face: Face instance representing the B-spline surface.
|
|
155
|
+
"""
|
|
156
|
+
U1 = [float(elem) for elem in U1]
|
|
157
|
+
U2 = [float(elem) for elem in U2]
|
|
158
|
+
# Extract unique knots and multiplicities for U and V directions
|
|
159
|
+
u_knots, u_mults = extract_knots_and_multiplicities(U1)
|
|
160
|
+
v_knots, v_mults = extract_knots_and_multiplicities(U2)
|
|
161
|
+
# Initialize control points array
|
|
162
|
+
num_u = len(control_points)
|
|
163
|
+
num_v = len(control_points[0])
|
|
164
|
+
poles = TColgp_Array2OfPnt(1, num_u, 1, num_v)
|
|
165
|
+
for i, row in enumerate(control_points):
|
|
166
|
+
for j, _pt in enumerate(row):
|
|
167
|
+
pt = cq.Vector(_pt[0],_pt[1],_pt[2])
|
|
168
|
+
poles.SetValue(i + 1, j + 1, pt.toPnt())
|
|
169
|
+
|
|
170
|
+
# Initialize weights array
|
|
171
|
+
weights_array = TColStd_Array2OfReal(1, num_u, 1, num_v)
|
|
172
|
+
for i, row in enumerate(weights):
|
|
173
|
+
for j, w in enumerate(row):
|
|
174
|
+
weights_array.SetValue(i + 1, j + 1, float(w))
|
|
175
|
+
|
|
176
|
+
# Initialize knot arrays for U and V directions
|
|
177
|
+
u_knots_array = TColStd_Array1OfReal(1, len(u_knots))
|
|
178
|
+
v_knots_array = TColStd_Array1OfReal(1, len(v_knots))
|
|
179
|
+
u_mults_array = TColStd_Array1OfInteger(1, len(u_mults))
|
|
180
|
+
v_mults_array = TColStd_Array1OfInteger(1, len(v_mults))
|
|
181
|
+
|
|
182
|
+
for idx, val in enumerate(u_knots):
|
|
183
|
+
u_knots_array.SetValue(idx + 1, val)
|
|
184
|
+
for idx, val in enumerate(v_knots):
|
|
185
|
+
v_knots_array.SetValue(idx + 1, val)
|
|
186
|
+
for idx, mult in enumerate(u_mults):
|
|
187
|
+
u_mults_array.SetValue(idx + 1, mult)
|
|
188
|
+
for idx, mult in enumerate(v_mults):
|
|
189
|
+
v_mults_array.SetValue(idx + 1, mult)
|
|
190
|
+
|
|
191
|
+
# Create the B-spline surface
|
|
192
|
+
spline_surface = Geom_BSplineSurface(
|
|
193
|
+
poles,
|
|
194
|
+
weights_array,
|
|
195
|
+
u_knots_array,
|
|
196
|
+
v_knots_array,
|
|
197
|
+
u_mults_array,
|
|
198
|
+
v_mults_array,
|
|
199
|
+
u_degree,
|
|
200
|
+
v_degree,
|
|
201
|
+
u_periodic,
|
|
202
|
+
v_periodic
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# Create a face from the B-spline surface
|
|
206
|
+
face = BRepBuilderAPI_MakeFace(spline_surface, Precision.Confusion_s()).Face()
|
|
207
|
+
|
|
208
|
+
# Return an instance of Face initialized with the generated face
|
|
209
|
+
return cq.Face(face)
|
|
210
|
+
|
|
211
|
+
def makeBsplineFace(
|
|
212
|
+
control_points,
|
|
213
|
+
U1,
|
|
214
|
+
U2,
|
|
215
|
+
u_degree: int,
|
|
216
|
+
v_degree: int,
|
|
217
|
+
u_periodic: bool = False,
|
|
218
|
+
v_periodic: bool = False
|
|
219
|
+
)->cq.Face:
|
|
220
|
+
"""
|
|
221
|
+
Create a non-rational B-spline surface face from control points and knot vectors.
|
|
222
|
+
|
|
223
|
+
Args:
|
|
224
|
+
control_points (np.ndarray): 2D array of control points (shape: [num_u, num_v, 3]).
|
|
225
|
+
U1 (list): Knot vector in U direction with implicit multiplicities.
|
|
226
|
+
U2 (list): Knot vector in V direction with implicit multiplicities.
|
|
227
|
+
u_degree (int): Degree of the B-spline in the U direction.
|
|
228
|
+
v_degree (int): Degree of the B-spline in the V direction.
|
|
229
|
+
u_periodic (bool, optional): If True, makes the surface periodic in the U direction. Defaults to False.
|
|
230
|
+
v_periodic (bool, optional): If True, makes the surface periodic in the V direction. Defaults to False.
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
cq.Face: Face instance representing the B-spline surface.
|
|
234
|
+
"""
|
|
235
|
+
|
|
236
|
+
weights = np.ones((control_points.shape[0],control_points.shape[1]),dtype=float)
|
|
237
|
+
return makeNurbsFace(control_points,weights,U1,U2,u_degree,v_degree,u_periodic,v_periodic)
|
|
238
|
+
|
|
239
|
+
def export_lens(file_path:str, lens, resolution:int, tol:float = 0.001):
|
|
240
|
+
"""
|
|
241
|
+
Export a lens to a CAD file.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
file_path (str): The path to save the CAD file.
|
|
245
|
+
lens: The lens object to be exported.
|
|
246
|
+
resolution (int): Resolution of the CAD model.
|
|
247
|
+
tol (float): Tolerance for the CAD model.
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
solid = lens_to_solid(lens,resolution,tol=tol)
|
|
251
|
+
cq.exporters.export(solid, file_path)
|
|
252
|
+
|
|
253
|
+
|