/ cli / source / datapack / geometry / DropCircle.ts
DropCircle.ts
 1  import _ from 'lodash'
 2  import { RoaringBitmap32, SerializationFormat } from 'roaring'
 3  import { CircleGeometryParameters, GeometryType, IGeometryGenerator } from './Interfaces'
 4  
 5  /*
 6      Computing polygon points:
 7      - compute circumference of circle
 8      - divide by 3 to get amount of points you get along circle line
 9  
10      Example:
11      - radius of 20
12      - circumference is 125.6637
13      - division by 3 gets you Math.floor(result) of 41
14   */
15  
16  /*
17      Implementation left out for future testing/reference.
18   */
19  function unwrap( value: number ) : any {
20      let x = 0x0000FFFF & value
21      let y = value >> 16
22  
23      return { x, y }
24  }
25  
26  export class DropCircle implements IGeometryGenerator {
27      name: string
28      minRadius: number
29      maxRadius: number
30      radiusIncrement: number
31      data: RoaringBitmap32 = new RoaringBitmap32()
32      distanceBetweenPoints: number
33  
34      constructor( name: string, minRadius: number, maxRadius: number, radiusIncrement: number, pointDistance : number = 5 ) {
35          this.name = name
36          this.minRadius = minRadius
37          this.maxRadius = maxRadius
38          this.radiusIncrement = radiusIncrement
39          this.distanceBetweenPoints = pointDistance
40  
41          if ( this.minRadius === this.maxRadius ) {
42              this.data.addMany( this.createCirclePoints( this.minRadius, this.maxRadius, this.maxRadius ) )
43              return
44          }
45  
46          for ( let radius = this.minRadius; radius <= this.maxRadius; radius = radius + this.radiusIncrement ) {
47              this.data.addMany( this.createCirclePoints( radius, this.maxRadius, this.maxRadius ) )
48          }
49      }
50  
51      private createCirclePoints( radius: number, centerX: number, centerY: number ): Array<number> {
52          let circumference = Math.PI * 2 * radius
53          let amount = Math.floor( circumference / this.distanceBetweenPoints )
54  
55          return _.times( amount, ( index: number ): number => {
56              let ratio = ( index * Math.PI * 2 ) / amount
57              let x = centerX + Math.round( radius * Math.cos( ratio ) )
58              let y = centerY + Math.round( radius * Math.sin( ratio ) )
59  
60              return x + ( y << 16 )
61          } )
62      }
63  
64      generatePoints() : Buffer {
65          // @ts-ignore
66          return this.data.serialize( SerializationFormat.croaring )
67      }
68  
69      getParameters() : CircleGeometryParameters {
70          return {
71              maxRadius: this.maxRadius,
72              minRadius: this.minRadius,
73              stepIncrement: this.radiusIncrement,
74          }
75      }
76  
77      getName(): string {
78          return this.name
79      }
80  
81      getSize(): number {
82          return this.data.size
83      }
84  
85      getType(): GeometryType {
86          return GeometryType.PointCircle
87      }
88  }