binary/util.go (67 lines of code) (raw):

/* Copyright (c) 2016-2023 Uber Technologies, Inc. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package binary import ( "math" ) const ( DECA_MICRO_DEG_FACTOR = 100000.0 DISTANCE_PER_INTERVAL = 58.6 RESOLUTION = 24 BEAR_SECTOR = 11.25 ) // Deg2Int // // @param deg coordinate in degrees // @return int integer resolution of degrees as 3 bytes func Deg2Int(deg float64) int { val := math.Copysign(1, deg)*0.5 + float64(deg*(1<<RESOLUTION))/360.0 return int(math.Round(val)) } // Int2Bytes // // @param val integer value to convert // @param size // @param signed // @return []byte converted integer expressed as big endian func Int2Bytes(val int, size int, signed bool) []byte { bs := make([]byte, size) max := 1 << (8 * size) if val < 0 { val += max } for i := size - 1; i >= 0; i-- { r := val % 256 val = val / 256 bs[i] = byte(r) } return bs } // Status2Bytes // // @param version openlr version // @param locationType location reference type // @return []byte status represented as a byte array of size 1 func Status2Bytes(version int, locationType int) []byte { version &= 0b111 locationType &= 0b1111 byteInteger := version + (locationType << 3) return Int2Bytes(byteInteger, 1, false) } // Offset2Bytes // // @param offset offset rate // @return []byte offset represented as a byte array of size 1 func Offset2Bytes(offset float64) []byte { idx := 0 if offset != 0.0 { idx = int(math.Round(offset*256 - 0.5)) } return Int2Bytes(idx, 1, false) } // Coords2Bytes // // @param lon longitude in degrees // @param lat latitude in degrees // @return []byte longitude and latitude represented as a byte array of size 6 func Coords2Bytes(lon float64, lat float64) []byte { lonInt := Deg2Int(lon) latInt := Deg2Int(lat) return append(Int2Bytes(lonInt, 3, true), Int2Bytes(latInt, 3, true)...) } // Attributes2Bytes // // @param fow form of way // @param frc functional road class // @param bear bearing angle // @param lfrcnp lowest frc to next point // @param reserved reserved for future usage/side of road/orientation // @return []byte point attributes represented as a byte array of size 2 func Attributes2Bytes(fow int, frc int, bear int, lfrcnp int, reserved int) []byte { bearfloat := (float64(bear) - BEAR_SECTOR/2.0) / BEAR_SECTOR bearInt := int(math.Round(bearfloat)) fow = fow & 0b111 frc = frc & 0b111 bearInt = bearInt & 0b11111 lfrcnp = lfrcnp & 0b111 reserved = reserved & 0b11 bytesFowFrcReserved := Int2Bytes(fow+(frc<<3)+(reserved<<6), 1, false) bytesBearLFRCNP := Int2Bytes(bearInt+(lfrcnp<<5), 1, false) return append(bytesFowFrcReserved, bytesBearLFRCNP...) } // Dnp2Bytes // // @param dnp distance to next point // @return []byte dnp represented as 1 byte array func Dnp2Bytes(dnp int) []byte { interval := float64(dnp)/DISTANCE_PER_INTERVAL - 0.5 intervalInteger := int(math.Round(interval)) return Int2Bytes(intervalInteger, 1, false) } // RelativeCoords2Bytes // // @param lon longitude // @param lat latitude // @param xLon relative longitude // @param xLat relative latitude // @return []byte relative coordinates represented as a byte array of size 4 func RelativeCoords2Bytes(lon float64, lat float64, xLon float64, xLat float64) []byte { relLon := int(math.Round(DECA_MICRO_DEG_FACTOR * (lon - xLon))) relLat := int(math.Round(DECA_MICRO_DEG_FACTOR * (lat - xLat))) return append(Int2Bytes(relLon, 2, true), Int2Bytes(relLat, 2, true)...) }