Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7d1127c6b5 | |||
| 7a54e424cb | |||
| 065f840941 | |||
| 74aedf6122 | |||
| 7c81beb1ba | |||
| 02b639d4ed |
@@ -0,0 +1,2 @@
|
|||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
@@ -114,7 +114,7 @@ def makeTrench(base=None):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
folder = FreeCAD.ActiveDocument.Trenches
|
folder = FreeCAD.ActiveDocument.Trenches
|
||||||
except:
|
except AttributeError:
|
||||||
folder = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", 'Trenches')
|
folder = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", 'Trenches')
|
||||||
folder.Label = "Trenches"
|
folder.Label = "Trenches"
|
||||||
folder.addObject(obj)
|
folder.addObject(obj)
|
||||||
|
|||||||
+89
-28
@@ -58,8 +58,9 @@ class MapWindow(QtGui.QWidget):
|
|||||||
self.setupUi()
|
self.setupUi()
|
||||||
|
|
||||||
def setupUi(self):
|
def setupUi(self):
|
||||||
from PySide2.QtWebEngineWidgets import QWebEngineView
|
# Intentar cargar QtWebEngine (no siempre disponible, ej: FreeCAD flatpak)
|
||||||
from PySide2.QtWebChannel import QWebChannel
|
QWebEngineView, QWebChannel = self._load_webengine()
|
||||||
|
self._webengine_available = QWebEngineView is not None
|
||||||
|
|
||||||
self.ui = FreeCADGui.PySideUic.loadUi(PVPlantResources.__dir__ + "/PVPlantGeoreferencing.ui", self)
|
self.ui = FreeCADGui.PySideUic.loadUi(PVPlantResources.__dir__ + "/PVPlantGeoreferencing.ui", self)
|
||||||
|
|
||||||
@@ -86,36 +87,54 @@ class MapWindow(QtGui.QWidget):
|
|||||||
self.layout.addWidget(RightWidget)
|
self.layout.addWidget(RightWidget)
|
||||||
|
|
||||||
# Left Widgets:
|
# Left Widgets:
|
||||||
# -- Search Bar:
|
if self._webengine_available:
|
||||||
self.valueSearch = QtGui.QLineEdit(self)
|
# -- Search Bar:
|
||||||
self.valueSearch.setPlaceholderText("Search")
|
self.valueSearch = QtGui.QLineEdit(self)
|
||||||
self.valueSearch.returnPressed.connect(self.onSearch)
|
self.valueSearch.setPlaceholderText("Search")
|
||||||
|
self.valueSearch.returnPressed.connect(self.onSearch)
|
||||||
|
|
||||||
searchbutton = QtGui.QPushButton('Search')
|
searchbutton = QtGui.QPushButton('Search')
|
||||||
searchbutton.setFixedWidth(80)
|
searchbutton.setFixedWidth(80)
|
||||||
searchbutton.clicked.connect(self.onSearch)
|
searchbutton.clicked.connect(self.onSearch)
|
||||||
|
|
||||||
SearchBarLayout = QtGui.QHBoxLayout(self)
|
SearchBarLayout = QtGui.QHBoxLayout(self)
|
||||||
SearchBarLayout.addWidget(self.valueSearch)
|
SearchBarLayout.addWidget(self.valueSearch)
|
||||||
SearchBarLayout.addWidget(searchbutton)
|
SearchBarLayout.addWidget(searchbutton)
|
||||||
LeftLayout.addLayout(SearchBarLayout)
|
LeftLayout.addLayout(SearchBarLayout)
|
||||||
|
|
||||||
# -- Webbroser:
|
# -- Web browser:
|
||||||
self.view = QWebEngineView()
|
self.view = QWebEngineView()
|
||||||
self.channel = QWebChannel(self.view.page())
|
self.channel = QWebChannel(self.view.page())
|
||||||
self.view.page().setWebChannel(self.channel)
|
self.view.page().setWebChannel(self.channel)
|
||||||
self.channel.registerObject("MyApp", self)
|
self.channel.registerObject("MyApp", self)
|
||||||
file = os.path.join(DirResources, "webs", "main.html")
|
file = os.path.join(DirResources, "webs", "main.html")
|
||||||
self.view.page().loadFinished.connect(self.onLoadFinished)
|
self.view.page().loadFinished.connect(self.onLoadFinished)
|
||||||
self.view.page().load(QtCore.QUrl.fromLocalFile(file))
|
self.view.page().load(QtCore.QUrl.fromLocalFile(file))
|
||||||
LeftLayout.addWidget(self.view)
|
LeftLayout.addWidget(self.view)
|
||||||
# self.layout.addWidget(self.view, 1, 0, 1, 3)
|
else:
|
||||||
|
# -- Modo manual: entrada de coordenadas sin mapa web
|
||||||
|
self.valueSearch = QtGui.QLineEdit(self)
|
||||||
|
self.valueSearch.setPlaceholderText("Latitud, Longitud (ej: 40.4168, -3.7038)")
|
||||||
|
self.valueSearch.returnPressed.connect(self.onManualCoords)
|
||||||
|
|
||||||
|
searchbutton = QtGui.QPushButton('Ir')
|
||||||
|
searchbutton.setFixedWidth(80)
|
||||||
|
searchbutton.clicked.connect(self.onManualCoords)
|
||||||
|
|
||||||
|
SearchBarLayout = QtGui.QHBoxLayout(self)
|
||||||
|
SearchBarLayout.addWidget(self.valueSearch)
|
||||||
|
SearchBarLayout.addWidget(searchbutton)
|
||||||
|
LeftLayout.addLayout(SearchBarLayout)
|
||||||
|
|
||||||
|
info = QtGui.QLabel("Mapa web no disponible. Introduce coordenadas manualmente.")
|
||||||
|
info.setStyleSheet("color: #888; font-style: italic; padding: 20px;")
|
||||||
|
info.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
|
LeftLayout.addWidget(info)
|
||||||
|
|
||||||
# -- Latitud y longitud:
|
# -- Latitud y longitud:
|
||||||
self.labelCoordinates = QtGui.QLabel()
|
self.labelCoordinates = QtGui.QLabel()
|
||||||
self.labelCoordinates.setFixedHeight(21)
|
self.labelCoordinates.setFixedHeight(21)
|
||||||
LeftLayout.addWidget(self.labelCoordinates)
|
LeftLayout.addWidget(self.labelCoordinates)
|
||||||
# self.layout.addWidget(self.labelCoordinates, 2, 0, 1, 3)
|
|
||||||
|
|
||||||
# Right Widgets:
|
# Right Widgets:
|
||||||
labelKMZ = QtGui.QLabel()
|
labelKMZ = QtGui.QLabel()
|
||||||
@@ -139,9 +158,6 @@ class MapWindow(QtGui.QWidget):
|
|||||||
radio3 = QtGui.QRadioButton("Datos GPS")
|
radio3 = QtGui.QRadioButton("Datos GPS")
|
||||||
radio1.setChecked(True)
|
radio1.setChecked(True)
|
||||||
|
|
||||||
# buttonDialog = QtGui.QPushButton('...')
|
|
||||||
# buttonDialog.setEnabled(False)
|
|
||||||
|
|
||||||
vbox = QtGui.QVBoxLayout(self)
|
vbox = QtGui.QVBoxLayout(self)
|
||||||
vbox.addWidget(radio1)
|
vbox.addWidget(radio1)
|
||||||
vbox.addWidget(radio2)
|
vbox.addWidget(radio2)
|
||||||
@@ -149,7 +165,6 @@ class MapWindow(QtGui.QWidget):
|
|||||||
|
|
||||||
self.groupbox.setLayout(vbox)
|
self.groupbox.setLayout(vbox)
|
||||||
RightLayout.addWidget(self.groupbox)
|
RightLayout.addWidget(self.groupbox)
|
||||||
# ------------------------
|
|
||||||
|
|
||||||
self.checkboxImportGis = QtGui.QCheckBox("Importar datos GIS")
|
self.checkboxImportGis = QtGui.QCheckBox("Importar datos GIS")
|
||||||
RightLayout.addWidget(self.checkboxImportGis)
|
RightLayout.addWidget(self.checkboxImportGis)
|
||||||
@@ -174,6 +189,52 @@ class MapWindow(QtGui.QWidget):
|
|||||||
with open(file, 'r') as f:
|
with open(file, 'r') as f:
|
||||||
frame.runJavaScript(f.read())
|
frame.runJavaScript(f.read())
|
||||||
|
|
||||||
|
def _load_webengine(self):
|
||||||
|
"""Intenta cargar QWebEngineView desde cualquier versión de PySide.
|
||||||
|
Retorna (QWebEngineView_class, QWebChannel_class) o (None, None)."""
|
||||||
|
for modpath in [
|
||||||
|
'PySide6.QtWebEngineWidgets',
|
||||||
|
'PySide6.QtWebEngineCore',
|
||||||
|
'PySide6.QtWebEngineQuick',
|
||||||
|
'PySide2.QtWebEngineWidgets',
|
||||||
|
'PySide.QtWebEngineWidgets',
|
||||||
|
]:
|
||||||
|
try:
|
||||||
|
parts = modpath.split('.')
|
||||||
|
mod = __import__(parts[0], fromlist=parts[1:])
|
||||||
|
for p in parts[1:]:
|
||||||
|
mod = getattr(mod, p)
|
||||||
|
View = getattr(mod, 'QWebEngineView', None)
|
||||||
|
Channel = getattr(mod, 'QWebChannel', None)
|
||||||
|
if View is not None:
|
||||||
|
return View, Channel
|
||||||
|
except (ImportError, AttributeError):
|
||||||
|
continue
|
||||||
|
# Fallback: intentar por separado QtWebChannel (sí existe en flatpak)
|
||||||
|
try:
|
||||||
|
from PySide6.QtWebChannel import QWebChannel as Channel
|
||||||
|
except ImportError:
|
||||||
|
Channel = None
|
||||||
|
FreeCAD.Console.PrintWarning(
|
||||||
|
"PVPlantGeoreferencing: QtWebEngine no disponible. "
|
||||||
|
"Usando modo manual de coordenadas.\n")
|
||||||
|
return None, Channel
|
||||||
|
|
||||||
|
def onManualCoords(self):
|
||||||
|
"""Procesa entrada manual de latitud,longitud"""
|
||||||
|
text = self.valueSearch.text().strip()
|
||||||
|
if not text:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
parts = text.replace(',', ' ').split()
|
||||||
|
lat = float(parts[0])
|
||||||
|
lon = float(parts[1])
|
||||||
|
self.georeference_coordinates = {'lat': lat, 'lon': lon}
|
||||||
|
self.labelCoordinates.setText(f"{lat:.6f}, {lon:.6f}")
|
||||||
|
FreeCAD.Console.PrintMessage(f"Coordenadas: {lat:.6f}, {lon:.6f}\n")
|
||||||
|
except (ValueError, IndexError):
|
||||||
|
FreeCAD.Console.PrintError("Formato inválido. Usa: latitud, longitud\n")
|
||||||
|
|
||||||
def onSearch(self):
|
def onSearch(self):
|
||||||
if self.valueSearch.text() == "":
|
if self.valueSearch.text() == "":
|
||||||
return
|
return
|
||||||
|
|||||||
+45
-6
@@ -39,6 +39,51 @@ import os
|
|||||||
from PVPlantResources import DirIcons as DirIcons
|
from PVPlantResources import DirIcons as DirIcons
|
||||||
import PVPlantSite
|
import PVPlantSite
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Adaptador UTM: emula la API de la librería 'utm' usando pyproj
|
||||||
|
# La librería 'utm' dejó de usarse en favor de pyproj (más completa y mantenida).
|
||||||
|
# from_latlon(lat, lon) -> (easting, northing, zone_number, zone_letter)
|
||||||
|
# to_latlon(easting, northing, zone_number, zone_letter) -> (lat, lon)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
_utm_cache = {}
|
||||||
|
|
||||||
|
def _get_transformer(lat, lon):
|
||||||
|
"""Obtiene o crea un transformador UTM para las coordenadas dadas."""
|
||||||
|
from pyproj import Transformer
|
||||||
|
zone = int((lon + 180) / 6) + 1
|
||||||
|
hem = 'S' if lat < 0 else 'N'
|
||||||
|
key = (zone, hem)
|
||||||
|
if key not in _utm_cache:
|
||||||
|
crs_utm = f'+proj=utm +zone={zone} +{hem.lower()} +ellps=WGS84 +datum=WGS84 +units=m +no_defs'
|
||||||
|
_utm_cache[key] = Transformer.from_crs('EPSG:4326', crs_utm, always_xy=True)
|
||||||
|
return _utm_cache[key], zone, hem
|
||||||
|
|
||||||
|
def from_latlon(lat, lon):
|
||||||
|
"""Convierte (lat, lon) a UTM. Retorna (easting, northing, zone_number, zone_letter)."""
|
||||||
|
transformer, zone, hem = _get_transformer(lat, lon)
|
||||||
|
easting, northing = transformer.transform(lon, lat)
|
||||||
|
return (easting, northing, zone, hem)
|
||||||
|
|
||||||
|
def to_latlon(easting, northing, zone_number, zone_letter):
|
||||||
|
"""Convierte UTM a (lat, lon)."""
|
||||||
|
from pyproj import Transformer
|
||||||
|
hem = zone_letter.upper()
|
||||||
|
key = (zone_number, hem)
|
||||||
|
if key not in _utm_cache:
|
||||||
|
crs_utm = f'+proj=utm +zone={zone_number} +{hem.lower()} +ellps=WGS84 +datum=WGS84 +units=m +no_defs'
|
||||||
|
_utm_cache[key] = Transformer.from_crs(crs_utm, 'EPSG:4326', always_xy=True)
|
||||||
|
lon, lat = _utm_cache[key].transform(easting, northing)
|
||||||
|
return (lat, lon)
|
||||||
|
|
||||||
|
# Parche: reemplazar el módulo 'utm' por nuestro adaptador
|
||||||
|
import sys
|
||||||
|
class _UTMWrapper:
|
||||||
|
"""Wrapper para que 'import utm' devuelva nuestras funciones."""
|
||||||
|
from_latlon = staticmethod(from_latlon)
|
||||||
|
to_latlon = staticmethod(to_latlon)
|
||||||
|
sys.modules['utm'] = _UTMWrapper
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
def get_elevation_from_oe(coordinates): # v1 deepseek
|
def get_elevation_from_oe(coordinates): # v1 deepseek
|
||||||
"""Obtiene elevaciones de Open-Elevation API y devuelve vectores FreeCAD en coordenadas UTM.
|
"""Obtiene elevaciones de Open-Elevation API y devuelve vectores FreeCAD en coordenadas UTM.
|
||||||
@@ -52,7 +97,6 @@ def get_elevation_from_oe(coordinates): # v1 deepseek
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import utm
|
|
||||||
from requests.exceptions import RequestException
|
from requests.exceptions import RequestException
|
||||||
|
|
||||||
# Construcción más eficiente de parámetros
|
# Construcción más eficiente de parámetros
|
||||||
@@ -110,7 +154,6 @@ def getElevationFromOE(coordinates):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
from requests import get
|
from requests import get
|
||||||
import utm
|
|
||||||
|
|
||||||
locations_str=""
|
locations_str=""
|
||||||
total = len(coordinates) - 1
|
total = len(coordinates) - 1
|
||||||
@@ -141,7 +184,6 @@ def getElevationFromOE(coordinates):
|
|||||||
|
|
||||||
def getSinglePointElevationFromBing(lat, lng):
|
def getSinglePointElevationFromBing(lat, lng):
|
||||||
#http://dev.virtualearth.net/REST/v1/Elevation/List?points={lat1,long1,lat2,long2,latN,longnN}&heights={heights}&key={BingMapsAPIKey}
|
#http://dev.virtualearth.net/REST/v1/Elevation/List?points={lat1,long1,lat2,long2,latN,longnN}&heights={heights}&key={BingMapsAPIKey}
|
||||||
import utm
|
|
||||||
|
|
||||||
source = "http://dev.virtualearth.net/REST/v1/Elevation/List?points="
|
source = "http://dev.virtualearth.net/REST/v1/Elevation/List?points="
|
||||||
source += str(lat) + "," + str(lng)
|
source += str(lat) + "," + str(lng)
|
||||||
@@ -166,7 +208,6 @@ def getSinglePointElevationFromBing(lat, lng):
|
|||||||
def getGridElevationFromBing(polygon, lat, lng, resolution = 1000):
|
def getGridElevationFromBing(polygon, lat, lng, resolution = 1000):
|
||||||
#http://dev.virtualearth.net/REST/v1/Elevation/Polyline?points=35.89431,-110.72522,35.89393,-110.72578,35.89374,-110.72606,35.89337,-110.72662
|
#http://dev.virtualearth.net/REST/v1/Elevation/Polyline?points=35.89431,-110.72522,35.89393,-110.72578,35.89374,-110.72606,35.89337,-110.72662
|
||||||
# &heights=ellipsoid&samples=10&key={BingMapsAPIKey}
|
# &heights=ellipsoid&samples=10&key={BingMapsAPIKey}
|
||||||
import utm
|
|
||||||
import math
|
import math
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
@@ -311,7 +352,6 @@ def getSinglePointElevationUtm(lat, lon):
|
|||||||
res = s['results']
|
res = s['results']
|
||||||
print (res)
|
print (res)
|
||||||
|
|
||||||
import utm
|
|
||||||
for r in res:
|
for r in res:
|
||||||
c = utm.from_latlon(r['location']['lat'], r['location']['lng'])
|
c = utm.from_latlon(r['location']['lat'], r['location']['lng'])
|
||||||
v = FreeCAD.Vector(
|
v = FreeCAD.Vector(
|
||||||
@@ -323,7 +363,6 @@ def getSinglePointElevationUtm(lat, lon):
|
|||||||
|
|
||||||
def getElevationUTM(polygon, lat, lng, resolution = 10000):
|
def getElevationUTM(polygon, lat, lng, resolution = 10000):
|
||||||
|
|
||||||
import utm
|
|
||||||
geo = utm.from_latlon(lat, lng)
|
geo = utm.from_latlon(lat, lng)
|
||||||
# result = (679434.3578335291, 4294023.585627955, 30, 'S')
|
# result = (679434.3578335291, 4294023.585627955, 30, 'S')
|
||||||
# EASTING, NORTHING, ZONE NUMBER, ZONE LETTER
|
# EASTING, NORTHING, ZONE NUMBER, ZONE LETTER
|
||||||
|
|||||||
+2
-2
@@ -1164,8 +1164,8 @@ from scipy.interpolate import LinearNDInterpolator
|
|||||||
import Part
|
import Part
|
||||||
import FreeCAD
|
import FreeCAD
|
||||||
import FreeCADGui
|
import FreeCADGui
|
||||||
from PySide2 import QtCore, QtGui
|
from PySide import QtCore, QtGui
|
||||||
from PySide2.QtWidgets import QListWidgetItem
|
from PySide.QtWidgets import QListWidgetItem
|
||||||
import os
|
import os
|
||||||
import PVPlantResources
|
import PVPlantResources
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
# Script para FreeCAD - Procesador de Documentos Word con Carátula
|
# Script para FreeCAD - Procesador de Documentos Word con Carátula
|
||||||
import os
|
import os
|
||||||
import glob
|
import glob
|
||||||
from PySide2 import QtWidgets, QtCore
|
from PySide import QtWidgets, QtCore
|
||||||
from PySide2.QtWidgets import (QFileDialog, QMessageBox, QProgressDialog,
|
from PySide.QtWidgets import (QFileDialog, QMessageBox, QProgressDialog,
|
||||||
QApplication, QVBoxLayout, QWidget, QPushButton,
|
QApplication, QVBoxLayout, QWidget, QPushButton,
|
||||||
QLabel, QTextEdit)
|
QLabel, QTextEdit)
|
||||||
import FreeCAD
|
import FreeCAD
|
||||||
|
|||||||
+2
-3
@@ -2,8 +2,6 @@ numpy~=1.26.2
|
|||||||
opencv-python~=4.8.1
|
opencv-python~=4.8.1
|
||||||
matplotlib~=3.8.2
|
matplotlib~=3.8.2
|
||||||
openpyxl~=3.1.2
|
openpyxl~=3.1.2
|
||||||
utm~=0.7.0
|
|
||||||
PySide2~=5.15.8
|
|
||||||
requests~=2.31.0
|
requests~=2.31.0
|
||||||
setuptools~=68.2.2
|
setuptools~=68.2.2
|
||||||
laspy~=2.5.3
|
laspy~=2.5.3
|
||||||
@@ -17,4 +15,5 @@ certifi~=2023.11.17
|
|||||||
SciPy~=1.11.4
|
SciPy~=1.11.4
|
||||||
pycollada~=0.7.2
|
pycollada~=0.7.2
|
||||||
shapely
|
shapely
|
||||||
rtree
|
rtree
|
||||||
|
pandas
|
||||||
|
|||||||
Reference in New Issue
Block a user