Skip to content

Commit 7e1fa69

Browse files
committed
fix line scaling
1 parent 82c0170 commit 7e1fa69

File tree

2 files changed

+81
-33
lines changed

2 files changed

+81
-33
lines changed

openglider/glider/parametric/table/lines.py

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ def get_lineset(self, glider: Glider, v_inf: euklid.vector.Vector3D) -> LineSet:
6969
line_type_name = str(self.table[row, column + 1])
7070

7171
name_or_length, trim_correction = self.parse_correction(value)
72+
if trim_correction is not None:
73+
trim_correction = trim_correction.replace("!", "")
7274

7375
if not len(current_nodes) > line_level:
7476
raise ValueError()
@@ -86,7 +88,7 @@ def get_lineset(self, glider: Glider, v_inf: euklid.vector.Vector3D) -> LineSet:
8688
else:
8789
upper = Node(node_type=Node.NODE_TYPE.KNOT)
8890
current_nodes.append(upper)
89-
line_length = Length(name_or_length)
91+
line_length = Length(name_or_length.replace("!", ""))
9092
column += 2
9193

9294
line_type_name_parts = line_type_name.split("#")
@@ -109,13 +111,13 @@ def get_lineset(self, glider: Glider, v_inf: euklid.vector.Vector3D) -> LineSet:
109111
return LineSet(lines, v_inf=v_inf)
110112

111113
@staticmethod
112-
def parse_correction(value: str) -> tuple[str, Length | None]:
114+
def parse_correction(value: str) -> tuple[str, str | None]:
113115
trim_correction: Length | None = None
114-
name_or_length = value
116+
name_or_length = str(value)
115117

116118
if match := isinstance(value, str) and re.match(r"(.*)([+-].*)", value):
117119
name_or_length = match.group(1)
118-
trim_correction = Length(match.group(2))
120+
trim_correction = match.group(2)
119121

120122
return name_or_length, trim_correction
121123

@@ -164,28 +166,63 @@ def insert_block(line: Line, upper: list[LineTreePart], row: int, column: int) -
164166
return cls(table=table, lower_attachment_points=lower_points)
165167

