/*
* Copyright (C) 2010 Sebastian Held (sebastian.held@gmx.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "CSPrimBox.h"
#include "CSPrimCylinder.h"
#include "CSPrimPolygon.h"
#include "CSPrimCurve.h"
#include "CSPrimWire.h"
#include "QVTKStructure.h"
#include "QCSXCAD.h"
#include "export_pov.h"
export_pov::export_pov( QCSXCAD *CSX ) : m_CSX(CSX)
{
m_epsilon = 1; // FIXME this should be small compared to any other linear dimension of any object in the scene
}
void export_pov::save( QString filename )
{
QFile file( filename );
if (!file.open( QFile::WriteOnly )) {
QMessageBox::warning( m_CSX, QObject::tr("save failed"), QObject::tr("Cannot save to the file %1").arg(filename), QMessageBox::Ok );
return;
}
QTextStream stream(&file);
stream.setCodec( "UTF-8" );
stream << "// povray-file exported by QCSXCAD" << endl;
stream << "// render with:" << endl;
stream << "// povray -W640 -H480 +A " << QFileInfo(filename).fileName() << endl;
stream << endl;
stream << "#declare TRANSPARENT = off; // if on, also use the \"+ua\" command line flag" << endl;
stream << endl;
stream << "#include \"colors.inc\"" << endl;
stream << "#include \"metals.inc\"" << endl;
stream << "#include \"textures.inc\"" << endl;
stream << "#include \"transforms.inc\"" << endl;
stream << "background { color rgb<1.000000,1.000000,1.000000> #if(TRANSPARENT) transmit 1.0 #end }" << endl;
// export material
std::vector properties = m_CSX->GetPropertyByType( CSProperties::MATERIAL );
export_properties( stream, properties, "pigment { color rgbt <0.000, 0.533, 0.800,0.0> } finish { diffuse 0.6 }" );
// export metal
properties = m_CSX->GetPropertyByType( CSProperties::METAL );
export_properties( stream, properties, "texture { Copper_Metal }" );
// create camera
stream << get_camera() << endl;
// create light
stream << get_light() << endl;
stream.flush();
file.close();
}
void export_pov::export_properties( QTextStream &stream, std::vector properties, QString default_obj_modifier )
{
foreach( CSProperties* prop, properties )
{
int size = prop->GetQtyPrimitives();
for( int i=0; iGetPrimitive(i);
if (prim->GetType() == CSPrimitives::BOX)
{
CSPrimBox *box = prim->ToBox();
double start[] = {box->GetCoord(0),box->GetCoord(2),box->GetCoord(4)};
double stop[] = {box->GetCoord(1),box->GetCoord(3),box->GetCoord(5)};
export_box( stream, start, stop, default_obj_modifier );
}
else if (prim->GetType() == CSPrimitives::POLYGON)
{
CSPrimPolygon *polygon = prim->ToPolygon();
size_t count = -1;
double *array = 0;
array = polygon->GetAllCoords( count, array );
int normDir = polygon->GetNormDir();
double elevation = polygon->GetElevation();
export_polygon( stream, count, array, elevation, normDir, default_obj_modifier );
}
else if (prim->GetType() == CSPrimitives::CYLINDER)
{
CSPrimCylinder *primitive = prim->ToCylinder();
double start[] = {primitive->GetCoord(0),primitive->GetCoord(2),primitive->GetCoord(4)};
double stop[] = {primitive->GetCoord(1),primitive->GetCoord(3),primitive->GetCoord(5)};
double radius = primitive->GetRadius();
export_cylinder( stream, start, stop, radius, default_obj_modifier );
}
else if (prim->GetType() == CSPrimitives::WIRE)
{
CSPrimWire *primitive = prim->ToWire();
double radius = primitive->GetWireRadius();
size_t count = primitive->GetNumberOfPoints();
double *array = new double[count*3];
for (unsigned int i=0; iGetPoint(i,array+i*3, CARTESIAN);
export_wire( stream, count, array, radius, default_obj_modifier );
delete[] array;
}
else if (prim->GetType() == CSPrimitives::CURVE)
{
CSPrimCurve *primitive = prim->ToCurve();
double radius = m_epsilon;
size_t count = primitive->GetNumberOfPoints();
double *array = new double[count*3];
for (unsigned int i=0; iGetPoint(i,array+i*3, CARTESIAN);
export_wire( stream, count, array, radius, default_obj_modifier );
delete[] array;
}
}
}
}
void export_pov::export_box( QTextStream &stream, double start[3], double stop[3], QString object_modifier )
{
for (int i=0; i<3; i++)
if (start[i] == stop[i]) {
// 2D box
// povray supports 2D polygons, but has no priority concept, therefore we use the box primitive
start[i] -= m_epsilon;
stop[i] += m_epsilon;
}
QString box = "box { %1, %2 %3 }";
box = box.arg(pov_vect(start),pov_vect(stop),object_modifier);
stream << box << endl;
}
void export_pov::export_polygon( QTextStream &stream, size_t count, double *array, double elevation, int normDir, QString object_modifier )
{
UNUSED(normDir);
Q_ASSERT((count%2)==0);
count = count / 2; // now count is the number of 2D-vectors
if (count < 2)
return;
elevation = -elevation;
//NormDir = [CSX_polygon.NormDir.ATTRIBUTE.X CSX_polygon.NormDir.ATTRIBUTE.Y CSX_polygon.NormDir.ATTRIBUTE.Z];
QString str = "prism { linear_spline linear_sweep %1, %2, %3";
str = str.arg(elevation - m_epsilon).arg(elevation + m_epsilon).arg(count+1);
for (unsigned int a=0; a }";
stream << str << endl;
}
void export_pov::export_cylinder( QTextStream &stream, double start[3], double stop[3], double radius, QString object_modifier )
{
QString str = "cylinder { %1, %2, %3 %4 }";
str = str.arg(pov_vect(start)).arg(pov_vect(stop)).arg(radius).arg(object_modifier);
stream << str << endl;
}
void export_pov::export_wire( QTextStream &stream, size_t count, double *array, double radius, QString object_modifier )
{
QString str = "sphere_sweep { linear_spline, " + QString::number(count);
for (unsigned int a=0; aStructureVTK->GetVTKWidget()))->GetRenderWindow()->GetRenderers();
vtkRenderer *r = collection->GetFirstRenderer();
if (!r)
return QString();
vtkCamera *c = r->GetActiveCamera();
if (!c)
return QString();
double *pos = c->GetPosition();
// cout << "Camera position: " << pos[0] << ", " << pos[1] << ", " << pos[2] << endl;
double *focalpos = c->GetFocalPoint();
// cout << "Camera focal point: " << focalpos[0] << ", " << focalpos[1] << ", " << focalpos[2] << endl;
// double distance = c->GetDistance();
// cout << "Camera distance (position to focal point): " << distance << endl;
// double roll = c->GetRoll();
// cout << "Camera roll angle (about direction of projection): " << roll << "°" << endl;
double angle = c->GetViewAngle();
// cout << "Camera view angle: " << angle << "°" << endl;
double *up = c->GetViewUp();
// cout << "Camera up vector: " << up[0] << ", " << up[1] << ", " << up[2] << endl;
QString camera_str;
camera_str = "camera { perspective location %1 look_at %2 sky %3 right -1.33*x angle %4 }";
camera_str = camera_str.arg(pov_vect(pos),pov_vect(focalpos),pov_vect(up)).arg(angle);
return camera_str;
}
QString export_pov::get_light()
{
vtkRendererCollection* collection = ((QVTKWidget*)(m_CSX->StructureVTK->GetVTKWidget()))->GetRenderWindow()->GetRenderers();
vtkRenderer *r = collection->GetFirstRenderer();
if (!r)
return QString();
vtkCamera *c = r->GetActiveCamera();
if (!c)
return QString();
double *pos = c->GetPosition();
// double *focalpos = c->GetFocalPoint();
// double distance = c->GetDistance();
// double roll = c->GetRoll();
// double angle = c->GetViewAngle();
// double *up = c->GetViewUp();
QString light_str;
light_str = "light_source { %1, rgb <1,1,1> }";
light_str = light_str.arg(pov_vect(pos));
return light_str;
}
QString export_pov::pov_vect( double *v )
{
QString v_str = "<%1,%2,%3>";
v_str = v_str.arg(v[0]).arg(v[1]).arg(v[2]);
return v_str;
}
QString export_pov::pov_vect2( double *v )
{
QString v_str = "<%1,%2>";
v_str = v_str.arg(v[0]).arg(v[1]);
return v_str;
}