go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/sdk/quad/zone.go (about)

     1  /*
     2  
     3  Copyright (c) 2023 - Present. Will Charczuk. All rights reserved.
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     5  
     6  */
     7  
     8  package quad
     9  
    10  import (
    11  	"strings"
    12  	"unicode/utf8"
    13  )
    14  
    15  // Zone is a quadrant zone identifier.
    16  type Zone string
    17  
    18  // ZoneElem is an individual element of the zone identifier.
    19  type ZoneElem rune
    20  
    21  const (
    22  	SW ZoneElem = 'A'
    23  	SE ZoneElem = 'B'
    24  	NW ZoneElem = 'C'
    25  	NE ZoneElem = 'D'
    26  )
    27  
    28  // EncodeZone encodes a zone value from a given list of quadrant choices.
    29  //
    30  // Quadrants are encoded according to a Z order such that
    31  // - SW => A
    32  // - SE => B
    33  // - NW => C
    34  // - NE => D
    35  func EncodeZone(values ...ZoneElem) (output Zone) {
    36  	return Zone(values)
    37  }
    38  
    39  // AppendZone adds a new index to a given parent.
    40  //
    41  // It works, basically, by prepending the new quadrant
    42  // on the existing parent, shifting the parent over
    43  // by two bits.
    44  func AppendZone(parent Zone, quadrantIndex ZoneElem) Zone {
    45  	return parent + Zone(quadrantIndex)
    46  }
    47  
    48  // Decode zone decodes a zone value fully into a slice of
    49  // "quad" choices as a query traverses the quad tree fully.
    50  func DecodeZone(zone Zone) (output []ZoneElem) {
    51  	output = []ZoneElem(zone)
    52  	return
    53  }
    54  
    55  // DecodeZoneHigh decodes _just_ the high order two bits of a given zone id.
    56  func DecodeZoneHigh(zone Zone) (output ZoneElem) {
    57  	if zone != "" {
    58  		next, _ := utf8.DecodeRuneInString(string(zone))
    59  		output = ZoneElem(next)
    60  		return
    61  	}
    62  	return 0
    63  }
    64  
    65  // ShiftZone removes the top order quadrant index returning
    66  // the lower order quadrant indices.
    67  func ShiftZone(zone Zone) Zone {
    68  	if zone == "" {
    69  		return ""
    70  	}
    71  	return Zone([]ZoneElem(zone)[1:])
    72  }
    73  
    74  // ZoneDepth returns the depth (or the number of levels of the tree)
    75  // represented by a given zone.
    76  func ZoneDepth(zone Zone) int {
    77  	return len(zone)
    78  }
    79  
    80  // HasZonePrefix returns if a given child exists within a given parent zone.
    81  //
    82  // It should be used to figure out if a given zone matches an arbitrary prefix.
    83  //
    84  //	HasZonePrefix(EncodeZone(2,1,2), EncodeZone(2,1,2,3,1)) => true
    85  func HasZonePrefix(zone, prefix Zone) bool {
    86  	return strings.HasPrefix(string(zone), string(prefix))
    87  }