[geos-devel] Patch that adds reading/writing WKB hex format
Charlie Savage
cfis at interserv.com
Sun Jan 8 19:25:09 EST 2006
I'm using geos in a stand-alone library that gets data from a remote
PostGIS server and then does some additional processing. As a result it
would be helpful if geos could read in the wkb hex format that PostGIS
produces. Looking through the GEOS/PostGIS code, I see that the wkb hex
interpretation code is in PostGIS and not geos.
As a result, I have added to geos the methods WKBReader.readHex,
WKBWriter.writeHEX (under the covers it calls WKBReader.printHEX which
already exists, although I'm not sure why its on WKBReader). I also
added a constructor to Envelope that takes a string - the same string
produced by Envelope.toString(). This makes it easy to serialize an
envelope to a string, and then recreate the Envelope later.
Since I thought these changes might be generally useful, I've attached a
patch below. The patch also fixes a few spelling mistakes that I
noticed in some error messages and in the DOxygen API comments.
Thanks,
Charlie
Index: source/headers/geos/io.h
===================================================================
RCS file: /home/cvs/postgis/geos/source/headers/geos/io.h,v
retrieving revision 1.18
diff -u -r1.18 io.h
--- source/headers/geos/io.h 29 Nov 2005 13:39:56 -0000 1.18
+++ source/headers/geos/io.h 8 Jan 2006 23:34:01 -0000
@@ -265,7 +265,7 @@
{
stream->read(reinterpret_cast<char *>(buf), 1);
if ( stream->eof() )
- throw new ParseException("Unespected EOF parsing WKB");
+ throw new ParseException("Unexpected EOF parsing WKB");
return buf[0];
}
@@ -273,7 +273,7 @@
{
stream->read(reinterpret_cast<char *>(buf), 4);
if ( stream->eof() )
- throw new ParseException("Unespected EOF parsing WKB");
+ throw new ParseException("Unexpected EOF parsing WKB");
return ByteOrderValues::getInt(buf, byteOrder);
}
@@ -281,7 +281,7 @@
{
stream->read(reinterpret_cast<char *>(buf), 8);
if ( stream->eof() )
- throw new ParseException("Unespected EOF parsing WKB");
+ throw new ParseException("Unexpected EOF parsing WKB");
return ByteOrderValues::getLong(buf, byteOrder);
}
@@ -289,7 +289,7 @@
{
stream->read(reinterpret_cast<char *>(buf), 8);
if ( stream->eof() )
- throw new ParseException("Unespected EOF parsing WKB");
+ throw new ParseException("Unexpected EOF parsing WKB");
return ByteOrderValues::getDouble(buf, byteOrder);
}
@@ -336,6 +336,17 @@
// throws IOException, ParseException
/**
+ * \brief Reads a Geometry from an istream in hex format.
+ *
+ * @param is the stream to read from
+ * @return the Geometry read
+ * @throws IOException
+ * @throws ParseException
+ */
+ Geometry *readHEX(istream &is);
+ // throws IOException, ParseException
+
+ /**
* \brief Print WKB in HEX form to out stream
*
* @param is is the stream to read from
@@ -419,6 +430,16 @@
WKBWriter(int dims=2, int bo=getMachineByteOrder());
/**
+ * \brief Write a Geometry to an ostream in binary hex format.
+ *
+ * @param g the geometry to write
+ * @param os the output stream
+ * @throws IOException
+ */
+ void
+ WKBWriter::writeHEX(const Geometry &g, ostream &os);
+
+ /**
* \brief Write a Geometry to an ostream.
*
* @param g the geometry to write
Index: source/headers/geos/geom.h
===================================================================
RCS file: /home/cvs/postgis/geos/source/headers/geos/geom.h,v
retrieving revision 1.57
diff -u -r1.57 geom.h
--- source/headers/geos/geom.h 8 Dec 2005 14:14:07 -0000 1.57
+++ source/headers/geos/geom.h 8 Jan 2006 23:30:03 -0000
@@ -1023,6 +1023,7 @@
Envelope(const Coordinate& p1, const Coordinate& p2);
Envelope(const Coordinate& p);
Envelope(const Envelope &env);
+ Envelope::Envelope(const string &str);
~Envelope(void);
static bool intersects(const Coordinate& p1,const Coordinate&
p2,const Coordinate& q);
static bool intersects(const Coordinate& p1,const Coordinate&
p2,const Coordinate& q1,const Coordinate& q2);
@@ -1070,31 +1071,31 @@
/**
* Check if the point p
- * overlaps (lies inside) the region of this Envelope.
+ * intersects (lies inside) the region of this Envelope.
*
* @param p the Coordinate to be tested
- * @return true if the point overlaps this Envelope
+ * @return true if the point intersects this Envelope
*/
inline bool intersects(const Coordinate& p) const;
/**
* Check if the point (x, y)
- * overlaps (lies inside) the region of this Envelope.
+ * intersects (lies inside) the region of this Envelope.
*
* @param x the x-ordinate of the point
* @param y the y-ordinate of the point
- * @return <code>true</code> if the point overlaps this Envelope
+ * @return <code>true</code> if the point intersects this Envelope
*/
inline bool intersects(double x, double y) const;
/**
* Check if the region defined by other Envelope
- * overlaps (intersects) the region of this Envelope.
+ * intersects (intersects) the region of this Envelope.
*
* @param other the Envelope which this Envelope is
- * being checked for overlapping
+ * being checked for intersection
*
- * @return true if the Envelopes overlap
+ * @return true if the Envelopes intersects
*/
inline bool intersects(const Envelope* other) const;
@@ -1104,6 +1105,7 @@
int hashCode() const;
private:
+ vector<string> split(const string &str, const string &delimiters =
" ");
static double distance(double x0,double y0,double x1,double y1);
double minx; /// the minimum x-coordinate
double maxx; /// the maximum x-coordinate
Index: source/geom/Envelope.cpp
===================================================================
RCS file: /home/cvs/postgis/geos/source/geom/Envelope.cpp,v
retrieving revision 1.21
diff -u -r1.21 Envelope.cpp
--- source/geom/Envelope.cpp 8 Nov 2005 10:03:28 -0000 1.21
+++ source/geom/Envelope.cpp 8 Jan 2006 23:18:09 -0000
@@ -135,6 +135,32 @@
init(env.minx, env.maxx, env.miny, env.maxy);
}
+/**
+ * Create an <code>Envelope</code> from an Envelope
+ * string representation produced by Envelope.toString()
+ *
+ * @param env the string Envelope to initialize from
+ */
+Envelope::Envelope(const string &str)
+{
+ // The string should be in the format:
+ // Env[7.2:2.3,7.1:8.2]
+
+ // extract out the values between the [ and ] characters
+ int index = str.find("[");
+ string coordString = str.substr(index + 1, str.size() - 1 - 1);
+
+ // now split apart the string on : and , characters
+ vector<string> values = split(coordString, ":,");
+
+ // create a new envelope
+ init(::atof(values[0].c_str()),
+ ::atof(values[1].c_str()),
+ ::atof(values[2].c_str()),
+ ::atof(values[3].c_str()));
+}
+
+
///Default destructor
Envelope::~Envelope(void) {}
@@ -464,10 +490,39 @@
result = 37 * result + Coordinate::hashCode(minx);
result = 37 * result + Coordinate::hashCode(maxx);
result = 37 * result + Coordinate::hashCode(miny);
- result = 37 * result + Coordinate::hashCode(maxy);
+ result = 37 * result + Coordinate::hashCode(maxy);
return result;
}
+/* This is a generic function that really belongs in a utility
+ file somewhere */
+/**
+ * Splits a string into parts based on the supplied delimiters.
+ */
+vector<string> Envelope::split(const string &str, const string &delimiters)
+{
+ vector<string> tokens;
+
+ // Find first "non-delimiter".
+ string::size_type lastPos = 0;
+ string::size_type pos = str.find_first_of(delimiters, lastPos);
+
+ while (string::npos != pos || string::npos != lastPos)
+ {
+ // Found a token, add it to the vector.
+ tokens.push_back(str.substr(lastPos, pos - lastPos));
+
+ // Skip delimiters. Note the "not_of"
+ lastPos = str.find_first_not_of(delimiters, pos);
+
+ // Find next "non-delimiter"
+ pos = str.find_first_of(delimiters, lastPos);
+ }
+
+ return tokens;
+}
+
+
} // namespace geos
/**********************************************************************
Index: source/io/WKBWriter.cpp
===================================================================
RCS file: /home/cvs/postgis/geos/source/io/WKBWriter.cpp,v
retrieving revision 1.3
diff -u -r1.3 WKBWriter.cpp
--- source/io/WKBWriter.cpp 28 Sep 2005 10:15:34 -0000 1.3
+++ source/io/WKBWriter.cpp 8 Jan 2006 21:00:21 -0000
@@ -27,6 +27,19 @@
}
void
+WKBWriter::writeHEX(const Geometry &g, ostream &os)
+{
+ // setup input/output stream
+ stringstream stream;
+
+ // write the geometry in wkb format
+ this->write(g, stream);
+
+ // convert to HEX
+ WKBReader::printHEX(stream, os);
+}
+
+void
WKBWriter::write(const Geometry &g, ostream &os)
{
outStream = &os;
Index: source/io/WKBReader.cpp
===================================================================
RCS file: /home/cvs/postgis/geos/source/io/WKBReader.cpp,v
retrieving revision 1.11
diff -u -r1.11 WKBReader.cpp
--- source/io/WKBReader.cpp 10 Nov 2005 16:26:12 -0000 1.11
+++ source/io/WKBReader.cpp 8 Jan 2006 20:58:34 -0000
@@ -47,6 +47,132 @@
return os;
}
+Geometry *
+WKBReader::readHEX(istream &is){
+ // setup input/output stream
+ stringstream os;
+
+ unsigned char high, low, result_high, result_low, value;
+
+ while(!is.eof())
+ {
+ // get the high part of the byte
+ is >> high;
+ // geth the low part of the byte
+ is >> low;
+
+ switch (high)
+ {
+ case '0' :
+ result_high = 0;
+ break;
+ case '1' :
+ result_high = 1;
+ break;
+ case '2' :
+ result_high = 2;
+ break;
+ case '3' :
+ result_high = 3;
+ break;
+ case '4' :
+ result_high = 4;
+ break;
+ case '5' :
+ result_high = 5;
+ break;
+ case '6' :
+ result_high = 6;
+ break;
+ case '7' :
+ result_high = 7;
+ break;
+ case '8' :
+ result_high = 8;
+ break;
+ case '9' :
+ result_high = 9;
+ break;
+ case 'A' :
+ result_high = 10;
+ break;
+ case 'B' :
+ result_high = 11;
+ break;
+ case 'C' :
+ result_high = 12;
+ break;
+ case 'D' :
+ result_high = 13;
+ break;
+ case 'E' :
+ result_high = 14;
+ break;
+ case 'F' :
+ result_high = 15;
+ break;
+ }
+
+ switch (low)
+ {
+ case '0' :
+ result_low = 0;
+ break;
+ case '1' :
+ result_low = 1;
+ break;
+ case '2' :
+ result_low = 2;
+ break;
+ case '3' :
+ result_low = 3;
+ break;
+ case '4' :
+ result_low = 4;
+ break;
+ case '5' :
+ result_low = 5;
+ break;
+ case '6' :
+ result_low = 6;
+ break;
+ case '7' :
+ result_low = 7;
+ break;
+ case '8' :
+ result_low = 8;
+ break;
+ case '9' :
+ result_low = 9;
+ break;
+ case 'A' :
+ result_low = 10;
+ break;
+ case 'B' :
+ result_low = 11;
+ break;
+ case 'C' :
+ result_low = 12;
+ break;
+ case 'D' :
+ result_low = 13;
+ break;
+ case 'E' :
+ result_low = 14;
+ break;
+ case 'F' :
+ result_low = 15;
+ break;
+ }
+
+ value = (result_high<<4) + result_low;
+ // write the value to the output stream
+ os << value;
+ }
+
+ // now call read to convert the geometry
+ return this->read(os);
+}
Geometry *
WKBReader::read(istream &is)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 2781 bytes
Desc: S/MIME Cryptographic Signature
Url : http://lists.osgeo.org/pipermail/geos-devel/attachments/20060108/12753795/smime.bin
More information about the geos-devel
mailing list