Skip to content

Commit

Permalink
WKTWriter: Support curved types
Browse files Browse the repository at this point in the history
  • Loading branch information
dbaston committed Feb 21, 2024
1 parent 27973ff commit 794c9a4
Show file tree
Hide file tree
Showing 9 changed files with 506 additions and 116 deletions.
11 changes: 9 additions & 2 deletions include/geos/geom/GeometryFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ class GEOS_DLL GeometryFactory {

/// Creates an EMPTY Point
std::unique_ptr<Point> createPoint(std::size_t coordinateDimension = 2) const;
std::unique_ptr<Point> createPoint(bool hasZ, bool hasM) const;

/// Creates a Point using the given Coordinate
std::unique_ptr<Point> createPoint(const Coordinate& coordinate) const;
Expand All @@ -164,7 +165,7 @@ class GEOS_DLL GeometryFactory {
std::unique_ptr<GeometryCollection> createGeometryCollection() const;

/// Construct the EMPTY Geometry
std::unique_ptr<Geometry> createEmptyGeometry() const;
std::unique_ptr<Geometry> createEmptyGeometry(GeometryTypeId type = GEOS_GEOMETRYCOLLECTION, bool hasZ=false, bool hasM=false) const;

/// Construct a GeometryCollection taking ownership of given arguments
template<typename T>
Expand Down Expand Up @@ -228,6 +229,7 @@ class GEOS_DLL GeometryFactory {

/// Construct an EMPTY LinearRing
std::unique_ptr<LinearRing> createLinearRing(std::size_t coordinateDimension = 2) const;
std::unique_ptr<LinearRing> createLinearRing(bool hasZ, bool hasM) const;

/// Construct a LinearRing taking ownership of given arguments
std::unique_ptr<LinearRing> createLinearRing(
Expand Down Expand Up @@ -269,6 +271,7 @@ class GEOS_DLL GeometryFactory {

/// Construct an EMPTY Polygon
std::unique_ptr<Polygon> createPolygon(std::size_t coordinateDimension = 2) const;
std::unique_ptr<Polygon> createPolygon(bool hasZ, bool hasM) const;

/// Construct a Polygon taking ownership of given arguments
std::unique_ptr<Polygon> createPolygon(std::unique_ptr<LinearRing> && shell) const;
Expand All @@ -284,6 +287,9 @@ class GEOS_DLL GeometryFactory {
const std::vector<LinearRing*>& holes) const;


/// Construct an EMPTY CurvePolygon
std::unique_ptr<CurvePolygon> createCurvePolygon(bool hasZ, bool hasM) const;

/// Construct a CurvePolygon taking ownership of given arguments
std::unique_ptr<CurvePolygon> createCurvePolygon(std::unique_ptr<Curve>&& shell) const;

Expand All @@ -292,6 +298,7 @@ class GEOS_DLL GeometryFactory {

/// Construct an EMPTY LineString
std::unique_ptr<LineString> createLineString(std::size_t coordinateDimension = 2) const;
std::unique_ptr<LineString> createLineString(bool hasZ, bool hasM) const;

/// Copy a LineString
std::unique_ptr<LineString> createLineString(const LineString& ls) const;
Expand All @@ -305,7 +312,7 @@ class GEOS_DLL GeometryFactory {
const CoordinateSequence& coordinates) const;

/// Construct an EMPTY CircularString
std::unique_ptr<CircularString> createCircularString(bool hasZ = false, bool hasM = false) const;
std::unique_ptr<CircularString> createCircularString(bool hasZ, bool hasM) const;

/// Copy a CircularString
std::unique_ptr<CircularString> createCircularString(const CircularString& ls) const;
Expand Down
2 changes: 1 addition & 1 deletion include/geos/io/WKTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class GEOS_DLL WKTReader {
static std::string getNextCloserOrComma(io::StringTokenizer* tokenizer);
static std::string getNextCloser(io::StringTokenizer* tokenizer);
static std::string getNextWord(io::StringTokenizer* tokenizer);
std::unique_ptr<geom::Geometry> readGeometryTaggedText(io::StringTokenizer* tokenizer, OrdinateSet& ordinateFlags) const;
std::unique_ptr<geom::Geometry> readGeometryTaggedText(io::StringTokenizer* tokenizer, OrdinateSet& ordinateFlags, const geom::GeometryTypeId* emptyType = nullptr) const;
std::unique_ptr<geom::Point> readPointText(io::StringTokenizer* tokenizer, OrdinateSet& ordinateFlags) const;
std::unique_ptr<geom::LineString> readLineStringText(io::StringTokenizer* tokenizer, OrdinateSet& ordinateFlags) const;
std::unique_ptr<geom::LinearRing> readLinearRingText(io::StringTokenizer* tokenizer, OrdinateSet& ordinateFlags) const;
Expand Down
57 changes: 37 additions & 20 deletions include/geos/io/WKTWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class Coordinate;
class CoordinateXY;
class CoordinateXYZM;
class CoordinateSequence;
class Curve;
class CompoundCurve;
class Geometry;
class GeometryCollection;
class Point;
Expand All @@ -49,6 +51,8 @@ class MultiPoint;
class MultiLineString;
class MultiPolygon;
class PrecisionModel;
class SimpleCurve;
class Surface;
}
namespace io {
class Writer;
Expand Down Expand Up @@ -208,23 +212,28 @@ class GEOS_DLL WKTWriter {
int level,
Writer& writer) const;

void appendTag(
const geom::Geometry& geometry,
OrdinateSet outputOrdinates,
Writer& writer) const;

void appendPointTaggedText(
const geom::Point& point,
OrdinateSet outputOrdinates,
int level, Writer& writer) const;

void appendLineStringTaggedText(
const geom::LineString& lineString,
void appendSimpleCurveTaggedText(
const geom::SimpleCurve& lineString,
OrdinateSet outputOrdinates,
int level, Writer& writer) const;

void appendLinearRingTaggedText(
const geom::LinearRing& lineString,
void appendCompoundCurveTaggedText(
const geom::CompoundCurve& lineString,
OrdinateSet outputOrdinates,
int level, Writer& writer) const;

void appendPolygonTaggedText(
const geom::Polygon& polygon,
void appendSurfaceTaggedText(
const geom::Surface& polygon,
OrdinateSet outputOrdinates,
int level, Writer& writer) const;

Expand All @@ -233,13 +242,13 @@ class GEOS_DLL WKTWriter {
OrdinateSet outputOrdinates,
int level, Writer& writer) const;

void appendMultiLineStringTaggedText(
const geom::MultiLineString& multiLineString,
void appendMultiCurveTaggedText(
const geom::GeometryCollection& multiCurve,
OrdinateSet outputOrdinates,
int level, Writer& writer) const;

void appendMultiPolygonTaggedText(
const geom::MultiPolygon& multiPolygon,
void appendMultiSurfaceTaggedText(
const geom::GeometryCollection& multiSurface,
OrdinateSet outputOrdinates,
int level, Writer& writer) const;

Expand All @@ -263,13 +272,25 @@ class GEOS_DLL WKTWriter {

std::string writeNumber(double d) const;

void appendCurveText(
const geom::Curve& lineString,
OrdinateSet outputOrdinates,
int level, bool doIndent, Writer& writer) const;

void appendSimpleCurveText(
const geom::SimpleCurve& lineString,
OrdinateSet outputOrdinates,
int level, bool doIndent, Writer& writer) const;

#if 0
void appendLineStringText(
const geom::LineString& lineString,
OrdinateSet outputOrdinates,
int level, bool doIndent, Writer& writer) const;
#endif

void appendPolygonText(
const geom::Polygon& polygon,
void appendSurfaceText(
const geom::Surface& polygon,
OrdinateSet outputOrdinates,
int level, bool indentFirst, Writer& writer) const;

Expand All @@ -278,13 +299,13 @@ class GEOS_DLL WKTWriter {
OrdinateSet outputOrdinates,
int level, Writer& writer) const;

void appendMultiLineStringText(
const geom::MultiLineString& multiLineString,
void appendMultiCurveText(
const geom::GeometryCollection& multiCurve,
OrdinateSet outputOrdinates,
int level, bool indentFirst, Writer& writer) const;

void appendMultiPolygonText(
const geom::MultiPolygon& multiPolygon,
void appendMultiSurfaceText(
const geom::GeometryCollection& multiSurface,
OrdinateSet outputOrdinates,
int level, Writer& writer) const;

Expand All @@ -299,8 +320,6 @@ class GEOS_DLL WKTWriter {
INDENT = 2
};

// static const int INDENT = 2;

bool isFormatted;

int roundingPrecision;
Expand All @@ -309,8 +328,6 @@ class GEOS_DLL WKTWriter {

bool removeEmptyDimensions = false;

int level;

static constexpr int coordsPerLine = 10;

uint8_t defaultOutputDimension;
Expand Down
4 changes: 3 additions & 1 deletion include/geos/util/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,7 @@ bool endsWith(const std::string & s, char suffix);
bool startsWith(const std::string & s, const std::string & prefix);
bool startsWith(const std::string & s, char prefix);

void toUpper(std::string& s);

}
}
}
67 changes: 63 additions & 4 deletions src/geom/GeometryFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,14 @@ GeometryFactory::createPoint(std::size_t coordinateDimension) const
return std::unique_ptr<Point>(new Point(std::move(seq), this));
}

/*public*/
std::unique_ptr<Point>
GeometryFactory::createPoint(bool hasZ, bool hasM) const
{
CoordinateSequence seq(0u, hasZ, hasM);
return std::unique_ptr<Point>(new Point(std::move(seq), this));
}

/*public*/
std::unique_ptr<Point>
GeometryFactory::createPoint(std::unique_ptr<CoordinateSequence>&& coords) const
Expand Down Expand Up @@ -334,9 +342,26 @@ GeometryFactory::createGeometryCollection() const

/*public*/
std::unique_ptr<Geometry>
GeometryFactory::createEmptyGeometry() const
GeometryFactory::createEmptyGeometry(GeometryTypeId type, bool hasZ, bool hasM) const
{
return createGeometryCollection();
switch (type) {
case GEOS_POINT: return createPoint(hasZ, hasM);
case GEOS_LINESTRING: return createLineString(hasZ, hasM);
case GEOS_LINEARRING: return createLinearRing(hasZ, hasM);
case GEOS_POLYGON: return createPolygon(hasZ, hasM);
case GEOS_MULTIPOINT: return createMultiPoint();
case GEOS_MULTILINESTRING: return createMultiLineString();
case GEOS_MULTIPOLYGON: return createMultiPolygon();
case GEOS_GEOMETRYCOLLECTION: return createGeometryCollection();
case GEOS_CIRCULARSTRING: return createCircularString(hasZ, hasM);
case GEOS_COMPOUNDCURVE: return createCompoundCurve();
case GEOS_CURVEPOLYGON: return createCurvePolygon(hasZ, hasM);
case GEOS_MULTICURVE: return createMultiCurve();
case GEOS_MULTISURFACE: return createMultiSurface();
default:
throw geos::util::IllegalArgumentException("Unexpected GeometryTypeId");

}
}

/*public*/
Expand Down Expand Up @@ -417,6 +442,15 @@ GeometryFactory::createLinearRing(std::size_t coordinateDimension) const
return std::unique_ptr<LinearRing>(new LinearRing(std::move(cs), *this));
}

/*public*/
std::unique_ptr<LinearRing>
GeometryFactory::createLinearRing(bool hasZ, bool hasM) const
{
// Can't use make_unique with protected constructor
auto cs = detail::make_unique<CoordinateSequence>(0u, hasZ, hasM);
return std::unique_ptr<LinearRing>(new LinearRing(std::move(cs), *this));
}

std::unique_ptr<LinearRing>
GeometryFactory::createLinearRing(CoordinateSequence::Ptr && newCoords) const
{
Expand Down Expand Up @@ -487,6 +521,15 @@ GeometryFactory::createPolygon(std::size_t coordinateDimension) const
return createPolygon(std::move(lr));
}

/*public*/
std::unique_ptr<Polygon>
GeometryFactory::createPolygon(bool hasZ, bool hasM) const
{
auto cs = detail::make_unique<CoordinateSequence>(0u, hasZ, hasM);
auto lr = createLinearRing(std::move(cs));
return createPolygon(std::move(lr));
}

std::unique_ptr<Polygon>
GeometryFactory::createPolygon(std::unique_ptr<LinearRing> && shell)
const
Expand Down Expand Up @@ -531,12 +574,20 @@ const
return new Polygon(std::move(newRing), std::move(newHoles), *this);
}

/* public */
std::unique_ptr<CurvePolygon>
GeometryFactory::createCurvePolygon(bool hasZ, bool hasM)
const
{
// Can't use make_unique with protected constructor
return std::unique_ptr<CurvePolygon>(new CurvePolygon(createLinearRing(hasZ, hasM), *this));
}

/* public */
std::unique_ptr<CurvePolygon>
GeometryFactory::createCurvePolygon(std::unique_ptr<Curve> && shell)
const
{
//auto shellCurve = std::unique_ptr<Curve>(detail::down_cast<Curve*>(shell.release()));
// Can't use make_unique with protected constructor
return std::unique_ptr<CurvePolygon>(new CurvePolygon(std::move(shell), *this));
}
Expand All @@ -558,6 +609,14 @@ GeometryFactory::createLineString(std::size_t coordinateDimension) const
return createLineString(std::move(cs));
}

/*public*/
std::unique_ptr<LineString>
GeometryFactory::createLineString(bool hasZ, bool hasM) const
{
auto cs = detail::make_unique<CoordinateSequence>(0u, hasZ, hasM);
return createLineString(std::move(cs));
}

/*public*/
std::unique_ptr<CircularString>
GeometryFactory::createCircularString(bool hasZ, bool hasM) const
Expand Down Expand Up @@ -599,7 +658,7 @@ GeometryFactory::createCircularString(CoordinateSequence::Ptr && newCoords)
const
{
if (!newCoords)
return createCircularString();
return createCircularString(false, false);
// Can't use make_unique with protected constructor
return std::unique_ptr<CircularString>(new CircularString(std::move(newCoords), *this));
}
Expand Down
22 changes: 17 additions & 5 deletions src/io/WKTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,14 +265,19 @@ WKTReader::getNextWord(StringTokenizer* tokenizer)
}

std::unique_ptr<Geometry>
WKTReader::readGeometryTaggedText(StringTokenizer* tokenizer, OrdinateSet& ordinateFlags) const
WKTReader::readGeometryTaggedText(StringTokenizer* tokenizer, OrdinateSet& ordinateFlags, const GeometryTypeId* emptyType) const
{
std::string type = getNextWord(tokenizer);

std::unique_ptr<Geometry> geom;
OrdinateSet origFlags = ordinateFlags;

OrdinateSet newFlags = OrdinateSet::createXY();
readOrdinateFlags(type, newFlags);
if (type == "EMPTY") {
newFlags = origFlags;
} else {
readOrdinateFlags(type, newFlags);
}

if(isTypeName(type, "POINT")) {
geom = readPointText(tokenizer, newFlags);
Expand Down Expand Up @@ -312,6 +317,11 @@ WKTReader::readGeometryTaggedText(StringTokenizer* tokenizer, OrdinateSet& ordin
}
else if(isTypeName(type, "GEOMETRYCOLLECTION")) {
geom = readGeometryCollectionText(tokenizer, newFlags);
} else if (type == "EMPTY" && emptyType != nullptr) {
if (*emptyType == GEOS_MULTICURVE) {
std::cout <<"XX";
}
return geometryFactory->createEmptyGeometry(*emptyType, newFlags.hasZ(), newFlags.hasM());
} else {
throw ParseException("Unknown type", type);
}
Expand Down Expand Up @@ -363,7 +373,8 @@ WKTReader::readCurveText(StringTokenizer* tokenizer, OrdinateSet& ordinateFlags)
return readLineStringText(tokenizer, ordinateFlags);
}

auto component = readGeometryTaggedText(tokenizer, ordinateFlags);
GeometryTypeId defaultType = GEOS_LINESTRING;
auto component = readGeometryTaggedText(tokenizer, ordinateFlags, &defaultType);
if (dynamic_cast<Curve*>(component.get())) {
return std::unique_ptr<Curve>(static_cast<Curve*>(component.release()));
}
Expand All @@ -379,8 +390,9 @@ WKTReader::readSurfaceText(StringTokenizer* tokenizer, OrdinateSet& ordinateFlag
return readPolygonText(tokenizer, ordinateFlags);
}

auto component = readGeometryTaggedText(tokenizer, ordinateFlags);
if (dynamic_cast<CurvePolygon*>(component.get())) {
GeometryTypeId defaultType = GEOS_POLYGON;
auto component = readGeometryTaggedText(tokenizer, ordinateFlags, &defaultType);
if (dynamic_cast<Surface*>(component.get())) {
return component;
}

Expand Down
Loading

0 comments on commit 794c9a4

Please sign in to comment.