1319 lines
53 KiB
Python
1319 lines
53 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
|
|
|
|
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")
|
|
)
|
|
|
|
# Poles --------------------------------------------------------------------------------------------------------
|
|
if not "PoleType" in pl:
|
|
obj.addProperty("App::PropertyLinkList",
|
|
"PoleType",
|
|
"Poles",
|
|
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
|
|
)
|
|
|
|
# Frame --------------------------------------------------------------------------------------------------------
|
|
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)
|
|
|
|
''' ------------------------------------------- Fixed Structure --------------------------------------------------- '''
|
|
def makeRack(name="Rack"):
|
|
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", name)
|
|
obj.Label = name
|
|
FixedRack(obj)
|
|
ViewProviderFixedRack(obj.ViewObject)
|
|
return obj
|
|
|
|
class FixedRack(FrameSetup):
|
|
"A Fixed Rack Obcject"
|
|
|
|
def __init__(self, obj):
|
|
#FrameSetup.__init__(self, obj)
|
|
super(FixedRack, self).__init__(obj)
|
|
self.setProperties(obj)
|
|
obj.ModuleColumns = 6
|
|
obj.ModuleRows = 2
|
|
obj.ModuleColGap = 20
|
|
obj.ModuleRowGap = 20
|
|
#obj.Tilt = 30
|
|
# Does a IfcType exist?
|
|
# obj.IfcType = "Fence"
|
|
# obj.MoveWithHost = False
|
|
|
|
def setProperties(self, obj):
|
|
FrameSetup.setProperties(self, obj)
|
|
pl = obj.PropertiesList
|
|
if not "ModuleElevation" in pl:
|
|
obj.addProperty("App::PropertyDistance",
|
|
"ModuleElevation",
|
|
"ModuleArray",
|
|
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
|
|
).ModuleElevation = 500
|
|
|
|
# Frame: ------------------------------------------------------------------------------------------------------
|
|
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 "FrameType" in pl:
|
|
obj.addProperty("App::PropertyEnumeration",
|
|
"FrameType",
|
|
"Frame",
|
|
QT_TRANSLATE_NOOP("App::Property",
|
|
"The facemaker type to use to build the profile of this object")
|
|
).FrameType = ["Simple", "West-Lest"]
|
|
|
|
|
|
# Pole: ------------------------------------------------------------------------------------------------------
|
|
if not "BackPostWidth" in pl:
|
|
obj.addProperty("App::PropertyLength",
|
|
"BackPostWidth",
|
|
"Pole",
|
|
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
|
|
).BackPostWidth = 80
|
|
|
|
if not "BackPostHeight" in pl:
|
|
obj.addProperty("App::PropertyLength",
|
|
"BackPostHeight",
|
|
"Pole",
|
|
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
|
|
).BackPostHeight = 160
|
|
|
|
if not "BackPostLength" in pl:
|
|
obj.addProperty("App::PropertyLength",
|
|
"BackPostLength",
|
|
"Pole",
|
|
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
|
|
).BackPostLength = 3200
|
|
|
|
if not "FrontPostWidth" in pl:
|
|
obj.addProperty("App::PropertyLength",
|
|
"FrontPostWidth",
|
|
"Pole",
|
|
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
|
|
).FrontPostWidth = 40
|
|
|
|
if not "FrontPostHeight" in pl:
|
|
obj.addProperty("App::PropertyLength",
|
|
"FrontPostHeight",
|
|
"Pole",
|
|
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
|
|
).FrontPostHeight = 80
|
|
|
|
if not "FrontPostLength" in pl:
|
|
obj.addProperty("App::PropertyLength",
|
|
"FrontPostLength",
|
|
"Pole",
|
|
QT_TRANSLATE_NOOP("App::Property", "The height of this object")
|
|
).FrontPostLength = 2300
|
|
|
|
# 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 = 3
|
|
|
|
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"
|
|
obj.Proxy = self
|
|
|
|
def onDocumentRestored(self, obj):
|
|
#ArchComponent.Component.onDocumentRestored(self, obj)
|
|
super(FixedRack, self).onDocumentRestored(obj)
|
|
self.setProperties(obj)
|
|
|
|
def __getstate__(self):
|
|
return self.Type
|
|
|
|
def __setstate__(self, state):
|
|
if state:
|
|
self.Type = state
|
|
|
|
def onChanged(self, fp, prop):
|
|
'''Do something when a property has changed'''
|
|
|
|
def generate_modules(self, obj, h, w):
|
|
modulos=[]
|
|
for y in range(int(obj.ModuleRows.Value)):
|
|
for x in range(int(obj.ModuleColumns.Value)):
|
|
mod = Part.makeBox(w, h, obj.ModuleThick.Value)
|
|
mod.Placement.Base = FreeCAD.Vector(
|
|
x * (w + obj.ModuleColGap.Value),
|
|
y * (h + obj.ModuleRowGap.Value),
|
|
0
|
|
)
|
|
modulos.append(mod)
|
|
|
|
compound = Part.makeCompound(modulos)
|
|
'''center = FreeCAD.Vector(compound.BoundBox.Center)
|
|
for mod in modulos:
|
|
mod.Placement.Base -= FreeCAD.Vector(center.x, center.y, 0)
|
|
compound = Part.makeCompound(modulos)'''
|
|
return compound
|
|
|
|
|
|
def generate_posts(self, obj):
|
|
postBack = Part.makeBox(obj.BackPostWidth.Value, obj.BackPostHeight.Value, obj.BackPostLength.Value)
|
|
postFront = Part.makeBox(obj.FrontPostWidth.Value, obj.FrontPostHeight.Value, obj.FrontPostLength.Value)
|
|
|
|
post_back = []
|
|
post_front = []
|
|
for x in range(int(obj.NumberPostsX.Value)):
|
|
postCopy = postBack.copy()
|
|
postCopy.Placement.Base = FreeCAD.Vector(x * obj.DistancePostsX.Value, obj.DistancePostsY.Value, 0)
|
|
post_back.append(postCopy)
|
|
|
|
if obj.FrontPost:
|
|
postCopy = postFront.copy()
|
|
postCopy.Placement.Base = FreeCAD.Vector(x * obj.DistancePostsX.Value, 0, 0)
|
|
post_front.append(postCopy)
|
|
|
|
return Part.makeCompound([Part.makeCompound(post_back), Part.makeCompound(post_front)])
|
|
|
|
def correct_placement(self, obj):
|
|
center = FreeCAD.Vector(obj.BoundBox.Center)
|
|
obj.Placement.Base -= FreeCAD.Vector(center.x, center.y, 0)
|
|
|
|
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
|
|
|
|
pl = obj.Placement
|
|
|
|
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)
|
|
|
|
modules = self.generate_modules(obj, h, w)
|
|
modules.Placement.Rotation = FreeCAD.Rotation(FreeCAD.Vector(1, 0, 0), obj.Tilt.Value)
|
|
self.correct_placement(modules)
|
|
modules.Placement.Base += FreeCAD.Vector(0, 0, obj.ModuleElevation.Value)
|
|
posts = self.generate_posts(obj)
|
|
self.correct_placement(posts)
|
|
posts.Placement.Base -= FreeCAD.Vector(0, 0, obj.RammingDeep.Value)
|
|
|
|
compound = Part.makeCompound([modules, posts])
|
|
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)
|
|
|
|
obj.Width = totalw
|
|
obj.Length = totalh
|
|
|
|
class ViewProviderFixedRack:
|
|
"A View Provider for the Pipe object"
|
|
|
|
def __init__(self, vobj):
|
|
vobj.Proxy = self
|
|
|
|
def getIcon(self):
|
|
""" Return the path to the appropriate icon. """
|
|
return str(os.path.join(DirIcons, "solar-fixed.svg"))
|
|
|
|
def setEdit(self, vobj, mode):
|
|
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.form = FreeCADGui.PySideUic.loadUi(PVPlantResources.__dir__ + "Mechanical/Frame/PVPlantFixedFrame.ui")
|
|
|
|
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
|
|
|
|
|
|
# Array of Posts: ------------------------------------------------------------------------------------------------------
|
|
'''movido a la clase madre
|
|
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 _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 True
|
|
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
|