feat: polish & windviz & deploy
This commit is contained in:
parent
81b8e763bd
commit
465ad00f7b
78 changed files with 20622 additions and 2154 deletions
41
internal/numerics/geometry.go
Normal file
41
internal/numerics/geometry.go
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
package numerics
|
||||
|
||||
import "math"
|
||||
|
||||
// PointInPolygon reports whether (lat, lng) lies inside the closed polygon
|
||||
// whose vertices are given as parallel latitude/longitude slices (degrees).
|
||||
//
|
||||
// The test is ray casting in plate-carrée space. Every longitude is
|
||||
// normalised to within 180° of the first vertex before testing, so a polygon
|
||||
// spanning the antimeridian is handled correctly as long as it spans no more
|
||||
// than 180° in longitude. polyLat and polyLng must have equal length >= 3.
|
||||
func PointInPolygon(lat, lng float64, polyLat, polyLng []float64) bool {
|
||||
n := len(polyLat)
|
||||
if n < 3 || len(polyLng) != n {
|
||||
return false
|
||||
}
|
||||
ref := polyLng[0]
|
||||
qx := NormalizeLng(lng, ref)
|
||||
|
||||
inside := false
|
||||
for i, j := 0, n-1; i < n; j, i = i, i+1 {
|
||||
yi, yj := polyLat[i], polyLat[j]
|
||||
xi := NormalizeLng(polyLng[i], ref)
|
||||
xj := NormalizeLng(polyLng[j], ref)
|
||||
|
||||
if (yi > lat) != (yj > lat) {
|
||||
xIntersect := (xj-xi)*(lat-yi)/(yj-yi) + xi
|
||||
if qx < xIntersect {
|
||||
inside = !inside
|
||||
}
|
||||
}
|
||||
}
|
||||
return inside
|
||||
}
|
||||
|
||||
// NormalizeLng rewrites v so that it lies within 180° of ref. For example,
|
||||
// NormalizeLng(350, 10) returns -10. Used to make longitude comparisons
|
||||
// continuous across the antimeridian.
|
||||
func NormalizeLng(v, ref float64) float64 {
|
||||
return ref + math.Mod(v-ref+540, 360) - 180
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue