Files
PVPlant/PVPlantSurface.py

292 lines
8.5 KiB
Python
Raw Normal View History

2025-01-28 00:04:13 +01:00
import copy
import random
import FreeCAD
import Mesh
from freecad.trails import ICONPATH, geo_origin
from pivy import coin
def create(name='Surface'):
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython", "Surface")
obj.Label = name
Surface(obj)
ViewProviderSurface(obj.ViewObject)
FreeCAD.ActiveDocument.recompute()
return obj
#class Surface(SurfaceFunc):
class Surface(ArchComponent.Component):
"""
This class is about Surface Object data features.
"""
def __init__(self, obj):
'''
Set data properties.
'''
ArchComponent.Component.__init__(self, obj)
self.Type = 'PVPlant::Surface'
self.setproperties()
obj.Proxy = self
# Does a IfcType exist?
obj.IfcType = "Civil Element"
obj.setEditorMode("IfcType", 1)
def setproperties(self):
# Triangulation properties.
obj.addProperty(
'App::PropertyLinkList', "PointGroups", "Base",
"List of Point Groups").PointGroups = []
obj.addProperty(
"App::PropertyIntegerList", "Delaunay", "Base",
"Index of Delaunay vertices", 4).Delaunay = []
obj.addProperty(
"Mesh::PropertyMeshKernel", "Mesh", "Base",
"Mesh object of triangulation").Mesh = Mesh.Mesh()
obj.addProperty(
"App::PropertyLength", "MaxLength", "Base",
"Maximum length of triangle edge").MaxLength = 50000
obj.addProperty(
"App::PropertyAngle", "MaxAngle", "Base",
"Maximum angle of triangle edge").MaxAngle = 170
# Contour properties.
obj.addProperty(
"App::PropertyFloatConstraint", "ContourInterval", "Contour",
"Size of the point group").ContourInterval = (1.0, 0.0, 100.0, 1.0)
obj.addProperty(
"App::PropertyVectorList", "ContourPoints", "Contour",
"Points of contours", 4).ContourPoints = []
obj.addProperty(
"App::PropertyIntegerList", "ContourVertices", "Contour",
"Vertices of contours.", 4).ContourVertices = []
def onChanged(self, obj, prop):
'''
Do something when a data property has changed.
'''
points = []
pgs = obj.getPropertyByName("PointGroups")
for pg in pgs:
points.extend(pg.Points)
if points:
origin = geo_origin.get(points[0])
else:
origin = geo_origin.get()
if prop == "PointGroups":
if len(points) > 2:
obj.Delaunay = self.triangulate(points)
else:
obj.Mesh = Mesh.Mesh()
if prop == "Delaunay" or prop == "MaxLength" or prop == "MaxAngle":
delaunay = obj.getPropertyByName("Delaunay")
lmax = obj.getPropertyByName("MaxLength")
amax = obj.getPropertyByName("MaxAngle")
if delaunay:
obj.Mesh = self.test_delaunay(
origin.Origin, points, delaunay, lmax, amax)
if prop == "Mesh" or prop == "ContourInterval":
deltaH = obj.getPropertyByName("ContourInterval")
mesh = obj.getPropertyByName("Mesh")
coords, num_vert = self.contour_points(origin.Origin, mesh, deltaH)
obj.ContourPoints = coords
obj.ContourVertices = num_vert
def execute(self, obj):
'''
Do something when doing a recomputation.
'''
pass
class ViewProviderSurface:
"""
This class is about Surface Object view features.
"""
def __init__(self, vobj):
'''
Set view properties.
'''
(r, g, b) = (random.random(), random.random(), random.random())
vobj.addProperty(
"App::PropertyColor", "TriangleColor", "Surface Style",
"Color of the point group").TriangleColor = (r, g, b)
vobj.Proxy = self
def attach(self, vobj):
'''
Create Object visuals in 3D view.
'''
# GeoCoords Node.
self.geo_coords = coin.SoGeoCoordinate()
# Surface features.
self.triangles = coin.SoIndexedFaceSet()
shape_hints = coin.SoShapeHints()
shape_hints.vertex_ordering = coin.SoShapeHints.COUNTERCLOCKWISE
self.mat_color = coin.SoMaterial()
mat_binding = coin.SoMaterialBinding()
mat_binding.value = coin.SoMaterialBinding.OVERALL
edge_color = coin.SoBaseColor()
edge_color.rgb = (0.5, 0.5, 0.5)
offset = coin.SoPolygonOffset()
# Line style.
line_style = coin.SoDrawStyle()
line_style.style = coin.SoDrawStyle.LINES
line_style.lineWidth = 2
# Contour features.
cont_color = coin.SoBaseColor()
cont_color.rgb = (1, 1, 0)
self.cont_coords = coin.SoGeoCoordinate()
self.cont_lines = coin.SoLineSet()
# Contour root.
contours = coin.SoSeparator()
contours.addChild(cont_color)
contours.addChild(line_style)
contours.addChild(self.cont_coords)
contours.addChild(self.cont_lines)
# Face root.
faces = coin.SoSeparator()
faces.addChild(shape_hints)
faces.addChild(self.mat_color)
faces.addChild(mat_binding)
faces.addChild(self.geo_coords)
faces.addChild(self.triangles)
# Highlight for selection.
highlight = coin.SoType.fromName('SoFCSelection').createInstance()
highlight.style = 'EMISSIVE_DIFFUSE'
highlight.addChild(edge_color)
highlight.addChild(line_style)
highlight.addChild(self.geo_coords)
highlight.addChild(self.triangles)
# Surface root.
surface_root = coin.SoSeparator()
surface_root.addChild(contours)
surface_root.addChild(offset)
surface_root.addChild(faces)
surface_root.addChild(offset)
surface_root.addChild(highlight)
vobj.addDisplayMode(surface_root, "Surface")
# Take features from properties.
self.onChanged(vobj, "TriangleColor")
def onChanged(self, vobj, prop):
'''
Update Object visuals when a view property changed.
'''
try:
if prop == "TriangleColor":
color = vobj.getPropertyByName("TriangleColor")
self.mat_color.diffuseColor = (color[0], color[1], color[2])
except Exception:
pass
def updateData(self, obj, prop):
'''
Update Object visuals when a data property changed.
'''
if prop == "Mesh":
mesh = obj.getPropertyByName("Mesh")
topo_points = mesh.Topology[0]
topo_tri = mesh.Topology[1]
# Get GeoOrigin.
points = []
triangles = []
origin = geo_origin.get()
base = copy.deepcopy(origin.Origin)
base.z = 0
for i in topo_points:
point = copy.deepcopy(i)
points.append(point.add(base))
for i in topo_tri:
triangles.extend(list(i))
triangles.append(-1)
# Set GeoCoords.
geo_system = ["UTM", origin.UtmZone, "FLAT"]
self.geo_coords.geoSystem.setValues(geo_system)
self.geo_coords.point.values = points
# Set contour system.
self.cont_coords.geoSystem.setValues(geo_system)
self.triangles.coordIndex.values = triangles
if prop == "Mesh" or prop == "ContourInterval":
cont_points = obj.getPropertyByName("ContourPoints")
cont_vert = obj.getPropertyByName("ContourVertices")
self.cont_coords.point.values = cont_points
self.cont_lines.numVertices.values = cont_vert
def getDisplayModes(self, vobj):
'''
Return a list of display modes.
'''
modes = []
modes.append("Surface")
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 getIcon(self):
'''
Return object treeview icon.
'''
return ICONPATH + '/icons/Surface.svg'
def __getstate__(self):
"""
Save variables to file.
"""
return None
def __setstate__(self, state):
"""
Get variables from file.
"""
return None