public JsonResult Analyze(RectangleModel model) { AppBusObj busObj = new AppBusObj(); try { RectangleDO r1 = new RectangleDO(model.r1.Top, model.r1.Left, model.r1.Width, model.r1.Height); RectangleDO r2 = new RectangleDO(model.r2.Top, model.r2.Left, model.r2.Width, model.r2.Height); RelationshipDO rel = busObj.GetRelationship(r1, r2); model.Header = rel.TypeName; model.Message = rel.TypeDescription; model.Success = true; if (rel.CompResult != null) { model.Diff = (Shape)rel.CompResult; } } catch (Exception ex) { PackageError(model, ex); } finally { busObj.Dispose(); busObj = null; } return Json(model); }
/// <summary> /// Determines the type of the relationship between the rectangles and provides a human readable description of the relationship /// </summary> /// <param name="r1">First Rectangle</param> /// <param name="r2">Second Rectangle</param> /// <returns>An instance of <see cref="RelationshipDO"/> that represents the current relationship</returns> public RelationshipDO GetRelationship(RectangleDO r1, RectangleDO r2) { RelationshipDO rel = null; RectangleBusObj busObj = null; try { busObj = new RectangleBusObj(); rel = busObj.GetRelationship(r1, r2); if (rel == null) { throw new GeometryException("MSG_ERR_LOGIC_COMPARE", "eng"); } rel.TypeName = TextFactory.Instance.GetText(rel.Type.ToString(), "eng"); rel.TypeDescription = TextFactory.Instance.GetLongText(rel.Type.ToString(), "eng"); } catch (Exception ex) { throw new GeometryException("MSG_ERR_RECT_COMPARE", "eng", ex); } finally { if (busObj != null) { busObj.Dispose(); } } return rel; }
/// <summary> /// Determins how this instance interects with the passed in rectangle /// </summary> /// <param name="insidePoints">Points of the passed in rectangle</param> /// <param name="other">The other rectangle</param> /// <returns>Shape representing the Interection</returns> public IShape FindIntersect(List<PointDO> insidePoints, RectangleDO other) { IShape intersect = null; //4 point scenario: 1-dim overlapp if (insidePoints.Count == 4) { intersect = FromPoints(insidePoints); } else { List<PointDO> complete = FindMissingPoints(insidePoints, other); intersect = FromPoints(complete); } //intersect return intersect; }
public RelationshipDO GetRelationship(RectangleDO r1, RectangleDO r2) { if (r1 == null || !r1.IsValid()) { throw new GeometryException("MSG_ERR_INVALID RECT", "eng"); } if (r2 == null || !r2.IsValid()) { throw new GeometryException("MSG_ERR_INVALID RECT", "eng"); } RelationshipDO result = null; if (r1.Area > r2.Area) { result = GetDiff(r1, r2, false); } else { result = GetDiff(r2, r1, r1.Area == r2.Area); } return result; }
/// <summary> /// Helper method to check intersect points /// </summary> /// <param name="r1"></param> /// <param name="r2"></param> /// <param name="insidePoints"></param> /// <param name="borderPoints"></param> private static void AnalyzeIntersect(RectangleDO r1, RectangleDO r2, List<PointDO> insidePoints, List<PointDO> borderPoints) { foreach (PointDO p in r2.Points) { PointLocation loc = r1.ContainsPoint(p); switch (loc) { case PointLocation.Inside: if (!insidePoints.Contains(p)) { insidePoints.Add(p); } break; case PointLocation.Border: if (!borderPoints.Contains(p)) { borderPoints.Add(p); } break; } } }
/// <summary> /// Given vertices of the passed in rectangle that are within the bound of the current instance, determines /// the missing vertices of the intersection /// </summary> /// <param name="insidePoints">Vertices of the passed in rectangle that are within bounds of the current instance</param> /// <param name="other">The other rectangle</param> /// <returns>List of all vertices of the intersect region</returns> private List<PointDO> FindMissingPoints(List<PointDO> insidePoints, RectangleDO other) { List<PointDO> complete = new List<PointDO>(); complete.AddRange(insidePoints); if (insidePoints.Count == 2 && insidePoints[0].Left != insidePoints[1].Left && insidePoints[0].Top != insidePoints[1].Top) { complete.Add(new PointDO(insidePoints[1].Top, insidePoints[0].Left)); complete.Add(new PointDO(insidePoints[0].Top, insidePoints[1].Left)); } else { if (other.Right > this.Right) { foreach(PointDO p in insidePoints) { if(p.Left < this.Right) { PointDO missing = new PointDO(p.Top, this.Right); if (!complete.Contains(missing)) { complete.Add(missing); } } } } else if (other.Left < this.Left) { foreach(PointDO p in insidePoints) { if(p.Left > this.Left) { PointDO missing = new PointDO(p.Top, this.Left); if (!complete.Contains(missing)) { complete.Add(missing); } } } } else if (other.Top < this.Top) { foreach(PointDO p in insidePoints) { if(p.Top > this.Top) { PointDO missing = new PointDO(this.Top, p.Left); if (!complete.Contains(missing)) { complete.Add(missing); } } } } else if (other.Bottom > this.Bottom) { foreach(PointDO p in insidePoints) { if(p.Top < this.Bottom) { PointDO missing = new PointDO(this.Bottom, p.Left); if (!complete.Contains(missing)) { complete.Add(missing); } } } } } return complete; }
/// <summary> /// Builds the complete <see cref="RelationshipDO"/> object /// </summary> /// <param name="r1">Larger rectangle, if different</param> /// <param name="r2">Smaller rectangle, if different</param> /// <returns></returns> private RelationshipDO GetDiff(RectangleDO r1, RectangleDO r2, bool equalSize) { RelationshipDO result = new RelationshipDO(); List<PointDO> insidePoints = new List<PointDO>(); List<PointDO> borderPoints = new List<PointDO>();; try { //see which points of the hypothetically smaller rectangle //fit in the larger one AnalyzeIntersect(r1, r2, insidePoints, borderPoints); //second rectangle is fully within the first one if (insidePoints.Count + borderPoints.Count == 4) { if (equalSize) { result.Type = RelationshipType.FullOverlap; } else { result.Type = RelationshipType.Containment; result.CompResult = r2; } } //smaller r2 intersecting with r1 else if (insidePoints.Count == 2 && borderPoints.Count == 0 || insidePoints.Count == 1 && borderPoints.Count == 1) { result.Type = RelationshipType.Intersection; result.CompResult = GetIntersect(r1, r2, insidePoints, borderPoints); } //if there are no border points nor inside points => the rectangles do not touch else if (insidePoints.Count == 0 && borderPoints.Count == 0) { result.Type = RelationshipType.None; result.CompResult = null; } //touching, but not adjacent else if (insidePoints.Count == 0 && borderPoints.Count == 1) { result.Type = RelationshipType.Touching; } else //need to find which points of r1 fall within r2 { AnalyzeIntersect(r2, r1, insidePoints, borderPoints); if (borderPoints.Count == 2) { result.Type = RelationshipType.Adjacency; result.CompResult = new LineDO(borderPoints[0], borderPoints[1]); } else if (insidePoints.Count == 2) { result.Type = RelationshipType.Intersection; result.CompResult = GetIntersect(r1, r2, insidePoints, borderPoints); } else if (borderPoints.Count == 4) { result.Type = RelationshipType.Intersection; result.CompResult = GetIntersect(r1, r2, insidePoints, borderPoints); } } } finally { if (insidePoints != null) { insidePoints.Clear(); insidePoints = null; } if (borderPoints != null) { borderPoints.Clear(); borderPoints = null; } } return result; }
/// <summary> /// Helper method to retrieve the area of the intersection provided by <see cref="RectangleDO"/> /// </summary> /// <param name="r1"></param> /// <param name="r2"></param> /// <param name="insidePoints"></param> /// <param name="borderPoints"></param> /// <returns></returns> private IShape GetIntersect(RectangleDO r1, RectangleDO r2, List<PointDO> insidePoints, List<PointDO> borderPoints) { List<PointDO> combined = new List<PointDO>(); combined.AddRange(insidePoints); combined.AddRange(borderPoints); return r1.FindIntersect(combined, r2); }