WRS2数据查询代码(Golang)

WRS2(全球参考系统)简介

参考:全球参考系统(WRS)概述及常用工具汇总

WRS(Worldwide Reference System)是Landsat卫星采用的全球参考系统,也是国际上非常具有代表意义的全球参考系统之一。WRS是依据卫星地面轨迹的重复特性,结合星下点成像特性而形成的固定地面参考网格。其WRS参考系网格与Landsat卫星数据的成像区域紧密的契合,WRS网格的二维坐标采用Path和Row进行标识。
目前WRS有两个系统,分别为WRS-1(1983年之前)和WRS-2(1983年之后)。Landsat1-3使用WRS-1,Landsat4、5、7、8使用WRS-2。

WRS2 数据

这个数据我找了很久,NASA的网站现在只有在线查询的地方,没有找到数据下载。后来在这里 Converting latitude/longitude co-ordinates to Landsat WRS-2 paths/rows 找到了数据的下载位置

代码

完整代码请见:https://github.com/sotex/Landsat8cvsToMySQL

WRS2 查询相关代码如下:

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"

	"github.com/tidwall/geojson"

	"github.com/jonas-p/go-shp"
	geometry "github.com/tidwall/geojson/geometry"
)

type (
	WRS2Object struct {
		Path     int            // 路径
		Row      int            // 行
		boundary *geometry.Poly // 有效范围
	}
)

// 转换为 geojson 格式
func (obj *WRS2Object) MarshalJSON() ([]byte, error) {
	buf := bytes.NewBuffer(nil)
	buf.WriteString(`{"type":"Feature","properties":{"path":`)
	buf.WriteString(strconv.Itoa(obj.Path))
	buf.WriteString(`,"row":`)
	buf.WriteString(strconv.Itoa(obj.Row))
	buf.WriteString(`},"geometry":`)
	data, err := json.Marshal(geojson.NewPolygon(obj.boundary))
	if err != nil {
		return nil, err
	}
	buf.Write(data)
	buf.WriteByte('}')
	return buf.Bytes(), err
}

var (
	// WRS2索引 key=path*1000+row
	sPathRowIndex map[int]*WRS2Object
)

func init() {
	sPathRowIndex = make(map[int]*WRS2Object)
}

// 加载 wrs2 数据
// 这里加载的数据是经过处理的,把极地附近的给去掉了
func loadWRS2Data(shpfile string) error {
	shape, err := shp.Open(shpfile)
	if err != nil {
		return fmt.Errorf("打开文件错误:%s", err.Error())
	}
	defer shape.Close()

	// 字段信息
	// AREA PERIMETER PR_ PR_ID RINGS_OK RINGS_NOK PATH ROW MODE SEQUENCE WRSPR PR ACQDayL7 ACQDayL8
	// fields := shape.Fields()
	// fmt.Println(fields)
	for shape.Next() {
		n, s := shape.Shape()
		p, ok := s.(*shp.Polygon)
		if !ok {
			continue
		}
		// 获取边界点坐标
		coordinates := make([][]geometry.Point, p.NumParts)
		for i := int32(0); i < p.NumParts; i += 1 {
			var startIndex, endIndex int32
			startIndex = p.Parts[i]
			if i == p.NumParts-1 {
				endIndex = int32(len(p.Points))
			} else {
				endIndex = p.Parts[i+1]
			}

			coordinates[i] = make([]geometry.Point, 0, endIndex-startIndex)
			cnt := 0
			for j := startIndex; j < endIndex; j = j + 1 {
				var point = geometry.Point{
					X: p.Points[j].X,
					Y: p.Points[j].Y,
				}
				// 如果不是第一个或者最后一个点,判断与前一个点的距离
				// 用于减少点数(变成四边形,虽然不准确)
				if cnt > 0 && cnt < int(endIndex-startIndex-1) {
					dx, dy := point.X-coordinates[i][cnt-1].X, point.Y-coordinates[i][cnt-1].Y
					// 如果距离小于0.1度,就认为是一个点
					if (dx*dx + dy*dy) < 0.1 {
						continue
					}
				}
				coordinates[i] = append(coordinates[i], point)
				cnt = cnt + 1
			}
		}
		// 获取路径和行号
		var path, row int
		path, _ = strconv.Atoi(shape.ReadAttribute(n, 6))
		row, _ = strconv.Atoi(shape.ReadAttribute(n, 7))
		// 插入map里面
		var pr = path*1000 + row
		polygon := geometry.NewPoly(coordinates[0], coordinates[1:], nil)
		sPathRowIndex[pr] = &WRS2Object{
			Path:     path,
			Row:      row,
			boundary: polygon,
		}
	}
	return nil
}

func queryWRS2(path, row int) *WRS2Object {
	p, ok := sPathRowIndex[path*1000+row]
	if ok {
		return p
	}
	return nil
}

// 简单的测试代码
func main() {
	loadWSR2Data("E:/WRS2_descending_0/WRS2_descending.shp")
	fmt.Println("数据加载完成,共读取:", len(sPathRowIndex))

	p := queryWSR2(13, 10)
	if p != nil {
		data, err := json.Marshal(p)
		if err == nil {
			fmt.Println(string(data))
		} else {
			fmt.Println(err.Error())
		}
	}
}
posted @ 2020-09-20 15:09  乌合之众  阅读(835)  评论(0编辑  收藏  举报
clear