Files
PVPlant/Mechanical/Frame/PVPlantFrame.py
2025-01-28 00:04:13 +01:00

1771 lines
70 KiB
Python

# /**********************************************************************
# * *
# * Copyright (c) 2021 Javier Braña <javier.branagutierrez@gmail.com> *
# * *
# * 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 math
import ArchComponent
import FreeCAD
import Part
import PVPlantSite
if FreeCAD.GuiUp:
import FreeCADGui
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
__title__ = "PVPlant Frames"
__author__ = "Javier Braña"
__url__ = "http://www.sogos-solar.com"
import os
import PVPlantResources
from PVPlantResources import DirIcons as DirIcons
def selectFrames():
objectlist = list()
#FreeCAD.ActiveDocument.findObjects(Name="Tracker")
for obj in FreeCAD.ActiveDocument.Objects:
if hasattr(obj, "Proxy") and obj.Proxy.isDerivedFrom("Frame"):
objectlist.append(obj)
return objectlist if len(objectlist) > 0 else None
def makeFrameSetup(name="FrameSetup"):
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", name)
FrameSetup(obj)
ViewProviderFrameSetup(obj.ViewObject)
return obj
class FrameSetup:
"A Base Frame Setup Class"
def __init__(self, obj):
# Definición de Variables:
self.obj = obj
def setProperties(self, obj):
''' Definición de Propiedades: '''
pl = obj.PropertiesList
# Modulo: ------------------------------------------------------------------------------------------------------
if not "ModuleThick" in pl:
obj.addProperty("App::PropertyLength",
"ModuleThick",
"Module",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleThick = 40
if not "ModuleWidth" in pl:
obj.addProperty("App::PropertyLength",
"ModuleWidth",
"Module",
QT_TRANSLATE_NOOP("App::Property", "The width of this object")
).ModuleWidth = 1130
if not "ModuleHeight" in pl:
obj.addProperty("App::PropertyLength",
"ModuleHeight",
"Module",
QT_TRANSLATE_NOOP("App::Property", "The Length of this object")
).ModuleHeight = 2250
if not "PoleCableLength" in pl:
obj.addProperty("App::PropertyLength",
"PoleCableLength",
"Module",
QT_TRANSLATE_NOOP("App::Property", "The Length of this object")
).PoleCableLength = 1200
if not "ModulePower" in pl:
obj.addProperty("App::PropertyQuantity",
"ModulePower",
"Module",
QT_TRANSLATE_NOOP("App::Property", "The Length of this object")
).ModulePower = 600
# Array de modulos: -------------------------------------------------------------------------------------------
if not "ModuleColumns" in pl:
obj.addProperty("App::PropertyQuantity",
"ModuleColumns",
"ModuleArray",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleColumns = 2
if not "ModuleRows" in pl:
obj.addProperty("App::PropertyQuantity",
"ModuleRows",
"ModuleArray",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleRows = 2
if not "ModuleColGap" in pl:
obj.addProperty("App::PropertyDistance",
"ModuleColGap",
"ModuleArray",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleColGap = 20
if not "ModuleRowGap" in pl:
obj.addProperty("App::PropertyDistance",
"ModuleRowGap",
"ModuleArray",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleRowGap = 20
if not "ModuleOffsetX" in pl:
obj.addProperty("App::PropertyDistance",
"ModuleOffsetX",
"ModuleArray",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleOffsetX = 0
if not "ModuleOffsetY" in pl:
obj.addProperty("App::PropertyDistance",
"ModuleOffsetY",
"ModuleArray",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleOffsetY = 0
if not "ModuleOrientation" in pl:
obj.addProperty("App::PropertyEnumeration",
"ModuleOrientation",
"ModuleArray",
QT_TRANSLATE_NOOP("App::Property",
"The facemaker type to use to build the profile of this object")
).ModuleOrientation = ["Portrait", "Landscape"]
if not "ModuleViews" in pl:
obj.addProperty("App::PropertyBool",
"ModuleViews",
"ModuleArray",
QT_TRANSLATE_NOOP("App::Property",
"The facemaker type to use to build the profile of this object")
).ModuleViews = True
if not "TotalPower" in pl:
obj.addProperty("App::PropertyQuantity",
"TotalPower",
"ModuleArray",
QT_TRANSLATE_NOOP("App::Property",
"The facemaker type to use to build the profile of this object")
)
# Frame --------------------------------------------------------------------------------------------------------
'''if not "Tilt" in pl:
obj.addProperty("App::PropertyAngle",
"Tilt",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).Tilt = 30'''
if not "MaxLengthwiseTilt" in pl:
obj.addProperty("App::PropertyAngle",
"MaxLengthwiseTilt",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "Máxima inclinación longitudinal")
).MaxLengthwiseTilt = 15
if not "Width" in pl:
obj.addProperty("App::PropertyDistance",
"Width",
"Frame",
QT_TRANSLATE_NOOP("App::Property",
"Largo de la estructura")
)
obj.setEditorMode("Width", 1)
if not "Length" in pl:
obj.addProperty("App::PropertyDistance",
"Length",
"Frame",
QT_TRANSLATE_NOOP("App::Property",
"Ancho de la estructura")
)
obj.setEditorMode("Length", 1)
if not "TotalAreaShape" in pl:
obj.addProperty("App::PropertyDistance",
"TotalAreaShape",
"Frame",
QT_TRANSLATE_NOOP("Part::PropertyPartShape",
"Total Area de los Paneles")
)
obj.setEditorMode("TotalAreaShape", 1)
class Frame(ArchComponent.Component):
"A Base Frame Obcject - Class"
def __init__(self, obj):
# Definición de Variables:
ArchComponent.Component.__init__(self, obj)
self.obj = obj
self.setProperties(obj)
# Does a IfcType exist?
obj.IfcType = "Structural Item"
obj.setEditorMode("IfcType", 1)
self.totalAreaShape = None
self.changed = True
def setProperties(self, obj):
# Definicion de Propiedades:
print("Frame - setProperties")
ArchComponent.Component.setProperties(self, obj)
pl = obj.PropertiesList
# Modulo: ------------------------------------------------------------------------------------------------------
if not "ModuleThick" in pl:
obj.addProperty("App::PropertyLength",
"ModuleThick",
"Module",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleThick = 40
if not "ModuleWidth" in pl:
obj.addProperty("App::PropertyLength",
"ModuleWidth",
"Module",
QT_TRANSLATE_NOOP("App::Property", "The width of this object")
).ModuleWidth = 992
if not "ModuleHeight" in pl:
obj.addProperty("App::PropertyLength",
"ModuleHeight",
"Module",
QT_TRANSLATE_NOOP("App::Property", "The Length of this object")
).ModuleHeight = 1996
if not "PoleCableLength" in pl:
obj.addProperty("App::PropertyLength",
"PoleCableLength",
"Module",
QT_TRANSLATE_NOOP("App::Property", "The Length of this object")
).PoleCableLength = 1200
if not "ModulePower" in pl:
obj.addProperty("App::PropertyQuantity",
"ModulePower",
"Module",
QT_TRANSLATE_NOOP("App::Property", "The Length of this object")
).ModulePower = 400
# Array de modulos: -------------------------------------------------------------------------------------------
if not "ModuleCols" in pl:
obj.addProperty("App::PropertyQuantity",
"ModuleCols",
"Posicion de modulos",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleCols = 15
if not "ModuleRows" in pl:
obj.addProperty("App::PropertyQuantity",
"ModuleRows",
"Posicion de modulos",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleRows = 2
if not "ModuleColGap" in pl:
obj.addProperty("App::PropertyDistance",
"ModuleColGap",
"Posicion de modulos",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleColGap = 20
if not "ModuleRowGap" in pl:
obj.addProperty("App::PropertyDistance",
"ModuleRowGap",
"Posicion de modulos",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleRowGap = 20
if not "ModuleOffsetX" in pl:
obj.addProperty("App::PropertyDistance",
"ModuleOffsetX",
"Posicion de modulos",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleOffsetX = 0
if not "ModuleOffsetY" in pl:
obj.addProperty("App::PropertyDistance",
"ModuleOffsetY",
"Posicion de modulos",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ModuleOffsetY = 0
if not "ModuleOrientation" in pl:
obj.addProperty("App::PropertyEnumeration",
"ModuleOrientation",
"Posicion de modulos",
QT_TRANSLATE_NOOP("App::Property",
"The facemaker type to use to build the profile of this object")
).ModuleOrientation = ["Portrait", "Landscape"]
if not "ModuleViews" in pl:
obj.addProperty("App::PropertyBool",
"ModuleViews",
"Posicion de modulos",
QT_TRANSLATE_NOOP("App::Property",
"The facemaker type to use to build the profile of this object")
).ModuleViews = True
'''
if not "Modules" in pl:
obj.addProperty("App::PropertyLinkSubListChild",
"Modules",
"Posicion de modulos",
QT_TRANSLATE_NOOP("App::Property",
"The facemaker type to use to build the profile of this object")
).ModuleViews = True
'''
# Frame --------------------------------------------------------------------------------------------------------
if not "Tilt" in pl:
obj.addProperty("App::PropertyAngle",
"Tilt",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).Tilt = 30
if not "MaxLengthwiseTilt" in pl:
obj.addProperty("App::PropertyAngle",
"MaxLengthwiseTilt",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "Máxima inclinación longitudinal")
).MaxLengthwiseTilt = 15
# Frame outputs -----------------------------
if not "Width" in pl:
obj.addProperty("App::PropertyDistance",
"Width",
"Frame",
QT_TRANSLATE_NOOP("App::Property",
"Ancho de la estructura")
)
obj.setEditorMode("Width", 1)
if not "Length" in pl:
obj.addProperty("App::PropertyDistance",
"Length",
"Frame",
QT_TRANSLATE_NOOP("App::Property",
"Largo de la estructura")
)
obj.setEditorMode("Length", 1)
if not "TotalArea" in pl:
obj.addProperty("App::PropertyArea",
"TotalArea",
"Frame",
QT_TRANSLATE_NOOP("Part::PropertyPartShape",
"Area total de los Paneles")
)
obj.setEditorMode("TotalArea", 1)
# Neighbours:
if not "North" in pl:
obj.addProperty("App::PropertyLink",
"North",
"Neighbours",
QT_TRANSLATE_NOOP("Part::PropertyPartShape",
"Area total de los Paneles")
)
if not "South" in pl:
obj.addProperty("App::PropertyLink",
"South",
"Neighbours",
QT_TRANSLATE_NOOP("Part::PropertyPartShape",
"Area total de los Paneles")
)
if not "East" in pl:
obj.addProperty("App::PropertyLink",
"East",
"Neighbours",
QT_TRANSLATE_NOOP("Part::PropertyPartShape",
"Area total de los Paneles")
)
if not "West" in pl:
obj.addProperty("App::PropertyLink",
"West",
"Neighbours",
QT_TRANSLATE_NOOP("Part::PropertyPartShape",
"Area total de los Paneles")
)
'''# Placement
if not "Route" in pl:
obj.addProperty("App::PropertyLink",
"Route",
"Placement",
QT_TRANSLATE_NOOP("Part::PropertyPartShape",
"Total Area de los Paneles")
)
obj.setEditorMode("Route", 1)
if not "RouteSection" in pl:
obj.addProperty("App::PropertyIntegerConstraint",
"RouteSection",
"Placement",
QT_TRANSLATE_NOOP("Part::PropertyPartShape",
"Total Area de los Paneles")
)
obj.setEditorMode("RouteSection", 1)'''
self.Type = "Frame"
def onChanged(self, obj, prop):
if prop == "North":
if obj.getPropertyByName(prop):
obj.getPropertyByName("Route").South = obj
if (prop == "Route"):
if obj.getPropertyByName(prop):
obj.RouteSection = (1, 1, len(obj.getPropertyByName("Route").Shape.Edges) + 1, 1)
def getTotalAreaShape(self):
return self.totalAreaShape
''' ------------------------------------------- Fixed Structure --------------------------------------------------- '''
def makeRack(name="Rack"):
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", name)
_FixedRack(obj)
_ViewProviderFixedRack(obj.ViewObject)
# FreeCAD.ActiveDocument.recompute()
return obj
class _FixedRack(Frame):
"A Fixed Rack Obcject"
def __init__(self, obj):
# Definición de Variables:
Frame.__init__(self, obj)
Frame.setProperties(self, obj)
self.setProperties(obj)
# Does a IfcType exist?
# obj.IfcType = "Fence"
# obj.MoveWithHost = False
def setProperties(self, obj):
pl = obj.PropertiesList
# Array of Posts: ------------------------------------------------------------------------------------------------------
if not "NumberPostsX" in pl:
obj.addProperty("App::PropertyQuantity",
"NumberPostsX",
"Poles",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).NumberPostsX = 5
if not "DistancePostsX" in pl:
obj.addProperty("App::PropertyLength",
"DistancePostsX",
"Poles",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).DistancePostsX = 3000
if not "FrontPost" in pl:
obj.addProperty("App::PropertyBool",
"FrontPost",
"Poles",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).FrontPost = False
if not "DistancePostsY" in pl:
obj.addProperty("App::PropertyLength",
"DistancePostsY",
"Poles",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).DistancePostsY = 2000
if not "RammingDeep" in pl:
obj.addProperty("App::PropertyLength",
"RammingDeep",
"Poles",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).RammingDeep = 1500
# Correas: ----------------------------------------------------------------------------------------------------
if not "BeamHeight" in pl:
obj.addProperty("App::PropertyLength",
"BeamHeight",
"Beam",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).BeamHeight = 80
if not "BeamWidth" in pl:
obj.addProperty("App::PropertyLength",
"BeamWidth",
"Beam",
QT_TRANSLATE_NOOP("App::Property", "The width of this object")
).BeamWidth = 50
if not "BeamOffset" in pl:
obj.addProperty("App::PropertyLength",
"BeamOffset",
"Beam",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).BeamOffset = 50
if not "BeamSpacing" in pl:
obj.addProperty("App::PropertyLength",
"BeamSpacing",
"Beam",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).BeamSpacing = 1000
self.Type = "Fixed Rack"
def onDocumentRestored(self, obj):
ArchComponent.Component.onDocumentRestored(self, obj)
self.setProperties(obj)
def __getstate__(self):
return self.Type
def __setstate__(self, state):
if state:
self.Type = state
'''
def addObject(self, child):
print("addObject")
def removeObject(self, child):
print("removeObject")
def onChanged(self, obj, prop):
FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n")
'''
def onChanged(self, fp, prop):
'''Do something when a property has changed'''
# FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n")
def CalculateModuleArray(self, obj, totalh, totalw, moduleh, modulew):
# ModuleThick
# ModuleWidth
# ModuleThinness
# ModuleColor
# ModuleCols
# ModuleRows
# ModuleColGap
# ModuleRowGap
# BeamHeight
# BeamWidth
# BeamOffset
import Part
# pl = obj.Placement
module = Part.makeBox(modulew, moduleh, obj.ModuleThick.Value)
correa = Part.makeBox(totalw + obj.BeamOffset.Value * 2, obj.BeamWidth.Value, obj.BeamHeight.Value)
# Longitud poste - Produndidad de hincado + correas
correaoffsetz = obj.BackPostLength.Value
offsetz = correaoffsetz + obj.BeamHeight.Value
p1 = FreeCAD.Vector(0, 0, 0)
p2 = FreeCAD.Vector(totalw, 0, 0)
p3 = FreeCAD.Vector(totalw, totalh, 0)
p4 = FreeCAD.Vector(0, totalh, 0)
totalArea = Part.Face(Part.makePolygon([p1, p2, p3, p4, p1]))
totalArea = Part.makePlane(totalw, totalh)
totalArea.Placement.Base.x = -totalw / 2
totalArea.Placement.Base.y = -totalh / 2
totalArea.Placement.Base.z = obj.BeamHeight.Value
self.ModuleArea = totalArea
# if ShowtotalArea:
self.ListModules.append(totalArea)
correaoffsety = (moduleh - obj.BeamSpacing.Value - obj.BeamWidth.Value) / 2
for y in range(int(obj.ModuleRows.Value)):
for x in range(int(obj.ModuleCols.Value)):
xx = totalArea.Placement.Base.x + (modulew + obj.ModuleColGap.Value) * x
yy = totalArea.Placement.Base.y + (moduleh + obj.ModuleRowGap.Value) * y
zz = obj.BeamHeight.Value
moduleCopy = module.copy()
moduleCopy.Placement.Base.x = xx
moduleCopy.Placement.Base.y = yy
moduleCopy.Placement.Base.z = zz
self.ListModules.append(moduleCopy)
compound = Part.makeCompound(self.ListModules)
compound.Placement.Base.z = correaoffsetz - obj.RammingDeep.Value
if obj.FrontPost:
base = FreeCAD.Vector(0, (-obj.BackPostHeight.Value + obj.DistancePostsY.Value) / 2,
correaoffsetz - obj.RammingDeep.Value)
else:
base = FreeCAD.Vector(0, -obj.BackPostHeight.Value / 2 + totalh / 3,
correaoffsetz - obj.RammingDeep.Value)
a = compound.rotate(base, FreeCAD.Vector(1, 0, 0), obj.Tilt)
del correa
del module
del compound
del self.ListModules[:]
self.ListModules.append(a)
def CalculatePosts(self, obj, totalh, totalw):
'''
# NumberPostsX
# NumberPostsY
# PostHeight
# PostWidth
# PostLength
# DistancePostsX
# DistancePostsY
'''
postBack = Part.makeBox(obj.BackPostWidth.Value, obj.BackPostHeight.Value, obj.BackPostLength.Value)
postFront = Part.makeBox(obj.FrontPostWidth.Value, obj.FrontPostHeight.Value, obj.FrontPostLength.Value)
angle = obj.Placement.Rotation.toEuler()[1]
offsetX = (-obj.DistancePostsX.Value * (obj.NumberPostsX.Value - 1)) / 2
# offsetY = (-obj.PostHeight.Value - obj.DistancePostsY * (obj.NumberPostsY - 1)) / 2
if obj.FrontPost:
offsetY = (-obj.BackPostHeight.Value + obj.DistancePostsY.Value) / 2
else:
# TODO: cambiar el totalh / 3 por el valor adecuado
offsetY = -obj.BackPostHeight.Value / 2 + totalh / 3
offsetZ = -obj.RammingDeep.Value
for x in range(int(obj.NumberPostsX.Value)):
xx = offsetX + (
obj.NumberPostsX.Value + obj.DistancePostsX.Value) * x # * math.cos(obj.Placement.Rotation.toEuler()[1])
yy = offsetY
zz = offsetZ # * math.sin(obj.Placement.Rotation.toEuler()[1])
postCopy = postBack.copy()
postCopy.Placement.Base.x = xx
postCopy.Placement.Base.y = yy
postCopy.Placement.Base.z = zz
base = FreeCAD.Vector(xx, yy, obj.BackPostHeight.Value - offsetZ)
postCopy = postCopy.rotate(base, FreeCAD.Vector(0, 1, 0), -angle)
self.ListPosts.append(postCopy)
if obj.FrontPost:
postCopy = postFront.copy()
postCopy.Placement.Base.x = xx
postCopy.Placement.Base.y = -yy
postCopy.Placement.Base.z = zz
base = FreeCAD.Vector(xx, yy, obj.FrontPostHeight.Value - offsetZ)
postCopy = postCopy.rotate(base, FreeCAD.Vector(0, 1, 0), -angle)
self.ListPosts.append(postCopy)
del postBack
del postFront
def execute(self, obj):
pl = obj.Placement
del self.ListModules[:]
del self.ListPosts[:]
self.ListModules = []
self.ListPosts = []
if obj.ModuleOrientation == "Portrait":
w = obj.ModuleWidth.Value
h = obj.ModuleHeight.Value
else:
h = obj.ModuleWidth.Value
w = obj.ModuleHeight.Value
totalh = h * obj.ModuleRows + obj.ModuleRowGap.Value * (obj.ModuleRows - 1)
totalw = w * obj.ModuleCols + obj.ModuleColGap.Value * (obj.ModuleCols - 1)
obj.Width = totalw
obj.Length = totalh
# hacer el shape:
self.CalculateModuleArray(obj, totalh, totalw, h, w)
self.CalculatePosts(obj, totalh, totalw)
allShapes = []
allShapes.extend(self.ListModules)
allShapes.extend(self.ListPosts)
compound = Part.makeCompound(allShapes)
obj.Shape = compound
obj.Placement = pl
angle = obj.Placement.Rotation.toEuler()[1]
if angle > obj.MaxLengthwiseTilt:
obj.ViewObject.ShapeColor = (1.0, 0.0, 0.0)
print("fin")
class _ViewProviderFixedRack(ArchComponent.ViewProviderComponent):
"A View Provider for the Pipe object"
def __init__(self, vobj):
ArchComponent.ViewProviderComponent.__init__(self, vobj)
'''
ArchSite._ViewProviderSite.__init__(self, vobj)
vobj.Proxy = self
vobj.addExtension("Gui::ViewProviderGroupExtensionPython", self)
self.setProperties(vobj)
'''
def getIcon(self):
""" Return the path to the appropriate icon. """
return str(os.path.join(DirIcons, "solar-fixed.svg"))
def setEdit(self, vobj, mode):
"""Method called when the document requests the object to enter edit mode.
Edit mode is entered when a user double clicks on an object in the tree
view, or when they use the menu option [Edit -> Toggle Edit Mode].
Just display the standard Arch component task panel.
Parameters
----------
mode: int or str
The edit mode the document has requested. Set to 0 when requested via
a double click or [Edit -> Toggle Edit Mode].
Returns
-------
bool
If edit mode was entered.
"""
if (mode == 0) and hasattr(self, "Object"):
taskd = _FixedRackTaskPanel(self.Object)
taskd.obj = self.Object
FreeCADGui.Control.showDialog(taskd)
return True
return False
class _FixedRackTaskPanel:
def __init__(self, obj=None):
self.obj = obj
# -------------------------------------------------------------------------------------------------------------
# Module widget form
# -------------------------------------------------------------------------------------------------------------
self.formRack = FreeCADGui.PySideUic.loadUi(PVPlantResources.__dir__ + "/PVPlantFrame.ui")
self.formRack.widgetTracker.setVisible(False)
self.formRack.comboFrameType.currentIndexChanged.connect(self.selectionchange)
self.formPiling = FreeCADGui.PySideUic.loadUi(PVPlantResources.__dir__ + "/PVPlantRackFixedPiling.ui")
self.formPiling.editBreadthwaysNumOfPost.valueChanged.connect(self.editBreadthwaysNumOfPostChange)
self.formPiling.editAlongNumOfPost.valueChanged.connect(self.editAlongNumOfPostChange)
self.form = [self.formRack, self.formPiling]
def selectionchange(self, i):
vis = False
if i == 1:
vis = True
self.formRack.widgetTracker.setVisible(vis)
def editBreadthwaysNumOfPostChange(self):
self.formPiling.tableBreadthwaysPosts.insertRow(self.formPiling.tableBreadthwaysPosts.rowCount)
def editAlongNumOfPostChange(self):
self.l1.setText("current value:" + str(self.sp.value()))
def getValues(self):
d = {}
d["ModuleFrame"] = self.ModuleFrame
d["ModuleHeight"] = self.ModuleHeight
d["ModuleWidth"] = self.ModuleWidth
d["ModuleThick"] = self.ModuleThick
return d
def accept(self):
FreeCADGui.Control.closeDialog()
return True
def reject(self):
FreeCAD.ActiveDocument.removeObject(self.obj.Name)
FreeCADGui.Control.closeDialog()
return True
''' ------------------------------------------- Tracker Structure --------------------------------------------------- '''
def makeTrackerSetup(name="TrackerSetup"):
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "TrackerSetup")
obj.Label = name
TrackerSetup(obj)
ViewProviderTrackerSetup(obj.ViewObject)
FreeCAD.ActiveDocument.recompute()
try:
site = PVPlantSite.get()
frame_list = site.Frames
frame_list.append(obj)
site.Frames = frame_list
except:
pass
return obj
def getarray(array, numberofpoles):
if len(array) == 0:
newarray = [0] * numberofpoles
return newarray
elif len(array) == 1:
newarray = [array[0]] * numberofpoles
return newarray
elif len(array) == 2:
newarray = [array[0]] * numberofpoles
half = int(numberofpoles / 2)
newarray[half] = array[1]
if numberofpoles % 2 == 0:
newarray[half - 1] = array[1]
return newarray
elif len(array) == 3:
half = int(numberofpoles / 2)
newarray = [array[0]] * half + [array[1]] + [array[2]] * half
if numberofpoles % 2 == 0:
newarray[half] = array[1]
return newarray
elif len(array) == numberofpoles:
return array
elif len(array) > numberofpoles:
return array[0: numberofpoles]
else:
newarray = [array[0]] * numberofpoles
return newarray
class TrackerSetup(FrameSetup):
"A 1 Axis Tracker Obcject"
def __init__(self, obj):
FrameSetup.__init__(self, obj)
self.setProperties(obj)
obj.ModuleColumns = 45
obj.ModuleRows = 2
obj.ModuleColGap = 20
obj.ModuleRowGap = 20
#obj.Tilt = 0
def setProperties(self, obj):
FrameSetup.setProperties(self, obj)
pl = obj.PropertiesList
# Array de modulos: -------------------------------------------------------------------------------------------
if not "MotorGap" in pl:
obj.addProperty("App::PropertyDistance",
"MotorGap",
"ModuleArray",
QT_TRANSLATE_NOOP("App::Property", "Thse height of this object")
).MotorGap = 550
if not "UseGroupsOfModules" in pl:
obj.addProperty("App::PropertyBool",
"UseGroupsOfModules",
"GroupsOfModules",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).UseGroupsOfModules = False
# Poles: ------------------------------------------------------------------------------------------------------
#TODO: cambiar todo esto por una lista de objetos??
'''if not "PoleHeight" in pl:
obj.addProperty("App::PropertyLength",
"PoleHeight",
"Pole",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).PoleHeight = 160
if not "PoleWidth" in pl:
obj.addProperty("App::PropertyLength",
"PoleWidth",
"Pole",
QT_TRANSLATE_NOOP("App::Property", "The width of this object")
).PoleWidth = 80
if not "PoleLength" in pl:
obj.addProperty("App::PropertyLength",
"PoleLength",
"Pole",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).PoleLength = 3000'''
# Array of Posts: ------------------------------------------------------------------------------------------------------
if not "PoleType" in pl:
obj.addProperty("App::PropertyLinkList",
"PoleType",
"Poles",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
)
if not "PoleSequence" in pl:
obj.addProperty("App::PropertyIntegerList",
"PoleSequence",
"Poles",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
)
if not "NumberPole" in pl:
obj.addProperty("App::PropertyQuantity",
"NumberPole",
"Poles",
"The total number of poles"
).NumberPole = 7
if not "DistancePole" in pl:
obj.addProperty("App::PropertyIntegerList", # No list of Lenght so I use float list
"DistancePole",
"Poles",
"Distance between poles starting from the left and from the first photovoltaic module "
"without taking into account the offsets"
).DistancePole = [7000, 7000, 7000, 7000, 7000, 7000, 7000]
if not "AerialPole" in pl:
obj.addProperty("App::PropertyIntegerList",
"AerialPole",
"Poles",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).AerialPole = [1050]
# Correas: ----------------------------------------------------------------------------------------------------
# 1. MainBeam: -------------------------------------------------------------------------------------------------
if not "MainBeamProfile" in pl:
obj.addProperty("App::PropertyEnumeration",
"MainBeamProfile",
"Beam",
"The height of this object"
).MainBeamProfile = ["Square", "Octagon", "Circle"]
if not "MainBeamHeight" in pl:
obj.addProperty("App::PropertyLength",
"MainBeamHeight",
"Beam",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).MainBeamHeight = 120
if not "MainBeamWidth" in pl:
obj.addProperty("App::PropertyLength",
"MainBeamWidth",
"Beam",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).MainBeamWidth = 120
if not "MainBeamAxisPosition" in pl:
obj.addProperty("App::PropertyLength",
"MainBeamAxisPosition",
"Beam",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).MainBeamAxisPosition = 1278
# 2. Costillas: ----------------------------------------------------------------------------------------------------
if not "ShowBeams" in pl:
obj.addProperty("App::PropertyBool",
"ShowBeams",
"Beam",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).ShowBeams = False
if not "BeamHeight" in pl:
obj.addProperty("App::PropertyLength",
"BeamHeight",
"Beam",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).BeamHeight = 80
if not "BeamWidth" in pl:
obj.addProperty("App::PropertyLength",
"BeamWidth",
"Beam",
QT_TRANSLATE_NOOP("App::Property", "The width of this object")
).BeamWidth = 83.2
if not "BeamOffset" in pl:
obj.addProperty("App::PropertyLength",
"BeamOffset",
"Beam",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).BeamOffset = 50
if not "BeamSpacing" in pl:
obj.addProperty("App::PropertyLength",
"BeamSpacing",
"Beam",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).BeamSpacing = 1000
# Tracker --------------------------------------------------------------------------------------------------------
if not "MaxPhi" in pl:
obj.addProperty("App::PropertyAngle",
"MaxPhi",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).MaxPhi = 60
if not "MinPhi" in pl:
obj.addProperty("App::PropertyAngle",
"MinPhi",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).MinPhi = -60
if not "MaxNegativeLengthwiseTilt" in pl:
obj.addProperty("App::PropertyAngle",
"MaxNegativeLengthwiseTilt",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).MaxNegativeLengthwiseTilt = 6
self.Type = "1 Axis Tracker"
obj.Proxy = self
def onDocumentRestored(self, obj):
self.setProperties(obj)
def onChanged(self, obj, prop):
'''Do something when a property has changed'''
'''if prop == "NumberPole":
obj.AerialPole = self.calculateAerialArray(obj)
obj.DistancePole = self.calculateDistanceArray(obj)
obj.PoleSequence = self.calculatePostSequence(obj)'''
if prop == "AerialPole":
obj.AerialPole = self.calculateAerialArray(obj)
if prop == "DistancePole":
obj.DistancePole = self.calculateDistanceArray(obj)
if prop == "PoleSequence":
obj.PoleSequence = self.calculatePostSequence(obj)
if prop == "UseGroupsOfModules":
if obj.getPropertyByName(prop) == True:
if not "ColumnsPerGroup" in obj.PropertiesList:
obj.addProperty("App::PropertyIntegerList",
"ColumnsPerGroup",
"GroupsOfModules",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
)
if not "GroupGaps" in obj.PropertiesList:
obj.addProperty("App::PropertyIntegerList",
"GroupGaps",
"GroupsOfModules",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
)
else:
if "ColumnsPerGroup" in obj.PropertiesList:
obj.removeProperty("ColumnsPerGroup")
if "GroupGaps" in obj.PropertiesList:
obj.removeProperty("GroupGaps")
def calculatePostSequence(self, obj):
return getarray(obj.PoleSequence, int(obj.NumberPole.Value))
def calculateAerialArray(self, obj):
return getarray(obj.AerialPole, int(obj.NumberPole.Value))
def calculateDistanceArray(self, obj):
return getarray(obj.DistancePole, int(obj.NumberPole.Value))
def CalculateModuleArray(self, obj, totalh, totalw, moduleh, modulew):
module = Part.makeBox(modulew, moduleh, obj.ModuleThick.Value)
compound = Part.makeCompound([])
offsetx = -totalw / 2
offsety = -totalh / 2
offsetz = obj.MainBeamHeight.Value + obj.BeamHeight.Value
if obj.ModuleViews:
mid = int(obj.ModuleColumns.Value / 2)
for row in range(int(obj.ModuleRows.Value)):
for col in range(int(obj.ModuleColumns.Value)):
xx = offsetx + (modulew + obj.ModuleColGap.Value) * col
if col >= mid:
xx += obj.MotorGap.Value - obj.ModuleColGap.Value
yy = offsety + (moduleh + obj.ModuleRowGap.Value) * row
zz = offsetz
moduleCopy = module.copy()
moduleCopy.Placement.Base = FreeCAD.Vector(xx, yy, zz)
compound.add(moduleCopy)
else:
totalArea = Part.makePlane(totalw, totalh)
totalArea.Placement.Base = FreeCAD.Vector(offsetx, offsety, offsetz)
compound.add(totalArea)
return compound
def calculateBeams(self, obj, totalh, totalw, moduleh, modulew):
''' make mainbeam and modules beams '''
compound = Part.makeCompound([])
if obj.MainBeamProfile == "Square":
mainbeam = Part.makeBox(totalw + obj.ModuleOffsetX.Value * 2,
obj.MainBeamWidth.Value,
obj.MainBeamHeight.Value)
mainbeam.Placement.Base.y = -obj.MainBeamWidth.Value / 2
elif obj.MainBeamProfile == "Octagon":
# base on Draft.polygon:
radius = obj.MainBeamWidth.Value / 2
angle = (math.pi * 2) / 8
angleoffset = angle/2
delta = radius / math.cos(angle / 2.0)
pts = []
for i in range(8):
ang = (i + 1) * angle + angleoffset
point = FreeCAD.Vector(0,
delta * math.cos(ang),
delta * math.sin(ang))
point = point.add(FreeCAD.Vector(0, 0, radius))
pts.append(point)
pts.append(pts[0])
profile = Part.makePolygon(pts)
profile = Part.Face(profile)
mainbeam = profile.extrude(FreeCAD.Vector(totalw + obj.ModuleOffsetX.Value * 2, 0, 0))
else:
radius = obj.MainBeamWidth.Value / 2
profile = Part.Face(Part.Wire(Part.makeCircle(radius, FreeCAD.Vector(0,0,radius),
FreeCAD.Vector(1,0,0))))
mainbeam = profile.extrude(FreeCAD.Vector(totalw + obj.ModuleOffsetX.Value * 2, 0, 0))
mainbeam.Placement.Base.x = -totalw / 2 - obj.ModuleOffsetX.Value
compound.add(mainbeam)
# Correa profile:
if obj.ShowBeams: # TODO: make it in another function
mid = int(obj.ModuleColumns.Value / 2)
up = 27.8 # todo
thi = 3.2 # todo
p1 = FreeCAD.Vector(obj.BeamWidth.Value / 2 - up, 0, thi)
p2 = FreeCAD.Vector(p1.x, 0, obj.BeamHeight.Value)
p3 = FreeCAD.Vector(obj.BeamWidth.Value / 2, 0, p2.z)
p4 = FreeCAD.Vector(p3.x, 0, obj.BeamHeight.Value - thi)
p5 = FreeCAD.Vector(p4.x - up + thi, 0, p4.z)
p6 = FreeCAD.Vector(p5.x, 0, 0)
p7 = FreeCAD.Vector(-p6.x, 0, p6.z)
p8 = FreeCAD.Vector(-p5.x, 0, p5.z)
p9 = FreeCAD.Vector(-p4.x, 0, p4.z)
p10 = FreeCAD.Vector(-p3.x, 0, p3.z)
p11 = FreeCAD.Vector(-p2.x, 0, p2.z)
p12 = FreeCAD.Vector(-p1.x, 0, p1.z)
p = Part.makePolygon([p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p1])
p = Part.Face(p)
profile = p.extrude(FreeCAD.Vector(0, 428, 0))
for col in range(int(obj.ModuleColumns.Value)):
xx = totalArea.Placement.Base.x + (modulew + obj.ModuleColGap.Value) * col
if col >= mid:
xx += float(obj.MotorGap.Value) - obj.ModuleColGap.Value
correaCopy = profile.copy()
correaCopy.Placement.Base.x = xx
correaCopy.Placement.Base.y = -428 / 2
correaCopy.Placement.Base.z = obj.MainBeamHeight.Value
self.ListModules.append(correaCopy)
compound.add(correaCopy)
return compound
def CalculatePosts(self, obj, totalh, totalw):
# Temp: utilizar el uso de versiones:
ver = 1
if ver == 0:
# versión 0:
'''posttmp = Part.makeBox(obj.PoleWidth.Value, obj.PoleHeight.Value, obj.PoleLength.Value)
linetmp = Part.LineSegment(FreeCAD.Vector(0), FreeCAD.Vector(0, obj.PoleHeight.Value / 2, 0)).toShape()
compoundPoles = Part.makeCompound([])
compoundAxis = Part.makeCompound([])
offsetX = - totalw / 2
offsetY = -obj.PoleHeight.Value / 2
arrayDistance = getarray(obj.DistancePole, int(obj.NumberPole.Value))
arrayAerial = getarray(obj.AerialPole, int(obj.NumberPole.Value))
for x in range(int(obj.NumberPole.Value)):
offsetX += arrayDistance[x] - obj.PoleWidth.Value / 2
postCopy = posttmp.copy()
postCopy.Placement.Base = FreeCAD.Vector(offsetX, offsetY, -(obj.PoleLength.Value - arrayAerial[x]))
compoundPoles.add(postCopy)
axis = linetmp.copy()
axis.Placement.Base = FreeCAD.Vector(offsetX + obj.PoleWidth.Value / 2, offsetY, arrayAerial[x])
compoundAxis.add(axis)
return compoundPoles, compoundAxis'''
elif ver == 1:
# versión 1:
linetmp = Part.LineSegment(FreeCAD.Vector(0), FreeCAD.Vector(0, 10, 0)).toShape()
compoundPoles = Part.makeCompound([])
compoundAxis = Part.makeCompound([])
offsetX = - totalw / 2
arrayDistance = obj.DistancePole
arrayAerial = obj.AerialPole
arrayPost = obj.PoleSequence
for x in range(int(obj.NumberPole.Value)):
postCopy = obj.PoleType[arrayPost[x]].Shape.copy()
offsetX += arrayDistance[x]
postCopy.Placement.Base = FreeCAD.Vector(offsetX, 0, -(postCopy.BoundBox.ZLength - arrayAerial[x]))
compoundPoles.add(postCopy)
axis = linetmp.copy()
axis.Placement.Base = FreeCAD.Vector(offsetX, 0, arrayAerial[x])
compoundAxis.add(axis)
return compoundPoles, compoundAxis
def execute(self, obj):
# obj.Shape: compound
# |- Modules and Beams: compound
# |-- Modules array: compound
# |--- Modules: solid
# |-- Beams: compound
# |--- MainBeam: solid
# |--- Secundary Beams: solid (if exist)
# |- Poles array: compound
# |-- Poles: solid
# |-- Axis: Edge/line (if exist)
if obj.ModuleOrientation == "Portrait":
w = obj.ModuleWidth.Value
h = obj.ModuleHeight.Value
else:
h = obj.ModuleWidth.Value
w = obj.ModuleHeight.Value
totalh = h * obj.ModuleRows + obj.ModuleRowGap.Value * (obj.ModuleRows - 1)
totalw = w * obj.ModuleColumns + obj.ModuleColGap.Value * (obj.ModuleColumns - 1) + \
(obj.MotorGap.Value - obj.ModuleColGap.Value) if obj.MotorGap.Value > 0 else 0
modules = self.CalculateModuleArray(obj, totalh, totalw, h, w)
beams = self.calculateBeams(obj, totalh, totalw, h, w)
poles, poleaxis = self.CalculatePosts(obj, totalh, totalw)
compound = Part.makeCompound([modules, beams])
compound.Placement.Base.z = obj.MainBeamAxisPosition.Value - (obj.MainBeamHeight.Value / 2)
obj.Shape = Part.makeCompound([compound, Part.makeCompound([poles, poleaxis])])
obj.Width = min(obj.Shape.BoundBox.XLength, obj.Shape.BoundBox.YLength)
obj.Length = max(obj.Shape.BoundBox.XLength, obj.Shape.BoundBox.YLength)
obj.TotalPower = obj.ModulePower.Value * obj.ModuleRows * obj.ModuleColumns
class ViewProviderTrackerSetup:
"A View Provider for the TrackerSetup object"
def __init__(self, obj):
'''Set this object to the proxy object of the actual view provider'''
obj.Proxy = self
def getIcon(self):
return str(os.path.join(DirIcons, "trackersetup.svg"))
def setEdit(self, vobj, mode):
if (mode == 0) and hasattr(self, "Object"):
taskd = _TrackerTaskPanel(self.Object)
taskd.obj = self.Object
FreeCADGui.Control.showDialog(taskd)
return True
return False
def makeTracker(name = "Tracker", setup = None):
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "Tracker")
obj.Label = name
Tracker(obj)
ViewProviderTracker(obj.ViewObject)
if setup is not None:
obj.Setup = setup
return obj
class Tracker(ArchComponent.Component):
"A 1 Axis single row Tracker Obcject"
def __init__(self, obj):
# Definición de Variables:
ArchComponent.Component.__init__(self, obj)
self.Type = None
self.oldTilt = 0
self.oldRotation = None
self.setProperties(obj)
def setProperties(self, obj):
pl = obj.PropertiesList
if not ("Setup" in pl):
obj.addProperty("App::PropertyLink",
"Setup",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
)
if not ("Tilt" in pl):
obj.addProperty("App::PropertyAngle",
"Tilt",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).Tilt = 0
if not ("AngleX" in pl):
obj.addProperty("App::PropertyAngle",
"AngleX",
"Outputs",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).AngleX = 0
if not ("AngleY" in pl):
obj.addProperty("App::PropertyAngle",
"AngleY",
"Outputs",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).AngleX = 0
if not ("AngleZ" in pl):
obj.addProperty("App::PropertyAngle",
"AngleZ",
"Outputs",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).AngleX = 0
self.Type = "Tracker"
#obj.Type = self.Type
obj.Proxy = self
def onDocumentRestored(self, obj):
ArchComponent.Component.onDocumentRestored(self, obj)
self.setProperties(obj)
def onBeforeChange(self, obj, prop):
if prop == "Tilt":
self.oldTilt = obj.Tilt.Value
if prop == "Placement":
self.oldRotation = obj.Placement.Rotation
def onChanged(self, obj, prop):
if prop.startswith("Angle"):
base = obj.Placement.Base
angles = obj.Placement.Rotation.toEulerAngles("XYZ")
if prop == "AngleX":
rot = FreeCAD.Rotation(angles[2], angles[1], obj.AngleX.Value)
elif prop == "AngleY":
rot = FreeCAD.Rotation(angles[2], obj.AngleY.Value, angles[0])
elif prop == "AngleZ":
rot = FreeCAD.Rotation(obj.AngleZ.Value, angles[1], angles[0])
obj.Placement = FreeCAD.Placement(base, rot, FreeCAD.Vector(0,0,0))
if hasattr(FreeCAD.ActiveDocument, "FramesChecking"):
from PVPlantRackChecking import checkSingleTracker
checkSingleTracker(obj, FreeCAD.ActiveDocument.FramesChecking)
def execute(self, obj):
# obj.Shape: compound
# |- Modules and Beams: compound
# |-- Modules array: compound
# |--- Modules: solid
# |-- Beams: compound
# |--- MainBeam: solid
# |--- Secundary Beams: solid (if exist)
# |- Poles array: compound
# |-- Poles array: compound
# |--- Pole: solid
# |-- PoleAxes: Edge
if obj.Setup is None:
return
pl = obj.Placement
shape = obj.Setup.Shape.copy()
p1 = shape.SubShapes[0].SubShapes[1].SubShapes[0].CenterOfMass
p2 = min(shape.SubShapes[0].SubShapes[1].SubShapes[0].Faces, key=lambda face: face.Area).CenterOfMass
axis = p1 - p2
modules = shape.SubShapes[0].rotate(p1, axis, obj.Tilt.Value)
angle = obj.Placement.Rotation.toEuler()[1]
newpoles = Part.makeCompound([])
for i in range(len(shape.SubShapes[1].SubShapes[0].SubShapes)):
pole = shape.SubShapes[1].SubShapes[0].SubShapes[i]
axis = shape.SubShapes[1].SubShapes[1].SubShapes[i]
base = axis.Vertexes[0].Point
axis = axis.Vertexes[1].Point - axis.Vertexes[0].Point
newpoles.add(pole.rotate(base, axis, -angle))
poles = Part.makeCompound([newpoles, shape.SubShapes[1].SubShapes[1].copy()])
obj.Shape = Part.makeCompound([modules, poles])
obj.Placement = pl
obj.AngleX, obj.AngleY, obj.AngleZ = obj.Placement.Rotation.toEulerAngles("XYZ")
class ViewProviderTracker(ArchComponent.ViewProviderComponent):
"A View Provider for the Pipe object"
def __init__(self, vobj):
ArchComponent.ViewProviderComponent.__init__(self, vobj)
self.Object = vobj.Object
vobj.Proxy = self
def getIcon(self):
return str(os.path.join(DirIcons, "solar-tracker.svg"))
def setEdit(self, vobj, mode):
"""Method called when the document requests the object to enter edit mode.
Edit mode is entered when a user double clicks on an object in the tree
view, or when they use the menu option [Edit -> Toggle Edit Mode].
Just display the standard FRAME SETUP task panel.
Parameters
----------
mode: int or str
The edit mode the document has requested. Set to 0 when requested via
a double click or [Edit -> Toggle Edit Mode].
Returns
-------
bool
If edit mode was entered.
"""
'''if (mode == 0) and hasattr(self, "Object"):
taskd = _TrackerTaskPanel(self.Object)
taskd.obj = self.Object
FreeCADGui.Control.showDialog(taskd)
return True'''
return False
class dualRowTracker(ArchComponent.Component):
"A 1 Axis Dual Row Tracker Obcject"
def __init__(self, obj):
# Definición de Variables:
ArchComponent.Component.__init__(self, obj)
self.setProperties(obj)
self.Type = None
self.oldTilt = 0
self.oldRotation = None
def setProperties(self, obj):
pl = obj.PropertiesList
if not "MotorPosition" in pl:
obj.addProperty("App::PropertyLink",
"MotorPosition",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
)
if not "MotorRow" in pl:
obj.addProperty("App::PropertyLink",
"MotorRow",
"Frame",
"The height of this object"
)
if not "DrivenRow" in pl:
obj.addProperty("App::PropertyLink",
"DrivenRow",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
)
if not "Tilt" in pl:
obj.addProperty("App::PropertyAngle",
"Tilt",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).Tilt = 0
if not "Tilt" in pl:
obj.addProperty("App::PropertyAngle",
"Tilt",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
)
if not "Tilt" in pl:
obj.addProperty("App::PropertyAngle",
"Tilt",
"Frame",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
)
if not "AngleX" in pl:
obj.addProperty("App::PropertyAngle",
"AngleX",
"Outputs",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).AngleX = 0
if not "AngleY" in pl:
obj.addProperty("App::PropertyAngle",
"AngleY",
"Outputs",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).AngleX = 0
if not "AngleZ" in pl:
obj.addProperty("App::PropertyAngle",
"AngleZ",
"Outputs",
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
).AngleX = 0
self.Type = "Tracker"
# obj.Type = self.Type
obj.Proxy = self
def onDocumentRestored(self, obj):
ArchComponent.Component.onDocumentRestored(self, obj)
self.setProperties(obj)
def execute(self, obj):
''' '''
class _TrackerTaskPanel:
def __init__(self, obj=None):
if not (obj is None):
self.new = True
self.obj = makeRack()
else:
self.new = False
self.obj = obj
# -------------------------------------------------------------------------------------------------------------
# Module widget form
# -------------------------------------------------------------------------------------------------------------
self.formRack = FreeCADGui.PySideUic.loadUi(PVPlantResources.__dir__ + "/PVPlantFrame.ui")
self.formRack.widgetTracker.setVisible(False)
self.formRack.comboFrameType.currentIndexChanged.connect(self.selectionchange)
self.formPiling = FreeCADGui.PySideUic.loadUi(PVPlantResources.__dir__ + "/PVPlantRackFixedPiling.ui")
self.formPiling.editBreadthwaysNumOfPost.valueChanged.connect(self.editBreadthwaysNumOfPostChange)
self.formPiling.editAlongNumOfPost.valueChanged.connect(self.editAlongNumOfPostChange)
self.form = [self.formRack, self.formPiling]
def selectionchange(self, i):
vis = False
if i == 1:
vis = True
self.formRack.widgetTracker.setVisible(vis)
def editBreadthwaysNumOfPostChange(self):
self.formPiling.tableBreadthwaysPosts.insertRow(self.formPiling.tableBreadthwaysPosts.rowCount)
def editAlongNumOfPostChange(self):
self.l1.setText("current value:" + str(self.sp.value()))
def getValues(self):
d = {}
d["ModuleFrame"] = self.ModuleFrame
d["ModuleHeight"] = self.ModuleHeight
d["ModuleWidth"] = self.ModuleWidth
d["ModuleThick"] = self.ModuleThick
return d
def accept(self):
FreeCADGui.Control.closeDialog()
return True
def reject(self):
if self.new:
FreeCAD.ActiveDocument.removeObject(self.obj.Name)
FreeCADGui.Control.closeDialog()
return True
class _FrameTaskPanel:
def __init__(self, obj=None):
if not (obj is None):
self.new = True
self.ojb = makeRack()
else:
self.new = False
self.obj = obj
self.formRack = FreeCADGui.PySideUic.loadUi(PVPlantResources.__dir__ + "/PVPlantFrame.ui")
self.formRack.widgetTracker.setVisible(False)
self.formRack.comboFrameType.setEnable(self.new)
self.formRack.comboFrameType.currentIndexChanged.connect(self.selectionchange)
self.formPiling = FreeCADGui.PySideUic.loadUi(PVPlantResources.__dir__ + "/PVPlantRackFixedPiling.ui")
self.formPiling.editBreadthwaysNumOfPost.valueChanged.connect(self.editBreadthwaysNumOfPostChange)
self.formPiling.editAlongNumOfPost.valueChanged.connect(self.editAlongNumOfPostChange)
self.form = [self.formRack, self.formPiling]
def selectionchange(self, i):
vis = False
if i == 1:
vis = True
self.formRack.widgetTracker.setVisible(vis)
def editBreadthwaysNumOfPostChange(self):
self.formPiling.tableBreadthwaysPosts.insertRow(self.formPiling.tableBreadthwaysPosts.rowCount)
def editAlongNumOfPostChange(self):
self.l1.setText("current value:" + str(self.sp.value()))
def getValues(self):
d = {}
d["ModuleFrame"] = self.ModuleFrame
d["ModuleHeight"] = self.ModuleHeight
d["ModuleWidth"] = self.ModuleWidth
d["ModuleThick"] = self.ModuleThick
return d
def accept(self):
FreeCADGui.Control.closeDialog()
return True
def reject(self):
FreeCAD.ActiveDocument.removeObject(self.obj.Name)
if self.new:
FreeCADGui.Control.closeDialog()
return True
class _CommandFixedRack:
"the Arch Building command definition"
def GetResources(self):
return {'Pixmap': str(os.path.join(DirIcons, "solar-fixed.svg")),
'MenuText': QtCore.QT_TRANSLATE_NOOP("PVPlantRack", "Fixed Rack"),
'Accel': "R, F",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PVPlantRack",
"Creates a Fixed Rack object from setup dialog.")}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
def Activated(self):
obj = makeRack()
self.TaskPanel = _FixedRackTaskPanel(obj)
FreeCADGui.Control.showDialog(self.TaskPanel)
return
class _CommandTrackerSetup:
"the Arch Building command definition"
def GetResources(self):
return {'Pixmap': str(os.path.join(DirIcons, "trackersetup.svg")),
'MenuText': QtCore.QT_TRANSLATE_NOOP("PVPlantTracker", "TrackerSetup"),
'Accel': "R, F",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PVPlanTracker",
"Creates a TrackerSetup object from setup dialog.")}
def IsActive(self):
return (not FreeCAD.ActiveDocument is None and
not FreeCAD.ActiveDocument.getObject("Site") is None)
def Activated(self):
obj = makeTrackerSetup()
self.TaskPanel = _FixedRackTaskPanel(obj)
FreeCADGui.Control.showDialog(self.TaskPanel)
return
class _CommandTracker:
"the Arch Building command definition"
def GetResources(self):
return {'Pixmap': str(os.path.join(DirIcons, "solar-tracker.svg")),
'MenuText': QtCore.QT_TRANSLATE_NOOP("PVPlantTracker", "Tracker"),
'Accel': "R, F",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("PVPlanTracker",
"Creates a Tracker object from setup dialog.")}
def IsActive(self):
return ((not (FreeCAD.ActiveDocument is None)) and
(not (FreeCAD.ActiveDocument.getObject("Site")) is None) and
(not (FreeCAD.ActiveDocument.getObject("TrackerSetup")) is None))
def Activated(self):
sel = FreeCADGui.Selection.getSelection()
setupobj = None
for obj in sel:
if obj.Name[:12] == "TrackerSetup":
setupobj = obj
break
makeTracker(setup=setupobj)
return
class _CommandMultiRowTracker:
"the Arch Building command definition"
def GetResources(self):
return {'Pixmap': str(os.path.join(DirIcons, "solar-tracker.svg")),
'MenuText': "Multi-row Tracker",
'Accel': "R, M",
'ToolTip': "Creates a multi-row Tracker object from trackers."}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
if FreeCAD.ActiveDocument is not None:
if FreeCADGui.Selection.getCompleteSelection():
for ob in FreeCAD.ActiveDocument.Objects:
if ob.Name[:4] == "Site":
return True
def Activated(self):
self.TaskPanel = _FixedRackTaskPanel()
FreeCADGui.Control.showDialog(self.TaskPanel)
return
if FreeCAD.GuiUp:
class CommandRackGroup:
def GetCommands(self):
return tuple(['PVPlantFixedRack',
'PVPlantTrackerSetup',
'PVPlantTracker'
])
def GetResources(self):
return {'MenuText': QT_TRANSLATE_NOOP("", 'Rack Types'),
'ToolTip': QT_TRANSLATE_NOOP("", 'Rack Types')
}
def IsActive(self):
return not FreeCAD.ActiveDocument is None
FreeCADGui.addCommand('PVPlantFixedRack', _CommandFixedRack())
FreeCADGui.addCommand('PVPlantTrackerSetup', _CommandTrackerSetup())
FreeCADGui.addCommand('PVPlantTracker', _CommandTracker())
FreeCADGui.addCommand('Multirow', _CommandMultiRowTracker())
FreeCADGui.addCommand('RackType', CommandRackGroup())