2025-01-28 00:04:13 +01:00
|
|
|
import math
|
|
|
|
|
|
|
|
|
|
import FreeCAD
|
|
|
|
|
import Part
|
|
|
|
|
import ArchComponent
|
|
|
|
|
from pivy import coin
|
|
|
|
|
import numpy as np
|
2025-04-14 10:05:32 +06:00
|
|
|
import DraftGeomUtils
|
2025-01-28 00:04:13 +01:00
|
|
|
|
|
|
|
|
if FreeCAD.GuiUp:
|
|
|
|
|
import FreeCADGui, os
|
|
|
|
|
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 PVPlantResources
|
|
|
|
|
from PVPlantResources import DirIcons as DirIcons
|
|
|
|
|
|
|
|
|
|
voltype = ["Fill", "Cut"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def makeEarthWorksVolume(vtype = 0):
|
|
|
|
|
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", voltype[vtype])
|
|
|
|
|
EarthWorksVolume(obj)
|
|
|
|
|
ViewProviderEarthWorksVolume(obj.ViewObject)
|
|
|
|
|
return obj
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class EarthWorksVolume(ArchComponent.Component):
|
|
|
|
|
def __init__(self, obj):
|
|
|
|
|
# Definición de Variables:
|
|
|
|
|
ArchComponent.Component.__init__(self, obj)
|
|
|
|
|
self.obj = obj
|
|
|
|
|
self.setProperties(obj)
|
|
|
|
|
|
|
|
|
|
def setProperties(self, obj):
|
|
|
|
|
# Definicion de Propiedades:
|
|
|
|
|
pl = obj.PropertiesList
|
|
|
|
|
|
|
|
|
|
if not ("VolumeType" in pl):
|
|
|
|
|
obj.addProperty("App::PropertyEnumeration",
|
|
|
|
|
"VolumeType",
|
|
|
|
|
"Volume",
|
|
|
|
|
"Connection").VolumeType = voltype
|
|
|
|
|
|
|
|
|
|
if not ("SurfaceSlope" in pl):
|
|
|
|
|
obj.addProperty("App::PropertyPercent",
|
|
|
|
|
"SurfaceSlope",
|
|
|
|
|
"Volume",
|
|
|
|
|
"Connection").SurfaceSlope = 2
|
|
|
|
|
|
|
|
|
|
if not ("VolumeMesh" in pl):
|
|
|
|
|
obj.addProperty("Mesh::PropertyMeshKernel",
|
|
|
|
|
"VolumeMesh",
|
|
|
|
|
"Volume",
|
|
|
|
|
"Volume")
|
|
|
|
|
obj.setEditorMode("VolumeMesh", 2)
|
|
|
|
|
|
|
|
|
|
if not ("Volume" in pl):
|
|
|
|
|
obj.addProperty("App::PropertyVolume",
|
|
|
|
|
"Volume",
|
|
|
|
|
"Volume",
|
|
|
|
|
"Volume")
|
|
|
|
|
obj.setEditorMode("Volume", 1)
|
|
|
|
|
|
|
|
|
|
obj.Proxy = self
|
|
|
|
|
obj.IfcType = "Civil Element"
|
|
|
|
|
obj.setEditorMode("IfcType", 1)
|
|
|
|
|
obj.Proxy = self
|
|
|
|
|
|
|
|
|
|
def onDocumentRestored(self, obj):
|
|
|
|
|
ArchComponent.Component.onDocumentRestored(self, obj)
|
|
|
|
|
self.setProperties(obj)
|
|
|
|
|
|
|
|
|
|
def onChange(self, obj, prop):
|
|
|
|
|
if prop == "VolumeMesh":
|
|
|
|
|
if obj.VolumeMesh:
|
|
|
|
|
obj.VolumeMesh = obj.VolumeMesh.Volume
|
|
|
|
|
|
|
|
|
|
def execute(self, obj):
|
|
|
|
|
''' '''
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ViewProviderEarthWorksVolume:
|
|
|
|
|
"A View Provider for the Pipe object"
|
|
|
|
|
|
|
|
|
|
def __init__(self, vobj):
|
|
|
|
|
''' Set view properties. '''
|
|
|
|
|
pl = vobj.PropertiesList
|
|
|
|
|
|
|
|
|
|
(r, g, b) = (1.0, 0.0, 0.0) if vobj.Object.VolumeType == "Cut" else (0.0, 0.0, 1.0)
|
|
|
|
|
|
|
|
|
|
# Triangulation properties.
|
|
|
|
|
if not "Transparency" in pl:
|
|
|
|
|
vobj.addProperty("App::PropertyIntegerConstraint",
|
|
|
|
|
"Transparency", "Surface Style",
|
|
|
|
|
"Set triangle face transparency")
|
|
|
|
|
vobj.Transparency = (50, 0, 100, 1)
|
|
|
|
|
|
|
|
|
|
if not "ShapeColor" in pl:
|
|
|
|
|
vobj.addProperty("App::PropertyColor",
|
|
|
|
|
"ShapeColor",
|
|
|
|
|
"Surface Style",
|
|
|
|
|
"Set triangle face color")
|
|
|
|
|
vobj.ShapeColor = (r, g, b, vobj.Transparency / 100)
|
|
|
|
|
|
|
|
|
|
if not "ShapeMaterial" in pl:
|
|
|
|
|
vobj.addProperty("App::PropertyMaterial",
|
|
|
|
|
"ShapeMaterial", "Surface Style",
|
|
|
|
|
"Triangle face material")
|
|
|
|
|
vobj.ShapeMaterial = FreeCAD.Material()
|
|
|
|
|
|
|
|
|
|
if not "LineTransparency" in pl:
|
|
|
|
|
vobj.addProperty("App::PropertyIntegerConstraint",
|
|
|
|
|
"LineTransparency", "Surface Style",
|
|
|
|
|
"Set triangle edge transparency")
|
|
|
|
|
vobj.LineTransparency = (50, 0, 100, 1)
|
|
|
|
|
|
|
|
|
|
if not "LineColor" in pl:
|
|
|
|
|
vobj.addProperty("App::PropertyColor",
|
|
|
|
|
"LineColor", "Surface Style",
|
|
|
|
|
"Set triangle face color")
|
|
|
|
|
vobj.LineColor = (0.5, 0.5, 0.5, vobj.LineTransparency / 100)
|
|
|
|
|
|
|
|
|
|
'''vobj.addProperty(
|
|
|
|
|
"App::PropertyMaterial", "LineMaterial", "Surface Style",
|
|
|
|
|
"Triangle face material").LineMaterial = FreeCAD.Material()
|
|
|
|
|
|
|
|
|
|
vobj.addProperty(
|
|
|
|
|
"App::PropertyFloatConstraint", "LineWidth", "Surface Style",
|
|
|
|
|
"Set triangle edge line width").LineWidth = (0.0, 1.0, 20.0, 1.0)
|
|
|
|
|
|
|
|
|
|
# Boundary properties.
|
|
|
|
|
vobj.addProperty(
|
|
|
|
|
"App::PropertyColor", "BoundaryColor", "Boundary Style",
|
|
|
|
|
"Set boundary contour color").BoundaryColor = (0.0, 0.75, 1.0, 0.0)
|
|
|
|
|
|
|
|
|
|
vobj.addProperty(
|
|
|
|
|
"App::PropertyFloatConstraint", "BoundaryWidth", "Boundary Style",
|
|
|
|
|
"Set boundary contour line width").BoundaryWidth = (3.0, 1.0, 20.0, 1.0)
|
|
|
|
|
|
|
|
|
|
vobj.addProperty(
|
|
|
|
|
"App::PropertyEnumeration", "BoundaryPattern", "Boundary Style",
|
|
|
|
|
"Set a line pattern for boundary").BoundaryPattern = [*line_patterns]
|
|
|
|
|
|
|
|
|
|
vobj.addProperty(
|
|
|
|
|
"App::PropertyIntegerConstraint", "PatternScale", "Boundary Style",
|
|
|
|
|
"Scale the line pattern").PatternScale = (3, 1, 20, 1)
|
|
|
|
|
|
|
|
|
|
# Contour properties.
|
|
|
|
|
vobj.addProperty(
|
|
|
|
|
"App::PropertyColor", "MajorColor", "Contour Style",
|
|
|
|
|
"Set major contour color").MajorColor = (1.0, 0.0, 0.0, 0.0)
|
|
|
|
|
|
|
|
|
|
vobj.addProperty(
|
|
|
|
|
"App::PropertyFloatConstraint", "MajorWidth", "Contour Style",
|
|
|
|
|
"Set major contour line width").MajorWidth = (4.0, 1.0, 20.0, 1.0)
|
|
|
|
|
|
|
|
|
|
vobj.addProperty(
|
|
|
|
|
"App::PropertyColor", "MinorColor", "Contour Style",
|
|
|
|
|
"Set minor contour color").MinorColor = (1.0, 1.0, 0.0, 0.0)
|
|
|
|
|
|
|
|
|
|
vobj.addProperty(
|
|
|
|
|
"App::PropertyFloatConstraint", "MinorWidth", "Contour Style",
|
|
|
|
|
"Set major contour line width").MinorWidth = (2.0, 1.0, 20.0, 1.0)
|
|
|
|
|
'''
|
|
|
|
|
vobj.Proxy = self
|
|
|
|
|
vobj.ShapeMaterial.DiffuseColor = vobj.ShapeColor
|
|
|
|
|
|
|
|
|
|
def onChanged(self, vobj, prop):
|
|
|
|
|
'''
|
|
|
|
|
Update Object visuals when a view property changed.
|
|
|
|
|
'''
|
|
|
|
|
if prop == "ShapeColor" or prop == "Transparency":
|
|
|
|
|
if hasattr(vobj, "ShapeColor") and hasattr(vobj, "Transparency"):
|
|
|
|
|
color = vobj.getPropertyByName("ShapeColor")
|
|
|
|
|
transparency = vobj.getPropertyByName("Transparency")
|
|
|
|
|
color = (color[0], color[1], color[2], transparency / 100)
|
|
|
|
|
vobj.ShapeMaterial.DiffuseColor = color
|
|
|
|
|
|
|
|
|
|
if prop == "ShapeMaterial":
|
|
|
|
|
if hasattr(vobj, "ShapeMaterial"):
|
|
|
|
|
material = vobj.getPropertyByName("ShapeMaterial")
|
|
|
|
|
self.face_material.diffuseColor.setValue(material.DiffuseColor[:3])
|
|
|
|
|
self.face_material.transparency = material.DiffuseColor[3]
|
|
|
|
|
|
|
|
|
|
if prop == "LineColor" or prop == "LineTransparency":
|
|
|
|
|
if hasattr(vobj, "LineColor") and hasattr(vobj, "LineTransparency"):
|
|
|
|
|
color = vobj.getPropertyByName("LineColor")
|
|
|
|
|
transparency = vobj.getPropertyByName("LineTransparency")
|
|
|
|
|
color = (color[0], color[1], color[2], transparency / 100)
|
|
|
|
|
vobj.LineMaterial.DiffuseColor = color
|
|
|
|
|
|
|
|
|
|
if prop == "LineMaterial":
|
|
|
|
|
material = vobj.getPropertyByName(prop)
|
|
|
|
|
self.edge_material.diffuseColor.setValue(material.DiffuseColor[:3])
|
|
|
|
|
self.edge_material.transparency = material.DiffuseColor[3]
|
|
|
|
|
|
|
|
|
|
if prop == "LineWidth":
|
|
|
|
|
width = vobj.getPropertyByName(prop)
|
|
|
|
|
self.edge_style.lineWidth = width
|
|
|
|
|
|
|
|
|
|
if prop == "BoundaryColor":
|
|
|
|
|
color = vobj.getPropertyByName(prop)
|
|
|
|
|
self.boundary_color.rgb = color[:3]
|
|
|
|
|
|
|
|
|
|
if prop == "BoundaryWidth":
|
|
|
|
|
width = vobj.getPropertyByName(prop)
|
|
|
|
|
self.boundary_style.lineWidth = width
|
|
|
|
|
|
|
|
|
|
if prop == "BoundaryPattern":
|
|
|
|
|
if hasattr(vobj, "BoundaryPattern"):
|
|
|
|
|
pattern = vobj.getPropertyByName(prop)
|
|
|
|
|
self.boundary_style.linePattern = line_patterns[pattern]
|
|
|
|
|
|
|
|
|
|
if prop == "PatternScale":
|
|
|
|
|
if hasattr(vobj, "PatternScale"):
|
|
|
|
|
scale = vobj.getPropertyByName(prop)
|
|
|
|
|
self.boundary_style.linePatternScaleFactor = scale
|
|
|
|
|
|
|
|
|
|
if prop == "MajorColor":
|
|
|
|
|
color = vobj.getPropertyByName(prop)
|
|
|
|
|
self.major_color.rgb = color[:3]
|
|
|
|
|
|
|
|
|
|
if prop == "MajorWidth":
|
|
|
|
|
width = vobj.getPropertyByName(prop)
|
|
|
|
|
self.major_style.lineWidth = width
|
|
|
|
|
|
|
|
|
|
if prop == "MinorColor":
|
|
|
|
|
color = vobj.getPropertyByName(prop)
|
|
|
|
|
self.minor_color.rgb = color[:3]
|
|
|
|
|
|
|
|
|
|
if prop == "MinorWidth":
|
|
|
|
|
width = vobj.getPropertyByName(prop)
|
|
|
|
|
self.minor_style.lineWidth = width
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def attach(self, vobj):
|
|
|
|
|
'''
|
|
|
|
|
Create Object visuals in 3D view.
|
|
|
|
|
'''
|
|
|
|
|
# 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()
|
|
|
|
|
offset.styles = coin.SoPolygonOffset.LINES
|
|
|
|
|
offset.factor = -2.0
|
|
|
|
|
|
|
|
|
|
# Boundary features.
|
|
|
|
|
self.boundary_color = coin.SoBaseColor()
|
|
|
|
|
self.boundary_coords = coin.SoGeoCoordinate()
|
|
|
|
|
self.boundary_lines = coin.SoLineSet()
|
|
|
|
|
self.boundary_style = coin.SoDrawStyle()
|
|
|
|
|
self.boundary_style.style = coin.SoDrawStyle.LINES
|
|
|
|
|
|
|
|
|
|
# Boundary root.
|
|
|
|
|
boundaries = coin.SoType.fromName('SoFCSelection').createInstance()
|
|
|
|
|
boundaries.style = 'EMISSIVE_DIFFUSE'
|
|
|
|
|
boundaries.addChild(self.boundary_color)
|
|
|
|
|
boundaries.addChild(self.boundary_style)
|
|
|
|
|
boundaries.addChild(self.boundary_coords)
|
|
|
|
|
boundaries.addChild(self.boundary_lines)
|
|
|
|
|
|
|
|
|
|
# Major Contour features.
|
|
|
|
|
self.major_color = coin.SoBaseColor()
|
|
|
|
|
self.major_coords = coin.SoGeoCoordinate()
|
|
|
|
|
self.major_lines = coin.SoLineSet()
|
|
|
|
|
self.major_style = coin.SoDrawStyle()
|
|
|
|
|
self.major_style.style = coin.SoDrawStyle.LINES
|
|
|
|
|
|
|
|
|
|
# Major Contour root.
|
|
|
|
|
major_contours = coin.SoSeparator()
|
|
|
|
|
major_contours.addChild(self.major_color)
|
|
|
|
|
major_contours.addChild(self.major_style)
|
|
|
|
|
major_contours.addChild(self.major_coords)
|
|
|
|
|
major_contours.addChild(self.major_lines)
|
|
|
|
|
|
|
|
|
|
# Minor Contour features.
|
|
|
|
|
self.minor_color = coin.SoBaseColor()
|
|
|
|
|
self.minor_coords = coin.SoGeoCoordinate()
|
|
|
|
|
self.minor_lines = coin.SoLineSet()
|
|
|
|
|
self.minor_style = coin.SoDrawStyle()
|
|
|
|
|
self.minor_style.style = coin.SoDrawStyle.LINES
|
|
|
|
|
|
|
|
|
|
# Minor Contour root.
|
|
|
|
|
minor_contours = coin.SoSeparator()
|
|
|
|
|
minor_contours.addChild(self.minor_color)
|
|
|
|
|
minor_contours.addChild(self.minor_style)
|
|
|
|
|
minor_contours.addChild(self.minor_coords)
|
|
|
|
|
minor_contours.addChild(self.minor_lines)
|
|
|
|
|
|
|
|
|
|
# Highlight for selection.
|
|
|
|
|
highlight = coin.SoType.fromName('SoFCSelection').createInstance()
|
|
|
|
|
highlight.style = 'EMISSIVE_DIFFUSE'
|
|
|
|
|
highlight.addChild(shape_hints)
|
|
|
|
|
highlight.addChild(mat_binding)
|
|
|
|
|
highlight.addChild(self.geo_coords)
|
|
|
|
|
highlight.addChild(self.triangles)
|
|
|
|
|
highlight.addChild(boundaries)
|
|
|
|
|
|
|
|
|
|
# Face root.
|
|
|
|
|
face = coin.SoSeparator()
|
|
|
|
|
face.addChild(self.face_material)
|
|
|
|
|
face.addChild(highlight)
|
|
|
|
|
|
|
|
|
|
# Edge root.
|
|
|
|
|
edge = coin.SoSeparator()
|
|
|
|
|
edge.addChild(self.edge_material)
|
|
|
|
|
edge.addChild(self.edge_style)
|
|
|
|
|
edge.addChild(highlight)
|
|
|
|
|
|
|
|
|
|
# Surface root.
|
|
|
|
|
surface_root = coin.SoSeparator()
|
|
|
|
|
surface_root.addChild(face)
|
|
|
|
|
surface_root.addChild(offset)
|
|
|
|
|
surface_root.addChild(edge)
|
|
|
|
|
surface_root.addChild(major_contours)
|
|
|
|
|
surface_root.addChild(minor_contours)
|
|
|
|
|
vobj.addDisplayMode(surface_root, "Surface")
|
|
|
|
|
|
|
|
|
|
# Boundary root.
|
|
|
|
|
boundary_root = coin.SoSeparator()
|
|
|
|
|
boundary_root.addChild(boundaries)
|
|
|
|
|
vobj.addDisplayMode(boundary_root, "Boundary")
|
|
|
|
|
|
|
|
|
|
# Elevation/Shaded root.
|
|
|
|
|
shaded_root = coin.SoSeparator()
|
|
|
|
|
shaded_root.addChild(face)
|
|
|
|
|
vobj.addDisplayMode(shaded_root, "Elevation")
|
|
|
|
|
vobj.addDisplayMode(shaded_root, "Slope")
|
|
|
|
|
vobj.addDisplayMode(shaded_root, "Shaded")
|
|
|
|
|
|
|
|
|
|
# Flat Lines root.
|
|
|
|
|
flatlines_root = coin.SoSeparator()
|
|
|
|
|
flatlines_root.addChild(face)
|
|
|
|
|
flatlines_root.addChild(offset)
|
|
|
|
|
flatlines_root.addChild(edge)
|
|
|
|
|
vobj.addDisplayMode(flatlines_root, "Flat Lines")
|
|
|
|
|
|
|
|
|
|
# Wireframe root.
|
|
|
|
|
wireframe_root = coin.SoSeparator()
|
|
|
|
|
wireframe_root.addChild(edge)
|
|
|
|
|
wireframe_root.addChild(major_contours)
|
|
|
|
|
wireframe_root.addChild(minor_contours)
|
|
|
|
|
vobj.addDisplayMode(wireframe_root, "Wireframe")
|
|
|
|
|
|
|
|
|
|
# Take features from properties.
|
|
|
|
|
self.onChanged(vobj, "ShapeColor")
|
|
|
|
|
self.onChanged(vobj, "LineColor")
|
|
|
|
|
self.onChanged(vobj, "LineWidth")
|
|
|
|
|
'''self.onChanged(vobj, "BoundaryColor")
|
|
|
|
|
self.onChanged(vobj, "BoundaryWidth")
|
|
|
|
|
self.onChanged(vobj, "BoundaryPattern")
|
|
|
|
|
self.onChanged(vobj, "PatternScale")
|
|
|
|
|
self.onChanged(vobj, "MajorColor")
|
|
|
|
|
self.onChanged(vobj, "MajorWidth")
|
|
|
|
|
self.onChanged(vobj, "MinorColor")
|
|
|
|
|
self.onChanged(vobj, "MinorWidth")'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def updateData(self, obj, prop):
|
|
|
|
|
'''
|
|
|
|
|
Update Object visuals when a data property changed.
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
# Set System.
|
|
|
|
|
geo_system = ["UTM", FreeCAD.ActiveDocument.Site.UtmZone, "FLAT"]
|
|
|
|
|
self.geo_coords.geoSystem.setValues(geo_system)
|
|
|
|
|
self.boundary_coords.geoSystem.setValues(geo_system)
|
|
|
|
|
self.major_coords.geoSystem.setValues(geo_system)
|
|
|
|
|
self.minor_coords.geoSystem.setValues(geo_system)
|
|
|
|
|
|
|
|
|
|
if prop == "VolumeMesh":
|
|
|
|
|
mesh = obj.VolumeMesh
|
|
|
|
|
copy_mesh = mesh.copy()
|
|
|
|
|
#copy_mesh.Placement.move(origin.Origin)
|
|
|
|
|
|
|
|
|
|
triangles = []
|
|
|
|
|
for i in copy_mesh.Topology[1]:
|
|
|
|
|
triangles.extend(list(i))
|
|
|
|
|
triangles.append(-1)
|
|
|
|
|
|
|
|
|
|
self.geo_coords.point.values = copy_mesh.Topology[0]
|
|
|
|
|
self.triangles.coordIndex.values = triangles
|
|
|
|
|
del copy_mesh
|
|
|
|
|
|
|
|
|
|
'''if prop == "ContourShapes":
|
|
|
|
|
contour_shape = obj.getPropertyByName(prop)
|
|
|
|
|
|
|
|
|
|
if contour_shape.SubShapes:
|
|
|
|
|
major_shape = contour_shape.SubShapes[0]
|
|
|
|
|
points, vertices = self.wire_view(major_shape, origin.Origin)
|
|
|
|
|
|
|
|
|
|
self.major_coords.point.values = points
|
|
|
|
|
self.major_lines.numVertices.values = vertices
|
|
|
|
|
|
|
|
|
|
minor_shape = contour_shape.SubShapes[1]
|
|
|
|
|
points, vertices = self.wire_view(minor_shape, origin.Origin)
|
|
|
|
|
|
|
|
|
|
self.minor_coords.point.values = points
|
|
|
|
|
self.minor_lines.numVertices.values = vertices
|
|
|
|
|
|
|
|
|
|
if prop == "BoundaryShapes":
|
|
|
|
|
boundary_shape = obj.getPropertyByName(prop)
|
|
|
|
|
points, vertices = self.wire_view(boundary_shape, origin.Origin, True)
|
|
|
|
|
|
|
|
|
|
self.boundary_coords.point.values = points
|
|
|
|
|
self.boundary_lines.numVertices.values = vertices
|
|
|
|
|
|
|
|
|
|
if prop == "AnalysisType" or prop == "Ranges":
|
|
|
|
|
analysis_type = obj.getPropertyByName("AnalysisType")
|
|
|
|
|
ranges = obj.getPropertyByName("Ranges")
|
|
|
|
|
|
|
|
|
|
if analysis_type == "Default":
|
|
|
|
|
if hasattr(obj.ViewObject, "ShapeMaterial"):
|
|
|
|
|
material = obj.ViewObject.ShapeMaterial
|
|
|
|
|
self.face_material.diffuseColor = material.DiffuseColor[:3]
|
|
|
|
|
|
|
|
|
|
if analysis_type == "Elevation":
|
|
|
|
|
colorlist = self.elevation_analysis(obj.Mesh, ranges)
|
|
|
|
|
self.face_material.diffuseColor.setValues(0, len(colorlist), colorlist)
|
|
|
|
|
|
|
|
|
|
elif analysis_type == "Slope":
|
|
|
|
|
colorlist = self.slope_analysis(obj.Mesh, ranges)
|
|
|
|
|
self.face_material.diffuseColor.setValues(0, len(colorlist), colorlist)
|
|
|
|
|
'''
|
|
|
|
|
def getIcon(self):
|
|
|
|
|
""" Return the path to the appropriate icon. """
|
|
|
|
|
return str(os.path.join(DirIcons, "solar-fixed.svg"))
|
|
|
|
|
|
|
|
|
|
def getDisplayModes(self, vobj):
|
|
|
|
|
'''
|
|
|
|
|
Return a list of display modes.
|
|
|
|
|
'''
|
|
|
|
|
modes = ["Surface", "Boundary", "Flat Lines", "Shaded", "Wireframe"]
|
|
|
|
|
|
|
|
|
|
return modes
|
|
|
|
|
|
|
|
|
|
def getDefaultDisplayMode(self):
|
|
|
|
|
'''
|
|
|
|
|
Return the name of the default display mode.
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
return "Surface"
|
|
|
|
|
|
|
|
|
|
def setDisplayMode(self, mode):
|
|
|
|
|
'''
|
|
|
|
|
Map the display mode defined in attach with
|
|
|
|
|
those defined in getDisplayModes.
|
|
|
|
|
'''
|
|
|
|
|
return mode
|
|
|
|
|
|
|
|
|
|
def __getstate__(self):
|
|
|
|
|
"""
|
|
|
|
|
Save variables to file.
|
|
|
|
|
"""
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def __setstate__(self, state):
|
|
|
|
|
"""
|
|
|
|
|
Get variables from file.
|
|
|
|
|
"""
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
2025-03-28 19:40:11 +06:00
|
|
|
class EarthWorksTaskPanel:
|
2025-01-28 00:04:13 +01:00
|
|
|
def __init__(self):
|
|
|
|
|
self.To = None
|
|
|
|
|
|
|
|
|
|
# self.form:
|
|
|
|
|
self.form = FreeCADGui.PySideUic.loadUi(os.path.join(PVPlantResources.__dir__, "PVPlantEarthworks.ui"))
|
|
|
|
|
self.form.setWindowIcon(QtGui.QIcon(os.path.join(PVPlantResources.DirIcons, "convert.svg")))
|
|
|
|
|
|
|
|
|
|
def accept(self):
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
starttime = datetime.now()
|
|
|
|
|
|
|
|
|
|
import MeshPart as mp
|
|
|
|
|
land = FreeCAD.ActiveDocument.Terrain.Mesh.copy()
|
|
|
|
|
frames = []
|
|
|
|
|
for obj in FreeCADGui.Selection.getSelection():
|
|
|
|
|
if hasattr(obj, "Proxy"):
|
|
|
|
|
if obj.Proxy.Type == "Tracker":
|
|
|
|
|
if not (obj in frames):
|
|
|
|
|
frames.append(obj)
|
|
|
|
|
elif obj.Proxy.Type == "FrameArea":
|
|
|
|
|
for fr in obj.Frames:
|
|
|
|
|
if not (fr in frames):
|
|
|
|
|
frames.append(fr)
|
|
|
|
|
if len(frames) == 0:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
FreeCAD.ActiveDocument.openTransaction("Calcular movimiento de tierras")
|
2025-04-14 10:05:32 +06:00
|
|
|
|
2025-01-28 00:04:13 +01:00
|
|
|
def calculateEarthWorks(line, extreme=False):
|
|
|
|
|
pts = []
|
|
|
|
|
pts1 = []
|
|
|
|
|
line1 = line.copy()
|
|
|
|
|
angles = line.Placement.Rotation.toEulerAngles("XYZ")
|
|
|
|
|
line1.Placement.Rotation.setEulerAngles("XYZ", 0, 0, angles[2])
|
|
|
|
|
line1.Placement.Base.z = 0
|
|
|
|
|
pro = mp.projectShapeOnMesh(line1, land, FreeCAD.Vector(0, 0, 1))
|
|
|
|
|
flat = []
|
|
|
|
|
for points in pro:
|
|
|
|
|
flat.extend(points)
|
|
|
|
|
pro = Part.makePolygon(flat)
|
|
|
|
|
points = pro.discretize(Distance=500)
|
|
|
|
|
|
|
|
|
|
for point in points:
|
|
|
|
|
ver = Part.Vertex(point)
|
|
|
|
|
dist = ver.distToShape(line)
|
|
|
|
|
linepoint = dist[1][0][1]
|
|
|
|
|
|
|
|
|
|
if not extreme:
|
|
|
|
|
if self.form.groupTolerances.isChecked():
|
|
|
|
|
if linepoint.z > point.z:
|
|
|
|
|
if linepoint.sub(point).Length > self.form.editToleranceCut.value():
|
|
|
|
|
pts.append(linepoint)
|
|
|
|
|
elif linepoint.z < point.z:
|
|
|
|
|
if linepoint.sub(point).Length > self.form.editToleranceFill.value():
|
|
|
|
|
pts1.append(linepoint)
|
|
|
|
|
else:
|
|
|
|
|
if linepoint.z > point.z:
|
|
|
|
|
pts.append(linepoint)
|
|
|
|
|
elif linepoint.z < point.z:
|
|
|
|
|
pts1.append(linepoint)
|
|
|
|
|
#pts.append(linepoint)
|
|
|
|
|
else:
|
|
|
|
|
if linepoint.z > point.z:
|
|
|
|
|
if linepoint.sub(point).Length > 200:
|
|
|
|
|
pts.append(linepoint)
|
|
|
|
|
|
|
|
|
|
return pts, pts1
|
|
|
|
|
|
|
|
|
|
tools = [[],[]]
|
|
|
|
|
ver = 2
|
|
|
|
|
if ver == 0:
|
|
|
|
|
frames = sorted(frames, key=lambda x: (x.Placement.Base.x, x.Placement.Base.y))
|
|
|
|
|
for frame in frames:
|
|
|
|
|
length = frame.Setup.Length.Value / 2
|
|
|
|
|
p1 = FreeCAD.Vector(-length, 0, 0)
|
|
|
|
|
p2 = FreeCAD.Vector(length, 0, 0)
|
|
|
|
|
line = Part.LineSegment(p1, p2).toShape()
|
|
|
|
|
line.Placement = frame.Placement.copy()
|
|
|
|
|
line.Placement.Base.x = frame.Shape.BoundBox.XMin
|
|
|
|
|
step = (frame.Shape.BoundBox.XMax - frame.Shape.BoundBox.XMin) / 2
|
|
|
|
|
for n in range(3):
|
|
|
|
|
ret = calculateEarthWorks(line, n % 2)
|
|
|
|
|
tools[0].extend(ret[0])
|
|
|
|
|
tools[1].extend(ret[1])
|
|
|
|
|
line.Placement.Base.x += step
|
|
|
|
|
elif ver == 1:
|
|
|
|
|
from PVPlantPlacement import getCols
|
|
|
|
|
columns = getCols(frames)
|
|
|
|
|
for groups in columns:
|
|
|
|
|
for group in groups:
|
|
|
|
|
first = group[0]
|
|
|
|
|
last = group[-1]
|
|
|
|
|
for frame in group:
|
|
|
|
|
length = frame.Setup.Length.Value / 2
|
|
|
|
|
p1 = FreeCAD.Vector(-(length + (self.form.editOffset.value() if frame == first else -1000)),
|
|
|
|
|
0, 0)
|
|
|
|
|
p2 = FreeCAD.Vector(length + (self.form.editOffset.value() if frame == last else -1000),
|
|
|
|
|
0, 0)
|
|
|
|
|
line = Part.LineSegment(p1, p2).toShape()
|
|
|
|
|
line.Placement = frame.Placement.copy()
|
|
|
|
|
line.Placement.Base.x = frame.Shape.BoundBox.XMin
|
|
|
|
|
step = (frame.Shape.BoundBox.XMax - frame.Shape.BoundBox.XMin) / 2
|
|
|
|
|
for n in range(3):
|
|
|
|
|
ret = calculateEarthWorks(line, n % 2 == 1)
|
|
|
|
|
tools[0].extend(ret[0])
|
|
|
|
|
tools[1].extend(ret[1])
|
|
|
|
|
line.Placement.Base.x += step
|
|
|
|
|
elif ver == 2:
|
|
|
|
|
print("versión 2")
|
|
|
|
|
import PVPlantPlacement
|
|
|
|
|
rows, columns = PVPlantPlacement.getRows(frames)
|
|
|
|
|
if (rows is None) or (columns is None):
|
|
|
|
|
print("Nada que procesar")
|
|
|
|
|
return False
|
|
|
|
|
tools = []
|
|
|
|
|
lofts = []
|
|
|
|
|
for group in rows:
|
|
|
|
|
lines = []
|
|
|
|
|
cont = 0
|
|
|
|
|
while cont < len(group):
|
|
|
|
|
aw = 0
|
|
|
|
|
if cont > 0:
|
|
|
|
|
p0 = FreeCAD.Vector(group[cont - 1].Placement.Base)
|
|
|
|
|
p1 = FreeCAD.Vector(group[cont].Placement.Base)
|
|
|
|
|
aw = getAngle(p0, p1)
|
|
|
|
|
|
|
|
|
|
ae = 0
|
|
|
|
|
if cont < (len(group) - 1):
|
|
|
|
|
p1 = FreeCAD.Vector(group[cont].Placement.Base)
|
|
|
|
|
p2 = FreeCAD.Vector(group[cont + 1].Placement.Base)
|
|
|
|
|
ae = getAngle(p1, p2)
|
|
|
|
|
|
|
|
|
|
lng = int(group[cont].Setup.Length / 2)
|
|
|
|
|
wdt = int(group[cont].Setup.Width / 2)
|
|
|
|
|
line = Part.LineSegment(FreeCAD.Vector(-lng, 0, 0),
|
|
|
|
|
FreeCAD.Vector(lng, 0, 0)).toShape()
|
|
|
|
|
|
|
|
|
|
line = Part.LineSegment(FreeCAD.Vector(group[cont].Setup.Shape.SubShapes[1].SubShapes[0].SubShapes[0].Placement.Base.x, 0, 0),
|
|
|
|
|
FreeCAD.Vector(group[cont].Setup.Shape.SubShapes[1].SubShapes[0].SubShapes[-1].Placement.Base.x, 0, 0)).toShape()
|
|
|
|
|
|
|
|
|
|
anf = (aw + ae) / 2
|
|
|
|
|
if anf > FreeCAD.ActiveDocument.MaximumWestEastSlope.Value:
|
|
|
|
|
anf = FreeCAD.ActiveDocument.MaximumWestEastSlope.Value
|
|
|
|
|
zz = wdt * math.sin(math.radians(anf))
|
|
|
|
|
|
|
|
|
|
li = line.copy()
|
|
|
|
|
li.Placement = group[cont].Placement
|
|
|
|
|
li.Placement.Rotation = group[cont].Placement.Rotation
|
|
|
|
|
li.Placement.Base.x -= wdt #+ (3000 if cont == 0 else 0))
|
|
|
|
|
li.Placement.Base.z -= zz
|
|
|
|
|
lines.append(li)
|
|
|
|
|
|
|
|
|
|
ld = line.copy()
|
|
|
|
|
ld.Placement = group[cont].Placement
|
|
|
|
|
ld.Placement.Rotation = group[cont].Placement.Rotation
|
|
|
|
|
ld.Placement.Base.x += wdt #+ (3000 if cont == len(group) - 1 else 0))
|
|
|
|
|
ld.Placement.Base.z += zz
|
|
|
|
|
lines.append(ld)
|
|
|
|
|
tools.append([group[cont], li, ld])
|
|
|
|
|
cont += 1
|
|
|
|
|
loft = Part.makeLoft(lines, False, True, False)
|
|
|
|
|
lofts.append(loft)
|
|
|
|
|
|
|
|
|
|
for group in rows:
|
|
|
|
|
lines = []
|
|
|
|
|
for frame in group:
|
|
|
|
|
col, idx = searchFrameInColumns(frame, columns)
|
|
|
|
|
tool = searchTool(frame, tools)
|
|
|
|
|
if idx == 0:
|
|
|
|
|
''' '''
|
|
|
|
|
|
|
|
|
|
if idx == (len(col) - 1):
|
|
|
|
|
''' '''
|
|
|
|
|
|
|
|
|
|
if (idx + 1) < len(col):
|
|
|
|
|
frame1 = col[idx + 1]
|
|
|
|
|
tool1 = searchTool(frame1, tools)
|
|
|
|
|
line = Part.LineSegment(tool[1].Vertexes[1].Point, tool1[1].Vertexes[0].Point).toShape()
|
|
|
|
|
lines.append(line)
|
|
|
|
|
line = Part.LineSegment(tool[2].Vertexes[1].Point, tool1[2].Vertexes[0].Point).toShape()
|
|
|
|
|
lines.append(line)
|
|
|
|
|
|
|
|
|
|
if len(lines) > 0:
|
|
|
|
|
loft = Part.makeLoft(lines, False, True, False)
|
|
|
|
|
lofts.append(loft)
|
|
|
|
|
|
|
|
|
|
faces = []
|
|
|
|
|
for loft in lofts:
|
|
|
|
|
faces.extend(loft.Faces)
|
|
|
|
|
sh = Part.makeShell(faces)
|
|
|
|
|
import Utils.PVPlantUtils as utils
|
|
|
|
|
import Mesh
|
|
|
|
|
pro = utils.getProjected(sh)
|
|
|
|
|
pro = utils.simplifyWire(pro)
|
|
|
|
|
pts = [ver.Point for ver in pro.Vertexes]
|
|
|
|
|
land.trim(pts, 1)
|
2025-04-14 10:05:32 +06:00
|
|
|
|
2025-01-28 00:04:13 +01:00
|
|
|
tmp = []
|
2025-05-07 23:42:54 +02:00
|
|
|
shp = Part.Shape()
|
2025-01-28 00:04:13 +01:00
|
|
|
for face in sh.Faces:
|
|
|
|
|
wire = face.Wires[0].copy()
|
|
|
|
|
pl = wire.Placement.Base
|
|
|
|
|
wire.Placement.Base = wire.Placement.Base - pl
|
2025-04-14 10:05:32 +06:00
|
|
|
|
|
|
|
|
if DraftGeomUtils.isPlanar(wire):
|
|
|
|
|
# Caso simple
|
|
|
|
|
wire = wire.makeOffset2D(10000, 0, False, False, True)
|
|
|
|
|
wire.Placement.Base.z = wire.Placement.Base.z - 10000
|
2025-05-07 23:42:54 +02:00
|
|
|
top = wire.makeOffset2D(1, 0, False, False, True)
|
|
|
|
|
loft = Part.makeLoft([top, wire], True, True, False)
|
|
|
|
|
tmp.append(loft)
|
|
|
|
|
shp = shp.fuse(loft)
|
2025-04-14 10:05:32 +06:00
|
|
|
else:
|
|
|
|
|
# Caso complejo:
|
|
|
|
|
vertices = face.Vertexes
|
|
|
|
|
# Dividir rectángulo en 2 triángulos
|
|
|
|
|
triangles = [
|
|
|
|
|
[vertices[0], vertices[1], vertices[2]],
|
|
|
|
|
[vertices[2], vertices[3], vertices[0]]
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
for tri in triangles:
|
|
|
|
|
# Crear wire triangular
|
|
|
|
|
wire = Part.makePolygon([v.Point for v in tri] + [tri[0].Point])
|
|
|
|
|
wire = wire.makeOffset2D(10000, 0, False, False, True)
|
|
|
|
|
wire.Placement.Base.z = wire.Placement.Base.z - 10000
|
2025-05-07 23:42:54 +02:00
|
|
|
top = wire.makeOffset2D(1, 0, False, False, True)
|
|
|
|
|
loft = Part.makeLoft([top, wire], True, True, False)
|
|
|
|
|
tmp.append(loft)
|
|
|
|
|
shp = shp.fuse(loft)
|
2025-04-14 10:05:32 +06:00
|
|
|
|
|
|
|
|
final_tool = Part.makeCompound(tmp)
|
|
|
|
|
Part.show(final_tool, "tool")
|
2025-05-07 23:42:54 +02:00
|
|
|
Part.show(shp)
|
2025-01-28 00:04:13 +01:00
|
|
|
|
|
|
|
|
FreeCAD.ActiveDocument.commitTransaction()
|
|
|
|
|
self.closeForm()
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
import MeshTools.Triangulation as TriangulateMesh
|
|
|
|
|
import MeshTools.MeshGetBoundary as mgb
|
|
|
|
|
import Mesh
|
|
|
|
|
|
|
|
|
|
for ind, points in enumerate(tools):
|
|
|
|
|
mesh = TriangulateMesh.Triangulate(points, MaxlengthLE=3000, MaxAngleLE=math.radians(100))
|
|
|
|
|
if mesh:
|
|
|
|
|
for mesh in mesh.getSeparateComponents():
|
|
|
|
|
boundary = mgb.get_boundary(mesh)
|
|
|
|
|
Part.show(boundary)
|
|
|
|
|
'''if self.form.editOffset.value() != 0:
|
|
|
|
|
import Utils.PVPlantUtils as utils
|
|
|
|
|
pro = utils.getProjected(boundary)
|
|
|
|
|
pro = pro.makeOffset2D(self.form.editOffset.value(), 0, False, False, True)
|
|
|
|
|
# TODO: paso intermedio de restar las areas prohibidas
|
|
|
|
|
pro = mp.projectShapeOnMesh(pro, land, FreeCAD.Vector(0, 0, 1))
|
|
|
|
|
cnt = 0
|
|
|
|
|
for lp in pro:
|
|
|
|
|
cnt += len(lp)
|
|
|
|
|
# points.extend(boundary.Wires[0].discretize(Number=cnt))
|
|
|
|
|
points = boundary.Wires[0].discretize(Distance=cnt)
|
|
|
|
|
for lp in pro:
|
|
|
|
|
points.extend(lp)
|
|
|
|
|
mesh1 = TriangulateMesh.Triangulate(points, MaxlengthLE=5000) # , MaxAngleLE=math.pi / 1.334)
|
|
|
|
|
import Mesh
|
|
|
|
|
Mesh.show(mesh1)
|
|
|
|
|
boundary = Part.makeCompound([])
|
|
|
|
|
for section in pro:
|
|
|
|
|
if len(section) > 0:
|
|
|
|
|
try:
|
|
|
|
|
boundary.add(Part.makePolygon(section))
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
Part.show(boundary)'''
|
|
|
|
|
#mesh.smooth("Laplace", 3)
|
|
|
|
|
#Mesh.show(mesh)
|
|
|
|
|
#Part.show(boundary)
|
|
|
|
|
vol = makeEarthWorksVolume(ind)
|
|
|
|
|
vol.VolumeMesh = mesh.copy()
|
|
|
|
|
if ind == 0:
|
|
|
|
|
''' put inside fills group '''
|
|
|
|
|
else:
|
|
|
|
|
''' put inside fills group '''
|
|
|
|
|
|
|
|
|
|
FreeCAD.ActiveDocument.commitTransaction()
|
|
|
|
|
self.closeForm()
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def reject(self):
|
|
|
|
|
self.closeForm()
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
def closeForm(self):
|
|
|
|
|
FreeCADGui.Control.closeDialog()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getAngle(vec1, vec2):
|
|
|
|
|
dX = vec2.x - vec1.x
|
|
|
|
|
dZ = vec2.z - vec1.z
|
|
|
|
|
return math.degrees(math.atan2(float(dZ), float(dX)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def searchFrameInColumns(obj, columns):
|
|
|
|
|
for colidx, col in enumerate(columns):
|
|
|
|
|
for group in col:
|
|
|
|
|
if obj in group:
|
|
|
|
|
return group, group.index(obj) #groupidx
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def searchTool(obj, tools):
|
|
|
|
|
for tool in tools:
|
|
|
|
|
if obj in tool:
|
|
|
|
|
return tool
|
|
|
|
|
|
|
|
|
|
|
2025-03-28 19:40:11 +06:00
|
|
|
'''class _CommandCalculateEarthworks:
|
2025-01-28 00:04:13 +01:00
|
|
|
|
|
|
|
|
def GetResources(self):
|
|
|
|
|
return {'Pixmap': str(os.path.join(PVPlantResources.DirIcons, "pico.svg")),
|
|
|
|
|
'Accel': "C, E",
|
|
|
|
|
'MenuText': QT_TRANSLATE_NOOP("Placement", "Movimiento de tierras"),
|
|
|
|
|
'ToolTip': QT_TRANSLATE_NOOP("Placement", "Calcular el movimiento de tierras")}
|
|
|
|
|
|
|
|
|
|
def Activated(self):
|
|
|
|
|
TaskPanel = _EarthWorksTaskPanel()
|
|
|
|
|
FreeCADGui.Control.showDialog(TaskPanel)
|
|
|
|
|
|
|
|
|
|
def IsActive(self):
|
|
|
|
|
active = not (FreeCAD.ActiveDocument is None)
|
|
|
|
|
if not (FreeCAD.ActiveDocument.getObject("Terrain") is None):
|
|
|
|
|
active = active and not (FreeCAD.ActiveDocument.getObject("Terrain").Mesh is None)
|
|
|
|
|
return active
|
|
|
|
|
|
|
|
|
|
if FreeCAD.GuiUp:
|
2025-03-28 19:40:11 +06:00
|
|
|
FreeCADGui.addCommand('PVPlantEarthworks', _CommandCalculateEarthworks())'''
|
2025-01-28 00:04:13 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def accept():
|
|
|
|
|
import MeshPart as mp
|
|
|
|
|
land = FreeCAD.ActiveDocument.Terrain.Mesh
|
|
|
|
|
frames = []
|
|
|
|
|
for obj in FreeCADGui.Selection.getSelection():
|
|
|
|
|
if hasattr(obj, "Proxy"):
|
|
|
|
|
if obj.Proxy.Type == "Tracker":
|
|
|
|
|
if not (obj in frames):
|
|
|
|
|
frames.append(obj)
|
|
|
|
|
elif obj.Proxy.Type == "FrameArea":
|
|
|
|
|
for fr in obj.Frames:
|
|
|
|
|
if not (fr in frames):
|
|
|
|
|
frames.append(fr)
|
|
|
|
|
if len(frames) == 0:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
FreeCAD.ActiveDocument.openTransaction("Calcular movimiento de tierras")
|
|
|
|
|
import PVPlantPlacement
|
|
|
|
|
rows, columns = PVPlantPlacement.getRows(frames)
|
|
|
|
|
if (rows is None) or (columns is None):
|
|
|
|
|
print("Nada que procesar")
|
|
|
|
|
return False
|
|
|
|
|
tools = []
|
|
|
|
|
|
|
|
|
|
for group in rows:
|
|
|
|
|
lines = []
|
|
|
|
|
cont = 0
|
|
|
|
|
while cont < len(group):
|
|
|
|
|
aw = 0
|
|
|
|
|
if cont > 0:
|
|
|
|
|
p0 = FreeCAD.Vector(group[cont - 1].Placement.Base)
|
|
|
|
|
p1 = FreeCAD.Vector(group[cont].Placement.Base)
|
|
|
|
|
aw = getAngle(p0, p1)
|
|
|
|
|
|
|
|
|
|
ae = 0
|
|
|
|
|
if cont < (len(group) - 1):
|
|
|
|
|
p1 = FreeCAD.Vector(group[cont].Placement.Base)
|
|
|
|
|
p2 = FreeCAD.Vector(group[cont + 1].Placement.Base)
|
|
|
|
|
ae = getAngle(p1, p2)
|
|
|
|
|
|
|
|
|
|
lng = int(group[cont].Setup.Length / 2)
|
|
|
|
|
wdt = int(group[cont].Setup.Width / 2)
|
|
|
|
|
line = Part.LineSegment(FreeCAD.Vector(-lng, 0, 0),
|
|
|
|
|
FreeCAD.Vector(lng, 0, 0)).toShape()
|
|
|
|
|
|
|
|
|
|
line = Part.LineSegment(FreeCAD.Vector(group[cont].Setup.Shape.SubShapes[1].SubShapes[0].SubShapes[0].Placement.Base.x, 0, 0),
|
|
|
|
|
FreeCAD.Vector(group[cont].Setup.Shape.SubShapes[1].SubShapes[0].SubShapes[-1].Placement.Base.x, 0, 0)).toShape()
|
|
|
|
|
|
|
|
|
|
anf = (aw + ae) / 2
|
|
|
|
|
if anf > FreeCAD.ActiveDocument.MaximumWestEastSlope.Value:
|
|
|
|
|
anf = FreeCAD.ActiveDocument.MaximumWestEastSlope.Value
|
|
|
|
|
zz = wdt * math.sin(math.radians(anf))
|
|
|
|
|
|
|
|
|
|
li = line.copy()
|
|
|
|
|
li.Placement = group[cont].Placement
|
|
|
|
|
li.Placement.Rotation = group[cont].Placement.Rotation
|
|
|
|
|
li.Placement.Base.x -= wdt #+ (3000 if cont == 0 else 0))
|
|
|
|
|
li.Placement.Base.z -= zz
|
|
|
|
|
lines.append(li)
|
|
|
|
|
|
|
|
|
|
ld = line.copy()
|
|
|
|
|
ld.Placement = group[cont].Placement
|
|
|
|
|
ld.Placement.Rotation = group[cont].Placement.Rotation
|
|
|
|
|
ld.Placement.Base.x += wdt #+ (3000 if cont == len(group) - 1 else 0))
|
|
|
|
|
ld.Placement.Base.z += zz
|
|
|
|
|
lines.append(ld)
|
|
|
|
|
tools.append([group[cont], li, ld])
|
|
|
|
|
cont += 1
|
|
|
|
|
|
|
|
|
|
loft = Part.makeLoft(lines, False, True, False)
|
|
|
|
|
import MeshPart as mp
|
|
|
|
|
msh = mp.meshFromShape(Shape=loft) #, MaxLength=1)
|
|
|
|
|
#msh = msh.smooth("Laplace", 3)
|
|
|
|
|
import Mesh
|
|
|
|
|
Mesh.show(msh)
|
|
|
|
|
'''intersec = land.section(msh, MinDist=0.01)
|
|
|
|
|
import Draft
|
|
|
|
|
for sec in intersec:
|
|
|
|
|
Draft.makeWire(sec)'''
|
|
|
|
|
|
|
|
|
|
for group in rows:
|
|
|
|
|
lines = []
|
|
|
|
|
for frame in group:
|
|
|
|
|
col, idx = searchFrameInColumns(frame, columns)
|
|
|
|
|
tool = searchTool(frame, tools)
|
|
|
|
|
if idx == 0:
|
|
|
|
|
''' '''
|
|
|
|
|
if idx == (len(col) - 1):
|
|
|
|
|
''' '''
|
|
|
|
|
|
|
|
|
|
if (idx + 1) < len(col):
|
|
|
|
|
frame1 = col[idx + 1]
|
|
|
|
|
tool1 = searchTool(frame1, tools)
|
|
|
|
|
line = Part.LineSegment(tool[1].Vertexes[1].Point, tool1[1].Vertexes[0].Point).toShape()
|
|
|
|
|
Part.show(line)
|
|
|
|
|
lines.append(line)
|
|
|
|
|
line = Part.LineSegment(tool[2].Vertexes[1].Point, tool1[2].Vertexes[0].Point).toShape()
|
|
|
|
|
Part.show(line)
|
|
|
|
|
lines.append(line)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(lines) > 0:
|
|
|
|
|
loft = Part.makeLoft(lines, False, True, False)
|
|
|
|
|
import MeshPart as mp
|
|
|
|
|
msh = mp.meshFromShape(Shape=loft) # , MaxLength=1)
|
|
|
|
|
#msh = msh.smooth("Laplace", 3)
|
|
|
|
|
import Mesh
|
|
|
|
|
Mesh.show(msh)
|
|
|
|
|
intersec = land.section(msh, MinDist=0.01)
|
|
|
|
|
import Draft
|
|
|
|
|
for sec in intersec:
|
|
|
|
|
Draft.makeWire(sec)
|
|
|
|
|
|
|
|
|
|
FreeCAD.ActiveDocument.commitTransaction()
|
|
|
|
|
self.closeForm()
|
2025-04-14 10:05:32 +06:00
|
|
|
return True
|
|
|
|
|
|