[geos-commits] r2995 - in trunk: include/geos/geom include/geos/io
src/geom src/io tests/unit tests/unit/geom tests/unit/io
svn_geos at osgeo.org
svn_geos at osgeo.org
Fri May 28 16:38:41 EDT 2010
Author: warmerdam
Date: 2010-05-28 16:38:40 -0400 (Fri, 28 May 2010)
New Revision: 2995
Modified:
trunk/include/geos/geom/Geometry.h
trunk/include/geos/geom/GeometryCollection.h
trunk/include/geos/geom/LineString.h
trunk/include/geos/geom/Point.h
trunk/include/geos/geom/Polygon.h
trunk/include/geos/io/WKBWriter.h
trunk/include/geos/io/WKTWriter.h
trunk/src/geom/GeometryCollection.cpp
trunk/src/geom/LineString.cpp
trunk/src/geom/Point.cpp
trunk/src/geom/Polygon.cpp
trunk/src/io/WKBWriter.cpp
trunk/src/io/WKTWriter.cpp
trunk/tests/unit/Makefile.am
trunk/tests/unit/geom/LineStringTest.cpp
trunk/tests/unit/geom/PointTest.cpp
trunk/tests/unit/io/WKTWriterTest.cpp
Log:
Implement getCoordinateDimension() for geometries (#331)
WKTWriter now has setOutputDimension() method, and writes 3D geometries (#292)
WKBWriter has fixes for writing 2D geometries from 3D geometry (#346)
Minimal unit tests for the above.
Modified: trunk/include/geos/geom/Geometry.h
===================================================================
--- trunk/include/geos/geom/Geometry.h 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/include/geos/geom/Geometry.h 2010-05-28 20:38:40 UTC (rev 2995)
@@ -303,6 +303,9 @@
/// Returns the dimension of this Geometry (0=point, 1=line, 2=surface)
virtual Dimension::DimensionType getDimension() const=0; //Abstract
+ /// Returns the coordinate dimension of this Geometry (2=XY, 3=XYZ, 4=XYZM in future).
+ virtual int getCoordinateDimension() const=0; //Abstract
+
/**
* \brief
* Returns the boundary, or an empty geometry of appropriate
Modified: trunk/include/geos/geom/GeometryCollection.h
===================================================================
--- trunk/include/geos/geom/GeometryCollection.h 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/include/geos/geom/GeometryCollection.h 2010-05-28 20:38:40 UTC (rev 2995)
@@ -105,6 +105,9 @@
*/
virtual Dimension::DimensionType getDimension() const;
+ /// Returns coordinate dimension.
+ virtual int getCoordinateDimension() const;
+
virtual Geometry* getBoundary() const;
/**
Modified: trunk/include/geos/geom/LineString.h
===================================================================
--- trunk/include/geos/geom/LineString.h 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/include/geos/geom/LineString.h 2010-05-28 20:38:40 UTC (rev 2995)
@@ -90,6 +90,9 @@
*/
virtual int getBoundaryDimension() const;
+ /// Returns coordinate dimension.
+ virtual int getCoordinateDimension() const;
+
/**
* \brief
* Returns a MultiPoint.
Modified: trunk/include/geos/geom/Point.h
===================================================================
--- trunk/include/geos/geom/Point.h 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/include/geos/geom/Point.h 2010-05-28 20:38:40 UTC (rev 2995)
@@ -92,6 +92,9 @@
/// Returns point dimension (0)
Dimension::DimensionType getDimension() const;
+ /// Returns coordinate dimension.
+ virtual int getCoordinateDimension() const;
+
/// Returns Dimension::False (Point has no boundary)
int getBoundaryDimension() const;
Modified: trunk/include/geos/geom/Polygon.h
===================================================================
--- trunk/include/geos/geom/Polygon.h 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/include/geos/geom/Polygon.h 2010-05-28 20:38:40 UTC (rev 2995)
@@ -88,6 +88,9 @@
/// Returns surface dimension (2)
Dimension::DimensionType getDimension() const;
+ /// Returns coordinate dimension.
+ virtual int getCoordinateDimension() const;
+
/// Returns 1 (Polygon boundary is a MultiLineString)
int getBoundaryDimension() const;
Modified: trunk/include/geos/io/WKBWriter.h
===================================================================
--- trunk/include/geos/io/WKBWriter.h 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/include/geos/io/WKBWriter.h 2010-05-28 20:38:40 UTC (rev 2995)
@@ -75,30 +75,38 @@
public:
/*
* \brief
- * Initializes writer with target coordinate dimention, endianness flag
- * and SRID value.
- * <code>WKBWriter</code>.
+ * Initializes writer with target coordinate dimension, endianness
+ * flag and SRID value.
+ *
+ * @param dims Supported values are 2 or 3. Note that 3 indicates
+ * up to 3 dimensions will be written but 2D WKB is still produced for 2D geometries.
+ * @param bo output byte order - default to native machine byte order.
+ * Legal values include 0 (big endian/xdr) and 1 (little endian/ndr).
+ * @param incudeSRID true if SRID should be included in WKB (an
+ * extension).
*/
WKBWriter(int dims=2, int bo=getMachineByteOrder(), bool includeSRID=false);
- /*
- * \brief
- * Destructor.
- */
- virtual ~WKBWriter();
+ /*
+ * \brief
+ * Destructor.
+ */
+ virtual ~WKBWriter();
/*
* \brief
* Returns the output dimension used by the
* <code>WKBWriter</code>.
*/
- virtual int getOutputDimension() const { return outputDimension; }
+ virtual int getOutputDimension() const { return defaultOutputDimension; }
/*
- * Sets the output dimension used by the
- * <code>WKBWriter</code>.
+ * Sets the output dimension used by the <code>WKBWriter</code>.
+ *
+ * @param newOutputDimension Supported values are 2 or 3. Note that 3 indicates
+ * up to 3 dimensions will be written but 2D WKB is still produced for 2D geometries.
*/
- virtual void setOutputDimension(int newOutputDimension) { outputDimension=newOutputDimension; }
+ virtual void setOutputDimension(int newOutputDimension) { defaultOutputDimension=newOutputDimension; }
/*
* \brief
@@ -124,7 +132,7 @@
* Sets whether SRID values should be output by the
* <code>WKBWriter</code>.
*/
- virtual void setIncludeSRID(int newIncludeSRID) { includeSRID = (0 == newIncludeSRID ? false : true); }
+ virtual void setIncludeSRID(int newIncludeSRID) { includeSRID = (0 == newIncludeSRID ? false : true); }
/**
* \brief Write a Geometry to an ostream.
@@ -148,7 +156,8 @@
private:
- int outputDimension;
+ int defaultOutputDimension;
+ int outputDimension;
int byteOrder;
Modified: trunk/include/geos/io/WKTWriter.h
===================================================================
--- trunk/include/geos/io/WKTWriter.h 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/include/geos/io/WKTWriter.h 2010-05-28 20:38:40 UTC (rev 2995)
@@ -139,6 +139,32 @@
*/
void setTrim(bool p0);
+ /**
+ * Enable old style 3D/4D WKT generation.
+ *
+ * By default the WKBWriter produces new style 3D/4D WKT (ie. "POINT Z (10 20 30)")
+ * but if this method is used to turn on old style WKT production then the WKT will
+ * be formatted in the style "POINT (10 20 30)".
+ *
+ * @param useOld3D true or false
+ */
+ void setOld3D(bool useOld3D ) { old3D = useOld3D; }
+
+ /*
+ * \brief
+ * Returns the output dimension used by the
+ * <code>WKBWriter</code>.
+ */
+ virtual int getOutputDimension() const { return defaultOutputDimension; }
+
+ /*
+ * Sets the output dimension used by the <code>WKBWriter</code>.
+ *
+ * @param newOutputDimension Supported values are 2 or 3. Note that 3 indicates
+ * up to 3 dimensions will be written but 2D WKB is still produced for 2D geometries.
+ */
+ virtual void setOutputDimension(int newOutputDimension) { defaultOutputDimension=newOutputDimension; }
+
protected:
std::string formatter;
@@ -229,6 +255,10 @@
int level;
+ int defaultOutputDimension;
+ int outputDimension;
+ bool old3D;
+
void writeFormatted(
const geom::Geometry *geometry,
bool isFormatted, Writer *writer);
Modified: trunk/src/geom/GeometryCollection.cpp
===================================================================
--- trunk/src/geom/GeometryCollection.cpp 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/src/geom/GeometryCollection.cpp 2010-05-28 20:38:40 UTC (rev 2995)
@@ -127,6 +127,18 @@
return dimension;
}
+int
+GeometryCollection::getCoordinateDimension() const
+{
+ int dimension=2;
+
+ for (size_t i=0, n=geometries->size(); i<n; ++i)
+ {
+ dimension=max(dimension,(*geometries)[i]->getCoordinateDimension());
+ }
+ return dimension;
+}
+
size_t
GeometryCollection::getNumGeometries() const
{
Modified: trunk/src/geom/LineString.cpp
===================================================================
--- trunk/src/geom/LineString.cpp 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/src/geom/LineString.cpp 2010-05-28 20:38:40 UTC (rev 2995)
@@ -136,6 +136,12 @@
}
int
+LineString::getCoordinateDimension() const
+{
+ return (int) points->getDimension();
+}
+
+int
LineString::getBoundaryDimension() const
{
if (isClosed()) {
Modified: trunk/src/geom/Point.cpp
===================================================================
--- trunk/src/geom/Point.cpp 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/src/geom/Point.cpp 2010-05-28 20:38:40 UTC (rev 2995)
@@ -99,6 +99,12 @@
}
int
+Point::getCoordinateDimension() const
+{
+ return (int) coordinates->getDimension();
+}
+
+int
Point::getBoundaryDimension() const
{
return Dimension::False;
Modified: trunk/src/geom/Polygon.cpp
===================================================================
--- trunk/src/geom/Polygon.cpp 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/src/geom/Polygon.cpp 2010-05-28 20:38:40 UTC (rev 2995)
@@ -145,6 +145,23 @@
}
int
+Polygon::getCoordinateDimension() const
+{
+ int dimension=2;
+
+ if( shell != NULL )
+ dimension = max(dimension,shell->getCoordinateDimension());
+
+ size_t nholes=holes->size();
+ for (size_t i=0; i<nholes; ++i)
+ {
+ dimension = max(dimension,(*holes)[i]->getCoordinateDimension());
+ }
+
+ return dimension;
+}
+
+int
Polygon::getBoundaryDimension() const
{
return 1;
Modified: trunk/src/io/WKBWriter.cpp
===================================================================
--- trunk/src/io/WKBWriter.cpp 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/src/io/WKBWriter.cpp 2010-05-28 20:38:40 UTC (rev 2995)
@@ -46,10 +46,11 @@
namespace io { // geos.io
WKBWriter::WKBWriter(int dims, int bo, bool srid):
- outputDimension(dims), byteOrder(bo), includeSRID(srid), outStream(NULL)
+ defaultOutputDimension(dims), byteOrder(bo), includeSRID(srid), outStream(NULL)
{
if ( dims < 2 || dims > 3 )
throw util::IllegalArgumentException("WKB output dimension must be 2 or 3");
+ outputDimension = defaultOutputDimension;
}
WKBWriter::~WKBWriter()
@@ -72,6 +73,10 @@
void
WKBWriter::write(const Geometry &g, ostream &os)
{
+ outputDimension = defaultOutputDimension;
+ if( outputDimension > g.getCoordinateDimension() )
+ outputDimension = g.getCoordinateDimension();
+
outStream = &os;
switch (g.getGeometryTypeId()) {
@@ -204,20 +209,19 @@
WKBWriter::writeGeometryType(int typeId, int SRID)
{
int flag3D = (outputDimension == 3) ? 0x80000000 : 0;
- int typeInt = typeId | flag3D;
+ int typeInt = typeId | flag3D;
- if (includeSRID && SRID != 0)
- typeInt = typeInt | 0x20000000;
+ if (includeSRID && SRID != 0)
+ typeInt = typeInt | 0x20000000;
- //writeInt(typeId);
writeInt(typeInt);
}
void
WKBWriter::writeSRID(int SRID)
{
- if (includeSRID && SRID != 0)
- writeInt(SRID);
+ if (includeSRID && SRID != 0)
+ writeInt(SRID);
}
void
@@ -234,7 +238,7 @@
{
int size = cs.getSize();
bool is3d=false;
- if ( cs.getDimension() > 2 && outputDimension > 2) is3d = true;
+ if ( outputDimension > 2) is3d = true;
if (sized) writeInt(size);
for (int i=0; i<size; i++) writeCoordinate(cs, i, is3d);
Modified: trunk/src/io/WKTWriter.cpp
===================================================================
--- trunk/src/io/WKTWriter.cpp 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/src/io/WKTWriter.cpp 2010-05-28 20:38:40 UTC (rev 2995)
@@ -38,8 +38,6 @@
#include <sstream>
#include <cassert>
-#define PRINT_Z 0
-
using namespace std;
using namespace geos::geom;
@@ -52,6 +50,8 @@
trim = false;
level=0;
formatter="%f";
+ defaultOutputDimension = 2;
+ old3D = false;
}
WKTWriter::~WKTWriter() {}
@@ -194,6 +194,8 @@
WKTWriter::appendGeometryTaggedText(const Geometry *geometry, int level,
Writer *writer)
{
+ outputDimension = min(defaultOutputDimension,geometry->getCoordinateDimension());
+
indent(level, writer);
if (typeid(*geometry)==typeid(Point)) {
Point* point=(Point*)geometry;
@@ -225,6 +227,9 @@
Writer *writer)
{
writer->write("POINT ");
+ if( outputDimension == 3 && !old3D )
+ writer->write( "Z " );
+
appendPointText(coordinate, level, writer);
}
@@ -233,6 +238,9 @@
Writer *writer)
{
writer->write("LINESTRING ");
+ if( outputDimension == 3 && !old3D )
+ writer->write( "Z " );
+
appendLineStringText(lineString, level, false, writer);
}
@@ -245,31 +253,43 @@
*/
void WKTWriter::appendLinearRingTaggedText(const LinearRing* linearRing, int level, Writer *writer) {
writer->write("LINEARRING ");
+ if( outputDimension == 3 && !old3D )
+ writer->write( "Z " );
appendLineStringText((LineString*)linearRing, level, false, writer);
}
void WKTWriter::appendPolygonTaggedText(const Polygon *polygon, int level, Writer *writer) {
writer->write("POLYGON ");
+ if( outputDimension == 3 && !old3D )
+ writer->write( "Z " );
appendPolygonText(polygon, level, false, writer);
}
void WKTWriter::appendMultiPointTaggedText(const MultiPoint *multipoint, int level, Writer *writer) {
writer->write("MULTIPOINT ");
+ if( outputDimension == 3 && !old3D )
+ writer->write( "Z " );
appendMultiPointText(multipoint, level, writer);
}
void WKTWriter::appendMultiLineStringTaggedText(const MultiLineString *multiLineString, int level,Writer *writer) {
writer->write("MULTILINESTRING ");
+ if( outputDimension == 3 && !old3D )
+ writer->write( "Z " );
appendMultiLineStringText(multiLineString, level, false, writer);
}
void WKTWriter::appendMultiPolygonTaggedText(const MultiPolygon *multiPolygon, int level, Writer *writer) {
writer->write("MULTIPOLYGON ");
+ if( outputDimension == 3 && !old3D )
+ writer->write( "Z " );
appendMultiPolygonText(multiPolygon, level, writer);
}
void WKTWriter::appendGeometryCollectionTaggedText(const GeometryCollection *geometryCollection, int level,Writer *writer) {
writer->write("GEOMETRYCOLLECTION ");
+ if( outputDimension == 3 && !old3D ) // ? do we really do this?
+ writer->write( "Z " );
appendGeometryCollectionText(geometryCollection, level, writer);
}
@@ -294,10 +314,11 @@
out+=writeNumber(coordinate->x);
out+=" ";
out+=writeNumber(coordinate->y);
-#if PRINT_Z
- out+=" ";
- out+=writeNumber(coordinate->z);
-#endif
+ if( outputDimension == 3 )
+ {
+ out+=" ";
+ out+=writeNumber(coordinate->z);
+ }
writer->write(out);
}
Modified: trunk/tests/unit/Makefile.am
===================================================================
--- trunk/tests/unit/Makefile.am 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/tests/unit/Makefile.am 2010-05-28 20:38:40 UTC (rev 2995)
@@ -62,6 +62,7 @@
index/quadtree/DoubleBitsTest.cpp \
io/ByteOrderValuesTest.cpp \
io/WKBReaderTest.cpp \
+ io/WKBWriterTest.cpp \
io/WKTReaderTest.cpp \
io/WKTWriterTest.cpp \
linearref/LengthIndexedLineTest.cpp \
Modified: trunk/tests/unit/geom/LineStringTest.cpp
===================================================================
--- trunk/tests/unit/geom/LineStringTest.cpp 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/tests/unit/geom/LineStringTest.cpp 2010-05-28 20:38:40 UTC (rev 2995)
@@ -129,6 +129,7 @@
ensure_equals( ls->getGeometryTypeId(), geos::geom::GEOS_LINESTRING );
ensure_equals( ls->getDimension(), geos::geom::Dimension::L );
ensure_equals( ls->getBoundaryDimension(), geos::geom::Dimension::P );
+ ensure_equals( ls->getCoordinateDimension(), 3 );
ensure_equals( ls->getNumPoints(), size3 );
ensure_equals( ls->getArea(), 0.0 );
ensure( ls->getLength() != 0.0 );
@@ -328,6 +329,7 @@
ensure( !line->isEmpty() );
ensure( !line->isClosed() );
ensure( !line->isRing() );
+ ensure( line->getCoordinateDimension() == 2 );
// FREE TESTED LINESTRING
factory_.destroyGeometry(line);
Modified: trunk/tests/unit/geom/PointTest.cpp
===================================================================
--- trunk/tests/unit/geom/PointTest.cpp 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/tests/unit/geom/PointTest.cpp 2010-05-28 20:38:40 UTC (rev 2995)
@@ -91,6 +91,10 @@
PointAutoPtr point(factory_.createPoint(coords));
ensure( !point->isEmpty() );
+
+ // currently the empty CoordinateArraySequence constructor
+ // produces a dimension 3 sequence.
+ ensure( point->getCoordinateDimension() == 3 );
}
// Test of user's constructor throwing IllegalArgumentException
@@ -510,5 +514,19 @@
factory_.destroyGeometry(p3);
}
+ // Test of getCoordinateDimension() for 2d/3d.
+ template<>
+ template<>
+ void object::test<40>()
+ {
+ GeometryPtr p = reader_.read("POINT(-1.233 5.678 1.0)");
+
+ ensure( p->getCoordinateDimension() == 3 );
+
+ p = reader_.read("POINT(-1.233 5.678)");
+
+ ensure( p->getCoordinateDimension() == 2 );
+ }
+
} // namespace tut
Modified: trunk/tests/unit/io/WKTWriterTest.cpp
===================================================================
--- trunk/tests/unit/io/WKTWriterTest.cpp 2010-05-28 20:32:14 UTC (rev 2994)
+++ trunk/tests/unit/io/WKTWriterTest.cpp 2010-05-28 20:38:40 UTC (rev 2995)
@@ -30,11 +30,11 @@
geos::io::WKTWriter wktwriter;
test_wktwriter_data()
- :
- pm(1000.0),
- gf(&pm),
- wktreader(&gf)
- {}
+ :
+ pm(1000.0),
+ gf(&pm),
+ wktreader(&gf)
+ {}
};
@@ -53,42 +53,85 @@
template<>
void object::test<1>()
{
- geos::geom::Geometry *geom = wktreader.read("POINT(-117 33)");
- std::string result;
+ geos::geom::Geometry *geom = wktreader.read("POINT(-117 33)");
+ std::string result;
- wktwriter.setTrim(false);
- result = wktwriter.write( geom );
+ wktwriter.setTrim(false);
+ result = wktwriter.write( geom );
- ensure( result == "POINT (-117.0000 33.0000)" );
+ ensure( result == "POINT (-117.0000 33.0000)" );
- wktwriter.setTrim(true);
- result = wktwriter.write( geom );
+ wktwriter.setTrim(true);
+ result = wktwriter.write( geom );
- ensure( result == "POINT (-117 33)" );
+ ensure( result == "POINT (-117 33)" );
- delete geom;
- }
+ delete geom;
+ }
// 2 - Test the output precision capability
template<>
template<>
void object::test<2>()
{
- geos::geom::Geometry *geom = wktreader.read("POINT(-117.1234567 33.1234567)");
- std::string result;
+ geos::geom::Geometry *geom = wktreader.read("POINT(-117.1234567 33.1234567)");
+ std::string result;
- wktwriter.setTrim(false);
- result = wktwriter.write( geom );
+ wktwriter.setTrim(false);
+ result = wktwriter.write( geom );
- ensure( result == "POINT (-117.1230 33.1230)" );
+ ensure( result == "POINT (-117.1230 33.1230)" );
- wktwriter.setRoundingPrecision(2);
- result = wktwriter.write( geom );
+ wktwriter.setRoundingPrecision(2);
+ result = wktwriter.write( geom );
- ensure( result == "POINT (-117.12 33.12)" );
+ ensure( result == "POINT (-117.12 33.12)" );
- delete geom;
- }
+ delete geom;
+ }
+
+ // 3 - Test 3D generation from a 3D geometry.
+ template<>
+ template<>
+ void object::test<3>()
+ {
+ geos::geom::Geometry *geom = wktreader.read("POINT Z (-117 33 120)");
+ std::string result;
+ wktwriter.setOutputDimension(3);
+ wktwriter.setTrim( true );
+ wktwriter.setOld3D( false );
+
+ result = wktwriter.write( geom );
+
+ ensure_equals( result, std::string("POINT Z (-117 33 120)") );
+
+ wktwriter.setOld3D( true );
+ result = wktwriter.write( geom );
+
+ ensure_equals( result, std::string("POINT (-117 33 120)") );
+
+ delete geom;
+ }
+
+ // 4 - Test 2D generation from a 3D geometry.
+ template<>
+ template<>
+ void object::test<4>()
+ {
+ geos::geom::Geometry *geom = wktreader.read("POINT(-117 33 120)");
+ std::string result;
+
+ wktwriter.setOutputDimension(2);
+ wktwriter.setTrim( true );
+ wktwriter.setOld3D( false );
+
+ result = wktwriter.write( geom );
+
+ ensure_equals( result, std::string("POINT (-117 33)") );
+
+ delete geom;
+ }
+
} // namespace tut
More information about the geos-commits
mailing list