812 lines
31 KiB
Python
812 lines
31 KiB
Python
import Draft
|
|
import FreeCAD
|
|
import Part
|
|
|
|
if FreeCAD.GuiUp:
|
|
import FreeCADGui
|
|
from PySide import QtCore, QtGui
|
|
from PySide.QtCore import QT_TRANSLATE_NOOP
|
|
else:
|
|
# \cond
|
|
def translate(ctxt, txt):
|
|
return txt
|
|
def QT_TRANSLATE_NOOP(ctxt, txt):
|
|
return txt
|
|
# \endcond
|
|
|
|
try:
|
|
_fromUtf8 = QtCore.QString.fromUtf8
|
|
except AttributeError:
|
|
def _fromUtf8(s):
|
|
return s
|
|
|
|
import os
|
|
from PVPlantResources import DirIcons as DirIcons
|
|
|
|
|
|
def Mest2FemMesh(obj):
|
|
import Fem
|
|
|
|
fm = Fem.FemMesh()
|
|
|
|
#i = 0
|
|
#nodes = []
|
|
for mp in obj.Mesh.Points:
|
|
fm.addNode(mp.Vector.x, mp.Vector.y, mp.Vector.z)
|
|
# nodes.append(mp)
|
|
# i += 1
|
|
for mf in obj.Mesh.Facets:
|
|
fm.addFace([mf.PointIndices[0] + 1, mf.PointIndices[1] + 1, mf.PointIndices[2] + 1])
|
|
|
|
obj2 = FreeCAD.ActiveDocument.addObject("Fem::FemMeshObject")
|
|
obj2.FemMesh = fm
|
|
obj2.ViewObject.DisplayMode = "Faces"
|
|
|
|
FreeCAD.activeDocument().recompute()
|
|
return obj2
|
|
|
|
|
|
def makeContours(land, minor = 1000, mayor = 5000,
|
|
minorColor=(0.0, 0.00, 0.80), mayorColor=(0.00, 0.00, 1.00),
|
|
minorThickness = 2, mayorThickness = 5,
|
|
filter_size = 5):
|
|
if not land:
|
|
return
|
|
|
|
if land.TypeId == 'Mesh::Feature':
|
|
Contours_Mesh(land.Mesh, minor, mayor, minorColor, mayorColor, minorThickness, mayorThickness, filter_size)
|
|
else:
|
|
Contours_Part(land, minor, mayor, minorColor, mayorColor, minorThickness, mayorThickness, filter_size)
|
|
|
|
FreeCAD.ActiveDocument.recompute()
|
|
|
|
|
|
def Contours_Mesh(Mesh, minor, mayor,
|
|
minorColor, mayorColor,
|
|
minorLineWidth, mayorLineWidth,
|
|
filter_size): #filter_size de 3 a 21 y siempre impar
|
|
|
|
def calculateSection(cuts):
|
|
for inc in cuts:
|
|
CrossSections = Mesh.crossSections([((0, 0, inc), (0, 0, 1))], 0.000001)
|
|
for PointList in CrossSections[0]:
|
|
if len(PointList) > 1:
|
|
if PointList[0].sub(PointList[-1]).Length <= 10000.0:
|
|
PointList.append(PointList[0])
|
|
|
|
# 1. Smooth the points
|
|
if (len(PointList) > filter_size) and (filter_size > 0):
|
|
for a in range(len(PointList)):
|
|
x = 0
|
|
y = 0
|
|
for p in range(-filter_radius, filter_radius + 1):
|
|
point_id = a + p
|
|
if point_id < 0:
|
|
point_id = 0
|
|
|
|
if point_id >= len(PointList):
|
|
point_id = len(PointList) - 1
|
|
|
|
x += PointList[point_id].x
|
|
y += PointList[point_id].y
|
|
|
|
x /= filter_size
|
|
y /= filter_size
|
|
PointList[a].x = x
|
|
PointList[a].y = y
|
|
|
|
for a in reversed(range(len(PointList))):
|
|
x = 0
|
|
y = 0
|
|
for p in range(-filter_radius, filter_radius + 1):
|
|
point_id = a + p
|
|
if point_id < 0:
|
|
point_id = 0
|
|
|
|
if point_id >= len(PointList):
|
|
point_id = len(PointList) - 1
|
|
|
|
x += PointList[point_id].x
|
|
y += PointList[point_id].y
|
|
|
|
x /= filter_size
|
|
y /= filter_size
|
|
PointList[a].x = x
|
|
PointList[a].y = y
|
|
|
|
# 2. Make lines
|
|
#Contour = Draft.makeWire(PointList, closed=False, face=None)
|
|
#Contour.Label = str(int(inc / 1000)) + "m"
|
|
Contour = Part.makePolygon(PointList)
|
|
Part.show(Contour, str(int(inc / 1000)) + "m")
|
|
'''Contours.addObject(Contour)
|
|
if inc % mayor == 0:
|
|
Contour.ViewObject.LineWidth = mayorLineWidth
|
|
Contour.ViewObject.LineColor = mayorColor
|
|
else:
|
|
Contour.ViewObject.LineWidth = minorLineWidth
|
|
Contour.ViewObject.LineColor = minorColor'''
|
|
|
|
del Contour, PointList
|
|
del CrossSections
|
|
|
|
filter_radius = int(filter_size / 2)
|
|
try:
|
|
Contours = FreeCAD.ActiveDocument.Contours
|
|
except:
|
|
Contours = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", 'Contours')
|
|
|
|
ZMin = Mesh.BoundBox.ZMin // 10000
|
|
ZMin *= 10000
|
|
ZMax = Mesh.BoundBox.ZMax
|
|
|
|
import numpy as np
|
|
minor_array = np.arange(ZMin, ZMax, minor)
|
|
mayor_array = np.arange(ZMin, ZMax, mayor)
|
|
minor_array = np.array(list(filter(lambda x: x not in mayor_array, minor_array)))
|
|
calculateSection(minor_array)
|
|
calculateSection(mayor_array)
|
|
|
|
|
|
def Contours_Part(Terrain, minor, mayor,
|
|
minorColor, mayorColor,
|
|
minorLineWidth, mayorLineWidth,
|
|
filter_size): #filter_size de 3 a 21 y siempre impar
|
|
|
|
def calculateSection(cuts):
|
|
cnt = 0
|
|
for inc in cuts:
|
|
CrossSections = Terrain.Shape.slice(FreeCAD.Vector(0, 0, 1), inc)
|
|
|
|
for wire in CrossSections:
|
|
PointList = []
|
|
for vertex in wire.Vertexes:
|
|
PointList.append(vertex.Point)
|
|
|
|
if len(PointList) > 1:
|
|
# 1. Smooth the points
|
|
if (len(PointList) > filter_size) and (filter_size > 0):
|
|
for a in range(len(PointList)):
|
|
x = 0
|
|
y = 0
|
|
for p in range(-filter_radius, filter_radius + 1):
|
|
point_id = a + p
|
|
if point_id < 0:
|
|
point_id = 0
|
|
|
|
if point_id >= len(PointList):
|
|
point_id = len(PointList) - 1
|
|
|
|
x += PointList[point_id].x
|
|
y += PointList[point_id].y
|
|
|
|
x /= filter_size
|
|
y /= filter_size
|
|
PointList[a].x = x
|
|
PointList[a].y = y
|
|
|
|
for a in reversed(range(len(PointList))):
|
|
x = 0
|
|
y = 0
|
|
for p in range(-filter_radius, filter_radius + 1):
|
|
point_id = a + p
|
|
if point_id < 0:
|
|
point_id = 0
|
|
|
|
if point_id >= len(PointList):
|
|
point_id = len(PointList) - 1
|
|
|
|
x += PointList[point_id].x
|
|
y += PointList[point_id].y
|
|
|
|
x /= filter_size
|
|
y /= filter_size
|
|
PointList[a].x = x
|
|
PointList[a].y = y
|
|
# 2. TODO: close wire
|
|
|
|
# 3. Make lines
|
|
Contour = Draft.makeWire(PointList, closed=False, face=None, support=None)
|
|
Contour.MakeFace = False
|
|
Contour.Label = str(int(inc / 1000)) + "m"
|
|
Contours.addObject(Contour)
|
|
|
|
if inc % mayor == 0:
|
|
Contour.ViewObject.LineWidth = mayorLineWidth
|
|
Contour.ViewObject.LineColor = mayorColor
|
|
else:
|
|
Contour.ViewObject.LineWidth = minorLineWidth
|
|
Contour.ViewObject.LineColor = minorColor
|
|
cnt += 1
|
|
if cnt == 10:
|
|
return
|
|
|
|
filter_radius = int(filter_size / 2)
|
|
try:
|
|
Contours = FreeCAD.ActiveDocument.Contours
|
|
except:
|
|
Contours = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", 'Contours')
|
|
|
|
ZMin = Terrain.Shape.BoundBox.ZMin // 10000
|
|
ZMin *= 10000
|
|
ZMax = Terrain.Shape.BoundBox.ZMax
|
|
|
|
import numpy as np
|
|
minor_array = np.arange(ZMin, ZMax, minor)
|
|
mayor_array = np.arange(ZMin, ZMax, mayor)
|
|
minor_array = np.array(list(filter(lambda x: x not in mayor_array, minor_array)))
|
|
calculateSection(minor_array)
|
|
calculateSection(mayor_array)
|
|
|
|
# Base widget for task panel terrain analisys
|
|
|
|
|
|
class _generalTaskPanel:
|
|
'''The TaskPanel for Slope setup'''
|
|
|
|
def __init__(self):
|
|
self.ranges = []
|
|
|
|
self.form = FreeCADGui.PySideUic.loadUi(os.path.dirname(__file__) + "/PVPlantTerrainAnalisys.ui")
|
|
self.tableWidget = self.form.tableWidget
|
|
self.form.editSteps.valueChanged.connect(self.changeDivision)
|
|
self.tableWidget.itemChanged.connect(self.cellChanged)
|
|
|
|
def cellChanged(self, item):
|
|
if (item.column() == 1) and (item.row() != (self.tableWidget.rowCount() - 1)):
|
|
item2 = self.tableWidget.item(item.row() + 1, 0)
|
|
item2.setText(item.text())
|
|
|
|
def updateTableValues(self):
|
|
maxval = self.form.editTo.value() - self.form.editFrom.value()
|
|
ran = maxval / self.tableWidget.rowCount()
|
|
|
|
for i in range(self.tableWidget.rowCount()):
|
|
for j in range(2):
|
|
item = self.tableWidget.item(i, j)
|
|
val = ran * (i + j) + self.form.editFrom.value()
|
|
item.setText('{:.1f}'.format(val))
|
|
self.ranges[i][j] = val
|
|
|
|
#self.tableWidget.item(0, 0).setText('{:.1f}'.format(self.form.editFrom.value()))
|
|
#self.tableWidget.item(self.tableWidget.rowCount() - 1, 1).setText('{:.1f}'.format(self.form.editTo.value()))
|
|
|
|
def changeDivision(self):
|
|
self.tableWidget.blockSignals(True)
|
|
rows = self.tableWidget.rowCount()
|
|
to = self.form.editSteps.value()
|
|
if to > rows:
|
|
for i in range(0, to - rows):
|
|
self.ranges.append([0.0, 0.0, (0.0, 0.0, 0.0)])
|
|
self.createRow()
|
|
elif to < rows:
|
|
self.tableWidget.setRowCount(to)
|
|
self.ranges = self.ranges[:to]
|
|
self.updateTableValues()
|
|
self.tableWidget.blockSignals(False)
|
|
|
|
def createRow(self):
|
|
row = self.tableWidget.rowCount()
|
|
self.tableWidget.setRowCount(self.tableWidget.rowCount() + 1)
|
|
|
|
newItem = QtGui.QTableWidgetItem("item")
|
|
self.tableWidget.setItem(row, 0, newItem)
|
|
newItem.setTextAlignment(QtCore.Qt.AlignCenter)
|
|
newItem.setText("0.0")
|
|
newItem.setFlags(QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEditable|QtCore.Qt.ItemIsDragEnabled|
|
|
QtCore.Qt.ItemIsDropEnabled|QtCore.Qt.ItemIsUserCheckable)
|
|
|
|
newItem = QtGui.QTableWidgetItem("item")
|
|
self.tableWidget.setItem(row, 1, newItem)
|
|
newItem.setTextAlignment(QtCore.Qt.AlignCenter)
|
|
newItem.setText("0.0")
|
|
|
|
#import random
|
|
# r = random.randint(0, 255)
|
|
# g = random.randint(0, 255)
|
|
# b = random.randint(0, 255)
|
|
|
|
val = int(127 * row / (self.form.editSteps.value() / 2))
|
|
g = (127 + val) if val <= 127 else 0
|
|
r = (328 - val if val >= 127 else 0)
|
|
color = QtGui.QColor(r, g, 0)
|
|
colorPix = QtGui.QPixmap(16, 16)
|
|
colorPix.fill(color)
|
|
self.ranges[row][2] = (color.red()/255, color.green()/255, color.blue()/255)
|
|
buttonColor = QtGui.QPushButton('')
|
|
buttonColor.setIcon(QtGui.QIcon(colorPix))
|
|
buttonColor.setMaximumSize(QtCore.QSize(20, 20))
|
|
buttonColor.clicked.connect(lambda: self.selColor(buttonColor))
|
|
self.tableWidget.setCellWidget(row, 2, buttonColor)
|
|
|
|
def selColor(self, button):
|
|
color = QtGui.QColorDialog.getColor()
|
|
if color.isValid():
|
|
print("añadir color")
|
|
colorPix = QtGui.QPixmap(16, 16)
|
|
colorPix.fill(color)
|
|
button.setIcon(QtGui.QIcon(colorPix))
|
|
curentIndex = self.tableWidget.currentIndex()
|
|
self.ranges[curentIndex.row()][2] = (color.red()/255, color.green()/255, color.blue()/255)
|
|
|
|
# Contours Analisys: ---------------------------------------------------------------------------------
|
|
class ContourTaskPanel():
|
|
'''The editmode TaskPanel for contours generator'''
|
|
|
|
def __init__(self):
|
|
self.MinorColor = (0.5, 0.5, 0.5)
|
|
self.MayorColor = (0.5, 0.5, 0.5)
|
|
land = None
|
|
self.intervals = ["0.1 m", "0.5 m", "1 m", "5 m", "10 m", "50 m", "100 m", "500 m"]
|
|
self.intervalvalues = [0.1, 0.5, 1, 5, 10, 50, 100, 500]
|
|
|
|
# form:
|
|
self.form = QtGui.QWidget()
|
|
self.form.resize(800,640)
|
|
self.form.setWindowTitle("Curvas de nivel")
|
|
self.form.setWindowIcon(QtGui.QIcon(os.path.join(DirIcons, "contours.svg")))
|
|
self.grid = QtGui.QGridLayout(self.form)
|
|
|
|
# parameters
|
|
self.labelTerrain = QtGui.QLabel()
|
|
self.labelTerrain.setText("Terreno:")
|
|
self.lineEdit1 = QtGui.QLineEdit(self.form)
|
|
self.lineEdit1.setObjectName(_fromUtf8("lineEdit1"))
|
|
self.lineEdit1.readOnly = True
|
|
self.grid.addWidget(self.labelTerrain, self.grid.rowCount(), 0, 1, 1)
|
|
self.grid.addWidget(self.lineEdit1, self.grid.rowCount() - 1, 1, 1, 1)
|
|
|
|
self.buttonAdd = QtGui.QPushButton('Seleccionar Terreno')
|
|
self.buttonAdd.clicked.connect(self.add)
|
|
self.grid.addWidget(self.buttonAdd, self.grid.rowCount(), 1, 1, 1)
|
|
|
|
###----------------------
|
|
|
|
self.widgetDivisions = QtGui.QGroupBox(self.form)
|
|
self.grid.addWidget(self.widgetDivisions, self.grid.rowCount(), 0, 1, -1)
|
|
self.gridDivisions = QtGui.QGridLayout(self.widgetDivisions)
|
|
|
|
self.labelTitle1 = QtGui.QLabel()
|
|
self.labelTitle1.setText("Intervalo")
|
|
self.labelTitle2 = QtGui.QLabel()
|
|
self.labelTitle2.setText("Grosor")
|
|
self.labelTitle3 = QtGui.QLabel()
|
|
self.labelTitle3.setText("Color")
|
|
self.gridDivisions.addWidget(self.labelTitle1, self.gridDivisions.rowCount(), 1, 1, -1)
|
|
self.gridDivisions.addWidget(self.labelTitle2, self.gridDivisions.rowCount() - 1, 2, 1, -1)
|
|
self.gridDivisions.addWidget(self.labelTitle3, self.gridDivisions.rowCount() - 1, 3, 1, -1)
|
|
|
|
self.labelMinorContour = QtGui.QLabel(self.form)
|
|
self.labelMinorContour.setText("Menor:")
|
|
self.inputMinorContourMargin = QtGui.QComboBox(self.form)
|
|
self.inputMinorContourMargin.addItems(self.intervals)
|
|
self.inputMinorContourMargin.setCurrentIndex(2)
|
|
self.inputMinorContourThickness = QtGui.QSpinBox(self.form)
|
|
self.inputMinorContourThickness.setRange(1, 10)
|
|
self.inputMinorContourThickness.setValue(2)
|
|
|
|
self.gridDivisions.addWidget(self.labelMinorContour, self.gridDivisions.rowCount(), 0, 1, 1)
|
|
self.gridDivisions.addWidget(self.inputMinorContourMargin, self.gridDivisions.rowCount() - 1, 1, 1, 1)
|
|
self.gridDivisions.addWidget(self.inputMinorContourThickness, self.gridDivisions.rowCount() - 1, 2, 1, 1)
|
|
|
|
self.buttonMinorContourColor = QtGui.QPushButton('')
|
|
self.color = QtGui.QColor(128, 128, 128)
|
|
colorPix = QtGui.QPixmap(16, 16)
|
|
colorPix.fill(self.color)
|
|
self.buttonMinorContourColor.setIcon(QtGui.QIcon(colorPix))
|
|
self.buttonMinorContourColor.clicked.connect(lambda: self.selColor(self.buttonMinorContourColor))
|
|
self.gridDivisions.addWidget(self.buttonMinorContourColor, self.gridDivisions.rowCount() - 1, 3, 1, 1)
|
|
|
|
###----------------------
|
|
|
|
self.labelMayorContour = QtGui.QLabel(self.form)
|
|
self.labelMayorContour.setText("Mayor:")
|
|
|
|
self.inputMayorContourMargin = QtGui.QComboBox(self.form)
|
|
self.inputMayorContourMargin.addItems(self.intervals)
|
|
self.inputMayorContourMargin.setCurrentIndex(3)
|
|
|
|
self.inputMayorContourThickness = QtGui.QSpinBox(self.form)
|
|
self.inputMayorContourThickness.setRange(1, 10)
|
|
self.inputMayorContourThickness.setValue(5)
|
|
|
|
self.gridDivisions.addWidget(self.labelMayorContour, self.gridDivisions.rowCount(), 0, 1, 1)
|
|
self.gridDivisions.addWidget(self.inputMayorContourMargin, self.gridDivisions.rowCount() - 1, 1, 1, 1)
|
|
self.gridDivisions.addWidget(self.inputMayorContourThickness, self.gridDivisions.rowCount() - 1, 2, 1, 1)
|
|
|
|
self.buttonMayorContourColor = QtGui.QPushButton('')
|
|
self.color = QtGui.QColor(128, 128, 128)
|
|
colorPix = QtGui.QPixmap(16, 16)
|
|
colorPix.fill(self.color)
|
|
self.buttonMayorContourColor.setIcon(QtGui.QIcon(colorPix))
|
|
self.buttonMayorContourColor.clicked.connect(lambda: self.selColor(self.buttonMayorContourColor))
|
|
self.gridDivisions.addWidget(self.buttonMayorContourColor, self.gridDivisions.rowCount() - 1, 3, 1, 1)
|
|
|
|
|
|
def add(self):
|
|
sel = FreeCADGui.Selection.getSelection()
|
|
if len(sel) > 0:
|
|
self.land = sel[0]
|
|
self.lineEdit1.setText(self.land.Label)
|
|
|
|
def selColor(self, button):
|
|
color = QtGui.QColorDialog.getColor()
|
|
colorPix = QtGui.QPixmap(16, 16)
|
|
colorPix.fill(color)
|
|
button.setIcon(QtGui.QIcon(colorPix))
|
|
|
|
r = float(color.red()/255.0)
|
|
g = float(color.green()/255.0)
|
|
b = float(color.blue()/255.0)
|
|
col = (r, g, b)
|
|
|
|
if button is self.buttonMinorContourColor:
|
|
self.MinorColor = col
|
|
elif button is self.buttonMayorContourColor:
|
|
self.MayorColor = col
|
|
|
|
def accept(self):
|
|
from datetime import datetime
|
|
starttime = datetime.now()
|
|
|
|
if self.land is None:
|
|
print("No hay objetos para procesar")
|
|
return False
|
|
else:
|
|
minor = FreeCAD.Units.Quantity(self.inputMinorContourMargin.currentText()).Value
|
|
mayor = FreeCAD.Units.Quantity(self.inputMayorContourMargin.currentText()).Value
|
|
|
|
i = 2
|
|
if i == 0:
|
|
makeContours(self.land, minor, mayor, self.MinorColor, self.MayorColor,
|
|
self.inputMinorContourThickness.value(), self.inputMayorContourThickness.value())
|
|
elif i == 1:
|
|
import multiprocessing
|
|
p = multiprocessing.Process(target=makeContours,
|
|
args=(self.land, minor, mayor,
|
|
self.MinorColor, self.MayorColor,
|
|
self.inputMinorContourThickness.value(),
|
|
self.inputMayorContourThickness.value(), ))
|
|
p.start()
|
|
p.join()
|
|
|
|
else:
|
|
import threading
|
|
hilo = threading.Thread(target = makeContours,
|
|
args = (self.land, minor, mayor,
|
|
self.MinorColor, self.MayorColor,
|
|
self.inputMinorContourThickness.value(),
|
|
self.inputMayorContourThickness.value()))
|
|
hilo.daemon = True
|
|
hilo.start()
|
|
|
|
total_time = datetime.now() - starttime
|
|
print(" -- Tiempo tardado:", total_time)
|
|
FreeCADGui.Control.closeDialog()
|
|
return True
|
|
|
|
# Height Analisys: ---------------------------------------------------------------------------------
|
|
class HeightTaskPanel(_generalTaskPanel):
|
|
'''The TaskPanel for Slope setup'''
|
|
|
|
def __init__(self):
|
|
_generalTaskPanel.__init__(self)
|
|
|
|
# Initial set-up:
|
|
land = FreeCAD.ActiveDocument.Site.Terrain
|
|
self.form.editFrom.setSuffix(" m")
|
|
self.form.editFrom.setValue(land.Shape.BoundBox.ZMin / 1000)
|
|
self.form.editTo.setSuffix(" m")
|
|
self.form.editTo.setValue(land.Shape.BoundBox.ZMax / 1000)
|
|
self.form.editSteps.setValue(10)
|
|
self.form.editFrom.valueChanged.connect(self.updateTableValues)
|
|
self.form.editTo.valueChanged.connect(self.updateTableValues)
|
|
|
|
def accept(self):
|
|
land = FreeCAD.ActiveDocument.Site.Terrain
|
|
if land.isDerivedFrom("Part::Feature"):
|
|
colorlist = []
|
|
for face in land.Shape.Faces:
|
|
zz = face.CenterOfMass.z / 1000
|
|
color = (.0, .0, .0)
|
|
for i in range(1,len(self.ranges)):
|
|
if self.ranges[i][0] <= zz <= self.ranges[i][1]:
|
|
color = self.ranges[i][2]
|
|
break
|
|
colorlist.append(color)
|
|
land.ViewObject.DiffuseColor = colorlist
|
|
FreeCAD.activeDocument().recompute()
|
|
return True
|
|
|
|
# Slope Analisys: ---------------------------------------------------------------------------------
|
|
class SlopeTaskPanel(_generalTaskPanel):
|
|
'''The TaskPanel for Slope setup'''
|
|
|
|
def __init__(self):
|
|
_generalTaskPanel.__init__(self)
|
|
self.angles = self.getAngles()
|
|
# Initial set-up:
|
|
self.form.editFrom.setSuffix(" º")
|
|
self.form.editFrom.setValue(0)
|
|
self.form.editTo.setSuffix(" º")
|
|
self.form.editTo.setValue(max(self.angles))
|
|
self.form.editSteps.setValue(10)
|
|
self.form.editFrom.valueChanged.connect(self.updateTableValues)
|
|
self.form.editTo.valueChanged.connect(self.updateTableValues)
|
|
|
|
def getAngles(self):
|
|
import math
|
|
land = FreeCAD.ActiveDocument.Site.Terrain
|
|
angles = []
|
|
for face in land.Shape.Faces:
|
|
normal = face.normalAt(0, 0)
|
|
rad = normal.getAngle(FreeCAD.Vector(0, 0, 1))
|
|
angle = math.degrees(rad)
|
|
angles.append(angle)
|
|
return angles
|
|
|
|
def getPointSlope(self, ranges = None):
|
|
from datetime import datetime
|
|
starttime = datetime.now()
|
|
import math
|
|
|
|
land = FreeCAD.ActiveDocument.Site.Terrain
|
|
if land.isDerivedFrom("Part::Feature"):
|
|
colorlist = []
|
|
for face in land.Shape.Faces:
|
|
normal = face.normalAt(0, 0)
|
|
rad = normal.getAngle(FreeCAD.Vector(0, 0, 1))
|
|
angle = math.degrees(rad)
|
|
if(angle > 90):
|
|
angle -= 90
|
|
color = (1.0, 1.0, 1.0)
|
|
for i in range(0, len(ranges)):
|
|
if ranges[i][0] <= angle <= ranges[i][1]:
|
|
color = ranges[i][2]
|
|
break
|
|
colorlist.append(color)
|
|
print(len(land.Shape.Faces) == len(colorlist))
|
|
land.ViewObject.DiffuseColor = colorlist
|
|
|
|
# TODO: check this code:
|
|
elif obj.isDerivedFrom("Mesh::Feature"):
|
|
fMesh = Mest2FemMesh(land)
|
|
import math
|
|
setColors = []
|
|
i = 1
|
|
normals = land.Mesh.getPointNormals()
|
|
for normal in normals:
|
|
rad = normal.getAngle(FreeCAD.Vector(0, 0, 1))
|
|
angle = math.degrees(rad)
|
|
|
|
# Cambiar esto a la lista de colores configurable
|
|
if angle < 5:
|
|
setColors[i] = (0.0, 0.5, 0.0)
|
|
elif angle < 7.5:
|
|
setColors[i] = (0.0, 1.0, 0.5)
|
|
elif (angle < 10):
|
|
setColors[i] = (0.0, 1.0, 1.0)
|
|
elif (angle < 12.5):
|
|
setColors[i] = (0.0, 0.0, 0.5)
|
|
elif (angle < 14):
|
|
setColors[i] = (0.0, 0.0, 1.0)
|
|
elif (angle > 20):
|
|
setColors[i] = (1.0, 0.0, 0.0)
|
|
else:
|
|
setColors[i] = (1.0, 1.0, 1.0)
|
|
i += 1
|
|
|
|
fMesh.ViewObject.NodeColor = setColors
|
|
|
|
FreeCAD.activeDocument().recompute()
|
|
print("Everything OK (", datetime.now() - starttime, ")")
|
|
|
|
def accept(self):
|
|
# self.getPointSlope()
|
|
import threading
|
|
hilo = threading.Thread(target=self.getPointSlope(self.ranges))
|
|
hilo.start()
|
|
return True
|
|
|
|
# Orientation Analisys: ---------------------------------------------------------------------------------
|
|
class OrientationTaskPanel(_generalTaskPanel):
|
|
'''The TaskPanel for Orientation setup'''
|
|
|
|
def __init__(self):
|
|
_generalTaskPanel.__init__(self)
|
|
|
|
self.getAngles()
|
|
|
|
# Initial set-up:
|
|
self.form.editFrom.setSuffix(" º")
|
|
self.form.editFrom.setValue(0.0)
|
|
self.form.editTo.setSuffix(" º")
|
|
self.form.editTo.setMaximum(360.0)
|
|
self.form.editTo.setValue(360.0)
|
|
self.form.editSteps.setValue(15)
|
|
self.form.editFrom.valueChanged.connect(self.updateTableValues)
|
|
self.form.editTo.valueChanged.connect(self.updateTableValues)
|
|
|
|
def getAngles(self):
|
|
import math
|
|
land = FreeCAD.ActiveDocument.Site.Terrain
|
|
anglesx = []
|
|
anglesy = []
|
|
for face in land.Shape.Faces:
|
|
normal = face.normalAt(0, 0)
|
|
normal.z = 0
|
|
anglesx.append(math.degrees(normal.getAngle(FreeCAD.Vector(1, 0, 0))))
|
|
anglesy.append(math.degrees(normal.getAngle(FreeCAD.Vector(0, 1, 0))))
|
|
|
|
print("Min x: ", min(anglesx), " y: ", min(anglesy))
|
|
print("Max x: ", max(anglesx), " y: ", max(anglesy))
|
|
return anglesx, anglesy
|
|
|
|
def accept(self):
|
|
import math
|
|
from datetime import datetime
|
|
starttime = datetime.now()
|
|
|
|
land = FreeCAD.ActiveDocument.Site.Terrain
|
|
if land.isDerivedFrom("Part::Feature"):
|
|
colorlist = []
|
|
j = 0
|
|
minx = 99999
|
|
miny = 99999
|
|
for face in land.Shape.Faces:
|
|
normal = face.normalAt(0, 0)
|
|
normal.z = 0
|
|
anglex = math.degrees(normal.getAngle(FreeCAD.Vector(1, 0, 0)))
|
|
angley = math.degrees(normal.getAngle(FreeCAD.Vector(0, 1, 0)))
|
|
|
|
minx = min([minx, anglex])
|
|
miny = min([miny, angley])
|
|
if angley >= 90:
|
|
anglex = 360.0 - anglex
|
|
|
|
#print(anglex, " ", angley)
|
|
for i in range(1, len(self.ranges)):
|
|
if self.ranges[i][0] <= anglex <= self.ranges[i][1]:
|
|
colorlist.append(self.ranges[i][2])
|
|
break
|
|
j += 1
|
|
if j == 100:
|
|
break
|
|
land.ViewObject.DiffuseColor = colorlist
|
|
print("Angulos: ", math.degrees(minx), " - ", miny)
|
|
|
|
# TODO: check this code:
|
|
elif land.isDerivedFrom("Mesh::Feature"):
|
|
fMesh = Mest2FemMesh(land)
|
|
fMesh = Mest2FemMesh(land)
|
|
|
|
setColors = {}
|
|
i = 1
|
|
normals = land.Mesh.getPointNormals()
|
|
print(" --------- time to FEMMESH: (", datetime.now() - starttime, ")")
|
|
|
|
for normal in normals:
|
|
rad = normal.getAngle(FreeCAD.Vector(1, 1, 0))
|
|
angle = math.degrees(rad)
|
|
|
|
# Cambiar esto a la lista de colores configurable
|
|
if angle < 45:
|
|
setColors[i] = (0.0, 1.0, 0.0)
|
|
elif (angle < 90):
|
|
setColors[i] = (0.0, 1.0, 1.0)
|
|
elif (angle < 135):
|
|
setColors[i] = (0.0, 0.0, 1.0)
|
|
elif (angle <= 180):
|
|
setColors[i] = (1.0, 0.0, 1.0)
|
|
#else:
|
|
# setColors[i] = (1.0, 0.0, 0.0)
|
|
|
|
i += 1
|
|
if i== 1000:
|
|
break
|
|
|
|
fMesh.ViewObject.NodeColor = setColors
|
|
|
|
FreeCAD.activeDocument().recompute()
|
|
print("Everything OK (", datetime.now() - starttime, ")")
|
|
return True
|
|
|
|
## Commands ----------------------------------------------------------------------------------------------------------
|
|
## 1. Contours:
|
|
'''class _CommandContours:
|
|
def GetResources(self):
|
|
return {'Pixmap': str(os.path.join(DirIcons, "TerrainContours.svg")),
|
|
'Accel': "T, C",
|
|
'MenuText': 'Curvas de nivel',
|
|
'ToolTip': 'Curvas de nivel'
|
|
}
|
|
|
|
def IsActive(self):
|
|
# return not FreeCAD.ActiveDocument is None
|
|
if FreeCAD.ActiveDocument is None:
|
|
return False
|
|
|
|
return True
|
|
|
|
if FreeCADGui.Selection.getSelection() is not None:
|
|
selection = FreeCADGui.Selection.getSelection()[-1]
|
|
if selection.TypeId == 'Mesh::Feature':
|
|
return True
|
|
|
|
return False
|
|
|
|
def Activated(self):
|
|
self.TaskPanel = _ContourTaskPanel()
|
|
FreeCADGui.Control.showDialog(self.TaskPanel)
|
|
|
|
## 2. Aspect:
|
|
class _CommandSlopeAnalisys:
|
|
def GetResources(self):
|
|
return {'Pixmap': str(os.path.join(DirIcons, "TerrainSlope.svg")),
|
|
'Accel': "T, S",
|
|
'MenuText': 'Analisis de Pendiente',
|
|
'ToolTip': 'Analisis de Pendiente'
|
|
}
|
|
|
|
def IsActive(self):
|
|
return not FreeCAD.ActiveDocument is None
|
|
|
|
def Activated(self):
|
|
self.TaskPanel = _SlopeTaskPanel()
|
|
FreeCADGui.Control.showDialog(self.TaskPanel)
|
|
|
|
## 3. Height:
|
|
class _CommandHeightAnalisys:
|
|
def GetResources(self):
|
|
return {'Pixmap': str(os.path.join(DirIcons, "TerrainHeight.svg")),
|
|
'Accel': "T, H",
|
|
'MenuText': 'Analisis de Altura',
|
|
'ToolTip': 'Analisis de Altura'
|
|
}
|
|
|
|
def IsActive(self):
|
|
return not FreeCAD.ActiveDocument is None
|
|
|
|
def Activated(self):
|
|
self.TaskPanel = _HeightTaskPanel()
|
|
FreeCADGui.Control.showDialog(self.TaskPanel)
|
|
|
|
## 4. Orientation:
|
|
class _CommandOrientationAnalisys:
|
|
|
|
def GetResources(self):
|
|
return {'Pixmap': str(os.path.join(DirIcons, "TerrainOrientation.svg")),
|
|
'Accel': "T, H",
|
|
'MenuText': 'Analisis de Orientación',
|
|
'ToolTip': 'Analisis de Orientación'
|
|
}
|
|
|
|
def IsActive(self):
|
|
return not FreeCAD.ActiveDocument is None
|
|
|
|
def Activated(self):
|
|
self.TaskPanel = _OrientationTaskPanel()
|
|
FreeCADGui.Control.showDialog(self.TaskPanel)
|
|
|
|
## 5. Commands
|
|
if FreeCAD.GuiUp:
|
|
class CommandTerrainAnalisysGroup:
|
|
|
|
def GetCommands(self):
|
|
return tuple(['Contours',
|
|
'HeightAnalisys',
|
|
'SlopeAnalisys',
|
|
'OrientationAnalisys'
|
|
])
|
|
def GetResources(self):
|
|
return { 'MenuText': QT_TRANSLATE_NOOP("",'Terrain Analisys'),
|
|
'ToolTip': QT_TRANSLATE_NOOP("",'Terrain Analisys')
|
|
}
|
|
def IsActive(self):
|
|
return not FreeCAD.ActiveDocument is None
|
|
|
|
FreeCADGui.addCommand('Contours', _CommandContours())
|
|
FreeCADGui.addCommand('SlopeAnalisys', _CommandSlopeAnalisys())
|
|
FreeCADGui.addCommand('HeightAnalisys', _CommandHeightAnalisys())
|
|
FreeCADGui.addCommand('OrientationAnalisys', _CommandOrientationAnalisys())
|
|
FreeCADGui.addCommand('TerrainAnalisys', CommandTerrainAnalisysGroup())''' |