gmshairfoil2d 0.2.32__tar.gz → 0.2.33__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 (21) hide show
  1. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/PKG-INFO +1 -1
  2. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/gmshairfoil2d/__init__.py +1 -1
  3. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/gmshairfoil2d/airfoil_func.py +71 -17
  4. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/gmshairfoil2d.egg-info/PKG-INFO +1 -1
  5. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/LICENSE +0 -0
  6. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/README.md +0 -0
  7. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/gmshairfoil2d/__main__.py +0 -0
  8. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/gmshairfoil2d/config_handler.py +0 -0
  9. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/gmshairfoil2d/geometry_def.py +0 -0
  10. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/gmshairfoil2d/gmshairfoil2d.py +0 -0
  11. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/gmshairfoil2d.egg-info/SOURCES.txt +0 -0
  12. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/gmshairfoil2d.egg-info/dependency_links.txt +0 -0
  13. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/gmshairfoil2d.egg-info/entry_points.txt +0 -0
  14. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/gmshairfoil2d.egg-info/requires.txt +0 -0
  15. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/gmshairfoil2d.egg-info/top_level.txt +0 -0
  16. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/setup.cfg +0 -0
  17. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/setup.py +0 -0
  18. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/tests/__init__.py +0 -0
  19. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/tests/test_airfoil_func.py +0 -0
  20. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/tests/test_config_handler.py +0 -0
  21. {gmshairfoil2d-0.2.32 → gmshairfoil2d-0.2.33}/tests/test_geometry_def.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gmshairfoil2d
3
- Version: 0.2.32
3
+ Version: 0.2.33
4
4
  Summary: Python tool to generate 2D mesh around an airfoil
5
5
  Home-page: https://github.com/cfsengineering/GMSH-Airfoil-2D
6
6
  Author: Giacomo Benedetti
@@ -1,3 +1,3 @@
1
1
  """GMSH-Airfoil-2D: 2D airfoil mesh generation with GMSH."""
2
2
 
3
- __version__ = "0.2.32"
3
+ __version__ = "0.2.33"
@@ -160,8 +160,14 @@ def get_airfoil_points(airfoil_name: str) -> list[tuple[float, float, float]]:
160
160
  airfoil_points = []
161
161
  with open(airfoil_file) as f:
162
162
  for line in f:
163
+ line = line.strip()
164
+ if not line or line.startswith(('#', 'Airfoil')):
165
+ continue
166
+ parts = line.split()
167
+ if len(parts) != 2:
168
+ continue
163
169
  try:
164
- x, y = map(float, line.strip().split())
170
+ x, y = map(float, parts)
165
171
  except ValueError:
166
172
  continue
167
173
  if x > 1 and y > 1:
@@ -171,26 +177,74 @@ def get_airfoil_points(airfoil_name: str) -> list[tuple[float, float, float]]:
171
177
  if not airfoil_points:
172
178
  raise ValueError(f"No valid points found for airfoil {airfoil_name}")
173
179
 
174
- n_points = len(airfoil_points)
175
- upper_len = n_points // 2
180
+ def _dedupe_consecutive(points, tol=1e-9):
181
+ out = []
182
+ for x, y in points:
183
+ if not out:
184
+ out.append((x, y))
185
+ continue
186
+ if abs(x - out[-1][0]) <= tol and abs(y - out[-1][1]) <= tol:
187
+ continue
188
+ out.append((x, y))
189
+ return out
176
190
 
177
- # Try to find split point at (0, 0)
178
- for i, (x, y) in enumerate(airfoil_points):
179
- if x == y == 0:
180
- upper_len = i
181
- break
191
+ def _dedupe_any(points, tol=1e-9):
192
+ out = []
193
+ for x, y in points:
194
+ if any(abs(x - ux) <= tol and abs(y - uy) <= tol for ux, uy in out):
195
+ continue
196
+ out.append((x, y))
197
+ return out
182
198
 
183
- upper_points = airfoil_points[:upper_len]
184
- lower_points = airfoil_points[upper_len:]
185
-
186
- if lower_points and lower_points[0][0] == 0:
187
- lower_points = lower_points[::-1]
199
+ tol = 1e-9
200
+ airfoil_points = _dedupe_consecutive(airfoil_points, tol=tol)
188
201
 
189
- x_up, y_up = zip(*upper_points) if upper_points else ([], [])
190
- x_lo, y_lo = zip(*lower_points) if lower_points else ([], [])
202
+ if len(airfoil_points) < 3:
203
+ raise ValueError(f"Not enough unique points for airfoil {airfoil_name}")
191
204
 
192
- cloud_points = [(x, y, 0) for x, y in zip([*x_up, *x_lo], [*y_up, *y_lo])]
193
- return sorted(set(cloud_points), key=cloud_points.index)
205
+ # Split into upper/lower when a LE point repeats (common in UIUC files)
206
+ min_x = min(x for x, _ in airfoil_points)
207
+ le_indices = [i for i, (x, _) in enumerate(airfoil_points) if abs(x - min_x) <= tol]
208
+
209
+ if len(le_indices) >= 2:
210
+ split_idx = le_indices[1]
211
+ upper = airfoil_points[:split_idx]
212
+ lower = airfoil_points[split_idx:]
213
+ else:
214
+ # Fallback: split at first maximum x (trailing edge)
215
+ max_x = max(x for x, _ in airfoil_points)
216
+ split_idx = next(i for i, (x, _) in enumerate(airfoil_points) if abs(x - max_x) <= tol)
217
+ upper = airfoil_points[:split_idx + 1]
218
+ lower = airfoil_points[split_idx + 1:]
219
+
220
+ def _ensure_le_to_te(points):
221
+ if len(points) < 2:
222
+ return points
223
+ return points if points[0][0] <= points[-1][0] else points[::-1]
224
+
225
+ upper = _ensure_le_to_te(upper)
226
+ lower = _ensure_le_to_te(lower)
227
+
228
+ # Build a closed loop starting at TE: TE->LE (upper reversed) then LE->TE (lower)
229
+ if upper and lower:
230
+ upper = upper[::-1]
231
+ loop = upper + lower[1:]
232
+ else:
233
+ loop = airfoil_points
234
+
235
+ # Remove duplicate closing point if present
236
+ if len(loop) > 1:
237
+ x0, y0 = loop[0]
238
+ x1, y1 = loop[-1]
239
+ if abs(x0 - x1) <= tol and abs(y0 - y1) <= tol:
240
+ loop.pop()
241
+
242
+ loop = _dedupe_any(loop, tol=tol)
243
+
244
+ if len(loop) < 3:
245
+ raise ValueError(f"Not enough unique points for airfoil {airfoil_name}")
246
+
247
+ return [(x, y, 0) for x, y in loop]
194
248
 
195
249
 
196
250
  def four_digit_naca_airfoil(naca_name: str, nb_points: int = 100):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gmshairfoil2d
3
- Version: 0.2.32
3
+ Version: 0.2.33
4
4
  Summary: Python tool to generate 2D mesh around an airfoil
5
5
  Home-page: https://github.com/cfsengineering/GMSH-Airfoil-2D
6
6
  Author: Giacomo Benedetti
File without changes
File without changes
File without changes
File without changes