import math import FreeCAD import Part import ArchComponent from pivy import coin import numpy as np import DraftGeomUtils 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 class EarthWorksTaskPanel: 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") 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) tmp = [] shp = Part.Shape() for face in sh.Faces: wire = face.Wires[0].copy() pl = wire.Placement.Base wire.Placement.Base = wire.Placement.Base - pl if DraftGeomUtils.isPlanar(wire): # Caso simple wire = wire.makeOffset2D(10000, 0, False, False, True) wire.Placement.Base.z = wire.Placement.Base.z - 10000 top = wire.makeOffset2D(1, 0, False, False, True) loft = Part.makeLoft([top, wire], True, True, False) tmp.append(loft) shp = shp.fuse(loft) 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 top = wire.makeOffset2D(1, 0, False, False, True) loft = Part.makeLoft([top, wire], True, True, False) tmp.append(loft) shp = shp.fuse(loft) final_tool = Part.makeCompound(tmp) Part.show(final_tool, "tool") Part.show(shp) 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 '''class _CommandCalculateEarthworks: 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: FreeCADGui.addCommand('PVPlantEarthworks', _CommandCalculateEarthworks())''' 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() return True