public void process_points_clip_of_feature_expect_clipped_feature() { var features = this.getSimplePointFeatures(); var clipper = new Clipper(); double buffer = 0.015625d; double z2 = 8192; double y = 3079; double k1 = 0.0078125d; double k2 = 0.4921875d; double k3 = 0.5078125d; double k4 = 1.0078125d; double minY = 0.37590819401923736d; double maxY = 0.375915411794357d; var topLeft = clipper.Clip(features, z2, y - k1, y + k3, Axis.Y, minY, maxY); var bottomLeft = clipper.Clip(features, z2, y + k2, y + k4, Axis.Y, minY, maxY); // The Top Left will have both points // Assert.AreEqual(2, topLeft.Count()); // The Bottom Left will only have one of the points // Assert.AreEqual(1, bottomLeft.Count()); var single = bottomLeft.Single() as Feature; Assert.AreEqual("777", single.Id); }
public void process_points_clip_of_feature_expect_no_clipped_feature() { var features = this.getSimplePointFeatures(); var clipper = new Clipper(); double buffer = 0.015625d; var left = clipper.Clip(features, scale: 1, k1: (-1 - buffer), k2: buffer, minAll: -1, maxAll: 2, axis: Axis.X); var right = clipper.Clip(features, scale: 1, k1: (1 - buffer), k2: (2 + buffer), minAll: -1, maxAll: 2, axis: Axis.X); Assert.AreEqual(0, left.Count()); Assert.AreEqual(0, right.Count()); }
public void ClipRepeats() { Equipment itemOne = new Equipment(EquipmentType.OneHand, Rarity.Rare, 2); Equipment itemTwo = new Equipment(EquipmentType.Shield, Rarity.Magic, 2); Equipment itemThree = new Equipment(EquipmentType.Body, Rarity.Normal, 2); var equipment = new List <Equipment> { itemOne, itemTwo, itemThree }; Clipper clipper = new Clipper(ClipStrategy.CLIP_REPEAT, 3, new[] { ClipPriority.MOST_RARE }); Dictionary <Equipment, int> result = clipper.Clip(equipment); Assert.AreEqual(2, result[itemOne]); Assert.AreEqual(1, result[itemTwo]); Assert.AreEqual(2, result.Count); }
public void ClipAllTwice() { Equipment itemOne = new Equipment(2); Equipment itemTwo = new Equipment(2); Equipment itemThree = new Equipment(1); var equipment = new List <Equipment> { itemOne, itemTwo, itemThree }; Clipper clipper = new Clipper(ClipStrategy.CLIP_ALL, 2); Dictionary <Equipment, int> result = clipper.Clip(equipment); Assert.AreEqual(2, result[itemOne]); Assert.AreEqual(2, result[itemTwo]); Assert.AreEqual(1, result[itemThree]); }
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); }
/// <summary> /// /// </summary> /// <remarks> /// GeoJSONVT.prototype.splitTile /// </remarks> /// <param name="features"></param> /// <param name="zoom"></param> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> internal int?SplitTile(IGeometryItem[] features, int zoom, int x, int y, int?currentZoom, int?currentX, int?currentY) { int?solidZoom = null; var tileStack = new Stack <object>(); tileStack.Push(y); tileStack.Push(x); tileStack.Push(zoom); tileStack.Push(features); while (tileStack.Count > 0) { features = (IGeometryItem[])tileStack.Pop(); zoom = (int)tileStack.Pop(); x = (int)tileStack.Pop(); y = (int)tileStack.Pop(); var zoomSqr = 1 << zoom; var tileTolerance = zoom == tileContext.MaxZoom ? 0 : tileContext.Tolerance / (zoomSqr * tileContext.Extent); ITile currentTile = cacheAccessor.GetRawTile(tileContext.Identifier, zoom, x, y); // If the tile is null then this is a creation of a tile // if (currentTile == null) { currentTile = CreateTile(features, zoomSqr, x, y, tileTolerance, zoom != tileContext.MaxZoom); cacheAccessor.StoreRawTile(tileContext.Identifier, zoom, x, y, currentTile); } // TO-DO: figure out if this can be moved to the interals of currentTile // currentTile.Source = features; // If this is the first-pass Tiling // if (!currentZoom.HasValue) { // Short circuit and return // if (zoom == tileContext.MaxZoomIndex || currentTile.NumberOfPoints <= tileContext.MaxAllowablePoints) { continue; } } else // Drill down to a specific Tile // { // stop tiling if we've reached base zoom or our target tile zoom // if (zoom == tileContext.MaxZoom || zoom == currentZoom) { continue; } // STOP tiling if it's not an ancestor of the target tile // var m = 1 << (currentZoom - zoom); double dividendX = currentX.Value / m.Value; double dividendY = currentY.Value / m.Value; if (x != Math.Floor(dividendX) || y != Math.Floor(dividendY)) { continue; } } // stop tiling if the tile is a solid clipped square // if (!tileContext.SolidChildren && transform.IsClippedSquare(currentTile, tileContext.Extent, tileContext.Buffer)) { // Remember the current zoom if we are drilling down // if (currentZoom.HasValue) { solidZoom = zoom; } continue; } // If we slice further down no need to keep source geometry // currentTile.Source = null; // Values used for Clipping // var k1 = 0.5 * (tileContext.Buffer / tileContext.Extent); var k2 = 0.5 - k1; var k3 = 0.5 + k1; var k4 = 1 + k1; var clipper = new Clipper(); var left = clipper.Clip(features, scale: zoomSqr, k1: x - k1, k2: x + k3, axis: Axis.X, minAll: currentTile.Min.X, maxAll: currentTile.Max.X); var right = clipper.Clip(features, scale: zoomSqr, k1: x + k2, k2: x + k4, axis: Axis.X, minAll: currentTile.Min.X, maxAll: currentTile.Max.X); // set up the four sections of tiles // IGeometryItem[] topLeft = null; IGeometryItem[] bottomLeft = null; IGeometryItem[] topRight = null; IGeometryItem[] bottomRight = null; if (left != null && left.Length > 0) { topLeft = clipper.Clip(left, scale: zoomSqr, k1: y - k1, k2: y + k3, axis: Axis.Y, minAll: currentTile.Min.Y, maxAll: currentTile.Max.Y); bottomLeft = clipper.Clip(left, scale: zoomSqr, k1: y + k2, k2: y + k4, axis: Axis.Y, minAll: currentTile.Min.Y, maxAll: currentTile.Max.Y); } if (right != null && right.Length > 0) { topRight = clipper.Clip(right, scale: zoomSqr, k1: y - k1, k2: y + k3, axis: Axis.Y, minAll: currentTile.Min.Y, maxAll: currentTile.Max.Y); bottomRight = clipper.Clip(right, scale: zoomSqr, k1: y + k2, k2: y + k4, axis: Axis.Y, minAll: currentTile.Min.Y, maxAll: currentTile.Max.Y); } if (features != null && features.Length > 0) { tileStack.Push(y * 2); tileStack.Push(x * 2); tileStack.Push(zoom + 1); tileStack.Push(topLeft); tileStack.Push(y * 2 + 1); tileStack.Push(x * 2); tileStack.Push(zoom + 1); tileStack.Push(bottomLeft); tileStack.Push(y * 2); tileStack.Push(x * 2 + 1); tileStack.Push(zoom + 1); tileStack.Push(topRight); tileStack.Push(y * 2 + 1); tileStack.Push(x * 2 + 1); tileStack.Push(zoom + 1); tileStack.Push(bottomRight); } } return(solidZoom); }