fig2poly.cc File Reference
#include <sstream>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdlib>

Functions

void ignore_ints (std::ifstream &fig_file, const unsigned &nints=1)
 Helper function – ignores specified number of ints from input stream. More...
 
void ignore_floats (std::ifstream &fig_file, const unsigned &nfloats=1)
 Helper function – ignores specified number of floats from input stream. More...
 
void ignore_ints (std::istream &fig_file, const unsigned &nints=1)
 Helper function – ignores specified number of floats from stringstream. More...
 
void ignore_floats (std::istream &fig_file, const unsigned &nfloats=1)
 Helper function – ignores specified number of floats from stringstream. More...
 
int main (int argc, char *argv[])
 

Function Documentation

◆ ignore_floats() [1/2]

void ignore_floats ( std::ifstream &  fig_file,
const unsigned nfloats = 1 
)

Helper function – ignores specified number of floats from input stream.

50  {
51  float dummy;
52  for (unsigned i=0;i<nfloats;i++)
53  {
54  fig_file >> dummy;
55  }
56  }
int i
Definition: BiCGSTAB_step_by_step.cpp:9

References i.

Referenced by main().

◆ ignore_floats() [2/2]

void ignore_floats ( std::istream &  fig_file,
const unsigned nfloats = 1 
)

Helper function – ignores specified number of floats from stringstream.

70  {
71  float dummy;
72  for (unsigned i=0;i<nfloats;i++)
73  {
74  fig_file >> dummy;
75  }
76  }

References i.

◆ ignore_ints() [1/2]

void ignore_ints ( std::ifstream &  fig_file,
const unsigned nints = 1 
)

Helper function – ignores specified number of ints from input stream.

40  {
41  int dummy;
42  for (unsigned i=0;i<nints;i++)
43  {
44  fig_file >> dummy;
45  }
46  }

References i.

Referenced by main().

◆ ignore_ints() [2/2]

void ignore_ints ( std::istream &  fig_file,
const unsigned nints = 1 
)

Helper function – ignores specified number of floats from stringstream.

60  {
61  int dummy;
62  for (unsigned i=0;i<nints;i++)
63  {
64  fig_file >> dummy;
65  }
66  }

References i.

◆ main()

int main ( int argc  ,
char argv[] 
)

///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// fig2poly: Converts xfig drawings into input files for Jonathan Shewczuk's triangle code.

