发出数据层请求

dataLayers 端点可提供指定地点周围区域的详细太阳能信息。该端点会返回 17 个可下载的 TIFF 文件,包括:

  • 数字地表模型 (DSM)
  • RGB 复合图层(航空影像)
  • 用于标识分析边界的掩码图层
  • 年太阳辐射量,或给定表面的年产量
  • 每月太阳辐射量,或给定表面的每月产量
  • 每小时遮阳度(24 小时)

如需详细了解 Solar API 如何定义通量,请参阅 Solar API 概念

数据层请求简介

以下示例展示了向 dataLayers 方法发出的 REST 请求的网址:

https://solar.googleapis.com/v1/dataLayers:get?parameters

添加请求网址参数,用于指定以下内容:

  • 相应位置的经纬度坐标
  • 相应地理位置周围区域的半径
  • 要返回的数据子集(DSM、RGB、掩码、年光合量或月光合量)
  • 结果中允许的最低质量
  • 要返回的数据的最小比例(以每像素米为单位)

数据层请求示例

以下示例请求纬度为 37.4450、经度为 -122.1390 的坐标位置方圆 100 米范围内的所有建筑数据分析信息:

如需向响应中的网址发出请求,请将您的 API 密钥附加到该网址:

curl -X GET "https://solar.googleapis.com/v1/dataLayers:get?location.latitude=37.4450&location.longitude=-122.1390&radiusMeters=100&view=FULL_LAYERS&requiredQuality=HIGH&exactQualityRequired=true&pixelSizeMeters=0.5&key=YOUR_API_KEY"

您还可以将 c网址 请求中的网址粘贴到浏览器的网址栏中,以发出 HTTP 请求。传递 API 密钥可让您更好地使用和分析数据,并更好地控制对响应数据的访问。

注意:此格式仅适用于测试环境。如需了解详情,请参阅使用 OAuth

如需向响应中的网址发出请求,请传入您的结算项目名称和 OAuth 令牌:

curl -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "X-Goog-User-Project: PROJECT_NUMBER_OR_ID" \
  "https://solar.googleapis.com/v1/dataLayers:get?location.latitude=37.4450&location.longitude=-122.1390&radius_meters=100&required_quality=HIGH&exactQualityRequired=true"
        

如需向响应中的网址发出请求,请在请求中添加您的 API 密钥或 OAuth 令牌。以下示例使用了 API 密钥:

/**
 * Fetches the data layers information from the Solar API.
 *   https://developers.google.com/maps/documentation/solar/data-layers
 *
 * @param  {LatLng} location      Point of interest as latitude longitude.
 * @param  {number} radiusMeters  Radius of the data layer size in meters.
 * @param  {string} apiKey        Google Cloud API key.
 * @return {Promise<DataLayersResponse>}  Data Layers response.
 */

export async function getDataLayerUrls(
  location
: LatLng,
  radiusMeters
: number,
  apiKey
: string,
): Promise<DataLayersResponse> {
 
const args = {
   
'location.latitude': location.latitude.toFixed(5),
   
'location.longitude': location.longitude.toFixed(5),
    radius_meters
: radiusMeters.toString(),
   
// The Solar API always returns the highest quality imagery available.
   
// By default the API asks for HIGH quality, which means that HIGH quality isn't available,
   
// but there is an existing MEDIUM or LOW quality, it won't return anything.
   
// Here we ask for *at least* LOW quality, but if there's a higher quality available,
   
// the Solar API will return us the highest quality available.
    required_quality
: 'LOW',
 
};
  console
.log('GET dataLayers\n', args);
 
const params = new URLSearchParams({ ...args, key: apiKey });
 
// https://developers.google.com/maps/documentation/solar/reference/rest/v1/dataLayers/get
 
return fetch(`https://solar.googleapis.com/v1/dataLayers:get?${params}`).then(
    async
(response) => {
     
const content = await response.json();
     
if (response.status != 200) {
        console
.error('getDataLayerUrls\n', content);
       
throw content;
     
}
      console
.log('dataLayersResponse', content);
     
return content;
   
},
 
);
}

字段和数据类型在 TypeScript 中是“类型”。在此示例中,我们定义了一个自定义类型,用于在响应中存储感兴趣的字段,例如像素值和经纬度边界框。您可以根据需要添加更多字段。

export interface GeoTiff {
  width
: number;
  height
: number;
  rasters
: Array<number>[];
  bounds
: Bounds;
}

支持以下数据类型:

export interface DataLayersResponse {
  imageryDate
: Date;
  imageryProcessedDate
: Date;
  dsmUrl
: string;
  rgbUrl
: string;
  maskUrl
: string;
  annualFluxUrl
: string;
  monthlyFluxUrl
: string;
  hourlyShadeUrls
: string[];
  imageryQuality
: 'HIGH' | 'MEDIUM' | 'LOW';
}

export interface Bounds {
  north
: number;
  south
: number;
  east
: number;
  west
: number;
}

