UNPKG

devexpress-diagram

Version:

DevExpress Diagram Control

93 lines (86 loc) 5.41 kB
import { Point } from "@devexpress/utils/lib/geometry/point"; import { Segment } from "@devexpress/utils/lib/geometry/segment"; import { Rectangle } from "@devexpress/utils/lib/geometry/rectangle"; import { MathUtils } from "@devexpress/utils/lib/utils/math"; import { RightAngleTurnDirection } from "../AStarAlgorithm/AStarMetrics"; import { GeometryUtils } from "../../../../Utils"; import { ConnectionPointSide } from "../../../DiagramItem"; export class RightAngleConnectorRoutingMathOperations { static createUnionSegments<TPoint extends Point>(segments: Segment<TPoint>[], shouldCreateSegment : (prevEndPoint : TPoint, startNextPoint: TPoint) => boolean) : Segment<TPoint>[] { const result = []; let startRenderPoint = segments[0].startPoint; let endRenderPoint = segments[0].endPoint; for(let i = 1; i < segments.length; i++) { const currentSegment = segments[i]; if(shouldCreateSegment(endRenderPoint, currentSegment.startPoint)) { result.push(new Segment(startRenderPoint.clone(), endRenderPoint.clone())); startRenderPoint = currentSegment.startPoint; } endRenderPoint = currentSegment.endPoint; } result.push(new Segment(startRenderPoint, endRenderPoint)); return result; } static unionPoints<TPoint extends Point>(points: TPoint[]): void { let index = 0; while(index < points.length - 2) if(GeometryUtils.isCorner(points[index], points[index + 1], points[index + 2])) index++; else { points.splice(index + 1, 1); index = Math.max(0, index - 1); } } static getTurnDirection(angle: number): RightAngleTurnDirection { if(MathUtils.numberCloseTo(angle, 0)) return RightAngleTurnDirection.Straight; if(MathUtils.numberCloseTo(angle, Math.PI)) return RightAngleTurnDirection.Backwards; return angle < Math.PI ? RightAngleTurnDirection.Left : RightAngleTurnDirection.Right; } static isSegmentNormal<TPoint extends Point>(segment: Segment<TPoint>, isHorizontal : boolean) : boolean { return isHorizontal ? MathUtils.numberCloseTo(segment.startPoint.y, segment.endPoint.y) : MathUtils.numberCloseTo(segment.startPoint.x, segment.endPoint.x); } static isConnectionRectanleLineIntersected<TPoint extends Point>(rect: Rectangle, segment : Segment<TPoint>, side : ConnectionPointSide, excludeBeginPoint : boolean, excludeEndPoint: boolean, createPoint: (x: number, y: number) => TPoint) : boolean { switch(side) { case ConnectionPointSide.North: return GeometryUtils.isLineIntersected(createPoint(rect.x, rect.y), createPoint(rect.right, rect.y), segment, excludeBeginPoint, excludeEndPoint); case ConnectionPointSide.South: return GeometryUtils.isLineIntersected(createPoint(rect.right, rect.bottom), createPoint(rect.x, rect.bottom), segment, excludeBeginPoint, excludeEndPoint); case ConnectionPointSide.West: return GeometryUtils.isLineIntersected(createPoint(rect.x, rect.y), createPoint(rect.x, rect.bottom), segment, excludeBeginPoint, excludeEndPoint); case ConnectionPointSide.East: return GeometryUtils.isLineIntersected(createPoint(rect.right, rect.y), createPoint(rect.right, rect.bottom), segment, excludeBeginPoint, excludeEndPoint); default: return false; } } static createBeginConnectionSegment<TPoint extends Point>(beginConnectionSide: ConnectionPointSide, beginPoint: TPoint, offset: number, createPoint: (x: number, y: number) => TPoint): Segment<TPoint> | TPoint { switch(beginConnectionSide) { case ConnectionPointSide.North: return new Segment(beginPoint, createPoint(beginPoint.x, beginPoint.y - offset)); case ConnectionPointSide.South: return new Segment(beginPoint, createPoint(beginPoint.x, beginPoint.y + offset)); case ConnectionPointSide.West: return new Segment(beginPoint, createPoint(beginPoint.x - offset, beginPoint.y)); case ConnectionPointSide.East: return new Segment(beginPoint, createPoint(beginPoint.x + offset, beginPoint.y)); default: return beginPoint; } } static createEndConnectionSegment<TPoint extends Point>(endConnectionSide: ConnectionPointSide, endPoint: TPoint, offset: number, createPoint: (x: number, y: number) => TPoint): Segment<TPoint> | TPoint { switch(endConnectionSide) { case ConnectionPointSide.North: return new Segment(createPoint(endPoint.x, endPoint.y - offset), endPoint); case ConnectionPointSide.South: return new Segment(createPoint(endPoint.x, endPoint.y + offset), endPoint); case ConnectionPointSide.West: return new Segment(createPoint(endPoint.x - offset, endPoint.y), endPoint); case ConnectionPointSide.East: return new Segment(createPoint(endPoint.x + offset, endPoint.y), endPoint); default: return endPoint; } } }