How do you make a rectangle using the GEOS library's C++ API?
Asked
Active
Viewed 2,787 times
4
-
I'm certainly no expert with the [tag:geos] library (1st time I read about this here). Though, a 2 minute research lead me to [`geos::geom::Polygon`](http://geos.osgeo.org/doxygen/classgeos_1_1geom_1_1Polygon.html), wich looks like a good starting point. (Lack of research is also a closing reason on SO). If you have experienced some particular problems with this, please elaborate your question. – πάντα ῥεῖ Dec 25 '14 at 00:23
-
1Thank you for your help, @πάντα ῥεῖ. I would not have asked the question were the search you performed sufficient, and made the posting only after what I felt was adequate research. The actual answer I cobbled together is more convoluted than probably either of us would have expected, especially for what seems to be a widely-used library. – Richard Dec 25 '14 at 01:35
-
2As regards your first comment, @πάντα ῥεῖ, I think the question is well-formed and was not seeking resources which would attract opinionated answers/spam. With my rep, I've seen sufficient of these questions to know how useful they can be to future coders. – Richard Dec 25 '14 at 01:38
-
_@Richard_ _"I think the question is well-formed .."_ Well, I'm not the only one. There are aleady 3 other users spotting this problem as well. If you have a broad question, and want to make it a _canonical Q&A_, research 1st, and post question and answer in one go. That will make it better acheived in the short term vs seeing a poor question unanswered. ([here's a good sample](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) of what I'm referring to). – πάντα ῥεῖ Dec 25 '14 at 01:45
-
@πάντα ῥεῖ, I shall certainly do so next time. In the meantime, I have edited the question to better conform to the example you have provided. – Richard Dec 25 '14 at 02:33
-
Well, I've put an upvote on your answer, but I still have doubts this queston will fly well up as a _canonical_. – πάντα ῥεῖ Dec 25 '14 at 02:36
-
4This question, and its answer were very useful. Really isn't anything out there to give concise examples. This is what I found on the internet. If every "How do I" question was closed on Stack Overflow there wouldn't be any posts! – Ben DeMott Oct 08 '15 at 02:04
-
Thanks @BenMott. If this was useful to you feel free to upvote if you can and/or suggest reopening if you'd like. – Richard Oct 08 '15 at 04:13
-
Unfortunately, the c++ example does not compile anymore with c++11 gcc. Also, the geos c++ port itself is now saying that the cpp api is unstable and are recommending the use of the c api. – kalyanswaroop Apr 10 '21 at 04:56
1 Answers
9
The following implementation gets the job done in GEOS.
//Compile with: g++ code.cpp -lgeos
//Updated: 2019-03-31
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/Polygon.h>
#include <geos/geom/LinearRing.h>
#include <geos/geom/CoordinateSequenceFactory.h>
#include <geos/geom/Geometry.h>
#include <geos/geom/GeometryFactory.h>
#include <iostream>
#include <memory>
geos::geom::Polygon* MakeBox(double xmin, double ymin, double xmax, double ymax){
std::unique_ptr<geos::geom::PrecisionModel> pm(new geos::geom::PrecisionModel());
geos::geom::GeometryFactory::unique_ptr factory = geos::geom::GeometryFactory::create(pm.get(), -1);
geos::geom::CoordinateSequence *temp = factory->getCoordinateSequenceFactory()->create((std::size_t) 0, 0);
temp->add(geos::geom::Coordinate(xmin, ymin));
temp->add(geos::geom::Coordinate(xmin, ymax));
temp->add(geos::geom::Coordinate(xmax, ymax));
temp->add(geos::geom::Coordinate(xmax, ymin));
//Must close the linear ring or we will get an error:
//"Points of LinearRing do not form a closed linestring"
temp->add(geos::geom::Coordinate(xmin, ymin));
geos::geom::LinearRing *shell=factory->createLinearRing(temp);
//NULL in this case could instead be a collection of one or more holes
//in the interior of the polygon
return factory->createPolygon(shell,NULL);
}
int main(){
geos::geom::Polygon* box = MakeBox(0,0,10,10);
std::cout<<box->getArea()<<std::endl;
delete box; //Important to avoid memory leaks
}
For reference, you can also accomplish this using the boost::polygon library, as follows.
//Compile with: g++ code.cpp
#include <boost/polygon/polygon.hpp>
#include <iostream>
namespace gtl = boost::polygon;
typedef gtl::polygon_data<float> Polygon;
Polygon MakeBox(float xmin, float ymin, float xmax, float ymax){
typedef gtl::polygon_traits<Polygon>::point_type Point;
Point pts[] = {
gtl::construct<Point>(xmin, ymin),
gtl::construct<Point>(xmin, ymax),
gtl::construct<Point>(xmax, ymax),
gtl::construct<Point>(xmax, ymin)
};
Polygon poly;
gtl::set_points(poly, pts, pts+4);
return poly;
}
int main(){
Polygon box = MakeBox(0,0,10,10);
std::cout<<gtl::area(box)<<std::endl;
}
And also with Clipper. Note that Clipper cannot use floating-point coordinates.
#include "clipper_cpp/clipper.hpp"
#include <iostream>
ClipperLib::Paths MakeBox(int xmin, int ymin, int xmax, int ymax){
ClipperLib::Paths box(1);
//Note that we run the path in the reverse direction to previous examples in
//order to maintain positive area
box[0] << ClipperLib::IntPoint(xmin,ymin) << ClipperLib::IntPoint(xmax,ymin)
<< ClipperLib::IntPoint(xmax,ymax) << ClipperLib::IntPoint(xmin,ymax);
return box;
}
int main(){
ClipperLib::Paths box = MakeBox(0,0,10,10);
std::cout<<ClipperLib::Area(box[0])<<std::endl;
}

Richard
- 56,349
- 34
- 180
- 251