/// <summary>s /// Checks if the point is inside our hexagon, /// but takes advantage of things we know to make it faster. /// The generic polygon check is way too slow. /// This is meant to be used during puzzle building. /// </summary> /// <param name="p"></param> /// <returns></returns> public bool IsPointInsideOptimized(Vector3D p) { if (!CircumCircle.IsPointInsideFast(p)) { return(false); } // We will check that we are on the same side of every segment as the center. Vector3D cen = Hexagon.Center; foreach (Segment s in Hexagon.Segments) { if (s.Type == SegmentType.Line) { if (!Euclidean2D.SameSideOfLine(s.P1, s.P2, cen, p)) { return(false); } } else { bool inside1 = s.Circle.IsPointInside(cen); bool inside2 = s.Circle.IsPointInside(p); if (inside1 ^ inside2) { return(false); } } } return(true); }
/// <summary> /// Helper to check if we will affect a sticker, and cache in our list if so. /// </summary> public void WillAffectSticker(Sticker sticker, bool sphericalPuzzle) { if (AffectedStickers == null) { AffectedStickers = new List <StickerList>(); for (int slice = 0; slice < this.NumSlices; slice++) { AffectedStickers.Add(new List <Sticker>()); } } if (Earthquake) { Vector3D cen = sticker.Poly.Center; if (Pants.IsPointInsideOptimized(cen)) { AffectedStickers[0].Add(sticker); } return; } // Slices are ordered by depth. // We cycle from the inner slice outward. for (int slice = 0; slice < this.Circles.Length; slice++) { CircleNE circle = this.Circles[slice]; bool isInside = sphericalPuzzle ? circle.IsPointInsideNE(sticker.Poly.Center) : circle.IsPointInsideFast(sticker.Poly.Center); if (isInside) { AffectedStickers[slice].Add(sticker); return; } } // If we made it here for spherical puzzles, we are in the last slice. // Second check was needed for {3,5} 8C if (sphericalPuzzle && (this.NumSlices != this.Circles.Length)) { AffectedStickers[this.NumSlices - 1].Add(sticker); } }