// https://developers.google.com/maps/documentation/solar/reference/rest/v1/buildingInsights/findClosest
export interface BuildingInsightsResponse {
  name
: string;
  center
: LatLng;
  boundingBox
: LatLngBox;
  imageryDate
: Date;
  imageryProcessedDate
: Date;
  postalCode
: string;
  administrativeArea
: string;
  statisticalArea
: string;
  regionCode
: string;
  solarPotential
: SolarPotential;
  imageryQuality
: 'HIGH' | 'MEDIUM' | 'LOW';
}

export interface SolarPotential {
  maxArrayPanelsCount
: number;
  panelCapacityWatts
: number;
  panelHeightMeters
: number;
  panelWidthMeters
: number;
  panelLifetimeYears
: number;
  maxArrayAreaMeters2
: number;
  maxSunshineHoursPerYear
: number;
  carbonOffsetFactorKgPerMwh
: number;
  wholeRoofStats
: SizeAndSunshineStats;
  buildingStats
: SizeAndSunshineStats;
  roofSegmentStats
: RoofSegmentSizeAndSunshineStats[];
  solarPanels
: SolarPanel[];
  solarPanelConfigs
: SolarPanelConfig[];
  financialAnalyses
: object;
}

export interface SizeAndSunshineStats {
  areaMeters2
: number;
  sunshineQuantiles
: number[];
  groundAreaMeters2
: number;
}

export interface RoofSegmentSizeAndSunshineStats {
  pitchDegrees
: number;
  azimuthDegrees
: number;
  stats
: SizeAndSunshineStats;
  center
: LatLng;
  boundingBox
: LatLngBox;
  planeHeightAtCenterMeters
: number;
}

export interface SolarPanel {
  center
: LatLng;
  orientation
: 'LANDSCAPE' | 'PORTRAIT';
  segmentIndex
: number;
  yearlyEnergyDcKwh
: number;
}

export interface SolarPanelConfig {
  panelsCount
: number;
  yearlyEnergyDcKwh
: number;
  roofSegmentSummaries
: RoofSegmentSummary[];
}

export interface RoofSegmentSummary {
  pitchDegrees
: number;
  azimuthDegrees
: number;
  panelsCount
: number;
  yearlyEnergyDcKwh
: number;
  segmentIndex
: number;
}

export interface LatLng {
  latitude
: number;
  longitude
: number;
}

export interface LatLngBox {
  sw
: LatLng;
  ne
: LatLng;
}

export interface Date {
  year
: number;
  month
: number;
  day
: number;
}

export interface RequestError {
  error
: {
    code
: number;
    message
: string;
    status
: string;
 
};
}

该 API 会返回以下格式的网址:

https://solar.googleapis.com/v1/solar/geoTiff:get?id=HASHED_ID

您可以使用这些网址访问包含请求数据的 GeoTIFF 文件。

示例响应

该请求会生成以下格式的 JSON 响应:

{
 
"imageryDate": {
   
"year": 2022,
   
"month": 4,
   
"day": 6
 
},
 
"imageryProcessedDate": {
   
"year": 2023,
   
"month": 8,
   
"day": 4
 
},
 
"dsmUrl": "https://solar.googleapis.com/v1/geoTiff:get?id=MmQyMzI0NTMyZDc3YjBjNmQ3OTgyM2ZhNzMyNzk5NjItN2ZjODJlOThkNmQ5ZDdmZDFlNWU3MDY4YWFlMWU0ZGQ6UkdCOkhJR0g=",
 
"rgbUrl": "https://solar.googleapis.com/v1/geoTiff:get?id=NzQwNGQ0NmUyMzAzYWRiNmMxNzMwZTJhN2IxMTc4NDctOTI5YTNkZTlkM2MzYjRiNjE4MGNkODVmNjNiNDhkMzE6UkdCOkhJR0g=",
 
"maskUrl": "https://solar.googleapis.com/v1/geoTiff:get?id=ZTk1YTBlZmY5Y2FhMThlNWYzMWEzZGZhYzEzMGQzOTAtM2Q4NmUyMmM5ZThjZmE0YjhhZWMwN2UzYzdmYmQ3ZjI6TUFTSzpISUdI",
 
"annualFluxUrl": "https://solar.googleapis.com/v1/geoTiff:get?id=OTE0OWIxZDM3NmNlYjkzMWY2YjQyYjY5Y2RkYzNiOTAtZjU5YTVjZGQ3MzE3ZTQ4NTNmN2M4ZmY2MWZlZGZkMzg6QU5OVUFMX0ZMVVg6SElHSA==",
 
"monthlyFluxUrl": "https://solar.googleapis.com/v1/geoTiff:get?id=Y2NhOGRhOWI2MjVmYmNiZTY3Njk4Yjk0MGJhNTk1NDUtY2MyYTI4NDJmN2Q5YTI0MmY2NDQyZGUwZWJkMWQ0ZDg6TU9OVEhMWV9GTFVYOkhJR0g=",
 
"hourlyShadeUrls": [
   
"https://solar.googleapis.com/v1/geoTiff:get?id=OWFhOTZmNDU2OGQyNTYxYWQ4YjZkYjQ5NWI4Zjg1ODItZGEwNDNhMmM3NDU0MTY2OGIzZDY2OGU1NTY0NTFlMzE6TU9OVEhMWV9GTFVYOkhJR0g=",
   
"https://solar.googleapis.com/v1/geoTiff:get?id=MTI1ZTI2YzM1ZTRlYjA3ZDM4NWE2ODY4MjUzZmIxZTMtNTRmYTI3YmQyYzVjZDcyYjc5ZTlmMTRjZjBmYTk4OTk6TU9OVEhMWV9GTFVYOkhJR0g=",
   
...
 
],
 
"imageryQuality": "HIGH"
}

