private IRectangle IntersectRects(IRectangle r1, IRectangle r2) { Debug.Assert(r1.Relate(r2).Intersects()); double minX, maxX; if (r1.RelateXRange(r2.MinX, r2.MinX).Intersects()) { minX = r2.MinX; } else { minX = r1.MinX; } if (r1.RelateXRange(r2.MaxX, r2.MaxX).Intersects()) { maxX = r2.MaxX; } else { maxX = r1.MaxX; } double minY, maxY; if (r1.RelateYRange(r2.MinY, r2.MinY).Intersects()) { minY = r2.MinY; } else { minY = r1.MinY; } if (r1.RelateYRange(r2.MaxY, r2.MaxY).Intersects()) { maxY = r2.MaxY; } else { maxY = r1.MaxY; } return(ctx.MakeRectangle(minX, maxX, minY, maxY)); }
private SpatialRelation RelateRectangleCircleWrapsPole(IRectangle r, SpatialContext ctx) { //This method handles the case where the circle wraps ONE pole, but not both. For both, // there is the inverseCircle case handled before now. The only exception is for the case where // the circle covers the entire globe, and we'll check that first. if (radiusDEG == 180) //whole globe { return(SpatialRelation.CONTAINS); } //Check if r is within the pole wrap region: double yTop = Center.Y + radiusDEG; if (yTop > 90) { double yTopOverlap = yTop - 90; Debug.Assert(yTopOverlap <= 90, "yTopOverlap: " + yTopOverlap); if (r.MinY >= 90 - yTopOverlap) { return(SpatialRelation.CONTAINS); } } else { double yBot = point.Y - radiusDEG; if (yBot < -90) { double yBotOverlap = -90 - yBot; Debug.Assert(yBotOverlap <= 90); if (r.MaxY <= -90 + yBotOverlap) { return(SpatialRelation.CONTAINS); } } else { //This point is probably not reachable ?? Debug.Assert(yTop == 90 || yBot == -90); //we simply touch a pole //continue } } //If there are no corners to check intersection because r wraps completely... if (r.Width == 360) { return(SpatialRelation.INTERSECTS); } //Check corners: int cornersIntersect = NumCornersIntersect(r); // (It might be possible to reduce contains() calls within nCI() to exactly two, but this intersection // code is complicated enough as it is.) double frontX = Center.X; if (cornersIntersect == 4) { //all double backX = frontX <= 0 ? frontX + 180 : frontX - 180; if (r.RelateXRange(backX, backX).Intersects()) { return(SpatialRelation.INTERSECTS); } else { return(SpatialRelation.CONTAINS); } } else if (cornersIntersect == 0) { //none if (r.RelateXRange(frontX, frontX).Intersects()) { return(SpatialRelation.INTERSECTS); } else { return(SpatialRelation.DISJOINT); } } else //partial { return(SpatialRelation.INTERSECTS); } }
/// <summary> /// Called after bounding box is intersected. /// </summary> /// <param name="r"></param> /// <param name="bboxSect"><see cref="SpatialRelation.INTERSECTS"/> or <see cref="SpatialRelation.CONTAINS"/> from enclosingBox's intersection</param> /// <returns><see cref="SpatialRelation.DISJOINT"/>, <see cref="SpatialRelation.CONTAINS"/>, or /// <see cref="SpatialRelation.INTERSECTS"/> (not <see cref="SpatialRelation.WITHIN"/>)</returns> protected override SpatialRelation RelateRectanglePhase2(IRectangle r, SpatialRelation bboxSect) { if (inverseCircle != null) { return(inverseCircle.Relate(r).Inverse()); } //if a pole is wrapped, we have a separate algorithm if (enclosingBox.Width == 360) { return(RelateRectangleCircleWrapsPole(r, ctx)); } //This is an optimization path for when there are no dateline or pole issues. if (!enclosingBox.CrossesDateLine && !r.CrossesDateLine) { return(base.RelateRectanglePhase2(r, bboxSect)); } //Rectangle wraps around the world longitudinally creating a solid band; there are no corners to test intersection if (r.Width == 360) { return(SpatialRelation.INTERSECTS); } //do quick check to see if all corners are within this circle for CONTAINS int cornersIntersect = NumCornersIntersect(r); if (cornersIntersect == 4) { //ensure r's x axis is within c's. If it doesn't, r sneaks around the globe to touch the other side (intersect). SpatialRelation xIntersect = r.RelateXRange(enclosingBox.MinX, enclosingBox.MaxX); if (xIntersect == SpatialRelation.WITHIN) { return(SpatialRelation.CONTAINS); } return(SpatialRelation.INTERSECTS); } //INTERSECT or DISJOINT ? if (cornersIntersect > 0) { return(SpatialRelation.INTERSECTS); } //Now we check if one of the axis of the circle intersect with r. If so we have // intersection. /* x axis intersects */ if (r.RelateYRange(YAxis, YAxis).Intersects() && // at y vertical r.RelateXRange(enclosingBox.MinX, enclosingBox.MaxX).Intersects()) { return(SpatialRelation.INTERSECTS); } /* y axis intersects */ if (r.RelateXRange(XAxis, XAxis).Intersects()) { // at x horizontal double yTop = Center.Y + radiusDEG; Debug.Assert(yTop <= 90); double yBot = Center.Y - radiusDEG; Debug.Assert(yBot >= -90); if (r.RelateYRange(yBot, yTop).Intersects()) //back bottom { return(SpatialRelation.INTERSECTS); } } return(SpatialRelation.DISJOINT); }