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 }