| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| |
|
| | import Arch |
| | import Draft |
| | import Part |
| | import FreeCAD as App |
| | from bimtests import TestArchBase |
| | from draftutils.messages import _msg |
| |
|
| | from math import pi, cos, sin, radians |
| |
|
| |
|
| | class TestArchComponent(TestArchBase.TestArchBase): |
| |
|
| | def testAdd(self): |
| | App.Console.PrintLog("Checking Arch Add...\n") |
| | l = Draft.makeLine(App.Vector(0, 0, 0), App.Vector(2, 0, 0)) |
| | w = Arch.makeWall(l, width=0.2, height=2) |
| | sb = Part.makeBox(1, 1, 1) |
| | b = App.ActiveDocument.addObject("Part::Feature", "Box") |
| | b.Shape = sb |
| | App.ActiveDocument.recompute() |
| | Arch.addComponents(b, w) |
| | App.ActiveDocument.recompute() |
| | r = w.Shape.Volume > 1.5 |
| | self.assertTrue(r, "Arch Add failed") |
| |
|
| | def testRemove(self): |
| | App.Console.PrintLog("Checking Arch Remove...\n") |
| | l = Draft.makeLine(App.Vector(0, 0, 0), App.Vector(2, 0, 0)) |
| | w = Arch.makeWall(l, width=0.2, height=2, align="Right") |
| | sb = Part.makeBox(1, 1, 1) |
| | b = App.ActiveDocument.addObject("Part::Feature", "Box") |
| | b.Shape = sb |
| | App.ActiveDocument.recompute() |
| | Arch.removeComponents(b, w) |
| | App.ActiveDocument.recompute() |
| | r = w.Shape.Volume < 0.75 |
| | self.assertTrue(r, "Arch Remove failed") |
| |
|
| | def testBsplineSlabAreas(self): |
| | """Test the HorizontalArea and VerticalArea properties of a Bspline-based slab. |
| | |
| | See https://github.com/FreeCAD/FreeCAD/issues/20989. |
| | """ |
| |
|
| | operation = "Checking Bspline slab area calculation..." |
| | self.printTestMessage(operation) |
| |
|
| | doc = App.ActiveDocument |
| |
|
| | |
| | radius = 10000 |
| | extrusionLength = 100 |
| | numPoints = 50 |
| | startAngle = 0 |
| | endAngle = 180 |
| |
|
| | |
| | points = [] |
| | angleStep = (endAngle - startAngle) / (numPoints - 1) |
| | for i in range(numPoints): |
| | angleDeg = startAngle + i * angleStep |
| | angleRad = radians(angleDeg) |
| | x = radius * cos(angleRad) |
| | y = radius * sin(angleRad) |
| | points.append(App.Vector(x, y, 0)) |
| |
|
| | |
| | bspline = Draft.makeBSpline(points, closed=False) |
| | closingLine = Draft.makeLine(points[-1], points[0]) |
| | doc.recompute() |
| |
|
| | |
| | |
| | |
| | sketch = Draft.makeSketch([bspline, closingLine], autoconstraints=True, delete=True) |
| | if sketch is None: |
| | self.fail("Sketch creation failed") |
| | sketch.recompute() |
| |
|
| | |
| | slab = Arch.makeStructure(sketch, length=extrusionLength, name="Slab") |
| | slab.recompute() |
| |
|
| | |
| | radiusMeters = radius / 1000 |
| | heightMeters = extrusionLength / 1000 |
| | theoreticalHorizontalArea = (pi * radiusMeters**2) / 2 |
| | theoreticalVerticalArea = (pi * radiusMeters + 2 * radiusMeters) * heightMeters |
| |
|
| | |
| | actualHorizontalArea = slab.HorizontalArea.getValueAs("m^2").Value |
| | actualVerticalArea = slab.VerticalArea.getValueAs("m^2").Value |
| |
|
| | |
| | self.assertAlmostEqual( |
| | actualHorizontalArea, |
| | theoreticalHorizontalArea, |
| | places=3, |
| | msg=( |
| | "Horizontal area > 0.1% tolerance | " |
| | f"Exp: {theoreticalHorizontalArea:.3f} m² | " |
| | f"Got: {actualHorizontalArea:.3f} m²" |
| | ), |
| | ) |
| |
|
| | self.assertAlmostEqual( |
| | actualVerticalArea, |
| | theoreticalVerticalArea, |
| | places=3, |
| | msg=( |
| | "Vertical area > 0.1% tolerance | " |
| | f"Exp: {theoreticalVerticalArea:.3f} m² | " |
| | f"Got: {actualVerticalArea:.3f} m²" |
| | ), |
| | ) |
| |
|
| | def testHouseSpaceAreas(self): |
| | """Test the HorizontalArea and VerticalArea properties of a house-like space. |
| | |
| | See https://github.com/FreeCAD/FreeCAD/issues/14687. |
| | """ |
| |
|
| | operation = "Checking house space area calculation..." |
| | self.printTestMessage(operation) |
| |
|
| | doc = App.ActiveDocument |
| |
|
| | |
| | baseLength = 5000 |
| | baseWidth = 5000 |
| | rectangleHeight = 2500 |
| | triangleHeight = 2500 |
| | totalHeight = rectangleHeight + triangleHeight |
| |
|
| | |
| | points = [ |
| | App.Vector(0, 0, 0), |
| | App.Vector(baseLength, 0, 0), |
| | App.Vector(baseLength, 0, rectangleHeight), |
| | App.Vector(baseLength / 2, 0, totalHeight), |
| | App.Vector(0, 0, rectangleHeight), |
| | ] |
| |
|
| | |
| | wire = Draft.makeWire(points, closed=True, face=True) |
| | if not wire: |
| | self.fail(f"Wire creation failed with points: {points}\n") |
| | doc.recompute() |
| |
|
| | |
| | extrudedObj = Draft.extrude(wire, App.Vector(0, baseWidth, 0), solid=True) |
| | if not extrudedObj: |
| | self.fail("Extrusion failed - no object created\n") |
| | extrudedObj.Label = "Extruded house" |
| | doc.recompute() |
| |
|
| | |
| | space = Arch.makeSpace(extrudedObj) |
| | space.Label = "House space" |
| | doc.recompute() |
| |
|
| | |
| | |
| | theoreticalHorizontalArea = (baseLength * baseWidth) / 1e6 |
| |
|
| | |
| | |
| | sideFaceArea = (rectangleHeight * baseWidth) / 1e6 |
| | totalSides = sideFaceArea * 2 |
| |
|
| | |
| | rectangularPart = (baseLength * rectangleHeight) / 1e6 |
| | triangularPart = (baseLength * triangleHeight / 2) / 1e6 |
| | totalFrontBack = (rectangularPart + triangularPart) * 2 |
| |
|
| | theoreticalVerticalArea = totalSides + totalFrontBack |
| |
|
| | |
| | actualHorizontalArea = space.HorizontalArea.getValueAs("m^2").Value |
| | actualVerticalArea = space.VerticalArea.getValueAs("m^2").Value |
| |
|
| | self.assertAlmostEqual( |
| | actualHorizontalArea, |
| | theoreticalHorizontalArea, |
| | places=3, |
| | msg=f"Horizontal area > 0.1% | Exp: {theoreticalHorizontalArea:.3f} | " |
| | f"Got: {actualHorizontalArea:.3f}", |
| | ) |
| |
|
| | self.assertAlmostEqual( |
| | actualVerticalArea, |
| | theoreticalVerticalArea, |
| | places=3, |
| | msg=f"Vertical area > 0.1% | Exp: {theoreticalVerticalArea:.3f} | " |
| | f"Got: {actualVerticalArea:.3f}", |
| | ) |
| |
|
| | def test_remove_single_window_from_wall_host_is_none(self): |
| | """ |
| | Tests that a window is removed from its wall's host list when |
| | Arch.removeComponents is called with host=None (single window selection scenario). |
| | |
| | See https://github.com/FreeCAD/FreeCAD/issues/21551 |
| | """ |
| |
|
| | |
| | wall_base = Draft.makeLine(App.Vector(0, 0, 0), App.Vector(3000, 0, 0)) |
| | wall = Arch.makeWall(wall_base, width=200, height=2500) |
| |
|
| | |
| | window_width = 1000.0 |
| | window_height = 1200.0 |
| |
|
| | |
| | |
| | window_base = Draft.makeRectangle(length=window_width, height=window_height) |
| |
|
| | window = Arch.makeWindow(baseobj=window_base) |
| | window.Width = window_width |
| | window.Height = window_height |
| |
|
| | self.document.recompute() |
| |
|
| | |
| | Arch.addComponents(window, wall) |
| | self.document.recompute() |
| |
|
| | |
| | self.assertIn(wall, window.Hosts, "Wall should be in window.Hosts before removal.") |
| | self.assertEqual(len(window.Hosts), 1, "Window should have 1 host before removal.") |
| |
|
| | |
| | |
| | Arch.removeComponents([window], host=None) |
| | self.document.recompute() |
| |
|
| | |
| | self.assertNotIn(wall, window.Hosts, "Wall should not be in window.Hosts after removal.") |
| | self.assertEqual(len(window.Hosts), 0, "Window.Hosts list should be empty after removal.") |
| |
|