访问响应数据

如需通过响应网址访问数据,需要进行额外的身份验证。如果您使用身份验证密钥,则必须将 API 密钥附加到网址。如果您使用 OAuth 身份验证,则必须添加 OAuth 标头。

如需向响应中的网址发出请求,请将您的 API 密钥附加到该网址:

curl -X GET "https://solar.googleapis.com/v1/solar/geoTiff:get?id=fbde33e9cd16d5fd10d19a19dc580bc1-8614f599c5c264553f821cd034d5cf32&key=YOUR_API_KEY"

您还可以将 c网址 请求中的网址粘贴到浏览器的网址栏中,以发出 HTTP 请求。传递 API 密钥可让您更好地使用和分析数据,并更好地控制对响应数据的访问。

如需向响应中的网址发出请求,请传入您的结算项目名称和 OAuth 令牌:

curl -X GET \
-H 'X-Goog-User-Project: PROJECT_NUMBER_OR_ID' \
-H "Authorization: Bearer $TOKEN" \
"https://solar.googleapis.com/v1/solar/geoTiff:get?id=fbde33e9cd16d5fd10d19a19dc580bc1-8614f599c5c264553f821cd034d5cf32"
        

以下示例展示了如何获取像素数据值(存储在数字图片的各个像素中的信息,包括颜色值和其他属性)、从 GeoTIFF 计算纬度和经度,并将其存储在 TypeScript 对象中。

对于这个具体示例,我们选择允许进行类型检查,这有助于减少类型错误,提高代码可靠性,并简化代码维护。

// npm install geotiff geotiff-geokeys-to-proj4 proj4

import * as geotiff from 'geotiff';
import * as geokeysToProj4 from 'geotiff-geokeys-to-proj4';
import proj4 from 'proj4';

/**
 * Downloads the pixel values for a Data Layer URL from the Solar API.
 *
 * @param  {string} url        URL from the Data Layers response.
 * @param  {string} apiKey     Google Cloud API key.
 * @return {Promise<GeoTiff>}  Pixel values with shape and lat/lon bounds.
 */

export async function downloadGeoTIFF(url: string, apiKey: string): Promise<GeoTiff> {
  console
.log(`Downloading data layer: ${url}`);

 
// Include your Google Cloud API key in the Data Layers URL.
 
const solarUrl = url.includes('solar.googleapis.com') ? url + `&key=${apiKey}` : url;
 
const response = await fetch(solarUrl);
 
if (response.status != 200) {
   
const error = await response.json();
    console
.error(`downloadGeoTIFF failed: ${url}\n`, error);
   
throw error;
 
}

 
// Get the GeoTIFF rasters, which are the pixel values for each band.
 
const arrayBuffer = await response.arrayBuffer();
 
const tiff = await geotiff.fromArrayBuffer(arrayBuffer);
 
const image = await tiff.getImage();
 
const rasters = await image.readRasters();

 
// Reproject the bounding box into lat/lon coordinates.
 
const geoKeys = image.getGeoKeys();
 
const projObj = geokeysToProj4.toProj4(geoKeys);
 
const projection = proj4(projObj.proj4, 'WGS84');
 
const box = image.getBoundingBox();
 
const sw = projection.forward({
    x
: box[0] * projObj.coordinatesConversionParameters.x,
    y
: box[1] * projObj.coordinatesConversionParameters.y,
 
});
 
const ne = projection.forward({
    x
: box[2] * projObj.coordinatesConversionParameters.x,
    y
: box[3] * projObj.coordinatesConversionParameters.y,
 
});

 
return {
   
// Width and height of the data layer image in pixels.
   
// Used to know the row and column since Javascript
   
// stores the values as flat arrays.
    width
: rasters.width,
    height
: rasters.height,
   
// Each raster reprents the pixel values of each band.
   
// We convert them from `geotiff.TypedArray`s into plain
   
// Javascript arrays to make them easier to process.
    rasters
: [...Array(rasters.length).keys()].map((i) =>
     
Array.from(rasters[i] as geotiff.TypedArray),
   
),
   
// The bounding box as a lat/lon rectangle.
    bounds
: {
      north
: ne.y,
      south
: sw.y,
      east
: ne.x,
      west
: sw.x,
   
},
 
};
}

除了 RGB 图层外,所有 TIFF 文件都将在图片查看器应用中显示为空白图片。如需查看下载的 TIFF 文件,请将其导入地图应用软件(例如 QGIS)。

如需查看此请求和响应的完整规范,请参阅参考文档