In my last post, I looked at the CircularString geometry introduced in SQL Server Denali, which allows you to define circular curve segments between points in a series, with each circular arc segment defined by a anchor point between the two endpoints.
In this post, I’ll look at another new geometry type – the CompoundCurve. Whereas the LineString defines a one dimensional geometry by linear interpolation between a series of points, and the CircularString uses circular interpolation, the CompoundCurve can include a mixture of both of these types.
Here’s the WKT syntax for a CompoundCurve consisting of two line segments and two circular arc segments. Notice that circular arc segments within the curve must be prefixed by CIRCULARSTRING, whereas linear segments do not require (and, in fact, must not have) the corresponding LINESTRING keyword.
DECLARE @CompoundCurve geometry = 'COMPOUNDCURVE((5 3, 5 13), CIRCULARSTRING(5 13, 7 15, 9 13), (9 13, 9 3), CIRCULARSTRING(9 3, 7 1, 5 3))'
What’s interesting is that we don’t actually need to use the CompoundCurve to define this geometry – the CircularString geometry alone can contain a mixture of curved and straight edges: for straight line edges, the anchor point simply needs to lie on the straight line between the start and end point. We therefore could create exactly the same geometry using the CircularString by defining one additional anchor point on each of the straight edge sides as follows:
DECLARE @CircularString geometry = 'CIRCULARSTRING(5 3, 5 8, 5 13, 7 15, 9 13, 9 8, 9 3, 7 1, 5 3)';
In fact, as stated earlier, the CompoundCurve is much like a GeometryCollection containing a mixture of LineStrings and CircularStrings. We could therefore also define this same geometry as follows:
DECLARE @GeometryCollection geometry = 'GEOMETRYCOLLECTION(LINESTRING(5 3, 5 13), CIRCULARSTRING(5 13, 7 15, 9 13), LINESTRING(9 13, 9 3), CIRCULARSTRING(9 3, 7 1, 5 3))';
All three of these instances contain exactly the same set of points, as can be demonstrated with the following code:
SELECT @CompoundCurve.STEquals(@CircularString); -- returns 1 (true) SELECT @CompoundCurve.STEquals(@GeometryCollection); -- returns 1 (true)
You can also test the length of each instance:
SELECT @CompoundCurve.STLength(); --32.5663706143592 SELECT @CircularString.STLength(); --32.5663706143592 SELECT @GeometryCollection.STLength(); --32.5663706143592
(The two line segments are 10 units long, and the two circular arcs combined form a circle of radius 2 units. (10 * 2) + (2 * PI * 2) = 32.5663706143592)
So why would you ever want to use the CompoundCurve class? Well, although it provides no greater functionality than the two alternatives presented here, and represents exactly the same set of points, it does provide a more efficient way of representing that geometry, certainly in terms of storage space required. Comparing the size of each geometry in this example:
SELECT DATALENGTH(@CompoundCurve), -- 152 DATALENGTH(@CircularString), --176 DATALENGTH(@GeometryCollection) --243
This is because the CompoundCurve doesn’t require the additional overhead of the GeometryCollection (which is capable of storing any type of geometry), nor the additional points required by the CircularString to define the straight line segments.
I don’t know if performing operations against the CompoundCurve would be significantly faster than the other two options but, in the absence of any other factors, it still seems to be the best choice in this situation.