updates
This commit is contained in:
@@ -141,29 +141,31 @@ def groupTrackersToTransformers(transformer_power, max_distance):
|
||||
|
||||
for i, group in enumerate(transformer_groups):
|
||||
# Crear la esfera que representará el CT
|
||||
ct_sphere = FreeCAD.ActiveDocument.addObject("Part::Sphere", f"CT_{i + 1}")
|
||||
ct_sphere.Radius = 5000 # 2m de radio
|
||||
ct_sphere.Placement.Base = FreeCAD.Vector(group['center'][0], group['center'][1], 0)
|
||||
ct_shape = FreeCAD.ActiveDocument.addObject("Part::Box", f"CT_{i + 1}")
|
||||
ct_shape.Length = 6058
|
||||
ct_shape.Width = 2438
|
||||
ct_shape.Height = 2591
|
||||
ct_shape.Placement.Base = FreeCAD.Vector(group['center'][0], group['center'][1], 0)
|
||||
|
||||
# Añadir propiedades personalizadas
|
||||
ct_sphere.addProperty("App::PropertyLinkList", "Trackers", "CT",
|
||||
ct_shape.addProperty("App::PropertyLinkList", "Trackers", "CT",
|
||||
"Lista de trackers asociados a este CT")
|
||||
ct_sphere.addProperty("App::PropertyFloat", "TotalPower", "CT",
|
||||
ct_shape.addProperty("App::PropertyFloat", "TotalPower", "CT",
|
||||
"Potencia total del grupo (W)")
|
||||
ct_sphere.addProperty("App::PropertyFloat", "NominalPower", "CT",
|
||||
ct_shape.addProperty("App::PropertyFloat", "NominalPower", "CT",
|
||||
"Potencia nominal del transformador (W)")
|
||||
ct_sphere.addProperty("App::PropertyFloat", "Utilization", "CT",
|
||||
ct_shape.addProperty("App::PropertyFloat", "Utilization", "CT",
|
||||
"Porcentaje de utilización (Total/Nominal)")
|
||||
|
||||
# Establecer valores de las propiedades
|
||||
ct_sphere.Trackers = group['trackers']
|
||||
ct_sphere.TotalPower = group['total_power'].Value
|
||||
ct_sphere.NominalPower = transformer_power
|
||||
ct_sphere.Utilization = (group['total_power'].Value / transformer_power) * 100
|
||||
ct_shape.Trackers = group['trackers']
|
||||
ct_shape.TotalPower = group['total_power'].Value
|
||||
ct_shape.NominalPower = transformer_power
|
||||
ct_shape.Utilization = (group['total_power'].Value / transformer_power) * 100
|
||||
|
||||
# Configurar visualización
|
||||
# Calcular color basado en utilización (verde < 100%, amarillo < 110%, rojo > 110%)
|
||||
utilization = ct_sphere.Utilization
|
||||
utilization = ct_shape.Utilization
|
||||
if utilization <= 100:
|
||||
color = (0.0, 1.0, 0.0) # Verde
|
||||
elif utilization <= 110:
|
||||
@@ -171,15 +173,15 @@ def groupTrackersToTransformers(transformer_power, max_distance):
|
||||
else:
|
||||
color = (1.0, 0.0, 0.0) # Rojo
|
||||
|
||||
ct_sphere.ViewObject.ShapeColor = color
|
||||
ct_sphere.ViewObject.Transparency = 40 # 40% de transparencia
|
||||
ct_shape.ViewObject.ShapeColor = color
|
||||
ct_shape.ViewObject.Transparency = 40 # 40% de transparencia
|
||||
|
||||
# Añadir etiqueta con información
|
||||
ct_sphere.ViewObject.DisplayMode = "Shaded"
|
||||
ct_sphere.Label = f"CT {i + 1} ({ct_sphere.TotalPower / 1000:.1f}kW/{ct_sphere.NominalPower / 1000:.1f}kW)"
|
||||
ct_shape.ViewObject.DisplayMode = "Shaded"
|
||||
ct_shape.Label = f"CT {i + 1} ({ct_shape.TotalPower / 1000:.1f}kW/{ct_shape.NominalPower / 1000:.1f}kW)"
|
||||
|
||||
# Añadir al grupo principal
|
||||
transformer_group.addObject(ct_sphere)
|
||||
transformer_group.addObject(ct_shape)
|
||||
|
||||
FreeCAD.Console.PrintMessage(f"Se crearon {len(transformer_groups)} centros de transformación\n")
|
||||
onSelectGatePoint()
|
||||
@@ -195,7 +197,7 @@ class InternalPathCreator:
|
||||
self.gate_point = gate_point
|
||||
self.strategy = strategy
|
||||
self.path_width = path_width
|
||||
self.ct_spheres = []
|
||||
self.ct_shapes = []
|
||||
self.ct_positions = []
|
||||
|
||||
def get_transformers(self):
|
||||
@@ -204,13 +206,13 @@ class InternalPathCreator:
|
||||
FreeCAD.Console.PrintError("No se encontró el grupo 'Transformers'\n")
|
||||
return False
|
||||
|
||||
self.ct_spheres = transformers_group.Group
|
||||
if not self.ct_spheres:
|
||||
self.ct_shapes = transformers_group.Group
|
||||
if not self.ct_shapes:
|
||||
FreeCAD.Console.PrintWarning("No hay Centros de Transformación en el grupo\n")
|
||||
return False
|
||||
|
||||
# Obtener las posiciones de los CTs
|
||||
for sphere in self.ct_spheres:
|
||||
for sphere in self.ct_shapes:
|
||||
base = sphere.Placement.Base
|
||||
self.ct_positions.append(FreeCAD.Vector(base.x, base.y, 0))
|
||||
return True
|
||||
@@ -263,6 +265,8 @@ class InternalPathCreator:
|
||||
y_proj = slope * x_proj + intercept
|
||||
return FreeCAD.Vector(x_proj, y_proj, 0)
|
||||
|
||||
# return slope * x + intercept --> desde placement
|
||||
|
||||
projected_points = [project_point(p) for p in all_points]
|
||||
|
||||
# Calcular distancias a lo largo de la línea
|
||||
|
||||
@@ -626,6 +626,7 @@ layers = [
|
||||
("Available area Names", QtGui.QColor(255, 255, 255), "Continuous", "1", True),
|
||||
|
||||
("Areas Exclusion", QtGui.QColor(255, 85, 0), "Continuous", "1", True),
|
||||
("Areas Exclusion Offset", QtGui.QColor(255, 85, 0), "Continuous", "1", True),
|
||||
("Areas Exclusion Name", QtGui.QColor(255, 85, 0), "Continuous", "1", True),
|
||||
("Areas Cadastral Plot", QtGui.QColor(255, 255, 255), "Continuous", "1", True),
|
||||
("Areas Cadastral Plot Name", QtGui.QColor(255, 255, 255), "Continuous", "1", True),
|
||||
|
||||
@@ -102,7 +102,7 @@ class _PVPlantPlacementTaskPanel:
|
||||
|
||||
def createFrameFromPoints(self, dataframe):
|
||||
from Mechanical.Frame import PVPlantFrame
|
||||
try:
|
||||
'''try:
|
||||
MechanicalGroup = FreeCAD.ActiveDocument.Frames
|
||||
except:
|
||||
MechanicalGroup = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", 'Frames')
|
||||
@@ -110,14 +110,41 @@ class _PVPlantPlacementTaskPanel:
|
||||
FreeCAD.ActiveDocument.MechanicalGroup.addObject(MechanicalGroup)
|
||||
|
||||
if self.form.cbSubfolders.isChecked:
|
||||
label = "Frames-" + self.PVArea.Label
|
||||
if label in [obj.Label for obj in FreeCAD.ActiveDocument.Frames.Group]:
|
||||
MechanicalGroup = FreeCAD.ActiveDocument.getObject(label)[0]
|
||||
name = "Frames-" + self.PVArea.Label
|
||||
if name in [obj.Name for obj in FreeCAD.ActiveDocument.Frames.Group]:
|
||||
MechanicalGroup = FreeCAD.ActiveDocument.getObject(name)[0]
|
||||
else:
|
||||
group = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", label)
|
||||
group.Label = label
|
||||
group = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", name)
|
||||
group.Label = name
|
||||
MechanicalGroup.addObject(group)
|
||||
MechanicalGroup = group
|
||||
MechanicalGroup = group'''
|
||||
|
||||
doc = FreeCAD.ActiveDocument
|
||||
|
||||
# 1. Obtener o crear el grupo principal 'Frames'
|
||||
main_group_name = "Frames"
|
||||
main_group = doc.getObject(main_group_name)
|
||||
if not main_group:
|
||||
main_group = doc.addObject("App::DocumentObjectGroup", main_group_name)
|
||||
main_group.Label = main_group_name
|
||||
# Asumiendo que existe un grupo 'MechanicalGroup'
|
||||
if hasattr(doc, 'MechanicalGroup'):
|
||||
doc.MechanicalGroup.addObject(main_group)
|
||||
|
||||
# 2. Manejar subgrupo si es necesario
|
||||
group = main_group # Grupo donde se añadirán los marcos
|
||||
if self.form.cbSubfolders.isChecked(): # ¡Corregido: falta de paréntesis!
|
||||
subgroup_name = f"Frames-{self.PVArea.Label}"
|
||||
|
||||
# Buscar subgrupo existente
|
||||
subgroup = next((obj for obj in main_group.Group if obj.Name == subgroup_name), None)
|
||||
|
||||
if not subgroup:
|
||||
subgroup = doc.addObject("App::DocumentObjectGroup", subgroup_name)
|
||||
subgroup.Label = subgroup_name
|
||||
main_group.addObject(subgroup)
|
||||
group = subgroup
|
||||
|
||||
try:
|
||||
placements = dataframe["placement"].tolist()
|
||||
types = dataframe["type"].tolist()
|
||||
@@ -127,7 +154,7 @@ class _PVPlantPlacementTaskPanel:
|
||||
newrack.Label = "Tracker"
|
||||
newrack.Visibility = False
|
||||
newrack.Placement = placements[idx]
|
||||
MechanicalGroup.addObject(newrack)
|
||||
group.addObject(newrack)
|
||||
frames.append(newrack)
|
||||
except:
|
||||
placements = dataframe[0]
|
||||
@@ -138,7 +165,7 @@ class _PVPlantPlacementTaskPanel:
|
||||
newrack.Label = "Tracker"
|
||||
newrack.Visibility = False
|
||||
newrack.Placement = idx[1]
|
||||
MechanicalGroup.addObject(newrack)
|
||||
groupq.addObject(newrack)
|
||||
frames.append(newrack)
|
||||
|
||||
if self.PVArea.Name.startswith("FrameArea"):
|
||||
@@ -160,7 +187,7 @@ class _PVPlantPlacementTaskPanel:
|
||||
if exclusion_areas:
|
||||
prohibited_faces = []
|
||||
for obj in exclusion_areas:
|
||||
face = self.getProjected(obj.Base.Shape)
|
||||
face = self.getProjected(obj.Shape.SubShapes[1])
|
||||
if face.isValid():
|
||||
prohibited_faces.append(face)
|
||||
self.Area = self.Area.cut(prohibited_faces)
|
||||
@@ -474,64 +501,70 @@ class _PVPlantPlacementTaskPanel:
|
||||
|
||||
def calculateNonAlignedArray(self):
|
||||
pointsx, pointsy = self.getAligments()
|
||||
if len(pointsx) == 0:
|
||||
FreeCAD.Console.PrintWarning("No se encontraron alineaciones X.\n")
|
||||
return []
|
||||
|
||||
footprints = []
|
||||
for frame in self.FrameSetups:
|
||||
xx = frame.Length.Value
|
||||
yy = frame.Width.Value
|
||||
xx_med = xx / 2
|
||||
yy_med = yy / 2
|
||||
rec = Part.makePolygon([FreeCAD.Vector(-xx_med, -yy_med, 0),
|
||||
FreeCAD.Vector(xx_med, -yy_med, 0),
|
||||
FreeCAD.Vector(xx_med, yy_med, 0),
|
||||
FreeCAD.Vector(-xx_med, yy_med, 0),
|
||||
FreeCAD.Vector(-xx_med, -yy_med, 0)])
|
||||
l = frame.Length.Value
|
||||
w = frame.Width.Value
|
||||
l_med = l / 2
|
||||
w_med = w / 2
|
||||
rec = Part.makePolygon([FreeCAD.Vector(-l_med, -w_med, 0),
|
||||
FreeCAD.Vector( l_med, -w_med, 0),
|
||||
FreeCAD.Vector( l_med, w_med, 0),
|
||||
FreeCAD.Vector(-l_med, w_med, 0),
|
||||
FreeCAD.Vector(-l_med, -w_med, 0)])
|
||||
rec.Placement.Rotation = FreeCAD.Rotation(FreeCAD.Vector(1, 0, 0), FreeCAD.Vector(0, 1, 0))
|
||||
footprints.append([frame, rec])
|
||||
ref = footprints.pop(0)
|
||||
xx = ref[0].Length.Value
|
||||
yy = ref[0].Width.Value
|
||||
xx_med = xx / 2
|
||||
yy_med = yy / 2
|
||||
|
||||
# variables for corridors:
|
||||
countcols = 0
|
||||
countrows = 0
|
||||
offsetcols = 0 # ??
|
||||
offsetrows = 0 # ??
|
||||
valcols = FreeCAD.Units.Quantity(self.form.editColGap.text()).Value - (self.gap_col - yy)
|
||||
corridor = self.form.groupCorridor.isChecked()
|
||||
corridor_offset = 0
|
||||
count = 0
|
||||
|
||||
pl = []
|
||||
for point in pointsx:
|
||||
p1 = FreeCAD.Vector(point, self.Area.BoundBox.YMax, 0.0)
|
||||
p2 = FreeCAD.Vector(point, self.Area.BoundBox.YMin, 0.0)
|
||||
cols = []
|
||||
for x in pointsx:
|
||||
col=[]
|
||||
x += corridor_offset
|
||||
p1 = FreeCAD.Vector(x, self.Area.BoundBox.YMax, 0.0)
|
||||
p2 = FreeCAD.Vector(x, self.Area.BoundBox.YMin, 0.0)
|
||||
line = Part.makePolygon([p1, p2])
|
||||
|
||||
inter = self.Area.section([line])
|
||||
pts = [ver.Point for ver in inter.Vertexes] # todo: sort points
|
||||
pts = [ver.Point for ver in inter.Vertexes]
|
||||
pts = sorted(pts, key=lambda p: p.y, reverse=True)
|
||||
for i in range(0, len(pts), 2):
|
||||
line = Part.LineSegment(pts[i], pts[i + 1])
|
||||
if line.length() >= ref[1].BoundBox.YLength:
|
||||
y1 = pts[i].y - ref[1].BoundBox.YLength / 2
|
||||
cp = ref[1].copy()
|
||||
cp.Placement.Base = FreeCAD.Vector(pts[i].x, y1, 0.0)
|
||||
Part.show(cp)
|
||||
top = pts[i]
|
||||
bootom = pts[i + 1]
|
||||
if top.distanceToPoint(bootom) > footprints[-1][1].BoundBox.YLength:
|
||||
y1 = top.y - (footprints[-1][1].BoundBox.YLength / 2)
|
||||
cp = footprints[-1][1].copy()
|
||||
cp.Placement.Base = FreeCAD.Vector(x + footprints[-1][1].BoundBox.XLength / 2, y1, 0.0)
|
||||
inter = cp.cut([self.Area])
|
||||
pts1 = [ver.Point for ver in inter.Vertexes]
|
||||
if len(pts1) == 0:
|
||||
continue
|
||||
y1 = min(pts1, key=lambda p: p.y).y
|
||||
pointsy = np.arange(y1, pts[i + 1].y, -self.gap_row)
|
||||
continue
|
||||
for pointy in pointsy:
|
||||
cp = ref[1].copy()
|
||||
cp.Placement.Base = FreeCAD.Vector(pts[i].x + ref[1].BoundBox.XLength / 2, pointy, 0.0)
|
||||
cut = cp.cut([self.Area], 0)
|
||||
#print(y1, " - ", pointy, " - ", len(cut.Vertexes))
|
||||
#if len(cut.Vertexes) == 0:
|
||||
Part.show(cp)
|
||||
pl.append([ref[0], pointy])
|
||||
return pl
|
||||
vtx = [ver.Point for ver in inter.Vertexes]
|
||||
mod = top.y
|
||||
if len(vtx) != 0:
|
||||
mod = min(vtx, key=lambda p: p.y).y
|
||||
#y1 = cp.Placement.Base.y - mod
|
||||
|
||||
tmp = optimized_cut(mod - bootom.y, [ftp[1].BoundBox.YLength for ftp in footprints], 500, 'greedy')
|
||||
for opt in tmp[0]:
|
||||
mod -= (footprints[opt][1].BoundBox.YLength / 2)
|
||||
pl = FreeCAD.Vector(x + footprints[opt][1].BoundBox.XLength / 2, mod, 0.0)
|
||||
cp = footprints[opt][1].copy()
|
||||
if self.isInside(cp, pl):
|
||||
col.append([footprints[opt][0], pl])
|
||||
mod -= ((footprints[opt][1].BoundBox.YLength / 2) + 500)
|
||||
Part.show(cp)
|
||||
|
||||
if corridor and len(col) > 0:
|
||||
count += 1
|
||||
if count == self.form.editColCount.value():
|
||||
corridor_offset += 12000
|
||||
count = 0
|
||||
|
||||
cols.append(cols)
|
||||
return self.adjustToTerrain(cols)
|
||||
|
||||
def accept(self):
|
||||
from datetime import datetime
|
||||
@@ -583,6 +616,115 @@ class _PVPlantPlacementTaskPanel:
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
|
||||
def optimized_cut(L_total, piezas, margen=0, metodo='auto'):
|
||||
"""
|
||||
Encuentra la combinación óptima de piezas para minimizar el desperdicio,
|
||||
considerando un margen entre piezas.
|
||||
|
||||
Args:
|
||||
L_total (int): Longitud total del material.
|
||||
piezas (list): Lista de longitudes de los patrones de corte.
|
||||
margen (int): Espacio perdido entre piezas consecutivas.
|
||||
metodo (str): 'dp' para programación dinámica, 'greedy' para voraz, 'auto' para selección automática.
|
||||
|
||||
Returns:
|
||||
tuple: (piezas_seleccionadas, desperdicio)
|
||||
"""
|
||||
# Filtrar piezas inválidas
|
||||
piezas = [p for p in piezas if 0 < p <= L_total]
|
||||
if not piezas:
|
||||
return [], L_total
|
||||
|
||||
# Transformar longitudes y longitud total con margen
|
||||
longitudes_aumentadas = [p + margen for p in piezas]
|
||||
L_total_aumentado = L_total + margen
|
||||
|
||||
# Selección automática de método
|
||||
if metodo == 'auto':
|
||||
if L_total_aumentado <= 10000 and len(piezas) <= 100:
|
||||
metodo = 'dp'
|
||||
else:
|
||||
metodo = 'greedy'
|
||||
|
||||
if metodo == 'dp':
|
||||
n = len(piezas)
|
||||
dp = [0] * (L_total_aumentado + 1)
|
||||
parent = [-1] * (L_total_aumentado + 1) # Almacena índices de piezas usadas
|
||||
|
||||
# Llenar la tabla dp y parent
|
||||
for j in range(1, L_total_aumentado + 1):
|
||||
for i in range(n):
|
||||
p_aum = longitudes_aumentadas[i]
|
||||
if p_aum <= j:
|
||||
if dp[j] < dp[j - p_aum] + p_aum:
|
||||
dp[j] = dp[j - p_aum] + p_aum
|
||||
parent[j] = i # Guardar índice de la pieza
|
||||
|
||||
# Reconstruir solución desde el final
|
||||
current = L_total_aumentado
|
||||
seleccion_indices = []
|
||||
while current > 0 and parent[current] != -1:
|
||||
i = parent[current]
|
||||
seleccion_indices.append(i)
|
||||
current -= longitudes_aumentadas[i]
|
||||
|
||||
# Calcular desperdicio real
|
||||
k = len(seleccion_indices)
|
||||
if k == 0:
|
||||
desperdicio = L_total
|
||||
else:
|
||||
suma_original = sum(piezas[i] for i in seleccion_indices)
|
||||
desperdicio = L_total - suma_original - margen * (k - 1)
|
||||
|
||||
return seleccion_indices, desperdicio
|
||||
|
||||
elif metodo == 'greedy':
|
||||
# Crear lista con índices y longitudes aumentadas
|
||||
lista_con_indices = [(longitudes_aumentadas[i], i) for i in range(len(piezas))]
|
||||
lista_con_indices.sort(key=lambda x: x[0], reverse=True) # Ordenar descendente
|
||||
|
||||
seleccion_indices = []
|
||||
restante = L_total_aumentado
|
||||
|
||||
# Seleccionar piezas vorazmente
|
||||
for p_aum, i in lista_con_indices:
|
||||
while restante >= p_aum:
|
||||
seleccion_indices.append(i)
|
||||
restante -= p_aum
|
||||
|
||||
# Calcular desperdicio real
|
||||
k = len(seleccion_indices)
|
||||
if k == 0:
|
||||
desperdicio = L_total
|
||||
else:
|
||||
suma_original = sum(piezas[i] for i in seleccion_indices)
|
||||
desperdicio = L_total - suma_original - margen * (k - 1)
|
||||
|
||||
return seleccion_indices, desperdicio
|
||||
|
||||
|
||||
# Ejemplo de uso
|
||||
'''if __name__ == "__main__":
|
||||
L_total = 100
|
||||
piezas = [25, 35, 40, 20, 15, 30, 50]
|
||||
margen = 5
|
||||
|
||||
print("Solución óptima con margen (programación dinámica):")
|
||||
seleccion, desperd = corte_optimizado(L_total, piezas, margen, 'dp')
|
||||
print(f"Piezas usadas: {seleccion}")
|
||||
print(f"Margen entre piezas: {margen} cm")
|
||||
print(f"Material útil: {sum(seleccion)} cm")
|
||||
print(f"Espacio usado por márgenes: {(len(seleccion) - 1) * margen} cm")
|
||||
print(f"Desperdicio total: {desperd} cm")
|
||||
|
||||
print("\nSolución aproximada con margen (algoritmo voraz):")
|
||||
seleccion_g, desperd_g = corte_optimizado(L_total, piezas, margen, 'greedy')
|
||||
print(f"Piezas usadas: {seleccion_g}")
|
||||
print(f"Margen entre piezas: {margen} cm")
|
||||
print(f"Material útil: {sum(seleccion_g)} cm")
|
||||
print(f"Espacio usado por márgenes: {(len(seleccion_g) - 1) * margen} cm")
|
||||
print(f"Desperdicio total: {desperd_g} cm")'''
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------
|
||||
# function AdjustToTerrain
|
||||
|
||||
@@ -54,30 +54,6 @@ class CommandPVPlantSite:
|
||||
return
|
||||
|
||||
|
||||
'''class CommandPVPlantGeoreferencing:
|
||||
@staticmethod
|
||||
def GetResources():
|
||||
return {'Pixmap': str(os.path.join(DirIcons, "Location.svg")),
|
||||
'Accel': "G, R",
|
||||
'MenuText': QT_TRANSLATE_NOOP("Georeferencing","Georeferencing"),
|
||||
'ToolTip': QT_TRANSLATE_NOOP("Georeferencing","Referenciar el lugar")}
|
||||
|
||||
@staticmethod
|
||||
def IsActive():
|
||||
if FreeCAD.ActiveDocument:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def Activated():
|
||||
import PVPlantGeoreferencing
|
||||
taskd = PVPlantGeoreferencing.MapWindow()
|
||||
#taskd.setParent(FreeCADGui.getMainWindow())
|
||||
#taskd.setWindowFlags(QtCore.Qt.Window)
|
||||
taskd.show()#exec_()'''
|
||||
|
||||
|
||||
class CommandProjectSetup:
|
||||
@staticmethod
|
||||
def GetResources():
|
||||
|
||||
@@ -224,14 +224,20 @@ def getProjected(shape, direction=FreeCAD.Vector(0, 0, 1)): # Based on Draft / s
|
||||
return ow
|
||||
|
||||
|
||||
def findObjects(classtype):
|
||||
'''def findObjects(classtype):
|
||||
objects = FreeCAD.ActiveDocument.Objects
|
||||
objlist = list()
|
||||
for object in objects:
|
||||
if hasattr(object, "Proxy"):
|
||||
if object.Proxy.Type == classtype:
|
||||
objlist.append(object)
|
||||
return objlist
|
||||
return objlist'''
|
||||
|
||||
def findObjects(classtype):
|
||||
return [obj for obj in FreeCAD.ActiveDocument.Objects
|
||||
if hasattr(obj, "Proxy")
|
||||
and hasattr(obj.Proxy, "Type")
|
||||
and obj.Proxy.Type == classtype]
|
||||
|
||||
def getClosePoints(sh1, angle):
|
||||
'''
|
||||
|
||||
Reference in New Issue
Block a user