91 {
92 
93  // Check number of command line arguments: Need exactly one.
94  if (argc!=2)
95  {
96  cout << "Wrong number of command line arguments. " << std::endl;
97  cout << "Must specify the single file name that " << std::endl;
98  cout << "specifies the xfig file" << std::endl;
99  exit(1);
100  }
101 
102  // Open fig file
103  ifstream xfig_file(argv[1]);
104 
105  // Storage for the coordinates of the points on the various
106  // boundaries: boundary_point_coords[i_boundary][i_point][i_coordinate]
107  vector<vector<vector<double> > > boundary_point_coords;
108 
109  // Storage for the coordinates of the points in the
110  // holes: hole_coords[i_hole][i_coordinate]
111  vector<vector<double> > hole_coords;
112 
113  // Temporary storage for input string
114  std::string input_string;
115 
116  // *.fig file must conform to "Fig Format 3.2"
117  // See http://en.wikipedia.org/wiki/Xfig [xfig is no
118  // longer actively maintained (listed as dormant)
119  // which is a shame. The user manual used to be at
120  // http : // www . xfig . org / userman
121  // (minus the spaces obviously -- added to stop the broken
122  // link checker from complaining...)]
123 
124  // Read initial comment lines
125  //---------------------------
126 
127  // First line contains the version of xfig format
128  getline(xfig_file,input_string,'\n');
129  std::string version_string=input_string.substr(0,8);
130  if (version_string!="#FIG 3.2")
131  {
132  std::cout << "*.fig file is in the wrong format!\n"
133  << "It must conform to Fig Format 3.2\n"
134  << "but the version string is: " << version_string
135  << std::endl;
136  exit(1);
137  }
138 
139 
140  // Ignore a few other irrelevant header lines
141  for (unsigned i=0;i<7;i++)
142  {
143  // Read entire line
144  getline(xfig_file,input_string,'\n');
145  }
146 
147  // The next two ints specify the resolution and some flag to do with the
148  // coordinate system.
149  int scaling_factor,dummy;
150  xfig_file >> scaling_factor;
151  xfig_file >> dummy;
152 
153 
154 
155  // Keep looping over objects and brutally write all lines into stringstream
156  //-------------------------------------------------------------------------
157  std::ostringstream buffer;
158  while (!xfig_file.eof())
159  {
160  // Read the line
161  getline(xfig_file,input_string,'\n');
162  // Copy into buffer but do not end a "\n" at the end -- this will allow
163  // us to detect the end of the data (the original fig file contains
164  // a newline on the last line and this confuses the read loop)
165  buffer << " " << input_string;
166  }
167 
168  // Remove trailing space
169  std::string aux_string(buffer.str(),0,buffer.str().length()-1);
170 
171  // Convert buffer into input string stream
172  std::istringstream buffer2(aux_string);
173 
174  // Keep looping over objects
175  //--------------------------
176  while (!buffer2.eof())
177  {
178 
179  // Now read the object identifier (first entry in object line)
180  int object_id;
181  buffer2 >> object_id;
182 
183 
184  // Circle/ellipse object id 2
185  //---------------------------
186  if (object_id==1)
187  {
188  cout
189  << "I've read a circle -- it will be used as a hole identifier."
190  << std::endl;
191 
192  // Ignore what's not needed
193  ignore_ints(buffer2,8);
194  ignore_floats(buffer2,1);
195  ignore_ints(buffer2,1);
196  ignore_floats(buffer2,1);
197 
198 
199  // Here's a new point in a hole
200  vector<double> new_hole(2);
201 
202  // Now read in the x/y coordinate of centre
203  int ix,iy;
204  buffer2 >> ix;
205  buffer2 >> iy;
206 
207  // Convert to scaled float
208  new_hole[0]=double(ix)/double(scaling_factor);
209  new_hole[1]=double(iy)/double(scaling_factor);
210 
211  // Stick into big container
212  hole_coords.push_back(new_hole);
213 
214  // Ignore the remaining 6 ints
215  ignore_ints(buffer2,6);
216 
217  }
218  // Polyline has object id 2
219  //-------------------------
220  else if (object_id==2)
221  {
222  cout << "I've read a polyline -- it defines a boundary."
223  << std::endl;
224 
225  // Next line: Type of polyline
226  int sub_type;
227  buffer2 >> sub_type;
228 
229  // Can only handle actual polylines (rather than polygons or boxes)
230  if (sub_type==1)
231  {
232  // Ignore what's not needed
233  ignore_ints(buffer2,7);
234  ignore_floats(buffer2,1);
235  ignore_ints(buffer2,5);
236 
237  // Finally: Number of points on line:
238  int npoints;
239  buffer2 >> npoints;
240 
241  // Here's another boundary
242  vector<vector<double> > new_boundary(npoints);
243 
244  // Now read in the x/y coordinates
245  int ix,iy;
246  for (unsigned i=0;i<unsigned(npoints);i++)
247  {
248  buffer2 >> ix;
249  buffer2 >> iy;
250  new_boundary[i].resize(2);
251  new_boundary[i][0]=double(ix)/double(scaling_factor);
252  new_boundary[i][1]=double(iy)/double(scaling_factor);
253  }
254 
255  // Stick into big container
256  boundary_point_coords.push_back(new_boundary);
257  }
258  else
259  {
260  std::cout
261  << "Can't handle this sub-type of polygon: " << sub_type << std::endl
262  << "Can only do open polylines -- no closed boxes, etc. " << std::endl;
263  exit(1);
264  }
265 
266  }
267  // Other object IDs can't be handled
268  //----------------------------------
269  else
270  {
271  std::cout
272  << "Can't handle this object id: " << object_id
273  << "\nMake sure your figure only contains: \n"
274  << "- polylines (which define boundaries) \n"
275  << "- circles/ellipses (which define hole points) \n"
276  << "Also make sure that you've broken up any\n"
277  << "compound objects. " << std::endl;
278  exit(1);
279  }
280 
281  } // end of loop over objects
282 
283 
284 
285  // Get ready for output
286  //---------------------
287 
288  // Get total number of points on all boundaries
289  unsigned total_npoints=0;
290  unsigned nbound=boundary_point_coords.size();
291  for (unsigned b=0;b<nbound;b++)
292  {
293  unsigned npoints=boundary_point_coords[b].size();
294  total_npoints+=npoints;
295  }
296 
297  // Output points in pslg format
298  //-----------------------------
299  char filename[100];
300  sprintf(filename,"%s.poly",argv[1]);
301  ofstream poly_file(filename);
302  {
303  poly_file
304  << total_npoints
305  << " 2 0 0 # of pts, 2D, no attributes or boundary markers for points"
306  << std::endl;
307  }
308 
309 
310  unsigned count=1;
311  for (unsigned b=0;b<nbound;b++)
312  {
313  unsigned npoints=boundary_point_coords[b].size();
314  for (unsigned i=0;i<npoints;i++)
315  {
316  // Global node number, x, y, [additional comment that helps
317  // to identify which boundary the node is located on -- mainly
318  // for debugging
319  poly_file << count << " " << boundary_point_coords[b][i][0]
320  << " " << boundary_point_coords[b][i][1]
321  << " # [located on boundary " << b << "]" << std::endl;
322 
323  // Increment counter
324  count++;
325  }
326  }
327 
328  // End of point block
329  poly_file << "# END_OF_NODE_BLOCK" << std::endl;
330 
331  // Output boundaries in poly format
332  //---------------------------------
333 
334 
335  // Number of edges, number of boundaries
336  poly_file << total_npoints << " 1 " //<< nbound
337  << " # [number of segments (i.e. boundary edges),"
338  << " flag for using boundary markers here]"
339  << std::endl;
340 
341 
342  // Set segment bounded flag:
343 
344  // Initialise counters
345  unsigned edge_count=1;
346  unsigned npoints_in_all_previous_boundaries=0;
347 
348  // Loop over boundaries
349  for (unsigned b=0;b<nbound;b++)
350  {
351  unsigned npoints=boundary_point_coords[b].size();
352  // Up to the last point, each point on the boundary connects
353  // to the next one
354  for (unsigned i=0;i<npoints-1;i++)
355  {
356  // Edge number, first node index, second node index (in global
357  // node numbering scheme above), boundary id
358  poly_file << edge_count << " "
359  << npoints_in_all_previous_boundaries+i+1 << " "
360  << npoints_in_all_previous_boundaries+i+2 << " "
361  << " " << b+1 << std::endl;
362 
363  // Increment counter
364  edge_count++;
365  }
366 
367  // Final point connects back to the first one
368  // Segment number, first node index, second node index (in global
369  // node numbering scheme above), boundary id
370  poly_file << edge_count << " "
371  << npoints_in_all_previous_boundaries+npoints << " "
372  << npoints_in_all_previous_boundaries+1 << " "
373  << " " << b+1 << std::endl;
374 
375  // Bump up counter
376  edge_count++;
377 
378  // Increment counter for points located in all previous boundaries
379  npoints_in_all_previous_boundaries+=npoints;
380  }
381 
382  // End of segment block
383  poly_file << "# END_OF_SEGMENT_BLOCK" << std::endl;
384 
385 
386  // Output "points in hole" in pslg format
387  //---------------------------------------
388 
389  // Vector of points that are located in the holes in the domain
390  // [NOTE: Historically (and in Gemma's thesis) this used to be
391  // called, somewhat confusingly, Hole_ID_pt]
392  vector<vector<double> > Point_in_hole;
393 
394  // Number of holes
395  unsigned nhole=hole_coords.size();
396  Point_in_hole.resize(nhole);
397  unsigned hole_count=1;
398  poly_file << nhole << " # [number of holes] " << std::endl;
399  for (unsigned i=0;i<nhole;i++)
400  {
401  poly_file << hole_count << " "
402  << hole_coords[i][0] << " "
403  << hole_coords[i][1] << std::endl;
404 
405  //Add the point to the vector of hole IDs
406  Point_in_hole[i].resize(2);
407  Point_in_hole[i][0]= hole_coords[i][0];
408  Point_in_hole[i][1]= hole_coords[i][1];
409 
410  // Increment counter
411  hole_count++;
412  }
413 
414 
415  // End of hole block
416  poly_file << "# END_OF_HOLE_BLOCK" << std::endl;
417 
418  poly_file.close();
419 
420 
421 }
Scalar * b
Definition: benchVecAdd.cpp:17
void ignore_ints(std::ifstream &fig_file, const unsigned &nints=1)
Helper function – ignores specified number of ints from input stream.
Definition: fig2poly.cc:39
void ignore_floats(std::ifstream &fig_file, const unsigned &nfloats=1)
Helper function – ignores specified number of floats from input stream.
Definition: fig2poly.cc:49
string filename
Definition: MergeRestartFiles.py:39
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286

References b, MergeRestartFiles::filename, i, ignore_floats(), ignore_ints(), and oomph::Global_string_for_annotation::string().