public int?SplitTile(List <VectorTileFeature> startfeatures, VectorTileCoord startCoord, int?cz = null, int?cx = null, int?cy = null)
        {
            var stack = new Stack <GeoJsonVTStackItem>();

            stack.Push(new GeoJsonVTStackItem {
                Features = startfeatures, Coord = startCoord
            });


            int?solid = null;

            while (stack.Count > 0)
            {
                var item     = stack.Pop();
                var features = item.Features;
                var x        = item.Coord.X;
                var y        = item.Coord.Y;
                var z        = item.Coord.Z;

                var        z2   = 1 << z;
                var        id   = item.Coord.ToID();
                VectorTile tile = Tiles.Contains(id) ? Tiles.Get(id) : null;



                if (tile == null)
                {
                    var tileTolerance = z == Options.MaxZoom ? 0 : Options.Tolerance / (z2 * Options.Extent);

                    tile = Tiles.Set(id, VectorTile.CreateTile(features, z2, x, y, tileTolerance, z == Options.MaxZoom));
                    Tiles.TileCoords.Add(new VectorTileCoord(z, x, y));
                }

                // save reference to original geometry in tile so that we can drill down later if we stop now
                tile.Source = features;

                // if it's the first-pass tiling
                if (!cz.HasValue)
                {
                    // stop tiling if we reached max zoom, or if the tile is too simple
                    if (z == Options.IndexMaxZoom || tile.NumPoints <= Options.IndexMaxPoints)
                    {
                        continue;
                    }

                    // if a drilldown to a specific tile
                }
                else
                {
                    // stop tiling if we reached base zoom or our target tile zoom
                    if (z == Options.MaxZoom)
                    {
                        continue;
                    }

                    // stop tiling if it's not an ancestor of the target tile
                    if (cz.HasValue)
                    {
                        if (z == cz.Value)
                        {
                            continue;
                        }

                        var m = 1 << (cz.Value - z);
                        if (x != (int)Math.Floor((double)cx.Value / m) || y != (int)Math.Floor((double)cy.Value / m))
                        {
                            continue;
                        }
                    }
                }

                // stop tiling if the tile is solid clipped square
                if (!Options.SolidChildren && IsClippedSquare(tile, Options.Extent, Options.Buffer))
                {
                    if (cz.HasValue)
                    {
                        solid = z;              // and remember the zoom if we're drilling down
                    }
                    continue;
                }

                // if we slice further down, no need to keep source geometry
                tile.Source = null;

                //  if (debug > 1) console.time('clipping');

                // values we'll use for clipping
                var k1 = 0.5 * Options.Buffer / Options.Extent;
                var k2 = 0.5 - k1;
                var k3 = 0.5 + k1;
                var k4 = 1 + k1;
                List <VectorTileFeature> tl, bl, tr, br, left, right;

                tl = bl = tr = br = null;

                left  = Clipper.Clip(features, z2, x - k1, x + k3, 0, IntersectX, tile.Min[0], tile.Max[0]);
                right = Clipper.Clip(features, z2, x + k2, x + k4, 0, IntersectX, tile.Min[0], tile.Max[0]);

                if (left.HasAny())
                {
                    tl = Clipper.Clip(left, z2, y - k1, y + k3, 1, intersectY, tile.Min[1], tile.Max[1]);
                    bl = Clipper.Clip(left, z2, y + k2, y + k4, 1, intersectY, tile.Min[1], tile.Max[1]);
                }

                if (right.HasAny())
                {
                    tr = Clipper.Clip(right, z2, y - k1, y + k3, 1, intersectY, tile.Min[1], tile.Max[1]);
                    br = Clipper.Clip(right, z2, y + k2, y + k4, 1, intersectY, tile.Min[1], tile.Max[1]);
                }

                //   if (debug > 1) console.timeEnd('clipping');

                if (tl.HasAny())
                {
                    stack.Push(new GeoJsonVTStackItem {
                        Features = tl, Coord = new VectorTileCoord(z + 1, x * 2, y * 2)
                    });
                }
                if (bl.HasAny())
                {
                    stack.Push(new GeoJsonVTStackItem {
                        Features = bl, Coord = new VectorTileCoord(z + 1, x * 2, y * 2 + 1)
                    });
                }
                if (tr.HasAny())
                {
                    stack.Push(new GeoJsonVTStackItem {
                        Features = tr, Coord = new VectorTileCoord(z + 1, x * 2 + 1, y * 2)
                    });
                }
                if (br.HasAny())
                {
                    stack.Push(new GeoJsonVTStackItem {
                        Features = br, Coord = new VectorTileCoord(z + 1, x * 2 + 1, y * 2 + 1)
                    });
                }
            }

            return(solid);
        }