1 /*
2  * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
3  * Applied Mathematics, Norway.
4  *
5  * Contact information: E-mail: tor.dokken@sintef.no
6  * SINTEF ICT, Department of Applied Mathematics,
7  * P.O. Box 124 Blindern,
8  * 0314 Oslo, Norway.
9  *
10  * This file is part of SISL.
11  *
12  * SISL is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU Affero General Public License as
14  * published by the Free Software Foundation, either version 3 of the
15  * License, or (at your option) any later version.
16  *
17  * SISL is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Affero General Public License for more details.
21  *
22  * You should have received a copy of the GNU Affero General Public
23  * License along with SISL. If not, see
24  * <http://www.gnu.org/licenses/>.
25  *
26  * In accordance with Section 7(b) of the GNU Affero General Public
27  * License, a covered work must retain the producer line in every data
28  * file that is created or manipulated using SISL.
29  *
30  * Other Usage
31  * You can be released from the requirements of the license by purchasing
32  * a commercial license. Buying such a license is mandatory as soon as you
33  * develop commercial activities involving the SISL library without
34  * disclosing the source code of your own applications.
35  *
36  * This file may be used in accordance with the terms contained in a
37  * written agreement between you and SINTEF ICT.
38  */
39 
40 #include "GoReadWrite.h"
41 #include <vector>
42 #include <iostream>
43 #include <stdexcept>
44 #include "sisl.h"
45 
46 
47 using namespace std;
48 
49 namespace {
50     // Go-header-related info.
51     const int HEADER_SIZE = 4;
52     const int CURVE_INSTANCE_TYPE = 100;
53     const int SURFACE_INSTANCE_TYPE = 200;
54     const int POINTCLOUD_INSTANCE_TYPE = 400;
55     const int MAJOR_VERSION = 1;
56     const int MINOR_VERSION = 0;
57 
determine_go_instance_type(istream & is)58     inline int determine_go_instance_type(istream& is)
59     {
60 	int result;
61 	is >> result;
62 	for (int dummy, i = 1; i < HEADER_SIZE; ++i)
63 	    is >> dummy;
64 	return result;
65     }
66 
read_basis(istream & is,int & n,int & k,vector<double> & knots)67     inline void read_basis(istream& is, int& n, int& k, vector<double>& knots)
68     {
69 	is >> n >> k;
70 	knots.resize(n + k);
71 	for (int i = 0; i < n + k; ++i) {
72 	     is >> knots[i];
73 	}
74     }
75 
write_basis(ostream & os,const int & n,const int & k,const double * knots)76     inline void write_basis(ostream& os, const int&n, const int& k, const double* knots)
77     {
78 	os << n << ' ' << k << '\n';
79 	for (int i = 0; i < n + k; ++i) {
80 	    os << knots[i] << ' ';
81 	}
82 	os << '\n';
83     }
84 
85 
86 }; // end anonymous namespace
87 
88 //===========================================================================
readGoSurface(istream & go_stream)89 SISLSurf* readGoSurface(istream& go_stream)
90 //===========================================================================
91 {
92     if (determine_go_instance_type(go_stream) != SURFACE_INSTANCE_TYPE) {
93 	throw runtime_error("stream given to readGoSurface() does not "
94 			    "contain surface type.");
95     }
96 
97     // reading basic surface properties
98     int kind, dim, rational;
99     go_stream >> dim >> rational;
100     kind = rational ? 2 : 1;
101 
102     // reading basis information (one basis for each parameter)
103     int num_coefs_1, num_coefs_2;
104     int order_1, order_2;
105     vector<double> knots_1, knots_2;
106     read_basis(go_stream, num_coefs_1, order_1, knots_1);
107     read_basis(go_stream, num_coefs_2, order_2, knots_2);
108 
109     // reading control points
110     int coef_size = num_coefs_1 * num_coefs_2 * (rational ? dim + 1 : dim);
111     vector<double> coef(coef_size);
112     for (int i = 0; i < coef_size; ++i) {
113 	go_stream >> coef[i];
114     }
115 
116     int copy = 1; // flag that the input arrays should be _copied_
117     return newSurf(num_coefs_1,
118 		   num_coefs_2,
119 		   order_1,
120 		   order_2,
121 		   &knots_1[0],
122 		   &knots_2[0],
123 		   &coef[0],
124 		   kind,
125 		   dim,
126 		   copy);
127 }
128 
129 //===========================================================================
writeGoSurface(SISLSurf * surf,ostream & go_stream)130 void writeGoSurface(SISLSurf* surf, ostream& go_stream)
131 //===========================================================================
132 {
133     if (!surf) {
134 	throw runtime_error("zero pointer given to writeGoSurface()");
135     }
136 
137     // write standard header
138     go_stream << SURFACE_INSTANCE_TYPE << ' ' << MAJOR_VERSION << ' '
139 	      << MINOR_VERSION << " 0\n";
140 
141     // write basic surface properties
142     const int& dim = surf->idim;
143     const int rational = (surf->ikind % 2 == 0) ? 1 : 0;
144     go_stream << dim << ' ' << rational << '\n';
145 
146     // writing basis information
147     write_basis(go_stream, surf->in1, surf->ik1, surf->et1);
148     write_basis(go_stream, surf->in2, surf->ik2, surf->et2);
149 
150     // writing control points
151     int coef_size = surf->in1 * surf->in2 * (rational ? dim + 1 : dim);
152     const double* coef_pointer = rational ? surf->rcoef : surf->ecoef;
153     for (int i = 0; i < coef_size; ++i) {
154 	go_stream << coef_pointer[i] << ' ';
155     }
156     go_stream << endl;
157 }
158 
159 
160 //===========================================================================
writeGoCurve(SISLCurve * curve,std::ostream & go_stream)161 void writeGoCurve(SISLCurve* curve, std::ostream& go_stream)
162 //===========================================================================
163 {
164     if (!curve) {
165 	throw runtime_error("zero pointer given to writeGoCurve()");
166     }
167 
168     // write standard header
169     go_stream << CURVE_INSTANCE_TYPE << ' ' << MAJOR_VERSION << ' '
170 	      << MINOR_VERSION << " 0\n";
171 
172     // write basic curve properties
173     const int& dim = curve->idim;
174     const int rational = (curve->ikind % 2 == 0) ? 1 : 0;
175     go_stream << dim << ' ' << rational << '\n';
176 
177     // write bspline basis information
178     write_basis(go_stream, curve->in, curve->ik, curve->et);
179 
180     // write control points
181     int coef_size = curve->in * (rational ? (dim + 1) : dim);
182     const double* coef_pointer = rational ? curve->rcoef : curve->ecoef;
183     for (int i = 0; i < coef_size; ++i) {
184 	go_stream << coef_pointer[i] << ' ';
185     }
186     go_stream << endl;
187 }
188 
189 
190 //===========================================================================
readGoCurve(istream & go_stream)191 SISLCurve* readGoCurve(istream& go_stream)
192 //===========================================================================
193 {
194     if (determine_go_instance_type(go_stream) != CURVE_INSTANCE_TYPE) {
195 	throw runtime_error("stream given to readGoCurve() does not contain curve.");
196     }
197 
198     // reading basic curve properties
199     int kind, dim, rational;
200     go_stream >> dim >> rational;
201     kind = rational ? 2 : 1;
202 
203     // reading bspline basis information
204     int num_coefs, order;
205     vector<double> knots;
206     read_basis(go_stream, num_coefs, order, knots);
207 
208     // reading control points
209     int coef_size = num_coefs * (rational ? (dim + 1) : dim);
210     vector<double> coef(coef_size);
211     for (int i = 0; i < coef_size; ++i) {
212 	go_stream >> coef[i];
213     }
214 
215     int copy = 1; // flag that the input arrays (knots, coef) should be _copied_
216     return newCurve(num_coefs, order, &knots[0], &coef[0], kind, dim, copy);
217 
218 }
219 
220 
221 //===========================================================================
writeGoPoints(int num_points,double * coords,std::ostream & go_stream)222 void writeGoPoints(int num_points, double* coords, std::ostream& go_stream)
223 //===========================================================================
224 {
225     if (!coords) {
226 	throw runtime_error("zero coordinate pointer given to writeGoPoints.");
227     }
228     // write standard header
229     go_stream << POINTCLOUD_INSTANCE_TYPE << ' ' << MAJOR_VERSION << ' '
230 	      << MINOR_VERSION << " 4 255 255 0 255\n";
231 
232     // write the number of points
233     go_stream << num_points << '\n';
234 
235     // write point coordinates
236     for (int i = 0; i < num_points * 3; ++i) {
237 	go_stream << coords[i];
238 	if ((i+1) % 3) {
239 	    go_stream << ' ';
240 	} else {
241 	    go_stream << '\n';
242 	}
243     }
244     go_stream << endl;
245 }
246 
247 //===========================================================================
readGoPoints(std::vector<double> & coords,std::istream & go_stream)248 void readGoPoints(std::vector<double>& coords, std::istream& go_stream)
249 //===========================================================================
250 {
251     if (determine_go_instance_type(go_stream) != POINTCLOUD_INSTANCE_TYPE) {
252 	throw runtime_error("stream given to readGoPoints() does not contain pointcloud.");
253     }
254     // read away extra header information
255     for (int dummy, i = 0; i < 4; ++i) {
256 	go_stream >> dummy;
257     }
258 
259     int num_points;
260     go_stream >> num_points;
261     coords.resize(num_points * 3);
262 
263     // read point coordinates
264     for (int i = 0; i < (int)coords.size(); ++i) {
265 	go_stream >> coords[i];
266     }
267 }
268