import { EarthConstants , GeoCoordinates , webMercatorProjection } from "@here/harp-geoutils" ; import { Math2D } from "@here/harp-utils" ; import { Vector2 , Vector3 } from "three" ; remarks internal class ClipEdge { readonly p0 : Vector2 ; readonly p1 : Vector2 ; param x1 param y1 param x2 param y2 param isInside constructor ( x1 , y1 , x2 , y2 , private readonly isInside ) { this . p0 = new Vector2 ( x1 , y1 ) ; this . p1 = new Vector2 ( x2 , y2 ) ; } /**
     * Tests if the given point is inside this clipping edge.
     */ inside ( point ) { return this . isInside ( point ) ; } remarks https *    | line-line intersection}.
      computeIntersection ( a , b ) { const result = new Vector2 ( ) ; Math2D . intersectLines ( a . x , a . y , b . x , b . y , this . p0 . x , this . p0 . y , this . p1 . x , this . p1 . y , result ) ; return result ; } /**
     * Clip the input line against this edge.
     */ clipLine ( lineString ) { const inputList = lineString ; const result = [ ] ; lineString = [ ] ; result . push ( lineString ) ; const pushPoint = ( point ) => { if ( lineString . length === 0 || ! lineString [ lineString . length - 1 ] . equals ( point ) ) { lineString . push ( point ) ; } } ; for ( let i = 0 ; i < inputList . length ; ++ i ) { const currentPoint = inputList [ i ] ; const prevPoint = i > 0 ? inputList [ i - 1 ] : undefined ; if ( this . inside ( currentPoint ) ) { if ( prevPoint !== undefined && ! this . inside ( prevPoint ) ) { if ( lineString . length > 0 ) { lineString = [ ] ; result . push ( lineString ) ; } pushPoint ( this . computeIntersection ( prevPoint , currentPoint ) ) ; } pushPoint ( currentPoint ) ; } else if ( prevPoint !== undefined && this . inside ( prevPoint ) ) { pushPoint ( this . computeIntersection ( prevPoint , currentPoint ) ) ; } } if ( result [ result . length - 1 ] . length === 0 ) { result . length = result . length - 1 ; } return result ; } /**
     * Clip the input lines against this edge.
     */ clipLines ( lineStrings ) { const reuslt = [ ] ; lineStrings . forEach ( lineString => { this . clipLine ( lineString ) . forEach ( clippedLine => { reuslt . push ( clippedLine ) ; } ) ; } ) ; return reuslt ; } } param lineString param minX param minY param maxX param maxY export function clipLineString ( lineString , minX , minY , maxX , maxY ) { const clipEdge0 = new ClipEdge ( minX , minY , minX , maxY , p => p . x > minX ) ; const clipEdge1 = new ClipEdge ( minX , maxY , maxX , maxY , p => p . y < maxY ) ; const clipEdge2 = new ClipEdge ( maxX , maxY , maxX , minY , p => p . x < maxX ) ; const clipEdge3 = new ClipEdge ( maxX , minY , minX , minY , p => p . y > minY ) ; let lines = clipEdge0 . clipLine ( lineString ) ; lines = clipEdge1 . clipLines ( lines ) ; lines = clipEdge2 . clipLines ( lines ) ; lines = clipEdge3 . clipLines ( lines ) ; return lines ; } /**
 * The result of wrapping a line string.
 */ interface WrappedLineString { left : GeoCoordinates [ ] [ ] ; middle : GeoCoordinates [ ] [ ] ; right : GeoCoordinates [ ] [ ] ; } param multiLineString param edges param offset internal function wrapMultiLineStringHelper ( multiLineString , edges , offset ) { for ( const clip of edges ) { multiLineString = clip . clipLines ( multiLineString ) ; } const worldP = new Vector3 ( ) ; const coordinates = [ ] ; multiLineString . forEach ( lineString => { if ( lineString . length === 0 ) { return ; } const coords = lineString . map ( ( { x , y } ) => { worldP . set ( x , y , 0 ) ; const geoPoint = webMercatorProjection . unprojectPoint ( worldP ) ; geoPoint . longitude += offset ; return geoPoint ; } ) ; coordinates . push ( coords ) ; } ) ; return coordinates . length > 0 ? coordinates : undefined ; } remarks param coordinates export function wrapLineString ( coordinates ) { const worldP = new Vector3 ( ) ; const lineString = coordinates . map ( g => { const { x , y } = webMercatorProjection . projectPoint ( g , worldP ) ; return new Vector2 ( x , y ) ; } ) ; const multiLineString = [ lineString ] ; return { left : wrapMultiLineStringHelper ( multiLineString , WRAP_LEFT_CLIP_EDGES , 360 ) , middle : wrapMultiLineStringHelper ( multiLineString , WRAP_MIDDLE_CLIP_EDGES , 0 ) , right : wrapMultiLineStringHelper ( multiLineString , WRAP_RIGHT_CLIP_EDGES , - 360 ) } ; } const ec = EarthConstants . EQUATORIAL_CIRCUMFERENCE ; const border = 0 ; const WRAP_MIDDLE_CLIP_EDGES = [ new ClipEdge ( 0 - border , ec , 0 - border , 0 , p => p . x > 0 - border ) , new ClipEdge ( ec + border , 0 , ec + border , ec , p => p . x < ec + border ) ] ; const WRAP_LEFT_CLIP_EDGES = [ new ClipEdge ( - ec - border , ec , - ec - border , 0 , p => p . x > - ec - border ) , new ClipEdge ( 0 + border , 0 , 0 + border , ec , p => p . x < 0 + border ) ] ; const WRAP_RIGHT_CLIP_EDGES = [ new ClipEdge ( ec - border , ec , ec - border , 0 , p => p . x > ec - border ) , new ClipEdge ( ec * 2 + border , 0 , ec * 2 + border , ec , p => p . x < ec * 2 + border ) ] ;