AbdulElahGwaith's picture
Upload folder using huggingface_hub
985c397 verified
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * *
# * Copyright (c) 2018 Yorik van Havre <yorik@uncreated.net> *
# * *
# * This file is part of FreeCAD. *
# * *
# * FreeCAD is free software: you can redistribute it and/or modify it *
# * under the terms of the GNU Lesser General Public License as *
# * published by the Free Software Foundation, either version 2.1 of the *
# * License, or (at your option) any later version. *
# * *
# * FreeCAD is distributed in the hope that it will be useful, but *
# * WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
# * Lesser General Public License for more details. *
# * *
# * You should have received a copy of the GNU Lesser General Public *
# * License along with FreeCAD. If not, see *
# * <https://www.gnu.org/licenses/>. *
# * *
# ***************************************************************************
"""The BIM Box command"""
import FreeCAD
import FreeCADGui
QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP
translate = FreeCAD.Qt.translate
class BIM_Box:
def GetResources(self):
return {
"Pixmap": "BIM_Box",
"MenuText": QT_TRANSLATE_NOOP("BIM_Box", "Box"),
"ToolTip": QT_TRANSLATE_NOOP(
"BIM_Box", "Graphically creates a generic box in the current document"
),
}
def IsActive(self):
v = hasattr(FreeCADGui.getMainWindow().getActiveWindow(), "getSceneGraph")
return v
def Activated(self):
import WorkingPlane
import draftguitools.gui_trackers as DraftTrackers
FreeCAD.activeDraftCommand = self # register as a Draft command for auto grid on/off
self.doc = FreeCAD.ActiveDocument
self.wp = WorkingPlane.get_working_plane()
# here we will store our points
self.points = []
# we build a special cube tracker which is a list of 4 rectangle trackers
self.cubetracker = []
self.LengthValue = 0
self.WidthValue = 0
self.HeightValue = 0
self.currentpoint = None
for i in range(4):
self.cubetracker.append(DraftTrackers.rectangleTracker())
if hasattr(FreeCADGui, "Snapper"):
FreeCADGui.Snapper.getPoint(
callback=self.PointCallback,
movecallback=self.MoveCallback,
extradlg=self.taskbox(),
)
def MoveCallback(self, point, snapinfo):
import DraftGeomUtils
import DraftVecUtils
self.currentpoint = point
if len(self.points) == 1:
# we have the base point already
self.Length.setText(
FreeCAD.Units.Quantity(
self.points[-1].sub(point).Length, FreeCAD.Units.Length
).UserString
)
self.Length.setFocus()
self.Length.setSelection(0, FreeCADGui.draftToolBar.number_length(self.Length.text()))
elif len(self.points) == 2:
# now we already have our base line, we update the 1st rectangle
p = point
v1 = point.sub(self.points[1])
v4 = v1.cross(self.points[1].sub(self.points[0]))
if v4 and v4.Length:
n = (self.points[1].sub(self.points[0])).cross(v4)
if n and n.Length:
n = DraftVecUtils.project(v1, n)
p = self.points[1].add(n)
self.cubetracker[0].p3(p)
self.Width.setText(
FreeCAD.Units.Quantity(
self.cubetracker[0].getSize()[1], FreeCAD.Units.Length
).UserString
)
self.Width.setFocus()
self.Width.setSelection(0, FreeCADGui.draftToolBar.number_length(self.Width.text()))
elif len(self.points) == 3:
h = DraftGeomUtils.distance_to_plane(point, self.cubetracker[0].p3(), self.normal)
w = self.normal * h
# then we update all rectangles
self.cubetracker[1].p3((self.cubetracker[0].p2()).add(w))
self.cubetracker[2].p3((self.cubetracker[0].p4()).add(w))
self.cubetracker[3].p1((self.cubetracker[0].p1()).add(w))
self.cubetracker[3].p3((self.cubetracker[0].p3()).add(w))
self.Height.setText(FreeCAD.Units.Quantity(h, FreeCAD.Units.Length).UserString)
self.Height.setFocus()
self.Height.setSelection(0, FreeCADGui.draftToolBar.number_length(self.Height.text()))
def PointCallback(self, point, snapinfo):
if not point:
# cancelled
self._finish()
return
if len(self.points) == 0:
# this is our first clicked point, nothing to do just yet
self.points.append(point)
FreeCADGui.Snapper.getPoint(
last=point,
callback=self.PointCallback,
movecallback=self.MoveCallback,
extradlg=self.taskbox(),
)
elif len(self.points) == 1:
# this is our second point
baseline = point.sub(self.points[0])
self.points.append(point)
self._setupForWidthInput(baseline)
elif len(self.points) == 2:
# this is our third point
self.points.append(point)
self._setupForHeightInput()
elif len(self.points) == 3:
# finally we have all our points. Let's create the actual cube
self._makeBox()
self._finish()
def taskbox(self):
"sets up a taskbox widget"
from PySide import QtGui
wid = QtGui.QWidget()
ui = FreeCADGui.UiLoader()
wid.setWindowTitle(translate("BIM", "Box dimensions"))
grid = QtGui.QGridLayout(wid)
label1 = QtGui.QLabel(translate("BIM", "Length"))
self.Length = ui.createWidget("Gui::InputField")
l = FreeCAD.Units.Quantity(self.LengthValue, FreeCAD.Units.Length)
self.Length.setText(l.UserString)
grid.addWidget(label1, 0, 0, 1, 1)
grid.addWidget(self.Length, 0, 1, 1, 1)
if self.LengthValue:
self.Length.setEnabled(False)
label2 = QtGui.QLabel(translate("BIM", "Width"))
self.Width = ui.createWidget("Gui::InputField")
l = FreeCAD.Units.Quantity(self.WidthValue, FreeCAD.Units.Length)
self.Width.setText(l.UserString)
grid.addWidget(label2, 1, 0, 1, 1)
grid.addWidget(self.Width, 1, 1, 1, 1)
if self.WidthValue or (not self.LengthValue):
self.Width.setEnabled(False)
label3 = QtGui.QLabel(translate("BIM", "Height"))
self.Height = ui.createWidget("Gui::InputField")
l = FreeCAD.Units.Quantity(self.HeightValue, FreeCAD.Units.Length)
self.Height.setText(l.UserString)
grid.addWidget(label3, 2, 0, 1, 1)
grid.addWidget(self.Height, 2, 1, 1, 1)
if not self.WidthValue:
self.Height.setEnabled(False)
self.Length.textEdited.connect(FreeCADGui.draftToolBar.checkSpecialChars)
self.Width.textEdited.connect(FreeCADGui.draftToolBar.checkSpecialChars)
self.Height.textEdited.connect(FreeCADGui.draftToolBar.checkSpecialChars)
self.Length.valueChanged.connect(self.setLength)
self.Width.valueChanged.connect(self.setWidth)
self.Height.valueChanged.connect(self.setHeight)
self.Length.returnPressed.connect(self.setLengthUI)
self.Width.returnPressed.connect(self.setWidthUI)
self.Height.returnPressed.connect(self.setHeightUI)
return wid
def setLength(self, d):
self.LengthValue = d
def setWidth(self, d):
self.WidthValue = d
def setHeight(self, d):
self.HeightValue = d
def setLengthUI(self):
if (len(self.points) == 1) and self.currentpoint and self.LengthValue:
baseline = self.currentpoint.sub(self.points[0])
baseline.normalize()
baseline.multiply(self.LengthValue)
p2 = self.points[0].add(baseline)
self.points.append(p2)
self._setupForWidthInput(baseline)
def setWidthUI(self):
if (len(self.points) == 2) and self.currentpoint and self.WidthValue:
self.normal = self.cubetracker[0].getNormal()
if self.normal:
n = (self.points[1].sub(self.points[0])).cross(self.normal)
if n and n.Length:
n.normalize()
n.multiply(self.WidthValue)
p2 = self.points[1].add(n)
self.cubetracker[0].p3(p2)
self.points.append(p2)
self._setupForHeightInput()
def setHeightUI(self):
if (len(self.points) == 3) and self.HeightValue:
self._makeBox()
self._finish()
def _setupForWidthInput(self, baseline):
# we turn on only one of the rectangles
self.cubetracker[0].setPlane(baseline)
self.cubetracker[0].p1(self.points[0])
self.cubetracker[0].on()
FreeCADGui.Snapper.getPoint(
last=self.points[-1],
callback=self.PointCallback,
movecallback=self.MoveCallback,
extradlg=self.taskbox(),
)
def _setupForHeightInput(self):
# we can get the cubes Z axis from our first rectangle
self.normal = self.cubetracker[0].getNormal()
# we can therefore define the (u,v) planes of all rectangles
u = self.cubetracker[0].u
v = self.cubetracker[0].v
self.cubetracker[1].setPlane(u, self.normal)
self.cubetracker[2].setPlane(u, self.normal)
self.cubetracker[3].setPlane(u, v)
# and the origin points of the vertical rectangles
self.cubetracker[1].p1(self.cubetracker[0].p1())
self.cubetracker[2].p1(self.cubetracker[0].p3())
# finally we turn all rectangles on
for r in self.cubetracker:
r.on()
point = self.cubetracker[0].p3()
axis = self.cubetracker[0].p2().sub(self.cubetracker[0].p3())
self.wp._save()
self.wp.align_to_point_and_axis(point, axis, upvec=self.normal, _hist_add=False)
FreeCADGui.Snapper.getPoint(
last=point,
callback=self.PointCallback,
movecallback=self.MoveCallback,
extradlg=self.taskbox(),
)
def _makeBox(self):
import DraftGeomUtils
p1 = self.cubetracker[0].p1()
p2 = self.cubetracker[0].p2()
p3 = self.cubetracker[0].p4()
pla = DraftGeomUtils.placement_from_points(p1, p2, p3)
if self.normal.isEqual(pla.Rotation.multVec(FreeCAD.Vector(0, 0, 1)), 1e-6):
if self.HeightValue < 0.0:
pla = DraftGeomUtils.placement_from_points(p1, p3, p2)
self.LengthValue, self.WidthValue = self.WidthValue, self.LengthValue
else:
if self.HeightValue > 0.0:
pla = DraftGeomUtils.placement_from_points(p1, p3, p2)
self.LengthValue, self.WidthValue = self.WidthValue, self.LengthValue
self.doc.openTransaction(translate("Arch", "Create Box"))
cube = self.doc.addObject("Part::Box", "Box")
cube.Placement = pla
cube.Length = self.LengthValue
cube.Width = self.WidthValue
cube.Height = abs(self.HeightValue)
self.doc.commitTransaction()
self.doc.recompute()
def _finish(self):
self.wp._restore()
FreeCAD.activeDraftCommand = None
FreeCADGui.Snapper.off()
for c in self.cubetracker:
c.finalize()
FreeCADGui.addCommand("BIM_Box", BIM_Box())