Spherical Toolkit Spherical Toolkit -
- - -
- -
- - - - -
- -

Learn by Examples

These simple examples are here to guide you on your first journey into programming with halfspaces, convexes and regions as well as the HTM both in C# and SQL. Are we missing something basic? Please let us know today!


Points on the sphere are represented as 3D unit vectors. You can create one using the (x,y,z) coordinates or even (RA, Dec) as in the following example:

Cartesian p1 = new Cartesian(180, 0);
Cartesian p2 = new Cartesian(181, 0);

Halfspaces are simplest contructs that can specify spherical caps of any direction and size. They are defined by the center point and the radius. Here we create two using the previous points and build a convex that represents their intersections:

double theta = Math.PI / 180; // 1 degree radii
Halfspace h1 = new Halfspace(p1, Math.Cos(theta));
Halfspace h2 = new Halfspace(p2, Math.Cos(theta));

Convex c = new Convex();

A region is a union of convexes. Here we define one using two convexes. The simplification step creates an irreducible representation and calculates the analytic area:

Region r = new Region();

The toolkit provides the full Boolean algebra for regions. Below is how you can create the union of two regions:

r.Union(r2); // regions may not be simplified
r.Simplify(); // simplification from scratch

An even better way is the following that makes use of the fully simplified representations:

r.SmartUnion(r2); // both simplified

Calculating the HTM index of a point is as easy as the function call:

Cartesian p = new Cartesian(180,0); // Point on the sky
Int64 htmID = Trixel.CartesianToHid20(p); // and its ID

Another function returns the vertices of a given trixel:

Cartesian v1, v2, v3; // Vertices of the trixel Trixel.ToTriangle(htmID, out v1, out v2, out v3);

The HTM cover of a region is an approximate description for speeding up searches. These covers can be completely inside the region (Markup.Inner) or completely cover it (Markup.Outer) Instantiate a cover object to investigate its properties as in this example:

Cover k = new Cover(region);
k.Run(); // Default processing, see also k.Step()
List<Int64> inner = k.GetTrixels(Markup.Inner);
List<Int64> outer = k.GetTrixels(Markup.Outer);

We current do not supply ready-to-use indexing mechanisms that implement the actual search pattern but this is fairly straighforward to do. We expect that programmers will use specific solutions that are most suited for their data structures. Better yet, use a database engine with proper indices.


The easiest way to create simple regions is to use our region specification language, which is also available for .NET programmers via the parser in the Shape namespace. The description follows a few simple rules that can be deduced from the following examples but we also have a BNF specification available for the purists in the documentation. Here is how to create regions in SQL using these strings, create their unions and return their areas:

SELECT @s = 'REGION CIRCLE J2000 180 0 60',
       @z = 'POLY J2000 180 0 182 0 182 2 180 2',
       @r = sph.fSimplifyString(@s),
       @u = sph.fUnion(@r,sph.fSimplifyString(@z))
SELECT sph.fGetArea(@r), SELECT sph.fGetArea(@u)
-- Returns: 3.14151290574491 6.35572804450646

One of the most basic HTM tasks is to compute the HTM addresses or HtmID for all entries of a table. The following simple command assumes that the specified table was defined with the appropriate HTM column and populates that using the (RA, Dec) positions that are also stored for each row:

UPDATE PhotoObj SET HtmID = dbo.fHtmEq(RA,Dec)

The query below is perhaps the most advanced of them all. It creates the HTM cover for a given region on the fly and uses the resulting ranges to filter the catalog. While this will overshoot and return more than what is covered by the specified region, it will execute very fast. The actual geometry cut can be done in subsequent steps or even written into the same query, but we leave that out here for simplicity.

    SELECT * FROM dbo.fHtmCoverRegion
      ('REGION CIRCLE J2000 180 0 10')
FROM PhotoObj AS o INNER JOIN Cover AS c
    ON o.HtmID BETWEEN c.HtmIDStart AND c.HtmIDEnd

Simple, isn't it? Why don't you try it now and let us know how it goes. Enjoy!

- - - - -