/* * 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; }