-
Notifications
You must be signed in to change notification settings - Fork 3.7k
/
geoproj.go
83 lines (76 loc) · 2.25 KB
/
geoproj.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Copyright 2020 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
// Package geoproj contains functions that interface with the PROJ library.
package geoproj
// #cgo CXXFLAGS: -std=c++14
// #cgo CPPFLAGS: -I../../../c-deps/proj/src
// #cgo LDFLAGS: -lproj
// #cgo linux LDFLAGS: -lrt -lm -lpthread
// #cgo windows LDFLAGS: -lshlwapi -lrpcrt4
//
// #include "proj.h"
import "C"
import (
"unsafe"
"github.com/cockroachdb/cockroach/pkg/geo/geoprojbase"
"github.com/cockroachdb/errors"
)
// maxArrayLen is the maximum safe length for this architecture.
const maxArrayLen = 1<<31 - 1
// goToCSlice returns a CR_PROJ_Slice from a given Go byte slice.
func goToCSlice(b []byte) C.CR_PROJ_Slice {
if len(b) == 0 {
return C.CR_PROJ_Slice{data: nil, len: 0}
}
return C.CR_PROJ_Slice{
data: (*C.char)(unsafe.Pointer(&b[0])),
len: C.size_t(len(b)),
}
}
func cStatusToUnsafeGoBytes(s C.CR_PROJ_Status) []byte {
if s.data == nil {
return nil
}
// Interpret the C pointer as a pointer to a Go array, then slice.
return (*[maxArrayLen]byte)(unsafe.Pointer(s.data))[:s.len:s.len]
}
// Project projects the given xCoords, yCoords and zCoords from one
// coordinate system to another using proj4text.
// Array elements are edited in place.
func Project(
from geoprojbase.Proj4Text,
to geoprojbase.Proj4Text,
xCoords []float64,
yCoords []float64,
zCoords []float64,
) error {
if len(xCoords) != len(yCoords) || len(xCoords) != len(zCoords) {
return errors.Newf(
"len(xCoords) != len(yCoords) != len(zCoords): %d != %d != %d",
len(xCoords),
len(yCoords),
len(zCoords),
)
}
if len(xCoords) == 0 {
return nil
}
if err := cStatusToUnsafeGoBytes(C.CR_PROJ_Transform(
goToCSlice([]byte(from)),
goToCSlice([]byte(to)),
C.long(len(xCoords)),
(*C.double)(unsafe.Pointer(&xCoords[0])),
(*C.double)(unsafe.Pointer(&yCoords[0])),
(*C.double)(unsafe.Pointer(&zCoords[0])),
)); err != nil {
return errors.Newf("error from PROJ: %s", string(err))
}
return nil
}