-
The algorithms that form the core value of GEOS are developed in Java in the JTS library. C++ developers will find this annoying, but:
- This is just history, JTS was written first and GEOS was a slavish port.
- Being memory managed, JTS is an easier language to prototype in.
- Having various visual tooling, JTS is an easier platform to debug spatial algorithms in.
- Being Java, JTS has less language legacy than GEOS, which was originally ported when STL was still not part of the standard, and therefor reflects a mix of styles and eras.
-
Ideally, new algorithms will be implemented in JTS and then ported to GEOS.
-
Smaller performance optimizations in GEOS can travel back to JTS.
- Short circuits, indexes, other non-language optimizations, should be ticketed in JTS when they are added to GEOS.
-
Don't rename things! It makes it harder to port updates and fixes.
-
Class names
-
Method names
-
Variable names
-
Class members
- Yes, we know in your last job you were taught all member variables are prefixed with
m_
, but please don't.
- Yes, we know in your last job you were taught all member variables are prefixed with
-
- Frequently objects are only used local to a method and not returned to the caller.
- In such cases, avoid lifecycle issues entirely by instantiating on the local stack.
MyObj foo = new MyObj("bar");
MyObj foo("bar");
- Long-lived members of objects that are passed around should be held using std::unique_ptr<>.
private MyMember foo = new MyMember();
private:
std::unique_ptr<MyMember> foo;
public:
MyMember()
: foo(new MyMember())
{}
- You can pass pointers to the object to other methods using
std::unique_ptr<>.get()
.
-
Heap allocations (objects created using
new
) are more expensive than stack allocations, but they can show up in batchs in JTS in places where structures are built, like index trees, or graphs. -
To both lower the overhead of heap allocations, and to manage the life-cycle of the objects, we recommend storing small objects in an appropriate "double-ended queue", like std::deque<>.
-
The implementation of
edgegraph
is an example.-
The
edgegraph
consists of a structure of manyHalfEdge
objects (two for each edge!), created in theEdgeGraph::createEdge()
method and stored in astd::deque<>
. -
The
std::deque<>
provides two benefits:- It lowers the number of heap allocations, because it allocates larger blocks of space to store multiple
HalfEdge
objects. - It handles the lifecycle of the
HalfEdge
objects that make up theEdgeGraph
, because when theEdgeGraph
is deallocated, thestd::deque<>
and all its contents are also automatically deallocated.
- It lowers the number of heap allocations, because it allocates larger blocks of space to store multiple
-