primera subida
This commit is contained in:
864
Export/exportPVSyst.py
Normal file
864
Export/exportPVSyst.py
Normal file
@@ -0,0 +1,864 @@
|
||||
# /**********************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2021 Javier Braña <javier.branagutierrez@gmail.com> *
|
||||
# * *
|
||||
# * This program is free software; you can redistribute it and/or modify*
|
||||
# * it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
# * as published by the Free Software Foundation; either version 2 of *
|
||||
# * the License, or (at your option) any later version. *
|
||||
# * for detail see the LICENCE text file. *
|
||||
# * *
|
||||
# * This program is distributed in the hope that it will be useful, *
|
||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
# * GNU Library General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Library General Public *
|
||||
# * License along with this program; if not, write to the Free Software *
|
||||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307*
|
||||
# * USA *
|
||||
# * *
|
||||
# ***********************************************************************
|
||||
|
||||
import Arch
|
||||
import Draft
|
||||
import FreeCAD
|
||||
import Mesh
|
||||
import MeshPart
|
||||
import Part
|
||||
import numpy
|
||||
import os
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
from DraftTools import translate
|
||||
else:
|
||||
def translate(ctxt, txt):
|
||||
return txt
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
from PVPlantResources import DirIcons as DirIcons
|
||||
|
||||
## @package importDAE
|
||||
# \ingroup ARCH
|
||||
# \brief DAE (Collada) file format importer and exporter
|
||||
#
|
||||
# This module provides tools to import and export Collada (.dae) files.
|
||||
|
||||
__title__ = "FreeCAD Collada importer"
|
||||
__author__ = "Yorik van Havre"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
try:
|
||||
# Python 2 forward compatibility
|
||||
range = xrange
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
|
||||
def checkCollada():
|
||||
"checks if collada if available"
|
||||
|
||||
global collada
|
||||
COLLADA = None
|
||||
try:
|
||||
import collada
|
||||
except ImportError:
|
||||
FreeCAD.Console.PrintError(translate("Arch", "pycollada not found, collada support is disabled.") + "\n")
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
# from ARCH:
|
||||
def triangulate(shape):
|
||||
"triangulates the given face"
|
||||
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||
mesher = p.GetInt("ColladaMesher", 0)
|
||||
tessellation = p.GetFloat("ColladaTessellation", 1.0)
|
||||
grading = p.GetFloat("ColladaGrading", 0.3)
|
||||
segsperedge = p.GetInt("ColladaSegsPerEdge", 1)
|
||||
segsperradius = p.GetInt("ColladaSegsPerRadius", 2)
|
||||
secondorder = p.GetBool("ColladaSecondOrder", False)
|
||||
optimize = p.GetBool("ColladaOptimize", True)
|
||||
allowquads = p.GetBool("ColladaAllowQuads", False)
|
||||
|
||||
if mesher == 0:
|
||||
return shape.tessellate(tessellation)
|
||||
elif mesher == 1:
|
||||
return MeshPart.meshFromShape(Shape=shape, MaxLength=tessellation).Topology
|
||||
else:
|
||||
return MeshPart.meshFromShape(Shape=shape, GrowthRate=grading, SegPerEdge=segsperedge,
|
||||
SegPerRadius=segsperradius, SecondOrder=secondorder, Optimize=optimize,
|
||||
AllowQuad=allowquads).Topology
|
||||
|
||||
def export(exportList, filename, tessellation=1, colors=None):
|
||||
"""export(exportList,filename,tessellation=1,colors=None) -- exports FreeCAD contents to a DAE file.
|
||||
colors is an optional dictionary of objName:shapeColorTuple or objName:diffuseColorList elements
|
||||
to be used in non-GUI mode if you want to be able to export colors. Tessellation is used when breaking
|
||||
curved surfaces into triangles."""
|
||||
|
||||
if not checkCollada(): return
|
||||
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
|
||||
scale = p.GetFloat("ColladaScalingFactor", 1.0)
|
||||
scale = scale * 0.001 # from millimeters (FreeCAD) to meters (Collada)
|
||||
p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View")
|
||||
c = p.GetUnsigned("DefaultShapeColor", 4294967295)
|
||||
defaultcolor = (float((c >> 24) & 0xFF) / 255.0, float((c >> 16) & 0xFF) / 255.0, float((c >> 8) & 0xFF) / 255.0)
|
||||
colmesh = collada.Collada()
|
||||
colmesh.assetInfo.upaxis = collada.asset.UP_AXIS.Z_UP
|
||||
|
||||
# authoring info
|
||||
cont = collada.asset.Contributor()
|
||||
try:
|
||||
author = FreeCAD.ActiveDocument.CreatedBy
|
||||
except UnicodeEncodeError:
|
||||
author = FreeCAD.ActiveDocument.CreatedBy.encode("utf8")
|
||||
author = author.replace("<", "")
|
||||
author = author.replace(">", "")
|
||||
cont.author = author
|
||||
ver = FreeCAD.Version()
|
||||
appli = "PVPlant for FreeCAD" + ver[0] + "." + ver[1] + " build" + ver[2] + "\n"
|
||||
cont.authoring_tool = appli
|
||||
|
||||
colmesh.assetInfo.contributors.append(cont)
|
||||
colmesh.assetInfo.unitname = "meter"
|
||||
colmesh.assetInfo.unitmeter = 1.0
|
||||
|
||||
defaultmat = None
|
||||
objind = 0
|
||||
scenenodes = []
|
||||
|
||||
# TODO: cambiar lo de objeclist. Buscar los elementos que se necesitan exportar
|
||||
objectlist = Draft.get_group_contents(exportList, walls=True, addgroups=True)
|
||||
objectlist = Arch.pruneIncluded(objectlist)
|
||||
for obj in objectlist:
|
||||
findex = numpy.array([])
|
||||
m = None
|
||||
if obj.isDerivedFrom("Part::Feature"):
|
||||
print("exporting object ", obj.Name, obj.Shape)
|
||||
new_shape = obj.Shape.copy()
|
||||
new_shape.Placement = obj.getGlobalPlacement()
|
||||
m = Mesh.Mesh(triangulate(new_shape))
|
||||
elif obj.isDerivedFrom("Mesh::Feature"):
|
||||
print("exporting object ", obj.Name, obj.Mesh)
|
||||
m = obj.Mesh
|
||||
elif obj.isDerivedFrom("App::Part"):
|
||||
for child in obj.OutList:
|
||||
objectlist.append(child)
|
||||
continue
|
||||
else:
|
||||
continue
|
||||
|
||||
if m:
|
||||
Topology = m.Topology
|
||||
Facets = m.Facets
|
||||
|
||||
# vertex indices
|
||||
vindex = numpy.empty(len(Topology[0]) * 3)
|
||||
for i in range(len(Topology[0])):
|
||||
v = Topology[0][i]
|
||||
vindex[list(range(i * 3, i * 3 + 3))] = (v.x * scale, v.y * scale, v.z * scale)
|
||||
|
||||
# normals
|
||||
nindex = numpy.empty(len(Facets) * 3)
|
||||
for i in range(len(Facets)):
|
||||
n = Facets[i].Normal
|
||||
nindex[list(range(i * 3, i * 3 + 3))] = (n.x, n.y, n.z)
|
||||
|
||||
# face indices
|
||||
findex = numpy.empty(len(Topology[1]) * 6, numpy.int64)
|
||||
for i in range(len(Topology[1])):
|
||||
f = Topology[1][i]
|
||||
findex[list(range(i * 6, i * 6 + 6))] = (f[0], i, f[1], i, f[2], i)
|
||||
|
||||
print(len(vindex), " vert indices, ", len(nindex), " norm indices, ", len(findex), " face indices.")
|
||||
vert_src = collada.source.FloatSource("cubeverts-array" + str(objind), vindex, ('X', 'Y', 'Z'))
|
||||
normal_src = collada.source.FloatSource("cubenormals-array" + str(objind), nindex, ('X', 'Y', 'Z'))
|
||||
geom = collada.geometry.Geometry(colmesh, "geometry" + str(objind), obj.Name, [vert_src, normal_src])
|
||||
input_list = collada.source.InputList()
|
||||
input_list.addInput(0, 'VERTEX', "#cubeverts-array" + str(objind))
|
||||
input_list.addInput(1, 'NORMAL', "#cubenormals-array" + str(objind))
|
||||
matnode = None
|
||||
matref = "materialref"
|
||||
if hasattr(obj, "Material"):
|
||||
if obj.Material:
|
||||
if hasattr(obj.Material, "Material"):
|
||||
if "DiffuseColor" in obj.Material.Material:
|
||||
kd = tuple([float(k) for k in obj.Material.Material["DiffuseColor"].strip("()").split(",")])
|
||||
effect = collada.material.Effect("effect_" + obj.Material.Name, [], "phong", diffuse=kd,
|
||||
specular=(1, 1, 1))
|
||||
mat = collada.material.Material("mat_" + obj.Material.Name, obj.Material.Name, effect)
|
||||
colmesh.effects.append(effect)
|
||||
colmesh.materials.append(mat)
|
||||
matref = "ref_" + obj.Material.Name
|
||||
matnode = collada.scene.MaterialNode(matref, mat, inputs=[])
|
||||
|
||||
if not matnode:
|
||||
if colors:
|
||||
if obj.Name in colors:
|
||||
color = colors[obj.Name]
|
||||
if color:
|
||||
if isinstance(color[0], tuple):
|
||||
# this is a diffusecolor. For now, use the first color - #TODO: Support per-face colors
|
||||
color = color[0]
|
||||
# print("found color for obj",obj.Name,":",color)
|
||||
kd = color[:3]
|
||||
effect = collada.material.Effect("effect_" + obj.Name, [], "phong", diffuse=kd,
|
||||
specular=(1, 1, 1))
|
||||
mat = collada.material.Material("mat_" + obj.Name, obj.Name, effect)
|
||||
colmesh.effects.append(effect)
|
||||
colmesh.materials.append(mat)
|
||||
matref = "ref_" + obj.Name
|
||||
matnode = collada.scene.MaterialNode(matref, mat, inputs=[])
|
||||
elif FreeCAD.GuiUp:
|
||||
if hasattr(obj.ViewObject, "ShapeColor"):
|
||||
kd = obj.ViewObject.ShapeColor[:3]
|
||||
effect = collada.material.Effect("effect_" + obj.Name, [], "phong", diffuse=kd, specular=(1, 1, 1))
|
||||
mat = collada.material.Material("mat_" + obj.Name, obj.Name, effect)
|
||||
colmesh.effects.append(effect)
|
||||
colmesh.materials.append(mat)
|
||||
matref = "ref_" + obj.Name
|
||||
matnode = collada.scene.MaterialNode(matref, mat, inputs=[])
|
||||
|
||||
if not matnode:
|
||||
if not defaultmat:
|
||||
effect = collada.material.Effect("effect_default", [], "phong", diffuse=defaultcolor,
|
||||
specular=(1, 1, 1))
|
||||
defaultmat = collada.material.Material("mat_default", "default_material", effect)
|
||||
colmesh.effects.append(effect)
|
||||
colmesh.materials.append(defaultmat)
|
||||
matnode = collada.scene.MaterialNode(matref, defaultmat, inputs=[])
|
||||
|
||||
triset = geom.createTriangleSet(findex, input_list, matref)
|
||||
geom.primitives.append(triset)
|
||||
colmesh.geometries.append(geom)
|
||||
geomnode = collada.scene.GeometryNode(geom, [matnode])
|
||||
node = collada.scene.Node("node" + str(objind), children=[geomnode])
|
||||
scenenodes.append(node)
|
||||
objind += 1
|
||||
|
||||
myscene = collada.scene.Scene("PVScene", scenenodes)
|
||||
colmesh.scenes.append(myscene)
|
||||
colmesh.scene = myscene
|
||||
colmesh.write(filename)
|
||||
|
||||
FreeCAD.Console.PrintMessage(translate("Arch", "file %s successfully created.") % filename)
|
||||
|
||||
def exportToDAE(path):
|
||||
filename = path + ".dae"
|
||||
|
||||
def exportToPVC(path, exportTerrain = False):
|
||||
filename = path + ".pvc"
|
||||
scale = 0.001 # from millimeters (FreeCAD) to meters (Collada)
|
||||
|
||||
from xml.etree.ElementTree import Element, SubElement
|
||||
import datetime
|
||||
|
||||
generated_on = str(datetime.datetime.now())
|
||||
|
||||
site = None
|
||||
tmp = FreeCAD.ActiveDocument.getObjectsByLabel('Site')
|
||||
for obj in tmp:
|
||||
if obj.Name.startswith("Site"):
|
||||
site = obj
|
||||
break
|
||||
terrain = None
|
||||
center = None
|
||||
if not(site.Terrain is None):
|
||||
terrain = site.Terrain.Mesh
|
||||
center = terrain.BoundBox.Center
|
||||
else:
|
||||
center = FreeCAD.Vector()
|
||||
|
||||
try:
|
||||
author = FreeCAD.ActiveDocument.CreatedBy
|
||||
except UnicodeEncodeError:
|
||||
author = FreeCAD.ActiveDocument.CreatedBy.encode("utf8")
|
||||
|
||||
author = author.replace("<", "")
|
||||
author = author.replace(">", "")
|
||||
ver = FreeCAD.Version()
|
||||
appli = "PVPlant for FreeCAD" + ver[0] + "." + ver[1] + " build" + ver[2] + "\n"
|
||||
|
||||
# xml: Configure one attribute with set()
|
||||
root = Element('COLLADA')
|
||||
root.set('xmlns:xsd', 'http://www.w3.org/2001/XMLSchema')
|
||||
root.set('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance')
|
||||
root.set('version', '1.4.1')
|
||||
root.set('xmlns', 'http://www.collada.org/2005/11/COLLADASchema')
|
||||
#root.append(Comment('Generated by ElementTree_csv_to_xml.py for PyMOTW'))
|
||||
|
||||
# xml: 1. Asset:
|
||||
asset = SubElement(root, 'asset')
|
||||
asset_contributor = SubElement(asset, 'contributor')
|
||||
asset_contributor_autor = SubElement(asset_contributor, 'autor')
|
||||
#asset_contributor_autor.text = author
|
||||
asset_contributor_authoring_tool = SubElement(asset_contributor, 'authoring_tool')
|
||||
#asset_contributor_authoring_tool.text = appli
|
||||
asset_contributor_comments = SubElement(asset_contributor, 'comments')
|
||||
asset_keywords = SubElement(asset, 'keywords')
|
||||
asset_revision = SubElement(asset, 'revision')
|
||||
asset_subject = SubElement(asset, 'subject')
|
||||
asset_tittle = SubElement(asset, 'title')
|
||||
#asset_tittle.text = FreeCAD.ActiveDocument.Name
|
||||
asset_unit = SubElement(asset, 'unit')
|
||||
asset_unit.set('meter', '0.001')
|
||||
asset_unit.set('name', 'millimeter')
|
||||
|
||||
# xml: 2. library_materials:
|
||||
library_materials = SubElement(root, 'library_materials')
|
||||
buf = ['Frames', 'Tree_trunk', 'Tree_crown', 'Topography_mesh']
|
||||
|
||||
for i in range(0, len(buf)):
|
||||
material = SubElement(library_materials, 'material')
|
||||
material.set('id', 'Material{0}'.format(i))
|
||||
material.set('name', buf[i])
|
||||
material_effect = SubElement(material, 'instance_effect')
|
||||
material_effect.set('url', '#Material{0}-fx'.format(i))
|
||||
|
||||
# xml: 3. library_effects:
|
||||
library_effects = SubElement(root, 'library_effects')
|
||||
buf = ['0.250000 0.500000 0.000000 1.000000',
|
||||
'0.500000 0.375000 0.250000 1.000000',
|
||||
'0.250000 1.000000 0.000000 1.000000',
|
||||
'0.250000 1.000000 0.000000 1.000000']
|
||||
|
||||
for i in range(0, len(buf)):
|
||||
effect = SubElement(library_effects, 'effect')
|
||||
effect.set('id', 'Material{0}-fx'.format(i))
|
||||
effect.set('name', 'Material{0}'.format(i))
|
||||
profile_COMMON = SubElement(effect, 'profile_COMMON')
|
||||
library_effects_effect_technique = SubElement(profile_COMMON, 'technique')
|
||||
library_effects_effect_technique.set('sid', 'standard')
|
||||
library_effects_effect_technique_lambert = SubElement(library_effects_effect_technique, 'lambert')
|
||||
library_effects_effect_technique_lambert_emission = SubElement(library_effects_effect_technique_lambert,
|
||||
'emission')
|
||||
library_effects_effect_technique_lambert_emission_color = SubElement(
|
||||
library_effects_effect_technique_lambert_emission, 'color')
|
||||
library_effects_effect_technique_lambert_emission_color.set('sid', 'emission')
|
||||
library_effects_effect_technique_lambert_emission_color.text = '0.000000 0.000000 0.000000 1.000000'
|
||||
ambient = SubElement(library_effects_effect_technique_lambert, 'ambient')
|
||||
ambient_color = SubElement(ambient, 'color')
|
||||
ambient_color.set('sid', 'ambient')
|
||||
ambient_color.text = '0.200000 0.200000 0.200000 1.000000'
|
||||
diffuse = SubElement(library_effects_effect_technique_lambert, 'diffuse')
|
||||
diffuse_color = SubElement(diffuse, 'color')
|
||||
diffuse_color.set('sid', 'diffuse')
|
||||
diffuse_color.text = buf[i]
|
||||
transparent = SubElement(library_effects_effect_technique_lambert, 'transparent')
|
||||
transparent.set('opaque', 'RGB_ZERO')
|
||||
transparent_color = SubElement(transparent, 'color')
|
||||
transparent_color.set('sid', 'transparent')
|
||||
transparent_color.text = '0.000000 0.000000 0.000000 1.000000'
|
||||
transparency = SubElement(library_effects_effect_technique_lambert, 'transparency')
|
||||
transparency_value = SubElement(transparency, 'float')
|
||||
transparency_value.set('sid', 'transparency')
|
||||
transparency_value.text = '0'
|
||||
|
||||
# xml: 4. library_geometries:
|
||||
library_geometries = SubElement(root, 'library_geometries')
|
||||
def add_geometry(objtype, vindex, findex, objind = 0, centers = None):
|
||||
|
||||
isFrame = False
|
||||
if objtype == 0:
|
||||
geometryName = 'Frame'
|
||||
referenceSTR = 'frame'
|
||||
isFrame = True
|
||||
elif objtype == 1:
|
||||
geometryName = 'ShadowMesh' ## --> ???
|
||||
referenceSTR = 'ShadowMesh' ## --> ???
|
||||
elif objtype == 2:
|
||||
geometryName = 'TerrainMesh'
|
||||
referenceSTR = 'TerrainMesh'
|
||||
|
||||
geometry = SubElement(library_geometries, 'geometry')
|
||||
geometry.set('id', geometryName + '{0}'.format(objind))
|
||||
mesh = SubElement(geometry, 'mesh')
|
||||
|
||||
source = SubElement(mesh, 'source')
|
||||
source.set('id', referenceSTR + '{0}MeshSource'.format(objind))
|
||||
float_array = SubElement(source, 'float_array')
|
||||
float_array.set('id', referenceSTR + '{0}FloatArray'.format(objind))
|
||||
float_array.set('count', '{0}'.format(len(vindex)))
|
||||
float_array.text = "" # vindex
|
||||
for ver in vindex:
|
||||
if len(float_array.text) > 0:
|
||||
float_array.text += ' '
|
||||
float_array.text += '{0:.6f}'.format(ver)
|
||||
|
||||
technique_common = SubElement(source, 'technique_common')
|
||||
accessor = SubElement(technique_common, 'accessor')
|
||||
accessor.set('count', '{0}'.format(len(vindex)))
|
||||
accessor.set('source', '#' + referenceSTR + '{0}FloatArray'.format(objind))
|
||||
accessor.set('stride', '3')
|
||||
param = SubElement(accessor, 'param')
|
||||
param.set('name', 'X')
|
||||
param.set('type', 'float')
|
||||
param = SubElement(accessor, 'param')
|
||||
param.set('name', 'Y')
|
||||
param.set('type', 'float')
|
||||
param = SubElement(accessor, 'param')
|
||||
param.set('name', 'Z')
|
||||
param.set('type', 'float')
|
||||
|
||||
vertices = SubElement(mesh, 'vertices')
|
||||
vertices.set('id', referenceSTR + '{0}VerticesSource'.format(objind))
|
||||
input = SubElement(vertices, "input")
|
||||
input.set('semantic', 'POSITION')
|
||||
input.set('source', '#' + referenceSTR + '{0}MeshSource'.format(objind))
|
||||
|
||||
triangles = SubElement(mesh, 'triangles')
|
||||
triangles.set('count', '0')
|
||||
triangles.set('material', 'Material0')
|
||||
input = SubElement(triangles, "input")
|
||||
input.set('offset', '0')
|
||||
input.set('semantic', 'VERTEX')
|
||||
input.set('source', '#' + referenceSTR + '{0}VerticesSource'.format(objind))
|
||||
p = SubElement(triangles, "p")
|
||||
p.text = ''
|
||||
for f in findex:
|
||||
if len(p.text) > 0:
|
||||
p.text += ' '
|
||||
p.text += '{0}'.format(f)
|
||||
|
||||
if isFrame:
|
||||
frame = SubElement(mesh, 'tracker_parameters' if isTracker else 'frame_parameters')
|
||||
module_width = SubElement(frame, "module_width")
|
||||
module_width.text = '{0}'.format(int(obj.Setup.ModuleWidth.Value))
|
||||
module_height = SubElement(frame, "module_height")
|
||||
module_height.text = '{0}'.format(int(obj.Setup.ModuleHeight.Value))
|
||||
module_x_spacing = SubElement(frame, "module_x_spacing")
|
||||
module_x_spacing.text = '{0}'.format(int(obj.Setup.ModuleColGap.Value))
|
||||
module_y_spacing = SubElement(frame, "module_y_spacing")
|
||||
module_y_spacing.text = '{0}'.format(int(obj.Setup.ModuleRowGap.Value))
|
||||
module_manufacturer = SubElement(frame, "module_manufacturer")
|
||||
module_manufacturer.text = 'generic'
|
||||
module_name = SubElement(frame, "module_name")
|
||||
module_name.text = 'generic'
|
||||
if isTracker:
|
||||
tracker_type = SubElement(frame, 'tracker_type')
|
||||
tracker_type.text = 'single_axis_trackers'
|
||||
axis = SubElement(frame, 'axis_vertices')
|
||||
for ind in range(0, len(centers)):
|
||||
array = SubElement(axis, 'float_array')
|
||||
array.set('id', 'tracker{0}AxisFloatArray1'.format(ind))
|
||||
array.set('count', '3')
|
||||
array.text = '{0:.6f} {1:.6f} {2:.6f}'.format(centers[i].x, centers[i].y, centers[i].z)
|
||||
|
||||
min_phi = SubElement(frame, 'min_phi')
|
||||
min_phi.text = '{0}'.format(int(obj.Setup.MinPhi.Value))
|
||||
max_phi = SubElement(frame, 'max_phi')
|
||||
max_phi.text = '{0}'.format(int(obj.Setup.MaxPhi.Value))
|
||||
min_theta = SubElement(frame, 'min_theta')
|
||||
min_theta.text = '{0}'.format(0)
|
||||
max_theta = SubElement(frame, 'max_theta')
|
||||
max_theta.text = '{0}'.format(0)
|
||||
|
||||
# xml: 5. library_visual_scenes:
|
||||
instance_geometry = SubElement(node, 'instance_geometry')
|
||||
instance_geometry.set('url', geometryName + '{0}'.format(objind))
|
||||
|
||||
bind_material = SubElement(instance_geometry, 'bind_material')
|
||||
technique_common = SubElement(bind_material, 'technique_common')
|
||||
instance_material = SubElement(technique_common, 'instance_material')
|
||||
instance_material.set('symbol', 'Material0')
|
||||
instance_material.set('target', '#Material0')
|
||||
instance_material = SubElement(technique_common, 'instance_material')
|
||||
instance_material.set('symbol', 'Material1')
|
||||
instance_material.set('target', '#Material1')
|
||||
instance_material = SubElement(technique_common, 'instance_material')
|
||||
instance_material.set('symbol', 'Material2')
|
||||
instance_material.set('target', '#Material2')
|
||||
|
||||
# xml: 5. library_visual_scenes:
|
||||
library_visual_scenes = SubElement(root, 'library_visual_scenes')
|
||||
visual_scene = SubElement(library_visual_scenes, 'visual_scene')
|
||||
visual_scene.set('id', '')
|
||||
visual_scene.set('name', '')
|
||||
|
||||
node = SubElement(visual_scene, 'node')
|
||||
node.set('id', 'Fbx_Root')
|
||||
node.set('name', 'Fbx_Root')
|
||||
node.set('sid', 'Fbx_Root')
|
||||
matrix = SubElement(node, 'matrix')
|
||||
matrix.set('sid', 'matrix')
|
||||
matrix.text = '1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 -1.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 1.000000'
|
||||
node = SubElement(node, 'node')
|
||||
node.set('id', 'PVcase52')
|
||||
node.set('name', 'PVcase52')
|
||||
node.set('sid', 'PVcase52')
|
||||
matrix = SubElement(node, 'matrix')
|
||||
matrix.set('sid', 'matrix')
|
||||
matrix.text = '1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 1.000000'
|
||||
|
||||
extra = SubElement(visual_scene, 'extra')
|
||||
technique = SubElement(extra, 'technique')
|
||||
technique.set('profile', 'MAX3D')
|
||||
frame_rate = SubElement(technique, 'frame_rate')
|
||||
frame_rate.text = '30.000000'
|
||||
technique = SubElement(extra, 'technique')
|
||||
technique.set('profile', 'FCOLLADA')
|
||||
start_time = SubElement(technique, 'start_time')
|
||||
start_time.text = '0.000000'
|
||||
end_time = SubElement(technique, 'end_time')
|
||||
end_time.text = '1.000000'
|
||||
|
||||
# xml: 6. scene:
|
||||
scene = SubElement(root, 'scene')
|
||||
instance = SubElement(scene, 'instance_visual_scene')
|
||||
instance.set('url', '#')
|
||||
|
||||
full_list_of_objects = FreeCAD.ActiveDocument.Objects
|
||||
|
||||
# CASO 1 - FRAMES:
|
||||
frameType = site.Frames
|
||||
frame_setup = {"type": [],
|
||||
"footprint": []}
|
||||
for obj in frameType:
|
||||
frame_setup["type"] = obj
|
||||
frame_setup["footprint"] = ""
|
||||
|
||||
objind = 0
|
||||
# TODO: revisar
|
||||
for type in frameType:
|
||||
isTracker = "tracker" in type.Proxy.Type.lower()
|
||||
#TODO: Sólo para los proyectos de NAcho. Borrar
|
||||
isTracker = False
|
||||
|
||||
objectlist = FreeCAD.ActiveDocument.findObjects(Name="Tracker")
|
||||
tmp = []
|
||||
for obj in objectlist:
|
||||
if obj.Name.startswith("TrackerSetup"):
|
||||
continue
|
||||
else:
|
||||
tmp.append(obj)
|
||||
objectlist = tmp.copy()
|
||||
|
||||
for obj in objectlist:
|
||||
if obj.Setup == type:
|
||||
findex = numpy.array([])
|
||||
|
||||
modules = obj.Setup.Shape.SubShapes[0].SubShapes[0]
|
||||
pts = []
|
||||
for i in range(4):
|
||||
pts.append(modules.BoundBox.getPoint(i))
|
||||
|
||||
# temp -----
|
||||
if obj.Tilt.Value != 0:
|
||||
zz = int(pts[0].z) - (obj.Setup.MainBeamHeight.Value / 2 + obj.Setup.BeamHeight.Value)
|
||||
for p in pts:
|
||||
p.z -= zz
|
||||
new_shape = Part.Face(Part.makePolygon(pts))
|
||||
new_shape.Placement.Rotation.setEulerAngles("XYZ", obj.Tilt.Value, 0, 0)
|
||||
pts = []
|
||||
for ver in new_shape.Vertexes:
|
||||
p = ver.Point
|
||||
p.z += zz
|
||||
pts.append(p)
|
||||
# end temp -----
|
||||
|
||||
new_shape = Part.Face(Part.makePolygon(pts))
|
||||
new_shape.Placement = obj.Placement.copy()
|
||||
m = Mesh.Mesh(triangulate(new_shape))
|
||||
centers = []
|
||||
|
||||
if isTracker:
|
||||
minLengths = []
|
||||
for ed in new_shape.Edges:
|
||||
minLengths.append(ed.Length)
|
||||
minLength = min(minLengths)
|
||||
for ed in new_shape.Edges:
|
||||
if ed.Length == minLength:
|
||||
centers.append(ed.CenterOfMass)
|
||||
if m:
|
||||
Topology = m.Topology
|
||||
|
||||
# 1. vertex indices
|
||||
vindex = numpy.empty(len(Topology[0]) * 3)
|
||||
for i in range(len(Topology[0])):
|
||||
v = Topology[0][i]
|
||||
vindex[list(range(i * 3, i * 3 + 3))] = (-(v.x - center.x) * scale, (v.z - center.z) * scale,
|
||||
(v.y - center.y) * scale)
|
||||
|
||||
# 2. face indices
|
||||
findex = numpy.empty(len(Topology[1]) * 3, numpy.int64)
|
||||
for i in range(len(Topology[1])):
|
||||
f = Topology[1][i]
|
||||
findex[list(range(i * 3, i * 3 + 3))] = (f[0], f[1], f[2])
|
||||
|
||||
add_geometry(0, vindex, findex, objind, centers if isTracker else None)
|
||||
objind += 1
|
||||
|
||||
# CASE 2: Shadow objects
|
||||
#objectlist = FreeCAD.ActiveDocument.findObjects(Label = "Tree") # TODO: Cambiar label por name
|
||||
objectlist=[]
|
||||
for obj in FreeCAD.ActiveDocument.Objects:
|
||||
if obj.Name.startswith("Tracker"):
|
||||
continue
|
||||
else:
|
||||
objectlist.append(obj)
|
||||
objind = 0
|
||||
|
||||
for obj in objectlist:
|
||||
findex = numpy.array([])
|
||||
m = None
|
||||
if obj.isDerivedFrom("Part::Feature"):
|
||||
new_shape = obj.Shape.copy()
|
||||
new_shape.Placement = obj.getGlobalPlacement()
|
||||
m = Mesh.Mesh(triangulate(new_shape))
|
||||
elif obj.isDerivedFrom("Mesh::Feature"):
|
||||
m = obj.Mesh
|
||||
elif obj.isDerivedFrom("App::Part"):
|
||||
for child in obj.OutList:
|
||||
objectlist.append(child)
|
||||
continue
|
||||
else:
|
||||
continue
|
||||
|
||||
if m:
|
||||
Topology = m.Topology
|
||||
# vertex indices
|
||||
vindex = numpy.empty(len(Topology[0]) * 3)
|
||||
for i in range(len(Topology[0])):
|
||||
v = Topology[0][i]
|
||||
vindex[list(range(i * 3, i * 3 + 3))] = (-(v.x - center.x) * scale, (v.z - center.z) * scale,
|
||||
(v.y - center.y) * scale)
|
||||
|
||||
# face indices
|
||||
findex = numpy.empty(len(Topology[1]) * 3, numpy.int64)
|
||||
for i in range(len(Topology[1])):
|
||||
f = Topology[1][i]
|
||||
findex[list(range(i * 3, i * 3 + 3))] = (f[0], f[1], f[2])
|
||||
|
||||
add_geometry(1, vindex, findex, objind)
|
||||
objind += 1
|
||||
|
||||
|
||||
# CASE 3: Terrain
|
||||
# TODO: ver si se puede partir en varias mesh para que trabaje más rápido
|
||||
if exportTerrain:
|
||||
m = terrain
|
||||
if m:
|
||||
Topology = m.Topology
|
||||
# Facets = m.Facets
|
||||
|
||||
# vertex indices
|
||||
vindex = numpy.empty(len(Topology[0]) * 3)
|
||||
for i in range(len(Topology[0])):
|
||||
v = Topology[0][i]
|
||||
vindex[list(range(i * 3, i * 3 + 3))] = (-v.x * scale, v.z * scale, v.y * scale)
|
||||
|
||||
# face indices
|
||||
findex = numpy.empty(len(Topology[1]) * 3, numpy.int64)
|
||||
for i in range(len(Topology[1])):
|
||||
f = Topology[1][i]
|
||||
findex[list(range(i * 3, i * 3 + 3))] = (f[0], f[1], f[2])
|
||||
|
||||
add_geometry(2, vindex, findex)
|
||||
|
||||
# xml: 5. library_visual_scenes: ¿¿¿¿¿???????
|
||||
'''
|
||||
instance_geometry = SubElement(node, 'instance_geometry')
|
||||
instance_geometry.set('url', 'TerrainMesh{0}'.format(0))
|
||||
|
||||
bind_material = SubElement(instance_geometry, 'bind_material')
|
||||
technique_common = SubElement(bind_material, 'technique_common')
|
||||
instance_material = SubElement(technique_common, 'instance_material')
|
||||
instance_material.set('symbol', 'Material0')
|
||||
instance_material.set('target', '#Material0')
|
||||
instance_material = SubElement(technique_common, 'instance_material')
|
||||
instance_material.set('symbol', 'Material1')
|
||||
instance_material.set('target', '#Material1')
|
||||
instance_material = SubElement(technique_common, 'instance_material')
|
||||
instance_material.set('symbol', 'Material2')
|
||||
instance_material.set('target', '#Material2')
|
||||
'''
|
||||
|
||||
extra = SubElement(node, 'extra')
|
||||
technique = SubElement(extra, 'technique')
|
||||
technique.set('profile', 'FCOLLADA')
|
||||
visibility = SubElement(technique, 'visibility')
|
||||
visibility.text = '1.000000'
|
||||
|
||||
|
||||
# save the file:
|
||||
st = prettify(root)
|
||||
#print(st)
|
||||
f = open(filename, "w")
|
||||
f.write(st)
|
||||
f.close()
|
||||
FreeCAD.Console.PrintMessage("Se ha generado correctamente el archivo PVC: ", filename)
|
||||
return True
|
||||
|
||||
def prettify(elem):
|
||||
""" Return a pretty-printed XML string for the Element. """
|
||||
|
||||
from xml.etree import ElementTree
|
||||
from xml.dom import minidom
|
||||
|
||||
rough_string = ElementTree.tostring(elem, 'utf-8')
|
||||
reparsed = minidom.parseString(rough_string)
|
||||
return reparsed.toprettyxml(indent=" ")
|
||||
|
||||
def exportToH2P(path): # sólo válido para mesas
|
||||
filename = path + ".h2p"
|
||||
f2 = '{:.2f}'
|
||||
f3 = '{:.3f}'
|
||||
|
||||
st = 'START\n'
|
||||
# TODO: hacer un bucle para cada tipo-tamaño de estructura.
|
||||
# posible solucción: un primer bucle para identificar los tipos-tamaños de estructura
|
||||
#FreeCAD.ActiveDocument.findObjects
|
||||
#FreeCAD.ActiveDocument.Objects
|
||||
|
||||
objects = FreeCAD.ActiveDocument.findObjects(Name="Tracker")
|
||||
grouptype = []
|
||||
#for obj in objects:
|
||||
grouptype.append(objects[0])
|
||||
|
||||
for type in grouptype:
|
||||
st += 'TABLE\n' \
|
||||
'10\n'
|
||||
st += f3.format(type.Width.Value) + ',' + f3.format(type.Length.Value) + ',' + \
|
||||
f3.format(0) + ',' + f3.format(0) + ',' + f3.format(0) + ',' + f3.format(0) + "\n"
|
||||
#'#{ f3 %pvsyst.ilb.to_mm },#{f3 %pvsyst.irb.to_mm},#{f3 %pvsyst.itb.to_mm},' \
|
||||
#'#{f3 %pvsyst.ibb.to_mm}\n'
|
||||
st += '20\n'
|
||||
st += str(int(type.ModulesCols.Value)) + ',' + str(int(type.ModulesRows.Value)) + ',' + \
|
||||
str(type.ModuleColGap.Value) + ',' + str(type.ModuleRowGap.Value) + ',' + '30\n'
|
||||
st += '30\n'
|
||||
st += '1,' + f3.format(type.ModuleWidth.Value) + ',' + f3.format(type.ModuleHeight.Value) + ',' + \
|
||||
f3.format(type.ModuleThick.Value) + ',' + f2.format(450) + '\n' #f2.format(type.ModulePower.Value) + '\n'
|
||||
|
||||
# cornerdown = find_component_sizes(group.cdef)[1]
|
||||
# pvorigin = Geom::Point3d.new(cornerdown.x, cornerdown.y, 0)
|
||||
# group.instances.each{ | ins | str += pvsyst_insert(ins, pvorigin)}
|
||||
|
||||
for obj in objects:
|
||||
if obj.CloneOf == type:
|
||||
st += H2PInsert(obj)
|
||||
|
||||
## TODO: Bucle para buscar objetos que den sombra y el terreno. Todos llaman a H2PMesh
|
||||
mesh = FreeCAD.ActiveDocument.getObjectsByLabel('Surface')[0].Mesh
|
||||
st += H2PMesh(mesh, False)
|
||||
st += "END\n"
|
||||
|
||||
# save the file:
|
||||
f = open(filename, "w")
|
||||
f.write(st)
|
||||
f.close()
|
||||
FreeCAD.Console.PrintMessage("Se ha generado el archivo PVC: ", filename)
|
||||
return True
|
||||
|
||||
def H2PInsert(obj):
|
||||
f3 = '{:.3f}'
|
||||
f2 = '{:.2f}'
|
||||
scale = 0.001 ## ver como se puede hacer para que sea general. Pasar de mm a m
|
||||
|
||||
st = 'INSERT\n' \
|
||||
'10\n'
|
||||
st += f3.format(obj.Placement.Base.x * scale) + ',' + f3.format(obj.Placement.Base.y * scale) + ',' + \
|
||||
f3.format((obj.Placement.Base.z + obj.PoleLength.Value - obj.RammingDeep.Value + 1000) * scale) + '\n'
|
||||
st += '50\n'
|
||||
st += f2.format(-obj.Placement.Rotation.toEuler()[0]) + '\n'
|
||||
st += '55\n'
|
||||
st += f2.format(obj.Placement.Rotation.toEuler()[1]) + '\n'
|
||||
st += '56\n'
|
||||
st += f2.format(obj.Placement.Rotation.toEuler()[2]) + '\n'
|
||||
|
||||
return st
|
||||
|
||||
def H2PMesh(mesh, type):
|
||||
scale = 0.001 ## ver como se puede hacer para que sea general. Pasar de mm a m
|
||||
|
||||
f3 = '{:.3f}'
|
||||
st = ''
|
||||
if type:
|
||||
st = 'ShadowObject\nFence\n'
|
||||
else:
|
||||
st = 'DGM\n'
|
||||
|
||||
for face in mesh.Facets:
|
||||
p1 = face.Points[0]
|
||||
p2 = face.Points[1]
|
||||
p3 = face.Points[2]
|
||||
|
||||
st += f3.format(p1[0] * scale) + "," + f3.format(p1[1] * scale) + "," + f3.format(p1[2] * scale) + ";"
|
||||
st += f3.format(p2[0] * scale) + "," + f3.format(p2[1] * scale) + "," + f3.format(p2[2] * scale) + ";"
|
||||
st += f3.format(p3[0] * scale) + "," + f3.format(p3[1] * scale) + "," + f3.format(p3[2] * scale) + "\n"
|
||||
|
||||
return st
|
||||
|
||||
class _PVSystTaskPanel:
|
||||
|
||||
def __init__(self):
|
||||
self.form = FreeCADGui.PySideUic.loadUi(os.path.dirname(__file__) + "/exportPVSyst.ui")
|
||||
self.form = self.form
|
||||
|
||||
def show(self):
|
||||
# self.form.setWindowModality(Qt.WindowModal)
|
||||
self.form.show()
|
||||
|
||||
def accept(self):
|
||||
import datetime
|
||||
x = datetime.datetime.now()
|
||||
date = x.strftime("%y%m%d%H%M%S")
|
||||
overwrite = True
|
||||
|
||||
path = os.path.join(os.path.dirname(FreeCAD.ActiveDocument.FileName), "outputs", "PVSyst")
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
name = FreeCAD.ActiveDocument.Label
|
||||
if not overwrite:
|
||||
name = date + "-" + name
|
||||
filename = os.path.join(path, name)
|
||||
|
||||
#if self.form.cbDAE.isChecked():
|
||||
# exportToDAE(filename)
|
||||
|
||||
if self.form.cbPVC.isChecked():
|
||||
exportToPVC(filename, self.form.cbTerrain.isChecked())
|
||||
|
||||
if self.form.cbH2P.isChecked():
|
||||
exportToH2P(filename)
|
||||
|
||||
FreeCADGui.Control.closeDialog()
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
FreeCADGui.Control.closeDialog()
|
||||
return True
|
||||
|
||||
class _CommandExportToPVSyst:
|
||||
"Export to PVSyst"
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap': str(os.path.join(DirIcons, "PVsyst.png")),
|
||||
'Accel': "E, P",
|
||||
'MenuText': QT_TRANSLATE_NOOP("Outputs", "Export to PVSyst"),
|
||||
'ToolTip': QT_TRANSLATE_NOOP("Outputs", "Exportar a PVSyst")}
|
||||
|
||||
def Activated(self):
|
||||
taskd = _PVSystTaskPanel()
|
||||
# taskd.show()
|
||||
FreeCADGui.Control.showDialog(taskd)
|
||||
|
||||
def IsActive(self):
|
||||
if FreeCAD.ActiveDocument:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
FreeCADGui.addCommand('ExportToPVSyst', _CommandExportToPVSyst())
|
||||
Reference in New Issue
Block a user