static void WriteComponentGeometryFragment(JsonTextWriter writer, Geometry geom, string name, DatedElectionResult[] results, DatedTPPResult[] tppResults, int? no = null)
        {
            if (results.Length == 0)
                return;

            int number = no.HasValue ? no.Value : 0;
            double area = geom.Area();

            //To keep the CZML payload to only the main areas (and not islands), don't write CZML packets for
            //island parts
            if (area < MIN_AREA)
                return;

            //Debug.WriteLine($"{name}: {number} - {area}");

            //if (!_areas.ContainsKey(name))
            //    _areas[name] = area;
            //else
            //    _areas[name] = Math.Max(_areas[name], area);

            // {
            writer.WriteStartObject();
            {
                var ring = geom.GetGeometryRef(0);
                var ptCount = ring.GetPointCount();

                // "id": "Electorate/<electorate>/<number>"
                writer.WritePropertyName("id");
                writer.WriteValue($"Electorate/{name}/{number}");
                // "name": "<electorate>"
                writer.WritePropertyName("name");
                writer.WriteValue("Federal Electorate");
                // "description": "<electorate>"
                writer.WritePropertyName("description");
                writer.WriteValue(name);
                // "parent": "Electorate/<electorate>"
                writer.WritePropertyName("parent");
                writer.WriteValue($"Electorate/{name}");
                
                // "polygon": {
                writer.WritePropertyName("polygon");
                writer.WriteStartObject();
                {
                    // "outline" {
                    writer.WritePropertyName("outline");
                    writer.WriteStartObject();
                    {
                        writer.WritePropertyName("boolean");
                        writer.WriteValue(true);
                    }
                    writer.WriteEndObject(); // }

                    // "outlineColor" {
                    writer.WritePropertyName("outlineColor");
                    writer.WriteStartObject();
                    {
                        // "rgba": [
                        writer.WritePropertyName("rgba");
                        writer.WriteStartArray();
                        {
                            //Black
                            writer.WriteValue(0);
                            writer.WriteValue(0);
                            writer.WriteValue(0);
                            writer.WriteValue(255);
                        }
                        writer.WriteEndArray(); // ]
                    }
                    writer.WriteEndObject(); // }

                    // "material": {
                    writer.WritePropertyName("material");
                    writer.WriteStartObject();
                    {
                        // "solidColor": {
                        writer.WritePropertyName("solidColor");
                        writer.WriteStartObject();
                        {
                            // "color": {
                            writer.WritePropertyName("color");
                            writer.WriteStartObject();
                            {
                                // "epoch": <start>
                                writer.WritePropertyName("epoch");
                                writer.WriteValue(_sceneStart);

                                // "rgba": [
                                writer.WritePropertyName("rgba");
                                writer.WriteStartArray();
                                {
                                    //HACK: This example doesn't take into account that electorate redistribution occurs
                                    //Meaning that our 2015 snapshot of Australian Federal Electorates may contain electorates
                                    //that either have changed or did not exist in earlier Federal Elections. Since the AEC does
                                    //not publicly provide such data, we'll denote such electorates as unknown (White)
                                    //
                                    //So peek at the first result, if it's dated on our first Federal Election we know the
                                    //electorate existed back then
                                    bool bDidNotExistIn2004 = !(results[0].ElectionDate.Year == _dtStart.Year &&
                                        results[0].ElectionDate.Month == _dtStart.Month &&
                                        results[0].ElectionDate.Day == _dtStart.Day);

                                    if (bDidNotExistIn2004)
                                    {
                                        //0 seconds since epoch
                                        writer.WriteValue(0);
                                        //White
                                        writer.WriteValue(255);
                                        writer.WriteValue(255);
                                        writer.WriteValue(255);
                                        writer.WriteValue(COLOR_ALPHA);
                                    }
                                    else
                                    {
                                        //0 seconds since epoch
                                        writer.WriteValue(0);

                                        int[] color = GetPartyColor(results[0].PartyNm);
                                        foreach (var c in color)
                                        {
                                            writer.WriteValue(c);
                                        }
                                    }

                                    foreach (var result in results.Skip(1))
                                    {
                                        int dt = (int)result.ElectionDate.Subtract(_dtStart).TotalSeconds;
                                        writer.WriteValue(dt);
                                        int[] color = GetPartyColor(result.PartyNm);
                                        foreach (var c in color)
                                        {
                                            writer.WriteValue(c);
                                        }
                                    }
                                }
                                writer.WriteEndArray(); // ]
                            }
                            writer.WriteEndObject(); // }
                        }
                        writer.WriteEndObject(); // }
                    }
                    writer.WriteEndObject(); // }

                    // "extrudedHeight": {
                    /*
                    writer.WritePropertyName("extrudedHeight");
                    writer.WriteStartObject();
                    {
                        // "epoch": <start>
                        writer.WritePropertyName("epoch");
                        writer.WriteValue(_sceneStart);

                        // "number": [
                        writer.WritePropertyName("number");
                        writer.WriteStartArray();
                        {
                            //HACK: This example doesn't take into account that electorate redistribution occurs
                            //Meaning that our 2015 snapshot of Australian Federal Electorates may contain electorates
                            //that either have changed or did not exist in earlier Federal Elections. Since the AEC does
                            //not publicly provide such data, we'll denote such electorates as unknown (White)
                            //
                            //So peek at the first result, if it's dated on our first Federal Election we know the
                            //electorate existed back then
                            bool bDidNotExistIn2004 = !(tppResults[0].ElectionDate.Year == _dtStart.Year &&
                                tppResults[0].ElectionDate.Month == _dtStart.Month &&
                                tppResults[0].ElectionDate.Day == _dtStart.Day);

                            if (bDidNotExistIn2004)
                            {
                                //0 seconds since epoch
                                writer.WriteValue(0);
                                //0 height
                                writer.WriteValue(0);
                            }
                            else
                            {
                                //0 seconds since epoch
                                writer.WriteValue(0);
                                //The winning party's percentage
                                writer.WriteValue(Math.Max(tppResults[0].LaborPc, tppResults[0].CoalitionPc) * EXTRUSION_MULTIPLIER);
                            }

                            foreach (var tppResult in tppResults.Skip(1))
                            {
                                int dt = (int)tppResult.ElectionDate.Subtract(_dtStart).TotalSeconds;
                                writer.WriteValue(dt);
                                //The winning party's percentage
                                writer.WriteValue(Math.Max(tppResults[0].LaborPc, tppResults[0].CoalitionPc) * EXTRUSION_MULTIPLIER);
                            }
                        }
                        writer.WriteEndArray(); // ]
                    }
                    writer.WriteEndObject(); // }
                    */
                    // "positions": {
                    writer.WritePropertyName("positions");
                    writer.WriteStartObject();
                    {
                        // "cartographicDegrees": [
                        writer.WritePropertyName("cartographicDegrees");
                        writer.WriteStartArray();
                        {
                            double[] coords = new double[3];
                            foreach (int idx in Enumerable.Range(0, ptCount - 1))
                            {
                                ring.GetPoint(idx, coords);
                                foreach (double coord in coords)
                                {
                                    writer.WriteValue(coord);
                                }
                            }
                        }
                        writer.WriteEndArray(); // ]
                    }
                    writer.WriteEndObject(); // }
                }
                writer.WriteEndObject(); // }
            }
            writer.WriteEndObject(); // }
        }
        static void WritePacket(JsonTextWriter writer, Feature feat, string name, DatedElectionResult[] results, DatedTPPResult[] tppResults)
        {
            Console.WriteLine($"Writing CZML packets for electorate: {name} ");
            
            writer.WriteStartObject(); // {
            {
                // "id": "Electorate/<electorate>"
                writer.WritePropertyName("id");
                writer.WriteValue($"Electorate/{name}");
                // "name": "<electorate>"
                writer.WritePropertyName("name");
                writer.WriteValue(name);
            }
            writer.WriteEndObject(); // }

            var geom = feat.GetGeometryRef();
            string geomName = geom.GetGeometryName();
            if (geomName == "MULTIPOLYGON")
            {
                var subGeomCount = geom.GetGeometryCount();
                foreach (int idx in Enumerable.Range(0, subGeomCount - 1))
                {
                    var subGeom = geom.GetGeometryRef(idx);
                    WriteComponentGeometryFragment(writer, subGeom, name, results, tppResults, idx);
                    Console.Write(".");
                }
                Console.WriteLine();
            }
            else if (geomName == "POLYGON")
            {
                WriteComponentGeometryFragment(writer, geom, name, results, tppResults);
            }
        }