166168
def scale(self, factor: float, scale_lower_floor: bool) -> Self:
167-
offset_2nd_level = Length(0.)
169+
offset_upper_level: list[Length] = []
170+
offset_table = Table()
171+
172+
def set_offset(level: int, offset: Length):
173+
nonlocal offset_upper_level
174+
offset_upper_level = offset_upper_level[:level]
175+
if len(offset_upper_level) < level:
176+
offset_upper_level += [0] * (level - len(offset_upper_level))
177+
178+
offset_upper_level.append(offset)
179+
168180
for row in range(self.table.num_rows):
169181
column = 1
170182
while column < self.table.num_columns:
171-
if column + 2 < self.table.num_columns and self.table[row, column+2] and self.table[row, column]:
172-
_original_length, trim_correction = self.parse_correction(self.table[row, column])
173-
original_length = Length(_original_length)
174-
scaled_length = original_length * factor
175-
if trim_correction is not None:
176-
trim_correction *= factor
183+
if self.table[row, column]:
184+
185+
if column + 2 < self.table.num_columns and self.table[row, column+2]:
186+
# not a gallery line
187+
_original_length, trim_correction = self.parse_correction(self.table[row, column])
188+
is_fixed_length = _original_length.endswith("!") or (column == 1 and not scale_lower_floor)
189+
original_length = Length(_original_length.replace("!", ""))
190+
scaled_length = original_length * factor
191+
192+
if trim_correction is not None and not trim_correction.endswith("!"):
193+
trim_correction = str(Length(trim_correction) * factor)
194+
if not trim_correction.startswith("-"):
195+
trim_correction = "+" + trim_correction
196+
197+
198+
if is_fixed_length:
199+
# riser offset
200+
# riser_theoretical = riser_original * factor
201+
# factor < 1 => riser remains longer than it should -> next floor should be shorter to compensate
202+
target_length = original_length
203+
offset = scaled_length - original_length
204+
if column > 2 and offset_upper_level[column//2-1]:
205+
offset += offset_upper_level[column//2-1]
206+
set_offset(column // 2, offset)
207+
else:
208+
target_length = scaled_length
209+
offset = offset_upper_level[column//2-1]
210+
if offset:
211+
target_length += offset
212+
213+
offset_table[row, column] = offset
214+
215+
set_offset(column // 2, None)
216+
217+
cell_content = str(target_length)
218+
if is_fixed_length:
219+
cell_content += "!"
220+
221+
if trim_correction is not None:
222+
cell_content += trim_correction
223+
224+
self.table[row, column] = cell_content
177225

178-
if column == 1 and not scale_lower_floor:
179-
# riser offset
180-
# riser_theoretical = riser_original * factor
181-
# factor < 1 => riser remains longer than it should -> next floor should be shorter to compensate
182-
offset_2nd_level = scaled_length - original_length
183-
else:
184-
if column == 3:
185-
scaled_length += offset_2nd_level
186-
187-
self.table[row, column] = scaled_length
188-
189226
column += 2
190227

191228
return self

openglider/gui/wizzards/input/shape.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,9 @@ class ShapeSettings:
209209
aspect_ratio: float
210210
sweep: float
211211
cell_count: int
212-
scale: Literal["Area"] | Literal["Span"] | None
212+
scale: Literal["Area"] | Literal["Span"] | None = None
213213
zrot: bool = False
214+
scale_lines: bool = True
214215

215216
class ShapeSettingsWidget(QtWidgets.QWidget):
216217
changed = QtCore.Signal()
@@ -222,9 +223,7 @@ def __init__(self, shape: ParametricShape):
222223
area=shape.area,
223224
aspect_ratio=shape.aspect_ratio,
224225
sweep=shape.get_sweep(),
225-
cell_count=shape.cell_num,
226-
scale=None,
227-
zrot=False
226+
cell_count=shape.cell_num
228227
)
229228

230229
self.setLayout(layout)
@@ -246,20 +245,26 @@ def __init__(self, shape: ParametricShape):
246245
self.input_zrot.setText("Apply ZRot")
247246
self.input_zrot.setChecked(False)
248247

249-
self.input_zrot.clicked.connect(self._update)
250-
self.input_area.on_changed.append(self._update)
251-
self.input_aspect_ratio.on_changed.append(self._update)
252-
self.input_sweep.on_changed.append(self._update)
253-
self.input_cell_count.on_changed.append(self._update)
248+
self.input_scale_lines = QtWidgets.QCheckBox()
249+
self.input_scale_lines.setText("Scale Lines")
250+
self.input_scale_lines.setChecked(self.settings.scale_lines)
251+
252+
self.input_scale_lines.clicked.connect(self._update_settings)
253+
self.input_zrot.clicked.connect(self._update_settings)
254+
self.input_area.on_changed.append(self._update_settings)
255+
self.input_aspect_ratio.on_changed.append(self._update_settings)
256+
self.input_sweep.on_changed.append(self._update_settings)
257+
self.input_cell_count.on_changed.append(self._update_settings)
254258

255259
layout.addWidget(self.input_area)
256260
layout.addWidget(self.input_aspect_ratio)
257261
layout.addWidget(self.input_sweep)
258262
layout.addWidget(self.input_cell_count)
259263
layout.addWidget(self.input_scale)
260264
layout.addWidget(self.input_zrot)
265+
layout.addWidget(self.input_scale_lines)
261266

262-
def _update(self, value: Any=None) -> None:
267+
def _update_settings(self, value: Any=None) -> None:
263268
self.settings.area = self.input_area.value
264269
self.settings.aspect_ratio = self.input_aspect_ratio.value
265270
self.settings.sweep = self.input_sweep.value
@@ -272,6 +277,7 @@ def _update(self, value: Any=None) -> None:
272277
self.settings.scale = None
273278

274279
self.settings.zrot = self.input_zrot.isChecked()
280+
self.settings.scale_lines = self.input_scale_lines.isChecked()
275281

276282
self.changed.emit()
277283

@@ -356,7 +362,12 @@ def apply(self, update: bool=True) -> None:
356362
logging.info(f"new shape: {self.shape_backup.area} -> {self.shape.area}")
357363
shape = self.shape.copy()
358364
self.project.glider.shape = self.shape_backup
359-
self.project.glider.set_area(shape.area) # scale everything
365+
366+
if self.settings.scale_lines:
367+
# scale everything before putting the new shape
368+
# (which has an updated area already)
369+
self.project.glider.set_area(shape.area)
370+
360371
self.project.glider.shape = shape
361372
self.project.glider.rescale_curves()
362373

0 commit comments

Comments
 (0)