/// <summary> /// Obtém o código confuso para a região rectangular. /// </summary> /// <param name="obj">A região rectangular.</param> /// <returns>O código confuso.</returns> public override int GetHashCode(IMergingRegion <T> obj) { if (obj == null) { return(0); } else { var h1 = this.equalityComparer.GetHashCode(obj.TopLeftX); var h2 = this.equalityComparer.GetHashCode(obj.TopLeftY); var hres1 = (((h1 << 5) + h1) ^ h2); var h3 = this.equalityComparer.GetHashCode(obj.BottomRightX); var h4 = this.equalityComparer.GetHashCode(obj.BottomRightY); var hres2 = (((h3 << 5) + h3) ^ h4); return(((hres1 << 5) + hres1) ^ hres2); } }
/// <summary> /// Compara duas regiões rectangulares. /// </summary> /// <param name="x">A primeira região rectangular.</param> /// <param name="y">A segunda região rectangular.</param> /// <returns> /// O valor -1 se a primeira região rectangular for inferior à segunda, 0 se ambas forem iguais e /// 1 caso contrário. /// </returns> public override int Compare(IMergingRegion <T> x, IMergingRegion <T> y) { if (object.ReferenceEquals(x, y)) { return(0); } else if (x == null) { return(-1); } else if (y == null) { return(1); } else { var comparision = this.comparer.Compare(x.TopLeftX, y.TopLeftX); if (comparision == -1 || comparision == 1) { return(comparision); } else { comparision = this.comparer.Compare(x.TopLeftY, y.TopLeftY); if (comparision == -1 || comparision == 1) { return(comparision); } else { comparision = this.comparer.Compare(x.BottomRightX, y.BottomRightX); if (comparision == -1 || comparision == 1) { return(comparision); } else { comparision = this.comparer.Compare(x.BottomRightY, y.BottomRightY); return(comparision); } } } } }
/// <summary> /// Determina se duas regiões rectangulares são iguais. /// </summary> /// <param name="x">O primeiro rectângulo.</param> /// <param name="y">O segundo rectângulo.</param> /// <returns>Verdadeiro caso as regiões rectangulares sejam iguais e falso caso contrário.</returns> public override bool Equals(IMergingRegion <T> x, IMergingRegion <T> y) { if (object.ReferenceEquals(x, y)) { return(true); } else if (x == null) { return(false); } else if (y == null) { return(false); } else { return(this.equalityComparer.Equals(x.TopLeftX, y.TopLeftX) && this.equalityComparer.Equals(x.TopLeftY, y.TopLeftY) && this.equalityComparer.Equals(x.BottomRightX, y.BottomRightX) && this.equalityComparer.Equals(x.BottomRightY, y.BottomRightY)); } }
/// <summary> /// Verifica se existe sobreposição das regiões rectangulares. /// </summary> /// <param name="other">A outra região rectangular.</param> /// <returns>Verdadeiro caso se dê sobreposição e falso caso contrário.</returns> public bool OverLaps(IMergingRegion <T> other) { if (other == null) { return(false); } else { if (this.comparer.Compare(this.topLeftX, other.BottomRightX) > 0 || this.comparer.Compare(this.bottomRightX, other.TopLeftX) < 0) { return(false); } else if (this.comparer.Compare(this.topLeftY, other.BottomRightY) > 0 || this.comparer.Compare(this.bottomRightY, other.TopLeftY) < 0) { return(false); } else { return(true); } } }
/// <summary> /// Funde duas regiões rectangulares quando tal é possível. /// </summary> /// <param name="other">A região rectangular a ser fundida.</param> /// <param name="increment">A função que permite determinar o incremento.</param> /// <param name="decrement">A função que permite determinar o decremento.</param> /// <returns>O resultado da fusão de duas regiões rectangulares.</returns> public IRectangularRegion <T> Merge( IMergingRegion <T> other, Func <T, T> increment, Func <T, T> decrement) { if (other == null) { throw new ArgumentNullException("other"); } else if (increment == null) { throw new ArgumentNullException("increment"); } else if (decrement == null) { throw new ArgumentNullException("decrement"); } else { if (this.comparer.Compare( this.topLeftX, other.TopLeftX) == 0 && this.comparer.Compare( this.bottomRightX, other.BottomRightX) == 0) { var otherBottomRightYIncremented = increment.Invoke( other.BottomRightY); if (this.comparer.Compare( this.topLeftY, otherBottomRightYIncremented) > 0) { throw new UtilitiesDataException("Can't merge the provided rectangular regions."); } else { var otherTopLeftYDecremented = decrement.Invoke( other.TopLeftY); if (this.comparer.Compare( this.BottomRightY, otherTopLeftYDecremented) < 0) { throw new UtilitiesDataException("Can't merge the provided rectangular regions."); } else { var currentTopLeftY = this.topLeftY; var currentBottomRightY = this.bottomRightY; if (this.comparer.Compare( this.topLeftY, other.TopLeftY) > 0) { currentTopLeftY = other.TopLeftY; } if (this.comparer.Compare( this.bottomRightY, other.BottomRightY) < 0) { currentBottomRightY = other.BottomRightY; } return(new RectangularRegion <T>( this.topLeftX, currentTopLeftY, this.bottomRightX, currentBottomRightY)); } } } else if (this.comparer.Compare( this.topLeftY, other.TopLeftY) == 0 && this.comparer.Compare( this.bottomRightY, other.BottomRightY) == 0) { var otherBottomRightXIncremented = increment.Invoke( other.BottomRightX); if (this.comparer.Compare( this.topLeftX, otherBottomRightXIncremented) > 0) { throw new UtilitiesDataException("Can't merge the provided rectangular regions."); } else { var otherTopLeftXDecremented = decrement.Invoke( other.TopLeftX); if (this.comparer.Compare( this.bottomRightX, otherTopLeftXDecremented) < 0) { throw new UtilitiesDataException("Can't merge the provided rectangular regions."); } else { var currentTopLeftX = this.topLeftX; var currentBottomRightX = this.bottomRightX; if (this.comparer.Compare( this.topLeftX, other.TopLeftX) > 0) { currentTopLeftX = other.TopLeftX; } if (this.comparer.Compare( this.bottomRightX, other.BottomRightX) < 0) { currentBottomRightX = other.BottomRightX; } return(new RectangularRegion <T>( currentTopLeftX, this.topLeftY, currentBottomRightX, this.bottomRightY)); } } } else { throw new UtilitiesDataException("Can't merge the provided rectangular regions."); } } }
/// <summary> /// Obtém uma lista de regiões rectangulares que resultam da subtracção /// da região proporcionada à região actual. /// </summary> /// <param name="other">A região a subtrair.</param> /// <param name="increment">A função que permite determinar o incremento.</param> /// <param name="decrement">A função que permite determinar o decremento.</param> /// <returns> /// O conjunto de regiões que cobrem a região actual com excepção da região definida. /// </returns> public List <IRectangularRegion <T> > Subtract( IMergingRegion <T> other, Func <T, T> increment, Func <T, T> decrement) { if (decrement == null) { throw new ArgumentNullException("decrement"); } else { var result = new List <IRectangularRegion <T> >(); if (other == null) { result.Add(this); } else { if (this.comparer.Compare(this.topLeftX, other.TopLeftX) < 0) { if (this.comparer.Compare(this.topLeftY, other.TopLeftY) < 0) { if (this.comparer.Compare(this.bottomRightX, other.TopLeftX) >= 0) { if (this.comparer.Compare(this.bottomRightY, other.TopLeftY) >= 0) { var otherTopLeftXDecremented = decrement.Invoke(other.TopLeftX); var otherTopLeftYDecremented = decrement.Invoke(other.TopLeftY); // Introdução do rectângulo horizontal superior result.Add(new RectangularRegion <T>( this.topLeftX, this.topLeftY, this.bottomRightX, otherTopLeftYDecremented)); // Introdução do rectângulo vertical esquerdo result.Add(new RectangularRegion <T>( this.topLeftX, other.TopLeftY, otherTopLeftXDecremented, this.bottomRightY)); if (this.comparer.Compare(this.bottomRightY, other.BottomRightY) > 0) { // Introdução do rectângulo horizontal inferior var otherBottomRightYIncremented = increment.Invoke(other.BottomRightY); result.Add(new RectangularRegion <T>( other.TopLeftX, otherBottomRightYIncremented, this.bottomRightX, this.bottomRightY)); if (this.comparer.Compare(this.bottomRightX, other.BottomRightX) > 0) { // Introdução do rectângulo vertical direito var otherBottomRightXIncremented = increment.Invoke(other.BottomRightX); result.Add(new RectangularRegion <T>( otherBottomRightXIncremented, other.TopLeftY, this.bottomRightX, other.BottomRightY)); } } else if (this.comparer.Compare(this.bottomRightX, other.BottomRightX) > 0) { // Introdução do rectângulo vertical direito var otherBottomRightXIncremented = increment.Invoke(other.BottomRightX); result.Add(new RectangularRegion <T>( otherBottomRightXIncremented, other.TopLeftY, this.bottomRightX, this.bottomRightY)); } } else { result.Add(this); } } else { result.Add(this); } } else if (this.comparer.Compare(this.topLeftY, other.BottomRightY) <= 0) { if (this.comparer.Compare(this.bottomRightX, other.TopLeftX) >= 0) { // Não há rectângulo horizontal superior var otherTopLeftXDecremented = decrement.Invoke(other.TopLeftX); var otherTopLeftYDecremented = decrement.Invoke(other.TopLeftY); // Introdução do rectângulo vertical esquerdo result.Add(new RectangularRegion <T>( this.topLeftX, this.topLeftY, otherTopLeftXDecremented, this.bottomRightY)); if (this.comparer.Compare(this.bottomRightY, other.BottomRightY) > 0) { // Introdução do rectângulo horizontal inferior var otherBottomRightYIncremented = increment.Invoke(other.BottomRightY); result.Add(new RectangularRegion <T>( other.TopLeftX, otherBottomRightYIncremented, this.bottomRightX, this.bottomRightY)); if (this.comparer.Compare(this.bottomRightX, other.BottomRightX) > 0) { // Introdução do rectângulo vertical direito var otherBottomRightXIncremented = increment.Invoke(other.BottomRightX); result.Add(new RectangularRegion <T>( otherBottomRightXIncremented, this.topLeftY, this.bottomRightX, other.BottomRightY)); } } else if (this.comparer.Compare(this.bottomRightX, other.BottomRightX) > 0) { // Introdução do rectângulo vertical direito var otherBottomRightXIncremented = increment.Invoke(other.BottomRightX); result.Add(new RectangularRegion <T>( otherBottomRightXIncremented, this.topLeftY, this.bottomRightX, this.bottomRightY)); } } else { result.Add(this); } } else { result.Add(this); } } else if (this.comparer.Compare(this.topLeftX, other.BottomRightX) <= 0) { if (this.comparer.Compare(this.topLeftY, other.TopLeftY) < 0) { if (this.comparer.Compare(this.bottomRightY, other.TopLeftY) >= 0) { var otherTopLeftXDecremented = decrement.Invoke(other.TopLeftX); var otherTopLeftYDecremented = decrement.Invoke(other.TopLeftY); // Introdução do rectângulo horizontal superior result.Add(new RectangularRegion <T>( this.topLeftX, this.topLeftY, this.bottomRightX, otherTopLeftYDecremented)); if (this.comparer.Compare(this.bottomRightY, other.BottomRightY) > 0) { // Introdução do rectângulo horizontal inferior var otherBottomRightYIncremented = increment.Invoke(other.BottomRightY); result.Add(new RectangularRegion <T>( this.topLeftX, otherBottomRightYIncremented, this.bottomRightX, this.bottomRightY)); if (this.comparer.Compare(this.bottomRightX, other.BottomRightX) > 0) { // Introdução do rectângulo vertical direito var otherBottomRightXIncremented = increment.Invoke(other.BottomRightX); result.Add(new RectangularRegion <T>( otherBottomRightXIncremented, other.TopLeftY, this.bottomRightX, other.BottomRightY)); } } else if (this.comparer.Compare(this.bottomRightX, other.BottomRightX) > 0) { // Introdução do rectângulo vertical direito var otherBottomRightXIncremented = increment.Invoke(other.BottomRightX); result.Add(new RectangularRegion <T>( otherBottomRightXIncremented, other.TopLeftY, this.bottomRightX, this.bottomRightY)); } } else { result.Add(this); } } else if (this.comparer.Compare(this.topLeftY, other.BottomRightY) <= 0) { // Não há rectângulo horizontal superior nem rectângulo vertical esquerdo if (this.comparer.Compare(this.bottomRightY, other.BottomRightY) > 0) { // Introdução do rectângulo horizontal inferior var otherBottomRightYIncremented = increment.Invoke(other.BottomRightY); result.Add(new RectangularRegion <T>( this.topLeftX, otherBottomRightYIncremented, this.bottomRightX, this.bottomRightY)); if (this.comparer.Compare(this.bottomRightX, other.BottomRightX) > 0) { // Introdução do rectângulo vertical direito var otherBottomRightXIncremented = increment.Invoke(other.BottomRightX); result.Add(new RectangularRegion <T>( otherBottomRightXIncremented, this.topLeftY, this.bottomRightX, other.BottomRightY)); } } else if (this.comparer.Compare(this.bottomRightX, other.BottomRightX) > 0) { // Introdução do rectângulo vertical direito var otherBottomRightXIncremented = increment.Invoke(other.BottomRightX); result.Add(new RectangularRegion <T>( otherBottomRightXIncremented, this.topLeftY, this.bottomRightX, this.bottomRightY)); } } else { result.Add(this); } } else { result.Add(this); } } return(result); } }
/// <summary> /// Obtém a intersecção da região rectangular actual com a região rectangular proporcionada. /// </summary> /// <remarks> /// A função retorna um rectângulo sem área sempre que exista uma fronteira /// em comum. Se não se verificar sobreposição, a função irá retornar um nulo. /// </remarks> /// <param name="other">A região rectangular a ser intersectada.</param> /// <returns>O resultado da intersecção.</returns> public IRectangularRegion <T> Intersect(IMergingRegion <T> other) { if (other == null) { return(null); } else { if (this.comparer.Compare(this.topLeftX, other.TopLeftX) <= 0) { if (this.comparer.Compare(this.topLeftY, other.TopLeftY) <= 0) { if (this.comparer.Compare(this.bottomRightX, other.TopLeftX) >= 0) { if (this.comparer.Compare(this.bottomRightY, other.TopLeftY) >= 0) { var rectTopLeftX = other.TopLeftX; var rectTopLeftY = other.TopLeftY; var rectBottomRightX = this.bottomRightX; var rectBottomRightY = this.bottomRightY; if (this.comparer.Compare(this.bottomRightX, other.BottomRightX) > 0) { rectBottomRightX = other.BottomRightX; } if (this.comparer.Compare(this.bottomRightY, other.BottomRightY) > 0) { rectBottomRightY = other.BottomRightY; } return(new RectangularRegion <T>( rectTopLeftX, rectTopLeftY, rectBottomRightX, rectBottomRightY)); } else { return(null); } } else { return(null); } } else if (this.comparer.Compare(this.topLeftY, other.BottomRightY) <= 0) { var rectTopLeftX = other.TopLeftX; var rectTopLeftY = this.topLeftY; var rectBottomRightX = this.bottomRightX; var rectBottomRightY = this.bottomRightY; if (this.comparer.Compare(this.bottomRightX, other.BottomRightX) > 0) { rectBottomRightX = other.BottomRightX; } if (this.comparer.Compare(this.bottomRightY, other.BottomRightY) > 0) { rectBottomRightY = other.BottomRightY; } return(new RectangularRegion <T>( rectTopLeftX, rectTopLeftY, rectBottomRightX, rectBottomRightY)); } else { return(null); } } else if (this.comparer.Compare(this.topLeftX, other.BottomRightX) <= 0) { if (this.comparer.Compare(this.topLeftY, other.TopLeftY) <= 0) { if (this.comparer.Compare(this.bottomRightY, other.TopLeftY) >= 0) { var rectTopLeftX = this.topLeftX; var rectTopLeftY = other.TopLeftY; var rectBottomRightX = this.bottomRightX; var rectBottomRightY = this.bottomRightY; if (this.comparer.Compare(this.bottomRightX, other.BottomRightX) > 0) { rectBottomRightX = other.BottomRightX; } if (this.comparer.Compare(this.bottomRightY, other.BottomRightY) > 0) { rectBottomRightY = other.BottomRightY; } return(new RectangularRegion <T>( rectTopLeftX, rectTopLeftY, rectBottomRightX, rectBottomRightY)); } else { return(null); } } else if (this.comparer.Compare(this.topLeftY, other.BottomRightY) <= 0) { var rectTopLeftX = this.topLeftX; var rectTopLeftY = this.topLeftY; var rectBottomRightX = this.bottomRightX; var rectBottomRightY = this.bottomRightY; if (this.comparer.Compare(this.bottomRightX, other.BottomRightX) > 0) { rectBottomRightX = other.BottomRightX; } if (this.comparer.Compare(this.bottomRightY, other.BottomRightY) > 0) { rectBottomRightY = other.BottomRightY; } return(new RectangularRegion <T>( rectTopLeftX, rectTopLeftY, rectBottomRightX, rectBottomRightY)); } else { return(null); } } else { return(null); } } }