1 /**
2  *   SFCGAL
3  *
4  *   Copyright (C) 2012-2013 Oslandia <infos@oslandia.com>
5  *   Copyright (C) 2012-2013 IGN (http://www.ign.fr)
6  *
7  *   This library is free software; you can redistribute it and/or
8  *   modify it under the terms of the GNU Library General Public
9  *   License as published by the Free Software Foundation; either
10  *   version 2 of the License, or (at your option) any later version.
11  *
12  *   This library is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *   Library General Public License for more details.
16 
17  *   You should have received a copy of the GNU Library General Public
18  *   License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #ifndef _SFCGAL_IO_VTK_H_
22 #define _SFCGAL_IO_VTK_H_
23 
24 #include <iostream>
25 #include <fstream>
26 #include <sstream>
27 
28 #include <SFCGAL/Point.h>
29 #include <SFCGAL/LineString.h>
30 #include <SFCGAL/Polygon.h>
31 #include <SFCGAL/Triangle.h>
32 #include <SFCGAL/PolyhedralSurface.h>
33 #include <SFCGAL/TriangulatedSurface.h>
34 #include <SFCGAL/Solid.h>
35 #include <SFCGAL/GeometryCollection.h>
36 #include <SFCGAL/MultiPoint.h>
37 #include <SFCGAL/MultiLineString.h>
38 #include <SFCGAL/MultiPolygon.h>
39 #include <SFCGAL/MultiSolid.h>
40 
41 using namespace SFCGAL ;
42 
43 namespace SFCGAL {
44 namespace io {
45 // print each ring has a different polygon
46 inline
vtk(const Polygon & poly,const std::string & file)47 void vtk( const Polygon& poly, const std::string& file )
48 {
49     std::stringstream pointStr;
50     std::stringstream polyStr;
51     size_t numPoints=0;
52     size_t numData=0;
53 
54     for ( size_t r=0; r!=poly.numRings(); ++r ) {
55         polyStr << poly.ringN( r ).numPoints();
56 
57         for ( size_t p=0; p!=poly.ringN( r ).numPoints(); ++p ) {
58             pointStr << poly.ringN( r ).pointN( p ).x() << " " << poly.ringN( r ).pointN( p ).y() << " " << poly.ringN( r ).pointN( p ).z() << "\n";
59             polyStr << " " << numPoints;
60             ++numPoints;
61             ++numData;
62         }
63 
64         ++numData;
65         polyStr << "\n";
66     }
67 
68     std::ofstream out( file.c_str() );
69     out << "# vtk DataFile Version 1.0\n"
70         << "Polygon output\n"
71         << "ASCII\n"
72         << "\n"
73         << "DATASET POLYDATA\n"
74         << "POINTS " << numPoints << " float\n"
75         << pointStr.str()
76         << "POLYGONS " << poly.numRings() << " " << numData << "\n"
77         << polyStr.str();
78 }
79 
80 template< typename MultiPolygonOrPolyhedraSurface >
vtk(const MultiPolygonOrPolyhedraSurface & multiPoly,const std::string & file)81 void vtk( const MultiPolygonOrPolyhedraSurface& multiPoly, const std::string& file )
82 {
83     std::stringstream pointStr;
84     std::stringstream polyStr;
85     size_t numPoints=0;
86     size_t numRings=0;
87     size_t numData=0;
88 
89     for ( size_t i=0; i!=multiPoly.numGeometries(); ++i ) {
90         const Polygon& poly = multiPoly.polygonN( i );
91 
92         for ( size_t r=0; r!=poly.numRings(); ++r ) {
93             polyStr << poly.ringN( r ).numPoints();
94 
95             for ( size_t p=0; p!=poly.ringN( r ).numPoints(); ++p ) {
96                 pointStr << poly.ringN( r ).pointN( p ).x() << " " << poly.ringN( r ).pointN( p ).y() << " " << poly.ringN( r ).pointN( p ).z() << "\n";
97                 polyStr << " " << numPoints;
98                 ++numPoints;
99                 ++numData;
100             }
101 
102             ++numData;
103             ++numRings;
104             polyStr << "\n";
105         }
106     }
107 
108     std::ofstream out( file.c_str() );
109     out << "# vtk DataFile Version 1.0\n"
110         << "Polygon output\n"
111         << "ASCII\n"
112         << "\n"
113         << "DATASET POLYDATA\n"
114         << "POINTS " << numPoints << " float\n"
115         << pointStr.str()
116         << "POLYGONS " << numRings << " " << numData << "\n"
117         << polyStr.str();
118 }
119 
120 inline
vtk(const Triangle & tri,const std::string & file)121 void vtk( const Triangle& tri, const std::string& file )
122 {
123     vtk( tri.toPolygon(), file );
124 }
125 
126 inline
vtk(const TriangulatedSurface & s,const std::string & file)127 void vtk( const TriangulatedSurface& s, const std::string& file )
128 {
129     std::stringstream pointStr;
130     std::stringstream polyStr;
131     size_t numPoints=0;
132     size_t numTri=0;
133     size_t numData=0;
134 
135     for ( size_t i=0; i!=s.numTriangles(); ++i ) {
136         const Triangle& tri = s.triangleN( i );
137         polyStr << 3;
138 
139         for ( size_t p=0; p!=3; ++p ) {
140             pointStr << tri.vertex( p ).x() << " " << tri.vertex( p ).y() << " " << tri.vertex( p ).z() << "\n";
141             polyStr << " " << numPoints;
142             ++numPoints;
143             ++numData;
144         }
145 
146         ++numData;
147         ++numTri;
148         polyStr << "\n";
149     }
150 
151     std::ofstream out( file.c_str() );
152     out << "# vtk DataFile Version 1.0\n"
153         << "Polygon output\n"
154         << "ASCII\n"
155         << "\n"
156         << "DATASET POLYDATA\n"
157         << "POINTS " << numPoints << " float\n"
158         << pointStr.str()
159         << "POLYGONS " << numTri << " " << numData << "\n"
160         << polyStr.str();
161 }
162 
163 inline
vtk(const Geometry & g,const std::string & file)164 void vtk( const Geometry& g, const std::string& file )
165 {
166     switch ( g.geometryTypeId() ) {
167     case TYPE_POLYGON:
168         vtk( g.as<Polygon>(), file ) ;
169         return ;
170 
171     case TYPE_MULTIPOLYGON:
172         vtk( g.as<MultiPolygon>(), file ) ;
173         return ;
174 
175     case TYPE_TRIANGLE:
176         vtk( g.as<Triangle>(), file ) ;
177         return ;
178 
179     case TYPE_TRIANGULATEDSURFACE:
180         vtk( g.as<TriangulatedSurface>(), file ) ;
181         return ;
182 
183     case TYPE_POLYHEDRALSURFACE:
184         vtk( g.as<PolyhedralSurface>(), file ) ;
185         return ;
186 
187     case TYPE_SOLID:
188         vtk( g.as<Solid>().exteriorShell(), file ) ;
189         return ;
190 
191     case TYPE_POINT:
192     case TYPE_LINESTRING:
193     case TYPE_MULTIPOINT:
194     case TYPE_MULTILINESTRING:
195     case TYPE_MULTISOLID:
196     case TYPE_GEOMETRYCOLLECTION:
197         BOOST_THROW_EXCEPTION( NotImplementedException(
198                                    ( boost::format( "vtk(%s, file) is not implemented" ) % g.geometryType() ).str()
199                                ) );
200     }
201 }
202 }
203 }
204 
205 #endif
206