BIM: add regression and functional test for ArchWall's MakeBlock feature (#27002)
Co-authored-by: Roy-043 <70520633+Roy-043@users.noreply.github.com>
This commit is contained in:
@@ -369,3 +369,107 @@ class TestArchWall(TestArchBase.TestArchBase):
|
||||
delta=1e-6,
|
||||
msg="Placement.Rotation was not updated correctly.",
|
||||
)
|
||||
|
||||
def test_wall_makeblocks(self):
|
||||
"""Test the 'MakeBlocks' feature of Arch Wall.
|
||||
This is a regression test for https://github.com/FreeCAD/FreeCAD/issues/26982, and
|
||||
a basic, functional test for the MakeBlocks code path.
|
||||
"""
|
||||
operation = "Checking Arch Wall MakeBlocks functional correctness..."
|
||||
self.printTestMessage(operation)
|
||||
|
||||
# Block parameters
|
||||
L, H, W = 1000.0, 600.0, 200.0
|
||||
BL, BH = 400.0, 200.0 # Block Length and Height
|
||||
O1, O2 = 0.0, 200.0 # Row offsets
|
||||
|
||||
# Create base line
|
||||
p1 = App.Vector(0, 0, 0)
|
||||
p2 = App.Vector(L, 0, 0)
|
||||
line = Draft.makeLine(p1, p2)
|
||||
self.document.recompute()
|
||||
|
||||
# Create wall based on line and block parameters
|
||||
wall = Arch.makeWall(line, width=W, height=H)
|
||||
wall.BlockLength = BL
|
||||
wall.BlockHeight = BH
|
||||
wall.Joint = 0 # For test and volume calculation simplicity
|
||||
wall.OffsetFirst = O1
|
||||
wall.OffsetSecond = O2
|
||||
|
||||
def calc_row(row_start):
|
||||
"""
|
||||
Simulates the 1D block-segmentation logic for a single horizontal course.
|
||||
|
||||
This helper replicates the "sawing" algorithm found in _Wall.execute:
|
||||
1. It places the first vertical joint at 'row_start'.
|
||||
2. It advances the cutting position by 'BlockLength' (BL).
|
||||
3. It measures the resulting segments between joints.
|
||||
4. It classifies segments equal to 'BL' as 'Entire' and any
|
||||
remainder (at the start or end of the row) as 'Broken'.
|
||||
|
||||
Args:
|
||||
row_start (float): The distance from the start of the wall to the first vertical
|
||||
joint.
|
||||
|
||||
Returns:
|
||||
tuple (int, int): A pair of integers (entire_count, broken_count)
|
||||
predicted for this specific row.
|
||||
"""
|
||||
row_entire, row_broken = 0, 0
|
||||
current_pos = row_start
|
||||
last_pos = 0.0
|
||||
|
||||
# Mimic the logic in ArchWall:
|
||||
# while offset < (Length - Joint): create cut at offset
|
||||
# Perform the cuts and record the resulting segments
|
||||
segments = []
|
||||
while current_pos < L:
|
||||
if current_pos > 0:
|
||||
segments.append(current_pos - last_pos)
|
||||
last_pos = current_pos
|
||||
current_pos += BL
|
||||
if last_pos < L:
|
||||
segments.append(L - last_pos)
|
||||
|
||||
# Classify segments
|
||||
for seg_len in segments:
|
||||
if abs(seg_len - BL) < 0.1: # Threshold for "Entire"
|
||||
row_entire += 1
|
||||
else:
|
||||
row_broken += 1
|
||||
return row_entire, row_broken
|
||||
|
||||
# Calculate expectations based on total courses (rows)
|
||||
num_rows = int(H // BH)
|
||||
expected_entire = 0
|
||||
expected_broken = 0
|
||||
|
||||
# Effectively "lay the bricks" in a running bond pattern: alternate offsets per even/odd row
|
||||
for r in range(num_rows):
|
||||
ent, brk = calc_row(O1 if r % 2 == 0 else O2)
|
||||
expected_entire += ent
|
||||
expected_broken += brk
|
||||
|
||||
# Enable the feature, triggering the #26982 bug via the code path in _Wall.execute()
|
||||
wall.MakeBlocks = True
|
||||
self.document.recompute()
|
||||
|
||||
# Regression check: did we crash?
|
||||
self.assertFalse(wall.Shape.isNull(), "Wall shape should not be null")
|
||||
|
||||
# Functional check: compare dynamic calculation to property values
|
||||
self.assertEqual(
|
||||
wall.CountEntire,
|
||||
expected_entire,
|
||||
f"Mismatch in Entire blocks. Expected {expected_entire}, got {wall.CountEntire}",
|
||||
)
|
||||
self.assertEqual(
|
||||
wall.CountBroken,
|
||||
expected_broken,
|
||||
f"Mismatch in Broken blocks. Expected {expected_broken}, got {wall.CountBroken}",
|
||||
)
|
||||
|
||||
# Integrity check: volume correctness
|
||||
expected_vol = L * W * H
|
||||
self.assertAlmostEqual(wall.Shape.Volume, expected_vol, places=3)
|
||||
|
||||
Reference in New Issue
Block a user