import {CompassVector} from '../../math/geometry/compassVector'
import {Direction} from '../../math/geometry/direction'
import {GeomConstants} from '../../math/geometry/geomConstants'
import {Point} from '../../math/geometry/point'
import {VisibilityVertex} from '../visibility/VisibilityVertex'
export class PointComparer {
// Due to the vagaries of rounding, we may encounter a result that is not quite 0
// when subtracting two numbers that are close.
// ReSharper disable InconsistentNaming
static differenceEpsilon: number = GeomConstants.distanceEpsilon / 2
// ReSharper restore InconsistentNaming
static get DifferenceEpsilon(): number {
return PointComparer.differenceEpsilon
}
// Determines whether the specified Points, which are assumed to have been Round()ed,
// are close enough to be considered equal.
// True if the inputs are close enough to be considered equal, else false
static EqualPP(a: Point, b: Point): boolean {
return PointComparer.Equal(a.x, b.x) && PointComparer.Equal(a.y, b.y)
}
// Determines whether the specified double values, which are assumed to have been Round()ed,
// are close enough to be considered equal.
// True if the inputs are close enough to be considered equal, else false
static Equal(x: number, y: number): boolean {
return PointComparer.Compare(x, y) === 0
}
// The usual Compare operation, with inputs that are assumed to have been Round()ed.
//
//
// 0 if the inputs are close enough to be considered equal, else -1 if lhs is
// less than rhs, else 1.
static Compare(lhs: number, rhs: number): number {
// If the inputs are not rounded, then two numbers that are close together at the
// middle of the rounding range may Compare as 0 but Round to different values
// (e.g., with rounding to 6 digits, xxx.yyyyyy49 and xxx.yyyyyy51 will exhibit this).
// PointComparer.Assert_Rounded(lhs)
// PointComparer.Assert_Rounded(rhs)
let cmp = 0
if (lhs + PointComparer.DifferenceEpsilon < rhs) {
cmp = -1
} else if (rhs + PointComparer.DifferenceEpsilon < lhs) {
cmp = 1
}
// Just to be sure we're in sync with CompassVector
/*Assert.assert(
cmp < 0 ==
(Direction.East ==
CompassVector.VectorDirectionPP(
new Point(lhs, 0),
new Point(rhs, 0),
)),
)*/
/*Assert.assert(
(0 === cmp) ==
(Direction.None ==
CompassVector.VectorDirectionPP(
new Point(lhs, 0),
new Point(rhs, 0),
)),
)*/
return cmp
}
// The usual Compare operation, with inputs that are assumed to have been Round()ed.
// 0 if the inputs are close enough to be considered equal, else -1 if lhs is
// less than rhs, else 1.
static ComparePP(lhs: Point, rhs: Point): number {
let cmp: number = PointComparer.Compare(lhs.x, rhs.x)
if (cmp === 0) {
cmp = PointComparer.Compare(lhs.y, rhs.y)
}
return cmp
}
// return true if less or equal holds for two values that are assumed to have been Round()ed
static LessOrEqual(a: number, b: number): boolean {
const comp: number = PointComparer.Compare(a, b)
return comp < 0 || comp === 0
}
static Less(a: number, b: number): boolean {
return PointComparer.Compare(a, b) < 0
}
// static Assert_Rounded(d: number) {
// // Be sure there is enough precision to round that far; anything larger than this is
// // unlikely to be a graph coordinate (it's probably a line intersection way out of range).
// if (Math.log10(Math.abs(d)) < 14 - GeomConstants.distanceEpsilonPrecision) {
// /*Assert.assert(
// Math.abs(Point.RoundDouble(d) - d) <
// PointComparer.DifferenceEpsilon,
// 'unRounded value passed',
// )*/
// }
// }
// static Assert_RoundedP(p: Point) {
// // PointComparer.Assert_Rounded(p.x)
// // PointComparer.Assert_Rounded(p.y)
// }
static GetDirections(a: Point, b: Point): Direction {
// PointComparer.Assert_RoundedP(a)
// PointComparer.Assert_RoundedP(b)
return CompassVector.DirectionFromPointToPoint(a, b)
}
static IsPureDirection(a: Point, b: Point): boolean {
// PointComparer.Assert_RoundedP(a)
// PointComparer.Assert_RoundedP(b)
return CompassVector.IsPureDirection(PointComparer.GetDirections(a, b))
}
static IsPureDirectionD(dir: Direction): boolean {
return CompassVector.IsPureDirection(dir)
}
static IsPureLower(a: Point, b: Point): boolean {
// PointComparer.Assert_RoundedP(a)
// PointComparer.Assert_RoundedP(b)
// Is a lower than b along the orthogonal line segment? That means moving
// from a to b is in the increasing direction.
const dir: Direction = PointComparer.GetDirections(a, b)
return Direction.East === dir || Direction.North === dir
}
static GetPureDirectionVV(first: VisibilityVertex, second: VisibilityVertex): Direction {
return PointComparer.GetDirections(first.point, second.point)
}
}