Punto de restauración.
This commit is contained in:
788
Civil/Fence/PVPlantFence.py
Normal file
788
Civil/Fence/PVPlantFence.py
Normal file
@@ -0,0 +1,788 @@
|
||||
# /**********************************************************************
|
||||
# * *
|
||||
# * 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 FreeCAD
|
||||
import Part
|
||||
import Draft
|
||||
import MeshPart as mp
|
||||
import ArchComponent
|
||||
|
||||
import Civil.Fence.PVPlantFencePost as PVPlantFencePost
|
||||
import PVPlantSite
|
||||
import Utils.PVPlantUtils as utils
|
||||
import copy
|
||||
import math
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
import PySide.QtGui as QtGui
|
||||
from pivy import coin
|
||||
else:
|
||||
# \cond
|
||||
def translate(ctxt, txt):
|
||||
return txt
|
||||
def QT_TRANSLATE_NOOP(ctxt, txt):
|
||||
return txt
|
||||
# \endcond
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
import os
|
||||
from PVPlantResources import DirIcons as DirIcons
|
||||
|
||||
EAST = FreeCAD.Vector(1, 0, 0)
|
||||
|
||||
def makePVPlantFence(section, post, path):
|
||||
obj = FreeCAD.ActiveDocument.addObject('Part::FeaturePython', 'Fence')
|
||||
|
||||
Fence(obj)
|
||||
obj.Post = post
|
||||
obj.Base = path
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
ViewProviderFence(obj.ViewObject)
|
||||
|
||||
hide(section)
|
||||
hide(post)
|
||||
hide(path)
|
||||
|
||||
try:
|
||||
fende_group = FreeCAD.ActiveDocument.Fences
|
||||
except:
|
||||
fende_group = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", 'Fences')
|
||||
fende_group.Label = "Fences"
|
||||
FreeCAD.ActiveDocument.CivilGroup.addObject(fende_group)
|
||||
fende_group.addObject(obj)
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return obj
|
||||
|
||||
def hide(obj):
|
||||
if hasattr(obj, 'ViewObject') and obj.ViewObject:
|
||||
obj.ViewObject.Visibility = False
|
||||
|
||||
def get_parameter_from_v0_old(edge, offset):
|
||||
""" Return parameter at distance offset from edge.Vertexes[0].sb method in Part.TopoShapeEdge??? """
|
||||
import DraftVecUtils
|
||||
|
||||
lpt = edge.valueAt(edge.getParameterByLength(0))
|
||||
vpt = edge.Vertexes[0].Point
|
||||
|
||||
if not DraftVecUtils.equals(vpt, lpt):
|
||||
# this edge is flipped
|
||||
length = edge.Length - offset
|
||||
else:
|
||||
# this edge is right way around
|
||||
length = offset
|
||||
return edge.getParameterByLength(length)
|
||||
|
||||
def get_parameter_from_v0(edge, offset):
|
||||
"""Parámetro a distancia offset desde el primer vértice"""
|
||||
lpt = edge.valueAt(edge.getParameterByLength(0))
|
||||
vpt = edge.Vertexes[0].Point
|
||||
|
||||
if not vpt.isEqual(lpt, 1e-6):
|
||||
return edge.getParameterByLength(edge.Length - offset)
|
||||
return edge.getParameterByLength(offset)
|
||||
|
||||
def calculatePlacement(globalRotation, edge, offset, RefPt, xlate, align, normal=None):
|
||||
placement = FreeCAD.Placement()
|
||||
placement.Rotation = globalRotation
|
||||
placement.move(RefPt + xlate)
|
||||
|
||||
if not align:
|
||||
return placement
|
||||
|
||||
t = edge.tangentAt(get_parameter_from_v0(edge, offset)).normalize()
|
||||
n = normal or FreeCAD.Vector(0, 0, 1)
|
||||
b = t.cross(n).normalize()
|
||||
|
||||
# Asegurar sistema de coordenadas derecho
|
||||
if n.dot(t.cross(b)) < 0:
|
||||
b = -b
|
||||
|
||||
# Construir matriz
|
||||
rotation_matrix = FreeCAD.Matrix(
|
||||
t.x, b.x, n.x, 0,
|
||||
t.y, b.y, n.y, 0,
|
||||
t.z, b.z, n.z, 0,
|
||||
0, 0, 0, 1
|
||||
)
|
||||
|
||||
placement.Rotation = FreeCAD.Rotation(rotation_matrix)
|
||||
return placement
|
||||
|
||||
def calculatePlacementsOnPath(shapeRotation, pathwire, count, xlate, align):
|
||||
""" Calculates the placements of a shape along a given path so that each copy will be distributed evenly
|
||||
- shapeRotation: rotation offset
|
||||
- pathwire: path where place the shapes
|
||||
- count: number of sections
|
||||
- xlate: transformation offset
|
||||
"""
|
||||
import Part
|
||||
import DraftGeomUtils
|
||||
|
||||
closedpath = DraftGeomUtils.isReallyClosed(pathwire)
|
||||
|
||||
normal = FreeCAD.Vector(0, 0, 1)
|
||||
path = Part.__sortEdges__(pathwire.Edges)
|
||||
ends = []
|
||||
cdist = 0
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
totalEdges = len(path)
|
||||
if not closedpath:
|
||||
totalEdges -= 1
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
for e in path: # find cumulative edge end distance
|
||||
cdist += e.Length
|
||||
ends.append(cdist)
|
||||
|
||||
placements = []
|
||||
# place the start shape
|
||||
pt = path[0].Vertexes[0].Point
|
||||
placements.append(calculatePlacement(shapeRotation, path[0], 0, pt, xlate, align, normal))
|
||||
|
||||
# closed path doesn't need shape on last vertex
|
||||
if not closedpath:
|
||||
# place the end shape
|
||||
pt = path[-1].Vertexes[-1].Point
|
||||
placements.append(calculatePlacement(shapeRotation, path[-1], path[-1].Length, pt, xlate, align, normal))
|
||||
|
||||
if count < 3:
|
||||
return placements
|
||||
|
||||
# place the middle shapes
|
||||
if closedpath:
|
||||
stop = count
|
||||
else:
|
||||
stop = count - 1
|
||||
step = float(cdist) / stop
|
||||
travel = step
|
||||
for i in range(1, stop):
|
||||
# which edge in path should contain this shape?
|
||||
# avoids problems with float math travel > ends[-1]
|
||||
iend = len(ends) - 1
|
||||
for j in range(0, len(ends)):
|
||||
if travel <= ends[j]:
|
||||
iend = j
|
||||
break
|
||||
# place shape at proper spot on proper edge
|
||||
remains = ends[iend] - travel
|
||||
offset = path[iend].Length - remains
|
||||
pt = path[iend].valueAt(get_parameter_from_v0(path[iend], offset))
|
||||
placements.append(calculatePlacement(shapeRotation, path[iend], offset, pt, xlate, align, normal))
|
||||
travel += step
|
||||
|
||||
return placements
|
||||
|
||||
class Fence(ArchComponent.Component):
|
||||
def __init__(self, obj):
|
||||
ArchComponent.Component.__init__(self, obj)
|
||||
self.setProperties(obj)
|
||||
self.Posts = []
|
||||
self.Foundations = []
|
||||
|
||||
# Does a IfcType exist?
|
||||
# obj.IfcType = "Fence"
|
||||
|
||||
def setProperties(self, obj):
|
||||
ArchComponent.Component.setProperties(self, obj)
|
||||
|
||||
pl = obj.PropertiesList
|
||||
|
||||
if not "Gate" in pl:
|
||||
obj.addProperty("App::PropertyLinkList",
|
||||
"Gate",
|
||||
"Fence",
|
||||
"A single fence post")
|
||||
|
||||
if not "Post" in pl:
|
||||
obj.addProperty("App::PropertyLink",
|
||||
"Post",
|
||||
"Fence",
|
||||
QT_TRANSLATE_NOOP("App::Property", "A single fence post"))
|
||||
|
||||
if not "Foundation" in pl:
|
||||
obj.addProperty("App::PropertyLength",
|
||||
"Foundation",
|
||||
"Fence",
|
||||
QT_TRANSLATE_NOOP("App::Property", "A single fence post"))
|
||||
|
||||
if not "Depth" in pl:
|
||||
obj.addProperty("App::PropertyLength",
|
||||
"Depth",
|
||||
"Fence",
|
||||
QT_TRANSLATE_NOOP("App::Property", "A single fence post")).Depth = 650
|
||||
|
||||
if not "Gap" in pl:
|
||||
obj.addProperty("App::PropertyLength",
|
||||
"Gap",
|
||||
"Fence",
|
||||
QT_TRANSLATE_NOOP("App::Property", "A single fence post")).Gap = 4000
|
||||
|
||||
if not "Angle" in pl:
|
||||
obj.addProperty("App::PropertyAngle",
|
||||
"Angle",
|
||||
"Fence",
|
||||
QT_TRANSLATE_NOOP("App::Property", "A single fence post")).Angle = 60
|
||||
|
||||
if not "MeshOffsetZ" in pl:
|
||||
obj.addProperty("App::PropertyLength",
|
||||
"MeshOffsetZ",
|
||||
"Fence",
|
||||
QT_TRANSLATE_NOOP("App::Property", "A single fence post")).MeshOffsetZ = 0
|
||||
|
||||
if not "MeshHeight" in pl:
|
||||
obj.addProperty("App::PropertyLength",
|
||||
"MeshHeight",
|
||||
"Fence",
|
||||
QT_TRANSLATE_NOOP("App::Property", "A single fence post")).MeshHeight = 2000
|
||||
|
||||
if not "Reinforce" in pl:
|
||||
obj.addProperty("App::PropertyLength",
|
||||
"Reinforce",
|
||||
"Fence",
|
||||
QT_TRANSLATE_NOOP("App::Property", "A single fence post")).Reinforce = 50000
|
||||
|
||||
|
||||
########## Datos informativos:
|
||||
if not "NumberOfSections" in pl:
|
||||
obj.addProperty("App::PropertyQuantity",
|
||||
"NumberOfSections",
|
||||
"Output",
|
||||
QT_TRANSLATE_NOOP("App::Property", "The number of sections the fence is built of"))
|
||||
obj.setEditorMode("NumberOfSections", 1)
|
||||
|
||||
if not "NumberOfPosts" in pl:
|
||||
obj.addProperty("App::PropertyQuantity",
|
||||
"NumberOfPosts",
|
||||
"Output",
|
||||
QT_TRANSLATE_NOOP("App::Property", "The number of posts used to build the fence"))
|
||||
obj.setEditorMode("NumberOfPosts", 1)
|
||||
|
||||
if not "Length" in pl:
|
||||
obj.addProperty("App::PropertyLength",
|
||||
"Length",
|
||||
"Output",
|
||||
QT_TRANSLATE_NOOP("App::Property", "The number of posts used to build the fence"))
|
||||
obj.setEditorMode("Length", 1)
|
||||
|
||||
if not "Concrete" in pl:
|
||||
obj.addProperty("App::PropertyVolume",
|
||||
"Concrete",
|
||||
"Output",
|
||||
"Concrete Volume")
|
||||
obj.setEditorMode("Concrete", 1)
|
||||
|
||||
if not "PlacementList" in pl:
|
||||
obj.addProperty("App::PropertyPlacementList",
|
||||
"PlacementList",
|
||||
"Output",
|
||||
QT_TRANSLATE_NOOP("App::Property", "The number of posts used to build the fence"))
|
||||
obj.setEditorMode("Length", 1)
|
||||
|
||||
self.Type = "PVPlatFence"
|
||||
|
||||
def __getstate__(self):
|
||||
if hasattr(self, 'sectionFaceNumbers'):
|
||||
return (self.sectionFaceNumbers)
|
||||
return None
|
||||
|
||||
def __setstate__(self, state):
|
||||
if state is not None and isinstance(state, tuple):
|
||||
self.sectionFaceNumbers = state[0]
|
||||
return None
|
||||
|
||||
def execute(self, obj):
|
||||
if not obj.Base or not obj.Post:
|
||||
return
|
||||
|
||||
# 1. Preparar trazado base
|
||||
pathwire = self.calculatePathWire(obj)
|
||||
pathwire = utils.getProjected(pathwire, FreeCAD.Vector(0, 0, 1))
|
||||
pathwire = utils.simplifyWire(pathwire)
|
||||
if not pathwire or not pathwire.Edges:
|
||||
return
|
||||
|
||||
# 2. Proyectar sobre terreno (con caché)
|
||||
self.Posts = []
|
||||
self.Foundations = []
|
||||
|
||||
site = PVPlantSite.get()
|
||||
segments = mp.projectShapeOnMesh(pathwire, site.Terrain.Mesh, FreeCAD.Vector(0, 0, 1))
|
||||
points=[]
|
||||
for segment in segments:
|
||||
points.extend(segment)
|
||||
pathwire = Part.makePolygon(points)
|
||||
|
||||
if pathwire is None:
|
||||
return
|
||||
|
||||
sectionLength = obj.Gap.Value
|
||||
postLength = 0 #obj.Post.Diameter.Value #considerarlo 0 porque no influye
|
||||
postPlacements = []
|
||||
pathsegments = self.calculateSegments(obj, pathwire)
|
||||
|
||||
count = 0
|
||||
drawFirstPost = True
|
||||
pathLength = 0
|
||||
for segment in pathsegments:
|
||||
segwire = Part.Wire(Part.__sortEdges__(segment))
|
||||
pathLength += segwire.Length
|
||||
|
||||
obj.NumberOfSections = self.calculateNumberOfSections(segwire.Length, sectionLength, postLength)
|
||||
obj.NumberOfPosts = obj.NumberOfSections + 1
|
||||
|
||||
count += obj.NumberOfSections
|
||||
|
||||
downRotation = FreeCAD.Rotation(FreeCAD.Vector(1, 0, 0), -90)
|
||||
placements = self.calculatePostPlacements(obj, segwire, downRotation)
|
||||
|
||||
if drawFirstPost:
|
||||
drawFirstPost = False
|
||||
else:
|
||||
placements.pop(0)
|
||||
|
||||
postPlacements.extend(placements)
|
||||
|
||||
# 5. Generar geometría
|
||||
postShapes, postFoundation = self.calculatePosts(obj, postPlacements)
|
||||
mesh = self.calculate_sections(obj, postPlacements)
|
||||
|
||||
postShapes = Part.makeCompound(postShapes)
|
||||
postFoundation = Part.makeCompound(postFoundation)
|
||||
|
||||
# 6. Crear forma final
|
||||
obj.Shape = Part.makeCompound([postShapes, postFoundation, mesh])
|
||||
|
||||
# 7. Actualizar propiedades
|
||||
obj.NumberOfSections = count
|
||||
obj.NumberOfPosts = count + 1
|
||||
obj.Length = pathLength
|
||||
obj.Concrete = count * postFoundation.SubShapes[0].Volume
|
||||
|
||||
def calculateSegments(self, obj, pathwire):
|
||||
''' Calcular los segmentos de la ruta '''
|
||||
import math
|
||||
segments = []
|
||||
segment = [pathwire.Edges[0]]
|
||||
segments.append(segment)
|
||||
for ind in range(len(pathwire.Edges) - 1):
|
||||
ed1 = pathwire.Edges[ind]
|
||||
ed2 = pathwire.Edges[ind + 1]
|
||||
vec1 = ed1.Vertexes[1].Point - ed1.Vertexes[0].Point
|
||||
vec2 = ed2.Vertexes[1].Point - ed2.Vertexes[0].Point
|
||||
angle = math.degrees(vec1.getAngle(vec2))
|
||||
if angle > obj.Angle.Value:
|
||||
segment = []
|
||||
segments.append(segment)
|
||||
segment.append(ed2)
|
||||
return segments
|
||||
|
||||
def calculateNumberOfSections(self, pathLength, sectionLength, postLength):
|
||||
withoutLastPost = pathLength - postLength
|
||||
realSectionLength = sectionLength + postLength
|
||||
return math.ceil(withoutLastPost / realSectionLength)
|
||||
|
||||
def calculatePostPlacements(self, obj, pathwire, rotation):
|
||||
postWidth = obj.Post.Diameter.Value
|
||||
transformationVector = FreeCAD.Vector(0, - postWidth / 2, 0)
|
||||
placements = calculatePlacementsOnPath(rotation, pathwire, int(obj.NumberOfSections) + 1, transformationVector, True)
|
||||
# The placement of the last object is always the second entry in the list.
|
||||
# So we move it to the end:
|
||||
if len(placements) > 1:
|
||||
placements.append(placements.pop(1))
|
||||
return placements
|
||||
|
||||
def calculatePosts(self, obj, postPlacements):
|
||||
posts = []
|
||||
foundations = []
|
||||
for placement in postPlacements:
|
||||
new_post = obj.Post.Shape.copy()
|
||||
new_post = Part.Solid(new_post)
|
||||
new_post.Placement = placement
|
||||
new_post.Placement.Base.z += 100
|
||||
posts.append(new_post)
|
||||
|
||||
foundation = Part.makeCylinder(150, 700)
|
||||
foundation.Placement = placement
|
||||
foundation.Placement.Base.z -= obj.Depth.Value
|
||||
#foundation = foundation.cut(new_post)
|
||||
foundations.append(foundation)
|
||||
|
||||
return posts, foundations
|
||||
|
||||
def calculate_sections(self, obj, postPlacements):
|
||||
offsetz = FreeCAD.Vector(0, 0, obj.MeshOffsetZ.Value)
|
||||
meshHeight = FreeCAD.Vector(0, 0, obj.MeshHeight.Value)
|
||||
|
||||
points_down = []
|
||||
points_up = []
|
||||
for i in range(len(postPlacements) - 1):
|
||||
p1 = postPlacements[i].Base + offsetz
|
||||
p2 = postPlacements[i + 1].Base + offsetz
|
||||
p3 = p1 + meshHeight
|
||||
p4 = p2 + meshHeight
|
||||
points_down.extend([p1, p2])
|
||||
points_up.extend([p3, p4])
|
||||
|
||||
shape = Part.makeRuledSurface(Part.makePolygon(points_down), Part.makePolygon(points_up))
|
||||
return shape
|
||||
|
||||
def calculatePathWire(self, obj):
|
||||
if obj.Base:
|
||||
wire = None
|
||||
if hasattr(obj.Base.Shape, 'Wires') and obj.Base.Shape.Wires:
|
||||
wire = obj.Base.Shape.Wires[0]
|
||||
elif obj.Base.Shape.Edges:
|
||||
wire = Part.Wire(obj.Base.Shape.Edges)
|
||||
return wire
|
||||
return None
|
||||
|
||||
|
||||
class ViewProviderFence(ArchComponent.ViewProviderComponent):
|
||||
"A View Provider for the Fence object"
|
||||
|
||||
def __init__(self, vobj):
|
||||
ArchComponent.ViewProviderComponent.__init__(self, vobj)
|
||||
vobj.Proxy = self
|
||||
#vobj.addExtension("Gui::ViewProviderGroupExtensionPython")
|
||||
|
||||
def getIcon(self):
|
||||
return str(os.path.join(DirIcons, "fence.svg"))
|
||||
|
||||
def attach(self, vobj):
|
||||
'''
|
||||
Create Object visuals in 3D view.
|
||||
'''
|
||||
|
||||
self.Object = vobj.Object
|
||||
|
||||
# GeoCoords Node.
|
||||
self.geo_coords = coin.SoGeoCoordinate()
|
||||
|
||||
# Surface features.
|
||||
self.triangles = coin.SoIndexedFaceSet()
|
||||
self.face_material = coin.SoMaterial()
|
||||
self.edge_material = coin.SoMaterial()
|
||||
self.edge_color = coin.SoBaseColor()
|
||||
self.edge_style = coin.SoDrawStyle()
|
||||
self.edge_style.style = coin.SoDrawStyle.LINES
|
||||
|
||||
shape_hints = coin.SoShapeHints()
|
||||
shape_hints.vertex_ordering = coin.SoShapeHints.COUNTERCLOCKWISE
|
||||
mat_binding = coin.SoMaterialBinding()
|
||||
mat_binding.value = coin.SoMaterialBinding.PER_FACE
|
||||
offset = coin.SoPolygonOffset()
|
||||
|
||||
# Face root.
|
||||
faces = coin.SoSeparator()
|
||||
faces.addChild(shape_hints)
|
||||
faces.addChild(self.face_material)
|
||||
faces.addChild(mat_binding)
|
||||
faces.addChild(self.geo_coords)
|
||||
faces.addChild(self.triangles)
|
||||
|
||||
# Highlight for selection.
|
||||
highlight = coin.SoType.fromName('SoFCSelection').createInstance()
|
||||
highlight.style = 'EMISSIVE_DIFFUSE'
|
||||
faces.addChild(shape_hints)
|
||||
highlight.addChild(self.edge_material)
|
||||
highlight.addChild(mat_binding)
|
||||
highlight.addChild(self.edge_style)
|
||||
highlight.addChild(self.geo_coords)
|
||||
highlight.addChild(self.triangles)
|
||||
|
||||
def updateData(self, obj, prop):
|
||||
'''
|
||||
Update Object visuals when a data property changed.
|
||||
'''
|
||||
origin = PVPlantSite.get()
|
||||
base = copy.deepcopy(origin.Origin)
|
||||
base.z = 0
|
||||
#print(" - Propiedad: ", prop)
|
||||
if prop == "Shape":
|
||||
shape = obj.getPropertyByName(prop)
|
||||
# Get GeoOrigin.
|
||||
points = [ver.Point for ver in shape.Vertexes]
|
||||
# Set GeoCoords.
|
||||
geo_system = ["UTM", origin.UtmZone, "FLAT"]
|
||||
self.geo_coords.geoSystem.setValues(geo_system)
|
||||
self.geo_coords.point.values = points
|
||||
|
||||
def claimChildren(self):
|
||||
children = []
|
||||
if self.Object.Post:
|
||||
children.append(self.Object.Post)
|
||||
if self.Object.Base:
|
||||
children.append(self.Object.Base)
|
||||
if self.Object.Gate:
|
||||
children.append(self.Object.Gate)
|
||||
return children
|
||||
|
||||
class FenceTaskPanel:
|
||||
'''The TaskPanel to setup the fence'''
|
||||
|
||||
def __init__(self):
|
||||
self.section = None
|
||||
self.post = None
|
||||
self.path = None
|
||||
|
||||
# form: -----------------------------------------------------------------------------------
|
||||
self.formFence = QtGui.QWidget()
|
||||
self.formFence.resize(800, 640)
|
||||
self.formFence.setWindowTitle("Fence setup")
|
||||
self.formFence.setWindowIcon(QtGui.QIcon(os.path.join(DirIcons, "contours.svg")))
|
||||
self.grid = QtGui.QGridLayout(self.formFence)
|
||||
|
||||
# parameters
|
||||
self.labelPath = QtGui.QLabel()
|
||||
self.labelPath.setText("Recorrido:")
|
||||
self.linePath = QtGui.QLineEdit(self.formFence)
|
||||
self.linePath.setObjectName(_fromUtf8("lineEdit1"))
|
||||
self.linePath.readOnly = True
|
||||
self.grid.addWidget(self.labelPath, self.grid.rowCount(), 0, 1, 1)
|
||||
self.grid.addWidget(self.linePath, self.grid.rowCount() - 1, 1, 1, 1)
|
||||
|
||||
self.buttonPathSelect = QtGui.QPushButton('Add')
|
||||
self.grid.addWidget(self.buttonPathSelect, self.grid.rowCount() - 1, 2, 1, 1)
|
||||
|
||||
self.line1 = QtGui.QFrame()
|
||||
self.line1.setFrameShape(QtGui.QFrame.HLine)
|
||||
self.line1.setFrameShadow(QtGui.QFrame.Sunken)
|
||||
self.grid.addWidget(self.line1, self.grid.rowCount(), 0, 1, -1)
|
||||
|
||||
self.label = QtGui.QLabel()
|
||||
self.label.setText("Separación entre apoyos:")
|
||||
self.grid.addWidget(self.label, self.grid.rowCount(), 0, 1, -1)
|
||||
|
||||
self.labelInterval = QtGui.QLabel()
|
||||
self.labelInterval.setText("Intervalo:")
|
||||
self.valueInterval = FreeCADGui.UiLoader().createWidget("Gui::InputField")
|
||||
self.valueInterval.setText("4,0 m")
|
||||
self.grid.addWidget(self.labelInterval, self.grid.rowCount(), 0, 1, 1)
|
||||
self.grid.addWidget(self.valueInterval, self.grid.rowCount() - 1, 1, 1, 2)
|
||||
|
||||
self.line1 = QtGui.QFrame()
|
||||
self.line1.setFrameShape(QtGui.QFrame.HLine)
|
||||
self.line1.setFrameShadow(QtGui.QFrame.Sunken)
|
||||
self.grid.addWidget(self.line1, self.grid.rowCount(), 0, 1, -1)
|
||||
|
||||
self.label = QtGui.QLabel()
|
||||
self.label.setText("Mayado:")
|
||||
self.grid.addWidget(self.label, self.grid.rowCount(), 0, 1, -1)
|
||||
|
||||
self.labelHeight = QtGui.QLabel()
|
||||
self.labelHeight.setText("Altura:")
|
||||
self.valueHeight = FreeCADGui.UiLoader().createWidget("Gui::InputField")
|
||||
self.valueHeight.setText("2 m")
|
||||
self.grid.addWidget(self.labelHeight, self.grid.rowCount(), 0, 1, 1)
|
||||
self.grid.addWidget(self.valueHeight, self.grid.rowCount() - 1, 1, 1, 2)
|
||||
|
||||
self.labelOffset = QtGui.QLabel()
|
||||
self.labelOffset.setText("Separación del suelo:")
|
||||
self.valueOffset = FreeCADGui.UiLoader().createWidget("Gui::InputField")
|
||||
self.valueOffset.setText("0 m")
|
||||
self.grid.addWidget(self.labelOffset, self.grid.rowCount(), 0, 1, 1)
|
||||
self.grid.addWidget(self.valueOffset, self.grid.rowCount() - 1, 1, 1, 2)
|
||||
|
||||
self.buttonPathSelect.clicked.connect(self.addPath)
|
||||
self.valueInterval.valueChanged.connect(self.SetupGrid)
|
||||
self.valueHeight.valueChanged.connect(self.SetupGrid)
|
||||
# self.valueDepth.valueChanged.connect(self.SetupPost)
|
||||
|
||||
# Form para configurar el poste: -------------------------------------------------------------------
|
||||
self.formPost = QtGui.QWidget()
|
||||
self.formPost.resize(800, 640)
|
||||
self.formPost.setWindowTitle("Post setup")
|
||||
self.formPost.setWindowIcon(QtGui.QIcon(os.path.join(DirIcons, "contours.svg")))
|
||||
self.grid = QtGui.QGridLayout(self.formPost)
|
||||
|
||||
# parameters
|
||||
self.labelDiameter = QtGui.QLabel()
|
||||
self.labelDiameter.setText("Diámetro:")
|
||||
self.valueDiameter = FreeCADGui.UiLoader().createWidget("Gui::InputField")
|
||||
self.valueDiameter.setText("48 mm")
|
||||
self.grid.addWidget(self.labelDiameter, self.grid.rowCount(), 0, 1, 1)
|
||||
self.grid.addWidget(self.valueDiameter, self.grid.rowCount() - 1, 1, 1, 1)
|
||||
|
||||
self.labelLength = QtGui.QLabel()
|
||||
self.labelLength.setText("Longitud:")
|
||||
self.valueLength = FreeCADGui.UiLoader().createWidget("Gui::InputField")
|
||||
self.valueLength.setText("3,0 m")
|
||||
self.grid.addWidget(self.labelLength, self.grid.rowCount(), 0, 1, 1)
|
||||
self.grid.addWidget(self.valueLength, self.grid.rowCount() - 1, 1, 1, 1)
|
||||
|
||||
self.labelDepth = QtGui.QLabel()
|
||||
self.labelDepth.setText("Profundidad:")
|
||||
self.valueDepth = FreeCADGui.UiLoader().createWidget("Gui::InputField")
|
||||
self.valueDepth.setText("700,0 mm")
|
||||
self.grid.addWidget(self.labelDepth, self.grid.rowCount(), 0, 1, 1)
|
||||
self.grid.addWidget(self.valueDepth, self.grid.rowCount() - 1, 1, 1, 1)
|
||||
|
||||
self.valueDiameter.valueChanged.connect(self.SetupPost)
|
||||
self.valueLength.valueChanged.connect(self.SetupPost)
|
||||
self.valueDepth.valueChanged.connect(self.SetupPost)
|
||||
|
||||
# Form para configurar la zapata: ----------------------------------------------------------
|
||||
self.formFoundation = QtGui.QWidget()
|
||||
self.formFoundation.resize(800, 640)
|
||||
self.formFoundation.setWindowTitle("Post setup")
|
||||
self.formFoundation.setWindowIcon(QtGui.QIcon(os.path.join(DirIcons, "contours.svg")))
|
||||
self.grid = QtGui.QGridLayout(self.formFoundation)
|
||||
|
||||
# parameters
|
||||
self.labelFoundationDiameter = QtGui.QLabel()
|
||||
self.labelFoundationDiameter.setText("Cimentación:")
|
||||
self.grid.addWidget(self.labelFoundationDiameter, self.grid.rowCount(), 0, 1, 1)
|
||||
|
||||
self.labelFoundationDiameter = QtGui.QLabel()
|
||||
self.labelFoundationDiameter.setText("Diámetro:")
|
||||
self.valueFoundationDiameter = FreeCADGui.UiLoader().createWidget("Gui::InputField")
|
||||
self.valueFoundationDiameter.setText("200,0 mm")
|
||||
self.grid.addWidget(self.labelFoundationDiameter, self.grid.rowCount(), 0, 1, 1)
|
||||
self.grid.addWidget(self.valueFoundationDiameter, self.grid.rowCount() - 1, 1, 1, 1)
|
||||
|
||||
self.labelFoundationDepth = QtGui.QLabel()
|
||||
self.labelFoundationDepth.setText("Profundidad:")
|
||||
self.valueFoundationDepth = FreeCADGui.UiLoader().createWidget("Gui::InputField")
|
||||
self.valueFoundationDepth.setText("700,0 mm")
|
||||
self.grid.addWidget(self.labelFoundationDepth, self.grid.rowCount(), 0, 1, 1)
|
||||
self.grid.addWidget(self.valueFoundationDepth, self.grid.rowCount() - 1, 1, 1, 1)
|
||||
|
||||
self.form = [self.formFence, self.formPost, self.formFoundation]
|
||||
|
||||
# valores iniciales y creación del la valla:
|
||||
self.post = PVPlantFencePost.makeFencePost()
|
||||
self.post.Label = "Post"
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
self.fence = makePVPlantFence(self.section, self.post, self.path)
|
||||
|
||||
def addPath(self):
|
||||
sel = FreeCADGui.Selection.getSelection()
|
||||
if len(sel) > 0:
|
||||
self.path = sel[0]
|
||||
self.linePath.setText(self.path.Label)
|
||||
self.fence.Base = self.path
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
def SetupPost(self):
|
||||
if self.post.Diameter != FreeCAD.Units.Quantity(self.valueDiameter.text()).Value:
|
||||
self.post.Diameter = FreeCAD.Units.Quantity(self.valueDiameter.text()).Value
|
||||
if self.post.Length != FreeCAD.Units.Quantity(self.valueLength.text()).Value:
|
||||
self.post.Length = FreeCAD.Units.Quantity(self.valueLength.text()).Value
|
||||
|
||||
if self.post.Placement.Base.z != -FreeCAD.Units.Quantity(self.valueDepth.text()).Value:
|
||||
self.post.Placement.Base.z = -FreeCAD.Units.Quantity(self.valueDepth.text()).Value
|
||||
self.fence.Depth = FreeCAD.Units.Quantity(self.valueDepth.text()).Value
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
def SetupGrid(self):
|
||||
return
|
||||
if self.path.End.x != FreeCAD.Units.Quantity(self.valueInterval.text()).Value:
|
||||
self.path.End.x = FreeCAD.Units.Quantity(self.valueInterval.text()).Value
|
||||
if self.section.LengthFwd != FreeCAD.Units.Quantity(self.valueHeight.text()).Value:
|
||||
self.section.LengthFwd = FreeCAD.Units.Quantity(self.valueHeight.text()).Value
|
||||
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
def makeGrid(self):
|
||||
return None
|
||||
|
||||
import Draft
|
||||
|
||||
p1 = FreeCAD.Vector(0, 0, 0)
|
||||
p2 = FreeCAD.Vector(4000, 0, 0)
|
||||
line = Draft.makeLine(p1, p2)
|
||||
|
||||
section = FreeCAD.ActiveDocument.addObject('Part::Extrusion', 'Extrude')
|
||||
section.Base = line
|
||||
section.DirMode = "Custom"
|
||||
section.Dir = FreeCAD.Vector(0.0, 0.0, 1.0)
|
||||
section.DirLink = None
|
||||
section.LengthFwd = 2000.0
|
||||
section.LengthRev = 0.0
|
||||
section.Solid = False
|
||||
section.Reversed = False
|
||||
section.Symmetric = False
|
||||
section.TaperAngle = 0.0
|
||||
section.TaperAngleRev = 0.0
|
||||
line.Visibility = False
|
||||
|
||||
return section
|
||||
|
||||
|
||||
# Commands ---------------------------------------------------------------------------------
|
||||
class CommandPVPlantFence:
|
||||
"the PVPlant Fence command definition"
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap': str(os.path.join(DirIcons, "fence.svg")),
|
||||
'Accel': "C, F",
|
||||
'MenuText': QT_TRANSLATE_NOOP("PVPlantFence", "Fence"),
|
||||
'ToolTip': QT_TRANSLATE_NOOP("PVPlantFence",
|
||||
"Creates a fence object from a selected section, post and path")}
|
||||
|
||||
def IsActive(self):
|
||||
return not FreeCAD.ActiveDocument is None
|
||||
|
||||
def Activated(self):
|
||||
self.TaskPanel = FenceTaskPanel()
|
||||
FreeCADGui.Control.showDialog(self.TaskPanel)
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
class CommandFenceGroup:
|
||||
def GetCommands(self):
|
||||
return tuple(['PVPlantFence',
|
||||
'PVPlantGate',
|
||||
'PVPlantFencePost'
|
||||
])
|
||||
|
||||
def GetResources(self):
|
||||
return {'MenuText': QT_TRANSLATE_NOOP("", 'PVPlantFence'),
|
||||
'ToolTip': QT_TRANSLATE_NOOP("", 'PVPlantFence')
|
||||
}
|
||||
|
||||
def IsActive(self):
|
||||
site = FreeCAD.ActiveDocument.getObject("Site")
|
||||
return (not (FreeCAD.ActiveDocument is None) and
|
||||
not (site is None) and
|
||||
not (site.Terrain is None))
|
||||
|
||||
import Civil.Fence.PVPlantFenceGate as PVPlantFenceGate
|
||||
FreeCADGui.addCommand('PVPlantFence', CommandPVPlantFence())
|
||||
FreeCADGui.addCommand('PVPlantGate', PVPlantFenceGate.CommandPVPlantGate())
|
||||
FreeCADGui.addCommand('PVPlantFencePost', PVPlantFencePost.CommandFencePost())
|
||||
#FreeCADGui.addCommand('PVPlantFenceGroup', CommandFenceGroup())
|
||||
768
Civil/Fence/PVPlantFence.ui
Normal file
768
Civil/Fence/PVPlantFence.ui
Normal file
@@ -0,0 +1,768 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>formRack</class>
|
||||
<widget class="QDialog" name="formRack">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>476</width>
|
||||
<height>641</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Fixed Frame:</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Configuración de la valla</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="horizontalSpacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QDoubleSpinBox" name="editModuleLenght">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>5.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.960000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Separación entre apoyos (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Recorrido:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Configuración del poste</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Columnas (un)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QDoubleSpinBox" name="editFrontHeight">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>5.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.800000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Orientación del módulo</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QDoubleSpinBox" name="editVerticalGap">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>0.900000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.020000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="editRows">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboFrameType">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Fija</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Tracker 1 Eje</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QDoubleSpinBox" name="editLeftOffset">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>0.900000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.050000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Offset borde derecha (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Ángulo de inclinación (º)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QDoubleSpinBox" name="editRightOffset">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>0.900000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.050000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QSpinBox" name="editTilt">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>60</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QSpinBox" name="editInclination">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>60</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Filas (un)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Distancia al suelo en el frente (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="editCols">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="labelVerticalGap">
|
||||
<property name="text">
|
||||
<string>Separación vertical entre módulos (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboModuleOrientation">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Landscape</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Portrait</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Separación horizontal entre módulos (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Ängulo máximo de inclinación longitudinal (ª)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QDoubleSpinBox" name="editHorizontalGap">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>0.900000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.020000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Tipo de estructura</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Offset borde izquierda (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0" colspan="2">
|
||||
<widget class="QWidget" name="widgetTracker" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelVerticalGap_2">
|
||||
<property name="text">
|
||||
<string>Separación entre uniones (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<property name="text">
|
||||
<string>Separación Motor (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="editInternalGapNumber">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>Número de uniones</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="editInternalGap">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>0.900000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.020000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="editMotorGap">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>0.900000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.020000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Cimentación</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Total de módulos</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="editTotalModules">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Potencia total (wp)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="editTotalPower">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Longitud (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="editTotalLength">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Anchura (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="editTotalWidth">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
427
Civil/Fence/PVPlantFenceGate.py
Normal file
427
Civil/Fence/PVPlantFenceGate.py
Normal file
@@ -0,0 +1,427 @@
|
||||
# /**********************************************************************
|
||||
# * *
|
||||
# * 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 ArchComponent
|
||||
import FreeCAD
|
||||
import Part
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui, QtSvg
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
import PySide.QtGui as QtGui
|
||||
import draftguitools.gui_trackers as DraftTrackers
|
||||
else:
|
||||
# \cond
|
||||
def translate(ctxt, txt):
|
||||
return txt
|
||||
|
||||
def QT_TRANSLATE_NOOP(ctxt, txt):
|
||||
return txt
|
||||
# \endcond
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
import os
|
||||
import PVPlantResources
|
||||
from PVPlantResources import DirIcons as DirIcons
|
||||
|
||||
def makePVPlantFence():
|
||||
obj = FreeCAD.ActiveDocument.addObject('Part::FeaturePython', 'FenceGate')
|
||||
FenceGate(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
ViewProviderGate(obj.ViewObject)
|
||||
return obj
|
||||
|
||||
|
||||
class FenceGate(ArchComponent.Component):
|
||||
def __init__(self, obj):
|
||||
ArchComponent.Component.__init__(self, obj)
|
||||
self.setProperties(obj)
|
||||
|
||||
def setProperties(self, obj):
|
||||
pl = obj.PropertiesList
|
||||
|
||||
if not ("GateType" in pl):
|
||||
obj.addProperty("App::PropertyEnumeration",
|
||||
"GateType",
|
||||
"Gate",
|
||||
QT_TRANSLATE_NOOP("App::Property",
|
||||
"The facemaker type to use to build the profile of this object")
|
||||
).GateType = ["Single", "Double"]
|
||||
|
||||
if not ("GateWidth" in pl):
|
||||
obj.addProperty("App::PropertyDistance",
|
||||
"GateWidth",
|
||||
"Gate",
|
||||
"Base wire"
|
||||
).GateWidth = 3000
|
||||
|
||||
if not ("GateHeight" in pl):
|
||||
obj.addProperty("App::PropertyDistance",
|
||||
"GateHeight",
|
||||
"Gate",
|
||||
"Base wire"
|
||||
).GateHeight = 2000
|
||||
|
||||
if not ("PostWidth" in pl):
|
||||
obj.addProperty("App::PropertyDistance",
|
||||
"PostWidth",
|
||||
"Gate",
|
||||
"Base wire"
|
||||
).PostWidth = 60
|
||||
|
||||
if not ("PostHeight" in pl):
|
||||
obj.addProperty("App::PropertyDistance",
|
||||
"PostHeight",
|
||||
"Gate",
|
||||
"Base wire"
|
||||
).PostHeight = 2000
|
||||
|
||||
if not "PostDepth" in pl:
|
||||
obj.addProperty("App::PropertyLength",
|
||||
"PostDepth",
|
||||
"Fence",
|
||||
"A single fence post").PostDepth = 700
|
||||
|
||||
self.Type = "PVPlatFenceGate"
|
||||
#obj.Type = self.Type
|
||||
obj.Proxy = self
|
||||
self.obj = obj
|
||||
|
||||
def __getstate__(self):
|
||||
if hasattr(self, 'sectionFaceNumbers'):
|
||||
return (self.sectionFaceNumbers)
|
||||
return None
|
||||
|
||||
def __setstate__(self, state):
|
||||
if state is not None and isinstance(state, tuple):
|
||||
self.sectionFaceNumbers = state[0]
|
||||
return None
|
||||
|
||||
def onDocumentRestored(self, obj):
|
||||
"""Method run when the document is restored."""
|
||||
self.setProperties(obj)
|
||||
|
||||
def onChanged(self, obj, prop):
|
||||
'''Do something when a property has changed'''
|
||||
|
||||
def execute(self, obj):
|
||||
tubewidth = 50
|
||||
gap = 20
|
||||
posts = Part.makeCompound([])
|
||||
gates = Part.makeCompound([])
|
||||
pl = obj.Placement
|
||||
|
||||
post = Part.makeBox(obj.PostWidth.Value,
|
||||
obj.PostWidth.Value,
|
||||
obj.PostHeight.Value + obj.PostDepth.Value)
|
||||
|
||||
gate = Part.makeBox(obj.GateWidth.Value,
|
||||
tubewidth,
|
||||
obj.GateHeight.Value)
|
||||
|
||||
cut = Part.makeBox(obj.GateWidth.Value - tubewidth * 2,
|
||||
tubewidth,
|
||||
obj.GateHeight.Value - tubewidth * 2)
|
||||
cut.Placement.Base += FreeCAD.Vector(tubewidth, 0, tubewidth)
|
||||
gate = gate.cut(cut)
|
||||
|
||||
if obj.GateType == "Single":
|
||||
post.Placement.Base = FreeCAD.Vector(-(obj.PostWidth.Value + gap + obj.GateWidth.Value / 2),
|
||||
-obj.PostWidth.Value / 2,
|
||||
-obj.PostDepth.Value)
|
||||
posts.add(post)
|
||||
post = post.copy()
|
||||
post.Placement.Base.x = -(post.Placement.Base.x + obj.PostWidth.Value)
|
||||
posts.add(post)
|
||||
gate.Placement.Base += FreeCAD.Vector(-obj.GateWidth.Value / 2,
|
||||
obj.PostWidth.Value / 2 - tubewidth,
|
||||
0)
|
||||
gates.add(gate)
|
||||
else:
|
||||
post.Placement.Base = FreeCAD.Vector(-(obj.PostWidth.Value + gap * 1.5 + obj.GateWidth.Value),
|
||||
-obj.PostWidth.Value / 2,
|
||||
-obj.PostDepth.Value)
|
||||
posts.add(post)
|
||||
post = post.copy()
|
||||
post.Placement.Base.x = -(post.Placement.Base.x + obj.PostWidth.Value)
|
||||
posts.add(post)
|
||||
|
||||
gate.Placement.Base += FreeCAD.Vector(-(obj.GateWidth.Value + gap * 0.5),
|
||||
obj.PostWidth.Value / 2 - tubewidth,
|
||||
0)
|
||||
gates.add(gate)
|
||||
gate = gate.copy()
|
||||
gate.Placement.Base.x = gap * 0.5
|
||||
gates.add(gate)
|
||||
|
||||
obj.Shape = Part.makeCompound([gates, posts])
|
||||
obj.Placement = pl
|
||||
|
||||
|
||||
class ViewProviderGate:
|
||||
def __init__(self, vobj):
|
||||
''' Set view properties. '''
|
||||
vobj.Proxy = self
|
||||
|
||||
def attach(self, vobj):
|
||||
self.Object = vobj.Object
|
||||
|
||||
def getIcon(self):
|
||||
''' Return object treeview icon. '''
|
||||
return str(os.path.join(DirIcons, "gate.svg"))
|
||||
|
||||
def claimChildren(self):
|
||||
""" Provides object grouping """
|
||||
children = []
|
||||
if self.Object.Base:
|
||||
children.append(self.Object.Base)
|
||||
return children
|
||||
|
||||
class CommandPVPlantGate:
|
||||
"the PVPlant Fence command definition"
|
||||
|
||||
def __init__(self):
|
||||
''' p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||
self.Thickness = p.GetFloat("WindowThickness", 50)
|
||||
self.Width = p.GetFloat("WindowWidth", 1000)
|
||||
self.Height = p.GetFloat("DoorHeight", 2100)'''
|
||||
|
||||
self.Width = 0
|
||||
self.Height = 0
|
||||
self.Length = 0
|
||||
self.tracker = None
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap': str(os.path.join(DirIcons, "gate.svg")),
|
||||
'Accel': "C, F",
|
||||
'MenuText': QT_TRANSLATE_NOOP("PVPlantFence", "Gate"),
|
||||
'ToolTip': QT_TRANSLATE_NOOP("PVPlantFence",
|
||||
"Creates a fence object from a selected section, post and path")}
|
||||
|
||||
def IsActive(self):
|
||||
return not FreeCAD.ActiveDocument is None
|
||||
|
||||
def Activated(self):
|
||||
self.tracker = DraftTrackers.boxTracker()
|
||||
self.tracker.length(self.Length)
|
||||
self.tracker.width(self.Width)
|
||||
self.tracker.height(self.Height)
|
||||
self.tracker.on()
|
||||
FreeCAD.Console.PrintMessage("Choose a face on an existing object or select a preset" + "\n")
|
||||
FreeCADGui.Snapper.getPoint(callback=self.getPoint,
|
||||
movecallback=self.update,
|
||||
extradlg=self.taskbox())
|
||||
|
||||
def getPoint(self, point=None, obj=None):
|
||||
"this function is called by the snapper when it has a 3D point"
|
||||
|
||||
if obj.Name[:5] == "Fence":
|
||||
self.tracker.finalize()
|
||||
if point is None:
|
||||
return
|
||||
ver = Part.Vertex(point)
|
||||
dist = ver.distToShape(obj.Base.Shape)
|
||||
point1 = dist[1][0][1]
|
||||
ed = None
|
||||
if dist[2][0][3] == "Edge":
|
||||
ed = obj.Base.Shape.Edges[int(dist[-1][0][4])]
|
||||
vec = ed.Vertexes[1].Point.sub(ed.Vertexes[0].Point)
|
||||
|
||||
FreeCAD.ActiveDocument.openTransaction("Create Gate")
|
||||
gate = makePVPlantFence()
|
||||
try:
|
||||
import MeshPart as mp
|
||||
import PVPlantSite
|
||||
site = PVPlantSite.get()
|
||||
point1 = mp.projectPointsOnMesh([point1,], site.Terrain.Mesh, FreeCAD.Vector(0, 0, 1))[0]
|
||||
|
||||
except:
|
||||
FreeCAD.Console.PrintError("No se puede encontrar punto 3D.." + "\n")
|
||||
pass
|
||||
|
||||
gate.Placement.Base = point1
|
||||
gate.Placement.Rotation = FreeCAD.Rotation(FreeCAD.Vector(-1, 0, 0), vec)
|
||||
tmp = obj.Gate
|
||||
tmp.append(gate)
|
||||
obj.Gate = tmp
|
||||
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
return
|
||||
else:
|
||||
FreeCADGui.Snapper.getPoint(callback=self.getPoint,
|
||||
movecallback=self.update,
|
||||
extradlg=self.taskbox())
|
||||
def update(self, point, info):
|
||||
''' this function is called by the Snapper when the mouse is moved '''
|
||||
|
||||
delta = FreeCAD.Vector(self.Length / 2, self.Width / 2, self.Height / 2)
|
||||
rot = FreeCAD.Rotation()
|
||||
|
||||
#self.tracker.setRotation(rot)
|
||||
self.tracker.pos(point)
|
||||
return
|
||||
|
||||
delta = FreeCAD.Vector(self.Length / 2, self.Width / 2, self.Height / 2)
|
||||
delta = delta.add(FreeCAD.Vector(0, 0, self.Sill))
|
||||
rot = FreeCAD.Rotation()
|
||||
if info:
|
||||
if "Face" in info['Component']:
|
||||
import WorkingPlane
|
||||
o = FreeCAD.ActiveDocument.getObject(info['Object'])
|
||||
self.baseFace = [o, int(info['Component'][4:]) - 1]
|
||||
# print("switching to ",o.Label," face ",self.baseFace[1])
|
||||
f = o.Shape.Faces[self.baseFace[1]]
|
||||
p = WorkingPlane.getPlacementFromFace(f, rotated=True)
|
||||
if p:
|
||||
rot = p.Rotation
|
||||
self.tracker.setRotation(rot)
|
||||
r = self.tracker.trans.rotation.getValue().getValue()
|
||||
if r != (0, 0, 0, 1):
|
||||
delta = FreeCAD.Rotation(r[0], r[1], r[2], r[3]).multVec(FreeCAD.Vector(delta.x, -delta.y, -delta.z))
|
||||
self.tracker.pos(point.add(delta))
|
||||
|
||||
def taskbox(self):
|
||||
"sets up a taskbox widget"
|
||||
|
||||
w = FreeCADGui.PySideUic.loadUi(PVPlantResources.__dir__ + "/PVPlantFenceGate.ui")
|
||||
self.Width = 80
|
||||
self.Height = 2000
|
||||
self.Length = 6146
|
||||
return w
|
||||
|
||||
w = QtGui.QWidget()
|
||||
ui = FreeCADGui.UiLoader()
|
||||
|
||||
w.setWindowTitle("Window options")
|
||||
grid = QtGui.QGridLayout(w)
|
||||
|
||||
# include box
|
||||
include = QtGui.QCheckBox(translate("Arch","Auto include in host object"))
|
||||
include.setChecked(True)
|
||||
grid.addWidget(include,0,0,1,2)
|
||||
QtCore.QObject.connect(include,QtCore.SIGNAL("stateChanged(int)"),self.setInclude)
|
||||
|
||||
# sill height
|
||||
labels = QtGui.QLabel(translate("Arch","Sill height"))
|
||||
values = ui.createWidget("Gui::InputField")
|
||||
grid.addWidget(labels,1,0,1,1)
|
||||
grid.addWidget(values,1,1,1,1)
|
||||
QtCore.QObject.connect(values,QtCore.SIGNAL("valueChanged(double)"),self.setSill)
|
||||
|
||||
# check for Parts library and Arch presets
|
||||
|
||||
# because of the use of FreeCADGui.doCommand() backslashes in the
|
||||
# paths in librarypresets need to be double escaped "\\\\", so let's
|
||||
# use forward slashes instead...
|
||||
self.librarypresets = []
|
||||
librarypath = FreeCAD.ParamGet("User parameter:Plugins/parts_library").GetString("destination", "")
|
||||
# librarypath should have only forward slashes already, but let's use replace() anyway just to be sure:
|
||||
librarypath = librarypath.replace("\\", "/") + "/Architectural Parts"
|
||||
presetdir = FreeCAD.getUserAppDataDir().replace("\\", "/") + "/Arch"
|
||||
for path in [librarypath, presetdir]:
|
||||
if os.path.isdir(path):
|
||||
for wtype in ["Windows", "Doors"]:
|
||||
wdir = path + "/" + wtype
|
||||
if os.path.isdir(wdir):
|
||||
for subtype in os.listdir(wdir):
|
||||
subdir = wdir + "/" + subtype
|
||||
if os.path.isdir(subdir):
|
||||
for subfile in os.listdir(subdir):
|
||||
if (os.path.isfile(subdir + "/" + subfile)
|
||||
and subfile.lower().endswith(".fcstd")):
|
||||
self.librarypresets.append([wtype + " - " + subtype + " - " + subfile[:-6],
|
||||
subdir + "/" + subfile])
|
||||
|
||||
# presets box
|
||||
labelp = QtGui.QLabel(translate("Arch","Preset"))
|
||||
valuep = QtGui.QComboBox()
|
||||
valuep.setMinimumContentsLength(6)
|
||||
valuep.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToContents)
|
||||
valuep.addItems(WindowPresets)
|
||||
valuep.setCurrentIndex(self.Preset)
|
||||
grid.addWidget(labelp,2,0,1,1)
|
||||
grid.addWidget(valuep,2,1,1,1)
|
||||
QtCore.QObject.connect(valuep,QtCore.SIGNAL("currentIndexChanged(int)"),self.setPreset)
|
||||
for it in self.librarypresets:
|
||||
valuep.addItem(it[0])
|
||||
|
||||
# image display
|
||||
self.pic = QtGui.QLabel()
|
||||
grid.addWidget(self.pic,3,0,1,2)
|
||||
self.pic.setFixedHeight(128)
|
||||
self.pic.hide()
|
||||
|
||||
# SVG display
|
||||
self.im = QtSvg.QSvgWidget(":/ui/ParametersWindowFixed.svg")
|
||||
self.im.setMaximumWidth(200)
|
||||
self.im.setMinimumHeight(120)
|
||||
grid.addWidget(self.im,4,0,1,2)
|
||||
#self.im.hide()
|
||||
|
||||
# parameters
|
||||
i = 5
|
||||
for param in self.wparams:
|
||||
lab = QtGui.QLabel(translate("Arch",param))
|
||||
setattr(self,"val"+param,ui.createWidget("Gui::InputField"))
|
||||
wid = getattr(self,"val"+param)
|
||||
if param == "Width":
|
||||
wid.setText(FreeCAD.Units.Quantity(self.Width,FreeCAD.Units.Length).UserString)
|
||||
elif param == "Height":
|
||||
wid.setText(FreeCAD.Units.Quantity(self.Height,FreeCAD.Units.Length).UserString)
|
||||
elif param == "O1":
|
||||
n = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetFloat("WindowO1",0.0)
|
||||
wid.setText(FreeCAD.Units.Quantity(n,FreeCAD.Units.Length).UserString)
|
||||
setattr(self,param,n)
|
||||
elif param == "W1":
|
||||
n = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetFloat("WindowW1",self.Thickness*2)
|
||||
wid.setText(FreeCAD.Units.Quantity(n,FreeCAD.Units.Length).UserString)
|
||||
setattr(self,param,n)
|
||||
else:
|
||||
n = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetFloat("Window"+param,self.Thickness)
|
||||
wid.setText(FreeCAD.Units.Quantity(n,FreeCAD.Units.Length).UserString)
|
||||
setattr(self,param,n)
|
||||
grid.addWidget(lab,i,0,1,1)
|
||||
grid.addWidget(wid,i,1,1,1)
|
||||
i += 1
|
||||
valueChanged = self.getValueChanged(param)
|
||||
FreeCAD.wid = wid
|
||||
QtCore.QObject.connect(getattr(self,"val"+param),QtCore.SIGNAL("valueChanged(double)"), valueChanged)
|
||||
|
||||
# restore saved states
|
||||
if self.doormode:
|
||||
i = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetInt("DoorPreset",0)
|
||||
d = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetFloat("DoorSill",0)
|
||||
else:
|
||||
i = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetInt("WindowPreset",0)
|
||||
d = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetFloat("WindowSill",0)
|
||||
if i < valuep.count():
|
||||
valuep.setCurrentIndex(i)
|
||||
values.setText(FreeCAD.Units.Quantity(d,FreeCAD.Units.Length).UserString)
|
||||
|
||||
return w
|
||||
352
Civil/Fence/PVPlantFenceGate.ui
Normal file
352
Civil/Fence/PVPlantFenceGate.ui
Normal file
@@ -0,0 +1,352 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>formGate</class>
|
||||
<widget class="QWidget" name="formGate">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>317</width>
|
||||
<height>289</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Puerta:</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Puerta</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Tipo de puerta</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="editGateHeight">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>5.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>2.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelVerticalGap">
|
||||
<property name="text">
|
||||
<string>Ancho (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="editGateWidth">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>10000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.500000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.850000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Alto (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboFrameType">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Simple</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Doble</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Poste</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="3" column="2">
|
||||
<widget class="QDoubleSpinBox" name="editPostBuried">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>2000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>50.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>700.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Alto (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Enterramiento (m)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QDoubleSpinBox" name="editPostHeight">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>5000.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>500.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>2000.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Ancho (mm)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QSpinBox" name="editPostWidth">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>80</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Espacio (mm)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="editGap">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>140</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::NoButtons</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>2</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
232
Civil/Fence/PVPlantFencePost.py
Normal file
232
Civil/Fence/PVPlantFencePost.py
Normal file
@@ -0,0 +1,232 @@
|
||||
import FreeCAD
|
||||
import Part
|
||||
import ArchComponent
|
||||
|
||||
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
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
def makeFencePost(diameter=48, length=3000, placement=None, name="FencePost"):
|
||||
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", name)
|
||||
obj.Label = name
|
||||
FencePost(obj)
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
ViewProviderFencePost(obj.ViewObject)
|
||||
|
||||
obj.Length = length
|
||||
obj.Diameter = diameter
|
||||
|
||||
if placement:
|
||||
obj.Placement = placement
|
||||
return obj
|
||||
|
||||
|
||||
def makeFenceReinforcePost(diameter=48, length=3000, placement=None, name="Post"):
|
||||
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", name)
|
||||
obj.Label = name
|
||||
FenceReinforcePost(obj)
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
ViewProviderFencePost(obj.ViewObject)
|
||||
|
||||
obj.Length = length
|
||||
obj.Diameter = diameter
|
||||
|
||||
if placement:
|
||||
obj.Placement = placement
|
||||
return obj
|
||||
|
||||
|
||||
class FencePost(ArchComponent.Component):
|
||||
def __init__(self, obj):
|
||||
ArchComponent.Component.__init__(self, obj)
|
||||
self.setProperties(obj)
|
||||
obj.IfcType = "Pipe Segment"
|
||||
self.Type = "FencePost"
|
||||
|
||||
def setProperties(self, obj):
|
||||
|
||||
pl = obj.PropertiesList
|
||||
if not "Diameter" in pl:
|
||||
obj.addProperty("App::PropertyLength", "Diameter", "Pipe",
|
||||
QT_TRANSLATE_NOOP("App::Property", "The diameter of this pipe, if not based on a profile")
|
||||
).Diameter = 48
|
||||
'''if not "Thickness" in pl:
|
||||
obj.addProperty("App::PropertyLength", "Thickness", "Pipe",
|
||||
QT_TRANSLATE_NOOP("App::Property", "The Thickness of this pipe, if not based on a profile")
|
||||
).Thickness = 4'''
|
||||
if not "Length" in pl:
|
||||
obj.addProperty("App::PropertyLength", "Length", "Pipe",
|
||||
QT_TRANSLATE_NOOP("App::Property", "The length of this pipe, if not based on an edge")
|
||||
).Length = 3000
|
||||
|
||||
def onDocumentRestored(self, obj):
|
||||
|
||||
ArchComponent.Component.onDocumentRestored(self, obj)
|
||||
self.setProperties(obj)
|
||||
|
||||
def get_axis(self, obj, lip_heigth):
|
||||
wire = Part.makeLine(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(0, 0, obj.Length.Value - lip_heigth))
|
||||
#wire = Part.makePolygon(FreeCAD.Vector(0, 0, obj.Length.Value - lip_heigth),)
|
||||
return Part.Wire(wire)
|
||||
|
||||
def execute(self, obj):
|
||||
pl = obj.Placement
|
||||
|
||||
lip_heigth = 20
|
||||
radius = obj.Diameter.Value / 2
|
||||
|
||||
# para que sea una función que sirva para los postes rectos y con curva:
|
||||
axis = self.get_axis(obj, lip_heigth)
|
||||
profile = Part.Wire([Part.Circle(FreeCAD.Vector(0,0,0), FreeCAD.Vector(0,0,1), radius).toShape()])
|
||||
post = axis.makePipeShell([profile, ],True,True,2)
|
||||
|
||||
lip = Part.makeCylinder(radius + 2, lip_heigth)
|
||||
lip = lip.makeFillet(5, [lip.Edges[0]])
|
||||
|
||||
# Obtener caras
|
||||
face_post = post.Faces[2] # Cara superior del cilindro largo
|
||||
face_lip = lip.Faces[2] # Cara inferior del cilindro corto
|
||||
|
||||
# Calcular centro y normal de las caras
|
||||
face_post_center = face_post.CenterOfMass
|
||||
face_post_normal = face_post.normalAt(0, 0)
|
||||
face_lip_center = face_lip.CenterOfMass
|
||||
face_lip_normal = face_lip.normalAt(0, 0)
|
||||
|
||||
# Calcular rotación para alinear normales (ajustar dirección)
|
||||
rotacion = FreeCAD.Rotation(face_lip_normal, -face_post_normal) # Invertir normal del cilindro corto
|
||||
lip.Placement.Rotation = rotacion.multiply(lip.Placement.Rotation)
|
||||
|
||||
# Calcular traslación: mover centro del cilindro corto al centro del cilindro largo
|
||||
traslacion = face_post_center - rotacion.multVec(face_lip_center)
|
||||
lip.Placement.Base = traslacion #face_post_center
|
||||
|
||||
obj.Shape = post.fuse(lip)
|
||||
obj.Placement = pl
|
||||
return
|
||||
|
||||
|
||||
class FenceReinforcePost(ArchComponent.Component):
|
||||
def __init__(self, obj):
|
||||
ArchComponent.Component.__init__(self, obj)
|
||||
self.setProperties(obj)
|
||||
obj.IfcType = "Pipe Segment"
|
||||
self.Type = "FencePost"
|
||||
|
||||
def setProperties(self, obj):
|
||||
|
||||
pl = obj.PropertiesList
|
||||
if not "Diameter" in pl:
|
||||
obj.addProperty("App::PropertyLength", "Diameter", "Pipe",
|
||||
QT_TRANSLATE_NOOP("App::Property", "The diameter of this pipe, if not based on a profile")
|
||||
).Diameter = 48
|
||||
if not "Length" in pl:
|
||||
obj.addProperty("App::PropertyLength", "Length", "Pipe",
|
||||
QT_TRANSLATE_NOOP("App::Property", "The length of this pipe, if not based on an edge")
|
||||
).Length = 3000
|
||||
self.Type = "Pipe"
|
||||
|
||||
def onDocumentRestored(self, obj):
|
||||
|
||||
ArchComponent.Component.onDocumentRestored(self, obj)
|
||||
self.setProperties(obj)
|
||||
|
||||
def execute(self, obj):
|
||||
pl = obj.Placement
|
||||
|
||||
lip_heigth = 20
|
||||
post = Part.makeCylinder(obj.Diameter.Value / 2, obj.Length.Value - lip_heigth)
|
||||
lip = Part.makeCylinder(obj.Diameter.Value / 2 + 2, lip_heigth)
|
||||
lip = lip.makeFillet(5, [lip.Edges[0]])
|
||||
lip.translate(FreeCAD.Vector(0, 0, obj.Length.Value - lip_heigth))
|
||||
obj.Shape = post.fuse(lip)
|
||||
obj.Placement = pl
|
||||
return
|
||||
|
||||
w = self.getWire(obj)
|
||||
try:
|
||||
# sh = w.makePipeShell([p], True, False, 2)
|
||||
sh = w.revolve(FreeCAD.Vector(0.0, 0.0, 0.0), FreeCAD.Vector(0.0, 0.0, 1.0), 360)
|
||||
except:
|
||||
FreeCAD.Console.PrintError(translate("Arch", "Unable to build the pipe") + "\n")
|
||||
else:
|
||||
obj.Shape = sh
|
||||
obj.Placement = pl
|
||||
|
||||
def getWire(self, obj):
|
||||
|
||||
import Part
|
||||
sin45 = 0.707106781
|
||||
radio = obj.Diameter.Value / 2
|
||||
taph = 20
|
||||
tapw = radio + 2
|
||||
chamfer = 5
|
||||
chamfer2 = chamfer * sin45
|
||||
|
||||
edge1 = Part.makeLine(FreeCAD.Vector(0, 0, 0), FreeCAD.Vector(radio, 0, 0))
|
||||
edge2 = Part.makeLine(FreeCAD.Vector(radio, 0, 0), FreeCAD.Vector(radio, 0, obj.Length.Value - taph))
|
||||
edge3 = Part.makeLine(FreeCAD.Vector(radio, 0, obj.Length.Value - taph),
|
||||
FreeCAD.Vector(tapw, 0, obj.Length.Value - taph))
|
||||
edge4 = Part.makeLine(FreeCAD.Vector(tapw, 0, obj.Length.Value - taph),
|
||||
FreeCAD.Vector(tapw, 0, obj.Length.Value - chamfer))
|
||||
|
||||
if True:
|
||||
edge5 = Part.makeLine(FreeCAD.Vector(tapw, 0, obj.Length.Value - chamfer),
|
||||
FreeCAD.Vector(tapw - chamfer, 0, obj.Length.Value))
|
||||
else:
|
||||
edge5 = Part.Arc(FreeCAD.Vector(tapw, 0, obj.Length.Value - chamfer),
|
||||
FreeCAD.Vector(tapw - chamfer2, 0, obj.Length.Value - chamfer2),
|
||||
FreeCAD.Vector(tapw - chamfer, 0, obj.Length.Value)
|
||||
).toShape()
|
||||
edge6 = Part.makeLine(FreeCAD.Vector(tapw - chamfer, 0, obj.Length.Value),
|
||||
FreeCAD.Vector(0, 0, obj.Length.Value))
|
||||
w = Part.Wire([edge1, edge2, edge3, edge4, edge5, edge6])
|
||||
|
||||
return w
|
||||
|
||||
|
||||
class ViewProviderFencePost(ArchComponent.ViewProviderComponent):
|
||||
"A View Provider for the Pipe object"
|
||||
|
||||
def __init__(self, vobj):
|
||||
ArchComponent.ViewProviderComponent.__init__(self, vobj)
|
||||
|
||||
def getIcon(self):
|
||||
return ":/icons/Arch_Pipe_Tree.svg"
|
||||
|
||||
|
||||
class CommandFencePost:
|
||||
"the Arch Pipe command definition"
|
||||
|
||||
def GetResources(self):
|
||||
|
||||
return {'Pixmap': 'Arch_Pipe',
|
||||
'MenuText': QT_TRANSLATE_NOOP("Arch_Pipe", "Pipe"),
|
||||
'Accel': "P, I",
|
||||
'ToolTip': QT_TRANSLATE_NOOP("Arch_Pipe", "Creates a pipe object from a given Wire or Line")}
|
||||
|
||||
def IsActive(self):
|
||||
|
||||
return not FreeCAD.ActiveDocument is None
|
||||
|
||||
def Activated(self):
|
||||
makeFencePost()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
Reference in New Issue
Block a user