public void Test_VisitCells_QueryEdgeOnFaceBoundary() { int kIters = 100; for (int iter = 0; iter < kIters; ++iter) { _logger.WriteLine("Iteration " + iter); // Choose an edge AB such that B is nearly on the edge between two S2 cube // faces, and such that the result of clipping AB to the face that nominally // contains B (according to S2.GetFace) is empty when no padding is used. int a_face, b_face; S2Point a, b; R2Point a_uv, b_uv; do { a_face = S2Testing.Random.Uniform(6); a = S2.FaceUVtoXYZ(a_face, S2Testing.Random.UniformDouble(-1, 1), S2Testing.Random.UniformDouble(-1, 1)).Normalize(); b_face = S2.GetUVWFace(a_face, 0, 1); // Towards positive u-axis var uTmp = 1 - S2Testing.Random.Uniform(2) * 0.5 * S2.DoubleEpsilon; b = S2.FaceUVtoXYZ(b_face, uTmp, S2Testing.Random.UniformDouble(-1, 1)).Normalize(); } while (S2.GetFace(b) != b_face || S2EdgeClipping.ClipToFace(a, b, b_face, out a_uv, out b_uv)); // Verify that the clipping result is non-empty when a padding of // S2EdgeClipping.kFaceClipErrorUVCoord is used instead. Assert.True(S2EdgeClipping.ClipToPaddedFace(a, b, b_face, S2EdgeClipping.kFaceClipErrorUVCoord, out a_uv, out b_uv)); // Create an S2ShapeIndex containing a single edge BC, where C is on the // same S2 cube face as B (which is different than the face containing A). S2Point c = S2.FaceUVtoXYZ(b_face, S2Testing.Random.UniformDouble(-1, 1), S2Testing.Random.UniformDouble(-1, 1)).Normalize(); MutableS2ShapeIndex index = new(); index.Add(new S2Polyline.OwningShape( new S2Polyline(new S2Point[] { b, c }))); // Check that the intersection between AB and BC is detected when the face // containing BC is specified as a root cell. (Note that VisitCells() // returns false only if the CellVisitor returns false, and otherwise // returns true.) S2CrossingEdgeQuery query = new(index); S2PaddedCell root = new(S2CellId.FromFace(b_face), 0); Assert.False(query.VisitCells(a, b, root, (S2ShapeIndexCell x) => false)); } }
// Returns true if any edge of the indexed shape "clipped" intersects the // cell "target". It may also return true if an edge is very close to // "target"; the maximum error is less than 10 * S2Constants.DoubleEpsilon radians (about // 15 nanometers). private bool AnyEdgeIntersects(S2ClippedShape clipped, S2Cell target) { var bound = target.BoundUV.Expanded(kMaxError); var face = target.Face; var shape = Index().Shape(clipped.ShapeId); int num_edges = clipped.NumEdges; for (int i = 0; i < num_edges; ++i) { var edge = shape.GetEdge(clipped.Edge(i)); if (S2EdgeClipping.ClipToPaddedFace(edge.V0, edge.V1, face, kMaxError, out var p0, out var p1) && S2EdgeClipping.IntersectsRect(p0, p1, bound)) { return(true); } } return(false); }