# /********************************************************************** # * * # * Copyright (c) 2021 Javier Braña * # * * # * This program is free software; you can redistribute it and/or modify* # * it under the terms of the GNU Lesser General Public License (LGPL) * # * as published by the Free Software Foundation; either version 2 of * # * the License, or (at your option) any later version. * # * for detail see the LICENCE text file. * # * * # * This program 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 Library General Public License for more details. * # * * # * You should have received a copy of the GNU Library General Public * # * License along with this program; if not, write to the Free Software * # * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307* # * USA * # * * # *********************************************************************** import ArchComponent import FreeCAD if FreeCAD.GuiUp: import FreeCADGui, os from PySide import QtCore from PySide.QtCore import QT_TRANSLATE_NOOP else: # \cond def translate(ctxt, txt): return txt def QT_TRANSLATE_NOOP(ctxt, txt): return txt # \endcond try: _fromUtf8 = QtCore.QString.fromUtf8 except AttributeError: def _fromUtf8(s): return s import PVPlantResources __dir__ = os.path.join(PVPlantResources.__dir__, "Electrical", "Cable") def makeElectricalLine(base = None): obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "ElectricalLine") ElectricalLine(obj) ViewProviderElectricalLine(obj.ViewObject) if base: obj.Base = base '''try: folder = FreeCAD.ActiveDocument.Trenches except: folder = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", 'Trenches') folder.Label = "Trenches" folder.addObject(obj)''' return obj class ElectricalLine(ArchComponent.Component): def __init__(self, obj): ArchComponent.Component.__init__(self, obj) self.setProperties(obj) def setProperties(self, obj): pl = obj.PropertiesList if not ("Paths" in pl): obj.addProperty("App::PropertyLinkSubList", "Paths", "General", "Connection") if not ("offset" in pl): obj.addProperty("App::PropertyVector", "offset", "General", "Connection") if not ("From" in pl): obj.addProperty("App::PropertyLink", "From", "Connections", QT_TRANSLATE_NOOP("App::Property", "Connection ")) if not ("To" in pl): obj.addProperty("App::PropertyLink", "To", "Connections", QT_TRANSLATE_NOOP("App::Property", "Connection ")) if not ("Cable" in pl): obj.addProperty("App::PropertyLink", "Cable", "Line", QT_TRANSLATE_NOOP("App::Property", "Connection ")) if not ("Phases" in pl): obj.addProperty("App::PropertyEnumeration", "Phases", "Line", "Connection").Phases = ["2", "3"] obj.Phases = "3" if not ("LineType" in pl): obj.addProperty("App::PropertyEnumeration", "LineType", "Line", "Connection").LineType = ["AC", "DC"] if not ("Setup" in pl): obj.addProperty("App::PropertyEnumeration", "Setup", "Line", "Connection").Setup = ["Trifoil", "Parallel"] obj.Proxy = self obj.IfcType = "Cable Segment" obj.setEditorMode("IfcType", 1) def onDocumentRestored(self, obj): """Method run when the document is restored. Re-adds the Arch component, and object properties.""" ArchComponent.Component.onDocumentRestored(self, obj) self.setProperties(obj) def updateOutputProperties(self, obj): ''' ''' def onChanged(self, obj, prop): '''Do something when a property has changed''' if prop == "Cable": ''' ''' if hasattr(obj.Cable, "Proxy") and (obj.Cable.Proxy.Type == "Cable"): ''' ''' else: obj.Cable = None if prop == "LineType": obj.Phases = "2" if obj.LineType == "DC" else "3" obj.setEditorMode("Phases", obj.LineType == "DC") self.updateOutputProperties(self, obj) def execute(self, obj): import Part, DraftGeomUtils w = self.generatePath(obj) if (not w) and (not obj.Cable): return r = obj.Cable.ExternalDiameter.Value / 2 sh = Part.makeCompound([]) cnt = int(obj.Phases) if obj.Phases == "3" and obj.Setup == "Parallel": offsets = [FreeCAD.Vector(-2 * r, 0, r), FreeCAD.Vector(2 * r, 0, r), FreeCAD.Vector(0, 0, r)] else: offsets = [FreeCAD.Vector(-r, 0, r), FreeCAD.Vector(r, 0, r), FreeCAD.Vector(0, 0, r * (1 + 3 ** 0.5))] for i in range(cnt): ph = Part.Wire([Part.Circle(offsets[i] + obj.offset, FreeCAD.Vector(0, 1, 0), r).toShape()]) v1 = w.Vertexes[1].Point - w.Vertexes[0].Point if v1.y < 0: v1 = -v1 v2 = DraftGeomUtils.getNormal(ph) ph.Placement.Base = w.Vertexes[0].Point ph.Placement.Rotation = FreeCAD.Rotation(v2, v1) sh.add(w.makePipeShell([ph, ], True, False, 0)) obj.Shape = sh def generatePath(self, obj): import Utils.PVPlantFillets as fillets result = None # 1. sort if not obj.Base: return None print(obj.Paths) w = obj.Base.Shape.SubShapes[1].SubShapes[0] w = fillets.filletWire(w, obj.Cable.RadiusOfCurvature) return w class ViewProviderElectricalLine(ArchComponent.ViewProviderComponent): def __init__(self, vobj): ArchComponent.ViewProviderComponent.__init__(self, vobj) self.Object = None vobj.Proxy = self def attach(self, vobj): ''' Create Object visuals in 3D view. ''' self.Object = vobj.Object def getIcon(self): return str(os.path.join(PVPlantResources.DirIcons, "electricalline.png")) def claimChildren(self): """ Provides object grouping """ children = [] if self.Object.Cable: children.append(self.Object.Cable) return children class ElectricalLineTaskPanel: def __init__(self, obj=None): self.new = False self.selection = None self.selectionViewObject = None self.obj = obj if obj is None: self.new = True self.form = FreeCADGui.PySideUic.loadUi(os.path.join(__dir__, "PVPlantElectricalLine.ui")) '''self.form.buttonAddLayer.clicked.connect(self.addLayer) self.form.buttonDeleteLayer.clicked.connect(self.removeLayer) self.form.buttonUp.clicked.connect(self.moveUp) self.form.buttonDown.clicked.connect(self.moveDown)''' #self.observer = SelectionObserver.SelObserver() FreeCADGui.Selection.addObserver(self) def addSelection(self, document, object, element, position): # Selection ''' ''' obj = FreeCAD.getDocument(document).getObject(object) if hasattr(obj, "Proxy"): if obj.Proxy.Type == "Trench": self.selection = obj self.selectionViewObject = obj.ViewObject.DisplayMode obj.ViewObject.DisplayMode = "Wireframe" self.TrechDialog = FreeCADGui.PySideUic.loadUi(os.path.join(__dir__, "PVPlantElectricalLineDialog.ui")) self.TrechDialog.labelTitle.setText(obj.Name) self.TrechDialog.spinBox.setMaximum(obj.Cables) self.TrechDialog.buttonAccept.clicked.connect(self.addTrenchRoute) self.TrechDialog.show() def clearSelection(self, doc): ''' ''' if self.selectionViewObject: self.selection.ViewObject.DisplayMode = self.selectionViewObject self.selectionViewObject = None pass def addTrenchRoute(self): val = self.TrechDialog.spinBox.value FreeCADGui.Selection.clearSelection() self.TrechDialog.close() def accept(self): FreeCAD.ActiveDocument.openTransaction("Create Electrical Line") makeElectricalLine() FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() self.closeForm() return True def reject(self): self.closeForm() return False def closeForm(self): FreeCADGui.Selection.removeObserver(self) FreeCADGui.Control.closeDialog() class CommandElectricalLine: def GetResources(self): return {'Pixmap': str(os.path.join(PVPlantResources.DirIcons, "electricalline.png")), 'Accel': "E, L", 'MenuText': "Línea eléctrica", 'ToolTip': "Crea una línea electríca en AC o DC.\n Selecciona la configuración de cable."} def Activated(self): TaskPanel = ElectricalLineTaskPanel() FreeCADGui.Control.showDialog(TaskPanel) def IsActive(self): if FreeCAD.ActiveDocument: return True else: return False active = not (FreeCAD.ActiveDocument is None) if FreeCAD.GuiUp: FreeCADGui.addCommand('PVPlanElectricalLine', CommandElectricalLine())