Fix warnings on MSVC 2008 64 Bit (#470)
[geos.git] / src / io / WKTWriter.cpp
blobbe06759ba653ae68724d2a818f3600ef2b42f5f6
1 /**********************************************************************
2 * $Id$
4 * GEOS - Geometry Engine Open Source
5 * http://geos.refractions.net
7 * Copyright (C) 2011 Sandro Santilli <strk@keybit.net>
8 * Copyright (C) 2005-2006 Refractions Research Inc.
9 * Copyright (C) 2001-2002 Vivid Solutions Inc.
11 * This is free software; you can redistribute and/or modify it under
12 * the terms of the GNU Lesser General Public Licence as published
13 * by the Free Software Foundation.
14 * See the COPYING file for more information.
16 **********************************************************************
18 * Last port: io/WKTWriter.java rev. 1.34 (JTS-1.7)
20 **********************************************************************/
22 #include <geos/io/WKTWriter.h>
23 #include <geos/io/Writer.h>
24 #include <geos/io/CLocalizer.h>
25 #include <geos/geom/Coordinate.h>
26 #include <geos/geom/Point.h>
27 #include <geos/geom/LinearRing.h>
28 #include <geos/geom/LineString.h>
29 #include <geos/geom/Polygon.h>
30 #include <geos/geom/MultiPoint.h>
31 #include <geos/geom/MultiLineString.h>
32 #include <geos/geom/MultiPolygon.h>
33 #include <geos/geom/CoordinateSequence.h>
34 #include <geos/geom/PrecisionModel.h>
35 #include <geos/util/IllegalArgumentException.h>
37 #include <typeinfo>
38 #include <cstdio> // should avoid this
39 #include <string>
40 #include <sstream>
41 #include <cassert>
42 #include <cmath>
43 #include <iomanip>
45 using namespace std;
46 using namespace geos::geom;
48 namespace geos {
49 namespace io { // geos.io
51 WKTWriter::WKTWriter():
52 decimalPlaces(6),
53 isFormatted(false),
54 roundingPrecision(-1),
55 trim(false),
56 level(0),
57 defaultOutputDimension(2),
58 old3D(false)
62 /* public */
63 void
64 WKTWriter::setOutputDimension(int dims)
66 if ( dims < 2 || dims > 3 )
67 throw util::IllegalArgumentException("WKT output dimension must be 2 or 3");
68 defaultOutputDimension = dims;
71 WKTWriter::~WKTWriter() {}
73 /*static*/
74 string
75 WKTWriter::toLineString(const CoordinateSequence& seq)
77 stringstream buf(ios_base::in|ios_base::out);
78 buf << "LINESTRING ";
79 unsigned int npts = seq.getSize();
80 if ( npts == 0 )
82 buf << "EMPTY";
84 else
86 buf << "(";
87 for (unsigned int i=0; i<npts; ++i)
89 if (i) buf << ", ";
90 buf << seq.getX(i) << " " << seq.getY(i);
91 #if PRINT_Z
92 buf << seq.getZ(i);
93 #endif
95 buf << ")";
98 return buf.str();
101 /*static*/
102 string
103 WKTWriter::toLineString(const Coordinate& p0, const Coordinate& p1)
105 stringstream ret(ios_base::in|ios_base::out);
106 ret << "LINESTRING (" << p0.x << " " << p0.y;
107 #if PRINT_Z
108 ret << " " << p0.z;
109 #endif
110 ret << ", " << p1.x << " " << p1.y;
111 #if PRINT_Z
112 ret << " " << p1.z;
113 #endif
114 ret << ")";
116 return ret.str();
119 /*static*/
120 string
121 WKTWriter::toPoint(const Coordinate& p0)
123 stringstream ret(ios_base::in|ios_base::out);
124 ret << "POINT (";
125 #if PRINT_Z
126 ret << p0.x << " " << p0.y << " " << p0.z << " )";
127 #else
128 ret << p0.x << " " << p0.y << " )";
129 #endif
130 return ret.str();
133 void
134 WKTWriter::setRoundingPrecision(int p0)
136 if(p0 < -1) {
137 p0 = -1;
139 roundingPrecision = p0;
142 void
143 WKTWriter::setTrim(bool p0)
145 trim = p0;
148 string WKTWriter::write(const Geometry *geometry) {
149 Writer sw;
150 writeFormatted(geometry,false,&sw);
151 string res=sw.toString();
152 return res;
155 void WKTWriter::write(const Geometry *geometry, Writer *writer) {
156 writeFormatted(geometry, false, writer);
159 string WKTWriter::writeFormatted(const Geometry *geometry) {
160 Writer sw;
161 writeFormatted(geometry, true, &sw);
162 return sw.toString();
165 void WKTWriter::writeFormatted(const Geometry *geometry, Writer *writer) {
166 writeFormatted(geometry, true, writer);
169 void
170 WKTWriter::writeFormatted(const Geometry *geometry, bool isFormatted,
171 Writer *writer)
173 CLocalizer clocale;
174 this->isFormatted=isFormatted;
175 decimalPlaces = roundingPrecision == -1 ? geometry->getPrecisionModel()->getMaximumSignificantDigits() : roundingPrecision;
176 appendGeometryTaggedText(geometry, 0, writer);
179 void
180 WKTWriter::appendGeometryTaggedText(const Geometry *geometry, int level,
181 Writer *writer)
183 outputDimension = min( defaultOutputDimension,
184 geometry->getCoordinateDimension() );
186 indent(level, writer);
187 if ( const Point* point = dynamic_cast<const Point*>(geometry) )
189 appendPointTaggedText(point->getCoordinate(),level,writer);
191 else if ( const LinearRing* lr =
192 dynamic_cast<const LinearRing*>(geometry) )
194 appendLinearRingTaggedText(lr, level, writer);
196 else if ( const LineString* ls =
197 dynamic_cast<const LineString*>(geometry) )
199 appendLineStringTaggedText(ls, level, writer);
201 else if ( const Polygon* x =
202 dynamic_cast<const Polygon*>(geometry) )
204 appendPolygonTaggedText(x, level, writer);
206 else if ( const MultiPoint* x =
207 dynamic_cast<const MultiPoint*>(geometry) )
209 appendMultiPointTaggedText(x, level, writer);
211 else if ( const MultiLineString* x =
212 dynamic_cast<const MultiLineString*>(geometry) )
214 appendMultiLineStringTaggedText(x, level, writer);
216 else if ( const MultiPolygon* x =
217 dynamic_cast<const MultiPolygon*>(geometry) )
219 appendMultiPolygonTaggedText(x, level, writer);
221 else if ( const GeometryCollection* x =
222 dynamic_cast<const GeometryCollection*>(geometry) )
224 appendGeometryCollectionTaggedText(x, level, writer);
226 else
228 assert(0); // Unsupported Geometry implementation
232 /*protected*/
233 void
234 WKTWriter::appendPointTaggedText(const Coordinate* coordinate, int level,
235 Writer *writer)
237 writer->write("POINT ");
238 if( outputDimension == 3 && !old3D && coordinate != NULL )
239 writer->write( "Z " );
241 appendPointText(coordinate, level, writer);
244 void
245 WKTWriter::appendLineStringTaggedText(const LineString *lineString, int level,
246 Writer *writer)
248 writer->write("LINESTRING ");
249 if( outputDimension == 3 && !old3D && !lineString->isEmpty() )
250 writer->write( "Z " );
252 appendLineStringText(lineString, level, false, writer);
256 * Converts a <code>LinearRing</code> to &lt;LinearRing Tagged Text&gt;
257 * format, then appends it to the writer.
259 * @param linearRing the <code>LinearRing</code> to process
260 * @param writer the output writer to append to
262 void WKTWriter::appendLinearRingTaggedText(const LinearRing* linearRing, int level, Writer *writer) {
263 writer->write("LINEARRING ");
264 if( outputDimension == 3 && !old3D && !linearRing->isEmpty() )
265 writer->write( "Z " );
266 appendLineStringText((LineString*)linearRing, level, false, writer);
269 void WKTWriter::appendPolygonTaggedText(const Polygon *polygon, int level, Writer *writer) {
270 writer->write("POLYGON ");
271 if( outputDimension == 3 && !old3D && !polygon->isEmpty())
272 writer->write( "Z " );
273 appendPolygonText(polygon, level, false, writer);
276 void WKTWriter::appendMultiPointTaggedText(const MultiPoint *multipoint, int level, Writer *writer) {
277 writer->write("MULTIPOINT ");
278 if( outputDimension == 3 && !old3D && !multipoint->isEmpty() )
279 writer->write( "Z " );
280 appendMultiPointText(multipoint, level, writer);
283 void WKTWriter::appendMultiLineStringTaggedText(const MultiLineString *multiLineString, int level,Writer *writer) {
284 writer->write("MULTILINESTRING ");
285 if( outputDimension == 3 && !old3D && !multiLineString->isEmpty() )
286 writer->write( "Z " );
287 appendMultiLineStringText(multiLineString, level, false, writer);
290 void WKTWriter::appendMultiPolygonTaggedText(const MultiPolygon *multiPolygon, int level, Writer *writer) {
291 writer->write("MULTIPOLYGON ");
292 if( outputDimension == 3 && !old3D && !multiPolygon->isEmpty() )
293 writer->write( "Z " );
294 appendMultiPolygonText(multiPolygon, level, writer);
297 void WKTWriter::appendGeometryCollectionTaggedText(const GeometryCollection *geometryCollection, int level,Writer *writer) {
298 writer->write("GEOMETRYCOLLECTION ");
299 if( outputDimension == 3 && !old3D && !geometryCollection->isEmpty() )
300 writer->write( "Z " );
301 appendGeometryCollectionText(geometryCollection, level, writer);
304 void
305 WKTWriter::appendPointText(const Coordinate* coordinate, int /*level*/,
306 Writer *writer)
308 if (coordinate==NULL) {
309 writer->write("EMPTY");
310 } else {
311 writer->write("(");
312 appendCoordinate(coordinate, writer);
313 writer->write(")");
317 /* pritected */
318 void
319 WKTWriter::appendCoordinate(const Coordinate* coordinate,
320 Writer *writer)
322 string out="";
323 out+=writeNumber(coordinate->x);
324 out+=" ";
325 out+=writeNumber(coordinate->y);
326 if( outputDimension == 3 )
328 out+=" ";
329 if( ISNAN(coordinate->z) )
330 out+=writeNumber(0.0);
331 else
332 out+=writeNumber(coordinate->z);
334 writer->write(out);
337 /* protected */
338 string
339 WKTWriter::writeNumber(double d) {
341 std::stringstream ss;
343 if ( ! trim ) ss << std::fixed;
344 ss << std::setprecision(decimalPlaces >= 0 ? decimalPlaces : 0) << d;
346 return ss.str();
349 void
350 WKTWriter::appendLineStringText(const LineString *lineString, int level,
351 bool doIndent, Writer *writer)
353 if (lineString->isEmpty()) {
354 writer->write("EMPTY");
355 } else {
356 if (doIndent) indent(level, writer);
357 writer->write("(");
358 for(size_t i=0, n=lineString->getNumPoints(); i<n; ++i)
360 if (i>0) {
361 writer->write(", ");
362 if (i%10==0) indent(level + 2, writer);
364 appendCoordinate(&(lineString->getCoordinateN(i)), writer);
366 writer->write(")");
370 void
371 WKTWriter::appendPolygonText(const Polygon *polygon, int /*level*/,
372 bool indentFirst, Writer *writer)
374 if (polygon->isEmpty()) {
375 writer->write("EMPTY");
376 } else {
377 if (indentFirst) indent(level, writer);
378 writer->write("(");
379 appendLineStringText(polygon->getExteriorRing(), level, false, writer);
380 for (size_t i=0, n=polygon->getNumInteriorRing(); i<n; ++i)
382 writer->write(", ");
383 const LineString *ls=polygon->getInteriorRingN(i);
384 appendLineStringText(ls, level + 1, true, writer);
386 writer->write(")");
390 void
391 WKTWriter::appendMultiPointText(const MultiPoint *multiPoint,
392 int /*level*/, Writer *writer)
394 if (multiPoint->isEmpty()) {
395 writer->write("EMPTY");
396 } else {
397 writer->write("(");
398 for (unsigned int i=0, n=multiPoint->getNumGeometries();
399 i<n; i++)
401 if (i > 0)
403 writer->write(", ");
405 appendCoordinate(
406 dynamic_cast<const Point*>(multiPoint->getGeometryN(i))->getCoordinate(),
407 writer);
409 writer->write(")");
413 void WKTWriter::appendMultiLineStringText(const MultiLineString *multiLineString, int level, bool indentFirst,
414 Writer *writer) {
415 if (multiLineString->isEmpty()) {
416 writer->write("EMPTY");
417 } else {
418 int level2=level;
419 bool doIndent=indentFirst;
420 writer->write("(");
421 for (unsigned int i=0, n=multiLineString->getNumGeometries();
422 i<n; i++)
424 if (i>0) {
425 writer->write(", ");
426 level2=level+1;
427 doIndent=true;
429 const LineString* ls = dynamic_cast<const LineString *>(
430 multiLineString->getGeometryN(i)
432 appendLineStringText(ls, level2, doIndent, writer);
434 writer->write(")");
438 void WKTWriter::appendMultiPolygonText(const MultiPolygon *multiPolygon, int level, Writer *writer) {
439 if (multiPolygon->isEmpty()) {
440 writer->write("EMPTY");
441 } else {
442 int level2=level;
443 bool doIndent=false;
444 writer->write("(");
445 for (unsigned int i=0, n=multiPolygon->getNumGeometries();
446 i < n; i++)
448 if (i>0) {
449 writer->write(", ");
450 level2=level+1;
451 doIndent=true;
453 const Polygon *p = dynamic_cast<const Polygon *>(
454 multiPolygon->getGeometryN(i)
456 appendPolygonText(p, level2, doIndent, writer);
458 writer->write(")");
462 void
463 WKTWriter::appendGeometryCollectionText(
464 const GeometryCollection *geometryCollection,
465 int level,
466 Writer *writer)
468 if (geometryCollection->isEmpty()) {
469 writer->write("EMPTY");
470 } else {
471 int level2=level;
472 writer->write("(");
473 for (unsigned int i=0, n=geometryCollection->getNumGeometries();
474 i < n ; ++i)
476 if (i>0) {
477 writer->write(", ");
478 level2=level+1;
480 appendGeometryTaggedText(geometryCollection->getGeometryN(i),level2,writer);
482 writer->write(")");
486 void WKTWriter::indent(int level, Writer *writer) {
487 if (!isFormatted || level<=0) return;
488 writer->write("\n");
489 writer->write(string(INDENT * level, ' '));
492 } // namespace geos.io
493 } // namespace geos